sl@391: /*
sl@391:  
sl@391:   This Source Code Form is subject to the terms of the Mozilla Public
sl@391:   License, v. 2.0. If a copy of the MPL was not distributed with this
sl@391:   file, You can obtain one at http://mozilla.org/MPL/2.0/.
sl@391:  
sl@391:   Copyright (C) 2009-2012 Michael Möller <mmoeller@openhardwaremonitor.org>
sl@391: 	
sl@391: */
sl@391: 
sl@391: using System;
sl@391: using System.Collections.Generic;
sl@391: using System.Drawing;
sl@391: using System.Text;
StephaneLenclud@394: using System.Diagnostics;
sl@391: using System.Windows.Forms;
sl@393: using System.Windows;
sl@391: using OpenHardwareMonitor.Hardware;
sl@391: using OpenHardwareMonitor.Utilities;
sl@391: using System.Runtime.InteropServices;
StephaneLenclud@394: using UacHelpers;
sl@391: 
sl@391: 
sl@391: 
sl@391: 
sl@391: 
sl@392: 
sl@391: 
sl@391: namespace OpenHardwareMonitor.GUI
sl@391: {
sl@391:     public class SoundGraphDisplay : IDisposable
sl@391:     {
sl@391:         private IComputer computer;
sl@391:         private PersistentSettings settings;
sl@391:         private UnitManager unitManager;
sl@391:         private List<SensorFrontView> list = new List<SensorFrontView>();
StephaneLenclud@394:         private SoundGraph.Server iServer;
StephaneLenclud@394: 
StephaneLenclud@397:         private int iNextSensorToDisplay=0;
StephaneLenclud@397:         private int iTickCounter=0;
StephaneLenclud@396: 
sl@391: 
sl@391:         public SoundGraphDisplay(IComputer computer, PersistentSettings settings,
sl@391:           UnitManager unitManager)
sl@391:         {
sl@391:             this.computer = computer;
sl@391:             this.settings = settings;
sl@391:             this.unitManager = unitManager;
sl@391:             computer.HardwareAdded += new HardwareEventHandler(HardwareAdded);
sl@391:             computer.HardwareRemoved += new HardwareEventHandler(HardwareRemoved);
sl@391: 
StephaneLenclud@394:             //Start our client if needed
StephaneLenclud@394:             Process[] processes = Process.GetProcessesByName("SoundGraphAccess");
StephaneLenclud@394:             if (!(processes.Length > 0))
StephaneLenclud@394:             {
StephaneLenclud@402:                 //Try to launch the sound graph process from the same folder as this executable
StephaneLenclud@402:                 string exeName=System.IO.Path.GetDirectoryName(Application.ExecutablePath);
StephaneLenclud@402:                 exeName += @"\SoundGraphAccess.exe";
StephaneLenclud@402:                 Process client = UserAccountControl.CreateProcessAsStandardUser(exeName,"");
StephaneLenclud@394:             }
StephaneLenclud@394: 
StephaneLenclud@395:             //Start our SoundGraph server
StephaneLenclud@395:             iServer = new SoundGraph.Server(@"\\.\pipe\sga-inbound", @"\\.\pipe\sga-outbound");
StephaneLenclud@394:             iServer.Start();
sl@391:         }
sl@391: 
sl@391:         private void HardwareRemoved(IHardware hardware)
sl@391:         {
sl@391:             hardware.SensorAdded -= new SensorEventHandler(SensorAdded);
sl@391:             hardware.SensorRemoved -= new SensorEventHandler(SensorRemoved);
sl@391:             foreach (ISensor sensor in hardware.Sensors)
sl@391:                 SensorRemoved(sensor);
sl@391:             foreach (IHardware subHardware in hardware.SubHardware)
sl@391:                 HardwareRemoved(subHardware);
sl@391:         }
sl@391: 
sl@391:         private void HardwareAdded(IHardware hardware)
sl@391:         {
sl@391:             foreach (ISensor sensor in hardware.Sensors)
sl@391:                 SensorAdded(sensor);
sl@391:             hardware.SensorAdded += new SensorEventHandler(SensorAdded);
sl@391:             hardware.SensorRemoved += new SensorEventHandler(SensorRemoved);
sl@391:             foreach (IHardware subHardware in hardware.SubHardware)
sl@391:                 HardwareAdded(subHardware);
sl@391:         }
sl@391: 
sl@391:         private void SensorAdded(ISensor sensor)
sl@391:         {
sl@391:             if (settings.GetValue(new Identifier(sensor.Identifier,
StephaneLenclud@396:               "FrontView").ToString(), false))
sl@391:                 Add(sensor, false);
sl@391:         }
sl@391: 
sl@391:         private void SensorRemoved(ISensor sensor)
sl@391:         {
sl@391:             if (Contains(sensor))
sl@391:                 Remove(sensor, false);
sl@391:         }
sl@391: 
sl@391:         public void Dispose()
sl@391:         {
sl@391:             foreach (SensorFrontView icon in list)
sl@391:                 icon.Dispose();
sl@391: 
StephaneLenclud@395:             Quit();
StephaneLenclud@394:             iServer.Stop();
sl@391: 
sl@391:         }
sl@391: 
lenclud@400:         public void Redraw(bool aPacked, bool aDisplayTime)
sl@391:         {
StephaneLenclud@401:             const int KNumberOfTickBeforeSwitch = 4;
StephaneLenclud@401:             const int KMaxCharacterPerLine = 16;
lenclud@400:             string packedFirstLine=""; //We have 16 chars per line on our VFD
lenclud@400:             string packedSecondLine="";
lenclud@400:             int count = 0;
lenclud@400: 
StephaneLenclud@401:             string time = DateTime.Now.ToShortTimeString();
StephaneLenclud@401: 
StephaneLenclud@397:             //Update all sensors from our front view
StephaneLenclud@396:             foreach (SensorFrontView sensor in list)
StephaneLenclud@396:             {
lenclud@400:                 count++;
StephaneLenclud@396:                 sensor.Update();
lenclud@400: 
StephaneLenclud@402:                 if (aDisplayTime && count == 1)
StephaneLenclud@402:                 {
StephaneLenclud@402:                     //First slot is take by time display
StephaneLenclud@402:                     count++;
StephaneLenclud@402:                     packedFirstLine = time + " ";
StephaneLenclud@402:                 }
StephaneLenclud@402: 
lenclud@400:                 if (aPacked)
lenclud@400:                 {
StephaneLenclud@402:                     //Build strings for packed mode
lenclud@400:                     string packedText = "";
lenclud@400:                     packedText = sensor.iFirstLine.Substring(0, 3) + ":" + sensor.iSecondLine;
lenclud@400:                     if (count == 1)
lenclud@400:                     {
StephaneLenclud@402:                         packedFirstLine = packedText + " "; //Minimum one space to separate sensors on the same line
lenclud@400:                     }
lenclud@400:                     else if (count == 2)
lenclud@400:                     {
StephaneLenclud@402:                         //Add enough spaces to align to right hand side
StephaneLenclud@401:                         while (packedFirstLine.Length + packedText.Length < KMaxCharacterPerLine)
lenclud@400:                         {
lenclud@400:                             packedFirstLine += " ";
lenclud@400:                         }
lenclud@400:                         packedFirstLine += packedText;
lenclud@400:                     }
lenclud@400:                     else if (count == 3)
lenclud@400:                     {
StephaneLenclud@402:                         packedSecondLine = packedText + " "; //Minimum one space to separate sensors on the same line
lenclud@400:                     }
lenclud@400:                     else if (count == 4)
lenclud@400:                     {
StephaneLenclud@402:                         //Add enough spaces to align to right hand side
StephaneLenclud@401:                         while (packedSecondLine.Length + packedText.Length < KMaxCharacterPerLine)
lenclud@400:                         {
lenclud@400:                             packedSecondLine += " ";
lenclud@400:                         }
lenclud@400:                         packedSecondLine += packedText;
lenclud@400:                     }
lenclud@400:                 }
StephaneLenclud@396:                 //SetText(sensor.iFirstLine, sensor.iSecondLine);
StephaneLenclud@396:             }
StephaneLenclud@396: 
StephaneLenclud@396:             //Alternate between sensors 
StephaneLenclud@396:             if (list.Count > 0)
StephaneLenclud@396:             {
lenclud@400:                 if (aPacked)
StephaneLenclud@397:                 {
lenclud@400:                     //string packedLine = "";
lenclud@400:                     iTickCounter++;
StephaneLenclud@401:                     if (iTickCounter == KNumberOfTickBeforeSwitch) //Move to the next sensor only every so many tick
lenclud@400:                     {
lenclud@400:                         iTickCounter = 0;
lenclud@400:                         if (iNextSensorToDisplay==1)
lenclud@400:                         {
lenclud@400:                             iNextSensorToDisplay=0;
lenclud@400:                         }
lenclud@400:                         else
lenclud@400:                         {
lenclud@400:                             iNextSensorToDisplay=1;
lenclud@400:                         }
lenclud@400:                     }
lenclud@400: 
StephaneLenclud@402:                     //TODO: Do something like that to cycle lines if ever we want to
StephaneLenclud@402:                     //SetText(time, (iNextSensorToDisplay == 1 && packedSecondLine.Length > 0 ? packedSecondLine : packedFirstLine));
lenclud@400: 
StephaneLenclud@402:                     //Display packed sensors on our FrontView display
StephaneLenclud@402:                     SetText(packedFirstLine, packedSecondLine);
lenclud@400:                 }
lenclud@400:                 else
lenclud@400:                 {
StephaneLenclud@401:                     string secondLine = list[iNextSensorToDisplay].iSecondLine;
StephaneLenclud@401:                     if (aDisplayTime)
StephaneLenclud@401:                     {
StephaneLenclud@401:                         //Add enough spaces
StephaneLenclud@401:                         while (secondLine.Length + time.Length < KMaxCharacterPerLine)
StephaneLenclud@401:                         {
StephaneLenclud@401:                             secondLine += " ";
StephaneLenclud@401:                         }
StephaneLenclud@401:                         secondLine += time;
StephaneLenclud@401:                     }
lenclud@400:                     //Display current sensor on our FrontView display
StephaneLenclud@401:                     SetText(list[iNextSensorToDisplay].iFirstLine, secondLine);
lenclud@400:                     iTickCounter++;
StephaneLenclud@401:                     if (iTickCounter == KNumberOfTickBeforeSwitch) //Move to the next sensor only every so many tick
lenclud@400:                     {
lenclud@400:                         iTickCounter = 0;
lenclud@400:                         iNextSensorToDisplay++;
lenclud@400:                     }
StephaneLenclud@397:                 }
StephaneLenclud@396:             }
StephaneLenclud@396: 
StephaneLenclud@397:             if (iNextSensorToDisplay == list.Count)
StephaneLenclud@396:             {
StephaneLenclud@396:                 //Go back to first sensor
StephaneLenclud@397:                 iNextSensorToDisplay = 0;
StephaneLenclud@396:             }
StephaneLenclud@396: 
StephaneLenclud@396:             
sl@391:         }
sl@391: 
sl@391:         public bool Contains(ISensor sensor)
sl@391:         {
sl@391:             foreach (SensorFrontView icon in list)
sl@391:                 if (icon.Sensor == sensor)
sl@391:                     return true;
sl@391:             return false;
sl@391:         }
sl@391: 
sl@391:         public void Add(ISensor sensor, bool balloonTip)
sl@391:         {
sl@391:             if (Contains(sensor))
sl@391:             {
sl@391:                 return;
sl@391:             }
sl@391:             else
sl@391:             {
sl@391:                 //SL:
StephaneLenclud@396:                 list.Add(new SensorFrontView(this, sensor, balloonTip, settings, unitManager));
sl@391:                 //UpdateMainIconVisibilty();
StephaneLenclud@396:                 settings.SetValue(new Identifier(sensor.Identifier, "FrontView").ToString(), true);
StephaneLenclud@397:                 iNextSensorToDisplay = 0;
StephaneLenclud@402:                 if (list.Count == 1)
StephaneLenclud@402:                 {
StephaneLenclud@402:                     //Just added first sensor in FrontView, unable FrontView plug-in mode
StephaneLenclud@402:                     Init();
StephaneLenclud@402:                 }
sl@391:             }
StephaneLenclud@396: 
sl@391:         }
sl@391: 
sl@391:         public void Remove(ISensor sensor)
sl@391:         {
sl@391:             Remove(sensor, true);
StephaneLenclud@397:             iNextSensorToDisplay = 0;
StephaneLenclud@402:             if (list.Count == 0)
StephaneLenclud@402:             {
StephaneLenclud@402:                 //No sensor to display in FrontView, just disable FrontView plug-in mode
StephaneLenclud@402:                 Uninit();
StephaneLenclud@402:             }
StephaneLenclud@402: 
sl@391:         }
sl@391: 
sl@391:         private void Remove(ISensor sensor, bool deleteConfig)
sl@391:         {
sl@391:             if (deleteConfig)
sl@391:             {
sl@391:                 settings.Remove(
StephaneLenclud@396:                   new Identifier(sensor.Identifier, "FrontView").ToString());
sl@391:             }
sl@391:             SensorFrontView instance = null;
sl@391:             foreach (SensorFrontView icon in list)
sl@391:                 if (icon.Sensor == sensor)
sl@391:                     instance = icon;
sl@391:             if (instance != null)
sl@391:             {
sl@391:                 list.Remove(instance);
StephaneLenclud@396:                 //UpdateMainIconVisibilty();
sl@391:                 instance.Dispose();
sl@391:             }
sl@391:         }
sl@391: 
sl@391: 
sl@391: 
sl@391:         private void UpdateMainIconVisibilty()
sl@391:         {
sl@391:             /*
sl@391:             if (mainIconEnabled)
sl@391:             {
sl@391:                 mainIcon.Visible = list.Count == 0;
sl@391:             }
sl@391:             else
sl@391:             {
sl@391:                 mainIcon.Visible = false;
sl@391:             }
sl@391:              */
sl@391:         }
sl@391: 
StephaneLenclud@394:         public void Init()
sl@392:         {
StephaneLenclud@394:             iServer.SendMessage("init:");
sl@392:         }
sl@392: 
sl@393:         public void Uninit()
sl@392:         {
StephaneLenclud@394:             iServer.SendMessage("uninit:");
sl@392:         }
sl@392: 
sl@393:         public void SetText(string aUpperLine, string aLowerLine)
sl@392:         {
StephaneLenclud@396:             iServer.SendMessage("set-vfd-text:" + aUpperLine + "\n" + aLowerLine);
sl@392:         }
sl@392: 
StephaneLenclud@395:         public void Quit()
StephaneLenclud@395:         {
StephaneLenclud@395:             iServer.SendMessage("quit:");
StephaneLenclud@395:         }
StephaneLenclud@395: 
sl@391:         /*
sl@391:         public bool IsMainIconEnabled
sl@391:         {
sl@391:             get { return mainIconEnabled; }
sl@391:             set
sl@391:             {
sl@391:                 if (mainIconEnabled != value)
sl@391:                 {
sl@391:                     mainIconEnabled = value;
sl@391:                     UpdateMainIconVisibilty();
sl@391:                 }
sl@391:             }
sl@391:         }*/
sl@392: 
sl@393: 
sl@391:     }
sl@391: }