Merge lp:~dangarner/xibo/1.2.2-pre into lp:xibo/1.2
- 1.2.2-pre
- Merge into biela
Proposed by
Dan Garner
Status: | Merged | ||||
---|---|---|---|---|---|
Merged at revision: | 213 | ||||
Proposed branch: | lp:~dangarner/xibo/1.2.2-pre | ||||
Merge into: | lp:xibo/1.2 | ||||
Diff against target: |
1513 lines (+770/-99) 24 files modified
client/dotNET/CacheManager.cs (+75/-1) client/dotNET/FileCollector.cs (+50/-29) 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 (+6/-7) 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 (+4/-1) client/dotNET/bin/Release/XiboClient.vshost.exe.config (+4/-1) server/install/database/27.sql (+9/-0) server/lib/app/kit.class.php (+9/-13) server/lib/data/display.data.class.php (+60/-16) server/lib/data/schedule.data.class.php (+5/-0) server/lib/pages/display.class.php (+74/-4) 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) |
||||
To merge this branch: | bzr merge lp:~dangarner/xibo/1.2.2-pre | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Xibo Maintainters | Pending | ||
Review via email: mp+51554@code.launchpad.net |
Commit message
Description of the change
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-02-28 15:09:32 +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-02-28 15:09:32 +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,18 +237,24 @@ |
220 | } |
221 | } |
222 | |
223 | - Debug.WriteLine(String.Format("There are {0} files to get", files.Count.ToString())); |
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 | string debugMessage = ""; |
228 | |
229 | - foreach (FileList fileToGet in files) |
230 | + foreach (RequiredFile fileToGet in _files) |
231 | debugMessage += string.Format("File: {0}, Type: {1}, MD5: {2}. ", fileToGet.path, fileToGet.type, fileToGet.md5); |
232 | |
233 | Debug.WriteLine(debugMessage); |
234 | |
235 | + // Report the files files back to XMDS |
236 | + _requiredFiles.ReportInventory(); |
237 | + |
238 | + // Write Required Files |
239 | + _requiredFiles.WriteRequiredFiles(); |
240 | + |
241 | // Is there anything to get? |
242 | - if (files.Count == 0) |
243 | + if (_files.Count == 0) |
244 | { |
245 | CollectionComplete(); |
246 | return; |
247 | @@ -255,7 +264,7 @@ |
248 | _currentFile = 0; |
249 | |
250 | // Preload the first filelist |
251 | - _currentFileList = files[_currentFile]; |
252 | + _currentFileList = _files[_currentFile]; |
253 | |
254 | // Get the first file |
255 | GetFile(); |
256 | @@ -375,6 +384,10 @@ |
257 | { |
258 | // Add to the CacheManager |
259 | _cacheManager.Add(_currentFileList.path + ".xlf", md5sum); |
260 | + |
261 | + // Report this completion back to XMDS |
262 | + _requiredFiles.MarkComplete(int.Parse(_currentFileList.path), md5sum); |
263 | + _requiredFiles.ReportInventory(); |
264 | } |
265 | |
266 | // Fire a layout complete event |
267 | @@ -445,6 +458,11 @@ |
268 | |
269 | System.Diagnostics.Debug.WriteLine(string.Format("File downloaded: {0}", _currentFileList.path)); |
270 | |
271 | + // Report this completion back to XMDS |
272 | + string[] filePart = _currentFileList.path.Split('.'); |
273 | + _requiredFiles.MarkComplete(int.Parse(filePart[0]), md5sum); |
274 | + _requiredFiles.ReportInventory(); |
275 | + |
276 | // All the file has been recieved. Move on to the next file. |
277 | _currentFile++; |
278 | } |
279 | @@ -475,13 +493,16 @@ |
280 | /// </summary> |
281 | public void GetFile() |
282 | { |
283 | - if (_currentFile > (files.Count - 1)) |
284 | + if (_currentFile > (_files.Count - 1)) |
285 | { |
286 | - System.Diagnostics.Debug.WriteLine(String.Format("Finished Recieving {0} files", files.Count)); |
287 | + System.Diagnostics.Debug.WriteLine(String.Format("Finished Receiving {0} files", _files.Count)); |
288 | |
289 | // Clean up |
290 | - files.Clear(); |
291 | - xmdsFile.Dispose(); |
292 | + _files.Clear(); |
293 | + xmdsFile.Dispose(); |
294 | + |
295 | + // Write Required Files |
296 | + _requiredFiles.WriteRequiredFiles(); |
297 | |
298 | // Finished getting this file list |
299 | CollectionComplete(); |
300 | @@ -491,7 +512,7 @@ |
301 | // Get the current file into the currentfilelist if the current one is finished |
302 | if (_currentFileList.complete) |
303 | { |
304 | - _currentFileList = files[_currentFile]; |
305 | + _currentFileList = _files[_currentFile]; |
306 | } |
307 | |
308 | System.Diagnostics.Debug.WriteLine(String.Format("Getting the file : {0} chunk : {1}", _currentFileList.path, _currentFileList.chunkOffset.ToString())); |
309 | @@ -504,7 +525,7 @@ |
310 | } |
311 | |
312 | [Serializable] |
313 | - private struct FileList |
314 | + private struct RequiredFile |
315 | { |
316 | public string path; |
317 | public string type; |
318 | @@ -519,9 +540,9 @@ |
319 | |
320 | private XmlDocument xml; |
321 | private HardwareKey hardwareKey; |
322 | - private Collection<FileList> files; |
323 | + private Collection<RequiredFile> _files; |
324 | private int _currentFile; |
325 | - private FileList _currentFileList; |
326 | + private RequiredFile _currentFileList; |
327 | private xmds.xmds xmdsFile; |
328 | |
329 | public event LayoutFileChangedDelegate LayoutFileChanged; |
330 | |
331 | === modified file 'client/dotNET/MainForm.cs' |
332 | --- client/dotNET/MainForm.cs 2011-01-30 18:13:32 +0000 |
333 | +++ client/dotNET/MainForm.cs 2011-02-28 15:09:32 +0000 |
334 | @@ -72,14 +72,45 @@ |
335 | |
336 | _statLog = new StatLog(); |
337 | |
338 | + this.FormClosing += new FormClosingEventHandler(MainForm_FormClosing); |
339 | + this.Shown += new EventHandler(MainForm_Shown); |
340 | + } |
341 | + |
342 | + /// <summary> |
343 | + /// Called after the form has been shown |
344 | + /// </summary> |
345 | + /// <param name="sender"></param> |
346 | + /// <param name="e"></param> |
347 | + void MainForm_Shown(object sender, EventArgs e) |
348 | + { |
349 | + // Process any stuff that has happened during the loading process |
350 | + Application.DoEvents(); |
351 | + |
352 | // Create a cachemanager |
353 | SetCacheManager(); |
354 | |
355 | - this.FormClosing += new FormClosingEventHandler(MainForm_FormClosing); |
356 | + try |
357 | + { |
358 | + // Create the Schedule |
359 | + _schedule = new Schedule(Application.UserAppDataPath + "\\" + Properties.Settings.Default.ScheduleFile, ref _cacheManager); |
360 | + |
361 | + // Bind to the schedule change event - notifys of changes to the schedule |
362 | + _schedule.ScheduleChangeEvent += new Schedule.ScheduleChangeDelegate(schedule_ScheduleChangeEvent); |
363 | + |
364 | + // Initialize the other schedule components |
365 | + _schedule.InitializeComponents(); |
366 | + } |
367 | + catch (Exception ex) |
368 | + { |
369 | + Debug.WriteLine(ex.Message, LogType.Error.ToString()); |
370 | + MessageBox.Show("Fatal Error initialising the application", "Fatal Error"); |
371 | + Close(); |
372 | + Dispose(); |
373 | + } |
374 | } |
375 | |
376 | /// <summary> |
377 | - /// Called when the form has finished loading |
378 | + /// Called before the form has loaded for the first time |
379 | /// </summary> |
380 | /// <param name="sender"></param> |
381 | /// <param name="e"></param> |
382 | @@ -96,30 +127,13 @@ |
383 | Cursor.Position = new Point(_clientSize.Width, _clientSize.Height); |
384 | Cursor.Hide(); |
385 | |
386 | + ShowSplashScreen(); |
387 | + |
388 | // Change the default Proxy class |
389 | OptionForm.SetGlobalProxy(); |
390 | |
391 | // UserApp data |
392 | Debug.WriteLine(new LogMessage("MainForm_Load", "User AppData Path: " + Application.UserAppDataPath), LogType.Info.ToString()); |
393 | - |
394 | - try |
395 | - { |
396 | - // Create the Schedule |
397 | - _schedule = new Schedule(Application.UserAppDataPath + "\\" + Properties.Settings.Default.ScheduleFile, ref _cacheManager); |
398 | - |
399 | - // Bind to the schedule change event - notifys of changes to the schedule |
400 | - _schedule.ScheduleChangeEvent += new Schedule.ScheduleChangeDelegate(schedule_ScheduleChangeEvent); |
401 | - |
402 | - // Initialize the other schedule components |
403 | - _schedule.InitializeComponents(); |
404 | - } |
405 | - catch (Exception ex) |
406 | - { |
407 | - Debug.WriteLine(ex.Message, LogType.Error.ToString()); |
408 | - MessageBox.Show("Fatal Error initialising the application", "Fatal Error"); |
409 | - Close(); |
410 | - Dispose(); |
411 | - } |
412 | } |
413 | |
414 | private void MainForm_FormClosing(object sender, FormClosingEventArgs e) |
415 | @@ -152,11 +166,20 @@ |
416 | } |
417 | catch (Exception ex) |
418 | { |
419 | - Trace.WriteLine(new LogMessage("Schedule", "Unable to reuse the Cache Manager because: " + ex.Message)); |
420 | + Trace.WriteLine(new LogMessage("MainForm - SetCacheManager", "Unable to reuse the Cache Manager because: " + ex.Message)); |
421 | |
422 | // Create a new cache manager |
423 | _cacheManager = new CacheManager(); |
424 | } |
425 | + |
426 | + try |
427 | + { |
428 | + _cacheManager.Regenerate(); |
429 | + } |
430 | + catch (Exception ex) |
431 | + { |
432 | + Trace.WriteLine(new LogMessage("MainForm - SetCacheManager", "Regenerate failed because: " + ex.Message)); |
433 | + } |
434 | } |
435 | |
436 | /// <summary> |
437 | |
438 | === modified file 'client/dotNET/Properties/Settings.Designer.cs' |
439 | --- client/dotNET/Properties/Settings.Designer.cs 2011-02-14 16:21:56 +0000 |
440 | +++ client/dotNET/Properties/Settings.Designer.cs 2011-02-28 15:09:32 +0000 |
441 | @@ -271,7 +271,7 @@ |
442 | |
443 | [global::System.Configuration.ApplicationScopedSettingAttribute()] |
444 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] |
445 | - [global::System.Configuration.DefaultSettingValueAttribute("1.2.1")] |
446 | + [global::System.Configuration.DefaultSettingValueAttribute("1.2.2")] |
447 | public string ClientVersion { |
448 | get { |
449 | return ((string)(this["ClientVersion"])); |
450 | @@ -370,5 +370,17 @@ |
451 | this["emptyLayoutDuration"] = value; |
452 | } |
453 | } |
454 | + |
455 | + [global::System.Configuration.UserScopedSettingAttribute()] |
456 | + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] |
457 | + [global::System.Configuration.DefaultSettingValueAttribute("requiredFiles.xml")] |
458 | + public string RequiredFilesFile { |
459 | + get { |
460 | + return ((string)(this["RequiredFilesFile"])); |
461 | + } |
462 | + set { |
463 | + this["RequiredFilesFile"] = value; |
464 | + } |
465 | + } |
466 | } |
467 | } |
468 | |
469 | === modified file 'client/dotNET/Properties/Settings.settings' |
470 | --- client/dotNET/Properties/Settings.settings 2011-02-14 16:21:56 +0000 |
471 | +++ client/dotNET/Properties/Settings.settings 2011-02-28 15:09:32 +0000 |
472 | @@ -69,7 +69,7 @@ |
473 | <Value Profile="(Default)">cacheManager.xml</Value> |
474 | </Setting> |
475 | <Setting Name="ClientVersion" Type="System.String" Scope="Application"> |
476 | - <Value Profile="(Default)">1.2.1</Value> |
477 | + <Value Profile="(Default)">1.2.2</Value> |
478 | </Setting> |
479 | <Setting Name="scrollStepAmount" Type="System.Decimal" Scope="User"> |
480 | <Value Profile="(Default)">1</Value> |
481 | @@ -95,5 +95,8 @@ |
482 | <Setting Name="emptyLayoutDuration" Type="System.Decimal" Scope="User"> |
483 | <Value Profile="(Default)">10</Value> |
484 | </Setting> |
485 | + <Setting Name="RequiredFilesFile" Type="System.String" Scope="User"> |
486 | + <Value Profile="(Default)">requiredFiles.xml</Value> |
487 | + </Setting> |
488 | </Settings> |
489 | </SettingsFile> |
490 | \ No newline at end of file |
491 | |
492 | === modified file 'client/dotNET/Region.cs' |
493 | --- client/dotNET/Region.cs 2010-11-09 21:23:31 +0000 |
494 | +++ client/dotNET/Region.cs 2011-02-28 15:09:32 +0000 |
495 | @@ -310,12 +310,11 @@ |
496 | } |
497 | |
498 | // We cannot have a 0 duration here... not sure why we would... but |
499 | - if (options.duration == 0) |
500 | - options.duration = int.Parse(Properties.Settings.Default.emptyLayoutDuration.ToString()); |
501 | - |
502 | - // Fail safe |
503 | - if (options.duration == 0) |
504 | - options.duration = 10; |
505 | + if (options.duration == 0 && options.type != "video") |
506 | + { |
507 | + int emptyLayoutDuration = int.Parse(Properties.Settings.Default.emptyLayoutDuration.ToString()); |
508 | + options.duration = (emptyLayoutDuration == 0) ? 10 : emptyLayoutDuration; |
509 | + } |
510 | |
511 | // There will be some stuff on option nodes |
512 | XmlNode optionNode = mediaNode.FirstChild; |
513 | @@ -386,7 +385,7 @@ |
514 | if (options.type == "video" || options.type == "flash" || options.type == "image" || options.type == "powerpoint") |
515 | { |
516 | // Use the cache manager to determine if the file is valid |
517 | - validNode = _cacheManager.IsValid(options.uri); |
518 | + validNode = _cacheManager.IsValidPath(options.uri); |
519 | } |
520 | } |
521 | |
522 | |
523 | === added file 'client/dotNET/RequiredFiles.cs' |
524 | --- client/dotNET/RequiredFiles.cs 1970-01-01 00:00:00 +0000 |
525 | +++ client/dotNET/RequiredFiles.cs 2011-02-28 15:09:32 +0000 |
526 | @@ -0,0 +1,206 @@ |
527 | +/* |
528 | + * Xibo - Digitial Signage - http://www.xibo.org.uk |
529 | + * Copyright (C) 2011 Daniel Garner |
530 | + * |
531 | + * This file is part of Xibo. |
532 | + * |
533 | + * Xibo is free software: you can redistribute it and/or modify |
534 | + * it under the terms of the GNU Affero General Public License as published by |
535 | + * the Free Software Foundation, either version 3 of the License, or |
536 | + * any later version. |
537 | + * |
538 | + * Xibo is distributed in the hope that it will be useful, |
539 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
540 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
541 | + * GNU Affero General Public License for more details. |
542 | + * |
543 | + * You should have received a copy of the GNU Affero General Public License |
544 | + * along with Xibo. If not, see <http://www.gnu.org/licenses/>. |
545 | + */ |
546 | +using System; |
547 | +using System.Collections.Generic; |
548 | +using System.Collections.ObjectModel; |
549 | +using System.Text; |
550 | +using System.IO; |
551 | +using System.Security.Cryptography; |
552 | +using System.Xml; |
553 | +using System.Diagnostics; |
554 | +using System.Windows.Forms; |
555 | +using System.Xml.Serialization; |
556 | + |
557 | +namespace XiboClient |
558 | +{ |
559 | + public class RequiredFiles |
560 | + { |
561 | + private XmlDocument _requiredFilesXml; |
562 | + public Collection<RequiredFile> _requiredFiles; |
563 | + private xmds.xmds _report; |
564 | + |
565 | + public RequiredFiles() |
566 | + { |
567 | + _requiredFiles = new Collection<RequiredFile>(); |
568 | + |
569 | + // Create a webservice call |
570 | + _report = new XiboClient.xmds.xmds(); |
571 | + |
572 | + // Start up the Xmds Service Object |
573 | + _report.Credentials = null; |
574 | + _report.Url = Properties.Settings.Default.XiboClient_xmds_xmds; |
575 | + _report.UseDefaultCredentials = false; |
576 | + } |
577 | + |
578 | + /// <summary> |
579 | + /// Set required files from the XML document |
580 | + /// </summary> |
581 | + private void SetRequiredFiles() |
582 | + { |
583 | + // Itterate through the RF XML and populate the RF collection |
584 | + XmlNodeList fileNodes = _requiredFilesXml.SelectNodes("/files/file"); |
585 | + |
586 | + foreach (XmlNode file in fileNodes) |
587 | + { |
588 | + RequiredFile rf = new RequiredFile(); |
589 | + |
590 | + XmlAttributeCollection attributes = file.Attributes; |
591 | + |
592 | + rf.FileType = attributes["type"].Value; |
593 | + rf.Complete = 0; |
594 | + rf.Md5 = ""; |
595 | + rf.LastChecked = DateTime.Now; |
596 | + |
597 | + if (rf.FileType == "media") |
598 | + { |
599 | + string[] filePart = attributes["path"].Value.Split('.'); |
600 | + rf.Id = int.Parse(filePart[0]); |
601 | + rf.Path = attributes["path"].Value; |
602 | + } |
603 | + else if (rf.FileType == "layout") |
604 | + { |
605 | + rf.Id = int.Parse(attributes["path"].Value); |
606 | + rf.Path = attributes["path"].Value + ".xlf"; |
607 | + } |
608 | + else |
609 | + { |
610 | + continue; |
611 | + } |
612 | + |
613 | + _requiredFiles.Add(rf); |
614 | + } |
615 | + } |
616 | + |
617 | + /// <summary> |
618 | + /// Required Files XML |
619 | + /// </summary> |
620 | + public XmlDocument RequiredFilesXml |
621 | + { |
622 | + set |
623 | + { |
624 | + _requiredFilesXml = value; |
625 | + SetRequiredFiles(); |
626 | + } |
627 | + } |
628 | + |
629 | + /// <summary> |
630 | + /// Mark a RequiredFile as complete |
631 | + /// </summary> |
632 | + /// <param name="id"></param> |
633 | + /// <param name="md5"></param> |
634 | + public void MarkComplete(int id, string md5) |
635 | + { |
636 | + foreach (RequiredFile rf in _requiredFiles) |
637 | + { |
638 | + if (rf.Id == id) |
639 | + { |
640 | + RequiredFile newRf = rf; |
641 | + |
642 | + newRf.Complete = 1; |
643 | + newRf.Md5 = md5; |
644 | + |
645 | + |
646 | + _requiredFiles.Add(newRf); |
647 | + _requiredFiles.Remove(rf); |
648 | + |
649 | + return; |
650 | + } |
651 | + } |
652 | + } |
653 | + |
654 | + /// <summary> |
655 | + /// Mark a RequiredFile as incomplete |
656 | + /// </summary> |
657 | + /// <param name="id"></param> |
658 | + /// <param name="md5"></param> |
659 | + public void MarkIncomplete(int id, string md5) |
660 | + { |
661 | + foreach (RequiredFile rf in _requiredFiles) |
662 | + { |
663 | + if (rf.Id == id) |
664 | + { |
665 | + RequiredFile newRf = rf; |
666 | + |
667 | + newRf.Complete = 0; |
668 | + newRf.Md5 = md5; |
669 | + |
670 | + _requiredFiles.Add(newRf); |
671 | + _requiredFiles.Remove(rf); |
672 | + |
673 | + return; |
674 | + } |
675 | + } |
676 | + } |
677 | + |
678 | + /// <summary> |
679 | + /// Writes Required Files to disk |
680 | + /// </summary> |
681 | + public void WriteRequiredFiles() |
682 | + { |
683 | + Debug.WriteLine(new LogMessage("RequiredFiles - WriteRequiredFiles", "About to Write RequiredFiles"), LogType.Info.ToString()); |
684 | + |
685 | + try |
686 | + { |
687 | + using (StreamWriter streamWriter = new StreamWriter(Application.UserAppDataPath + "\\" + Properties.Settings.Default.RequiredFilesFile)) |
688 | + { |
689 | + XmlSerializer xmlSerializer = new XmlSerializer(typeof(RequiredFiles)); |
690 | + |
691 | + xmlSerializer.Serialize(streamWriter, this); |
692 | + } |
693 | + } |
694 | + catch (Exception ex) |
695 | + { |
696 | + System.Diagnostics.Trace.WriteLine(new LogMessage("RequiredFiles - WriteRequiredFiles", "Unable to write RequiredFiles to disk because: " + ex.Message)); |
697 | + } |
698 | + } |
699 | + |
700 | + /// <summary> |
701 | + /// Report Required Files to XMDS |
702 | + /// </summary> |
703 | + public void ReportInventory() |
704 | + { |
705 | + HardwareKey hardwareKey = new HardwareKey(); |
706 | + |
707 | + // Build the XML required by media file |
708 | + string xml = ""; |
709 | + |
710 | + foreach (RequiredFile rf in _requiredFiles) |
711 | + { |
712 | + xml += string.Format("<file type=\"{0}\" id=\"{1}\" complete=\"{2}\" lastChecked=\"{3}\" md5=\"{4}\" />", |
713 | + rf.FileType, rf.Id.ToString(), rf.Complete.ToString(), rf.LastChecked.ToString(), rf.Md5); |
714 | + } |
715 | + |
716 | + xml = string.Format("<files>{0}</files>", xml); |
717 | + |
718 | + _report.MediaInventoryAsync(Properties.Settings.Default.Version, Properties.Settings.Default.ServerKey, |
719 | + hardwareKey.Key, xml); |
720 | + } |
721 | + } |
722 | + |
723 | + public struct RequiredFile |
724 | + { |
725 | + public string FileType; |
726 | + public int Id; |
727 | + public int Complete; |
728 | + public DateTime LastChecked; |
729 | + public string Md5; |
730 | + public string Path; |
731 | + } |
732 | +} |
733 | |
734 | === modified file 'client/dotNET/Schedule.cs' |
735 | --- client/dotNET/Schedule.cs 2010-08-22 16:49:09 +0000 |
736 | +++ client/dotNET/Schedule.cs 2011-02-28 15:09:32 +0000 |
737 | @@ -74,7 +74,7 @@ |
738 | _cacheManager = cacheManager; |
739 | |
740 | // Create a schedule manager |
741 | - _scheduleManager = new ScheduleManager(scheduleLocation); |
742 | + _scheduleManager = new ScheduleManager(_cacheManager, scheduleLocation); |
743 | |
744 | // Create a new Xmds service object |
745 | _xmds2 = new XiboClient.xmds.xmds(); |
746 | |
747 | === modified file 'client/dotNET/ScheduleManager.cs' |
748 | --- client/dotNET/ScheduleManager.cs 2010-08-25 21:39:53 +0000 |
749 | +++ client/dotNET/ScheduleManager.cs 2011-02-28 15:09:32 +0000 |
750 | @@ -42,13 +42,15 @@ |
751 | private Collection<LayoutSchedule> _layoutSchedule; |
752 | private Collection<LayoutSchedule> _currentSchedule; |
753 | private bool _refreshSchedule; |
754 | + private CacheManager _cacheManager; |
755 | |
756 | /// <summary> |
757 | /// Creates a new schedule Manager |
758 | /// </summary> |
759 | /// <param name="scheduleLocation"></param> |
760 | - public ScheduleManager(string scheduleLocation) |
761 | + public ScheduleManager(CacheManager cacheManager, string scheduleLocation) |
762 | { |
763 | + _cacheManager = cacheManager; |
764 | _location = scheduleLocation; |
765 | |
766 | // Create an empty layout schedule |
767 | @@ -178,6 +180,19 @@ |
768 | // For each layout in the schedule determine if it is currently inside the _currentSchedule, and whether it should be |
769 | foreach (LayoutSchedule layout in _layoutSchedule) |
770 | { |
771 | + // Is the layout valid in the cachemanager? |
772 | + try |
773 | + { |
774 | + if (!_cacheManager.IsValidLayout(layout.id + ".xlf")) |
775 | + continue; |
776 | + } |
777 | + catch |
778 | + { |
779 | + // TODO: Ignore this layout.. raise an error? |
780 | + Trace.WriteLine("Unable to determine if layout is valid or not"); |
781 | + continue; |
782 | + } |
783 | + |
784 | // If this is the default, skip it |
785 | if (layout.NodeName == "default") |
786 | { |
787 | |
788 | === modified file 'client/dotNET/Web References/xmds/Reference.cs' |
789 | --- client/dotNET/Web References/xmds/Reference.cs 2010-11-09 21:23:31 +0000 |
790 | +++ client/dotNET/Web References/xmds/Reference.cs 2011-02-28 15:09:32 +0000 |
791 | @@ -45,6 +45,8 @@ |
792 | |
793 | private System.Threading.SendOrPostCallback SubmitStatsOperationCompleted; |
794 | |
795 | + private System.Threading.SendOrPostCallback MediaInventoryOperationCompleted; |
796 | + |
797 | private bool useDefaultCredentialsSetExplicitly; |
798 | |
799 | /// <remarks/> |
800 | @@ -108,6 +110,9 @@ |
801 | public event SubmitStatsCompletedEventHandler SubmitStatsCompleted; |
802 | |
803 | /// <remarks/> |
804 | + public event MediaInventoryCompletedEventHandler MediaInventoryCompleted; |
805 | + |
806 | + /// <remarks/> |
807 | [System.Web.Services.Protocols.SoapRpcMethodAttribute("urn:xmds#RegisterDisplay", RequestNamespace="urn:xmds", ResponseNamespace="urn:xmds")] |
808 | [return: System.Xml.Serialization.SoapElementAttribute("ActivationMessage")] |
809 | public string RegisterDisplay(string serverKey, string hardwareKey, string displayName, string version) { |
810 | @@ -402,6 +407,42 @@ |
811 | } |
812 | |
813 | /// <remarks/> |
814 | + [System.Web.Services.Protocols.SoapRpcMethodAttribute("urn:xmds#MediaInventory", RequestNamespace="urn:xmds", ResponseNamespace="urn:xmds")] |
815 | + [return: System.Xml.Serialization.SoapElementAttribute("success")] |
816 | + public bool MediaInventory(string version, string serverKey, string hardwareKey, [System.Xml.Serialization.SoapElementAttribute("mediaInventory")] string mediaInventory1) { |
817 | + object[] results = this.Invoke("MediaInventory", new object[] { |
818 | + version, |
819 | + serverKey, |
820 | + hardwareKey, |
821 | + mediaInventory1}); |
822 | + return ((bool)(results[0])); |
823 | + } |
824 | + |
825 | + /// <remarks/> |
826 | + public void MediaInventoryAsync(string version, string serverKey, string hardwareKey, string mediaInventory1) { |
827 | + this.MediaInventoryAsync(version, serverKey, hardwareKey, mediaInventory1, null); |
828 | + } |
829 | + |
830 | + /// <remarks/> |
831 | + public void MediaInventoryAsync(string version, string serverKey, string hardwareKey, string mediaInventory1, object userState) { |
832 | + if ((this.MediaInventoryOperationCompleted == null)) { |
833 | + this.MediaInventoryOperationCompleted = new System.Threading.SendOrPostCallback(this.OnMediaInventoryOperationCompleted); |
834 | + } |
835 | + this.InvokeAsync("MediaInventory", new object[] { |
836 | + version, |
837 | + serverKey, |
838 | + hardwareKey, |
839 | + mediaInventory1}, this.MediaInventoryOperationCompleted, userState); |
840 | + } |
841 | + |
842 | + private void OnMediaInventoryOperationCompleted(object arg) { |
843 | + if ((this.MediaInventoryCompleted != null)) { |
844 | + System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg)); |
845 | + this.MediaInventoryCompleted(this, new MediaInventoryCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState)); |
846 | + } |
847 | + } |
848 | + |
849 | + /// <remarks/> |
850 | public new void CancelAsync(object userState) { |
851 | base.CancelAsync(userState); |
852 | } |
853 | @@ -627,6 +668,32 @@ |
854 | } |
855 | } |
856 | } |
857 | + |
858 | + /// <remarks/> |
859 | + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "2.0.50727.4927")] |
860 | + public delegate void MediaInventoryCompletedEventHandler(object sender, MediaInventoryCompletedEventArgs e); |
861 | + |
862 | + /// <remarks/> |
863 | + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "2.0.50727.4927")] |
864 | + [System.Diagnostics.DebuggerStepThroughAttribute()] |
865 | + [System.ComponentModel.DesignerCategoryAttribute("code")] |
866 | + public partial class MediaInventoryCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { |
867 | + |
868 | + private object[] results; |
869 | + |
870 | + internal MediaInventoryCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) : |
871 | + base(exception, cancelled, userState) { |
872 | + this.results = results; |
873 | + } |
874 | + |
875 | + /// <remarks/> |
876 | + public bool Result { |
877 | + get { |
878 | + this.RaiseExceptionIfNecessary(); |
879 | + return ((bool)(this.results[0])); |
880 | + } |
881 | + } |
882 | + } |
883 | } |
884 | |
885 | #pragma warning restore 1591 |
886 | \ No newline at end of file |
887 | |
888 | === modified file 'client/dotNET/Web References/xmds/xmds.wsdl' |
889 | --- client/dotNET/Web References/xmds/xmds.wsdl 2010-11-09 21:23:31 +0000 |
890 | +++ client/dotNET/Web References/xmds/xmds.wsdl 2011-02-28 15:09:32 +0000 |
891 | @@ -81,6 +81,15 @@ |
892 | <wsdl:message name="SubmitStatsResponse"> |
893 | <wsdl:part name="success" type="xsd:boolean" /> |
894 | </wsdl:message> |
895 | + <wsdl:message name="MediaInventoryRequest"> |
896 | + <wsdl:part name="version" type="xsd:string" /> |
897 | + <wsdl:part name="serverKey" type="xsd:string" /> |
898 | + <wsdl:part name="hardwareKey" type="xsd:string" /> |
899 | + <wsdl:part name="mediaInventory" type="xsd:string" /> |
900 | + </wsdl:message> |
901 | + <wsdl:message name="MediaInventoryResponse"> |
902 | + <wsdl:part name="success" type="xsd:boolean" /> |
903 | + </wsdl:message> |
904 | <wsdl:portType name="xmdsPortType"> |
905 | <wsdl:operation name="RegisterDisplay"> |
906 | <documentation>Registered the Display on the Xibo Network</documentation> |
907 | @@ -122,6 +131,11 @@ |
908 | <wsdl:input message="tns:SubmitStatsRequest" /> |
909 | <wsdl:output message="tns:SubmitStatsResponse" /> |
910 | </wsdl:operation> |
911 | + <wsdl:operation name="MediaInventory"> |
912 | + <documentation>Report back the clients MediaInventory</documentation> |
913 | + <wsdl:input message="tns:MediaInventoryRequest" /> |
914 | + <wsdl:output message="tns:MediaInventoryResponse" /> |
915 | + </wsdl:operation> |
916 | </wsdl:portType> |
917 | <wsdl:binding name="xmdsBinding" type="tns:xmdsPortType"> |
918 | <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="rpc" /> |
919 | @@ -197,6 +211,15 @@ |
920 | <soap:body use="encoded" namespace="urn:xmds" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> |
921 | </wsdl:output> |
922 | </wsdl:operation> |
923 | + <wsdl:operation name="MediaInventory"> |
924 | + <soap:operation soapAction="urn:xmds#MediaInventory" style="rpc" /> |
925 | + <wsdl:input> |
926 | + <soap:body use="encoded" namespace="urn:xmds" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> |
927 | + </wsdl:input> |
928 | + <wsdl:output> |
929 | + <soap:body use="encoded" namespace="urn:xmds" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> |
930 | + </wsdl:output> |
931 | + </wsdl:operation> |
932 | </wsdl:binding> |
933 | <wsdl:service name="xmds"> |
934 | <wsdl:port name="xmdsPort" binding="tns:xmdsBinding"> |
935 | |
936 | === modified file 'client/dotNET/XiboClient.csproj' |
937 | --- client/dotNET/XiboClient.csproj 2011-02-09 17:15:43 +0000 |
938 | +++ client/dotNET/XiboClient.csproj 2011-02-28 15:09:32 +0000 |
939 | @@ -161,6 +161,7 @@ |
940 | <Compile Include="Region.cs"> |
941 | <SubType>Component</SubType> |
942 | </Compile> |
943 | + <Compile Include="RequiredFiles.cs" /> |
944 | <Compile Include="Rss.cs"> |
945 | <SubType>Form</SubType> |
946 | </Compile> |
947 | |
948 | === modified file 'client/dotNET/app.config' |
949 | --- client/dotNET/app.config 2011-02-14 16:21:56 +0000 |
950 | +++ client/dotNET/app.config 2011-02-28 15:09:32 +0000 |
951 | @@ -79,6 +79,9 @@ |
952 | <setting name="emptyLayoutDuration" serializeAs="String"> |
953 | <value>10</value> |
954 | </setting> |
955 | + <setting name="RequiredFilesFile" serializeAs="String"> |
956 | + <value>requiredFiles.xml</value> |
957 | + </setting> |
958 | </XiboClient.Properties.Settings> |
959 | </userSettings> |
960 | <applicationSettings> |
961 | @@ -102,7 +105,7 @@ |
962 | <value>cacheManager.xml</value> |
963 | </setting> |
964 | <setting name="ClientVersion" serializeAs="String"> |
965 | - <value>1.2.1</value> |
966 | + <value>1.2.2</value> |
967 | </setting> |
968 | <setting name="xmdsResetTimeout" serializeAs="String"> |
969 | <value>900</value> |
970 | |
971 | === modified file 'client/dotNET/bin/Release/AxInterop.ShockwaveFlashObjects.dll' |
972 | 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 |
973 | === modified file 'client/dotNET/bin/Release/AxInterop.WMPLib.dll' |
974 | 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 |
975 | === modified file 'client/dotNET/bin/Release/Interop.ShockwaveFlashObjects.dll' |
976 | 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 |
977 | === modified file 'client/dotNET/bin/Release/Interop.WMPLib.dll' |
978 | 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 |
979 | === modified file 'client/dotNET/bin/Release/XiboClient.exe.config' |
980 | --- client/dotNET/bin/Release/XiboClient.exe.config 2011-02-14 16:21:56 +0000 |
981 | +++ client/dotNET/bin/Release/XiboClient.exe.config 2011-02-28 15:09:32 +0000 |
982 | @@ -79,6 +79,9 @@ |
983 | <setting name="emptyLayoutDuration" serializeAs="String"> |
984 | <value>10</value> |
985 | </setting> |
986 | + <setting name="RequiredFilesFile" serializeAs="String"> |
987 | + <value>requiredFiles.xml</value> |
988 | + </setting> |
989 | </XiboClient.Properties.Settings> |
990 | </userSettings> |
991 | <applicationSettings> |
992 | @@ -102,7 +105,7 @@ |
993 | <value>cacheManager.xml</value> |
994 | </setting> |
995 | <setting name="ClientVersion" serializeAs="String"> |
996 | - <value>1.2.1</value> |
997 | + <value>1.2.2</value> |
998 | </setting> |
999 | <setting name="xmdsResetTimeout" serializeAs="String"> |
1000 | <value>900</value> |
1001 | |
1002 | === modified file 'client/dotNET/bin/Release/XiboClient.vshost.exe.config' |
1003 | --- client/dotNET/bin/Release/XiboClient.vshost.exe.config 2011-02-14 16:21:56 +0000 |
1004 | +++ client/dotNET/bin/Release/XiboClient.vshost.exe.config 2011-02-28 15:09:32 +0000 |
1005 | @@ -79,6 +79,9 @@ |
1006 | <setting name="emptyLayoutDuration" serializeAs="String"> |
1007 | <value>10</value> |
1008 | </setting> |
1009 | + <setting name="RequiredFilesFile" serializeAs="String"> |
1010 | + <value>requiredFiles.xml</value> |
1011 | + </setting> |
1012 | </XiboClient.Properties.Settings> |
1013 | </userSettings> |
1014 | <applicationSettings> |
1015 | @@ -102,7 +105,7 @@ |
1016 | <value>cacheManager.xml</value> |
1017 | </setting> |
1018 | <setting name="ClientVersion" serializeAs="String"> |
1019 | - <value>1.2.1</value> |
1020 | + <value>1.2.2</value> |
1021 | </setting> |
1022 | <setting name="xmdsResetTimeout" serializeAs="String"> |
1023 | <value>900</value> |
1024 | |
1025 | === added file 'server/install/database/27.sql' |
1026 | --- server/install/database/27.sql 1970-01-01 00:00:00 +0000 |
1027 | +++ server/install/database/27.sql 2011-02-28 15:09:32 +0000 |
1028 | @@ -0,0 +1,9 @@ |
1029 | + |
1030 | +ALTER TABLE `display` ADD `MediaInventoryStatus` TINYINT NOT NULL , |
1031 | +ADD `MediaInventoryXml` LONGTEXT NULL; |
1032 | + |
1033 | +/* VERSION UPDATE */ |
1034 | +/* Set the version table, etc */ |
1035 | +UPDATE `version` SET `app_ver` = '1.2.2-pre', `XmdsVersion` = 2; |
1036 | +UPDATE `setting` SET `value` = 0 WHERE `setting` = 'PHONE_HOME_DATE'; |
1037 | +UPDATE `version` SET `DBVersion` = '27'; |
1038 | \ No newline at end of file |
1039 | |
1040 | === modified file 'server/lib/app/kit.class.php' |
1041 | --- server/lib/app/kit.class.php 2010-12-01 14:49:39 +0000 |
1042 | +++ server/lib/app/kit.class.php 2011-02-28 15:09:32 +0000 |
1043 | @@ -376,9 +376,7 @@ |
1044 | static function ClassLoader($class) |
1045 | { |
1046 | if (class_exists($class)) |
1047 | - { |
1048 | - return true; |
1049 | - } |
1050 | + return; |
1051 | |
1052 | $class = strtolower($class); |
1053 | |
1054 | @@ -387,28 +385,26 @@ |
1055 | { |
1056 | include_once('lib/pages/' . $class . '.class.php'); |
1057 | } |
1058 | - elseif (file_exists('lib/data/' . $class . '.data.class.php')) |
1059 | + |
1060 | + if (file_exists('lib/data/' . $class . '.data.class.php')) |
1061 | { |
1062 | include_once('lib/data/' . $class . '.data.class.php'); |
1063 | } |
1064 | - elseif (file_exists('modules/' . $class . '.module.php')) |
1065 | + |
1066 | + if (file_exists('modules/' . $class . '.module.php')) |
1067 | { |
1068 | include_once('modules/' . $class . '.module.php'); |
1069 | } |
1070 | - elseif (file_exists('modules/' . $class . '.php')) |
1071 | + |
1072 | + if (file_exists('modules/' . $class . '.php')) |
1073 | { |
1074 | include_once('modules/' . $class . '.php'); |
1075 | } |
1076 | - elseif (file_exists('lib/service/' . $class . '.class.php')) |
1077 | + |
1078 | + if (file_exists('lib/service/' . $class . '.class.php')) |
1079 | { |
1080 | include_once('lib/service/' . $class . '.class.php'); |
1081 | } |
1082 | - else |
1083 | - { |
1084 | - return false; |
1085 | - } |
1086 | - |
1087 | - return true; |
1088 | } |
1089 | |
1090 | /** |
1091 | |
1092 | === modified file 'server/lib/data/display.data.class.php' |
1093 | --- server/lib/data/display.data.class.php 2011-02-10 20:42:24 +0000 |
1094 | +++ server/lib/data/display.data.class.php 2011-02-28 15:09:32 +0000 |
1095 | @@ -251,7 +251,7 @@ |
1096 | * @return |
1097 | * @param $license Object |
1098 | */ |
1099 | - public function Touch($license, $clientAddress = '') |
1100 | + public function Touch($license, $clientAddress = '', $mediaInventoryComplete = 0, $mediaInventoryXml = '') |
1101 | { |
1102 | $db =& $this->db; |
1103 | $time = time(); |
1104 | @@ -266,6 +266,13 @@ |
1105 | if ($clientAddress != '') |
1106 | $SQL .= sprintf(" , ClientAddress = '%s' ", $db->escape_string($clientAddress)); |
1107 | |
1108 | + // Media Inventory Settings (if appropriate) |
1109 | + if ($mediaInventoryComplete != 0) |
1110 | + $SQL .= sprintf(" , MediaInventoryStatus = %d ", $mediaInventoryComplete); |
1111 | + |
1112 | + if ($mediaInventoryXml != '') |
1113 | + $SQL .= sprintf(" , MediaInventoryXml = '%s' ", $mediaInventoryXml); |
1114 | + |
1115 | // Restrict to the display license |
1116 | $SQL .= " WHERE license = '%s'"; |
1117 | $SQL = sprintf($SQL, $time, $license); |
1118 | @@ -284,31 +291,68 @@ |
1119 | } |
1120 | |
1121 | /** |
1122 | - * Edits the default layout for a display |
1123 | + * Flags a display as being incomplete |
1124 | * @param <type> $displayId |
1125 | - * @param <type> $defaultLayoutId |
1126 | - * @return <type> |
1127 | */ |
1128 | - public function EditDefaultLayout($displayId, $defaultLayoutId) |
1129 | + private function FlagIncomplete($displayId) |
1130 | { |
1131 | - $db =& $this->db; |
1132 | - |
1133 | - Debug::LogEntry($db, 'audit', 'IN', 'Display', 'EditDefaultLayout'); |
1134 | - |
1135 | - $SQL = sprintf('UPDATE display SET defaultLayoutId = %d WHERE displayID = %d ', $defaultLayoutId, $displayId); |
1136 | + $db =& $this->db; |
1137 | + |
1138 | + Debug::LogEntry($db, 'audit', sprintf('Flag DisplayID %d incomplete.', $displayId), 'display', 'NotifyDisplays'); |
1139 | + |
1140 | + $SQL = sprintf("UPDATE display SET MediaInventoryStatus = 3 WHERE displayID = %d", $displayId); |
1141 | |
1142 | if (!$db->query($SQL)) |
1143 | { |
1144 | trigger_error($db->error()); |
1145 | - $this->SetError(25012, __('Error updating this displays default layout.')); |
1146 | - |
1147 | - return false; |
1148 | + return $this->SetError(25004, 'Unable to Flag Display as incomplete'); |
1149 | } |
1150 | |
1151 | - |
1152 | - Debug::LogEntry($db, 'audit', 'OUT', 'Display', 'EditDefaultLayout'); |
1153 | - |
1154 | return true; |
1155 | } |
1156 | + |
1157 | + /** |
1158 | + * Notify displays of this layout change |
1159 | + * @param <type> $layoutId |
1160 | + */ |
1161 | + public function NotifyDisplays($layoutId) |
1162 | + { |
1163 | + $db =& $this->db; |
1164 | + $currentdate = time(); |
1165 | + $rfLookahead = Kit::ValidateParam(Config::GetSetting($db,'REQUIRED_FILES_LOOKAHEAD'), _INT); |
1166 | + |
1167 | + $rfLookahead = $currentdate + $rfLookahead; |
1168 | + |
1169 | + Debug::LogEntry($db, 'audit', sprintf('Checking for Displays to refresh on Layout %d', $layoutId), 'display', 'NotifyDisplays'); |
1170 | + |
1171 | + // Which displays does a change to this layout effect? |
1172 | + $SQL = " SELECT DISTINCT display.DisplayID "; |
1173 | + $SQL .= " FROM schedule_detail "; |
1174 | + $SQL .= " INNER JOIN lkdisplaydg "; |
1175 | + $SQL .= " ON lkdisplaydg.DisplayGroupID = schedule_detail.DisplayGroupID "; |
1176 | + $SQL .= " INNER JOIN display "; |
1177 | + $SQL .= " ON lkdisplaydg.DisplayID = display.displayID "; |
1178 | + $SQL .= " WHERE schedule_detail.layoutID = %d "; |
1179 | + $SQL .= " AND schedule_detail.FromDT < %d AND schedule_detail.ToDT > %d "; |
1180 | + $SQL .= " UNION "; |
1181 | + $SQL .= " SELECT DisplayID FROM display WHERE DefaultLayoutID = %d"; |
1182 | + |
1183 | + $SQL = sprintf($SQL, $layoutId, $rfLookahead, $currentdate - 3600, $layoutId); |
1184 | + |
1185 | + Debug::LogEntry($db, 'audit', $SQL, 'display', 'NotifyDisplays'); |
1186 | + |
1187 | + if (!$result = $db->query($SQL)) |
1188 | + { |
1189 | + trigger_error($db->error()); |
1190 | + return $this->SetError(25037, __('Unable to get layouts for Notify')); |
1191 | + } |
1192 | + |
1193 | + while ($row = $db->get_assoc_row($result)) |
1194 | + { |
1195 | + // Notify each display in turn |
1196 | + $displayId = Kit::ValidateParam($row['DisplayID'], _INT); |
1197 | + $this->FlagIncomplete($displayId); |
1198 | + } |
1199 | + } |
1200 | } |
1201 | ?> |
1202 | |
1203 | === modified file 'server/lib/data/schedule.data.class.php' |
1204 | --- server/lib/data/schedule.data.class.php 2011-02-10 19:46:44 +0000 |
1205 | +++ server/lib/data/schedule.data.class.php 2011-02-28 15:09:32 +0000 |
1206 | @@ -164,6 +164,11 @@ |
1207 | } |
1208 | } |
1209 | } |
1210 | + |
1211 | + // Notify (dont error) |
1212 | + Kit::ClassLoader('Display'); |
1213 | + $displayObject = new Display($db); |
1214 | + $displayObject->NotifyDisplays($layoutID); |
1215 | |
1216 | Debug::LogEntry($db, 'audit', 'OUT', 'Schedule', 'Add'); |
1217 | |
1218 | |
1219 | === modified file 'server/lib/pages/display.class.php' |
1220 | --- server/lib/pages/display.class.php 2011-02-13 17:16:01 +0000 |
1221 | +++ server/lib/pages/display.class.php 2011-02-28 15:09:32 +0000 |
1222 | @@ -37,6 +37,8 @@ |
1223 | private $email_alert; |
1224 | private $alert_timeout; |
1225 | private $ajax; |
1226 | + private $mediaInventoryStatus; |
1227 | + private $mediaInventoryXml; |
1228 | |
1229 | function __construct(database $db, user $user) |
1230 | { |
1231 | @@ -71,7 +73,9 @@ |
1232 | display.isAuditing, |
1233 | display.email_alert, |
1234 | display.alert_timeout, |
1235 | - display.ClientAddress |
1236 | + display.ClientAddress, |
1237 | + display.MediaInventoryStatus, |
1238 | + display.MediaInventoryXml |
1239 | FROM display |
1240 | WHERE display.displayid = %d |
1241 | SQL; |
1242 | @@ -95,8 +99,10 @@ |
1243 | $this->licensed = Kit::ValidateParam($row[4], _INT); |
1244 | $this->inc_schedule = Kit::ValidateParam($row[5], _INT); |
1245 | $this->auditing = Kit::ValidateParam($row[6], _INT); |
1246 | - $this->email_alert = Kit::ValidateParam($row[7], _INT); |
1247 | - $this->alert_timeout = Kit::ValidateParam($row[8], _INT); |
1248 | + $this->email_alert = Kit::ValidateParam($row[7], _INT); |
1249 | + $this->alert_timeout = Kit::ValidateParam($row[8], _INT); |
1250 | + $this->mediaInventoryStatus = Kit::ValidateParam($row[9], _INT); |
1251 | + $this->mediaInventoryXml = Kit::ValidateParam($row[10], _HTMLSTRING); |
1252 | } |
1253 | } |
1254 | |
1255 | @@ -309,7 +315,12 @@ |
1256 | CASE WHEN display.licensed = 1 THEN '<img src="img/act.gif">' ELSE '<img src="img/disact.gif">' END AS licensed, |
1257 | CASE WHEN display.email_alert = 1 THEN '<img src="img/act.gif">' ELSE '<img src="img/disact.gif">' END AS email_alert, |
1258 | displaygroup.DisplayGroupID, |
1259 | - display.ClientAddress |
1260 | + display.ClientAddress, |
1261 | + CASE WHEN display.MediaInventoryStatus = 1 THEN '<img src="img/act.gif">' |
1262 | + WHEN display.MediaInventoryStatus = 2 THEN '<img src="img/warn.gif">' |
1263 | + ELSE '<img src="img/disact.gif">' |
1264 | + END AS MediaInventoryStatus, |
1265 | + display.MediaInventoryXml |
1266 | FROM display |
1267 | INNER JOIN lkdisplaydg ON lkdisplaydg.DisplayID = display.DisplayID |
1268 | INNER JOIN displaygroup ON displaygroup.DisplayGroupID = lkdisplaydg.DisplayGroupID |
1269 | @@ -341,6 +352,8 @@ |
1270 | $msgGroupSecurity = __('Group Security'); |
1271 | $msgClientAddress = __('IP Address'); |
1272 | $msgDefault = __('Default Layout'); |
1273 | + $msgStatus = __('Status'); |
1274 | + $msgMediaInventory = __('Media Inventory'); |
1275 | |
1276 | $output = <<<END |
1277 | <div class="info_table"> |
1278 | @@ -356,6 +369,7 @@ |
1279 | <th>$msgLogIn</th> |
1280 | <th>$msgLastA</th> |
1281 | <th>$msgClientAddress</th> |
1282 | + <th>$msgStatus</th> |
1283 | <th>$msgAction</th> |
1284 | </tr> |
1285 | </thead> |
1286 | @@ -385,6 +399,7 @@ |
1287 | // Do we want to make a VNC link out of the display name? |
1288 | $vncTemplate = Config::GetSetting($db, 'SHOW_DISPLAY_AS_VNCLINK'); |
1289 | $linkTarget = Kit::ValidateParam(Config::GetSetting($db, 'SHOW_DISPLAY_AS_VNC_TGT'), _STRING); |
1290 | + $mediaInventoryStatusLight = Kit::ValidateParam($aRow[10], _STRING); |
1291 | |
1292 | if ($vncTemplate != '' && $clientAddress != '') |
1293 | { |
1294 | @@ -424,6 +439,7 @@ |
1295 | <td>$loggedin</td> |
1296 | <td>$lastaccessed</td> |
1297 | <td>$clientAddress</td> |
1298 | + <td>$mediaInventoryStatusLight</td> |
1299 | <td>$buttons</td> |
1300 | END; |
1301 | } |
1302 | @@ -720,5 +736,59 @@ |
1303 | $response->SetFormSubmitResponse(__('Display Saved.')); |
1304 | $response->Respond(); |
1305 | } |
1306 | + |
1307 | + /** |
1308 | + * Shows the inventory XML for the display |
1309 | + */ |
1310 | + public function MediaInventory() |
1311 | + { |
1312 | + $db =& $this->db; |
1313 | + $response = new ResponseManager(); |
1314 | + $displayId = Kit::GetParam('DisplayId', _GET, _INT); |
1315 | + |
1316 | + if ($displayId == 0) |
1317 | + trigger_error(__('No DisplayId Given')); |
1318 | + |
1319 | + // Get the media inventory xml for this display |
1320 | + $SQL = "SELECT MediaInventoryXml FROM display WHERE DisplayId = %d"; |
1321 | + $SQL = sprintf($SQL, $displayId); |
1322 | + |
1323 | + if (!$mediaInventoryXml = $db->GetSingleValue($SQL, 'MediaInventoryXml', _HTMLSTRING)) |
1324 | + { |
1325 | + trigger_error($db->error()); |
1326 | + trigger_error(__('Unable to get the Inventory for this Display'), E_USER_ERROR); |
1327 | + } |
1328 | + |
1329 | + // Load the XML into a DOMDocument |
1330 | + $document = new DOMDocument("1.0"); |
1331 | + |
1332 | + if (!$document->loadXML($mediaInventoryXml)) |
1333 | + trigger_error(__('Invalid Media Inventory'), E_USER_ERROR); |
1334 | + |
1335 | + // Output a table |
1336 | + $table = '<table><tr><th>Type</th><th>Id</th><th>Complete</th><th>Last Checked</th><th>MD5</th></tr>'; |
1337 | + |
1338 | + foreach ($document->documentElement->childNodes as $node) |
1339 | + { |
1340 | + $type = $node->getAttribute('type'); |
1341 | + $id = $node->getAttribute('id'); |
1342 | + $complete = $node->getAttribute('complete'); |
1343 | + $lastChecked = $node->getAttribute('lastChecked'); |
1344 | + $md5 = $node->getAttribute('md5'); |
1345 | + |
1346 | + if ($complete == 0) |
1347 | + $complete = __('No'); |
1348 | + else |
1349 | + $complete = __('Yes'); |
1350 | + |
1351 | + $table .= sprintf('<tr><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td>', $type, $id, $complete, $lastChecked, $md5); |
1352 | + } |
1353 | + |
1354 | + $table .= '</table>'; |
1355 | + |
1356 | + $response->SetFormRequestResponse($table, __('Media Inventory'), '550px', '350px'); |
1357 | + $response->AddButton(__('Close'), 'XiboDialogClose()'); |
1358 | + $response->Respond(); |
1359 | + } |
1360 | } |
1361 | ?> |
1362 | |
1363 | === modified file 'server/lib/pages/layout.class.php' |
1364 | --- server/lib/pages/layout.class.php 2011-02-10 21:01:27 +0000 |
1365 | +++ server/lib/pages/layout.class.php 2011-02-28 15:09:32 +0000 |
1366 | @@ -427,6 +427,12 @@ |
1367 | trigger_error($layoutObject->GetErrorMessage(), E_USER_ERROR); |
1368 | } |
1369 | |
1370 | + // Notify (dont error) |
1371 | + Kit::ClassLoader('display'); |
1372 | + $displayObject = new Display($db); |
1373 | + $displayObject->NotifyDisplays($this->layoutid); |
1374 | + |
1375 | + |
1376 | $response->SetFormSubmitResponse(__('Layout Details Changed.')); |
1377 | $response->Respond(); |
1378 | } |
1379 | |
1380 | === modified file 'server/lib/pages/region.class.php' |
1381 | --- server/lib/pages/region.class.php 2010-05-29 11:16:24 +0000 |
1382 | +++ server/lib/pages/region.class.php 2011-02-28 15:09:32 +0000 |
1383 | @@ -76,6 +76,11 @@ |
1384 | $this->errMsg = __("Unable to Update that layouts XML with a new Media Node"); |
1385 | return false; |
1386 | } |
1387 | + |
1388 | + // Notify (dont error) |
1389 | + Kit::ClassLoader('display'); |
1390 | + $displayObject = new Display($db); |
1391 | + $displayObject->NotifyDisplays($layoutid); |
1392 | |
1393 | return true; |
1394 | } |
1395 | |
1396 | === modified file 'server/lib/service/service.wsdl' |
1397 | --- server/lib/service/service.wsdl 2010-01-31 00:38:32 +0000 |
1398 | +++ server/lib/service/service.wsdl 2011-02-28 15:09:32 +0000 |
1399 | @@ -80,6 +80,15 @@ |
1400 | <message name="SubmitStatsResponse"> |
1401 | <part name="success" type="xsd:boolean" /> |
1402 | </message> |
1403 | + <message name="MediaInventoryRequest"> |
1404 | + <part name="version" type="xsd:string" /> |
1405 | + <part name="serverKey" type="xsd:string" /> |
1406 | + <part name="hardwareKey" type="xsd:string" /> |
1407 | + <part name="mediaInventory" type="xsd:string" /> |
1408 | + </message> |
1409 | + <message name="MediaInventoryResponse"> |
1410 | + <part name="success" type="xsd:boolean" /> |
1411 | + </message> |
1412 | <portType name="xmdsPortType"> |
1413 | <operation name="RegisterDisplay"> |
1414 | <documentation>Registered the Display on the Xibo Network</documentation> |
1415 | @@ -121,6 +130,11 @@ |
1416 | <input message="tns:SubmitStatsRequest"/> |
1417 | <output message="tns:SubmitStatsResponse"/> |
1418 | </operation> |
1419 | + <operation name="MediaInventory"> |
1420 | + <documentation>Report back the clients MediaInventory</documentation> |
1421 | + <input message="tns:MediaInventoryRequest" /> |
1422 | + <output message="tns:MediaInventoryResponse" /> |
1423 | + </operation> |
1424 | </portType> |
1425 | <binding name="xmdsBinding" type="tns:xmdsPortType"> |
1426 | <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/> |
1427 | @@ -196,6 +210,15 @@ |
1428 | <soap:body use="encoded" namespace="urn:xmds" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> |
1429 | </output> |
1430 | </operation> |
1431 | + <operation name="MediaInventory"> |
1432 | + <soap:operation soapAction="urn:xmds#MediaInventory" style="rpc"/> |
1433 | + <input> |
1434 | + <soap:body use="encoded" namespace="urn:xmds" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> |
1435 | + </input> |
1436 | + <output> |
1437 | + <soap:body use="encoded" namespace="urn:xmds" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> |
1438 | + </output> |
1439 | + </operation> |
1440 | </binding> |
1441 | <service name="xmds"> |
1442 | <port name="xmdsPort" binding="tns:xmdsBinding"> |
1443 | |
1444 | === modified file 'server/lib/service/xmdssoap.class.php' |
1445 | --- server/lib/service/xmdssoap.class.php 2011-02-07 16:46:09 +0000 |
1446 | +++ server/lib/service/xmdssoap.class.php 2011-02-28 15:09:32 +0000 |
1447 | @@ -848,6 +848,66 @@ |
1448 | } |
1449 | |
1450 | /** |
1451 | + * Store the media inventory for a client |
1452 | + * @param <type> $hardwareKey |
1453 | + * @param <type> $inventory |
1454 | + */ |
1455 | + public function MediaInventory($version, $serverKey, $hardwareKey, $inventory) |
1456 | + { |
1457 | + $db =& $this->db; |
1458 | + |
1459 | + // Sanitize |
1460 | + $serverKey = Kit::ValidateParam($serverKey, _STRING); |
1461 | + $hardwareKey = Kit::ValidateParam($hardwareKey, _STRING); |
1462 | + $version = Kit::ValidateParam($version, _STRING); |
1463 | + $inventory = Kit::ValidateParam($inventory, _HTMLSTRING); |
1464 | + |
1465 | + // Make sure we are talking the same language |
1466 | + if (!$this->CheckVersion($version)) |
1467 | + 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"); |
1468 | + |
1469 | + // Auth this request... |
1470 | + if (!$this->AuthDisplay($hardwareKey)) |
1471 | + throw new SoapFault('Receiver', 'This display client is not licensed'); |
1472 | + |
1473 | + if ($this->isAuditing == 1) Debug::LogEntry ($db, 'audit', $inventory, 'xmds', 'MediaInventory', '', $this->displayId); |
1474 | + |
1475 | + // Check that the $inventory contains something |
1476 | + if ($inventory == '') |
1477 | + throw new SoapFault('Receiver', 'Inventory Cannot be Empty'); |
1478 | + |
1479 | + // Load the XML into a DOMDocument |
1480 | + $document = new DOMDocument("1.0"); |
1481 | + $document->loadXML($inventory); |
1482 | + |
1483 | + // Assume we are complete (but we are getting some) |
1484 | + $mediaInventoryComplete = 1; |
1485 | + |
1486 | + foreach ($document->documentElement->childNodes as $node) |
1487 | + { |
1488 | + // Make sure we dont consider any text nodes |
1489 | + if ($node->nodeType == XML_TEXT_NODE) continue; |
1490 | + |
1491 | + $mediaId = $node->getAttribute('id'); |
1492 | + $complete = $node->getAttribute('complete'); |
1493 | + $md5 = $node->getAttribute('md5'); |
1494 | + $lastChecked = $node->getAttribute('lastChecked'); |
1495 | + |
1496 | + // Check the MD5? |
1497 | + |
1498 | + // If this item is a 0 then set not complete |
1499 | + if ($complete == 0) |
1500 | + $mediaInventoryComplete = 2; |
1501 | + } |
1502 | + |
1503 | + // Touch the display record |
1504 | + $displayObject = new Display($db); |
1505 | + $displayObject->Touch($hardwareKey, '', $mediaInventoryComplete, $inventory); |
1506 | + |
1507 | + return true; |
1508 | + } |
1509 | + |
1510 | + /** |
1511 | * Authenticates the display |
1512 | * @param <type> $hardwareKey |
1513 | * @return <type> |