=== modified file 'client/dotNET/CacheManager.cs'
--- client/dotNET/CacheManager.cs 2010-04-19 21:45:10 +0000
+++ client/dotNET/CacheManager.cs 2011-02-28 15:09:32 +0000
@@ -25,6 +25,7 @@
using System.Windows.Forms;
using System.Xml.Serialization;
using System.Diagnostics;
+using System.Xml;
namespace XiboClient
{
@@ -173,7 +174,7 @@
///
///
/// True is it is and false if it isnt
- public bool IsValid(String path)
+ public bool IsValidPath(String path)
{
// TODO: what makes a path valid?
// Currently a path is valid if it is in the cache
@@ -185,6 +186,10 @@
{
if (file.path == path)
{
+ // If we cached it over 2 minutes ago, then check the GetLastWriteTime
+ if (file.cacheDate > DateTime.Now.AddMinutes(-2))
+ return true;
+
try
{
// Check to see if this file has been modified since the MD5 cache
@@ -209,6 +214,75 @@
// Reached the end of the cache and havent found the file.
return false;
}
+
+ ///
+ /// Is the provided layout file a valid layout (has all media)
+ ///
+ ///
+ ///
+ public bool IsValidLayout(string layoutFile)
+ {
+ Debug.WriteLine("Checking Layout " + layoutFile + " is valid");
+
+ if (!IsValidPath(layoutFile))
+ return false;
+
+ // Load the XLF, get all media ID's
+ XmlDocument layoutXml = new XmlDocument();
+ layoutXml.Load(Properties.Settings.Default.LibraryPath + @"\" + layoutFile);
+
+ XmlNodeList mediaNodes = layoutXml.SelectNodes("//media");
+
+ foreach (XmlNode media in mediaNodes)
+ {
+ // Is this a stored media type?
+ switch (media.Attributes["type"].Value)
+ {
+ case "video":
+ case "image":
+ case "flash":
+ case "ppt":
+
+ // Get the path and see if its valid
+ if (!IsValidPath(media.InnerText))
+ return false;
+
+ break;
+
+ default:
+ continue;
+ }
+ }
+
+ return true;
+ }
+
+ ///
+ /// Regenerate from Required Files
+ ///
+ public void Regenerate()
+ {
+ if (!File.Exists(Application.UserAppDataPath + "\\" + Properties.Settings.Default.RequiredFilesFile))
+ return;
+
+ // Open the XML file and check each required file that isnt already there
+ XmlDocument xml = new XmlDocument();
+ xml.Load(Application.UserAppDataPath + "\\" + Properties.Settings.Default.RequiredFilesFile);
+
+ XmlNodeList fileNodes = xml.SelectNodes("//RequiredFile/Path");
+
+ foreach (XmlNode file in fileNodes)
+ {
+ string path = file.InnerText;
+
+ // Does the file exist?
+ if (!File.Exists(Properties.Settings.Default.LibraryPath + @"\" + path))
+ continue;
+
+ // Add this file to the cache manager
+ Add(path, GetMD5(path));
+ }
+ }
}
public struct Md5Resource
=== modified file 'client/dotNET/FileCollector.cs'
--- client/dotNET/FileCollector.cs 2011-01-30 18:13:32 +0000
+++ client/dotNET/FileCollector.cs 2011-02-28 15:09:32 +0000
@@ -31,28 +31,26 @@
class FileCollector
{
private CacheManager _cacheManager;
+ private RequiredFiles _requiredFiles;
+ private XmlDocument _xml;
public FileCollector(CacheManager cacheManager, string xmlString)
{
_cacheManager = cacheManager;
- xml = new XmlDocument();
+ // Load the XML file RF call
+ _xml = new XmlDocument();
+ _xml.LoadXml(xmlString);
- try
- {
- xml.LoadXml(xmlString);
- }
- catch (Exception e)
- {
- //Log this error
- System.Diagnostics.Debug.WriteLine(e.Message);
- }
+ // Create a required files object
+ _requiredFiles = new RequiredFiles();
+ _requiredFiles.RequiredFilesXml = _xml;
// Get the key for later use
hardwareKey = new HardwareKey();
// Make a new filelist collection
- files = new Collection();
+ _files = new Collection();
// Create a webservice call
xmdsFile = new XiboClient.xmds.xmds();
@@ -73,13 +71,13 @@
///
public void CompareAndCollect()
{
- XmlNodeList fileNodes = xml.SelectNodes("/files/file");
+ XmlNodeList fileNodes = _xml.SelectNodes("/files/file");
//Inspect each file we have here
foreach (XmlNode file in fileNodes)
{
XmlAttributeCollection attributes = file.Attributes;
- FileList fileList = new FileList();
+ RequiredFile fileList = new RequiredFile();
if (attributes["type"].Value == "layout")
{
@@ -120,13 +118,15 @@
fileList.md5 = attributes["md5"].Value;
fileList.retrys = 0;
- files.Add(fileList);
+ _files.Add(fileList);
}
else
{
// The MD5 of the current file and the MD5 in RequiredFiles are the same.
// Therefore make sure this MD5 is in the CacheManager
_cacheManager.Add(path + ".xlf", md5);
+
+ _requiredFiles.MarkComplete(int.Parse(path), md5);
}
}
else
@@ -141,7 +141,7 @@
fileList.md5 = attributes["md5"].Value;
fileList.retrys = 0;
- files.Add(fileList);
+ _files.Add(fileList);
}
}
else if (attributes["type"].Value == "media")
@@ -183,13 +183,16 @@
fileList.md5 = attributes["md5"].Value;
fileList.retrys = 0;
- files.Add(fileList);
+ _files.Add(fileList);
}
else
{
// The MD5 of the current file and the MD5 in RequiredFiles are the same.
// Therefore make sure this MD5 is in the CacheManager
_cacheManager.Add(path, md5);
+
+ string[] filePart = path.Split('.');
+ _requiredFiles.MarkComplete(int.Parse(filePart[0]), md5);
}
}
else
@@ -205,7 +208,7 @@
fileList.md5 = attributes["md5"].Value;
fileList.retrys = 0;
- files.Add(fileList);
+ _files.Add(fileList);
}
}
else if (attributes["type"].Value == "blacklist")
@@ -234,18 +237,24 @@
}
}
- Debug.WriteLine(String.Format("There are {0} files to get", files.Count.ToString()));
+ Debug.WriteLine(String.Format("There are {0} files to get", _files.Count.ToString()));
// Output a list of the files we need to get
string debugMessage = "";
- foreach (FileList fileToGet in files)
+ foreach (RequiredFile fileToGet in _files)
debugMessage += string.Format("File: {0}, Type: {1}, MD5: {2}. ", fileToGet.path, fileToGet.type, fileToGet.md5);
Debug.WriteLine(debugMessage);
+ // Report the files files back to XMDS
+ _requiredFiles.ReportInventory();
+
+ // Write Required Files
+ _requiredFiles.WriteRequiredFiles();
+
// Is there anything to get?
- if (files.Count == 0)
+ if (_files.Count == 0)
{
CollectionComplete();
return;
@@ -255,7 +264,7 @@
_currentFile = 0;
// Preload the first filelist
- _currentFileList = files[_currentFile];
+ _currentFileList = _files[_currentFile];
// Get the first file
GetFile();
@@ -375,6 +384,10 @@
{
// Add to the CacheManager
_cacheManager.Add(_currentFileList.path + ".xlf", md5sum);
+
+ // Report this completion back to XMDS
+ _requiredFiles.MarkComplete(int.Parse(_currentFileList.path), md5sum);
+ _requiredFiles.ReportInventory();
}
// Fire a layout complete event
@@ -445,6 +458,11 @@
System.Diagnostics.Debug.WriteLine(string.Format("File downloaded: {0}", _currentFileList.path));
+ // Report this completion back to XMDS
+ string[] filePart = _currentFileList.path.Split('.');
+ _requiredFiles.MarkComplete(int.Parse(filePart[0]), md5sum);
+ _requiredFiles.ReportInventory();
+
// All the file has been recieved. Move on to the next file.
_currentFile++;
}
@@ -475,13 +493,16 @@
///
public void GetFile()
{
- if (_currentFile > (files.Count - 1))
+ if (_currentFile > (_files.Count - 1))
{
- System.Diagnostics.Debug.WriteLine(String.Format("Finished Recieving {0} files", files.Count));
+ System.Diagnostics.Debug.WriteLine(String.Format("Finished Receiving {0} files", _files.Count));
// Clean up
- files.Clear();
- xmdsFile.Dispose();
+ _files.Clear();
+ xmdsFile.Dispose();
+
+ // Write Required Files
+ _requiredFiles.WriteRequiredFiles();
// Finished getting this file list
CollectionComplete();
@@ -491,7 +512,7 @@
// Get the current file into the currentfilelist if the current one is finished
if (_currentFileList.complete)
{
- _currentFileList = files[_currentFile];
+ _currentFileList = _files[_currentFile];
}
System.Diagnostics.Debug.WriteLine(String.Format("Getting the file : {0} chunk : {1}", _currentFileList.path, _currentFileList.chunkOffset.ToString()));
@@ -504,7 +525,7 @@
}
[Serializable]
- private struct FileList
+ private struct RequiredFile
{
public string path;
public string type;
@@ -519,9 +540,9 @@
private XmlDocument xml;
private HardwareKey hardwareKey;
- private Collection files;
+ private Collection _files;
private int _currentFile;
- private FileList _currentFileList;
+ private RequiredFile _currentFileList;
private xmds.xmds xmdsFile;
public event LayoutFileChangedDelegate LayoutFileChanged;
=== modified file 'client/dotNET/MainForm.cs'
--- client/dotNET/MainForm.cs 2011-01-30 18:13:32 +0000
+++ client/dotNET/MainForm.cs 2011-02-28 15:09:32 +0000
@@ -72,14 +72,45 @@
_statLog = new StatLog();
+ this.FormClosing += new FormClosingEventHandler(MainForm_FormClosing);
+ this.Shown += new EventHandler(MainForm_Shown);
+ }
+
+ ///
+ /// Called after the form has been shown
+ ///
+ ///
+ ///
+ void MainForm_Shown(object sender, EventArgs e)
+ {
+ // Process any stuff that has happened during the loading process
+ Application.DoEvents();
+
// Create a cachemanager
SetCacheManager();
- this.FormClosing += new FormClosingEventHandler(MainForm_FormClosing);
+ try
+ {
+ // Create the Schedule
+ _schedule = new Schedule(Application.UserAppDataPath + "\\" + Properties.Settings.Default.ScheduleFile, ref _cacheManager);
+
+ // Bind to the schedule change event - notifys of changes to the schedule
+ _schedule.ScheduleChangeEvent += new Schedule.ScheduleChangeDelegate(schedule_ScheduleChangeEvent);
+
+ // Initialize the other schedule components
+ _schedule.InitializeComponents();
+ }
+ catch (Exception ex)
+ {
+ Debug.WriteLine(ex.Message, LogType.Error.ToString());
+ MessageBox.Show("Fatal Error initialising the application", "Fatal Error");
+ Close();
+ Dispose();
+ }
}
///
- /// Called when the form has finished loading
+ /// Called before the form has loaded for the first time
///
///
///
@@ -96,30 +127,13 @@
Cursor.Position = new Point(_clientSize.Width, _clientSize.Height);
Cursor.Hide();
+ ShowSplashScreen();
+
// Change the default Proxy class
OptionForm.SetGlobalProxy();
// UserApp data
Debug.WriteLine(new LogMessage("MainForm_Load", "User AppData Path: " + Application.UserAppDataPath), LogType.Info.ToString());
-
- try
- {
- // Create the Schedule
- _schedule = new Schedule(Application.UserAppDataPath + "\\" + Properties.Settings.Default.ScheduleFile, ref _cacheManager);
-
- // Bind to the schedule change event - notifys of changes to the schedule
- _schedule.ScheduleChangeEvent += new Schedule.ScheduleChangeDelegate(schedule_ScheduleChangeEvent);
-
- // Initialize the other schedule components
- _schedule.InitializeComponents();
- }
- catch (Exception ex)
- {
- Debug.WriteLine(ex.Message, LogType.Error.ToString());
- MessageBox.Show("Fatal Error initialising the application", "Fatal Error");
- Close();
- Dispose();
- }
}
private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
@@ -152,11 +166,20 @@
}
catch (Exception ex)
{
- Trace.WriteLine(new LogMessage("Schedule", "Unable to reuse the Cache Manager because: " + ex.Message));
+ Trace.WriteLine(new LogMessage("MainForm - SetCacheManager", "Unable to reuse the Cache Manager because: " + ex.Message));
// Create a new cache manager
_cacheManager = new CacheManager();
}
+
+ try
+ {
+ _cacheManager.Regenerate();
+ }
+ catch (Exception ex)
+ {
+ Trace.WriteLine(new LogMessage("MainForm - SetCacheManager", "Regenerate failed because: " + ex.Message));
+ }
}
///
=== modified file 'client/dotNET/Properties/Settings.Designer.cs'
--- client/dotNET/Properties/Settings.Designer.cs 2011-02-14 16:21:56 +0000
+++ client/dotNET/Properties/Settings.Designer.cs 2011-02-28 15:09:32 +0000
@@ -271,7 +271,7 @@
[global::System.Configuration.ApplicationScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
- [global::System.Configuration.DefaultSettingValueAttribute("1.2.1")]
+ [global::System.Configuration.DefaultSettingValueAttribute("1.2.2")]
public string ClientVersion {
get {
return ((string)(this["ClientVersion"]));
@@ -370,5 +370,17 @@
this["emptyLayoutDuration"] = value;
}
}
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("requiredFiles.xml")]
+ public string RequiredFilesFile {
+ get {
+ return ((string)(this["RequiredFilesFile"]));
+ }
+ set {
+ this["RequiredFilesFile"] = value;
+ }
+ }
}
}
=== modified file 'client/dotNET/Properties/Settings.settings'
--- client/dotNET/Properties/Settings.settings 2011-02-14 16:21:56 +0000
+++ client/dotNET/Properties/Settings.settings 2011-02-28 15:09:32 +0000
@@ -69,7 +69,7 @@
cacheManager.xml
- 1.2.1
+ 1.2.21
@@ -95,5 +95,8 @@
10
+
+ requiredFiles.xml
+
\ No newline at end of file
=== modified file 'client/dotNET/Region.cs'
--- client/dotNET/Region.cs 2010-11-09 21:23:31 +0000
+++ client/dotNET/Region.cs 2011-02-28 15:09:32 +0000
@@ -310,12 +310,11 @@
}
// We cannot have a 0 duration here... not sure why we would... but
- if (options.duration == 0)
- options.duration = int.Parse(Properties.Settings.Default.emptyLayoutDuration.ToString());
-
- // Fail safe
- if (options.duration == 0)
- options.duration = 10;
+ if (options.duration == 0 && options.type != "video")
+ {
+ int emptyLayoutDuration = int.Parse(Properties.Settings.Default.emptyLayoutDuration.ToString());
+ options.duration = (emptyLayoutDuration == 0) ? 10 : emptyLayoutDuration;
+ }
// There will be some stuff on option nodes
XmlNode optionNode = mediaNode.FirstChild;
@@ -386,7 +385,7 @@
if (options.type == "video" || options.type == "flash" || options.type == "image" || options.type == "powerpoint")
{
// Use the cache manager to determine if the file is valid
- validNode = _cacheManager.IsValid(options.uri);
+ validNode = _cacheManager.IsValidPath(options.uri);
}
}
=== added file 'client/dotNET/RequiredFiles.cs'
--- client/dotNET/RequiredFiles.cs 1970-01-01 00:00:00 +0000
+++ client/dotNET/RequiredFiles.cs 2011-02-28 15:09:32 +0000
@@ -0,0 +1,206 @@
+/*
+ * Xibo - Digitial Signage - http://www.xibo.org.uk
+ * Copyright (C) 2011 Daniel Garner
+ *
+ * This file is part of Xibo.
+ *
+ * Xibo is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * any later version.
+ *
+ * Xibo is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with Xibo. If not, see .
+ */
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Text;
+using System.IO;
+using System.Security.Cryptography;
+using System.Xml;
+using System.Diagnostics;
+using System.Windows.Forms;
+using System.Xml.Serialization;
+
+namespace XiboClient
+{
+ public class RequiredFiles
+ {
+ private XmlDocument _requiredFilesXml;
+ public Collection _requiredFiles;
+ private xmds.xmds _report;
+
+ public RequiredFiles()
+ {
+ _requiredFiles = new Collection();
+
+ // Create a webservice call
+ _report = new XiboClient.xmds.xmds();
+
+ // Start up the Xmds Service Object
+ _report.Credentials = null;
+ _report.Url = Properties.Settings.Default.XiboClient_xmds_xmds;
+ _report.UseDefaultCredentials = false;
+ }
+
+ ///
+ /// Set required files from the XML document
+ ///
+ private void SetRequiredFiles()
+ {
+ // Itterate through the RF XML and populate the RF collection
+ XmlNodeList fileNodes = _requiredFilesXml.SelectNodes("/files/file");
+
+ foreach (XmlNode file in fileNodes)
+ {
+ RequiredFile rf = new RequiredFile();
+
+ XmlAttributeCollection attributes = file.Attributes;
+
+ rf.FileType = attributes["type"].Value;
+ rf.Complete = 0;
+ rf.Md5 = "";
+ rf.LastChecked = DateTime.Now;
+
+ if (rf.FileType == "media")
+ {
+ string[] filePart = attributes["path"].Value.Split('.');
+ rf.Id = int.Parse(filePart[0]);
+ rf.Path = attributes["path"].Value;
+ }
+ else if (rf.FileType == "layout")
+ {
+ rf.Id = int.Parse(attributes["path"].Value);
+ rf.Path = attributes["path"].Value + ".xlf";
+ }
+ else
+ {
+ continue;
+ }
+
+ _requiredFiles.Add(rf);
+ }
+ }
+
+ ///
+ /// Required Files XML
+ ///
+ public XmlDocument RequiredFilesXml
+ {
+ set
+ {
+ _requiredFilesXml = value;
+ SetRequiredFiles();
+ }
+ }
+
+ ///
+ /// Mark a RequiredFile as complete
+ ///
+ ///
+ ///
+ public void MarkComplete(int id, string md5)
+ {
+ foreach (RequiredFile rf in _requiredFiles)
+ {
+ if (rf.Id == id)
+ {
+ RequiredFile newRf = rf;
+
+ newRf.Complete = 1;
+ newRf.Md5 = md5;
+
+
+ _requiredFiles.Add(newRf);
+ _requiredFiles.Remove(rf);
+
+ return;
+ }
+ }
+ }
+
+ ///
+ /// Mark a RequiredFile as incomplete
+ ///
+ ///
+ ///
+ public void MarkIncomplete(int id, string md5)
+ {
+ foreach (RequiredFile rf in _requiredFiles)
+ {
+ if (rf.Id == id)
+ {
+ RequiredFile newRf = rf;
+
+ newRf.Complete = 0;
+ newRf.Md5 = md5;
+
+ _requiredFiles.Add(newRf);
+ _requiredFiles.Remove(rf);
+
+ return;
+ }
+ }
+ }
+
+ ///
+ /// Writes Required Files to disk
+ ///
+ public void WriteRequiredFiles()
+ {
+ Debug.WriteLine(new LogMessage("RequiredFiles - WriteRequiredFiles", "About to Write RequiredFiles"), LogType.Info.ToString());
+
+ try
+ {
+ using (StreamWriter streamWriter = new StreamWriter(Application.UserAppDataPath + "\\" + Properties.Settings.Default.RequiredFilesFile))
+ {
+ XmlSerializer xmlSerializer = new XmlSerializer(typeof(RequiredFiles));
+
+ xmlSerializer.Serialize(streamWriter, this);
+ }
+ }
+ catch (Exception ex)
+ {
+ System.Diagnostics.Trace.WriteLine(new LogMessage("RequiredFiles - WriteRequiredFiles", "Unable to write RequiredFiles to disk because: " + ex.Message));
+ }
+ }
+
+ ///
+ /// Report Required Files to XMDS
+ ///
+ public void ReportInventory()
+ {
+ HardwareKey hardwareKey = new HardwareKey();
+
+ // Build the XML required by media file
+ string xml = "";
+
+ foreach (RequiredFile rf in _requiredFiles)
+ {
+ xml += string.Format("",
+ rf.FileType, rf.Id.ToString(), rf.Complete.ToString(), rf.LastChecked.ToString(), rf.Md5);
+ }
+
+ xml = string.Format("{0}", xml);
+
+ _report.MediaInventoryAsync(Properties.Settings.Default.Version, Properties.Settings.Default.ServerKey,
+ hardwareKey.Key, xml);
+ }
+ }
+
+ public struct RequiredFile
+ {
+ public string FileType;
+ public int Id;
+ public int Complete;
+ public DateTime LastChecked;
+ public string Md5;
+ public string Path;
+ }
+}
=== modified file 'client/dotNET/Schedule.cs'
--- client/dotNET/Schedule.cs 2010-08-22 16:49:09 +0000
+++ client/dotNET/Schedule.cs 2011-02-28 15:09:32 +0000
@@ -74,7 +74,7 @@
_cacheManager = cacheManager;
// Create a schedule manager
- _scheduleManager = new ScheduleManager(scheduleLocation);
+ _scheduleManager = new ScheduleManager(_cacheManager, scheduleLocation);
// Create a new Xmds service object
_xmds2 = new XiboClient.xmds.xmds();
=== modified file 'client/dotNET/ScheduleManager.cs'
--- client/dotNET/ScheduleManager.cs 2010-08-25 21:39:53 +0000
+++ client/dotNET/ScheduleManager.cs 2011-02-28 15:09:32 +0000
@@ -42,13 +42,15 @@
private Collection _layoutSchedule;
private Collection _currentSchedule;
private bool _refreshSchedule;
+ private CacheManager _cacheManager;
///
/// Creates a new schedule Manager
///
///
- public ScheduleManager(string scheduleLocation)
+ public ScheduleManager(CacheManager cacheManager, string scheduleLocation)
{
+ _cacheManager = cacheManager;
_location = scheduleLocation;
// Create an empty layout schedule
@@ -178,6 +180,19 @@
// 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
+ {
+ if (!_cacheManager.IsValidLayout(layout.id + ".xlf"))
+ continue;
+ }
+ catch
+ {
+ // TODO: Ignore this layout.. raise an error?
+ Trace.WriteLine("Unable to determine if layout is valid or not");
+ continue;
+ }
+
// If this is the default, skip it
if (layout.NodeName == "default")
{
=== modified file 'client/dotNET/Web References/xmds/Reference.cs'
--- client/dotNET/Web References/xmds/Reference.cs 2010-11-09 21:23:31 +0000
+++ client/dotNET/Web References/xmds/Reference.cs 2011-02-28 15:09:32 +0000
@@ -45,6 +45,8 @@
private System.Threading.SendOrPostCallback SubmitStatsOperationCompleted;
+ private System.Threading.SendOrPostCallback MediaInventoryOperationCompleted;
+
private bool useDefaultCredentialsSetExplicitly;
///
@@ -108,6 +110,9 @@
public event SubmitStatsCompletedEventHandler SubmitStatsCompleted;
///
+ public event MediaInventoryCompletedEventHandler MediaInventoryCompleted;
+
+ ///
[System.Web.Services.Protocols.SoapRpcMethodAttribute("urn:xmds#RegisterDisplay", RequestNamespace="urn:xmds", ResponseNamespace="urn:xmds")]
[return: System.Xml.Serialization.SoapElementAttribute("ActivationMessage")]
public string RegisterDisplay(string serverKey, string hardwareKey, string displayName, string version) {
@@ -402,6 +407,42 @@
}
///
+ [System.Web.Services.Protocols.SoapRpcMethodAttribute("urn:xmds#MediaInventory", RequestNamespace="urn:xmds", ResponseNamespace="urn:xmds")]
+ [return: System.Xml.Serialization.SoapElementAttribute("success")]
+ public bool MediaInventory(string version, string serverKey, string hardwareKey, [System.Xml.Serialization.SoapElementAttribute("mediaInventory")] string mediaInventory1) {
+ object[] results = this.Invoke("MediaInventory", new object[] {
+ version,
+ serverKey,
+ hardwareKey,
+ mediaInventory1});
+ return ((bool)(results[0]));
+ }
+
+ ///
+ public void MediaInventoryAsync(string version, string serverKey, string hardwareKey, string mediaInventory1) {
+ this.MediaInventoryAsync(version, serverKey, hardwareKey, mediaInventory1, null);
+ }
+
+ ///
+ public void MediaInventoryAsync(string version, string serverKey, string hardwareKey, string mediaInventory1, object userState) {
+ if ((this.MediaInventoryOperationCompleted == null)) {
+ this.MediaInventoryOperationCompleted = new System.Threading.SendOrPostCallback(this.OnMediaInventoryOperationCompleted);
+ }
+ this.InvokeAsync("MediaInventory", new object[] {
+ version,
+ serverKey,
+ hardwareKey,
+ mediaInventory1}, this.MediaInventoryOperationCompleted, userState);
+ }
+
+ private void OnMediaInventoryOperationCompleted(object arg) {
+ if ((this.MediaInventoryCompleted != null)) {
+ System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg));
+ this.MediaInventoryCompleted(this, new MediaInventoryCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState));
+ }
+ }
+
+ ///
public new void CancelAsync(object userState) {
base.CancelAsync(userState);
}
@@ -627,6 +668,32 @@
}
}
}
+
+ ///
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "2.0.50727.4927")]
+ public delegate void MediaInventoryCompletedEventHandler(object sender, MediaInventoryCompletedEventArgs e);
+
+ ///
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "2.0.50727.4927")]
+ [System.Diagnostics.DebuggerStepThroughAttribute()]
+ [System.ComponentModel.DesignerCategoryAttribute("code")]
+ public partial class MediaInventoryCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs {
+
+ private object[] results;
+
+ internal MediaInventoryCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) :
+ base(exception, cancelled, userState) {
+ this.results = results;
+ }
+
+ ///
+ public bool Result {
+ get {
+ this.RaiseExceptionIfNecessary();
+ return ((bool)(this.results[0]));
+ }
+ }
+ }
}
#pragma warning restore 1591
\ No newline at end of file
=== modified file 'client/dotNET/Web References/xmds/xmds.wsdl'
--- client/dotNET/Web References/xmds/xmds.wsdl 2010-11-09 21:23:31 +0000
+++ client/dotNET/Web References/xmds/xmds.wsdl 2011-02-28 15:09:32 +0000
@@ -81,6 +81,15 @@
+
+
+
+
+
+
+
+
+ Registered the Display on the Xibo Network
@@ -122,6 +131,11 @@
+
+ Report back the clients MediaInventory
+
+
+
@@ -197,6 +211,15 @@
+
+
+
+
+
+
+
+
+
=== modified file 'client/dotNET/XiboClient.csproj'
--- client/dotNET/XiboClient.csproj 2011-02-09 17:15:43 +0000
+++ client/dotNET/XiboClient.csproj 2011-02-28 15:09:32 +0000
@@ -161,6 +161,7 @@
Component
+ Form
=== modified file 'client/dotNET/app.config'
--- client/dotNET/app.config 2011-02-14 16:21:56 +0000
+++ client/dotNET/app.config 2011-02-28 15:09:32 +0000
@@ -79,6 +79,9 @@
10
+
+ requiredFiles.xml
+
@@ -102,7 +105,7 @@
cacheManager.xml
- 1.2.1
+ 1.2.2900
=== modified file 'client/dotNET/bin/Release/AxInterop.ShockwaveFlashObjects.dll'
Binary files client/dotNET/bin/Release/AxInterop.ShockwaveFlashObjects.dll 2010-04-19 21:45:10 +0000 and client/dotNET/bin/Release/AxInterop.ShockwaveFlashObjects.dll 2011-02-28 15:09:32 +0000 differ
=== modified file 'client/dotNET/bin/Release/AxInterop.WMPLib.dll'
Binary files client/dotNET/bin/Release/AxInterop.WMPLib.dll 2010-04-19 21:45:10 +0000 and client/dotNET/bin/Release/AxInterop.WMPLib.dll 2011-02-28 15:09:32 +0000 differ
=== modified file 'client/dotNET/bin/Release/Interop.ShockwaveFlashObjects.dll'
Binary files client/dotNET/bin/Release/Interop.ShockwaveFlashObjects.dll 2010-04-19 21:45:10 +0000 and client/dotNET/bin/Release/Interop.ShockwaveFlashObjects.dll 2011-02-28 15:09:32 +0000 differ
=== modified file 'client/dotNET/bin/Release/Interop.WMPLib.dll'
Binary files client/dotNET/bin/Release/Interop.WMPLib.dll 2010-04-19 21:45:10 +0000 and client/dotNET/bin/Release/Interop.WMPLib.dll 2011-02-28 15:09:32 +0000 differ
=== modified file 'client/dotNET/bin/Release/XiboClient.exe.config'
--- client/dotNET/bin/Release/XiboClient.exe.config 2011-02-14 16:21:56 +0000
+++ client/dotNET/bin/Release/XiboClient.exe.config 2011-02-28 15:09:32 +0000
@@ -79,6 +79,9 @@
10
+
+ requiredFiles.xml
+
@@ -102,7 +105,7 @@
cacheManager.xml
- 1.2.1
+ 1.2.2900
=== modified file 'client/dotNET/bin/Release/XiboClient.vshost.exe.config'
--- client/dotNET/bin/Release/XiboClient.vshost.exe.config 2011-02-14 16:21:56 +0000
+++ client/dotNET/bin/Release/XiboClient.vshost.exe.config 2011-02-28 15:09:32 +0000
@@ -79,6 +79,9 @@
10
+
+ requiredFiles.xml
+
@@ -102,7 +105,7 @@
cacheManager.xml
- 1.2.1
+ 1.2.2900
=== added file 'server/install/database/27.sql'
--- server/install/database/27.sql 1970-01-01 00:00:00 +0000
+++ server/install/database/27.sql 2011-02-28 15:09:32 +0000
@@ -0,0 +1,9 @@
+
+ALTER TABLE `display` ADD `MediaInventoryStatus` TINYINT NOT NULL ,
+ADD `MediaInventoryXml` LONGTEXT NULL;
+
+/* VERSION UPDATE */
+/* Set the version table, etc */
+UPDATE `version` SET `app_ver` = '1.2.2-pre', `XmdsVersion` = 2;
+UPDATE `setting` SET `value` = 0 WHERE `setting` = 'PHONE_HOME_DATE';
+UPDATE `version` SET `DBVersion` = '27';
\ No newline at end of file
=== modified file 'server/lib/app/kit.class.php'
--- server/lib/app/kit.class.php 2010-12-01 14:49:39 +0000
+++ server/lib/app/kit.class.php 2011-02-28 15:09:32 +0000
@@ -376,9 +376,7 @@
static function ClassLoader($class)
{
if (class_exists($class))
- {
- return true;
- }
+ return;
$class = strtolower($class);
@@ -387,28 +385,26 @@
{
include_once('lib/pages/' . $class . '.class.php');
}
- elseif (file_exists('lib/data/' . $class . '.data.class.php'))
+
+ if (file_exists('lib/data/' . $class . '.data.class.php'))
{
include_once('lib/data/' . $class . '.data.class.php');
}
- elseif (file_exists('modules/' . $class . '.module.php'))
+
+ if (file_exists('modules/' . $class . '.module.php'))
{
include_once('modules/' . $class . '.module.php');
}
- elseif (file_exists('modules/' . $class . '.php'))
+
+ if (file_exists('modules/' . $class . '.php'))
{
include_once('modules/' . $class . '.php');
}
- elseif (file_exists('lib/service/' . $class . '.class.php'))
+
+ if (file_exists('lib/service/' . $class . '.class.php'))
{
include_once('lib/service/' . $class . '.class.php');
}
- else
- {
- return false;
- }
-
- return true;
}
/**
=== modified file 'server/lib/data/display.data.class.php'
--- server/lib/data/display.data.class.php 2011-02-10 20:42:24 +0000
+++ server/lib/data/display.data.class.php 2011-02-28 15:09:32 +0000
@@ -251,7 +251,7 @@
* @return
* @param $license Object
*/
- public function Touch($license, $clientAddress = '')
+ public function Touch($license, $clientAddress = '', $mediaInventoryComplete = 0, $mediaInventoryXml = '')
{
$db =& $this->db;
$time = time();
@@ -266,6 +266,13 @@
if ($clientAddress != '')
$SQL .= sprintf(" , ClientAddress = '%s' ", $db->escape_string($clientAddress));
+ // Media Inventory Settings (if appropriate)
+ if ($mediaInventoryComplete != 0)
+ $SQL .= sprintf(" , MediaInventoryStatus = %d ", $mediaInventoryComplete);
+
+ if ($mediaInventoryXml != '')
+ $SQL .= sprintf(" , MediaInventoryXml = '%s' ", $mediaInventoryXml);
+
// Restrict to the display license
$SQL .= " WHERE license = '%s'";
$SQL = sprintf($SQL, $time, $license);
@@ -284,31 +291,68 @@
}
/**
- * Edits the default layout for a display
+ * Flags a display as being incomplete
* @param $displayId
- * @param $defaultLayoutId
- * @return
*/
- public function EditDefaultLayout($displayId, $defaultLayoutId)
+ private function FlagIncomplete($displayId)
{
- $db =& $this->db;
-
- Debug::LogEntry($db, 'audit', 'IN', 'Display', 'EditDefaultLayout');
-
- $SQL = sprintf('UPDATE display SET defaultLayoutId = %d WHERE displayID = %d ', $defaultLayoutId, $displayId);
+ $db =& $this->db;
+
+ Debug::LogEntry($db, 'audit', sprintf('Flag DisplayID %d incomplete.', $displayId), 'display', 'NotifyDisplays');
+
+ $SQL = sprintf("UPDATE display SET MediaInventoryStatus = 3 WHERE displayID = %d", $displayId);
if (!$db->query($SQL))
{
trigger_error($db->error());
- $this->SetError(25012, __('Error updating this displays default layout.'));
-
- return false;
+ return $this->SetError(25004, 'Unable to Flag Display as incomplete');
}
-
- Debug::LogEntry($db, 'audit', 'OUT', 'Display', 'EditDefaultLayout');
-
return true;
}
+
+ /**
+ * Notify displays of this layout change
+ * @param $layoutId
+ */
+ public function NotifyDisplays($layoutId)
+ {
+ $db =& $this->db;
+ $currentdate = time();
+ $rfLookahead = Kit::ValidateParam(Config::GetSetting($db,'REQUIRED_FILES_LOOKAHEAD'), _INT);
+
+ $rfLookahead = $currentdate + $rfLookahead;
+
+ Debug::LogEntry($db, 'audit', sprintf('Checking for Displays to refresh on Layout %d', $layoutId), 'display', 'NotifyDisplays');
+
+ // Which displays does a change to this layout effect?
+ $SQL = " SELECT DISTINCT display.DisplayID ";
+ $SQL .= " FROM schedule_detail ";
+ $SQL .= " INNER JOIN lkdisplaydg ";
+ $SQL .= " ON lkdisplaydg.DisplayGroupID = schedule_detail.DisplayGroupID ";
+ $SQL .= " INNER JOIN display ";
+ $SQL .= " ON lkdisplaydg.DisplayID = display.displayID ";
+ $SQL .= " WHERE schedule_detail.layoutID = %d ";
+ $SQL .= " AND schedule_detail.FromDT < %d AND schedule_detail.ToDT > %d ";
+ $SQL .= " UNION ";
+ $SQL .= " SELECT DisplayID FROM display WHERE DefaultLayoutID = %d";
+
+ $SQL = sprintf($SQL, $layoutId, $rfLookahead, $currentdate - 3600, $layoutId);
+
+ Debug::LogEntry($db, 'audit', $SQL, 'display', 'NotifyDisplays');
+
+ if (!$result = $db->query($SQL))
+ {
+ trigger_error($db->error());
+ return $this->SetError(25037, __('Unable to get layouts for Notify'));
+ }
+
+ while ($row = $db->get_assoc_row($result))
+ {
+ // Notify each display in turn
+ $displayId = Kit::ValidateParam($row['DisplayID'], _INT);
+ $this->FlagIncomplete($displayId);
+ }
+ }
}
?>
=== modified file 'server/lib/data/schedule.data.class.php'
--- server/lib/data/schedule.data.class.php 2011-02-10 19:46:44 +0000
+++ server/lib/data/schedule.data.class.php 2011-02-28 15:09:32 +0000
@@ -164,6 +164,11 @@
}
}
}
+
+ // Notify (dont error)
+ Kit::ClassLoader('Display');
+ $displayObject = new Display($db);
+ $displayObject->NotifyDisplays($layoutID);
Debug::LogEntry($db, 'audit', 'OUT', 'Schedule', 'Add');
=== modified file 'server/lib/pages/display.class.php'
--- server/lib/pages/display.class.php 2011-02-13 17:16:01 +0000
+++ server/lib/pages/display.class.php 2011-02-28 15:09:32 +0000
@@ -37,6 +37,8 @@
private $email_alert;
private $alert_timeout;
private $ajax;
+ private $mediaInventoryStatus;
+ private $mediaInventoryXml;
function __construct(database $db, user $user)
{
@@ -71,7 +73,9 @@
display.isAuditing,
display.email_alert,
display.alert_timeout,
- display.ClientAddress
+ display.ClientAddress,
+ display.MediaInventoryStatus,
+ display.MediaInventoryXml
FROM display
WHERE display.displayid = %d
SQL;
@@ -95,8 +99,10 @@
$this->licensed = Kit::ValidateParam($row[4], _INT);
$this->inc_schedule = Kit::ValidateParam($row[5], _INT);
$this->auditing = Kit::ValidateParam($row[6], _INT);
- $this->email_alert = Kit::ValidateParam($row[7], _INT);
- $this->alert_timeout = Kit::ValidateParam($row[8], _INT);
+ $this->email_alert = Kit::ValidateParam($row[7], _INT);
+ $this->alert_timeout = Kit::ValidateParam($row[8], _INT);
+ $this->mediaInventoryStatus = Kit::ValidateParam($row[9], _INT);
+ $this->mediaInventoryXml = Kit::ValidateParam($row[10], _HTMLSTRING);
}
}
@@ -309,7 +315,12 @@
CASE WHEN display.licensed = 1 THEN '' ELSE '' END AS licensed,
CASE WHEN display.email_alert = 1 THEN '' ELSE '' END AS email_alert,
displaygroup.DisplayGroupID,
- display.ClientAddress
+ display.ClientAddress,
+ CASE WHEN display.MediaInventoryStatus = 1 THEN ''
+ WHEN display.MediaInventoryStatus = 2 THEN ''
+ ELSE ''
+ END AS MediaInventoryStatus,
+ display.MediaInventoryXml
FROM display
INNER JOIN lkdisplaydg ON lkdisplaydg.DisplayID = display.DisplayID
INNER JOIN displaygroup ON displaygroup.DisplayGroupID = lkdisplaydg.DisplayGroupID
@@ -341,6 +352,8 @@
$msgGroupSecurity = __('Group Security');
$msgClientAddress = __('IP Address');
$msgDefault = __('Default Layout');
+ $msgStatus = __('Status');
+ $msgMediaInventory = __('Media Inventory');
$output = <<
@@ -356,6 +369,7 @@
$msgLogIn
$msgLastA
$msgClientAddress
+
$msgStatus
$msgAction
@@ -385,6 +399,7 @@
// Do we want to make a VNC link out of the display name?
$vncTemplate = Config::GetSetting($db, 'SHOW_DISPLAY_AS_VNCLINK');
$linkTarget = Kit::ValidateParam(Config::GetSetting($db, 'SHOW_DISPLAY_AS_VNC_TGT'), _STRING);
+ $mediaInventoryStatusLight = Kit::ValidateParam($aRow[10], _STRING);
if ($vncTemplate != '' && $clientAddress != '')
{
@@ -424,6 +439,7 @@
$loggedin
$lastaccessed
$clientAddress
+
$mediaInventoryStatusLight
$buttons
END;
}
@@ -720,5 +736,59 @@
$response->SetFormSubmitResponse(__('Display Saved.'));
$response->Respond();
}
+
+ /**
+ * Shows the inventory XML for the display
+ */
+ public function MediaInventory()
+ {
+ $db =& $this->db;
+ $response = new ResponseManager();
+ $displayId = Kit::GetParam('DisplayId', _GET, _INT);
+
+ if ($displayId == 0)
+ trigger_error(__('No DisplayId Given'));
+
+ // Get the media inventory xml for this display
+ $SQL = "SELECT MediaInventoryXml FROM display WHERE DisplayId = %d";
+ $SQL = sprintf($SQL, $displayId);
+
+ if (!$mediaInventoryXml = $db->GetSingleValue($SQL, 'MediaInventoryXml', _HTMLSTRING))
+ {
+ trigger_error($db->error());
+ trigger_error(__('Unable to get the Inventory for this Display'), E_USER_ERROR);
+ }
+
+ // Load the XML into a DOMDocument
+ $document = new DOMDocument("1.0");
+
+ if (!$document->loadXML($mediaInventoryXml))
+ trigger_error(__('Invalid Media Inventory'), E_USER_ERROR);
+
+ // Output a table
+ $table = '