diff --git a/.gitignore b/.gitignore index 9560bb6b..bd5add46 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ setup/Release setup/*.cmd pages/ cov-int* +/UpgradeLog.htm diff --git a/FileStoreRaptorDB/FileStore.cs b/FileStoreRaptorDB/FileStore.cs new file mode 100644 index 00000000..0d110a95 --- /dev/null +++ b/FileStoreRaptorDB/FileStore.cs @@ -0,0 +1,92 @@ +using NMaier.SimpleDlna.FileMediaServer; +using NMaier.SimpleDlna.Utilities; +using System; +using System.Linq; +using System.IO; +using RaptorDB; + +namespace NMaier.SimpleDlna.FileStore.RaptorDB +{///Logging, + public sealed class FileStore : IFileStore, IDisposable + { + public string Description + { + get + { + return "RaptorDB file cache"; + } + } + + public string Name + { + get + { + return "RaptorDB"; + } + } + + FileInfo _storeFile; + public string StoreFile { get { return _storeFile.FullName; } } + + private static readonly ILogging _logger = Logging.GetLogger(); + + public void Dispose() + { + _db.Shutdown(); + _db.Dispose(); + } + + public override string ToString() + { + return string.Format("{0} - {1}", Name, Description); + } + + public bool HasCover(IStoreItem file) + { + return MaybeGetCover(file) != null; + } + + RaptorDB _db; + + public const string DefaultFileName = "sdlna.cache.raptor.db"; + + public void Init() + { + var storePath = _parameters.Keys.Contains("file") ? Convert.ToString(_parameters.GetValuesForKey("file").First()):DefaultFileName; + if (!Path.IsPathRooted(storePath)) storePath = DataPath.Combine(storePath); + _storeFile = new FileInfo(storePath); + _logger.NoticeFormat("Opening [{0}] Store...", _storeFile); + _db = RaptorDB.Open(_storeFile.FullName, false); + } + + public const string CoverPrefix = "Cover$$"; + + public byte[] MaybeGetCover(IStoreItem file) + { + byte[] data; + _db.Get(CoverPrefix + file.Item.FullName, out data); + return data; + } + + public byte[] MaybeGetFile(FileInfo info) + { + byte[] data; + _db.Get(info.FullName, out data); + return data; + } + + public void MaybeStoreFile(IStoreItem file, byte[] data, byte[] coverData) + { + _logger.NoticeFormat("MaybeStoreFile [{0}][{1}][{2}]", file.Item.Name, (data == null)?0:data.Length, (coverData == null)?0:coverData.Length); + _db.Set(file.Item.FullName, data); + _db.Set(CoverPrefix + file.Item.FullName, coverData); + } + + AttributeCollection _parameters = new AttributeCollection(); + + public void SetParameters(AttributeCollection parameters) + { + _parameters = parameters; + } + } +} diff --git a/FileStoreRaptorDB/FileStoreRaptorDB.csproj b/FileStoreRaptorDB/FileStoreRaptorDB.csproj new file mode 100644 index 00000000..bc13cc51 --- /dev/null +++ b/FileStoreRaptorDB/FileStoreRaptorDB.csproj @@ -0,0 +1,77 @@ + + + + + Debug + AnyCPU + {6961F1C2-41E9-4E7F-8E88-7D4A259B3DF8} + Library + Properties + NMaier.SimpleDlna.FileStore.RaptorDB + SimpleDlna.FileStore.RaptorDB + v4.0 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + none + true + bin\Release\ + TRACE + prompt + 4 + + + false + + + sdlna.key.snk + + + + ..\packages\RaptorDB.2.6\lib\net40\RaptorDB.dll + True + + + + + + + + + + + + + + + + {50e06b21-e11a-42f0-81e2-0911e771e861} + fsserver + + + {a8960a7a-887c-40d7-9632-002e94bfc830} + util + + + + + + + + + \ No newline at end of file diff --git a/FileStoreRaptorDB/Properties/AssemblyInfo.cs b/FileStoreRaptorDB/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..cfc71ae8 --- /dev/null +++ b/FileStoreRaptorDB/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +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("FileStoreRaptorDB")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("FileStoreRaptorDB")] +[assembly: AssemblyCopyright("Copyright © 2015")] +[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("6961f1c2-41e9-4e7f-8e88-7d4a259b3df8")] + +// 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.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/FileStoreRaptorDB/packages.config b/FileStoreRaptorDB/packages.config new file mode 100644 index 00000000..e687bd46 --- /dev/null +++ b/FileStoreRaptorDB/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/FileStoreRaptorDB/sdlna.key.snk b/FileStoreRaptorDB/sdlna.key.snk new file mode 100644 index 00000000..7e30ff02 Binary files /dev/null and b/FileStoreRaptorDB/sdlna.key.snk differ diff --git a/util/App.config b/FileStoreSQLite/App.config similarity index 53% rename from util/App.config rename to FileStoreSQLite/App.config index 5e4eee9c..764bdd32 100644 --- a/util/App.config +++ b/FileStoreSQLite/App.config @@ -1,19 +1,24 @@  +
- - + - + - + + + + + + \ No newline at end of file diff --git a/fsserver/Files/FileStore.cs b/FileStoreSQLite/FileStore.cs similarity index 60% rename from fsserver/Files/FileStore.cs rename to FileStoreSQLite/FileStore.cs index 7d1d0437..0b58756c 100644 --- a/fsserver/Files/FileStore.cs +++ b/FileStoreSQLite/FileStore.cs @@ -1,63 +1,81 @@ -using NMaier.SimpleDlna.Server; using NMaier.SimpleDlna.Utilities; +using NMaier.SimpleDlna.FileMediaServer; using System; using System.Data; using System.Data.Common; using System.IO; using System.Reflection; -using System.Runtime.Serialization; -using System.Runtime.Serialization.Formatters; -using System.Runtime.Serialization.Formatters.Binary; using System.Threading; +using System.Linq; -namespace NMaier.SimpleDlna.FileMediaServer -{ - internal sealed class FileStore : Logging, IDisposable +namespace NMaier.SimpleDlna.FileStore.SQLite +{//Logging, + public class FileStore : IFileStore { private const uint SCHEMA = 0x20140818; - private readonly IDbConnection connection; + private IDbConnection connection; - private readonly IDbCommand insert; + private IDbCommand insert; - private readonly IDbDataParameter insertCover; + private IDbDataParameter insertCover; - private readonly IDbDataParameter insertData; + private IDbDataParameter insertData; - private readonly IDbDataParameter insertKey; + private IDbDataParameter insertKey; - private readonly IDbDataParameter insertSize; + private IDbDataParameter insertSize; - private readonly IDbDataParameter insertTime; + private IDbDataParameter insertTime; - private readonly IDbCommand select; + private IDbCommand select; - private readonly IDbCommand selectCover; + private IDbCommand selectCover; - private readonly IDbDataParameter selectCoverKey; + private IDbDataParameter selectCoverKey; - private readonly IDbDataParameter selectCoverSize; + private IDbDataParameter selectCoverSize; - private readonly IDbDataParameter selectCoverTime; + private IDbDataParameter selectCoverTime; - private readonly IDbDataParameter selectKey; + private IDbDataParameter selectKey; - private readonly IDbDataParameter selectSize; + private IDbDataParameter selectSize; - private readonly IDbDataParameter selectTime; + private IDbDataParameter selectTime; private static readonly FileStoreVacuumer vacuumer = new FileStoreVacuumer(); + protected static readonly ILogging _logger = Logging.GetLogger(); + private readonly static object globalLock = new object(); - public readonly FileInfo StoreFile; + FileInfo _storeFile; + public string StoreFile { get { return _storeFile.FullName; } } - internal FileStore(FileInfo storeFile) + public string Description { - StoreFile = storeFile; + get + { + return "SQLite database file cache"; + } + } - OpenConnection(storeFile, out connection); + public string Name + { + get + { + return "SQLite"; + } + } + + public const string DefaultFileName = "sdlna.cache.sqlite"; + + public void Init() { + _storeFile = new FileInfo(_parameters.Keys.Contains("file") ? Convert.ToString(_parameters.GetValuesForKey("file").First()):DefaultFileName); + + OpenConnection(_storeFile, out connection); SetupDatabase(); select = connection.CreateCommand(); @@ -100,11 +118,15 @@ internal FileStore(FileInfo storeFile) insertCover.DbType = DbType.Binary; insertCover.ParameterName = "@cover"; - InfoFormat("FileStore at {0} is ready", storeFile.FullName); + _logger.InfoFormat("FileStore at {0} is ready", StoreFile); vacuumer.Add(connection); } + public FileStore() + { + } + private void OpenConnection(FileInfo storeFile, out IDbConnection newConnection) { @@ -120,7 +142,7 @@ private void OpenConnection(FileInfo storeFile, } } catch (Exception ex) { - NoticeFormat( + _logger.NoticeFormat( "Recreating database, schema update. ({0})", ex.Message ); @@ -170,7 +192,7 @@ private void SetupDatabase() } } - internal bool HasCover(BaseFile file) + public bool HasCover(IStoreItem file) { if (connection == null) { return false; @@ -186,105 +208,108 @@ internal bool HasCover(BaseFile file) return (data as byte[]) != null; } catch (DbException ex) { - Error("Failed to lookup file cover existence from store", ex); + _logger.Error("Failed to lookup file cover existence from store", ex); return false; } } } - internal Cover MaybeGetCover(BaseFile file) + public byte[] MaybeGetCover(IStoreItem file) { if (connection == null) { return null; } var info = file.Item; - byte[] data; + //byte[] data; lock (connection) { selectCoverKey.Value = info.FullName; selectCoverSize.Value = info.Length; selectCoverTime.Value = info.LastWriteTimeUtc.Ticks; try { - data = selectCover.ExecuteScalar() as byte[]; + return selectCover.ExecuteScalar() as byte[]; } catch (DbException ex) { - Error("Failed to lookup file cover from store", ex); + _logger.Error("Failed to lookup file cover from store", ex); return null; } } - if (data == null) { - return null; - } - try { - using (var s = new MemoryStream(data)) { - var ctx = new StreamingContext( - StreamingContextStates.Persistence, - new DeserializeInfo(null, info, DlnaMime.ImageJPEG) - ); - var formatter = new BinaryFormatter(null, ctx) { - TypeFormat = FormatterTypeStyle.TypesWhenNeeded, - AssemblyFormat = FormatterAssemblyStyle.Simple - }; - var rv = formatter.Deserialize(s) as Cover; - return rv; - } - } - catch (SerializationException ex) { - Debug("Failed to deserialize a cover", ex); - return null; - } - catch (Exception ex) { - Fatal("Failed to deserialize a cover", ex); - throw; - } + //if (data == null) { + // return null; + //} + //try { + // using (var s = new MemoryStream(data)) { + // var ctx = new StreamingContext( + // StreamingContextStates.Persistence, + // new DeserializeInfo(null, info, DlnaMime.ImageJPEG) + // ); + // var formatter = new BinaryFormatter(null, ctx) { + // TypeFormat = FormatterTypeStyle.TypesWhenNeeded, + // AssemblyFormat = FormatterAssemblyStyle.Simple + // }; + // var rv = formatter.Deserialize(s) as Cover; + // return rv; + // } + //} + //catch (SerializationException ex) { + // Debug("Failed to deserialize a cover", ex); + // return null; + //} + //catch (Exception ex) { + // Fatal("Failed to deserialize a cover", ex); + // throw; + //} } - internal BaseFile MaybeGetFile(FileServer server, FileInfo info, - DlnaMime type) + public byte[] MaybeGetFile( + //FileServer server, + FileInfo info//, + //DlnaMime type + ) { if (connection == null) { return null; } - byte[] data; + //byte[] data; lock (connection) { selectKey.Value = info.FullName; selectSize.Value = info.Length; selectTime.Value = info.LastWriteTimeUtc.Ticks; try { - data = select.ExecuteScalar() as byte[]; + return select.ExecuteScalar() as byte[]; } catch (DbException ex) { - Error("Failed to lookup file from store", ex); + _logger.Error("Failed to lookup file from store", ex); return null; } } - if (data == null) { - return null; - } - try { - using (var s = new MemoryStream(data)) { - var ctx = new StreamingContext( - StreamingContextStates.Persistence, - new DeserializeInfo(server, info, type)); - var formatter = new BinaryFormatter(null, ctx) { - TypeFormat = FormatterTypeStyle.TypesWhenNeeded, - AssemblyFormat = FormatterAssemblyStyle.Simple - }; - var rv = formatter.Deserialize(s) as BaseFile; - rv.Item = info; - return rv; - } - } - catch (Exception ex) { - if (ex is TargetInvocationException || ex is SerializationException) { - Debug("Failed to deserialize an item", ex); - return null; - } - throw; - } + //if (data == null) { + // return null; + //} + //try { + // using (var s = new MemoryStream(data)) { + // var ctx = new StreamingContext( + // StreamingContextStates.Persistence, + // new DeserializeInfo(server, info, type)); + // var formatter = new BinaryFormatter(null, ctx) { + // TypeFormat = FormatterTypeStyle.TypesWhenNeeded, + // AssemblyFormat = FormatterAssemblyStyle.Simple + // }; + // var rv = formatter.Deserialize(s) as BaseFile; + // rv.Item = info; + // return rv; + // } + //} + //catch (Exception ex) { + // if (ex is TargetInvocationException || ex is SerializationException) { + // Debug("Failed to deserialize an item", ex); + // return null; + // } + // throw; + //} } - internal void MaybeStoreFile(BaseFile file) + public void MaybeStoreFile(IStoreItem file, byte[] data, byte[] coverData) { if (connection == null) { return; @@ -293,48 +318,27 @@ internal void MaybeStoreFile(BaseFile file) return; } try { - using (var s = new MemoryStream()) { - var ctx = new StreamingContext( - StreamingContextStates.Persistence, - null - ); - var formatter = new BinaryFormatter(null, ctx) { - TypeFormat = FormatterTypeStyle.TypesWhenNeeded, - AssemblyFormat = FormatterAssemblyStyle.Simple - }; - formatter.Serialize(s, file); + lock (connection) { insertKey.Value = file.Item.FullName; insertSize.Value = file.Item.Length; insertTime.Value = file.Item.LastWriteTimeUtc.Ticks; - insertData.Value = s.ToArray(); + insertData.Value = data; - insertCover.Value = null; - try { - var cover = file.MaybeGetCover(); - if (cover != null) { - using (var c = new MemoryStream()) { - formatter.Serialize(c, cover); - insertCover.Value = c.ToArray(); - } - } - } - catch (NotSupportedException) { - // Ignore and store null. - } + insertCover.Value = coverData; try { insert.ExecuteNonQuery(); } catch (DbException ex) { - Error("Failed to put file cover into store", ex); + _logger.Error("Failed to put file cover into store", ex); return; } } - } + } catch (Exception ex) { - Error("Failed to serialize an object of type " + file.GetType(), ex); + _logger.Error("Failed to serialize an object of type " + file.GetType(), ex); throw; } } @@ -353,5 +357,18 @@ public void Dispose() connection.Dispose(); } } + + AttributeCollection _parameters = new AttributeCollection(); + + public void SetParameters(AttributeCollection parameters) + { + _parameters = parameters; + } + + public override string ToString() + { + return string.Format("{0} - {1}", Name, Description); + } + } } diff --git a/FileStoreSQLite/FileStoreSQLite.csproj b/FileStoreSQLite/FileStoreSQLite.csproj new file mode 100644 index 00000000..704760dd --- /dev/null +++ b/FileStoreSQLite/FileStoreSQLite.csproj @@ -0,0 +1,109 @@ + + + + + Debug + AnyCPU + {25741114-7F31-421E-8D2B-357A3155CEE2} + Library + Properties + NMaier.SimpleDlna.FileStore.SQLite + SimpleDlna.FileStore.SQLite + v4.0 + 512 + Client + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + none + true + bin\Release\ + TRACE + prompt + 4 + + + true + + + sdlna.key.snk + + + + ..\packages\EntityFramework.6.0.0\lib\net40\EntityFramework.dll + True + + + ..\packages\EntityFramework.6.0.0\lib\net40\EntityFramework.SqlServer.dll + True + + + + + + ..\packages\System.Data.SQLite.Core.1.0.98.1\lib\net40\System.Data.SQLite.dll + True + + + ..\packages\System.Data.SQLite.EF6.1.0.98.1\lib\net40\System.Data.SQLite.EF6.dll + True + + + ..\packages\System.Data.SQLite.Linq.1.0.98.1\lib\net40\System.Data.SQLite.Linq.dll + True + + + + + + + + + + + + + + + + {50e06b21-e11a-42f0-81e2-0911e771e861} + fsserver + + + {a8960a7a-887c-40d7-9632-002e94bfc830} + util + + + + + Designer + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + \ No newline at end of file diff --git a/fsserver/Files/FileStoreVacuumer.cs b/FileStoreSQLite/FileStoreVacuumer.cs similarity index 98% rename from fsserver/Files/FileStoreVacuumer.cs rename to FileStoreSQLite/FileStoreVacuumer.cs index 57c6e45b..80b50fce 100644 --- a/fsserver/Files/FileStoreVacuumer.cs +++ b/FileStoreSQLite/FileStoreVacuumer.cs @@ -7,7 +7,7 @@ using System.Threading.Tasks; using System.Timers; -namespace NMaier.SimpleDlna.FileMediaServer +namespace NMaier.SimpleDlna.FileStore.SQLite { internal sealed class FileStoreVacuumer : Logging, IDisposable { diff --git a/FileStoreSQLite/Properties/AssemblyInfo.cs b/FileStoreSQLite/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..9f3aa9f7 --- /dev/null +++ b/FileStoreSQLite/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +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("FileStoreSQLite")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("FileStoreSQLite")] +[assembly: AssemblyCopyright("Copyright © 2015")] +[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("25741114-7f31-421e-8d2b-357a3155cee2")] + +// 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.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/util/Sqlite.cs b/FileStoreSQLite/Sqlite.cs similarity index 94% rename from util/Sqlite.cs rename to FileStoreSQLite/Sqlite.cs index 3cc56d2d..ca722d65 100644 --- a/util/Sqlite.cs +++ b/FileStoreSQLite/Sqlite.cs @@ -1,10 +1,10 @@ -using System; +using NMaier.SimpleDlna.Utilities; +using System; using System.Data; using System.IO; using System.Reflection; -using System.Runtime.InteropServices; -namespace NMaier.SimpleDlna.Utilities +namespace NMaier.SimpleDlna.FileStore.SQLite { public static class Sqlite { @@ -55,7 +55,7 @@ private static IDbConnection GetDatabaseConnectionSDS(string cs) rv.SetChunkSize(GROW_SIZE); } catch (Exception ex) { - log4net.LogManager.GetLogger(typeof(Sqlite)).Error( + Logging.GetLogger(typeof(Sqlite)).Error( "Failed to sqlite control", ex); } diff --git a/FileStoreSQLite/packages.config b/FileStoreSQLite/packages.config new file mode 100644 index 00000000..e4c8fd6c --- /dev/null +++ b/FileStoreSQLite/packages.config @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/FileStoreSQLite/sdlna.key.snk b/FileStoreSQLite/sdlna.key.snk new file mode 100644 index 00000000..7e30ff02 Binary files /dev/null and b/FileStoreSQLite/sdlna.key.snk differ diff --git a/NMaier.Windows.Forms/Form.cs b/NMaier.Windows.Forms/Form.cs index 45bbd797..b3d9cb1d 100644 --- a/NMaier.Windows.Forms/Form.cs +++ b/NMaier.Windows.Forms/Form.cs @@ -1,4 +1,3 @@ -using System; using System.ComponentModel; using System.Drawing; using System.Windows.Forms.VisualStyles; diff --git a/NMaier.Windows.Forms/NMaier.Windows.Forms.csproj b/NMaier.Windows.Forms/NMaier.Windows.Forms.csproj index eff47cc9..27d522a1 100644 --- a/NMaier.Windows.Forms/NMaier.Windows.Forms.csproj +++ b/NMaier.Windows.Forms/NMaier.Windows.Forms.csproj @@ -23,7 +23,7 @@ 4 - pdbonly + none true bin\Release\ TRACE diff --git a/SimpleDLNA/FormAbout.cs b/SimpleDLNA/FormAbout.cs index c624d56d..f9266116 100644 --- a/SimpleDLNA/FormAbout.cs +++ b/SimpleDLNA/FormAbout.cs @@ -1,8 +1,6 @@ using NMaier.SimpleDlna.Utilities; using System; -using System.Drawing; using System.Text; -using System.Windows.Forms; namespace NMaier.SimpleDlna.GUI { diff --git a/SimpleDLNA/FormMain.cs b/SimpleDLNA/FormMain.cs index 5d1c8a97..8cea10a4 100644 --- a/SimpleDLNA/FormMain.cs +++ b/SimpleDLNA/FormMain.cs @@ -3,7 +3,8 @@ using log4net.Config; using log4net.Core; using log4net.Layout; -using NMaier.SimpleDlna.Server; +using NMaier.SimpleDlna.Server.Http; +using NMaier.SimpleDlna.Utilities; using System; using System.Collections.Concurrent; using System.Collections.Generic; @@ -14,7 +15,6 @@ using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; -using System.Xml.Serialization; namespace NMaier.SimpleDlna.GUI { @@ -28,14 +28,14 @@ public partial class FormMain : NMaier.Windows.Forms.Form, IAppender, IDisposabl Properties.Settings.Default; private readonly FileInfo cacheFile = - new FileInfo(Path.Combine(cacheDir, "sdlna.cache")); + new FileInfo(DataPath.Combine("sdlna.cache")); #if DEBUG private readonly FileInfo logFile = - new FileInfo(Path.Combine(cacheDir, "sdlna.dbg.log")); + new FileInfo(DataPath.Combine("sdlna.dbg.log")); #else private readonly FileInfo logFile = - new FileInfo(Path.Combine(cacheDir, "sdlna.log")); + new FileInfo(DataPath.Combine("sdlna.log")); #endif private readonly object appenderLock = new object(); @@ -56,6 +56,11 @@ public partial class FormMain : NMaier.Windows.Forms.Form, IAppender, IDisposabl public FormMain() { + var rv = Config.cache; + if (!string.IsNullOrWhiteSpace(rv) && Directory.Exists(rv)) { + DataPath.Path = rv; + } + HandleCreated += (o, e) => { logging = true; @@ -100,41 +105,6 @@ public FormMain() private delegate void logDelegate(string level, string logger, string msg, string ex); - private static string cacheDir - { - get - { - var rv = Config.cache; - if (!string.IsNullOrWhiteSpace(rv) && Directory.Exists(rv)) { - return rv; - } - try { - try { - rv = Environment.GetFolderPath( - Environment.SpecialFolder.LocalApplicationData); - if (string.IsNullOrEmpty(rv)) { - throw new IOException("Cannot get LocalAppData"); - } - } - catch (Exception) { - rv = Environment.GetFolderPath( - Environment.SpecialFolder.ApplicationData); - if (string.IsNullOrEmpty(rv)) { - throw new IOException("Cannot get LocalAppData"); - } - } - rv = Path.Combine(rv, "SimpleDLNA"); - if (!Directory.Exists(rv)) { - Directory.CreateDirectory(rv); - } - return rv; - } - catch (Exception) { - return Path.GetTempPath(); - } - } - } - public override string Text { get @@ -381,11 +351,7 @@ private ServerListViewItem[] LoadDescriptors() { List rv; try { - var serializer = new XmlSerializer(typeof(List)); - using (var reader = new StreamReader( - Path.Combine(cacheDir, descriptorFile))) { - rv = serializer.Deserialize(reader) as List; - } + rv = XmlHelper.FromFile>(DataPath.Combine(descriptorFile)); } catch (Exception) { rv = Config.Descriptors; @@ -476,15 +442,13 @@ private void SaveConfig() try { var descs = (from ServerListViewItem item in listDescriptions.Items select item.Description).ToArray(); - var serializer = new XmlSerializer(descs.GetType()); - var file = new FileInfo( - Path.Combine(cacheDir, descriptorFile + ".tmp")); - using (var writer = new StreamWriter(file.FullName)) { - serializer.Serialize(writer, descs); - } - var outfile = Path.Combine(cacheDir, descriptorFile); - File.Copy(file.FullName, outfile, true); - file.Delete(); + + var file = DataPath.Combine(descriptorFile + ".tmp"); + XmlHelper.ToFile(descs, file); + + var outfile = DataPath.Combine(descriptorFile); + File.Copy(file, outfile, true); + File.Delete(file); } catch (Exception ex) { log.Error("Failed to write descriptors", ex); diff --git a/SimpleDLNA/FormServer.Designer.cs b/SimpleDLNA/FormServer.Designer.cs index 415a1edf..492b0cf5 100644 --- a/SimpleDLNA/FormServer.Designer.cs +++ b/SimpleDLNA/FormServer.Designer.cs @@ -65,6 +65,8 @@ private void InitializeComponent() this.colRestrictionType = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.buttonRemoveRestriction = new System.Windows.Forms.Button(); this.buttonAddRestriction = new System.Windows.Forms.Button(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.comboCache = new System.Windows.Forms.ComboBox(); this.groupName.SuspendLayout(); this.groupOrder.SuspendLayout(); this.groupTypes.SuspendLayout(); @@ -73,6 +75,7 @@ private void InitializeComponent() this.tabbedOptions.SuspendLayout(); this.tabPageViews.SuspendLayout(); this.tabPageRestrictions.SuspendLayout(); + this.groupBox1.SuspendLayout(); this.SuspendLayout(); // // groupName @@ -80,9 +83,9 @@ private void InitializeComponent() this.groupName.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.groupName.Controls.Add(this.textName); - this.groupName.Location = new System.Drawing.Point(12, 12); + this.groupName.Location = new System.Drawing.Point(14, 14); this.groupName.Name = "groupName"; - this.groupName.Size = new System.Drawing.Size(520, 46); + this.groupName.Size = new System.Drawing.Size(607, 53); this.groupName.TabIndex = 2; this.groupName.TabStop = false; this.groupName.Text = "Name"; @@ -91,9 +94,9 @@ private void InitializeComponent() // this.textName.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this.textName.Location = new System.Drawing.Point(6, 19); + this.textName.Location = new System.Drawing.Point(7, 22); this.textName.Name = "textName"; - this.textName.Size = new System.Drawing.Size(485, 20); + this.textName.Size = new System.Drawing.Size(565, 23); this.textName.TabIndex = 0; this.textName.Validating += new System.ComponentModel.CancelEventHandler(this.textName_Validating); // @@ -103,9 +106,9 @@ private void InitializeComponent() | System.Windows.Forms.AnchorStyles.Right))); this.groupOrder.Controls.Add(this.checkOrderDescending); this.groupOrder.Controls.Add(this.comboOrder); - this.groupOrder.Location = new System.Drawing.Point(12, 64); + this.groupOrder.Location = new System.Drawing.Point(14, 74); this.groupOrder.Name = "groupOrder"; - this.groupOrder.Size = new System.Drawing.Size(520, 46); + this.groupOrder.Size = new System.Drawing.Size(607, 53); this.groupOrder.TabIndex = 3; this.groupOrder.TabStop = false; this.groupOrder.Text = "Order"; @@ -114,9 +117,9 @@ private void InitializeComponent() // this.checkOrderDescending.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.checkOrderDescending.AutoSize = true; - this.checkOrderDescending.Location = new System.Drawing.Point(431, 19); + this.checkOrderDescending.Location = new System.Drawing.Point(511, 22); this.checkOrderDescending.Name = "checkOrderDescending"; - this.checkOrderDescending.Size = new System.Drawing.Size(83, 17); + this.checkOrderDescending.Size = new System.Drawing.Size(88, 19); this.checkOrderDescending.TabIndex = 1; this.checkOrderDescending.Text = "Descending"; this.checkOrderDescending.UseVisualStyleBackColor = true; @@ -127,9 +130,9 @@ private void InitializeComponent() | System.Windows.Forms.AnchorStyles.Right))); this.comboOrder.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.comboOrder.FormattingEnabled = true; - this.comboOrder.Location = new System.Drawing.Point(6, 19); + this.comboOrder.Location = new System.Drawing.Point(7, 22); this.comboOrder.Name = "comboOrder"; - this.comboOrder.Size = new System.Drawing.Size(419, 21); + this.comboOrder.Size = new System.Drawing.Size(488, 23); this.comboOrder.TabIndex = 0; // // groupTypes @@ -139,9 +142,9 @@ private void InitializeComponent() this.groupTypes.Controls.Add(this.checkImages); this.groupTypes.Controls.Add(this.checkAudio); this.groupTypes.Controls.Add(this.checkVideo); - this.groupTypes.Location = new System.Drawing.Point(12, 116); + this.groupTypes.Location = new System.Drawing.Point(14, 134); this.groupTypes.Name = "groupTypes"; - this.groupTypes.Size = new System.Drawing.Size(520, 46); + this.groupTypes.Size = new System.Drawing.Size(607, 53); this.groupTypes.TabIndex = 4; this.groupTypes.TabStop = false; this.groupTypes.Text = "Types"; @@ -150,9 +153,9 @@ private void InitializeComponent() // checkImages // this.checkImages.AutoSize = true; - this.checkImages.Location = new System.Drawing.Point(133, 19); + this.checkImages.Location = new System.Drawing.Point(155, 22); this.checkImages.Name = "checkImages"; - this.checkImages.Size = new System.Drawing.Size(60, 17); + this.checkImages.Size = new System.Drawing.Size(64, 19); this.checkImages.TabIndex = 2; this.checkImages.Text = "Images"; this.checkImages.UseVisualStyleBackColor = true; @@ -160,9 +163,9 @@ private void InitializeComponent() // checkAudio // this.checkAudio.AutoSize = true; - this.checkAudio.Location = new System.Drawing.Point(74, 19); + this.checkAudio.Location = new System.Drawing.Point(86, 22); this.checkAudio.Name = "checkAudio"; - this.checkAudio.Size = new System.Drawing.Size(53, 17); + this.checkAudio.Size = new System.Drawing.Size(58, 19); this.checkAudio.TabIndex = 1; this.checkAudio.Text = "Audio"; this.checkAudio.UseVisualStyleBackColor = true; @@ -170,9 +173,9 @@ private void InitializeComponent() // checkVideo // this.checkVideo.AutoSize = true; - this.checkVideo.Location = new System.Drawing.Point(15, 19); + this.checkVideo.Location = new System.Drawing.Point(17, 22); this.checkVideo.Name = "checkVideo"; - this.checkVideo.Size = new System.Drawing.Size(53, 17); + this.checkVideo.Size = new System.Drawing.Size(56, 19); this.checkVideo.TabIndex = 0; this.checkVideo.Text = "Video"; this.checkVideo.UseVisualStyleBackColor = true; @@ -186,9 +189,9 @@ private void InitializeComponent() this.groupDirectories.Controls.Add(this.buttonRemoveDirectory); this.groupDirectories.Controls.Add(this.buttonAddDirectory); this.groupDirectories.Controls.Add(this.listDirectories); - this.groupDirectories.Location = new System.Drawing.Point(13, 334); + this.groupDirectories.Location = new System.Drawing.Point(15, 385); this.groupDirectories.Name = "groupDirectories"; - this.groupDirectories.Size = new System.Drawing.Size(519, 138); + this.groupDirectories.Size = new System.Drawing.Size(605, 170); this.groupDirectories.TabIndex = 6; this.groupDirectories.TabStop = false; this.groupDirectories.Text = "Directories"; @@ -196,17 +199,17 @@ private void InitializeComponent() // listDirectoriesAnchor // this.listDirectoriesAnchor.AutoSize = true; - this.listDirectoriesAnchor.Location = new System.Drawing.Point(441, 74); + this.listDirectoriesAnchor.Location = new System.Drawing.Point(514, 85); this.listDirectoriesAnchor.Name = "listDirectoriesAnchor"; - this.listDirectoriesAnchor.Size = new System.Drawing.Size(0, 13); + this.listDirectoriesAnchor.Size = new System.Drawing.Size(0, 15); this.listDirectoriesAnchor.TabIndex = 2; // // buttonRemoveDirectory // this.buttonRemoveDirectory.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.buttonRemoveDirectory.Location = new System.Drawing.Point(438, 48); + this.buttonRemoveDirectory.Location = new System.Drawing.Point(511, 55); this.buttonRemoveDirectory.Name = "buttonRemoveDirectory"; - this.buttonRemoveDirectory.Size = new System.Drawing.Size(75, 23); + this.buttonRemoveDirectory.Size = new System.Drawing.Size(87, 27); this.buttonRemoveDirectory.TabIndex = 2; this.buttonRemoveDirectory.Text = "Remove"; this.buttonRemoveDirectory.UseVisualStyleBackColor = true; @@ -215,9 +218,9 @@ private void InitializeComponent() // buttonAddDirectory // this.buttonAddDirectory.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.buttonAddDirectory.Location = new System.Drawing.Point(438, 19); + this.buttonAddDirectory.Location = new System.Drawing.Point(511, 22); this.buttonAddDirectory.Name = "buttonAddDirectory"; - this.buttonAddDirectory.Size = new System.Drawing.Size(75, 23); + this.buttonAddDirectory.Size = new System.Drawing.Size(87, 27); this.buttonAddDirectory.TabIndex = 0; this.buttonAddDirectory.Text = "Add"; this.buttonAddDirectory.UseVisualStyleBackColor = true; @@ -230,9 +233,9 @@ private void InitializeComponent() | System.Windows.Forms.AnchorStyles.Right))); this.listDirectories.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { this.colDirectory}); - this.listDirectories.Location = new System.Drawing.Point(6, 19); + this.listDirectories.Location = new System.Drawing.Point(7, 22); this.listDirectories.Name = "listDirectories"; - this.listDirectories.Size = new System.Drawing.Size(429, 113); + this.listDirectories.Size = new System.Drawing.Size(500, 141); this.listDirectories.Sorting = System.Windows.Forms.SortOrder.Ascending; this.listDirectories.TabIndex = 3; this.listDirectories.UseCompatibleStateImageBehavior = false; @@ -248,9 +251,9 @@ private void InitializeComponent() // this.buttonCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); this.buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; - this.buttonCancel.Location = new System.Drawing.Point(457, 478); + this.buttonCancel.Location = new System.Drawing.Point(533, 631); this.buttonCancel.Name = "buttonCancel"; - this.buttonCancel.Size = new System.Drawing.Size(75, 23); + this.buttonCancel.Size = new System.Drawing.Size(87, 27); this.buttonCancel.TabIndex = 1; this.buttonCancel.Text = "&Cancel"; this.buttonCancel.UseVisualStyleBackColor = true; @@ -259,9 +262,9 @@ private void InitializeComponent() // this.buttonAccept.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); this.buttonAccept.DialogResult = System.Windows.Forms.DialogResult.OK; - this.buttonAccept.Location = new System.Drawing.Point(376, 478); + this.buttonAccept.Location = new System.Drawing.Point(439, 631); this.buttonAccept.Name = "buttonAccept"; - this.buttonAccept.Size = new System.Drawing.Size(75, 23); + this.buttonAccept.Size = new System.Drawing.Size(87, 27); this.buttonAccept.TabIndex = 0; this.buttonAccept.Text = "&OK"; this.buttonAccept.UseVisualStyleBackColor = true; @@ -275,10 +278,10 @@ private void InitializeComponent() // this.tabbedOptions.Controls.Add(this.tabPageViews); this.tabbedOptions.Controls.Add(this.tabPageRestrictions); - this.tabbedOptions.Location = new System.Drawing.Point(12, 168); + this.tabbedOptions.Location = new System.Drawing.Point(14, 194); this.tabbedOptions.Name = "tabbedOptions"; this.tabbedOptions.SelectedIndex = 0; - this.tabbedOptions.Size = new System.Drawing.Size(520, 160); + this.tabbedOptions.Size = new System.Drawing.Size(607, 185); this.tabbedOptions.TabIndex = 6; // // tabPageViews @@ -289,10 +292,10 @@ private void InitializeComponent() this.tabPageViews.Controls.Add(this.buttonRemoveView); this.tabPageViews.Controls.Add(this.buttonAddView); this.tabPageViews.Controls.Add(this.listViews); - this.tabPageViews.Location = new System.Drawing.Point(4, 22); + this.tabPageViews.Location = new System.Drawing.Point(4, 24); this.tabPageViews.Name = "tabPageViews"; this.tabPageViews.Padding = new System.Windows.Forms.Padding(3); - this.tabPageViews.Size = new System.Drawing.Size(512, 134); + this.tabPageViews.Size = new System.Drawing.Size(599, 157); this.tabPageViews.TabIndex = 0; this.tabPageViews.Text = "Views"; this.tabPageViews.UseVisualStyleBackColor = true; @@ -303,17 +306,17 @@ private void InitializeComponent() | System.Windows.Forms.AnchorStyles.Right))); this.comboNewView.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.comboNewView.FormattingEnabled = true; - this.comboNewView.Location = new System.Drawing.Point(6, 6); + this.comboNewView.Location = new System.Drawing.Point(7, 7); this.comboNewView.Name = "comboNewView"; - this.comboNewView.Size = new System.Drawing.Size(419, 21); + this.comboNewView.Size = new System.Drawing.Size(488, 23); this.comboNewView.TabIndex = 0; // // buttonViewDown // this.buttonViewDown.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.buttonViewDown.Location = new System.Drawing.Point(431, 102); + this.buttonViewDown.Location = new System.Drawing.Point(503, 118); this.buttonViewDown.Name = "buttonViewDown"; - this.buttonViewDown.Size = new System.Drawing.Size(75, 23); + this.buttonViewDown.Size = new System.Drawing.Size(87, 27); this.buttonViewDown.TabIndex = 4; this.buttonViewDown.Text = "Down"; this.buttonViewDown.UseVisualStyleBackColor = true; @@ -321,9 +324,9 @@ private void InitializeComponent() // buttonViewUp // this.buttonViewUp.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.buttonViewUp.Location = new System.Drawing.Point(431, 73); + this.buttonViewUp.Location = new System.Drawing.Point(503, 84); this.buttonViewUp.Name = "buttonViewUp"; - this.buttonViewUp.Size = new System.Drawing.Size(75, 23); + this.buttonViewUp.Size = new System.Drawing.Size(87, 27); this.buttonViewUp.TabIndex = 3; this.buttonViewUp.Text = "Up"; this.buttonViewUp.UseVisualStyleBackColor = true; @@ -331,9 +334,9 @@ private void InitializeComponent() // buttonRemoveView // this.buttonRemoveView.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.buttonRemoveView.Location = new System.Drawing.Point(431, 35); + this.buttonRemoveView.Location = new System.Drawing.Point(503, 40); this.buttonRemoveView.Name = "buttonRemoveView"; - this.buttonRemoveView.Size = new System.Drawing.Size(75, 23); + this.buttonRemoveView.Size = new System.Drawing.Size(87, 27); this.buttonRemoveView.TabIndex = 2; this.buttonRemoveView.Text = "Remove"; this.buttonRemoveView.UseVisualStyleBackColor = true; @@ -342,9 +345,9 @@ private void InitializeComponent() // buttonAddView // this.buttonAddView.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.buttonAddView.Location = new System.Drawing.Point(431, 6); + this.buttonAddView.Location = new System.Drawing.Point(503, 7); this.buttonAddView.Name = "buttonAddView"; - this.buttonAddView.Size = new System.Drawing.Size(75, 23); + this.buttonAddView.Size = new System.Drawing.Size(87, 27); this.buttonAddView.TabIndex = 1; this.buttonAddView.Text = "Add"; this.buttonAddView.UseVisualStyleBackColor = true; @@ -359,9 +362,9 @@ private void InitializeComponent() this.colViewName, this.colViewDesc}); this.listViews.FullRowSelect = true; - this.listViews.Location = new System.Drawing.Point(6, 33); + this.listViews.Location = new System.Drawing.Point(7, 38); this.listViews.Name = "listViews"; - this.listViews.Size = new System.Drawing.Size(419, 95); + this.listViews.Size = new System.Drawing.Size(488, 109); this.listViews.TabIndex = 5; this.listViews.UseCompatibleStateImageBehavior = false; this.listViews.View = System.Windows.Forms.View.Details; @@ -383,10 +386,10 @@ private void InitializeComponent() this.tabPageRestrictions.Controls.Add(this.listRestrictions); this.tabPageRestrictions.Controls.Add(this.buttonRemoveRestriction); this.tabPageRestrictions.Controls.Add(this.buttonAddRestriction); - this.tabPageRestrictions.Location = new System.Drawing.Point(4, 22); + this.tabPageRestrictions.Location = new System.Drawing.Point(4, 24); this.tabPageRestrictions.Name = "tabPageRestrictions"; this.tabPageRestrictions.Padding = new System.Windows.Forms.Padding(3); - this.tabPageRestrictions.Size = new System.Drawing.Size(512, 134); + this.tabPageRestrictions.Size = new System.Drawing.Size(599, 157); this.tabPageRestrictions.TabIndex = 1; this.tabPageRestrictions.Text = "Restrictions"; this.tabPageRestrictions.UseVisualStyleBackColor = true; @@ -395,9 +398,9 @@ private void InitializeComponent() // this.textRestriction.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this.textRestriction.Location = new System.Drawing.Point(6, 6); + this.textRestriction.Location = new System.Drawing.Point(7, 7); this.textRestriction.Name = "textRestriction"; - this.textRestriction.Size = new System.Drawing.Size(274, 20); + this.textRestriction.Size = new System.Drawing.Size(319, 23); this.textRestriction.TabIndex = 0; // // comboNewRestriction @@ -409,9 +412,9 @@ private void InitializeComponent() "MAC", "IP", "User-Agent"}); - this.comboNewRestriction.Location = new System.Drawing.Point(305, 6); + this.comboNewRestriction.Location = new System.Drawing.Point(356, 7); this.comboNewRestriction.Name = "comboNewRestriction"; - this.comboNewRestriction.Size = new System.Drawing.Size(120, 21); + this.comboNewRestriction.Size = new System.Drawing.Size(139, 23); this.comboNewRestriction.TabIndex = 1; // // listRestrictions @@ -423,9 +426,9 @@ private void InitializeComponent() this.colRestriction, this.colRestrictionType}); this.listRestrictions.FullRowSelect = true; - this.listRestrictions.Location = new System.Drawing.Point(6, 33); + this.listRestrictions.Location = new System.Drawing.Point(7, 38); this.listRestrictions.Name = "listRestrictions"; - this.listRestrictions.Size = new System.Drawing.Size(419, 95); + this.listRestrictions.Size = new System.Drawing.Size(488, 109); this.listRestrictions.TabIndex = 4; this.listRestrictions.UseCompatibleStateImageBehavior = false; this.listRestrictions.View = System.Windows.Forms.View.Details; @@ -443,9 +446,9 @@ private void InitializeComponent() // buttonRemoveRestriction // this.buttonRemoveRestriction.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.buttonRemoveRestriction.Location = new System.Drawing.Point(431, 35); + this.buttonRemoveRestriction.Location = new System.Drawing.Point(503, 40); this.buttonRemoveRestriction.Name = "buttonRemoveRestriction"; - this.buttonRemoveRestriction.Size = new System.Drawing.Size(75, 23); + this.buttonRemoveRestriction.Size = new System.Drawing.Size(87, 27); this.buttonRemoveRestriction.TabIndex = 3; this.buttonRemoveRestriction.Text = "Remove"; this.buttonRemoveRestriction.UseVisualStyleBackColor = true; @@ -454,22 +457,46 @@ private void InitializeComponent() // buttonAddRestriction // this.buttonAddRestriction.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.buttonAddRestriction.Location = new System.Drawing.Point(431, 6); + this.buttonAddRestriction.Location = new System.Drawing.Point(503, 7); this.buttonAddRestriction.Name = "buttonAddRestriction"; - this.buttonAddRestriction.Size = new System.Drawing.Size(75, 23); + this.buttonAddRestriction.Size = new System.Drawing.Size(87, 27); this.buttonAddRestriction.TabIndex = 2; this.buttonAddRestriction.Text = "Add"; this.buttonAddRestriction.UseVisualStyleBackColor = true; this.buttonAddRestriction.Click += new System.EventHandler(this.buttonAddRestriction_Click); // + // groupBox1 + // + this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupBox1.Controls.Add(this.comboCache); + this.groupBox1.Location = new System.Drawing.Point(14, 561); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(607, 53); + this.groupBox1.TabIndex = 8; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "Cache"; + // + // comboCache + // + this.comboCache.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.comboCache.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboCache.FormattingEnabled = true; + this.comboCache.Location = new System.Drawing.Point(7, 22); + this.comboCache.Name = "comboCache"; + this.comboCache.Size = new System.Drawing.Size(488, 23); + this.comboCache.TabIndex = 0; + // // FormServer // this.AcceptButton = this.buttonAccept; - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.AutoValidate = System.Windows.Forms.AutoValidate.EnableAllowFocusChange; this.CancelButton = this.buttonCancel; - this.ClientSize = new System.Drawing.Size(544, 508); + this.ClientSize = new System.Drawing.Size(635, 665); + this.Controls.Add(this.groupBox1); this.Controls.Add(this.tabbedOptions); this.Controls.Add(this.buttonAccept); this.Controls.Add(this.buttonCancel); @@ -496,6 +523,7 @@ private void InitializeComponent() this.tabPageViews.ResumeLayout(false); this.tabPageRestrictions.ResumeLayout(false); this.tabPageRestrictions.PerformLayout(); + this.groupBox1.ResumeLayout(false); this.ResumeLayout(false); } @@ -539,5 +567,7 @@ private void InitializeComponent() private System.Windows.Forms.ColumnHeader colRestrictionType; private System.Windows.Forms.Button buttonRemoveRestriction; private System.Windows.Forms.Button buttonAddRestriction; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.ComboBox comboCache; } } \ No newline at end of file diff --git a/SimpleDLNA/FormServer.cs b/SimpleDLNA/FormServer.cs index 4b1132b7..bf29767f 100644 --- a/SimpleDLNA/FormServer.cs +++ b/SimpleDLNA/FormServer.cs @@ -1,4 +1,5 @@ -using NMaier.SimpleDlna.Server; +using NMaier.SimpleDlna.FileMediaServer; +using NMaier.SimpleDlna.Server; using NMaier.SimpleDlna.Server.Comparers; using NMaier.SimpleDlna.Server.Views; using NMaier.SimpleDlna.Utilities; @@ -41,6 +42,12 @@ public FormServer(ServerDescription description) break; } } + foreach (var i in comboCache.Items) { + if ((i is IFileStore) && (((IFileStore)i).Name == description.FileStore)) { + comboCache.SelectedItem = i; + break; + } + } checkOrderDescending.Checked = description.OrderDescending; foreach (var v in description.Views) { @@ -106,6 +113,7 @@ public ServerDescription Description var rv = new ServerDescription() { Name = textName.Text, Order = ((IItemComparer)comboOrder.SelectedItem).Name, + FileStore = (comboCache.SelectedItem is IFileStore) ? ((IFileStore)comboCache.SelectedItem).Name : null, OrderDescending = checkOrderDescending.Checked, Types = types, Views = views, @@ -131,6 +139,14 @@ orderby v.Key } } + private void AddCacheItems() + { + var items = FileStoreRepository.ListItems().OrderBy(l => l.Key).ToList(); + comboCache.Items.Clear(); + comboCache.Items.Add(string.Empty); + comboCache.Items.AddRange(items.Select(i => i.Value).ToArray()); + } + private void AddViewItems() { var items = from v in ViewRepository.ListItems() @@ -245,6 +261,7 @@ private void Init() Icon = Properties.Resources.server; AddOrderItems(); AddViewItems(); + AddCacheItems(); comboNewRestriction.SelectedIndex = 0; } diff --git a/SimpleDLNA/Properties/Settings.Designer.cs b/SimpleDLNA/Properties/Settings.Designer.cs index db06330a..91a650a9 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.18444 +// Runtime Version:4.0.30319.42000 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -12,7 +12,7 @@ namespace NMaier.SimpleDlna.GUI.Properties { [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "14.0.0.0")] internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); @@ -25,7 +25,7 @@ public static Settings Default { [global::System.Configuration.UserScopedSettingAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("")] + [global::System.Configuration.DefaultSettingValueAttribute("cache.db")] public string cache { get { return ((string)(this["cache"])); diff --git a/SimpleDLNA/Properties/Settings.settings b/SimpleDLNA/Properties/Settings.settings index 8a76ab1f..c1490052 100644 --- a/SimpleDLNA/Properties/Settings.settings +++ b/SimpleDLNA/Properties/Settings.settings @@ -3,7 +3,7 @@ - + cache.db 0 diff --git a/SimpleDLNA/ServerDescription.cs b/SimpleDLNA/ServerDescription.cs index 36ba6c0c..2afab9ed 100644 --- a/SimpleDLNA/ServerDescription.cs +++ b/SimpleDLNA/ServerDescription.cs @@ -31,6 +31,8 @@ public ServerDescription() public string[] Views { get; set; } + public string FileStore { get; set; } + public void AdoptInfo(ServerDescription other) { if (other == null) { @@ -39,6 +41,7 @@ public void AdoptInfo(ServerDescription other) Directories = other.Directories; Name = other.Name; Order = other.Order; + FileStore = other.FileStore; OrderDescending = other.OrderDescending; Types = other.Types; Views = other.Views; diff --git a/SimpleDLNA/ServerListViewItem.cs b/SimpleDLNA/ServerListViewItem.cs index 4fcc465e..5d93cd1e 100644 --- a/SimpleDLNA/ServerListViewItem.cs +++ b/SimpleDLNA/ServerListViewItem.cs @@ -3,6 +3,7 @@ using NMaier.SimpleDlna.FileMediaServer; using NMaier.SimpleDlna.Server; using NMaier.SimpleDlna.Server.Comparers; +using NMaier.SimpleDlna.Server.Http; using System; using System.IO; using System.Linq; @@ -99,11 +100,14 @@ where d.Exists fileServer = new FileServer(Description.Types, ids, dirs) { FriendlyName = Description.Name }; -#if !DEBUG - if (cacheFile != null) { - fileServer.SetCacheFile(cacheFile); +//#if !DEBUG + if(!string.IsNullOrEmpty(Description.FileStore)) { + fileServer.SetCacheFile(FileStoreRepository.Lookup(Description.FileStore)); } -#endif + //if (cacheFile != null) { + // fileServer.SetCacheFile(); + //} +//#endif fileServer.Changing += (o, e) => { state = State.Refreshing; @@ -138,7 +142,7 @@ where d.Exists ); } catch (Exception ex) { - server.ErrorFormat("Failed to start {0}, {1}", Description.Name, ex); + server.Logger.ErrorFormat("Failed to start {0}, {1}", Description.Name, ex); Description.ToggleActive(); state = State.Stopped; } diff --git a/SimpleDLNA/SimpleDLNA.csproj b/SimpleDLNA/SimpleDLNA.csproj index 6548defa..6d8e5c31 100644 --- a/SimpleDLNA/SimpleDLNA.csproj +++ b/SimpleDLNA/SimpleDLNA.csproj @@ -13,7 +13,10 @@ v4.0 Client 512 - publish\ + false + ..\ + true + C:\work\temp\deploy\simpleDLNA\ true Disk false @@ -23,13 +26,11 @@ false false true - 0 + 1 1.0.0.%2a - false false + true true - ..\ - true sdlna.ico @@ -51,7 +52,7 @@ bin\Release\ TRACE true - pdbonly + none AnyCPU bin\Release\SimpleDLNA.exe.CodeAnalysisLog.xml true @@ -60,6 +61,7 @@ ..\sdlna.ruleset false true + false true @@ -67,6 +69,18 @@ sdlna.key.snk + + 0B33F26E32F5937FB76E80B63014F6A0902E11E2 + + + SimpleDLNA_TemporaryKey.pfx + + + true + + + true + False @@ -161,6 +175,7 @@ + @@ -208,6 +223,14 @@ + + {6961f1c2-41e9-4e7f-8e88-7d4a259b3df8} + FileStoreRaptorDB + + + {25741114-7f31-421e-8d2b-357a3155cee2} + FileStoreSQLite + {50E06B21-E11A-42F0-81E2-0911E771E861} fsserver diff --git a/SimpleDLNA/SimpleDLNA_TemporaryKey.pfx b/SimpleDLNA/SimpleDLNA_TemporaryKey.pfx new file mode 100644 index 00000000..0eab6f92 Binary files /dev/null and b/SimpleDLNA/SimpleDLNA_TemporaryKey.pfx differ diff --git a/SimpleDLNA/app.config b/SimpleDLNA/app.config index a3471e29..ca663e6b 100644 --- a/SimpleDLNA/app.config +++ b/SimpleDLNA/app.config @@ -8,7 +8,7 @@ - + cache.db 0 diff --git a/SimpleDLNA/public.pk b/SimpleDLNA/public.pk new file mode 100644 index 00000000..500d9514 Binary files /dev/null and b/SimpleDLNA/public.pk differ diff --git a/fsserver/BackgroundCacher.cs b/fsserver/BackgroundCacher.cs index 9f1bf92d..69db1f1d 100644 --- a/fsserver/BackgroundCacher.cs +++ b/fsserver/BackgroundCacher.cs @@ -1,9 +1,9 @@ using NMaier.SimpleDlna.Server.Metadata; +using NMaier.SimpleDlna.Utilities; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Threading; -using System.Threading.Tasks; namespace NMaier.SimpleDlna.FileMediaServer { @@ -23,10 +23,11 @@ private static BlockingCollection CreateQueue() return new BlockingCollection(new ConcurrentQueue()); } + private readonly static ILogging _logger = Logging.GetLogger(); + private static void Run() { - var logger = log4net.LogManager.GetLogger(typeof(BackgroundCacher)); - logger.Debug("started"); + _logger.Debug("started"); var loadedSubTitles = 0ul; try { for (; ; ) { @@ -35,8 +36,9 @@ private static void Run() continue; } var item = queue.Take(); - var store = item.Store.Target as FileStore; + var store = item.Store.Target as IFileStore; var file = item.File.Target as BaseFile; + _logger.NoticeFormat("Processing [{0}]", file.Item.Name); if (store == null || file == null) { continue; } @@ -58,11 +60,11 @@ private static void Run() } } finally { - logger.DebugFormat("stopped subtitles: {0}", loadedSubTitles); + _logger.DebugFormat("stopped subtitles: {0}", loadedSubTitles); } } - public static void AddFiles(FileStore store, + public static void AddFiles(IFileStore store, IEnumerable items) { var storeRef = new WeakReference(store); diff --git a/fsserver/FileServer.cs b/fsserver/FileServer.cs index e3f3bdb7..57672aa1 100644 --- a/fsserver/FileServer.cs +++ b/fsserver/FileServer.cs @@ -1,4 +1,5 @@ using NMaier.SimpleDlna.Server; +using NMaier.SimpleDlna.Server.Http; using NMaier.SimpleDlna.Utilities; using System; using System.Collections.Generic; @@ -41,12 +42,13 @@ public sealed class FileServer private static readonly double ChangeDeleteTime = TimeSpan.FromSeconds(2).TotalMilliseconds; - private readonly List pendingFiles = - new List(); + private readonly List pendingFiles = new List(); private readonly Identifiers ids; - private FileStore store = null; + private IFileStore _store = null; + private FileStoreReader _storeReader = null; + private FileStoreWriter _storeWriter = null; private readonly DlnaMediaTypes types; @@ -182,10 +184,10 @@ private void DoRoot() private void OnChanged(Object source, FileSystemEventArgs e) { try { - if (store != null && - icomparer.Equals(e.FullPath, store.StoreFile.FullName)) { - return; - } + //if (_store != null && + // icomparer.Equals(e.FullPath, _store.StoreFile.FullName)) { + // return; + //} var ext = string.IsNullOrEmpty(e.FullPath) ? Path.GetExtension(e.FullPath) : string.Empty; @@ -287,20 +289,21 @@ private void RescanTimer(object sender, ElapsedEventArgs e) RescanInternal(); } + void ClearPending() { + lock (pendingFiles) { + pendingFiles.Clear(); + } + } + private void Thumbnail() { - if (store == null) { - lock (this) { - pendingFiles.Clear(); + if (_store != null) { + lock (pendingFiles) { + DebugFormat("Passing {0} files to background cacher", pendingFiles.Count); + BackgroundCacher.AddFiles(_store, pendingFiles); } - return; - } - lock (this) { - DebugFormat( - "Passing {0} files to background cacher", pendingFiles.Count); - BackgroundCacher.AddFiles(store, pendingFiles); - pendingFiles.Clear(); } + ClearPending(); } internal void DelayedRescan(WatcherChangeTypes changeType) @@ -338,8 +341,8 @@ internal void DelayedRescan(WatcherChangeTypes changeType) internal Cover GetCover(BaseFile file) { - if (store != null) { - return store.MaybeGetCover(file); + if (_storeReader != null) { + return _storeReader.GetCover(file); } return null; } @@ -363,27 +366,30 @@ internal BaseFile GetFile(PlainFolder aParent, FileInfo info) var type = DlnaMaps.Ext2Dlna[ext]; var mediaType = DlnaMaps.Ext2Media[ext]; - if (store != null) { - item = store.MaybeGetFile(this, info, type); + if (_store != null) { + item = _storeReader.GetFile(info, this, type); if (item != null) { - lock (this) { - pendingFiles.Add(new WeakReference(item)); - } + AddPending(item); return item; } } - lock (this) { - var rv = BaseFile.GetFile(aParent, info, type, mediaType); - pendingFiles.Add(new WeakReference(rv)); - return rv; - } + var rv = BaseFile.GetFile(aParent, info, type, mediaType); + AddPending(rv); + return rv; + } + + void AddPending(BaseFile file) { + lock (pendingFiles) { + if (pendingFiles.Any(f => ((BaseFile)f.Target).Path == file.Path)) return; + pendingFiles.Add(new WeakReference(file)); + } } internal void UpdateFileCache(BaseFile aFile) { - if (store != null) { - store.MaybeStoreFile(aFile); + if (_storeWriter != null) { + _storeWriter.StoreFile(aFile); } } @@ -398,8 +404,8 @@ public void Dispose() if (watchTimer != null) { watchTimer.Dispose(); } - if (store != null) { - store.Dispose(); + if (_store != null) { + _store.Dispose(); } FileStreamCache.Clear(); } @@ -442,17 +448,23 @@ public void Rescan() RescanInternal(); } - public void SetCacheFile(FileInfo info) + public void SetCacheFile(IFileStore store) { - if (store != null) { - store.Dispose(); - store = null; + if (_store != null) { + _store.Dispose(); + _store = null; + _storeReader = null; + _storeWriter = null; } try { - store = new FileStore(info); + _store = store; + if (_store == null) return; + _store.Init(); + _storeReader = new FileStoreReader(store); + _storeWriter = new FileStoreWriter(store); } catch (Exception ex) { - Warn("FileStore is not available; failed to load SQLite Adapter", ex); + WarnFormat("FileStore is not available; failed to load [{0}]:{1}", store, ex); store = null; } } diff --git a/fsserver/FileStoreReader.cs b/fsserver/FileStoreReader.cs new file mode 100644 index 00000000..b614dc2a --- /dev/null +++ b/fsserver/FileStoreReader.cs @@ -0,0 +1,99 @@ +using NMaier.SimpleDlna.Server; +using NMaier.SimpleDlna.Utilities; +using System.IO; +using System.Runtime.Serialization; +using System.Runtime.Serialization.Formatters; +using System.Runtime.Serialization.Formatters.Binary; + +namespace NMaier.SimpleDlna.FileMediaServer +{ + public class FileStoreReader : Logging + { + IFileStore _store; + + public FileStoreReader(IFileStore store) { + _store = store; + } + /* ------------------ BaseFile serialize ------------------ + using (var s = new MemoryStream()) { + var ctx = new StreamingContext( + StreamingContextStates.Persistence, + null + ); + var formatter = new BinaryFormatter(null, ctx) { + TypeFormat = FormatterTypeStyle.TypesWhenNeeded, + AssemblyFormat = FormatterAssemblyStyle.Simple + }; + formatter.Serialize(s, file); + } + */ + /* + using (var s = new MemoryStream(data)) { + var ctx = new StreamingContext( + StreamingContextStates.Persistence, + new DeserializeInfo(null, info, DlnaMime.ImageJPEG) + ); + var formatter = new BinaryFormatter(null, ctx) { + TypeFormat = FormatterTypeStyle.TypesWhenNeeded, + AssemblyFormat = FormatterAssemblyStyle.Simple + }; + var rv = formatter.Deserialize(s) as Cover; + return rv; + } */ + + /* ------------------ Cover deserialize ------------------ + using (var s = new MemoryStream(data)) { + var ctx = new StreamingContext( + StreamingContextStates.Persistence, + new DeserializeInfo(null, info, DlnaMime.ImageJPEG) + ); + var formatter = new BinaryFormatter(null, ctx) { + TypeFormat = FormatterTypeStyle.TypesWhenNeeded, + AssemblyFormat = FormatterAssemblyStyle.Simple + }; + var rv = formatter.Deserialize(s) as Cover; + return rv; + } + */ + /* ------------------ BaseFile deserialize ------------------ + using (var s = new MemoryStream(data)) { + var ctx = new StreamingContext( + StreamingContextStates.Persistence, + new DeserializeInfo(server, info, type)); + var formatter = new BinaryFormatter(null, ctx) { + TypeFormat = FormatterTypeStyle.TypesWhenNeeded, + AssemblyFormat = FormatterAssemblyStyle.Simple + }; + var rv = formatter.Deserialize(s) as BaseFile; + rv.Item = info; + return rv; + } + */ + + private static T Decode(byte[] data, DeserializeInfo dinfo) where T : class { + if (data == null) return (T)null; + using (var s = new MemoryStream(data)) { + var ctx = new StreamingContext(StreamingContextStates.Persistence,dinfo); + var formatter = new BinaryFormatter(null, ctx) { + TypeFormat = FormatterTypeStyle.TypesWhenNeeded, + AssemblyFormat = FormatterAssemblyStyle.Simple + }; + return formatter.Deserialize(s) as T; + } + } + + public Cover GetCover(IStoreItem file) { + try { + return Decode(_store.MaybeGetCover(file), new DeserializeInfo(null, file.Item, DlnaMime.ImageJPEG)); + } + catch (SerializationException ex) { + Debug("Failed to deserialize a cover", ex); + return null; + } + } + + public BaseFile GetFile(FileInfo info, FileServer server, DlnaMime type) { + return Decode(_store.MaybeGetFile(info), new DeserializeInfo(server, info, type)); + } + } +} diff --git a/fsserver/FileStoreRepository.cs b/fsserver/FileStoreRepository.cs new file mode 100644 index 00000000..7b44d9db --- /dev/null +++ b/fsserver/FileStoreRepository.cs @@ -0,0 +1,8 @@ +using NMaier.SimpleDlna.Utilities; + +namespace NMaier.SimpleDlna.FileMediaServer +{ + public sealed class FileStoreRepository : Repository + { + } +} diff --git a/fsserver/FileStoreWriter.cs b/fsserver/FileStoreWriter.cs new file mode 100644 index 00000000..25862a52 --- /dev/null +++ b/fsserver/FileStoreWriter.cs @@ -0,0 +1,49 @@ +using NMaier.SimpleDlna.Utilities; +using System; +using System.IO; +using System.Runtime.Serialization; +using System.Runtime.Serialization.Formatters; +using System.Runtime.Serialization.Formatters.Binary; + +namespace NMaier.SimpleDlna.FileMediaServer +{ + public class FileStoreWriter : Logging + { + IFileStore _store; + + public FileStoreWriter(IFileStore store) { + _store = store; + } + + private static byte[] Encode(object obj) { + using (var s = new MemoryStream()) { + var ctx = new StreamingContext( + StreamingContextStates.Persistence, + null + ); + var formatter = new BinaryFormatter(null, ctx) { + TypeFormat = FormatterTypeStyle.TypesWhenNeeded, + AssemblyFormat = FormatterAssemblyStyle.Simple + }; + formatter.Serialize(s, obj); + return s.ToArray(); + } + } + + /* + , byte[] coverData + */ + + public void StoreFile(BaseFile file) { + byte[] coverData = null; + try { + coverData = Encode(file.MaybeGetCover()); + } + catch (Exception) { + // Ignore and store null. + } + + _store.MaybeStoreFile(file, Encode(file), coverData); + } + } +} diff --git a/fsserver/Files/AudioFile.cs b/fsserver/Files/AudioFile.cs index fb3a0bf9..85011989 100644 --- a/fsserver/Files/AudioFile.cs +++ b/fsserver/Files/AudioFile.cs @@ -211,7 +211,7 @@ private void InitCover(TagLib.Tag tag) cover = new Cover(Item, pic.Data.ToStream()); } catch (Exception ex) { - Debug("Failed to generate thumb for " + Item.FullName, ex); + _logger.Debug("Failed to generate thumb for " + Item.FullName, ex); } } } @@ -231,7 +231,7 @@ private void MaybeInit() } } catch (Exception ex) { - Debug("Failed to transpose Properties props", ex); + _logger.Debug("Failed to transpose Properties props", ex); } try { @@ -240,7 +240,7 @@ private void MaybeInit() InitCover(t); } catch (Exception ex) { - Debug("Failed to transpose Tag props", ex); + _logger.Debug("Failed to transpose Tag props", ex); } } @@ -249,17 +249,17 @@ private void MaybeInit() Server.UpdateFileCache(this); } catch (TagLib.CorruptFileException ex) { - Debug( + _logger.Debug( "Failed to read meta data via taglib for file " + Item.FullName, ex); initialized = true; } catch (TagLib.UnsupportedFormatException ex) { - Debug( + _logger.Debug( "Failed to read meta data via taglib for file " + Item.FullName, ex); initialized = true; } catch (Exception ex) { - Warn( + _logger.Warn( "Unhandled exception reading meta data for file " + Item.FullName, ex); } diff --git a/fsserver/Files/BaseFile.cs b/fsserver/Files/BaseFile.cs index 741eb2be..02b68461 100644 --- a/fsserver/Files/BaseFile.cs +++ b/fsserver/Files/BaseFile.cs @@ -7,8 +7,8 @@ namespace NMaier.SimpleDlna.FileMediaServer { using CoverCache = LeastRecentlyUsedDictionary; - - internal class BaseFile : Logging, IMediaResource, IMediaCover, IMetaInfo + [Serializable] //Logging, + public class BaseFile : IStoreItem, IMediaResource, IMediaCover, IMetaInfo { private string comparableTitle; @@ -16,6 +16,7 @@ internal class BaseFile : Logging, IMediaResource, IMediaCover, IMetaInfo private long? length = null; + [NonSerialized] private readonly FileServer server; private readonly string title; @@ -27,6 +28,8 @@ internal class BaseFile : Logging, IMediaResource, IMediaCover, IMetaInfo private static readonly StringComparer comparer = new NaturalStringComparer(false); + protected static readonly ILogging _logger = Logging.GetLogger(); + protected BaseFile(FileServer server, FileInfo file, DlnaMime type, DlnaMediaTypes mediaType) { @@ -80,7 +83,7 @@ protected FileServer Server } } - internal FileInfo Item + public FileInfo Item { get; set; @@ -168,7 +171,7 @@ public virtual IHeaders Properties } } catch (Exception ex) { - Debug("Failed to access cover", ex); + _logger.Debug("Failed to access cover", ex); } return rv; } @@ -209,7 +212,7 @@ internal static BaseFile GetFile(PlainFolder parentFolder, FileInfo file, } } - internal Cover MaybeGetCover() + public Cover MaybeGetCover() { return cover; } @@ -228,17 +231,17 @@ public Stream CreateContentStream() return FileStreamCache.Get(Item); } catch (FileNotFoundException ex) { - Error("Failed to access: " + Item.FullName, ex); + _logger.Error("Failed to access: " + Item.FullName, ex); server.DelayedRescan(WatcherChangeTypes.Deleted); throw; } catch (UnauthorizedAccessException ex) { - Error("Failed to access: " + Item.FullName, ex); + _logger.Error("Failed to access: " + Item.FullName, ex); server.DelayedRescan(WatcherChangeTypes.Changed); throw; } catch (IOException ex) { - Error("Failed to access: " + Item.FullName, ex); + _logger.Error("Failed to access: " + Item.FullName, ex); server.DelayedRescan(WatcherChangeTypes.Changed); throw; } diff --git a/fsserver/Files/Cover.cs b/fsserver/Files/Cover.cs index a41ba15a..e0d23a0c 100644 --- a/fsserver/Files/Cover.cs +++ b/fsserver/Files/Cover.cs @@ -9,7 +9,7 @@ namespace NMaier.SimpleDlna.FileMediaServer { [Serializable] - internal sealed class Cover + public sealed class Cover : Logging, IMediaCoverResource, IMetaInfo, ISerializable { private byte[] bytes; diff --git a/fsserver/Files/FileReadStream.cs b/fsserver/Files/FileReadStream.cs index dae38199..9b9674e5 100644 --- a/fsserver/Files/FileReadStream.cs +++ b/fsserver/Files/FileReadStream.cs @@ -1,8 +1,6 @@ -using log4net; using NMaier.SimpleDlna.Utilities; using System; using System.Collections.Generic; -using System.Diagnostics; using System.IO; using System.Threading; @@ -10,8 +8,7 @@ namespace NMaier.SimpleDlna.FileMediaServer { internal class FileStreamCache { - private readonly static ILog logger = - LogManager.GetLogger(typeof(FileReadStream)); + private readonly static ILogging _logger = Logging.GetLogger(); private class CacheItem { @@ -35,7 +32,7 @@ private static void Cleanup(object o) if (streams.TryGetValue(key, out item)) { var diff = (DateTime.UtcNow - item.insertionPoint); if (diff.TotalMilliseconds > 2500) { - logger.DebugFormat("Removed file stream {0} from cache", key); + _logger.DebugFormat("Removed file stream {0} from cache", key); item.stream.Kill(); streams.Remove(key); } @@ -61,11 +58,11 @@ internal static FileReadStream Get(FileInfo info) lock (streams) { if (streams.TryGetValue(key, out rv)) { streams.Remove(key); - logger.DebugFormat("Retrieved file stream {0} from cache", key); + _logger.DebugFormat("Retrieved file stream {0} from cache", key); return rv.stream; } } - logger.DebugFormat("Constructing file stream {0}", key); + _logger.DebugFormat("Constructing file stream {0}", key); return new FileReadStream(info); } @@ -77,7 +74,7 @@ internal static void Recycle(FileReadStream stream) CacheItem ignore; if (!streams.TryGetValue(key, out ignore) || Object.Equals(ignore.stream, stream)) { - logger.DebugFormat("Recycling {0}", key); + _logger.DebugFormat("Recycling {0}", key); stream.Seek(0, SeekOrigin.Begin); var removed = streams.AddAndPop(key, new CacheItem(stream)); if (removed != null) { @@ -100,8 +97,7 @@ internal sealed class FileReadStream : FileStream private readonly FileInfo info; - private readonly static ILog logger = - LogManager.GetLogger(typeof(FileReadStream)); + private readonly static ILogging _logger = Logging.GetLogger(); private bool killed = false; @@ -112,12 +108,12 @@ public FileReadStream(FileInfo info) FileOptions.Asynchronous | FileOptions.SequentialScan) { this.info = info; - logger.DebugFormat("Opened file {0}", this.info.FullName); + _logger.DebugFormat("Opened file {0}", this.info.FullName); } public void Kill() { - logger.DebugFormat("Killed file {0}", info.FullName); + _logger.DebugFormat("Killed file {0}", info.FullName); killed = true; Close(); Dispose(); @@ -130,7 +126,7 @@ public override void Close() return; } base.Close(); - logger.DebugFormat("Closed file {0}", info.FullName); + _logger.DebugFormat("Closed file {0}", info.FullName); } protected override void Dispose(bool disposing) diff --git a/fsserver/Files/ImageFile.cs b/fsserver/Files/ImageFile.cs index f4f9ca1b..d3ba08e6 100644 --- a/fsserver/Files/ImageFile.cs +++ b/fsserver/Files/ImageFile.cs @@ -127,7 +127,7 @@ private void MaybeInit() height = tl.Properties.PhotoHeight; } catch (Exception ex) { - Debug("Failed to transpose Properties props", ex); + _logger.Debug("Failed to transpose Properties props", ex); } try { @@ -146,7 +146,7 @@ private void MaybeInit() } } catch (Exception ex) { - Debug("Failed to transpose Tag props", ex); + _logger.Debug("Failed to transpose Tag props", ex); } } @@ -156,17 +156,17 @@ private void MaybeInit() Server.UpdateFileCache(this); } catch (TagLib.CorruptFileException ex) { - Debug( + _logger.Debug( "Failed to read meta data via taglib for file " + Item.FullName, ex); initialized = true; } catch (TagLib.UnsupportedFormatException ex) { - Debug( + _logger.Debug( "Failed to read meta data via taglib for file " + Item.FullName, ex); initialized = true; } catch (Exception ex) { - Warn( + _logger.Warn( "Unhandled exception reading meta data for file " + Item.FullName, ex); } diff --git a/fsserver/Files/VideoFile.cs b/fsserver/Files/VideoFile.cs index 0ce826e5..44102d27 100644 --- a/fsserver/Files/VideoFile.cs +++ b/fsserver/Files/VideoFile.cs @@ -198,7 +198,7 @@ public Subtitle Subtitle } } catch (Exception ex) { - Error("Failed to look up subtitle", ex); + _logger.Error("Failed to look up subtitle", ex); subTitle = new Subtitle(); } return subTitle; @@ -233,7 +233,7 @@ private void MaybeInit() height = tl.Properties.VideoHeight; } catch (Exception ex) { - Debug("Failed to transpose Properties props", ex); + _logger.Debug("Failed to transpose Properties props", ex); } try { @@ -257,7 +257,7 @@ private void MaybeInit() } } catch (Exception ex) { - Debug("Failed to transpose Tag props", ex); + _logger.Debug("Failed to transpose Tag props", ex); } } @@ -266,17 +266,17 @@ private void MaybeInit() Server.UpdateFileCache(this); } catch (TagLib.CorruptFileException ex) { - Debug( + _logger.Debug( "Failed to read meta data via taglib for file " + Item.FullName, ex); initialized = true; } catch (TagLib.UnsupportedFormatException ex) { - Debug( + _logger.Debug( "Failed to read meta data via taglib for file " + Item.FullName, ex); initialized = true; } catch (Exception ex) { - Warn( + _logger.Warn( "Unhandled exception reading meta data for file " + Item.FullName, ex); } diff --git a/fsserver/IFileStore.cs b/fsserver/IFileStore.cs new file mode 100644 index 00000000..65886bbf --- /dev/null +++ b/fsserver/IFileStore.cs @@ -0,0 +1,16 @@ +using NMaier.SimpleDlna.Utilities; +using System; +using System.IO; + +namespace NMaier.SimpleDlna.FileMediaServer +{ + public interface IFileStore : IDisposable, IRepositoryItem + { + void Init(); + string StoreFile { get; } + bool HasCover(IStoreItem file); + byte[] MaybeGetCover(IStoreItem file); + byte[] MaybeGetFile(FileInfo info); + void MaybeStoreFile(IStoreItem file, byte[] data, byte[] coverData); + } +} diff --git a/fsserver/IStoreItem.cs b/fsserver/IStoreItem.cs new file mode 100644 index 00000000..91694daa --- /dev/null +++ b/fsserver/IStoreItem.cs @@ -0,0 +1,10 @@ +using System.IO; + +namespace NMaier.SimpleDlna.FileMediaServer +{ + public interface IStoreItem + { + FileInfo Item { get; set; } + Cover MaybeGetCover(); + } +} diff --git a/fsserver/Properties/AssemblyInfo.cs b/fsserver/Properties/AssemblyInfo.cs index 1b1f278c..c48005ac 100644 --- a/fsserver/Properties/AssemblyInfo.cs +++ b/fsserver/Properties/AssemblyInfo.cs @@ -1,6 +1,12 @@ using System.Reflection; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; [assembly: AssemblyTitle("File Server class library")] [assembly: AssemblyDescription("")] [assembly: Guid("0c898974-f4a3-4aa9-a096-5cd8a3bdd9d5")] +[assembly: InternalsVisibleTo("SimpleDLNA.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e345bff51cdfb0"+ +"3db6c1071f51f9e1b983ebdad46137eb74f1af2c435519bb40b904d19877e9a1dbec209ae51518"+ +"833d96be14a7034f36d73cd8126bea72be226fccdcce79f02ca0dcbe08f430f7c18c044677f0d5"+ +"499371a7864af49ae7bb0d30f92c21dd65f65e9dbe9a77d33a4552b7b216a61a0bf2e91e4ce938"+ +"ee7e14ad")] \ No newline at end of file diff --git a/fsserver/SerializeHelper.cs b/fsserver/SerializeHelper.cs new file mode 100644 index 00000000..bd8dd722 --- /dev/null +++ b/fsserver/SerializeHelper.cs @@ -0,0 +1,6 @@ +namespace NMaier.SimpleDlna.FileMediaServer +{ + internal static class SerializeHelper + { + } +} diff --git a/fsserver/fsserver.csproj b/fsserver/fsserver.csproj index a860fa22..ecf32a9f 100644 --- a/fsserver/fsserver.csproj +++ b/fsserver/fsserver.csproj @@ -27,7 +27,7 @@ AnyCPU - pdbonly + none true bin\Release\ TRACE @@ -45,10 +45,6 @@ sdlna.key.snk - - False - ..\packages\log4net.2.0.3\lib\net40-client\log4net.dll - @@ -63,23 +59,27 @@ Properties\GlobalAssemblyInfo.cs + + + - - + + + @@ -96,7 +96,9 @@ - + + Designer + diff --git a/fsserver/packages.config b/fsserver/packages.config index a1ab14d6..65653459 100644 --- a/fsserver/packages.config +++ b/fsserver/packages.config @@ -1,5 +1,4 @@  - \ No newline at end of file diff --git a/sdlna.VS2010.sln b/sdlna.VS2010.sln new file mode 100644 index 00000000..6549d5a6 --- /dev/null +++ b/sdlna.VS2010.sln @@ -0,0 +1,81 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FileStoreRaptorDB", "FileStoreRaptorDB\FileStoreRaptorDB.csproj", "{6961F1C2-41E9-4E7F-8E88-7D4A259B3DF8}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FileStoreSQLite", "FileStoreSQLite\FileStoreSQLite.csproj", "{25741114-7F31-421E-8D2B-357A3155CEE2}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "fsserver", "fsserver\fsserver.csproj", "{50E06B21-E11A-42F0-81E2-0911E771E861}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NMaier.Windows.Forms", "NMaier.Windows.Forms\NMaier.Windows.Forms.csproj", "{56667283-EBCD-4D63-BF61-FF319CB28A0B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "sdlna", "sdlna\sdlna.csproj", "{C99E77FD-0728-4A2F-A9C0-47AAC7CAEFED}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "server", "server\server.csproj", "{232A96F6-A2BF-44C8-B623-6E411F6296F2}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimpleDLNA", "SimpleDLNA\SimpleDLNA.csproj", "{9BAEFB29-C818-446B-9BB5-014E6A0CBB49}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "tests", "tests\tests.csproj", "{ED38A2A8-C0E5-4881-8F8E-591B34FD2C06}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "thumbs", "thumbs\thumbs.csproj", "{EF29F98A-B8B6-4591-BA29-E71BCC308E98}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "util", "util\util.csproj", "{A8960A7A-887C-40D7-9632-002E94BFC830}" +EndProject +Global + GlobalSection(SubversionScc) = preSolution + Svn-Managed = True + Manager = AnkhSVN - Subversion Support for Visual Studio + EndGlobalSection + GlobalSection(TestCaseManagementSettings) = postSolution + CategoryFile = Nrd.Core.vsmdi + EndGlobalSection + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {6961F1C2-41E9-4E7F-8E88-7D4A259B3DF8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6961F1C2-41E9-4E7F-8E88-7D4A259B3DF8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6961F1C2-41E9-4E7F-8E88-7D4A259B3DF8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6961F1C2-41E9-4E7F-8E88-7D4A259B3DF8}.Release|Any CPU.Build.0 = Release|Any CPU + {25741114-7F31-421E-8D2B-357A3155CEE2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {25741114-7F31-421E-8D2B-357A3155CEE2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {25741114-7F31-421E-8D2B-357A3155CEE2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {25741114-7F31-421E-8D2B-357A3155CEE2}.Release|Any CPU.Build.0 = Release|Any CPU + {50E06B21-E11A-42F0-81E2-0911E771E861}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {50E06B21-E11A-42F0-81E2-0911E771E861}.Debug|Any CPU.Build.0 = Debug|Any CPU + {50E06B21-E11A-42F0-81E2-0911E771E861}.Release|Any CPU.ActiveCfg = Release|Any CPU + {50E06B21-E11A-42F0-81E2-0911E771E861}.Release|Any CPU.Build.0 = Release|Any CPU + {56667283-EBCD-4D63-BF61-FF319CB28A0B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {56667283-EBCD-4D63-BF61-FF319CB28A0B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {56667283-EBCD-4D63-BF61-FF319CB28A0B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {56667283-EBCD-4D63-BF61-FF319CB28A0B}.Release|Any CPU.Build.0 = Release|Any CPU + {C99E77FD-0728-4A2F-A9C0-47AAC7CAEFED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C99E77FD-0728-4A2F-A9C0-47AAC7CAEFED}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C99E77FD-0728-4A2F-A9C0-47AAC7CAEFED}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C99E77FD-0728-4A2F-A9C0-47AAC7CAEFED}.Release|Any CPU.Build.0 = Release|Any CPU + {232A96F6-A2BF-44C8-B623-6E411F6296F2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {232A96F6-A2BF-44C8-B623-6E411F6296F2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {232A96F6-A2BF-44C8-B623-6E411F6296F2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {232A96F6-A2BF-44C8-B623-6E411F6296F2}.Release|Any CPU.Build.0 = Release|Any CPU + {9BAEFB29-C818-446B-9BB5-014E6A0CBB49}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9BAEFB29-C818-446B-9BB5-014E6A0CBB49}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9BAEFB29-C818-446B-9BB5-014E6A0CBB49}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9BAEFB29-C818-446B-9BB5-014E6A0CBB49}.Release|Any CPU.Build.0 = Release|Any CPU + {ED38A2A8-C0E5-4881-8F8E-591B34FD2C06}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {ED38A2A8-C0E5-4881-8F8E-591B34FD2C06}.Debug|Any CPU.Build.0 = Debug|Any CPU + {ED38A2A8-C0E5-4881-8F8E-591B34FD2C06}.Release|Any CPU.ActiveCfg = Release|Any CPU + {ED38A2A8-C0E5-4881-8F8E-591B34FD2C06}.Release|Any CPU.Build.0 = Release|Any CPU + {EF29F98A-B8B6-4591-BA29-E71BCC308E98}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EF29F98A-B8B6-4591-BA29-E71BCC308E98}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EF29F98A-B8B6-4591-BA29-E71BCC308E98}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EF29F98A-B8B6-4591-BA29-E71BCC308E98}.Release|Any CPU.Build.0 = Release|Any CPU + {A8960A7A-887C-40D7-9632-002E94BFC830}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A8960A7A-887C-40D7-9632-002E94BFC830}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A8960A7A-887C-40D7-9632-002E94BFC830}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A8960A7A-887C-40D7-9632-002E94BFC830}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/sdlna.sln b/sdlna.sln index 710aa9eb..a755b0b8 100644 --- a/sdlna.sln +++ b/sdlna.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2013 -VisualStudioVersion = 12.0.31101.0 +# Visual Studio 14 +VisualStudioVersion = 14.0.23107.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "sdlna", "sdlna\sdlna.csproj", "{C99E77FD-0728-4A2F-A9C0-47AAC7CAEFED}" EndProject @@ -34,6 +34,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{311651 .nuget\NuGet.targets = .nuget\NuGet.targets EndProjectSection EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "tests", "tests\tests.csproj", "{ED38A2A8-C0E5-4881-8F8E-591B34FD2C06}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FileStoreSQLite", "FileStoreSQLite\FileStoreSQLite.csproj", "{25741114-7F31-421E-8D2B-357A3155CEE2}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FileStoreRaptorDB", "FileStoreRaptorDB\FileStoreRaptorDB.csproj", "{6961F1C2-41E9-4E7F-8E88-7D4A259B3DF8}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -70,6 +76,18 @@ Global {56667283-EBCD-4D63-BF61-FF319CB28A0B}.Debug|Any CPU.Build.0 = Debug|Any CPU {56667283-EBCD-4D63-BF61-FF319CB28A0B}.Release|Any CPU.ActiveCfg = Release|Any CPU {56667283-EBCD-4D63-BF61-FF319CB28A0B}.Release|Any CPU.Build.0 = Release|Any CPU + {ED38A2A8-C0E5-4881-8F8E-591B34FD2C06}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {ED38A2A8-C0E5-4881-8F8E-591B34FD2C06}.Debug|Any CPU.Build.0 = Debug|Any CPU + {ED38A2A8-C0E5-4881-8F8E-591B34FD2C06}.Release|Any CPU.ActiveCfg = Release|Any CPU + {ED38A2A8-C0E5-4881-8F8E-591B34FD2C06}.Release|Any CPU.Build.0 = Release|Any CPU + {25741114-7F31-421E-8D2B-357A3155CEE2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {25741114-7F31-421E-8D2B-357A3155CEE2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {25741114-7F31-421E-8D2B-357A3155CEE2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {25741114-7F31-421E-8D2B-357A3155CEE2}.Release|Any CPU.Build.0 = Release|Any CPU + {6961F1C2-41E9-4E7F-8E88-7D4A259B3DF8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6961F1C2-41E9-4E7F-8E88-7D4A259B3DF8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6961F1C2-41E9-4E7F-8E88-7D4A259B3DF8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6961F1C2-41E9-4E7F-8E88-7D4A259B3DF8}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/sdlna/Options.cs b/sdlna/Options.cs index 29236cd9..4cd9f2d3 100644 --- a/sdlna/Options.cs +++ b/sdlna/Options.cs @@ -37,9 +37,14 @@ internal class Options : GetOpt private int port = 0; - [Argument("cache", HelpVar = "file", HelpText = "Cache file to use for storing meta data (default: none)")] - [ShortArgument('c')] - public FileInfo CacheFile = null; + //[Argument("cache", HelpVar = "file", HelpText = "Cache file to use for storing meta data (default: none)")] + //[ShortArgument('c')] + //public FileInfo CacheFile = null; + + [Argument("storage", HelpText = "Storage database; see --list-sort-orders")] + [ShortArgument('o')] + [FlagArgument(true)] + public string FileStore = "RaptorDB"; [Argument("name", HelpVar = "name", HelpText = "Friendly name for this server (group)")] [ShortArgument('n')] diff --git a/sdlna/Program.cs b/sdlna/Program.cs index 951e832a..1929ed99 100644 --- a/sdlna/Program.cs +++ b/sdlna/Program.cs @@ -3,6 +3,7 @@ using NMaier.SimpleDlna.FileMediaServer; using NMaier.SimpleDlna.Server; using NMaier.SimpleDlna.Server.Comparers; +using NMaier.SimpleDlna.Server.Http; using NMaier.SimpleDlna.Server.Views; using NMaier.SimpleDlna.Utilities; using System; @@ -117,29 +118,29 @@ private static void Main(string[] args) var types = options.Types[0]; foreach (var t in options.Types) { types = types | t; - server.InfoFormat("Enabled type {0}", t); + server.Logger.InfoFormat("Enabled type {0}", t); } var friendlyName = "sdlna"; if (options.Seperate) { foreach (var d in options.Directories) { - server.InfoFormat("Mounting FileServer for {0}", d.FullName); + server.Logger.InfoFormat("Mounting FileServer for {0}", d.FullName); var fs = SetupFileServer( options, types, new DirectoryInfo[] { d }); friendlyName = fs.FriendlyName; server.RegisterMediaServer(fs); - server.NoticeFormat("{0} mounted", d.FullName); + server.Logger.NoticeFormat("{0} mounted", d.FullName); } } else { - server.InfoFormat( + server.Logger.InfoFormat( "Mounting FileServer for {0} ({1})", options.Directories[0], options.Directories.Length); var fs = SetupFileServer(options, types, options.Directories); friendlyName = fs.FriendlyName; server.RegisterMediaServer(fs); - server.NoticeFormat( + server.Logger.NoticeFormat( "{0} ({1}) mounted", options.Directories[0], options.Directories.Length); } @@ -167,11 +168,11 @@ private static void Main(string[] args) private static void Run(HttpServer server) { - server.Info("CTRL-C to terminate"); + server.Logger.Info("CTRL-C to terminate"); BlockEvent.WaitOne(); - server.Info("Going down!"); - server.Info("Closed!"); + server.Logger.Info("Going down!"); + server.Logger.Info("Closed!"); } private static FileServer SetupFileServer(Options options, @@ -193,8 +194,8 @@ private static FileServer SetupFileServer(Options options, fs.FriendlyName = options.FriendlyName; } try { - if (options.CacheFile != null) { - fs.SetCacheFile(options.CacheFile); + if (options.FileStore != null) { + fs.SetCacheFile(FileStoreRepository.Lookup(options.FileStore)); } fs.Load(); if (!options.Rescanning) { @@ -218,7 +219,7 @@ private static void ShowLicense() private static void ShowVersion() { Console.WriteLine("Version: {0}", ProductInformation.ProductVersion); - Console.WriteLine("Http: {0}", HttpServer.Signature); + Console.WriteLine("Http: {0}", Server.Http.HttpServer.Signature); } } } diff --git a/sdlna/sdlna.csproj b/sdlna/sdlna.csproj index 25104c21..082f946d 100644 --- a/sdlna/sdlna.csproj +++ b/sdlna/sdlna.csproj @@ -53,10 +53,10 @@ ..\sdlna.ruleset - D:\bin\ + bin\Release\ TRACE true - pdbonly + none AnyCPU bin\Release\sdnla.exe.CodeAnalysisLog.xml true @@ -104,6 +104,10 @@ + + {6961f1c2-41e9-4e7f-8e88-7d4a259b3df8} + FileStoreRaptorDB + {50E06B21-E11A-42F0-81E2-0911E771E861} fsserver diff --git a/server/Handlers/IconHandler.cs b/server/Handlers/IconHandler.cs index ad216865..59a8bc31 100644 --- a/server/Handlers/IconHandler.cs +++ b/server/Handlers/IconHandler.cs @@ -1,4 +1,6 @@ -namespace NMaier.SimpleDlna.Server +using NMaier.SimpleDlna.Server.Http; + +namespace NMaier.SimpleDlna.Server { internal sealed class IconHandler : IPrefixHandler { diff --git a/server/Handlers/IndexHandler.cs b/server/Handlers/IndexHandler.cs index b870243e..30c8b2b9 100644 --- a/server/Handlers/IndexHandler.cs +++ b/server/Handlers/IndexHandler.cs @@ -1,4 +1,5 @@ -using NMaier.SimpleDlna.Utilities; +using NMaier.SimpleDlna.Server.Http; +using NMaier.SimpleDlna.Utilities; using System.Linq; namespace NMaier.SimpleDlna.Server diff --git a/server/Handlers/MediaMount.cs b/server/Handlers/MediaMount.cs index e33bee53..a6c8aa2e 100644 --- a/server/Handlers/MediaMount.cs +++ b/server/Handlers/MediaMount.cs @@ -1,5 +1,5 @@ -using NMaier.SimpleDlna.Server.Metadata; -using NMaier.SimpleDlna.Utilities; +using NMaier.SimpleDlna.Server.Http; +using NMaier.SimpleDlna.Server.Metadata; using System; using System.Collections.Generic; using System.Net; @@ -7,9 +7,9 @@ using System.Xml; namespace NMaier.SimpleDlna.Server -{ +{//Logging, internal sealed partial class MediaMount - : Logging, IMediaServer, IPrefixHandler + : IMediaServer, IPrefixHandler { private readonly Dictionary guidsForAddresses = new Dictionary(); @@ -75,7 +75,7 @@ public Guid Uuid private void ChangedServer(object sender, EventArgs e) { soapCache.Clear(); - InfoFormat("Rescanned mount {0}", Uuid); + _logger.InfoFormat("Rescanned mount {0}", Uuid); systemID++; } @@ -138,16 +138,17 @@ public IResponse HandleRequest(IRequest request) { if (Authorizer != null && !IPAddress.IsLoopback(request.RemoteEndpoint.Address) && - !Authorizer.Authorize( - request.Headers, - request.RemoteEndpoint, - IP.GetMAC(request.RemoteEndpoint.Address) - )) { + !Authorizer.Authorize(new HttpRequestAuthParameters(request.Headers, request.RemoteEndpoint)) + // request.Headers, + // request.RemoteEndpoint, + // IP.GetMAC(request.RemoteEndpoint.Address) + //) + ) { throw new HttpStatusException(HttpCode.Denied); } var path = request.Path.Substring(prefix.Length); - Debug(path); + _logger.Debug(path); if (path == "description.xml") { return new StringResponse( HttpCode.Ok, @@ -181,19 +182,19 @@ public IResponse HandleRequest(IRequest request) } if (path.StartsWith("file/", StringComparison.Ordinal)) { var id = path.Split('/')[1]; - InfoFormat("Serving file {0}", id); + _logger.InfoFormat("Serving file {0}", id); var item = GetItem(id) as IMediaResource; return new ItemResponse(prefix, request, item); } if (path.StartsWith("cover/", StringComparison.Ordinal)) { var id = path.Split('/')[1]; - InfoFormat("Serving cover {0}", id); + _logger.InfoFormat("Serving cover {0}", id); var item = GetItem(id) as IMediaCover; return new ItemResponse(prefix, request, item.Cover, "Interactive"); } if (path.StartsWith("subtitle/", StringComparison.Ordinal)) { var id = path.Split('/')[1]; - InfoFormat("Serving subtitle {0}", id); + _logger.InfoFormat("Serving subtitle {0}", id); var item = GetItem(id) as IMetaVideoItem; return new ItemResponse(prefix, request, item.Subtitle, "Background"); } @@ -215,7 +216,7 @@ public IResponse HandleRequest(IRequest request) if (request.Method == "UNSUBSCRIBE") { return new StringResponse(HttpCode.Ok, string.Empty); } - WarnFormat("Did not understand {0} {1}", request.Method, path); + _logger.WarnFormat("Did not understand {0} {1}", request.Method, path); throw new HttpStatusException(HttpCode.NotFound); } } diff --git a/server/Handlers/MediaMount_HTML.cs b/server/Handlers/MediaMount_HTML.cs index 6a6900d8..0ba5bb6e 100644 --- a/server/Handlers/MediaMount_HTML.cs +++ b/server/Handlers/MediaMount_HTML.cs @@ -1,4 +1,5 @@ -using NMaier.SimpleDlna.Utilities; +using NMaier.SimpleDlna.Server.Http; +using NMaier.SimpleDlna.Utilities; using System; using System.Collections.Generic; using System.Xml; diff --git a/server/Handlers/MediaMount_SOAP.cs b/server/Handlers/MediaMount_SOAP.cs index 0a641890..6e88bb84 100644 --- a/server/Handlers/MediaMount_SOAP.cs +++ b/server/Handlers/MediaMount_SOAP.cs @@ -1,4 +1,5 @@ -using NMaier.SimpleDlna.Server.Metadata; +using NMaier.SimpleDlna.Server.Http; +using NMaier.SimpleDlna.Server.Metadata; using NMaier.SimpleDlna.Utilities; using System; using System.Collections.Generic; @@ -9,6 +10,7 @@ namespace NMaier.SimpleDlna.Server { internal partial class MediaMount { + private static readonly ILogging _logger = Logging.GetLogger(); private const string NS_DC = "http://purl.org/dc/elements/1.1/"; private const string NS_DIDL = @@ -370,7 +372,7 @@ private IEnumerable> HandleBrowse( } } catch (Exception ex) { - Debug("Not all params provided", ex); + _logger.Debug("Not all params provided", ex); } var root = GetItem(id) as IMediaFolder; @@ -573,7 +575,7 @@ private IResponse ProcessSoapRequest(IRequest request) "401Invalid Action"; fault.AppendChild(detail); rbody.AppendChild(fault); - WarnFormat( + _logger.WarnFormat( "Invalid call: Action: {0}, Params: {1}, Problem {2}", method.LocalName, sparams, ex.Message); } diff --git a/server/Http/HTTPServer.cs b/server/Http/HTTPServer.cs index 2ba4ac78..b72e4fd7 100644 --- a/server/Http/HTTPServer.cs +++ b/server/Http/HTTPServer.cs @@ -1,5 +1,4 @@ -using log4net; -using NMaier.SimpleDlna.Server.Ssdp; +using NMaier.SimpleDlna.Server.Ssdp; using NMaier.SimpleDlna.Utilities; using System; using System.Collections.Concurrent; @@ -10,10 +9,14 @@ using System.Reflection; using System.Timers; -namespace NMaier.SimpleDlna.Server -{ - public sealed class HttpServer : Logging, IDisposable +namespace NMaier.SimpleDlna.Server.Http +{//Logging, + public sealed class HttpServer : IDisposable { + + private static readonly ILogging _logger = Logging.GetLogger(); + public ILogging Logger{get{return _logger;} } + private readonly ConcurrentDictionary clients = new ConcurrentDictionary(); @@ -60,7 +63,7 @@ public HttpServer(int port) RealPort = (listener.LocalEndpoint as IPEndPoint).Port; - NoticeFormat( + Logger.NoticeFormat( "Running HTTP Server: {0} on port {1}", Signature, RealPort); ssdpServer = new SsdpHandler(); @@ -97,7 +100,7 @@ private void Accept() catch (ObjectDisposedException) { } catch (Exception ex) { - Fatal("Failed to accept", ex); + Logger.Fatal("Failed to accept", ex); } } @@ -111,7 +114,7 @@ private void AcceptCallback(IAsyncResult result) { return DateTime.Now; }); - DebugFormat("Accepted client {0}", client); + Logger.DebugFormat("Accepted client {0}", client); client.Start(); } catch (Exception) { @@ -122,7 +125,7 @@ private void AcceptCallback(IAsyncResult result) catch (ObjectDisposedException) { } catch (Exception ex) { - Error("Failed to accept a client", ex); + Logger.Error("Failed to accept a client", ex); } finally { Accept(); @@ -144,7 +147,7 @@ private static string GenerateServerSignature() pstring = Formatting.GetSystemName(); } catch (Exception ex) { - LogManager.GetLogger(typeof(HttpServer)).Debug("Failed to get uname", ex); + _logger.Debug("Failed to get uname", ex); } break; } @@ -163,7 +166,7 @@ private void TimeouterCallback(object sender, ElapsedEventArgs e) { foreach (var c in clients.ToList()) { if (c.Key.IsATimeout) { - DebugFormat("Collected timeout client {0}", c); + Logger.DebugFormat("Collected timeout client {0}", c); c.Key.Close(); } } @@ -219,7 +222,7 @@ internal void RegisterHandler(IPrefixHandler handler) if (!prefixes.TryAdd(prefix, handler)) { throw new ArgumentException("Invalid preifx; already taken"); } - DebugFormat("Registered Handler for {0}", prefix); + Logger.DebugFormat("Registered Handler for {0}", prefix); } internal void RemoveClient(HttpClient client) @@ -232,13 +235,13 @@ internal void UnregisterHandler(IPrefixHandler handler) { IPrefixHandler ignored; if (prefixes.TryRemove(handler.Prefix, out ignored)) { - DebugFormat("Unregistered Handler for {0}", handler.Prefix); + Logger.DebugFormat("Unregistered Handler for {0}", handler.Prefix); } } public void Dispose() { - Debug("Disposing HTTP"); + Logger.Debug("Disposing HTTP"); timeouter.Enabled = false; foreach (var s in servers.Values.ToList()) { UnregisterMediaServer(s); @@ -268,7 +271,7 @@ public void RegisterMediaServer(IMediaServer server) RegisterHandler(mount); foreach (var address in IP.ExternalIPAddresses) { - DebugFormat("Registering device for {0}", address); + Logger.DebugFormat("Registering device for {0}", address); var deviceGuid = Guid.NewGuid(); var list = devicesForServers.GetOrAdd(guid, new List()); lock (list) { @@ -282,7 +285,7 @@ public void RegisterMediaServer(IMediaServer server) mount.DescriptorURI )); ssdpServer.RegisterNotification(deviceGuid, uri, address); - NoticeFormat("New mount at: {0}", uri); + Logger.NoticeFormat("New mount at: {0}", uri); } } @@ -310,7 +313,7 @@ public void UnregisterMediaServer(IMediaServer server) MediaMount ignored; if (servers.TryRemove(server.Uuid, out ignored)) { - InfoFormat("Unregistered Media Server {0}", server.Uuid); + Logger.InfoFormat("Unregistered Media Server {0}", server.Uuid); } } } diff --git a/server/Http/HttpAuthorizationEventArgs.cs b/server/Http/HttpAuthorizationEventArgs.cs index 22bcab6d..606499d0 100644 --- a/server/Http/HttpAuthorizationEventArgs.cs +++ b/server/Http/HttpAuthorizationEventArgs.cs @@ -1,7 +1,7 @@ using System; using System.Net; -namespace NMaier.SimpleDlna.Server +namespace NMaier.SimpleDlna.Server.Http { public sealed class HttpAuthorizationEventArgs : EventArgs { diff --git a/server/Http/HttpAuthorizer.cs b/server/Http/HttpAuthorizer.cs index ef93c1ec..d80e2d3b 100644 --- a/server/Http/HttpAuthorizer.cs +++ b/server/Http/HttpAuthorizer.cs @@ -1,16 +1,13 @@ using NMaier.SimpleDlna.Utilities; using System; using System.Collections.Generic; -using System.Net; -namespace NMaier.SimpleDlna.Server -{ - public sealed class HttpAuthorizer - : Logging, IHttpAuthorizationMethod, IDisposable +namespace NMaier.SimpleDlna.Server.Http +{//Logging, + public sealed class HttpAuthorizer : IHttpAuthorizationMethod, IDisposable { - private readonly List methods = - new List(); - + private static readonly ILogging _logger = Logging.GetLogger(); + private readonly List methods = new List(); private readonly HttpServer server = null; public HttpAuthorizer() @@ -28,10 +25,10 @@ public HttpAuthorizer(HttpServer server) private void OnAuthorize(object sender, HttpAuthorizationEventArgs e) { - e.Cancel = !Authorize( - e.Headers, - e.RemoteEndpoint, - IP.GetMAC(e.RemoteEndpoint.Address) + e.Cancel = !Authorize(new HttpRequestAuthParameters(e.Headers,e.RemoteEndpoint) + //e.Headers, + //e.RemoteEndpoint, + //IP.GetMAC(e.RemoteEndpoint.Address) ); } @@ -43,21 +40,22 @@ public void AddMethod(IHttpAuthorizationMethod method) methods.Add(method); } - public bool Authorize(IHeaders headers, IPEndPoint endPoint, string mac) + public bool Authorize(HttpRequestAuthParameters ap)//IHeaders headers, IPEndPoint endPoint, string mac) { + _logger.NoticeFormat("Authorize:[{0}]", ap); if (methods.Count == 0) { return true; } try { foreach (var m in methods) { - if (m.Authorize(headers, endPoint, mac)) { + if (m.Authorize(ap)) { return true; } } return false; } catch (Exception ex) { - Error("Failed to authorize", ex); + _logger.Error("Failed to authorize", ex); return false; } } diff --git a/server/Http/HttpClient.cs b/server/Http/HttpClient.cs index 4889220d..3cdd434f 100644 --- a/server/Http/HttpClient.cs +++ b/server/Http/HttpClient.cs @@ -6,10 +6,12 @@ using System.Text; using System.Text.RegularExpressions; -namespace NMaier.SimpleDlna.Server -{ - internal sealed class HttpClient : Logging, IRequest, IDisposable +namespace NMaier.SimpleDlna.Server.Http +{//Logging, + internal sealed class HttpClient : IRequest, IDisposable { + private static readonly ILogging _logger = Logging.GetLogger(); + private const uint BEGIN_TIMEOUT = 30; private const int BUFFER_SIZE = 1 << 16; @@ -244,7 +246,7 @@ private Stream ProcessRanges(IResponse rangedResponse, ref HttpCode status) status = HttpCode.Partial; } catch (Exception ex) { - Warn(String.Format( + _logger.Warn(String.Format( "{0} - Failed to process range request!", this), ex); } return responseBody; @@ -256,7 +258,7 @@ private void Read() stream.BeginRead(buffer, 0, buffer.Length, ReadCallback, 0); } catch (IOException ex) { - Warn(String.Format("{0} - Failed to BeginRead", this), ex); + _logger.Warn(String.Format("{0} - Failed to BeginRead", this), ex); Close(); } } @@ -275,13 +277,13 @@ private void ReadCallback(IAsyncResult result) if (read < 0) { throw new HttpException("Client did not send anything"); } - DebugFormat("{0} - Read {1} bytes", this, read); + _logger.DebugFormat("{0} - Read {1} bytes", this, read); readStream.Write(buffer, 0, read); lastActivity = DateTime.Now; } catch (Exception) { if (!IsATimeout) { - WarnFormat("{0} - Failed to read data", this); + _logger.WarnFormat("{0} - Failed to read data", this); Close(); } return; @@ -304,7 +306,7 @@ private void ReadCallback(IAsyncResult result) } var bytes = Encoding.ASCII.GetBytes(reader.ReadToEnd()); readStream.Write(bytes, 0, bytes.Length); - DebugFormat("Must read body bytes {0}", bodyBytes); + _logger.DebugFormat("Must read body bytes {0}", bodyBytes); } else { readStream = new MemoryStream(); @@ -315,7 +317,7 @@ private void ReadCallback(IAsyncResult result) var parts = line.Split(new char[] { ' ' }, 3); method = parts[0].Trim().ToUpperInvariant(); path = parts[1].Trim(); - DebugFormat("{0} - {1} request for {2}", this, method, path); + _logger.DebugFormat("{0} - {1} request for {2}", this, method, path); } else { var parts = line.Split(new char[] { ':' }, 2); @@ -324,20 +326,20 @@ private void ReadCallback(IAsyncResult result) } } if (bodyBytes != 0 && bodyBytes > readStream.Length) { - DebugFormat( + _logger.DebugFormat( "{0} - Bytes to go {1}", this, bodyBytes - readStream.Length); Read(); return; } using (readStream) { body = Encoding.UTF8.GetString(readStream.ToArray()); - Debug(body); - Debug(headers); + _logger.Debug(body); + _logger.Debug(headers); } SetupResponse(); } catch (Exception ex) { - Warn(String.Format("{0} - Failed to process request", this), ex); + _logger.Warn(String.Format("{0} - Failed to process request", this), ex); response = Error500.HandleRequest(this); SendResponse(); } @@ -380,7 +382,7 @@ private void SendResponse() responseStream.AddStream(responseBody); responseBody = null; } - InfoFormat("{0} - {1} response for {2}", this, (uint)statusCode, path); + _logger.InfoFormat("{0} - {1} response for {2}", this, (uint)statusCode, path); state = HttpStates.WRITING; var sp = new StreamPump(responseStream, stream, BUFFER_SIZE); sp.Pump((pump, result) => @@ -388,7 +390,7 @@ private void SendResponse() pump.Input.Close(); pump.Input.Dispose(); if (result == StreamPumpResult.Delivered) { - DebugFormat("{0} - Done writing response", this); + _logger.DebugFormat("{0} - Done writing response", this); string conn; if (headers.TryGetValue("connection", out conn) && @@ -398,7 +400,7 @@ private void SendResponse() } } else { - DebugFormat("{0} - Client aborted connection", this); + _logger.DebugFormat("{0} - Client aborted connection", this); } Close(); }); @@ -422,6 +424,7 @@ private void SetupResponse() throw new HttpStatusException(HttpCode.Denied); } if (string.IsNullOrEmpty(path)) { + _logger.Error("Empty path"); throw new HttpStatusException(HttpCode.NotFound); } var handler = owner.FindHandler(path); @@ -435,9 +438,9 @@ private void SetupResponse() } catch (HttpStatusException ex) { #if DEBUG - Warn(String.Format("{0} - Got a {2}: {1}", this, path, ex.Code), ex); + _logger.Warn(String.Format("{0} - Got a {2}: {1}", this, path, ex.Code), ex); #else - InfoFormat("{0} - Got a {2}: {1}", this, path, ex.Code); + _logger.InfoFormat("{0} - Got a {2}: {1}", this, path, ex.Code); #endif switch (ex.Code) { case HttpCode.NotFound: @@ -459,7 +462,7 @@ private void SetupResponse() } } catch (Exception ex) { - Warn(String.Format("{0} - Failed to process response", this), ex); + _logger.Warn(String.Format("{0} - Failed to process response", this), ex); response = Error500.HandleRequest(this); } SendResponse(); @@ -469,7 +472,7 @@ internal void Close() { State = HttpStates.CLOSED; - DebugFormat( + _logger.DebugFormat( "{0} - Closing connection after {1} requests", this, requestCount); try { client.Close(); diff --git a/server/Http/HttpCode.cs b/server/Http/HttpCode.cs index 06f5cce3..75d8e5b4 100644 --- a/server/Http/HttpCode.cs +++ b/server/Http/HttpCode.cs @@ -1,4 +1,4 @@ -namespace NMaier.SimpleDlna.Server +namespace NMaier.SimpleDlna.Server.Http { public enum HttpCode : int { diff --git a/server/Http/HttpPhrases.cs b/server/Http/HttpPhrases.cs index 09266ea0..21767a65 100644 --- a/server/Http/HttpPhrases.cs +++ b/server/Http/HttpPhrases.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; -namespace NMaier.SimpleDlna.Server +namespace NMaier.SimpleDlna.Server.Http { internal static class HttpPhrases { diff --git a/server/Http/HttpRequestAuthParameters.cs b/server/Http/HttpRequestAuthParameters.cs new file mode 100644 index 00000000..70ee89e7 --- /dev/null +++ b/server/Http/HttpRequestAuthParameters.cs @@ -0,0 +1,30 @@ +using NMaier.SimpleDlna.Utilities; +using System.Net; + +namespace NMaier.SimpleDlna.Server.Http +{ + public class HttpRequestAuthParameters + { + string _userAgent; + public string UserAgent { get { return _userAgent; } } + IPAddress _address; + public IPAddress Address { get { return _address; } } + string _mac; + public string Mac { get { return _mac; } } + + public HttpRequestAuthParameters(IHeaders headers, IPEndPoint endPoint) { + if (headers != null) { + headers.TryGetValue("User-Agent", out _userAgent); + } + if (endPoint != null) { + _address = endPoint.Address; + _mac = IP.GetMAC(_address); + } + } + + public override string ToString() + { + return string.Format("[{0}][{1}][{2}]",_address,_mac,_userAgent); + } + } +} diff --git a/server/Http/IHttpAuthorizationMethod.cs b/server/Http/IHttpAuthorizationMethod.cs index c04c96b8..4ae0cd42 100644 --- a/server/Http/IHttpAuthorizationMethod.cs +++ b/server/Http/IHttpAuthorizationMethod.cs @@ -1,6 +1,4 @@ -using System.Net; - -namespace NMaier.SimpleDlna.Server +namespace NMaier.SimpleDlna.Server.Http { public interface IHttpAuthorizationMethod { @@ -11,6 +9,6 @@ public interface IHttpAuthorizationMethod /// Client EndPoint /// Client MAC address /// true if authorized - bool Authorize(IHeaders headers, IPEndPoint endPoint, string mac); + bool Authorize(HttpRequestAuthParameters ap);//IHeaders headers, IPEndPoint endPoint, string mac); } } diff --git a/server/Http/IPAddressAuthorizer.cs b/server/Http/IPAddressAuthorizer.cs index f7f453ac..647729dc 100644 --- a/server/Http/IPAddressAuthorizer.cs +++ b/server/Http/IPAddressAuthorizer.cs @@ -4,10 +4,11 @@ using System.Linq; using System.Net; -namespace NMaier.SimpleDlna.Server -{ - public sealed class IPAddressAuthorizer : Logging, IHttpAuthorizationMethod +namespace NMaier.SimpleDlna.Server.Http +{//Logging, + public sealed class IPAddressAuthorizer : IHttpAuthorizationMethod { + private static readonly ILogging _logger = Logging.GetLogger(); private readonly Dictionary ips = new Dictionary(); @@ -30,21 +31,21 @@ public IPAddressAuthorizer(IEnumerable addresses) { } - public bool Authorize(IHeaders headers, IPEndPoint endPoint, string mac) + public bool Authorize(HttpRequestAuthParameters ap)//IHeaders headers, IPEndPoint endPoint, string mac) { - if (endPoint == null) { + //if (endPoint == null) { + // return false; + //} + //var addr = endPoint.Address; + if (ap.Address == null) { return false; } - var addr = endPoint.Address; - if (addr == null) { - return false; - } - var rv = ips.ContainsKey(addr); + var rv = ips.ContainsKey(ap.Address); if (!rv) { - DebugFormat("Rejecting {0}. Not in IP whitelist", addr); + _logger.DebugFormat("Rejecting {0}. Not in IP whitelist", ap.Address); } else { - DebugFormat("Accepted {0} via IP whitelist", addr); + _logger.DebugFormat("Accepted {0} via IP whitelist", ap.Address); } return rv; } diff --git a/server/Http/MacAuthorizer.cs b/server/Http/MacAuthorizer.cs index a3f33482..e976d898 100644 --- a/server/Http/MacAuthorizer.cs +++ b/server/Http/MacAuthorizer.cs @@ -1,12 +1,12 @@ using NMaier.SimpleDlna.Utilities; using System; using System.Collections.Generic; -using System.Net; -namespace NMaier.SimpleDlna.Server -{ - public sealed class MacAuthorizer : Logging, IHttpAuthorizationMethod +namespace NMaier.SimpleDlna.Server.Http +{//Logging, + public sealed class MacAuthorizer : IHttpAuthorizationMethod { + private static readonly ILogging _logger = Logging.GetLogger(); private readonly Dictionary macs = new Dictionary(); @@ -28,18 +28,18 @@ public MacAuthorizer(IEnumerable macs) } } - public bool Authorize(IHeaders headers, IPEndPoint endPoint, string mac) + public bool Authorize(HttpRequestAuthParameters ap)//IHeaders headers, IPEndPoint endPoint, string mac) { - if (string.IsNullOrEmpty(mac)) { + if (string.IsNullOrEmpty(ap.Mac)) { return false; } - var rv = macs.ContainsKey(mac); + var rv = macs.ContainsKey(ap.Mac); if (!rv) { - DebugFormat("Rejecting {0}. Not in MAC whitelist", mac ?? ""); + _logger.DebugFormat("Rejecting {0}. Not in MAC whitelist", ap.Mac ?? ""); } else { - DebugFormat("Accepted {0} via MAC whitelist", mac); + _logger.DebugFormat("Accepted {0} via MAC whitelist", ap.Mac); } return rv; } diff --git a/server/Http/ResponseHeaders.cs b/server/Http/ResponseHeaders.cs index e8762a54..ee456681 100644 --- a/server/Http/ResponseHeaders.cs +++ b/server/Http/ResponseHeaders.cs @@ -1,6 +1,6 @@ using System; -namespace NMaier.SimpleDlna.Server +namespace NMaier.SimpleDlna.Server.Http { public sealed class ResponseHeaders : RawHeaders { diff --git a/server/Http/UserAgentAuthorizer.cs b/server/Http/UserAgentAuthorizer.cs index eb4575bb..385c0a0a 100644 --- a/server/Http/UserAgentAuthorizer.cs +++ b/server/Http/UserAgentAuthorizer.cs @@ -1,12 +1,12 @@ using NMaier.SimpleDlna.Utilities; using System; using System.Collections.Generic; -using System.Net; -namespace NMaier.SimpleDlna.Server -{ - public sealed class UserAgentAuthorizer : Logging, IHttpAuthorizationMethod +namespace NMaier.SimpleDlna.Server.Http +{//Logging, + public sealed class UserAgentAuthorizer : IHttpAuthorizationMethod { + private static readonly ILogging _logger = Logging.GetLogger(); private readonly Dictionary userAgents = new Dictionary(); @@ -27,24 +27,24 @@ public UserAgentAuthorizer(IEnumerable userAgents) } } - public bool Authorize(IHeaders headers, IPEndPoint endPoint, string mac) + public bool Authorize(HttpRequestAuthParameters ap)//IHeaders headers, IPEndPoint endPoint, string mac) { - if (headers == null) { - throw new ArgumentNullException("headers"); - } - string ua; - if (!headers.TryGetValue("User-Agent", out ua)) { - return false; - } - if (string.IsNullOrEmpty(ua)) { + //if (headers == null) { + // throw new ArgumentNullException("headers"); + //} + //string ua; + //if (!headers.TryGetValue("User-Agent", out ua)) { + // return false; + //} + if (string.IsNullOrEmpty(ap.UserAgent)) { return false; } - var rv = userAgents.ContainsKey(ua); + var rv = userAgents.ContainsKey(ap.UserAgent); if (!rv) { - DebugFormat("Rejecting {0}. Not in User-Agent whitelist", ua); + _logger.DebugFormat("Rejecting {0}. Not in User-Agent whitelist", ap.UserAgent); } else { - DebugFormat("Accepted {0} via User-Agent whitelist", ua); + _logger.DebugFormat("Accepted {0} via User-Agent whitelist", ap.UserAgent); } return rv; } diff --git a/server/Interfaces/IMediaServer.cs b/server/Interfaces/IMediaServer.cs index dc5b6cf8..0e80ea78 100644 --- a/server/Interfaces/IMediaServer.cs +++ b/server/Interfaces/IMediaServer.cs @@ -1,4 +1,5 @@ -using System; +using NMaier.SimpleDlna.Server.Http; +using System; namespace NMaier.SimpleDlna.Server { diff --git a/server/Interfaces/IResponse.cs b/server/Interfaces/IResponse.cs index 5282b3db..6c239bdf 100644 --- a/server/Interfaces/IResponse.cs +++ b/server/Interfaces/IResponse.cs @@ -1,4 +1,5 @@ -using System.IO; +using NMaier.SimpleDlna.Server.Http; +using System.IO; namespace NMaier.SimpleDlna.Server { diff --git a/server/Responses/FileResponse.cs b/server/Responses/FileResponse.cs index 83c8156e..71ff615b 100644 --- a/server/Responses/FileResponse.cs +++ b/server/Responses/FileResponse.cs @@ -1,4 +1,5 @@ -using System.IO; +using NMaier.SimpleDlna.Server.Http; +using System.IO; namespace NMaier.SimpleDlna.Server { diff --git a/server/Responses/ItemResponse.cs b/server/Responses/ItemResponse.cs index 0d625bcc..1882d65e 100644 --- a/server/Responses/ItemResponse.cs +++ b/server/Responses/ItemResponse.cs @@ -1,12 +1,14 @@ -using NMaier.SimpleDlna.Server.Metadata; +using NMaier.SimpleDlna.Server.Http; +using NMaier.SimpleDlna.Server.Metadata; using NMaier.SimpleDlna.Utilities; using System; using System.IO; namespace NMaier.SimpleDlna.Server -{ - internal sealed class ItemResponse : Logging, IResponse +{//Logging, + internal sealed class ItemResponse : IResponse { + private static readonly ILogging _logger = Logging.GetLogger(); private readonly Headers headers; private readonly IMediaResource item; @@ -63,7 +65,7 @@ public ItemResponse(string prefix, IRequest request, IMediaResource item, prefix, item.Id ); - DebugFormat("Sending subtitles {0}", surl); + _logger.DebugFormat("Sending subtitles {0}", surl); headers.Add("CaptionInfo.sec", surl); } } @@ -81,7 +83,7 @@ public ItemResponse(string prefix, IRequest request, IMediaResource item, } headers.Add("transferMode.dlna.org", transferMode); - Debug(headers); + _logger.Debug(headers); } public Stream Body diff --git a/server/Responses/Redirect.cs b/server/Responses/Redirect.cs index 1df1e5d4..eda58fd5 100644 --- a/server/Responses/Redirect.cs +++ b/server/Responses/Redirect.cs @@ -1,4 +1,5 @@ -using System; +using NMaier.SimpleDlna.Server.Http; +using System; namespace NMaier.SimpleDlna.Server { diff --git a/server/Responses/ResourceResponse.cs b/server/Responses/ResourceResponse.cs index e2b43f27..c4332cc9 100644 --- a/server/Responses/ResourceResponse.cs +++ b/server/Responses/ResourceResponse.cs @@ -1,12 +1,14 @@ -using NMaier.SimpleDlna.Utilities; +using NMaier.SimpleDlna.Server.Http; +using NMaier.SimpleDlna.Utilities; using System; using System.IO; using System.Resources; namespace NMaier.SimpleDlna.Server -{ - internal sealed class ResourceResponse : Logging, IResponse +{//Logging, + internal sealed class ResourceResponse : IResponse { + private static readonly ILogging _logger = Logging.GetLogger(); private readonly IHeaders headers = new ResponseHeaders(); private readonly byte[] resource; @@ -29,7 +31,7 @@ public ResourceResponse(HttpCode aStatus, string type, headers["Content-Length"] = resource.Length.ToString(); } catch (Exception ex) { - Error("Failed to prepare resource " + aResource, ex); + _logger.Error("Failed to prepare resource " + aResource, ex); throw; } } diff --git a/server/Responses/StringResponse.cs b/server/Responses/StringResponse.cs index 4076d479..22d06c9a 100644 --- a/server/Responses/StringResponse.cs +++ b/server/Responses/StringResponse.cs @@ -1,4 +1,5 @@ -using System.IO; +using NMaier.SimpleDlna.Server.Http; +using System.IO; using System.Text; namespace NMaier.SimpleDlna.Server diff --git a/server/Ssdp/Datagram.cs b/server/Ssdp/Datagram.cs index a9fd1077..fb393b99 100644 --- a/server/Ssdp/Datagram.cs +++ b/server/Ssdp/Datagram.cs @@ -6,8 +6,9 @@ namespace NMaier.SimpleDlna.Server.Ssdp { - internal sealed class Datagram : Logging + internal sealed class Datagram// : Logging { + private static readonly ILogging _logger = Logging.GetLogger(); public readonly IPEndPoint EndPoint; public readonly IPAddress LocalAddress; @@ -46,7 +47,7 @@ public void Send() client.EndSend(result); } catch (Exception ex) { - Debug(ex); + _logger.Debug(ex); } finally { try { @@ -58,7 +59,7 @@ public void Send() }, null); } catch (Exception ex) { - Error(ex); + _logger.Error(ex); } ++SendCount; } diff --git a/server/Ssdp/SsdpHandler.cs b/server/Ssdp/SsdpHandler.cs index 7e86c6ce..5753589c 100644 --- a/server/Ssdp/SsdpHandler.cs +++ b/server/Ssdp/SsdpHandler.cs @@ -1,4 +1,5 @@ -using NMaier.SimpleDlna.Utilities; +using NMaier.SimpleDlna.Server.Http; +using NMaier.SimpleDlna.Utilities; using System; using System.Collections.Concurrent; using System.Collections.Generic; @@ -12,9 +13,12 @@ using Timers = System.Timers; namespace NMaier.SimpleDlna.Server.Ssdp -{ - internal sealed class SsdpHandler : Logging, IDisposable +{//Logging, + internal sealed class SsdpHandler : IDisposable { + + private static readonly ILogging _logger = Logging.GetLogger(); + private const int DATAGRAMS_PER_MESSAGE = 3; private const string SSDP_ADDR = "239.255.255.250"; @@ -67,7 +71,7 @@ public SsdpHandler() client.ExclusiveAddressUse = false; client.Client.Bind(new IPEndPoint(IPAddress.Any, SSDP_PORT)); client.JoinMulticastGroup(SSDP_IP, 10); - Notice("SSDP service started"); + _logger.Notice("SSDP service started"); Receive(); } @@ -163,10 +167,10 @@ private void ReceiveCallback(IAsyncResult result) } } catch (IOException ex) { - Debug("Failed to read SSDP message", ex); + _logger.Debug("Failed to read SSDP message", ex); } catch (Exception ex) { - Warn("Failed to read SSDP message", ex); + _logger.Warn("Failed to read SSDP message", ex); } Receive(); } @@ -202,21 +206,21 @@ private void SendSearchResponse(IPEndPoint endpoint, UpnpDevice dev) String.Format("HTTP/1.1 200 OK\r\n{0}\r\n", headers.HeaderBlock), false ); - InfoFormat( + _logger.InfoFormat( "{2}, {1} - Responded to a {0} request", dev.Type, endpoint, dev.Address); } private void Tick(object sender, Timers.ElapsedEventArgs e) { - Debug("Sending SSDP notifications!"); + _logger.Debug("Sending SSDP notifications!"); notificationTimer.Interval = random.Next(60000, 120000); NotifyAll(); } internal void NotifyAll() { - Debug("NotifyAll"); + _logger.Debug("NotifyAll"); foreach (var d in Devices) { NotifyDevice(d, "alive", false); } @@ -224,7 +228,7 @@ internal void NotifyAll() internal void NotifyDevice(UpnpDevice dev, string type, bool sticky) { - Debug("NotifyDevice"); + _logger.Debug("NotifyDevice"); var headers = new RawHeaders(); headers.Add("HOST", "239.255.255.250:1900"); headers.Add("CACHE-CONTROL", "max-age = 600"); @@ -248,7 +252,7 @@ internal void NotifyDevice(UpnpDevice dev, string type, bool sticky) String.Format("NOTIFY * HTTP/1.1\r\n{0}\r\n", headers.HeaderBlock), sticky ); - DebugFormat("{0} said {1}", dev.USN, type); + _logger.DebugFormat("{0} said {1}", dev.USN, type); } internal void RegisterNotification(Guid UUID, Uri Descriptor, @@ -272,7 +276,7 @@ internal void RegisterNotification(Guid UUID, Uri Descriptor, } NotifyAll(); - DebugFormat("Registered mount {0}, {1}", UUID, address); + _logger.DebugFormat("Registered mount {0}, {1}", UUID, address); } internal void RespondToSearch(IPEndPoint endpoint, string req) @@ -281,7 +285,7 @@ internal void RespondToSearch(IPEndPoint endpoint, string req) req = null; } - DebugFormat("RespondToSearch {0} {1}", endpoint, req); + _logger.DebugFormat("RespondToSearch {0} {1}", endpoint, req); foreach (var d in Devices) { if (!string.IsNullOrEmpty(req) && req != d.Type) { continue; @@ -302,12 +306,12 @@ internal void UnregisterNotification(Guid UUID) foreach (var d in dl) { NotifyDevice(d, "byebye", true); } - DebugFormat("Unregistered mount {0}", UUID); + _logger.DebugFormat("Unregistered mount {0}", UUID); } public void Dispose() { - Debug("Disposing SSDP"); + _logger.Debug("Disposing SSDP"); running = false; while (messageQueue.Count != 0) { datagramPosted.WaitOne(); diff --git a/server/Types/HttpStatusException.cs b/server/Types/HttpStatusException.cs index 545708bf..fbf33a8d 100644 --- a/server/Types/HttpStatusException.cs +++ b/server/Types/HttpStatusException.cs @@ -1,4 +1,5 @@ -using System; +using NMaier.SimpleDlna.Server.Http; +using System; using System.Runtime.Serialization; namespace NMaier.SimpleDlna.Server diff --git a/server/Types/Identifiers.cs b/server/Types/Identifiers.cs index 8368aa39..6b3ef829 100644 --- a/server/Types/Identifiers.cs +++ b/server/Types/Identifiers.cs @@ -7,8 +7,9 @@ namespace NMaier.SimpleDlna.Server { - public sealed class Identifiers : Logging + public sealed class Identifiers// : Logging { + private static readonly ILogging _logger = Logging.GetLogger(); public const string GeneralRoot = "0"; public const string SamsungAudio = "A"; @@ -92,7 +93,7 @@ public void AddView(string name) views.Add(ViewRepository.Lookup(name)); } catch (Exception ex) { - Error("Failed to add view", ex); + _logger.Error("Failed to add view", ex); throw; } } @@ -112,7 +113,7 @@ public void Cleanup() } } paths = npaths; - DebugFormat("Cleanup complete: ids (evicted) {0} ({1}), paths {2} ({3})", ids.Count, ic - ids.Count, paths.Count, pc - paths.Count); + _logger.DebugFormat("Cleanup complete: ids (evicted) {0} ({1}), paths {2} ({3})", ids.Count, ic - ids.Count, paths.Count, pc - paths.Count); } public IMediaItem GetItemById(string id) diff --git a/server/Types/SubTitle.cs b/server/Types/SubTitle.cs index 89587ff9..cf56d93d 100644 --- a/server/Types/SubTitle.cs +++ b/server/Types/SubTitle.cs @@ -1,5 +1,4 @@ -using log4net; -using NMaier.SimpleDlna.Utilities; +using NMaier.SimpleDlna.Utilities; using System; using System.IO; using System.Text; @@ -12,12 +11,9 @@ public sealed class Subtitle : IMediaResource [NonSerialized] private byte[] encodedText = null; - [NonSerialized] - private static readonly ILog logger = - LogManager.GetLogger(typeof(Subtitle)); + private static readonly ILogging _logger = Logging.GetLogger(); - [NonSerialized] - private static readonly string[] exts = new string[] { + private static readonly string[] exts = new string[] { ".srt", ".SRT", ".ass", ".ASS", ".ssa", ".SSA", @@ -167,7 +163,7 @@ private void Load(FileInfo file) catch (NotSupportedException) { } catch (Exception ex) { - logger.Debug(string.Format( + _logger.Debug(string.Format( "Failed to get subtitle from {0}", sti.FullName), ex); } } @@ -177,12 +173,12 @@ private void Load(FileInfo file) catch (NotSupportedException) { } catch (Exception ex) { - logger.Debug(string.Format( + _logger.Debug(string.Format( "Failed to get subtitle from {0}", file.FullName), ex); } } catch (Exception ex) { - logger.Error(string.Format( + _logger.Error(string.Format( "Failed to load subtitle for {0}", file.FullName), ex); } } diff --git a/server/Views/BaseView.cs b/server/Views/BaseView.cs index 25f20120..588015b0 100644 --- a/server/Views/BaseView.cs +++ b/server/Views/BaseView.cs @@ -1,8 +1,8 @@ using NMaier.SimpleDlna.Utilities; namespace NMaier.SimpleDlna.Server.Views -{ - internal abstract class BaseView : Logging, IView +{//Logging, + internal abstract class BaseView : IView { public abstract string Description { get; } diff --git a/server/Views/ByDateView.cs b/server/Views/ByDateView.cs new file mode 100644 index 00000000..b43a1804 --- /dev/null +++ b/server/Views/ByDateView.cs @@ -0,0 +1,63 @@ +using NMaier.SimpleDlna.Server.Metadata; +using System.Linq; + +namespace NMaier.SimpleDlna.Server.Views +{ + internal sealed class ByDateView : BaseView + { + public override string Description + { + get + { + return "Reorganizes files into folders by date"; + } + } + + public override string Name + { + get + { + return "bydate"; + } + } + + private static void SortFolder(VirtualFolder folder, TitlesFolder titles) + { + folder.AllItems.GroupBy( + r => (r is IMetaInfo) ? ((r as IMetaInfo).InfoDate.ToString("yyyy-MMM")) : "Unknown", + r => r, + (k, g) => new { Key = k, Lst = g.ToList() } + ) + .ToList() + .ForEach(i => { + var tf = titles.GetFolder(i.Key); + i.Lst.ForEach(r => { + tf.AddResource(r); + folder.RemoveResource(r); + }); + }); + } + + public override IMediaFolder Transform(IMediaFolder Root) + { + var root = new VirtualClonedFolder(Root); + var titles = new TitlesFolder(root); + SortFolder(root, titles); + foreach (var i in root.ChildFolders.ToList()) { + root.ReleaseFolder(i); + } + foreach (var i in titles.ChildFolders.ToList()) { + root.AdoptFolder(i); + } + return root; + } + + private class TitlesFolder : KeyedVirtualFolder + { + public TitlesFolder(IMediaFolder aParent) + : base(aParent, "titles") + { + } + } + } +} diff --git a/server/Views/ByTitleView.cs b/server/Views/ByTitleView.cs index f5ddc1f0..56a9520f 100644 --- a/server/Views/ByTitleView.cs +++ b/server/Views/ByTitleView.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using NMaier.SimpleDlna.Utilities; +using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; @@ -6,6 +7,7 @@ namespace NMaier.SimpleDlna.Server.Views { internal sealed class ByTitleView : BaseView { + private static readonly ILogging _logger = Logging.GetLogger(); public override string Description { get @@ -93,7 +95,7 @@ public override IMediaFolder Transform(IMediaFolder Root) } foreach (var i in titles.ChildFolders.ToList()) { if (i.ChildCount > 100) { - ErrorFormat("Partioning folder {0}", i.Title); + _logger.ErrorFormat("Partioning folder {0}", i.Title); PartitionChildren(i as VirtualFolder, new Prefixer()); } root.AdoptFolder(i); diff --git a/server/Views/FilterView.cs b/server/Views/FilterView.cs index 729b67da..19dad468 100644 --- a/server/Views/FilterView.cs +++ b/server/Views/FilterView.cs @@ -7,6 +7,7 @@ namespace NMaier.SimpleDlna.Server.Views { internal class FilterView : FilteringView { + private static readonly ILogging _logger = Logging.GetLogger(); private Regex filter = null; public override string Description @@ -61,7 +62,7 @@ public override void SetParameters(AttributeCollection parameters) String.Join("|", filters), RegexOptions.Compiled | RegexOptions.IgnoreCase ); - NoticeFormat("Using filter {0}", filter.ToString()); + _logger.NoticeFormat("Using filter {0}", filter.ToString()); } public override IMediaFolder Transform(IMediaFolder root) diff --git a/server/Views/LargeView.cs b/server/Views/LargeView.cs index 5861944d..416c3bf9 100644 --- a/server/Views/LargeView.cs +++ b/server/Views/LargeView.cs @@ -1,7 +1,6 @@ using NMaier.SimpleDlna.Server.Metadata; using NMaier.SimpleDlna.Utilities; using System; -using System.Linq; namespace NMaier.SimpleDlna.Server.Views { diff --git a/server/packages.config b/server/packages.config deleted file mode 100644 index 7e8e029a..00000000 --- a/server/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/server/server.csproj b/server/server.csproj index cba3a122..4625ecf7 100644 --- a/server/server.csproj +++ b/server/server.csproj @@ -26,7 +26,7 @@ 4 - pdbonly + none true bin\Release\ TRACE @@ -44,10 +44,6 @@ - - False - ..\packages\log4net.2.0.3\lib\net40-client\log4net.dll - @@ -71,6 +67,7 @@ + @@ -141,6 +138,7 @@ + @@ -165,7 +163,6 @@ - diff --git a/tests/App.config b/tests/App.config new file mode 100644 index 00000000..764bdd32 --- /dev/null +++ b/tests/App.config @@ -0,0 +1,24 @@ + + + + +
+ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/ByDateViewTest.cs b/tests/ByDateViewTest.cs new file mode 100644 index 00000000..eaf04d4e --- /dev/null +++ b/tests/ByDateViewTest.cs @@ -0,0 +1,50 @@ +using NUnit.Framework; +using NMaier.SimpleDlna.Server; +using NMaier.SimpleDlna.Server.Comparers; +using System.Linq; +using tests.Mocks; +using NMaier.SimpleDlna.Server.Metadata; +using System; + +namespace SimpleDlna.Tests +{ + /// + /// ByDateViewTest transformation tests + /// + [TestFixture] + public class ByDateViewTest + { + + public class MediaResourceMockWithInfo : MediaResource, IMetaInfo + { + public DateTime InfoDate { get; set; } + + public long? InfoSize { get; set; } + } + + [Test] + public void ByDateView_RegisterFolder_Test() + { + var ids = new Identifiers(ComparerRepository.Lookup("title"), false); + ids.AddView("bydate"); + var f = new MediaFolder(); + var addRes = new[] { + new MediaResource() { Path = @"C:\somepath\resrouceZ.mkv", Title = "Z" } + ,new MediaResource() { Path = @"C:\somepath\resrouceY.mkv", Title = "Y" } + ,new MediaResource() { Path = @"C:\somepath\resrouceV.mkv", Title = "V" } + ,new MediaResource() { Path = @"C:\somepath\resrouceO.mkv", Title = "O" } + ,new MediaResource() { Path = @"C:\somepath\resrouceP.mkv", Title = "P" } + ,new MediaResource() { Path = @"C:\somepath\resrouceQ.mkv", Title = "Q" } + ,new MediaResourceMockWithInfo() { Path = @"C:\somepath\resrouceM.mkv", Title = "M", InfoDate = new DateTime(2015,1,1) } + ,new MediaResource() { Path = @"C:\somepath\resrouceE.mkv", Title = "E" } + }; + f.AccessorChildItems.AddRange(addRes); + f.AccessorChildFolders.Add(new MediaFolder() { Path = @"C:\somepath" }); + ids.RegisterFolder("tempid", f); + var res = ids.Resources; + Assert.IsTrue(res.Select(r => r.Target).ToList().Contains(addRes[2]), "Not contains added resource"); + Assert.IsNotNull(ids.GetItemByPath("/:/:2015-Jan"), @"GetItemByPath(""/:/:2015-Jan"") failed"); + Assert.AreEqual(ids.GetItemById(addRes[2].Id), addRes[2], "GetItemById(addRes[2].Id) failed"); + } + } +} diff --git a/tests/ByTitleViewTest.cs b/tests/ByTitleViewTest.cs new file mode 100644 index 00000000..f8a2ff7b --- /dev/null +++ b/tests/ByTitleViewTest.cs @@ -0,0 +1,42 @@ +using NUnit.Framework; +using NMaier.SimpleDlna.Server; +using NMaier.SimpleDlna.Server.Comparers; +using System.Linq; +using tests.Mocks; + +namespace SimpleDlna.Tests +{ + /// + /// ByTitleView transformation tests + /// + [TestFixture] + public class ByTitleViewTest + { + + [Test] + public void ByTitleView_RegisterFolder_Test() + { + var ids = new Identifiers(ComparerRepository.Lookup("title"), false); + ids.AddView("bytitle"); + var f = new MediaFolder(); + var addRes = new[] { + new MediaResource() { Path = @"C:\somepath\resrouceZ.mkv", Title = "Z" } + ,new MediaResource() { Path = @"C:\somepath\resrouceY.mkv", Title = "Y" } + ,new MediaResource() { Path = @"C:\somepath\resrouceV.mkv", Title = "V" } + ,new MediaResource() { Path = @"C:\somepath\resrouceO.mkv", Title = "O" } + ,new MediaResource() { Path = @"C:\somepath\resrouceP.mkv", Title = "P" } + ,new MediaResource() { Path = @"C:\somepath\resrouceQ.mkv", Title = "Q" } + ,new MediaResource() { Path = @"C:\somepath\resrouceM.mkv", Title = "M" } + ,new MediaResource() { Path = @"C:\somepath\resrouceE.mkv", Title = "E" } + }; + f.AccessorChildItems.AddRange(addRes); + f.AccessorChildFolders.Add(new MediaFolder() { Path = @"C:\somepath" }); + ids.RegisterFolder("tempid", f); + var res = ids.Resources; + Assert.IsTrue(res.Select(r => r.Target).ToList().Contains(addRes[2]), "Not contains added resource"); + Assert.IsNotNull(ids.GetItemByPath("/:/:Q"), "GetItemByPath(\"/:/:Q\") failed"); + Assert.AreEqual(ids.GetItemById(addRes[2].Id), addRes[2]); + //target.Load(); + } + } +} diff --git a/tests/FileStoreReaderWriterTest.cs b/tests/FileStoreReaderWriterTest.cs new file mode 100644 index 00000000..2955d2e2 --- /dev/null +++ b/tests/FileStoreReaderWriterTest.cs @@ -0,0 +1,104 @@ +using NUnit.Framework; +using NMaier.SimpleDlna.FileMediaServer; +using System.IO; +using System; +using NMaier.SimpleDlna.Utilities; +using NMaier.SimpleDlna.Server; + +namespace SimpleDlna.Tests +{ + /// + /// ByTitleView transformation tests + /// + [TestFixture] + public class FileStoreReaderTest + { + [Serializable] + public class FileStoreMock : IFileStore + { + public string StoreFile + { + get + { + throw new NotImplementedException(); + } + } + + public string Description + { + get + { + throw new NotImplementedException(); + } + } + + public string Name + { + get + { + throw new NotImplementedException(); + } + } + + public void Dispose() + { + } + + public bool HasCover(IStoreItem file) + { + return _coverData != null; + } + + public byte[] MaybeGetCover(IStoreItem file) + { + return _coverData; + } + + byte[] _fileData = null; + byte[] _coverData = null; + + public byte[] MaybeGetFile(FileInfo info) + { + return _fileData; + } + + public void MaybeStoreFile(IStoreItem file, byte[] data, byte[] coverData) + { + _fileData = data; + _coverData = coverData; + } + + public void SetParameters(AttributeCollection parameters) + { + throw new NotImplementedException(); + } + + public void Init() + { + throw new NotImplementedException(); + } + } + + [Serializable] + public class BaseFileMock : BaseFile { + public BaseFileMock(FileServer server, FileInfo file, DlnaMime type, + DlnaMediaTypes mediaType) : base(server,file,type,mediaType) { + } + } + + [Test] + public void FileStoreReaderWriter_File_Roundtrip_Test() + { + var store = new FileStoreMock(); + var fi = new FileInfo(@"img\Patern_test.jpg"); + var reader = new FileStoreReader(store); + var writer = new FileStoreWriter(store); + var server = new FileServer(DlnaMediaTypes.All, null, new DirectoryInfo[] { new DirectoryInfo(".") }); + var item = new BaseFileMock(server,fi,DlnaMime.AudioAAC,DlnaMediaTypes.Image); + writer.StoreFile(item); + var result = reader.GetFile(fi, null, NMaier.SimpleDlna.Server.DlnaMime.ImageJPEG); + Assert.IsNotNull(result); + Assert.AreEqual(item.Path, result.Path); + } + } +} diff --git a/tests/FileStoreTest.cs b/tests/FileStoreTest.cs new file mode 100644 index 00000000..c754c71e --- /dev/null +++ b/tests/FileStoreTest.cs @@ -0,0 +1,66 @@ +using NUnit.Framework; +using NMaier.SimpleDlna.FileMediaServer; +using System.IO; +using SimpleDlna.Tests.Mocks; + +namespace SimpleDlna.Tests +{ + /// + /// ByTitleView transformation tests + /// + [TestFixture] + public class FileStoreTest + { + [Test] + public void FileStore_SQLite_File_Roundtrip_Test() + { + //var filename = "test.cache"; + IFileStore target = null; + try { + var fi = new FileInfo(@"img\Patern_test.jpg"); + target = new NMaier.SimpleDlna.FileStore.SQLite.FileStore(); + target.Init(); + var f1 = new StoreItemMock(fi); + var data = File.ReadAllBytes(fi.FullName); + var data2 = File.ReadAllBytes(fi.FullName); + target.MaybeStoreFile(f1, data, data2); + //var f1Cover = target.MaybeGetCover(f1); + var f2 = target.MaybeGetFile(fi); + Assert.IsNotNull(f2); + } + finally { + if (target != null) { + target.Dispose(); + if (File.Exists(target.StoreFile)) File.Delete(target.StoreFile); + } + } + } + + [Test] + public void FileStore_RaptorDB_File_Roundtrip_Test() + { + //var filename = "test.cache"; + IFileStore target = null; + try { + var fi = new FileInfo(@"img\Patern_test.jpg"); + target = new NMaier.SimpleDlna.FileStore.RaptorDB.FileStore(); + target.Init(); + var f1 = new StoreItemMock(fi); + var data = File.ReadAllBytes(fi.FullName); + var data2 = File.ReadAllBytes(fi.FullName); + target.MaybeStoreFile(f1, data, data2); + //var f1Cover = target.MaybeGetCover(f1); + var f2 = target.MaybeGetFile(fi); + Assert.IsNotNull(f2); + } + finally { + if (target != null) { + var filename = target.StoreFile; + target.Dispose(); + if ((filename != null) && File.Exists(filename)) File.Delete(filename); + } + } + } + + } +} diff --git a/tests/Mocks/MediaFolder.cs b/tests/Mocks/MediaFolder.cs new file mode 100644 index 00000000..ee20cb84 --- /dev/null +++ b/tests/Mocks/MediaFolder.cs @@ -0,0 +1,88 @@ +using NMaier.SimpleDlna.Server; +using System; +using System.Collections.Generic; + +namespace tests.Mocks +{ + public class MediaFolder : IMediaFolder + { + public int ChildCount + { + get + { + throw new NotImplementedException(); + } + } + + public List AccessorChildFolders = new List(); + + public IEnumerable ChildFolders + { + get + { + return AccessorChildFolders; + } + } + + public List AccessorChildItems = new List(); + + public IEnumerable ChildItems + { + get + { + return AccessorChildItems; + } + } + + public string Id { get; set; } + + public IMediaFolder Parent { get; set; } + + public string Path { get; set; } + + public IHeaders Properties { get; set; } + + public string Title { get; set; } + + public int FullChildCount + { + get + { + throw new NotImplementedException(); + } + } + + public void AddResource(IMediaResource res) + { + throw new NotImplementedException(); + } + + public void Cleanup() + { + } + + public int CompareTo(IMediaItem other) + { + throw new NotImplementedException(); + } + + public bool Equals(IMediaItem other) + { + throw new NotImplementedException(); + } + + public void RemoveResource(IMediaResource res) + { + throw new NotImplementedException(); + } + + public void Sort(IComparer comparer, bool descending) + { + } + + public string ToComparableTitle() + { + throw new NotImplementedException(); + } + } +} diff --git a/tests/Mocks/MediaResource.cs b/tests/Mocks/MediaResource.cs new file mode 100644 index 00000000..d37727f7 --- /dev/null +++ b/tests/Mocks/MediaResource.cs @@ -0,0 +1,45 @@ +using NMaier.SimpleDlna.Server; +using System; +using System.IO; + +namespace tests.Mocks +{ + public class MediaResource : IMediaResource + { + public IMediaCoverResource Cover { get; set; } + + public string Id { get; set; } + + public DlnaMediaTypes MediaType { get; set; } + + public string Path { get; set; } + + public string PN { get; set; } + + public IHeaders Properties { get; set; } + + public string Title { get; set; } + + public DlnaMime Type { get; set; } + + public int CompareTo(IMediaItem other) + { + throw new NotImplementedException(); + } + + public Stream CreateContentStream() + { + throw new NotImplementedException(); + } + + public bool Equals(IMediaItem other) + { + throw new NotImplementedException(); + } + + public string ToComparableTitle() + { + return this.Title; + } + } +} diff --git a/tests/Mocks/StoreItem.cs b/tests/Mocks/StoreItem.cs new file mode 100644 index 00000000..b70eb504 --- /dev/null +++ b/tests/Mocks/StoreItem.cs @@ -0,0 +1,19 @@ +using NMaier.SimpleDlna.FileMediaServer; +using System; +using System.IO; + +namespace SimpleDlna.Tests.Mocks +{ + [Serializable] + public class StoreItemMock : IStoreItem + { + public StoreItemMock(FileInfo item) { + Item = item; + } + + public FileInfo Item { get; set; } + + public Cover MaybeGetCover() { return null; } + } + +} diff --git a/tests/Mocks/View.cs b/tests/Mocks/View.cs new file mode 100644 index 00000000..1ad4692f --- /dev/null +++ b/tests/Mocks/View.cs @@ -0,0 +1,36 @@ +using NMaier.SimpleDlna.Server; +using NMaier.SimpleDlna.Server.Views; +using NMaier.SimpleDlna.Utilities; +using System; + +namespace tests.Mocks +{ + public class View : IView + { + public string Description + { + get + { + return string.Format("[{0}] - Description", this.GetType().Name); + } + } + + public string Name + { + get + { + return this.GetType().Name; + } + } + + public void SetParameters(AttributeCollection parameters) + { + throw new NotImplementedException(); + } + + public IMediaFolder Transform(IMediaFolder root) + { + return root; + } + } +} diff --git a/tests/Properties/AssemblyInfo.cs b/tests/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..ce9534b8 --- /dev/null +++ b/tests/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +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("tests")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("tests")] +[assembly: AssemblyCopyright("Copyright © 2015")] +[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("ed38a2a8-c0e5-4881-8f8e-591b34fd2c06")] + +// 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.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/tests/ServerDescriptionTest.cs b/tests/ServerDescriptionTest.cs new file mode 100644 index 00000000..2a8d8b2b --- /dev/null +++ b/tests/ServerDescriptionTest.cs @@ -0,0 +1,55 @@ +using NUnit.Framework; +using NMaier.SimpleDlna.Server; +using NMaier.SimpleDlna.GUI; +using NMaier.SimpleDlna.Utilities; +using System.IO; + +namespace SimpleDlna.Tests +{ + /// + /// ByTitleView transformation tests + /// + [TestFixture] + public class ServerDescriptionTest + { + + [Test] + public void ServerDescription_AdoptInfo_Test() + { + var data = new ServerDescription { + Directories = new [] { "dir1", "dir2" }, + Name = "data", + Order = "Order", + FileStore = "FileStore", + OrderDescending = false, + Types = DlnaMediaTypes.All, + Views = new [] { "Views1", "Views2" }, + Macs = new [] { "Mac1", "Mac2" }, + Ips = new [] { "IP1", "IP2" }, + UserAgents = new [] { "UserAgent1", "UserAgent2" } + }; + var data2 = new ServerDescription(); + data2.AdoptInfo(data); + Assert.AreEqual(data.Directories, data2.Directories); + Assert.AreEqual(data.Name, data2.Name); + Assert.AreEqual(data.Order, data2.Order); + Assert.AreEqual(data.FileStore, data2.FileStore); + Assert.AreEqual(data.OrderDescending, data2.OrderDescending); + Assert.AreEqual(data.Types, data2.Types); + Assert.AreEqual(data.Views, data2.Views); + Assert.AreEqual(data.Macs, data2.Macs); + Assert.AreEqual(data.Ips, data2.Ips); + Assert.AreEqual(data.UserAgents, data2.UserAgents); + var filenames = new[] { "ServerDescription.tmp1", "ServerDescription.tmp2" }; + try { + XmlHelper.ToFile(data, filenames[0]); + XmlHelper.ToFile(data2, filenames[1]); + Assert.AreEqual(File.ReadAllText(filenames[0]), File.ReadAllText(filenames[1])); + } + finally { + if (File.Exists(filenames[0])) File.Delete(filenames[0]); + if (File.Exists(filenames[1])) File.Delete(filenames[1]); + } + } + } +} diff --git a/tests/Utilities/ReflectionHelperTest.cs b/tests/Utilities/ReflectionHelperTest.cs new file mode 100644 index 00000000..90a7814f --- /dev/null +++ b/tests/Utilities/ReflectionHelperTest.cs @@ -0,0 +1,31 @@ +using NUnit.Framework; +using NMaier.SimpleDlna.Utilities; +using NMaier.SimpleDlna.FileStore.SQLite; + +namespace SimpleDlna.Tests.Utilities +{ + /// + /// ByTitleView transformation tests + /// + [TestFixture] + public class ReflectionHelperTest + { + [Test] + public void ReflectionHelper_Create_Test() + { + Assert.IsNotNull(ReflectionHelper.Create("assembly=SimpleDlna.FileStore.SQLite;type=NMaier.SimpleDlna.FileStore.SQLite.FileStore;")); + } + + [Test] + public void ReflectionHelper_StringToDictionary_Test() + { + var d = ReflectionHelper.StringToDictionary(string.Format("assembly={0};type={1};", typeof(FileStore).AssemblyQualifiedName, typeof(FileStore).FullName)); + Assert.IsTrue(d.ContainsKey("assembly")); + Assert.IsTrue(d.ContainsValue(typeof(FileStore).AssemblyQualifiedName)); + Assert.IsTrue(d.ContainsKey("type")); + Assert.IsTrue(d.ContainsValue(typeof(FileStore).FullName)); + Assert.AreEqual(typeof(FileStore).FullName, d["type"]); + Assert.AreEqual(typeof(FileStore).AssemblyQualifiedName, d["assembly"]); + } + } +} diff --git a/tests/Utilities/RepositoryBaseTest.cs b/tests/Utilities/RepositoryBaseTest.cs new file mode 100644 index 00000000..bf2ad1f6 --- /dev/null +++ b/tests/Utilities/RepositoryBaseTest.cs @@ -0,0 +1,19 @@ +using NUnit.Framework; +using NMaier.SimpleDlna.Utilities; + +namespace SimpleDlna.Tests.Utilities +{ + /// + /// ByTitleView transformation tests + /// + [TestFixture] + public class RepositoryBaseTest + { + [Test] + public void RepositoryBase_GetDomainAssemblies_Test() + { + var a = RepositoryBase.GetDomainAssemblies(); + Assert.IsTrue(a.Length > 0); + } + } +} diff --git a/tests/Utilities/RepositoryTest.cs b/tests/Utilities/RepositoryTest.cs new file mode 100644 index 00000000..28134dba --- /dev/null +++ b/tests/Utilities/RepositoryTest.cs @@ -0,0 +1,67 @@ +using System; +using NUnit.Framework; +using NMaier.SimpleDlna.Server.Views; +using NMaier.SimpleDlna.Utilities; +using System.Linq; +using tests.Mocks; +using NMaier.SimpleDlna.FileMediaServer; +using NMaier.SimpleDlna.FileStore.SQLite; + +namespace SimpleDlna.Tests.Utilities +{ + /// + /// Summary description for FileServerTest + /// + [TestFixture] + public class RepositoryTest + { + + public sealed class ViewRepositoryMock : Repository + { + } + + [Test] + public void Repository_GetAllTypes_Test() + { + var itype = typeof(IView); + var types = AppDomain.CurrentDomain.GetAssemblies() + .SelectMany(a => a.GetTypes()) + .Where(t => itype.IsAssignableFrom(t) && t.IsClass && !t.IsAbstract) + .ToList(); + Assert.IsTrue(types.Contains(typeof(View))); + } + + [Test] + public void Repository_ViewRepository_Lookup_Test() + { + var target = ViewRepositoryMock.Lookup(typeof(View).Name); + Assert.IsNotNull(target); + } + + [Test] + public void Repository_ViewRepository_ListItems_Test() + { + var target = ViewRepositoryMock.ListItems(); + Assert.IsTrue(target.Count > 0); + } + + [Test] + public void Repository_FileStoreRepository_Lookup_Test() + { + var target = FileStoreRepository.Lookup((new NMaier.SimpleDlna.FileStore.SQLite.FileStore()).Name); + Assert.IsNotNull(target); + } + + [Test] + public void Repository_FileStoreRepository_ListItems_Test() + { + var target = FileStoreRepository.ListItems(); + Assert.IsTrue(target.Count > 0); + var keys = target.Keys.ToArray(); + var specificObject = new FileStore(); + Assert.IsTrue(keys.Contains(specificObject.Name)); + } + + + } +} diff --git a/tests/img/Patern_test.jpg b/tests/img/Patern_test.jpg new file mode 100644 index 00000000..716ddd68 Binary files /dev/null and b/tests/img/Patern_test.jpg differ diff --git a/tests/packages.config b/tests/packages.config new file mode 100644 index 00000000..fb463a0b --- /dev/null +++ b/tests/packages.config @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/tests/sdlna.key.snk b/tests/sdlna.key.snk new file mode 100644 index 00000000..7e30ff02 Binary files /dev/null and b/tests/sdlna.key.snk differ diff --git a/tests/tests.csproj b/tests/tests.csproj new file mode 100644 index 00000000..5534ba6f --- /dev/null +++ b/tests/tests.csproj @@ -0,0 +1,173 @@ + + + + Debug + AnyCPU + {ED38A2A8-C0E5-4881-8F8E-591B34FD2C06} + Library + Properties + SimpleDlna.Tests + SimpleDLNA.Tests + v4.0 + 512 + {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 10.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages + False + UnitTest + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + false + + + sdlna.key.snk + + + + ..\packages\EntityFramework.6.0.0\lib\net40\EntityFramework.dll + True + + + ..\packages\EntityFramework.6.0.0\lib\net40\EntityFramework.SqlServer.dll + True + + + ..\packages\log4net.2.0.3\lib\net40-full\log4net.dll + True + + + ..\packages\NUnit.2.6.4\lib\nunit.framework.dll + True + + + + + 3.5 + + + ..\packages\System.Data.SQLite.Core.1.0.98.1\lib\net40\System.Data.SQLite.dll + True + + + ..\packages\System.Data.SQLite.EF6.1.0.98.1\lib\net40\System.Data.SQLite.EF6.dll + True + + + ..\packages\System.Data.SQLite.Linq.1.0.98.1\lib\net40\System.Data.SQLite.Linq.dll + True + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {6961f1c2-41e9-4e7f-8e88-7d4a259b3df8} + FileStoreRaptorDB + + + {25741114-7f31-421e-8d2b-357a3155cee2} + FileStoreSQLite + + + {50e06b21-e11a-42f0-81e2-0911e771e861} + fsserver + + + {232a96f6-a2bf-44c8-b623-6e411f6296f2} + server + + + {9baefb29-c818-446b-9bb5-014e6a0cbb49} + SimpleDLNA + + + {a8960a7a-887c-40d7-9632-002e94bfc830} + util + + + + + Always + + + + + + + False + + + False + + + False + + + False + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + \ No newline at end of file diff --git a/thumbs/ThumbnailMaker.cs b/thumbs/ThumbnailMaker.cs index a73ca093..ca34b8bb 100644 --- a/thumbs/ThumbnailMaker.cs +++ b/thumbs/ThumbnailMaker.cs @@ -1,5 +1,4 @@ -using log4net; -using NMaier.SimpleDlna.Server; +using NMaier.SimpleDlna.Server; using NMaier.SimpleDlna.Utilities; using System; using System.Collections.Generic; @@ -91,6 +90,8 @@ private byte[] GetThumbnailInternal(string key, object item, throw new ArgumentException("Not a supported resource"); } + private readonly static ILogging _logger = Logging.GetLogger(); + internal static Image ResizeImage(Image image, int width, int height, ThumbnailMakerBorder border) { @@ -114,7 +115,7 @@ internal static Image ResizeImage(Image image, int width, int height, result.SetResolution(image.HorizontalResolution, image.VerticalResolution); } catch (Exception ex) { - LogManager.GetLogger(typeof(ThumbnailMaker)).Debug("Failed to set resolution", ex); + _logger.Debug("Failed to set resolution", ex); } using (var graphics = Graphics.FromImage(result)) { if (result.Width > image.Width && result.Height > image.Height) { diff --git a/thumbs/packages.config b/thumbs/packages.config deleted file mode 100644 index 7e8e029a..00000000 --- a/thumbs/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/thumbs/thumbs.csproj b/thumbs/thumbs.csproj index d242fc3c..8fba3576 100644 --- a/thumbs/thumbs.csproj +++ b/thumbs/thumbs.csproj @@ -26,7 +26,7 @@ 4 - pdbonly + none true bin\Release\ TRACE @@ -42,10 +42,6 @@ sdlna.key.snk - - False - ..\packages\log4net.2.0.3\lib\net40-client\log4net.dll - @@ -79,7 +75,6 @@ - diff --git a/util/DataPath.cs b/util/DataPath.cs new file mode 100644 index 00000000..bc34e71b --- /dev/null +++ b/util/DataPath.cs @@ -0,0 +1,49 @@ +using System; +using System.IO; +using System.Linq; + +namespace NMaier.SimpleDlna.Utilities +{ + public class DataPath + { + private static string _workPath = GetSystemWorkPath(); + + public static string Path { + get { return _workPath; } + set { _workPath = value; } + } + + public static string Combine(params string[] paths) { + return System.IO.Path.Combine((new [] { _workPath }).Concat(paths).ToArray()); + } + + private static string GetSystemWorkPath() + { + string rv; + try { + try { + rv = Environment.GetFolderPath( + Environment.SpecialFolder.LocalApplicationData); + if (string.IsNullOrEmpty(rv)) { + throw new IOException("Cannot get LocalAppData"); + } + } + catch (Exception) { + rv = Environment.GetFolderPath( + Environment.SpecialFolder.ApplicationData); + if (string.IsNullOrEmpty(rv)) { + throw new IOException("Cannot get LocalAppData"); + } + } + rv = System.IO.Path.Combine(rv, "SimpleDLNA"); + if (!Directory.Exists(rv)) { + Directory.CreateDirectory(rv); + } + return rv; + } + catch (Exception) { + return System.IO.Path.GetTempPath(); + } + } + } +} diff --git a/util/ILogging.cs b/util/ILogging.cs new file mode 100644 index 00000000..b3e4f956 --- /dev/null +++ b/util/ILogging.cs @@ -0,0 +1,765 @@ +using System; + +namespace NMaier.SimpleDlna.Utilities +{ + public interface ILogging + { + void Notice(object message); + + void Notice(object message, Exception exception); + + void NoticeFormat(string format, params object[] args); + + void NoticeFormat(string format, object arg0); + + void NoticeFormat(string format, object arg0, object arg1); + + void NoticeFormat(IFormatProvider provider, string format, + params object[] args); + + void NoticeFormat(string format, object arg0, object arg1, + object arg2); + + // + // Summary: + // Checks if this logger is enabled for the log4net.Core.Level.Debug level. + // + // Remarks: + // This function is intended to lessen the computational cost of disabled log debug + // statements. + // For some ILog interface log, when you write: + // log.Debug("This is entry number: " + i ); + // You incur the cost constructing the message, string construction and concatenation + // in this case, regardless of whether the message is logged or not. + // If you are worried about speed (who isn't), then you should write: + // if (log.IsDebugEnabled) { log.Debug("This is entry number: " + i ); } + // This way you will not incur the cost of parameter construction if debugging is + // disabled for log. On the other hand, if the log is debug enabled, you will incur + // the cost of evaluating whether the logger is debug enabled twice. Once in log4net.ILog.IsDebugEnabled + // and once in the Debug(object). This is an insignificant overhead since evaluating + // a logger takes about 1% of the time it takes to actually log. This is the preferred + // style of logging. + // Alternatively if your logger is available statically then the is debug enabled + // state can be stored in a static variable like this: + // private static readonly bool isDebugEnabled = log.IsDebugEnabled; + // Then when you come to log you can write: + // if (isDebugEnabled) { log.Debug("This is entry number: " + i ); } + // This way the debug enabled state is only queried once when the class is loaded. + // Using a private static readonly variable is the most efficient because it is + // a run time constant and can be heavily optimized by the JIT compiler. + // Of course if you use a static readonly variable to hold the enabled state of + // the logger then you cannot change the enabled state at runtime to vary the logging + // that is produced. You have to decide if you need absolute speed or runtime flexibility. + bool IsDebugEnabled { get; } + // + // Summary: + // Checks if this logger is enabled for the log4net.Core.Level.Error level. + // + // Remarks: + // For more information see log4net.ILog.IsDebugEnabled. + bool IsErrorEnabled { get; } + // + // Summary: + // Checks if this logger is enabled for the log4net.Core.Level.Fatal level. + // + // Remarks: + // For more information see log4net.ILog.IsDebugEnabled. + bool IsFatalEnabled { get; } + // + // Summary: + // Checks if this logger is enabled for the log4net.Core.Level.Info level. + // + // Remarks: + // For more information see log4net.ILog.IsDebugEnabled. + bool IsInfoEnabled { get; } + // + // Summary: + // Checks if this logger is enabled for the log4net.Core.Level.Warn level. + // + // Remarks: + // For more information see log4net.ILog.IsDebugEnabled. + bool IsWarnEnabled { get; } + + // + // Summary: + // Log a message object with the log4net.Core.Level.Debug level. + // + // Parameters: + // message: + // The message object to log. + // + // Remarks: + // This method first checks if this logger is DEBUG enabled by comparing the level + // of this logger with the log4net.Core.Level.Debug level. If this logger is DEBUG + // enabled, then it converts the message object (passed as parameter) to a string + // by invoking the appropriate log4net.ObjectRenderer.IObjectRenderer. It then proceeds + // to call all the registered appenders in this logger and also higher in the hierarchy + // depending on the value of the additivity flag. + // WARNING Note that passing an System.Exception to this method will print the name + // of the System.Exception but no stack trace. To print a stack trace use the Debug(object,Exception) + // form instead. + void Debug(object message); + // + // Summary: + // Log a message object with the log4net.Core.Level.Debug level including the stack + // trace of the System.Exception passed as a parameter. + // + // Parameters: + // message: + // The message object to log. + // + // exception: + // The exception to log, including its stack trace. + // + // Remarks: + // See the Debug(object) form for more detailed information. + void Debug(object message, Exception exception); + // + // Summary: + // Logs a formatted message string with the log4net.Core.Level.Debug level. + // + // Parameters: + // format: + // A String containing zero or more format items + // + // arg0: + // An Object to format + // + // Remarks: + // The message is formatted using the String.Format method. See String.Format(string, + // object[]) for details of the syntax of the format string and the behavior of + // the formatting. + // This method does not take an System.Exception object to include in the log event. + // To pass an System.Exception use one of the Debug(object,Exception) methods instead. + void DebugFormat(string format, object arg0); + // + // Summary: + // Logs a formatted message string with the log4net.Core.Level.Debug level. + // + // Parameters: + // format: + // A String containing zero or more format items + // + // args: + // An Object array containing zero or more objects to format + // + // Remarks: + // The message is formatted using the String.Format method. See String.Format(string, + // object[]) for details of the syntax of the format string and the behavior of + // the formatting. + // This method does not take an System.Exception object to include in the log event. + // To pass an System.Exception use one of the Debug(object,Exception) methods instead. + void DebugFormat(string format, params object[] args); + // + // Summary: + // Logs a formatted message string with the log4net.Core.Level.Debug level. + // + // Parameters: + // provider: + // An System.IFormatProvider that supplies culture-specific formatting information + // + // format: + // A String containing zero or more format items + // + // args: + // An Object array containing zero or more objects to format + // + // Remarks: + // The message is formatted using the String.Format method. See String.Format(string, + // object[]) for details of the syntax of the format string and the behavior of + // the formatting. + // This method does not take an System.Exception object to include in the log event. + // To pass an System.Exception use one of the Debug(object,Exception) methods instead. + void DebugFormat(IFormatProvider provider, string format, params object[] args); + // + // Summary: + // Logs a formatted message string with the log4net.Core.Level.Debug level. + // + // Parameters: + // format: + // A String containing zero or more format items + // + // arg0: + // An Object to format + // + // arg1: + // An Object to format + // + // Remarks: + // The message is formatted using the String.Format method. See String.Format(string, + // object[]) for details of the syntax of the format string and the behavior of + // the formatting. + // This method does not take an System.Exception object to include in the log event. + // To pass an System.Exception use one of the Debug(object,Exception) methods instead. + void DebugFormat(string format, object arg0, object arg1); + // + // Summary: + // Logs a formatted message string with the log4net.Core.Level.Debug level. + // + // Parameters: + // format: + // A String containing zero or more format items + // + // arg0: + // An Object to format + // + // arg1: + // An Object to format + // + // arg2: + // An Object to format + // + // Remarks: + // The message is formatted using the String.Format method. See String.Format(string, + // object[]) for details of the syntax of the format string and the behavior of + // the formatting. + // This method does not take an System.Exception object to include in the log event. + // To pass an System.Exception use one of the Debug(object,Exception) methods instead. + void DebugFormat(string format, object arg0, object arg1, object arg2); + // + // Summary: + // Logs a message object with the log4net.Core.Level.Error level. + // + // Parameters: + // message: + // The message object to log. + // + // Remarks: + // This method first checks if this logger is ERROR enabled by comparing the level + // of this logger with the log4net.Core.Level.Error level. If this logger is ERROR + // enabled, then it converts the message object (passed as parameter) to a string + // by invoking the appropriate log4net.ObjectRenderer.IObjectRenderer. It then proceeds + // to call all the registered appenders in this logger and also higher in the hierarchy + // depending on the value of the additivity flag. + // WARNING Note that passing an System.Exception to this method will print the name + // of the System.Exception but no stack trace. To print a stack trace use the Error(object,Exception) + // form instead. + void Error(object message); + // + // Summary: + // Log a message object with the log4net.Core.Level.Error level including the stack + // trace of the System.Exception passed as a parameter. + // + // Parameters: + // message: + // The message object to log. + // + // exception: + // The exception to log, including its stack trace. + // + // Remarks: + // See the Error(object) form for more detailed information. + void Error(object message, Exception exception); + // + // Summary: + // Logs a formatted message string with the log4net.Core.Level.Error level. + // + // Parameters: + // format: + // A String containing zero or more format items + // + // arg0: + // An Object to format + // + // Remarks: + // The message is formatted using the String.Format method. See String.Format(string, + // object[]) for details of the syntax of the format string and the behavior of + // the formatting. + // This method does not take an System.Exception object to include in the log event. + // To pass an System.Exception use one of the Error(object,Exception) methods instead. + void ErrorFormat(string format, object arg0); + // + // Summary: + // Logs a formatted message string with the log4net.Core.Level.Error level. + // + // Parameters: + // format: + // A String containing zero or more format items + // + // args: + // An Object array containing zero or more objects to format + // + // Remarks: + // The message is formatted using the String.Format method. See String.Format(string, + // object[]) for details of the syntax of the format string and the behavior of + // the formatting. + // This method does not take an System.Exception object to include in the log event. + // To pass an System.Exception use one of the Error(object) methods instead. + void ErrorFormat(string format, params object[] args); + // + // Summary: + // Logs a formatted message string with the log4net.Core.Level.Error level. + // + // Parameters: + // provider: + // An System.IFormatProvider that supplies culture-specific formatting information + // + // format: + // A String containing zero or more format items + // + // args: + // An Object array containing zero or more objects to format + // + // Remarks: + // The message is formatted using the String.Format method. See String.Format(string, + // object[]) for details of the syntax of the format string and the behavior of + // the formatting. + // This method does not take an System.Exception object to include in the log event. + // To pass an System.Exception use one of the Error(object) methods instead. + void ErrorFormat(IFormatProvider provider, string format, params object[] args); + // + // Summary: + // Logs a formatted message string with the log4net.Core.Level.Error level. + // + // Parameters: + // format: + // A String containing zero or more format items + // + // arg0: + // An Object to format + // + // arg1: + // An Object to format + // + // Remarks: + // The message is formatted using the String.Format method. See String.Format(string, + // object[]) for details of the syntax of the format string and the behavior of + // the formatting. + // This method does not take an System.Exception object to include in the log event. + // To pass an System.Exception use one of the Error(object,Exception) methods instead. + void ErrorFormat(string format, object arg0, object arg1); + // + // Summary: + // Logs a formatted message string with the log4net.Core.Level.Error level. + // + // Parameters: + // format: + // A String containing zero or more format items + // + // arg0: + // An Object to format + // + // arg1: + // An Object to format + // + // arg2: + // An Object to format + // + // Remarks: + // The message is formatted using the String.Format method. See String.Format(string, + // object[]) for details of the syntax of the format string and the behavior of + // the formatting. + // This method does not take an System.Exception object to include in the log event. + // To pass an System.Exception use one of the Error(object,Exception) methods instead. + void ErrorFormat(string format, object arg0, object arg1, object arg2); + // + // Summary: + // Log a message object with the log4net.Core.Level.Fatal level. + // + // Parameters: + // message: + // The message object to log. + // + // Remarks: + // This method first checks if this logger is FATAL enabled by comparing the level + // of this logger with the log4net.Core.Level.Fatal level. If this logger is FATAL + // enabled, then it converts the message object (passed as parameter) to a string + // by invoking the appropriate log4net.ObjectRenderer.IObjectRenderer. It then proceeds + // to call all the registered appenders in this logger and also higher in the hierarchy + // depending on the value of the additivity flag. + // WARNING Note that passing an System.Exception to this method will print the name + // of the System.Exception but no stack trace. To print a stack trace use the Fatal(object,Exception) + // form instead. + void Fatal(object message); + // + // Summary: + // Log a message object with the log4net.Core.Level.Fatal level including the stack + // trace of the System.Exception passed as a parameter. + // + // Parameters: + // message: + // The message object to log. + // + // exception: + // The exception to log, including its stack trace. + // + // Remarks: + // See the Fatal(object) form for more detailed information. + void Fatal(object message, Exception exception); + // + // Summary: + // Logs a formatted message string with the log4net.Core.Level.Fatal level. + // + // Parameters: + // format: + // A String containing zero or more format items + // + // arg0: + // An Object to format + // + // Remarks: + // The message is formatted using the String.Format method. See String.Format(string, + // object[]) for details of the syntax of the format string and the behavior of + // the formatting. + // This method does not take an System.Exception object to include in the log event. + // To pass an System.Exception use one of the Fatal(object,Exception) methods instead. + void FatalFormat(string format, object arg0); + // + // Summary: + // Logs a formatted message string with the log4net.Core.Level.Fatal level. + // + // Parameters: + // format: + // A String containing zero or more format items + // + // args: + // An Object array containing zero or more objects to format + // + // Remarks: + // The message is formatted using the String.Format method. See String.Format(string, + // object[]) for details of the syntax of the format string and the behavior of + // the formatting. + // This method does not take an System.Exception object to include in the log event. + // To pass an System.Exception use one of the Fatal(object) methods instead. + void FatalFormat(string format, params object[] args); + // + // Summary: + // Logs a formatted message string with the log4net.Core.Level.Fatal level. + // + // Parameters: + // provider: + // An System.IFormatProvider that supplies culture-specific formatting information + // + // format: + // A String containing zero or more format items + // + // args: + // An Object array containing zero or more objects to format + // + // Remarks: + // The message is formatted using the String.Format method. See String.Format(string, + // object[]) for details of the syntax of the format string and the behavior of + // the formatting. + // This method does not take an System.Exception object to include in the log event. + // To pass an System.Exception use one of the Fatal(object) methods instead. + void FatalFormat(IFormatProvider provider, string format, params object[] args); + // + // Summary: + // Logs a formatted message string with the log4net.Core.Level.Fatal level. + // + // Parameters: + // format: + // A String containing zero or more format items + // + // arg0: + // An Object to format + // + // arg1: + // An Object to format + // + // Remarks: + // The message is formatted using the String.Format method. See String.Format(string, + // object[]) for details of the syntax of the format string and the behavior of + // the formatting. + // This method does not take an System.Exception object to include in the log event. + // To pass an System.Exception use one of the Fatal(object,Exception) methods instead. + void FatalFormat(string format, object arg0, object arg1); + // + // Summary: + // Logs a formatted message string with the log4net.Core.Level.Fatal level. + // + // Parameters: + // format: + // A String containing zero or more format items + // + // arg0: + // An Object to format + // + // arg1: + // An Object to format + // + // arg2: + // An Object to format + // + // Remarks: + // The message is formatted using the String.Format method. See String.Format(string, + // object[]) for details of the syntax of the format string and the behavior of + // the formatting. + // This method does not take an System.Exception object to include in the log event. + // To pass an System.Exception use one of the Fatal(object,Exception) methods instead. + void FatalFormat(string format, object arg0, object arg1, object arg2); + // + // Summary: + // Logs a message object with the log4net.Core.Level.Info level. + // + // Parameters: + // message: + // The message object to log. + // + // Remarks: + // This method first checks if this logger is INFO enabled by comparing the level + // of this logger with the log4net.Core.Level.Info level. If this logger is INFO + // enabled, then it converts the message object (passed as parameter) to a string + // by invoking the appropriate log4net.ObjectRenderer.IObjectRenderer. It then proceeds + // to call all the registered appenders in this logger and also higher in the hierarchy + // depending on the value of the additivity flag. + // WARNING Note that passing an System.Exception to this method will print the name + // of the System.Exception but no stack trace. To print a stack trace use the Info(object,Exception) + // form instead. + void Info(object message); + // + // Summary: + // Logs a message object with the INFO level including the stack trace of the System.Exception + // passed as a parameter. + // + // Parameters: + // message: + // The message object to log. + // + // exception: + // The exception to log, including its stack trace. + // + // Remarks: + // See the Info(object) form for more detailed information. + void Info(object message, Exception exception); + // + // Summary: + // Logs a formatted message string with the log4net.Core.Level.Info level. + // + // Parameters: + // format: + // A String containing zero or more format items + // + // arg0: + // An Object to format + // + // Remarks: + // The message is formatted using the String.Format method. See String.Format(string, + // object[]) for details of the syntax of the format string and the behavior of + // the formatting. + // This method does not take an System.Exception object to include in the log event. + // To pass an System.Exception use one of the Info(object,Exception) methods instead. + void InfoFormat(string format, object arg0); + // + // Summary: + // Logs a formatted message string with the log4net.Core.Level.Info level. + // + // Parameters: + // format: + // A String containing zero or more format items + // + // args: + // An Object array containing zero or more objects to format + // + // Remarks: + // The message is formatted using the String.Format method. See String.Format(string, + // object[]) for details of the syntax of the format string and the behavior of + // the formatting. + // This method does not take an System.Exception object to include in the log event. + // To pass an System.Exception use one of the Info(object) methods instead. + void InfoFormat(string format, params object[] args); + // + // Summary: + // Logs a formatted message string with the log4net.Core.Level.Info level. + // + // Parameters: + // provider: + // An System.IFormatProvider that supplies culture-specific formatting information + // + // format: + // A String containing zero or more format items + // + // args: + // An Object array containing zero or more objects to format + // + // Remarks: + // The message is formatted using the String.Format method. See String.Format(string, + // object[]) for details of the syntax of the format string and the behavior of + // the formatting. + // This method does not take an System.Exception object to include in the log event. + // To pass an System.Exception use one of the Info(object) methods instead. + void InfoFormat(IFormatProvider provider, string format, params object[] args); + // + // Summary: + // Logs a formatted message string with the log4net.Core.Level.Info level. + // + // Parameters: + // format: + // A String containing zero or more format items + // + // arg0: + // An Object to format + // + // arg1: + // An Object to format + // + // Remarks: + // The message is formatted using the String.Format method. See String.Format(string, + // object[]) for details of the syntax of the format string and the behavior of + // the formatting. + // This method does not take an System.Exception object to include in the log event. + // To pass an System.Exception use one of the Info(object,Exception) methods instead. + void InfoFormat(string format, object arg0, object arg1); + // + // Summary: + // Logs a formatted message string with the log4net.Core.Level.Info level. + // + // Parameters: + // format: + // A String containing zero or more format items + // + // arg0: + // An Object to format + // + // arg1: + // An Object to format + // + // arg2: + // An Object to format + // + // Remarks: + // The message is formatted using the String.Format method. See String.Format(string, + // object[]) for details of the syntax of the format string and the behavior of + // the formatting. + // This method does not take an System.Exception object to include in the log event. + // To pass an System.Exception use one of the Info(object,Exception) methods instead. + void InfoFormat(string format, object arg0, object arg1, object arg2); + // + // Summary: + // Log a message object with the log4net.Core.Level.Warn level. + // + // Parameters: + // message: + // The message object to log. + // + // Remarks: + // This method first checks if this logger is WARN enabled by comparing the level + // of this logger with the log4net.Core.Level.Warn level. If this logger is WARN + // enabled, then it converts the message object (passed as parameter) to a string + // by invoking the appropriate log4net.ObjectRenderer.IObjectRenderer. It then proceeds + // to call all the registered appenders in this logger and also higher in the hierarchy + // depending on the value of the additivity flag. + // WARNING Note that passing an System.Exception to this method will print the name + // of the System.Exception but no stack trace. To print a stack trace use the Warn(object,Exception) + // form instead. + void Warn(object message); + // + // Summary: + // Log a message object with the log4net.Core.Level.Warn level including the stack + // trace of the System.Exception passed as a parameter. + // + // Parameters: + // message: + // The message object to log. + // + // exception: + // The exception to log, including its stack trace. + // + // Remarks: + // See the Warn(object) form for more detailed information. + void Warn(object message, Exception exception); + // + // Summary: + // Logs a formatted message string with the log4net.Core.Level.Warn level. + // + // Parameters: + // format: + // A String containing zero or more format items + // + // arg0: + // An Object to format + // + // Remarks: + // The message is formatted using the String.Format method. See String.Format(string, + // object[]) for details of the syntax of the format string and the behavior of + // the formatting. + // This method does not take an System.Exception object to include in the log event. + // To pass an System.Exception use one of the Warn(object,Exception) methods instead. + void WarnFormat(string format, object arg0); + // + // Summary: + // Logs a formatted message string with the log4net.Core.Level.Warn level. + // + // Parameters: + // format: + // A String containing zero or more format items + // + // args: + // An Object array containing zero or more objects to format + // + // Remarks: + // The message is formatted using the String.Format method. See String.Format(string, + // object[]) for details of the syntax of the format string and the behavior of + // the formatting. + // This method does not take an System.Exception object to include in the log event. + // To pass an System.Exception use one of the Warn(object) methods instead. + void WarnFormat(string format, params object[] args); + // + // Summary: + // Logs a formatted message string with the log4net.Core.Level.Warn level. + // + // Parameters: + // provider: + // An System.IFormatProvider that supplies culture-specific formatting information + // + // format: + // A String containing zero or more format items + // + // args: + // An Object array containing zero or more objects to format + // + // Remarks: + // The message is formatted using the String.Format method. See String.Format(string, + // object[]) for details of the syntax of the format string and the behavior of + // the formatting. + // This method does not take an System.Exception object to include in the log event. + // To pass an System.Exception use one of the Warn(object) methods instead. + void WarnFormat(IFormatProvider provider, string format, params object[] args); + // + // Summary: + // Logs a formatted message string with the log4net.Core.Level.Warn level. + // + // Parameters: + // format: + // A String containing zero or more format items + // + // arg0: + // An Object to format + // + // arg1: + // An Object to format + // + // Remarks: + // The message is formatted using the String.Format method. See String.Format(string, + // object[]) for details of the syntax of the format string and the behavior of + // the formatting. + // This method does not take an System.Exception object to include in the log event. + // To pass an System.Exception use one of the Warn(object,Exception) methods instead. + void WarnFormat(string format, object arg0, object arg1); + // + // Summary: + // Logs a formatted message string with the log4net.Core.Level.Warn level. + // + // Parameters: + // format: + // A String containing zero or more format items + // + // arg0: + // An Object to format + // + // arg1: + // An Object to format + // + // arg2: + // An Object to format + // + // Remarks: + // The message is formatted using the String.Format method. See String.Format(string, + // object[]) for details of the syntax of the format string and the behavior of + // the formatting. + // This method does not take an System.Exception object to include in the log event. + // To pass an System.Exception use one of the Warn(object,Exception) methods instead. + void WarnFormat(string format, object arg0, object arg1, object arg2); + + } +} diff --git a/util/Logging.cs b/util/Logging.cs index b7c7ae78..7cc3c883 100644 --- a/util/Logging.cs +++ b/util/Logging.cs @@ -4,17 +4,29 @@ namespace NMaier.SimpleDlna.Utilities { - public class Logging : ILog + public class Logging : ILogging { private ILog instance; + public static ILogging GetLogger() { + return GetLogger(typeof(T)); + } + + public static ILogging GetLogger(Type t) { + return new Logging(t); + } + + public Logging() { instance = LogManager.GetLogger(GetType()); } + + public Logging(Type t) { instance = LogManager.GetLogger(t); } + private ILog logger { get { - if (instance == null) { - instance = LogManager.GetLogger(GetType()); - } + //if (instance == null) { + // instance = LogManager.GetLogger(GetType()); + //} return instance; } } diff --git a/util/ReflectionHelper.cs b/util/ReflectionHelper.cs new file mode 100644 index 00000000..f660028c --- /dev/null +++ b/util/ReflectionHelper.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text.RegularExpressions; + +namespace NMaier.SimpleDlna.Utilities +{ + public class ReflectionHelper + { + static readonly Regex _parser = new Regex("(?[^=;]*)((=\"(?[^\"]*)\")|(=(?[^;]*)))?", RegexOptions.IgnoreCase); + + public static Dictionary StringToDictionary(string param) { + return _parser + .Matches(param) + .OfType() + .Where(m => m.Success && (m.Length > 0)) + .ToDictionary( + m => m.Groups["Token"].ToString().Trim() + ,m => m.Groups["Value"].ToString() + ); + } + + public static Type FindType(string parameter) { + var dparam = StringToDictionary(parameter); + if(!dparam.ContainsKey(AssemblyParameter)) { + return AppDomain.CurrentDomain.GetAssemblies().Select(a => a.GetType(dparam["type"])).FirstOrDefault(); + } + else { + var a = Assembly.Load(dparam[AssemblyParameter]); + if (a == null) throw new Exception(string.Format("Failed to load assembly [{0}]",dparam[AssemblyParameter])); + var t = a.GetType(dparam[TypeParameter]); + if (t == null) throw new Exception(string.Format("Failed to get type [{0}]",dparam[TypeParameter])); + return t; + } + } + + public const string AssemblyParameter = "assembly"; + public const string TypeParameter = "type"; + + public static object Create(string parameter) { + var t = FindType(parameter); + var constr = t.GetConstructor(Type.EmptyTypes); + if (constr == null) throw new Exception(string.Format("Can't find a default constructor for type:[{0}]", t.Name)); + return constr.Invoke(null); + } + } +} diff --git a/util/Repository.cs b/util/Repository.cs index 7dc90517..41ed53f8 100644 --- a/util/Repository.cs +++ b/util/Repository.cs @@ -3,8 +3,7 @@ namespace NMaier.SimpleDlna.Utilities { - public abstract class Repository - where TInterface : class, IRepositoryItem + public abstract class Repository : RepositoryBase where TInterface : class, IRepositoryItem { private static readonly Dictionary items = BuildRepository(); @@ -13,8 +12,8 @@ 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 a = typeof(TInterface).Assembly; + foreach (Type t in GetInterfaceImplementations()) { if (t.GetInterface(type) == null) { continue; } diff --git a/util/RepositoryBase.cs b/util/RepositoryBase.cs new file mode 100644 index 00000000..ff52e658 --- /dev/null +++ b/util/RepositoryBase.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; + +namespace NMaier.SimpleDlna.Utilities +{ + public class RepositoryBase + { + static readonly Assembly[] _assemblies; + static RepositoryBase() { + //Collect all assemblies in work path + var mask = string.Format("{0}.*.dll", Assembly.GetExecutingAssembly().GetName().Name.Split('.')[0]); + var additional = Directory.GetFiles(".", mask).Select(p => Assembly.UnsafeLoadFrom(p)).ToArray(); + _assemblies = AppDomain.CurrentDomain.GetAssemblies() + .Concat(additional) + .Distinct() + .ToArray(); + } + + public static Assembly[] GetDomainAssemblies() { + return _assemblies; + } + + protected static IEnumerable GetInterfaceImplementations() + { + var iface = typeof(TInterface); + return _assemblies.SelectMany(a => a.GetTypes()).Where(t => iface.IsAssignableFrom(t) && t.IsClass && !t.IsAbstract); + } + + } +} diff --git a/util/XmlHelper.cs b/util/XmlHelper.cs new file mode 100644 index 00000000..4f7645cf --- /dev/null +++ b/util/XmlHelper.cs @@ -0,0 +1,22 @@ +using System.IO; +using System.Xml.Serialization; + +namespace NMaier.SimpleDlna.Utilities +{ + public static class XmlHelper + { + public static void ToFile(object obj, string filename) { + var serializer = new XmlSerializer(obj.GetType()); + using (var writer = new StreamWriter(filename)) { + serializer.Serialize(writer, obj); + } + } + + public static T FromFile(string filename) { + var serializer = new XmlSerializer(typeof(T)); + using (var reader = new StreamReader(filename)) { + return (T)serializer.Deserialize(reader); + } + } + } +} diff --git a/util/packages.config b/util/packages.config deleted file mode 100644 index 9f737f39..00000000 --- a/util/packages.config +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/util/util.csproj b/util/util.csproj index 3eb3b7ad..78c7c8f6 100644 --- a/util/util.csproj +++ b/util/util.csproj @@ -15,6 +15,8 @@ Client ..\ true + + true @@ -26,7 +28,7 @@ 4 - pdbonly + none true bin\Release\ TRACE @@ -42,18 +44,22 @@ sdlna.key.snk + + ..\packages\EntityFramework.6.0.0\lib\net40\EntityFramework.dll + True + + + ..\packages\EntityFramework.6.0.0\lib\net40\EntityFramework.SqlServer.dll + True + False ..\packages\log4net.2.0.3\lib\net40-client\log4net.dll + - - False - ..\packages\System.Data.SQLite.Core.1.0.93.0\lib\net40\System.Data.SQLite.dll - - @@ -63,11 +69,13 @@ + + @@ -78,29 +86,21 @@ + + - + - - - - - Always - - - Always - - @@ -108,7 +108,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}. + +