diff --git a/Action/XmrSubscriber.cs b/Action/XmrSubscriber.cs index 33c9f8e6..1a144e07 100644 --- a/Action/XmrSubscriber.cs +++ b/Action/XmrSubscriber.cs @@ -87,7 +87,7 @@ public void Run() try { NetMQMessage message = socket.ReceiveMultipartMessage(); - + // Update status _clientInfoForm.XmrSubscriberStatus = "Connected (" + ApplicationSettings.Default.XmrNetworkAddress + "), last activity: " + DateTime.Now.ToString(); @@ -130,6 +130,10 @@ public void Run() OnCollectNowAction(); break; + case "screenShot": + ScreenShot.TakeAndSend(); + break; + default: Trace.WriteLine(new LogMessage("XmrSubscriber - Run", "Unknown Message: " + action.action), LogType.Info.ToString()); break; diff --git a/Logic/ApplicationSettings.cs b/Logic/ApplicationSettings.cs index 93087ae2..49397d33 100644 --- a/Logic/ApplicationSettings.cs +++ b/Logic/ApplicationSettings.cs @@ -19,6 +19,7 @@ */ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; @@ -38,16 +39,14 @@ public class ApplicationSettings private static string _default = "default"; // Application Specific Settings we want to protect - private string _clientVersion = "1.7.5"; + private string _clientVersion = "1.8.0-alpha2"; private string _version = "5"; - private int _clientCodeVersion = 109; + private int _clientCodeVersion = 120; public string ClientVersion { get { return _clientVersion; } } public string Version { get { return _version; } } public int ClientCodeVersion { get { return _clientCodeVersion; } } - private static readonly DateTime unixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Local); - public static ApplicationSettings Default { get @@ -122,7 +121,6 @@ public object this[string propertyName] } public int XmdsResetTimeout { get; set; } - public double CmsTimeOffset { get; set; } public decimal SizeX { get; set; } public decimal SizeY { get; set; } @@ -165,29 +163,15 @@ public object this[string propertyName] public string XmrNetworkAddress { get; set; } // Download window - - public long DownloadStartWindow { get; set; } - public long DownloadEndWindow { get; set; } + public string DisplayTimeZone { get; set; } + public string DownloadStartWindow { get; set; } + public string DownloadEndWindow { get; set; } public DateTime DownloadStartWindowTime { get { - // Get the local time now and add our Unix timestamp to it. - // We know that the DownloadStartWindow is saved in UTC (GMT to be precise, but no biggie) - DateTime now = DateTime.Now; - DateTime start = unixEpoch.AddMilliseconds(DownloadStartWindow); - - // start is now UTC download window start. - if (CmsTimeOffset != null && CmsTimeOffset != 0) - { - // Adjust for the timezone - start = start.AddHours(CmsTimeOffset); - } - - // Reset to local time, using the H:m:i from the Unix Time. - // This gives us a local time - return new DateTime(now.Year, now.Month, now.Day, start.Hour, start.Minute, start.Second, DateTimeKind.Local); + return getDateFromHi(DownloadStartWindow); } } @@ -195,18 +179,43 @@ public DateTime DownloadEndWindowTime { get { - // See notes from DownloadStartWindowTime - DateTime now = DateTime.Now; - DateTime end = unixEpoch.AddMilliseconds(DownloadEndWindow); + return getDateFromHi(DownloadEndWindow); + } + } - if (CmsTimeOffset != null && CmsTimeOffset != 0) + /// + /// Get a locally formatted date based on the H:i string provided. + /// + /// + /// + private DateTime getDateFromHi(string hi) + { + DateTime now = DateTime.Now; + + try + { + int h; + int m; + + // Expect the format H:i (24 hour). If we don't have a : in it, then it is likely being fed by an old CMS, so disable + if (!hi.Contains(":")) + { + h = 0; + m = 0; + } + else { - // Adjust for the timezone - end = end.AddHours(CmsTimeOffset); + string[] split = hi.Split(':'); + h = int.Parse(split[0]); + m = int.Parse(split[1]); } - // Reset to today - return new DateTime(now.Year, now.Month, now.Day, end.Hour, end.Minute, end.Second, DateTimeKind.Local); + return new DateTime(now.Year, now.Month, now.Day, h, m, 0, DateTimeKind.Local); + } + catch (Exception e) + { + Trace.WriteLine(new LogMessage("getDateFromHi", "Unable to parse H:i, Error = " + e.Message), LogType.Info.ToString()); + return new DateTime(now.Year, now.Month, now.Day, 0, 0, 0, DateTimeKind.Local); } } @@ -219,10 +228,14 @@ public bool InDownloadWindow { try { - if (DownloadStartWindow == 0 && DownloadEndWindow == 0) + if (DownloadStartWindow == DownloadEndWindow) return true; - return (DownloadStartWindowTime <= DateTime.Now && DownloadEndWindowTime >= DateTime.Now); + DateTime startWindow = DownloadStartWindowTime; + if (DownloadEndWindowTime < startWindow) + startWindow = DownloadStartWindowTime.AddDays(-1); + + return (startWindow <= DateTime.Now && DownloadEndWindowTime >= DateTime.Now); } catch { @@ -251,21 +264,6 @@ public bool InDownloadWindow public bool UseCefWebBrowser { get; set; } public bool SendCurrentLayoutAsStatusUpdate { get; set; } - private bool _screenShotRequested = false; - public bool ScreenShotRequested - { - get - { - return _screenShotRequested; - } - set - { - _screenShotRequested = value; - // Reset the Hash so that the next update is taken into account. - Hash = "0"; - } - } - // XMDS Status Flags private DateTime _xmdsLastConnection; public DateTime XmdsLastConnection { get { return _xmdsLastConnection; } set { _xmdsErrorCountSinceSuccessful = 0; _xmdsLastConnection = value; } } diff --git a/Logic/ScheduleManager.cs b/Logic/ScheduleManager.cs index 8970c5bb..a2385190 100644 --- a/Logic/ScheduleManager.cs +++ b/Logic/ScheduleManager.cs @@ -302,35 +302,53 @@ private Collection LoadNewSchdule() // Temporary default Layout incase we have no layout nodes. LayoutSchedule defaultLayout = new LayoutSchedule(); + // Store the valid layout id's + List validLayoutIds = new List(); + List invalidLayouts = new List(); + // For each layout in the schedule determine if it is currently inside the _currentSchedule, and whether it should be foreach (LayoutSchedule layout in _layoutSchedule) { - // Is the layout valid in the cachemanager? - try + // Is this already invalid + if (invalidLayouts.Contains(layout.id)) + continue; + + // If we haven't already assessed this layout before, then check that it is valid + if (!validLayoutIds.Contains(layout.id)) { - if (!_cacheManager.IsValidLayout(layout.id + ".xlf")) + // Is the layout valid in the cachemanager? + try + { + if (!_cacheManager.IsValidLayout(layout.id + ".xlf")) + { + invalidLayouts.Add(layout.id); + Trace.WriteLine(new LogMessage("ScheduleManager - LoadNewSchedule", "Layout invalid: " + layout.id), LogType.Error.ToString()); + continue; + } + } + catch { - Trace.WriteLine(new LogMessage("ScheduleManager - LoadNewSchedule", "Layout invalid: " + layout.id), LogType.Error.ToString()); + // Ignore this layout.. raise an error? + invalidLayouts.Add(layout.id); + Trace.WriteLine(new LogMessage("ScheduleManager - LoadNewSchedule", "Unable to determine if layout is valid or not"), LogType.Error.ToString()); continue; } - } - catch - { - // Ignore this layout.. raise an error? - Trace.WriteLine(new LogMessage("ScheduleManager - LoadNewSchedule", "Unable to determine if layout is valid or not"), LogType.Error.ToString()); - continue; - } - // Check dependents - foreach (string dependent in layout.Dependents) - { - if (!_cacheManager.IsValidPath(dependent)) + // Check dependents + foreach (string dependent in layout.Dependents) { - Trace.WriteLine(new LogMessage("ScheduleManager - LoadNewSchedule", "Layout has invalid dependent: " + dependent), LogType.Info.ToString()); - continue; + if (!_cacheManager.IsValidPath(dependent)) + { + invalidLayouts.Add(layout.id); + Trace.WriteLine(new LogMessage("ScheduleManager - LoadNewSchedule", "Layout has invalid dependent: " + dependent), LogType.Info.ToString()); + continue; + } } } + // Add to the valid layout ids + validLayoutIds.Add(layout.id); + // If this is the default, skip it if (layout.NodeName == "default") { @@ -466,6 +484,21 @@ private void LoadScheduleFromFile() } } + // Look for dependents nodes + foreach (XmlNode childNode in node.ChildNodes) + { + if (childNode.Name == "dependents") + { + foreach (XmlNode dependent in childNode.ChildNodes) + { + if (dependent.Name == "file") + { + temp.Dependents.Add(dependent.InnerText); + } + } + } + } + _layoutSchedule.Add(temp); } } diff --git a/Media/CefWebMedia.cs b/Media/CefWebMedia.cs index 659a12ff..9bfc7fd2 100644 --- a/Media/CefWebMedia.cs +++ b/Media/CefWebMedia.cs @@ -43,7 +43,7 @@ public CefWebMedia(RegionOptions options) _filePath = ApplicationSettings.Default.LibraryPath + @"\" + _options.mediaid + ".htm"; } - Color backgroundColor = ColorTranslator.FromHtml(_options.backgroundColor); + Color backgroundColor = ColorTranslator.FromHtml(_options.Dictionary.Get("backgroundColor", _options.backgroundColor)); CefBrowserSettings settings = new CefBrowserSettings(); settings.BackgroundColor = new CefColor(backgroundColor.A, backgroundColor.R, backgroundColor.G, backgroundColor.B); @@ -216,14 +216,15 @@ private void xmds_GetResourceCompleted(object sender, XiboClient.xmds.GetResourc // Handle the background String bodyStyle; + String backgroundColor = _options.Dictionary.Get("backgroundColor", _options.backgroundColor); if (_options.backgroundImage == null || _options.backgroundImage == "") { - bodyStyle = "background-color:" + _options.backgroundColor + " ;"; + bodyStyle = "background-color:" + backgroundColor + " ;"; } else { - bodyStyle = "background-image: url('" + _options.backgroundImage.Replace('\\', '/') + "'); background-attachment:fixed; background-color:" + _options.backgroundColor + "; background-repeat: no-repeat; background-position: " + _options.backgroundLeft + "px " + _options.backgroundTop + "px;"; + bodyStyle = "background-image: url('" + _options.backgroundImage.Replace('\\', '/') + "'); background-attachment:fixed; background-color:" + backgroundColor + "; background-repeat: no-repeat; background-position: " + _options.backgroundLeft + "px " + _options.backgroundTop + "px;"; } string html = cachedFile.Replace("", ""); @@ -274,14 +275,15 @@ private void UpdateCacheIfNecessary() { // Handle the background String bodyStyle; + String backgroundColor = _options.Dictionary.Get("backgroundColor", _options.backgroundColor); if (_options.backgroundImage == null || _options.backgroundImage == "") { - bodyStyle = "background-color:" + _options.backgroundColor + " ;"; + bodyStyle = "background-color:" + backgroundColor + " ;"; } else { - bodyStyle = "background-image: url('" + _options.backgroundImage.Replace('\\', '/') + "'); background-attachment:fixed; background-color:" + _options.backgroundColor + "; background-repeat: no-repeat; background-position: " + _options.backgroundLeft + "px " + _options.backgroundTop + "px;"; + bodyStyle = "background-image: url('" + _options.backgroundImage.Replace('\\', '/') + "'); background-attachment:fixed; background-color:" + backgroundColor + "; background-repeat: no-repeat; background-position: " + _options.backgroundLeft + "px " + _options.backgroundTop + "px;"; } string html = cachedFile.Replace("", ""); diff --git a/Media/IeWebMedia.cs b/Media/IeWebMedia.cs index e3a3a7de..281edcbe 100644 --- a/Media/IeWebMedia.cs +++ b/Media/IeWebMedia.cs @@ -206,14 +206,15 @@ private void xmds_GetResourceCompleted(object sender, XiboClient.xmds.GetResourc // Handle the background String bodyStyle; + String backgroundColor = _options.Dictionary.Get("backgroundColor", _options.backgroundColor); if (_options.backgroundImage == null || _options.backgroundImage == "") { - bodyStyle = "background-color:" + _options.backgroundColor + " ;"; + bodyStyle = "background-color:" + backgroundColor + " ;"; } else { - bodyStyle = "background-image: url('" + _options.backgroundImage.Replace('\\', '/') + "'); background-attachment:fixed; background-color:" + _options.backgroundColor + "; background-repeat: no-repeat; background-position: " + _options.backgroundLeft + "px " + _options.backgroundTop + "px;"; + bodyStyle = "background-image: url('" + _options.backgroundImage.Replace('\\', '/') + "'); background-attachment:fixed; background-color:" + backgroundColor + "; background-repeat: no-repeat; background-position: " + _options.backgroundLeft + "px " + _options.backgroundTop + "px;"; } string html = cachedFile.Replace("", ""); @@ -264,14 +265,15 @@ private void UpdateCacheIfNecessary() { // Handle the background String bodyStyle; + String backgroundColor = _options.Dictionary.Get("backgroundColor", _options.backgroundColor); if (_options.backgroundImage == null || _options.backgroundImage == "") { - bodyStyle = "background-color:" + _options.backgroundColor + " ;"; + bodyStyle = "background-color:" + backgroundColor + " ;"; } else { - bodyStyle = "background-image: url('" + _options.backgroundImage.Replace('\\', '/') + "'); background-attachment:fixed; background-color:" + _options.backgroundColor + "; background-repeat: no-repeat; background-position: " + _options.backgroundLeft + "px " + _options.backgroundTop + "px;"; + bodyStyle = "background-image: url('" + _options.backgroundImage.Replace('\\', '/') + "'); background-attachment:fixed; background-color:" + backgroundColor + "; background-repeat: no-repeat; background-position: " + _options.backgroundLeft + "px " + _options.backgroundTop + "px;"; } string html = cachedFile.Replace("", ""); diff --git a/Media/Image.cs b/Media/Image.cs index 1ba1b41b..11b8d303 100644 --- a/Media/Image.cs +++ b/Media/Image.cs @@ -29,10 +29,12 @@ class ImagePosition : Media { private string _filePath; PictureBox _pictureBox; + RegionOptions _options; public ImagePosition(RegionOptions options) : base(options.width, options.height, options.top, options.left) { + _options = options; _filePath = options.uri; if (!System.IO.File.Exists(_filePath)) @@ -45,18 +47,23 @@ public ImagePosition(RegionOptions options) try { _pictureBox = new PictureBox(); - _pictureBox.SizeMode = (options.Dictionary.Get("scaleType", "center") == "stretch") ? PictureBoxSizeMode.StretchImage : PictureBoxSizeMode.Zoom; - _pictureBox.Image = new Bitmap(_filePath); _pictureBox.Size = new Size(_width, _height); _pictureBox.Location = new Point(0, 0); _pictureBox.BorderStyle = BorderStyle.None; _pictureBox.BackColor = Color.Transparent; - /*if (options.Dictionary.Get("scaleType", "stretch") == "center") + // Do we need to align the image in any way? + if (options.Dictionary.Get("scaleType", "stretch") == "center" && (options.Dictionary.Get("align", "center") != "center" || options.Dictionary.Get("valign", "middle") != "middle")) { - string align = options.Dictionary.Get("align", "center"); - string valign = options.Dictionary.Get("valign", "middle"); - }*/ + // Yes we do, so we must override the paint method + _pictureBox.Paint += _pictureBox_Paint; + } + else + { + // No we don't so use a normal picture box. + _pictureBox.SizeMode = (options.Dictionary.Get("scaleType", "center") == "stretch") ? PictureBoxSizeMode.StretchImage : PictureBoxSizeMode.Zoom; + _pictureBox.Image = new Bitmap(_filePath); + } Controls.Add(this._pictureBox); } @@ -66,6 +73,62 @@ public ImagePosition(RegionOptions options) } } + void _pictureBox_Paint(object sender, PaintEventArgs e) + { + string align = _options.Dictionary.Get("align", "center"); + string valign = _options.Dictionary.Get("valign", "middle"); + + Image image = Image.FromFile(_filePath); + + // Get our image + Graphics graphics = e.Graphics; + graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; + + // Calculate the width and height required + double imageProportion = (double)image.Width / (double)image.Height; + double regionProportion = _pictureBox.Width / _pictureBox.Height; + + int x = 0; + int y = 0; + int width = _pictureBox.Width; + int height = _pictureBox.Height; + + if (imageProportion > regionProportion) + { + // Use the full width possible and adjust the height accordingly + height = (int)(_pictureBox.Width / imageProportion); + + if (valign == "middle") + { + // top margin needs to drop down half + x = x + ((_pictureBox.Height - height) / 2); + } + else if (valign == "bottom") { + x = x + (_pictureBox.Height - height); + } + } + else + { + // Use the full height possible and adjust the width accordingly + width = (int)(imageProportion * _pictureBox.Height); + + if (align == "center") + { + y = y + ((_pictureBox.Width - width) / 2); + } + else if (align == "right") + { + y = y + (_pictureBox.Width - width); + } + } + + graphics.DrawImage(image, + y, + x, + width, + height); + } + public override void RenderMedia() { base.RenderMedia(); @@ -79,7 +142,9 @@ protected override void Dispose(bool disposing) { Controls.Remove(_pictureBox); - _pictureBox.Image.Dispose(); + if (_pictureBox.Image != null) + _pictureBox.Image.Dispose(); + _pictureBox.Dispose(); } catch (Exception ex) diff --git a/XiboClient.v11.suo b/XiboClient.v11.suo index 62c2f29f..ced5b0db 100644 Binary files a/XiboClient.v11.suo and b/XiboClient.v11.suo differ diff --git a/XmdsAgents/RegisterAgent.cs b/XmdsAgents/RegisterAgent.cs index 274aaa00..ebf98d8a 100644 --- a/XmdsAgents/RegisterAgent.cs +++ b/XmdsAgents/RegisterAgent.cs @@ -102,13 +102,6 @@ public void Run() // Set the flag to indicate we have a connection to XMDS ApplicationSettings.Default.XmdsLastConnection = DateTime.Now; - // Do we need to send a screenshot? - if (ApplicationSettings.Default.ScreenShotRequested) - { - ApplicationSettings.Default.ScreenShotRequested = false; - ScreenShot.TakeAndSend(); - } - // Has the XMR address changed? if (xmrAddress != ApplicationSettings.Default.XmrNetworkAddress) { @@ -143,37 +136,26 @@ public static string ProcessRegisterXml(string xml) string message = ""; bool error = false; - // Work out if we need to do anything (have the settings changed since the last time) - string md5 = Hashes.MD5(xml); - try { // Load the result into an XML document XmlDocument result = new XmlDocument(); result.LoadXml(xml); - // If the XML we received has not changed, then go no further. - if (ApplicationSettings.Default.Hash == md5) - return result.DocumentElement.Attributes["message"].Value; - // Test the XML if (result.DocumentElement.Attributes["code"].Value == "READY") { - // Pull the CMS time and store it - try - { - DateTime cmsTime = DateTime.Parse(result.DocumentElement.Attributes["date"].Value); - ApplicationSettings.Default.CmsTimeOffset = (cmsTime - DateTime.Now).TotalHours; - } - catch - { - Trace.WriteLine(new LogMessage("Register", "CMS Date parse error"), LogType.Info.ToString()); - } - // Get the config element if (result.DocumentElement.ChildNodes.Count <= 0) throw new Exception("Configuration not set for this display"); + // Hash after removing the date + result.DocumentElement.Attributes["date"].Value = ""; + string md5 = Hashes.MD5(result.OuterXml); + + if (md5 == ApplicationSettings.Default.Hash) + return result.DocumentElement.Attributes["message"].Value; + foreach (XmlNode node in result.DocumentElement.ChildNodes) { // Are we a commands node? diff --git a/default.config.xml b/default.config.xml index 73df049f..2ad8cd9b 100644 --- a/default.config.xml +++ b/default.config.xml @@ -47,9 +47,9 @@ 0001-01-01T00:00:00 false false - false 0 - 0 - 0 + + + \ No newline at end of file