~alexharrington/xibo/pyclient-1.1.0a22

« back to all changes in this revision

Viewing changes to client/dotNET/Schedule.cs

  • Committer: Alex Harrington
  • Date: 2009-12-31 11:38:50 UTC
  • Revision ID: alex@longhill.org.uk-20091231113850-bz5flhqq2gsw0qxf
Converted to 2.0 repo format and fixed lineendings

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Xibo - Digitial Signage - http://www.xibo.org.uk
3
 
 * Copyright (C) 2006,2007,2008 Daniel Garner and James Packer
4
 
 *
5
 
 * This file is part of Xibo.
6
 
 *
7
 
 * Xibo is free software: you can redistribute it and/or modify
8
 
 * it under the terms of the GNU Affero General Public License as published by
9
 
 * the Free Software Foundation, either version 3 of the License, or
10
 
 * any later version. 
11
 
 *
12
 
 * Xibo is distributed in the hope that it will be useful,
13
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 
 * GNU Affero General Public License for more details.
16
 
 *
17
 
 * You should have received a copy of the GNU Affero General Public License
18
 
 * along with Xibo.  If not, see <http://www.gnu.org/licenses/>.
19
 
 */
20
 
using System;
21
 
using System.Collections.Generic;
22
 
using System.Collections.ObjectModel;
23
 
using System.Security.Cryptography;
24
 
using System.IO;
25
 
using System.Text;
26
 
using System.Windows.Forms;
27
 
using System.Xml;
28
 
using System.Xml.Serialization;
29
 
using System.Diagnostics;
30
 
 
31
 
namespace XiboClient
32
 
{
33
 
    /// <summary>
34
 
    /// Reads the schedule
35
 
    /// </summary>
36
 
    class Schedule
37
 
    {
38
 
        public delegate void ScheduleChangeDelegate(string layoutPath, int scheduleId, int layoutId);
39
 
        public event ScheduleChangeDelegate ScheduleChangeEvent;
40
 
 
41
 
        private Collection<LayoutSchedule> layoutSchedule;
42
 
        private int currentLayout = 0;
43
 
        private string scheduleLocation;
44
 
 
45
 
        //FileCollector
46
 
        private XiboClient.xmds.xmds xmds2;
47
 
        private bool xmdsProcessing;
48
 
        private bool forceChange = false;
49
 
 
50
 
        // Key
51
 
        private HardwareKey hardwareKey;
52
 
 
53
 
        // Cache Manager
54
 
        private CacheManager _cacheManager;
55
 
 
56
 
        /// <summary>
57
 
        /// Create a schedule
58
 
        /// </summary>
59
 
        /// <param name="scheduleLocation"></param>
60
 
        public Schedule(string scheduleLocation, ref CacheManager cacheManager)
61
 
        {
62
 
            // Save the schedule location
63
 
            this.scheduleLocation = scheduleLocation;
64
 
 
65
 
            // Create a new collection for the layouts in the schedule
66
 
            layoutSchedule = new Collection<LayoutSchedule>();
67
 
            
68
 
            // Set cachemanager
69
 
            _cacheManager = cacheManager;
70
 
 
71
 
            // Create a new Xmds service object
72
 
            xmds2 = new XiboClient.xmds.xmds();
73
 
        }
74
 
 
75
 
        /// <summary>
76
 
        /// Initialize the Schedule components
77
 
        /// </summary>
78
 
        public void InitializeComponents() 
79
 
        {
80
 
            //
81
 
            // Parse and Load the Schedule into the Collection
82
 
            //
83
 
            this.GetSchedule();
84
 
 
85
 
            // Get the key for this display
86
 
            hardwareKey = new HardwareKey();
87
 
 
88
 
            //
89
 
            // Start up the Xmds Service Object
90
 
            //
91
 
            this.xmds2.Credentials = null;
92
 
            this.xmds2.Url = Properties.Settings.Default.XiboClient_xmds_xmds;
93
 
            this.xmds2.UseDefaultCredentials = false;
94
 
 
95
 
            xmdsProcessing = false;
96
 
            xmds2.RequiredFilesCompleted += new XiboClient.xmds.RequiredFilesCompletedEventHandler(xmds2_RequiredFilesCompleted);
97
 
            xmds2.ScheduleCompleted += new XiboClient.xmds.ScheduleCompletedEventHandler(xmds2_ScheduleCompleted);
98
 
 
99
 
            System.Diagnostics.Trace.WriteLine(String.Format("Collection Interval: {0}", Properties.Settings.Default.collectInterval), "Schedule - InitializeComponents");
100
 
            //
101
 
            // The Timer for the Service call
102
 
            //
103
 
            Timer xmdsTimer = new Timer();
104
 
            xmdsTimer.Interval = (int) Properties.Settings.Default.collectInterval * 1000;
105
 
            xmdsTimer.Tick += new EventHandler(xmdsTimer_Tick);
106
 
            xmdsTimer.Start();
107
 
 
108
 
            // Manual first tick
109
 
            xmdsProcessing = true;
110
 
 
111
 
            // Fire off a get required files event - async
112
 
            xmds2.RequiredFilesAsync(Properties.Settings.Default.ServerKey, hardwareKey.Key, Properties.Settings.Default.Version);
113
 
        }
114
 
 
115
 
        void xmds2_RequiredFilesCompleted(object sender, XiboClient.xmds.RequiredFilesCompletedEventArgs e)
116
 
        {
117
 
            System.Diagnostics.Debug.WriteLine("RequiredFilesAsync complete.", "Schedule - RequiredFilesCompleted");
118
 
 
119
 
            //Dont let this effect the rendering
120
 
            Application.DoEvents();
121
 
 
122
 
            if (e.Error != null)
123
 
            {
124
 
                // There was an error - what do we do?
125
 
                System.Diagnostics.Trace.WriteLine(new LogMessage("Schedule - RequiredFilesCompleted", e.Error.Message), LogType.Error.ToString());
126
 
 
127
 
                // Is it a "not licensed" error
128
 
                if (e.Error.Message == "This display client is not licensed")
129
 
                {
130
 
                    Properties.Settings.Default.licensed = 0;
131
 
                }
132
 
 
133
 
                xmdsProcessing = false;
134
 
            }
135
 
            else
136
 
            {
137
 
                // Set the flag to indicate we have a connection to XMDS
138
 
                Properties.Settings.Default.XmdsLastConnection = DateTime.Now;
139
 
 
140
 
                // Firstly we know we are licensed if we get this far
141
 
                if (Properties.Settings.Default.licensed == 0)
142
 
                {
143
 
                    Properties.Settings.Default.licensed = 1;
144
 
                }
145
 
 
146
 
                try
147
 
                {
148
 
                    // Load the result into XML
149
 
                    FileCollector fileCollector = new FileCollector(_cacheManager, e.Result);
150
 
 
151
 
                    // Bind some events that the fileCollector will raise
152
 
                    fileCollector.LayoutFileChanged += new FileCollector.LayoutFileChangedDelegate(fileCollector_LayoutFileChanged);
153
 
                    fileCollector.CollectionComplete += new FileCollector.CollectionCompleteDelegate(fileCollector_CollectionComplete);
154
 
                    fileCollector.MediaFileChanged += new FileCollector.MediaFileChangedDelegate(fileCollector_MediaFileChanged);
155
 
 
156
 
                    fileCollector.CompareAndCollect();
157
 
                }
158
 
                catch (Exception ex)
159
 
                {
160
 
                    xmdsProcessing = false;
161
 
 
162
 
                    // Log and move on
163
 
                    System.Diagnostics.Trace.WriteLine(new LogMessage("Schedule - RequiredFilesCompleted", "Error Comparing and Collecting: " + ex.Message), LogType.Error.ToString());
164
 
                }
165
 
 
166
 
                _cacheManager.WriteCacheManager();
167
 
            }
168
 
        }
169
 
 
170
 
        void fileCollector_MediaFileChanged(string path)
171
 
        {
172
 
            System.Diagnostics.Debug.WriteLine("Media file changed");
173
 
            return;
174
 
        }
175
 
 
176
 
        void fileCollector_CollectionComplete()
177
 
        {
178
 
            System.Diagnostics.Debug.WriteLine("File Collector Complete - getting Schedule.");
179
 
            
180
 
            // All the files have been collected, so we want to update the schedule (do we want to send off a MD5 of the schedule?)
181
 
            xmds2.ScheduleAsync(Properties.Settings.Default.ServerKey, hardwareKey.Key, Properties.Settings.Default.Version);
182
 
        }
183
 
 
184
 
        void xmds2_ScheduleCompleted(object sender, XiboClient.xmds.ScheduleCompletedEventArgs e)
185
 
        {
186
 
            System.Diagnostics.Debug.WriteLine("Schedule Retrival Complete.");
187
 
 
188
 
            // Set XMDS to no longer be processing
189
 
            xmdsProcessing = false;
190
 
 
191
 
            // Expect new schedule XML
192
 
            if (e.Error != null)
193
 
            {
194
 
                //There was an error - what do we do?
195
 
                System.Diagnostics.Trace.WriteLine(e.Error.Message);
196
 
            }
197
 
            else
198
 
            {
199
 
                // Only update the schedule if its changed.
200
 
                String md5CurrentSchedule = "";
201
 
 
202
 
                // Set the flag to indicate we have a connection to XMDS
203
 
                Properties.Settings.Default.XmdsLastConnection = DateTime.Now;
204
 
 
205
 
                try
206
 
                {
207
 
                    StreamReader sr = new StreamReader(File.Open(this.scheduleLocation, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite));
208
 
 
209
 
                    // Yes - get the MD5 of it, and compare to the MD5 of the file in the XML
210
 
                    md5CurrentSchedule = Hashes.MD5(sr.ReadToEnd());
211
 
 
212
 
                    sr.Close();
213
 
                }
214
 
                catch (Exception ex)
215
 
                {
216
 
                    System.Diagnostics.Debug.WriteLine(ex.Message);
217
 
                }
218
 
 
219
 
                // Hash of the result
220
 
                String md5NewSchedule = Hashes.MD5(e.Result);
221
 
 
222
 
                if (md5CurrentSchedule == md5NewSchedule) return;
223
 
 
224
 
                System.Diagnostics.Debug.WriteLine("Different Schedules Detected, writing new schedule.", "Schedule - ScheduleCompleted");
225
 
 
226
 
                // Write the result to the schedule xml location
227
 
                StreamWriter sw = new StreamWriter(this.scheduleLocation, false, Encoding.UTF8);
228
 
                sw.Write(e.Result);
229
 
 
230
 
                sw.Close();
231
 
 
232
 
                System.Diagnostics.Debug.WriteLine("New Schedule Recieved", "xmds_ScheduleCompleted");
233
 
 
234
 
                // The schedule has been updated with new information.
235
 
                // We could improve the logic here, perhaps generating a new layoutSchedule collection and comparing the two before we destroy this one..
236
 
                layoutSchedule.Clear();
237
 
 
238
 
                this.GetSchedule();
239
 
            }
240
 
        }
241
 
 
242
 
        void fileCollector_LayoutFileChanged(string layoutPath)
243
 
        {
244
 
            System.Diagnostics.Debug.WriteLine("Layout file changed");
245
 
 
246
 
            // If the layout that got changed is the current layout, move on
247
 
            try
248
 
            {
249
 
                if (layoutSchedule[currentLayout].layoutFile == Properties.Settings.Default.LibraryPath + @"\" + layoutPath)
250
 
                {
251
 
                    forceChange = true;
252
 
                    NextLayout();
253
 
                }
254
 
            }
255
 
            catch (Exception ex)
256
 
            {
257
 
                System.Diagnostics.Trace.WriteLine(new LogMessage("fileCollector_LayoutFileChanged", String.Format("Unable to determine current layout with exception {0}", ex.Message)), LogType.Error.ToString());
258
 
            }
259
 
        }
260
 
 
261
 
        void xmdsTimer_Tick(object sender, EventArgs e)
262
 
        {
263
 
 
264
 
            // Ticks every "collectInterval"
265
 
            if (xmdsProcessing)
266
 
            {
267
 
                System.Diagnostics.Debug.WriteLine("Collection Timer Ticked, but previous request still active", "XmdsTicker");
268
 
                return;
269
 
            }
270
 
            else
271
 
            {
272
 
                Application.DoEvents(); // Make sure everything that is queued to render does
273
 
 
274
 
                xmdsProcessing = true;
275
 
 
276
 
                System.Diagnostics.Debug.WriteLine("Collection Timer Ticked, Firing RequiredFilesAsync");
277
 
 
278
 
                // Fire off a get required files event - async
279
 
                xmds2.RequiredFilesAsync(Properties.Settings.Default.ServerKey, hardwareKey.Key, Properties.Settings.Default.Version);
280
 
            }
281
 
 
282
 
            // Flush the log
283
 
            System.Diagnostics.Trace.Flush();
284
 
        }
285
 
 
286
 
        /// <summary>
287
 
        /// Moves the layout on
288
 
        /// </summary>
289
 
        public void NextLayout()
290
 
        {
291
 
            int previousLayout = currentLayout;
292
 
 
293
 
            //increment the current layout
294
 
            currentLayout++;
295
 
 
296
 
            //if the current layout is greater than the count of layouts, then reset to 0
297
 
            if (currentLayout >= layoutSchedule.Count)
298
 
            {
299
 
                currentLayout = 0;
300
 
            }
301
 
 
302
 
            if (layoutSchedule.Count == 1 && !forceChange)
303
 
            {
304
 
                Debug.WriteLine(new LogMessage("Schedule - NextLayout", "Only 1 layout showing, refreshing it"), LogType.Info.ToString());
305
 
            }
306
 
 
307
 
            System.Diagnostics.Debug.WriteLine(String.Format("Next layout: {0}", layoutSchedule[currentLayout].layoutFile), "Schedule - Next Layout");
308
 
 
309
 
            forceChange = false;
310
 
 
311
 
            //Raise the event
312
 
            ScheduleChangeEvent(layoutSchedule[currentLayout].layoutFile, layoutSchedule[currentLayout].scheduleid, layoutSchedule[currentLayout].id);
313
 
        }
314
 
 
315
 
        /// <summary>
316
 
        /// Gets the schedule from the schedule location
317
 
        /// If the schedule location doesn't exist - use the default.xml (how to we guarentee that the default.xml exists?)
318
 
        /// If layouts in the schedule file dont exist, then ignore them - if none of them exist then add a default one?
319
 
        /// </summary>
320
 
        void GetSchedule()
321
 
        {
322
 
            XmlDocument scheduleXml;
323
 
 
324
 
            // Check the schedule file exists
325
 
            if (File.Exists(scheduleLocation))
326
 
            {
327
 
                // Read the schedule file
328
 
                XmlReader reader = XmlReader.Create(scheduleLocation);
329
 
 
330
 
                scheduleXml = new XmlDocument();
331
 
                scheduleXml.Load(reader);
332
 
 
333
 
                reader.Close();
334
 
            }
335
 
            else
336
 
            {
337
 
                // Use the default XML
338
 
                scheduleXml = new XmlDocument();
339
 
                scheduleXml.LoadXml("<schedule></schedule>");
340
 
            }
341
 
 
342
 
            // Get the layouts in this schedule
343
 
            XmlNodeList listLayouts = scheduleXml.SelectNodes("/schedule/layout");
344
 
 
345
 
            // Have we got some?
346
 
            if (listLayouts.Count == 0)
347
 
            {
348
 
                // Schedule up the default
349
 
                LayoutSchedule temp = new LayoutSchedule();
350
 
                temp.layoutFile = Properties.Settings.Default.LibraryPath + @"\Default.xml";
351
 
                temp.id = 0;
352
 
                temp.scheduleid = 0;
353
 
 
354
 
                layoutSchedule.Add(temp);
355
 
            }
356
 
            else
357
 
            {
358
 
                // Get them and add to collection
359
 
                foreach (XmlNode layout in listLayouts)
360
 
                {
361
 
                    XmlAttributeCollection attributes = layout.Attributes;
362
 
 
363
 
                    string layoutFile = attributes["file"].Value;
364
 
                    string replace = ".xml";
365
 
                    layoutFile = layoutFile.TrimEnd(replace.ToCharArray());
366
 
                    
367
 
                    string scheduleId = "";
368
 
                    if (attributes["scheduleid"] != null) scheduleId = attributes["scheduleid"].Value;
369
 
 
370
 
                    LayoutSchedule temp = new LayoutSchedule();
371
 
                    temp.layoutFile = Properties.Settings.Default.LibraryPath + @"\" + layoutFile + @".xlf";
372
 
                    temp.id = int.Parse(layoutFile);
373
 
                    
374
 
                    if (scheduleId != "") temp.scheduleid = int.Parse(scheduleId);
375
 
 
376
 
                    layoutSchedule.Add(temp);
377
 
                }
378
 
            }
379
 
 
380
 
            //clean up
381
 
            listLayouts = null;
382
 
            scheduleXml = null;
383
 
 
384
 
            //raise an event
385
 
            ScheduleChangeEvent(layoutSchedule[0].layoutFile, layoutSchedule[0].scheduleid, layoutSchedule[0].id);
386
 
 
387
 
        }
388
 
 
389
 
        /// <summary>
390
 
        /// The number of active layouts in the current schedule
391
 
        /// </summary>
392
 
        public int ActiveLayouts
393
 
        {
394
 
            get
395
 
            {
396
 
                return layoutSchedule.Count;
397
 
            }
398
 
        }
399
 
 
400
 
        /// <summary>
401
 
        /// A LayoutSchedule
402
 
        /// </summary>
403
 
        [Serializable]
404
 
        public struct LayoutSchedule
405
 
        {
406
 
            public string layoutFile;
407
 
            public int id;
408
 
            public int scheduleid;
409
 
        }
410
 
    }
411
 
}
 
1
/*
 
2
 * Xibo - Digitial Signage - http://www.xibo.org.uk
 
3
 * Copyright (C) 2006,2007,2008 Daniel Garner and James Packer
 
4
 *
 
5
 * This file is part of Xibo.
 
6
 *
 
7
 * Xibo is free software: you can redistribute it and/or modify
 
8
 * it under the terms of the GNU Affero General Public License as published by
 
9
 * the Free Software Foundation, either version 3 of the License, or
 
10
 * any later version. 
 
11
 *
 
12
 * Xibo is distributed in the hope that it will be useful,
 
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
 * GNU Affero General Public License for more details.
 
16
 *
 
17
 * You should have received a copy of the GNU Affero General Public License
 
18
 * along with Xibo.  If not, see <http://www.gnu.org/licenses/>.
 
19
 */
 
20
using System;
 
21
using System.Collections.Generic;
 
22
using System.Collections.ObjectModel;
 
23
using System.Security.Cryptography;
 
24
using System.IO;
 
25
using System.Text;
 
26
using System.Windows.Forms;
 
27
using System.Xml;
 
28
using System.Xml.Serialization;
 
29
using System.Diagnostics;
 
30
 
 
31
namespace XiboClient
 
32
{
 
33
    /// <summary>
 
34
    /// Reads the schedule
 
35
    /// </summary>
 
36
    class Schedule
 
37
    {
 
38
        public delegate void ScheduleChangeDelegate(string layoutPath, int scheduleId, int layoutId);
 
39
        public event ScheduleChangeDelegate ScheduleChangeEvent;
 
40
 
 
41
        private Collection<LayoutSchedule> layoutSchedule;
 
42
        private int currentLayout = 0;
 
43
        private string scheduleLocation;
 
44
 
 
45
        //FileCollector
 
46
        private XiboClient.xmds.xmds xmds2;
 
47
        private bool xmdsProcessing;
 
48
        private bool forceChange = false;
 
49
 
 
50
        // Key
 
51
        private HardwareKey hardwareKey;
 
52
 
 
53
        // Cache Manager
 
54
        private CacheManager _cacheManager;
 
55
 
 
56
        /// <summary>
 
57
        /// Create a schedule
 
58
        /// </summary>
 
59
        /// <param name="scheduleLocation"></param>
 
60
        public Schedule(string scheduleLocation, ref CacheManager cacheManager)
 
61
        {
 
62
            // Save the schedule location
 
63
            this.scheduleLocation = scheduleLocation;
 
64
 
 
65
            // Create a new collection for the layouts in the schedule
 
66
            layoutSchedule = new Collection<LayoutSchedule>();
 
67
            
 
68
            // Set cachemanager
 
69
            _cacheManager = cacheManager;
 
70
 
 
71
            // Create a new Xmds service object
 
72
            xmds2 = new XiboClient.xmds.xmds();
 
73
        }
 
74
 
 
75
        /// <summary>
 
76
        /// Initialize the Schedule components
 
77
        /// </summary>
 
78
        public void InitializeComponents() 
 
79
        {
 
80
            //
 
81
            // Parse and Load the Schedule into the Collection
 
82
            //
 
83
            this.GetSchedule();
 
84
 
 
85
            // Get the key for this display
 
86
            hardwareKey = new HardwareKey();
 
87
 
 
88
            //
 
89
            // Start up the Xmds Service Object
 
90
            //
 
91
            this.xmds2.Credentials = null;
 
92
            this.xmds2.Url = Properties.Settings.Default.XiboClient_xmds_xmds;
 
93
            this.xmds2.UseDefaultCredentials = false;
 
94
 
 
95
            xmdsProcessing = false;
 
96
            xmds2.RequiredFilesCompleted += new XiboClient.xmds.RequiredFilesCompletedEventHandler(xmds2_RequiredFilesCompleted);
 
97
            xmds2.ScheduleCompleted += new XiboClient.xmds.ScheduleCompletedEventHandler(xmds2_ScheduleCompleted);
 
98
 
 
99
            System.Diagnostics.Trace.WriteLine(String.Format("Collection Interval: {0}", Properties.Settings.Default.collectInterval), "Schedule - InitializeComponents");
 
100
            //
 
101
            // The Timer for the Service call
 
102
            //
 
103
            Timer xmdsTimer = new Timer();
 
104
            xmdsTimer.Interval = (int) Properties.Settings.Default.collectInterval * 1000;
 
105
            xmdsTimer.Tick += new EventHandler(xmdsTimer_Tick);
 
106
            xmdsTimer.Start();
 
107
 
 
108
            // Manual first tick
 
109
            xmdsProcessing = true;
 
110
 
 
111
            // Fire off a get required files event - async
 
112
            xmds2.RequiredFilesAsync(Properties.Settings.Default.ServerKey, hardwareKey.Key, Properties.Settings.Default.Version);
 
113
        }
 
114
 
 
115
        void xmds2_RequiredFilesCompleted(object sender, XiboClient.xmds.RequiredFilesCompletedEventArgs e)
 
116
        {
 
117
            System.Diagnostics.Debug.WriteLine("RequiredFilesAsync complete.", "Schedule - RequiredFilesCompleted");
 
118
 
 
119
            //Dont let this effect the rendering
 
120
            Application.DoEvents();
 
121
 
 
122
            if (e.Error != null)
 
123
            {
 
124
                // There was an error - what do we do?
 
125
                System.Diagnostics.Trace.WriteLine(new LogMessage("Schedule - RequiredFilesCompleted", e.Error.Message), LogType.Error.ToString());
 
126
 
 
127
                // Is it a "not licensed" error
 
128
                if (e.Error.Message == "This display client is not licensed")
 
129
                {
 
130
                    Properties.Settings.Default.licensed = 0;
 
131
                }
 
132
 
 
133
                xmdsProcessing = false;
 
134
            }
 
135
            else
 
136
            {
 
137
                // Set the flag to indicate we have a connection to XMDS
 
138
                Properties.Settings.Default.XmdsLastConnection = DateTime.Now;
 
139
 
 
140
                // Firstly we know we are licensed if we get this far
 
141
                if (Properties.Settings.Default.licensed == 0)
 
142
                {
 
143
                    Properties.Settings.Default.licensed = 1;
 
144
                }
 
145
 
 
146
                try
 
147
                {
 
148
                    // Load the result into XML
 
149
                    FileCollector fileCollector = new FileCollector(_cacheManager, e.Result);
 
150
 
 
151
                    // Bind some events that the fileCollector will raise
 
152
                    fileCollector.LayoutFileChanged += new FileCollector.LayoutFileChangedDelegate(fileCollector_LayoutFileChanged);
 
153
                    fileCollector.CollectionComplete += new FileCollector.CollectionCompleteDelegate(fileCollector_CollectionComplete);
 
154
                    fileCollector.MediaFileChanged += new FileCollector.MediaFileChangedDelegate(fileCollector_MediaFileChanged);
 
155
 
 
156
                    fileCollector.CompareAndCollect();
 
157
                }
 
158
                catch (Exception ex)
 
159
                {
 
160
                    xmdsProcessing = false;
 
161
 
 
162
                    // Log and move on
 
163
                    System.Diagnostics.Trace.WriteLine(new LogMessage("Schedule - RequiredFilesCompleted", "Error Comparing and Collecting: " + ex.Message), LogType.Error.ToString());
 
164
                }
 
165
 
 
166
                _cacheManager.WriteCacheManager();
 
167
            }
 
168
        }
 
169
 
 
170
        void fileCollector_MediaFileChanged(string path)
 
171
        {
 
172
            System.Diagnostics.Debug.WriteLine("Media file changed");
 
173
            return;
 
174
        }
 
175
 
 
176
        void fileCollector_CollectionComplete()
 
177
        {
 
178
            System.Diagnostics.Debug.WriteLine("File Collector Complete - getting Schedule.");
 
179
            
 
180
            // All the files have been collected, so we want to update the schedule (do we want to send off a MD5 of the schedule?)
 
181
            xmds2.ScheduleAsync(Properties.Settings.Default.ServerKey, hardwareKey.Key, Properties.Settings.Default.Version);
 
182
        }
 
183
 
 
184
        void xmds2_ScheduleCompleted(object sender, XiboClient.xmds.ScheduleCompletedEventArgs e)
 
185
        {
 
186
            System.Diagnostics.Debug.WriteLine("Schedule Retrival Complete.");
 
187
 
 
188
            // Set XMDS to no longer be processing
 
189
            xmdsProcessing = false;
 
190
 
 
191
            // Expect new schedule XML
 
192
            if (e.Error != null)
 
193
            {
 
194
                //There was an error - what do we do?
 
195
                System.Diagnostics.Trace.WriteLine(e.Error.Message);
 
196
            }
 
197
            else
 
198
            {
 
199
                // Only update the schedule if its changed.
 
200
                String md5CurrentSchedule = "";
 
201
 
 
202
                // Set the flag to indicate we have a connection to XMDS
 
203
                Properties.Settings.Default.XmdsLastConnection = DateTime.Now;
 
204
 
 
205
                try
 
206
                {
 
207
                    StreamReader sr = new StreamReader(File.Open(this.scheduleLocation, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite));
 
208
 
 
209
                    // Yes - get the MD5 of it, and compare to the MD5 of the file in the XML
 
210
                    md5CurrentSchedule = Hashes.MD5(sr.ReadToEnd());
 
211
 
 
212
                    sr.Close();
 
213
                }
 
214
                catch (Exception ex)
 
215
                {
 
216
                    System.Diagnostics.Debug.WriteLine(ex.Message);
 
217
                }
 
218
 
 
219
                // Hash of the result
 
220
                String md5NewSchedule = Hashes.MD5(e.Result);
 
221
 
 
222
                if (md5CurrentSchedule == md5NewSchedule) return;
 
223
 
 
224
                System.Diagnostics.Debug.WriteLine("Different Schedules Detected, writing new schedule.", "Schedule - ScheduleCompleted");
 
225
 
 
226
                // Write the result to the schedule xml location
 
227
                StreamWriter sw = new StreamWriter(this.scheduleLocation, false, Encoding.UTF8);
 
228
                sw.Write(e.Result);
 
229
 
 
230
                sw.Close();
 
231
 
 
232
                System.Diagnostics.Debug.WriteLine("New Schedule Recieved", "xmds_ScheduleCompleted");
 
233
 
 
234
                // The schedule has been updated with new information.
 
235
                // We could improve the logic here, perhaps generating a new layoutSchedule collection and comparing the two before we destroy this one..
 
236
                layoutSchedule.Clear();
 
237
 
 
238
                this.GetSchedule();
 
239
            }
 
240
        }
 
241
 
 
242
        void fileCollector_LayoutFileChanged(string layoutPath)
 
243
        {
 
244
            System.Diagnostics.Debug.WriteLine("Layout file changed");
 
245
 
 
246
            // If the layout that got changed is the current layout, move on
 
247
            try
 
248
            {
 
249
                if (layoutSchedule[currentLayout].layoutFile == Properties.Settings.Default.LibraryPath + @"\" + layoutPath)
 
250
                {
 
251
                    forceChange = true;
 
252
                    NextLayout();
 
253
                }
 
254
            }
 
255
            catch (Exception ex)
 
256
            {
 
257
                System.Diagnostics.Trace.WriteLine(new LogMessage("fileCollector_LayoutFileChanged", String.Format("Unable to determine current layout with exception {0}", ex.Message)), LogType.Error.ToString());
 
258
            }
 
259
        }
 
260
 
 
261
        void xmdsTimer_Tick(object sender, EventArgs e)
 
262
        {
 
263
 
 
264
            // Ticks every "collectInterval"
 
265
            if (xmdsProcessing)
 
266
            {
 
267
                System.Diagnostics.Debug.WriteLine("Collection Timer Ticked, but previous request still active", "XmdsTicker");
 
268
                return;
 
269
            }
 
270
            else
 
271
            {
 
272
                Application.DoEvents(); // Make sure everything that is queued to render does
 
273
 
 
274
                xmdsProcessing = true;
 
275
 
 
276
                System.Diagnostics.Debug.WriteLine("Collection Timer Ticked, Firing RequiredFilesAsync");
 
277
 
 
278
                // Fire off a get required files event - async
 
279
                xmds2.RequiredFilesAsync(Properties.Settings.Default.ServerKey, hardwareKey.Key, Properties.Settings.Default.Version);
 
280
            }
 
281
 
 
282
            // Flush the log
 
283
            System.Diagnostics.Trace.Flush();
 
284
        }
 
285
 
 
286
        /// <summary>
 
287
        /// Moves the layout on
 
288
        /// </summary>
 
289
        public void NextLayout()
 
290
        {
 
291
            int previousLayout = currentLayout;
 
292
 
 
293
            //increment the current layout
 
294
            currentLayout++;
 
295
 
 
296
            //if the current layout is greater than the count of layouts, then reset to 0
 
297
            if (currentLayout >= layoutSchedule.Count)
 
298
            {
 
299
                currentLayout = 0;
 
300
            }
 
301
 
 
302
            if (layoutSchedule.Count == 1 && !forceChange)
 
303
            {
 
304
                Debug.WriteLine(new LogMessage("Schedule - NextLayout", "Only 1 layout showing, refreshing it"), LogType.Info.ToString());
 
305
            }
 
306
 
 
307
            System.Diagnostics.Debug.WriteLine(String.Format("Next layout: {0}", layoutSchedule[currentLayout].layoutFile), "Schedule - Next Layout");
 
308
 
 
309
            forceChange = false;
 
310
 
 
311
            //Raise the event
 
312
            ScheduleChangeEvent(layoutSchedule[currentLayout].layoutFile, layoutSchedule[currentLayout].scheduleid, layoutSchedule[currentLayout].id);
 
313
        }
 
314
 
 
315
        /// <summary>
 
316
        /// Gets the schedule from the schedule location
 
317
        /// If the schedule location doesn't exist - use the default.xml (how to we guarentee that the default.xml exists?)
 
318
        /// If layouts in the schedule file dont exist, then ignore them - if none of them exist then add a default one?
 
319
        /// </summary>
 
320
        void GetSchedule()
 
321
        {
 
322
            XmlDocument scheduleXml;
 
323
 
 
324
            // Check the schedule file exists
 
325
            if (File.Exists(scheduleLocation))
 
326
            {
 
327
                // Read the schedule file
 
328
                XmlReader reader = XmlReader.Create(scheduleLocation);
 
329
 
 
330
                scheduleXml = new XmlDocument();
 
331
                scheduleXml.Load(reader);
 
332
 
 
333
                reader.Close();
 
334
            }
 
335
            else
 
336
            {
 
337
                // Use the default XML
 
338
                scheduleXml = new XmlDocument();
 
339
                scheduleXml.LoadXml("<schedule></schedule>");
 
340
            }
 
341
 
 
342
            // Get the layouts in this schedule
 
343
            XmlNodeList listLayouts = scheduleXml.SelectNodes("/schedule/layout");
 
344
 
 
345
            // Have we got some?
 
346
            if (listLayouts.Count == 0)
 
347
            {
 
348
                // Schedule up the default
 
349
                LayoutSchedule temp = new LayoutSchedule();
 
350
                temp.layoutFile = Properties.Settings.Default.LibraryPath + @"\Default.xml";
 
351
                temp.id = 0;
 
352
                temp.scheduleid = 0;
 
353
 
 
354
                layoutSchedule.Add(temp);
 
355
            }
 
356
            else
 
357
            {
 
358
                // Get them and add to collection
 
359
                foreach (XmlNode layout in listLayouts)
 
360
                {
 
361
                    XmlAttributeCollection attributes = layout.Attributes;
 
362
 
 
363
                    string layoutFile = attributes["file"].Value;
 
364
                    string replace = ".xml";
 
365
                    layoutFile = layoutFile.TrimEnd(replace.ToCharArray());
 
366
                    
 
367
                    string scheduleId = "";
 
368
                    if (attributes["scheduleid"] != null) scheduleId = attributes["scheduleid"].Value;
 
369
 
 
370
                    LayoutSchedule temp = new LayoutSchedule();
 
371
                    temp.layoutFile = Properties.Settings.Default.LibraryPath + @"\" + layoutFile + @".xlf";
 
372
                    temp.id = int.Parse(layoutFile);
 
373
                    
 
374
                    if (scheduleId != "") temp.scheduleid = int.Parse(scheduleId);
 
375
 
 
376
                    layoutSchedule.Add(temp);
 
377
                }
 
378
            }
 
379
 
 
380
            //clean up
 
381
            listLayouts = null;
 
382
            scheduleXml = null;
 
383
 
 
384
            //raise an event
 
385
            ScheduleChangeEvent(layoutSchedule[0].layoutFile, layoutSchedule[0].scheduleid, layoutSchedule[0].id);
 
386
 
 
387
        }
 
388
 
 
389
        /// <summary>
 
390
        /// The number of active layouts in the current schedule
 
391
        /// </summary>
 
392
        public int ActiveLayouts
 
393
        {
 
394
            get
 
395
            {
 
396
                return layoutSchedule.Count;
 
397
            }
 
398
        }
 
399
 
 
400
        /// <summary>
 
401
        /// A LayoutSchedule
 
402
        /// </summary>
 
403
        [Serializable]
 
404
        public struct LayoutSchedule
 
405
        {
 
406
            public string layoutFile;
 
407
            public int id;
 
408
            public int scheduleid;
 
409
        }
 
410
    }
 
411
}