Server/MainForm.cs
author StephaneLenclud
Thu, 21 Jan 2016 15:00:05 +0100
changeset 178 9eb93d079a3e
parent 177 c24dc0c6b64b
child 179 533eb8a80d56
permissions -rw-r--r--
Simplify GetIcon function.
StephaneLenclud@123
     1
´╗┐//
StephaneLenclud@123
     2
// Copyright (C) 2014-2015 St├ęphane Lenclud.
StephaneLenclud@123
     3
//
StephaneLenclud@123
     4
// This file is part of SharpDisplayManager.
StephaneLenclud@123
     5
//
StephaneLenclud@123
     6
// SharpDisplayManager is free software: you can redistribute it and/or modify
StephaneLenclud@123
     7
// it under the terms of the GNU General Public License as published by
StephaneLenclud@123
     8
// the Free Software Foundation, either version 3 of the License, or
StephaneLenclud@123
     9
// (at your option) any later version.
StephaneLenclud@123
    10
//
StephaneLenclud@123
    11
// SharpDisplayManager is distributed in the hope that it will be useful,
StephaneLenclud@123
    12
// but WITHOUT ANY WARRANTY; without even the implied warranty of
StephaneLenclud@123
    13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
StephaneLenclud@123
    14
// GNU General Public License for more details.
StephaneLenclud@123
    15
//
StephaneLenclud@123
    16
// You should have received a copy of the GNU General Public License
StephaneLenclud@123
    17
// along with SharpDisplayManager.  If not, see <http://www.gnu.org/licenses/>.
StephaneLenclud@123
    18
//
StephaneLenclud@123
    19
StephaneLenclud@123
    20
using System;
sl@0
    21
using System.Collections.Generic;
sl@0
    22
using System.ComponentModel;
sl@0
    23
using System.Data;
sl@0
    24
using System.Drawing;
sl@0
    25
using System.Linq;
sl@0
    26
using System.Text;
sl@0
    27
using System.Threading.Tasks;
sl@0
    28
using System.Windows.Forms;
sl@14
    29
using System.IO;
sl@0
    30
using CodeProject.Dialog;
sl@14
    31
using System.Drawing.Imaging;
sl@17
    32
using System.ServiceModel;
sl@25
    33
using System.Threading;
sl@31
    34
using System.Diagnostics;
sl@88
    35
using System.Deployment.Application;
sl@94
    36
using System.Reflection;
StephaneLenclud@112
    37
//NAudio
StephaneLenclud@112
    38
using NAudio.CoreAudioApi;
StephaneLenclud@112
    39
using NAudio.CoreAudioApi.Interfaces;
StephaneLenclud@112
    40
using System.Runtime.InteropServices;
StephaneLenclud@117
    41
//Network
StephaneLenclud@117
    42
using NETWORKLIST;
sl@25
    43
//
sl@25
    44
using SharpDisplayClient;
sl@55
    45
using SharpDisplay;
StephaneLenclud@135
    46
using MiniDisplayInterop;
StephaneLenclud@171
    47
using SharpLib.Display;
StephaneLenclud@124
    48
sl@0
    49
namespace SharpDisplayManager
sl@0
    50
{
sl@58
    51
    //Types declarations
sl@58
    52
    public delegate uint ColorProcessingDelegate(int aX, int aY, uint aPixel);
sl@58
    53
    public delegate int CoordinateTranslationDelegate(System.Drawing.Bitmap aBmp, int aInt);
sl@62
    54
    //Delegates are used for our thread safe method
sl@62
    55
    public delegate void AddClientDelegate(string aSessionId, ICallback aCallback);
sl@62
    56
    public delegate void RemoveClientDelegate(string aSessionId);
sl@79
    57
    public delegate void SetFieldDelegate(string SessionId, DataField aField);
sl@79
    58
    public delegate void SetFieldsDelegate(string SessionId, System.Collections.Generic.IList<DataField> aFields);
sl@62
    59
    public delegate void SetLayoutDelegate(string SessionId, TableLayout aLayout);
sl@62
    60
    public delegate void SetClientNameDelegate(string aSessionId, string aName);
StephaneLenclud@112
    61
	public delegate void PlainUpdateDelegate();
StephaneLenclud@167
    62
    public delegate void WndProcDelegate(ref Message aMessage);
sl@58
    63
sl@58
    64
    /// <summary>
sl@58
    65
    /// Our Display manager main form
sl@58
    66
    /// </summary>
StephaneLenclud@126
    67
	[System.ComponentModel.DesignerCategory("Form")]
StephaneLenclud@126
    68
	public partial class MainForm : MainFormHid, IMMNotificationClient
sl@0
    69
    {
sl@2
    70
        DateTime LastTickTime;
sl@3
    71
        Display iDisplay;
sl@14
    72
        System.Drawing.Bitmap iBmp;
sl@14
    73
        bool iCreateBitmap; //Workaround render to bitmap issues when minimized
sl@17
    74
        ServiceHost iServiceHost;
sl@65
    75
        // Our collection of clients sorted by session id.
sl@33
    76
        public Dictionary<string, ClientData> iClients;
sl@65
    77
        // The name of the client which informations are currently displayed.
sl@65
    78
        public string iCurrentClientSessionId;
sl@65
    79
        ClientData iCurrentClientData;
sl@65
    80
        //
sl@29
    81
        public bool iClosing;
StephaneLenclud@122
    82
		//
StephaneLenclud@122
    83
		public bool iSkipFrameRendering;
sl@65
    84
        //Function pointer for pixel color filtering
sl@58
    85
        ColorProcessingDelegate iColorFx;
sl@65
    86
        //Function pointer for pixel X coordinate intercept
sl@58
    87
        CoordinateTranslationDelegate iScreenX;
sl@65
    88
        //Function pointer for pixel Y coordinate intercept
sl@58
    89
        CoordinateTranslationDelegate iScreenY;
StephaneLenclud@112
    90
		//NAudio
StephaneLenclud@112
    91
		private MMDeviceEnumerator iMultiMediaDeviceEnumerator;
StephaneLenclud@112
    92
		private MMDevice iMultiMediaDevice;
StephaneLenclud@117
    93
		//Network
StephaneLenclud@117
    94
		private NetworkManager iNetworkManager;
StephaneLenclud@167
    95
StephaneLenclud@167
    96
        /// <summary>
StephaneLenclud@167
    97
        /// CEC - Consumer Electronic Control.
StephaneLenclud@167
    98
        /// Notably used to turn TV on and off as Windows broadcast monitor on and off notifications.
StephaneLenclud@167
    99
        /// </summary>
StephaneLenclud@167
   100
        private ConsumerElectronicControl iCecManager;
StephaneLenclud@112
   101
		
sl@94
   102
		/// <summary>
sl@94
   103
		/// Manage run when Windows startup option
sl@94
   104
		/// </summary>
sl@92
   105
		private StartupManager iStartupManager;
sl@92
   106
sl@94
   107
		/// <summary>
sl@94
   108
		/// System tray icon.
sl@94
   109
		/// </summary>
StephaneLenclud@173
   110
		private SharpLib.Notification.Control iNotifyIcon;
sl@94
   111
StephaneLenclud@167
   112
        /// <summary>
StephaneLenclud@167
   113
        /// Allow user to receive window messages;
StephaneLenclud@167
   114
        /// </summary>
StephaneLenclud@167
   115
        public event WndProcDelegate OnWndProc;
StephaneLenclud@167
   116
sl@0
   117
        public MainForm()
sl@0
   118
        {
StephaneLenclud@122
   119
			iSkipFrameRendering = false;
StephaneLenclud@122
   120
			iClosing = false;
sl@65
   121
            iCurrentClientSessionId = "";
sl@65
   122
            iCurrentClientData = null;
sl@2
   123
            LastTickTime = DateTime.Now;
StephaneLenclud@104
   124
			//Instantiate our display and register for events notifications
sl@3
   125
            iDisplay = new Display();
StephaneLenclud@104
   126
			iDisplay.OnOpened += OnDisplayOpened;
StephaneLenclud@104
   127
			iDisplay.OnClosed += OnDisplayClosed;
StephaneLenclud@104
   128
			//
StephaneLenclud@104
   129
			iClients = new Dictionary<string, ClientData>();
sl@92
   130
			iStartupManager = new StartupManager();
StephaneLenclud@173
   131
			iNotifyIcon = new SharpLib.Notification.Control();
sl@2
   132
StephaneLenclud@104
   133
			//Have our designer initialize its controls
sl@0
   134
            InitializeComponent();
StephaneLenclud@104
   135
StephaneLenclud@104
   136
			//Populate device types
StephaneLenclud@104
   137
			PopulateDeviceTypes();
StephaneLenclud@104
   138
StephaneLenclud@152
   139
            //Populate optical drives
StephaneLenclud@152
   140
            PopulateOpticalDrives();
StephaneLenclud@152
   141
StephaneLenclud@104
   142
			//Initial status update 
sl@7
   143
            UpdateStatus();
StephaneLenclud@104
   144
sl@14
   145
            //We have a bug when drawing minimized and reusing our bitmap
StephaneLenclud@158
   146
            //Though I could not reproduce it on Windows 10
StephaneLenclud@175
   147
            iBmp = new System.Drawing.Bitmap(iTableLayoutPanel.Width, iTableLayoutPanel.Height, PixelFormat.Format32bppArgb);
sl@14
   148
            iCreateBitmap = false;
sl@94
   149
StephaneLenclud@104
   150
			//Minimize our window if desired
sl@94
   151
			if (Properties.Settings.Default.StartMinimized)
sl@94
   152
			{
sl@94
   153
				WindowState = FormWindowState.Minimized;
sl@94
   154
			}
sl@94
   155
sl@0
   156
        }
sl@0
   157
sl@94
   158
		/// <summary>
StephaneLenclud@106
   159
		///
StephaneLenclud@106
   160
		/// </summary>
StephaneLenclud@106
   161
		/// <param name="sender"></param>
StephaneLenclud@106
   162
		/// <param name="e"></param>
StephaneLenclud@106
   163
        private void MainForm_Load(object sender, EventArgs e)
StephaneLenclud@106
   164
        {
StephaneLenclud@106
   165
			//Check if we are running a Click Once deployed application
StephaneLenclud@106
   166
			if (ApplicationDeployment.IsNetworkDeployed)
StephaneLenclud@106
   167
			{
StephaneLenclud@106
   168
				//This is a proper Click Once installation, fetch and show our version number
StephaneLenclud@106
   169
				this.Text += " - v" + ApplicationDeployment.CurrentDeployment.CurrentVersion;
StephaneLenclud@106
   170
			}
StephaneLenclud@106
   171
			else
StephaneLenclud@106
   172
			{
StephaneLenclud@106
   173
				//Not a proper Click Once installation, assuming development build then
StephaneLenclud@106
   174
				this.Text += " - development";
StephaneLenclud@106
   175
			}
StephaneLenclud@106
   176
StephaneLenclud@112
   177
			//NAudio
StephaneLenclud@112
   178
			iMultiMediaDeviceEnumerator = new MMDeviceEnumerator();
StephaneLenclud@117
   179
			iMultiMediaDeviceEnumerator.RegisterEndpointNotificationCallback(this);			
StephaneLenclud@112
   180
			UpdateAudioDeviceAndMasterVolumeThreadSafe();
StephaneLenclud@112
   181
StephaneLenclud@117
   182
			//Network
StephaneLenclud@117
   183
			iNetworkManager = new NetworkManager();
StephaneLenclud@117
   184
			iNetworkManager.OnConnectivityChanged += OnConnectivityChanged;
StephaneLenclud@117
   185
			UpdateNetworkStatus();
StephaneLenclud@117
   186
StephaneLenclud@167
   187
            //CEC
StephaneLenclud@167
   188
            iCecManager = new ConsumerElectronicControl();
StephaneLenclud@167
   189
            OnWndProc += iCecManager.OnWndProc;
StephaneLenclud@168
   190
            ResetCec();
StephaneLenclud@168
   191
StephaneLenclud@167
   192
StephaneLenclud@167
   193
            //Setup notification icon
StephaneLenclud@167
   194
            SetupTrayIcon();
StephaneLenclud@106
   195
StephaneLenclud@106
   196
			// To make sure start up with minimize to tray works
StephaneLenclud@106
   197
			if (WindowState == FormWindowState.Minimized && Properties.Settings.Default.MinimizeToTray)
StephaneLenclud@106
   198
			{
StephaneLenclud@106
   199
				Visible = false;
StephaneLenclud@106
   200
			}
StephaneLenclud@106
   201
StephaneLenclud@106
   202
#if !DEBUG
StephaneLenclud@106
   203
			//When not debugging we want the screen to be empty until a client takes over
StephaneLenclud@106
   204
			ClearLayout();
StephaneLenclud@106
   205
#else
StephaneLenclud@106
   206
			//When developing we want at least one client for testing
StephaneLenclud@106
   207
			StartNewClient("abcdefghijklmnopqrst-0123456789","ABCDEFGHIJKLMNOPQRST-0123456789");
StephaneLenclud@106
   208
#endif
StephaneLenclud@106
   209
StephaneLenclud@106
   210
			//Open display connection on start-up if needed
StephaneLenclud@106
   211
			if (Properties.Settings.Default.DisplayConnectOnStartup)
StephaneLenclud@106
   212
			{
StephaneLenclud@106
   213
				OpenDisplayConnection();
StephaneLenclud@106
   214
			}
StephaneLenclud@106
   215
StephaneLenclud@106
   216
			//Start our server so that we can get client requests
StephaneLenclud@106
   217
			StartServer();
StephaneLenclud@124
   218
StephaneLenclud@124
   219
			//Register for HID events
StephaneLenclud@124
   220
			RegisterHidDevices();
StephaneLenclud@106
   221
        }
StephaneLenclud@106
   222
StephaneLenclud@106
   223
		/// <summary>
StephaneLenclud@104
   224
		/// Called when our display is opened.
StephaneLenclud@104
   225
		/// </summary>
StephaneLenclud@104
   226
		/// <param name="aDisplay"></param>
StephaneLenclud@104
   227
		private void OnDisplayOpened(Display aDisplay)
StephaneLenclud@104
   228
		{
StephaneLenclud@122
   229
			//Make sure we resume frame rendering
StephaneLenclud@122
   230
			iSkipFrameRendering = false;
StephaneLenclud@122
   231
StephaneLenclud@105
   232
			//Set our screen size now that our display is connected
StephaneLenclud@105
   233
			//Our panelDisplay is the container of our tableLayoutPanel
StephaneLenclud@105
   234
			//tableLayoutPanel will resize itself to fit the client size of our panelDisplay
StephaneLenclud@105
   235
			//panelDisplay needs an extra 2 pixels for borders on each sides
StephaneLenclud@105
   236
			//tableLayoutPanel will eventually be the exact size of our display
StephaneLenclud@105
   237
			Size size = new Size(iDisplay.WidthInPixels() + 2, iDisplay.HeightInPixels() + 2);
StephaneLenclud@105
   238
			panelDisplay.Size = size;
StephaneLenclud@105
   239
StephaneLenclud@104
   240
			//Our display was just opened, update our UI
StephaneLenclud@104
   241
			UpdateStatus();
StephaneLenclud@104
   242
			//Initiate asynchronous request
StephaneLenclud@104
   243
			iDisplay.RequestFirmwareRevision();
StephaneLenclud@108
   244
StephaneLenclud@117
   245
			//Audio
StephaneLenclud@112
   246
			UpdateMasterVolumeThreadSafe();
StephaneLenclud@117
   247
			//Network
StephaneLenclud@117
   248
			UpdateNetworkStatus();
StephaneLenclud@112
   249
StephaneLenclud@108
   250
#if DEBUG
StephaneLenclud@108
   251
			//Testing icon in debug, no arm done if icon not supported
StephaneLenclud@109
   252
			//iDisplay.SetIconStatus(Display.TMiniDisplayIconType.EMiniDisplayIconRecording, 0, 1);
StephaneLenclud@112
   253
			//iDisplay.SetAllIconsStatus(2);
StephaneLenclud@108
   254
#endif
StephaneLenclud@108
   255
StephaneLenclud@104
   256
		}
StephaneLenclud@104
   257
StephaneLenclud@104
   258
		/// <summary>
StephaneLenclud@104
   259
		/// Called when our display is closed.
StephaneLenclud@104
   260
		/// </summary>
StephaneLenclud@104
   261
		/// <param name="aDisplay"></param>
StephaneLenclud@104
   262
		private void OnDisplayClosed(Display aDisplay)
StephaneLenclud@104
   263
		{
StephaneLenclud@104
   264
			//Our display was just closed, update our UI consequently
StephaneLenclud@104
   265
			UpdateStatus();
StephaneLenclud@104
   266
		}
StephaneLenclud@117
   267
StephaneLenclud@117
   268
		public void OnConnectivityChanged(NetworkManager aNetwork, NLM_CONNECTIVITY newConnectivity)
StephaneLenclud@117
   269
		{
StephaneLenclud@117
   270
			//Update network status
StephaneLenclud@117
   271
			UpdateNetworkStatus();			
StephaneLenclud@117
   272
		}
StephaneLenclud@117
   273
StephaneLenclud@117
   274
		/// <summary>
StephaneLenclud@117
   275
		/// Update our Network Status
StephaneLenclud@117
   276
		/// </summary>
StephaneLenclud@117
   277
		private void UpdateNetworkStatus()
StephaneLenclud@117
   278
		{
StephaneLenclud@117
   279
			if (iDisplay.IsOpen())
StephaneLenclud@117
   280
			{
StephaneLenclud@135
   281
                iDisplay.SetIconOnOff(MiniDisplay.IconType.Internet, iNetworkManager.NetworkListManager.IsConnectedToInternet);
StephaneLenclud@135
   282
                iDisplay.SetIconOnOff(MiniDisplay.IconType.NetworkSignal, iNetworkManager.NetworkListManager.IsConnected);
StephaneLenclud@117
   283
			}
StephaneLenclud@117
   284
		}
StephaneLenclud@117
   285
StephaneLenclud@117
   286
StephaneLenclud@118
   287
		int iLastNetworkIconIndex = 0;
StephaneLenclud@118
   288
		int iUpdateCountSinceLastNetworkAnimation = 0;
StephaneLenclud@118
   289
StephaneLenclud@118
   290
		/// <summary>
StephaneLenclud@118
   291
		/// 
StephaneLenclud@118
   292
		/// </summary>
StephaneLenclud@118
   293
		private void UpdateNetworkSignal(DateTime aLastTickTime, DateTime aNewTickTime)
StephaneLenclud@118
   294
		{
StephaneLenclud@118
   295
			iUpdateCountSinceLastNetworkAnimation++;
StephaneLenclud@118
   296
			iUpdateCountSinceLastNetworkAnimation = iUpdateCountSinceLastNetworkAnimation % 4;
StephaneLenclud@118
   297
StephaneLenclud@118
   298
			if (iDisplay.IsOpen() && iNetworkManager.NetworkListManager.IsConnected && iUpdateCountSinceLastNetworkAnimation==0)
StephaneLenclud@135
   299
			{
StephaneLenclud@135
   300
                int iconCount = iDisplay.IconCount(MiniDisplay.IconType.NetworkSignal);
StephaneLenclud@120
   301
				if (iconCount <= 0)
StephaneLenclud@120
   302
				{
StephaneLenclud@120
   303
					//Prevents div by zero and other undefined behavior
StephaneLenclud@120
   304
					return;
StephaneLenclud@120
   305
				}
StephaneLenclud@118
   306
				iLastNetworkIconIndex++;
StephaneLenclud@119
   307
				iLastNetworkIconIndex = iLastNetworkIconIndex % (iconCount*2);
StephaneLenclud@118
   308
				for (int i=0;i<iconCount;i++)
StephaneLenclud@118
   309
				{
StephaneLenclud@119
   310
					if (i < iLastNetworkIconIndex && !(i == 0 && iLastNetworkIconIndex > 3) && !(i == 1 && iLastNetworkIconIndex > 4))
StephaneLenclud@118
   311
					{
StephaneLenclud@135
   312
                        iDisplay.SetIconOn(MiniDisplay.IconType.NetworkSignal, i);
StephaneLenclud@118
   313
					}
StephaneLenclud@118
   314
					else
StephaneLenclud@118
   315
					{
StephaneLenclud@135
   316
                        iDisplay.SetIconOff(MiniDisplay.IconType.NetworkSignal, i);
StephaneLenclud@118
   317
					}
StephaneLenclud@118
   318
				}				
StephaneLenclud@118
   319
			}
StephaneLenclud@118
   320
		}
StephaneLenclud@118
   321
StephaneLenclud@118
   322
StephaneLenclud@118
   323
StephaneLenclud@112
   324
        /// <summary>
StephaneLenclud@112
   325
        /// Receive volume change notification and reflect changes on our slider.
StephaneLenclud@112
   326
        /// </summary>
StephaneLenclud@112
   327
        /// <param name="data"></param>
StephaneLenclud@112
   328
        public void OnVolumeNotificationThreadSafe(AudioVolumeNotificationData data)
StephaneLenclud@112
   329
        {
StephaneLenclud@112
   330
			UpdateMasterVolumeThreadSafe();
StephaneLenclud@112
   331
        }
StephaneLenclud@112
   332
StephaneLenclud@112
   333
        /// <summary>
StephaneLenclud@112
   334
        /// Update master volume when user moves our slider.
StephaneLenclud@112
   335
        /// </summary>
StephaneLenclud@112
   336
        /// <param name="sender"></param>
StephaneLenclud@112
   337
        /// <param name="e"></param>
StephaneLenclud@112
   338
        private void trackBarMasterVolume_Scroll(object sender, EventArgs e)
StephaneLenclud@112
   339
        {
StephaneLenclud@116
   340
			//Just like Windows Volume Mixer we unmute if the volume is adjusted
StephaneLenclud@116
   341
			iMultiMediaDevice.AudioEndpointVolume.Mute = false;
StephaneLenclud@116
   342
			//Set volume level according to our volume slider new position
StephaneLenclud@112
   343
			iMultiMediaDevice.AudioEndpointVolume.MasterVolumeLevelScalar = trackBarMasterVolume.Value / 100.0f;
StephaneLenclud@112
   344
        }
StephaneLenclud@112
   345
StephaneLenclud@113
   346
StephaneLenclud@113
   347
		/// <summary>
StephaneLenclud@113
   348
		/// Mute check box changed.
StephaneLenclud@113
   349
		/// </summary>
StephaneLenclud@113
   350
		/// <param name="sender"></param>
StephaneLenclud@113
   351
		/// <param name="e"></param>
StephaneLenclud@113
   352
		private void checkBoxMute_CheckedChanged(object sender, EventArgs e)
StephaneLenclud@113
   353
		{
StephaneLenclud@113
   354
			iMultiMediaDevice.AudioEndpointVolume.Mute = checkBoxMute.Checked;
StephaneLenclud@113
   355
		}
StephaneLenclud@113
   356
StephaneLenclud@112
   357
        /// <summary>
StephaneLenclud@112
   358
        /// Device State Changed
StephaneLenclud@112
   359
        /// </summary>
StephaneLenclud@112
   360
        public void OnDeviceStateChanged([MarshalAs(UnmanagedType.LPWStr)] string deviceId, [MarshalAs(UnmanagedType.I4)] DeviceState newState){}
StephaneLenclud@112
   361
StephaneLenclud@112
   362
        /// <summary>
StephaneLenclud@112
   363
        /// Device Added
StephaneLenclud@112
   364
        /// </summary>
StephaneLenclud@112
   365
        public void OnDeviceAdded([MarshalAs(UnmanagedType.LPWStr)] string pwstrDeviceId) { }
StephaneLenclud@112
   366
StephaneLenclud@112
   367
        /// <summary>
StephaneLenclud@112
   368
        /// Device Removed
StephaneLenclud@112
   369
        /// </summary>
StephaneLenclud@112
   370
        public void OnDeviceRemoved([MarshalAs(UnmanagedType.LPWStr)] string deviceId) { }
StephaneLenclud@112
   371
StephaneLenclud@112
   372
        /// <summary>
StephaneLenclud@112
   373
        /// Default Device Changed
StephaneLenclud@112
   374
        /// </summary>
StephaneLenclud@112
   375
        public void OnDefaultDeviceChanged(DataFlow flow, Role role, [MarshalAs(UnmanagedType.LPWStr)] string defaultDeviceId)
StephaneLenclud@112
   376
        {
StephaneLenclud@112
   377
            if (role == Role.Multimedia && flow == DataFlow.Render)
StephaneLenclud@112
   378
            {
StephaneLenclud@112
   379
                UpdateAudioDeviceAndMasterVolumeThreadSafe();
StephaneLenclud@112
   380
            }
StephaneLenclud@112
   381
        }
StephaneLenclud@112
   382
StephaneLenclud@112
   383
        /// <summary>
StephaneLenclud@112
   384
        /// Property Value Changed
StephaneLenclud@112
   385
        /// </summary>
StephaneLenclud@112
   386
        /// <param name="pwstrDeviceId"></param>
StephaneLenclud@112
   387
        /// <param name="key"></param>
StephaneLenclud@112
   388
        public void OnPropertyValueChanged([MarshalAs(UnmanagedType.LPWStr)] string pwstrDeviceId, PropertyKey key){}
StephaneLenclud@112
   389
StephaneLenclud@112
   390
StephaneLenclud@112
   391
        
StephaneLenclud@112
   392
StephaneLenclud@112
   393
		/// <summary>
StephaneLenclud@116
   394
		/// Update master volume indicators based our current system states.
StephaneLenclud@116
   395
		/// This typically includes volume levels and mute status.
StephaneLenclud@112
   396
		/// </summary>
StephaneLenclud@112
   397
		private void UpdateMasterVolumeThreadSafe()
StephaneLenclud@112
   398
		{
StephaneLenclud@112
   399
			if (this.InvokeRequired)
StephaneLenclud@112
   400
			{
StephaneLenclud@112
   401
				//Not in the proper thread, invoke ourselves
StephaneLenclud@112
   402
				PlainUpdateDelegate d = new PlainUpdateDelegate(UpdateMasterVolumeThreadSafe);
StephaneLenclud@112
   403
				this.Invoke(d, new object[] { });
StephaneLenclud@112
   404
				return;
StephaneLenclud@112
   405
			}
StephaneLenclud@112
   406
StephaneLenclud@113
   407
			//Update volume slider
StephaneLenclud@112
   408
			float volumeLevelScalar = iMultiMediaDevice.AudioEndpointVolume.MasterVolumeLevelScalar;
StephaneLenclud@112
   409
			trackBarMasterVolume.Value = Convert.ToInt32(volumeLevelScalar * 100);
StephaneLenclud@113
   410
			//Update mute checkbox
StephaneLenclud@113
   411
			checkBoxMute.Checked = iMultiMediaDevice.AudioEndpointVolume.Mute;
StephaneLenclud@112
   412
StephaneLenclud@116
   413
			//If our display connection is open we need to update its icons
StephaneLenclud@112
   414
			if (iDisplay.IsOpen())
StephaneLenclud@112
   415
			{
StephaneLenclud@116
   416
				//First take care our our volume level icons
StephaneLenclud@135
   417
                int volumeIconCount = iDisplay.IconCount(MiniDisplay.IconType.Volume);
StephaneLenclud@112
   418
				if (volumeIconCount > 0)
StephaneLenclud@114
   419
				{					
StephaneLenclud@116
   420
					//Compute current volume level from system level and the number of segments in our display volume bar.
StephaneLenclud@116
   421
					//That tells us how many segments in our volume bar needs to be turned on.
StephaneLenclud@116
   422
					float currentVolume = volumeLevelScalar * volumeIconCount;
StephaneLenclud@116
   423
					int segmentOnCount = Convert.ToInt32(currentVolume);
StephaneLenclud@116
   424
					//Check if our segment count was rounded up, this will later be used for half brightness segment
StephaneLenclud@116
   425
					bool roundedUp = segmentOnCount > currentVolume;
StephaneLenclud@114
   426
StephaneLenclud@112
   427
					for (int i = 0; i < volumeIconCount; i++)
StephaneLenclud@112
   428
					{
StephaneLenclud@116
   429
						if (i < segmentOnCount)
StephaneLenclud@112
   430
						{
StephaneLenclud@116
   431
							//If we are dealing with our last segment and our segment count was rounded up then we will use half brightness.
StephaneLenclud@116
   432
							if (i == segmentOnCount - 1 && roundedUp)
StephaneLenclud@114
   433
							{
StephaneLenclud@114
   434
								//Half brightness
StephaneLenclud@135
   435
                                iDisplay.SetIconStatus(MiniDisplay.IconType.Volume, i, (iDisplay.IconStatusCount(MiniDisplay.IconType.Volume) - 1) / 2);
StephaneLenclud@114
   436
							}
StephaneLenclud@114
   437
							else
StephaneLenclud@114
   438
							{
StephaneLenclud@114
   439
								//Full brightness
StephaneLenclud@135
   440
                                iDisplay.SetIconStatus(MiniDisplay.IconType.Volume, i, iDisplay.IconStatusCount(MiniDisplay.IconType.Volume) - 1);
StephaneLenclud@114
   441
							}
StephaneLenclud@112
   442
						}
StephaneLenclud@112
   443
						else
StephaneLenclud@112
   444
						{
StephaneLenclud@135
   445
                            iDisplay.SetIconStatus(MiniDisplay.IconType.Volume, i, 0);
StephaneLenclud@112
   446
						}
StephaneLenclud@112
   447
					}
StephaneLenclud@112
   448
				}
StephaneLenclud@113
   449
StephaneLenclud@116
   450
				//Take care our our mute icon
StephaneLenclud@135
   451
                iDisplay.SetIconOnOff(MiniDisplay.IconType.Mute, iMultiMediaDevice.AudioEndpointVolume.Mute);
StephaneLenclud@112
   452
			}
StephaneLenclud@112
   453
StephaneLenclud@112
   454
		}
StephaneLenclud@112
   455
StephaneLenclud@112
   456
        /// <summary>
StephaneLenclud@112
   457
        /// 
StephaneLenclud@112
   458
        /// </summary>
StephaneLenclud@112
   459
        private void UpdateAudioDeviceAndMasterVolumeThreadSafe()
StephaneLenclud@112
   460
        {
StephaneLenclud@112
   461
            if (this.InvokeRequired)
StephaneLenclud@112
   462
            {
StephaneLenclud@112
   463
                //Not in the proper thread, invoke ourselves
StephaneLenclud@112
   464
				PlainUpdateDelegate d = new PlainUpdateDelegate(UpdateAudioDeviceAndMasterVolumeThreadSafe);
StephaneLenclud@112
   465
                this.Invoke(d, new object[] { });
StephaneLenclud@112
   466
                return;
StephaneLenclud@112
   467
            }
StephaneLenclud@112
   468
            
StephaneLenclud@112
   469
            //We are in the correct thread just go ahead.
StephaneLenclud@112
   470
            try
StephaneLenclud@112
   471
            {                
StephaneLenclud@112
   472
                //Get our master volume            
StephaneLenclud@112
   473
				iMultiMediaDevice = iMultiMediaDeviceEnumerator.GetDefaultAudioEndpoint(DataFlow.Render, Role.Multimedia);
StephaneLenclud@116
   474
				//Update our label
StephaneLenclud@116
   475
				labelDefaultAudioDevice.Text = iMultiMediaDevice.FriendlyName;
StephaneLenclud@116
   476
StephaneLenclud@112
   477
                //Show our volume in our track bar
StephaneLenclud@112
   478
				UpdateMasterVolumeThreadSafe();
StephaneLenclud@112
   479
StephaneLenclud@112
   480
                //Register to get volume modifications
StephaneLenclud@112
   481
				iMultiMediaDevice.AudioEndpointVolume.OnVolumeNotification += OnVolumeNotificationThreadSafe;
StephaneLenclud@112
   482
                //
StephaneLenclud@112
   483
				trackBarMasterVolume.Enabled = true;
StephaneLenclud@112
   484
            }
StephaneLenclud@112
   485
            catch (Exception ex)
StephaneLenclud@112
   486
            {
StephaneLenclud@112
   487
                Debug.WriteLine("Exception thrown in UpdateAudioDeviceAndMasterVolume");
StephaneLenclud@112
   488
                Debug.WriteLine(ex.ToString());
StephaneLenclud@112
   489
                //Something went wrong S/PDIF device ca throw exception I guess
StephaneLenclud@112
   490
				trackBarMasterVolume.Enabled = false;
StephaneLenclud@112
   491
            }
StephaneLenclud@112
   492
        }
StephaneLenclud@104
   493
StephaneLenclud@104
   494
		/// <summary>
StephaneLenclud@104
   495
		/// 
StephaneLenclud@104
   496
		/// </summary>
StephaneLenclud@104
   497
		private void PopulateDeviceTypes()
StephaneLenclud@104
   498
		{
StephaneLenclud@104
   499
			int count = Display.TypeCount();
StephaneLenclud@104
   500
StephaneLenclud@106
   501
			for (int i = 0; i < count; i++)
StephaneLenclud@104
   502
			{
StephaneLenclud@135
   503
				comboBoxDisplayType.Items.Add(Display.TypeName((MiniDisplay.Type)i));
StephaneLenclud@106
   504
			}
StephaneLenclud@104
   505
		}
StephaneLenclud@104
   506
StephaneLenclud@152
   507
        /// <summary>
StephaneLenclud@152
   508
        /// 
StephaneLenclud@152
   509
        /// </summary>
StephaneLenclud@152
   510
        private void PopulateOpticalDrives()
StephaneLenclud@152
   511
        {
StephaneLenclud@152
   512
            //Reset our list of drives
StephaneLenclud@152
   513
            comboBoxOpticalDrives.Items.Clear();
StephaneLenclud@153
   514
            comboBoxOpticalDrives.Items.Add("None");
StephaneLenclud@152
   515
StephaneLenclud@152
   516
            //Go through each drives on our system and collected the optical ones in our list
StephaneLenclud@152
   517
            DriveInfo[] allDrives = DriveInfo.GetDrives();
StephaneLenclud@152
   518
            foreach (DriveInfo d in allDrives)
StephaneLenclud@152
   519
            {
StephaneLenclud@157
   520
                Debug.WriteLine("Drive " + d.Name);
StephaneLenclud@152
   521
                Debug.WriteLine("  Drive type: {0}", d.DriveType);
StephaneLenclud@152
   522
StephaneLenclud@152
   523
                if (d.DriveType==DriveType.CDRom)
StephaneLenclud@152
   524
                {
StephaneLenclud@152
   525
                    //This is an optical drive, add it now
StephaneLenclud@152
   526
                    comboBoxOpticalDrives.Items.Add(d.Name.Substring(0,2));
StephaneLenclud@152
   527
                }                
StephaneLenclud@153
   528
            }           
StephaneLenclud@152
   529
        }
StephaneLenclud@152
   530
StephaneLenclud@152
   531
        /// <summary>
StephaneLenclud@152
   532
        /// 
StephaneLenclud@152
   533
        /// </summary>
StephaneLenclud@152
   534
        /// <returns></returns>
StephaneLenclud@152
   535
        public string OpticalDriveToEject()
StephaneLenclud@152
   536
        {
StephaneLenclud@153
   537
            return comboBoxOpticalDrives.SelectedItem.ToString();
StephaneLenclud@152
   538
        }
StephaneLenclud@152
   539
StephaneLenclud@152
   540
StephaneLenclud@152
   541
StephaneLenclud@104
   542
		/// <summary>
sl@99
   543
		///
sl@94
   544
		/// </summary>
sl@95
   545
		private void SetupTrayIcon()
sl@95
   546
		{
sl@95
   547
			iNotifyIcon.Icon = GetIcon("vfd.ico");
sl@95
   548
			iNotifyIcon.Text = "Sharp Display Manager";
sl@95
   549
			iNotifyIcon.Visible = true;
sl@95
   550
sl@95
   551
			//Double click toggles visibility - typically brings up the application
sl@95
   552
			iNotifyIcon.DoubleClick += delegate(object obj, EventArgs args)
sl@95
   553
			{
sl@95
   554
				SysTrayHideShow();
sl@95
   555
			};
sl@95
   556
sl@95
   557
			//Adding a context menu, useful to be able to exit the application
sl@95
   558
			ContextMenu contextMenu = new ContextMenu();
sl@95
   559
			//Context menu item to toggle visibility
sl@95
   560
			MenuItem hideShowItem = new MenuItem("Hide/Show");
sl@95
   561
			hideShowItem.Click += delegate(object obj, EventArgs args)
sl@95
   562
			{
sl@95
   563
				SysTrayHideShow();
sl@95
   564
			};
sl@95
   565
			contextMenu.MenuItems.Add(hideShowItem);
sl@95
   566
sl@95
   567
			//Context menu item separator
sl@95
   568
			contextMenu.MenuItems.Add(new MenuItem("-"));
sl@95
   569
sl@95
   570
			//Context menu exit item
sl@95
   571
			MenuItem exitItem = new MenuItem("Exit");
sl@95
   572
			exitItem.Click += delegate(object obj, EventArgs args)
sl@95
   573
			{
sl@95
   574
				Application.Exit();
sl@95
   575
			};
sl@95
   576
			contextMenu.MenuItems.Add(exitItem);
sl@95
   577
sl@95
   578
			iNotifyIcon.ContextMenu = contextMenu;
sl@95
   579
		}
sl@95
   580
StephaneLenclud@178
   581
        /// <summary>
StephaneLenclud@178
   582
        /// Access icons from embedded resources.
StephaneLenclud@178
   583
        /// </summary>
StephaneLenclud@178
   584
        /// <param name="aName"></param>
StephaneLenclud@178
   585
        /// <returns></returns>
StephaneLenclud@178
   586
        public static Icon GetIcon(string aName)
sl@94
   587
		{
StephaneLenclud@178
   588
			string[] names =  Assembly.GetExecutingAssembly().GetManifestResourceNames();
StephaneLenclud@178
   589
			foreach (string name in names)
sl@94
   590
			{
StephaneLenclud@178
   591
                //Find a resource name that ends with the given name
StephaneLenclud@178
   592
				if (name.EndsWith(aName))
sl@94
   593
				{
StephaneLenclud@178
   594
					using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(name))
sl@94
   595
					{
sl@94
   596
						return new Icon(stream);
sl@94
   597
					}
sl@94
   598
				}
sl@94
   599
			}
sl@94
   600
sl@94
   601
			return null;
sl@94
   602
		}
sl@94
   603
sl@94
   604
sl@65
   605
        /// <summary>
sl@65
   606
        /// Set our current client.
sl@65
   607
        /// This will take care of applying our client layout and set data fields.
sl@65
   608
        /// </summary>
sl@65
   609
        /// <param name="aSessionId"></param>
StephaneLenclud@141
   610
        void SetCurrentClient(string aSessionId, bool aForce=false)
sl@57
   611
        {
sl@65
   612
            if (aSessionId == iCurrentClientSessionId)
sl@57
   613
            {
sl@65
   614
                //Given client is already the current one.
sl@65
   615
                //Don't bother changing anything then.
sl@65
   616
                return;
sl@65
   617
            }
sl@57
   618
StephaneLenclud@141
   619
StephaneLenclud@141
   620
            //Check when was the last time we switched to that client
StephaneLenclud@142
   621
            if (iCurrentClientData != null)
StephaneLenclud@141
   622
            {
StephaneLenclud@142
   623
                double lastSwitchToClientSecondsAgo = (DateTime.Now - iCurrentClientData.LastSwitchTime).TotalSeconds;
StephaneLenclud@142
   624
                //TODO: put that hard coded value as a client property
StephaneLenclud@142
   625
                //Clients should be able to define how often they can be interrupted
StephaneLenclud@142
   626
                //Thus a background client can set this to zero allowing any other client to interrupt at any time
StephaneLenclud@142
   627
                //We could also compute this delay by looking at the requests frequencies?
StephaneLenclud@142
   628
                if (!aForce && (lastSwitchToClientSecondsAgo < 30)) //Make sure a client is on for at least 30 seconds
StephaneLenclud@142
   629
                {
StephaneLenclud@142
   630
                    //Don't switch clients too often
StephaneLenclud@142
   631
                    return;
StephaneLenclud@142
   632
                }
StephaneLenclud@141
   633
            }
StephaneLenclud@141
   634
sl@65
   635
            //Set current client ID.
sl@65
   636
            iCurrentClientSessionId = aSessionId;
StephaneLenclud@141
   637
            //Set the time we last switched to that client
StephaneLenclud@141
   638
            iClients[aSessionId].LastSwitchTime = DateTime.Now;
sl@65
   639
            //Fetch and set current client data.
sl@65
   640
            iCurrentClientData = iClients[aSessionId];
sl@65
   641
            //Apply layout and set data fields.
sl@65
   642
            UpdateTableLayoutPanel(iCurrentClientData);
sl@57
   643
        }
sl@57
   644
sl@0
   645
        private void buttonFont_Click(object sender, EventArgs e)
sl@0
   646
        {
sl@0
   647
            //fontDialog.ShowColor = true;
sl@0
   648
            //fontDialog.ShowApply = true;
sl@0
   649
            fontDialog.ShowEffects = true;
sl@99
   650
            fontDialog.Font = cds.Font;
sl@28
   651
sl@28
   652
            fontDialog.FixedPitchOnly = checkBoxFixedPitchFontOnly.Checked;
sl@28
   653
sl@0
   654
            //fontDialog.ShowHelp = true;
sl@0
   655
sl@0
   656
            //fontDlg.MaxSize = 40;
sl@0
   657
            //fontDlg.MinSize = 22;
sl@0
   658
sl@0
   659
            //fontDialog.Parent = this;
sl@0
   660
            //fontDialog.StartPosition = FormStartPosition.CenterParent;
sl@0
   661
sl@0
   662
            //DlgBox.ShowDialog(fontDialog);
sl@0
   663
sl@0
   664
            //if (fontDialog.ShowDialog(this) != DialogResult.Cancel)
sl@0
   665
            if (DlgBox.ShowDialog(fontDialog) != DialogResult.Cancel)
sl@0
   666
            {
sl@99
   667
                //Set the fonts to all our labels in our layout
StephaneLenclud@175
   668
                foreach (Control ctrl in iTableLayoutPanel.Controls)
sl@99
   669
                {
sl@99
   670
                    if (ctrl is MarqueeLabel)
sl@99
   671
                    {
sl@99
   672
                        ((MarqueeLabel)ctrl).Font = fontDialog.Font;
sl@99
   673
                    }
sl@99
   674
                }
sl@0
   675
sl@99
   676
                //Save font settings
sl@48
   677
                cds.Font = fontDialog.Font;
sl@8
   678
                Properties.Settings.Default.Save();
sl@36
   679
                //
sl@37
   680
                CheckFontHeight();
sl@37
   681
            }
sl@37
   682
        }
sl@36
   683
sl@37
   684
        /// <summary>
sl@38
   685
        ///
sl@37
   686
        /// </summary>
sl@37
   687
        void CheckFontHeight()
sl@37
   688
        {
sl@54
   689
            //Show font height and width
sl@54
   690
            labelFontHeight.Text = "Font height: " + cds.Font.Height;
sl@54
   691
            float charWidth = IsFixedWidth(cds.Font);
sl@54
   692
            if (charWidth == 0.0f)
sl@54
   693
            {
sl@54
   694
                labelFontWidth.Visible = false;
sl@54
   695
            }
sl@54
   696
            else
sl@54
   697
            {
sl@54
   698
                labelFontWidth.Visible = true;
sl@54
   699
                labelFontWidth.Text = "Font width: " + charWidth;
sl@54
   700
            }
sl@54
   701
sl@70
   702
            MarqueeLabel label = null;
sl@68
   703
            //Get the first label control we can find
StephaneLenclud@175
   704
            foreach (Control ctrl in iTableLayoutPanel.Controls)
sl@68
   705
            {
sl@68
   706
                if (ctrl is MarqueeLabel)
sl@68
   707
                {
sl@68
   708
                    label = (MarqueeLabel)ctrl;
sl@68
   709
                    break;
sl@68
   710
                }
sl@68
   711
            }
sl@68
   712
sl@54
   713
            //Now check font height and show a warning if needed.
sl@68
   714
            if (label != null && label.Font.Height > label.Height)
sl@37
   715
            {
sl@60
   716
                labelWarning.Text = "WARNING: Selected font is too height by " + (label.Font.Height - label.Height) + " pixels!";
sl@37
   717
                labelWarning.Visible = true;
sl@0
   718
            }
sl@37
   719
            else
sl@37
   720
            {
sl@37
   721
                labelWarning.Visible = false;
sl@37
   722
            }
sl@37
   723
sl@0
   724
        }
sl@0
   725
sl@0
   726
        private void buttonCapture_Click(object sender, EventArgs e)
sl@0
   727
        {
StephaneLenclud@175
   728
            System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(iTableLayoutPanel.Width, iTableLayoutPanel.Height);
StephaneLenclud@175
   729
            iTableLayoutPanel.DrawToBitmap(bmp, iTableLayoutPanel.ClientRectangle);
sl@14
   730
            //Bitmap bmpToSave = new Bitmap(bmp);
sl@14
   731
            bmp.Save("D:\\capture.png");
sl@14
   732
StephaneLenclud@175
   733
            ((MarqueeLabel)iTableLayoutPanel.Controls[0]).Text = "Captured";
sl@17
   734
sl@14
   735
            /*
sl@14
   736
            string outputFileName = "d:\\capture.png";
sl@14
   737
            using (MemoryStream memory = new MemoryStream())
sl@14
   738
            {
sl@14
   739
                using (FileStream fs = new FileStream(outputFileName, FileMode.OpenOrCreate, FileAccess.ReadWrite))
sl@14
   740
                {
sl@14
   741
                    bmp.Save(memory, System.Drawing.Imaging.ImageFormat.Png);
sl@14
   742
                    byte[] bytes = memory.ToArray();
sl@14
   743
                    fs.Write(bytes, 0, bytes.Length);
sl@14
   744
                }
sl@14
   745
            }
sl@14
   746
             */
sl@14
   747
sl@0
   748
        }
sl@2
   749
sl@12
   750
        private void CheckForRequestResults()
sl@12
   751
        {
sl@12
   752
            if (iDisplay.IsRequestPending())
sl@12
   753
            {
sl@12
   754
                switch (iDisplay.AttemptRequestCompletion())
sl@12
   755
                {
StephaneLenclud@135
   756
                    case MiniDisplay.Request.FirmwareRevision:
sl@51
   757
                        toolStripStatusLabelConnect.Text += " v" + iDisplay.FirmwareRevision();
sl@51
   758
                        //Issue next request then
sl@51
   759
                        iDisplay.RequestPowerSupplyStatus();
sl@51
   760
                        break;
sl@51
   761
StephaneLenclud@135
   762
                    case MiniDisplay.Request.PowerSupplyStatus:
sl@12
   763
                        if (iDisplay.PowerSupplyStatus())
sl@12
   764
                        {
sl@12
   765
                            toolStripStatusLabelPower.Text = "ON";
sl@12
   766
                        }
sl@12
   767
                        else
sl@12
   768
                        {
sl@12
   769
                            toolStripStatusLabelPower.Text = "OFF";
sl@12
   770
                        }
sl@12
   771
                        //Issue next request then
sl@12
   772
                        iDisplay.RequestDeviceId();
sl@12
   773
                        break;
sl@12
   774
StephaneLenclud@135
   775
                    case MiniDisplay.Request.DeviceId:
sl@12
   776
                        toolStripStatusLabelConnect.Text += " - " + iDisplay.DeviceId();
sl@12
   777
                        //No more request to issue
sl@12
   778
                        break;
sl@12
   779
                }
sl@12
   780
            }
sl@12
   781
        }
sl@12
   782
sl@58
   783
        public static uint ColorWhiteIsOn(int aX, int aY, uint aPixel)
sl@58
   784
        {
sl@58
   785
            if ((aPixel & 0x00FFFFFF) == 0x00FFFFFF)
sl@58
   786
            {
sl@58
   787
                return 0xFFFFFFFF;
sl@58
   788
            }
sl@58
   789
            return 0x00000000;
sl@58
   790
        }
sl@16
   791
sl@58
   792
        public static uint ColorUntouched(int aX, int aY, uint aPixel)
sl@57
   793
        {
sl@57
   794
            return aPixel;
sl@57
   795
        }
sl@57
   796
sl@58
   797
        public static uint ColorInversed(int aX, int aY, uint aPixel)
sl@57
   798
        {
sl@57
   799
            return ~aPixel;
sl@57
   800
        }
sl@57
   801
sl@58
   802
        public static uint ColorChessboard(int aX, int aY, uint aPixel)
sl@58
   803
        {
sl@58
   804
            if ((aX % 2 == 0) && (aY % 2 == 0))
sl@58
   805
            {
sl@58
   806
                return ~aPixel;
sl@58
   807
            }
sl@58
   808
            else if ((aX % 2 != 0) && (aY % 2 != 0))
sl@58
   809
            {
sl@58
   810
                return ~aPixel;
sl@58
   811
            }
sl@58
   812
            return 0x00000000;
sl@58
   813
        }
sl@58
   814
sl@16
   815
sl@16
   816
        public static int ScreenReversedX(System.Drawing.Bitmap aBmp, int aX)
sl@16
   817
        {
sl@16
   818
            return aBmp.Width - aX - 1;
sl@16
   819
        }
sl@16
   820
sl@16
   821
        public int ScreenReversedY(System.Drawing.Bitmap aBmp, int aY)
sl@16
   822
        {
sl@16
   823
            return iBmp.Height - aY - 1;
sl@16
   824
        }
sl@16
   825
sl@16
   826
        public int ScreenX(System.Drawing.Bitmap aBmp, int aX)
sl@16
   827
        {
sl@16
   828
            return aX;
sl@16
   829
        }
sl@16
   830
sl@16
   831
        public int ScreenY(System.Drawing.Bitmap aBmp, int aY)
sl@16
   832
        {
sl@16
   833
            return aY;
sl@16
   834
        }
sl@16
   835
sl@58
   836
        /// <summary>
sl@58
   837
        /// Select proper pixel delegates according to our current settings.
sl@58
   838
        /// </summary>
sl@58
   839
        private void SetupPixelDelegates()
sl@58
   840
        {
sl@59
   841
            //Select our pixel processing routine
sl@58
   842
            if (cds.InverseColors)
sl@58
   843
            {
sl@58
   844
                //iColorFx = ColorChessboard;
sl@58
   845
                iColorFx = ColorInversed;
sl@58
   846
            }
sl@58
   847
            else
sl@58
   848
            {
sl@58
   849
                iColorFx = ColorWhiteIsOn;
sl@58
   850
            }
sl@58
   851
sl@58
   852
            //Select proper coordinate translation functions
sl@58
   853
            //We used delegate/function pointer to support reverse screen without doing an extra test on each pixels
sl@58
   854
            if (cds.ReverseScreen)
sl@58
   855
            {
sl@58
   856
                iScreenX = ScreenReversedX;
sl@58
   857
                iScreenY = ScreenReversedY;
sl@58
   858
            }
sl@58
   859
            else
sl@58
   860
            {
sl@58
   861
                iScreenX = ScreenX;
sl@58
   862
                iScreenY = ScreenY;
sl@58
   863
            }
sl@58
   864
sl@58
   865
        }
sl@16
   866
sl@16
   867
        //This is our timer tick responsible to perform our render
sl@2
   868
        private void timer_Tick(object sender, EventArgs e)
sl@14
   869
        {
sl@2
   870
            //Update our animations
sl@2
   871
            DateTime NewTickTime = DateTime.Now;
sl@2
   872
StephaneLenclud@118
   873
			UpdateNetworkSignal(LastTickTime, NewTickTime);
StephaneLenclud@118
   874
sl@60
   875
            //Update animation for all our marquees
StephaneLenclud@175
   876
            foreach (Control ctrl in iTableLayoutPanel.Controls)
sl@60
   877
            {
sl@68
   878
                if (ctrl is MarqueeLabel)
sl@68
   879
                {
sl@68
   880
                    ((MarqueeLabel)ctrl).UpdateAnimation(LastTickTime, NewTickTime);
sl@68
   881
                }
sl@60
   882
            }
sl@60
   883
sl@4
   884
            //Update our display
sl@4
   885
            if (iDisplay.IsOpen())
sl@4
   886
            {
sl@12
   887
                CheckForRequestResults();
sl@12
   888
StephaneLenclud@122
   889
				//Check if frame rendering is needed
StephaneLenclud@122
   890
				//Typically used when showing clock
StephaneLenclud@122
   891
				if (!iSkipFrameRendering)
StephaneLenclud@122
   892
				{
StephaneLenclud@122
   893
					//Draw to bitmap
StephaneLenclud@122
   894
					if (iCreateBitmap)
StephaneLenclud@122
   895
					{
StephaneLenclud@175
   896
                        iBmp = new System.Drawing.Bitmap(iTableLayoutPanel.Width, iTableLayoutPanel.Height, PixelFormat.Format32bppArgb);
StephaneLenclud@158
   897
                        iCreateBitmap = false;
StephaneLenclud@158
   898
                    }
StephaneLenclud@175
   899
					iTableLayoutPanel.DrawToBitmap(iBmp, iTableLayoutPanel.ClientRectangle);
StephaneLenclud@122
   900
					//iBmp.Save("D:\\capture.png");
sl@16
   901
StephaneLenclud@122
   902
					//Send it to our display
StephaneLenclud@122
   903
					for (int i = 0; i < iBmp.Width; i++)
StephaneLenclud@122
   904
					{
StephaneLenclud@122
   905
						for (int j = 0; j < iBmp.Height; j++)
StephaneLenclud@122
   906
						{
StephaneLenclud@122
   907
							unchecked
StephaneLenclud@122
   908
							{
StephaneLenclud@122
   909
								//Get our processed pixel coordinates
StephaneLenclud@122
   910
								int x = iScreenX(iBmp, i);
StephaneLenclud@122
   911
								int y = iScreenY(iBmp, j);
StephaneLenclud@122
   912
								//Get pixel color
StephaneLenclud@122
   913
								uint color = (uint)iBmp.GetPixel(i, j).ToArgb();
StephaneLenclud@122
   914
								//Apply color effects
StephaneLenclud@122
   915
								color = iColorFx(x, y, color);
StephaneLenclud@122
   916
								//Now set our pixel
StephaneLenclud@122
   917
								iDisplay.SetPixel(x, y, color);
StephaneLenclud@122
   918
							}
StephaneLenclud@122
   919
						}
StephaneLenclud@122
   920
					}
sl@4
   921
StephaneLenclud@122
   922
					iDisplay.SwapBuffers();
StephaneLenclud@122
   923
				}
sl@4
   924
            }
sl@8
   925
sl@8
   926
            //Compute instant FPS
sl@47
   927
            toolStripStatusLabelFps.Text = (1.0/NewTickTime.Subtract(LastTickTime).TotalSeconds).ToString("F0") + " / " + (1000/timer.Interval).ToString() + " FPS";
sl@8
   928
sl@8
   929
            LastTickTime = NewTickTime;
sl@8
   930
sl@2
   931
        }
sl@3
   932
StephaneLenclud@103
   933
		/// <summary>
StephaneLenclud@103
   934
		/// Attempt to establish connection with our display hardware.
StephaneLenclud@103
   935
		/// </summary>
sl@46
   936
        private void OpenDisplayConnection()
sl@3
   937
        {
sl@46
   938
            CloseDisplayConnection();
sl@46
   939
StephaneLenclud@135
   940
            if (!iDisplay.Open((MiniDisplay.Type)cds.DisplayType))
StephaneLenclud@104
   941
            {   
StephaneLenclud@104
   942
				UpdateStatus();               
StephaneLenclud@104
   943
				toolStripStatusLabelConnect.Text = "Connection error";
sl@7
   944
            }
sl@46
   945
        }
sl@7
   946
sl@46
   947
        private void CloseDisplayConnection()
sl@46
   948
        {
StephaneLenclud@104
   949
			//Status will be updated upon receiving the closed event
StephaneLenclud@122
   950
StephaneLenclud@122
   951
			if (iDisplay == null || !iDisplay.IsOpen())
StephaneLenclud@122
   952
			{
StephaneLenclud@122
   953
				return;
StephaneLenclud@122
   954
			}
StephaneLenclud@122
   955
StephaneLenclud@122
   956
			//Do not clear if we gave up on rendering already.
StephaneLenclud@122
   957
			//This means we will keep on displaying clock on MDM166AA for instance.
StephaneLenclud@122
   958
			if (!iSkipFrameRendering)
StephaneLenclud@122
   959
			{
StephaneLenclud@122
   960
				iDisplay.Clear();
StephaneLenclud@122
   961
				iDisplay.SwapBuffers();
StephaneLenclud@122
   962
			}
StephaneLenclud@122
   963
StephaneLenclud@122
   964
			iDisplay.SetAllIconsStatus(0); //Turn off all icons
sl@46
   965
            iDisplay.Close();
sl@46
   966
        }
sl@46
   967
sl@46
   968
        private void buttonOpen_Click(object sender, EventArgs e)
sl@46
   969
        {
sl@46
   970
            OpenDisplayConnection();
sl@3
   971
        }
sl@3
   972
sl@3
   973
        private void buttonClose_Click(object sender, EventArgs e)
sl@3
   974
        {
sl@46
   975
            CloseDisplayConnection();
sl@3
   976
        }
sl@3
   977
sl@3
   978
        private void buttonClear_Click(object sender, EventArgs e)
sl@3
   979
        {
sl@3
   980
            iDisplay.Clear();
sl@3
   981
            iDisplay.SwapBuffers();
sl@3
   982
        }
sl@3
   983
sl@3
   984
        private void buttonFill_Click(object sender, EventArgs e)
sl@3
   985
        {
sl@3
   986
            iDisplay.Fill();
sl@3
   987
            iDisplay.SwapBuffers();
sl@3
   988
        }
sl@3
   989
sl@3
   990
        private void trackBarBrightness_Scroll(object sender, EventArgs e)
sl@3
   991
        {
sl@48
   992
            cds.Brightness = trackBarBrightness.Value;
sl@9
   993
            Properties.Settings.Default.Save();
sl@3
   994
            iDisplay.SetBrightness(trackBarBrightness.Value);
sl@9
   995
sl@3
   996
        }
sl@7
   997
sl@48
   998
sl@48
   999
        /// <summary>
sl@48
  1000
        /// CDS stands for Current Display Settings
sl@48
  1001
        /// </summary>
sl@50
  1002
        private DisplaySettings cds
sl@48
  1003
        {
sl@48
  1004
            get
sl@48
  1005
            {
sl@65
  1006
                DisplaysSettings settings = Properties.Settings.Default.DisplaysSettings;
sl@51
  1007
                if (settings == null)
sl@51
  1008
                {
sl@51
  1009
                    settings = new DisplaysSettings();
sl@51
  1010
                    settings.Init();
sl@65
  1011
                    Properties.Settings.Default.DisplaysSettings = settings;
sl@51
  1012
                }
sl@48
  1013
sl@48
  1014
                //Make sure all our settings have been created
sl@48
  1015
                while (settings.Displays.Count <= Properties.Settings.Default.CurrentDisplayIndex)
sl@48
  1016
                {
sl@50
  1017
                    settings.Displays.Add(new DisplaySettings());
sl@48
  1018
                }
sl@48
  1019
sl@50
  1020
                DisplaySettings displaySettings = settings.Displays[Properties.Settings.Default.CurrentDisplayIndex];
sl@48
  1021
                return displaySettings;
sl@48
  1022
            }
sl@48
  1023
        }
sl@48
  1024
sl@54
  1025
        /// <summary>
sl@54
  1026
        /// Check if the given font has a fixed character pitch.
sl@54
  1027
        /// </summary>
sl@54
  1028
        /// <param name="ft"></param>
sl@54
  1029
        /// <returns>0.0f if this is not a monospace font, otherwise returns the character width.</returns>
sl@54
  1030
        public float IsFixedWidth(Font ft)
sl@54
  1031
        {
sl@54
  1032
            Graphics g = CreateGraphics();
sl@54
  1033
            char[] charSizes = new char[] { 'i', 'a', 'Z', '%', '#', 'a', 'B', 'l', 'm', ',', '.' };
sl@54
  1034
            float charWidth = g.MeasureString("I", ft, Int32.MaxValue, StringFormat.GenericTypographic).Width;
sl@54
  1035
sl@54
  1036
            bool fixedWidth = true;
sl@54
  1037
sl@54
  1038
            foreach (char c in charSizes)
sl@54
  1039
                if (g.MeasureString(c.ToString(), ft, Int32.MaxValue, StringFormat.GenericTypographic).Width != charWidth)
sl@54
  1040
                    fixedWidth = false;
sl@54
  1041
sl@54
  1042
            if (fixedWidth)
sl@54
  1043
            {
sl@54
  1044
                return charWidth;
sl@54
  1045
            }
sl@54
  1046
sl@54
  1047
            return 0.0f;
sl@54
  1048
        }
sl@54
  1049
StephaneLenclud@103
  1050
		/// <summary>
StephaneLenclud@103
  1051
		/// Synchronize UI with settings
StephaneLenclud@103
  1052
		/// </summary>
sl@7
  1053
        private void UpdateStatus()
StephaneLenclud@103
  1054
        {            
sl@48
  1055
            //Load settings
sl@54
  1056
            checkBoxShowBorders.Checked = cds.ShowBorders;
StephaneLenclud@175
  1057
            iTableLayoutPanel.CellBorderStyle = (cds.ShowBorders ? TableLayoutPanelCellBorderStyle.Single : TableLayoutPanelCellBorderStyle.None);
sl@60
  1058
sl@60
  1059
            //Set the proper font to each of our labels
StephaneLenclud@175
  1060
            foreach (MarqueeLabel ctrl in iTableLayoutPanel.Controls)
sl@60
  1061
            {
sl@60
  1062
                ctrl.Font = cds.Font;
sl@60
  1063
            }
sl@60
  1064
sl@54
  1065
            CheckFontHeight();
sl@96
  1066
			//Check if "run on Windows startup" is enabled
sl@96
  1067
			checkBoxAutoStart.Checked = iStartupManager.Startup;
sl@96
  1068
			//
sl@48
  1069
            checkBoxConnectOnStartup.Checked = Properties.Settings.Default.DisplayConnectOnStartup;
sl@94
  1070
			checkBoxMinimizeToTray.Checked = Properties.Settings.Default.MinimizeToTray;
sl@94
  1071
			checkBoxStartMinimized.Checked = Properties.Settings.Default.StartMinimized;
StephaneLenclud@126
  1072
			labelStartFileName.Text = Properties.Settings.Default.StartFileName;
StephaneLenclud@153
  1073
StephaneLenclud@153
  1074
            //Try find our drive in our drive list
StephaneLenclud@153
  1075
            int opticalDriveItemIndex=0;
StephaneLenclud@153
  1076
            bool driveNotFound = true;
StephaneLenclud@153
  1077
            string opticalDriveToEject=Properties.Settings.Default.OpticalDriveToEject;
StephaneLenclud@153
  1078
            foreach (object item in comboBoxOpticalDrives.Items)
StephaneLenclud@153
  1079
            {
StephaneLenclud@154
  1080
                if (opticalDriveToEject == item.ToString())
StephaneLenclud@153
  1081
                {
StephaneLenclud@153
  1082
                    comboBoxOpticalDrives.SelectedIndex = opticalDriveItemIndex;
StephaneLenclud@153
  1083
                    driveNotFound = false;
StephaneLenclud@153
  1084
                    break;
StephaneLenclud@153
  1085
                }
StephaneLenclud@153
  1086
                opticalDriveItemIndex++;
StephaneLenclud@153
  1087
            }
StephaneLenclud@153
  1088
StephaneLenclud@153
  1089
            if (driveNotFound)
StephaneLenclud@153
  1090
            {
StephaneLenclud@153
  1091
                //We could not find the drive we had saved.
StephaneLenclud@153
  1092
                //Select "None" then.
StephaneLenclud@153
  1093
                comboBoxOpticalDrives.SelectedIndex = 0;
StephaneLenclud@153
  1094
            }
StephaneLenclud@153
  1095
StephaneLenclud@168
  1096
            //CEC settings
StephaneLenclud@168
  1097
            checkBoxCecEnabled.Checked = Properties.Settings.Default.CecEnabled;
StephaneLenclud@168
  1098
            checkBoxCecMonitorOn.Checked = Properties.Settings.Default.CecMonitorOn;
StephaneLenclud@168
  1099
            checkBoxCecMonitorOff.Checked = Properties.Settings.Default.CecMonitorOff;
StephaneLenclud@168
  1100
            comboBoxHdmiPort.SelectedIndex = Properties.Settings.Default.CecHdmiPort - 1;
StephaneLenclud@153
  1101
StephaneLenclud@168
  1102
            //Mini Display settings
sl@48
  1103
            checkBoxReverseScreen.Checked = cds.ReverseScreen;
sl@57
  1104
            checkBoxInverseColors.Checked = cds.InverseColors;
StephaneLenclud@115
  1105
			checkBoxShowVolumeLabel.Checked = cds.ShowVolumeLabel;
sl@100
  1106
            checkBoxScaleToFit.Checked = cds.ScaleToFit;
sl@100
  1107
            maskedTextBoxMinFontSize.Enabled = cds.ScaleToFit;
sl@100
  1108
            labelMinFontSize.Enabled = cds.ScaleToFit;
sl@100
  1109
            maskedTextBoxMinFontSize.Text = cds.MinFontSize.ToString();
StephaneLenclud@106
  1110
			maskedTextBoxScrollingSpeed.Text = cds.ScrollingSpeedInPixelsPerSecond.ToString();
sl@48
  1111
            comboBoxDisplayType.SelectedIndex = cds.DisplayType;
sl@48
  1112
            timer.Interval = cds.TimerInterval;
sl@48
  1113
            maskedTextBoxTimerInterval.Text = cds.TimerInterval.ToString();
sl@100
  1114
            textBoxScrollLoopSeparator.Text = cds.Separator;
sl@58
  1115
            //
sl@58
  1116
            SetupPixelDelegates();
sl@48
  1117
sl@7
  1118
            if (iDisplay.IsOpen())
sl@7
  1119
            {
StephaneLenclud@103
  1120
				//We have a display connection
StephaneLenclud@103
  1121
				//Reflect that in our UI
StephaneLenclud@103
  1122
StephaneLenclud@175
  1123
				iTableLayoutPanel.Enabled = true;
StephaneLenclud@105
  1124
				panelDisplay.Enabled = true;
StephaneLenclud@103
  1125
sl@48
  1126
                //Only setup brightness if display is open
sl@48
  1127
                trackBarBrightness.Minimum = iDisplay.MinBrightness();
sl@48
  1128
                trackBarBrightness.Maximum = iDisplay.MaxBrightness();
StephaneLenclud@105
  1129
				if (cds.Brightness < iDisplay.MinBrightness() || cds.Brightness > iDisplay.MaxBrightness())
StephaneLenclud@105
  1130
				{
StephaneLenclud@105
  1131
					//Brightness out of range, this can occur when using auto-detect
StephaneLenclud@105
  1132
					//Use max brightness instead
StephaneLenclud@105
  1133
					trackBarBrightness.Value = iDisplay.MaxBrightness();
StephaneLenclud@105
  1134
					iDisplay.SetBrightness(iDisplay.MaxBrightness());
StephaneLenclud@105
  1135
				}
StephaneLenclud@105
  1136
				else
StephaneLenclud@105
  1137
				{
StephaneLenclud@105
  1138
					trackBarBrightness.Value = cds.Brightness;
StephaneLenclud@105
  1139
					iDisplay.SetBrightness(cds.Brightness);
StephaneLenclud@105
  1140
				}
StephaneLenclud@105
  1141
StephaneLenclud@105
  1142
				//Try compute the steps to something that makes sense
sl@48
  1143
                trackBarBrightness.LargeChange = Math.Max(1, (iDisplay.MaxBrightness() - iDisplay.MinBrightness()) / 5);
sl@48
  1144
                trackBarBrightness.SmallChange = 1;
StephaneLenclud@105
  1145
                
sl@48
  1146
                //
sl@7
  1147
                buttonFill.Enabled = true;
sl@7
  1148
                buttonClear.Enabled = true;
sl@7
  1149
                buttonOpen.Enabled = false;
sl@7
  1150
                buttonClose.Enabled = true;
sl@7
  1151
                trackBarBrightness.Enabled = true;
sl@10
  1152
                toolStripStatusLabelConnect.Text = "Connected - " + iDisplay.Vendor() + " - " + iDisplay.Product();
sl@10
  1153
                //+ " - " + iDisplay.SerialNumber();
sl@52
  1154
sl@52
  1155
                if (iDisplay.SupportPowerOnOff())
sl@52
  1156
                {
sl@52
  1157
                    buttonPowerOn.Enabled = true;
sl@52
  1158
                    buttonPowerOff.Enabled = true;
sl@52
  1159
                }
sl@52
  1160
                else
sl@52
  1161
                {
sl@52
  1162
                    buttonPowerOn.Enabled = false;
sl@52
  1163
                    buttonPowerOff.Enabled = false;
sl@52
  1164
                }
sl@53
  1165
sl@53
  1166
                if (iDisplay.SupportClock())
sl@53
  1167
                {
sl@53
  1168
                    buttonShowClock.Enabled = true;
sl@53
  1169
                    buttonHideClock.Enabled = true;
sl@53
  1170
                }
sl@53
  1171
                else
sl@53
  1172
                {
sl@53
  1173
                    buttonShowClock.Enabled = false;
sl@53
  1174
                    buttonHideClock.Enabled = false;
sl@53
  1175
                }
StephaneLenclud@115
  1176
StephaneLenclud@115
  1177
				
StephaneLenclud@115
  1178
				//Check if Volume Label is supported. To date only MDM166AA supports that crap :)
StephaneLenclud@135
  1179
				checkBoxShowVolumeLabel.Enabled = iDisplay.IconCount(MiniDisplay.IconType.VolumeLabel)>0;
StephaneLenclud@115
  1180
StephaneLenclud@115
  1181
				if (cds.ShowVolumeLabel)
StephaneLenclud@115
  1182
				{
StephaneLenclud@135
  1183
                    iDisplay.SetIconOn(MiniDisplay.IconType.VolumeLabel);
StephaneLenclud@115
  1184
				}
StephaneLenclud@115
  1185
				else
StephaneLenclud@115
  1186
				{
StephaneLenclud@135
  1187
                    iDisplay.SetIconOff(MiniDisplay.IconType.VolumeLabel);
StephaneLenclud@115
  1188
				}
sl@7
  1189
            }
sl@7
  1190
            else
sl@7
  1191
            {
StephaneLenclud@103
  1192
				//Display is connection not available
StephaneLenclud@103
  1193
				//Reflect that in our UI
StephaneLenclud@115
  1194
				checkBoxShowVolumeLabel.Enabled = false;
StephaneLenclud@175
  1195
				iTableLayoutPanel.Enabled = false;
StephaneLenclud@105
  1196
				panelDisplay.Enabled = false;
sl@7
  1197
                buttonFill.Enabled = false;
sl@7
  1198
                buttonClear.Enabled = false;
sl@7
  1199
                buttonOpen.Enabled = true;
sl@7
  1200
                buttonClose.Enabled = false;
sl@7
  1201
                trackBarBrightness.Enabled = false;
sl@52
  1202
                buttonPowerOn.Enabled = false;
sl@52
  1203
                buttonPowerOff.Enabled = false;
sl@53
  1204
                buttonShowClock.Enabled = false;
sl@53
  1205
                buttonHideClock.Enabled = false;
sl@9
  1206
                toolStripStatusLabelConnect.Text = "Disconnected";
sl@48
  1207
                toolStripStatusLabelPower.Text = "N/A";
sl@7
  1208
            }
StephaneLenclud@106
  1209
sl@7
  1210
        }
sl@9
  1211
sl@13
  1212
StephaneLenclud@115
  1213
		/// <summary>
StephaneLenclud@115
  1214
		/// 
StephaneLenclud@115
  1215
		/// </summary>
StephaneLenclud@115
  1216
		/// <param name="sender"></param>
StephaneLenclud@115
  1217
		/// <param name="e"></param>
StephaneLenclud@115
  1218
		private void checkBoxShowVolumeLabel_CheckedChanged(object sender, EventArgs e)
StephaneLenclud@115
  1219
		{
StephaneLenclud@115
  1220
			cds.ShowVolumeLabel = checkBoxShowVolumeLabel.Checked;
StephaneLenclud@115
  1221
			Properties.Settings.Default.Save();
StephaneLenclud@115
  1222
			UpdateStatus();
StephaneLenclud@115
  1223
		}
sl@13
  1224
sl@9
  1225
        private void checkBoxShowBorders_CheckedChanged(object sender, EventArgs e)
sl@9
  1226
        {
sl@16
  1227
            //Save our show borders setting
StephaneLenclud@175
  1228
            iTableLayoutPanel.CellBorderStyle = (checkBoxShowBorders.Checked ? TableLayoutPanelCellBorderStyle.Single : TableLayoutPanelCellBorderStyle.None);
sl@48
  1229
            cds.ShowBorders = checkBoxShowBorders.Checked;
sl@9
  1230
            Properties.Settings.Default.Save();
sl@57
  1231
            CheckFontHeight();
sl@9
  1232
        }
sl@13
  1233
sl@13
  1234
        private void checkBoxConnectOnStartup_CheckedChanged(object sender, EventArgs e)
sl@13
  1235
        {
sl@16
  1236
            //Save our connect on startup setting
sl@13
  1237
            Properties.Settings.Default.DisplayConnectOnStartup = checkBoxConnectOnStartup.Checked;
sl@13
  1238
            Properties.Settings.Default.Save();
sl@13
  1239
        }
sl@13
  1240
sl@94
  1241
		private void checkBoxMinimizeToTray_CheckedChanged(object sender, EventArgs e)
sl@94
  1242
		{
sl@94
  1243
			//Save our "Minimize to tray" setting
sl@94
  1244
			Properties.Settings.Default.MinimizeToTray = checkBoxMinimizeToTray.Checked;
sl@94
  1245
			Properties.Settings.Default.Save();
sl@94
  1246
sl@94
  1247
		}
sl@94
  1248
sl@94
  1249
		private void checkBoxStartMinimized_CheckedChanged(object sender, EventArgs e)
sl@94
  1250
		{
sl@94
  1251
			//Save our "Start minimized" setting
sl@94
  1252
			Properties.Settings.Default.StartMinimized = checkBoxStartMinimized.Checked;
sl@94
  1253
			Properties.Settings.Default.Save();
sl@94
  1254
		}
sl@94
  1255
sl@94
  1256
		private void checkBoxAutoStart_CheckedChanged(object sender, EventArgs e)
sl@94
  1257
		{
sl@94
  1258
			iStartupManager.Startup = checkBoxAutoStart.Checked;
sl@94
  1259
		}
sl@94
  1260
sl@94
  1261
sl@16
  1262
        private void checkBoxReverseScreen_CheckedChanged(object sender, EventArgs e)
sl@16
  1263
        {
sl@16
  1264
            //Save our reverse screen setting
sl@48
  1265
            cds.ReverseScreen = checkBoxReverseScreen.Checked;
sl@16
  1266
            Properties.Settings.Default.Save();
sl@58
  1267
            SetupPixelDelegates();
sl@16
  1268
        }
sl@16
  1269
sl@57
  1270
        private void checkBoxInverseColors_CheckedChanged(object sender, EventArgs e)
sl@57
  1271
        {
sl@57
  1272
            //Save our inverse colors setting
sl@57
  1273
            cds.InverseColors = checkBoxInverseColors.Checked;
sl@57
  1274
            Properties.Settings.Default.Save();
sl@58
  1275
            SetupPixelDelegates();
sl@57
  1276
        }
sl@57
  1277
sl@100
  1278
        private void checkBoxScaleToFit_CheckedChanged(object sender, EventArgs e)
sl@100
  1279
        {
sl@100
  1280
            //Save our scale to fit setting
sl@100
  1281
            cds.ScaleToFit = checkBoxScaleToFit.Checked;
sl@100
  1282
            Properties.Settings.Default.Save();
sl@100
  1283
            //
sl@100
  1284
            labelMinFontSize.Enabled = cds.ScaleToFit;
sl@100
  1285
            maskedTextBoxMinFontSize.Enabled = cds.ScaleToFit;
sl@100
  1286
        }
sl@100
  1287
sl@14
  1288
        private void MainForm_Resize(object sender, EventArgs e)
sl@14
  1289
        {
sl@14
  1290
            if (WindowState == FormWindowState.Minimized)
sl@14
  1291
            {
StephaneLenclud@158
  1292
                // To workaround our empty bitmap bug on Windows 7 we need to recreate our bitmap when the application is minimized
StephaneLenclud@158
  1293
                // That's apparently not needed on Windows 10 but we better leave it in place.
sl@14
  1294
                iCreateBitmap = true;
sl@14
  1295
            }
sl@14
  1296
        }
sl@14
  1297
sl@17
  1298
        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
sl@17
  1299
        {
StephaneLenclud@167
  1300
            iCecManager.Stop();
StephaneLenclud@117
  1301
			iNetworkManager.Dispose();
StephaneLenclud@105
  1302
			CloseDisplayConnection();
sl@17
  1303
            StopServer();
sl@32
  1304
            e.Cancel = iClosing;
sl@17
  1305
        }
sl@17
  1306
sl@17
  1307
        public void StartServer()
sl@17
  1308
        {
sl@17
  1309
            iServiceHost = new ServiceHost
sl@17
  1310
                (
sl@55
  1311
                    typeof(Session),
sl@20
  1312
                    new Uri[] { new Uri("net.tcp://localhost:8001/") }
sl@17
  1313
                );
sl@17
  1314
sl@55
  1315
            iServiceHost.AddServiceEndpoint(typeof(IService), new NetTcpBinding(SecurityMode.None, true), "DisplayService");
sl@17
  1316
            iServiceHost.Open();
sl@17
  1317
        }
sl@17
  1318
sl@17
  1319
        public void StopServer()
sl@17
  1320
        {
sl@32
  1321
            if (iClients.Count > 0 && !iClosing)
sl@29
  1322
            {
sl@29
  1323
                //Tell our clients
sl@32
  1324
                iClosing = true;
sl@29
  1325
                BroadcastCloseEvent();
sl@29
  1326
            }
sl@32
  1327
            else if (iClosing)
sl@32
  1328
            {
sl@32
  1329
                if (MessageBox.Show("Force exit?", "Waiting for clients...", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes)
sl@32
  1330
                {
sl@32
  1331
                    iClosing = false; //We make sure we force close if asked twice
sl@32
  1332
                }
sl@32
  1333
            }
sl@32
  1334
            else
sl@36
  1335
            {
sl@32
  1336
                //We removed that as it often lags for some reason
sl@32
  1337
                //iServiceHost.Close();
sl@32
  1338
            }
sl@17
  1339
        }
sl@17
  1340
sl@21
  1341
        public void BroadcastCloseEvent()
sl@21
  1342
        {
sl@31
  1343
            Trace.TraceInformation("BroadcastCloseEvent - start");
sl@31
  1344
sl@21
  1345
            var inactiveClients = new List<string>();
sl@21
  1346
            foreach (var client in iClients)
sl@21
  1347
            {
sl@21
  1348
                //if (client.Key != eventData.ClientName)
sl@21
  1349
                {
sl@21
  1350
                    try
sl@21
  1351
                    {
sl@31
  1352
                        Trace.TraceInformation("BroadcastCloseEvent - " + client.Key);
sl@33
  1353
                        client.Value.Callback.OnCloseOrder(/*eventData*/);
sl@21
  1354
                    }
sl@21
  1355
                    catch (Exception ex)
sl@21
  1356
                    {
sl@21
  1357
                        inactiveClients.Add(client.Key);
sl@21
  1358
                    }
sl@21
  1359
                }
sl@21
  1360
            }
sl@21
  1361
sl@21
  1362
            if (inactiveClients.Count > 0)
sl@21
  1363
            {
sl@21
  1364
                foreach (var client in inactiveClients)
sl@21
  1365
                {
sl@21
  1366
                    iClients.Remove(client);
sl@30
  1367
                    Program.iMainForm.treeViewClients.Nodes.Remove(Program.iMainForm.treeViewClients.Nodes.Find(client, false)[0]);
sl@21
  1368
                }
sl@21
  1369
            }
sl@97
  1370
sl@97
  1371
			if (iClients.Count==0)
sl@97
  1372
			{
sl@97
  1373
				ClearLayout();
sl@97
  1374
			}
sl@21
  1375
        }
sl@21
  1376
sl@97
  1377
		/// <summary>
sl@97
  1378
		/// Just remove all our fields.
sl@97
  1379
		/// </summary>
sl@97
  1380
		private void ClearLayout()
sl@97
  1381
		{
StephaneLenclud@175
  1382
			iTableLayoutPanel.Controls.Clear();
StephaneLenclud@175
  1383
			iTableLayoutPanel.RowStyles.Clear();
StephaneLenclud@175
  1384
			iTableLayoutPanel.ColumnStyles.Clear();
StephaneLenclud@122
  1385
			iCurrentClientData = null;
sl@97
  1386
		}
sl@97
  1387
StephaneLenclud@106
  1388
		/// <summary>
StephaneLenclud@106
  1389
		/// Just launch a demo client.
StephaneLenclud@106
  1390
		/// </summary>
StephaneLenclud@106
  1391
		private void StartNewClient(string aTopText = "", string aBottomText = "")
StephaneLenclud@106
  1392
		{
StephaneLenclud@106
  1393
			Thread clientThread = new Thread(SharpDisplayClient.Program.MainWithParams);
StephaneLenclud@106
  1394
			SharpDisplayClient.StartParams myParams = new SharpDisplayClient.StartParams(new Point(this.Right, this.Top),aTopText,aBottomText);
StephaneLenclud@106
  1395
			clientThread.Start(myParams);
StephaneLenclud@106
  1396
			BringToFront();
StephaneLenclud@106
  1397
		}
StephaneLenclud@106
  1398
sl@25
  1399
        private void buttonStartClient_Click(object sender, EventArgs e)
sl@25
  1400
        {
StephaneLenclud@106
  1401
			StartNewClient();
sl@25
  1402
        }
sl@25
  1403
sl@27
  1404
        private void buttonSuspend_Click(object sender, EventArgs e)
sl@27
  1405
        {
sl@52
  1406
            LastTickTime = DateTime.Now; //Reset timer to prevent jump
sl@27
  1407
            timer.Enabled = !timer.Enabled;
sl@27
  1408
            if (!timer.Enabled)
sl@27
  1409
            {
sl@52
  1410
                buttonSuspend.Text = "Run";
sl@27
  1411
            }
sl@27
  1412
            else
sl@27
  1413
            {
sl@27
  1414
                buttonSuspend.Text = "Pause";
sl@27
  1415
            }
sl@27
  1416
        }
sl@27
  1417
sl@29
  1418
        private void buttonCloseClients_Click(object sender, EventArgs e)
sl@29
  1419
        {
sl@29
  1420
            BroadcastCloseEvent();
sl@29
  1421
        }
sl@29
  1422
sl@30
  1423
        private void treeViewClients_AfterSelect(object sender, TreeViewEventArgs e)
sl@30
  1424
        {
StephaneLenclud@141
  1425
            //Root node must have at least one child
StephaneLenclud@141
  1426
            if (e.Node.Nodes.Count == 0)
StephaneLenclud@141
  1427
            {
StephaneLenclud@141
  1428
                return;
StephaneLenclud@141
  1429
            }
sl@21
  1430
StephaneLenclud@141
  1431
            //If the selected node is the root node of a client then switch to it
StephaneLenclud@141
  1432
            string sessionId=e.Node.Nodes[0].Text; //First child of a root node is the sessionId
StephaneLenclud@141
  1433
            if (iClients.ContainsKey(sessionId)) //Check that's actually what we are looking at
StephaneLenclud@141
  1434
            {
StephaneLenclud@141
  1435
                //We have a valid session just switch to that client
StephaneLenclud@141
  1436
                SetCurrentClient(sessionId,true);
StephaneLenclud@141
  1437
            }
StephaneLenclud@141
  1438
            
sl@30
  1439
        }
sl@30
  1440
sl@36
  1441
sl@30
  1442
        /// <summary>
sl@36
  1443
        ///
sl@30
  1444
        /// </summary>
sl@30
  1445
        /// <param name="aSessionId"></param>
sl@30
  1446
        /// <param name="aCallback"></param>
sl@55
  1447
        public void AddClientThreadSafe(string aSessionId, ICallback aCallback)
sl@30
  1448
        {
sl@33
  1449
            if (this.InvokeRequired)
sl@30
  1450
            {
sl@30
  1451
                //Not in the proper thread, invoke ourselves
sl@30
  1452
                AddClientDelegate d = new AddClientDelegate(AddClientThreadSafe);
sl@30
  1453
                this.Invoke(d, new object[] { aSessionId, aCallback });
sl@30
  1454
            }
sl@30
  1455
            else
sl@30
  1456
            {
sl@30
  1457
                //We are in the proper thread
sl@30
  1458
                //Add this session to our collection of clients
sl@33
  1459
                ClientData newClient = new ClientData(aSessionId, aCallback);
sl@33
  1460
                Program.iMainForm.iClients.Add(aSessionId, newClient);
sl@30
  1461
                //Add this session to our UI
sl@33
  1462
                UpdateClientTreeViewNode(newClient);
sl@30
  1463
            }
sl@30
  1464
        }
sl@30
  1465
sl@30
  1466
        /// <summary>
sl@36
  1467
        ///
sl@30
  1468
        /// </summary>
sl@30
  1469
        /// <param name="aSessionId"></param>
sl@30
  1470
        public void RemoveClientThreadSafe(string aSessionId)
sl@30
  1471
        {
sl@33
  1472
            if (this.InvokeRequired)
sl@30
  1473
            {
sl@30
  1474
                //Not in the proper thread, invoke ourselves
sl@30
  1475
                RemoveClientDelegate d = new RemoveClientDelegate(RemoveClientThreadSafe);
sl@30
  1476
                this.Invoke(d, new object[] { aSessionId });
sl@30
  1477
            }
sl@30
  1478
            else
sl@30
  1479
            {
sl@30
  1480
                //We are in the proper thread
sl@33
  1481
                //Remove this session from both client collection and UI tree view
sl@30
  1482
                if (Program.iMainForm.iClients.Keys.Contains(aSessionId))
sl@30
  1483
                {
sl@30
  1484
                    Program.iMainForm.iClients.Remove(aSessionId);
sl@30
  1485
                    Program.iMainForm.treeViewClients.Nodes.Remove(Program.iMainForm.treeViewClients.Nodes.Find(aSessionId, false)[0]);
sl@32
  1486
                }
sl@32
  1487
sl@97
  1488
				if (iClients.Count == 0)
sl@97
  1489
				{
sl@97
  1490
					//Clear our screen when last client disconnects
sl@97
  1491
					ClearLayout();
sl@97
  1492
sl@97
  1493
					if (iClosing)
sl@97
  1494
					{
sl@97
  1495
						//We were closing our form
sl@97
  1496
						//All clients are now closed
sl@97
  1497
						//Just resume our close operation
sl@97
  1498
						iClosing = false;
sl@97
  1499
						Close();
sl@97
  1500
					}
sl@97
  1501
				}
sl@30
  1502
            }
sl@30
  1503
        }
sl@30
  1504
sl@30
  1505
        /// <summary>
sl@36
  1506
        ///
sl@30
  1507
        /// </summary>
sl@62
  1508
        /// <param name="aSessionId"></param>
sl@72
  1509
        /// <param name="aLayout"></param>
sl@62
  1510
        public void SetClientLayoutThreadSafe(string aSessionId, TableLayout aLayout)
sl@62
  1511
        {
sl@62
  1512
            if (this.InvokeRequired)
sl@62
  1513
            {
sl@62
  1514
                //Not in the proper thread, invoke ourselves
sl@62
  1515
                SetLayoutDelegate d = new SetLayoutDelegate(SetClientLayoutThreadSafe);
sl@62
  1516
                this.Invoke(d, new object[] { aSessionId, aLayout });
sl@62
  1517
            }
sl@62
  1518
            else
sl@62
  1519
            {
sl@62
  1520
                ClientData client = iClients[aSessionId];
sl@62
  1521
                if (client != null)
sl@62
  1522
                {
StephaneLenclud@148
  1523
                    //Don't change a thing if the layout is the same
StephaneLenclud@148
  1524
                    if (!client.Layout.IsSameAs(aLayout))
StephaneLenclud@148
  1525
                    {
StephaneLenclud@158
  1526
                        Debug.Print("SetClientLayoutThreadSafe: Layout updated.");
StephaneLenclud@148
  1527
                        //Set our client layout then
StephaneLenclud@148
  1528
                        client.Layout = aLayout;
StephaneLenclud@175
  1529
                        //So that next time we update all our fields at ones
StephaneLenclud@175
  1530
                        client.HasNewLayout = true;
StephaneLenclud@158
  1531
                        //Layout has changed clear our fields then
StephaneLenclud@158
  1532
                        client.Fields.Clear();
StephaneLenclud@148
  1533
                        //
StephaneLenclud@148
  1534
                        UpdateClientTreeViewNode(client);
StephaneLenclud@148
  1535
                    }
StephaneLenclud@158
  1536
                    else
StephaneLenclud@158
  1537
                    {
StephaneLenclud@158
  1538
                        Debug.Print("SetClientLayoutThreadSafe: Layout has not changed.");
StephaneLenclud@158
  1539
                    }
sl@62
  1540
                }
sl@62
  1541
            }
sl@62
  1542
        }
sl@62
  1543
sl@62
  1544
        /// <summary>
sl@62
  1545
        ///
sl@62
  1546
        /// </summary>
sl@67
  1547
        /// <param name="aSessionId"></param>
sl@72
  1548
        /// <param name="aField"></param>
sl@75
  1549
        public void SetClientFieldThreadSafe(string aSessionId, DataField aField)
sl@30
  1550
        {
sl@33
  1551
            if (this.InvokeRequired)
sl@30
  1552
            {
sl@30
  1553
                //Not in the proper thread, invoke ourselves
sl@79
  1554
                SetFieldDelegate d = new SetFieldDelegate(SetClientFieldThreadSafe);
sl@72
  1555
                this.Invoke(d, new object[] { aSessionId, aField });
sl@30
  1556
            }
sl@30
  1557
            else
sl@30
  1558
            {
sl@75
  1559
                //We are in the proper thread
sl@75
  1560
                //Call the non-thread-safe variant
sl@75
  1561
                SetClientField(aSessionId, aField);
sl@75
  1562
            }
sl@75
  1563
        }
sl@75
  1564
StephaneLenclud@176
  1565
StephaneLenclud@176
  1566
StephaneLenclud@176
  1567
sl@75
  1568
        /// <summary>
StephaneLenclud@175
  1569
        /// Set a data field in the given client.
sl@75
  1570
        /// </summary>
sl@75
  1571
        /// <param name="aSessionId"></param>
sl@75
  1572
        /// <param name="aField"></param>
sl@75
  1573
        private void SetClientField(string aSessionId, DataField aField)
StephaneLenclud@141
  1574
        {   
StephaneLenclud@141
  1575
            //TODO: should check if the field actually changed?
StephaneLenclud@141
  1576
sl@75
  1577
            ClientData client = iClients[aSessionId];
StephaneLenclud@141
  1578
            bool layoutChanged = false;
StephaneLenclud@148
  1579
            bool contentChanged = true;
StephaneLenclud@141
  1580
StephaneLenclud@176
  1581
            //Fetch our field index
StephaneLenclud@176
  1582
            int fieldIndex = client.FindSameFieldIndex(aField);
StephaneLenclud@176
  1583
StephaneLenclud@176
  1584
            if (fieldIndex < 0)
sl@75
  1585
            {
StephaneLenclud@176
  1586
                //No corresponding field, just bail out
StephaneLenclud@176
  1587
                return;
StephaneLenclud@141
  1588
            }
sl@76
  1589
StephaneLenclud@175
  1590
            //Keep our previous field in there
StephaneLenclud@176
  1591
            DataField previousField = client.Fields[fieldIndex];
StephaneLenclud@176
  1592
            //Just update that field then 
StephaneLenclud@176
  1593
            client.Fields[fieldIndex] = aField;
StephaneLenclud@148
  1594
StephaneLenclud@176
  1595
            if (!aField.IsTableField)
StephaneLenclud@176
  1596
            {
StephaneLenclud@176
  1597
                //We are done then if that field is not in our table layout
StephaneLenclud@176
  1598
                return;
StephaneLenclud@176
  1599
            }
StephaneLenclud@176
  1600
StephaneLenclud@176
  1601
            TableField tableField = (TableField) aField;
StephaneLenclud@172
  1602
StephaneLenclud@175
  1603
            if (previousField.IsSameLayout(aField))
StephaneLenclud@141
  1604
            {
StephaneLenclud@141
  1605
                //If we are updating a field in our current client we need to update it in our panel
StephaneLenclud@141
  1606
                if (aSessionId == iCurrentClientSessionId)
sl@30
  1607
                {
StephaneLenclud@176
  1608
                    Control ctrl=iTableLayoutPanel.GetControlFromPosition(tableField.Column, tableField.Row);
StephaneLenclud@176
  1609
                    if (aField.IsTextField && ctrl is MarqueeLabel)
sl@79
  1610
                    {
StephaneLenclud@172
  1611
                        TextField textField=(TextField)aField;
sl@75
  1612
                        //Text field control already in place, just change the text
StephaneLenclud@176
  1613
                        MarqueeLabel label = (MarqueeLabel)ctrl;
StephaneLenclud@172
  1614
                        contentChanged = (label.Text != textField.Text || label.TextAlign != textField.Alignment);
StephaneLenclud@172
  1615
                        label.Text = textField.Text;
StephaneLenclud@172
  1616
                        label.TextAlign = textField.Alignment;
sl@68
  1617
                    }
StephaneLenclud@176
  1618
                    else if (aField.IsBitmapField && ctrl is PictureBox)
sl@75
  1619
                    {
StephaneLenclud@172
  1620
                        BitmapField bitmapField = (BitmapField)aField;
StephaneLenclud@148
  1621
                        contentChanged = true; //TODO: Bitmap comp or should we leave that to clients?
sl@75
  1622
                        //Bitmap field control already in place just change the bitmap
StephaneLenclud@176
  1623
                        PictureBox pictureBox = (PictureBox)ctrl;
StephaneLenclud@172
  1624
                        pictureBox.Image = bitmapField.Bitmap;
sl@75
  1625
                    }
sl@68
  1626
                    else
sl@68
  1627
                    {
StephaneLenclud@141
  1628
                        layoutChanged = true;
sl@68
  1629
                    }
sl@30
  1630
                }
StephaneLenclud@141
  1631
            }
StephaneLenclud@141
  1632
            else
StephaneLenclud@148
  1633
            {                
StephaneLenclud@141
  1634
                layoutChanged = true;
StephaneLenclud@141
  1635
            }
StephaneLenclud@141
  1636
StephaneLenclud@148
  1637
            //If either content or layout changed we need to update our tree view to reflect the changes
StephaneLenclud@148
  1638
            if (contentChanged || layoutChanged)
StephaneLenclud@141
  1639
            {
StephaneLenclud@141
  1640
                UpdateClientTreeViewNode(client);
StephaneLenclud@148
  1641
                //
StephaneLenclud@148
  1642
                if (layoutChanged)
sl@75
  1643
                {
StephaneLenclud@148
  1644
                    Debug.Print("Layout changed");
StephaneLenclud@148
  1645
                    //Our layout has changed, if we are already the current client we need to update our panel
StephaneLenclud@148
  1646
                    if (aSessionId == iCurrentClientSessionId)
StephaneLenclud@148
  1647
                    {
StephaneLenclud@148
  1648
                        //Apply layout and set data fields.
StephaneLenclud@148
  1649
                        UpdateTableLayoutPanel(iCurrentClientData);
StephaneLenclud@148
  1650
                    }
sl@75
  1651
                }
StephaneLenclud@158
  1652
                else
StephaneLenclud@158
  1653
                {
StephaneLenclud@158
  1654
                    Debug.Print("Layout has not changed.");
StephaneLenclud@158
  1655
                }
StephaneLenclud@158
  1656
            }
StephaneLenclud@158
  1657
            else
StephaneLenclud@158
  1658
            {
StephaneLenclud@158
  1659
                Debug.Print("WARNING: content and layout have not changed!");
StephaneLenclud@141
  1660
            }
sl@75
  1661
StephaneLenclud@141
  1662
            //When a client field is set we try switching to this client to present the new information to our user
StephaneLenclud@141
  1663
            SetCurrentClient(aSessionId);
sl@30
  1664
        }
sl@30
  1665
sl@30
  1666
        /// <summary>
sl@36
  1667
        ///
sl@30
  1668
        /// </summary>
sl@30
  1669
        /// <param name="aTexts"></param>
sl@75
  1670
        public void SetClientFieldsThreadSafe(string aSessionId, System.Collections.Generic.IList<DataField> aFields)
sl@30
  1671
        {
sl@33
  1672
            if (this.InvokeRequired)
sl@30
  1673
            {
sl@30
  1674
                //Not in the proper thread, invoke ourselves
sl@75
  1675
                SetFieldsDelegate d = new SetFieldsDelegate(SetClientFieldsThreadSafe);
sl@72
  1676
                this.Invoke(d, new object[] { aSessionId, aFields });
sl@30
  1677
            }
sl@30
  1678
            else
sl@30
  1679
            {
StephaneLenclud@175
  1680
                ClientData client = iClients[aSessionId];
StephaneLenclud@175
  1681
StephaneLenclud@175
  1682
                if (client.HasNewLayout)
sl@30
  1683
                {
StephaneLenclud@175
  1684
                    //TODO: Assert client.Count == 0
StephaneLenclud@175
  1685
                    //Our layout was just changed
StephaneLenclud@175
  1686
                    //Do some special handling to avoid re-creating our panel N times, once for each fields
StephaneLenclud@175
  1687
                    client.HasNewLayout = false;
StephaneLenclud@175
  1688
                    //Just set all our fields then
StephaneLenclud@175
  1689
                    client.Fields.AddRange(aFields);
StephaneLenclud@175
  1690
                    //Try switch to that client
StephaneLenclud@175
  1691
                    SetCurrentClient(aSessionId);
StephaneLenclud@175
  1692
StephaneLenclud@175
  1693
                    //If we are updating the current client update our panel
StephaneLenclud@175
  1694
                    if (aSessionId == iCurrentClientSessionId)
StephaneLenclud@175
  1695
                    {
StephaneLenclud@175
  1696
                        //Apply layout and set data fields.
StephaneLenclud@175
  1697
                        UpdateTableLayoutPanel(iCurrentClientData);
StephaneLenclud@175
  1698
                    }
StephaneLenclud@176
  1699
StephaneLenclud@176
  1700
                    UpdateClientTreeViewNode(client);
StephaneLenclud@175
  1701
                }
StephaneLenclud@175
  1702
                else
StephaneLenclud@175
  1703
                {
StephaneLenclud@175
  1704
                    //Put each our text fields in a label control
StephaneLenclud@175
  1705
                    foreach (DataField field in aFields)
StephaneLenclud@175
  1706
                    {
StephaneLenclud@175
  1707
                        SetClientField(aSessionId, field);
StephaneLenclud@175
  1708
                    }
sl@30
  1709
                }
sl@30
  1710
            }
sl@32
  1711
        }
sl@30
  1712
sl@67
  1713
        /// <summary>
sl@67
  1714
        ///
sl@67
  1715
        /// </summary>
sl@67
  1716
        /// <param name="aSessionId"></param>
sl@32
  1717
        /// <param name="aName"></param>
sl@32
  1718
        public void SetClientNameThreadSafe(string aSessionId, string aName)
sl@32
  1719
        {
sl@32
  1720
            if (this.InvokeRequired)
sl@32
  1721
            {
sl@32
  1722
                //Not in the proper thread, invoke ourselves
sl@32
  1723
                SetClientNameDelegate d = new SetClientNameDelegate(SetClientNameThreadSafe);
sl@32
  1724
                this.Invoke(d, new object[] { aSessionId, aName });
sl@32
  1725
            }
sl@32
  1726
            else
sl@32
  1727
            {
sl@32
  1728
                //We are in the proper thread
sl@33
  1729
                //Get our client
sl@33
  1730
                ClientData client = iClients[aSessionId];
sl@33
  1731
                if (client != null)
sl@32
  1732
                {
sl@33
  1733
                    //Set its name
sl@33
  1734
                    client.Name = aName;
sl@33
  1735
                    //Update our tree-view
sl@33
  1736
                    UpdateClientTreeViewNode(client);
sl@33
  1737
                }
sl@33
  1738
            }
sl@33
  1739
        }
sl@33
  1740
sl@33
  1741
        /// <summary>
sl@36
  1742
        ///
sl@33
  1743
        /// </summary>
sl@33
  1744
        /// <param name="aClient"></param>
sl@33
  1745
        private void UpdateClientTreeViewNode(ClientData aClient)
sl@33
  1746
        {
StephaneLenclud@148
  1747
            Debug.Print("UpdateClientTreeViewNode");
StephaneLenclud@148
  1748
sl@33
  1749
            if (aClient == null)
sl@33
  1750
            {
sl@33
  1751
                return;
sl@33
  1752
            }
sl@33
  1753
sl@33
  1754
            TreeNode node = null;
sl@33
  1755
            //Check that our client node already exists
sl@33
  1756
            //Get our client root node using its key which is our session ID
sl@33
  1757
            TreeNode[] nodes = treeViewClients.Nodes.Find(aClient.SessionId, false);
sl@33
  1758
            if (nodes.Count()>0)
sl@33
  1759
            {
sl@33
  1760
                //We already have a node for that client
sl@33
  1761
                node = nodes[0];
sl@33
  1762
                //Clear children as we are going to recreate them below
sl@33
  1763
                node.Nodes.Clear();
sl@33
  1764
            }
sl@33
  1765
            else
sl@33
  1766
            {
sl@33
  1767
                //Client node does not exists create a new one
sl@33
  1768
                treeViewClients.Nodes.Add(aClient.SessionId, aClient.SessionId);
sl@33
  1769
                node = treeViewClients.Nodes.Find(aClient.SessionId, false)[0];
sl@33
  1770
            }
sl@33
  1771
sl@33
  1772
            if (node != null)
sl@33
  1773
            {
sl@33
  1774
                //Change its name
sl@33
  1775
                if (aClient.Name != "")
sl@33
  1776
                {
sl@33
  1777
                    //We have a name, us it as text for our root node
sl@33
  1778
                    node.Text = aClient.Name;
sl@32
  1779
                    //Add a child with SessionId
sl@33
  1780
                    node.Nodes.Add(new TreeNode(aClient.SessionId));
sl@33
  1781
                }
sl@33
  1782
                else
sl@33
  1783
                {
sl@33
  1784
                    //No name, use session ID instead
sl@33
  1785
                    node.Text = aClient.SessionId;
sl@33
  1786
                }
sl@36
  1787
sl@67
  1788
                if (aClient.Fields.Count > 0)
sl@33
  1789
                {
sl@33
  1790
                    //Create root node for our texts
sl@70
  1791
                    TreeNode textsRoot = new TreeNode("Fields");
sl@33
  1792
                    node.Nodes.Add(textsRoot);
sl@33
  1793
                    //For each text add a new entry
sl@67
  1794
                    foreach (DataField field in aClient.Fields)
sl@33
  1795
                    {
StephaneLenclud@172
  1796
                        if (field.IsTextField)
sl@67
  1797
                        {
StephaneLenclud@172
  1798
                            TextField textField = (TextField)field;
sl@70
  1799
                            textsRoot.Nodes.Add(new TreeNode("[Text]" + textField.Text));
sl@67
  1800
                        }
StephaneLenclud@172
  1801
                        else if (field.IsBitmapField)
sl@67
  1802
                        {
sl@72
  1803
                            textsRoot.Nodes.Add(new TreeNode("[Bitmap]"));
sl@70
  1804
                        }
StephaneLenclud@172
  1805
                        else if (field.IsRecordingField)
StephaneLenclud@172
  1806
                        {
StephaneLenclud@177
  1807
                            RecordingField recordingField = (RecordingField)field;
StephaneLenclud@177
  1808
                            textsRoot.Nodes.Add(new TreeNode("[Recording]" + recordingField.IsActive));
StephaneLenclud@172
  1809
                        }
sl@33
  1810
                    }
sl@32
  1811
                }
sl@34
  1812
sl@34
  1813
                node.ExpandAll();
sl@32
  1814
            }
sl@30
  1815
        }
sl@17
  1816
sl@60
  1817
        /// <summary>
sl@60
  1818
        /// Update our table layout row styles to make sure each rows have similar height
sl@60
  1819
        /// </summary>
sl@60
  1820
        private void UpdateTableLayoutRowStyles()
sl@60
  1821
        {
StephaneLenclud@175
  1822
            foreach (RowStyle rowStyle in iTableLayoutPanel.RowStyles)
sl@60
  1823
            {
sl@60
  1824
                rowStyle.SizeType = SizeType.Percent;
StephaneLenclud@175
  1825
                rowStyle.Height = 100 / iTableLayoutPanel.RowCount;
sl@60
  1826
            }
sl@60
  1827
        }
sl@60
  1828
sl@63
  1829
        /// <summary>
sl@63
  1830
        /// Update our display table layout.
StephaneLenclud@175
  1831
        /// Will instanciated every field control as defined by our client.
StephaneLenclud@175
  1832
        /// Fields must be specified by rows from the left.
sl@63
  1833
        /// </summary>
sl@63
  1834
        /// <param name="aLayout"></param>
sl@65
  1835
        private void UpdateTableLayoutPanel(ClientData aClient)
sl@63
  1836
        {
StephaneLenclud@175
  1837
            Debug.Print("UpdateTableLayoutPanel");
StephaneLenclud@148
  1838
StephaneLenclud@106
  1839
			if (aClient == null)
StephaneLenclud@106
  1840
			{
StephaneLenclud@106
  1841
				//Just drop it
StephaneLenclud@106
  1842
				return;
StephaneLenclud@106
  1843
			}
StephaneLenclud@106
  1844
StephaneLenclud@106
  1845
sl@65
  1846
            TableLayout layout = aClient.Layout;
sl@70
  1847
StephaneLenclud@141
  1848
            //First clean our current panel
StephaneLenclud@175
  1849
            iTableLayoutPanel.Controls.Clear();
StephaneLenclud@175
  1850
            iTableLayoutPanel.RowStyles.Clear();
StephaneLenclud@175
  1851
            iTableLayoutPanel.ColumnStyles.Clear();
StephaneLenclud@175
  1852
            iTableLayoutPanel.RowCount = 0;
StephaneLenclud@175
  1853
            iTableLayoutPanel.ColumnCount = 0;
sl@63
  1854
StephaneLenclud@175
  1855
            //Then recreate our rows...
StephaneLenclud@175
  1856
            while (iTableLayoutPanel.RowCount < layout.Rows.Count)
sl@63
  1857
            {
StephaneLenclud@175
  1858
                iTableLayoutPanel.RowCount++;
sl@63
  1859
            }
sl@63
  1860
StephaneLenclud@175
  1861
            // ...and columns 
StephaneLenclud@175
  1862
            while (iTableLayoutPanel.ColumnCount < layout.Columns.Count)
sl@63
  1863
            {
StephaneLenclud@175
  1864
                iTableLayoutPanel.ColumnCount++;
sl@63
  1865
            }
sl@63
  1866
StephaneLenclud@175
  1867
            //For each column
StephaneLenclud@175
  1868
            for (int i = 0; i < iTableLayoutPanel.ColumnCount; i++)
sl@63
  1869
            {
sl@63
  1870
                //Create our column styles
StephaneLenclud@175
  1871
                this.iTableLayoutPanel.ColumnStyles.Add(layout.Columns[i]);
sl@63
  1872
StephaneLenclud@175
  1873
                //For each rows
StephaneLenclud@175
  1874
                for (int j = 0; j < iTableLayoutPanel.RowCount; j++)
sl@63
  1875
                {
sl@63
  1876
                    if (i == 0)
sl@63
  1877
                    {
sl@63
  1878
                        //Create our row styles
StephaneLenclud@175
  1879
                        this.iTableLayoutPanel.RowStyles.Add(layout.Rows[j]);
sl@63
  1880
                    }
StephaneLenclud@176
  1881
                    else
sl@70
  1882
                    {
sl@70
  1883
                        continue;
sl@70
  1884
                    }
sl@63
  1885
                }
sl@63
  1886
            }
sl@63
  1887
StephaneLenclud@176
  1888
            //For each field
StephaneLenclud@176
  1889
            foreach (DataField field in aClient.Fields)
sl@70
  1890
            {
StephaneLenclud@176
  1891
                if (!field.IsTableField)
StephaneLenclud@176
  1892
                {
StephaneLenclud@176
  1893
                    //That field is not taking part in our table layout skip it
StephaneLenclud@176
  1894
                    continue;
StephaneLenclud@176
  1895
                }
StephaneLenclud@176
  1896
StephaneLenclud@176
  1897
                TableField tableField = (TableField)field;
StephaneLenclud@176
  1898
StephaneLenclud@176
  1899
                //Create a control corresponding to the field specified for that cell
StephaneLenclud@176
  1900
                Control control = CreateControlForDataField(tableField);
StephaneLenclud@176
  1901
StephaneLenclud@176
  1902
                //Add newly created control to our table layout at the specified row and column
StephaneLenclud@176
  1903
                iTableLayoutPanel.Controls.Add(control, tableField.Column, tableField.Row);
StephaneLenclud@176
  1904
                //Make sure we specify column and row span for that new control
StephaneLenclud@176
  1905
                iTableLayoutPanel.SetColumnSpan(control, tableField.ColumnSpan);
StephaneLenclud@176
  1906
                iTableLayoutPanel.SetRowSpan(control, tableField.RowSpan);
sl@70
  1907
            }
sl@70
  1908
StephaneLenclud@176
  1909
sl@63
  1910
            CheckFontHeight();
sl@63
  1911
        }
sl@63
  1912
sl@68
  1913
        /// <summary>
sl@70
  1914
        /// Check our type of data field and create corresponding control
sl@68
  1915
        /// </summary>
sl@68
  1916
        /// <param name="aField"></param>
sl@69
  1917
        private Control CreateControlForDataField(DataField aField)
sl@68
  1918
        {
sl@68
  1919
            Control control=null;
StephaneLenclud@172
  1920
            if (aField.IsTextField)
sl@68
  1921
            {
sl@68
  1922
                MarqueeLabel label = new SharpDisplayManager.MarqueeLabel();
sl@68
  1923
                label.AutoEllipsis = true;
sl@68
  1924
                label.AutoSize = true;
sl@68
  1925
                label.BackColor = System.Drawing.Color.Transparent;
sl@68
  1926
                label.Dock = System.Windows.Forms.DockStyle.Fill;
sl@68
  1927
                label.Location = new System.Drawing.Point(1, 1);
sl@68
  1928
                label.Margin = new System.Windows.Forms.Padding(0);
StephaneLenclud@176
  1929
                label.Name = "marqueeLabel" + aField;
sl@68
  1930
                label.OwnTimer = false;
StephaneLenclud@106
  1931
                label.PixelsPerSecond = cds.ScrollingSpeedInPixelsPerSecond;
sl@100
  1932
                label.Separator = cds.Separator;
sl@100
  1933
                label.MinFontSize = cds.MinFontSize;
sl@100
  1934
                label.ScaleToFit = cds.ScaleToFit;
sl@68
  1935
                //control.Size = new System.Drawing.Size(254, 30);
sl@68
  1936
                //control.TabIndex = 2;
sl@68
  1937
                label.Font = cds.Font;
sl@68
  1938
StephaneLenclud@172
  1939
                TextField field = (TextField)aField;
StephaneLenclud@172
  1940
                label.TextAlign = field.Alignment;
sl@68
  1941
                label.UseCompatibleTextRendering = true;
StephaneLenclud@172
  1942
                label.Text = field.Text;
sl@68
  1943
                //
sl@68
  1944
                control = label;
sl@68
  1945
            }
StephaneLenclud@172
  1946
            else if (aField.IsBitmapField)
sl@68
  1947
            {
sl@68
  1948
                //Create picture box
sl@68
  1949
                PictureBox picture = new PictureBox();
sl@68
  1950
                picture.AutoSize = true;
sl@68
  1951
                picture.BackColor = System.Drawing.Color.Transparent;
sl@68
  1952
                picture.Dock = System.Windows.Forms.DockStyle.Fill;
sl@68
  1953
                picture.Location = new System.Drawing.Point(1, 1);
sl@68
  1954
                picture.Margin = new System.Windows.Forms.Padding(0);
sl@68
  1955
                picture.Name = "pictureBox" + aField;
sl@68
  1956
                //Set our image
StephaneLenclud@172
  1957
                BitmapField field = (BitmapField)aField;
StephaneLenclud@172
  1958
                picture.Image = field.Bitmap;
sl@68
  1959
                //
sl@68
  1960
                control = picture;
sl@68
  1961
            }
StephaneLenclud@172
  1962
            //TODO: Handle recording field?
sl@68
  1963
sl@69
  1964
            return control;
sl@68
  1965
        }
sl@68
  1966
StephaneLenclud@103
  1967
		/// <summary>
StephaneLenclud@103
  1968
		/// Called when the user selected a new display type.
StephaneLenclud@103
  1969
		/// </summary>
StephaneLenclud@103
  1970
		/// <param name="sender"></param>
StephaneLenclud@103
  1971
		/// <param name="e"></param>
sl@46
  1972
        private void comboBoxDisplayType_SelectedIndexChanged(object sender, EventArgs e)
sl@46
  1973
        {
StephaneLenclud@103
  1974
			//Store the selected display type in our settings
sl@48
  1975
            Properties.Settings.Default.CurrentDisplayIndex = comboBoxDisplayType.SelectedIndex;
sl@48
  1976
            cds.DisplayType = comboBoxDisplayType.SelectedIndex;
sl@46
  1977
            Properties.Settings.Default.Save();
StephaneLenclud@103
  1978
StephaneLenclud@103
  1979
			//Try re-opening the display connection if we were already connected.
StephaneLenclud@103
  1980
			//Otherwise just update our status to reflect display type change.
sl@51
  1981
            if (iDisplay.IsOpen())
sl@51
  1982
            {
sl@51
  1983
                OpenDisplayConnection();
sl@51
  1984
            }
sl@51
  1985
            else
sl@51
  1986
            {
sl@51
  1987
                UpdateStatus();
sl@51
  1988
            }
sl@46
  1989
        }
sl@46
  1990
sl@47
  1991
        private void maskedTextBoxTimerInterval_TextChanged(object sender, EventArgs e)
sl@47
  1992
        {
sl@47
  1993
            if (maskedTextBoxTimerInterval.Text != "")
sl@47
  1994
            {
sl@51
  1995
                int interval = Convert.ToInt32(maskedTextBoxTimerInterval.Text);
sl@51
  1996
sl@51
  1997
                if (interval > 0)
sl@51
  1998
                {
sl@51
  1999
                    timer.Interval = interval;
sl@51
  2000
                    cds.TimerInterval = timer.Interval;
sl@51
  2001
                    Properties.Settings.Default.Save();
sl@51
  2002
                }
sl@47
  2003
            }
sl@47
  2004
        }
sl@47
  2005
sl@100
  2006
        private void maskedTextBoxMinFontSize_TextChanged(object sender, EventArgs e)
sl@100
  2007
        {
sl@100
  2008
            if (maskedTextBoxMinFontSize.Text != "")
sl@100
  2009
            {
sl@100
  2010
                int minFontSize = Convert.ToInt32(maskedTextBoxMinFontSize.Text);
sl@100
  2011
sl@100
  2012
                if (minFontSize > 0)
sl@100
  2013
                {
sl@100
  2014
                    cds.MinFontSize = minFontSize;
sl@100
  2015
                    Properties.Settings.Default.Save();
StephaneLenclud@106
  2016
					//We need to recreate our layout for that change to take effect
StephaneLenclud@106
  2017
					UpdateTableLayoutPanel(iCurrentClientData);
sl@100
  2018
                }
sl@100
  2019
            }
sl@100
  2020
        }
sl@100
  2021
StephaneLenclud@106
  2022
StephaneLenclud@106
  2023
		private void maskedTextBoxScrollingSpeed_TextChanged(object sender, EventArgs e)
StephaneLenclud@106
  2024
		{
StephaneLenclud@106
  2025
			if (maskedTextBoxScrollingSpeed.Text != "")
StephaneLenclud@106
  2026
			{
StephaneLenclud@106
  2027
				int scrollingSpeed = Convert.ToInt32(maskedTextBoxScrollingSpeed.Text);
StephaneLenclud@106
  2028
StephaneLenclud@106
  2029
				if (scrollingSpeed > 0)
StephaneLenclud@106
  2030
				{
StephaneLenclud@106
  2031
					cds.ScrollingSpeedInPixelsPerSecond = scrollingSpeed;
StephaneLenclud@106
  2032
					Properties.Settings.Default.Save();
StephaneLenclud@106
  2033
					//We need to recreate our layout for that change to take effect
StephaneLenclud@106
  2034
					UpdateTableLayoutPanel(iCurrentClientData);
StephaneLenclud@106
  2035
				}
StephaneLenclud@106
  2036
			}
StephaneLenclud@106
  2037
		}
StephaneLenclud@106
  2038
sl@100
  2039
        private void textBoxScrollLoopSeparator_TextChanged(object sender, EventArgs e)
sl@100
  2040
        {
sl@100
  2041
            cds.Separator = textBoxScrollLoopSeparator.Text;
sl@100
  2042
            Properties.Settings.Default.Save();
StephaneLenclud@110
  2043
StephaneLenclud@110
  2044
			//Update our text fields
StephaneLenclud@175
  2045
			foreach (MarqueeLabel ctrl in iTableLayoutPanel.Controls)
StephaneLenclud@110
  2046
			{
StephaneLenclud@110
  2047
				ctrl.Separator = cds.Separator;
StephaneLenclud@110
  2048
			}
StephaneLenclud@110
  2049
sl@100
  2050
        }
sl@100
  2051
sl@52
  2052
        private void buttonPowerOn_Click(object sender, EventArgs e)
sl@52
  2053
        {
sl@52
  2054
            iDisplay.PowerOn();
sl@52
  2055
        }
sl@52
  2056
sl@52
  2057
        private void buttonPowerOff_Click(object sender, EventArgs e)
sl@52
  2058
        {
sl@52
  2059
            iDisplay.PowerOff();
sl@52
  2060
        }
sl@52
  2061
sl@53
  2062
        private void buttonShowClock_Click(object sender, EventArgs e)
sl@53
  2063
        {
StephaneLenclud@122
  2064
			ShowClock();
sl@53
  2065
        }
sl@53
  2066
sl@53
  2067
        private void buttonHideClock_Click(object sender, EventArgs e)
sl@53
  2068
        {
StephaneLenclud@122
  2069
			HideClock();
sl@53
  2070
        }
sl@88
  2071
sl@88
  2072
        private void buttonUpdate_Click(object sender, EventArgs e)
sl@88
  2073
        {
sl@88
  2074
            InstallUpdateSyncWithInfo();
sl@88
  2075
        }
sl@88
  2076
StephaneLenclud@122
  2077
		/// <summary>
StephaneLenclud@122
  2078
		/// 
StephaneLenclud@122
  2079
		/// </summary>
StephaneLenclud@122
  2080
		void ShowClock()
StephaneLenclud@122
  2081
		{
StephaneLenclud@122
  2082
			if (!iDisplay.IsOpen())
StephaneLenclud@122
  2083
			{
StephaneLenclud@122
  2084
				return;
StephaneLenclud@122
  2085
			}
StephaneLenclud@122
  2086
StephaneLenclud@122
  2087
			//Devices like MDM166AA don't support windowing and frame rendering must be stopped while showing our clock
StephaneLenclud@122
  2088
			iSkipFrameRendering = true;
StephaneLenclud@122
  2089
			//Clear our screen 
StephaneLenclud@122
  2090
			iDisplay.Clear();
StephaneLenclud@122
  2091
			iDisplay.SwapBuffers();
StephaneLenclud@122
  2092
			//Then show our clock
StephaneLenclud@122
  2093
			iDisplay.ShowClock();
StephaneLenclud@122
  2094
		}
StephaneLenclud@122
  2095
StephaneLenclud@122
  2096
		/// <summary>
StephaneLenclud@122
  2097
		/// 
StephaneLenclud@122
  2098
		/// </summary>
StephaneLenclud@122
  2099
		void HideClock()
StephaneLenclud@122
  2100
		{
StephaneLenclud@122
  2101
			if (!iDisplay.IsOpen())
StephaneLenclud@122
  2102
			{
StephaneLenclud@122
  2103
				return;
StephaneLenclud@122
  2104
			}
StephaneLenclud@122
  2105
StephaneLenclud@122
  2106
			//Devices like MDM166AA don't support windowing and frame rendering must be stopped while showing our clock
StephaneLenclud@122
  2107
			iSkipFrameRendering = false;
StephaneLenclud@122
  2108
			iDisplay.HideClock();
StephaneLenclud@122
  2109
		}
sl@88
  2110
sl@88
  2111
        private void InstallUpdateSyncWithInfo()
sl@88
  2112
        {
sl@88
  2113
            UpdateCheckInfo info = null;
sl@88
  2114
sl@88
  2115
            if (ApplicationDeployment.IsNetworkDeployed)
sl@88
  2116
            {
sl@88
  2117
                ApplicationDeployment ad = ApplicationDeployment.CurrentDeployment;
sl@88
  2118
sl@88
  2119
                try
sl@88
  2120
                {
sl@88
  2121
                    info = ad.CheckForDetailedUpdate();
sl@88
  2122
sl@88
  2123
                }
sl@88
  2124
                catch (DeploymentDownloadException dde)
sl@88
  2125
                {
sl@88
  2126
                    MessageBox.Show("The new version of the application cannot be downloaded at this time. \n\nPlease check your network connection, or try again later. Error: " + dde.Message);
sl@88
  2127
                    return;
sl@88
  2128
                }
sl@88
  2129
                catch (InvalidDeploymentException ide)
sl@88
  2130
                {
sl@88
  2131
                    MessageBox.Show("Cannot check for a new version of the application. The ClickOnce deployment is corrupt. Please redeploy the application and try again. Error: " + ide.Message);
sl@88
  2132
                    return;
sl@88
  2133
                }
sl@88
  2134
                catch (InvalidOperationException ioe)
sl@88
  2135
                {
sl@88
  2136
                    MessageBox.Show("This application cannot be updated. It is likely not a ClickOnce application. Error: " + ioe.Message);
sl@88
  2137
                    return;
sl@88
  2138
                }
sl@88
  2139
sl@90
  2140
				if (info.UpdateAvailable)
sl@90
  2141
				{
sl@90
  2142
					Boolean doUpdate = true;
sl@88
  2143
sl@90
  2144
					if (!info.IsUpdateRequired)
sl@90
  2145
					{
sl@90
  2146
						DialogResult dr = MessageBox.Show("An update is available. Would you like to update the application now?", "Update Available", MessageBoxButtons.OKCancel);
sl@90
  2147
						if (!(DialogResult.OK == dr))
sl@90
  2148
						{
sl@90
  2149
							doUpdate = false;
sl@90
  2150
						}
sl@90
  2151
					}
sl@90
  2152
					else
sl@90
  2153
					{
sl@90
  2154
						// Display a message that the app MUST reboot. Display the minimum required version.
sl@90
  2155
						MessageBox.Show("This application has detected a mandatory update from your current " +
sl@90
  2156
							"version to version " + info.MinimumRequiredVersion.ToString() +
sl@90
  2157
							". The application will now install the update and restart.",
sl@90
  2158
							"Update Available", MessageBoxButtons.OK,
sl@90
  2159
							MessageBoxIcon.Information);
sl@90
  2160
					}
sl@88
  2161
sl@90
  2162
					if (doUpdate)
sl@90
  2163
					{
sl@90
  2164
						try
sl@90
  2165
						{
sl@90
  2166
							ad.Update();
sl@90
  2167
							MessageBox.Show("The application has been upgraded, and will now restart.");
sl@90
  2168
							Application.Restart();
sl@90
  2169
						}
sl@90
  2170
						catch (DeploymentDownloadException dde)
sl@90
  2171
						{
sl@90
  2172
							MessageBox.Show("Cannot install the latest version of the application. \n\nPlease check your network connection, or try again later. Error: " + dde);
sl@90
  2173
							return;
sl@90
  2174
						}
sl@90
  2175
					}
sl@90
  2176
				}
sl@90
  2177
				else
sl@90
  2178
				{
sl@90
  2179
					MessageBox.Show("You are already running the latest version.", "Application up-to-date");
sl@90
  2180
				}
sl@88
  2181
            }
sl@88
  2182
        }
sl@92
  2183
sl@94
  2184
sl@94
  2185
		/// <summary>
sl@99
  2186
		/// Used to
sl@94
  2187
		/// </summary>
sl@94
  2188
		private void SysTrayHideShow()
sl@92
  2189
		{
sl@94
  2190
			Visible = !Visible;
sl@94
  2191
			if (Visible)
sl@94
  2192
			{
sl@94
  2193
				Activate();
sl@94
  2194
				WindowState = FormWindowState.Normal;
sl@94
  2195
			}
sl@92
  2196
		}
sl@94
  2197
sl@94
  2198
		/// <summary>
sl@94
  2199
		/// Use to handle minimize events.
sl@94
  2200
		/// </summary>
sl@94
  2201
		/// <param name="sender"></param>
sl@94
  2202
		/// <param name="e"></param>
sl@94
  2203
		private void MainForm_SizeChanged(object sender, EventArgs e)
sl@94
  2204
		{
sl@94
  2205
			if (WindowState == FormWindowState.Minimized && Properties.Settings.Default.MinimizeToTray)
sl@94
  2206
			{
sl@94
  2207
				if (Visible)
sl@94
  2208
				{
sl@94
  2209
					SysTrayHideShow();
sl@94
  2210
				}
sl@94
  2211
			}
sl@94
  2212
		}
sl@94
  2213
StephaneLenclud@105
  2214
		/// <summary>
StephaneLenclud@105
  2215
		/// 
StephaneLenclud@105
  2216
		/// </summary>
StephaneLenclud@105
  2217
		/// <param name="sender"></param>
StephaneLenclud@105
  2218
		/// <param name="e"></param>
StephaneLenclud@105
  2219
		private void tableLayoutPanel_SizeChanged(object sender, EventArgs e)
StephaneLenclud@105
  2220
		{
StephaneLenclud@105
  2221
			//Our table layout size has changed which means our display size has changed.
StephaneLenclud@105
  2222
			//We need to re-create our bitmap.
StephaneLenclud@105
  2223
			iCreateBitmap = true;
StephaneLenclud@105
  2224
		}
StephaneLenclud@126
  2225
StephaneLenclud@126
  2226
		/// <summary>
StephaneLenclud@126
  2227
		/// 
StephaneLenclud@126
  2228
		/// </summary>
StephaneLenclud@126
  2229
		/// <param name="sender"></param>
StephaneLenclud@126
  2230
		/// <param name="e"></param>
StephaneLenclud@126
  2231
		private void buttonSelectFile_Click(object sender, EventArgs e)
StephaneLenclud@126
  2232
		{
StephaneLenclud@126
  2233
			//openFileDialog1.InitialDirectory = "c:\\";
StephaneLenclud@126
  2234
			//openFileDialog.Filter = "EXE files (*.exe)|*.exe|All files (*.*)|*.*";
StephaneLenclud@126
  2235
			//openFileDialog.FilterIndex = 1;
StephaneLenclud@126
  2236
			openFileDialog.RestoreDirectory = true;
StephaneLenclud@126
  2237
StephaneLenclud@126
  2238
			if (DlgBox.ShowDialog(openFileDialog) == DialogResult.OK)
StephaneLenclud@126
  2239
			{
StephaneLenclud@126
  2240
				labelStartFileName.Text = openFileDialog.FileName;
StephaneLenclud@126
  2241
				Properties.Settings.Default.StartFileName = openFileDialog.FileName;
StephaneLenclud@126
  2242
				Properties.Settings.Default.Save();
StephaneLenclud@126
  2243
			}
StephaneLenclud@126
  2244
		}
StephaneLenclud@153
  2245
StephaneLenclud@153
  2246
        /// <summary>
StephaneLenclud@153
  2247
        /// 
StephaneLenclud@153
  2248
        /// </summary>
StephaneLenclud@153
  2249
        /// <param name="sender"></param>
StephaneLenclud@153
  2250
        /// <param name="e"></param>
StephaneLenclud@153
  2251
        private void comboBoxOpticalDrives_SelectedIndexChanged(object sender, EventArgs e)
StephaneLenclud@153
  2252
        {
StephaneLenclud@153
  2253
            //Save the optical drive the user selected for ejection
StephaneLenclud@153
  2254
            Properties.Settings.Default.OpticalDriveToEject = comboBoxOpticalDrives.SelectedItem.ToString();
StephaneLenclud@153
  2255
            Properties.Settings.Default.Save();
StephaneLenclud@153
  2256
        }
StephaneLenclud@167
  2257
StephaneLenclud@167
  2258
        /// <summary>
StephaneLenclud@167
  2259
        /// Broadcast messages to subscribers.
StephaneLenclud@167
  2260
        /// </summary>
StephaneLenclud@167
  2261
        /// <param name="message"></param>
StephaneLenclud@167
  2262
        protected override void WndProc(ref Message aMessage)
StephaneLenclud@167
  2263
        {
StephaneLenclud@167
  2264
            if (OnWndProc!=null)
StephaneLenclud@167
  2265
            {
StephaneLenclud@167
  2266
                OnWndProc(ref aMessage);
StephaneLenclud@167
  2267
            }
StephaneLenclud@167
  2268
            
StephaneLenclud@167
  2269
            base.WndProc(ref aMessage);
StephaneLenclud@167
  2270
        }
StephaneLenclud@168
  2271
StephaneLenclud@168
  2272
        private void checkBoxCecEnabled_CheckedChanged(object sender, EventArgs e)
StephaneLenclud@168
  2273
        {
StephaneLenclud@168
  2274
            //Save CEC enabled status
StephaneLenclud@168
  2275
            Properties.Settings.Default.CecEnabled = checkBoxCecEnabled.Checked;
StephaneLenclud@168
  2276
            Properties.Settings.Default.Save();
StephaneLenclud@168
  2277
            //
StephaneLenclud@168
  2278
            ResetCec();
StephaneLenclud@168
  2279
        }
StephaneLenclud@168
  2280
StephaneLenclud@168
  2281
        private void comboBoxHdmiPort_SelectedIndexChanged(object sender, EventArgs e)
StephaneLenclud@168
  2282
        {
StephaneLenclud@168
  2283
            //Save CEC HDMI port
StephaneLenclud@168
  2284
            Properties.Settings.Default.CecHdmiPort = Convert.ToByte(comboBoxHdmiPort.SelectedIndex);
StephaneLenclud@168
  2285
            Properties.Settings.Default.CecHdmiPort++;
StephaneLenclud@168
  2286
            Properties.Settings.Default.Save();
StephaneLenclud@168
  2287
            //
StephaneLenclud@168
  2288
            ResetCec();
StephaneLenclud@168
  2289
        }
StephaneLenclud@168
  2290
StephaneLenclud@168
  2291
        private void checkBoxCecMonitorOff_CheckedChanged(object sender, EventArgs e)
StephaneLenclud@168
  2292
        {
StephaneLenclud@168
  2293
            Properties.Settings.Default.CecMonitorOff = checkBoxCecMonitorOff.Checked;
StephaneLenclud@168
  2294
            Properties.Settings.Default.Save();
StephaneLenclud@168
  2295
            //
StephaneLenclud@168
  2296
            ResetCec();
StephaneLenclud@168
  2297
        }
StephaneLenclud@168
  2298
StephaneLenclud@168
  2299
        private void checkBoxCecMonitorOn_CheckedChanged(object sender, EventArgs e)
StephaneLenclud@168
  2300
        {
StephaneLenclud@168
  2301
            Properties.Settings.Default.CecMonitorOn = checkBoxCecMonitorOn.Checked;
StephaneLenclud@168
  2302
            Properties.Settings.Default.Save();
StephaneLenclud@168
  2303
            //
StephaneLenclud@168
  2304
            ResetCec();
StephaneLenclud@168
  2305
        }
StephaneLenclud@168
  2306
StephaneLenclud@168
  2307
        /// <summary>
StephaneLenclud@168
  2308
        /// 
StephaneLenclud@168
  2309
        /// </summary>
StephaneLenclud@168
  2310
        private void ResetCec()
StephaneLenclud@168
  2311
        {
StephaneLenclud@168
  2312
            if (iCecManager==null)
StephaneLenclud@168
  2313
            {
StephaneLenclud@168
  2314
                //Thus skipping initial UI setup
StephaneLenclud@168
  2315
                return;
StephaneLenclud@168
  2316
            }
StephaneLenclud@168
  2317
StephaneLenclud@168
  2318
            iCecManager.Stop();
StephaneLenclud@168
  2319
            //
StephaneLenclud@168
  2320
            if (Properties.Settings.Default.CecEnabled)
StephaneLenclud@168
  2321
            {
StephaneLenclud@168
  2322
                iCecManager.Start(Handle, "CEC",
StephaneLenclud@168
  2323
                Properties.Settings.Default.CecHdmiPort,
StephaneLenclud@168
  2324
                Properties.Settings.Default.CecMonitorOn,
StephaneLenclud@168
  2325
                Properties.Settings.Default.CecMonitorOff);
StephaneLenclud@168
  2326
            }
StephaneLenclud@168
  2327
        }
sl@0
  2328
    }
sl@0
  2329
}