From 254c9f43436fe8d6fe73eefce902c0855908ecac Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Lenclud?= <git@lenclud.com>
Date: Sun, 5 Jan 2014 00:54:24 +0100
Subject: [PATCH 2/2] MiniDisplayLibrary for iMON VFD and LCD.

---
 .../MiniDisplayLibrary/MiniDisplayLibrary.csproj   |  12 +
 .../MiniDisplayPlugin/Drivers/ImonBase.cs          | 239 ++++++
 .../MiniDisplayPlugin/Drivers/ImonLcd.cs           | 918 +++++++++++++++++++++
 .../Drivers/ImonLcd_AdvancedSetupForm.Designer.cs  | 162 ++++
 .../Drivers/ImonLcd_AdvancedSetupForm.cs           |  41 +
 .../Drivers/ImonLcd_AdvancedSetupForm.resx         | 120 +++
 .../MiniDisplayPlugin/Drivers/ImonVfd.cs           |  42 +
 .../MiniDisplayPlugin/Settings.cs                  |  14 +-
 8 files changed, 1546 insertions(+), 2 deletions(-)
 create mode 100644 mediaportal/MiniDisplayLibrary/MiniDisplayPlugin/Drivers/ImonBase.cs
 create mode 100644 mediaportal/MiniDisplayLibrary/MiniDisplayPlugin/Drivers/ImonLcd.cs
 create mode 100644 mediaportal/MiniDisplayLibrary/MiniDisplayPlugin/Drivers/ImonLcd_AdvancedSetupForm.Designer.cs
 create mode 100644 mediaportal/MiniDisplayLibrary/MiniDisplayPlugin/Drivers/ImonLcd_AdvancedSetupForm.cs
 create mode 100644 mediaportal/MiniDisplayLibrary/MiniDisplayPlugin/Drivers/ImonLcd_AdvancedSetupForm.resx
 create mode 100644 mediaportal/MiniDisplayLibrary/MiniDisplayPlugin/Drivers/ImonVfd.cs

diff --git a/mediaportal/MiniDisplayLibrary/MiniDisplayLibrary.csproj b/mediaportal/MiniDisplayLibrary/MiniDisplayLibrary.csproj
index d48dc4a..9eb6cec 100644
--- a/mediaportal/MiniDisplayLibrary/MiniDisplayLibrary.csproj
+++ b/mediaportal/MiniDisplayLibrary/MiniDisplayLibrary.csproj
@@ -108,6 +108,15 @@
     <Compile Include="MiniDisplayPlugin\ByteArray.cs">
       <SubType>Code</SubType>
     </Compile>
+    <Compile Include="MiniDisplayPlugin\Drivers\ImonBase.cs" />
+    <Compile Include="MiniDisplayPlugin\Drivers\ImonLcd.cs" />
+    <Compile Include="MiniDisplayPlugin\Drivers\ImonLcd_AdvancedSetupForm.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="MiniDisplayPlugin\Drivers\ImonLcd_AdvancedSetupForm.Designer.cs">
+      <DependentUpon>ImonLcd_AdvancedSetupForm.cs</DependentUpon>
+    </Compile>
+    <Compile Include="MiniDisplayPlugin\Drivers\ImonVfd.cs" />
     <Compile Include="MiniDisplayPlugin\Drivers\ShuttlePF27.cs" />
     <Compile Include="MiniDisplayPlugin\Drivers\DM140GINK.cs" />
     <Compile Include="MiniDisplayPlugin\Drivers\FicSpectra.cs" />
@@ -345,6 +354,9 @@
     <EmbeddedResource Include="MiniDisplayPlugin\Drivers\iMONLCDg_AdvancedSetupForm.resx">
       <DependentUpon>iMONLCDg_AdvancedSetupForm.cs</DependentUpon>
     </EmbeddedResource>
+    <EmbeddedResource Include="MiniDisplayPlugin\Drivers\ImonLcd_AdvancedSetupForm.resx">
+      <DependentUpon>ImonLcd_AdvancedSetupForm.cs</DependentUpon>
+    </EmbeddedResource>
   </ItemGroup>
   <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
   <PropertyGroup>
diff --git a/mediaportal/MiniDisplayLibrary/MiniDisplayPlugin/Drivers/ImonBase.cs b/mediaportal/MiniDisplayLibrary/MiniDisplayPlugin/Drivers/ImonBase.cs
new file mode 100644
index 0000000..be812a1
--- /dev/null
+++ b/mediaportal/MiniDisplayLibrary/MiniDisplayPlugin/Drivers/ImonBase.cs
@@ -0,0 +1,239 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Runtime.InteropServices;
+using System.Text;
+using MediaPortal.GUI.Library;
+
+namespace MediaPortal.ProcessPlugins.MiniDisplayPlugin.Drivers
+{
+    /// <summary>
+    /// Base Class for iMON Display API in iMON Manager >= 8.01.0419
+    /// </summary>
+    public abstract class ImonBase : IDisplay
+    {
+        public ImonBase()
+        {
+            Disabled = null;
+            ImonErrorMessage = string.Empty;
+            Initialized = false;
+            Line1 = string.Empty;
+            Line2 = string.Empty;
+        }
+
+        protected bool? Disabled { get; set; }
+
+        protected string ImonErrorMessage { get; set;}
+
+        protected bool Initialized { get; set; }
+
+        protected string Line1 { get; set; }
+
+        protected string Line2 { get; set; }
+
+        public string Description { get; protected set; }
+
+        protected string ClassErrorName { get; set; }
+
+        protected string UnsupportedDeviceErrorMessage { get; set; }
+
+        protected int DisplayType { get; set; }
+
+        public string ErrorMessage
+        {
+            get
+            {
+                if (IsDisabled)
+                {
+                    return ImonErrorMessage;
+                }
+                return string.Empty;
+            }
+        }
+
+        public bool IsDisabled
+        {
+            get
+            {
+                if (!Disabled.HasValue)
+                {
+                    IDWINITRESULT initResult = new IDWINITRESULT();
+                    int ret = IDW_Init(initResult);
+                    if (ret != DSP_SUCCEEDED)
+                    {
+                        ImonErrorMessage = DSPResult2String(ret);
+                        Disabled = true;
+                        Log.Error(string.Format("{0}.IsDisabled: {1}", ClassErrorName, ImonErrorMessage));
+                    }
+                    else if (initResult.initResult != DSPN_SUCCEEDED)
+                    {
+                        ImonErrorMessage = DSPNResult2String(initResult.initResult);
+                        Disabled = true;
+                        Log.Error(string.Format("{0}.IsDisabled: {1}", ClassErrorName, ImonErrorMessage));
+                    }
+                    else if (initResult.dspType != DisplayType)
+                    {
+                        ImonErrorMessage = UnsupportedDeviceErrorMessage;
+                        Disabled = true;
+                        IDW_Uninit();
+                        Log.Error(string.Format("{0}.IsDisabled: {1}", ClassErrorName, ImonErrorMessage));
+                    }
+                    else
+                    {
+                        Disabled = false;
+                        IDW_Uninit();
+                    }
+
+                }
+                return Disabled.Value;
+            }
+        }
+
+        public string Name { get; protected set; }
+
+        public bool SupportsGraphics { get { return false; } }
+
+        public bool SupportsText { get { return true; } }
+
+        public virtual void Dispose()
+        {
+            CleanUp();
+        }
+
+        public virtual void Initialize()
+        {
+            Log.Info("(IDisplay) ImonBase.Initialize(): called");
+            if (Initialized)
+            {
+                Log.Info("(IDisplay) ImonBase.Initialize(): already initialized, skipping");
+                return;
+            }
+            if (IsDisabled)
+            {
+                Log.Info("(IDisplay) ImonBase.Initialize(): driver disabled, cannot initialize");
+                return;
+            }
+            IDWINITRESULT initResult = new IDWINITRESULT();
+            IDW_Init(initResult);
+            Initialized = true;
+            Log.Info("(IDisplay) ImonBase.Initialize(): completed");
+        }
+
+        public virtual void CleanUp()
+        {
+            Log.Info("(IDisplay) ImonBase.CleanUp(): called");
+            if (!Initialized)
+            {
+                return;
+            }
+            IDW_Uninit();
+            Initialized = false;
+            Log.Info("(IDisplay) ImonBase.CleanUp(): completed");
+        }
+
+        public abstract void SetLine(int line, string message);
+
+        public virtual void Configure()
+        {
+            // No configuration possible/necessary
+        }
+
+        public void DrawImage(Bitmap bitmap)
+        {
+            // Not supported
+        }
+
+        public void SetCustomCharacters(int[][] customCharacters)
+        {
+            // Not supported
+        }
+
+        public void Setup(string port,
+          int lines, int cols, int delay,
+          int linesG, int colsG, int timeG,
+          bool backLight, int backLightLevel,
+          bool contrast, int contrastLevel,
+          bool BlankOnExit)
+        {
+            // iMON VFD/LCD cannot be setup
+        }
+
+        protected string DSPResult2String(int result)
+        {
+            switch (result)
+            {
+                case DSP_SUCCEEDED:
+                    return "Success";
+                case DSP_E_FAIL:
+                    return "An unknown error occurred";
+                case DSP_E_OUTOFMEMORY:
+                    return "Out of memory";
+                case DSP_E_INVALIDARG:
+                    return "One or more arguments are invalid";
+                case DSP_E_NOT_INITED:
+                    return "API is not initialized";
+                case DSP_E_POINTER:
+                    return "Pointer is invalid";
+                default:
+                    return "An unknown error occurred";
+            }
+        }
+
+        protected string DSPNResult2String(int result)
+        {
+            switch (result)
+            {
+                case DSPN_SUCCEEDED:
+                    return "Success";
+                case DSPN_ERR_IN_USING:
+                    return "Display plug-in is already used by another application";
+                case DSPN_ERR_HW_DISCONNECTED:
+                    return "iMON hardware is not connected";
+                case DSPN_ERR_NOT_SUPPORTED_HW:
+                    return "The connected hardware does not support the plug-in mode";
+                case DSPN_ERR_PLUGIN_DISABLED:
+                    return "The plug-in mode option is disabled";
+                case DSPN_ERR_IMON_NO_REPLY:
+                    return "The latest iMON is not installed or iMON is not running";
+                default:
+                    return "An unknown error occurred";
+            }
+        }
+
+        protected const int DSP_SUCCEEDED = 0;
+        protected const int DSP_E_FAIL = 1;
+        protected const int DSP_E_OUTOFMEMORY = 2;
+        protected const int DSP_E_INVALIDARG = 3;
+        protected const int DSP_E_NOT_INITED = 4;
+        protected const int DSP_E_POINTER = 5;
+        protected const int DSP_S_INITED = 0x1000;
+        protected const int DSP_S_NOT_INITED = 0x1001;
+        protected const int DSP_S_IN_PLUGIN_MODE = 0x1002;
+        protected const int DSP_S_NOT_IN_PLUGIN_MODE = 0x1003;
+
+        protected const int DSPN_SUCCEEDED = 0;
+        protected const int DSPN_ERR_IN_USING = 0x0100;
+        protected const int DSPN_ERR_HW_DISCONNECTED = 0x0101;
+        protected const int DSPN_ERR_NOT_SUPPORTED_HW = 0x0102;
+        protected const int DSPN_ERR_PLUGIN_DISABLED = 0x0103;
+        protected const int DSPN_ERR_IMON_NO_REPLY = 0x0104;
+        protected const int DSPN_ERR_UNKNOWN = 0x0200;
+
+        protected const int DSPN_DSP_NONE = 0;
+        protected const int DSPN_DSP_VFD = 0x01;
+        protected const int DSPN_DSP_LCD = 0x02;
+
+        [StructLayout(LayoutKind.Sequential)]
+        protected class IDWINITRESULT
+        {
+            public int initResult;
+            public int dspType;
+        }
+
+        [DllImport("iMONDisplayWrapper.dll")]
+        protected static extern int IDW_Init(IDWINITRESULT initResult);
+
+        [DllImport("iMONDisplayWrapper.dll")]
+        protected static extern int IDW_Uninit();
+    }
+}
diff --git a/mediaportal/MiniDisplayLibrary/MiniDisplayPlugin/Drivers/ImonLcd.cs b/mediaportal/MiniDisplayLibrary/MiniDisplayPlugin/Drivers/ImonLcd.cs
new file mode 100644
index 0000000..e4794de
--- /dev/null
+++ b/mediaportal/MiniDisplayLibrary/MiniDisplayPlugin/Drivers/ImonLcd.cs
@@ -0,0 +1,918 @@
+﻿using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading;
+using System.Windows.Forms;
+using System.Xml;
+using System.Xml.Serialization;
+using MediaPortal.Configuration;
+using MediaPortal.GUI.Library;
+using MediaPortal.Player;
+using Microsoft.Win32;
+
+namespace MediaPortal.ProcessPlugins.MiniDisplayPlugin.Drivers
+{
+    /// <summary>
+    /// iMON LCD Driver for iMON Manager >= 8.01.0419
+    /// </summary>
+    public class ImonLcd : ImonBase
+    {
+        Thread _monitorMediaThread;
+        volatile bool _stopMonitorMediaThread = false;
+        MediaTypes _currentMediaTypes;
+        const int MediaTotalTime = 100;
+        int _currentMediaCurrentPosition = 0;
+        byte _currentSpeakers = 0;
+        byte _currentSpeakerRR = 0;
+        byte _currentVideoCodecs = 0;
+        byte _currentAudioCodecs = 0;
+        byte _currentAspectRatioIcons = 0;
+        ImonMediaInfo _videoMediaInfo = new ImonMediaInfo();
+        ImonMediaInfo _audioMediaInfo = new ImonMediaInfo();
+        ActiveWindowInfo _activeWindowInfo = new ActiveWindowInfo();
+        private AdvancedSettings AdvSettings;
+        bool _preferLine1General;
+        bool _preferLine1Playback;
+        
+        public ImonLcd()
+        {
+            UnsupportedDeviceErrorMessage = "Only LCDs are supported";
+            Description = "iMON LCD for iMON Manager >= 8.01.0419";
+            Name = "iMONLCD";
+            DisplayType = DSPN_DSP_LCD;
+
+            LoadAdvancedSettings();
+            AdvancedSettings.OnSettingsChanged += 
+                AdvancedSettings_OnSettingsChanged;
+
+            SystemEvents.PowerModeChanged += 
+                SystemEvents_PowerModeChanged;
+        }
+
+        private void SystemEvents_PowerModeChanged(object sender, PowerModeChangedEventArgs e)
+        {
+            Log.Info("(IDisplay) ImonLcd.SystemEvents_PowerModeChanged() called, power mode is now " + e.Mode.ToString());
+            SetDefaults();
+            Log.Info("(IDisplay) ImonLcd.SystemEvents_PowerModeChanged() completed");
+        }
+
+        private void SetDefaults()
+        {
+            Log.Info("(IDisplay) ImonLcd.SetDefaults() called");
+            _stopMonitorMediaThread = false;
+            _currentMediaCurrentPosition = 0;
+            _currentSpeakers = 0;
+            _currentSpeakerRR = 0;
+            _currentVideoCodecs = 0;
+            _currentAudioCodecs = 0;
+            _currentAspectRatioIcons = 0;
+            Log.Info("(IDisplay) ImonLcd.SetDefaults() completed");
+        }
+
+        [Flags]
+        enum OrangeDiskPieces : byte
+        {
+            Piece1 = 0x80, // top piece
+            Piece2 = 0x40, // next piece counter-clockwise
+            Piece3 = 0x20, // and so on...
+            Piece4 = 0x10,
+            Piece5 = 0x8,
+            Piece6 = 0x4,
+            Piece7 = 0x2,
+            Piece8 = 0x1,
+            None = 0x0
+        }
+
+        enum OrangeDiskIcon : byte
+        {
+            On = 0x80,
+            Off = 0x0
+        }
+
+        [Flags]
+        enum MediaTypes : byte
+        {
+            Music = 0x80,
+            Movie = 0x40,
+            Photo = 0x20,
+            Cd_Dvd = 0x10,
+            Tv = 0x8,
+            WebCasting = 0x4,
+            News_Weather = 0x2,
+            None = 0x0
+        }
+
+        [Flags]
+        enum Speakers : byte
+        {
+            L = 0x80,
+            C = 0x40,
+            R = 0x20,
+            SL = 0x10,
+            LFE = 0x8,
+            SR = 0x4,
+            RL = 0x2,
+            SPDIF = 0x1,
+            None = 0x0
+        }
+
+        enum SpeakersRR : byte
+        {
+            RR = 0x80,
+            Off = 0x0
+        }
+
+        [Flags]
+        enum VideoCodecs : byte
+        {
+            MPG = 0x80,
+            DIVX = 0x40,
+            XVID = 0x20,
+            WMV = 0x10,
+            MPG2 = 0x8,
+            AC3 = 0x4,
+            DTS = 0x2,
+            WMA = 0x1,
+            None = 0x0
+        }
+
+        [Flags]
+        enum AudioCodecs : byte
+        {
+            MP3 = 0x80,
+            OGG = 0x40,
+            WMA = 0x20,
+            WAV = 0x10,
+            None = 0x0
+        }
+
+        [Flags]
+        enum AspectRatios : byte
+        {
+            SRC = 0x80,
+            FIT = 0x40,
+            TV = 0x20,
+            HDTV = 0x10,
+            SCR1 = 0x8,
+            SCR2 = 0x4,
+            None = 0x0
+        }
+
+        [Flags]
+        enum EtcIcons : byte
+        {
+            Repeat = 0x80,
+            Shuffle = 0x40,
+            Alarm = 0x20,
+            Recording = 0x10,
+            Volume = 0x8,
+            Time = 0x4,
+            None = 0x0
+        }
+
+        public override void Configure()
+        {
+            Log.Info("(IDisplay) ImonLcd.Configure() called");
+            Form form = new ImonLcd_AdvancedSetupForm();
+            form.ShowDialog();
+            form.Dispose();
+            Log.Info("(IDisplay) ImonLcd.Configure() completed");
+        }
+
+        public override void SetLine(int line, string message)
+        {
+            Log.Info("(IDisplay) ImonLcd.SetLine() called");
+            if (message == null)
+            {
+                Log.Info("(IDisplay) ImonLcd.SetDefaults(): empty message, return");
+                return;
+            }
+
+            int lineToCheckFirst, lineToCheckSecond;
+            if (g_Player.Player != null && g_Player.Player.Playing)
+            {
+                Log.Info("(IDisplay) ImonLcd.SetLine(): determing line to display during playback");
+                if (_preferLine1Playback)
+                {
+                    lineToCheckFirst = 0;
+                    lineToCheckSecond = 1;
+                }
+                else
+                {
+                    lineToCheckFirst = 1;
+                    lineToCheckSecond = 0;
+                }
+            }
+            else
+            {
+                Log.Info("(IDisplay) ImonLcd.SetLine(): determine line to display during general use");
+                if (_preferLine1General)
+                {
+                    lineToCheckFirst = 0;
+                    lineToCheckSecond = 1;
+                }
+                else
+                {
+                    lineToCheckFirst = 1;
+                    lineToCheckSecond = 0;
+                }
+            }
+            Log.Info("(IDisplay) ImonLcd.SetLine(): preferred 0-based line: " + lineToCheckFirst);
+
+            if (line == lineToCheckFirst)
+            {
+                Line1 = message;
+                IDW_SetLcdText(Line1);
+                Log.Info("(IDisplay) ImonLcd.SetLine(): displaying 0-based line (first choice): " + line + ", message: " + Line1);
+            }
+            else if (line == lineToCheckSecond)
+            {
+                if (Line1.Trim().Length == 0 && message.Length > 0)
+                {
+                    Line1 = message;
+                    IDW_SetLcdText(Line1);
+                    Log.Info("(IDisplay) ImonLcd.SetLine(): displaying 0-based line (second choice): " + line + ", message: " + Line1);
+                }
+            }
+            Log.Info("(IDisplay) ImonLcd.SetDefaults() completed");
+        }
+
+        private void MonitorMedia()
+        {
+            Log.Info("(IDisplay) ImonLcd.MonitorMedia() called");
+            while (true)
+            {
+                Log.Info("(IDisplay) ImonLcd.MonitorMedia() thread loop begin");
+                if (_stopMonitorMediaThread)
+                {
+                    IDW_SetLcdAllIcons(false);
+                    return;
+                }
+
+                SetMediaTypeIcons();
+                SetCodecs();
+                SetMediaProgress();
+                SetSpeakerConfig();
+                SetAspectRatio();
+
+                Thread.Sleep(300);
+                Log.Info("(IDisplay) ImonLcd.MonitorMedia() thread loop end");
+            }
+            Log.Info("(IDisplay) ImonLcd.MonitorMedia() complete");
+        }
+
+        private void SetAspectRatio()
+        {
+            Log.Info("(IDisplay) ImonLcd.SetAspectRatio() called");
+            byte newAspectRatioIcons = 0;
+
+            if (g_Player.Player != null && g_Player.Player.Playing &&
+                g_Player.MediaInfo != null && g_Player.IsVideo)
+            {
+                int videoHeight = g_Player.MediaInfo.Height;
+
+                if (videoHeight >= 720)
+                {
+                    newAspectRatioIcons |= (byte)AspectRatios.HDTV;
+                }
+                else if (videoHeight > 0)
+                {
+                    newAspectRatioIcons |= (byte)AspectRatios.TV;
+                }
+                Log.Info("(IDisplay) ImonLcd.SetAspectRatio(): determined video height: " + videoHeight);
+
+                if (g_Player.ARType == Geometry.Type.Original)
+                {
+                    newAspectRatioIcons |= (byte)AspectRatios.SRC;
+                }
+                else
+                {
+                    newAspectRatioIcons |= (byte)AspectRatios.FIT;
+                }
+                Log.Info("(IDisplay) ImonLcd.SetAspectRatio(): determined ARType: " + g_Player.ARType.ToString());
+            }
+            else
+            {
+                newAspectRatioIcons = 0;
+            }
+
+            if (newAspectRatioIcons != _currentAspectRatioIcons)
+            {
+                Log.Info("(IDisplay) ImonLcd.SetAspectRatio(): new settings found, call API");
+                IDW_SetLcdAspectRatioIcon(newAspectRatioIcons);
+                _currentAspectRatioIcons = newAspectRatioIcons;
+            }
+            Log.Info("(IDisplay) ImonLcd.SetAspectRatio() completed");
+        }
+
+        private void SetSpeakerConfig()
+        {
+            Log.Info("(IDisplay) ImonLcd.SetSpeakerConfig() called");
+            byte newSpeakers = 0, newSpeakerRR = 0;
+
+            if (g_Player.Player != null && g_Player.Player.Playing && g_Player.MediaInfo != null)
+            {
+                switch (g_Player.MediaInfo.AudioChannels)
+                {
+                    case 1: // mono
+                    case 2: // stereo
+                        newSpeakers |= (byte)Speakers.L;
+                        newSpeakers |= (byte)Speakers.R;
+                        break;
+                    case 3: // 2.1
+                        newSpeakers |= (byte)Speakers.L;
+                        newSpeakers |= (byte)Speakers.R;
+                        newSpeakers |= (byte)Speakers.LFE;
+                        break;
+                    case 4: // quad
+                        newSpeakers |= (byte)Speakers.L;
+                        newSpeakers |= (byte)Speakers.R;
+                        newSpeakers |= (byte)Speakers.SL;
+                        newSpeakers |= (byte)Speakers.SR;
+                        break;
+                    case 5: // surround
+                        newSpeakers |= (byte)Speakers.L;
+                        newSpeakers |= (byte)Speakers.R;
+                        newSpeakers |= (byte)Speakers.SL;
+                        newSpeakers |= (byte)Speakers.SR;
+                        newSpeakers |= (byte)Speakers.C;
+                        break;
+                    case 6: // 5.1
+                        newSpeakers |= (byte)Speakers.L;
+                        newSpeakers |= (byte)Speakers.R;
+                        newSpeakers |= (byte)Speakers.RL;
+                        newSpeakers |= (byte)Speakers.C;
+                        newSpeakers |= (byte)Speakers.LFE;
+                        newSpeakerRR |= (byte)SpeakersRR.RR;
+                        break;
+                    case 7: // 6.1
+                        newSpeakers |= (byte)Speakers.L;
+                        newSpeakers |= (byte)Speakers.R;
+                        newSpeakers |= (byte)Speakers.SL;
+                        newSpeakers |= (byte)Speakers.SR;
+                        newSpeakers |= (byte)Speakers.C;
+                        newSpeakers |= (byte)Speakers.LFE;
+                        newSpeakers |= (byte)Speakers.RL;
+                        break;
+                    case 8: // 7.1
+                        newSpeakers |= (byte)Speakers.L;
+                        newSpeakers |= (byte)Speakers.R;
+                        newSpeakers |= (byte)Speakers.SL;
+                        newSpeakers |= (byte)Speakers.SR;
+                        newSpeakers |= (byte)Speakers.C;
+                        newSpeakers |= (byte)Speakers.LFE;
+                        newSpeakers |= (byte)Speakers.RL;
+                        newSpeakerRR |= (byte)SpeakersRR.RR;
+                        break;
+                    default: // no audio/unknown
+                        newSpeakers = newSpeakerRR = 0;
+                        break;
+                }
+                Log.Info("(IDisplay) ImonLcd.SetSpeakerConfig(): determined speaker config, speakers: " + newSpeakers + ", speakerRR: " + newSpeakerRR);
+            }
+            else
+            {
+                newSpeakers = newSpeakerRR = 0;
+            }
+            if (newSpeakers != _currentSpeakers || newSpeakerRR != _currentSpeakerRR)
+            {
+                Log.Info("(IDisplay) ImonLcd.SetSpeakerConfig(): new settings found, call API");
+                IDW_SetLcdSpeakerIcon(newSpeakers, newSpeakerRR);
+                _currentSpeakers = newSpeakers;
+                _currentSpeakerRR = newSpeakerRR;
+            }
+            Log.Info("(IDisplay) ImonLcd.SetSpeakerConfig() completed");
+        }
+
+        private void SetCodecs()
+        {
+            Log.Info("(IDisplay) ImonLcd.SetCodecs() called");
+            byte newVideoCodecs = 0;
+            byte newAudioCodecs = 0;
+            if (g_Player.Player != null && g_Player.Player.Playing)
+            {
+                if (g_Player.MediaInfo != null && g_Player.IsVideo)
+                {
+                    // video playback
+                    _videoMediaInfo.Format = g_Player.MediaInfo.VideoCodec;
+                    _audioMediaInfo.Format = g_Player.MediaInfo.AudioCodec;
+
+                    // video stream
+                    if (_videoMediaInfo.IsMpg)
+                    {
+                        newVideoCodecs |= (byte)VideoCodecs.MPG;
+                    }
+                    else if (_videoMediaInfo.IsMpg2)
+                    {
+                        newVideoCodecs |= (byte)VideoCodecs.MPG2;
+                    }
+                    else if (_videoMediaInfo.IsDivx)
+                    {
+                        newVideoCodecs |= (byte)VideoCodecs.DIVX;
+                    }
+                    else if (_videoMediaInfo.IsXvid)
+                    {
+                        newVideoCodecs |= (byte)VideoCodecs.XVID;
+                    }
+                    else if (_videoMediaInfo.IsWmv)
+                    {
+                        newVideoCodecs |= (byte)VideoCodecs.WMV;
+                    }
+
+                    // audio stream
+                    if (_audioMediaInfo.IsMp3)
+                    {
+                        newAudioCodecs |= (byte)AudioCodecs.MP3;
+                    }
+                    else if (_audioMediaInfo.IsWma)
+                    {
+                        newVideoCodecs |= (byte)VideoCodecs.WMA;
+                    }
+                    else if (_audioMediaInfo.IsDts)
+                    {
+                        newVideoCodecs |= (byte)VideoCodecs.DTS;
+                    }
+                    else if (_audioMediaInfo.IsAc3)
+                    {
+                        newVideoCodecs |= (byte)VideoCodecs.AC3;
+                    }
+                    else if (_audioMediaInfo.IsOgg)
+                    {
+                        newAudioCodecs |= (byte)AudioCodecs.OGG;
+                    }
+                    Log.Info("(IDisplay) ImonLcd.SetCodecs(): determined video codec: " + newVideoCodecs);
+                    Log.Info("(IDisplay) ImonLcd.SetCodecs(): determined audio codec: " + newAudioCodecs);
+                }
+                else if (g_Player.IsMusic)
+                {
+                    // music playback
+                    string currentFile = GUIPropertyManager.GetProperty("#Play.Current.File");
+                    Log.Info("(IDisplay) ImonLcd.SetCodecs(): determined current music file: " + currentFile);
+                    if (currentFile != null && currentFile.Length > 0)
+                    {
+                        string extension = System.IO.Path.GetExtension(currentFile).ToUpper();
+
+                        switch (extension)
+                        {
+                            case ".MP3":
+                                newAudioCodecs |= (byte)AudioCodecs.MP3;
+                                break;
+                            case ".OGG":
+                                newAudioCodecs |= (byte)AudioCodecs.OGG;
+                                break;
+                            case ".WMA":
+                                newAudioCodecs |= (byte)AudioCodecs.WMA;
+                                break;
+                            case ".WAV":
+                                newAudioCodecs |= (byte)AudioCodecs.WAV;
+                                break;
+                            default:
+                                break;
+                        }
+                        Log.Info("(IDisplay) ImonLcd.SetCodecs(): determined music codec by extension: " + newAudioCodecs);
+                    }
+                }
+            }
+            else
+            {
+                newVideoCodecs = 0;
+            }
+
+            if (newVideoCodecs != _currentVideoCodecs)
+            {
+                Log.Info("(IDisplay) ImonLcd.SetCodecs(): new video settings found, call API");
+                IDW_SetLcdVideoCodecIcon(newVideoCodecs);
+                _currentVideoCodecs = newVideoCodecs;
+            }
+
+            if (newAudioCodecs != _currentAudioCodecs)
+            {
+                Log.Info("(IDisplay) ImonLcd.SetCodecs(): new audio settings found, call API");
+                IDW_SetLcdAudioCodecIcon(newAudioCodecs);
+                _currentAudioCodecs = newAudioCodecs;
+            }
+            Log.Info("(IDisplay) ImonLcd.SetCodecs() completed");
+        }
+
+        private void SetMediaProgress()
+        {
+            Log.Info("(IDisplay) ImonLcd.SetMediaProgress() called");
+            int newMediaCurrentPosition = 0;
+
+            if (g_Player.Player != null && g_Player.Player.Playing)
+            {
+                double duration = g_Player.Duration;
+                double currentPosition = g_Player.CurrentPosition;
+                if (duration == 0)
+                {
+                    newMediaCurrentPosition = 0;
+                }
+                else
+                {
+                    newMediaCurrentPosition =
+                        (int)((g_Player.CurrentPosition / g_Player.Duration) * MediaTotalTime);
+                }
+                Log.Info("(IDisplay) ImonLcd.SetMediaProgress(): determined media position: " + newMediaCurrentPosition);
+            }
+            else
+            {
+                newMediaCurrentPosition = 0;
+            }
+
+            if (newMediaCurrentPosition != _currentMediaCurrentPosition)
+            {
+                Log.Info("(IDisplay) ImonLcd.SetMediaProgress(): new settings found, call API");
+                IDW_SetLcdProgress(newMediaCurrentPosition, MediaTotalTime);
+                _currentMediaCurrentPosition = newMediaCurrentPosition;
+            }
+            Log.Info("(IDisplay) ImonLcd.SetMediaProgress() completed");
+        }
+
+        private void SetMediaTypeIcons()
+        {
+            Log.Info("(IDisplay) ImonLcd.SetMediaTypeIcons() called");
+            MediaTypes newMediaTypes = MediaTypes.None;
+
+            _activeWindowInfo.ActiveWindow = GUIWindowManager.ActiveWindow;
+            if (_activeWindowInfo.IsWeather)
+            {
+                newMediaTypes |= MediaTypes.News_Weather;
+                Log.Info("(IDisplay) ImonLcd.SetMediaTypeIcons(): in weather plugin");
+            }
+
+            if (g_Player.Player != null && g_Player.Player.Playing)
+            {
+                if (g_Player.IsCDA)
+                {
+                    newMediaTypes |= MediaTypes.Cd_Dvd;
+                    newMediaTypes |= MediaTypes.Music;
+                }
+                if (g_Player.IsDVD || g_Player.IsDVDMenu)
+                {
+                    newMediaTypes |= MediaTypes.Cd_Dvd;
+                    newMediaTypes |= MediaTypes.Movie;
+                }
+                if (g_Player.IsMusic)
+                {
+                    newMediaTypes |= MediaTypes.Music;
+                }
+                if (g_Player.IsTV || g_Player.IsTVRecording)
+                {
+                    newMediaTypes |= MediaTypes.Tv;
+                }
+                if (g_Player.IsVideo)
+                {
+                    newMediaTypes |= MediaTypes.Movie;
+                }
+                if (_activeWindowInfo.IsWebCasting)
+                {
+                    newMediaTypes |= MediaTypes.WebCasting;
+                }
+                Log.Info("(IDisplay) ImonLcd.SetMediaTypeIcons(): determined media type: " + newMediaTypes);
+            }
+
+            if (_currentMediaTypes != newMediaTypes)
+            {
+                Log.Info("(IDisplay) ImonLcd.SetMediaTypeIcons(): new settings found, call API");
+                IDW_SetLcdMediaTypeIcon((byte)newMediaTypes);
+                _currentMediaTypes = newMediaTypes;
+            }
+            Log.Info("(IDisplay) ImonLcd.SetMediaTypeIcons() completed");
+        }
+
+        public override void Initialize()
+        {
+            Log.Info("(IDisplay) ImonLcd.Initialize() called");
+            base.Initialize();
+            _monitorMediaThread = new Thread(new ThreadStart(MonitorMedia));
+            _monitorMediaThread.Start();
+            Log.Info("(IDisplay) ImonLcd.Initialize() completed");
+        }
+
+        public override void CleanUp()
+        {
+            Log.Info("(IDisplay) ImonLcd.CleanUp(): called");
+            if (!Initialized)
+            {
+                return;
+            }
+
+            _stopMonitorMediaThread = true;
+            int maxWaitTime = 10000; // 10 seconds
+            int waitTime = 0;
+            while (_monitorMediaThread.IsAlive)
+            {
+                waitTime += 200;
+                Thread.Sleep(200);
+                if (waitTime >= maxWaitTime)
+                {
+                    try
+                    {
+                        _monitorMediaThread.Abort();
+                    }
+                    catch (ThreadAbortException ex)
+                    {
+                        Log.Error(
+                            "(IDisplay) ImonLcd.CleanUp(): unable to exit mediaMonitorThread cleanly: "
+                            + ex.Message + "\n" + ex.StackTrace);
+                    }
+                    break;
+                }
+            }
+
+            IDW_Uninit();
+            Initialized = false;
+            Log.Info("(IDisplay) ImonLcd.CleanUp(): completed");
+        }
+
+        public override void Dispose()
+        {
+            base.Dispose();
+
+            AdvancedSettings.OnSettingsChanged -=
+                AdvancedSettings_OnSettingsChanged;
+            SystemEvents.PowerModeChanged -=
+                SystemEvents_PowerModeChanged;
+        }
+
+        private void LoadAdvancedSettings()
+        {
+            AdvSettings = AdvancedSettings.Load();
+            _preferLine1General = AdvSettings.PreferFirstLineGeneral;
+            _preferLine1Playback = AdvSettings.PreferFirstLinePlayback;
+        }
+
+        private void AdvancedSettings_OnSettingsChanged()
+        {
+            Log.Info("ImonLcd.AdvancedSettings_OnSettingsChanged(): RELOADING SETTINGS");
+
+            CleanUp();
+            Thread.Sleep(100);
+            LoadAdvancedSettings();
+
+            Initialize();
+        }
+
+        [DllImport("iMONDisplayWrapper.dll")]
+        private static extern int IDW_SetLcdText(
+            [MarshalAs(UnmanagedType.LPWStr)] string line);
+
+        [DllImport("iMONDisplayWrapper.dll")]
+        private static extern int IDW_SetLcdAllIcons(
+            [MarshalAs(UnmanagedType.Bool)] bool on);
+
+        [DllImport("iMONDisplayWrapper.dll")]
+        private static extern int IDW_SetLcdOrangeIcon(
+            byte iconData1, byte iconData2);
+
+        [DllImport("iMONDisplayWrapper.dll")]
+        private static extern int IDW_SetLcdMediaTypeIcon(byte iconData);
+
+        [DllImport("iMONDisplayWrapper.dll")]
+        private static extern int IDW_SetLcdSpeakerIcon(
+            byte iconData1, byte iconData2);
+
+        [DllImport("iMONDisplayWrapper.dll")]
+        private static extern int IDW_SetLcdVideoCodecIcon(byte iconData);
+
+        [DllImport("iMONDisplayWrapper.dll")]
+        private static extern int IDW_SetLcdAudioCodecIcon(byte iconData);
+
+        [DllImport("iMONDisplayWrapper.dll")]
+        private static extern int IDW_SetLcdAspectRatioIcon(byte iconData);
+
+        [DllImport("iMONDisplayWrapper.dll")]
+        private static extern int IDW_SetLcdEtcIcon(byte iconData);
+
+        [DllImport("iMONDisplayWrapper.dll")]
+        private static extern int IDW_SetLcdProgress(
+            int currentPosition, int total);
+
+        private class ImonMediaInfo
+        {
+            const string _mpgCodec = "MPEG VIDEO";
+            readonly string[] _divxCodecs = { "DX50", "DIVX", "DIV3", "3IV" };
+            const string _xvidCodec = "XVID";
+            const string _wmvCodec = "VC-1";
+            const string _mpg2Codec = "AVC";
+            const string _dtsCodec = "DTS";
+            const string _wmaCodec = "WMA";
+            const string _ac3Codec = "AC-3";
+            const string _mp3Codec = "LAYER 3";
+            const string _oggCodec = "VORBIS";
+            private string _format;
+
+            public string Format
+            {
+                get { return _format; }
+                set
+                {
+                    _format = value;
+                    if (_format != null && _format.Length > 0)
+                    {
+                        _format = _format.ToUpper();
+                    }
+                }
+            }
+
+            public bool IsMpg
+            {
+                get { return IsCodec(_mpgCodec); }
+            }
+
+            public bool IsDivx
+            {
+                get
+                {
+                    if (Format != null && Format.Length > 0)
+                    {
+                        foreach (string codec in _divxCodecs)
+                        {
+                            if (Format.IndexOf(codec) >= 0)
+                            {
+                                return true;
+                            }
+                        }
+                        return false;
+                    }
+                    return false;
+                }
+            }
+
+            public bool IsXvid
+            {
+                get { return IsCodec(_xvidCodec); }
+            }
+
+            public bool IsWmv
+            {
+                get { return IsCodec(_wmvCodec); }
+            }
+
+            public bool IsMpg2
+            {
+                get { return IsCodec(_mpg2Codec); }
+            }
+
+            public bool IsWma
+            {
+                get { return IsCodec(_wmaCodec); }
+            }
+
+            public bool IsDts
+            {
+                get { return IsCodec(_dtsCodec); }
+            }
+
+            public bool IsAc3
+            {
+                get { return IsCodec(_ac3Codec); }
+            }
+
+            public bool IsMp3
+            {
+                get { return IsCodec(_mp3Codec); }
+            }
+
+            public bool IsOgg
+            {
+                get { return IsCodec(_oggCodec); }
+            }
+
+            private bool IsCodec(string codec)
+            {
+                if (Format != null && Format.Length > 0)
+                {
+                    if (Format.IndexOf(codec) >= 0)
+                    {
+                        return true;
+                    }
+                    return false;
+                }
+                return false;
+            }
+        }
+
+        private class ActiveWindowInfo
+        {
+            const int Weather = (int)GUIWindow.Window.WINDOW_WEATHER;
+            readonly int[] MyNetflix = { 10099 };
+            readonly int[] MyOnlineVideos = { 4755, 4757, 4758, 4759 };
+            readonly int[] MyTrailers = { 5900 };
+
+            readonly List<int> OnlineStreamingPluginWindows;
+
+            public int ActiveWindow { get; set; }
+
+            public bool IsWeather
+            {
+                get { return ActiveWindow == Weather; }
+            }
+
+            public bool IsWebCasting
+            {
+                get { return OnlineStreamingPluginWindows.Contains(ActiveWindow); }
+            }
+
+            public ActiveWindowInfo()
+            {
+                OnlineStreamingPluginWindows = new List<int>();
+                OnlineStreamingPluginWindows.AddRange(MyNetflix);
+                OnlineStreamingPluginWindows.AddRange(MyOnlineVideos);
+                OnlineStreamingPluginWindows.AddRange(MyTrailers);
+            }
+        }
+
+        [Serializable]
+        public class AdvancedSettings
+        {
+            #region Delegates
+
+            public delegate void OnSettingsChangedHandler();
+
+            #endregion
+
+            private static AdvancedSettings m_Instance;
+            public const string m_Filename = "MiniDisplay_ImonLcd.xml";
+
+            public static AdvancedSettings Instance
+            {
+                get
+                {
+                    if (m_Instance == null)
+                    {
+                        m_Instance = Load();
+                    }
+                    return m_Instance;
+                }
+                set { m_Instance = value; }
+            }
+
+            [XmlAttribute]
+            public bool PreferFirstLineGeneral { get; set; }
+
+            [XmlAttribute]
+            public bool PreferFirstLinePlayback { get; set; }
+
+            public static event OnSettingsChangedHandler OnSettingsChanged;
+
+            private static void Default(AdvancedSettings _settings)
+            {
+                _settings.PreferFirstLineGeneral = true;
+                _settings.PreferFirstLinePlayback = true;
+            }
+
+            public static AdvancedSettings Load()
+            {
+                AdvancedSettings settings;
+                Log.Info("ImonLcd.AdvancedSettings.Load(): started");
+                if (File.Exists(Config.GetFile(Config.Dir.Config, m_Filename)))
+                {
+                    Log.Info("ImonLcd.AdvancedSettings.Load(): Loading settings from XML file");
+                    var serializer = new XmlSerializer(typeof(AdvancedSettings));
+                    var xmlReader = new XmlTextReader(Config.GetFile(Config.Dir.Config, m_Filename));
+                    settings = (AdvancedSettings)serializer.Deserialize(xmlReader);
+                    xmlReader.Close();
+                }
+                else
+                {
+                    Log.Info("ImonLcd.AdvancedSettings.Load(): Loading settings from defaults");
+                    settings = new AdvancedSettings();
+                    Default(settings);
+                    Log.Info("ImonLcd.AdvancedSettings.Load(): Loaded settings from defaults");
+                }
+                Log.Info("ImonLcd.AdvancedSettings.Load(): completed");
+                return settings;
+            }
+
+            public static void NotifyDriver()
+            {
+                if (OnSettingsChanged != null)
+                {
+                    OnSettingsChanged();
+                }
+            }
+
+            public static void Save()
+            {
+                Save(Instance);
+            }
+
+            public static void Save(AdvancedSettings ToSave)
+            {
+                var serializer = new XmlSerializer(typeof(AdvancedSettings));
+                var writer = new XmlTextWriter(Config.GetFile(Config.Dir.Config, m_Filename),
+                                               Encoding.UTF8) { Formatting = Formatting.Indented, Indentation = 2 };
+                serializer.Serialize(writer, ToSave);
+                writer.Close();
+            }
+
+            public static void SetDefaults()
+            {
+                Default(Instance);
+            }
+        }
+    }
+}
diff --git a/mediaportal/MiniDisplayLibrary/MiniDisplayPlugin/Drivers/ImonLcd_AdvancedSetupForm.Designer.cs b/mediaportal/MiniDisplayLibrary/MiniDisplayPlugin/Drivers/ImonLcd_AdvancedSetupForm.Designer.cs
new file mode 100644
index 0000000..64ef381
--- /dev/null
+++ b/mediaportal/MiniDisplayLibrary/MiniDisplayPlugin/Drivers/ImonLcd_AdvancedSetupForm.Designer.cs
@@ -0,0 +1,162 @@
+﻿namespace MediaPortal.ProcessPlugins.MiniDisplayPlugin.Drivers
+{
+    partial class ImonLcd_AdvancedSetupForm
+    {
+        /// <summary>
+        /// Required designer variable.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary>
+        /// Clean up any resources being used.
+        /// </summary>
+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Windows Form Designer generated code
+
+        /// <summary>
+        /// Required method for Designer support - do not modify
+        /// the contents of this method with the code editor.
+        /// </summary>
+        private void InitializeComponent()
+        {
+            this.btnOK = new MediaPortal.UserInterface.Controls.MPButton();
+            this.gbxLineOptions = new System.Windows.Forms.GroupBox();
+            this.gbxPlayback = new System.Windows.Forms.GroupBox();
+            this.rbtnPlaybackSecondLine = new System.Windows.Forms.RadioButton();
+            this.rbtnPlaybackFirstLine = new System.Windows.Forms.RadioButton();
+            this.gbxGeneral = new System.Windows.Forms.GroupBox();
+            this.rbtnGeneralSecondLine = new System.Windows.Forms.RadioButton();
+            this.rbtnGeneralFirstLine = new System.Windows.Forms.RadioButton();
+            this.gbxLineOptions.SuspendLayout();
+            this.gbxPlayback.SuspendLayout();
+            this.gbxGeneral.SuspendLayout();
+            this.SuspendLayout();
+            // 
+            // btnOK
+            // 
+            this.btnOK.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+            this.btnOK.Location = new System.Drawing.Point(244, 141);
+            this.btnOK.Name = "btnOK";
+            this.btnOK.Size = new System.Drawing.Size(78, 23);
+            this.btnOK.TabIndex = 7;
+            this.btnOK.Text = "&OK";
+            this.btnOK.UseVisualStyleBackColor = true;
+            this.btnOK.Click += new System.EventHandler(this.btnOK_Click);
+            // 
+            // gbxLineOptions
+            // 
+            this.gbxLineOptions.Controls.Add(this.gbxPlayback);
+            this.gbxLineOptions.Controls.Add(this.gbxGeneral);
+            this.gbxLineOptions.Location = new System.Drawing.Point(13, 13);
+            this.gbxLineOptions.Name = "gbxLineOptions";
+            this.gbxLineOptions.Size = new System.Drawing.Size(309, 123);
+            this.gbxLineOptions.TabIndex = 8;
+            this.gbxLineOptions.TabStop = false;
+            this.gbxLineOptions.Text = "Line Options";
+            // 
+            // gbxPlayback
+            // 
+            this.gbxPlayback.Controls.Add(this.rbtnPlaybackSecondLine);
+            this.gbxPlayback.Controls.Add(this.rbtnPlaybackFirstLine);
+            this.gbxPlayback.Location = new System.Drawing.Point(7, 69);
+            this.gbxPlayback.Name = "gbxPlayback";
+            this.gbxPlayback.Size = new System.Drawing.Size(296, 43);
+            this.gbxPlayback.TabIndex = 1;
+            this.gbxPlayback.TabStop = false;
+            this.gbxPlayback.Text = "During Playback";
+            // 
+            // rbtnPlaybackSecondLine
+            // 
+            this.rbtnPlaybackSecondLine.AutoSize = true;
+            this.rbtnPlaybackSecondLine.Location = new System.Drawing.Point(145, 18);
+            this.rbtnPlaybackSecondLine.Name = "rbtnPlaybackSecondLine";
+            this.rbtnPlaybackSecondLine.Size = new System.Drawing.Size(116, 17);
+            this.rbtnPlaybackSecondLine.TabIndex = 3;
+            this.rbtnPlaybackSecondLine.TabStop = true;
+            this.rbtnPlaybackSecondLine.Text = "Prefer Second Line";
+            this.rbtnPlaybackSecondLine.UseVisualStyleBackColor = true;
+            // 
+            // rbtnPlaybackFirstLine
+            // 
+            this.rbtnPlaybackFirstLine.AutoSize = true;
+            this.rbtnPlaybackFirstLine.Location = new System.Drawing.Point(7, 19);
+            this.rbtnPlaybackFirstLine.Name = "rbtnPlaybackFirstLine";
+            this.rbtnPlaybackFirstLine.Size = new System.Drawing.Size(98, 17);
+            this.rbtnPlaybackFirstLine.TabIndex = 2;
+            this.rbtnPlaybackFirstLine.TabStop = true;
+            this.rbtnPlaybackFirstLine.Text = "Prefer First Line";
+            this.rbtnPlaybackFirstLine.UseVisualStyleBackColor = true;
+            // 
+            // gbxGeneral
+            // 
+            this.gbxGeneral.Controls.Add(this.rbtnGeneralSecondLine);
+            this.gbxGeneral.Controls.Add(this.rbtnGeneralFirstLine);
+            this.gbxGeneral.Location = new System.Drawing.Point(7, 20);
+            this.gbxGeneral.Name = "gbxGeneral";
+            this.gbxGeneral.Size = new System.Drawing.Size(296, 43);
+            this.gbxGeneral.TabIndex = 0;
+            this.gbxGeneral.TabStop = false;
+            this.gbxGeneral.Text = "General";
+            // 
+            // rbtnGeneralSecondLine
+            // 
+            this.rbtnGeneralSecondLine.AutoSize = true;
+            this.rbtnGeneralSecondLine.Location = new System.Drawing.Point(145, 19);
+            this.rbtnGeneralSecondLine.Name = "rbtnGeneralSecondLine";
+            this.rbtnGeneralSecondLine.Size = new System.Drawing.Size(116, 17);
+            this.rbtnGeneralSecondLine.TabIndex = 1;
+            this.rbtnGeneralSecondLine.TabStop = true;
+            this.rbtnGeneralSecondLine.Text = "Prefer Second Line";
+            this.rbtnGeneralSecondLine.UseVisualStyleBackColor = true;
+            // 
+            // rbtnGeneralFirstLine
+            // 
+            this.rbtnGeneralFirstLine.AutoSize = true;
+            this.rbtnGeneralFirstLine.Location = new System.Drawing.Point(7, 20);
+            this.rbtnGeneralFirstLine.Name = "rbtnGeneralFirstLine";
+            this.rbtnGeneralFirstLine.Size = new System.Drawing.Size(98, 17);
+            this.rbtnGeneralFirstLine.TabIndex = 0;
+            this.rbtnGeneralFirstLine.TabStop = true;
+            this.rbtnGeneralFirstLine.Text = "Prefer First Line";
+            this.rbtnGeneralFirstLine.UseVisualStyleBackColor = true;
+            // 
+            // ImonLcd_AdvancedSetupForm
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.ClientSize = new System.Drawing.Size(334, 176);
+            this.Controls.Add(this.gbxLineOptions);
+            this.Controls.Add(this.btnOK);
+            this.Name = "ImonLcd_AdvancedSetupForm";
+            this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
+            this.Text = "MiniDisplay - Setup - Advanced Settings";
+            this.gbxLineOptions.ResumeLayout(false);
+            this.gbxPlayback.ResumeLayout(false);
+            this.gbxPlayback.PerformLayout();
+            this.gbxGeneral.ResumeLayout(false);
+            this.gbxGeneral.PerformLayout();
+            this.ResumeLayout(false);
+
+        }
+
+        #endregion
+
+        private UserInterface.Controls.MPButton btnOK;
+        private System.Windows.Forms.GroupBox gbxLineOptions;
+        private System.Windows.Forms.GroupBox gbxPlayback;
+        private System.Windows.Forms.RadioButton rbtnPlaybackSecondLine;
+        private System.Windows.Forms.RadioButton rbtnPlaybackFirstLine;
+        private System.Windows.Forms.GroupBox gbxGeneral;
+        private System.Windows.Forms.RadioButton rbtnGeneralSecondLine;
+        private System.Windows.Forms.RadioButton rbtnGeneralFirstLine;
+    }
+}
\ No newline at end of file
diff --git a/mediaportal/MiniDisplayLibrary/MiniDisplayPlugin/Drivers/ImonLcd_AdvancedSetupForm.cs b/mediaportal/MiniDisplayLibrary/MiniDisplayPlugin/Drivers/ImonLcd_AdvancedSetupForm.cs
new file mode 100644
index 0000000..8956650
--- /dev/null
+++ b/mediaportal/MiniDisplayLibrary/MiniDisplayPlugin/Drivers/ImonLcd_AdvancedSetupForm.cs
@@ -0,0 +1,41 @@
+﻿using System;
+using MediaPortal.UserInterface.Controls;
+
+namespace MediaPortal.ProcessPlugins.MiniDisplayPlugin.Drivers
+{
+    public partial class ImonLcd_AdvancedSetupForm : MPConfigForm
+    {
+        public ImonLcd_AdvancedSetupForm()
+        {
+            InitializeComponent();
+
+            if (ImonLcd.AdvancedSettings.Instance.PreferFirstLineGeneral)
+            {
+                rbtnGeneralFirstLine.Checked = true;
+            }
+            else
+            {
+                rbtnGeneralSecondLine.Checked = true;
+            }
+
+            if (ImonLcd.AdvancedSettings.Instance.PreferFirstLinePlayback)
+            {
+                rbtnPlaybackFirstLine.Checked = true;
+            }
+            else
+            {
+                rbtnPlaybackSecondLine.Checked = true;
+            }
+        }
+
+        private void btnOK_Click(object sender, EventArgs e)
+        {
+            ImonLcd.AdvancedSettings.Instance.PreferFirstLineGeneral =
+                rbtnGeneralFirstLine.Checked;
+            ImonLcd.AdvancedSettings.Instance.PreferFirstLinePlayback =
+                rbtnPlaybackFirstLine.Checked;
+            ImonLcd.AdvancedSettings.Save();
+            Close();
+        }
+    }
+}
diff --git a/mediaportal/MiniDisplayLibrary/MiniDisplayPlugin/Drivers/ImonLcd_AdvancedSetupForm.resx b/mediaportal/MiniDisplayLibrary/MiniDisplayPlugin/Drivers/ImonLcd_AdvancedSetupForm.resx
new file mode 100644
index 0000000..7080a7d
--- /dev/null
+++ b/mediaportal/MiniDisplayLibrary/MiniDisplayPlugin/Drivers/ImonLcd_AdvancedSetupForm.resx
@@ -0,0 +1,120 @@
+﻿<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+</root>
\ No newline at end of file
diff --git a/mediaportal/MiniDisplayLibrary/MiniDisplayPlugin/Drivers/ImonVfd.cs b/mediaportal/MiniDisplayLibrary/MiniDisplayPlugin/Drivers/ImonVfd.cs
new file mode 100644
index 0000000..89a6423
--- /dev/null
+++ b/mediaportal/MiniDisplayLibrary/MiniDisplayPlugin/Drivers/ImonVfd.cs
@@ -0,0 +1,42 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Runtime.InteropServices;
+using System.Text;
+using MediaPortal.GUI.Library;
+
+namespace MediaPortal.ProcessPlugins.MiniDisplayPlugin.Drivers
+{
+    /// <summary>
+    /// iMON VFD Driver for iMON Manager >= 8.01.0419
+    /// </summary>
+    public class ImonVfd : ImonBase
+    {
+        public ImonVfd()
+        {
+            UnsupportedDeviceErrorMessage = "Only VFDs are supported";
+            Description = "iMON VFD for iMON Manager >= 8.01.0419";
+            Name = "iMONVFD";
+            DisplayType = DSPN_DSP_VFD;
+        }
+
+        public override void SetLine(int line, string message)
+        {
+            if (line == 0)
+            {
+                Line1 = message;
+            }
+            else if (line == 1)
+            {
+                Line2 = message;
+                IDW_SetVfdText(Line1, Line2);
+            }
+        }
+
+        [DllImport("iMONDisplayWrapper.dll")]
+        private static extern int IDW_SetVfdText(
+          [MarshalAs(UnmanagedType.LPWStr)] string line1,
+          [MarshalAs(UnmanagedType.LPWStr)] string line2);
+
+    }
+}
diff --git a/mediaportal/MiniDisplayLibrary/MiniDisplayPlugin/Settings.cs b/mediaportal/MiniDisplayLibrary/MiniDisplayPlugin/Settings.cs
index 464ef96..7d9a640 100644
--- a/mediaportal/MiniDisplayLibrary/MiniDisplayPlugin/Settings.cs
+++ b/mediaportal/MiniDisplayLibrary/MiniDisplayPlugin/Settings.cs
@@ -1,6 +1,6 @@
-#region Copyright (C) 2005-2011 Team MediaPortal
+#region Copyright (C) 2005-2010 Team MediaPortal
 
-// Copyright (C) 2005-2011 Team MediaPortal
+// Copyright (C) 2005-2010 Team MediaPortal
 // http://www.team-mediaportal.com
 // 
 // MediaPortal is free software: you can redistribute it and/or modify
@@ -319,6 +319,16 @@ namespace MediaPortal.ProcessPlugins.MiniDisplayPlugin
       list.Add(new ShuttlePF27());
       if (this.ExtensiveLogging)
       {
+        Log.Info("MiniDisplay.Settings.LoadDrivers(): Loading iMON VFD...");
+      }
+      list.Add(new ImonVfd());
+      if (this.ExtensiveLogging)
+      {
+        Log.Info("MiniDisplay.Settings.LoadDrivers(): Loading iMON LCD...");
+      }
+      list.Add(new ImonLcd());
+      if (this.ExtensiveLogging)
+      {
         Log.Info("MiniDisplay.Settings.LoadDrivers(): Loading Debug Display...");
       }
       list.Add(new DebugForm());
-- 
1.8.3.msysgit.0

