diff --git a/.gitignore b/.gitignore index 9560bb6b..f2680446 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,8 @@ packages/ */obj *.suo *.user +*.DotSettings +*.dat setup/Debug setup/Release setup/*.cmd diff --git a/GlobalAssemblyInfo.cs b/GlobalAssemblyInfo.cs index 4adf8baf..f71fbd15 100644 --- a/GlobalAssemblyInfo.cs +++ b/GlobalAssemblyInfo.cs @@ -8,13 +8,14 @@ #else [assembly: AssemblyConfiguration("Release")] #endif + [assembly: AssemblyCompany("Nils Maier")] [assembly: AssemblyProduct("SimpleDLNA")] -[assembly: AssemblyCopyright("Copyright © 2012-2015 Nils Maier")] +[assembly: AssemblyCopyright("Copyright © 2012-2016 Nils Maier")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] [assembly: ComVisible(false)] -[assembly: AssemblyVersion("1.1.*")] -[assembly: AssemblyInformationalVersion("1.1")] -[assembly: NeutralResourcesLanguageAttribute("en-US")] +[assembly: AssemblyVersion("1.2.*")] +[assembly: AssemblyInformationalVersion("1.2")] +[assembly: NeutralResourcesLanguage("en-US")] [assembly: CLSCompliant(true)] diff --git a/NMaier.Windows.Forms/NMaier.Windows.Forms.csproj b/NMaier.Windows.Forms/NMaier.Windows.Forms.csproj index eff47cc9..847c0b7a 100644 --- a/NMaier.Windows.Forms/NMaier.Windows.Forms.csproj +++ b/NMaier.Windows.Forms/NMaier.Windows.Forms.csproj @@ -9,9 +9,10 @@ Properties NMaier.Windows.Forms NMaier.Windows.Forms - v4.0 + v4.5.1 512 - Client + + true @@ -21,6 +22,7 @@ DEBUG;TRACE prompt 4 + false pdbonly @@ -29,6 +31,7 @@ TRACE prompt 4 + false true diff --git a/NgenInstaller.cs b/NgenInstaller.cs index 4d35e297..fb516f89 100644 --- a/NgenInstaller.cs +++ b/NgenInstaller.cs @@ -20,10 +20,7 @@ public override void Install(IDictionary stateSaver) RuntimeEnvironment.GetRuntimeDirectory(), "ngen.exe" ); - proc.StartInfo.Arguments = string.Format( - "install /nologo \"{0}\"", - Assembly.GetExecutingAssembly().Location - ); + proc.StartInfo.Arguments = $"install /nologo \"{Assembly.GetExecutingAssembly().Location}\""; proc.StartInfo.UseShellExecute = false; proc.StartInfo.CreateNoWindow = true; proc.Start(); diff --git a/SimpleDLNA/FormAbout.Designer.cs b/SimpleDLNA/FormAbout.Designer.cs index 5e0160bf..13cba54c 100644 --- a/SimpleDLNA/FormAbout.Designer.cs +++ b/SimpleDLNA/FormAbout.Designer.cs @@ -1,6 +1,6 @@ namespace NMaier.SimpleDlna.GUI { - partial class FormAbout + sealed partial class FormAbout { /// /// Required designer variable. diff --git a/SimpleDLNA/FormAbout.cs b/SimpleDLNA/FormAbout.cs index c624d56d..7cf6a93c 100644 --- a/SimpleDLNA/FormAbout.cs +++ b/SimpleDLNA/FormAbout.cs @@ -1,24 +1,22 @@ -using NMaier.SimpleDlna.Utilities; -using System; -using System.Drawing; -using System.Text; -using System.Windows.Forms; +using System.Text; +using NMaier.SimpleDlna.GUI.Properties; +using NMaier.SimpleDlna.Utilities; +using NMaier.Windows.Forms; namespace NMaier.SimpleDlna.GUI { - partial class FormAbout : NMaier.Windows.Forms.Form + internal sealed partial class FormAbout : Form { public FormAbout() { InitializeComponent(); - Text = String.Format("About {0}", ProductInformation.Title); + Text = $"About {ProductInformation.Title}"; Product.Text = ProductInformation.Title; Product.Font = BoldFont; - Version.Text = String.Format( - "Version {0}", ProductInformation.ProductVersion); + Version.Text = $"Version {ProductInformation.ProductVersion}"; Copyright.Text = ProductInformation.Copyright; Copyright.Font = ItalicFont; - License.Text = Encoding.UTF8.GetString(Properties.Resources.LICENSE); + License.Text = Encoding.UTF8.GetString(Resources.LICENSE); } } } diff --git a/SimpleDLNA/FormMain.cs b/SimpleDLNA/FormMain.cs index 2a17b392..5c9043e2 100644 --- a/SimpleDLNA/FormMain.cs +++ b/SimpleDLNA/FormMain.cs @@ -1,110 +1,104 @@ -using log4net; -using log4net.Appender; -using log4net.Config; -using log4net.Core; -using log4net.Layout; -using NMaier.SimpleDlna.Server; -using System; +using System; using System.Collections.Concurrent; using System.Collections.Generic; +using System.ComponentModel; using System.Diagnostics; using System.IO; using System.IO.Pipes; using System.Linq; using System.Threading; using System.Threading.Tasks; +using System.Timers; using System.Windows.Forms; using System.Xml.Serialization; +using log4net; +using log4net.Appender; +using log4net.Config; +using log4net.Core; +using log4net.Layout; +using NMaier.SimpleDlna.GUI.Properties; +using NMaier.SimpleDlna.Server; +using Form = NMaier.Windows.Forms.Form; +using SystemInformation = NMaier.SimpleDlna.Utilities.SystemInformation; +using Timer = System.Timers.Timer; namespace NMaier.SimpleDlna.GUI { - public partial class FormMain : NMaier.Windows.Forms.Form, IAppender, IDisposable + public partial class FormMain : Form, IAppender { - private const string descriptorFile = "descriptors.xml"; + private const string DESCRIPTOR_FILE = "descriptors.xml"; - private bool canClose = false; + private bool canClose; - private static readonly Properties.Settings Config = - Properties.Settings.Default; + private static readonly Settings config = Settings.Default; private readonly FileInfo cacheFile = - new FileInfo(Path.Combine(cacheDir, "sdlna.cache")); + new FileInfo(Path.Combine(CacheDir, "sdlna.cache")); #if DEBUG private readonly FileInfo logFile = new FileInfo(Path.Combine(cacheDir, "sdlna.dbg.log")); #else private readonly FileInfo logFile = - new FileInfo(Path.Combine(cacheDir, "sdlna.log")); + new FileInfo(Path.Combine(CacheDir, "sdlna.log")); #endif private readonly object appenderLock = new object(); - private readonly System.Timers.Timer appenderTimer = - new System.Timers.Timer(2000); + private readonly Timer appenderTimer = + new Timer(2000); private readonly ConcurrentQueue pendingLogEntries = new ConcurrentQueue(); - private static readonly ILog log = LogManager.GetLogger(typeof(FormMain)); + private static readonly ILog log = LogManager.GetLogger(typeof (FormMain)); - private bool minimized = Config.startminimized; + private bool minimized = config.startminimized; private HttpServer httpServer; - private bool logging = false; + private bool logging; public FormMain() { - HandleCreated += (o, e) => - { - logging = true; - }; - HandleDestroyed += (o, e) => - { - logging = false; - }; + HandleCreated += (o, e) => { logging = true; }; + HandleDestroyed += (o, e) => { logging = false; }; InitializeComponent(); - listImages.Images.Add("idle", Properties.Resources.idle); - listImages.Images.Add("active", Properties.Resources.active); - listImages.Images.Add("inactive", Properties.Resources.inactive); - listImages.Images.Add("refreshing", Properties.Resources.refreshing); - listImages.Images.Add("loading", Properties.Resources.loading); - listImages.Images.Add("info", Properties.Resources.info); - listImages.Images.Add("warn", Properties.Resources.warn); - listImages.Images.Add("error", Properties.Resources.error); - listImages.Images.Add("server", Properties.Resources.server.ToBitmap()); - - appenderTimer.Elapsed += (s, e) => - { - BeginInvoke((Action)(() => - { - DoAppendInternal(s, e); - })); - }; + listImages.Images.Add("idle", Resources.idle); + listImages.Images.Add("active", Resources.active); + listImages.Images.Add("inactive", Resources.inactive); + listImages.Images.Add("refreshing", Resources.refreshing); + listImages.Images.Add("loading", Resources.loading); + listImages.Images.Add("info", Resources.info); + listImages.Images.Add("warn", Resources.warn); + listImages.Images.Add("error", Resources.error); + listImages.Images.Add("server", Resources.server.ToBitmap()); + + appenderTimer.Elapsed += (s, e) => { BeginInvoke((Action)(() => { DoAppendInternal(s, e); })); }; SetupLogging(); StartPipeNotification(); notifyIcon.Icon = Icon; - if (!string.IsNullOrWhiteSpace(Config.cache)) { - cacheFile = new FileInfo(Config.cache); + if (!string.IsNullOrWhiteSpace(config.cache)) { + cacheFile = new FileInfo(config.cache); } CreateHandle(); SetupServer(); } - private delegate void logDelegate(string level, string logger, string msg, - string ex); + protected sealed override void CreateHandle() + { + base.CreateHandle(); + } - private static string cacheDir + private static string CacheDir { - get - { - var rv = Config.cache; + get { + var rv = config.cache; if (!string.IsNullOrWhiteSpace(rv) && Directory.Exists(rv)) { return rv; } @@ -137,12 +131,8 @@ private static string cacheDir public override string Text { - get - { - return base.Text; - } - set - { + get { return base.Text; } + set { base.Text = value; notifyIcon.Text = value; } @@ -168,10 +158,7 @@ private void ButtonEdit_Click(object sender, EventArgs e) Task.Factory.StartNew(() => { item.UpdateInfo(desc); - BeginInvoke((Action)(() => - { - SaveConfig(); - })); + BeginInvoke((Action)SaveConfig); }); } } @@ -198,7 +185,7 @@ private void buttonRemove_Click(object sender, EventArgs e) return; } var dr = MessageBox.Show( - string.Format("Would you like to remove {0}?", item.Description.Name), + $"Would you like to remove {item.Description.Name}?", "Remove Server", MessageBoxButtons.YesNo, MessageBoxIcon.Question); @@ -243,9 +230,9 @@ private void ButtonStartStop_Click(object sender, EventArgs e) ctxStartStop.Text = buttonStartStop.Text = item.Description.Active ? "Stop" : "Start"; ctxStartStop.Image = buttonStartStop.Image = - item.Description.Active ? - Properties.Resources.inactive : - Properties.Resources.active; + item.Description.Active + ? Resources.inactive + : Resources.active; })); }); } @@ -274,7 +261,7 @@ where item.Description.Active } catch (Exception ex) { log.Error( - string.Format("Failed to remove cache file {0}", cacheFile.FullName), + $"Failed to remove cache file {cacheFile.FullName}", ex); } foreach (var item in running) { @@ -334,20 +321,20 @@ private void listDescriptions_DoubleClick(object sender, EventArgs e) } private void ListDescriptions_SelectedIndexChanged(object sender, - EventArgs e) + EventArgs e) { var enable = listDescriptions.SelectedItems.Count != 0; ctxStartStop.Enabled = ctxRemove.Enabled = ctxEdit.Enabled = buttonStartStop.Enabled = buttonRemove.Enabled = buttonEdit.Enabled = - enable; + enable; if (enable) { - var item = (listDescriptions.SelectedItems[0] as ServerListViewItem); + var item = (ServerListViewItem)listDescriptions.SelectedItems[0]; ctxStartStop.Text = buttonStartStop.Text = item.Description.Active ? "Stop" : "Start"; ctxStartStop.Image = buttonStartStop.Image = - item.Description.Active ? - Properties.Resources.inactive : - Properties.Resources.active; + item.Description.Active + ? Resources.inactive + : Resources.active; ctxRescan.Enabled = buttonRescan.Enabled = item.Description.Active; } else { @@ -358,20 +345,23 @@ private void ListDescriptions_SelectedIndexChanged(object sender, private void LoadConfig() { var descs = LoadDescriptors(); - listDescriptions.Items.AddRange(descs.ToArray()); + if (descs == null) { + throw new ArgumentException("Failed to load config"); + } + var items = new List(); + items.AddRange(descs.ToArray()); + listDescriptions.Items.AddRange(items.ToArray()); Task.Factory.StartNew(() => { - var po = new ParallelOptions() { + var po = new ParallelOptions + { MaxDegreeOfParallelism = Math.Min(2, Environment.ProcessorCount) }; - Parallel.ForEach(descs, po, i => - { - i.Load(); - }); + Parallel.ForEach(descs, po, i => { i.Load(); }); BeginInvoke((Action)(() => { - Config.Descriptors.Clear(); + config.Descriptors.Clear(); SaveConfig(); })); }); @@ -381,14 +371,14 @@ private ServerListViewItem[] LoadDescriptors() { List rv; try { - var serializer = new XmlSerializer(typeof(List)); + var serializer = new XmlSerializer(typeof (List)); using (var reader = new StreamReader( - Path.Combine(cacheDir, descriptorFile))) { + Path.Combine(CacheDir, DESCRIPTOR_FILE))) { rv = serializer.Deserialize(reader) as List; } } catch (Exception) { - rv = Config.Descriptors; + rv = config.Descriptors; } return (from d in rv let i = new ServerListViewItem(httpServer, cacheFile, d) @@ -396,14 +386,11 @@ private ServerListViewItem[] LoadDescriptors() } private void notifyContext_Opening(object sender, - System.ComponentModel.CancelEventArgs e) + CancelEventArgs e) { - var items = new List(); - foreach (ToolStripItem i in notifyContext.Items) { - if (i.Tag != null) { - items.Add(i); - } - } + var items = (from ToolStripItem i in notifyContext.Items + where i.Tag != null + select i).ToList(); foreach (var i in items) { notifyContext.Items.Remove(i); } @@ -419,9 +406,10 @@ private void notifyContext_Opening(object sender, } var innerItem = item; var menuItem = - new ToolStripMenuItem(String.Format("Rescan {0}", item.Text)) { + new ToolStripMenuItem($"Rescan {item.Text}") + { Tag = innerItem, - Image = Properties.Resources.refreshing + Image = Resources.refreshing }; menuItem.Click += (s, a) => { @@ -453,10 +441,9 @@ private void notifyIcon_DoubleClick(object sender, EventArgs e) } private void openInBrowserToolStripMenuItem_Click(object sender, - EventArgs e) + EventArgs e) { - Process.Start(string.Format( - "http://localhost:{0}/", httpServer.RealPort)); + Process.Start($"http://localhost:{httpServer.RealPort}/"); } private void rescanAllContextMenuItem_Click(object sender, EventArgs e) @@ -478,41 +465,43 @@ private void SaveConfig() select item.Description).ToArray(); var serializer = new XmlSerializer(descs.GetType()); var file = new FileInfo( - Path.Combine(cacheDir, descriptorFile + ".tmp")); + Path.Combine(CacheDir, DESCRIPTOR_FILE + ".tmp")); using (var writer = new StreamWriter(file.FullName)) { serializer.Serialize(writer, descs); } - var outfile = Path.Combine(cacheDir, descriptorFile); + var outfile = Path.Combine(CacheDir, DESCRIPTOR_FILE); File.Copy(file.FullName, outfile, true); file.Delete(); } catch (Exception ex) { log.Error("Failed to write descriptors", ex); } - Config.Save(); + config.Save(); } private void settingsToolStripMenuItem_Click(object sender, EventArgs e) { using (var settings = new FormSettings()) { settings.ShowDialog(); - Config.Save(); + config.Save(); SetupLogging(); } } private void SetupLogging() { - if (!Config.filelogging) { + if (!config.filelogging) { BasicConfigurator.Configure(this); return; } - var layout = new PatternLayout() { + var layout = new PatternLayout + { ConversionPattern = "%date %6level [%3thread] %-30.30logger{1} - %message%newline%exception" }; layout.ActivateOptions(); - var fileAppender = new RollingFileAppender() { + var fileAppender = new RollingFileAppender + { File = logFile.FullName, Layout = layout, MaximumFileSize = "10MB", @@ -528,9 +517,9 @@ private void SetupLogging() private void SetupServer() { - httpServer = new HttpServer((int)Config.port); + httpServer = new HttpServer((int)config.port); LoadConfig(); - Text = string.Format("{0} - Port {1}", Text, httpServer.RealPort); + Text = $"{Text} - Port {httpServer.RealPort}"; } private void StartPipeNotification() @@ -538,16 +527,16 @@ private void StartPipeNotification() #if DEBUG log.Info("Debug mode / Skipping one-instance-only stuff"); #else - if (Utilities.SystemInformation.IsRunningOnMono()) { + if (SystemInformation.IsRunningOnMono()) { // XXX Mono sometimes stack overflows for whatever reason. return; } new Thread(() => { - for (; ; ) { + for (;;) { try { using (var pipe = new NamedPipeServerStream( - "simpledlnagui", PipeDirection.InOut)) { + "simpledlnagui", PipeDirection.InOut)) { pipe.WaitForConnection(); pipe.ReadByte(); BeginInvoke((Action)(() => @@ -558,9 +547,11 @@ private void StartPipeNotification() } } catch (Exception) { + // ignored } } - }) { IsBackground = true }.Start(); + // ReSharper disable once FunctionNeverReturns + }) {IsBackground = true}.Start(); #endif } @@ -598,7 +589,8 @@ public void DoAppend(LoggingEvent loggingEvent) key = "warn"; } } - pendingLogEntries.Enqueue(new LogEntry() { + pendingLogEntries.Enqueue(new LogEntry + { Class = cls, Exception = loggingEvent.GetExceptionString(), Key = key, @@ -611,7 +603,7 @@ public void DoAppend(LoggingEvent loggingEvent) } public void DoAppendInternal(object sender, - System.Timers.ElapsedEventArgs e) + ElapsedEventArgs e) { lock (appenderLock) { appenderTimer.Enabled = false; @@ -619,22 +611,24 @@ public void DoAppendInternal(object sender, if (!logging) { return; } - LogEntry entry; ListViewItem last = null; logger.BeginUpdate(); try { + LogEntry entry; while (pendingLogEntries.TryDequeue(out entry)) { if (logger.Items.Count >= 300) { logger.Items.RemoveAt(0); } last = logger.Items.Add( - new ListViewItem(new string[] { + new ListViewItem(new[] + { entry.Time, entry.Class, entry.Message })); last.ImageKey = entry.Key; if (!string.IsNullOrWhiteSpace(entry.Exception)) { last = logger.Items.Add( - new ListViewItem(new string[] { + new ListViewItem(new[] + { string.Empty, entry.Class, entry.Exception })); last.ImageKey = entry.Key; diff --git a/SimpleDLNA/FormServer.Designer.cs b/SimpleDLNA/FormServer.Designer.cs index 415a1edf..19ceab42 100644 --- a/SimpleDLNA/FormServer.Designer.cs +++ b/SimpleDLNA/FormServer.Designer.cs @@ -1,6 +1,6 @@ namespace NMaier.SimpleDlna.GUI { - partial class FormServer + sealed partial class FormServer { /// /// Required designer variable. diff --git a/SimpleDLNA/FormServer.cs b/SimpleDLNA/FormServer.cs index 4b1132b7..5d221765 100644 --- a/SimpleDLNA/FormServer.cs +++ b/SimpleDLNA/FormServer.cs @@ -1,16 +1,18 @@ -using NMaier.SimpleDlna.Server; -using NMaier.SimpleDlna.Server.Comparers; -using NMaier.SimpleDlna.Server.Views; -using NMaier.SimpleDlna.Utilities; -using System; +using System; using System.ComponentModel; using System.Linq; using System.Net; using System.Windows.Forms; +using NMaier.SimpleDlna.GUI.Properties; +using NMaier.SimpleDlna.Server; +using NMaier.SimpleDlna.Server.Comparers; +using NMaier.SimpleDlna.Server.Views; +using NMaier.SimpleDlna.Utilities; +using Form = NMaier.Windows.Forms.Form; namespace NMaier.SimpleDlna.GUI { - internal partial class FormServer : NMaier.Windows.Forms.Form + internal sealed partial class FormServer : Form { public FormServer() { @@ -44,7 +46,8 @@ public FormServer(ServerDescription description) checkOrderDescending.Checked = description.OrderDescending; foreach (var v in description.Views) { - var i = new ListViewItem(new string[] { + var i = new ListViewItem(new[] + { v, ViewRepository.Lookup(v).Description }); listViews.Items.Add(i); @@ -78,8 +81,7 @@ public FormServer(ServerDescription description) public ServerDescription Description { - get - { + get { DlnaMediaTypes types = 0; if (checkVideo.Checked) { types |= DlnaMediaTypes.Video; @@ -103,7 +105,8 @@ public ServerDescription Description var uas = (from ListViewItem i in listRestrictions.Items where (int)i.Tag == 2 select i.Text).ToArray(); - var rv = new ServerDescription() { + var rv = new ServerDescription + { Name = textName.Text, Order = ((IItemComparer)comboOrder.SelectedItem).Name, OrderDescending = checkOrderDescending.Checked, @@ -148,7 +151,7 @@ private void buttonAddDirectory_Click(object sender, EventArgs e) var found = from ListViewItem i in listDirectories.Items where StringComparer.InvariantCulture.Equals(path, i.Text) select i; - if (found.Count() == 0) { + if (!found.Any()) { listDirectories.Items.Add(path); } } @@ -160,18 +163,18 @@ private void buttonAddRestriction_Click(object sender, EventArgs e) var valid = false; var re = textRestriction.Text; switch (comboNewRestriction.SelectedIndex) { - case 0: - valid = IP.IsAcceptedMAC(re); - break; - case 1: - IPAddress o; - valid = IPAddress.TryParse(re, out o); - break; - case 2: - valid = !string.IsNullOrWhiteSpace(re); - break; - default: - break; + case 0: + valid = IP.IsAcceptedMAC(re); + break; + case 1: + IPAddress o; + valid = IPAddress.TryParse(re, out o); + break; + case 2: + valid = !string.IsNullOrWhiteSpace(re); + break; + default: + break; } if (!valid) { errorProvider.SetError( @@ -191,14 +194,14 @@ private void buttonAddView_Click(object sender, EventArgs e) return; } listViews.Items.Add( - new ListViewItem(new string[] { i.Name, i.Description })); + new ListViewItem(new[] {i.Name, i.Description})); SizeColumns(listViews); } private void buttonRemoveDirectory_Click(object sender, EventArgs e) { foreach (var i in listDirectories.SelectedItems) { - listDirectories.Items.Remove(i as ListViewItem); + listDirectories.Items.Remove((ListViewItem)i); } SizeDirectoryColumn(); } @@ -206,7 +209,7 @@ private void buttonRemoveDirectory_Click(object sender, EventArgs e) private void buttonRemoveRestriction_Click(object sender, EventArgs e) { foreach (var i in listRestrictions.SelectedItems) { - var item = i as ListViewItem; + var item = (ListViewItem)i; var index = (int)item.Tag; textRestriction.Text = item.Text; comboNewRestriction.SelectedIndex = index; @@ -218,7 +221,7 @@ private void buttonRemoveRestriction_Click(object sender, EventArgs e) private void buttonRemoveView_Click(object sender, EventArgs e) { foreach (var i in listViews.SelectedItems) { - listViews.Items.Remove(i as ListViewItem); + listViews.Items.Remove((ListViewItem)i); } SizeColumns(listViews); } @@ -242,7 +245,7 @@ private void FormServer_FormClosing(object sender, FormClosingEventArgs e) private void Init() { InitializeComponent(); - Icon = Properties.Resources.server; + Icon = Resources.server; AddOrderItems(); AddViewItems(); comboNewRestriction.SelectedIndex = 0; diff --git a/SimpleDLNA/FormSettings.cs b/SimpleDLNA/FormSettings.cs index e742c949..26bfccf0 100644 --- a/SimpleDLNA/FormSettings.cs +++ b/SimpleDLNA/FormSettings.cs @@ -1,22 +1,25 @@ using System; using System.Windows.Forms; +using NMaier.SimpleDlna.GUI.Properties; +using Form = NMaier.Windows.Forms.Form; +using SystemInformation = NMaier.SimpleDlna.Utilities.SystemInformation; namespace NMaier.SimpleDlna.GUI { - public partial class FormSettings : NMaier.Windows.Forms.Form + public partial class FormSettings : Form { - private const string AppKeyName = "SimpleDLNA"; + private const string APP_KEY_NAME = "SimpleDLNA"; - private StartupUtilities startUpUtilities; + private readonly StartupUtilities startUpUtilities; public FormSettings() { InitializeComponent(); - Icon = Properties.Resources.preferencesIcon; + Icon = Resources.preferencesIcon; - if (!Utilities.SystemInformation.IsRunningOnMono()) { + if (!SystemInformation.IsRunningOnMono()) { startUpUtilities = new StartupUtilities(StartupUtilities.StartupUserScope.CurrentUser); - checkAutoStart.Checked = startUpUtilities.CheckIfRunAtWinBoot(AppKeyName); + checkAutoStart.Checked = startUpUtilities.CheckIfRunAtWinBoot(APP_KEY_NAME); } else { checkAutoStart.Visible = false; @@ -33,10 +36,10 @@ private void buttonBrowseCacheFile_Click(object sender, EventArgs e) private void checkAutoStart_CheckedChanged(object sender, EventArgs e) { if (checkAutoStart.Checked) { - startUpUtilities.InstallAutoRun(AppKeyName); + startUpUtilities.InstallAutoRun(APP_KEY_NAME); } else { - startUpUtilities.UninstallAutoRun(AppKeyName); + startUpUtilities.UninstallAutoRun(APP_KEY_NAME); } } } diff --git a/SimpleDLNA/PathEnvironmentInstaller.cs b/SimpleDLNA/PathEnvironmentInstaller.cs index f6974845..8c16b15d 100644 --- a/SimpleDLNA/PathEnvironmentInstaller.cs +++ b/SimpleDLNA/PathEnvironmentInstaller.cs @@ -1,11 +1,11 @@ -using Microsoft.Win32; -using System; +using System; using System.Collections; using System.ComponentModel; using System.Configuration.Install; using System.IO; using System.Linq; using System.Reflection; +using Microsoft.Win32; namespace NMaier.SimpleDlna.GUI { @@ -19,7 +19,7 @@ public class PathEnvironmentInstaller : Installer private const string REG_PATH = "PATH"; private readonly DirectoryInfo directory = - new FileInfo(Assembly.GetExecutingAssembly().Location).Directory; + new FileInfo(Assembly.GetExecutingAssembly().Location ?? string.Empty).Directory; public override void Install(IDictionary stateSaver) { @@ -29,7 +29,7 @@ public override void Install(IDictionary stateSaver) } using (var registry = Registry.CurrentUser.OpenSubKey(REG_ENV, true)) { - var path = registry.GetValue( + var path = registry?.GetValue( REG_PATH, string.Empty, RegistryValueOptions.DoNotExpandEnvironmentNames) as string; if (path == null) { @@ -39,13 +39,13 @@ public override void Install(IDictionary stateSaver) var exists = from p in path.Split(';') where c.Equals(p, directory.FullName) select p; - if (exists.Count() > 0) { + if (exists.Any()) { return; } stateSaver[ENV_PATH] = path; var newpath = directory.FullName; if (!string.IsNullOrWhiteSpace(path)) { - newpath = string.Format("{0};{1}", path, newpath); + newpath = $"{path};{newpath}"; } registry.SetValue(REG_PATH, newpath, RegistryValueKind.ExpandString); } @@ -58,7 +58,7 @@ public override void Rollback(IDictionary savedState) return; } using (var registry = Registry.CurrentUser.OpenSubKey(REG_ENV, true)) { - registry.SetValue( + registry?.SetValue( REG_PATH, savedState[ENV_PATH], registry.GetValueKind(REG_PATH)); } } @@ -71,7 +71,7 @@ public override void Uninstall(IDictionary savedState) } using (var registry = Registry.CurrentUser.OpenSubKey(REG_ENV, true)) { - var path = registry.GetValue( + var path = registry?.GetValue( REG_PATH, string.Empty, RegistryValueOptions.DoNotExpandEnvironmentNames) as string; if (string.IsNullOrEmpty(path)) { diff --git a/SimpleDLNA/Properties/Resources.Designer.cs b/SimpleDLNA/Properties/Resources.Designer.cs index aa2b1ed1..1311973d 100644 --- a/SimpleDLNA/Properties/Resources.Designer.cs +++ b/SimpleDLNA/Properties/Resources.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:4.0.30319.34209 +// Runtime Version:4.0.30319.42000 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. diff --git a/SimpleDLNA/Properties/Settings.Designer.cs b/SimpleDLNA/Properties/Settings.Designer.cs index a68b9818..12510b3c 100644 --- a/SimpleDLNA/Properties/Settings.Designer.cs +++ b/SimpleDLNA/Properties/Settings.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:4.0.30319.34209 +// Runtime Version:4.0.30319.42000 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. diff --git a/SimpleDLNA/ServerDescription.cs b/SimpleDLNA/ServerDescription.cs index 36ba6c0c..766cf1bf 100644 --- a/SimpleDLNA/ServerDescription.cs +++ b/SimpleDLNA/ServerDescription.cs @@ -1,5 +1,5 @@ -using NMaier.SimpleDlna.Server; using System; +using NMaier.SimpleDlna.Server; namespace NMaier.SimpleDlna.GUI { @@ -34,7 +34,7 @@ public ServerDescription() public void AdoptInfo(ServerDescription other) { if (other == null) { - throw new ArgumentNullException("other"); + throw new ArgumentNullException(nameof(other)); } Directories = other.Directories; Name = other.Name; diff --git a/SimpleDLNA/ServerListViewItem.cs b/SimpleDLNA/ServerListViewItem.cs index 4fcc465e..c4745d63 100644 --- a/SimpleDLNA/ServerListViewItem.cs +++ b/SimpleDLNA/ServerListViewItem.cs @@ -1,26 +1,26 @@ +using System; +using System.IO; +using System.Linq; +using System.Windows.Forms; using log4net; using log4net.Core; using NMaier.SimpleDlna.FileMediaServer; using NMaier.SimpleDlna.Server; using NMaier.SimpleDlna.Server.Comparers; -using System; -using System.IO; -using System.Linq; -using System.Windows.Forms; namespace NMaier.SimpleDlna.GUI { internal class ServerListViewItem : ListViewItem, IDisposable { - private readonly FileInfo cacheFile = null; - - private FileServer fileServer; + private readonly FileInfo cacheFile; - private State internalState = State.Idle; + internal readonly ServerDescription Description; private readonly HttpServer server; - internal readonly ServerDescription Description; + private FileServer fileServer; + + private State internalState = State.Idle; internal ServerListViewItem(HttpServer server, FileInfo cacheFile, ServerDescription description) { @@ -34,25 +34,20 @@ internal ServerListViewItem(HttpServer server, FileInfo cacheFile, ServerDescrip ImageIndex = 0; } - private enum State : int + private State InternalState { - Idle = 0, - Running = 1, - Stopped = 2, - Refreshing = 3, - Loading = 4, + get { return internalState; } + set { + internalState = value; + UpdateInfo(); + } } - private State state + public void Dispose() { - get - { - return internalState; - } - set - { - internalState = value; - UpdateInfo(); + if (fileServer != null) { + fileServer.Dispose(); + fileServer = null; } } @@ -69,7 +64,7 @@ private void BeginInvoke(Action func) ? ColumnHeaderAutoResizeStyle.HeaderSize : ColumnHeaderAutoResizeStyle.ColumnContent; foreach (var c in ListView.Columns) { - (c as ColumnHeader).AutoResize(mode); + ((ColumnHeader)c).AutoResize(mode); } } } @@ -79,12 +74,12 @@ private void BeginInvoke(Action func) private void StartFileServer() { if (!Description.Active) { - state = State.Stopped; + InternalState = State.Stopped; return; } var start = DateTime.Now; try { - state = State.Loading; + InternalState = State.Loading; var ids = new Identifiers(ComparerRepository.Lookup(Description.Order), Description.OrderDescending); foreach (var v in Description.Views) { ids.AddView(v); @@ -96,7 +91,8 @@ where d.Exists if (dirs.Length == 0) { throw new InvalidOperationException("No remaining directories"); } - fileServer = new FileServer(Description.Types, ids, dirs) { + fileServer = new FileServer(Description.Types, ids, dirs) + { FriendlyName = Description.Name }; #if !DEBUG @@ -104,14 +100,8 @@ where d.Exists fileServer.SetCacheFile(cacheFile); } #endif - fileServer.Changing += (o, e) => - { - state = State.Refreshing; - }; - fileServer.Changed += (o, e) => - { - state = Description.Active ? State.Running : State.Stopped; - }; + fileServer.Changing += (o, e) => { InternalState = State.Refreshing; }; + fileServer.Changed += (o, e) => { InternalState = Description.Active ? State.Running : State.Stopped; }; fileServer.Load(); var authorizer = new HttpAuthorizer(); if (Description.Ips.Length != 0) { @@ -125,22 +115,19 @@ where d.Exists } fileServer.Authorizer = authorizer; server.RegisterMediaServer(fileServer); - state = State.Running; + InternalState = State.Running; var elapsed = DateTime.Now - start; LogManager.GetLogger("State").Logger.Log( GetType(), Level.Notice, - string.Format( - "{0} loaded in {1:F2} seconds", - fileServer.FriendlyName, - elapsed.TotalSeconds), + $"{fileServer.FriendlyName} loaded in {elapsed.TotalSeconds:F2} seconds", null - ); + ); } catch (Exception ex) { server.ErrorFormat("Failed to start {0}, {1}", Description.Name, ex); Description.ToggleActive(); - state = State.Stopped; + InternalState = State.Stopped; } } @@ -153,7 +140,7 @@ private void StopFileServer() fileServer.Dispose(); fileServer = null; - state = State.Stopped; + InternalState = State.Stopped; } private void UpdateInfo() @@ -164,14 +151,14 @@ private void UpdateInfo() Text = Description.Name; SubItems.Add(Description.Directories.Length.ToString()); - SubItems.Add(state.ToString()); - ImageIndex = (int)state; + SubItems.Add(InternalState.ToString()); + ImageIndex = (int)InternalState; }); } internal void Load() { - state = State.Loading; + InternalState = State.Loading; StartFileServer(); } @@ -201,12 +188,13 @@ internal void UpdateInfo(ServerDescription description) StartFileServer(); } - public void Dispose() + private enum State { - if (fileServer != null) { - fileServer.Dispose(); - fileServer = null; - } + Idle = 0, + Running = 1, + Stopped = 2, + Refreshing = 3, + Loading = 4 } } } diff --git a/SimpleDLNA/SimpleDLNA.csproj b/SimpleDLNA/SimpleDLNA.csproj index ee64040a..5246e611 100644 --- a/SimpleDLNA/SimpleDLNA.csproj +++ b/SimpleDLNA/SimpleDLNA.csproj @@ -1,5 +1,5 @@  - + Debug x86 @@ -10,8 +10,9 @@ Properties NMaier.SimpleDlna.GUI SimpleDLNA - v4.0 - Client + v4.5.1 + + 512 publish\ true @@ -30,6 +31,8 @@ true ..\ true + + sdlna.ico @@ -46,6 +49,7 @@ prompt ..\sdlna.ruleset false + false bin\Release\ @@ -60,6 +64,7 @@ ..\sdlna.ruleset false true + false true @@ -69,16 +74,17 @@ - False - ..\packages\log4net.2.0.5\lib\net40-client\log4net.dll + ..\packages\log4net.2.0.5\lib\net45-full\log4net.dll + True - - + + ..\packages\System.Data.SQLite.Core.1.0.103\lib\net451\System.Data.SQLite.dll + True + - @@ -236,7 +242,9 @@ This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + @@ -11,9 +11,12 @@ - + + + + \ No newline at end of file diff --git a/util/AttributeCollection.cs b/util/AttributeCollection.cs index 9a3bf20a..2eb2abc8 100644 --- a/util/AttributeCollection.cs +++ b/util/AttributeCollection.cs @@ -7,37 +7,24 @@ namespace NMaier.SimpleDlna.Utilities { using Attribute = KeyValuePair; - public sealed class AttributeCollection : IEnumerable + public class AttributeCollection : IEnumerable { private readonly IList list = new List(); - public int Count - { - get - { - return list.Count; - } - } + public int Count => list.Count; - public ICollection Keys - { - get - { - return (from i in list - select i.Key).ToList(); - } - } + public ICollection Keys => (from i in list + select i.Key).ToList(); + + public ICollection Values => (from i in list + select i.Value).ToList(); - public ICollection Values + IEnumerator IEnumerable.GetEnumerator() { - get - { - return (from i in list - select i.Value).ToList(); - } + return list.GetEnumerator(); } - IEnumerator IEnumerable.GetEnumerator() + public IEnumerator GetEnumerator() { return list.GetEnumerator(); } @@ -62,15 +49,25 @@ public bool Contains(Attribute item) return list.Contains(item); } - public IEnumerator GetEnumerator() + public bool Has(string key) { - return list.GetEnumerator(); + return Has(key, StringComparer.CurrentCultureIgnoreCase); + } + + public bool Has(string key, StringComparer comparer) + { + return list.Any(e => comparer.Equals(key, e.Key)); } public IEnumerable GetValuesForKey(string key) + { + return GetValuesForKey(key, StringComparer.CurrentCultureIgnoreCase); + } + + public IEnumerable GetValuesForKey(string key, StringComparer comparer) { return from i in list - where StringComparer.CurrentCultureIgnoreCase.Equals(i.Key, key) + where comparer.Equals(i.Key, key) select i.Value; } } diff --git a/util/BaseSortPart.cs b/util/BaseSortPart.cs index b87f3967..f3b8e4aa 100644 --- a/util/BaseSortPart.cs +++ b/util/BaseSortPart.cs @@ -17,7 +17,7 @@ public int CompareTo(BaseSortPart other) return 1; } if (type != other.type) { - if (type == typeof(StringSortPart)) { + if (type == typeof (StringSortPart)) { return 1; } return -1; diff --git a/util/ConcatenatedStream.cs b/util/ConcatenatedStream.cs index aed8a40e..13ec9f0b 100644 --- a/util/ConcatenatedStream.cs +++ b/util/ConcatenatedStream.cs @@ -8,48 +8,21 @@ public sealed class ConcatenatedStream : Stream { private readonly Queue streams = new Queue(); - public override bool CanRead - { - get - { - return true; - } - } + public override bool CanRead => true; - public override bool CanSeek - { - get - { - return false; - } - } + public override bool CanSeek => false; - public override bool CanWrite - { - get - { - return false; - } - } + public override bool CanWrite => false; public override long Length { - get - { - throw new NotSupportedException(); - } + get { throw new NotSupportedException(); } } public override long Position { - get - { - throw new NotSupportedException(); - } - set - { - throw new NotSupportedException(); - } + get { throw new NotSupportedException(); } + set { throw new NotSupportedException(); } } public void AddStream(Stream stream) diff --git a/util/ConfigParameters.cs b/util/ConfigParameters.cs new file mode 100644 index 00000000..1323337a --- /dev/null +++ b/util/ConfigParameters.cs @@ -0,0 +1,93 @@ +using System; +using System.ComponentModel; +using System.Linq; + +namespace NMaier.SimpleDlna.Utilities +{ + public class ConfigParameters : AttributeCollection + { + public ConfigParameters() + { + } + + public ConfigParameters(string parameters) + { + foreach (var valuesplit in parameters.Split(',').Select(p => p.Split(new[] {'='}, 2))) { + Add(valuesplit[0], valuesplit.Length == 2 ? valuesplit[1] : null); + } + } + + public bool TryGet(string key, out TValue rv) where TValue : struct + { + return TryGet(key, out rv, StringComparer.CurrentCultureIgnoreCase); + } + + public bool TryGet(string key, out TValue rv, StringComparer comparer) where TValue : struct + { + rv = new TValue(); + var convertible = rv as IConvertible; + if (convertible == null) { + throw new NotSupportedException("Not convertible"); + } + switch (convertible.GetTypeCode()) { + case TypeCode.Boolean: + foreach (var val in GetValuesForKey(key, comparer)) { + try { + rv = (TValue)(object)Formatting.Booley(val); + return true; + } + catch (Exception) { + // ignored + } + } + break; + case TypeCode.Object: + throw new NotSupportedException("Non pod types are not supported"); + default: + var conv = TypeDescriptor.GetConverter(typeof (TValue)); + foreach (var val in GetValuesForKey(key, comparer)) { + try { + var converted = conv.ConvertFromString(val); + if (converted == null) { + continue; + } + rv = (TValue)converted; + return true; + } + catch (Exception) { + // ignored + } + } + break; + } + return false; + } + + public TValue Get(string key, TValue defaultValue) where TValue : struct + { + return Get(key, defaultValue, StringComparer.CurrentCultureIgnoreCase); + } + + public TValue Get(string key, TValue defaultValue, StringComparer comparer) + where TValue : struct + { + TValue rv; + return TryGet(key, out rv, comparer) ? rv : defaultValue; + } + + public TValue? MaybeGet(string key) where TValue : struct + { + return MaybeGet(key, StringComparer.CurrentCultureIgnoreCase); + } + + public TValue? MaybeGet(string key, StringComparer comparer) where TValue : struct + { + TValue? rv = null; + TValue attempt; + if (TryGet(key, out attempt, comparer)) { + rv = attempt; + } + return rv; + } + } +} diff --git a/util/Ffmpeg.cs b/util/Ffmpeg.cs index c1430a5d..6f7e14b3 100644 --- a/util/Ffmpeg.cs +++ b/util/Ffmpeg.cs @@ -1,5 +1,4 @@ -using log4net; -using System; +using System; using System.Collections.Generic; using System.Diagnostics; using System.Drawing; @@ -7,6 +6,7 @@ using System.IO; using System.Reflection; using System.Text.RegularExpressions; +using log4net; namespace NMaier.SimpleDlna.Utilities { @@ -14,14 +14,8 @@ namespace NMaier.SimpleDlna.Utilities public static class FFmpeg { - private static DirectoryInfo GetFFMpegFolder( - Environment.SpecialFolder folder) + private static readonly DirectoryInfo[] specialLocations = { - return new DirectoryInfo( - Path.Combine(Environment.GetFolderPath(folder), "ffmpeg")); - } - - private static readonly DirectoryInfo[] specialLocations = new DirectoryInfo[] { GetFFMpegFolder(Environment.SpecialFolder.CommonProgramFiles), GetFFMpegFolder(Environment.SpecialFolder.CommonProgramFilesX86), GetFFMpegFolder(Environment.SpecialFolder.ProgramFiles), @@ -31,7 +25,7 @@ private static DirectoryInfo GetFFMpegFolder( Environment.SpecialFolder.UserProfile)) }; - private readonly static InfoCache infoCache = new InfoCache(500); + private static readonly InfoCache infoCache = new InfoCache(500); private static readonly Regex regAssStrip = new Regex(@"^,+", RegexOptions.Compiled); @@ -46,6 +40,13 @@ private static DirectoryInfo GetFFMpegFolder( public static readonly string FFmpegExecutable = FindExecutable("ffmpeg"); + private static DirectoryInfo GetFFMpegFolder( + Environment.SpecialFolder folder) + { + return new DirectoryInfo( + Path.Combine(Environment.GetFolderPath(folder), "ffmpeg")); + } + private static string FindExecutable(string executable) { var os = Environment.OSVersion.Platform.ToString().ToUpperInvariant(); @@ -54,39 +55,48 @@ private static string FindExecutable(string executable) executable += ".exe"; } var places = new List(); - places.Add(new FileInfo( - Assembly.GetExecutingAssembly().Location).Directory); + var assemblyLoc = Assembly.GetExecutingAssembly().Location; + if (assemblyLoc != null) { + places.Add(new FileInfo(assemblyLoc).Directory); + } try { - places.Add(new DirectoryInfo( - Environment.GetEnvironmentVariable("FFMPEG_HOME"))); + var ffhome = Environment.GetEnvironmentVariable("FFMPEG_HOME"); + if (!string.IsNullOrWhiteSpace(ffhome)) { + places.Add(new DirectoryInfo(ffhome)); + } } catch (Exception) { + // ignored } foreach (var l in specialLocations) { try { places.Add(l); } catch (Exception) { - continue; + // ignored } } - foreach (var p in Environment.GetEnvironmentVariable("PATH"). - Split(isWin ? ';' : ':')) { - try { - places.Add(new DirectoryInfo(p.Trim())); - } - catch (Exception) { - continue; + var envpath = Environment.GetEnvironmentVariable("PATH"); + if (!string.IsNullOrWhiteSpace(envpath)) { + foreach (var p in envpath. + Split(isWin ? ';' : ':')) { + try { + places.Add(new DirectoryInfo(p.Trim())); + } + catch (Exception) { + // ignored + } } } foreach (var i in places) { - LogManager.GetLogger(typeof(FFmpeg)).DebugFormat( + LogManager.GetLogger(typeof (FFmpeg)).DebugFormat( "Searching {0}", i.FullName); if (!i.Exists) { continue; } - var folders = new[] { + var folders = new[] + { i, new DirectoryInfo(Path.Combine(i.FullName, "bin")) }; @@ -95,20 +105,20 @@ private static string FindExecutable(string executable) var r = di.GetFiles(executable, SearchOption.TopDirectoryOnly); if (r.Length != 0) { var rv = r[0]; - LogManager.GetLogger(typeof(FFmpeg)).InfoFormat( + LogManager.GetLogger(typeof (FFmpeg)).InfoFormat( "Found {0} at {1}", executable, rv.FullName - ); + ); return rv.FullName; } } catch (Exception) { - continue; + // ignored } } } - LogManager.GetLogger(typeof(FFmpeg)).WarnFormat( + LogManager.GetLogger(typeof (FFmpeg)).WarnFormat( "Did not find {0}", executable); return null; } @@ -116,11 +126,11 @@ private static string FindExecutable(string executable) private static IDictionary IdentifyFileInternal( FileInfo file) { - if (FFmpeg.FFmpegExecutable == null) { + if (FFmpegExecutable == null) { throw new NotSupportedException(); } if (file == null) { - throw new ArgumentNullException("file"); + throw new ArgumentNullException(nameof(file)); } IDictionary rv; if (infoCache.TryGetValue(file, out rv)) { @@ -137,22 +147,20 @@ private static IDictionary IdentifyFileInternal( private static IDictionary IdentifyInternalFromProcess( FileInfo file) { - IDictionary rv; - using (var p = new Process()) { var sti = p.StartInfo; #if !DEBUG sti.CreateNoWindow = true; #endif sti.UseShellExecute = false; - sti.FileName = FFmpeg.FFmpegExecutable; - sti.Arguments = String.Format("-i \"{0}\"", file.FullName); + sti.FileName = FFmpegExecutable; + sti.Arguments = $"-i \"{file.FullName}\""; sti.LoadUserProfile = false; sti.RedirectStandardError = true; p.Start(); - rv = new Dictionary(); + IDictionary rv = new Dictionary(); - using (var reader = new StreamReader(new MemoryStream())) { + using (var reader = new StreamReader(StreamManager.GetStream())) { using (var pump = new StreamPump( p.StandardError.BaseStream, reader.BaseStream, 4096)) { pump.Pump(null); @@ -166,11 +174,12 @@ private static IDictionary IdentifyInternalFromProcess( var output = reader.ReadToEnd(); var match = regDuration.Match(output); - if (match != null && match.Success) { - int h, m, s, ms; + if (match.Success) { + int h, m, s; if (int.TryParse(match.Groups[1].Value, out h) && - int.TryParse(match.Groups[2].Value, out m) && - int.TryParse(match.Groups[3].Value, out s)) { + int.TryParse(match.Groups[2].Value, out m) && + int.TryParse(match.Groups[3].Value, out s)) { + int ms; if (match.Groups.Count < 5 || !int.TryParse(match.Groups[4].Value, out ms)) { ms = 0; @@ -182,10 +191,10 @@ private static IDictionary IdentifyInternalFromProcess( } } match = regDimensions.Match(output); - if (match != null && match.Success) { + if (match.Success) { int w, h; if (int.TryParse(match.Groups[1].Value, out w) && - int.TryParse(match.Groups[2].Value, out h)) { + int.TryParse(match.Groups[2].Value, out h)) { rv.Add("VIDEO_WIDTH", w.ToString()); rv.Add("VIDEO_HEIGHT", h.ToString()); } @@ -204,10 +213,10 @@ public static Size GetFileDimensions(FileInfo file) string sw, sh; int w, h; if (IdentifyFile(file).TryGetValue("VIDEO_WIDTH", out sw) - && IdentifyFile(file).TryGetValue("VIDEO_HEIGHT", out sh) - && int.TryParse(sw, out w) - && int.TryParse(sh, out h) - && w > 0 && h > 0) { + && IdentifyFile(file).TryGetValue("VIDEO_HEIGHT", out sh) + && int.TryParse(sw, out w) + && int.TryParse(sh, out h) + && w > 0 && h > 0) { return new Size(w, h); } throw new NotSupportedException(); @@ -216,9 +225,9 @@ public static Size GetFileDimensions(FileInfo file) public static double GetFileDuration(FileInfo file) { string sl; - if (FFmpeg.IdentifyFile(file).TryGetValue("LENGTH", out sl)) { + if (IdentifyFile(file).TryGetValue("LENGTH", out sl)) { double dur; - bool valid = Double.TryParse( + var valid = double.TryParse( sl, NumberStyles.AllowDecimalPoint, CultureInfo.GetCultureInfo("en-US", "en"), out dur); if (valid && dur > 0) { @@ -230,11 +239,11 @@ public static double GetFileDuration(FileInfo file) public static string GetSubtitleSubrip(FileInfo file) { - if (FFmpeg.FFmpegExecutable == null) { + if (FFmpegExecutable == null) { throw new NotSupportedException(); } if (file == null) { - throw new ArgumentNullException("file"); + throw new ArgumentNullException(nameof(file)); } try { using (var p = new Process()) { @@ -243,15 +252,14 @@ public static string GetSubtitleSubrip(FileInfo file) sti.CreateNoWindow = true; #endif sti.UseShellExecute = false; - sti.FileName = FFmpeg.FFmpegExecutable; - sti.Arguments = String.Format( - "-i \"{0}\" -map s:0 -f srt pipe:", file.FullName); + sti.FileName = FFmpegExecutable; + sti.Arguments = $"-i \"{file.FullName}\" -map s:0 -f srt pipe:"; sti.LoadUserProfile = false; sti.RedirectStandardOutput = true; p.Start(); var lastPosition = 0L; - using (var reader = new StreamReader(new MemoryStream())) { + using (var reader = new StreamReader(StreamManager.GetStream())) { using (var pump = new StreamPump( p.StandardOutput.BaseStream, reader.BaseStream, 100)) { pump.Pump(null); @@ -289,7 +297,7 @@ public static string GetSubtitleSubrip(FileInfo file) public static IDictionary IdentifyFile(FileInfo file) { - if (FFmpeg.FFmpegExecutable != null) { + if (FFmpegExecutable != null) { return IdentifyFileInternal(file); } throw new NotSupportedException(); diff --git a/util/Formatting.cs b/util/Formatting.cs index 403e6f95..d4273747 100644 --- a/util/Formatting.cs +++ b/util/Formatting.cs @@ -6,52 +6,55 @@ namespace NMaier.SimpleDlna.Utilities { public static class Formatting { - private readonly static Regex sanitizer = new Regex( + private static readonly Regex sanitizer = new Regex( @"\b(?:the|an?|ein(?:e[rs]?)?|der|die|das)\b", RegexOptions.IgnoreCase | RegexOptions.Compiled ); - private readonly static Regex trim = new Regex( + private static readonly Regex trim = new Regex( @"\s+|^[._+)}\]-]+|[._+({\[-]+$", RegexOptions.Compiled ); - private readonly static Regex trimmore = + private static readonly Regex trimmore = new Regex(@"^[^\d\w]+|[^\d\w]+$", RegexOptions.Compiled); - private readonly static Regex respace = + private static readonly Regex respace = new Regex(@"[.+]+", RegexOptions.Compiled); - public static bool Booley(string str) + public static bool Booley(string maybeBoolean) { - str = str.Trim(); + if (maybeBoolean == null) { + throw new ArgumentNullException(nameof(maybeBoolean)); + } + maybeBoolean = maybeBoolean.Trim(); var sc = StringComparer.CurrentCultureIgnoreCase; - return sc.Equals("yes", str) || sc.Equals("1", str) || sc.Equals("true", str); + return sc.Equals("yes", maybeBoolean) || sc.Equals("1", maybeBoolean) || sc.Equals("true", maybeBoolean); } public static string FormatFileSize(this long size) { if (size < 900) { - return string.Format("{0} B", size); + return $"{size} B"; } var ds = size / 1024.0; if (ds < 900) { - return string.Format("{0:F2} KB", ds); + return $"{ds:F2} KB"; } ds /= 1024.0; if (ds < 900) { - return string.Format("{0:F2} MB", ds); + return $"{ds:F2} MB"; } ds /= 1024.0; if (ds < 900) { - return string.Format("{0:F3} GB", ds); + return $"{ds:F3} GB"; } ds /= 1024.0; if (ds < 900) { - return string.Format("{0:F3} TB", ds); + return $"{ds:F3} TB"; } ds /= 1024.0; - return string.Format("{0:F4} PB", ds); + return $"{ds:F4} PB"; } public static string GetSystemName() @@ -69,7 +72,7 @@ public static string GetSystemName() public static string StemCompareBase(this string name) { if (name == null) { - throw new ArgumentNullException("name"); + throw new ArgumentNullException(nameof(name)); } var san = trimmore.Replace( @@ -84,7 +87,7 @@ public static string StemCompareBase(this string name) public static string StemNameBase(this string name) { if (name == null) { - throw new ArgumentNullException("name"); + throw new ArgumentNullException(nameof(name)); } if (!name.Contains(" ")) { @@ -95,12 +98,11 @@ public static string StemNameBase(this string name) name = respace.Replace(name, " "); } var ws = name; - var wsprev = name; + string wsprev; do { wsprev = ws; ws = trim.Replace(wsprev.Trim(), " ").Trim(); - } - while (wsprev != ws); + } while (wsprev != ws); if (string.IsNullOrWhiteSpace(ws)) { return name; } diff --git a/util/GlobalSuppressions.cs b/util/GlobalSuppressions.cs index 8b297922..35499ac3 100644 --- a/util/GlobalSuppressions.cs +++ b/util/GlobalSuppressions.cs @@ -25,3 +25,6 @@ [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Scope = "member", Target = "NMaier.SimpleDlna.Utilities.Sqlite.#GetDatabaseConnectionSDS(System.String)")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Scope = "member", Target = "NMaier.SimpleDlna.Utilities.FFmpeg.#IdentifyInternalFromProcess(System.IO.FileInfo)")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "ffmpeg", Scope = "member", Target = "NMaier.SimpleDlna.Utilities.FFmpeg.#IdentifyInternalFromProcess(System.IO.FileInfo)")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Booley", Scope = "member", Target = "NMaier.SimpleDlna.Utilities.Formatting.#Booley(System.String)")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", Scope = "member", Target = "NMaier.SimpleDlna.Utilities.Formatting.#GetSystemName()")] + diff --git a/util/HttpStream.cs b/util/HttpStream.cs index f933ba5c..d60b5e89 100644 --- a/util/HttpStream.cs +++ b/util/HttpStream.cs @@ -1,8 +1,8 @@ -using log4net; -using System; +using System; using System.IO; using System.Net; using System.Reflection; +using log4net; namespace NMaier.SimpleDlna.Utilities { @@ -14,18 +14,20 @@ public class HttpStream : Stream, IDisposable private const int TIMEOUT = 30000; - private Stream bufferedStream; + private static readonly ILog logger = + LogManager.GetLogger(typeof (HttpStream)); - private long? length; + public static readonly string UserAgent = GenerateUserAgent(); - private readonly static ILog logger = - LogManager.GetLogger(typeof(HttpStream)); + private readonly Uri referrer; - public static readonly string UserAgent = GenerateUserAgent(); + private readonly Uri uri; - private long position = 0; + private Stream bufferedStream; - private readonly Uri referrer; + private long? length; + + private long position; private HttpWebRequest request; @@ -33,8 +35,6 @@ public class HttpStream : Stream, IDisposable private Stream responseStream; - private readonly Uri uri; - public HttpStream(Uri uri) : this(uri, null) { @@ -43,24 +43,17 @@ public HttpStream(Uri uri) public HttpStream(Uri uri, Uri referrer) { if (uri == null) { - throw new ArgumentNullException("uri"); + throw new ArgumentNullException(nameof(uri)); } this.uri = uri; this.referrer = referrer; } - public override bool CanRead - { - get - { - return true; - } - } + public override bool CanRead => true; public override bool CanSeek { - get - { + get { if (Length <= 0) { return false; } @@ -68,40 +61,20 @@ public override bool CanSeek EnsureResponse(); var ranges = response.Headers.Get("Accept-Ranges"); if (!string.IsNullOrEmpty(ranges) && - ranges.ToUpperInvariant() == "none") { + ranges.ToUpperInvariant() == "none") { return false; } return true; } } - public override bool CanTimeout - { - get - { - return true; - } - } + public override bool CanTimeout => true; - public override bool CanWrite - { - get - { - return false; - } - } + public override bool CanWrite => false; - private void EnsureResponse() - { - if (response != null) { - return; - } - OpenAt(0, HttpMethod.HEAD); - } public string ContentType { - get - { + get { EnsureResponse(); return response.ContentType; } @@ -109,8 +82,7 @@ public string ContentType public DateTime LastModified { - get - { + get { EnsureResponse(); return response.LastModified; } @@ -118,8 +90,7 @@ public DateTime LastModified public override long Length { - get - { + get { if (!length.HasValue) { OpenAt(0, HttpMethod.HEAD); length = response.ContentLength; @@ -133,39 +104,41 @@ public override long Length public override long Position { - get - { - return position; - } - set - { - Seek(Position, SeekOrigin.Begin); - } + get { return position; } + set { Seek(value, SeekOrigin.Begin); } + } + + public Uri Uri => new Uri(uri.ToString()); + + public new void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); } - public Uri Uri + private void EnsureResponse() { - get - { - return new Uri(uri.ToString()); + if (response != null) { + return; } + OpenAt(0, HttpMethod.HEAD); } private static string GenerateUserAgent() { var os = Environment.OSVersion; - var pstring = os.Platform.ToString(); + string pstring; switch (os.Platform) { - case PlatformID.Win32NT: - case PlatformID.Win32S: - case PlatformID.Win32Windows: - pstring = "WIN"; - break; - default: - pstring = "Unix"; - break; + case PlatformID.Win32NT: + case PlatformID.Win32S: + case PlatformID.Win32Windows: + pstring = "WIN"; + break; + default: + pstring = "Unix"; + break; } - return String.Format( + return string.Format( "sdlna/{4}.{5} ({0}{1} {2}.{3}) like curl/7.3 like wget/1.0", pstring, IntPtr.Size * 8, @@ -220,40 +193,29 @@ protected void OpenAt(long offset, HttpMethod method) response = (HttpWebResponse)request.GetResponse(); if (method != HttpMethod.HEAD) { responseStream = response.GetResponseStream(); + if (responseStream == null) { + throw new IOException("Didn't get a response stream"); + } bufferedStream = new BufferedStream(responseStream, BUFFER_SIZE); } if (offset > 0 && response.StatusCode != HttpStatusCode.PartialContent) { throw new IOException( "Failed to open the http stream at a specific position"); } - else { - if (offset == 0 && response.StatusCode != HttpStatusCode.OK) { - throw new IOException("Failed to open the http stream"); - } + if (offset == 0 && response.StatusCode != HttpStatusCode.OK) { + throw new IOException("Failed to open the http stream"); } logger.InfoFormat("Opened {0} {1} at {2}", method, uri, offset); } public override void Close() { - if (bufferedStream != null) { - bufferedStream.Close(); - } - if (responseStream != null) { - responseStream.Close(); - } - if (response != null) { - response.Close(); - } + bufferedStream?.Close(); + responseStream?.Close(); + response?.Close(); base.Close(); } - public new void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - public override void Flush() { Dispose(true); @@ -282,15 +244,15 @@ public override long Seek(long offset, SeekOrigin origin) logger.DebugFormat("Seek to {0}, {1} requested", offset, origin); var np = 0L; switch (origin) { - case SeekOrigin.Begin: - np = offset; - break; - case SeekOrigin.Current: - np = position + offset; - break; - case SeekOrigin.End: - np = Length + np; - break; + case SeekOrigin.Begin: + np = offset; + break; + case SeekOrigin.Current: + np = position + offset; + break; + case SeekOrigin.End: + np = Length + np; + break; } if (np < 0 || np >= Length) { throw new IOException("Invalid seek; out of stream bounds"); diff --git a/util/IConfigurable.cs b/util/IConfigurable.cs new file mode 100644 index 00000000..073124e4 --- /dev/null +++ b/util/IConfigurable.cs @@ -0,0 +1,7 @@ +namespace NMaier.SimpleDlna.Utilities +{ + public interface IConfigurable + { + void SetParameters(ConfigParameters parameters); + } +} diff --git a/util/IP.cs b/util/IP.cs index e8abb665..bb5321ae 100644 --- a/util/IP.cs +++ b/util/IP.cs @@ -1,26 +1,25 @@ -using log4net; -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.NetworkInformation; using System.Net.Sockets; +using log4net; namespace NMaier.SimpleDlna.Utilities { public static class IP { - private readonly static AddressToMacResolver macResolver = + private static readonly AddressToMacResolver macResolver = new AddressToMacResolver(); - private readonly static ILog logger = LogManager.GetLogger(typeof(IP)); + private static readonly ILog logger = LogManager.GetLogger(typeof (IP)); - private static bool warned = false; + private static bool warned; public static IEnumerable AllIPAddresses { - get - { + get { try { return GetIPsDefault().ToArray(); } @@ -36,15 +35,9 @@ public static IEnumerable AllIPAddresses } } - public static IEnumerable ExternalIPAddresses - { - get - { - return from i in AllIPAddresses - where !IPAddress.IsLoopback(i) - select i; - } - } + public static IEnumerable ExternalIPAddresses => from i in AllIPAddresses + where !IPAddress.IsLoopback(i) + select i; private static IEnumerable GetIPsDefault() { @@ -54,7 +47,7 @@ private static IEnumerable GetIPsDefault() var gateways = from ga in props.GatewayAddresses where !ga.Address.Equals(IPAddress.Any) select true; - if (gateways.Count() == 0) { + if (!gateways.Any()) { logger.DebugFormat("Skipping {0}. No gateways", props); continue; } diff --git a/util/IRepositoryItem.cs b/util/IRepositoryItem.cs index 03384eb3..b6a9f6ad 100644 --- a/util/IRepositoryItem.cs +++ b/util/IRepositoryItem.cs @@ -5,7 +5,5 @@ public interface IRepositoryItem string Description { get; } string Name { get; } - - void SetParameters(AttributeCollection parameters); } } diff --git a/util/LeastRecentlyUsedDictionary.cs b/util/LeastRecentlyUsedDictionary.cs index fef97e7b..b4985518 100644 --- a/util/LeastRecentlyUsedDictionary.cs +++ b/util/LeastRecentlyUsedDictionary.cs @@ -10,8 +10,6 @@ namespace NMaier.SimpleDlna.Utilities public sealed class LeastRecentlyUsedDictionary : IDictionary { - private readonly uint capacity; - private readonly ConcurrentDictionary>> items = new ConcurrentDictionary>>(); @@ -23,7 +21,7 @@ public sealed class LeastRecentlyUsedDictionary [CLSCompliant(false)] public LeastRecentlyUsedDictionary(uint capacity) { - this.capacity = capacity; + Capacity = capacity; toDrop = Math.Min(10, (uint)(capacity * 0.07)); } @@ -33,56 +31,22 @@ public LeastRecentlyUsedDictionary(int capacity) } [CLSCompliant(false)] - public uint Capacity - { - get - { - return capacity; - } - } + public uint Capacity { get; } - public int Count - { - get - { - return items.Count; - } - } + public int Count => items.Count; - public bool IsReadOnly - { - get - { - return false; - } - } + public bool IsReadOnly => false; - public ICollection Keys - { - get - { - return items.Keys; - } - } + public ICollection Keys => items.Keys; - public ICollection Values - { - get - { - return (from i in items.Values - select i.Value.Value).ToList(); - } - } + public ICollection Values => (from i in items.Values + select i.Value.Value).ToList(); public TValue this[TKey key] { - get - { - return items[key].Value.Value; - } + get { return items[key].Value.Value; } [MethodImpl(MethodImplOptions.Synchronized)] - set - { + set { Remove(key); Add(key, value); } @@ -93,47 +57,12 @@ IEnumerator IEnumerable.GetEnumerator() return items.GetEnumerator(); } - private TValue MaybeDropSome() - { - if (Count <= capacity) { - return default(TValue); - } - lock (order) { - LinkedListNode> item; - TValue rv = default(TValue); - for (var i = 0; i < toDrop; ++i) { - if (items.TryRemove(order.Last.Value.Key, out item)) { - rv = item.Value.Value; - } - order.RemoveLast(); - } - return rv; - } - } - - [MethodImpl(MethodImplOptions.Synchronized)] - public TValue AddAndPop(KeyValuePair item) - { - LinkedListNode> node; - lock (order) { - node = order.AddFirst(item); - } - items.TryAdd(item.Key, node); - return MaybeDropSome(); - } - [MethodImpl(MethodImplOptions.Synchronized)] public void Add(KeyValuePair item) { AddAndPop(item); } - [MethodImpl(MethodImplOptions.Synchronized)] - public TValue AddAndPop(TKey key, TValue value) - { - return AddAndPop(new KeyValuePair(key, value)); - } - [MethodImpl(MethodImplOptions.Synchronized)] public void Add(TKey key, TValue value) { @@ -167,9 +96,7 @@ public void CopyTo(KeyValuePair[] array, int arrayIndex) public IEnumerator> GetEnumerator() { - foreach (var i in items) { - yield return i.Value.Value; - } + return items.Select(i => i.Value.Value).GetEnumerator(); } [MethodImpl(MethodImplOptions.Synchronized)] @@ -208,5 +135,40 @@ public bool TryGetValue(TKey key, out TValue value) value = default(TValue); return false; } + + private TValue MaybeDropSome() + { + if (Count <= Capacity) { + return default(TValue); + } + lock (order) { + var rv = default(TValue); + for (var i = 0; i < toDrop; ++i) { + LinkedListNode> item; + if (items.TryRemove(order.Last.Value.Key, out item)) { + rv = item.Value.Value; + } + order.RemoveLast(); + } + return rv; + } + } + + [MethodImpl(MethodImplOptions.Synchronized)] + public TValue AddAndPop(KeyValuePair item) + { + LinkedListNode> node; + lock (order) { + node = order.AddFirst(item); + } + items.TryAdd(item.Key, node); + return MaybeDropSome(); + } + + [MethodImpl(MethodImplOptions.Synchronized)] + public TValue AddAndPop(TKey key, TValue value) + { + return AddAndPop(new KeyValuePair(key, value)); + } } } diff --git a/util/Logging.cs b/util/Logging.cs index b7c7ae78..b73cbd96 100644 --- a/util/Logging.cs +++ b/util/Logging.cs @@ -1,6 +1,6 @@ -using log4net; +using System; +using log4net; using log4net.Core; -using System; namespace NMaier.SimpleDlna.Utilities { @@ -8,297 +8,246 @@ public class Logging : ILog { private ILog instance; - private ILog logger - { - get - { - if (instance == null) { - instance = LogManager.GetLogger(GetType()); - } - return instance; - } - } + private ILog InternalLogger => instance ?? (instance = LogManager.GetLogger(GetType())); - public bool IsDebugEnabled - { - get - { - return logger.IsDebugEnabled; - } - } + public bool IsNoticeEnabled => Logger.IsEnabledFor(Level.Notice); - public bool IsErrorEnabled - { - get - { - return logger.IsErrorEnabled; - } - } + public bool IsDebugEnabled => InternalLogger.IsDebugEnabled; - public bool IsFatalEnabled - { - get - { - return logger.IsFatalEnabled; - } - } + public bool IsErrorEnabled => InternalLogger.IsErrorEnabled; - public bool IsInfoEnabled - { - get - { - return logger.IsInfoEnabled; - } - } + public bool IsFatalEnabled => InternalLogger.IsFatalEnabled; - public bool IsNoticeEnabled - { - get - { - return Logger.IsEnabledFor(Level.Notice); - } - } + public bool IsInfoEnabled => InternalLogger.IsInfoEnabled; - public bool IsWarnEnabled - { - get - { - return logger.IsWarnEnabled; - } - } + public bool IsWarnEnabled => InternalLogger.IsWarnEnabled; - public ILogger Logger - { - get - { - return logger.Logger; - } - } + public ILogger Logger => InternalLogger.Logger; public void Debug(object message) { - logger.Debug(message); + InternalLogger.Debug(message); } public void Debug(object message, Exception exception) { - logger.Debug(message, exception); + InternalLogger.Debug(message, exception); } public void DebugFormat(string format, params object[] args) { - logger.DebugFormat(format, args); + InternalLogger.DebugFormat(format, args); } public void DebugFormat(string format, object arg0) { - logger.DebugFormat(format, arg0); + InternalLogger.DebugFormat(format, arg0); } public void DebugFormat(string format, object arg0, object arg1) { - logger.DebugFormat(format, arg0, arg1); + InternalLogger.DebugFormat(format, arg0, arg1); } public void DebugFormat(IFormatProvider provider, string format, - params object[] args) + params object[] args) { - logger.DebugFormat(provider, format, args); + InternalLogger.DebugFormat(provider, format, args); } public void DebugFormat(string format, object arg0, object arg1, - object arg2) + object arg2) { - logger.DebugFormat(format, arg0, arg1, arg2); + InternalLogger.DebugFormat(format, arg0, arg1, arg2); } public void Error(object message) { - logger.Error(message); + InternalLogger.Error(message); } public void Error(object message, Exception exception) { - logger.Error(message, exception); + InternalLogger.Error(message, exception); } public void ErrorFormat(string format, params object[] args) { - logger.ErrorFormat(format, args); + InternalLogger.ErrorFormat(format, args); } public void ErrorFormat(string format, object arg0) { - logger.ErrorFormat(format, arg0); + InternalLogger.ErrorFormat(format, arg0); } public void ErrorFormat(string format, object arg0, object arg1) { - logger.ErrorFormat(format, arg0, arg1); + InternalLogger.ErrorFormat(format, arg0, arg1); } public void ErrorFormat(IFormatProvider provider, string format, - params object[] args) + params object[] args) { - logger.ErrorFormat(provider, format, args); + InternalLogger.ErrorFormat(provider, format, args); } public void ErrorFormat(string format, object arg0, object arg1, - object arg2) + object arg2) { - logger.ErrorFormat(format, arg0, arg1, arg2); + InternalLogger.ErrorFormat(format, arg0, arg1, arg2); } public void Fatal(object message) { - logger.Fatal(message); + InternalLogger.Fatal(message); } public void Fatal(object message, Exception exception) { - logger.Fatal(message, exception); + InternalLogger.Fatal(message, exception); } public void FatalFormat(string format, params object[] args) { - logger.FatalFormat(format, args); + InternalLogger.FatalFormat(format, args); } public void FatalFormat(string format, object arg0) { - logger.FatalFormat(format, arg0); + InternalLogger.FatalFormat(format, arg0); } public void FatalFormat(string format, object arg0, object arg1) { - logger.FatalFormat(format, arg0, arg1); + InternalLogger.FatalFormat(format, arg0, arg1); } public void FatalFormat(IFormatProvider provider, string format, - params object[] args) + params object[] args) { - logger.FatalFormat(provider, format, args); + InternalLogger.FatalFormat(provider, format, args); } public void FatalFormat(string format, object arg0, object arg1, - object arg2) + object arg2) { - logger.FatalFormat(format, arg0, arg1, arg2); + InternalLogger.FatalFormat(format, arg0, arg1, arg2); } public void Info(object message) { - logger.Info(message); + InternalLogger.Info(message); } public void Info(object message, Exception exception) { - logger.Info(message, exception); + InternalLogger.Info(message, exception); } public void InfoFormat(string format, params object[] args) { - logger.InfoFormat(format, args); + InternalLogger.InfoFormat(format, args); } public void InfoFormat(string format, object arg0) { - logger.InfoFormat(format, arg0); + InternalLogger.InfoFormat(format, arg0); } public void InfoFormat(string format, object arg0, object arg1) { - logger.InfoFormat(format, arg0, arg1); + InternalLogger.InfoFormat(format, arg0, arg1); } public void InfoFormat(IFormatProvider provider, string format, - params object[] args) + params object[] args) { - logger.InfoFormat(provider, format, args); + InternalLogger.InfoFormat(provider, format, args); } public void InfoFormat(string format, object arg0, object arg1, - object arg2) + object arg2) { - logger.InfoFormat(format, arg0, arg1, arg2); + InternalLogger.InfoFormat(format, arg0, arg1, arg2); } - public void Notice(object message) + public void Warn(object message) { - Logger.Log(GetType(), Level.Notice, message, null); + InternalLogger.Warn(message); } - public void Notice(object message, Exception exception) + public void Warn(object message, Exception exception) { - Logger.Log(GetType(), Level.Notice, message, exception); + InternalLogger.Warn(message, exception); } - public void NoticeFormat(string format, params object[] args) + public void WarnFormat(string format, params object[] args) { - Logger.Log(GetType(), Level.Notice, string.Format(format, args), null); + InternalLogger.WarnFormat(format, args); } - public void NoticeFormat(string format, object arg0) + public void WarnFormat(string format, object arg0) { - Logger.Log(GetType(), Level.Notice, string.Format(format, arg0), null); + InternalLogger.WarnFormat(format, arg0); } - public void NoticeFormat(string format, object arg0, object arg1) + public void WarnFormat(string format, object arg0, object arg1) { - Logger.Log( - GetType(), Level.Notice, string.Format(format, arg0, arg1), null); + InternalLogger.WarnFormat(format, arg0, arg1); } - public void NoticeFormat(IFormatProvider provider, string format, - params object[] args) + public void WarnFormat(IFormatProvider provider, string format, + params object[] args) { - Logger.Log( - GetType(), Level.Notice, string.Format(provider, format, args), null); + InternalLogger.WarnFormat(provider, format, args); } - public void NoticeFormat(string format, object arg0, object arg1, - object arg2) + public void WarnFormat(string format, object arg0, object arg1, + object arg2) { - Logger.Log( - GetType(), Level.Notice, string.Format(format, arg0, arg1, arg2), - null); + InternalLogger.WarnFormat(format, arg0, arg1, arg2); } - public void Warn(object message) + public void Notice(object message) { - logger.Warn(message); + Logger.Log(GetType(), Level.Notice, message, null); } - public void Warn(object message, Exception exception) + public void Notice(object message, Exception exception) { - logger.Warn(message, exception); + Logger.Log(GetType(), Level.Notice, message, exception); } - public void WarnFormat(string format, params object[] args) + public void NoticeFormat(string format, params object[] args) { - logger.WarnFormat(format, args); + Logger.Log(GetType(), Level.Notice, string.Format(format, args), null); } - public void WarnFormat(string format, object arg0) + public void NoticeFormat(string format, object arg0) { - logger.WarnFormat(format, arg0); + Logger.Log(GetType(), Level.Notice, string.Format(format, arg0), null); } - public void WarnFormat(string format, object arg0, object arg1) + public void NoticeFormat(string format, object arg0, object arg1) { - logger.WarnFormat(format, arg0, arg1); + Logger.Log( + GetType(), Level.Notice, string.Format(format, arg0, arg1), null); } - public void WarnFormat(IFormatProvider provider, string format, - params object[] args) + public void NoticeFormat(IFormatProvider provider, string format, + params object[] args) { - logger.WarnFormat(provider, format, args); + Logger.Log( + GetType(), Level.Notice, string.Format(provider, format, args), null); } - public void WarnFormat(string format, object arg0, object arg1, - object arg2) + public void NoticeFormat(string format, object arg0, object arg1, + object arg2) { - logger.WarnFormat(format, arg0, arg1, arg2); + Logger.Log( + GetType(), Level.Notice, string.Format(format, arg0, arg1, arg2), + null); } } } diff --git a/util/MoreDom.cs b/util/MoreDom.cs index 3a7a7239..6d8b2393 100644 --- a/util/MoreDom.cs +++ b/util/MoreDom.cs @@ -11,7 +11,7 @@ public static XmlElement EL(this XmlDocument doc, string name) } public static XmlElement EL(this XmlDocument doc, string name, - AttributeCollection attributes) + AttributeCollection attributes) { return EL(doc, name, attributes, null); } @@ -22,10 +22,10 @@ public static XmlElement EL(this XmlDocument doc, string name, string text) } public static XmlElement EL(this XmlDocument doc, string name, - AttributeCollection attributes, string text) + AttributeCollection attributes, string text) { if (doc == null) { - throw new ArgumentNullException("doc"); + throw new ArgumentNullException(nameof(doc)); } var rv = doc.CreateElement(name); if (text != null) { diff --git a/util/NaturalStringComparer.cs b/util/NaturalStringComparer.cs index 497971f3..435e2580 100644 --- a/util/NaturalStringComparer.cs +++ b/util/NaturalStringComparer.cs @@ -8,7 +8,7 @@ namespace NMaier.SimpleDlna.Utilities public sealed class NaturalStringComparer : StringComparer { private static readonly StringComparer comparer = - StringComparer.CurrentCultureIgnoreCase; + CurrentCultureIgnoreCase; private static readonly bool platformSupport = HasPlatformSupport(); @@ -26,6 +26,8 @@ public NaturalStringComparer(bool stemBase) this.stemBase = stemBase; } + public static IComparer Comparer { get; } = new NaturalStringComparer(); + private static bool HasPlatformSupport() { try { @@ -39,8 +41,10 @@ private static bool HasPlatformSupport() private BaseSortPart[] Split(string str) { BaseSortPart[] rv; - if (partsCache.TryGetValue(str, out rv)) { - return rv; + lock (partsCache) { + if (partsCache.TryGetValue(str, out rv)) { + return rv; + } } var parts = new List(); @@ -92,7 +96,7 @@ public override int Compare(string x, string y) if (platformSupport) { return SafeNativeMethods.StrCmpLogicalW(x, y); } - if (x == y || StringComparer.InvariantCulture.Compare(x, y) == 0) { + if (x == y || InvariantCulture.Compare(x, y) == 0) { return 0; } var p1 = Split(x); diff --git a/util/NumericSortPart.cs b/util/NumericSortPart.cs index f182e085..841021f6 100644 --- a/util/NumericSortPart.cs +++ b/util/NumericSortPart.cs @@ -17,7 +17,7 @@ public NumericSortPart(string s) public int CompareTo(NumericSortPart other) { if (other == null) { - throw new ArgumentNullException("other"); + throw new ArgumentNullException(nameof(other)); } var rv = val.CompareTo(other.val); if (rv == 0) { diff --git a/util/ProductInformation.cs b/util/ProductInformation.cs index fdb65ce6..5eeb09e4 100644 --- a/util/ProductInformation.cs +++ b/util/ProductInformation.cs @@ -1,4 +1,5 @@ -using System.Reflection; +using System.IO; +using System.Reflection; namespace NMaier.SimpleDlna.Utilities { @@ -6,10 +7,9 @@ public static class ProductInformation { public static string Company { - get - { + get { var attributes = Assembly.GetEntryAssembly().GetCustomAttributes( - typeof(AssemblyCompanyAttribute), false); + typeof (AssemblyCompanyAttribute), false); if (attributes.Length == 0) { return string.Empty; } @@ -19,10 +19,9 @@ public static string Company public static string Copyright { - get - { + get { var attributes = Assembly.GetEntryAssembly().GetCustomAttributes( - typeof(AssemblyCopyrightAttribute), false); + typeof (AssemblyCopyrightAttribute), false); if (attributes.Length == 0) { return string.Empty; } @@ -32,10 +31,9 @@ public static string Copyright public static string ProductVersion { - get - { + get { var attributes = Assembly.GetExecutingAssembly().GetCustomAttributes( - typeof(AssemblyInformationalVersionAttribute), false); + typeof (AssemblyInformationalVersionAttribute), false); if (attributes.Length == 0) { return string.Empty; } @@ -47,17 +45,16 @@ public static string ProductVersion public static string Title { - get - { + get { var attributes = Assembly.GetEntryAssembly().GetCustomAttributes( - typeof(AssemblyTitleAttribute), false); + typeof (AssemblyTitleAttribute), false); if (attributes.Length > 0) { var titleAttribute = (AssemblyTitleAttribute)attributes[0]; if (!string.IsNullOrWhiteSpace(titleAttribute.Title)) { return titleAttribute.Title; } } - return System.IO.Path.GetFileNameWithoutExtension( + return Path.GetFileNameWithoutExtension( Assembly.GetExecutingAssembly().CodeBase); } } diff --git a/util/Repository.cs b/util/Repository.cs index 7dc90517..d4f8c06c 100644 --- a/util/Repository.cs +++ b/util/Repository.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; namespace NMaier.SimpleDlna.Utilities { @@ -11,38 +12,34 @@ public abstract class Repository private static Dictionary BuildRepository() { - var items = new Dictionary(); - var type = typeof(TInterface).Name; - var a = typeof(TInterface).Assembly; - foreach (Type t in a.GetTypes()) { + var found = new Dictionary(StringComparer.CurrentCultureIgnoreCase); + var type = typeof (TInterface).Name; + var a = typeof (TInterface).Assembly; + foreach (var t in a.GetTypes()) { if (t.GetInterface(type) == null) { continue; } - var ctor = t.GetConstructor(new Type[] { }); + var ctor = t.GetConstructor(new Type[] {}); if (ctor == null) { continue; } try { - var item = ctor.Invoke(new object[] { }) as TInterface; + var item = ctor.Invoke(new object[] {}) as TInterface; if (item == null) { continue; } - items.Add(item.Name.ToUpperInvariant(), item); + found.Add(item.Name, item); } catch (Exception) { - continue; + // ignored } } - return items; + return found; } public static IDictionary ListItems() { - var rv = new Dictionary(); - foreach (var v in items.Values) { - rv.Add(v.Name, v); - } - return rv; + return items.Values.ToDictionary(v => v.Name, v => v); } public static TInterface Lookup(string name) @@ -50,44 +47,36 @@ public static TInterface Lookup(string name) if (string.IsNullOrWhiteSpace(name)) { throw new ArgumentException( "Invalid repository name", - "name"); + nameof(name)); } - var n_p = name.Split(new char[] { ':' }, 2); - name = n_p[0].ToUpperInvariant().Trim(); - var result = (TInterface)null; + var argsplit = name.Split(new[] {':'}, 2); + name = argsplit[0].ToUpperInvariant().Trim(); + TInterface result; if (!items.TryGetValue(name, out result)) { throw new RepositoryLookupException(name); } - if (n_p.Length == 1) { + if (argsplit.Length == 1 || !(result is IConfigurable)) { return result; } - - var ctor = result.GetType().GetConstructor(new Type[] { }); + var parameters = new ConfigParameters(argsplit[1]); + if (parameters.Count == 0) { + return result; + } + var ctor = result.GetType().GetConstructor(new Type[] {}); if (ctor == null) { throw new RepositoryLookupException(name); } - var parameters = new AttributeCollection(); - foreach (var p in n_p[1].Split(',')) { - var k_v = p.Split(new char[] { '=' }, 2); - if (k_v.Length == 2) { - parameters.Add(k_v[0], k_v[1]); - } - else { - parameters.Add(k_v[0], null); - } - } try { - var item = ctor.Invoke(new object[] { }) as TInterface; + var item = ctor.Invoke(new object[] {}) as TInterface; if (item == null) { throw new RepositoryLookupException(name); } - item.SetParameters(parameters); + var configItem = item as IConfigurable; + configItem?.SetParameters(parameters); return item; } catch (Exception ex) { - throw new RepositoryLookupException(string.Format( - "Cannot construct repository item: {0}", - ex.Message), ex); + throw new RepositoryLookupException($"Cannot construct repository item: {ex.Message}", ex); } } } diff --git a/util/RepositoryLookupException.cs b/util/RepositoryLookupException.cs index 8ca08eb6..7cdb7d96 100644 --- a/util/RepositoryLookupException.cs +++ b/util/RepositoryLookupException.cs @@ -7,7 +7,7 @@ namespace NMaier.SimpleDlna.Utilities public sealed class RepositoryLookupException : ArgumentException { private RepositoryLookupException(SerializationInfo info, - StreamingContext context) + StreamingContext context) : base(info, context) { } @@ -17,7 +17,7 @@ public RepositoryLookupException() } public RepositoryLookupException(string key) - : base(String.Format("Failed to lookup {0}", key)) + : base($"Failed to lookup {key}") { Key = key; } @@ -27,16 +27,6 @@ public RepositoryLookupException(string message, Exception inner) { } - public string Key - { - get; - private set; - } - - public override void GetObjectData(SerializationInfo info, - StreamingContext context) - { - base.GetObjectData(info, context); - } + public string Key { get; private set; } } } diff --git a/util/SafeNativeMethods.cs b/util/SafeNativeMethods.cs index dce96af2..ee1fd0c4 100644 --- a/util/SafeNativeMethods.cs +++ b/util/SafeNativeMethods.cs @@ -9,11 +9,11 @@ internal static class SafeNativeMethods internal static extern int StrCmpLogicalW(string psz1, string psz2); [DllImport("iphlpapi.dll")] - public static extern UInt32 SendARP( - UInt32 DestIP, UInt32 SrcIP, [Out] byte[] pMacAddr, - ref UInt32 PhyAddrLen); + public static extern uint SendARP( + uint destIP, uint srcIP, [Out] byte[] pMacAddr, + ref uint phyAddrLen); [DllImport("libc", CharSet = CharSet.Ansi)] - public static extern Int32 uname(IntPtr buf); + public static extern int uname(IntPtr buf); } } diff --git a/util/Sqlite.cs b/util/Sqlite.cs index 434b8af2..6f93b111 100644 --- a/util/Sqlite.cs +++ b/util/Sqlite.cs @@ -1,8 +1,9 @@ using System; using System.Data; +using System.Data.SQLite; using System.IO; using System.Reflection; -using System.Runtime.InteropServices; +using log4net; namespace NMaier.SimpleDlna.Utilities { @@ -10,7 +11,7 @@ public static class Sqlite { private const int GROW_SIZE = 1 << 24; - private static Action clearPool = null; + private static Action clearPool; private static IDbConnection GetDatabaseConnectionMono(string cs) { @@ -25,8 +26,11 @@ private static IDbConnection GetDatabaseConnectionMono(string cs) } var dbconn = monoSqlite.GetType( "Mono.Data.Sqlite.SqliteConnection"); - var ctor = dbconn.GetConstructor(new[] { typeof(string) }); - var rv = ctor.Invoke(new[] { cs }) as IDbConnection; + var ctor = dbconn.GetConstructor(new[] {typeof (string)}); + if (ctor == null) { + throw new ArgumentException("No mono SQLite found"); + } + var rv = ctor.Invoke(new object[] {cs}) as IDbConnection; if (rv == null) { throw new ArgumentException("no connection"); } @@ -35,9 +39,7 @@ private static IDbConnection GetDatabaseConnectionMono(string cs) var cp = dbconn.GetMethod("ClearPool"); clearPool = conn => { - if (cp != null) { - cp.Invoke(null, new object[] { conn }); - } + cp?.Invoke(null, new object[] {conn}); }; } return rv; @@ -45,7 +47,7 @@ private static IDbConnection GetDatabaseConnectionMono(string cs) private static IDbConnection GetDatabaseConnectionSDS(string cs) { - var rv = new System.Data.SQLite.SQLiteConnection(cs); + var rv = new SQLiteConnection(cs); if (rv == null) { throw new ArgumentException("no connection"); } @@ -55,15 +57,15 @@ private static IDbConnection GetDatabaseConnectionSDS(string cs) rv.SetChunkSize(GROW_SIZE); } catch (Exception ex) { - log4net.LogManager.GetLogger(typeof(Sqlite)).Error( + LogManager.GetLogger(typeof (Sqlite)).Error( "Failed to sqlite control", ex); } if (clearPool == null) { clearPool = conn => { - System.Data.SQLite.SQLiteConnection.ClearPool( - conn as System.Data.SQLite.SQLiteConnection); + SQLiteConnection.ClearPool( + conn as SQLiteConnection); }; } return rv; @@ -71,29 +73,23 @@ private static IDbConnection GetDatabaseConnectionSDS(string cs) public static void ClearPool(IDbConnection conn) { - if (clearPool != null) { - clearPool(conn); - } + clearPool?.Invoke(conn); } public static IDbConnection GetDatabaseConnection(FileInfo database) { if (database == null) { - throw new ArgumentNullException("database"); + throw new ArgumentNullException(nameof(database)); } if (database.Exists && database.IsReadOnly) { throw new ArgumentException( "Database file is read only", - "database" + nameof(database) ); } - var cs = string.Format( - "Uri=file:{0};Pooling=true;Synchronous=Off;journal mode=TRUNCATE;DefaultTimeout=5", - database.FullName - ); + var cs = $"Uri=file:{database.FullName};Pooling=true;Synchronous=Off;journal mode=TRUNCATE;DefaultTimeout=5"; - if (Utilities.SystemInformation.IsRunningOnMono()) - { + if (SystemInformation.IsRunningOnMono()) { return GetDatabaseConnectionMono(cs); } return GetDatabaseConnectionSDS(cs); diff --git a/util/StreamManager.cs b/util/StreamManager.cs new file mode 100644 index 00000000..8cc14848 --- /dev/null +++ b/util/StreamManager.cs @@ -0,0 +1,20 @@ +using System.IO; +using Microsoft.IO; + +namespace NMaier.SimpleDlna.Utilities +{ + public static class StreamManager + { + private static readonly RecyclableMemoryStreamManager manager = new RecyclableMemoryStreamManager(); + + public static MemoryStream GetStream() + { + return manager.GetStream(); + } + + public static MemoryStream GetStream(string tag) + { + return manager.GetStream(tag); + } + } +} diff --git a/util/StreamPump.cs b/util/StreamPump.cs index 0a70d879..f28ded2e 100644 --- a/util/StreamPump.cs +++ b/util/StreamPump.cs @@ -18,18 +18,18 @@ public StreamPump(Stream inputStream, Stream outputStream, int bufferSize) Output = outputStream; } - public Stream Input { get; private set; } + public Stream Input { get; } - public Stream Output { get; private set; } + public Stream Output { get; } + + public void Dispose() + { + sem.Dispose(); + } private void Finish(StreamPumpResult result, StreamPumpCallback callback) { - if (callback != null) { - callback.BeginInvoke(this, result, ir => - { - callback.EndInvoke(ir); - }, null); - } + callback?.BeginInvoke(this, result, callback.EndInvoke, null); try { sem.Release(); } @@ -37,15 +37,10 @@ private void Finish(StreamPumpResult result, StreamPumpCallback callback) // ignore } catch (Exception ex) { - LogManager.GetLogger(typeof(StreamPump)).Error(ex.Message, ex); + LogManager.GetLogger(typeof (StreamPump)).Error(ex.Message, ex); } } - public void Dispose() - { - sem.Dispose(); - } - public void Pump(StreamPumpCallback callback) { try { diff --git a/util/StreamPumpCallback.cs b/util/StreamPumpCallback.cs index 1ed416a7..4c86c470 100644 --- a/util/StreamPumpCallback.cs +++ b/util/StreamPumpCallback.cs @@ -1,5 +1,4 @@ namespace NMaier.SimpleDlna.Utilities { - public delegate void StreamPumpCallback( - StreamPump pump, StreamPumpResult result); + public delegate void StreamPumpCallback(StreamPump pump, StreamPumpResult result); } diff --git a/util/StreamPumpResult.cs b/util/StreamPumpResult.cs index a618ceb1..d46fb292 100644 --- a/util/StreamPumpResult.cs +++ b/util/StreamPumpResult.cs @@ -4,5 +4,5 @@ public enum StreamPumpResult { Aborted, Delivered - }; + } } diff --git a/util/StringSortPart.cs b/util/StringSortPart.cs index b1dae762..9db0125b 100644 --- a/util/StringSortPart.cs +++ b/util/StringSortPart.cs @@ -3,7 +3,7 @@ namespace NMaier.SimpleDlna.Utilities { internal sealed class StringSortPart - : BaseSortPart, IComparable + : BaseSortPart, IComparable { private readonly StringComparer comparer; @@ -18,7 +18,7 @@ internal StringSortPart(string str, StringComparer comparer) public int CompareTo(StringSortPart other) { if (other == null) { - throw new ArgumentNullException("other"); + throw new ArgumentNullException(nameof(other)); } return comparer.Compare(str, other.str); } diff --git a/util/SystemInformation.cs b/util/SystemInformation.cs index d5943506..c0d024f8 100644 --- a/util/SystemInformation.cs +++ b/util/SystemInformation.cs @@ -5,7 +5,7 @@ namespace NMaier.SimpleDlna.Utilities public static class SystemInformation { /// - /// Returns true if applicaton is running under mono + /// Returns true if applicaton is running under mono /// public static bool IsRunningOnMono() { diff --git a/util/packages.config b/util/packages.config index 33555e99..8fa0fb80 100644 --- a/util/packages.config +++ b/util/packages.config @@ -1,5 +1,7 @@  - - + + + + \ No newline at end of file diff --git a/util/util.csproj b/util/util.csproj index 7b7b50d8..f9c9b3b9 100644 --- a/util/util.csproj +++ b/util/util.csproj @@ -1,5 +1,5 @@  - + Debug AnyCPU @@ -10,11 +10,14 @@ Properties NMaier.SimpleDlna.Utilities SimpleDlna.Utilities - v4.0 + v4.5.1 512 - Client + + ..\ true + + true @@ -24,6 +27,7 @@ DEBUG;TRACE prompt 4 + false pdbonly @@ -34,6 +38,7 @@ 4 false ..\sdlna.ruleset + false true @@ -42,15 +47,27 @@ sdlna.key.snk + + ..\packages\EntityFramework.6.0.0\lib\net45\EntityFramework.dll + True + + + ..\packages\EntityFramework.6.0.0\lib\net45\EntityFramework.SqlServer.dll + True + - False - ..\packages\log4net.2.0.5\lib\net40-client\log4net.dll + ..\packages\log4net.2.0.5\lib\net45-full\log4net.dll + True + + + ..\packages\Microsoft.IO.RecyclableMemoryStream.1.1.0.0\lib\net45\Microsoft.IO.RecyclableMemoryStream.dll + - - False - ..\packages\System.Data.SQLite.Core.1.0.93.0\lib\net40\System.Data.SQLite.dll + + ..\packages\System.Data.SQLite.Core.1.0.103\lib\net451\System.Data.SQLite.dll + True @@ -63,11 +80,13 @@ + + @@ -82,6 +101,7 @@ + @@ -93,14 +113,6 @@ - - - Always - - - Always - - @@ -108,7 +120,9 @@ This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + +