diff --git a/Action/Rs232Command.cs b/Action/Rs232Command.cs
index 7b17912f..12db207c 100644
--- a/Action/Rs232Command.cs
+++ b/Action/Rs232Command.cs
@@ -21,6 +21,7 @@ public Rs232Command(Command command)
///
/// Run the command
+ /// throws an exception if we cannot open or write to the port
///
public string Run()
{
@@ -29,6 +30,8 @@ public string Run()
// Parse and configure the port
parse();
+ Trace.WriteLine(new LogMessage("Rs232Command - run", "Parsed command, will open port " + _port.PortName + " and write " + _toSend), LogType.Audit.ToString());
+
// try to open the COM port
if (!_port.IsOpen)
_port.Open();
diff --git a/Action/XmrSubscriber.cs b/Action/XmrSubscriber.cs
index f0e414ac..463f604d 100644
--- a/Action/XmrSubscriber.cs
+++ b/Action/XmrSubscriber.cs
@@ -175,7 +175,7 @@ public void Run()
}
catch (Exception e)
{
- Trace.WriteLine(new LogMessage("XmrSubscriber - Run", "Unable to Subscribe to XMR: " + e.Message), LogType.Error.ToString());
+ Trace.WriteLine(new LogMessage("XmrSubscriber - Run", "Unable to Subscribe to XMR: " + e.Message), LogType.Info.ToString());
_clientInfoForm.XmrSubscriberStatus = e.Message;
}
}
diff --git a/Control/EmbeddedServer.cs b/Control/EmbeddedServer.cs
index 45e6fe70..561dd279 100644
--- a/Control/EmbeddedServer.cs
+++ b/Control/EmbeddedServer.cs
@@ -52,7 +52,14 @@ public void Run()
using (WebServer server = new WebServer(ApplicationSettings.Default.EmbeddedServerAddress))
{
- server.RegisterModule(new StaticFilesModule(ApplicationSettings.Default.LibraryPath));
+ Dictionary headers = new Dictionary()
+ {
+ { Constants.HeaderCacheControl, "no-cache, no-store, must-revalidate" },
+ { Constants.HeaderPragma, "no-cache" },
+ { Constants.HeaderExpires, "0" }
+ };
+
+ server.RegisterModule(new StaticFilesModule(ApplicationSettings.Default.LibraryPath, headers));
server.Module().UseRamCache = true;
server.Module().DefaultExtension = ".html";
diff --git a/Control/Region.cs b/Control/Region.cs
index 61e9bf4e..76e59443 100644
--- a/Control/Region.cs
+++ b/Control/Region.cs
@@ -1,6 +1,6 @@
/*
* Xibo - Digitial Signage - http://www.xibo.org.uk
- * Copyright (C) 2006-2015 Daniel Garner
+ * Copyright (C) 2006-2016 Daniel Garner
*
* This file is part of Xibo.
*
@@ -171,18 +171,26 @@ private void EvalOptions()
if (!SetNextMediaNodeInOptions())
{
// For some reason we cannot set a media node... so we need this region to become invalid
- _hasExpired = true;
-
- if (DurationElapsedEvent != null)
- DurationElapsedEvent();
- return;
+ throw new InvalidOperationException("Unable to set any region media nodes.");
}
// If the sequence hasnt been changed, OR the layout has been expired
// there has been no change to the sequence, therefore the media we have already created is still valid
// or this media has actually been destroyed and we are working out way out the call stack
- if (_layoutExpired || (_currentSequence == temp))
+ if (_layoutExpired)
+ {
return;
+ }
+ else if (_currentSequence == temp)
+ {
+ // Media has not changed, we are likely the only valid media item in the region
+ // the layout has not yet expired, so depending on whether we loop or not, we either
+ // reload the same media item again
+ // or do nothing (return)
+ // This could be made more succinct, but is clearer written as an elseif.
+ if (!_options.RegionLoop)
+ return;
+ }
// Store the Current Index
_options.CurrentIndex = _currentSequence;
@@ -199,7 +207,7 @@ private void EvalOptions()
// Try the next node
startSuccessful = false;
continue;
- }
+ }
// First thing we do is stop the current stat record
if (!initialMedia)
@@ -449,23 +457,26 @@ private void ParseOptionsForMediaNode(XmlNode mediaNode, XmlAttributeCollection
// And some stuff on Raw nodes
XmlNode rawNode = mediaNode.SelectSingleNode("raw");
- foreach (XmlNode raw in rawNode.ChildNodes)
+ if (rawNode != null)
{
- if (raw.Name == "text")
- {
- _options.text = raw.InnerText;
- }
- else if (raw.Name == "template")
- {
- _options.documentTemplate = raw.InnerText;
- }
- else if (raw.Name == "embedHtml")
+ foreach (XmlNode raw in rawNode.ChildNodes)
{
- _options.text = raw.InnerText;
- }
- else if (raw.Name == "embedScript")
- {
- _options.javaScript = raw.InnerText;
+ if (raw.Name == "text")
+ {
+ _options.text = raw.InnerText;
+ }
+ else if (raw.Name == "template")
+ {
+ _options.documentTemplate = raw.InnerText;
+ }
+ else if (raw.Name == "embedHtml")
+ {
+ _options.text = raw.InnerText;
+ }
+ else if (raw.Name == "embedScript")
+ {
+ _options.javaScript = raw.InnerText;
+ }
}
}
@@ -539,6 +550,8 @@ private Media CreateNextMediaNode(RegionOptions options)
}
else
{
+ // We've set our next media node in options already
+ // this includes checking that file based media is valid.
switch (options.type)
{
case "image":
@@ -775,11 +788,16 @@ private void media_DurationElapsedEvent(int filesPlayed)
///
/// Clears the Region of anything that it shouldnt still have...
+ /// called when Destroying a Layout and when Removing an Overlay
///
public void Clear()
{
try
{
+ // Stop the current media item
+ if (_media != null)
+ StopMedia(_media);
+
// What happens if we are disposing this region but we have not yet completed the stat event?
if (string.IsNullOrEmpty(_stat.toDate))
{
diff --git a/Control/WatchDogManager.cs b/Control/WatchDogManager.cs
index c6dbb283..537424ac 100644
--- a/Control/WatchDogManager.cs
+++ b/Control/WatchDogManager.cs
@@ -13,6 +13,8 @@ class WatchDogManager
public static void Start()
{
// Check to see if the WatchDog EXE exists where we expect it to be
+ // Uncomment to test local watchdog install.
+ //string path = @"C:\Program Files (x86)\Xibo Player\watchdog\x86\XiboClientWatchdog.exe";
string path = Path.GetDirectoryName(Application.ExecutablePath) + @"\watchdog\x86\XiboClientWatchdog.exe";
string args = "-p \"" + Application.ExecutablePath + "\" -l \"" + ApplicationSettings.Default.LibraryPath + "\"";
@@ -21,7 +23,16 @@ public static void Start()
{
try
{
- Process.Start(path, args);
+ Process process = new Process();
+ ProcessStartInfo info = new ProcessStartInfo();
+
+ info.CreateNoWindow = true;
+ info.WindowStyle = ProcessWindowStyle.Hidden;
+ info.FileName = "cmd.exe";
+ info.Arguments = "/c start \"watchdog\" \"" + path + "\" " + args;
+
+ process.StartInfo = info;
+ process.Start();
}
catch (Exception e)
{
diff --git a/Error/DefaultLayoutException.cs b/Error/DefaultLayoutException.cs
new file mode 100644
index 00000000..ac196cba
--- /dev/null
+++ b/Error/DefaultLayoutException.cs
@@ -0,0 +1,12 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace XiboClient.Error
+{
+ class DefaultLayoutException : Exception
+ {
+ }
+}
diff --git a/Log/ClientInfo.cs b/Log/ClientInfo.cs
index f7d2536d..34bb646d 100644
--- a/Log/ClientInfo.cs
+++ b/Log/ClientInfo.cs
@@ -17,6 +17,9 @@ public partial class ClientInfo : Form
public delegate void StatusDelegate(string status);
public delegate void AddLogMessage(string message, LogType logType);
+ // Delegate for updating the status file
+ public delegate void UpdateStatusFile();
+
///
/// Set the schedule status
///
@@ -298,5 +301,29 @@ private void saveFileDialog_FileOk(object sender, CancelEventArgs e)
MessageBox.Show("Log saved as " + saveFileDialog.FileName, "Log Saved");
}
+
+ ///
+ /// Update Status Marker File
+ ///
+ public void UpdateStatusMarkerFile()
+ {
+ if (InvokeRequired)
+ {
+ BeginInvoke(new UpdateStatusFile(updateStatusFile));
+ }
+ else
+ {
+ updateStatusFile();
+ }
+ }
+
+ ///
+ /// Update status file
+ ///
+ private void updateStatusFile()
+ {
+ File.WriteAllText(Path.Combine(ApplicationSettings.Default.LibraryPath, "status.json"),
+ "{\"lastActivity\":\"" + DateTime.Now.ToString() + "\",\"state\":\"" + Thread.State.ToString() + "\",\"xmdsLastActivity\":\"" + ApplicationSettings.Default.XmdsLastConnection.ToString() + "\",\"xmdsCollectInterval\":\"" + ApplicationSettings.Default.CollectInterval.ToString() + "\"}");
+ }
}
}
\ No newline at end of file
diff --git a/Logic/ApplicationSettings.cs b/Logic/ApplicationSettings.cs
index deeef9a6..ebbcac9a 100644
--- a/Logic/ApplicationSettings.cs
+++ b/Logic/ApplicationSettings.cs
@@ -39,9 +39,9 @@ public class ApplicationSettings
private static string _default = "default";
// Application Specific Settings we want to protect
- private string _clientVersion = "1.8.0-beta";
+ private string _clientVersion = "1.8.0-rc1";
private string _version = "5";
- private int _clientCodeVersion = 122;
+ private int _clientCodeVersion = 124;
public string ClientVersion { get { return _clientVersion; } }
public string Version { get { return _version; } }
diff --git a/Logic/CacheManager.cs b/Logic/CacheManager.cs
index 53e0d3f2..15b97d56 100644
--- a/Logic/CacheManager.cs
+++ b/Logic/CacheManager.cs
@@ -199,7 +199,7 @@ public bool IsValidPath(String path)
{
// If we cached it over 2 minutes ago, then check the GetLastWriteTime
if (file.cacheDate > DateTime.Now.AddMinutes(-2))
- return true;
+ return File.Exists(ApplicationSettings.Default.LibraryPath + @"\" + path);
try
{
@@ -231,93 +231,6 @@ public bool IsValidPath(String path)
}
}
- ///
- /// Is the provided layout file a valid layout (has all media)
- ///
- ///
- ///
- public bool IsValidLayout(string layoutFile)
- {
- lock (_locker)
- {
- Debug.WriteLine("Checking if Layout " + layoutFile + " is valid");
-
- if (!IsValidPath(layoutFile))
- return false;
-
-
- // Load the XLF, get all media ID's
- XmlDocument layoutXml = new XmlDocument();
- layoutXml.Load(ApplicationSettings.Default.LibraryPath + @"\" + layoutFile);
-
- try
- {
- XmlNodeList mediaNodes = layoutXml.SelectNodes("//media");
-
- // Store some information about the validity of local video to decide if this layout should be valid or not.
- int countInvalidLocalVideo = 0;
-
- foreach (XmlNode media in mediaNodes)
- {
- // Is this a stored media type?
- switch (media.Attributes["type"].Value)
- {
- case "video":
- case "image":
- case "flash":
- case "powerpoint":
-
- // Get the path and see if its
- if (!IsValidPath(GetUri(media)))
- {
- Trace.WriteLine(new LogMessage("CacheManager - IsValidLayout", "Invalid Media: " + media.Attributes["id"].Value.ToString()), LogType.Audit.ToString());
- return false;
- }
-
- break;
-
- default:
- continue;
- }
- }
-
- // If the number of invalid local video elements is equal to the number of elements on the layout, then don't show
- if (countInvalidLocalVideo == mediaNodes.Count)
- return false;
- }
- catch (Exception ex)
- {
- Trace.WriteLine(new LogMessage("CacheManager - IsValidLayout", "Exception checking media. " + ex.Message), LogType.Audit.ToString());
- return false;
- }
-
- // Also check to see if there is a background image that needs to be downloaded
- try
- {
- XmlNode layoutNode = layoutXml.SelectSingleNode("/layout");
- XmlAttributeCollection layoutAttributes = layoutNode.Attributes;
-
- if (layoutAttributes["background"] != null && !string.IsNullOrEmpty(layoutAttributes["background"].Value))
- {
- if (!IsValidPath(layoutAttributes["background"].Value))
- {
- Debug.WriteLine("Invalid background: " + layoutAttributes["background"].Value);
- return false;
- }
- }
- }
- catch
- {
- // We dont want a missing background attribute to stop this process
- return true;
- }
-
- Debug.WriteLine("Layout " + layoutFile + " is valid");
-
- return true;
- }
- }
-
///
/// Get the URI of this media item
///
diff --git a/Logic/HardwareKey.cs b/Logic/HardwareKey.cs
index 5ca7cc54..6b3444e5 100644
--- a/Logic/HardwareKey.cs
+++ b/Logic/HardwareKey.cs
@@ -72,6 +72,9 @@ public HardwareKey()
{
Debug.WriteLine("[IN]", "HardwareKey");
+ // Get the Mac Address
+ _macAddress = GetMacAddress();
+
// Get the key from the Settings
_hardwareKey = ApplicationSettings.Default.HardwareKey;
@@ -80,8 +83,10 @@ public HardwareKey()
{
try
{
+ string systemDriveLetter = Path.GetPathRoot(Environment.SystemDirectory);
+
// Calculate the Hardware key from the CPUID and Volume Serial
- _hardwareKey = Hashes.MD5(GetCPUId() + GetVolumeSerial("C"));
+ _hardwareKey = Hashes.MD5(GetCPUId() + GetVolumeSerial(systemDriveLetter[0].ToString()) + _macAddress);
}
catch
{
@@ -92,9 +97,6 @@ public HardwareKey()
ApplicationSettings.Default.HardwareKey = _hardwareKey;
}
- // Get the Mac Address
- _macAddress = GetMacAddress();
-
Debug.WriteLine("[OUT]", "HardwareKey");
}
@@ -154,14 +156,21 @@ private string GetMacAddress()
{
string macAddresses = string.Empty;
- foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces())
+ try
{
- if (nic.OperationalStatus == OperationalStatus.Up)
+ foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces())
{
- macAddresses += BitConverter.ToString(nic.GetPhysicalAddress().GetAddressBytes()).Replace('-', ':');
- break;
+ if (nic.OperationalStatus == OperationalStatus.Up)
+ {
+ macAddresses += BitConverter.ToString(nic.GetPhysicalAddress().GetAddressBytes()).Replace('-', ':');
+ break;
+ }
}
}
+ catch
+ {
+ macAddresses = "00:00:00:00:00:00";
+ }
return macAddresses;
}
@@ -203,7 +212,7 @@ public AsymmetricCipherKeyPair getXmrKey()
const int PROVIDER_RSA_FULL = 1;
CspParameters cspParams;
cspParams = new CspParameters(PROVIDER_RSA_FULL);
- cspParams.KeyContainerName = Application.ProductName + "RsaKey";
+ cspParams.KeyContainerName = Application.ProductName + "-" + Environment.UserName + "-" + "RsaKey";
cspParams.Flags = CspProviderFlags.UseMachineKeyStore;
cspParams.ProviderName = "Microsoft Strong Cryptographic Provider";
@@ -217,15 +226,23 @@ public AsymmetricCipherKeyPair getXmrKey()
public string getXmrPublicKey()
{
- AsymmetricCipherKeyPair key = getXmrKey();
-
- using (TextWriter textWriter = new StringWriter())
+ try
{
- PemWriter writer = new PemWriter(textWriter);
- writer.WriteObject(key.Public);
- writer.Writer.Flush();
+ AsymmetricCipherKeyPair key = getXmrKey();
+
+ using (TextWriter textWriter = new StringWriter())
+ {
+ PemWriter writer = new PemWriter(textWriter);
+ writer.WriteObject(key.Public);
+ writer.Writer.Flush();
- return textWriter.ToString();
+ return textWriter.ToString();
+ }
+ }
+ catch (Exception e)
+ {
+ Trace.WriteLine(new LogMessage("HardwareKey - getXmrPublicKey", "Unable to get XMR public key. E = " + e.Message), LogType.Error.ToString());
+ return null;
}
}
}
diff --git a/Logic/RegionOptions.cs b/Logic/RegionOptions.cs
index 6013d986..583dd67e 100644
--- a/Logic/RegionOptions.cs
+++ b/Logic/RegionOptions.cs
@@ -46,6 +46,9 @@ struct RegionOptions
public string uri;
public int duration;
+ // Region Loop
+ public bool RegionLoop;
+
//xml
public XmlNodeList mediaNodes;
diff --git a/Logic/Schedule.cs b/Logic/Schedule.cs
index d085a4f4..064cba23 100644
--- a/Logic/Schedule.cs
+++ b/Logic/Schedule.cs
@@ -64,6 +64,25 @@ class Schedule
private string _scheduleLocation;
+ ///
+ /// The current layout id
+ ///
+ public int CurrentLayoutId
+ {
+ get
+ {
+ return _currentLayoutId;
+ }
+ set
+ {
+ _currentLayoutId = value;
+
+ if (_scheduleManager != null)
+ _scheduleManager.CurrentLayoutId = _currentLayoutId;
+ }
+ }
+ private int _currentLayoutId;
+
private bool _forceChange = false;
///
@@ -85,13 +104,9 @@ class Schedule
private RegisterAgent _registerAgent;
Thread _registerAgentThread;
- // Schedule Agent
- private ScheduleAgent _scheduleAgent;
- Thread _scheduleAgentThread;
-
// Required Files Agent
- private RequiredFilesAgent _requiredFilesAgent;
- Thread _requiredFilesAgentThread;
+ private ScheduleAndFilesAgent _scheduleAndRfAgent;
+ Thread _scheduleAndRfAgentThread;
// Library Agent
private LibraryAgent _libraryAgent;
@@ -154,28 +169,19 @@ public Schedule(string scheduleLocation, ref CacheManager cacheManager, ref Clie
_scheduleManagerThread = new Thread(new ThreadStart(_scheduleManager.Run));
_scheduleManagerThread.Name = "ScheduleManagerThread";
- // Create a Schedule Agent
- _scheduleAgent = new ScheduleAgent();
- _scheduleAgent.CurrentScheduleManager = _scheduleManager;
- _scheduleAgent.ScheduleLocation = scheduleLocation;
- _scheduleAgent.HardwareKey = _hardwareKey.Key;
- _scheduleAgent.ClientInfoForm = _clientInfoForm;
-
- // Create a thread for the Schedule Agent to run in - but dont start it up yet.
- _scheduleAgentThread = new Thread(new ThreadStart(_scheduleAgent.Run));
- _scheduleAgentThread.Name = "ScheduleAgentThread";
-
// Create a RequiredFilesAgent
- _requiredFilesAgent = new RequiredFilesAgent();
- _requiredFilesAgent.CurrentCacheManager = cacheManager;
- _requiredFilesAgent.HardwareKey = _hardwareKey.Key;
- _requiredFilesAgent.ClientInfoForm = _clientInfoForm;
- _requiredFilesAgent.OnComplete += new RequiredFilesAgent.OnCompleteDelegate(LayoutFileModified);
- _requiredFilesAgent.OnFullyProvisioned += _requiredFilesAgent_OnFullyProvisioned;
+ _scheduleAndRfAgent = new ScheduleAndFilesAgent();
+ _scheduleAndRfAgent.CurrentCacheManager = cacheManager;
+ _scheduleAndRfAgent.CurrentScheduleManager = _scheduleManager;
+ _scheduleAndRfAgent.ScheduleLocation = scheduleLocation;
+ _scheduleAndRfAgent.HardwareKey = _hardwareKey.Key;
+ _scheduleAndRfAgent.OnFullyProvisioned += _requiredFilesAgent_OnFullyProvisioned;
+ _scheduleAndRfAgent.ClientInfoForm = _clientInfoForm;
+ _scheduleAndRfAgent.OnComplete += new ScheduleAndFilesAgent.OnCompleteDelegate(LayoutFileModified);
// Create a thread for the RequiredFiles Agent to run in - but dont start it up yet.
- _requiredFilesAgentThread = new Thread(new ThreadStart(_requiredFilesAgent.Run));
- _requiredFilesAgentThread.Name = "RequiredFilesAgentThread";
+ _scheduleAndRfAgentThread = new Thread(new ThreadStart(_scheduleAndRfAgent.Run));
+ _scheduleAndRfAgentThread.Name = "RequiredFilesAgentThread";
// Library Agent
_libraryAgent = new LibraryAgent();
@@ -216,11 +222,8 @@ public void InitializeComponents()
// Start the RegisterAgent thread
_registerAgentThread.Start();
- // Start the ScheduleAgent thread
- _scheduleAgentThread.Start();
-
// Start the RequiredFilesAgent thread
- _requiredFilesAgentThread.Start();
+ _scheduleAndRfAgentThread.Start();
// Start the ScheduleManager thread
_scheduleManagerThread.Start();
@@ -270,13 +273,29 @@ void _scheduleManager_OnRefreshSchedule()
///
void _scheduleManager_OnScheduleManagerCheckComplete()
{
+ if (agentThreadsAlive())
+ {
+ // Update status marker on the main thread.
+ _clientInfoForm.UpdateStatusMarkerFile();
+ }
+ else
+ {
+ Trace.WriteLine(new LogMessage("Schedule - OnScheduleManagerCheckComplete", "Agent threads are dead, not updating status.json"), LogType.Error.ToString());
+ }
+
try
{
// See if XMR should be running
if (!string.IsNullOrEmpty(ApplicationSettings.Default.XmrNetworkAddress) && _xmrSubscriber.LastHeartBeat != DateTime.MinValue)
{
+ // Log when severly overdue a check
+ if (_xmrSubscriber.LastHeartBeat < DateTime.Now.AddHours(-1))
+ {
+ Trace.WriteLine(new LogMessage("Schedule - OnScheduleManagerCheckComplete", "XMR heart beat last received over an hour ago."));
+ }
+
// Check to see if the last update date was over 5 minutes ago
- if (_xmrSubscriber.LastHeartBeat < DateTime.Now.AddSeconds(-90))
+ if (_xmrSubscriber.LastHeartBeat < DateTime.Now.AddMinutes(-5))
{
// Reconfigure it
_registerAgent_OnXmrReconfigure();
@@ -288,6 +307,18 @@ void _scheduleManager_OnScheduleManagerCheckComplete()
Trace.WriteLine(new LogMessage("Schedule - OnScheduleManagerCheckComplete", "Error = " + e.Message), LogType.Error.ToString());
}
}
+
+ ///
+ /// Are all the required agent threads alive?
+ ///
+ ///
+ private bool agentThreadsAlive()
+ {
+ return _registerAgentThread.IsAlive &&
+ _scheduleAndRfAgentThread.IsAlive &&
+ _logAgentThread.IsAlive &&
+ _libraryAgentThread.IsAlive;
+ }
///
/// XMR Reconfigure
@@ -398,8 +429,7 @@ private void _requiredFilesAgent_OnFullyProvisioned()
public void wakeUpXmds()
{
_registerAgent.WakeUp();
- _scheduleAgent.WakeUp();
- _requiredFilesAgent.WakeUp();
+ _scheduleAndRfAgent.WakeUp();
_logAgent.WakeUp();
}
@@ -493,7 +523,22 @@ private void LayoutFileModified(string layoutPath)
if (_layoutSchedule[_currentLayout].layoutFile == ApplicationSettings.Default.LibraryPath + @"\" + layoutPath)
{
// What happens if the action of downloading actually invalidates this layout?
- if (!_cacheManager.IsValidLayout(layoutPath))
+ bool valid = _cacheManager.IsValidPath(layoutPath);
+
+ if (valid)
+ {
+ // Check dependents
+ foreach (string dependent in _layoutSchedule[_currentLayout].Dependents)
+ {
+ if (!string.IsNullOrEmpty(dependent) && !_cacheManager.IsValidPath(dependent))
+ {
+ valid = false;
+ break;
+ }
+ }
+ }
+
+ if (!valid)
{
Trace.WriteLine(new LogMessage("Schedule - LayoutFileModified", "The current layout is now invalid, refreshing the current schedule."), LogType.Audit.ToString());
@@ -541,11 +586,8 @@ public void Stop()
// Stop the register agent
_registerAgent.Stop();
- // Stop the schedule agent
- _scheduleAgent.Stop();
-
// Stop the requiredfiles agent
- _requiredFilesAgent.Stop();
+ _scheduleAndRfAgent.Stop();
// Stop the Schedule Manager Thread
_scheduleManager.Stop();
diff --git a/Logic/ScheduleItem.cs b/Logic/ScheduleItem.cs
index f0ee286c..6fb4614d 100644
--- a/Logic/ScheduleItem.cs
+++ b/Logic/ScheduleItem.cs
@@ -24,5 +24,32 @@ public class ScheduleItem
public DateTime ToDt;
public List Dependents = new List();
+
+ ///
+ /// ToString
+ ///
+ ///
+ public override string ToString()
+ {
+ return string.Format("[{0}] From {1} to {2} with priority {3}. {4} dependents.", id, FromDt.ToString(), ToDt.ToString(), Priority, Dependents.Count);
+ }
+
+ public override int GetHashCode()
+ {
+ return id + scheduleid;
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (obj == null || GetType() != obj.GetType())
+ return false;
+
+ ScheduleItem compare = obj as ScheduleItem;
+
+ return id == compare.id &&
+ scheduleid == compare.scheduleid &&
+ FromDt.Ticks == compare.FromDt.Ticks &&
+ ToDt.Ticks == compare.ToDt.Ticks;
+ }
}
}
diff --git a/Logic/ScheduleManager.cs b/Logic/ScheduleManager.cs
index 45a24207..f4d1c4d4 100644
--- a/Logic/ScheduleManager.cs
+++ b/Logic/ScheduleManager.cs
@@ -75,6 +75,11 @@ class ScheduleManager
private bool _refreshSchedule;
private CacheManager _cacheManager;
private DateTime _lastScreenShotDate;
+
+ ///
+ /// The currently playing layout Id
+ ///
+ private int _currenctLayoutId;
///
/// Client Info Form
@@ -152,6 +157,22 @@ public Collection CurrentOverlaySchedule
return _currentOverlaySchedule;
}
}
+
+ ///
+ /// Get or Set the current layout id
+ ///
+ public int CurrentLayoutId
+ {
+ get
+ {
+ return _currenctLayoutId;
+ }
+ set
+ {
+ lock (_locker)
+ _currenctLayoutId = value;
+ }
+ }
#endregion
@@ -235,7 +256,8 @@ public void Run()
}
// Write a flag to the status.xml file
- File.WriteAllText(Path.Combine(ApplicationSettings.Default.LibraryPath, "status.json"), "{\"lastActivity\":\"" + DateTime.Now.ToString() + "\"}");
+ if (OnScheduleManagerCheckComplete != null)
+ OnScheduleManagerCheckComplete();
}
catch (Exception ex)
{
@@ -314,13 +336,30 @@ private bool IsNewScheduleAvailable()
if (_currentSchedule.Count == 0)
forceChange = true;
+ // Log
+ List currentScheduleString = new List();
+ List newScheduleString = new List();
+
// Are all the items that were in the _currentSchedule still there?
foreach (ScheduleItem layout in _currentSchedule)
{
if (!newSchedule.Contains(layout))
+ {
+ Trace.WriteLine(new LogMessage("ScheduleManager - IsNewScheduleAvailable", "New Schedule does not contain " + layout.id), LogType.Audit.ToString());
forceChange = true;
+ }
+ currentScheduleString.Add(layout.ToString());
+ }
+
+ foreach (ScheduleItem layout in _currentSchedule)
+ {
+ newScheduleString.Add(layout.ToString());
}
+ Trace.WriteLine(new LogMessage("ScheduleManager - IsNewScheduleAvailable", "Layouts in Current Schedule: " + string.Join(Environment.NewLine, currentScheduleString)), LogType.Audit.ToString());
+ Trace.WriteLine(new LogMessage("ScheduleManager - IsNewScheduleAvailable", "Layouts in New Schedule: " + string.Join(Environment.NewLine, newScheduleString)), LogType.Audit.ToString());
+
+
// Are all the items that were in the _currentOverlaySchedule still there?
foreach (ScheduleItem layout in _currentOverlaySchedule)
{
@@ -328,6 +367,7 @@ private bool IsNewScheduleAvailable()
forceChange = true;
}
+
// Set the new schedule
_currentSchedule = newSchedule;
@@ -374,11 +414,17 @@ private Collection LoadNewSchedule()
// If we haven't already assessed this layout before, then check that it is valid
if (!validLayoutIds.Contains(layout.id))
+ {
+ if (!ApplicationSettings.Default.ExpireModifiedLayouts && layout.id == CurrentLayoutId)
+ {
+ Trace.WriteLine(new LogMessage("ScheduleManager - LoadNewSchedule", "Skipping validity test for current layout."), LogType.Audit.ToString());
+ }
+ else
{
// Is the layout valid in the cachemanager?
try
{
- if (!_cacheManager.IsValidLayout(layout.id + ".xlf"))
+ if (!_cacheManager.IsValidPath(layout.id + ".xlf"))
{
invalidLayouts.Add(layout.id);
Trace.WriteLine(new LogMessage("ScheduleManager - LoadNewSchedule", "Layout invalid: " + layout.id), LogType.Info.ToString());
@@ -394,15 +440,22 @@ private Collection LoadNewSchedule()
}
// Check dependents
+ bool validDependents = true;
foreach (string dependent in layout.Dependents)
{
- if (!_cacheManager.IsValidPath(dependent))
+ if (!string.IsNullOrEmpty(dependent) && !_cacheManager.IsValidPath(dependent))
{
invalidLayouts.Add(layout.id);
Trace.WriteLine(new LogMessage("ScheduleManager - LoadNewSchedule", "Layout has invalid dependent: " + dependent), LogType.Info.ToString());
- continue;
+
+ validDependents = false;
+ break;
}
}
+
+ if (!validDependents)
+ continue;
+ }
}
// Add to the valid layout ids
@@ -494,7 +547,7 @@ private Collection LoadNewOverlaySchedule()
// Is the layout valid in the cachemanager?
try
{
- if (!_cacheManager.IsValidLayout(layout.id + ".xlf"))
+ if (!_cacheManager.IsValidPath(layout.id + ".xlf"))
{
invalidLayouts.Add(layout.id);
Trace.WriteLine(new LogMessage("ScheduleManager - LoadNewOverlaySchedule", "Layout invalid: " + layout.id), LogType.Info.ToString());
@@ -659,6 +712,15 @@ private ScheduleItem ParseNodeIntoScheduleItem(XmlNode node)
temp.layoutFile = ApplicationSettings.Default.LibraryPath + @"\" + layoutFile + @".xlf";
temp.id = int.Parse(layoutFile);
+ // Dependents
+ if (attributes["dependents"] != null && !string.IsNullOrEmpty(attributes["dependents"].Value))
+ {
+ foreach (string dependent in attributes["dependents"].Value.Split(','))
+ {
+ temp.Dependents.Add(dependent);
+ }
+ }
+
// Get attributes that only exist on the default
if (temp.NodeName != "default")
{
@@ -682,7 +744,6 @@ private ScheduleItem ParseNodeIntoScheduleItem(XmlNode node)
// Add it to the layout schedule
if (scheduleId != "") temp.scheduleid = int.Parse(scheduleId);
-
// Dependents
if (attributes["dependents"] != null)
{
diff --git a/MainForm.Designer.cs b/MainForm.Designer.cs
index 3b16c1a4..fff83877 100644
--- a/MainForm.Designer.cs
+++ b/MainForm.Designer.cs
@@ -44,7 +44,7 @@ private void InitializeComponent()
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
this.Icon = System.Drawing.Icon.ExtractAssociatedIcon(Application.ExecutablePath);
this.Name = "MainForm";
- this.Text = "Xibo Client";
+ this.Text = Application.ProductName;
this.WindowState = System.Windows.Forms.FormWindowState.Maximized;
this.Load += new System.EventHandler(this.MainForm_Load);
this.ResumeLayout(false);
diff --git a/MainForm.cs b/MainForm.cs
index bb09667c..86fbfbfa 100644
--- a/MainForm.cs
+++ b/MainForm.cs
@@ -1,6 +1,6 @@
/*
* Xibo - Digitial Signage - http://www.xibo.org.uk
- * Copyright (C) 2006-15 Daniel Garner
+ * Copyright (C) 2006-16 Daniel Garner
*
* This file is part of Xibo.
*
@@ -39,6 +39,7 @@
using System.Globalization;
using XiboClient.Logic;
using XiboClient.Control;
+using XiboClient.Error;
namespace XiboClient
{
@@ -324,7 +325,7 @@ void MainForm_Shown(object sender, EventArgs e)
_schedule = new Schedule(ApplicationSettings.Default.LibraryPath + @"\" + ApplicationSettings.Default.ScheduleFile, ref _cacheManager, ref _clientInfoForm);
// Bind to the schedule change event - notifys of changes to the schedule
- _schedule.ScheduleChangeEvent += new Schedule.ScheduleChangeDelegate(schedule_ScheduleChangeEvent);
+ _schedule.ScheduleChangeEvent += ScheduleChangeEvent;
// Bind to the overlay change event
_schedule.OverlayChangeEvent += ScheduleOverlayChangeEvent;
@@ -446,7 +447,7 @@ private void SetCacheManager()
/// Handles the ScheduleChange event
///
///
- void schedule_ScheduleChangeEvent(string layoutPath, int scheduleId, int layoutId)
+ void ScheduleChangeEvent(string layoutPath, int scheduleId, int layoutId)
{
Trace.WriteLine(new LogMessage("MainForm - ScheduleChangeEvent", string.Format("Schedule Changing to {0}", layoutPath)), LogType.Audit.ToString());
@@ -517,6 +518,11 @@ private void ChangeToNextLayout(string layoutPath)
PrepareLayout(layoutPath);
_clientInfoForm.CurrentLayoutId = layoutPath;
+ _schedule.CurrentLayoutId = _layoutId;
+ }
+ catch (DefaultLayoutException)
+ {
+ throw;
}
catch (Exception e)
{
@@ -547,7 +553,8 @@ private void ChangeToNextLayout(string layoutPath)
}
catch (Exception ex)
{
- Trace.WriteLine(new LogMessage("MainForm - ChangeToNextLayout", "Layout Change to " + layoutPath + " failed. Exception raised was: " + ex.Message), LogType.Error.ToString());
+ if (!(ex is DefaultLayoutException))
+ Trace.WriteLine(new LogMessage("MainForm - ChangeToNextLayout", "Layout Change to " + layoutPath + " failed. Exception raised was: " + ex.Message), LogType.Error.ToString());
if (!_showingSplash)
ShowSplashScreen();
@@ -593,7 +600,7 @@ private void PrepareLayout(string layoutPath)
// Default or not
if (layoutPath == ApplicationSettings.Default.LibraryPath + @"\Default.xml" || String.IsNullOrEmpty(layoutPath))
{
- throw new Exception("Default layout");
+ throw new DefaultLayoutException();
}
else
{
@@ -613,6 +620,7 @@ private void PrepareLayout(string layoutPath)
}
catch (IOException ioEx)
{
+ _cacheManager.Remove(layoutPath);
Trace.WriteLine(new LogMessage("MainForm - PrepareLayout", "IOException: " + ioEx.ToString()), LogType.Error.ToString());
throw;
}
@@ -686,7 +694,7 @@ private void PrepareLayout(string layoutPath)
GenerateBackgroundImage(layoutAttributes["background"].Value, backgroundWidth, backgroundHeight, bgFilePath);
BackgroundImage = new Bitmap(bgFilePath);
- options.backgroundImage = bgFilePath;
+ options.backgroundImage = @"/backgrounds/" + backgroundWidth + "x" + backgroundHeight + "_" + layoutAttributes["background"].Value; ;
}
else
{
@@ -752,6 +760,20 @@ private void PrepareLayout(string layoutPath)
continue;
}
+ // Region loop setting
+ options.RegionLoop = false;
+
+ XmlNode regionOptionsNode = region.SelectSingleNode("options");
+
+ if (regionOptionsNode != null)
+ {
+ foreach (XmlNode option in regionOptionsNode.ChildNodes)
+ {
+ if (option.Name == "loop" && option.InnerText == "1")
+ options.RegionLoop = true;
+ }
+ }
+
//each region
XmlAttributeCollection nodeAttibutes = region.Attributes;
@@ -797,9 +819,6 @@ private void PrepareLayout(string layoutPath)
// We have loaded a layout and therefore are no longer showing the splash screen
_showingSplash = false;
- // We have loaded a layout and therefore are no longer showing the splash screen
- _showingSplash = false;
-
// Null stuff
listRegions = null;
listMedia = null;
diff --git a/Media/Flash.cs b/Media/Flash.cs
index 032053e2..5329b423 100644
--- a/Media/Flash.cs
+++ b/Media/Flash.cs
@@ -92,6 +92,7 @@ private void GenerateHeadHtml()
}
else
{
+ string bgImage = ApplicationSettings.Default.LibraryPath + @"/" + _backgroundImage;
bodyStyle = "background-image: url('" + _backgroundImage + "'); background-attachment:fixed; background-color:" + _backgroundColor + " background-repeat: no-repeat; background-position: " + _backgroundLeft + " " + _backgroundTop + ";";
}
diff --git a/Media/IeWebMedia.cs b/Media/IeWebMedia.cs
index f162fc6c..96b15a55 100644
--- a/Media/IeWebMedia.cs
+++ b/Media/IeWebMedia.cs
@@ -1,6 +1,6 @@
/*
* Xibo - Digitial Signage - http://www.xibo.org.uk
- * Copyright (C) 2014 Spring Signage Ltd
+ * Copyright (C) 2014-2016 Spring Signage Ltd
*
* This file is part of Xibo.
*
@@ -264,7 +264,7 @@ private void xmds_GetResourceCompleted(object sender, XiboClient.xmds.GetResourc
}
else
{
- 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;";
+ bodyStyle = "background-image: url('" + _options.backgroundImage + "'); background-attachment:fixed; background-color:" + backgroundColor + "; background-repeat: no-repeat; background-position: " + _options.backgroundLeft + "px " + _options.backgroundTop + "px;";
}
string html = cachedFile.Replace("", "");
@@ -336,7 +336,7 @@ private void UpdateCacheIfNecessary()
}
else
{
- 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;";
+ bodyStyle = "background-image: url('" + _options.backgroundImage + "'); background-attachment:fixed; background-color:" + backgroundColor + "; background-repeat: no-repeat; background-position: " + _options.backgroundLeft + "px " + _options.backgroundTop + "px;";
}
string html = cachedFile.Replace("", "");
@@ -378,9 +378,9 @@ protected override void Dispose(bool disposing)
_webBrowser.Navigate("about:blank");
_webBrowser.Dispose();
}
- catch
+ catch (Exception e)
{
- Debug.WriteLine(new LogMessage("WebBrowser still in use.", String.Format("Dispose")));
+ Trace.WriteLine(new LogMessage("IeWebMedia - Dispose", "Cannot dispose of web browser. E = " + e.Message), LogType.Info.ToString());
}
}
diff --git a/Media/ShellCommand.cs b/Media/ShellCommand.cs
index 423b67bb..34e9a833 100644
--- a/Media/ShellCommand.cs
+++ b/Media/ShellCommand.cs
@@ -1,6 +1,6 @@
/*
* Xibo - Digitial Signage - http://www.xibo.org.uk
- * Copyright (C) 2012 Daniel Garner
+ * Copyright (C) 2012-16 Daniel Garner
*
* This file is part of Xibo.
*
@@ -30,12 +30,23 @@ class ShellCommand : Media
{
string _command = "";
string _code = "";
+ bool _launchThroughCmd = true;
+ bool _terminateCommand = false;
+ bool _useTaskKill = false;
+ int _processId;
public ShellCommand(RegionOptions options)
: base(options.width, options.height, options.top, options.left)
{
_command = Uri.UnescapeDataString(options.Dictionary.Get("windowsCommand")).Replace('+', ' ');
_code = options.Dictionary.Get("commandCode");
+
+ // Default to launching through CMS for backwards compatiblity
+ _launchThroughCmd = (options.Dictionary.Get("launchThroughCmd", "1") == "1");
+
+ // Termination
+ _terminateCommand = (options.Dictionary.Get("terminateCommand") == "1");
+ _useTaskKill = (options.Dictionary.Get("useTaskkill") == "1");
}
public override void RenderMedia()
@@ -122,14 +133,88 @@ private void ExecuteShellCommand()
{
ProcessStartInfo startInfo = new ProcessStartInfo();
+ if (_launchThroughCmd)
+ {
+ startInfo.WindowStyle = ProcessWindowStyle.Hidden;
+ startInfo.FileName = "cmd.exe";
+ startInfo.Arguments = "/C " + _command;
+ }
+ else
+ {
+ // Split the command into a command string and arguments.
+ string[] splitCommand = _command.Split(new[] { ' ' }, 2);
+ startInfo.FileName = splitCommand[0];
+
+ if (splitCommand.Length > 1)
+ startInfo.Arguments = splitCommand[1];
+ }
+
+ process.StartInfo = startInfo;
+ process.Start();
+
+ // Grab the ID
+ _processId = process.Id;
+ }
+ }
+ }
+
+ ///
+ /// Terminates the shell command
+ ///
+ private void TerminateCommand()
+ {
+ Trace.WriteLine(new LogMessage("ShellCommand - TerminateCommand", _command), LogType.Info.ToString());
+
+ if (_processId == 0)
+ {
+ Trace.WriteLine(new LogMessage("ShellCommand - TerminateCommand", "ProcessID empty for command: " + _command), LogType.Error.ToString());
+ return;
+ }
+
+ if (_useTaskKill)
+ {
+ using (Process process = new Process())
+ {
+ ProcessStartInfo startInfo = new ProcessStartInfo();
+
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
- startInfo.FileName = "cmd.exe";
- startInfo.Arguments = "/C " + _command;
+ startInfo.FileName = "taskkill.exe";
+ startInfo.Arguments = "/pid " + _processId.ToString();
process.StartInfo = startInfo;
process.Start();
}
}
+ else
+ {
+ using (Process process = Process.GetProcessById(_processId))
+ {
+ process.Kill();
+ }
+ }
+ }
+
+ ///
+ /// Dispose of this text item
+ ///
+ ///
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ // Remove the webbrowser control
+ try
+ {
+ // Terminate the command
+ TerminateCommand();
+ }
+ catch
+ {
+ Debug.WriteLine(new LogMessage("Unable to terminate command", "Dispose"));
+ }
+ }
+
+ base.Dispose(disposing);
}
}
}
diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs
index 63a5c671..bc48410b 100644
--- a/Properties/AssemblyInfo.cs
+++ b/Properties/AssemblyInfo.cs
@@ -30,6 +30,6 @@
// Build Number
// Revision
//
-[assembly: AssemblyVersion("2.0.0.0")]
-[assembly: AssemblyFileVersion("2.0.0.0")]
+[assembly: AssemblyVersion("10.8.0.1")]
+[assembly: AssemblyFileVersion("10.8.0.1")]
[assembly: NeutralResourcesLanguageAttribute("en-GB")]
diff --git a/XiboClient.csproj b/XiboClient.csproj
index 51aa8ee5..a3124782 100644
--- a/XiboClient.csproj
+++ b/XiboClient.csproj
@@ -80,28 +80,31 @@
false
-
- packages\AsyncIO.0.1.18.0\lib\net40\AsyncIO.dll
+
+ packages\AsyncIO.0.1.26.0\lib\net40\AsyncIO.dll
+ True
False
wmpdll\AxInterop.WMPLib.dll
False
-
- packages\BouncyCastle.1.7.0\lib\Net40-Client\BouncyCastle.Crypto.dll
+
+ packages\BouncyCastle.1.8.1\lib\BouncyCastle.Crypto.dll
+ True
False
False
wmpdll\Interop.WMPLib.dll
-
- packages\NetMQ.3.3.2.2\lib\net40\NetMQ.dll
+
+ packages\NetMQ.3.3.3.4\lib\net40\NetMQ.dll
+ True
-
- False
- packages\Newtonsoft.Json.8.0.3\lib\net40\Newtonsoft.Json.dll
+
+ packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll
+ True
@@ -112,8 +115,9 @@
-
- packages\EmbedIO.1.0.17\lib\Unosquare.Labs.EmbedIO.dll
+
+ packages\EmbedIO.1.0.24\lib\Unosquare.Labs.EmbedIO.dll
+ True
@@ -124,6 +128,7 @@
+
Form
@@ -256,8 +261,7 @@
-
-
+
@@ -340,4 +344,4 @@
-->
-
+
\ No newline at end of file
diff --git a/XmdsAgents/FileAgent.cs b/XmdsAgents/FileAgent.cs
index 068938d4..b6d13fce 100644
--- a/XmdsAgents/FileAgent.cs
+++ b/XmdsAgents/FileAgent.cs
@@ -295,6 +295,9 @@ public void Run()
}
catch (WebException webEx)
{
+ // Remove from the cache manager
+ _requiredFiles.CurrentCacheManager.Remove(file.SaveAs);
+
// Log this message, but dont abort the thread
Trace.WriteLine(new LogMessage("FileAgent - Run", "Web Exception in Run: " + webEx.Message), LogType.Info.ToString());
@@ -303,6 +306,9 @@ public void Run()
}
catch (Exception ex)
{
+ // Remove from the cache manager
+ _requiredFiles.CurrentCacheManager.Remove(file.SaveAs);
+
// Log this message, but dont abort the thread
Trace.WriteLine(new LogMessage("FileAgent - Run", "Exception in Run: " + ex.Message), LogType.Error.ToString());
diff --git a/XmdsAgents/RequiredFilesAgent.cs b/XmdsAgents/ScheduleAndFilesAgent.cs
similarity index 80%
rename from XmdsAgents/RequiredFilesAgent.cs
rename to XmdsAgents/ScheduleAndFilesAgent.cs
index 10f6eef0..1dd0eedc 100644
--- a/XmdsAgents/RequiredFilesAgent.cs
+++ b/XmdsAgents/ScheduleAndFilesAgent.cs
@@ -35,7 +35,7 @@
namespace XiboClient.XmdsAgents
{
- class RequiredFilesAgent
+ class ScheduleAndFilesAgent
{
private static object _locker = new object();
private bool _forceStop = false;
@@ -54,6 +54,30 @@ class RequiredFilesAgent
private RequiredFiles _requiredFiles;
private Semaphore _fileDownloadLimit;
+ ///
+ /// Current Schedule Manager for this Xibo Client
+ ///
+ public ScheduleManager CurrentScheduleManager
+ {
+ set
+ {
+ _scheduleManager = value;
+ }
+ }
+ private ScheduleManager _scheduleManager;
+
+ ///
+ /// Schedule File Location
+ ///
+ public string ScheduleLocation
+ {
+ set
+ {
+ _scheduleLocation = value;
+ }
+ }
+ private string _scheduleLocation;
+
///
/// Client Hardware key
///
@@ -93,7 +117,7 @@ public ClientInfo ClientInfoForm
///
/// Required Files Agent
///
- public RequiredFilesAgent()
+ public ScheduleAndFilesAgent()
{
_fileDownloadLimit = new Semaphore(ApplicationSettings.Default.MaxConcurrentDownloads, ApplicationSettings.Default.MaxConcurrentDownloads);
_requiredFiles = new RequiredFiles();
@@ -125,15 +149,18 @@ public void Run()
while (!_forceStop)
{
+ // If we are restarting, reset
+ _manualReset.Reset();
+
lock (_locker)
{
+ // Run the schedule Agent thread
+ scheduleAgent();
+
if (ApplicationSettings.Default.InDownloadWindow)
{
try
{
- // If we are restarting, reset
- _manualReset.Reset();
-
int filesToDownload = _requiredFiles.FilesDownloading;
// If we are currently downloading something, we have to wait
@@ -339,7 +366,7 @@ private void reportStorage()
{
using (xmds.xmds xmds = new xmds.xmds())
{
- string status = "{\"availableSpace\":\"" + drive.TotalFreeSpace + "\", \"totalSpace\":\"" + drive.TotalSize + "\"}";
+ string status = "{\"availableSpace\":\"" + drive.TotalFreeSpace + "\", \"totalSpace\":\"" + drive.TotalSize + "\", \"deviceName\":\"" + Environment.MachineName + "\"}";
xmds.Credentials = null;
xmds.Url = ApplicationSettings.Default.XiboClient_xmds_xmds;
@@ -351,5 +378,71 @@ private void reportStorage()
}
}
}
+
+ ///
+ /// Schedule Agent
+ ///
+ private void scheduleAgent()
+ {
+ try
+ {
+ // If we are restarting, reset
+ _manualReset.Reset();
+
+ Trace.WriteLine(new LogMessage("ScheduleAgent - Run", "Thread Woken and Lock Obtained"), LogType.Audit.ToString());
+
+ _clientInfoForm.ScheduleStatus = "Running: Get Data from Xibo Server";
+
+ using (xmds.xmds xmds = new xmds.xmds())
+ {
+ xmds.Credentials = null;
+ xmds.Url = ApplicationSettings.Default.XiboClient_xmds_xmds;
+ xmds.UseDefaultCredentials = false;
+
+ string scheduleXml = xmds.Schedule(ApplicationSettings.Default.ServerKey, _hardwareKey);
+
+ // Set the flag to indicate we have a connection to XMDS
+ ApplicationSettings.Default.XmdsLastConnection = DateTime.Now;
+
+ _clientInfoForm.ScheduleStatus = "Running: Data Received";
+
+ // Hash of the result
+ string md5NewSchedule = Hashes.MD5(scheduleXml);
+ string md5CurrentSchedule = Hashes.MD5(ScheduleManager.GetScheduleXmlString(_scheduleLocation));
+
+ // Compare the results of the HASH
+ if (md5CurrentSchedule != md5NewSchedule)
+ {
+ Trace.WriteLine(new LogMessage("Schedule Agent - Run", "Received new schedule"));
+
+ _clientInfoForm.ScheduleStatus = "Running: New Schedule Received";
+
+ // Write the result to the schedule xml location
+ ScheduleManager.WriteScheduleXmlToDisk(_scheduleLocation, scheduleXml);
+
+ // Indicate to the schedule manager that it should read the XML file
+ _scheduleManager.RefreshSchedule = true;
+ }
+
+ _clientInfoForm.ScheduleStatus = "Sleeping";
+ }
+ }
+ catch (WebException webEx)
+ {
+ // Increment the quantity of XMDS failures and bail out
+ ApplicationSettings.Default.IncrementXmdsErrorCount();
+
+ // Log this message, but dont abort the thread
+ Trace.WriteLine(new LogMessage("ScheduleAgent - Run", "WebException in Run: " + webEx.Message), LogType.Info.ToString());
+
+ _clientInfoForm.ScheduleStatus = "Error: " + webEx.Message;
+ }
+ catch (Exception ex)
+ {
+ // Log this message, but dont abort the thread
+ Trace.WriteLine(new LogMessage("ScheduleAgent - Run", "Exception in Run: " + ex.Message), LogType.Error.ToString());
+ _clientInfoForm.ScheduleStatus = "Error. " + ex.Message;
+ }
+ }
}
}
diff --git a/app.config b/app.config
index 878ccccc..d26435b2 100644
--- a/app.config
+++ b/app.config
@@ -1,17 +1,17 @@
-
+
-
+
-
-
+
+
-
+
diff --git a/bin/x86/Release/Xibo.scr b/bin/x86/Release/Xibo.scr
index 7c1d0045..b684ed6a 100644
Binary files a/bin/x86/Release/Xibo.scr and b/bin/x86/Release/Xibo.scr differ
diff --git a/packages.config b/packages.config
index 973b6881..0b43064f 100644
--- a/packages.config
+++ b/packages.config
@@ -1,8 +1,8 @@
-
-
-
-
-
+
+
+
+
+
\ No newline at end of file