Merge lp:~alexharrington/xibo/pyclient-122-fix into lp:xibo/1.3

Proposed by Alex Harrington
Status: Merged
Merged at revision: 213
Proposed branch: lp:~alexharrington/xibo/pyclient-122-fix
Merge into: lp:xibo/1.3
Diff against target: 1962 lines (+1081/-176) (has conflicts)
27 files modified
client/dotNET/CacheManager.cs (+75/-1)
client/dotNET/FileCollector.cs (+60/-27)
client/dotNET/MainForm.cs (+45/-22)
client/dotNET/Properties/Settings.Designer.cs (+13/-1)
client/dotNET/Properties/Settings.settings (+4/-1)
client/dotNET/Region.cs (+11/-1)
client/dotNET/RequiredFiles.cs (+206/-0)
client/dotNET/Schedule.cs (+1/-1)
client/dotNET/ScheduleManager.cs (+16/-1)
client/dotNET/Web References/xmds/Reference.cs (+67/-0)
client/dotNET/Web References/xmds/xmds.wsdl (+23/-0)
client/dotNET/XiboClient.csproj (+1/-0)
client/dotNET/app.config (+4/-1)
client/dotNET/bin/Release/XiboClient.exe.config (+24/-3)
client/dotNET/bin/Release/XiboClient.vshost.exe.config (+24/-3)
client/python/XiboClient.py (+14/-0)
server/install/database/27.sql (+9/-0)
server/lib/app/kit.class.php (+3/-0)
server/lib/data/display.data.class.php (+134/-29)
server/lib/data/schedule.data.class.php (+5/-0)
server/lib/include.php (+3/-3)
server/lib/pages/display.class.php (+244/-81)
server/lib/pages/layout.class.php (+6/-0)
server/lib/pages/region.class.php (+5/-0)
server/lib/service/service.wsdl (+23/-0)
server/lib/service/xmdssoap.class.php (+60/-0)
server/modules/module_db_mysql.php (+1/-1)
Text conflict in client/dotNET/FileCollector.cs
Text conflict in client/dotNET/Region.cs
Text conflict in client/python/XiboClient.py
Text conflict in server/lib/app/kit.class.php
Text conflict in server/lib/data/display.data.class.php
Text conflict in server/lib/pages/display.class.php
To merge this branch: bzr merge lp:~alexharrington/xibo/pyclient-122-fix
Reviewer Review Type Date Requested Status
Xibo Maintainters Pending
Review via email: mp+52028@code.launchpad.net
To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'client/dotNET/CacheManager.cs'
2--- client/dotNET/CacheManager.cs 2010-04-19 21:45:10 +0000
3+++ client/dotNET/CacheManager.cs 2011-03-03 10:16:18 +0000
4@@ -25,6 +25,7 @@
5 using System.Windows.Forms;
6 using System.Xml.Serialization;
7 using System.Diagnostics;
8+using System.Xml;
9
10 namespace XiboClient
11 {
12@@ -173,7 +174,7 @@
13 /// </summary>
14 /// <param name="path"></param>
15 /// <returns>True is it is and false if it isnt</returns>
16- public bool IsValid(String path)
17+ public bool IsValidPath(String path)
18 {
19 // TODO: what makes a path valid?
20 // Currently a path is valid if it is in the cache
21@@ -185,6 +186,10 @@
22 {
23 if (file.path == path)
24 {
25+ // If we cached it over 2 minutes ago, then check the GetLastWriteTime
26+ if (file.cacheDate > DateTime.Now.AddMinutes(-2))
27+ return true;
28+
29 try
30 {
31 // Check to see if this file has been modified since the MD5 cache
32@@ -209,6 +214,75 @@
33 // Reached the end of the cache and havent found the file.
34 return false;
35 }
36+
37+ /// <summary>
38+ /// Is the provided layout file a valid layout (has all media)
39+ /// </summary>
40+ /// <param name="layoutFile"></param>
41+ /// <returns></returns>
42+ public bool IsValidLayout(string layoutFile)
43+ {
44+ Debug.WriteLine("Checking Layout " + layoutFile + " is valid");
45+
46+ if (!IsValidPath(layoutFile))
47+ return false;
48+
49+ // Load the XLF, get all media ID's
50+ XmlDocument layoutXml = new XmlDocument();
51+ layoutXml.Load(Properties.Settings.Default.LibraryPath + @"\" + layoutFile);
52+
53+ XmlNodeList mediaNodes = layoutXml.SelectNodes("//media");
54+
55+ foreach (XmlNode media in mediaNodes)
56+ {
57+ // Is this a stored media type?
58+ switch (media.Attributes["type"].Value)
59+ {
60+ case "video":
61+ case "image":
62+ case "flash":
63+ case "ppt":
64+
65+ // Get the path and see if its valid
66+ if (!IsValidPath(media.InnerText))
67+ return false;
68+
69+ break;
70+
71+ default:
72+ continue;
73+ }
74+ }
75+
76+ return true;
77+ }
78+
79+ /// <summary>
80+ /// Regenerate from Required Files
81+ /// </summary>
82+ public void Regenerate()
83+ {
84+ if (!File.Exists(Application.UserAppDataPath + "\\" + Properties.Settings.Default.RequiredFilesFile))
85+ return;
86+
87+ // Open the XML file and check each required file that isnt already there
88+ XmlDocument xml = new XmlDocument();
89+ xml.Load(Application.UserAppDataPath + "\\" + Properties.Settings.Default.RequiredFilesFile);
90+
91+ XmlNodeList fileNodes = xml.SelectNodes("//RequiredFile/Path");
92+
93+ foreach (XmlNode file in fileNodes)
94+ {
95+ string path = file.InnerText;
96+
97+ // Does the file exist?
98+ if (!File.Exists(Properties.Settings.Default.LibraryPath + @"\" + path))
99+ continue;
100+
101+ // Add this file to the cache manager
102+ Add(path, GetMD5(path));
103+ }
104+ }
105 }
106
107 public struct Md5Resource
108
109=== modified file 'client/dotNET/FileCollector.cs'
110--- client/dotNET/FileCollector.cs 2011-01-30 18:13:32 +0000
111+++ client/dotNET/FileCollector.cs 2011-03-03 10:16:18 +0000
112@@ -31,28 +31,26 @@
113 class FileCollector
114 {
115 private CacheManager _cacheManager;
116+ private RequiredFiles _requiredFiles;
117+ private XmlDocument _xml;
118
119 public FileCollector(CacheManager cacheManager, string xmlString)
120 {
121 _cacheManager = cacheManager;
122
123- xml = new XmlDocument();
124+ // Load the XML file RF call
125+ _xml = new XmlDocument();
126+ _xml.LoadXml(xmlString);
127
128- try
129- {
130- xml.LoadXml(xmlString);
131- }
132- catch (Exception e)
133- {
134- //Log this error
135- System.Diagnostics.Debug.WriteLine(e.Message);
136- }
137+ // Create a required files object
138+ _requiredFiles = new RequiredFiles();
139+ _requiredFiles.RequiredFilesXml = _xml;
140
141 // Get the key for later use
142 hardwareKey = new HardwareKey();
143
144 // Make a new filelist collection
145- files = new Collection<FileList>();
146+ _files = new Collection<RequiredFile>();
147
148 // Create a webservice call
149 xmdsFile = new XiboClient.xmds.xmds();
150@@ -73,13 +71,13 @@
151 /// </summary>
152 public void CompareAndCollect()
153 {
154- XmlNodeList fileNodes = xml.SelectNodes("/files/file");
155+ XmlNodeList fileNodes = _xml.SelectNodes("/files/file");
156
157 //Inspect each file we have here
158 foreach (XmlNode file in fileNodes)
159 {
160 XmlAttributeCollection attributes = file.Attributes;
161- FileList fileList = new FileList();
162+ RequiredFile fileList = new RequiredFile();
163
164 if (attributes["type"].Value == "layout")
165 {
166@@ -120,13 +118,15 @@
167 fileList.md5 = attributes["md5"].Value;
168 fileList.retrys = 0;
169
170- files.Add(fileList);
171+ _files.Add(fileList);
172 }
173 else
174 {
175 // The MD5 of the current file and the MD5 in RequiredFiles are the same.
176 // Therefore make sure this MD5 is in the CacheManager
177 _cacheManager.Add(path + ".xlf", md5);
178+
179+ _requiredFiles.MarkComplete(int.Parse(path), md5);
180 }
181 }
182 else
183@@ -141,7 +141,7 @@
184 fileList.md5 = attributes["md5"].Value;
185 fileList.retrys = 0;
186
187- files.Add(fileList);
188+ _files.Add(fileList);
189 }
190 }
191 else if (attributes["type"].Value == "media")
192@@ -183,13 +183,16 @@
193 fileList.md5 = attributes["md5"].Value;
194 fileList.retrys = 0;
195
196- files.Add(fileList);
197+ _files.Add(fileList);
198 }
199 else
200 {
201 // The MD5 of the current file and the MD5 in RequiredFiles are the same.
202 // Therefore make sure this MD5 is in the CacheManager
203 _cacheManager.Add(path, md5);
204+
205+ string[] filePart = path.Split('.');
206+ _requiredFiles.MarkComplete(int.Parse(filePart[0]), md5);
207 }
208 }
209 else
210@@ -205,7 +208,7 @@
211 fileList.md5 = attributes["md5"].Value;
212 fileList.retrys = 0;
213
214- files.Add(fileList);
215+ _files.Add(fileList);
216 }
217 }
218 else if (attributes["type"].Value == "blacklist")
219@@ -234,6 +237,7 @@
220 }
221 }
222
223+<<<<<<< TREE
224 Debug.WriteLine(String.Format("There are {0} files to get", files.Count.ToString()));
225
226 // Output a list of the files we need to get
227@@ -243,9 +247,26 @@
228 debugMessage += string.Format("File: {0}, Type: {1}, MD5: {2}. ", fileToGet.path, fileToGet.type, fileToGet.md5);
229
230 Debug.WriteLine(debugMessage);
231+=======
232+ Debug.WriteLine(String.Format("There are {0} files to get", _files.Count.ToString()));
233+
234+ // Output a list of the files we need to get
235+ string debugMessage = "";
236+
237+ foreach (RequiredFile fileToGet in _files)
238+ debugMessage += string.Format("File: {0}, Type: {1}, MD5: {2}. ", fileToGet.path, fileToGet.type, fileToGet.md5);
239+
240+ Debug.WriteLine(debugMessage);
241+
242+ // Report the files files back to XMDS
243+ _requiredFiles.ReportInventory();
244+
245+ // Write Required Files
246+ _requiredFiles.WriteRequiredFiles();
247+>>>>>>> MERGE-SOURCE
248
249 // Is there anything to get?
250- if (files.Count == 0)
251+ if (_files.Count == 0)
252 {
253 CollectionComplete();
254 return;
255@@ -255,7 +276,7 @@
256 _currentFile = 0;
257
258 // Preload the first filelist
259- _currentFileList = files[_currentFile];
260+ _currentFileList = _files[_currentFile];
261
262 // Get the first file
263 GetFile();
264@@ -375,6 +396,10 @@
265 {
266 // Add to the CacheManager
267 _cacheManager.Add(_currentFileList.path + ".xlf", md5sum);
268+
269+ // Report this completion back to XMDS
270+ _requiredFiles.MarkComplete(int.Parse(_currentFileList.path), md5sum);
271+ _requiredFiles.ReportInventory();
272 }
273
274 // Fire a layout complete event
275@@ -445,6 +470,11 @@
276
277 System.Diagnostics.Debug.WriteLine(string.Format("File downloaded: {0}", _currentFileList.path));
278
279+ // Report this completion back to XMDS
280+ string[] filePart = _currentFileList.path.Split('.');
281+ _requiredFiles.MarkComplete(int.Parse(filePart[0]), md5sum);
282+ _requiredFiles.ReportInventory();
283+
284 // All the file has been recieved. Move on to the next file.
285 _currentFile++;
286 }
287@@ -475,13 +505,16 @@
288 /// </summary>
289 public void GetFile()
290 {
291- if (_currentFile > (files.Count - 1))
292+ if (_currentFile > (_files.Count - 1))
293 {
294- System.Diagnostics.Debug.WriteLine(String.Format("Finished Recieving {0} files", files.Count));
295+ System.Diagnostics.Debug.WriteLine(String.Format("Finished Receiving {0} files", _files.Count));
296
297 // Clean up
298- files.Clear();
299- xmdsFile.Dispose();
300+ _files.Clear();
301+ xmdsFile.Dispose();
302+
303+ // Write Required Files
304+ _requiredFiles.WriteRequiredFiles();
305
306 // Finished getting this file list
307 CollectionComplete();
308@@ -491,7 +524,7 @@
309 // Get the current file into the currentfilelist if the current one is finished
310 if (_currentFileList.complete)
311 {
312- _currentFileList = files[_currentFile];
313+ _currentFileList = _files[_currentFile];
314 }
315
316 System.Diagnostics.Debug.WriteLine(String.Format("Getting the file : {0} chunk : {1}", _currentFileList.path, _currentFileList.chunkOffset.ToString()));
317@@ -504,7 +537,7 @@
318 }
319
320 [Serializable]
321- private struct FileList
322+ private struct RequiredFile
323 {
324 public string path;
325 public string type;
326@@ -519,9 +552,9 @@
327
328 private XmlDocument xml;
329 private HardwareKey hardwareKey;
330- private Collection<FileList> files;
331+ private Collection<RequiredFile> _files;
332 private int _currentFile;
333- private FileList _currentFileList;
334+ private RequiredFile _currentFileList;
335 private xmds.xmds xmdsFile;
336
337 public event LayoutFileChangedDelegate LayoutFileChanged;
338
339=== modified file 'client/dotNET/MainForm.cs'
340--- client/dotNET/MainForm.cs 2011-01-30 18:13:32 +0000
341+++ client/dotNET/MainForm.cs 2011-03-03 10:16:18 +0000
342@@ -72,14 +72,45 @@
343
344 _statLog = new StatLog();
345
346+ this.FormClosing += new FormClosingEventHandler(MainForm_FormClosing);
347+ this.Shown += new EventHandler(MainForm_Shown);
348+ }
349+
350+ /// <summary>
351+ /// Called after the form has been shown
352+ /// </summary>
353+ /// <param name="sender"></param>
354+ /// <param name="e"></param>
355+ void MainForm_Shown(object sender, EventArgs e)
356+ {
357+ // Process any stuff that has happened during the loading process
358+ Application.DoEvents();
359+
360 // Create a cachemanager
361 SetCacheManager();
362
363- this.FormClosing += new FormClosingEventHandler(MainForm_FormClosing);
364+ try
365+ {
366+ // Create the Schedule
367+ _schedule = new Schedule(Application.UserAppDataPath + "\\" + Properties.Settings.Default.ScheduleFile, ref _cacheManager);
368+
369+ // Bind to the schedule change event - notifys of changes to the schedule
370+ _schedule.ScheduleChangeEvent += new Schedule.ScheduleChangeDelegate(schedule_ScheduleChangeEvent);
371+
372+ // Initialize the other schedule components
373+ _schedule.InitializeComponents();
374+ }
375+ catch (Exception ex)
376+ {
377+ Debug.WriteLine(ex.Message, LogType.Error.ToString());
378+ MessageBox.Show("Fatal Error initialising the application", "Fatal Error");
379+ Close();
380+ Dispose();
381+ }
382 }
383
384 /// <summary>
385- /// Called when the form has finished loading
386+ /// Called before the form has loaded for the first time
387 /// </summary>
388 /// <param name="sender"></param>
389 /// <param name="e"></param>
390@@ -96,30 +127,13 @@
391 Cursor.Position = new Point(_clientSize.Width, _clientSize.Height);
392 Cursor.Hide();
393
394+ ShowSplashScreen();
395+
396 // Change the default Proxy class
397 OptionForm.SetGlobalProxy();
398
399 // UserApp data
400 Debug.WriteLine(new LogMessage("MainForm_Load", "User AppData Path: " + Application.UserAppDataPath), LogType.Info.ToString());
401-
402- try
403- {
404- // Create the Schedule
405- _schedule = new Schedule(Application.UserAppDataPath + "\\" + Properties.Settings.Default.ScheduleFile, ref _cacheManager);
406-
407- // Bind to the schedule change event - notifys of changes to the schedule
408- _schedule.ScheduleChangeEvent += new Schedule.ScheduleChangeDelegate(schedule_ScheduleChangeEvent);
409-
410- // Initialize the other schedule components
411- _schedule.InitializeComponents();
412- }
413- catch (Exception ex)
414- {
415- Debug.WriteLine(ex.Message, LogType.Error.ToString());
416- MessageBox.Show("Fatal Error initialising the application", "Fatal Error");
417- Close();
418- Dispose();
419- }
420 }
421
422 private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
423@@ -152,11 +166,20 @@
424 }
425 catch (Exception ex)
426 {
427- Trace.WriteLine(new LogMessage("Schedule", "Unable to reuse the Cache Manager because: " + ex.Message));
428+ Trace.WriteLine(new LogMessage("MainForm - SetCacheManager", "Unable to reuse the Cache Manager because: " + ex.Message));
429
430 // Create a new cache manager
431 _cacheManager = new CacheManager();
432 }
433+
434+ try
435+ {
436+ _cacheManager.Regenerate();
437+ }
438+ catch (Exception ex)
439+ {
440+ Trace.WriteLine(new LogMessage("MainForm - SetCacheManager", "Regenerate failed because: " + ex.Message));
441+ }
442 }
443
444 /// <summary>
445
446=== modified file 'client/dotNET/Properties/Settings.Designer.cs'
447--- client/dotNET/Properties/Settings.Designer.cs 2010-11-09 21:23:31 +0000
448+++ client/dotNET/Properties/Settings.Designer.cs 2011-03-03 10:16:18 +0000
449@@ -271,7 +271,7 @@
450
451 [global::System.Configuration.ApplicationScopedSettingAttribute()]
452 [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
453- [global::System.Configuration.DefaultSettingValueAttribute("1.2.0")]
454+ [global::System.Configuration.DefaultSettingValueAttribute("1.2.2")]
455 public string ClientVersion {
456 get {
457 return ((string)(this["ClientVersion"]));
458@@ -370,5 +370,17 @@
459 this["emptyLayoutDuration"] = value;
460 }
461 }
462+
463+ [global::System.Configuration.UserScopedSettingAttribute()]
464+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
465+ [global::System.Configuration.DefaultSettingValueAttribute("requiredFiles.xml")]
466+ public string RequiredFilesFile {
467+ get {
468+ return ((string)(this["RequiredFilesFile"]));
469+ }
470+ set {
471+ this["RequiredFilesFile"] = value;
472+ }
473+ }
474 }
475 }
476
477=== modified file 'client/dotNET/Properties/Settings.settings'
478--- client/dotNET/Properties/Settings.settings 2010-11-09 21:23:31 +0000
479+++ client/dotNET/Properties/Settings.settings 2011-03-03 10:16:18 +0000
480@@ -69,7 +69,7 @@
481 <Value Profile="(Default)">cacheManager.xml</Value>
482 </Setting>
483 <Setting Name="ClientVersion" Type="System.String" Scope="Application">
484- <Value Profile="(Default)">1.2.0</Value>
485+ <Value Profile="(Default)">1.2.2</Value>
486 </Setting>
487 <Setting Name="scrollStepAmount" Type="System.Decimal" Scope="User">
488 <Value Profile="(Default)">1</Value>
489@@ -95,5 +95,8 @@
490 <Setting Name="emptyLayoutDuration" Type="System.Decimal" Scope="User">
491 <Value Profile="(Default)">10</Value>
492 </Setting>
493+ <Setting Name="RequiredFilesFile" Type="System.String" Scope="User">
494+ <Value Profile="(Default)">requiredFiles.xml</Value>
495+ </Setting>
496 </Settings>
497 </SettingsFile>
498\ No newline at end of file
499
500=== modified file 'client/dotNET/Region.cs'
501--- client/dotNET/Region.cs 2010-11-09 21:23:31 +0000
502+++ client/dotNET/Region.cs 2011-03-03 10:16:18 +0000
503@@ -309,6 +309,7 @@
504 System.Diagnostics.Trace.WriteLine("Duration is Empty, using a default of 60.", "Region - SetNextMediaNode");
505 }
506
507+<<<<<<< TREE
508 // We cannot have a 0 duration here... not sure why we would... but
509 if (options.duration == 0)
510 options.duration = int.Parse(Properties.Settings.Default.emptyLayoutDuration.ToString());
511@@ -317,6 +318,15 @@
512 if (options.duration == 0)
513 options.duration = 10;
514
515+=======
516+ // We cannot have a 0 duration here... not sure why we would... but
517+ if (options.duration == 0 && options.type != "video")
518+ {
519+ int emptyLayoutDuration = int.Parse(Properties.Settings.Default.emptyLayoutDuration.ToString());
520+ options.duration = (emptyLayoutDuration == 0) ? 10 : emptyLayoutDuration;
521+ }
522+
523+>>>>>>> MERGE-SOURCE
524 // There will be some stuff on option nodes
525 XmlNode optionNode = mediaNode.FirstChild;
526
527@@ -386,7 +396,7 @@
528 if (options.type == "video" || options.type == "flash" || options.type == "image" || options.type == "powerpoint")
529 {
530 // Use the cache manager to determine if the file is valid
531- validNode = _cacheManager.IsValid(options.uri);
532+ validNode = _cacheManager.IsValidPath(options.uri);
533 }
534 }
535
536
537=== added file 'client/dotNET/RequiredFiles.cs'
538--- client/dotNET/RequiredFiles.cs 1970-01-01 00:00:00 +0000
539+++ client/dotNET/RequiredFiles.cs 2011-03-03 10:16:18 +0000
540@@ -0,0 +1,206 @@
541+/*
542+ * Xibo - Digitial Signage - http://www.xibo.org.uk
543+ * Copyright (C) 2011 Daniel Garner
544+ *
545+ * This file is part of Xibo.
546+ *
547+ * Xibo is free software: you can redistribute it and/or modify
548+ * it under the terms of the GNU Affero General Public License as published by
549+ * the Free Software Foundation, either version 3 of the License, or
550+ * any later version.
551+ *
552+ * Xibo is distributed in the hope that it will be useful,
553+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
554+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
555+ * GNU Affero General Public License for more details.
556+ *
557+ * You should have received a copy of the GNU Affero General Public License
558+ * along with Xibo. If not, see <http://www.gnu.org/licenses/>.
559+ */
560+using System;
561+using System.Collections.Generic;
562+using System.Collections.ObjectModel;
563+using System.Text;
564+using System.IO;
565+using System.Security.Cryptography;
566+using System.Xml;
567+using System.Diagnostics;
568+using System.Windows.Forms;
569+using System.Xml.Serialization;
570+
571+namespace XiboClient
572+{
573+ public class RequiredFiles
574+ {
575+ private XmlDocument _requiredFilesXml;
576+ public Collection<RequiredFile> _requiredFiles;
577+ private xmds.xmds _report;
578+
579+ public RequiredFiles()
580+ {
581+ _requiredFiles = new Collection<RequiredFile>();
582+
583+ // Create a webservice call
584+ _report = new XiboClient.xmds.xmds();
585+
586+ // Start up the Xmds Service Object
587+ _report.Credentials = null;
588+ _report.Url = Properties.Settings.Default.XiboClient_xmds_xmds;
589+ _report.UseDefaultCredentials = false;
590+ }
591+
592+ /// <summary>
593+ /// Set required files from the XML document
594+ /// </summary>
595+ private void SetRequiredFiles()
596+ {
597+ // Itterate through the RF XML and populate the RF collection
598+ XmlNodeList fileNodes = _requiredFilesXml.SelectNodes("/files/file");
599+
600+ foreach (XmlNode file in fileNodes)
601+ {
602+ RequiredFile rf = new RequiredFile();
603+
604+ XmlAttributeCollection attributes = file.Attributes;
605+
606+ rf.FileType = attributes["type"].Value;
607+ rf.Complete = 0;
608+ rf.Md5 = "";
609+ rf.LastChecked = DateTime.Now;
610+
611+ if (rf.FileType == "media")
612+ {
613+ string[] filePart = attributes["path"].Value.Split('.');
614+ rf.Id = int.Parse(filePart[0]);
615+ rf.Path = attributes["path"].Value;
616+ }
617+ else if (rf.FileType == "layout")
618+ {
619+ rf.Id = int.Parse(attributes["path"].Value);
620+ rf.Path = attributes["path"].Value + ".xlf";
621+ }
622+ else
623+ {
624+ continue;
625+ }
626+
627+ _requiredFiles.Add(rf);
628+ }
629+ }
630+
631+ /// <summary>
632+ /// Required Files XML
633+ /// </summary>
634+ public XmlDocument RequiredFilesXml
635+ {
636+ set
637+ {
638+ _requiredFilesXml = value;
639+ SetRequiredFiles();
640+ }
641+ }
642+
643+ /// <summary>
644+ /// Mark a RequiredFile as complete
645+ /// </summary>
646+ /// <param name="id"></param>
647+ /// <param name="md5"></param>
648+ public void MarkComplete(int id, string md5)
649+ {
650+ foreach (RequiredFile rf in _requiredFiles)
651+ {
652+ if (rf.Id == id)
653+ {
654+ RequiredFile newRf = rf;
655+
656+ newRf.Complete = 1;
657+ newRf.Md5 = md5;
658+
659+
660+ _requiredFiles.Add(newRf);
661+ _requiredFiles.Remove(rf);
662+
663+ return;
664+ }
665+ }
666+ }
667+
668+ /// <summary>
669+ /// Mark a RequiredFile as incomplete
670+ /// </summary>
671+ /// <param name="id"></param>
672+ /// <param name="md5"></param>
673+ public void MarkIncomplete(int id, string md5)
674+ {
675+ foreach (RequiredFile rf in _requiredFiles)
676+ {
677+ if (rf.Id == id)
678+ {
679+ RequiredFile newRf = rf;
680+
681+ newRf.Complete = 0;
682+ newRf.Md5 = md5;
683+
684+ _requiredFiles.Add(newRf);
685+ _requiredFiles.Remove(rf);
686+
687+ return;
688+ }
689+ }
690+ }
691+
692+ /// <summary>
693+ /// Writes Required Files to disk
694+ /// </summary>
695+ public void WriteRequiredFiles()
696+ {
697+ Debug.WriteLine(new LogMessage("RequiredFiles - WriteRequiredFiles", "About to Write RequiredFiles"), LogType.Info.ToString());
698+
699+ try
700+ {
701+ using (StreamWriter streamWriter = new StreamWriter(Application.UserAppDataPath + "\\" + Properties.Settings.Default.RequiredFilesFile))
702+ {
703+ XmlSerializer xmlSerializer = new XmlSerializer(typeof(RequiredFiles));
704+
705+ xmlSerializer.Serialize(streamWriter, this);
706+ }
707+ }
708+ catch (Exception ex)
709+ {
710+ System.Diagnostics.Trace.WriteLine(new LogMessage("RequiredFiles - WriteRequiredFiles", "Unable to write RequiredFiles to disk because: " + ex.Message));
711+ }
712+ }
713+
714+ /// <summary>
715+ /// Report Required Files to XMDS
716+ /// </summary>
717+ public void ReportInventory()
718+ {
719+ HardwareKey hardwareKey = new HardwareKey();
720+
721+ // Build the XML required by media file
722+ string xml = "";
723+
724+ foreach (RequiredFile rf in _requiredFiles)
725+ {
726+ xml += string.Format("<file type=\"{0}\" id=\"{1}\" complete=\"{2}\" lastChecked=\"{3}\" md5=\"{4}\" />",
727+ rf.FileType, rf.Id.ToString(), rf.Complete.ToString(), rf.LastChecked.ToString(), rf.Md5);
728+ }
729+
730+ xml = string.Format("<files>{0}</files>", xml);
731+
732+ _report.MediaInventoryAsync(Properties.Settings.Default.Version, Properties.Settings.Default.ServerKey,
733+ hardwareKey.Key, xml);
734+ }
735+ }
736+
737+ public struct RequiredFile
738+ {
739+ public string FileType;
740+ public int Id;
741+ public int Complete;
742+ public DateTime LastChecked;
743+ public string Md5;
744+ public string Path;
745+ }
746+}
747
748=== modified file 'client/dotNET/Schedule.cs'
749--- client/dotNET/Schedule.cs 2010-08-22 16:49:09 +0000
750+++ client/dotNET/Schedule.cs 2011-03-03 10:16:18 +0000
751@@ -74,7 +74,7 @@
752 _cacheManager = cacheManager;
753
754 // Create a schedule manager
755- _scheduleManager = new ScheduleManager(scheduleLocation);
756+ _scheduleManager = new ScheduleManager(_cacheManager, scheduleLocation);
757
758 // Create a new Xmds service object
759 _xmds2 = new XiboClient.xmds.xmds();
760
761=== modified file 'client/dotNET/ScheduleManager.cs'
762--- client/dotNET/ScheduleManager.cs 2010-08-25 21:39:53 +0000
763+++ client/dotNET/ScheduleManager.cs 2011-03-03 10:16:18 +0000
764@@ -42,13 +42,15 @@
765 private Collection<LayoutSchedule> _layoutSchedule;
766 private Collection<LayoutSchedule> _currentSchedule;
767 private bool _refreshSchedule;
768+ private CacheManager _cacheManager;
769
770 /// <summary>
771 /// Creates a new schedule Manager
772 /// </summary>
773 /// <param name="scheduleLocation"></param>
774- public ScheduleManager(string scheduleLocation)
775+ public ScheduleManager(CacheManager cacheManager, string scheduleLocation)
776 {
777+ _cacheManager = cacheManager;
778 _location = scheduleLocation;
779
780 // Create an empty layout schedule
781@@ -178,6 +180,19 @@
782 // For each layout in the schedule determine if it is currently inside the _currentSchedule, and whether it should be
783 foreach (LayoutSchedule layout in _layoutSchedule)
784 {
785+ // Is the layout valid in the cachemanager?
786+ try
787+ {
788+ if (!_cacheManager.IsValidLayout(layout.id + ".xlf"))
789+ continue;
790+ }
791+ catch
792+ {
793+ // TODO: Ignore this layout.. raise an error?
794+ Trace.WriteLine("Unable to determine if layout is valid or not");
795+ continue;
796+ }
797+
798 // If this is the default, skip it
799 if (layout.NodeName == "default")
800 {
801
802=== modified file 'client/dotNET/Web References/xmds/Reference.cs'
803--- client/dotNET/Web References/xmds/Reference.cs 2010-11-09 21:23:31 +0000
804+++ client/dotNET/Web References/xmds/Reference.cs 2011-03-03 10:16:18 +0000
805@@ -45,6 +45,8 @@
806
807 private System.Threading.SendOrPostCallback SubmitStatsOperationCompleted;
808
809+ private System.Threading.SendOrPostCallback MediaInventoryOperationCompleted;
810+
811 private bool useDefaultCredentialsSetExplicitly;
812
813 /// <remarks/>
814@@ -108,6 +110,9 @@
815 public event SubmitStatsCompletedEventHandler SubmitStatsCompleted;
816
817 /// <remarks/>
818+ public event MediaInventoryCompletedEventHandler MediaInventoryCompleted;
819+
820+ /// <remarks/>
821 [System.Web.Services.Protocols.SoapRpcMethodAttribute("urn:xmds#RegisterDisplay", RequestNamespace="urn:xmds", ResponseNamespace="urn:xmds")]
822 [return: System.Xml.Serialization.SoapElementAttribute("ActivationMessage")]
823 public string RegisterDisplay(string serverKey, string hardwareKey, string displayName, string version) {
824@@ -402,6 +407,42 @@
825 }
826
827 /// <remarks/>
828+ [System.Web.Services.Protocols.SoapRpcMethodAttribute("urn:xmds#MediaInventory", RequestNamespace="urn:xmds", ResponseNamespace="urn:xmds")]
829+ [return: System.Xml.Serialization.SoapElementAttribute("success")]
830+ public bool MediaInventory(string version, string serverKey, string hardwareKey, [System.Xml.Serialization.SoapElementAttribute("mediaInventory")] string mediaInventory1) {
831+ object[] results = this.Invoke("MediaInventory", new object[] {
832+ version,
833+ serverKey,
834+ hardwareKey,
835+ mediaInventory1});
836+ return ((bool)(results[0]));
837+ }
838+
839+ /// <remarks/>
840+ public void MediaInventoryAsync(string version, string serverKey, string hardwareKey, string mediaInventory1) {
841+ this.MediaInventoryAsync(version, serverKey, hardwareKey, mediaInventory1, null);
842+ }
843+
844+ /// <remarks/>
845+ public void MediaInventoryAsync(string version, string serverKey, string hardwareKey, string mediaInventory1, object userState) {
846+ if ((this.MediaInventoryOperationCompleted == null)) {
847+ this.MediaInventoryOperationCompleted = new System.Threading.SendOrPostCallback(this.OnMediaInventoryOperationCompleted);
848+ }
849+ this.InvokeAsync("MediaInventory", new object[] {
850+ version,
851+ serverKey,
852+ hardwareKey,
853+ mediaInventory1}, this.MediaInventoryOperationCompleted, userState);
854+ }
855+
856+ private void OnMediaInventoryOperationCompleted(object arg) {
857+ if ((this.MediaInventoryCompleted != null)) {
858+ System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg));
859+ this.MediaInventoryCompleted(this, new MediaInventoryCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState));
860+ }
861+ }
862+
863+ /// <remarks/>
864 public new void CancelAsync(object userState) {
865 base.CancelAsync(userState);
866 }
867@@ -627,6 +668,32 @@
868 }
869 }
870 }
871+
872+ /// <remarks/>
873+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "2.0.50727.4927")]
874+ public delegate void MediaInventoryCompletedEventHandler(object sender, MediaInventoryCompletedEventArgs e);
875+
876+ /// <remarks/>
877+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "2.0.50727.4927")]
878+ [System.Diagnostics.DebuggerStepThroughAttribute()]
879+ [System.ComponentModel.DesignerCategoryAttribute("code")]
880+ public partial class MediaInventoryCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs {
881+
882+ private object[] results;
883+
884+ internal MediaInventoryCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) :
885+ base(exception, cancelled, userState) {
886+ this.results = results;
887+ }
888+
889+ /// <remarks/>
890+ public bool Result {
891+ get {
892+ this.RaiseExceptionIfNecessary();
893+ return ((bool)(this.results[0]));
894+ }
895+ }
896+ }
897 }
898
899 #pragma warning restore 1591
900\ No newline at end of file
901
902=== modified file 'client/dotNET/Web References/xmds/xmds.wsdl'
903--- client/dotNET/Web References/xmds/xmds.wsdl 2010-11-09 21:23:31 +0000
904+++ client/dotNET/Web References/xmds/xmds.wsdl 2011-03-03 10:16:18 +0000
905@@ -81,6 +81,15 @@
906 <wsdl:message name="SubmitStatsResponse">
907 <wsdl:part name="success" type="xsd:boolean" />
908 </wsdl:message>
909+ <wsdl:message name="MediaInventoryRequest">
910+ <wsdl:part name="version" type="xsd:string" />
911+ <wsdl:part name="serverKey" type="xsd:string" />
912+ <wsdl:part name="hardwareKey" type="xsd:string" />
913+ <wsdl:part name="mediaInventory" type="xsd:string" />
914+ </wsdl:message>
915+ <wsdl:message name="MediaInventoryResponse">
916+ <wsdl:part name="success" type="xsd:boolean" />
917+ </wsdl:message>
918 <wsdl:portType name="xmdsPortType">
919 <wsdl:operation name="RegisterDisplay">
920 <documentation>Registered the Display on the Xibo Network</documentation>
921@@ -122,6 +131,11 @@
922 <wsdl:input message="tns:SubmitStatsRequest" />
923 <wsdl:output message="tns:SubmitStatsResponse" />
924 </wsdl:operation>
925+ <wsdl:operation name="MediaInventory">
926+ <documentation>Report back the clients MediaInventory</documentation>
927+ <wsdl:input message="tns:MediaInventoryRequest" />
928+ <wsdl:output message="tns:MediaInventoryResponse" />
929+ </wsdl:operation>
930 </wsdl:portType>
931 <wsdl:binding name="xmdsBinding" type="tns:xmdsPortType">
932 <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="rpc" />
933@@ -197,6 +211,15 @@
934 <soap:body use="encoded" namespace="urn:xmds" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
935 </wsdl:output>
936 </wsdl:operation>
937+ <wsdl:operation name="MediaInventory">
938+ <soap:operation soapAction="urn:xmds#MediaInventory" style="rpc" />
939+ <wsdl:input>
940+ <soap:body use="encoded" namespace="urn:xmds" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
941+ </wsdl:input>
942+ <wsdl:output>
943+ <soap:body use="encoded" namespace="urn:xmds" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
944+ </wsdl:output>
945+ </wsdl:operation>
946 </wsdl:binding>
947 <wsdl:service name="xmds">
948 <wsdl:port name="xmdsPort" binding="tns:xmdsBinding">
949
950=== modified file 'client/dotNET/XiboClient.csproj'
951--- client/dotNET/XiboClient.csproj 2011-02-09 17:15:43 +0000
952+++ client/dotNET/XiboClient.csproj 2011-03-03 10:16:18 +0000
953@@ -161,6 +161,7 @@
954 <Compile Include="Region.cs">
955 <SubType>Component</SubType>
956 </Compile>
957+ <Compile Include="RequiredFiles.cs" />
958 <Compile Include="Rss.cs">
959 <SubType>Form</SubType>
960 </Compile>
961
962=== modified file 'client/dotNET/app.config'
963--- client/dotNET/app.config 2010-11-09 21:23:31 +0000
964+++ client/dotNET/app.config 2011-03-03 10:16:18 +0000
965@@ -79,6 +79,9 @@
966 <setting name="emptyLayoutDuration" serializeAs="String">
967 <value>10</value>
968 </setting>
969+ <setting name="RequiredFilesFile" serializeAs="String">
970+ <value>requiredFiles.xml</value>
971+ </setting>
972 </XiboClient.Properties.Settings>
973 </userSettings>
974 <applicationSettings>
975@@ -102,7 +105,7 @@
976 <value>cacheManager.xml</value>
977 </setting>
978 <setting name="ClientVersion" serializeAs="String">
979- <value>1.2.0</value>
980+ <value>1.2.2</value>
981 </setting>
982 <setting name="xmdsResetTimeout" serializeAs="String">
983 <value>900</value>
984
985=== modified file 'client/dotNET/bin/Release/AxInterop.ShockwaveFlashObjects.dll'
986Binary files client/dotNET/bin/Release/AxInterop.ShockwaveFlashObjects.dll 2010-04-19 21:45:10 +0000 and client/dotNET/bin/Release/AxInterop.ShockwaveFlashObjects.dll 2011-03-03 10:16:18 +0000 differ
987=== modified file 'client/dotNET/bin/Release/AxInterop.WMPLib.dll'
988Binary files client/dotNET/bin/Release/AxInterop.WMPLib.dll 2010-04-19 21:45:10 +0000 and client/dotNET/bin/Release/AxInterop.WMPLib.dll 2011-03-03 10:16:18 +0000 differ
989=== modified file 'client/dotNET/bin/Release/Interop.ShockwaveFlashObjects.dll'
990Binary files client/dotNET/bin/Release/Interop.ShockwaveFlashObjects.dll 2010-04-19 21:45:10 +0000 and client/dotNET/bin/Release/Interop.ShockwaveFlashObjects.dll 2011-03-03 10:16:18 +0000 differ
991=== modified file 'client/dotNET/bin/Release/Interop.WMPLib.dll'
992Binary files client/dotNET/bin/Release/Interop.WMPLib.dll 2010-04-19 21:45:10 +0000 and client/dotNET/bin/Release/Interop.WMPLib.dll 2011-03-03 10:16:18 +0000 differ
993=== modified file 'client/dotNET/bin/Release/XiboClient.exe.config'
994--- client/dotNET/bin/Release/XiboClient.exe.config 2010-04-19 21:45:10 +0000
995+++ client/dotNET/bin/Release/XiboClient.exe.config 2011-03-03 10:16:18 +0000
996@@ -14,7 +14,7 @@
997 <value>DEFAULT</value>
998 </setting>
999 <setting name="XiboClient_xmds_xmds" serializeAs="String">
1000- <value>http://localhost/xibo/xmds.php</value>
1001+ <value>http://localhost/Series%201.2/server-121-soap-wsdl/server/xmds.php</value>
1002 </setting>
1003 <setting name="ServerKey" serializeAs="String">
1004 <value>yourserverkey</value>
1005@@ -61,6 +61,27 @@
1006 <setting name="scrollStepAmount" serializeAs="String">
1007 <value>1</value>
1008 </setting>
1009+ <setting name="sizeX" serializeAs="String">
1010+ <value>0</value>
1011+ </setting>
1012+ <setting name="sizeY" serializeAs="String">
1013+ <value>0</value>
1014+ </setting>
1015+ <setting name="offsetX" serializeAs="String">
1016+ <value>0</value>
1017+ </setting>
1018+ <setting name="offsetY" serializeAs="String">
1019+ <value>0</value>
1020+ </setting>
1021+ <setting name="expireModifiedLayouts" serializeAs="String">
1022+ <value>True</value>
1023+ </setting>
1024+ <setting name="emptyLayoutDuration" serializeAs="String">
1025+ <value>10</value>
1026+ </setting>
1027+ <setting name="RequiredFilesFile" serializeAs="String">
1028+ <value>requiredFiles.xml</value>
1029+ </setting>
1030 </XiboClient.Properties.Settings>
1031 </userSettings>
1032 <applicationSettings>
1033@@ -75,7 +96,7 @@
1034 <value>blacklist.xml</value>
1035 </setting>
1036 <setting name="Version" serializeAs="String">
1037- <value>1</value>
1038+ <value>2</value>
1039 </setting>
1040 <setting name="StatsLogFile" serializeAs="String">
1041 <value>stats.xml</value>
1042@@ -84,7 +105,7 @@
1043 <value>cacheManager.xml</value>
1044 </setting>
1045 <setting name="ClientVersion" serializeAs="String">
1046- <value>1.0.7</value>
1047+ <value>1.2.2</value>
1048 </setting>
1049 <setting name="xmdsResetTimeout" serializeAs="String">
1050 <value>900</value>
1051
1052=== modified file 'client/dotNET/bin/Release/XiboClient.vshost.exe.config'
1053--- client/dotNET/bin/Release/XiboClient.vshost.exe.config 2010-04-19 21:45:10 +0000
1054+++ client/dotNET/bin/Release/XiboClient.vshost.exe.config 2011-03-03 10:16:18 +0000
1055@@ -14,7 +14,7 @@
1056 <value>DEFAULT</value>
1057 </setting>
1058 <setting name="XiboClient_xmds_xmds" serializeAs="String">
1059- <value>http://localhost/xibo/xmds.php</value>
1060+ <value>http://localhost/Series%201.2/server-121-soap-wsdl/server/xmds.php</value>
1061 </setting>
1062 <setting name="ServerKey" serializeAs="String">
1063 <value>yourserverkey</value>
1064@@ -61,6 +61,27 @@
1065 <setting name="scrollStepAmount" serializeAs="String">
1066 <value>1</value>
1067 </setting>
1068+ <setting name="sizeX" serializeAs="String">
1069+ <value>0</value>
1070+ </setting>
1071+ <setting name="sizeY" serializeAs="String">
1072+ <value>0</value>
1073+ </setting>
1074+ <setting name="offsetX" serializeAs="String">
1075+ <value>0</value>
1076+ </setting>
1077+ <setting name="offsetY" serializeAs="String">
1078+ <value>0</value>
1079+ </setting>
1080+ <setting name="expireModifiedLayouts" serializeAs="String">
1081+ <value>True</value>
1082+ </setting>
1083+ <setting name="emptyLayoutDuration" serializeAs="String">
1084+ <value>10</value>
1085+ </setting>
1086+ <setting name="RequiredFilesFile" serializeAs="String">
1087+ <value>requiredFiles.xml</value>
1088+ </setting>
1089 </XiboClient.Properties.Settings>
1090 </userSettings>
1091 <applicationSettings>
1092@@ -75,7 +96,7 @@
1093 <value>blacklist.xml</value>
1094 </setting>
1095 <setting name="Version" serializeAs="String">
1096- <value>1</value>
1097+ <value>2</value>
1098 </setting>
1099 <setting name="StatsLogFile" serializeAs="String">
1100 <value>stats.xml</value>
1101@@ -84,7 +105,7 @@
1102 <value>cacheManager.xml</value>
1103 </setting>
1104 <setting name="ClientVersion" serializeAs="String">
1105- <value>1.0.7</value>
1106+ <value>1.2.2</value>
1107 </setting>
1108 <setting name="xmdsResetTimeout" serializeAs="String">
1109 <value>900</value>
1110
1111=== modified file 'client/python/XiboClient.py'
1112--- client/python/XiboClient.py 2011-02-10 22:25:35 +0000
1113+++ client/python/XiboClient.py 2011-03-03 10:16:18 +0000
1114@@ -48,7 +48,11 @@
1115 import PIL.Image
1116 import math
1117
1118+<<<<<<< TREE
1119 version = "1.3.0a1"
1120+=======
1121+version = "1.2.2a1"
1122+>>>>>>> MERGE-SOURCE
1123
1124 # What layout schema version is supported
1125 schemaVersion = 1
1126@@ -908,8 +912,18 @@
1127 tmpSize = long(f.attributes['size'].value)
1128 tmpHash = str(f.attributes['md5'].value)
1129 tmpType = str(f.attributes['type'].value)
1130+<<<<<<< TREE
1131 tmpId = int(f.attributes['id'].value)
1132
1133+=======
1134+ try:
1135+ tmpId = int(f.attributes['id'].value)
1136+ except:
1137+ # Layout background images don't come down with IDs
1138+ # Blame Dan :D
1139+ tmpId = 0
1140+
1141+>>>>>>> MERGE-SOURCE
1142 if os.path.isfile(tmpPath) and os.path.getsize(tmpPath) == tmpSize:
1143 # File exists and is the right size
1144 # See if we checksummed it recently
1145
1146=== added file 'server/install/database/27.sql'
1147--- server/install/database/27.sql 1970-01-01 00:00:00 +0000
1148+++ server/install/database/27.sql 2011-03-03 10:16:18 +0000
1149@@ -0,0 +1,9 @@
1150+
1151+ALTER TABLE `display` ADD `MediaInventoryStatus` TINYINT NOT NULL ,
1152+ADD `MediaInventoryXml` LONGTEXT NULL;
1153+
1154+/* VERSION UPDATE */
1155+/* Set the version table, etc */
1156+UPDATE `version` SET `app_ver` = '1.2.2', `XmdsVersion` = 2;
1157+UPDATE `setting` SET `value` = 0 WHERE `setting` = 'PHONE_HOME_DATE';
1158+UPDATE `version` SET `DBVersion` = '27';
1159\ No newline at end of file
1160
1161=== modified file 'server/lib/app/kit.class.php'
1162--- server/lib/app/kit.class.php 2011-02-28 15:37:03 +0000
1163+++ server/lib/app/kit.class.php 2011-03-03 10:16:18 +0000
1164@@ -405,8 +405,11 @@
1165 {
1166 include_once('lib/service/' . $class . '.class.php');
1167 }
1168+<<<<<<< TREE
1169
1170 return;
1171+=======
1172+>>>>>>> MERGE-SOURCE
1173 }
1174
1175 /**
1176
1177=== modified file 'server/lib/data/display.data.class.php'
1178--- server/lib/data/display.data.class.php 2011-02-10 20:42:24 +0000
1179+++ server/lib/data/display.data.class.php 2011-03-03 10:16:18 +0000
1180@@ -251,7 +251,7 @@
1181 * @return
1182 * @param $license Object
1183 */
1184- public function Touch($license, $clientAddress = '')
1185+ public function Touch($license, $clientAddress = '', $mediaInventoryComplete = 0, $mediaInventoryXml = '')
1186 {
1187 $db =& $this->db;
1188 $time = time();
1189@@ -266,6 +266,13 @@
1190 if ($clientAddress != '')
1191 $SQL .= sprintf(" , ClientAddress = '%s' ", $db->escape_string($clientAddress));
1192
1193+ // Media Inventory Settings (if appropriate)
1194+ if ($mediaInventoryComplete != 0)
1195+ $SQL .= sprintf(" , MediaInventoryStatus = %d ", $mediaInventoryComplete);
1196+
1197+ if ($mediaInventoryXml != '')
1198+ $SQL .= sprintf(" , MediaInventoryXml = '%s' ", $mediaInventoryXml);
1199+
1200 // Restrict to the display license
1201 $SQL .= " WHERE license = '%s'";
1202 $SQL = sprintf($SQL, $time, $license);
1203@@ -282,33 +289,131 @@
1204
1205 return true;
1206 }
1207-
1208- /**
1209- * Edits the default layout for a display
1210- * @param <type> $displayId
1211- * @param <type> $defaultLayoutId
1212- * @return <type>
1213- */
1214- public function EditDefaultLayout($displayId, $defaultLayoutId)
1215- {
1216- $db =& $this->db;
1217-
1218- Debug::LogEntry($db, 'audit', 'IN', 'Display', 'EditDefaultLayout');
1219-
1220- $SQL = sprintf('UPDATE display SET defaultLayoutId = %d WHERE displayID = %d ', $defaultLayoutId, $displayId);
1221-
1222- if (!$db->query($SQL))
1223- {
1224- trigger_error($db->error());
1225- $this->SetError(25012, __('Error updating this displays default layout.'));
1226-
1227- return false;
1228- }
1229-
1230-
1231- Debug::LogEntry($db, 'audit', 'OUT', 'Display', 'EditDefaultLayout');
1232-
1233- return true;
1234- }
1235+<<<<<<< TREE
1236+
1237+ /**
1238+ * Edits the default layout for a display
1239+ * @param <type> $displayId
1240+ * @param <type> $defaultLayoutId
1241+ * @return <type>
1242+ */
1243+ public function EditDefaultLayout($displayId, $defaultLayoutId)
1244+ {
1245+ $db =& $this->db;
1246+
1247+ Debug::LogEntry($db, 'audit', 'IN', 'Display', 'EditDefaultLayout');
1248+
1249+ $SQL = sprintf('UPDATE display SET defaultLayoutId = %d WHERE displayID = %d ', $defaultLayoutId, $displayId);
1250+
1251+ if (!$db->query($SQL))
1252+ {
1253+ trigger_error($db->error());
1254+ $this->SetError(25012, __('Error updating this displays default layout.'));
1255+
1256+ return false;
1257+ }
1258+
1259+
1260+ Debug::LogEntry($db, 'audit', 'OUT', 'Display', 'EditDefaultLayout');
1261+
1262+ return true;
1263+ }
1264+=======
1265+
1266+ /**
1267+ * Flags a display as being incomplete
1268+ * @param <type> $displayId
1269+ */
1270+ private function FlagIncomplete($displayId)
1271+ {
1272+ $db =& $this->db;
1273+
1274+ Debug::LogEntry($db, 'audit', sprintf('Flag DisplayID %d incomplete.', $displayId), 'display', 'NotifyDisplays');
1275+
1276+ $SQL = sprintf("UPDATE display SET MediaInventoryStatus = 3 WHERE displayID = %d", $displayId);
1277+
1278+ if (!$db->query($SQL))
1279+ {
1280+ trigger_error($db->error());
1281+ return $this->SetError(25004, 'Unable to Flag Display as incomplete');
1282+ }
1283+
1284+ return true;
1285+ }
1286+
1287+ /**
1288+ * Notify displays of this layout change
1289+ * @param <type> $layoutId
1290+ */
1291+ public function NotifyDisplays($layoutId)
1292+ {
1293+ $db =& $this->db;
1294+ $currentdate = time();
1295+ $rfLookahead = Kit::ValidateParam(Config::GetSetting($db,'REQUIRED_FILES_LOOKAHEAD'), _INT);
1296+
1297+ $rfLookahead = $currentdate + $rfLookahead;
1298+
1299+ Debug::LogEntry($db, 'audit', sprintf('Checking for Displays to refresh on Layout %d', $layoutId), 'display', 'NotifyDisplays');
1300+
1301+ // Which displays does a change to this layout effect?
1302+ $SQL = " SELECT DISTINCT display.DisplayID ";
1303+ $SQL .= " FROM schedule_detail ";
1304+ $SQL .= " INNER JOIN lkdisplaydg ";
1305+ $SQL .= " ON lkdisplaydg.DisplayGroupID = schedule_detail.DisplayGroupID ";
1306+ $SQL .= " INNER JOIN display ";
1307+ $SQL .= " ON lkdisplaydg.DisplayID = display.displayID ";
1308+ $SQL .= " WHERE schedule_detail.layoutID = %d ";
1309+ $SQL .= " AND schedule_detail.FromDT < %d AND schedule_detail.ToDT > %d ";
1310+ $SQL .= " UNION ";
1311+ $SQL .= " SELECT DisplayID FROM display WHERE DefaultLayoutID = %d";
1312+
1313+ $SQL = sprintf($SQL, $layoutId, $rfLookahead, $currentdate - 3600, $layoutId);
1314+
1315+ Debug::LogEntry($db, 'audit', $SQL, 'display', 'NotifyDisplays');
1316+
1317+ if (!$result = $db->query($SQL))
1318+ {
1319+ trigger_error($db->error());
1320+ return $this->SetError(25037, __('Unable to get layouts for Notify'));
1321+ }
1322+
1323+ while ($row = $db->get_assoc_row($result))
1324+ {
1325+ // Notify each display in turn
1326+ $displayId = Kit::ValidateParam($row['DisplayID'], _INT);
1327+ $this->FlagIncomplete($displayId);
1328+ }
1329+ }
1330+
1331+ /**
1332+ * Edits the default layout for a display
1333+ * @param <type> $displayId
1334+ * @param <type> $defaultLayoutId
1335+ * @return <type>
1336+ */
1337+ public function EditDefaultLayout($displayId, $defaultLayoutId)
1338+ {
1339+ $db =& $this->db;
1340+
1341+ Debug::LogEntry($db, 'audit', 'IN', 'Display', 'EditDefaultLayout');
1342+
1343+ $SQL = sprintf('UPDATE display SET defaultLayoutId = %d WHERE displayID = %d ', $defaultLayoutId, $displayId);
1344+
1345+ if (!$db->query($SQL))
1346+ {
1347+ trigger_error($db->error());
1348+ $this->SetError(25012, __('Error updating this displays default layout.'));
1349+
1350+ return false;
1351+ }
1352+
1353+ // Flag this display as not having all the content
1354+ $this->FlagIncomplete($displayId);
1355+
1356+ Debug::LogEntry($db, 'audit', 'OUT', 'Display', 'EditDefaultLayout');
1357+
1358+ return true;
1359+ }
1360+>>>>>>> MERGE-SOURCE
1361 }
1362 ?>
1363
1364=== modified file 'server/lib/data/schedule.data.class.php'
1365--- server/lib/data/schedule.data.class.php 2011-02-10 19:46:44 +0000
1366+++ server/lib/data/schedule.data.class.php 2011-03-03 10:16:18 +0000
1367@@ -164,6 +164,11 @@
1368 }
1369 }
1370 }
1371+
1372+ // Notify (dont error)
1373+ Kit::ClassLoader('Display');
1374+ $displayObject = new Display($db);
1375+ $displayObject->NotifyDisplays($layoutID);
1376
1377 Debug::LogEntry($db, 'audit', 'OUT', 'Schedule', 'Add');
1378
1379
1380=== modified file 'server/lib/include.php'
1381--- server/lib/include.php 2011-02-28 15:37:03 +0000
1382+++ server/lib/include.php 2011-03-03 10:16:18 +0000
1383@@ -107,8 +107,8 @@
1384 Config::Version($db);
1385
1386 // Does the version in the DB match the version of the code?
1387-if (DBVERSION != '26')
1388- die(sprintf('Incompatible database version detected. Please ensure your database and website versions match. You have %d and the website for %d', DBVERSION, 25));
1389+if (DBVERSION != '27')
1390+ die(sprintf('Incompatible database version detected. Please ensure your database and website versions match. You have %d and the website for %d', DBVERSION, 27));
1391
1392 // What is the production mode of the server?
1393 if(Config::GetSetting($db, "SERVER_MODE")=="Test") ini_set('display_errors', 1);
1394@@ -143,4 +143,4 @@
1395 $pageManager->Render();
1396
1397 die();
1398-?>
1399\ No newline at end of file
1400+?>
1401
1402=== modified file 'server/lib/pages/display.class.php'
1403--- server/lib/pages/display.class.php 2011-02-13 17:16:01 +0000
1404+++ server/lib/pages/display.class.php 2011-03-03 10:16:18 +0000
1405@@ -37,6 +37,8 @@
1406 private $email_alert;
1407 private $alert_timeout;
1408 private $ajax;
1409+ private $mediaInventoryStatus;
1410+ private $mediaInventoryXml;
1411
1412 function __construct(database $db, user $user)
1413 {
1414@@ -71,7 +73,9 @@
1415 display.isAuditing,
1416 display.email_alert,
1417 display.alert_timeout,
1418- display.ClientAddress
1419+ display.ClientAddress,
1420+ display.MediaInventoryStatus,
1421+ display.MediaInventoryXml
1422 FROM display
1423 WHERE display.displayid = %d
1424 SQL;
1425@@ -95,8 +99,10 @@
1426 $this->licensed = Kit::ValidateParam($row[4], _INT);
1427 $this->inc_schedule = Kit::ValidateParam($row[5], _INT);
1428 $this->auditing = Kit::ValidateParam($row[6], _INT);
1429- $this->email_alert = Kit::ValidateParam($row[7], _INT);
1430- $this->alert_timeout = Kit::ValidateParam($row[8], _INT);
1431+ $this->email_alert = Kit::ValidateParam($row[7], _INT);
1432+ $this->alert_timeout = Kit::ValidateParam($row[8], _INT);
1433+ $this->mediaInventoryStatus = Kit::ValidateParam($row[9], _INT);
1434+ $this->mediaInventoryXml = Kit::ValidateParam($row[10], _HTMLSTRING);
1435 }
1436 }
1437
1438@@ -309,7 +315,12 @@
1439 CASE WHEN display.licensed = 1 THEN '<img src="img/act.gif">' ELSE '<img src="img/disact.gif">' END AS licensed,
1440 CASE WHEN display.email_alert = 1 THEN '<img src="img/act.gif">' ELSE '<img src="img/disact.gif">' END AS email_alert,
1441 displaygroup.DisplayGroupID,
1442- display.ClientAddress
1443+ display.ClientAddress,
1444+ CASE WHEN display.MediaInventoryStatus = 1 THEN '<img src="img/act.gif">'
1445+ WHEN display.MediaInventoryStatus = 2 THEN '<img src="img/warn.gif">'
1446+ ELSE '<img src="img/disact.gif">'
1447+ END AS MediaInventoryStatus,
1448+ display.MediaInventoryXml
1449 FROM display
1450 INNER JOIN lkdisplaydg ON lkdisplaydg.DisplayID = display.DisplayID
1451 INNER JOIN displaygroup ON displaygroup.DisplayGroupID = lkdisplaydg.DisplayGroupID
1452@@ -340,7 +351,13 @@
1453 $msgDelete = __('Delete');
1454 $msgGroupSecurity = __('Group Security');
1455 $msgClientAddress = __('IP Address');
1456- $msgDefault = __('Default Layout');
1457+<<<<<<< TREE
1458+ $msgDefault = __('Default Layout');
1459+=======
1460+ $msgDefault = __('Default Layout');
1461+ $msgStatus = __('Status');
1462+ $msgMediaInventory = __('Media Inventory');
1463+>>>>>>> MERGE-SOURCE
1464
1465 $output = <<<END
1466 <div class="info_table">
1467@@ -356,6 +373,7 @@
1468 <th>$msgLogIn</th>
1469 <th>$msgLastA</th>
1470 <th>$msgClientAddress</th>
1471+ <th>$msgStatus</th>
1472 <th>$msgAction</th>
1473 </tr>
1474 </thead>
1475@@ -385,6 +403,7 @@
1476 // Do we want to make a VNC link out of the display name?
1477 $vncTemplate = Config::GetSetting($db, 'SHOW_DISPLAY_AS_VNCLINK');
1478 $linkTarget = Kit::ValidateParam(Config::GetSetting($db, 'SHOW_DISPLAY_AS_VNC_TGT'), _STRING);
1479+ $mediaInventoryStatusLight = Kit::ValidateParam($aRow[10], _STRING);
1480
1481 if ($vncTemplate != '' && $clientAddress != '')
1482 {
1483@@ -396,22 +415,42 @@
1484 $display = sprintf('<a href="' . $vncTemplate . '" title="VNC to ' . $display . '" target="' . $linkTarget . '">' . $display . '</a>', $clientAddress);
1485 }
1486
1487- $buttons = '';
1488-
1489- if ($user->usertypeid == 1)
1490- {
1491- $buttons = <<<END
1492- <button class='XiboFormButton' href='index.php?p=display&q=displayForm&displayid=$displayid'><span>$msgEdit</span></button>
1493- <button class='XiboFormButton' href='index.php?p=display&q=DeleteForm&displayid=$displayid'><span>$msgDelete</span></button>
1494- <button class="XiboFormButton" href="index.php?p=displaygroup&q=GroupSecurityForm&DisplayGroupID=$displayGroupID&DisplayGroup=$displayName"><span>$msgGroupSecurity</span></button>
1495- <button class="XiboFormButton" href="index.php?p=display&q=DefaultLayoutForm&DisplayId=$displayid"><span>$msgDefault</span></button>
1496-END;
1497- }
1498- else
1499- {
1500- $buttons = '<button class="XiboFormButton" href="index.php?p=display&q=DefaultLayoutForm&DisplayId=' . $displayid . '"><span>' . $msgDefault . '</span></button>';
1501- }
1502-
1503+<<<<<<< TREE
1504+ $buttons = '';
1505+
1506+ if ($user->usertypeid == 1)
1507+ {
1508+ $buttons = <<<END
1509+ <button class='XiboFormButton' href='index.php?p=display&q=displayForm&displayid=$displayid'><span>$msgEdit</span></button>
1510+ <button class='XiboFormButton' href='index.php?p=display&q=DeleteForm&displayid=$displayid'><span>$msgDelete</span></button>
1511+ <button class="XiboFormButton" href="index.php?p=displaygroup&q=GroupSecurityForm&DisplayGroupID=$displayGroupID&DisplayGroup=$displayName"><span>$msgGroupSecurity</span></button>
1512+ <button class="XiboFormButton" href="index.php?p=display&q=DefaultLayoutForm&DisplayId=$displayid"><span>$msgDefault</span></button>
1513+END;
1514+ }
1515+ else
1516+ {
1517+ $buttons = '<button class="XiboFormButton" href="index.php?p=display&q=DefaultLayoutForm&DisplayId=' . $displayid . '"><span>' . $msgDefault . '</span></button>';
1518+ }
1519+
1520+=======
1521+ $buttons = '';
1522+
1523+ if ($user->usertypeid == 1)
1524+ {
1525+ $buttons = <<<END
1526+ <button class='XiboFormButton' href='index.php?p=display&q=displayForm&displayid=$displayid'><span>$msgEdit</span></button>
1527+ <button class='XiboFormButton' href='index.php?p=display&q=DeleteForm&displayid=$displayid'><span>$msgDelete</span></button>
1528+ <button class="XiboFormButton" href="index.php?p=displaygroup&q=GroupSecurityForm&DisplayGroupID=$displayGroupID&DisplayGroup=$displayName"><span>$msgGroupSecurity</span></button>
1529+ <button class="XiboFormButton" href="index.php?p=display&q=DefaultLayoutForm&DisplayId=$displayid"><span>$msgDefault</span></button>
1530+ <button class="XiboFormButton" href="index.php?p=display&q=MediaInventory&DisplayId=$displayid"><span>$msgMediaInventory</span></button>
1531+END;
1532+ }
1533+ else
1534+ {
1535+ $buttons = '<button class="XiboFormButton" href="index.php?p=display&q=DefaultLayoutForm&DisplayId=' . $displayid . '"><span>' . $msgDefault . '</span></button>';
1536+ }
1537+
1538+>>>>>>> MERGE-SOURCE
1539 $output .= <<<END
1540
1541 <tr>
1542@@ -424,7 +463,12 @@
1543 <td>$loggedin</td>
1544 <td>$lastaccessed</td>
1545 <td>$clientAddress</td>
1546- <td>$buttons</td>
1547+<<<<<<< TREE
1548+ <td>$buttons</td>
1549+=======
1550+ <td>$mediaInventoryStatusLight</td>
1551+ <td>$buttons</td>
1552+>>>>>>> MERGE-SOURCE
1553 END;
1554 }
1555 $output .= "</tbody></table></div>";
1556@@ -661,64 +705,183 @@
1557 $response->SetFormSubmitResponse(__("The Display has been Deleted"));
1558 $response->Respond();
1559 }
1560-
1561- /**
1562- * Form for editing the default layout of a display
1563- */
1564- public function DefaultLayoutForm()
1565- {
1566- $db =& $this->db;
1567- $response = new ResponseManager();
1568-
1569- $displayId = Kit::GetParam('DisplayId', _GET, _INT);
1570-
1571- if (!$defaultLayoutId = $this->db->GetSingleValue(sprintf("SELECT defaultlayoutid FROM display WHERE displayid = %d", $displayId),
1572- 'defaultlayoutid', _INT))
1573- {
1574- trigger_error($db->error());
1575- trigger_error(__('Unable to get the default layout'), E_USER_ERROR);
1576- }
1577-
1578- $msgDefault = __('Default Layout');
1579- $layoutList = dropdownlist('SELECT layoutid, layout FROM layout WHERE retired = 0 ORDER by layout', 'defaultlayoutid', $defaultLayoutId);
1580-
1581- $form = <<<END
1582- <form id="DefaultLayoutForm" class="XiboForm" method="post" action="index.php?p=display&q=DefaultLayout&DisplayId=$displayId">
1583- <input type="hidden" name="DisplayId" value="$displayId">
1584- <table>
1585- <tr>
1586- <td>$msgDefault<span class="required">*</span></td>
1587- <td>$layoutList</td>
1588- </tr>
1589- </table>
1590- </form>
1591-END;
1592-
1593- $response->SetFormRequestResponse($form, __('Edit Default Layout'), '300px', '150px');
1594- $response->AddButton(__('Cancel'), 'XiboDialogClose()');
1595- $response->AddButton(__('Save'), '$("#DefaultLayoutForm").submit()');
1596- $response->Respond();
1597- }
1598-
1599- /**
1600- * Edit the default layout for a display
1601- */
1602- public function DefaultLayout()
1603- {
1604- $db =& $this->db;
1605- $response = new ResponseManager();
1606- $displayObject = new Display($db);
1607-
1608- $displayId = Kit::GetParam('DisplayId', _POST, _INT);
1609- $defaultLayoutId = Kit::GetParam('defaultlayoutid', _POST, _INT);
1610-
1611- if (!$displayObject->EditDefaultLayout($displayId, $defaultLayoutId))
1612- {
1613- trigger_error(__('Cannot Edit this Display'), E_USER_ERROR);
1614- }
1615-
1616- $response->SetFormSubmitResponse(__('Display Saved.'));
1617- $response->Respond();
1618- }
1619+<<<<<<< TREE
1620+
1621+ /**
1622+ * Form for editing the default layout of a display
1623+ */
1624+ public function DefaultLayoutForm()
1625+ {
1626+ $db =& $this->db;
1627+ $response = new ResponseManager();
1628+
1629+ $displayId = Kit::GetParam('DisplayId', _GET, _INT);
1630+
1631+ if (!$defaultLayoutId = $this->db->GetSingleValue(sprintf("SELECT defaultlayoutid FROM display WHERE displayid = %d", $displayId),
1632+ 'defaultlayoutid', _INT))
1633+ {
1634+ trigger_error($db->error());
1635+ trigger_error(__('Unable to get the default layout'), E_USER_ERROR);
1636+ }
1637+
1638+ $msgDefault = __('Default Layout');
1639+ $layoutList = dropdownlist('SELECT layoutid, layout FROM layout WHERE retired = 0 ORDER by layout', 'defaultlayoutid', $defaultLayoutId);
1640+
1641+ $form = <<<END
1642+ <form id="DefaultLayoutForm" class="XiboForm" method="post" action="index.php?p=display&q=DefaultLayout&DisplayId=$displayId">
1643+ <input type="hidden" name="DisplayId" value="$displayId">
1644+ <table>
1645+ <tr>
1646+ <td>$msgDefault<span class="required">*</span></td>
1647+ <td>$layoutList</td>
1648+ </tr>
1649+ </table>
1650+ </form>
1651+END;
1652+
1653+ $response->SetFormRequestResponse($form, __('Edit Default Layout'), '300px', '150px');
1654+ $response->AddButton(__('Cancel'), 'XiboDialogClose()');
1655+ $response->AddButton(__('Save'), '$("#DefaultLayoutForm").submit()');
1656+ $response->Respond();
1657+ }
1658+
1659+ /**
1660+ * Edit the default layout for a display
1661+ */
1662+ public function DefaultLayout()
1663+ {
1664+ $db =& $this->db;
1665+ $response = new ResponseManager();
1666+ $displayObject = new Display($db);
1667+
1668+ $displayId = Kit::GetParam('DisplayId', _POST, _INT);
1669+ $defaultLayoutId = Kit::GetParam('defaultlayoutid', _POST, _INT);
1670+
1671+ if (!$displayObject->EditDefaultLayout($displayId, $defaultLayoutId))
1672+ {
1673+ trigger_error(__('Cannot Edit this Display'), E_USER_ERROR);
1674+ }
1675+
1676+ $response->SetFormSubmitResponse(__('Display Saved.'));
1677+ $response->Respond();
1678+ }
1679+=======
1680+
1681+ /**
1682+ * Form for editing the default layout of a display
1683+ */
1684+ public function DefaultLayoutForm()
1685+ {
1686+ $db =& $this->db;
1687+ $response = new ResponseManager();
1688+
1689+ $displayId = Kit::GetParam('DisplayId', _GET, _INT);
1690+
1691+ if (!$defaultLayoutId = $this->db->GetSingleValue(sprintf("SELECT defaultlayoutid FROM display WHERE displayid = %d", $displayId),
1692+ 'defaultlayoutid', _INT))
1693+ {
1694+ trigger_error($db->error());
1695+ trigger_error(__('Unable to get the default layout'), E_USER_ERROR);
1696+ }
1697+
1698+ $msgDefault = __('Default Layout');
1699+ $layoutList = dropdownlist('SELECT layoutid, layout FROM layout WHERE retired = 0 ORDER by layout', 'defaultlayoutid', $defaultLayoutId);
1700+
1701+ $form = <<<END
1702+ <form id="DefaultLayoutForm" class="XiboForm" method="post" action="index.php?p=display&q=DefaultLayout&DisplayId=$displayId">
1703+ <input type="hidden" name="DisplayId" value="$displayId">
1704+ <table>
1705+ <tr>
1706+ <td>$msgDefault<span class="required">*</span></td>
1707+ <td>$layoutList</td>
1708+ </tr>
1709+ </table>
1710+ </form>
1711+END;
1712+
1713+ $response->SetFormRequestResponse($form, __('Edit Default Layout'), '300px', '150px');
1714+ $response->AddButton(__('Cancel'), 'XiboDialogClose()');
1715+ $response->AddButton(__('Save'), '$("#DefaultLayoutForm").submit()');
1716+ $response->Respond();
1717+ }
1718+
1719+ /**
1720+ * Edit the default layout for a display
1721+ */
1722+ public function DefaultLayout()
1723+ {
1724+ $db =& $this->db;
1725+ $response = new ResponseManager();
1726+ $displayObject = new Display($db);
1727+
1728+ $displayId = Kit::GetParam('DisplayId', _POST, _INT);
1729+ $defaultLayoutId = Kit::GetParam('defaultlayoutid', _POST, _INT);
1730+
1731+ if (!$displayObject->EditDefaultLayout($displayId, $defaultLayoutId))
1732+ {
1733+ trigger_error(__('Cannot Edit this Display'), E_USER_ERROR);
1734+ }
1735+
1736+ $response->SetFormSubmitResponse(__('Display Saved.'));
1737+ $response->Respond();
1738+ }
1739+
1740+ /**
1741+ * Shows the inventory XML for the display
1742+ */
1743+ public function MediaInventory()
1744+ {
1745+ $db =& $this->db;
1746+ $response = new ResponseManager();
1747+ $displayId = Kit::GetParam('DisplayId', _GET, _INT);
1748+
1749+ if ($displayId == 0)
1750+ trigger_error(__('No DisplayId Given'));
1751+
1752+ // Get the media inventory xml for this display
1753+ $SQL = "SELECT MediaInventoryXml FROM display WHERE DisplayId = %d";
1754+ $SQL = sprintf($SQL, $displayId);
1755+
1756+ if (!$mediaInventoryXml = $db->GetSingleValue($SQL, 'MediaInventoryXml', _HTMLSTRING))
1757+ {
1758+ trigger_error($db->error());
1759+ trigger_error(__('Unable to get the Inventory for this Display'), E_USER_ERROR);
1760+ }
1761+
1762+ // Load the XML into a DOMDocument
1763+ $document = new DOMDocument("1.0");
1764+
1765+ if (!$document->loadXML($mediaInventoryXml))
1766+ trigger_error(__('Invalid Media Inventory'), E_USER_ERROR);
1767+
1768+ // Output a table
1769+ $table = '<table><tr><th>Type</th><th>Id</th><th>Complete</th><th>Last Checked</th><th>MD5</th></tr>';
1770+
1771+ $xpath = new DOMXPath($document);
1772+ $fileNodes = $xpath->query("//file");
1773+
1774+ foreach ($fileNodes as $node)
1775+ {
1776+ $type = $node->getAttribute('type');
1777+ $id = $node->getAttribute('id');
1778+ $complete = $node->getAttribute('complete');
1779+ $lastChecked = $node->getAttribute('lastChecked');
1780+ $md5 = $node->getAttribute('md5');
1781+
1782+ if ($complete == 0)
1783+ $complete = __('No');
1784+ else
1785+ $complete = __('Yes');
1786+
1787+ $table .= sprintf('<tr><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td>', $type, $id, $complete, $lastChecked, $md5);
1788+ }
1789+
1790+ $table .= '</table>';
1791+
1792+ $response->SetFormRequestResponse($table, __('Media Inventory'), '550px', '350px');
1793+ $response->AddButton(__('Close'), 'XiboDialogClose()');
1794+ $response->Respond();
1795+ }
1796+>>>>>>> MERGE-SOURCE
1797 }
1798 ?>
1799
1800=== modified file 'server/lib/pages/layout.class.php'
1801--- server/lib/pages/layout.class.php 2011-02-28 15:58:42 +0000
1802+++ server/lib/pages/layout.class.php 2011-03-03 10:16:18 +0000
1803@@ -325,6 +325,12 @@
1804 trigger_error($layoutObject->GetErrorMessage(), E_USER_ERROR);
1805 }
1806
1807+ // Notify (dont error)
1808+ Kit::ClassLoader('display');
1809+ $displayObject = new Display($db);
1810+ $displayObject->NotifyDisplays($this->layoutid);
1811+
1812+
1813 $response->SetFormSubmitResponse(__('Layout Details Changed.'));
1814 $response->Respond();
1815 }
1816
1817=== modified file 'server/lib/pages/region.class.php'
1818--- server/lib/pages/region.class.php 2010-05-29 11:16:24 +0000
1819+++ server/lib/pages/region.class.php 2011-03-03 10:16:18 +0000
1820@@ -76,6 +76,11 @@
1821 $this->errMsg = __("Unable to Update that layouts XML with a new Media Node");
1822 return false;
1823 }
1824+
1825+ // Notify (dont error)
1826+ Kit::ClassLoader('display');
1827+ $displayObject = new Display($db);
1828+ $displayObject->NotifyDisplays($layoutid);
1829
1830 return true;
1831 }
1832
1833=== modified file 'server/lib/service/service.wsdl'
1834--- server/lib/service/service.wsdl 2010-01-31 00:38:32 +0000
1835+++ server/lib/service/service.wsdl 2011-03-03 10:16:18 +0000
1836@@ -80,6 +80,15 @@
1837 <message name="SubmitStatsResponse">
1838 <part name="success" type="xsd:boolean" />
1839 </message>
1840+ <message name="MediaInventoryRequest">
1841+ <part name="version" type="xsd:string" />
1842+ <part name="serverKey" type="xsd:string" />
1843+ <part name="hardwareKey" type="xsd:string" />
1844+ <part name="mediaInventory" type="xsd:string" />
1845+ </message>
1846+ <message name="MediaInventoryResponse">
1847+ <part name="success" type="xsd:boolean" />
1848+ </message>
1849 <portType name="xmdsPortType">
1850 <operation name="RegisterDisplay">
1851 <documentation>Registered the Display on the Xibo Network</documentation>
1852@@ -121,6 +130,11 @@
1853 <input message="tns:SubmitStatsRequest"/>
1854 <output message="tns:SubmitStatsResponse"/>
1855 </operation>
1856+ <operation name="MediaInventory">
1857+ <documentation>Report back the clients MediaInventory</documentation>
1858+ <input message="tns:MediaInventoryRequest" />
1859+ <output message="tns:MediaInventoryResponse" />
1860+ </operation>
1861 </portType>
1862 <binding name="xmdsBinding" type="tns:xmdsPortType">
1863 <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
1864@@ -196,6 +210,15 @@
1865 <soap:body use="encoded" namespace="urn:xmds" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
1866 </output>
1867 </operation>
1868+ <operation name="MediaInventory">
1869+ <soap:operation soapAction="urn:xmds#MediaInventory" style="rpc"/>
1870+ <input>
1871+ <soap:body use="encoded" namespace="urn:xmds" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
1872+ </input>
1873+ <output>
1874+ <soap:body use="encoded" namespace="urn:xmds" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
1875+ </output>
1876+ </operation>
1877 </binding>
1878 <service name="xmds">
1879 <port name="xmdsPort" binding="tns:xmdsBinding">
1880
1881=== modified file 'server/lib/service/xmdssoap.class.php'
1882--- server/lib/service/xmdssoap.class.php 2011-02-28 15:58:42 +0000
1883+++ server/lib/service/xmdssoap.class.php 2011-03-03 10:16:18 +0000
1884@@ -848,6 +848,66 @@
1885 }
1886
1887 /**
1888+ * Store the media inventory for a client
1889+ * @param <type> $hardwareKey
1890+ * @param <type> $inventory
1891+ */
1892+ public function MediaInventory($version, $serverKey, $hardwareKey, $inventory)
1893+ {
1894+ $db =& $this->db;
1895+
1896+ // Sanitize
1897+ $serverKey = Kit::ValidateParam($serverKey, _STRING);
1898+ $hardwareKey = Kit::ValidateParam($hardwareKey, _STRING);
1899+ $version = Kit::ValidateParam($version, _STRING);
1900+ $inventory = Kit::ValidateParam($inventory, _HTMLSTRING);
1901+
1902+ // Make sure we are talking the same language
1903+ if (!$this->CheckVersion($version))
1904+ throw new SoapFault('Receiver', "Your client is not of the correct version for communication with this server. You can get the latest from http://www.xibo.org.uk");
1905+
1906+ // Auth this request...
1907+ if (!$this->AuthDisplay($hardwareKey))
1908+ throw new SoapFault('Receiver', 'This display client is not licensed');
1909+
1910+ if ($this->isAuditing == 1) Debug::LogEntry ($db, 'audit', $inventory, 'xmds', 'MediaInventory', '', $this->displayId);
1911+
1912+ // Check that the $inventory contains something
1913+ if ($inventory == '')
1914+ throw new SoapFault('Receiver', 'Inventory Cannot be Empty');
1915+
1916+ // Load the XML into a DOMDocument
1917+ $document = new DOMDocument("1.0");
1918+ $document->loadXML($inventory);
1919+
1920+ // Assume we are complete (but we are getting some)
1921+ $mediaInventoryComplete = 1;
1922+
1923+ $xpath = new DOMXPath($document);
1924+ $fileNodes = $xpath->query("//file");
1925+
1926+ foreach ($fileNodes as $node)
1927+ {
1928+ $mediaId = $node->getAttribute('id');
1929+ $complete = $node->getAttribute('complete');
1930+ $md5 = $node->getAttribute('md5');
1931+ $lastChecked = $node->getAttribute('lastChecked');
1932+
1933+ // TODO: Check the MD5?
1934+
1935+ // If this item is a 0 then set not complete
1936+ if ($complete == 0)
1937+ $mediaInventoryComplete = 2;
1938+ }
1939+
1940+ // Touch the display record
1941+ $displayObject = new Display($db);
1942+ $displayObject->Touch($hardwareKey, '', $mediaInventoryComplete, $inventory);
1943+
1944+ return true;
1945+ }
1946+
1947+ /**
1948 * Authenticates the display
1949 * @param <type> $hardwareKey
1950 * @return <type>
1951
1952=== modified file 'server/modules/module_db_mysql.php'
1953--- server/modules/module_db_mysql.php 2010-09-22 20:11:36 +0000
1954+++ server/modules/module_db_mysql.php 2011-03-03 10:16:18 +0000
1955@@ -156,7 +156,7 @@
1956
1957 if (!isset($row[$columnName]))
1958 {
1959- $this->error_text = 'No such column';
1960+ $this->error_text = 'No such column or column is null';
1961 return false;
1962 }
1963

Subscribers

People subscribed via source and target branches

to status/vote changes: