source: other-projects/playing-in-the-street/summer-2013/trunk/Playing-in-the-Street-WPF/MainWindow.xaml.cs@ 30123

Last change on this file since 30123 was 30123, checked in by davidb, 9 years ago

Refactoring to use better playing-in-the-street (PITS) 'branding'

File size: 11.0 KB
Line 
1//------------------------------------------------------------------------------
2// <copyright file="MainWindow.xaml.cs" company="Microsoft">
3// Copyright (c) Microsoft Corporation. All rights reserved.
4// </copyright>
5//------------------------------------------------------------------------------
6
7namespace Microsoft.Samples.Kinect.WebserverBasics
8{
9 using System;
10 using System.Diagnostics;
11 using System.Diagnostics.CodeAnalysis;
12 using System.IO;
13 using System.Windows;
14
15 using Microsoft.Kinect.Toolkit;
16 using Microsoft.Samples.Kinect.Webserver;
17
18 /// <summary>
19 /// Interaction logic for MainWindow.
20 /// </summary>
21 public partial class MainWindow : Window
22 {
23 public static readonly DependencyProperty IsStartedProperty = DependencyProperty.Register(
24 "IsStarted", typeof(bool), typeof(MainWindow), new PropertyMetadata(false));
25
26 public static readonly DependencyProperty ErrorTextProperty = DependencyProperty.Register(
27 "ErrorText", typeof(string), typeof(MainWindow), new PropertyMetadata(string.Empty));
28
29 /// <summary>
30 /// Name (URI sub-path) to be used by clients to refer to the default kinect sensor.
31 /// </summary>
32 private const string DefaultSensorChooserName = "default";
33
34 /// <summary>
35 /// Name of main page for web sample.
36 /// </summary>
37 private const string SamplePageName = "playing-in-the-street.html";
38
39 /// <summary>
40 /// Character used to separate origins in list of origins allowed to access this server.
41 /// </summary>
42 private const char AllowedOriginSeparator = ',';
43
44 /// <summary>
45 /// Component that manages finding a Kinect sensor
46 /// </summary>
47 private readonly KinectSensorChooser sensorChooser = new KinectSensorChooser();
48
49 /// <summary>
50 /// Webserver that handles requests from web clients.
51 /// </summary>
52 private readonly KinectWebserver webserver = new KinectWebserver();
53
54 /// <summary>
55 /// Error buffer listener used to update error text in UI.
56 /// </summary>
57 private readonly RecentEventBufferTraceListener errorBufferListener;
58
59 /// <summary>
60 /// Initializes a new instance of the MainWindow class.
61 /// </summary>
62 public MainWindow()
63 {
64 this.InitializeComponent();
65
66 if (!IsSupportedOsVersion(Environment.OSVersion))
67 {
68 MessageBox.Show(
69 Properties.Resources.SystemVersionNotSupportedMessage,
70 Properties.Resources.SystemVersionNotSupportedCaption,
71 MessageBoxButton.OK);
72 Application.Current.Shutdown();
73 }
74
75 this.DataContext = this;
76
77 this.errorBufferListener = Trace.Listeners["errorBufferListener"] as RecentEventBufferTraceListener;
78 if (this.errorBufferListener != null)
79 {
80 this.errorBufferListener.RecentEventBufferChanged += this.ErrorBufferListenerOnChanged;
81 }
82
83 Uri originUri;
84 try
85 {
86 originUri = new Uri(Properties.Settings.Default.OriginUri.Trim());
87 }
88 catch (UriFormatException)
89 {
90 Trace.TraceError("Invalid format for listening origin: \"{0}\"", Properties.Settings.Default.OriginUri);
91
92 // If we can't listen on origin, we can't serve any data whatsover, so there is no sense in continuing
93 // setup
94 return;
95 }
96
97 this.webserver.SensorChooserMap.Add(DefaultSensorChooserName, this.sensorChooser);
98 if (!string.IsNullOrWhiteSpace(Properties.Settings.Default.FileRootDirectory))
99 {
100 this.webserver.FileServerRootDirectory = Properties.Settings.Default.FileRootDirectory;
101
102 try
103 {
104 this.RootDirectoryTextRun.Text = Path.GetFullPath(Properties.Settings.Default.FileRootDirectory);
105 }
106 catch (ArgumentException e)
107 {
108 this.ShowNotServingFilesUi();
109 Trace.TraceError("Exception encountered while parsing root directory for serving files:\n{0}", e);
110 }
111 }
112 else
113 {
114 this.ShowNotServingFilesUi();
115 }
116
117 this.webserver.OriginUri = originUri;
118 if (!string.IsNullOrWhiteSpace(Properties.Settings.Default.AccessControlAllowedOrigins))
119 {
120 foreach (var origin in Properties.Settings.Default.AccessControlAllowedOrigins.Split(AllowedOriginSeparator))
121 {
122 try
123 {
124 originUri = new Uri(origin.Trim());
125 }
126 catch (UriFormatException)
127 {
128 Trace.TraceError("Invalid format for access control allowed origin: {0}", origin);
129 continue;
130 }
131
132 this.webserver.AccessControlAllowedOrigins.Add(originUri);
133 }
134 }
135
136 //// TODO: Optionally add factories here for custom handlers:
137 //// this.webserver.SensorStreamHandlerFactories.Add(new MyCustomSensorStreamHandlerFactory());
138 //// Your custom factory would implement ISensorStreamHandlerFactory, in which the
139 //// CreateHandler method would return a class derived from SensorStreamHandlerBase
140 //// which overrides one or more of its virtual methods.
141
142 this.webserver.Started += (server, args) => this.IsStarted = true;
143 this.webserver.Stopped += (server, args) => this.IsStarted = false;
144 }
145
146 /// <summary>
147 /// Gets the KinectSensorChooser component
148 /// </summary>
149 public KinectSensorChooser KinectSensorChooser
150 {
151 get { return this.sensorChooser; }
152 }
153
154 /// <summary>
155 /// true if server has started listening, false otherwise.
156 /// </summary>
157 public bool IsStarted
158 {
159 get
160 {
161 return (bool)this.GetValue(IsStartedProperty);
162 }
163
164 set
165 {
166 this.SetValue(IsStartedProperty, value);
167 }
168 }
169
170 /// <summary>
171 /// Error text to display in UI.
172 /// </summary>
173 public string ErrorText
174 {
175 get
176 {
177 return (string)this.GetValue(ErrorTextProperty);
178 }
179
180 set
181 {
182 this.SetValue(ErrorTextProperty, value);
183 }
184 }
185
186 /// <summary>
187 /// Determine if running this application is supported in the specified operating
188 /// system version.
189 /// </summary>
190 /// <param name="systemInfo">
191 /// Operating system version information.
192 /// </param>
193 /// <returns>
194 /// true if running this application is supported in the specified operating system.
195 /// false otherwise.
196 /// </returns>
197 private static bool IsSupportedOsVersion(OperatingSystem systemInfo)
198 {
199 const int MinimumMajorVersion = 6;
200 const int MinimumMinorVersion = 2;
201
202 return (systemInfo.Version.Major > MinimumMajorVersion)
203 || ((systemInfo.Version.Major == MinimumMajorVersion) && (systemInfo.Version.Minor >= MinimumMinorVersion));
204 }
205
206 /// <summary>
207 /// Start web server, reporting an error to trace listeners if exception is encountered.
208 /// </summary>
209 [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Server application should never crash. Errors are reported in web server UI instead.")]
210 private void StartWebserver()
211 {
212 try
213 {
214 this.webserver.Start();
215 }
216 catch (Exception e)
217 {
218 Trace.TraceError("Unable to start server due to exception:\n{0}", e);
219 }
220 }
221
222 /// <summary>
223 /// Stop web server, reporting an error to trace listeners if exception is encountered.
224 /// </summary>
225 [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Server application should never crash. Errors are reported in web server UI instead.")]
226 private void StopWebserver()
227 {
228 try
229 {
230 this.webserver.Stop();
231 }
232 catch (Exception e)
233 {
234 Trace.TraceError("Unable to stop server due to exception:\n{0}", e);
235 }
236 }
237
238 /// <summary>
239 /// Show UI appropriate for when we're not serving static files.
240 /// </summary>
241 private void ShowNotServingFilesUi()
242 {
243 this.ServingFilesText.Visibility = Visibility.Collapsed;
244 this.OpenBrowserText.Visibility = Visibility.Collapsed;
245 this.NotServingFilesText.Visibility = Visibility.Visible;
246 }
247
248 private void WindowLoaded(object sender, RoutedEventArgs e)
249 {
250 this.sensorChooser.Start();
251
252 this.StartWebserver();
253 }
254
255 private void WindowClosing(object sender, System.ComponentModel.CancelEventArgs e)
256 {
257 this.StopWebserver();
258 }
259
260 private void StartButtonOnClick(object sender, RoutedEventArgs e)
261 {
262 this.StartWebserver();
263 }
264
265 private void StopButtonOnClick(object sender, RoutedEventArgs e)
266 {
267 this.StopWebserver();
268 }
269
270 private void ErrorBufferListenerOnChanged(object sender, EventArgs e)
271 {
272 this.Dispatcher.BeginInvoke((Action)(() => this.ErrorText = this.errorBufferListener.RecentEventBuffer));
273 }
274
275 /// <summary>
276 /// Event handler for UriLink's Click event.
277 /// </summary>
278 /// <param name="sender">
279 /// Object triggering the event.
280 /// </param>
281 /// <param name="e">
282 /// Event arguments.
283 /// </param>
284 private void UriLinkOnClick(object sender, RoutedEventArgs e)
285 {
286 // Shell execute the URI of sample page to open in default browser
287 var samplePageUri = this.webserver.OriginUri.ConcatenateSegments(this.webserver.FileServerBasePath, SamplePageName);
288
289 if (samplePageUri == null)
290 {
291 return;
292 }
293
294 var startInfo = new ProcessStartInfo(samplePageUri.ToString()) { UseShellExecute = true };
295 using (var process = new Process())
296 {
297 process.StartInfo = startInfo;
298 process.Start();
299 }
300 }
301 }
302}
Note: See TracBrowser for help on using the repository browser.