Merge lp:~dangarner/xibo/1.2.2-pre into lp:xibo/1.3

Proposed by Dan Garner
Status: Merged
Merged at revision: 211
Proposed branch: lp:~dangarner/xibo/1.2.2-pre
Merge into: lp:xibo/1.3
Diff against target: 7154 lines (+4782/-473) (has conflicts)
36 files modified
client/dotNET/CacheManager.cs (+75/-1)
client/dotNET/FileCollector.cs (+57/-28)
client/dotNET/MainForm.cs (+88/-62)
client/dotNET/Properties/Resources.Designer.cs (+1/-1)
client/dotNET/Properties/Settings.Designer.cs (+14/-2)
client/dotNET/Properties/Settings.settings (+5/-2)
client/dotNET/Region.cs (+8/-1)
client/dotNET/RequiredFiles.cs (+206/-0)
client/dotNET/RssReader.cs (+1/-1)
client/dotNET/Schedule.cs (+1/-1)
client/dotNET/ScheduleManager.cs (+16/-1)
client/dotNET/Web References/xmds/Reference.cs (+86/-19)
client/dotNET/Web References/xmds/Reference.map (+1/-1)
client/dotNET/Web References/xmds/xmds.wsdl (+24/-1)
client/dotNET/XiboClient.csproj (+7/-5)
client/dotNET/app.config (+5/-2)
client/dotNET/bin/Release/XiboClient.exe.config (+24/-3)
client/dotNET/bin/Release/XiboClient.vshost.exe.config (+24/-3)
client/python/XiboClient.py (+196/-0)
client/python/client.conf (+25/-0)
client/python/configure.py (+1753/-0)
client/python/gui.glade (+1451/-0)
default.pot (+293/-283)
server/README.TXT (+4/-4)
server/install/database/27.sql (+9/-0)
server/lib/app/kit.class.php (+9/-13)
server/lib/data/display.data.class.php (+84/-6)
server/lib/data/displaygroup.data.class.php (+9/-0)
server/lib/data/schedule.data.class.php (+10/-5)
server/lib/pages/display.class.php (+169/-19)
server/lib/pages/layout.class.php (+8/-2)
server/lib/pages/module.class.php (+16/-0)
server/lib/pages/region.class.php (+5/-0)
server/lib/pages/schedule.class.php (+14/-6)
server/lib/service/service.wsdl (+23/-0)
server/lib/service/xmdssoap.class.php (+61/-1)
Text conflict in client/python/XiboClient.py
Conflict adding file client/python/client.conf.  Moved existing file to client/python/client.conf.moved.
Conflict adding file client/python/configure.py.  Moved existing file to client/python/configure.py.moved.
Conflict adding file client/python/gui.glade.  Moved existing file to client/python/gui.glade.moved.
Conflict adding file client/python/xibo.ico.  Moved existing file to client/python/xibo.ico.moved.
To merge this branch: bzr merge lp:~dangarner/xibo/1.2.2-pre
Reviewer Review Type Date Requested Status
Dan Garner Approve
Review via email: mp+51553@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Dan Garner (dangarner) :
review: Approve

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:00 +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 2010-04-19 21:45:10 +0000
111+++ client/dotNET/FileCollector.cs 2011-02-28 15:09:00 +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,10 +237,24 @@
220 }
221 }
222
223- System.Diagnostics.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 (RequiredFile fileToGet in _files)
230+ debugMessage += string.Format("File: {0}, Type: {1}, MD5: {2}. ", fileToGet.path, fileToGet.type, fileToGet.md5);
231+
232+ Debug.WriteLine(debugMessage);
233+
234+ // Report the files files back to XMDS
235+ _requiredFiles.ReportInventory();
236+
237+ // Write Required Files
238+ _requiredFiles.WriteRequiredFiles();
239
240 // Is there anything to get?
241- if (files.Count == 0)
242+ if (_files.Count == 0)
243 {
244 CollectionComplete();
245 return;
246@@ -247,7 +264,7 @@
247 _currentFile = 0;
248
249 // Preload the first filelist
250- _currentFileList = files[_currentFile];
251+ _currentFileList = _files[_currentFile];
252
253 // Get the first file
254 GetFile();
255@@ -367,6 +384,10 @@
256 {
257 // Add to the CacheManager
258 _cacheManager.Add(_currentFileList.path + ".xlf", md5sum);
259+
260+ // Report this completion back to XMDS
261+ _requiredFiles.MarkComplete(int.Parse(_currentFileList.path), md5sum);
262+ _requiredFiles.ReportInventory();
263 }
264
265 // Fire a layout complete event
266@@ -437,6 +458,11 @@
267
268 System.Diagnostics.Debug.WriteLine(string.Format("File downloaded: {0}", _currentFileList.path));
269
270+ // Report this completion back to XMDS
271+ string[] filePart = _currentFileList.path.Split('.');
272+ _requiredFiles.MarkComplete(int.Parse(filePart[0]), md5sum);
273+ _requiredFiles.ReportInventory();
274+
275 // All the file has been recieved. Move on to the next file.
276 _currentFile++;
277 }
278@@ -467,13 +493,16 @@
279 /// </summary>
280 public void GetFile()
281 {
282- if (_currentFile > (files.Count - 1))
283+ if (_currentFile > (_files.Count - 1))
284 {
285- System.Diagnostics.Debug.WriteLine(String.Format("Finished Recieving {0} files", files.Count));
286+ System.Diagnostics.Debug.WriteLine(String.Format("Finished Receiving {0} files", _files.Count));
287
288 // Clean up
289- files.Clear();
290- xmdsFile.Dispose();
291+ _files.Clear();
292+ xmdsFile.Dispose();
293+
294+ // Write Required Files
295+ _requiredFiles.WriteRequiredFiles();
296
297 // Finished getting this file list
298 CollectionComplete();
299@@ -483,7 +512,7 @@
300 // Get the current file into the currentfilelist if the current one is finished
301 if (_currentFileList.complete)
302 {
303- _currentFileList = files[_currentFile];
304+ _currentFileList = _files[_currentFile];
305 }
306
307 System.Diagnostics.Debug.WriteLine(String.Format("Getting the file : {0} chunk : {1}", _currentFileList.path, _currentFileList.chunkOffset.ToString()));
308@@ -496,7 +525,7 @@
309 }
310
311 [Serializable]
312- private struct FileList
313+ private struct RequiredFile
314 {
315 public string path;
316 public string type;
317@@ -511,9 +540,9 @@
318
319 private XmlDocument xml;
320 private HardwareKey hardwareKey;
321- private Collection<FileList> files;
322+ private Collection<RequiredFile> _files;
323 private int _currentFile;
324- private FileList _currentFileList;
325+ private RequiredFile _currentFileList;
326 private xmds.xmds xmdsFile;
327
328 public event LayoutFileChangedDelegate LayoutFileChanged;
329
330=== modified file 'client/dotNET/MainForm.cs'
331--- client/dotNET/MainForm.cs 2010-08-26 20:15:36 +0000
332+++ client/dotNET/MainForm.cs 2011-02-28 15:09:00 +0000
333@@ -72,14 +72,45 @@
334
335 _statLog = new StatLog();
336
337+ this.FormClosing += new FormClosingEventHandler(MainForm_FormClosing);
338+ this.Shown += new EventHandler(MainForm_Shown);
339+ }
340+
341+ /// <summary>
342+ /// Called after the form has been shown
343+ /// </summary>
344+ /// <param name="sender"></param>
345+ /// <param name="e"></param>
346+ void MainForm_Shown(object sender, EventArgs e)
347+ {
348+ // Process any stuff that has happened during the loading process
349+ Application.DoEvents();
350+
351 // Create a cachemanager
352 SetCacheManager();
353
354- this.FormClosing += new FormClosingEventHandler(MainForm_FormClosing);
355+ try
356+ {
357+ // Create the Schedule
358+ _schedule = new Schedule(Application.UserAppDataPath + "\\" + Properties.Settings.Default.ScheduleFile, ref _cacheManager);
359+
360+ // Bind to the schedule change event - notifys of changes to the schedule
361+ _schedule.ScheduleChangeEvent += new Schedule.ScheduleChangeDelegate(schedule_ScheduleChangeEvent);
362+
363+ // Initialize the other schedule components
364+ _schedule.InitializeComponents();
365+ }
366+ catch (Exception ex)
367+ {
368+ Debug.WriteLine(ex.Message, LogType.Error.ToString());
369+ MessageBox.Show("Fatal Error initialising the application", "Fatal Error");
370+ Close();
371+ Dispose();
372+ }
373 }
374
375 /// <summary>
376- /// Called when the form has finished loading
377+ /// Called before the form has loaded for the first time
378 /// </summary>
379 /// <param name="sender"></param>
380 /// <param name="e"></param>
381@@ -96,30 +127,13 @@
382 Cursor.Position = new Point(_clientSize.Width, _clientSize.Height);
383 Cursor.Hide();
384
385+ ShowSplashScreen();
386+
387 // Change the default Proxy class
388 OptionForm.SetGlobalProxy();
389
390 // UserApp data
391 Debug.WriteLine(new LogMessage("MainForm_Load", "User AppData Path: " + Application.UserAppDataPath), LogType.Info.ToString());
392-
393- try
394- {
395- // Create the Schedule
396- _schedule = new Schedule(Application.UserAppDataPath + "\\" + Properties.Settings.Default.ScheduleFile, ref _cacheManager);
397-
398- // Bind to the schedule change event - notifys of changes to the schedule
399- _schedule.ScheduleChangeEvent += new Schedule.ScheduleChangeDelegate(schedule_ScheduleChangeEvent);
400-
401- // Initialize the other schedule components
402- _schedule.InitializeComponents();
403- }
404- catch (Exception ex)
405- {
406- Debug.WriteLine(ex.Message, LogType.Error.ToString());
407- MessageBox.Show("Fatal Error initialising the application", "Fatal Error");
408- Close();
409- Dispose();
410- }
411 }
412
413 private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
414@@ -152,11 +166,20 @@
415 }
416 catch (Exception ex)
417 {
418- Trace.WriteLine(new LogMessage("Schedule", "Unable to reuse the Cache Manager because: " + ex.Message));
419+ Trace.WriteLine(new LogMessage("MainForm - SetCacheManager", "Unable to reuse the Cache Manager because: " + ex.Message));
420
421 // Create a new cache manager
422 _cacheManager = new CacheManager();
423 }
424+
425+ try
426+ {
427+ _cacheManager.Regenerate();
428+ }
429+ catch (Exception ex)
430+ {
431+ Trace.WriteLine(new LogMessage("MainForm - SetCacheManager", "Regenerate failed because: " + ex.Message));
432+ }
433 }
434
435 /// <summary>
436@@ -191,9 +214,29 @@
437 {
438 Debug.WriteLine(ex.Message);
439 _isExpired = true;
440+
441+ ShowSplashScreen();
442+
443+ // In 10 seconds fire the next layout?
444+ Timer timer = new Timer();
445+ timer.Interval = 10000;
446+ timer.Tick += new EventHandler(splashScreenTimer_Tick);
447+
448+ // Start the timer
449+ timer.Start();
450 }
451 }
452
453+ void splashScreenTimer_Tick(object sender, EventArgs e)
454+ {
455+ Debug.WriteLine(new LogMessage("timer_Tick", "Loading next layout after splashscreen"));
456+
457+ Timer timer = (Timer)sender;
458+ timer.Stop();
459+ timer.Dispose();
460+
461+ _schedule.NextLayout();
462+ }
463
464 /// <summary>
465 /// Prepares the Layout.. rendering all the necessary controls
466@@ -213,8 +256,7 @@
467 // Default or not
468 if (layoutPath == Properties.Settings.Default.LibraryPath + @"\Default.xml" || String.IsNullOrEmpty(layoutPath))
469 {
470- ShowSplashScreen();
471- return;
472+ throw new Exception("Default layout");
473 }
474 else
475 {
476@@ -232,33 +274,16 @@
477 }
478 catch (Exception ex)
479 {
480- // couldnt open the layout file, so use the embedded one
481- System.Reflection.Assembly assembly = System.Reflection.Assembly.GetExecutingAssembly();
482- Stream resourceStream = assembly.GetManifestResourceStream("XiboClient.Resources.splash.jpg");
483-
484- // Load into a stream and then into an Image
485- try
486- {
487- Image bgSplash = Image.FromStream(resourceStream);
488-
489- Bitmap bmpSplash = new Bitmap(bgSplash, _clientSize);
490- this.BackgroundImage = bmpSplash;
491- }
492- catch
493- {
494- // Log
495- System.Diagnostics.Debug.WriteLine(ex.Message);
496- System.Diagnostics.Trace.WriteLine("Could not find the layout file {0}", layoutPath);
497- }
498- return;
499+ Trace.WriteLine(string.Format("Could not find the layout file {0}: {1}", layoutPath, ex.Message));
500+ throw;
501 }
502 }
503
504 // Attributes of the main layout node
505 XmlNode layoutNode = layoutXml.SelectSingleNode("/layout");
506-
507- XmlAttributeCollection layoutAttributes = layoutNode.Attributes;
508-
509+
510+ XmlAttributeCollection layoutAttributes = layoutNode.Attributes;
511+
512 // Set the background and size of the form
513 _layoutWidth = int.Parse(layoutAttributes["width"].Value);
514 _layoutHeight = int.Parse(layoutAttributes["height"].Value);
515@@ -266,7 +291,7 @@
516
517 // Scaling factor, will be applied to all regions
518 _scaleFactor = Math.Min(_clientSize.Width / _layoutWidth, _clientSize.Height / _layoutHeight);
519-
520+
521 // Want to be able to center this shiv - therefore work out which one of these is going to have left overs
522 int backgroundWidth = (int)(_layoutWidth * _scaleFactor);
523 int backgroundHeight = (int)(_layoutHeight * _scaleFactor);
524@@ -282,7 +307,7 @@
525 if (leftOverX != 0) leftOverX = leftOverX / 2;
526 if (leftOverY != 0) leftOverY = leftOverY / 2;
527 }
528- catch
529+ catch
530 {
531 leftOverX = 0;
532 leftOverY = 0;
533@@ -361,25 +386,24 @@
534 // Check to see if there are any regions on this layout.
535 if (listRegions.Count == 0 || listMedia.Count == 0)
536 {
537- Trace.WriteLine(new LogMessage("PrepareLayout",
538- string.Format("A layout with {0} regions and {1} media has been detected.", listRegions.Count.ToString(), listMedia.Count.ToString())),
539+ Trace.WriteLine(new LogMessage("PrepareLayout",
540+ string.Format("A layout with {0} regions and {1} media has been detected.", listRegions.Count.ToString(), listMedia.Count.ToString())),
541 LogType.Info.ToString());
542
543 if (_schedule.ActiveLayouts == 1)
544 {
545 Trace.WriteLine(new LogMessage("PrepareLayout", "Only 1 layout scheduled and it has nothing to show."), LogType.Info.ToString());
546
547- // Fall back to the splash screen (will only shift from here once a new schedule is detected)
548- ShowSplashScreen();
549+ throw new Exception("Only 1 layout schduled and it has nothing to show");
550 }
551 else
552 {
553- Trace.WriteLine(new LogMessage("PrepareLayout",
554+ Trace.WriteLine(new LogMessage("PrepareLayout",
555 string.Format(string.Format("An empty layout detected, will show for {0} seconds.", Properties.Settings.Default.emptyLayoutDuration.ToString()))), LogType.Info.ToString());
556
557 // Put a small dummy region in place, with a small dummy media node - which expires in 10 seconds.
558 XmlDocument dummyXml = new XmlDocument();
559- dummyXml.LoadXml(string.Format("<region id='blah' width='1' height='1' top='1' left='1'><media id='blah' type='text' duration='{0}'><raw><text></text></raw></media></region>",
560+ dummyXml.LoadXml(string.Format("<region id='blah' width='1' height='1' top='1' left='1'><media id='blah' type='text' duration='{0}'><raw><text></text></raw></media></region>",
561 Properties.Settings.Default.emptyLayoutDuration.ToString()));
562
563 // Replace the list of regions (they mean nothing as they are empty)
564@@ -400,10 +424,10 @@
565
566 options.scheduleId = _scheduleId;
567 options.layoutId = _layoutId;
568- options.width = (int) (double.Parse(nodeAttibutes["width"].Value) * _scaleFactor);
569- options.height = (int) (double.Parse(nodeAttibutes["height"].Value) * _scaleFactor);
570- options.left = (int) (double.Parse(nodeAttibutes["left"].Value) * _scaleFactor);
571- options.top = (int) (double.Parse(nodeAttibutes["top"].Value) * _scaleFactor);
572+ options.width = (int)(double.Parse(nodeAttibutes["width"].Value) * _scaleFactor);
573+ options.height = (int)(double.Parse(nodeAttibutes["height"].Value) * _scaleFactor);
574+ options.left = (int)(double.Parse(nodeAttibutes["left"].Value) * _scaleFactor);
575+ options.top = (int)(double.Parse(nodeAttibutes["top"].Value) * _scaleFactor);
576 options.scaleFactor = _scaleFactor;
577
578 // Set the backgrounds (used for Web content offsets)
579@@ -411,9 +435,9 @@
580 options.backgroundTop = options.top * -1;
581
582 //Account for scaling
583- options.left = options.left + (int) leftOverX;
584- options.top = options.top + (int) leftOverY;
585-
586+ options.left = options.left + (int)leftOverX;
587+ options.top = options.top + (int)leftOverY;
588+
589 // All the media nodes for this region / layout combination
590 options.mediaNodes = region.ChildNodes;
591
592@@ -421,7 +445,7 @@
593 temp.DurationElapsedEvent += new Region.DurationElapsedDelegate(temp_DurationElapsedEvent);
594
595 Debug.WriteLine("Created new region", "MainForm - Prepare Layout");
596-
597+
598 // Dont be fooled, this innocent little statement kicks everything off
599 temp.regionOptions = options;
600
601@@ -456,6 +480,8 @@
602
603 Bitmap bmpSplash = new Bitmap(bgSplash, _clientSize);
604 this.BackgroundImage = bmpSplash;
605+
606+ bgSplash.Dispose();
607 }
608 catch (Exception ex)
609 {
610
611=== modified file 'client/dotNET/Properties/Resources.Designer.cs'
612--- client/dotNET/Properties/Resources.Designer.cs 2009-12-31 11:38:50 +0000
613+++ client/dotNET/Properties/Resources.Designer.cs 2011-02-28 15:09:00 +0000
614@@ -1,7 +1,7 @@
615 //------------------------------------------------------------------------------
616 // <auto-generated>
617 // This code was generated by a tool.
618-// Runtime Version:2.0.50727.4927
619+// Runtime Version:2.0.50727.4952
620 //
621 // Changes to this file may cause incorrect behavior and will be lost if
622 // the code is regenerated.
623
624=== modified file 'client/dotNET/Properties/Settings.Designer.cs'
625--- client/dotNET/Properties/Settings.Designer.cs 2010-09-26 14:33:38 +0000
626+++ client/dotNET/Properties/Settings.Designer.cs 2011-02-28 15:09:00 +0000
627@@ -47,7 +47,7 @@
628 [global::System.Configuration.UserScopedSettingAttribute()]
629 [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
630 [global::System.Configuration.SpecialSettingAttribute(global::System.Configuration.SpecialSetting.WebServiceUrl)]
631- [global::System.Configuration.DefaultSettingValueAttribute("http://localhost/xibo/xmds.php")]
632+ [global::System.Configuration.DefaultSettingValueAttribute("http://localhost/Series%201.2/server-121-soap-wsdl/server/xmds.php")]
633 public string XiboClient_xmds_xmds {
634 get {
635 return ((string)(this["XiboClient_xmds_xmds"]));
636@@ -271,7 +271,7 @@
637
638 [global::System.Configuration.ApplicationScopedSettingAttribute()]
639 [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
640- [global::System.Configuration.DefaultSettingValueAttribute("1.2.0")]
641+ [global::System.Configuration.DefaultSettingValueAttribute("1.2.2")]
642 public string ClientVersion {
643 get {
644 return ((string)(this["ClientVersion"]));
645@@ -370,5 +370,17 @@
646 this["emptyLayoutDuration"] = value;
647 }
648 }
649+
650+ [global::System.Configuration.UserScopedSettingAttribute()]
651+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
652+ [global::System.Configuration.DefaultSettingValueAttribute("requiredFiles.xml")]
653+ public string RequiredFilesFile {
654+ get {
655+ return ((string)(this["RequiredFilesFile"]));
656+ }
657+ set {
658+ this["RequiredFilesFile"] = value;
659+ }
660+ }
661 }
662 }
663
664=== modified file 'client/dotNET/Properties/Settings.settings'
665--- client/dotNET/Properties/Settings.settings 2010-09-26 14:33:38 +0000
666+++ client/dotNET/Properties/Settings.settings 2011-02-28 15:09:00 +0000
667@@ -9,7 +9,7 @@
668 <Value Profile="(Default)">schedule.xml</Value>
669 </Setting>
670 <Setting Name="XiboClient_xmds_xmds" Type="(Web Service URL)" Scope="User">
671- <Value Profile="(Default)">http://localhost/xibo/xmds.php</Value>
672+ <Value Profile="(Default)">http://localhost/Series%201.2/server-121-soap-wsdl/server/xmds.php</Value>
673 </Setting>
674 <Setting Name="ServerKey" Type="System.String" Scope="User">
675 <Value Profile="(Default)">yourserverkey</Value>
676@@ -69,7 +69,7 @@
677 <Value Profile="(Default)">cacheManager.xml</Value>
678 </Setting>
679 <Setting Name="ClientVersion" Type="System.String" Scope="Application">
680- <Value Profile="(Default)">1.2.0</Value>
681+ <Value Profile="(Default)">1.2.2</Value>
682 </Setting>
683 <Setting Name="scrollStepAmount" Type="System.Decimal" Scope="User">
684 <Value Profile="(Default)">1</Value>
685@@ -95,5 +95,8 @@
686 <Setting Name="emptyLayoutDuration" Type="System.Decimal" Scope="User">
687 <Value Profile="(Default)">10</Value>
688 </Setting>
689+ <Setting Name="RequiredFilesFile" Type="System.String" Scope="User">
690+ <Value Profile="(Default)">requiredFiles.xml</Value>
691+ </Setting>
692 </Settings>
693 </SettingsFile>
694\ No newline at end of file
695
696=== modified file 'client/dotNET/Region.cs'
697--- client/dotNET/Region.cs 2010-08-26 19:23:14 +0000
698+++ client/dotNET/Region.cs 2011-02-28 15:09:00 +0000
699@@ -309,6 +309,13 @@
700 System.Diagnostics.Trace.WriteLine("Duration is Empty, using a default of 60.", "Region - SetNextMediaNode");
701 }
702
703+ // We cannot have a 0 duration here... not sure why we would... but
704+ if (options.duration == 0 && options.type != "video")
705+ {
706+ int emptyLayoutDuration = int.Parse(Properties.Settings.Default.emptyLayoutDuration.ToString());
707+ options.duration = (emptyLayoutDuration == 0) ? 10 : emptyLayoutDuration;
708+ }
709+
710 // There will be some stuff on option nodes
711 XmlNode optionNode = mediaNode.FirstChild;
712
713@@ -378,7 +385,7 @@
714 if (options.type == "video" || options.type == "flash" || options.type == "image" || options.type == "powerpoint")
715 {
716 // Use the cache manager to determine if the file is valid
717- validNode = _cacheManager.IsValid(options.uri);
718+ validNode = _cacheManager.IsValidPath(options.uri);
719 }
720 }
721
722
723=== added file 'client/dotNET/RequiredFiles.cs'
724--- client/dotNET/RequiredFiles.cs 1970-01-01 00:00:00 +0000
725+++ client/dotNET/RequiredFiles.cs 2011-02-28 15:09:00 +0000
726@@ -0,0 +1,206 @@
727+/*
728+ * Xibo - Digitial Signage - http://www.xibo.org.uk
729+ * Copyright (C) 2011 Daniel Garner
730+ *
731+ * This file is part of Xibo.
732+ *
733+ * Xibo is free software: you can redistribute it and/or modify
734+ * it under the terms of the GNU Affero General Public License as published by
735+ * the Free Software Foundation, either version 3 of the License, or
736+ * any later version.
737+ *
738+ * Xibo is distributed in the hope that it will be useful,
739+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
740+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
741+ * GNU Affero General Public License for more details.
742+ *
743+ * You should have received a copy of the GNU Affero General Public License
744+ * along with Xibo. If not, see <http://www.gnu.org/licenses/>.
745+ */
746+using System;
747+using System.Collections.Generic;
748+using System.Collections.ObjectModel;
749+using System.Text;
750+using System.IO;
751+using System.Security.Cryptography;
752+using System.Xml;
753+using System.Diagnostics;
754+using System.Windows.Forms;
755+using System.Xml.Serialization;
756+
757+namespace XiboClient
758+{
759+ public class RequiredFiles
760+ {
761+ private XmlDocument _requiredFilesXml;
762+ public Collection<RequiredFile> _requiredFiles;
763+ private xmds.xmds _report;
764+
765+ public RequiredFiles()
766+ {
767+ _requiredFiles = new Collection<RequiredFile>();
768+
769+ // Create a webservice call
770+ _report = new XiboClient.xmds.xmds();
771+
772+ // Start up the Xmds Service Object
773+ _report.Credentials = null;
774+ _report.Url = Properties.Settings.Default.XiboClient_xmds_xmds;
775+ _report.UseDefaultCredentials = false;
776+ }
777+
778+ /// <summary>
779+ /// Set required files from the XML document
780+ /// </summary>
781+ private void SetRequiredFiles()
782+ {
783+ // Itterate through the RF XML and populate the RF collection
784+ XmlNodeList fileNodes = _requiredFilesXml.SelectNodes("/files/file");
785+
786+ foreach (XmlNode file in fileNodes)
787+ {
788+ RequiredFile rf = new RequiredFile();
789+
790+ XmlAttributeCollection attributes = file.Attributes;
791+
792+ rf.FileType = attributes["type"].Value;
793+ rf.Complete = 0;
794+ rf.Md5 = "";
795+ rf.LastChecked = DateTime.Now;
796+
797+ if (rf.FileType == "media")
798+ {
799+ string[] filePart = attributes["path"].Value.Split('.');
800+ rf.Id = int.Parse(filePart[0]);
801+ rf.Path = attributes["path"].Value;
802+ }
803+ else if (rf.FileType == "layout")
804+ {
805+ rf.Id = int.Parse(attributes["path"].Value);
806+ rf.Path = attributes["path"].Value + ".xlf";
807+ }
808+ else
809+ {
810+ continue;
811+ }
812+
813+ _requiredFiles.Add(rf);
814+ }
815+ }
816+
817+ /// <summary>
818+ /// Required Files XML
819+ /// </summary>
820+ public XmlDocument RequiredFilesXml
821+ {
822+ set
823+ {
824+ _requiredFilesXml = value;
825+ SetRequiredFiles();
826+ }
827+ }
828+
829+ /// <summary>
830+ /// Mark a RequiredFile as complete
831+ /// </summary>
832+ /// <param name="id"></param>
833+ /// <param name="md5"></param>
834+ public void MarkComplete(int id, string md5)
835+ {
836+ foreach (RequiredFile rf in _requiredFiles)
837+ {
838+ if (rf.Id == id)
839+ {
840+ RequiredFile newRf = rf;
841+
842+ newRf.Complete = 1;
843+ newRf.Md5 = md5;
844+
845+
846+ _requiredFiles.Add(newRf);
847+ _requiredFiles.Remove(rf);
848+
849+ return;
850+ }
851+ }
852+ }
853+
854+ /// <summary>
855+ /// Mark a RequiredFile as incomplete
856+ /// </summary>
857+ /// <param name="id"></param>
858+ /// <param name="md5"></param>
859+ public void MarkIncomplete(int id, string md5)
860+ {
861+ foreach (RequiredFile rf in _requiredFiles)
862+ {
863+ if (rf.Id == id)
864+ {
865+ RequiredFile newRf = rf;
866+
867+ newRf.Complete = 0;
868+ newRf.Md5 = md5;
869+
870+ _requiredFiles.Add(newRf);
871+ _requiredFiles.Remove(rf);
872+
873+ return;
874+ }
875+ }
876+ }
877+
878+ /// <summary>
879+ /// Writes Required Files to disk
880+ /// </summary>
881+ public void WriteRequiredFiles()
882+ {
883+ Debug.WriteLine(new LogMessage("RequiredFiles - WriteRequiredFiles", "About to Write RequiredFiles"), LogType.Info.ToString());
884+
885+ try
886+ {
887+ using (StreamWriter streamWriter = new StreamWriter(Application.UserAppDataPath + "\\" + Properties.Settings.Default.RequiredFilesFile))
888+ {
889+ XmlSerializer xmlSerializer = new XmlSerializer(typeof(RequiredFiles));
890+
891+ xmlSerializer.Serialize(streamWriter, this);
892+ }
893+ }
894+ catch (Exception ex)
895+ {
896+ System.Diagnostics.Trace.WriteLine(new LogMessage("RequiredFiles - WriteRequiredFiles", "Unable to write RequiredFiles to disk because: " + ex.Message));
897+ }
898+ }
899+
900+ /// <summary>
901+ /// Report Required Files to XMDS
902+ /// </summary>
903+ public void ReportInventory()
904+ {
905+ HardwareKey hardwareKey = new HardwareKey();
906+
907+ // Build the XML required by media file
908+ string xml = "";
909+
910+ foreach (RequiredFile rf in _requiredFiles)
911+ {
912+ xml += string.Format("<file type=\"{0}\" id=\"{1}\" complete=\"{2}\" lastChecked=\"{3}\" md5=\"{4}\" />",
913+ rf.FileType, rf.Id.ToString(), rf.Complete.ToString(), rf.LastChecked.ToString(), rf.Md5);
914+ }
915+
916+ xml = string.Format("<files>{0}</files>", xml);
917+
918+ _report.MediaInventoryAsync(Properties.Settings.Default.Version, Properties.Settings.Default.ServerKey,
919+ hardwareKey.Key, xml);
920+ }
921+ }
922+
923+ public struct RequiredFile
924+ {
925+ public string FileType;
926+ public int Id;
927+ public int Complete;
928+ public DateTime LastChecked;
929+ public string Md5;
930+ public string Path;
931+ }
932+}
933
934=== modified file 'client/dotNET/Resources/splash.jpg'
935Binary files client/dotNET/Resources/splash.jpg 2008-12-19 23:34:13 +0000 and client/dotNET/Resources/splash.jpg 2011-02-28 15:09:00 +0000 differ
936=== modified file 'client/dotNET/RssReader.cs'
937--- client/dotNET/RssReader.cs 2010-09-26 17:37:39 +0000
938+++ client/dotNET/RssReader.cs 2011-02-28 15:09:00 +0000
939@@ -120,7 +120,7 @@
940 item.DateString = date;
941
942 // Fudge the date...
943- if (date.Contains("+"))
944+ if (date.Contains("+") || date.Contains("-"))
945 DateTime.TryParse(date, out item.Date);
946 else
947 DateTime.TryParse(date.Substring(0, date.Length - 4), out item.Date);
948
949=== modified file 'client/dotNET/Schedule.cs'
950--- client/dotNET/Schedule.cs 2010-08-22 16:49:09 +0000
951+++ client/dotNET/Schedule.cs 2011-02-28 15:09:00 +0000
952@@ -74,7 +74,7 @@
953 _cacheManager = cacheManager;
954
955 // Create a schedule manager
956- _scheduleManager = new ScheduleManager(scheduleLocation);
957+ _scheduleManager = new ScheduleManager(_cacheManager, scheduleLocation);
958
959 // Create a new Xmds service object
960 _xmds2 = new XiboClient.xmds.xmds();
961
962=== modified file 'client/dotNET/ScheduleManager.cs'
963--- client/dotNET/ScheduleManager.cs 2010-08-25 21:39:53 +0000
964+++ client/dotNET/ScheduleManager.cs 2011-02-28 15:09:00 +0000
965@@ -42,13 +42,15 @@
966 private Collection<LayoutSchedule> _layoutSchedule;
967 private Collection<LayoutSchedule> _currentSchedule;
968 private bool _refreshSchedule;
969+ private CacheManager _cacheManager;
970
971 /// <summary>
972 /// Creates a new schedule Manager
973 /// </summary>
974 /// <param name="scheduleLocation"></param>
975- public ScheduleManager(string scheduleLocation)
976+ public ScheduleManager(CacheManager cacheManager, string scheduleLocation)
977 {
978+ _cacheManager = cacheManager;
979 _location = scheduleLocation;
980
981 // Create an empty layout schedule
982@@ -178,6 +180,19 @@
983 // For each layout in the schedule determine if it is currently inside the _currentSchedule, and whether it should be
984 foreach (LayoutSchedule layout in _layoutSchedule)
985 {
986+ // Is the layout valid in the cachemanager?
987+ try
988+ {
989+ if (!_cacheManager.IsValidLayout(layout.id + ".xlf"))
990+ continue;
991+ }
992+ catch
993+ {
994+ // TODO: Ignore this layout.. raise an error?
995+ Trace.WriteLine("Unable to determine if layout is valid or not");
996+ continue;
997+ }
998+
999 // If this is the default, skip it
1000 if (layout.NodeName == "default")
1001 {
1002
1003=== modified file 'client/dotNET/Web References/xmds/Reference.cs'
1004--- client/dotNET/Web References/xmds/Reference.cs 2009-12-31 11:38:50 +0000
1005+++ client/dotNET/Web References/xmds/Reference.cs 2011-02-28 15:09:00 +0000
1006@@ -1,7 +1,7 @@
1007 //------------------------------------------------------------------------------
1008 // <auto-generated>
1009 // This code was generated by a tool.
1010-// Runtime Version:2.0.50727.4927
1011+// Runtime Version:2.0.50727.4952
1012 //
1013 // Changes to this file may cause incorrect behavior and will be lost if
1014 // the code is regenerated.
1015@@ -9,7 +9,7 @@
1016 //------------------------------------------------------------------------------
1017
1018 //
1019-// This source code was auto-generated by Microsoft.VSDesigner, Version 2.0.50727.4927.
1020+// This source code was auto-generated by Microsoft.VSDesigner, Version 2.0.50727.4952.
1021 //
1022 #pragma warning disable 1591
1023
1024@@ -23,7 +23,7 @@
1025
1026
1027 /// <remarks/>
1028- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "2.0.50727.4918")]
1029+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "2.0.50727.4927")]
1030 [System.Diagnostics.DebuggerStepThroughAttribute()]
1031 [System.ComponentModel.DesignerCategoryAttribute("code")]
1032 [System.Web.Services.WebServiceBindingAttribute(Name="xmdsBinding", Namespace="urn:xmds")]
1033@@ -45,6 +45,8 @@
1034
1035 private System.Threading.SendOrPostCallback SubmitStatsOperationCompleted;
1036
1037+ private System.Threading.SendOrPostCallback MediaInventoryOperationCompleted;
1038+
1039 private bool useDefaultCredentialsSetExplicitly;
1040
1041 /// <remarks/>
1042@@ -108,6 +110,9 @@
1043 public event SubmitStatsCompletedEventHandler SubmitStatsCompleted;
1044
1045 /// <remarks/>
1046+ public event MediaInventoryCompletedEventHandler MediaInventoryCompleted;
1047+
1048+ /// <remarks/>
1049 [System.Web.Services.Protocols.SoapRpcMethodAttribute("urn:xmds#RegisterDisplay", RequestNamespace="urn:xmds", ResponseNamespace="urn:xmds")]
1050 [return: System.Xml.Serialization.SoapElementAttribute("ActivationMessage")]
1051 public string RegisterDisplay(string serverKey, string hardwareKey, string displayName, string version) {
1052@@ -402,6 +407,42 @@
1053 }
1054
1055 /// <remarks/>
1056+ [System.Web.Services.Protocols.SoapRpcMethodAttribute("urn:xmds#MediaInventory", RequestNamespace="urn:xmds", ResponseNamespace="urn:xmds")]
1057+ [return: System.Xml.Serialization.SoapElementAttribute("success")]
1058+ public bool MediaInventory(string version, string serverKey, string hardwareKey, [System.Xml.Serialization.SoapElementAttribute("mediaInventory")] string mediaInventory1) {
1059+ object[] results = this.Invoke("MediaInventory", new object[] {
1060+ version,
1061+ serverKey,
1062+ hardwareKey,
1063+ mediaInventory1});
1064+ return ((bool)(results[0]));
1065+ }
1066+
1067+ /// <remarks/>
1068+ public void MediaInventoryAsync(string version, string serverKey, string hardwareKey, string mediaInventory1) {
1069+ this.MediaInventoryAsync(version, serverKey, hardwareKey, mediaInventory1, null);
1070+ }
1071+
1072+ /// <remarks/>
1073+ public void MediaInventoryAsync(string version, string serverKey, string hardwareKey, string mediaInventory1, object userState) {
1074+ if ((this.MediaInventoryOperationCompleted == null)) {
1075+ this.MediaInventoryOperationCompleted = new System.Threading.SendOrPostCallback(this.OnMediaInventoryOperationCompleted);
1076+ }
1077+ this.InvokeAsync("MediaInventory", new object[] {
1078+ version,
1079+ serverKey,
1080+ hardwareKey,
1081+ mediaInventory1}, this.MediaInventoryOperationCompleted, userState);
1082+ }
1083+
1084+ private void OnMediaInventoryOperationCompleted(object arg) {
1085+ if ((this.MediaInventoryCompleted != null)) {
1086+ System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg));
1087+ this.MediaInventoryCompleted(this, new MediaInventoryCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState));
1088+ }
1089+ }
1090+
1091+ /// <remarks/>
1092 public new void CancelAsync(object userState) {
1093 base.CancelAsync(userState);
1094 }
1095@@ -421,11 +462,11 @@
1096 }
1097
1098 /// <remarks/>
1099- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "2.0.50727.4918")]
1100+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "2.0.50727.4927")]
1101 public delegate void RegisterDisplayCompletedEventHandler(object sender, RegisterDisplayCompletedEventArgs e);
1102
1103 /// <remarks/>
1104- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "2.0.50727.4918")]
1105+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "2.0.50727.4927")]
1106 [System.Diagnostics.DebuggerStepThroughAttribute()]
1107 [System.ComponentModel.DesignerCategoryAttribute("code")]
1108 public partial class RegisterDisplayCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs {
1109@@ -447,11 +488,11 @@
1110 }
1111
1112 /// <remarks/>
1113- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "2.0.50727.4918")]
1114+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "2.0.50727.4927")]
1115 public delegate void RequiredFilesCompletedEventHandler(object sender, RequiredFilesCompletedEventArgs e);
1116
1117 /// <remarks/>
1118- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "2.0.50727.4918")]
1119+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "2.0.50727.4927")]
1120 [System.Diagnostics.DebuggerStepThroughAttribute()]
1121 [System.ComponentModel.DesignerCategoryAttribute("code")]
1122 public partial class RequiredFilesCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs {
1123@@ -473,11 +514,11 @@
1124 }
1125
1126 /// <remarks/>
1127- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "2.0.50727.4918")]
1128+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "2.0.50727.4927")]
1129 public delegate void GetFileCompletedEventHandler(object sender, GetFileCompletedEventArgs e);
1130
1131 /// <remarks/>
1132- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "2.0.50727.4918")]
1133+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "2.0.50727.4927")]
1134 [System.Diagnostics.DebuggerStepThroughAttribute()]
1135 [System.ComponentModel.DesignerCategoryAttribute("code")]
1136 public partial class GetFileCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs {
1137@@ -499,11 +540,11 @@
1138 }
1139
1140 /// <remarks/>
1141- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "2.0.50727.4918")]
1142+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "2.0.50727.4927")]
1143 public delegate void ScheduleCompletedEventHandler(object sender, ScheduleCompletedEventArgs e);
1144
1145 /// <remarks/>
1146- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "2.0.50727.4918")]
1147+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "2.0.50727.4927")]
1148 [System.Diagnostics.DebuggerStepThroughAttribute()]
1149 [System.ComponentModel.DesignerCategoryAttribute("code")]
1150 public partial class ScheduleCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs {
1151@@ -525,11 +566,11 @@
1152 }
1153
1154 /// <remarks/>
1155- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "2.0.50727.4918")]
1156+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "2.0.50727.4927")]
1157 public delegate void RecieveXmlLogCompletedEventHandler(object sender, RecieveXmlLogCompletedEventArgs e);
1158
1159 /// <remarks/>
1160- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "2.0.50727.4918")]
1161+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "2.0.50727.4927")]
1162 [System.Diagnostics.DebuggerStepThroughAttribute()]
1163 [System.ComponentModel.DesignerCategoryAttribute("code")]
1164 public partial class RecieveXmlLogCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs {
1165@@ -551,11 +592,11 @@
1166 }
1167
1168 /// <remarks/>
1169- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "2.0.50727.4918")]
1170+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "2.0.50727.4927")]
1171 public delegate void BlackListCompletedEventHandler(object sender, BlackListCompletedEventArgs e);
1172
1173 /// <remarks/>
1174- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "2.0.50727.4918")]
1175+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "2.0.50727.4927")]
1176 [System.Diagnostics.DebuggerStepThroughAttribute()]
1177 [System.ComponentModel.DesignerCategoryAttribute("code")]
1178 public partial class BlackListCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs {
1179@@ -577,11 +618,11 @@
1180 }
1181
1182 /// <remarks/>
1183- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "2.0.50727.4918")]
1184+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "2.0.50727.4927")]
1185 public delegate void SubmitLogCompletedEventHandler(object sender, SubmitLogCompletedEventArgs e);
1186
1187 /// <remarks/>
1188- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "2.0.50727.4918")]
1189+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "2.0.50727.4927")]
1190 [System.Diagnostics.DebuggerStepThroughAttribute()]
1191 [System.ComponentModel.DesignerCategoryAttribute("code")]
1192 public partial class SubmitLogCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs {
1193@@ -603,11 +644,11 @@
1194 }
1195
1196 /// <remarks/>
1197- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "2.0.50727.4918")]
1198+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "2.0.50727.4927")]
1199 public delegate void SubmitStatsCompletedEventHandler(object sender, SubmitStatsCompletedEventArgs e);
1200
1201 /// <remarks/>
1202- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "2.0.50727.4918")]
1203+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "2.0.50727.4927")]
1204 [System.Diagnostics.DebuggerStepThroughAttribute()]
1205 [System.ComponentModel.DesignerCategoryAttribute("code")]
1206 public partial class SubmitStatsCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs {
1207@@ -627,6 +668,32 @@
1208 }
1209 }
1210 }
1211+
1212+ /// <remarks/>
1213+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "2.0.50727.4927")]
1214+ public delegate void MediaInventoryCompletedEventHandler(object sender, MediaInventoryCompletedEventArgs e);
1215+
1216+ /// <remarks/>
1217+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "2.0.50727.4927")]
1218+ [System.Diagnostics.DebuggerStepThroughAttribute()]
1219+ [System.ComponentModel.DesignerCategoryAttribute("code")]
1220+ public partial class MediaInventoryCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs {
1221+
1222+ private object[] results;
1223+
1224+ internal MediaInventoryCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) :
1225+ base(exception, cancelled, userState) {
1226+ this.results = results;
1227+ }
1228+
1229+ /// <remarks/>
1230+ public bool Result {
1231+ get {
1232+ this.RaiseExceptionIfNecessary();
1233+ return ((bool)(this.results[0]));
1234+ }
1235+ }
1236+ }
1237 }
1238
1239 #pragma warning restore 1591
1240\ No newline at end of file
1241
1242=== modified file 'client/dotNET/Web References/xmds/Reference.map'
1243--- client/dotNET/Web References/xmds/Reference.map 2009-12-31 11:38:50 +0000
1244+++ client/dotNET/Web References/xmds/Reference.map 2011-02-28 15:09:00 +0000
1245@@ -1,6 +1,6 @@
1246 <?xml version="1.0" encoding="utf-8"?>
1247 <DiscoveryClientResultsFile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
1248 <Results>
1249- <DiscoveryClientResult referenceType="System.Web.Services.Discovery.ContractReference" url="http://localhost/1.0.0/server/xmds.php?wsdl" filename="xmds.wsdl" />
1250+ <DiscoveryClientResult referenceType="System.Web.Services.Discovery.ContractReference" url="http://localhost/Series 1.2/server-121-soap-wsdl/server/xmds.php?wsdl" filename="xmds.wsdl" />
1251 </Results>
1252 </DiscoveryClientResultsFile>
1253\ No newline at end of file
1254
1255=== modified file 'client/dotNET/Web References/xmds/xmds.wsdl'
1256--- client/dotNET/Web References/xmds/xmds.wsdl 2009-12-31 11:38:50 +0000
1257+++ client/dotNET/Web References/xmds/xmds.wsdl 2011-02-28 15:09:00 +0000
1258@@ -81,6 +81,15 @@
1259 <wsdl:message name="SubmitStatsResponse">
1260 <wsdl:part name="success" type="xsd:boolean" />
1261 </wsdl:message>
1262+ <wsdl:message name="MediaInventoryRequest">
1263+ <wsdl:part name="version" type="xsd:string" />
1264+ <wsdl:part name="serverKey" type="xsd:string" />
1265+ <wsdl:part name="hardwareKey" type="xsd:string" />
1266+ <wsdl:part name="mediaInventory" type="xsd:string" />
1267+ </wsdl:message>
1268+ <wsdl:message name="MediaInventoryResponse">
1269+ <wsdl:part name="success" type="xsd:boolean" />
1270+ </wsdl:message>
1271 <wsdl:portType name="xmdsPortType">
1272 <wsdl:operation name="RegisterDisplay">
1273 <documentation>Registered the Display on the Xibo Network</documentation>
1274@@ -122,6 +131,11 @@
1275 <wsdl:input message="tns:SubmitStatsRequest" />
1276 <wsdl:output message="tns:SubmitStatsResponse" />
1277 </wsdl:operation>
1278+ <wsdl:operation name="MediaInventory">
1279+ <documentation>Report back the clients MediaInventory</documentation>
1280+ <wsdl:input message="tns:MediaInventoryRequest" />
1281+ <wsdl:output message="tns:MediaInventoryResponse" />
1282+ </wsdl:operation>
1283 </wsdl:portType>
1284 <wsdl:binding name="xmdsBinding" type="tns:xmdsPortType">
1285 <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="rpc" />
1286@@ -197,10 +211,19 @@
1287 <soap:body use="encoded" namespace="urn:xmds" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
1288 </wsdl:output>
1289 </wsdl:operation>
1290+ <wsdl:operation name="MediaInventory">
1291+ <soap:operation soapAction="urn:xmds#MediaInventory" style="rpc" />
1292+ <wsdl:input>
1293+ <soap:body use="encoded" namespace="urn:xmds" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
1294+ </wsdl:input>
1295+ <wsdl:output>
1296+ <soap:body use="encoded" namespace="urn:xmds" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
1297+ </wsdl:output>
1298+ </wsdl:operation>
1299 </wsdl:binding>
1300 <wsdl:service name="xmds">
1301 <wsdl:port name="xmdsPort" binding="tns:xmdsBinding">
1302- <soap:address location="http://localhost/1.0.0/server/xmds.php" />
1303+ <soap:address location="http://localhost/Series%201.2/server-121-soap-wsdl/server/xmds.php" />
1304 </wsdl:port>
1305 </wsdl:service>
1306 </wsdl:definitions>
1307\ No newline at end of file
1308
1309=== modified file 'client/dotNET/XiboClient.csproj'
1310--- client/dotNET/XiboClient.csproj 2010-08-22 12:42:36 +0000
1311+++ client/dotNET/XiboClient.csproj 2011-02-28 15:09:00 +0000
1312@@ -161,6 +161,7 @@
1313 <Compile Include="Region.cs">
1314 <SubType>Component</SubType>
1315 </Compile>
1316+ <Compile Include="RequiredFiles.cs" />
1317 <Compile Include="Rss.cs">
1318 <SubType>Form</SubType>
1319 </Compile>
1320@@ -267,10 +268,10 @@
1321 <WebReferences Include="Web References\" />
1322 </ItemGroup>
1323 <ItemGroup>
1324- <WebReferenceUrl Include="http://localhost/1.0.0/server/xmds.php%3fwsdl">
1325+ <WebReferenceUrl Include="http://localhost/Series%25201.2/server-121-soap-wsdl/server/xmds.php%3fwsdl">
1326 <UrlBehavior>Dynamic</UrlBehavior>
1327 <RelPath>Web References\xmds\</RelPath>
1328- <UpdateFromURL>http://localhost/1.0.0/server/xmds.php%3fwsdl</UpdateFromURL>
1329+ <UpdateFromURL>http://localhost/Series%25201.2/server-121-soap-wsdl/server/xmds.php%3fwsdl</UpdateFromURL>
1330 <ServiceLocationURL>
1331 </ServiceLocationURL>
1332 <CachedDynamicPropName>
1333@@ -294,11 +295,12 @@
1334 </EmbeddedResource>
1335 </ItemGroup>
1336 <ItemGroup>
1337- <EmbeddedResource Include="Resources\splash.jpg" />
1338- </ItemGroup>
1339- <ItemGroup>
1340 <EmbeddedResource Include="Resources\HtmlTemplate.htm" />
1341 </ItemGroup>
1342+ <ItemGroup>
1343+ <EmbeddedResource Include="Resources\splash.jpg">
1344+ </EmbeddedResource>
1345+ </ItemGroup>
1346 <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
1347 <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
1348 Other similar extension points exist, see Microsoft.Common.targets.
1349
1350=== modified file 'client/dotNET/app.config'
1351--- client/dotNET/app.config 2010-09-26 14:33:38 +0000
1352+++ client/dotNET/app.config 2011-02-28 15:09:00 +0000
1353@@ -14,7 +14,7 @@
1354 <value>DEFAULT</value>
1355 </setting>
1356 <setting name="XiboClient_xmds_xmds" serializeAs="String">
1357- <value>http://localhost/xibo/xmds.php</value>
1358+ <value>http://localhost/Series%201.2/server-121-soap-wsdl/server/xmds.php</value>
1359 </setting>
1360 <setting name="ServerKey" serializeAs="String">
1361 <value>yourserverkey</value>
1362@@ -79,6 +79,9 @@
1363 <setting name="emptyLayoutDuration" serializeAs="String">
1364 <value>10</value>
1365 </setting>
1366+ <setting name="RequiredFilesFile" serializeAs="String">
1367+ <value>requiredFiles.xml</value>
1368+ </setting>
1369 </XiboClient.Properties.Settings>
1370 </userSettings>
1371 <applicationSettings>
1372@@ -102,7 +105,7 @@
1373 <value>cacheManager.xml</value>
1374 </setting>
1375 <setting name="ClientVersion" serializeAs="String">
1376- <value>1.2.0</value>
1377+ <value>1.2.2</value>
1378 </setting>
1379 <setting name="xmdsResetTimeout" serializeAs="String">
1380 <value>900</value>
1381
1382=== modified file 'client/dotNET/bin/Release/AxInterop.ShockwaveFlashObjects.dll'
1383Binary 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:00 +0000 differ
1384=== modified file 'client/dotNET/bin/Release/AxInterop.WMPLib.dll'
1385Binary 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:00 +0000 differ
1386=== modified file 'client/dotNET/bin/Release/Interop.ShockwaveFlashObjects.dll'
1387Binary 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:00 +0000 differ
1388=== modified file 'client/dotNET/bin/Release/Interop.WMPLib.dll'
1389Binary 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:00 +0000 differ
1390=== modified file 'client/dotNET/bin/Release/XiboClient.exe.config'
1391--- client/dotNET/bin/Release/XiboClient.exe.config 2010-04-19 21:45:10 +0000
1392+++ client/dotNET/bin/Release/XiboClient.exe.config 2011-02-28 15:09:00 +0000
1393@@ -14,7 +14,7 @@
1394 <value>DEFAULT</value>
1395 </setting>
1396 <setting name="XiboClient_xmds_xmds" serializeAs="String">
1397- <value>http://localhost/xibo/xmds.php</value>
1398+ <value>http://localhost/Series%201.2/server-121-soap-wsdl/server/xmds.php</value>
1399 </setting>
1400 <setting name="ServerKey" serializeAs="String">
1401 <value>yourserverkey</value>
1402@@ -61,6 +61,27 @@
1403 <setting name="scrollStepAmount" serializeAs="String">
1404 <value>1</value>
1405 </setting>
1406+ <setting name="sizeX" serializeAs="String">
1407+ <value>0</value>
1408+ </setting>
1409+ <setting name="sizeY" serializeAs="String">
1410+ <value>0</value>
1411+ </setting>
1412+ <setting name="offsetX" serializeAs="String">
1413+ <value>0</value>
1414+ </setting>
1415+ <setting name="offsetY" serializeAs="String">
1416+ <value>0</value>
1417+ </setting>
1418+ <setting name="expireModifiedLayouts" serializeAs="String">
1419+ <value>True</value>
1420+ </setting>
1421+ <setting name="emptyLayoutDuration" serializeAs="String">
1422+ <value>10</value>
1423+ </setting>
1424+ <setting name="RequiredFilesFile" serializeAs="String">
1425+ <value>requiredFiles.xml</value>
1426+ </setting>
1427 </XiboClient.Properties.Settings>
1428 </userSettings>
1429 <applicationSettings>
1430@@ -75,7 +96,7 @@
1431 <value>blacklist.xml</value>
1432 </setting>
1433 <setting name="Version" serializeAs="String">
1434- <value>1</value>
1435+ <value>2</value>
1436 </setting>
1437 <setting name="StatsLogFile" serializeAs="String">
1438 <value>stats.xml</value>
1439@@ -84,7 +105,7 @@
1440 <value>cacheManager.xml</value>
1441 </setting>
1442 <setting name="ClientVersion" serializeAs="String">
1443- <value>1.0.7</value>
1444+ <value>1.2.2</value>
1445 </setting>
1446 <setting name="xmdsResetTimeout" serializeAs="String">
1447 <value>900</value>
1448
1449=== modified file 'client/dotNET/bin/Release/XiboClient.vshost.exe.config'
1450--- client/dotNET/bin/Release/XiboClient.vshost.exe.config 2010-04-19 21:45:10 +0000
1451+++ client/dotNET/bin/Release/XiboClient.vshost.exe.config 2011-02-28 15:09:00 +0000
1452@@ -14,7 +14,7 @@
1453 <value>DEFAULT</value>
1454 </setting>
1455 <setting name="XiboClient_xmds_xmds" serializeAs="String">
1456- <value>http://localhost/xibo/xmds.php</value>
1457+ <value>http://localhost/Series%201.2/server-121-soap-wsdl/server/xmds.php</value>
1458 </setting>
1459 <setting name="ServerKey" serializeAs="String">
1460 <value>yourserverkey</value>
1461@@ -61,6 +61,27 @@
1462 <setting name="scrollStepAmount" serializeAs="String">
1463 <value>1</value>
1464 </setting>
1465+ <setting name="sizeX" serializeAs="String">
1466+ <value>0</value>
1467+ </setting>
1468+ <setting name="sizeY" serializeAs="String">
1469+ <value>0</value>
1470+ </setting>
1471+ <setting name="offsetX" serializeAs="String">
1472+ <value>0</value>
1473+ </setting>
1474+ <setting name="offsetY" serializeAs="String">
1475+ <value>0</value>
1476+ </setting>
1477+ <setting name="expireModifiedLayouts" serializeAs="String">
1478+ <value>True</value>
1479+ </setting>
1480+ <setting name="emptyLayoutDuration" serializeAs="String">
1481+ <value>10</value>
1482+ </setting>
1483+ <setting name="RequiredFilesFile" serializeAs="String">
1484+ <value>requiredFiles.xml</value>
1485+ </setting>
1486 </XiboClient.Properties.Settings>
1487 </userSettings>
1488 <applicationSettings>
1489@@ -75,7 +96,7 @@
1490 <value>blacklist.xml</value>
1491 </setting>
1492 <setting name="Version" serializeAs="String">
1493- <value>1</value>
1494+ <value>2</value>
1495 </setting>
1496 <setting name="StatsLogFile" serializeAs="String">
1497 <value>stats.xml</value>
1498@@ -84,7 +105,7 @@
1499 <value>cacheManager.xml</value>
1500 </setting>
1501 <setting name="ClientVersion" serializeAs="String">
1502- <value>1.0.7</value>
1503+ <value>1.2.2</value>
1504 </setting>
1505 <setting name="xmdsResetTimeout" serializeAs="String">
1506 <value>900</value>
1507
1508=== modified file 'client/python/XiboClient.py'
1509--- client/python/XiboClient.py 2011-02-10 22:25:35 +0000
1510+++ client/python/XiboClient.py 2011-02-28 15:09:00 +0000
1511@@ -48,7 +48,11 @@
1512 import PIL.Image
1513 import math
1514
1515+<<<<<<< TREE
1516 version = "1.3.0a1"
1517+=======
1518+version = "1.2.1a1"
1519+>>>>>>> MERGE-SOURCE
1520
1521 # What layout schema version is supported
1522 schemaVersion = 1
1523@@ -1015,11 +1019,18 @@
1524 if config.get('Main','manualUpdate') == 'true':
1525 log.lights('offlineUpdate','start')
1526
1527+ if config.get('Main','manualUpdate') == 'true':
1528+ log.lights('offlineUpdate','start')
1529+
1530 # Check if the file is downloading already
1531 if not tmpFileName in self.runningDownloads:
1532 # Make a download thread and actually download the file.
1533 # Add the running thread to the self.runningDownloads dictionary
1534+<<<<<<< TREE
1535 self.runningDownloads[tmpFileName] = XiboDownloadThread(self,tmpType,tmpFileName,tmpSize,tmpHash,tmpId)
1536+=======
1537+ self.runningDownloads[tmpFileName] = XiboDownloadThread(self,tmpType,tmpFileName,tmpSize,tmpHash)
1538+>>>>>>> MERGE-SOURCE
1539 log.updateRunningDownloads(len(self.runningDownloads))
1540
1541 if self.offline:
1542@@ -2544,7 +2555,11 @@
1543
1544 class XMDS:
1545 def __init__(self):
1546+<<<<<<< TREE
1547 self.__schemaVersion__ = "3"
1548+=======
1549+ self.__schemaVersion__ = "2"
1550+>>>>>>> MERGE-SOURCE
1551
1552 # Semaphore to allow only one XMDS call to run check simultaneously
1553 self.checkLock = Semaphore()
1554@@ -2959,6 +2974,7 @@
1555 log.log(0,"error",str(err))
1556 self.hasInitialised = False
1557
1558+<<<<<<< TREE
1559 def MediaInventory(self,inventoryXml):
1560 response = None
1561 log.lights('Log','amber')
1562@@ -3186,6 +3202,186 @@
1563 log.lights('RD','green')
1564
1565 #### Finish Webservice
1566+=======
1567+class XMDSOffline(Thread):
1568+ def __init__(self,displayManager):
1569+ Thread.__init__(self)
1570+ self.__schemaVersion__ = "2"
1571+ self.displayManager = displayManager
1572+ self.updatePath = ""
1573+ self.__running__ = True
1574+ self.__scanPath__ = '/media'
1575+
1576+ # Semaphore to allow only one XMDS call to run check simultaneously
1577+ self.checkLock = Semaphore()
1578+
1579+ self.hasInitialised = False
1580+
1581+ salt = None
1582+ try:
1583+ salt = config.get('Main','xmdsClientID')
1584+ except:
1585+ log.log(0,"error",_("No XMDS Client ID specified in your configuration"))
1586+ log.log(0,"error",_("Please check your xmdsClientID configuration option"))
1587+ exit(1)
1588+
1589+ self.uuid = uuid.uuid5(uuid.NAMESPACE_DNS, salt)
1590+ # Convert the UUID in to a SHA1 hash
1591+ self.uuid = hashlib.sha1(str(self.uuid)).hexdigest()
1592+
1593+ licenseKey = ''
1594+ try:
1595+ licenseKey = config.get('Main','xmdsLicenseKey')
1596+ except:
1597+ pass
1598+
1599+ if licenseKey != '':
1600+ self.uuid = licenseKey
1601+
1602+ self.name = None
1603+ try:
1604+ self.name = config.get('Main','xmdsClientName')
1605+ except:
1606+ pass
1607+
1608+ if self.name == None or self.name == "":
1609+ import platform
1610+ self.name = platform.node()
1611+
1612+ self.start()
1613+
1614+ def run(self):
1615+ # Sleep for 10 seconds to allow the client time to start and settle.
1616+ time.sleep(10)
1617+
1618+ # Startup a loop listening scanning for new mounts
1619+ log.log(5,'info','Offline Update: Scanning.',True)
1620+ while self.__running__:
1621+ for folder in os.listdir(self.__scanPath__):
1622+ log.log(5,'info','Offline Update: Checking %s for new content.' % os.path.join(self.__scanPath__,folder),True)
1623+ log.log(5,'info','Offline Update: Client License Key: %s' % self.uuid,True)
1624+ if os.path.isdir(os.path.join(self.__scanPath__,folder,self.uuid)):
1625+ log.log(5,'info','Offline Update: Starting update from %s.' % os.path.join(self.__scanPath__,folder,self.uuid),True)
1626+ self.updatePath = os.path.join(self.__scanPath__,folder)
1627+ self.displayManager.scheduler.collect()
1628+ time.sleep(5)
1629+ self.displayManager.downloader.collect()
1630+ log.log(5,'info','Offline Update: Sleeping 30 seconds.',True)
1631+ time.sleep(30)
1632+
1633+ def getIP(self):
1634+ return 'Offline Mode'
1635+
1636+ def getDisk(self):
1637+ s = os.statvfs(config.get('Main','libraryDir'))
1638+ return (s.f_bsize * s.f_blocks,s.f_bsize * s.f_bavail)
1639+
1640+ def getUUID(self):
1641+ return str(self.uuid)
1642+
1643+ def getName(self):
1644+ return str(self.name)
1645+
1646+ def getKey(self):
1647+ return 'Offline'
1648+
1649+ def check(self):
1650+ return True
1651+
1652+ def RequiredFiles(self):
1653+ """Connect to XMDS and get a list of required files"""
1654+ log.lights('RF','amber')
1655+ req = None
1656+ if self.check():
1657+ try:
1658+ # Update the IP Address shown on the infoScreen
1659+ log.updateIP(self.getIP())
1660+ except:
1661+ pass
1662+
1663+ log.updateFreeSpace(self.getDisk())
1664+
1665+ try:
1666+ fh = open(os.path.join(self.updatePath,self.uuid,'rf.xml'), 'r')
1667+ req = fh.read()
1668+ fh.close()
1669+ except IOError:
1670+ log.lights('RF','red')
1671+ raise XMDSException("XMDS could not be initialised")
1672+
1673+ else:
1674+ log.log(0,"error","XMDS could not be initialised")
1675+ log.lights('RF','grey')
1676+ raise XMDSException("XMDS could not be initialised")
1677+
1678+ log.lights('RF','green')
1679+ return req
1680+
1681+ def SubmitLog(self,logXml):
1682+ pass
1683+
1684+ def SubmitStats(self,statXml):
1685+ pass
1686+
1687+ def Schedule(self):
1688+ """Connect to XMDS and get the current schedule"""
1689+ log.lights('S','amber')
1690+ req = None
1691+ if self.check():
1692+ try:
1693+ fh = open(os.path.join(self.updatePath,self.uuid,'schedule.xml'), 'r')
1694+ req = fh.read()
1695+ fh.close()
1696+ except IOError:
1697+ log.lights('S','red')
1698+ raise XMDSException("XMDS could not be initialised")
1699+ else:
1700+ log.log(0,"error","XMDS could not be initialised")
1701+ log.lights('S','grey')
1702+ raise XMDSException("XMDS could not be initialised")
1703+
1704+ log.lights('S','green')
1705+ return req
1706+
1707+ def GetFile(self,tmpPath,tmpType,tmpOffset,tmpChunk):
1708+ """Connect to XMDS and download a file"""
1709+ response = None
1710+ log.lights('GF','amber')
1711+ if self.check():
1712+ if tmpType == 'media':
1713+ try:
1714+ fh = open(os.path.join(self.updatePath,self.uuid,tmpPath), 'r')
1715+ fh.seek(tmpOffset)
1716+ response = fh.read(tmpChunk)
1717+ fh.close()
1718+ except:
1719+ log.lights('GF','red')
1720+ raise XMDSException("XMDS could not be initialised")
1721+ if tmpType == 'layout':
1722+ try:
1723+ fh = open(os.path.join(self.updatePath,self.uuid,tmpPath), 'r')
1724+ response = fh.read()
1725+ fh.close()
1726+ except:
1727+ log.lights('GF','red')
1728+ raise XMDSException("XMDS could not be initialised")
1729+ if tmpType == 'blacklist':
1730+ response = ""
1731+ else:
1732+ log.log(0,"error","XMDS could not be initialised")
1733+ log.lights('GF','grey')
1734+ raise XMDSException("XMDS could not be initialised")
1735+
1736+ log.lights('GF','green')
1737+ return response
1738+
1739+ def RegisterDisplay(self):
1740+ log.lights('RD','amber')
1741+ time.sleep(5)
1742+ log.lights('RD','green')
1743+
1744+#### Finish Webservice
1745+>>>>>>> MERGE-SOURCE
1746
1747 class XiboDisplayManager:
1748 def __init__(self):
1749
1750=== added file 'client/python/client.conf'
1751--- client/python/client.conf 1970-01-01 00:00:00 +0000
1752+++ client/python/client.conf 2011-02-28 15:09:00 +0000
1753@@ -0,0 +1,25 @@
1754+[Main]
1755+;clientConfLoc=/home/matt/xibo
1756+;clientConfName=site.cfg
1757+
1758+;logWriter defines where the log file is written to
1759+;xiboLogScreen - Console
1760+;xiboLogFile - Log file stored in the same folder as the executable
1761+
1762+logWriter=xiboLogFile
1763+
1764+;logLevel defines the level of information written to the logger
1765+;INFO - information, warning and error messages
1766+;WARNING - warning and error messages
1767+;ERROR - error messages
1768+
1769+logLevel=INFO
1770+
1771+logFileName=error.log
1772+
1773+[Options]
1774+logType=XiboLogXmds,XiboLogFile,XiboLogScreen
1775+logTypeHuman=Xibo Server,Local File,Console
1776+scheduler=XmdsScheduler
1777+downloader=XiboDownloadManager
1778+colourDepth=8,16,24
1779
1780=== renamed file 'client/python/client.conf' => 'client/python/client.conf.moved'
1781=== added file 'client/python/configure.py'
1782--- client/python/configure.py 1970-01-01 00:00:00 +0000
1783+++ client/python/configure.py 2011-02-28 15:09:00 +0000
1784@@ -0,0 +1,1753 @@
1785+#!/usr/bin/python
1786+
1787+# -*- coding: utf-8 -*-
1788+
1789+#
1790+# Xibo - Digitial Signage - http://www.xibo.org.uk
1791+# Copyright (C) 2011 Matt Holder
1792+#
1793+# This file is part of Xibo.
1794+#
1795+# Xibo is free software: you can redistribute it and/or modify
1796+# it under the terms of the GNU Affero General Public License as published by
1797+# the Free Software Foundation, either version 3 of the License, or
1798+# any later version.
1799+#
1800+# Xibo is distributed in the hope that it will be useful,
1801+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1802+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1803+# GNU Affero General Public License for more details.
1804+#
1805+# You should have received a copy of the GNU Affero General Public License
1806+# along with Xibo. If not, see <http://www.gnu.org/licenses/>.
1807+#
1808+
1809+gettextAvailable = None
1810+
1811+try:
1812+ import gettext
1813+ gettextAvailable = True
1814+except:
1815+ print "Could not import gettext"
1816+ print "Creating dummy function for _()"
1817+ def _(string):
1818+ return string
1819+try:
1820+ import sys
1821+except:
1822+ print "Could not import sys module"
1823+ sys.exit()
1824+
1825+try:
1826+ import uuid
1827+except:
1828+ print "Could not import uuid module"
1829+ sys.exit()
1830+
1831+try:
1832+ import ConfigParser
1833+except:
1834+ print "Could not import ConfigParser module"
1835+ sys.exit()
1836+
1837+try:
1838+ import os
1839+except:
1840+ print "Could not import os module"
1841+ sys.exit()
1842+
1843+try:
1844+ import logging
1845+except:
1846+ print "Could not import logging module"
1847+ sys.exit()
1848+
1849+try:
1850+ import pygtk
1851+ pygtk.require("2.0")
1852+except:
1853+ print "Could not import pygtk"
1854+ sys.exit()
1855+
1856+try:
1857+ import gtk
1858+except:
1859+ print "Could not import gtk"
1860+ sys.exit(1)
1861+
1862+try:
1863+ import gtk.glade
1864+except:
1865+ print "Could not import gtk.glade"
1866+ sys.exit(1)
1867+
1868+try:
1869+ import gobject
1870+except:
1871+ print "Could not import gobject"
1872+ sys.exit()
1873+
1874+#Only run this if gettext is available
1875+if gettextAvailable:
1876+ gettext.install('ivcm', './locale', unicode=False)
1877+
1878+
1879+class xiboConfWindow:
1880+ """This is the PyWine application"""
1881+
1882+
1883+ def __init__(self,clientConfFile,lift = False):
1884+
1885+ #This is the location of the config. file for the client
1886+ #itself. This comes from when the instance of the class
1887+ #is created.
1888+ self.clientConfFile = clientConfFile
1889+
1890+ #Firstly, read in the values relating to log from the config. client config. file
1891+ config = None
1892+ try:
1893+ config = ConfigParser.ConfigParser()
1894+ config.read(self.clientConfFile)
1895+ except:
1896+ print "Could not open %s"%self.clientConfFile
1897+
1898+ #Xibo client configuration file name
1899+ logFileName="error.log"
1900+ try:
1901+ logFileName = config.get('Main','logFileName')
1902+ except:
1903+ pass
1904+
1905+ logWriter="xiboLogScreen"
1906+ try:
1907+ logWriter = config.get('Main','logWriter')
1908+ except:
1909+ pass
1910+
1911+
1912+ logLevel="INFO"
1913+ try:
1914+ logLevel = config.get('Main','logLevel')
1915+ except:
1916+ pass
1917+ a=logging
1918+
1919+ loggingLevel = None
1920+ if logLevel == "INFO":
1921+ loggingLevel = a.INFO
1922+ elif logLevel == "WARNING":
1923+ loggingLevel = a.WARNING
1924+ elif logLevel == "ERROR":
1925+ loggingLevel = a.ERROR
1926+
1927+ if logWriter == "xiboLogScreen":
1928+ a.basicConfig(level=loggingLevel)
1929+ elif logWriter == "xiboLogFile":
1930+
1931+ a.basicConfig(level=loggingLevel,filename=logFileName,filemode="w")
1932+
1933+# #Set up the logger
1934+# logging.basicConfig(level=logging.INFO,filename="error.log",filemode="w")
1935+# #format='%(asctime)s %(levelname)s %(lineno)d %(message)s'
1936+
1937+
1938+ self.logger = a.getLogger("PyClientConfig")
1939+ self.logger1 = a.getLogger("PyClientConfig.GUI")
1940+ self.logger2 = a.getLogger('PyClientConfig.readConfig')
1941+ self.logger3 = a.getLogger("PyClientConfig.saveConfigSignal")
1942+ self.logger4 = a.getLogger("PyClientConfig.genClientID")
1943+ self.logger5 = a.getLogger("PyClientConfig.getConfValues")
1944+ self.logger6 = a.getLogger("PyClientConfig.advancedOptionsCheck")
1945+ self.logger7 = a.getLogger("PyClientConfig.readConfigAppConf")
1946+ self.logger8 = a.getLogger("PyClientConfig.offlineOperationToggle")
1947+ self.logger9 = a.getLogger("PyClientConfig.clearFormSignal")
1948+ self.logger10 = a.getLogger("PyClientConfig.onDestroy")
1949+ self.logger11 = a.getLogger("PyClientConfig.saveSignal")
1950+ self.logger12 = a.getLogger("PyclientConfig.LoadDefaultValues")
1951+
1952+ self.logger1.info('Config. client config. file: %s'%self.clientConfFile)
1953+
1954+ self.logger1.info("logWriter: %s"%logWriter)
1955+ self.logger1.info("logLevel: %s"%logLevel)
1956+ self.logger.info("logFileName: %s"%logFileName)
1957+
1958+ #Name of the default log file for the python client
1959+ self.pyClientLogName = "run.log"
1960+
1961+
1962+ #Read out the values from the client configuration file
1963+ configValues = self.readConfigAppConf()
1964+
1965+ #Take the options for log type from the file, and set the
1966+ #class instance variable. The combo box is then populated from this.
1967+ self.logWriterTypes = configValues["logTypeOptions"]
1968+
1969+ self.logger1.info("logWriter: %s"%self.logWriterTypes)
1970+
1971+ #Take the options for the human readable log type options
1972+ self.logWriterHumanTypes = configValues["logTypeHumanOptions"]
1973+
1974+ self.logger1.info("logWriteHumanOptions: %s"%self.logWriterHumanTypes)
1975+
1976+ #Take the location of the configuration file and set the class
1977+ #instance variable. This path is then used when the config.
1978+ #file is written
1979+
1980+ self.pyClientConfName = configValues["xiboClientConf"]
1981+
1982+
1983+ self.logger1.info("Xibo client config. file: %s"%self.pyClientConfName)
1984+
1985+ self.pyClientConfDefaultsName = "defaults.cfg"
1986+
1987+ #Grab the directory location and check this directory exists.
1988+
1989+ self.pyclientConfPath = configValues["clientConfLoc"]
1990+
1991+ self.logger1.info("Xibo client config. file path: %s"%self.pyclientConfPath)
1992+
1993+ self.logger1.info("Config file combined path: %s"%os.path.join(self.pyclientConfPath,self.pyClientConfName))
1994+
1995+ #Take the options for scheduler type and add them to a class
1996+ #instance variable
1997+
1998+ self.schedulerOptions = configValues["schedulerOptions"]
1999+
2000+ #Add a blank entry to the combo box, so that a blank option
2001+ #can mean that the value is not written to the config. file
2002+ self.schedulerOptions.insert(0,"")
2003+
2004+ #Downloader options
2005+ self.downloaderOptions = configValues["downloaderOptions"]
2006+ self.downloaderOptions.insert(0,"")
2007+
2008+ #Colour Depth options
2009+ self.colourDepthOptions = configValues["colourDepthOptions"]
2010+ self.colourDepthOptions.insert(0,"")
2011+
2012+ #Lift enable options
2013+ self.liftEnableOptions = ["True","False"]
2014+
2015+ #Manual update options
2016+ self.manualUpdateOptions = ["True","False"]
2017+
2018+ #Set the Glade file
2019+ self.builder = gtk.Builder()
2020+ self.builder.add_from_file("gui.glade")
2021+ self.builder.connect_signals(self)
2022+
2023+ #Create instances of the text fields, window etc
2024+ self.window = self.builder.get_object("mainWindow")
2025+ self.clearButton = self.builder.get_object("clearFields")
2026+ self.saveButton = self.builder.get_object("saveConfig")
2027+
2028+ self.serverURLText = self.builder.get_object("serverURLText")
2029+ self.clientIDText = self.builder.get_object("clientIDText")
2030+ self.serverKeyText = self.builder.get_object("serverKeyText")
2031+ self.refreshText = self.builder.get_object("refreshText")
2032+ self.serverConnBool = self.builder.get_object("serverConnection")
2033+ self.fullScreenBool = self.builder.get_object("fullScreen")
2034+ self.screenWidthText = self.builder.get_object("screenWidthText")
2035+ self.screenHeightText = self.builder.get_object("screenHeightText")
2036+ self.captureStatisticsBool = self.builder.get_object("captureStatistics")
2037+ self.queueSizeText = self.builder.get_object("queueSizeText")
2038+ self.logLevelSpin = self.builder.get_object("logLevelSpin")
2039+ self.logTypeCombo = self.builder.get_object("logTypeCombo")
2040+ self.clientNameText = self.builder.get_object("clientNameText")
2041+
2042+ self.offlineCheckButton = self.builder.get_object("offlineCheckButton")
2043+
2044+ #Advanced options widgets
2045+
2046+ self.liftDefaultTagText = self.builder.get_object('liftDefaultTagText')
2047+ self.lift7TagText = self.builder.get_object('lift7TagText')
2048+ self.lift6TagText = self.builder.get_object('lift6TagText')
2049+ self.lift5TagText = self.builder.get_object('lift5TagText')
2050+ self.lift4TagText = self.builder.get_object('lift4TagText')
2051+ self.lift3TagText = self.builder.get_object('lift3TagText')
2052+ self.lift2TagText = self.builder.get_object('lift2TagText')
2053+ self.lift1TagText = self.builder.get_object('lift1TagText')
2054+ self.lift0TagText = self.builder.get_object('lift0TagText')
2055+ self.firstSerialText = self.builder.get_object('firstSerialText')
2056+ self.secondSerialText = self.builder.get_object('secondSerialText')
2057+ self.liftTriggerValue = self.builder.get_object('liftTriggerValue')
2058+ self.liftEnableCombo = self.builder.get_object('liftEnableCombo')
2059+ self.dateFormatEntry = self.builder.get_object('dateFormatEntry')
2060+ self.libraryEntry = self.builder.get_object('libraryEntry')
2061+ self.socketTimeSpin = self.builder.get_object('socketTimeSpin')
2062+ self.checksumCheckButton = self.builder.get_object('checksumCheckButton')
2063+ self.lowTextureCheckButton = self.builder.get_object('lowTextureCheckButton')
2064+ self.framesSpin = self.builder.get_object('framesSpin')
2065+ self.vwidthSpin = self.builder.get_object('vwidthSpin')
2066+ self.vheightSpin = self.builder.get_object('vheightSpin')
2067+ self.vrotateSpin = self.builder.get_object('vrotateSpin')
2068+ self.schedulerCombo = self.builder.get_object("schedulerCombo")
2069+ self.downloaderCombo = self.builder.get_object("downloaderCombo")
2070+ self.colourDepthCombo = self.builder.get_object("colourDepthCombo")
2071+ self.notebook1 = self.builder.get_object("notebook1")
2072+
2073+ self.errorDialog = self.builder.get_object("errorDialog")
2074+ self.messageDialog = self.builder.get_object("infoDialog")
2075+
2076+ self.statsCaptureLabel = self.builder.get_object("statsCaptureLabel")
2077+ self.statsQueueSizeLabel = self.builder.get_object("statsQueueSizeLabel")
2078+
2079+ #Grab the log file link button and make it invisible by default
2080+ self.logFileLinkButton = self.builder.get_object("logFileLinkButton")
2081+ self.logFileLinkButton.hide()
2082+
2083+ self.statsFrame = self.builder.get_object("frame2")
2084+
2085+ #We want to be able to hide the lift options if the command line flag
2086+ #has not been passed. We can do this by grabbing the 5th (4th when
2087+ #counting from zero) page, and using the hide method.
2088+
2089+ self.liftTabVisible = lift
2090+ print self.liftTabVisible
2091+
2092+ if lift == False:
2093+ liftPage = self.notebook1.get_nth_page(4)
2094+ liftPage.hide()
2095+ self.logger1.info("Lift options hidden")
2096+
2097+ #Hide the statistics options unless the lift
2098+ #tab is being shown
2099+ self.captureStatisticsBool.hide()
2100+ self.queueSizeText.hide()
2101+ self.statsCaptureLabel.hide()
2102+ self.statsQueueSizeLabel.hide()
2103+ self.statsFrame.hide()
2104+
2105+ else:
2106+ self.logger1.info("Lift options available")
2107+
2108+ #Set a class instance variable for whether the advanced tab is shown or not
2109+ self.advancedTabVisible = False
2110+
2111+ #Now hide the tab
2112+ advancedPage = self.notebook1.get_nth_page(3)
2113+ advancedPage.hide()
2114+
2115+ #Fill in the comboboxes
2116+
2117+ #log type combobox
2118+
2119+ liststore = gtk.ListStore(gobject.TYPE_STRING)
2120+ print "ABC: ",self.logWriterHumanTypes
2121+ for elem in self.logWriterHumanTypes:
2122+ liststore.append([elem])
2123+
2124+ self.logTypeCombo.set_model(liststore)
2125+ self.logTypeCombo.set_active(0)
2126+
2127+ cell = gtk.CellRendererText()
2128+ self.logTypeCombo.pack_start(cell, True)
2129+ self.logTypeCombo.add_attribute(cell, "text", 0)
2130+
2131+ #scheduler combobox
2132+
2133+ schedulerListStore = gtk.ListStore(gobject.TYPE_STRING)
2134+
2135+ for elem in self.schedulerOptions:
2136+ schedulerListStore.append([elem])
2137+
2138+ self.schedulerCombo.set_model(schedulerListStore)
2139+ self.schedulerCombo.set_active(0)
2140+
2141+ self.schedulerCombo.pack_start(cell, True)
2142+ self.schedulerCombo.add_attribute(cell, "text", 0)
2143+
2144+
2145+ #downloader combobox
2146+
2147+ downloaderListStore = gtk.ListStore(gobject.TYPE_STRING)
2148+
2149+ for elem in self.downloaderOptions:
2150+ downloaderListStore.append([elem])
2151+
2152+ self.downloaderCombo.set_model(downloaderListStore)
2153+ self.downloaderCombo.set_active(0)
2154+
2155+ self.downloaderCombo.pack_start(cell, True)
2156+ self.downloaderCombo.add_attribute(cell, "text", 0)
2157+
2158+ #colour depth combobox
2159+
2160+ colourDepthListStore = gtk.ListStore(gobject.TYPE_STRING)
2161+
2162+ for elem in self.colourDepthOptions:
2163+ colourDepthListStore.append([elem])
2164+
2165+ self.colourDepthCombo.set_model(colourDepthListStore)
2166+ self.colourDepthCombo.set_active(0)
2167+
2168+ self.colourDepthCombo.pack_start(cell, True)
2169+ self.colourDepthCombo.add_attribute(cell, "text", 0)
2170+
2171+
2172+
2173+ #lift enable combobox
2174+
2175+ liftEnableListStore = gtk.ListStore(gobject.TYPE_STRING)
2176+
2177+ liftEnableOptions = ["True","False"]
2178+
2179+ for elem in liftEnableOptions:
2180+ liftEnableListStore.append([elem])
2181+
2182+ self.liftEnableCombo.set_model(liftEnableListStore)
2183+ self.liftEnableCombo.set_active(0)
2184+
2185+ self.liftEnableCombo.pack_start(cell, True)
2186+ self.liftEnableCombo.add_attribute(cell, "text", 0)
2187+
2188+
2189+ #Set the range of values we accept for the spin controls
2190+
2191+ width_adj = gtk.Adjustment(1024, 1.0, 10000, 1.0, 5.0, 0.0)
2192+ height_adj = gtk.Adjustment(1024, 1.0, 10000, 1.0, 5.0, 0.0)
2193+ queue_adj = gtk.Adjustment(10, 1.0, 10000, 1.0, 5.0, 0.0)
2194+ refresh_adj = gtk.Adjustment(100, 1.0, 10000, 1.0, 5.0, 0.0)
2195+ logLevel_adj = gtk.Adjustment(0, 0, 10, 1.0, 2.0, 0.0)
2196+
2197+ socketTime_adj = gtk.Adjustment(0, 0, 100, 1.0, 2.0, 0.0)
2198+ frames_adj = gtk.Adjustment(0, 0, 100, 1.0, 2.0, 0.0)
2199+ vwidth_adj = gtk.Adjustment(0, 0, 10000, 1.0, 2.0, 0.0)
2200+ vheight_adj = gtk.Adjustment(0, 0, 10000, 1.0, 2.0, 0.0)
2201+ vrotate_adj = gtk.Adjustment(0, -359, 359, 1.0, 2.0, 0.0)
2202+ liftTrigger_adj = gtk.Adjustment(0, 0, 100, 1.0, 2.0, 0.0)
2203+
2204+ self.screenWidthText.configure(width_adj, 0, 0)
2205+ self.screenWidthText.set_wrap(True)
2206+
2207+ self.screenHeightText.configure(height_adj, 0, 0)
2208+ self.screenHeightText.set_wrap(True)
2209+
2210+ self.queueSizeText.configure(queue_adj, 0, 0)
2211+ self.queueSizeText.set_wrap(True)
2212+
2213+ self.refreshText.configure(refresh_adj, 0, 0)
2214+ self.refreshText.set_wrap(True)
2215+
2216+ self.logLevelSpin.configure(logLevel_adj, 0, 0)
2217+ self.logLevelSpin.set_wrap(True)
2218+
2219+ self.socketTimeSpin.configure(socketTime_adj,0,0)
2220+ self.socketTimeSpin.set_wrap(True)
2221+
2222+ self.framesSpin.configure(frames_adj,0,0)
2223+ self.framesSpin.set_wrap(True)
2224+
2225+ self.vwidthSpin.configure(vwidth_adj,0,0)
2226+ self.vwidthSpin.set_wrap(True)
2227+
2228+ self.vheightSpin.configure(vheight_adj,0,0)
2229+ self.vheightSpin.set_wrap(True)
2230+
2231+ self.vrotateSpin.configure(vrotate_adj,0,0)
2232+ self.vrotateSpin.set_wrap(True)
2233+
2234+ self.liftTriggerValue.configure(liftTrigger_adj,0,0)
2235+ self.liftTriggerValue.set_wrap(True)
2236+
2237+ #We want the labels to be translatable,
2238+ #Using the Glade stuff grab the labels
2239+ self.serverURLLabel = self.builder.get_object("serverURLLabel")
2240+ self.clientIDLabel = self.builder.get_object("clientIDLabel")
2241+ self.serverKeyLabel = self.builder.get_object("serverKeyLabel")
2242+ self.refreshLabel = self.builder.get_object("refreshLabel")
2243+ self.connectionLabel = self.builder.get_object("connectionLabel")
2244+ self.fullscreenLabel = self.builder.get_object("fullscreenLabel")
2245+ self.widthLabel = self.builder.get_object("widthLabel")
2246+ self.heightLabel = self.builder.get_object("heightLabel")
2247+ self.logLevelLabel = self.builder.get_object("logLevelLabel")
2248+ self.logTypeLabel = self.builder.get_object("logTypeLabel")
2249+ self.loggingFrameLabel = self.builder.get_object("loggingFrameLabel")
2250+ self.statsFrameLabel = self.builder.get_object("statsFrameLabel")
2251+ self.clientNameLabel = self.builder.get_object("clientNameLabel")
2252+
2253+ #Labels for advanced options and tabs
2254+ self.liftDefaultLabel = self.builder.get_object('liftDefaultLabel')
2255+ self.lift7Label = self.builder.get_object('lift7Label')
2256+ self.lift6Label = self.builder.get_object('lift6Label')
2257+ self.lift5Label = self.builder.get_object('lift5Label')
2258+ self.lift4Label = self.builder.get_object('lift4Label')
2259+ self.lift3Label = self.builder.get_object('lift3Label')
2260+ self.lift2Label = self.builder.get_object('lift2Label')
2261+ self.lift1Label = self.builder.get_object('lift1Label')
2262+ self.lift0Label = self.builder.get_object('lift0Label')
2263+ self.tagLiftLabel = self.builder.get_object('tagLiftLabel')
2264+ self.genLiftOptions = self.builder.get_object('genLiftOptions')
2265+ self.firstSerialLabel = self.builder.get_object('firstSerialLabel')
2266+ self.secondSerialLabel = self.builder.get_object('secondSerialLabel')
2267+ self.liftTriggerLabel = self.builder.get_object('liftTriggerLabel')
2268+ self.liftEnableLabel = self.builder.get_object('liftEnableLabel')
2269+ self.liftOptionsLabel = self.builder.get_object('liftOptionsLabel')
2270+ self.advancedOptionsLabel = self.builder.get_object('advancedOptionsLabel')
2271+ self.otherSettingsLabel = self.builder.get_object('otherSettingsLabel')
2272+ self.clientSettingsLabel = self.builder.get_object('clientSettingsLabel')
2273+ self.serverSettingsLabel = self.builder.get_object('serverSettingsLabel')
2274+ self.dateFormatLabel = self.builder.get_object('dateFormatLabel')
2275+ self.schedulerLabel = self.builder.get_object('schedulerLabel')
2276+ self.downloaderLabel = self.builder.get_object('downloaderLabel')
2277+ self.libraryLabel = self.builder.get_object('libraryLabel')
2278+ self.bppLabel = self.builder.get_object('bppLabel')
2279+ self.socketTimeLabel = self.builder.get_object('socketTimeLabel')
2280+ self.checksumLabel = self.builder.get_object('checksumLabel')
2281+ self.lowTextureLabel = self.builder.get_object('lowTextureLabel')
2282+ self.framesLabel = self.builder.get_object('framesLabel')
2283+ self.vwidthLabel = self.builder.get_object('vwidthLabel')
2284+ self.vheightLabel = self.builder.get_object('vheightLabel')
2285+ self.vrotationLabel = self.builder.get_object('vrotationLabel')
2286+ self.advancedOptionsCheck = self.builder.get_object("advancedOptionsCheck")
2287+
2288+# self.manualUpdateLabel = self.builder.get_object("manualUpdateLabel")
2289+# self.manualUpdateCombo = self.builder.get_object("manualUpdateCombo")
2290+ self.xmdsLicenseKeyLabel = self.builder.get_object("xmdsLicenseKeyLabel")
2291+ self.xmdsLicenseKeyEntry = self.builder.get_object("xmdsLicenseKeyEntry")
2292+
2293+ self.onlineOpLabel = self.builder.get_object("onlineOpLabel")
2294+ self.offlineOpLabel = self.builder.get_object("offlineOpLabel")
2295+
2296+
2297+ #Now set the text in the labels. This is useful so that we can
2298+ #then use this as a basis for translations on launchpad
2299+
2300+# self.manualUpdateLabel.set_text(_("Manual Update"))
2301+ self.xmdsLicenseKeyLabel.set_text(_("xmdsLicenseKey"))
2302+
2303+ self.serverURLLabel.set_text(_("Server URL"))
2304+ self.clientIDLabel.set_text(_("Client ID"))
2305+ self.serverKeyLabel.set_text(_("Server Key"))
2306+ self.refreshLabel.set_text(_("Set the number of seconds between the client contacting the server for updates"))
2307+ self.connectionLabel.set_text(_("Require connection to server"))
2308+ self.fullscreenLabel.set_text(_("Fullscreen"))
2309+ self.widthLabel.set_text(_("Width"))
2310+ self.heightLabel.set_text(_("Height"))
2311+ self.logLevelLabel.set_text(_("Log Level"))
2312+ self.logTypeLabel.set_text(_("Log Type"))
2313+ self.statsCaptureLabel.set_text(_("Statistics Capturing"))
2314+ self.statsQueueSizeLabel.set_text(_("Queue Size"))
2315+ self.loggingFrameLabel.set_text(_("Logging"))
2316+ self.statsFrameLabel.set_text(_("Statistics Generation"))
2317+
2318+ self.clientNameLabel.set_text(_("Client Name"))
2319+
2320+ self.liftDefaultLabel.set_label(_('Default'))
2321+ self.lift7Label.set_label(_('Lift 7'))
2322+ self.lift6Label.set_label(_('Lift 6'))
2323+ self.lift5Label.set_label(_('Lift 5'))
2324+ self.lift4Label.set_label(_('Lift 4'))
2325+ self.lift3Label.set_label(_('Lift 3'))
2326+ self.lift2Label.set_label(_('Lift 2'))
2327+ self.lift1Label.set_label(_('Lift 1'))
2328+ self.lift0Label.set_label(_('Lift 0'))
2329+ self.tagLiftLabel.set_label(_('Tagging Lift Options'))
2330+ self.genLiftOptions.set_label(_('General Lift Options'))
2331+ self.firstSerialLabel.set_label(_('1st Serial Port'))
2332+ self.secondSerialLabel.set_label(_('2nd Serial Port'))
2333+ self.liftTriggerLabel.set_label(_('Lift Trigger'))
2334+ self.liftEnableLabel.set_label(_('Lift Enable'))
2335+ self.liftOptionsLabel.set_label(_('Lift Options'))
2336+ self.advancedOptionsLabel.set_label(_('Advanced Options'))
2337+ self.otherSettingsLabel.set_label(_('Other Settings'))
2338+ self.clientSettingsLabel.set_label(_('Client Settings'))
2339+ self.serverSettingsLabel.set_label(_('Server Settings'))
2340+ self.dateFormatLabel.set_label(_('Date Format'))
2341+ self.schedulerLabel.set_label(_('Scheduler'))
2342+ self.downloaderLabel.set_label(_('Downloader'))
2343+ self.libraryLabel.set_label(_('Library Location'))
2344+ self.bppLabel.set_label(_('Colour Depth (BPP)'))
2345+ self.socketTimeLabel.set_label(_('Socket Timeout (s)'))
2346+ self.checksumLabel.set_label(_('Checksum Downloaded Media'))
2347+ self.lowTextureLabel.set_label(_('Low Texture Memory'))
2348+ self.framesLabel.set_label(_('Frames per Second'))
2349+ self.vwidthLabel.set_label(_('Virtual Width'))
2350+ self.vheightLabel.set_label(_('Virtual Height'))
2351+ self.vrotationLabel.set_label(_('Rotation'))
2352+
2353+ self.onlineOpLabel.set_label(_("Online operation (syncronise with Xibo server)"))
2354+# self.offlineOpLabel.set_label(_("Offline operation (synchronise with USB memory stick)"))
2355+
2356+ #Set the icon for the Window
2357+ self.window.set_icon_from_file("xibo.ico")
2358+
2359+
2360+ #Now set the labels of the buttons and window
2361+
2362+ self.clearButton.set_label(_("Clear Form"))
2363+ self.saveButton.set_label(_("Save Config"))
2364+ self.window.set_title(_("Xibo Client Configuration"))
2365+
2366+
2367+ #Set up the combo box
2368+
2369+# manualUpdateListStore = gtk.ListStore(gobject.TYPE_STRING)
2370+
2371+# for elem in self.manualUpdateOptions:
2372+# manualUpdateListStore.append([elem])
2373+
2374+# self.manualUpdateCombo.set_model(manualUpdateListStore)
2375+# self.manualUpdateCombo.set_active(1)
2376+
2377+# self.manualUpdateCombo.pack_start(cell, True)
2378+# self.manualUpdateCombo.add_attribute(cell, "text", 0)
2379+
2380+ logFilePath = os.path.join(os.path.abspath(''),self.pyClientLogName)
2381+
2382+ self.logFileLinkButton.set_uri("file:%s%s%s"%(os.sep,os.sep,logFilePath))
2383+
2384+# print "File path: ", logFilePath
2385+
2386+ #Set the tick box to online operation
2387+ self.offlineCheckButton.set_active(True)
2388+ self.offlineCheckButton.set_active(False)
2389+
2390+ #Set tooltips
2391+ self.set_tooltips()
2392+
2393+ self.window.show()
2394+
2395+ #Check that the directory exists where the configuration file
2396+ #is stored.
2397+
2398+ if os.path.exists(self.pyclientConfPath):
2399+ if os.path.isfile(self.pyclientConfPath):
2400+
2401+ self.logger1.error("Python client path chosen is a file")
2402+
2403+ print "Location is a file."
2404+ self.errorDialog.set_markup(_("File path is a file. Cannot write to it"))
2405+ self.errorDialog.show()
2406+ print "Exiting gracefully"
2407+# sys.exit()
2408+ elif os.path.isdir(self.pyclientConfPath):
2409+ self.logger1.info("Python client path chosen is available")
2410+ print "Location exists."
2411+ print "Carrying on..."
2412+
2413+ self.pyClientConfName = os.path.join(self.pyclientConfPath,self.pyClientConfName)
2414+ else:
2415+ print "Configuration directory does not exist"
2416+ self.logger1.warning("Python client path chosen does not exist")
2417+ try:
2418+ os.makedirs(self.pyclientConfPath)
2419+ print "Directory created"
2420+ self.logger1.info("Python client path chosen has been created")
2421+ self.pyClientConfName = os.path.join(self.pyclientConfPath,self.pyClientConfName)
2422+ except OSError:
2423+ self.logger1.error("Python client path chosen could not be created")
2424+ self.errorDialog.set_markup(_("File path could not be created"))
2425+ self.errorDialog.show()
2426+
2427+
2428+ #Check that a file can be written to this directory
2429+ try:
2430+ file_written = open(os.path.join(self.pyclientConfPath,"tmp"),"w")
2431+ file_written.close()
2432+ except:
2433+ self.logger1.error("Could not write to testing file")
2434+
2435+ is_file = os.path.isfile(os.path.join(self.pyclientConfPath,"tmp"))
2436+
2437+ self.logger1.info("Testing file has been created in the chosen location")
2438+
2439+ #Check that the file can be written to
2440+
2441+ try:
2442+ file_edit = open(os.path.join(self.pyclientConfPath,"tmp"),"w")
2443+ file_edit.write("tmp")
2444+ file_edit.close()
2445+ print "boo"
2446+ except:
2447+ self.logger1.info("Testing file could not be written to")
2448+
2449+ is_data = False
2450+ data = None
2451+
2452+ try:
2453+ data = open(os.path.join(self.pyclientConfPath,"tmp"),"r").read()
2454+ except:
2455+ self.logger1.error("Cannot open testing file to read data")
2456+ if data == "tmp":
2457+ is_data = True
2458+ self.logger1.info("Testing file could be written to")
2459+ else:
2460+ self.logger1.info("Testing file could not be written to")
2461+
2462+ #Check that the file can be deleted
2463+ is_deleted = False
2464+ try:
2465+ os.remove(os.path.join(self.pyclientConfPath,"tmp"))
2466+ except:
2467+ self.logger1.error("Cannot delete testing file")
2468+
2469+ if os.path.isfile(os.path.join(self.pyclientConfPath,"tmp")) == False:
2470+ is_deleted = True
2471+ self.logger1.info("Testing file has been deleted successfully")
2472+
2473+ if is_deleted and is_data and is_file:
2474+ print "Location is acceptable for file writing"
2475+ self.logger1.info("Location is acceptable for file writing")
2476+ self.messageDialog.set_markup(_("File location is acceptable"))
2477+ self.messageDialog.show()
2478+
2479+ else:
2480+ print "Cannot write to file"
2481+ self.logger1.error("Location selected is not acceptable for file writing")
2482+ print "Exiting gracefully"
2483+ self.errorDialog.show()
2484+ self.errorDialog.set_markup(_("Cannot write to file"))
2485+# sys.exit()
2486+
2487+
2488+
2489+ print self.pyClientConfName
2490+
2491+
2492+ if is_deleted and is_data and is_file:
2493+
2494+ #Read the configuration information from the configuration file
2495+ self.readConfig()
2496+
2497+ #Check to see if the client ID field is blank.
2498+ #If so, then generate one
2499+
2500+ if self.clientIDText.get_text() == "":
2501+ uuid = self.genClientID()
2502+ self.clientIDText.set_text(str(uuid))
2503+
2504+ def messageDialogExit(self,widget):
2505+ sys.exit()
2506+
2507+ def infoDialogOKSignal(self,widget):
2508+ self.messageDialog.hide()
2509+
2510+ def offlineOperationToggle(self,widget):
2511+
2512+ offlineOperation = widget.get_active()
2513+
2514+ self.logger8.info(_("Offline operation checkbox toggled"))
2515+
2516+ if offlineOperation:
2517+ print "Offline operation selected"
2518+# self.manualUpdateCombo.set_sensitive(True)
2519+ # self.xmdsLicenseKeyEntry.set_sensitive(True)
2520+
2521+ self.logger8.info(_("Offline operation selected"))
2522+
2523+ self.serverURLText.set_sensitive(False)
2524+ self.clientIDText.set_sensitive(False)
2525+ self.serverKeyText.set_sensitive(False)
2526+ self.clientNameText.set_sensitive(False)
2527+
2528+ else:
2529+ print "Online operation selected"
2530+ self.logger8.info(_("Online operation selected"))
2531+# self.manualUpdateCombo.set_sensitive(False)
2532+ # self.xmdsLicenseKeyEntry.set_sensitive(False)
2533+
2534+ self.serverURLText.set_sensitive(True)
2535+ self.clientIDText.set_sensitive(True)
2536+ self.serverKeyText.set_sensitive(True)
2537+ self.clientNameText.set_sensitive(True)
2538+
2539+ def on_advancedOptionsCheck(self,widget):
2540+ """Function called when advanced options checkbox is toggled.
2541+ Used to hide / display the advanced notebook tab"""
2542+
2543+ advancedPage = self.notebook1.get_nth_page(3)
2544+
2545+ if self.advancedOptionsCheck.get_active() and self.advancedTabVisible == False:
2546+ advancedPage.show()
2547+ self.advancedTabVisible = True
2548+ self.logger6.info(_("advancedTabEnabled"))
2549+
2550+ elif self.advancedOptionsCheck.get_active() == False and self.advancedTabVisible:
2551+ advancedPage.hide()
2552+ self.advancedTabVisible = False
2553+ self.logger6.info(_("advancedTabDisabled"))
2554+
2555+ def readConfigAppConf(self):
2556+ """This reads the configuration file that is used by the configuration application"""
2557+ self.logger7.info(_("Configuration application configuration file being read in"))
2558+ config_file = ""
2559+ try:
2560+ config_file = open(self.clientConfFile,"r")
2561+
2562+ #Implement all the stuff to read the config file in
2563+ data = config_file.read()
2564+ config_file.close()
2565+ self.logger7.info(_("Reading configuration file to make sure file is not empty"))
2566+ #If the file is not empty, then try and process it
2567+
2568+ if len(data) != 0:
2569+ config = ConfigParser.ConfigParser()
2570+ config.read(self.clientConfFile)
2571+
2572+ self.logger7.info(_("Reading configuration file"))
2573+
2574+ #Get the information from the configuration file
2575+ #and display into the GUI
2576+
2577+ #Xibo client configuration file location
2578+ xiboClientConf = None
2579+
2580+ try:
2581+ xiboClientConf = config.get('Main','clientConfName')
2582+ except:
2583+ xiboClientConf = "site.cfg"
2584+
2585+ self.logger7.info(_("Client configuration: %s"%xiboClientConf))
2586+
2587+ #Options pertaining to log type
2588+ logTypeOptions = config.get("Options","logType").split(",")
2589+ for i in range(len(logTypeOptions)):
2590+ logTypeOptions[i] = _(logTypeOptions[i])
2591+
2592+ print logTypeOptions
2593+
2594+ #Options pertaining to log type (human readable form)
2595+ logTypeHumanOptions = config.get("Options","logTypeHuman").split(",")
2596+
2597+ for i in range(len(logTypeHumanOptions)):
2598+ logTypeHumanOptions[i] = _(logTypeHumanOptions[i])
2599+
2600+ self.logger7.info(_("logTypeOptions: %s"%logTypeOptions))
2601+
2602+ self.logger7.info(_("logTypeHumanOptions: %s"%logTypeHumanOptions))
2603+
2604+ #Options pertaining to scheduler
2605+ schedulerOptions = config.get("Options","scheduler").split(",")
2606+ for i in range(len(schedulerOptions)):
2607+ schedulerOptions[i] = _(schedulerOptions[i])
2608+
2609+ print schedulerOptions
2610+
2611+ self.logger7.info(_("schedulerOptions: %s"%schedulerOptions))
2612+
2613+
2614+ #Options pertaining to downloader
2615+ downloaderOptions = config.get("Options","downloader").split(",")
2616+ for i in range(len(downloaderOptions)):
2617+ downloaderOptions[i] = _(downloaderOptions[i])
2618+
2619+ print downloaderOptions
2620+
2621+ self.logger7.info(_("downloaderOptions: %s"%downloaderOptions))
2622+
2623+ #Options pertaining to colour depth (BPP)
2624+ colourDepthOptions = config.get("Options","colourDepth").split(",")
2625+ for i in range(len(colourDepthOptions)):
2626+ colourDepthOptions[i] = _(colourDepthOptions[i])
2627+
2628+ print colourDepthOptions
2629+
2630+ self.logger7.info(_("colourDepthOptions: %s"%colourDepthOptions))
2631+
2632+ clientConfLoc = None
2633+
2634+ try:
2635+ clientConfLoc = config.get("Main","clientConfLoc")
2636+ except:
2637+ clientConfLoc = os.path.expanduser('~/.xibo')
2638+
2639+ clientConfName = None
2640+ try:
2641+ clientConfName = config.get("Main","clientConfName")
2642+ except:
2643+ clientConfName = "site.cfg"
2644+
2645+
2646+ self.logger7.info(_("clientConfLocation: %s"%clientConfLoc))
2647+ self.logger7.info(_("clientConfName: %s"%clientConfName))
2648+
2649+
2650+ return {"xiboClientConf":xiboClientConf,"logTypeOptions":logTypeOptions,"logTypeHumanOptions":logTypeHumanOptions,"clientConfLoc":clientConfLoc,"clientConfName":clientConfName,"schedulerOptions":schedulerOptions,"downloaderOptions":downloaderOptions,"colourDepthOptions":colourDepthOptions}
2651+
2652+ else:
2653+ self.logger7.error("Configuration file is empty. Cannot continue")
2654+ self.errorDialog.set_markup(_("The configuration application configuration file is empty. Cannot continue"))
2655+ self.errorDialog.show()
2656+
2657+ except:
2658+ print "Could not open the configuration application configuration file"
2659+
2660+ self.logger7.error(_("Could not open configuration file. Cannot continue"))
2661+
2662+ self.errorDialog.set_markup(_("File path is a file. Cannot write to itCould not open the configuration application configuration file"))
2663+ self.errorDialog.show()
2664+ return -1
2665+
2666+ def clearFormSignal(self,widget,data=None):
2667+
2668+ self.serverURLText.set_text("")
2669+ self.clientIDText.set_text("")
2670+ self.serverKeyText.set_text("")
2671+ self.refreshText.set_text("")
2672+ self.serverConnBool.set_active(False)
2673+ self.fullScreenBool.set_active(False)
2674+ self.screenWidthText.set_text("")
2675+ self.screenHeightText.set_text("")
2676+ self.captureStatisticsBool.set_active(False)
2677+ self.queueSizeText.set_text("")
2678+
2679+ self.screenWidthText.set_value(0)
2680+ self.screenHeightText.set_value(0)
2681+ self.queueSizeText.set_value(0)
2682+
2683+
2684+ self.clearButton.set_tooltip_text(_("Clear input fields"))
2685+ self.saveButton.set_tooltip_text(_("Save data to file"))
2686+
2687+ self.logLevelSpin.set_value(0)
2688+
2689+ self.logTypeCombo.set_active(0)
2690+ self.liftEnableCombo.set_active(0)
2691+ self.schedulerCombo.set_active(0)
2692+ self.downloaderCombo.set_active(0)
2693+ self.colourDepthCombo.set_active(0)
2694+ self.manualUpdateCombo.set_active(0)
2695+
2696+
2697+ self.checksumCheckButton.set_active(False)
2698+ self.lowTextureCheckButton.set_active(False)
2699+
2700+ self.clientNameText.set_text("")
2701+
2702+ #Advanced options widgets
2703+
2704+ self.liftDefaultTagText.set_text("")
2705+ self.lift7TagText.set_text("")
2706+ self.lift6TagText.set_text("")
2707+ self.lift5TagText.set_text("")
2708+ self.lift4TagText.set_text("")
2709+ self.lift3TagText.set_text("")
2710+ self.lift2TagText.set_text("")
2711+ self.lift1TagText.set_text("")
2712+ self.lift0TagText.set_text("")
2713+ self.firstSerialText.set_text("")
2714+ self.secondSerialText.set_text("")
2715+ self.liftTriggerValue.set_value(0)
2716+
2717+ self.dateFormatEntry.set_text("")
2718+ self.libraryEntry.set_text("")
2719+ self.socketTimeSpin.set_value(0)
2720+
2721+ self.framesSpin.set_value(0)
2722+ self.vwidthSpin.set_value(0)
2723+ self.vheightSpin.set_value(0)
2724+ self.vrotateSpin.set_value(0)
2725+
2726+ self.xmdsLicenseKeyEntry.set_text("")
2727+
2728+ self.logger9.info("Clearing form elements")
2729+
2730+ def logTypeComboChanged(self,widget,data=None):
2731+
2732+ model = widget.get_model()
2733+ index = widget.get_active()
2734+ logTypeText = model[index][0].lower()
2735+
2736+ if logTypeText == "local file":
2737+ #Check to see if the file pointed to by the link exists
2738+ error_file = self.logFileLinkButton.get_uri().split(":%s%s"%(os.sep,os.sep))[1]
2739+ if os.path.isfile(error_file):
2740+ self.logFileLinkButton.show()
2741+ else:
2742+ self.logFileLinkButton.hide()
2743+
2744+ val = widget.get_active()
2745+
2746+
2747+ def onDestroy(self,widget,data=None):
2748+ """
2749+ Close the program. Executes when the main
2750+ window is destroyed
2751+ """
2752+ self.logger10.info("Exiting program")
2753+ gtk.main_quit()
2754+
2755+
2756+ def confValErr(self,err,logger):
2757+ #print "Error finding config. value in file: %s"%err
2758+ #self.logger2.warning("%s item not in config. file"%err)
2759+ logger.warning("%s item not in config. file"%err)
2760+
2761+ def readConfig(self):
2762+ """Function used to read in the configuration file and
2763+ fill in the GUI text elements"""
2764+
2765+ #Firstly check if the configuration file exists. If it does then
2766+ #open it and extract the values. These can then be filled into the
2767+ #fields on the GUI
2768+
2769+ #Try opening the configuration file, if it does not exists, then
2770+ #create it
2771+
2772+ config_file = ""
2773+ try:
2774+ config_file = open(self.pyClientConfName,"r")
2775+
2776+ self.logger2.info("Config. file opened successfully")
2777+
2778+ #Implement all the stuff to read the config file in
2779+ data = config_file.read()
2780+ config_file.close()
2781+ #If the file is not empty, then try and process it
2782+
2783+ if len(data) != 0:
2784+ self.logger2.info("Config. data read in successfully")
2785+
2786+
2787+ self.readDataFromConfigFile(self.pyClientConfName,self.logger2)
2788+
2789+
2790+ except IOError:
2791+ print "Cannot open"
2792+ self.logger2.warning("Cannot open configuration file")
2793+ #Read in the values from the site.cfg.default
2794+
2795+ self.readDataFromConfigFile(self.pyClientConfDefaultsName,self.logger12,defaults=True)
2796+ self.messageDialog.set_markup(_("Could not open configuration file. A new one will be created"))
2797+ self.messageDialog.show()
2798+
2799+
2800+
2801+
2802+ def readDataFromConfigFile(self,confFileName,logger,defaults=False):
2803+
2804+
2805+ config = ConfigParser.ConfigParser()
2806+ config.read(confFileName)
2807+
2808+ #Get the information from the configuration file
2809+ #and display into the GUI
2810+
2811+ try:
2812+ self.serverURLText.set_text(config.get('Main','xmdsUrl'))
2813+ logger.info("serverURL: %s"%config.get('Main','xmdsUrl'))
2814+ except:
2815+ self.confValErr('xmdsUrl',logger)
2816+
2817+ if defaults == False:
2818+ try:
2819+ self.clientIDText.set_text(config.get("Main","xmdsClientID"))
2820+ logger.info("clientID: %s"%config.get('Main','xmdsClientID'))
2821+ except:
2822+ self.confValErr("xmdsClientID",logger)
2823+ logger.warning("xmdClientID item not in config. file")
2824+
2825+ try:
2826+ self.serverKeyText.set_text(config.get('Main','xmdsKey'))
2827+ logger.info("xmdsKey: %s"%config.get('Main','xmdsKey'))
2828+ except:
2829+ self.confValErr('xmdsKey',logger)
2830+
2831+ try:
2832+ self.refreshText.set_text(config.get('Main','xmdsUpdateInterval'))
2833+ logger.info("xmdsUpdateInterval: %s"%config.get('Main','xmdsUpdateInterval'))
2834+ except:
2835+ self.confValErr('xmdsUpdateInterval',logger)
2836+
2837+ try:
2838+ self.clientNameText.set_text(config.get('Main','xmdsClientName'))
2839+ logger.info("xmdsClientName: %s"%config.get('Main','xmdsClientName'))
2840+ except:
2841+ self.confValErr('xmdsClientName',logger)
2842+
2843+
2844+ try:
2845+ requireXmds = False
2846+ if config.get('Main','requireXmds') == "true":
2847+ requireXmds = True
2848+
2849+ self.serverConnBool.set_active(requireXmds)
2850+ logger.info("requireXMDS: %s"%requireXmds)
2851+
2852+ except:
2853+ self.confValErr("requireXmds",logger)
2854+
2855+ try:
2856+ fullScreen = False
2857+ if config.get('Main','fullscreen') == "true":
2858+ fullScreen = True
2859+ self.fullScreenBool.set_active(fullScreen)
2860+ logger.info("fullscreen: %s"%fullscreen)
2861+
2862+
2863+ except:
2864+ self.confValErr("fullscreen",logger)
2865+
2866+ try:
2867+ captureStats = False
2868+ if config.get('Stats','collect') == "true":
2869+ captureStats = True
2870+ logger.info("captureStats: %s"%captureStats)
2871+
2872+ self.captureStatisticsBool.set_active(captureStats)
2873+ except:
2874+ self.confValErr("Stats - Collect",logger)
2875+
2876+
2877+ try:
2878+ self.screenWidthText.set_value(int(config.get('Main','width')))
2879+ logger.info("screenWidth: %s"%config.get('Main','width'))
2880+
2881+ except:
2882+ self.confValErr("width",logger)
2883+
2884+ try:
2885+ self.screenHeightText.set_value(int(config.get('Main','height')))
2886+ logger.info("screenHeight: %s"%config.get('Main','height'))
2887+
2888+ except:
2889+ self.confValErr("height",logger)
2890+
2891+ try:
2892+ self.queueSizeText.set_value(int(config.get('Stats','queueSize')))
2893+ logger.info("queueSize: %s"%config.get('Stats','queueSize'))
2894+
2895+ except:
2896+ self.confValErr("queueSize",logger)
2897+
2898+ try:
2899+ self.logLevelSpin.set_value(int(config.get('Logging','logLevel')))
2900+ logger.info("Logging level: %s"%config.get('Logging','logLevel'))
2901+
2902+ except:
2903+ self.confValErr("logLevel",logger)
2904+
2905+ try:
2906+ logType = config.get('Logging','logWriter')
2907+
2908+ val = 0
2909+
2910+ for elem in self.logWriterTypes:
2911+ if elem.lower() == logType.lower():
2912+ print elem.lower(), logType.lower()
2913+ break
2914+ val += 1
2915+ print "*"*len(str(self.logWriterTypes))
2916+ print logType
2917+ print self.logWriterTypes
2918+ print " "*(len(str(self.logWriterTypes))/2),val
2919+ print self.logWriterHumanTypes
2920+ print "*"*len(str(self.logWriterTypes))
2921+
2922+ logger.info("logWriter: %s"%self.logWriterTypes[val])
2923+ logger.info("logWriterHuman: %s"%self.logWriterHumanTypes[val])
2924+ self.logTypeCombo.set_active(val)
2925+ except:
2926+ self.confValErr("logWriter",logger)
2927+
2928+
2929+ #Advanced options
2930+
2931+ try:
2932+ self.dateFormatEntry.set_text(config.get("TickerMedia","dateFormat"))
2933+ logger.info("tickerMedia: %s"%config.get('TickerMedia','dateFormat'))
2934+
2935+ except:
2936+ self.confValErr("dateFormat",logger)
2937+
2938+ try:
2939+ self.libraryEntry.set_text(config.get("Main","libraryDir"))
2940+ logger.info("libraryDir: %s"%config.get('Main','libraryDir'))
2941+
2942+ except:
2943+ self.confValErr("libraryDir",logger)
2944+
2945+ try:
2946+ self.socketTimeSpin.set_value(int(config.get("Main","socketTimeout")))
2947+ logger.info("socketTimeout: %s"%config.get('Main','socketTimeout'))
2948+
2949+ except:
2950+ self.confValErr("socketTimeout",logger)
2951+
2952+ try:
2953+ self.framesSpin.set_value(int(config.get("Main","fps")))
2954+ logger.info("FPS: %s"%config.get('Main','fps'))
2955+
2956+ except:
2957+ self.confValErr("fps",logger)
2958+
2959+ try:
2960+ self.vwidthSpin.set_value(int(config.get("Main","vwidth")))
2961+ logger.info("VirtualWidth: %s"%config.get('Main','vwidth'))
2962+
2963+ except:
2964+ self.confValErr("vwidth",logger)
2965+
2966+ try:
2967+ self.vheightSpin.set_value(int(config.get("Main","vheight")))
2968+ logger.info("VirtualHeight: %s"%config.get('Main','vheight'))
2969+
2970+ except:
2971+ self.confValErr("vheight",logger)
2972+
2973+ try:
2974+ self.vrotateSpin.set_value(int(config.get("Main","vrotation")))
2975+ logger.info("VirtualRotation: %s"%config.get('Main','vrotation'))
2976+
2977+ except:
2978+ self.confValErr("vrotation",logger)
2979+
2980+
2981+ try:
2982+ self.xmdsLicenseKeyEntry.set_text(config.get("Main","xmdsLicenseKey"))
2983+ logger.info("xmdsLicenseKey: %s"%config.get('Main','xmdsLicenseKey'))
2984+
2985+ except:
2986+ self.confValErr('xmdsLicenseKey',logger)
2987+
2988+
2989+ #Sort out the combo boxes
2990+
2991+ try:
2992+ schedType = config.get("Main","Scheduler")
2993+
2994+ val = 0
2995+ for elem in self.schedulerOptions:
2996+ if elem.lower() == schedType.lower():
2997+ break
2998+ val += 1
2999+ logger.info("scheduler: %s"%self.schedulerOptions[val])
3000+
3001+ self.schedulerCombo.set_active(val)
3002+ except:
3003+ self.confValErr("scheduler",logger)
3004+
3005+ try:
3006+ dloadType = config.get("Main","Downloader")
3007+
3008+ val = 0
3009+ for elem in self.downloaderOptions:
3010+ if elem.lower() == dloadType.lower():
3011+ break
3012+ val += 1
3013+ logger.info("downloader: %s"%self.downloaderOptions[val])
3014+
3015+ self.downloaderCombo.set_active(val)
3016+ except:
3017+ self.confValErr("downloader",logger)
3018+
3019+ try:
3020+ bppType = config.get("Main","bpp")
3021+
3022+ val = 0
3023+
3024+ for elem in self.colourDepthOptions:
3025+ if elem.lower() == bppType.lower():
3026+ break
3027+ val += 1
3028+ logger.info("BPP: %s"%self.colourDepthOptions[val])
3029+
3030+ self.colourDepthCombo.set_active(val)
3031+ except:
3032+ self.confValErr("bpp",logger)
3033+
3034+ #USB update section
3035+ try:
3036+ manualUpdateType = config.get("Main","manualUpdate")
3037+ logger.info("offlineUpdate: %s"%manualUpdateType)
3038+
3039+ if manualUpdateType == "true":
3040+ manualUpdateType = True
3041+ elif manualUpdateType == "false":
3042+ manualUpdateType = False
3043+
3044+ if manualUpdateType == True or manualUpdateType == False:
3045+ if manualUpdateType == True:
3046+ print "Stuff done"
3047+ self.offlineCheckButton.set_active(True)
3048+ self.offlineOperationToggle(self,self.offlineCheckButton)
3049+
3050+ except:
3051+ self.confValErr('offlineUpdate',logger)
3052+ print "Manual Update Failed"
3053+
3054+ #Now the check boxes
3055+
3056+ checksum = False
3057+ try:
3058+ if config.get('Main','checksumPreviousDownloads') == "true":
3059+ checksum = True
3060+
3061+ logger.info("checksumPreviousDownloads: %s"%checksum)
3062+
3063+ except:
3064+ self.confValErr("checksumPreviousDownloads",logger)
3065+
3066+
3067+ lowTexture = False
3068+
3069+ try:
3070+ if config.get('Main','lowTextureMemory') == "true":
3071+ lowTexture = True
3072+ logger.info("lowTextureMemory: %s"%lowTexture)
3073+
3074+ except:
3075+ self.confValErr("lowTextureMemory",logger)
3076+
3077+
3078+ self.checksumCheckButton.set_active(checksum)
3079+
3080+ self.lowTextureCheckButton.set_active(lowTexture)
3081+
3082+
3083+ #Now the lift options
3084+ try:
3085+ self.liftDefaultTagText.set_text(config.get("LiftTags","default"))
3086+ logger.info("DefaultLiftTag: %s"%config.get('LiftTags','default'))
3087+
3088+ except:
3089+ self.confValErr("liftTags",logger)
3090+
3091+ try:
3092+ self.lift7TagText.set_text(config.get("LiftTags","lift7"))
3093+ logger.info("Lift7Tag: %s"%config.get('LiftTags','lift7'))
3094+
3095+ except:
3096+ self.confValErr("lift7",logger)
3097+
3098+ try:
3099+ self.lift6TagText.set_text(config.get("LiftTags","lift6"))
3100+ logger.info("Lift6Tag: %s"%config.get('LiftTags','lift6'))
3101+ except:
3102+ self.confValErr("lift6",logger)
3103+
3104+ try:
3105+ self.lift5TagText.set_text(config.get("LiftTags","lift5"))
3106+ logger.info("Lift5Tag: %s"%config.get('LiftTags','lift5'))
3107+ except:
3108+ self.confValErr("lift5",logger)
3109+
3110+ try:
3111+ self.lift4TagText.set_text(config.get("LiftTags","lift4"))
3112+ logger.info("Lift4Tag: %s"%config.get('LiftTags','lift4'))
3113+ except:
3114+ self.confValErr("lift4",logger)
3115+
3116+ try:
3117+ self.lift3TagText.set_text(config.get("LiftTags","lift3"))
3118+ logger.info("Lift3Tag: %s"%config.get('LiftTags','lift3'))
3119+ except:
3120+ self.confValErr("lift3",logger)
3121+
3122+ try:
3123+ self.lift2TagText.set_text(config.get("LiftTags","lift2"))
3124+ logger.info("Lift2Tag: %s"%config.get('LiftTags','lift2'))
3125+ except:
3126+ self.confValErr("lift2",logger)
3127+
3128+ try:
3129+ self.lift1TagText.set_text(config.get("LiftTags","lift1"))
3130+ logger.info("Lift1Tag: %s"%config.get('LiftTags','lift1'))
3131+ except:
3132+ self.confValErr("lift1",logger)
3133+
3134+ try:
3135+ self.lift0TagText.set_text(config.get("LiftTags","lift0"))
3136+ logger.info("Lift0Tag: %s"%config.get('LiftTags','lift0'))
3137+ except:
3138+ self.confValErr("lift0",logger)
3139+
3140+ try:
3141+ self.firstSerialText.set_text(config.get("Lift","serial0"))
3142+ logger.info("FirstSerial: %s"%config.get('Lift','serial0'))
3143+ except:
3144+ self.confValErr("serial0",logger)
3145+
3146+ try:
3147+ self.secondSerialText.set_text(config.get("Lift","serial1"))
3148+ logger.info("SecondSerial: %s"%config.get('Lift','serial1'))
3149+ except:
3150+ self.confValErr("serial1",logger)
3151+
3152+ try:
3153+ self.liftTriggerValue.set_value(int(config.get("Lift","trigger")))
3154+ logger.info("LiftTrigger: %s"%config.get('Lift','trigger'))
3155+ except:
3156+ self.confValErr("trigger",logger)
3157+
3158+ try:
3159+
3160+ liftEnableType = config.get("Lift","enabled")
3161+ logger.info("LiftEnabled: %s"%config.get('Lift','enabled'))
3162+
3163+ val = 0
3164+
3165+ for elem in self.liftEnableOptions:
3166+ if elem.lower() == liftEnableType.lower():
3167+ break
3168+ val += 1
3169+
3170+ self.liftEnableCombo.set_active(val)
3171+ except:
3172+ self.confValErr("liftEnabled",logger)
3173+
3174+ def saveConfigSignal(self,widget,data=None):
3175+ a = self.getConfValues()
3176+ self.logger11.info("Config Values to process: %s"%a)
3177+ config = ConfigParser.RawConfigParser()
3178+
3179+ config.optionxform = str
3180+
3181+ configOptions = ["Main", "Logging", "Stats", "TickerMedia", "Lift", "LiftTags"]
3182+
3183+ for configOption in configOptions:
3184+ #print configOption
3185+ config.add_section(configOption)
3186+
3187+ for elem in a:
3188+ #print elem, a[elem][1], configOption
3189+ if a[elem][0] == configOption:
3190+ print elem, a[elem][1],configOption
3191+ try:
3192+
3193+ config.set(configOption, elem, str(a[elem][1]))
3194+ self.logger11.info("Value: %s %s %s"%(configOption,elem,str(a[elem][1])))
3195+ except:
3196+ print "Error setting option:"
3197+ print "Element:", elem
3198+ print "Data:", a[elem]
3199+ print "Error setting: %s, %s"%(elem,a[elem][1])
3200+ print a[elem][1]
3201+ print str(a[elem][1])
3202+ self.logger11.error("Error setting value: %s %s %s"%(configOption,elem,str(a[elem][1])))
3203+ finally:
3204+ #Write everything, barring the error item
3205+
3206+ # with open(self.pyClientConfName, 'wb') as configfile:
3207+ # config.write(configfile)
3208+
3209+ try:
3210+ configfile = open(self.pyClientConfName,"wb")
3211+ config.write(configfile)
3212+ self.logger11.info("Data successfully written")
3213+ self.messageDialog.set_markup(_("Successfully written configuration file"))
3214+ self.messageDialog.show()
3215+
3216+ except:
3217+ self.logger11.error("Data could not be written")
3218+ self.errorDialog.set_markup(_("Could not open / write to configuration file. Cannot continue"))
3219+ self.errorDialog.show()
3220+
3221+# #Read in the existing configuration file as a string
3222+# #we can then replace every instance of %s with one of the
3223+# #configuration items
3224+
3225+# #I have chosen this way because then we can keep the comments
3226+# #in place for manual usage
3227+
3228+# config_template_string = ""
3229+# try:
3230+# f = open("site.cfg.default","r")
3231+# config_template_string = f.read()
3232+# f.close()
3233+# except:
3234+# print "Error reading default config file"
3235+
3236+ #Now create the string to write to the new config. file
3237+
3238+# config_string = config_template_string%(a["serverURL"],a["clientID"],a["serverKey"],a["refresh"],a["serverConn"],a["screenWidth"],a["screenHeight"],a["fullScreen"],a["logType"],a["logVal"],a["captureStats"],a["queueSize"])
3239+
3240+# #Now write the configuration file
3241+
3242+# try:
3243+# f = open(self.pyClientConfLoc,"w")
3244+# # f.write(config_string)
3245+# f.close()
3246+# except:
3247+# print "Could not write configuration file"
3248+
3249+ def genClientID(self):
3250+ """Function used to generate a random client ID. Returns a generated UUID"""
3251+ uuidStr = uuid.uuid4()
3252+ self.logger4.info("UUID Generated: %s"%uuidStr)
3253+ return uuidStr
3254+
3255+
3256+ def set_tooltips(self):
3257+
3258+ self.clearButton.set_tooltip_text(_("Clear input fields"))
3259+ self.saveButton.set_tooltip_text(_("Save data to file"))
3260+
3261+ self.serverURLText.set_tooltip_text(_("URL of your Xibo server"))
3262+ self.clientIDText.set_tooltip_text(_("Client identifier (used to generate license key hash)"))
3263+ self.serverKeyText.set_tooltip_text(_("Server key"))
3264+ self.refreshText.set_tooltip_text(_("Collection interval"))
3265+ self.serverConnBool.set_tooltip_text(_("Does the client have to connect to XMDS before playing cached content?"))
3266+ self.fullScreenBool.set_tooltip_text(_("Should the client run fullscreen"))
3267+ self.screenWidthText.set_tooltip_text(_("Width of the rendered output screen"))
3268+ self.screenHeightText.set_tooltip_text(_("Height of the rendered output screen"))
3269+ self.captureStatisticsBool.set_tooltip_text(_("States whether statistics are generated or not"))
3270+ self.queueSizeText.set_tooltip_text(_("Statistics queue size"))
3271+ self.logLevelSpin.set_tooltip_text(_("Amount of log data to write. The higher the number, the more is written"))
3272+ self.logTypeCombo.set_tooltip_text(_("Where log data should be written to"))
3273+ self.clientNameText.set_tooltip_text(_("Name as it will be displayed in the server app"))
3274+
3275+ #Advanced options widgets
3276+
3277+ self.liftDefaultTagText.set_tooltip_text(_("Tag associated with lift input"))
3278+ self.lift7TagText.set_tooltip_text(_("Tag associated with lift input"))
3279+ self.lift6TagText.set_tooltip_text(_("Tag associated with lift input"))
3280+ self.lift5TagText.set_tooltip_text(_("Tag associated with lift input"))
3281+ self.lift4TagText.set_tooltip_text(_("Tag associated with lift input"))
3282+ self.lift3TagText.set_tooltip_text(_("Tag associated with lift input"))
3283+ self.lift2TagText.set_tooltip_text(_("Tag associated with lift input"))
3284+ self.lift1TagText.set_tooltip_text(_("Tag associated with lift input"))
3285+ self.lift0TagText.set_tooltip_text(_("Tag associated with lift input"))
3286+ self.firstSerialText.set_tooltip_text(_("First serial port to use for lift purposes"))
3287+ self.secondSerialText.set_tooltip_text(_("First serial port to use for lift purposes"))
3288+ self.liftTriggerValue.set_tooltip_text(_("Number of times lift is triggered before layout is changed"))
3289+ self.liftEnableCombo.set_tooltip_text(_("Sets whether lift functionality is enabled or not"))
3290+ self.dateFormatEntry.set_tooltip_text(_("Date format the client should render dates in when displaying RSS tickers"))
3291+ self.libraryEntry.set_tooltip_text(_("Which folder to store content in. Can be relative or absolute path"))
3292+ self.socketTimeSpin.set_tooltip_text(_("How long should we wait (in seconds) before timing out a hung socket"))
3293+ self.checksumCheckButton.set_tooltip_text(_("Should the client checksum all downloaded content to ensure it's unchanged at startup"))
3294+ self.lowTextureCheckButton.set_tooltip_text(_("Should the client attempt to minimise the amount of graphics texture memory it uses"))
3295+ self.framesSpin.set_tooltip_text(_("How many fps to force the client to run"))
3296+ self.vwidthSpin.set_tooltip_text(_("Width of the rendered virtual output screen (this will be a section within the overall window"))
3297+ self.vheightSpin.set_tooltip_text(_("Height of the rendered virtual output screen (this will be a section within the overall window"))
3298+ self.vrotateSpin.set_tooltip_text(_("Angle to rotate virtual window within the rendered output window"))
3299+ self.schedulerCombo.set_tooltip_text(_("Which scheduler module to use"))
3300+ self.downloaderCombo.set_tooltip_text(_("Which download manager module to use"))
3301+ self.colourDepthCombo.set_tooltip_text(_("Colour depth of the rendered output"))
3302+
3303+ self.xmdsLicenseKeyEntry.set_tooltip_text(_("Sets license key value to use when syncronising from memory stick"))
3304+# self.manualUpdateCombo.set_tooltip_text(_("Sets whether update from memory stick is enabled"))
3305+
3306+ def getConfValues(self):
3307+
3308+ model = self.logTypeCombo.get_model()
3309+ index = self.logTypeCombo.get_active()
3310+# logTypeText = model[index][0]
3311+
3312+ logTypeText = self.logWriterTypes[index]
3313+
3314+ configType = "Main"
3315+
3316+ serverUrl = [configType,self.serverURLText.get_text()]
3317+ clientId = [configType,self.clientIDText.get_text()]
3318+ serverKey = [configType,self.serverKeyText.get_text()]
3319+ refresh = [configType,int(self.refreshText.get_text())]
3320+ serverConn = [configType,str(self.serverConnBool.get_active()).lower()]
3321+ fullScreen = [configType,str(self.fullScreenBool.get_active()).lower()]
3322+ screenWidth = [configType, self.screenWidthText.get_value_as_int()]
3323+ screenHeight = [configType, self.screenHeightText.get_value_as_int()]
3324+ captureStats = ["Stats",str(self.captureStatisticsBool.get_active()).lower()]
3325+ queueSize = ["Stats",self.queueSizeText.get_value_as_int()]
3326+ logType = ["Logging", logTypeText]
3327+ logVal = ["Logging",self.logLevelSpin.get_value_as_int()]
3328+ xmdsClientName = ["Main",self.clientNameText.get_text()]
3329+
3330+ self.logger5.info("ServerURL: %s"%serverUrl)
3331+ self.logger5.info("clientID: %s"%clientId)
3332+ self.logger5.info("serverKey: %s"%serverKey)
3333+ self.logger5.info("refresh: %s"%refresh)
3334+ self.logger5.info("serverConn: %s"%serverConn)
3335+ self.logger5.info("fullScreen: %s"%fullScreen)
3336+ self.logger5.info("screenWidth: %s"%screenWidth)
3337+ self.logger5.info("screenHeight: %s"%screenHeight)
3338+ self.logger5.info("captureStats: %s"%captureStats)
3339+ self.logger5.info("queueSize: %s"%queueSize)
3340+ self.logger5.info("logType: %s"%logType)
3341+ self.logger5.info("logVal: %s"%logVal)
3342+ self.logger5.info("xmdsClientName: %s"%xmdsClientName)
3343+
3344+ #Take the boolean values and make them lower case.
3345+
3346+ configOptions = {"xmdsUrl": serverUrl, "xmdsClientID": clientId,"xmdsKey":serverKey,"xmdsUpdateInterval":refresh,"requireXMDS":serverConn,"fullScreen":fullScreen,"width":screenWidth,"height":screenHeight,"collect":captureStats,"queueSize":queueSize,"logWriter":logType,"logLevel":logVal,"xmdsClientName":xmdsClientName}
3347+
3348+ #GET THE LIFT OPTIONS
3349+
3350+
3351+ #ONLY DO THIS IF THE LIFT TAB IS SHOWING
3352+ #THEN ADD THEM TO THE DICTIONARY
3353+
3354+# if self.liftTabVisible == True:
3355+
3356+ #The above is deprecated. This is because we don't want the information to be
3357+ #"deleted" from the configuration file if we choose not to show these options
3358+ #on subsequent file loads
3359+ if 1:
3360+
3361+ configType = "Lift"
3362+ configType1 = "LiftTags"
3363+
3364+ model = self.liftEnableCombo.get_model()
3365+ index = self.liftEnableCombo.get_active()
3366+ liftEnableText = model[index][0].lower()
3367+
3368+ liftDefaultTag = [configType1,self.liftDefaultTagText.get_text()]
3369+ lift7Tag = [configType1, self.lift7TagText.get_text()]
3370+ lift6Tag = [configType1, self.lift6TagText.get_text()]
3371+ lift5Tag = [configType1, self.lift5TagText.get_text()]
3372+ lift4Tag = [configType1, self.lift4TagText.get_text()]
3373+ lift3Tag = [configType1, self.lift3TagText.get_text()]
3374+ lift2Tag = [configType1, self.lift2TagText.get_text()]
3375+ lift1Tag = [configType1, self.lift1TagText.get_text()]
3376+ lift0Tag = [configType1, self.lift0TagText.get_text()]
3377+ firstSerial = [configType, self.firstSerialText.get_text()]
3378+ secondSerial = [configType, self.secondSerialText.get_text()]
3379+ liftTrigger = [configType, self.liftTriggerValue.get_text()]
3380+ liftEnable = [configType, liftEnableText]
3381+
3382+ if liftDefaultTag[1] != "":
3383+ configOptions["default"] = liftDefaultTag
3384+
3385+ if lift7Tag[1] != "":
3386+ configOptions["lift7"] =lift7Tag
3387+
3388+ if lift6Tag[1] != "":
3389+ configOptions["lift6"] =lift6Tag
3390+
3391+ if lift5Tag[1] != "":
3392+ configOptions["lift5"] =lift5Tag
3393+
3394+ if lift4Tag[1] != "":
3395+ configOptions["lift4"] =lift4Tag
3396+
3397+ if lift3Tag[1] != "":
3398+ configOptions["lift3"] =lift3Tag
3399+
3400+ if lift2Tag[1] != "":
3401+ configOptions["lift2"] =lift2Tag
3402+
3403+ if lift1Tag[1] != "":
3404+ configOptions["lift1"] =lift1Tag
3405+
3406+ if lift0Tag[1] != "":
3407+ configOptions["lift0"] =lift0Tag
3408+
3409+ if firstSerial[1] != "":
3410+ configOptions["serial0"] =firstSerial
3411+
3412+ if secondSerial[1] != "":
3413+ configOptions["serial1"] =secondSerial
3414+
3415+ if liftEnable[1] != "false":
3416+ configOptions["enabled"] =liftEnable
3417+
3418+ if liftTrigger != "0":
3419+ configOptions["trigger"] =liftTrigger
3420+
3421+# if self.advancedTabVisible == True:
3422+
3423+ #The above is deprecated. This is because we don't want the information to be
3424+ #"deleted" from the configuration file if we choose not to show these options
3425+ #on subsequent file loads
3426+ if 1:
3427+ configType = "Main"
3428+
3429+ model = self.schedulerCombo.get_model()
3430+ index = self.schedulerCombo.get_active()
3431+ schedulerComboText = model[index][0]
3432+
3433+ model = self.downloaderCombo.get_model()
3434+ index = self.downloaderCombo.get_active()
3435+ downloaderComboText = model[index][0]
3436+
3437+ model = self.colourDepthCombo.get_model()
3438+ index = self.colourDepthCombo.get_active()
3439+ colourDepthComboText = model[index][0]
3440+
3441+ xmdsLicenseKeyEntry = [configType,self.xmdsLicenseKeyEntry.get_text()]
3442+
3443+# model = self.manualUpdateCombo.get_model()
3444+# index = self.manualUpdateCombo.get_active()
3445+# manualUpdateText = model[index][0]
3446+
3447+ manualUpdateText = str(self.offlineCheckButton.get_active()).lower()
3448+
3449+ manualUpdate = [configType,manualUpdateText.lower()]
3450+
3451+ dateFormatEntry = ["TickerMedia", self.dateFormatEntry.get_text()]
3452+
3453+ libraryEntry = [configType, self.libraryEntry.get_text()]
3454+ socketTimeSpin = [configType, self.socketTimeSpin.get_text()]
3455+ checksum = [configType, str(self.checksumCheckButton.get_active()).lower()]
3456+ lowTexture = [configType, str(self.lowTextureCheckButton.get_active()).lower()]
3457+
3458+
3459+ frames = [configType, self.framesSpin.get_text()]
3460+ vwidth = [configType, self.vwidthSpin.get_text()]
3461+ vheight = [configType, self.vheightSpin.get_text()]
3462+ vrotate = [configType, self.vrotateSpin.get_text()]
3463+ scheduler = [configType, schedulerComboText]
3464+ downloader = [configType, downloaderComboText]
3465+ colourDepth = [configType, colourDepthComboText]
3466+
3467+ if xmdsLicenseKeyEntry[1] != "":
3468+ configOptions["xmdsLicenseKey"] = xmdsLicenseKeyEntry
3469+
3470+ if manualUpdateText[1] != "":
3471+ configOptions["manualUpdate"] = manualUpdate
3472+
3473+
3474+ if dateFormatEntry[1] != "":
3475+ configOptions["dateFormat"] = dateFormatEntry
3476+
3477+ if libraryEntry[1] != "":
3478+ configOptions["libraryDir"] = libraryEntry
3479+
3480+ if socketTimeSpin[1] != "0":
3481+ configOptions["socketTimeout"] = socketTimeSpin
3482+
3483+ if checksum[1] == "true":
3484+ configOptions["checksumPreviousDownloads"] = checksum
3485+
3486+ if lowTexture[1] == "true":
3487+ configOptions["lowTextureMemory"] = lowTexture
3488+
3489+ if frames[1] != "0":
3490+ configOptions["fps"] = frames
3491+
3492+ if vwidth[1] != "0":
3493+ configOptions["vwidth"] = vwidth
3494+
3495+ if vheight[1] != "0":
3496+ configOptions["vheight"] = vheight
3497+
3498+ if vrotate[1] != "0":
3499+ configOptions["vrotation"] = vrotate
3500+
3501+ if scheduler[1] != "":
3502+ configOptions["scheduler"] = scheduler
3503+
3504+ if downloader[1] != "":
3505+ configOptions["downloader"] = downloader
3506+
3507+ if colourDepth[1] != "":
3508+ configOptions["bpp"] = colourDepth
3509+
3510+ return configOptions
3511+def cmdOptions():
3512+ options = sys.argv[1:]
3513+
3514+ #For each option in the array strip off any - characters and convert to lower case
3515+
3516+ for i in range(len(options)):
3517+ options[i] = options[i].strip("-").lower()
3518+
3519+ return options
3520+
3521+if __name__ == "__main__":
3522+
3523+ #Grab the command line options
3524+ options = cmdOptions()
3525+
3526+ #Find out of the lift option has been passed
3527+ lift = False
3528+ try:
3529+ options.index("lift")
3530+ lift = True
3531+ except ValueError:
3532+ print "Option not found"
3533+ lift = False
3534+
3535+
3536+ wine = xiboConfWindow("client.conf", lift = lift)
3537+ gtk.main()
3538
3539=== renamed file 'client/python/configure.py' => 'client/python/configure.py.moved'
3540=== modified file 'client/python/defaults.cfg'
3541=== added file 'client/python/gui.glade'
3542--- client/python/gui.glade 1970-01-01 00:00:00 +0000
3543+++ client/python/gui.glade 2011-02-28 15:09:00 +0000
3544@@ -0,0 +1,1451 @@
3545+<?xml version="1.0" encoding="UTF-8"?>
3546+<interface>
3547+ <requires lib="gtk+" version="2.16"/>
3548+ <!-- interface-naming-policy project-wide -->
3549+ <object class="GtkWindow" id="mainWindow">
3550+ <property name="width_request">600</property>
3551+ <property name="height_request">445</property>
3552+ <property name="title" translatable="yes">Xibo Client Configuration</property>
3553+ <property name="resizable">False</property>
3554+ <signal name="destroy" handler="onDestroy"/>
3555+ <child>
3556+ <object class="GtkFixed" id="fixed1">
3557+ <property name="width_request">600</property>
3558+ <property name="height_request">445</property>
3559+ <property name="visible">True</property>
3560+ <child>
3561+ <object class="GtkNotebook" id="notebook1">
3562+ <property name="width_request">600</property>
3563+ <property name="height_request">440</property>
3564+ <property name="visible">True</property>
3565+ <property name="can_focus">True</property>
3566+ <child>
3567+ <object class="GtkFixed" id="fixed2">
3568+ <property name="visible">True</property>
3569+ <child>
3570+ <object class="GtkLabel" id="refreshLabel">
3571+ <property name="width_request">267</property>
3572+ <property name="height_request">38</property>
3573+ <property name="visible">True</property>
3574+ <property name="label" translatable="yes">Set the number of seconds between the client contacting the server for updates</property>
3575+ <property name="justify">right</property>
3576+ <property name="wrap">True</property>
3577+ </object>
3578+ <packing>
3579+ <property name="x">8</property>
3580+ <property name="y">303</property>
3581+ </packing>
3582+ </child>
3583+ <child>
3584+ <object class="GtkButton" id="clearFields">
3585+ <property name="label" translatable="yes">Clear Form</property>
3586+ <property name="width_request">100</property>
3587+ <property name="height_request">33</property>
3588+ <property name="visible">True</property>
3589+ <property name="can_focus">True</property>
3590+ <property name="receives_default">True</property>
3591+ <signal name="clicked" handler="clearFormSignal"/>
3592+ </object>
3593+ <packing>
3594+ <property name="x">370</property>
3595+ <property name="y">364</property>
3596+ </packing>
3597+ </child>
3598+ <child>
3599+ <object class="GtkButton" id="saveConfig">
3600+ <property name="label" translatable="yes">Save Config</property>
3601+ <property name="width_request">100</property>
3602+ <property name="height_request">33</property>
3603+ <property name="visible">True</property>
3604+ <property name="can_focus">True</property>
3605+ <property name="receives_default">True</property>
3606+ <signal name="clicked" handler="saveConfigSignal"/>
3607+ </object>
3608+ <packing>
3609+ <property name="x">475</property>
3610+ <property name="y">363</property>
3611+ </packing>
3612+ </child>
3613+ <child>
3614+ <object class="GtkLabel" id="connectionLabel">
3615+ <property name="width_request">213</property>
3616+ <property name="height_request">40</property>
3617+ <property name="visible">True</property>
3618+ <property name="label" translatable="yes">Require connection to server</property>
3619+ <property name="justify">right</property>
3620+ <property name="wrap">True</property>
3621+ </object>
3622+ <packing>
3623+ <property name="x">12</property>
3624+ <property name="y">357</property>
3625+ </packing>
3626+ </child>
3627+ <child>
3628+ <object class="GtkCheckButton" id="serverConnection">
3629+ <property name="width_request">40</property>
3630+ <property name="height_request">32</property>
3631+ <property name="visible">True</property>
3632+ <property name="can_focus">True</property>
3633+ <property name="receives_default">False</property>
3634+ <property name="tooltip_text" translatable="yes">This setting is used by the client to
3635+determine whether a connection to
3636+the server is needed before the client
3637+displays any content.
3638+
3639+This can be used to allow client that
3640+are not connected to a network to show
3641+pre-loaded content</property>
3642+ <property name="draw_indicator">True</property>
3643+ </object>
3644+ <packing>
3645+ <property name="x">220</property>
3646+ <property name="y">362</property>
3647+ </packing>
3648+ </child>
3649+ <child>
3650+ <object class="GtkSpinButton" id="refreshText">
3651+ <property name="width_request">100</property>
3652+ <property name="height_request">27</property>
3653+ <property name="visible">True</property>
3654+ <property name="can_focus">True</property>
3655+ <property name="invisible_char">●</property>
3656+ </object>
3657+ <packing>
3658+ <property name="x">272</property>
3659+ <property name="y">308</property>
3660+ </packing>
3661+ </child>
3662+ <child>
3663+ <object class="GtkCheckButton" id="advancedOptionsCheck">
3664+ <property name="label" translatable="yes">Display Advanced Options</property>
3665+ <property name="width_request">200</property>
3666+ <property name="height_request">33</property>
3667+ <property name="visible">True</property>
3668+ <property name="can_focus">True</property>
3669+ <property name="receives_default">False</property>
3670+ <property name="draw_indicator">True</property>
3671+ <signal name="toggled" handler="on_advancedOptionsCheck"/>
3672+ </object>
3673+ <packing>
3674+ <property name="x">386</property>
3675+ <property name="y">316</property>
3676+ </packing>
3677+ </child>
3678+ <child>
3679+ <object class="GtkFrame" id="frame7">
3680+ <property name="width_request">561</property>
3681+ <property name="height_request">186</property>
3682+ <property name="visible">True</property>
3683+ <property name="label_xalign">0</property>
3684+ <property name="shadow_type">out</property>
3685+ <child>
3686+ <object class="GtkAlignment" id="alignment7">
3687+ <property name="visible">True</property>
3688+ <property name="left_padding">12</property>
3689+ <child>
3690+ <object class="GtkFixed" id="fixed13">
3691+ <property name="visible">True</property>
3692+ <child>
3693+ <object class="GtkEntry" id="serverURLText">
3694+ <property name="width_request">375</property>
3695+ <property name="height_request">30</property>
3696+ <property name="visible">True</property>
3697+ <property name="can_focus">True</property>
3698+ <property name="invisible_char">●</property>
3699+ </object>
3700+ <packing>
3701+ <property name="x">108</property>
3702+ <property name="y">7</property>
3703+ </packing>
3704+ </child>
3705+ <child>
3706+ <object class="GtkLabel" id="serverURLLabel">
3707+ <property name="width_request">100</property>
3708+ <property name="height_request">27</property>
3709+ <property name="visible">True</property>
3710+ <property name="label" translatable="yes">Server URL</property>
3711+ <property name="justify">right</property>
3712+ </object>
3713+ <packing>
3714+ <property name="y">10</property>
3715+ </packing>
3716+ </child>
3717+ <child>
3718+ <object class="GtkEntry" id="clientIDText">
3719+ <property name="width_request">375</property>
3720+ <property name="height_request">30</property>
3721+ <property name="visible">True</property>
3722+ <property name="can_focus">True</property>
3723+ <property name="invisible_char">●</property>
3724+ </object>
3725+ <packing>
3726+ <property name="x">108</property>
3727+ <property name="y">48</property>
3728+ </packing>
3729+ </child>
3730+ <child>
3731+ <object class="GtkLabel" id="clientIDLabel">
3732+ <property name="width_request">100</property>
3733+ <property name="height_request">30</property>
3734+ <property name="visible">True</property>
3735+ <property name="label" translatable="yes">Client ID</property>
3736+ <property name="justify">right</property>
3737+ </object>
3738+ <packing>
3739+ <property name="x">7</property>
3740+ <property name="y">49</property>
3741+ </packing>
3742+ </child>
3743+ <child>
3744+ <object class="GtkEntry" id="serverKeyText">
3745+ <property name="width_request">375</property>
3746+ <property name="height_request">30</property>
3747+ <property name="visible">True</property>
3748+ <property name="can_focus">True</property>
3749+ <property name="invisible_char">●</property>
3750+ </object>
3751+ <packing>
3752+ <property name="x">108</property>
3753+ <property name="y">91</property>
3754+ </packing>
3755+ </child>
3756+ <child>
3757+ <object class="GtkLabel" id="serverKeyLabel">
3758+ <property name="width_request">100</property>
3759+ <property name="height_request">30</property>
3760+ <property name="visible">True</property>
3761+ <property name="label" translatable="yes">Server Key</property>
3762+ <property name="justify">right</property>
3763+ </object>
3764+ <packing>
3765+ <property name="y">92</property>
3766+ </packing>
3767+ </child>
3768+ <child>
3769+ <object class="GtkEntry" id="clientNameText">
3770+ <property name="width_request">375</property>
3771+ <property name="height_request">30</property>
3772+ <property name="visible">True</property>
3773+ <property name="can_focus">True</property>
3774+ <property name="invisible_char">●</property>
3775+ </object>
3776+ <packing>
3777+ <property name="x">108</property>
3778+ <property name="y">132</property>
3779+ </packing>
3780+ </child>
3781+ <child>
3782+ <object class="GtkLabel" id="clientNameLabel">
3783+ <property name="width_request">87</property>
3784+ <property name="height_request">27</property>
3785+ <property name="visible">True</property>
3786+ <property name="label" translatable="yes">Client Name</property>
3787+ </object>
3788+ <packing>
3789+ <property name="y">135</property>
3790+ </packing>
3791+ </child>
3792+ </object>
3793+ </child>
3794+ </object>
3795+ </child>
3796+ <child type="label">
3797+ <object class="GtkLabel" id="onlineOpLabel">
3798+ <property name="visible">True</property>
3799+ <property name="label" translatable="yes">&lt;b&gt;Online operation (synchronise with server)&lt;/b&gt;</property>
3800+ <property name="use_markup">True</property>
3801+ </object>
3802+ </child>
3803+ </object>
3804+ <packing>
3805+ <property name="x">17</property>
3806+ <property name="y">46</property>
3807+ </packing>
3808+ </child>
3809+ <child>
3810+ <object class="GtkCheckButton" id="offlineCheckButton">
3811+ <property name="label" translatable="yes">Offline operation (syncronise from memory stick)</property>
3812+ <property name="width_request">362</property>
3813+ <property name="height_request">30</property>
3814+ <property name="visible">True</property>
3815+ <property name="can_focus">True</property>
3816+ <property name="receives_default">False</property>
3817+ <property name="draw_indicator">True</property>
3818+ <signal name="toggled" handler="offlineOperationToggle"/>
3819+ </object>
3820+ <packing>
3821+ <property name="x">16</property>
3822+ <property name="y">7</property>
3823+ </packing>
3824+ </child>
3825+ <child>
3826+ <object class="GtkLabel" id="xmdsLicenseKeyLabel">
3827+ <property name="width_request">122</property>
3828+ <property name="height_request">30</property>
3829+ <property name="visible">True</property>
3830+ <property name="label" translatable="yes">XMDS License Key</property>
3831+ </object>
3832+ <packing>
3833+ <property name="x">16</property>
3834+ <property name="y">247</property>
3835+ </packing>
3836+ </child>
3837+ <child>
3838+ <object class="GtkEntry" id="xmdsLicenseKeyEntry">
3839+ <property name="width_request">296</property>
3840+ <property name="height_request">30</property>
3841+ <property name="visible">True</property>
3842+ <property name="can_focus">True</property>
3843+ <property name="invisible_char">●</property>
3844+ </object>
3845+ <packing>
3846+ <property name="x">140</property>
3847+ <property name="y">246</property>
3848+ </packing>
3849+ </child>
3850+ </object>
3851+ </child>
3852+ <child type="tab">
3853+ <object class="GtkLabel" id="serverSettingsLabel">
3854+ <property name="visible">True</property>
3855+ <property name="label" translatable="yes">Server Settings</property>
3856+ </object>
3857+ <packing>
3858+ <property name="tab_fill">False</property>
3859+ </packing>
3860+ </child>
3861+ <child>
3862+ <object class="GtkFixed" id="fixed3">
3863+ <property name="visible">True</property>
3864+ <child>
3865+ <object class="GtkLabel" id="fullscreenLabel">
3866+ <property name="width_request">100</property>
3867+ <property name="height_request">32</property>
3868+ <property name="visible">True</property>
3869+ <property name="label" translatable="yes">Fullscreen</property>
3870+ </object>
3871+ <packing>
3872+ <property name="x">19</property>
3873+ <property name="y">27</property>
3874+ </packing>
3875+ </child>
3876+ <child>
3877+ <object class="GtkCheckButton" id="fullScreen">
3878+ <property name="width_request">100</property>
3879+ <property name="height_request">32</property>
3880+ <property name="visible">True</property>
3881+ <property name="can_focus">True</property>
3882+ <property name="receives_default">False</property>
3883+ <property name="tooltip_text" translatable="yes">Set this option if the client
3884+should run in full screen mode</property>
3885+ <property name="draw_indicator">True</property>
3886+ </object>
3887+ <packing>
3888+ <property name="x">125</property>
3889+ <property name="y">24</property>
3890+ </packing>
3891+ </child>
3892+ <child>
3893+ <object class="GtkLabel" id="widthLabel">
3894+ <property name="width_request">57</property>
3895+ <property name="height_request">32</property>
3896+ <property name="visible">True</property>
3897+ <property name="label" translatable="yes">Width</property>
3898+ <property name="justify">right</property>
3899+ </object>
3900+ <packing>
3901+ <property name="x">54</property>
3902+ <property name="y">60</property>
3903+ </packing>
3904+ </child>
3905+ <child>
3906+ <object class="GtkSpinButton" id="screenWidthText">
3907+ <property name="width_request">100</property>
3908+ <property name="height_request">27</property>
3909+ <property name="visible">True</property>
3910+ <property name="can_focus">True</property>
3911+ <property name="invisible_char">●</property>
3912+ </object>
3913+ <packing>
3914+ <property name="x">126</property>
3915+ <property name="y">61</property>
3916+ </packing>
3917+ </child>
3918+ <child>
3919+ <object class="GtkLabel" id="heightLabel">
3920+ <property name="width_request">57</property>
3921+ <property name="height_request">27</property>
3922+ <property name="visible">True</property>
3923+ <property name="label" translatable="yes">Height</property>
3924+ </object>
3925+ <packing>
3926+ <property name="x">49</property>
3927+ <property name="y">100</property>
3928+ </packing>
3929+ </child>
3930+ <child>
3931+ <object class="GtkSpinButton" id="screenHeightText">
3932+ <property name="width_request">100</property>
3933+ <property name="height_request">30</property>
3934+ <property name="visible">True</property>
3935+ <property name="can_focus">True</property>
3936+ <property name="invisible_char">●</property>
3937+ </object>
3938+ <packing>
3939+ <property name="x">125</property>
3940+ <property name="y">97</property>
3941+ </packing>
3942+ </child>
3943+ </object>
3944+ <packing>
3945+ <property name="position">1</property>
3946+ </packing>
3947+ </child>
3948+ <child type="tab">
3949+ <object class="GtkLabel" id="clientSettingsLabel">
3950+ <property name="visible">True</property>
3951+ <property name="label" translatable="yes">Client Settings</property>
3952+ </object>
3953+ <packing>
3954+ <property name="position">1</property>
3955+ <property name="tab_fill">False</property>
3956+ </packing>
3957+ </child>
3958+ <child>
3959+ <object class="GtkFixed" id="fixed4">
3960+ <property name="visible">True</property>
3961+ <child>
3962+ <object class="GtkFrame" id="frame1">
3963+ <property name="width_request">582</property>
3964+ <property name="height_request">172</property>
3965+ <property name="visible">True</property>
3966+ <property name="label_xalign">0</property>
3967+ <property name="shadow_type">out</property>
3968+ <child>
3969+ <object class="GtkAlignment" id="alignment1">
3970+ <property name="visible">True</property>
3971+ <property name="left_padding">12</property>
3972+ <child>
3973+ <object class="GtkFixed" id="fixed5">
3974+ <property name="visible">True</property>
3975+ <child>
3976+ <object class="GtkLabel" id="logTypeLabel">
3977+ <property name="width_request">100</property>
3978+ <property name="height_request">28</property>
3979+ <property name="visible">True</property>
3980+ <property name="label" translatable="yes">Log Type</property>
3981+ </object>
3982+ <packing>
3983+ <property name="x">4</property>
3984+ <property name="y">15</property>
3985+ </packing>
3986+ </child>
3987+ <child>
3988+ <object class="GtkLabel" id="logLevelLabel">
3989+ <property name="width_request">100</property>
3990+ <property name="height_request">30</property>
3991+ <property name="visible">True</property>
3992+ <property name="label" translatable="yes">Log Level</property>
3993+ </object>
3994+ <packing>
3995+ <property name="y">44</property>
3996+ </packing>
3997+ </child>
3998+ <child>
3999+ <object class="GtkComboBox" id="logTypeCombo">
4000+ <property name="width_request">218</property>
4001+ <property name="height_request">28</property>
4002+ <property name="visible">True</property>
4003+ <signal name="changed" handler="logTypeComboChanged"/>
4004+ </object>
4005+ <packing>
4006+ <property name="x">103</property>
4007+ <property name="y">14</property>
4008+ </packing>
4009+ </child>
4010+ <child>
4011+ <object class="GtkSpinButton" id="logLevelSpin">
4012+ <property name="width_request">97</property>
4013+ <property name="height_request">27</property>
4014+ <property name="visible">True</property>
4015+ <property name="can_focus">True</property>
4016+ <property name="tooltip_text" translatable="yes">The higher the value, the
4017+more verbose the logging</property>
4018+ <property name="invisible_char">●</property>
4019+ </object>
4020+ <packing>
4021+ <property name="x">103</property>
4022+ <property name="y">50</property>
4023+ </packing>
4024+ </child>
4025+ <child>
4026+ <object class="GtkLinkButton" id="logFileLinkButton">
4027+ <property name="label" translatable="yes">Open Log File</property>
4028+ <property name="width_request">114</property>
4029+ <property name="height_request">27</property>
4030+ <property name="visible">True</property>
4031+ <property name="can_focus">True</property>
4032+ <property name="receives_default">True</property>
4033+ <property name="has_tooltip">True</property>
4034+ <property name="relief">none</property>
4035+ </object>
4036+ <packing>
4037+ <property name="x">207</property>
4038+ <property name="y">50</property>
4039+ </packing>
4040+ </child>
4041+ </object>
4042+ </child>
4043+ </object>
4044+ </child>
4045+ <child type="label">
4046+ <object class="GtkLabel" id="loggingFrameLabel">
4047+ <property name="visible">True</property>
4048+ <property name="label" translatable="yes">&lt;b&gt;Logging&lt;/b&gt;</property>
4049+ <property name="use_markup">True</property>
4050+ </object>
4051+ </child>
4052+ </object>
4053+ <packing>
4054+ <property name="x">8</property>
4055+ <property name="y">9</property>
4056+ </packing>
4057+ </child>
4058+ <child>
4059+ <object class="GtkFrame" id="frame2">
4060+ <property name="width_request">582</property>
4061+ <property name="height_request">208</property>
4062+ <property name="visible">True</property>
4063+ <property name="label_xalign">0</property>
4064+ <property name="shadow_type">out</property>
4065+ <child>
4066+ <object class="GtkAlignment" id="alignment2">
4067+ <property name="visible">True</property>
4068+ <property name="left_padding">12</property>
4069+ <child>
4070+ <object class="GtkFixed" id="fixed6">
4071+ <property name="visible">True</property>
4072+ <child>
4073+ <object class="GtkLabel" id="statsCaptureLabel">
4074+ <property name="width_request">63</property>
4075+ <property name="height_request">43</property>
4076+ <property name="visible">True</property>
4077+ <property name="label" translatable="yes">Statistics capturing</property>
4078+ <property name="justify">right</property>
4079+ <property name="wrap">True</property>
4080+ </object>
4081+ <packing>
4082+ <property name="x">17</property>
4083+ <property name="y">13</property>
4084+ </packing>
4085+ </child>
4086+ <child>
4087+ <object class="GtkCheckButton" id="captureStatistics">
4088+ <property name="width_request">100</property>
4089+ <property name="height_request">30</property>
4090+ <property name="visible">True</property>
4091+ <property name="can_focus">True</property>
4092+ <property name="receives_default">False</property>
4093+ <property name="draw_indicator">True</property>
4094+ </object>
4095+ <packing>
4096+ <property name="x">99</property>
4097+ <property name="y">18</property>
4098+ </packing>
4099+ </child>
4100+ <child>
4101+ <object class="GtkLabel" id="statsQueueSizeLabel">
4102+ <property name="width_request">73</property>
4103+ <property name="height_request">25</property>
4104+ <property name="visible">True</property>
4105+ <property name="label" translatable="yes">Queue Size</property>
4106+ </object>
4107+ <packing>
4108+ <property name="x">5</property>
4109+ <property name="y">62</property>
4110+ </packing>
4111+ </child>
4112+ <child>
4113+ <object class="GtkSpinButton" id="queueSizeText">
4114+ <property name="width_request">100</property>
4115+ <property name="height_request">30</property>
4116+ <property name="visible">True</property>
4117+ <property name="can_focus">True</property>
4118+ <property name="invisible_char">●</property>
4119+ </object>
4120+ <packing>
4121+ <property name="x">101</property>
4122+ <property name="y">57</property>
4123+ </packing>
4124+ </child>
4125+ </object>
4126+ </child>
4127+ </object>
4128+ </child>
4129+ <child type="label">
4130+ <object class="GtkLabel" id="statsFrameLabel">
4131+ <property name="visible">True</property>
4132+ <property name="label" translatable="yes">&lt;b&gt;Statistic Capturing&lt;/b&gt;</property>
4133+ <property name="use_markup">True</property>
4134+ </object>
4135+ </child>
4136+ </object>
4137+ <packing>
4138+ <property name="x">8</property>
4139+ <property name="y">192</property>
4140+ </packing>
4141+ </child>
4142+ </object>
4143+ <packing>
4144+ <property name="position">2</property>
4145+ </packing>
4146+ </child>
4147+ <child type="tab">
4148+ <object class="GtkLabel" id="otherSettingsLabel">
4149+ <property name="visible">True</property>
4150+ <property name="label" translatable="yes">Other settings</property>
4151+ </object>
4152+ <packing>
4153+ <property name="position">2</property>
4154+ <property name="tab_fill">False</property>
4155+ </packing>
4156+ </child>
4157+ <child>
4158+ <object class="GtkFixed" id="fixed10">
4159+ <property name="visible">True</property>
4160+ <child>
4161+ <object class="GtkLabel" id="schedulerLabel">
4162+ <property name="width_request">73</property>
4163+ <property name="height_request">25</property>
4164+ <property name="visible">True</property>
4165+ <property name="label" translatable="yes">Scheduler</property>
4166+ </object>
4167+ <packing>
4168+ <property name="x">14</property>
4169+ <property name="y">16</property>
4170+ </packing>
4171+ </child>
4172+ <child>
4173+ <object class="GtkLabel" id="downloaderLabel">
4174+ <property name="width_request">82</property>
4175+ <property name="height_request">22</property>
4176+ <property name="visible">True</property>
4177+ <property name="label" translatable="yes">Downloader</property>
4178+ </object>
4179+ <packing>
4180+ <property name="x">15</property>
4181+ <property name="y">51</property>
4182+ </packing>
4183+ </child>
4184+ <child>
4185+ <object class="GtkLabel" id="libraryLabel">
4186+ <property name="width_request">68</property>
4187+ <property name="height_request">38</property>
4188+ <property name="visible">True</property>
4189+ <property name="label" translatable="yes">Library Location</property>
4190+ <property name="wrap">True</property>
4191+ </object>
4192+ <packing>
4193+ <property name="x">17</property>
4194+ <property name="y">82</property>
4195+ </packing>
4196+ </child>
4197+ <child>
4198+ <object class="GtkLabel" id="bppLabel">
4199+ <property name="width_request">82</property>
4200+ <property name="height_request">40</property>
4201+ <property name="visible">True</property>
4202+ <property name="label" translatable="yes">Colour depth (BPP)</property>
4203+ <property name="wrap">True</property>
4204+ </object>
4205+ <packing>
4206+ <property name="x">17</property>
4207+ <property name="y">129</property>
4208+ </packing>
4209+ </child>
4210+ <child>
4211+ <object class="GtkFrame" id="frame5">
4212+ <property name="width_request">278</property>
4213+ <property name="height_request">125</property>
4214+ <property name="visible">True</property>
4215+ <property name="label_xalign">0</property>
4216+ <property name="shadow_type">out</property>
4217+ <child>
4218+ <object class="GtkAlignment" id="alignment5">
4219+ <property name="visible">True</property>
4220+ <property name="left_padding">12</property>
4221+ <child>
4222+ <object class="GtkFixed" id="fixed11">
4223+ <property name="visible">True</property>
4224+ <child>
4225+ <object class="GtkLabel" id="vwidthLabel">
4226+ <property name="width_request">100</property>
4227+ <property name="height_request">25</property>
4228+ <property name="visible">True</property>
4229+ <property name="label" translatable="yes">Virtual Width</property>
4230+ </object>
4231+ <packing>
4232+ <property name="y">9</property>
4233+ </packing>
4234+ </child>
4235+ <child>
4236+ <object class="GtkLabel" id="vheightLabel">
4237+ <property name="width_request">100</property>
4238+ <property name="height_request">25</property>
4239+ <property name="visible">True</property>
4240+ <property name="label" translatable="yes">Virtual Height</property>
4241+ </object>
4242+ <packing>
4243+ <property name="y">41</property>
4244+ </packing>
4245+ </child>
4246+ <child>
4247+ <object class="GtkLabel" id="vrotationLabel">
4248+ <property name="width_request">66</property>
4249+ <property name="height_request">25</property>
4250+ <property name="visible">True</property>
4251+ <property name="label" translatable="yes">Rotation</property>
4252+ </object>
4253+ <packing>
4254+ <property name="y">72</property>
4255+ </packing>
4256+ </child>
4257+ <child>
4258+ <object class="GtkSpinButton" id="vwidthSpin">
4259+ <property name="width_request">100</property>
4260+ <property name="height_request">27</property>
4261+ <property name="visible">True</property>
4262+ <property name="can_focus">True</property>
4263+ <property name="invisible_char">●</property>
4264+ </object>
4265+ <packing>
4266+ <property name="x">135</property>
4267+ <property name="y">7</property>
4268+ </packing>
4269+ </child>
4270+ <child>
4271+ <object class="GtkSpinButton" id="vheightSpin">
4272+ <property name="width_request">100</property>
4273+ <property name="height_request">27</property>
4274+ <property name="visible">True</property>
4275+ <property name="can_focus">True</property>
4276+ <property name="invisible_char">●</property>
4277+ </object>
4278+ <packing>
4279+ <property name="x">135</property>
4280+ <property name="y">39</property>
4281+ </packing>
4282+ </child>
4283+ <child>
4284+ <object class="GtkSpinButton" id="vrotateSpin">
4285+ <property name="width_request">100</property>
4286+ <property name="height_request">27</property>
4287+ <property name="visible">True</property>
4288+ <property name="can_focus">True</property>
4289+ <property name="invisible_char">●</property>
4290+ </object>
4291+ <packing>
4292+ <property name="x">135</property>
4293+ <property name="y">71</property>
4294+ </packing>
4295+ </child>
4296+ </object>
4297+ </child>
4298+ </object>
4299+ </child>
4300+ <child type="label">
4301+ <object class="GtkLabel" id="virtualWinLabel">
4302+ <property name="visible">True</property>
4303+ <property name="label" translatable="yes">&lt;b&gt;Virtual Window&lt;/b&gt;</property>
4304+ <property name="use_markup">True</property>
4305+ </object>
4306+ </child>
4307+ </object>
4308+ <packing>
4309+ <property name="x">308</property>
4310+ <property name="y">269</property>
4311+ </packing>
4312+ </child>
4313+ <child>
4314+ <object class="GtkLabel" id="socketTimeLabel">
4315+ <property name="width_request">107</property>
4316+ <property name="height_request">40</property>
4317+ <property name="visible">True</property>
4318+ <property name="label" translatable="yes">Socket Timeout (seconds)</property>
4319+ <property name="wrap">True</property>
4320+ </object>
4321+ <packing>
4322+ <property name="x">16</property>
4323+ <property name="y">183</property>
4324+ </packing>
4325+ </child>
4326+ <child>
4327+ <object class="GtkLabel" id="checksumLabel">
4328+ <property name="width_request">100</property>
4329+ <property name="height_request">57</property>
4330+ <property name="visible">True</property>
4331+ <property name="label" translatable="yes">Checksum Downloaded Media</property>
4332+ <property name="wrap">True</property>
4333+ </object>
4334+ <packing>
4335+ <property name="x">15</property>
4336+ <property name="y">232</property>
4337+ </packing>
4338+ </child>
4339+ <child>
4340+ <object class="GtkLabel" id="lowTextureLabel">
4341+ <property name="width_request">85</property>
4342+ <property name="height_request">42</property>
4343+ <property name="visible">True</property>
4344+ <property name="label" translatable="yes">Low Texture Memory</property>
4345+ <property name="wrap">True</property>
4346+ </object>
4347+ <packing>
4348+ <property name="x">14</property>
4349+ <property name="y">299</property>
4350+ </packing>
4351+ </child>
4352+ <child>
4353+ <object class="GtkLabel" id="framesLabel">
4354+ <property name="width_request">80</property>
4355+ <property name="height_request">42</property>
4356+ <property name="visible">True</property>
4357+ <property name="label" translatable="yes">Frames per Second</property>
4358+ <property name="wrap">True</property>
4359+ </object>
4360+ <packing>
4361+ <property name="x">14</property>
4362+ <property name="y">351</property>
4363+ </packing>
4364+ </child>
4365+ <child>
4366+ <object class="GtkLabel" id="dateFormatLabel">
4367+ <property name="width_request">100</property>
4368+ <property name="height_request">27</property>
4369+ <property name="visible">True</property>
4370+ <property name="label" translatable="yes">Date Format</property>
4371+ </object>
4372+ <packing>
4373+ <property name="x">307</property>
4374+ <property name="y">14</property>
4375+ </packing>
4376+ </child>
4377+ <child>
4378+ <object class="GtkComboBox" id="schedulerCombo">
4379+ <property name="width_request">170</property>
4380+ <property name="height_request">27</property>
4381+ <property name="visible">True</property>
4382+ </object>
4383+ <packing>
4384+ <property name="x">127</property>
4385+ <property name="y">15</property>
4386+ </packing>
4387+ </child>
4388+ <child>
4389+ <object class="GtkComboBox" id="downloaderCombo">
4390+ <property name="width_request">170</property>
4391+ <property name="height_request">27</property>
4392+ <property name="visible">True</property>
4393+ </object>
4394+ <packing>
4395+ <property name="x">127</property>
4396+ <property name="y">48</property>
4397+ </packing>
4398+ </child>
4399+ <child>
4400+ <object class="GtkEntry" id="libraryEntry">
4401+ <property name="width_request">170</property>
4402+ <property name="height_request">27</property>
4403+ <property name="visible">True</property>
4404+ <property name="can_focus">True</property>
4405+ <property name="invisible_char">●</property>
4406+ </object>
4407+ <packing>
4408+ <property name="x">127</property>
4409+ <property name="y">85</property>
4410+ </packing>
4411+ </child>
4412+ <child>
4413+ <object class="GtkComboBox" id="colourDepthCombo">
4414+ <property name="width_request">100</property>
4415+ <property name="height_request">27</property>
4416+ <property name="visible">True</property>
4417+ </object>
4418+ <packing>
4419+ <property name="x">127</property>
4420+ <property name="y">133</property>
4421+ </packing>
4422+ </child>
4423+ <child>
4424+ <object class="GtkSpinButton" id="socketTimeSpin">
4425+ <property name="width_request">100</property>
4426+ <property name="height_request">27</property>
4427+ <property name="visible">True</property>
4428+ <property name="can_focus">True</property>
4429+ <property name="invisible_char">●</property>
4430+ </object>
4431+ <packing>
4432+ <property name="x">127</property>
4433+ <property name="y">188</property>
4434+ </packing>
4435+ </child>
4436+ <child>
4437+ <object class="GtkCheckButton" id="checksumCheckButton">
4438+ <property name="width_request">18</property>
4439+ <property name="height_request">27</property>
4440+ <property name="visible">True</property>
4441+ <property name="can_focus">True</property>
4442+ <property name="receives_default">False</property>
4443+ <property name="draw_indicator">True</property>
4444+ </object>
4445+ <packing>
4446+ <property name="x">127</property>
4447+ <property name="y">240</property>
4448+ </packing>
4449+ </child>
4450+ <child>
4451+ <object class="GtkCheckButton" id="lowTextureCheckButton">
4452+ <property name="width_request">20</property>
4453+ <property name="height_request">20</property>
4454+ <property name="visible">True</property>
4455+ <property name="can_focus">True</property>
4456+ <property name="receives_default">False</property>
4457+ <property name="draw_indicator">True</property>
4458+ </object>
4459+ <packing>
4460+ <property name="x">127</property>
4461+ <property name="y">308</property>
4462+ </packing>
4463+ </child>
4464+ <child>
4465+ <object class="GtkSpinButton" id="framesSpin">
4466+ <property name="width_request">100</property>
4467+ <property name="height_request">27</property>
4468+ <property name="visible">True</property>
4469+ <property name="can_focus">True</property>
4470+ <property name="invisible_char">●</property>
4471+ </object>
4472+ <packing>
4473+ <property name="x">127</property>
4474+ <property name="y">356</property>
4475+ </packing>
4476+ </child>
4477+ <child>
4478+ <object class="GtkEntry" id="dateFormatEntry">
4479+ <property name="width_request">150</property>
4480+ <property name="height_request">27</property>
4481+ <property name="visible">True</property>
4482+ <property name="can_focus">True</property>
4483+ <property name="invisible_char">●</property>
4484+ </object>
4485+ <packing>
4486+ <property name="x">432</property>
4487+ <property name="y">15</property>
4488+ </packing>
4489+ </child>
4490+ </object>
4491+ <packing>
4492+ <property name="position">3</property>
4493+ </packing>
4494+ </child>
4495+ <child type="tab">
4496+ <object class="GtkLabel" id="advancedOptionsLabel">
4497+ <property name="visible">True</property>
4498+ <property name="label" translatable="yes">Advanced Options</property>
4499+ </object>
4500+ <packing>
4501+ <property name="position">3</property>
4502+ <property name="tab_fill">False</property>
4503+ </packing>
4504+ </child>
4505+ <child>
4506+ <object class="GtkFixed" id="fixed7">
4507+ <property name="visible">True</property>
4508+ <child>
4509+ <object class="GtkFrame" id="frame3">
4510+ <property name="width_request">290</property>
4511+ <property name="height_request">390</property>
4512+ <property name="visible">True</property>
4513+ <property name="label_xalign">0</property>
4514+ <property name="shadow_type">out</property>
4515+ <child>
4516+ <object class="GtkAlignment" id="alignment3">
4517+ <property name="visible">True</property>
4518+ <property name="left_padding">12</property>
4519+ <child>
4520+ <object class="GtkFixed" id="fixed8">
4521+ <property name="visible">True</property>
4522+ <child>
4523+ <object class="GtkLabel" id="firstSerialLabel">
4524+ <property name="width_request">100</property>
4525+ <property name="height_request">22</property>
4526+ <property name="visible">True</property>
4527+ <property name="label" translatable="yes">1st Serial Port</property>
4528+ </object>
4529+ <packing>
4530+ <property name="y">11</property>
4531+ </packing>
4532+ </child>
4533+ <child>
4534+ <object class="GtkLabel" id="secondSerialLabel">
4535+ <property name="width_request">100</property>
4536+ <property name="height_request">22</property>
4537+ <property name="visible">True</property>
4538+ <property name="label" translatable="yes">2nd Serial Port</property>
4539+ </object>
4540+ <packing>
4541+ <property name="x">1</property>
4542+ <property name="y">50</property>
4543+ </packing>
4544+ </child>
4545+ <child>
4546+ <object class="GtkLabel" id="liftTriggerLabel">
4547+ <property name="width_request">87</property>
4548+ <property name="height_request">22</property>
4549+ <property name="visible">True</property>
4550+ <property name="label" translatable="yes">Trigger Value</property>
4551+ </object>
4552+ <packing>
4553+ <property name="x">2</property>
4554+ <property name="y">97</property>
4555+ </packing>
4556+ </child>
4557+ <child>
4558+ <object class="GtkLabel" id="liftEnableLabel">
4559+ <property name="width_request">75</property>
4560+ <property name="height_request">23</property>
4561+ <property name="visible">True</property>
4562+ <property name="label" translatable="yes">Enable Lift</property>
4563+ </object>
4564+ <packing>
4565+ <property name="y">136</property>
4566+ </packing>
4567+ </child>
4568+ <child>
4569+ <object class="GtkEntry" id="firstSerialText">
4570+ <property name="width_request">140</property>
4571+ <property name="height_request">27</property>
4572+ <property name="visible">True</property>
4573+ <property name="can_focus">True</property>
4574+ <property name="invisible_char">●</property>
4575+ </object>
4576+ <packing>
4577+ <property name="x">118</property>
4578+ <property name="y">5</property>
4579+ </packing>
4580+ </child>
4581+ <child>
4582+ <object class="GtkEntry" id="secondSerialText">
4583+ <property name="width_request">140</property>
4584+ <property name="height_request">27</property>
4585+ <property name="visible">True</property>
4586+ <property name="can_focus">True</property>
4587+ <property name="invisible_char">●</property>
4588+ </object>
4589+ <packing>
4590+ <property name="x">118</property>
4591+ <property name="y">45</property>
4592+ </packing>
4593+ </child>
4594+ <child>
4595+ <object class="GtkSpinButton" id="liftTriggerValue">
4596+ <property name="width_request">100</property>
4597+ <property name="height_request">27</property>
4598+ <property name="visible">True</property>
4599+ <property name="can_focus">True</property>
4600+ <property name="invisible_char">●</property>
4601+ </object>
4602+ <packing>
4603+ <property name="x">117</property>
4604+ <property name="y">93</property>
4605+ </packing>
4606+ </child>
4607+ <child>
4608+ <object class="GtkComboBox" id="liftEnableCombo">
4609+ <property name="width_request">100</property>
4610+ <property name="height_request">27</property>
4611+ <property name="visible">True</property>
4612+ </object>
4613+ <packing>
4614+ <property name="x">117</property>
4615+ <property name="y">138</property>
4616+ </packing>
4617+ </child>
4618+ </object>
4619+ </child>
4620+ </object>
4621+ </child>
4622+ <child type="label">
4623+ <object class="GtkLabel" id="genLiftOptions">
4624+ <property name="visible">True</property>
4625+ <property name="label" translatable="yes">&lt;b&gt;General Lift Options&lt;/b&gt;</property>
4626+ <property name="use_markup">True</property>
4627+ </object>
4628+ </child>
4629+ </object>
4630+ <packing>
4631+ <property name="x">5</property>
4632+ <property name="y">6</property>
4633+ </packing>
4634+ </child>
4635+ <child>
4636+ <object class="GtkFrame" id="frame4">
4637+ <property name="width_request">290</property>
4638+ <property name="height_request">390</property>
4639+ <property name="visible">True</property>
4640+ <property name="label_xalign">0</property>
4641+ <property name="shadow_type">out</property>
4642+ <child>
4643+ <object class="GtkAlignment" id="alignment4">
4644+ <property name="visible">True</property>
4645+ <property name="left_padding">12</property>
4646+ <child>
4647+ <object class="GtkFixed" id="fixed9">
4648+ <property name="visible">True</property>
4649+ <child>
4650+ <object class="GtkLabel" id="lift0Label">
4651+ <property name="width_request">40</property>
4652+ <property name="height_request">27</property>
4653+ <property name="visible">True</property>
4654+ <property name="label" translatable="yes">lift0</property>
4655+ </object>
4656+ <packing>
4657+ <property name="y">10</property>
4658+ </packing>
4659+ </child>
4660+ <child>
4661+ <object class="GtkLabel" id="lift1Label">
4662+ <property name="width_request">40</property>
4663+ <property name="height_request">27</property>
4664+ <property name="visible">True</property>
4665+ <property name="label" translatable="yes">lift1</property>
4666+ </object>
4667+ <packing>
4668+ <property name="y">40</property>
4669+ </packing>
4670+ </child>
4671+ <child>
4672+ <object class="GtkLabel" id="lift2Label">
4673+ <property name="width_request">40</property>
4674+ <property name="height_request">27</property>
4675+ <property name="visible">True</property>
4676+ <property name="label" translatable="yes">lift2</property>
4677+ </object>
4678+ <packing>
4679+ <property name="y">72</property>
4680+ </packing>
4681+ </child>
4682+ <child>
4683+ <object class="GtkLabel" id="lift3Label">
4684+ <property name="width_request">40</property>
4685+ <property name="height_request">27</property>
4686+ <property name="visible">True</property>
4687+ <property name="label" translatable="yes">lift3</property>
4688+ </object>
4689+ <packing>
4690+ <property name="y">104</property>
4691+ </packing>
4692+ </child>
4693+ <child>
4694+ <object class="GtkLabel" id="lift4Label">
4695+ <property name="width_request">40</property>
4696+ <property name="height_request">27</property>
4697+ <property name="visible">True</property>
4698+ <property name="label" translatable="yes">lift4</property>
4699+ </object>
4700+ <packing>
4701+ <property name="y">136</property>
4702+ </packing>
4703+ </child>
4704+ <child>
4705+ <object class="GtkLabel" id="lift5Label">
4706+ <property name="width_request">40</property>
4707+ <property name="height_request">27</property>
4708+ <property name="visible">True</property>
4709+ <property name="label" translatable="yes">lift5</property>
4710+ </object>
4711+ <packing>
4712+ <property name="y">169</property>
4713+ </packing>
4714+ </child>
4715+ <child>
4716+ <object class="GtkLabel" id="lift6Label">
4717+ <property name="width_request">40</property>
4718+ <property name="height_request">27</property>
4719+ <property name="visible">True</property>
4720+ <property name="label" translatable="yes">lift6</property>
4721+ </object>
4722+ <packing>
4723+ <property name="y">200</property>
4724+ </packing>
4725+ </child>
4726+ <child>
4727+ <object class="GtkLabel" id="lift7Label">
4728+ <property name="width_request">40</property>
4729+ <property name="height_request">27</property>
4730+ <property name="visible">True</property>
4731+ <property name="label" translatable="yes">lift7</property>
4732+ </object>
4733+ <packing>
4734+ <property name="y">233</property>
4735+ </packing>
4736+ </child>
4737+ <child>
4738+ <object class="GtkLabel" id="liftDefaultLabel">
4739+ <property name="width_request">50</property>
4740+ <property name="height_request">27</property>
4741+ <property name="visible">True</property>
4742+ <property name="label" translatable="yes">default</property>
4743+ </object>
4744+ <packing>
4745+ <property name="x">5</property>
4746+ <property name="y">264</property>
4747+ </packing>
4748+ </child>
4749+ <child>
4750+ <object class="GtkEntry" id="lift0TagText">
4751+ <property name="width_request">140</property>
4752+ <property name="height_request">27</property>
4753+ <property name="visible">True</property>
4754+ <property name="can_focus">True</property>
4755+ <property name="invisible_char">●</property>
4756+ </object>
4757+ <packing>
4758+ <property name="x">77</property>
4759+ <property name="y">8</property>
4760+ </packing>
4761+ </child>
4762+ <child>
4763+ <object class="GtkEntry" id="lift1TagText">
4764+ <property name="width_request">140</property>
4765+ <property name="height_request">27</property>
4766+ <property name="visible">True</property>
4767+ <property name="can_focus">True</property>
4768+ <property name="invisible_char">●</property>
4769+ </object>
4770+ <packing>
4771+ <property name="x">77</property>
4772+ <property name="y">39</property>
4773+ </packing>
4774+ </child>
4775+ <child>
4776+ <object class="GtkEntry" id="lift2TagText">
4777+ <property name="width_request">140</property>
4778+ <property name="height_request">27</property>
4779+ <property name="visible">True</property>
4780+ <property name="can_focus">True</property>
4781+ <property name="invisible_char">●</property>
4782+ </object>
4783+ <packing>
4784+ <property name="x">77</property>
4785+ <property name="y">71</property>
4786+ </packing>
4787+ </child>
4788+ <child>
4789+ <object class="GtkEntry" id="lift3TagText">
4790+ <property name="width_request">140</property>
4791+ <property name="height_request">27</property>
4792+ <property name="visible">True</property>
4793+ <property name="can_focus">True</property>
4794+ <property name="invisible_char">●</property>
4795+ </object>
4796+ <packing>
4797+ <property name="x">77</property>
4798+ <property name="y">103</property>
4799+ </packing>
4800+ </child>
4801+ <child>
4802+ <object class="GtkEntry" id="lift4TagText">
4803+ <property name="width_request">140</property>
4804+ <property name="height_request">27</property>
4805+ <property name="visible">True</property>
4806+ <property name="can_focus">True</property>
4807+ <property name="invisible_char">●</property>
4808+ </object>
4809+ <packing>
4810+ <property name="x">77</property>
4811+ <property name="y">135</property>
4812+ </packing>
4813+ </child>
4814+ <child>
4815+ <object class="GtkEntry" id="lift5TagText">
4816+ <property name="width_request">140</property>
4817+ <property name="height_request">27</property>
4818+ <property name="visible">True</property>
4819+ <property name="can_focus">True</property>
4820+ <property name="invisible_char">●</property>
4821+ </object>
4822+ <packing>
4823+ <property name="x">77</property>
4824+ <property name="y">167</property>
4825+ </packing>
4826+ </child>
4827+ <child>
4828+ <object class="GtkEntry" id="lift6TagText">
4829+ <property name="width_request">140</property>
4830+ <property name="height_request">27</property>
4831+ <property name="visible">True</property>
4832+ <property name="can_focus">True</property>
4833+ <property name="invisible_char">●</property>
4834+ </object>
4835+ <packing>
4836+ <property name="x">77</property>
4837+ <property name="y">199</property>
4838+ </packing>
4839+ </child>
4840+ <child>
4841+ <object class="GtkEntry" id="lift7TagText">
4842+ <property name="width_request">140</property>
4843+ <property name="height_request">27</property>
4844+ <property name="visible">True</property>
4845+ <property name="can_focus">True</property>
4846+ <property name="invisible_char">●</property>
4847+ </object>
4848+ <packing>
4849+ <property name="x">77</property>
4850+ <property name="y">231</property>
4851+ </packing>
4852+ </child>
4853+ <child>
4854+ <object class="GtkEntry" id="liftDefaultTagText">
4855+ <property name="width_request">140</property>
4856+ <property name="height_request">27</property>
4857+ <property name="visible">True</property>
4858+ <property name="can_focus">True</property>
4859+ <property name="invisible_char">●</property>
4860+ </object>
4861+ <packing>
4862+ <property name="x">77</property>
4863+ <property name="y">265</property>
4864+ </packing>
4865+ </child>
4866+ </object>
4867+ </child>
4868+ </object>
4869+ </child>
4870+ <child type="label">
4871+ <object class="GtkLabel" id="tagLiftLabel">
4872+ <property name="visible">True</property>
4873+ <property name="label" translatable="yes">&lt;b&gt;Tagging Lift Options&lt;/b&gt;</property>
4874+ <property name="use_markup">True</property>
4875+ </object>
4876+ </child>
4877+ </object>
4878+ <packing>
4879+ <property name="x">299</property>
4880+ <property name="y">5</property>
4881+ </packing>
4882+ </child>
4883+ </object>
4884+ <packing>
4885+ <property name="position">4</property>
4886+ </packing>
4887+ </child>
4888+ <child type="tab">
4889+ <object class="GtkLabel" id="liftOptionsLabel">
4890+ <property name="visible">True</property>
4891+ <property name="label" translatable="yes">Lift Options</property>
4892+ </object>
4893+ <packing>
4894+ <property name="position">4</property>
4895+ <property name="tab_fill">False</property>
4896+ </packing>
4897+ </child>
4898+ </object>
4899+ <packing>
4900+ <property name="y">1</property>
4901+ </packing>
4902+ </child>
4903+ </object>
4904+ </child>
4905+ </object>
4906+ <object class="GtkMessageDialog" id="errorDialog">
4907+ <property name="border_width">5</property>
4908+ <property name="modal">True</property>
4909+ <property name="type_hint">normal</property>
4910+ <property name="skip_taskbar_hint">True</property>
4911+ <property name="message_type">error</property>
4912+ <property name="use_markup">True</property>
4913+ <property name="secondary_use_markup">True</property>
4914+ <child internal-child="vbox">
4915+ <object class="GtkVBox" id="dialog-vbox1">
4916+ <property name="visible">True</property>
4917+ <property name="spacing">2</property>
4918+ <child internal-child="action_area">
4919+ <object class="GtkHButtonBox" id="dialog-action_area1">
4920+ <property name="visible">True</property>
4921+ <property name="layout_style">end</property>
4922+ <child>
4923+ <placeholder/>
4924+ </child>
4925+ <child>
4926+ <object class="GtkButton" id="errorExitButton">
4927+ <property name="label" translatable="yes">Exit</property>
4928+ <property name="visible">True</property>
4929+ <property name="can_focus">True</property>
4930+ <property name="receives_default">True</property>
4931+ <signal name="clicked" handler="messageDialogExit"/>
4932+ </object>
4933+ <packing>
4934+ <property name="expand">False</property>
4935+ <property name="fill">False</property>
4936+ <property name="position">1</property>
4937+ </packing>
4938+ </child>
4939+ </object>
4940+ <packing>
4941+ <property name="expand">False</property>
4942+ <property name="pack_type">end</property>
4943+ <property name="position">0</property>
4944+ </packing>
4945+ </child>
4946+ </object>
4947+ </child>
4948+ <action-widgets>
4949+ <action-widget response="0">errorExitButton</action-widget>
4950+ </action-widgets>
4951+ </object>
4952+ <object class="GtkMessageDialog" id="infoDialog">
4953+ <property name="border_width">5</property>
4954+ <property name="modal">True</property>
4955+ <property name="type_hint">normal</property>
4956+ <property name="skip_taskbar_hint">True</property>
4957+ <child internal-child="vbox">
4958+ <object class="GtkVBox" id="dialog-vbox3">
4959+ <property name="visible">True</property>
4960+ <property name="spacing">2</property>
4961+ <child internal-child="action_area">
4962+ <object class="GtkHButtonBox" id="dialog-action_area3">
4963+ <property name="visible">True</property>
4964+ <property name="layout_style">end</property>
4965+ <child>
4966+ <object class="GtkButton" id="infoDialogOK">
4967+ <property name="label" translatable="yes">OK</property>
4968+ <property name="visible">True</property>
4969+ <property name="can_focus">True</property>
4970+ <property name="receives_default">True</property>
4971+ <signal name="clicked" handler="infoDialogOKSignal"/>
4972+ </object>
4973+ <packing>
4974+ <property name="expand">False</property>
4975+ <property name="fill">False</property>
4976+ <property name="position">0</property>
4977+ </packing>
4978+ </child>
4979+ <child>
4980+ <placeholder/>
4981+ </child>
4982+ </object>
4983+ <packing>
4984+ <property name="expand">False</property>
4985+ <property name="pack_type">end</property>
4986+ <property name="position">0</property>
4987+ </packing>
4988+ </child>
4989+ </object>
4990+ </child>
4991+ <action-widgets>
4992+ <action-widget response="0">infoDialogOK</action-widget>
4993+ </action-widgets>
4994+ </object>
4995+</interface>
4996
4997=== renamed file 'client/python/gui.glade' => 'client/python/gui.glade.moved'
4998=== added file 'client/python/xibo.ico'
4999Binary files client/python/xibo.ico 1970-01-01 00:00:00 +0000 and client/python/xibo.ico 2011-02-28 15:09:00 +0000 differ
5000=== renamed file 'client/python/xibo.ico' => 'client/python/xibo.ico.moved'
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches

to status/vote changes: