Client/Client.cs
author StephaneLenclud
Wed, 06 May 2015 19:40:00 +0200
changeset 133 004d7509f280
parent 80 408ef0501cb7
child 138 426cc984fd18
permissions -rw-r--r--
Update to latest version of NAudio and SharpLibHid.
     1 //
     2 // Copyright (C) 2014-2015 Stéphane Lenclud.
     3 //
     4 // This file is part of SharpDisplayManager.
     5 //
     6 // SharpDisplayManager is free software: you can redistribute it and/or modify
     7 // it under the terms of the GNU General Public License as published by
     8 // the Free Software Foundation, either version 3 of the License, or
     9 // (at your option) any later version.
    10 //
    11 // SharpDisplayManager is distributed in the hope that it will be useful,
    12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
    13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    14 // GNU General Public License for more details.
    15 //
    16 // You should have received a copy of the GNU General Public License
    17 // along with SharpDisplayManager.  If not, see <http://www.gnu.org/licenses/>.
    18 //
    19 
    20 using System;
    21 using System.Collections.Generic;
    22 using System.Linq;
    23 using System.Text;
    24 using System.Threading.Tasks;
    25 using System.Windows.Forms;
    26 using SharpDisplay;
    27 using System.ServiceModel;
    28 using System.ServiceModel.Channels;
    29 
    30 
    31 namespace SharpDisplayClient
    32 {
    33     /// <summary>
    34     ///
    35     /// </summary>
    36     [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
    37     public class Callback : ICallback, IDisposable
    38     {
    39         private MainForm MainForm { get; set; }
    40 
    41         public Callback(MainForm aMainForm)
    42         {
    43             MainForm = aMainForm;
    44         }
    45 
    46         public void OnConnected()
    47         {
    48             //Debug.Assert(Thread.CurrentThread.IsThreadPoolThread);
    49             //Trace.WriteLine("Callback thread = " + Thread.CurrentThread.ManagedThreadId);
    50 
    51             MessageBox.Show("OnConnected()", "Client");
    52         }
    53 
    54 
    55         public void OnCloseOrder()
    56         {
    57             //Debug.Assert(Thread.CurrentThread.IsThreadPoolThread);
    58             //Trace.WriteLine("Callback thread = " + Thread.CurrentThread.ManagedThreadId);
    59 
    60             //MessageBox.Show("OnServerClosing()", "Client");
    61             MainForm.CloseConnectionThreadSafe();
    62             MainForm.CloseThreadSafe();
    63         }
    64 
    65         //From IDisposable
    66         public void Dispose()
    67         {
    68 
    69         }
    70     }
    71 
    72 
    73     /// <summary>
    74     ///
    75     /// </summary>
    76     [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
    77     public class Client : DuplexClientBase<IService>
    78     {
    79         public string SessionId { get { return InnerChannel.SessionId; } }
    80 
    81         public Client(ICallback aCallback)
    82             : base(new InstanceContext(aCallback), new NetTcpBinding(SecurityMode.None, true), new EndpointAddress("net.tcp://localhost:8001/DisplayService"))
    83         { }
    84 
    85         public void SetName(string aClientName)
    86         {
    87             Channel.SetName(aClientName);
    88         }
    89 
    90         public void SetLayout(TableLayout aLayout)
    91         {
    92             Channel.SetLayout(aLayout);
    93         }
    94 
    95         public void SetField(DataField aField)
    96         {
    97             Channel.SetField(aField);
    98         }
    99 
   100         public void SetFields(System.Collections.Generic.IList<DataField> aFields)
   101         {
   102             Channel.SetFields(aFields);
   103         }
   104 
   105         public int ClientCount()
   106         {
   107             return Channel.ClientCount();
   108         }
   109 
   110         public bool IsReady()
   111         {
   112             return State == CommunicationState.Opened || State == CommunicationState.Created;
   113         }
   114     }
   115 
   116 
   117     /// <summary>
   118     /// Handle connection with our Sharp Display Server.
   119     /// If the connection is faulted it will attempt to restart it.
   120     /// </summary>
   121     public class DisplayClient
   122     {
   123         private Client iClient;
   124         private Callback iCallback;
   125         private bool resetingConnection = false;
   126 
   127         private MainForm MainForm { get; set; }
   128         public string SessionId { get { return iClient.SessionId; } }
   129         public string Name { get; private set; }
   130         private TableLayout Layout { get; set; }
   131         private System.Collections.Generic.IList<DataField> Fields { get; set; }
   132 
   133 
   134         public DisplayClient(MainForm aMainForm)
   135         {
   136             MainForm = aMainForm;
   137             Name = "";
   138             Fields = new DataField[]{};
   139         }
   140 
   141         /// <summary>
   142         /// Initialize our server connection.
   143         /// </summary>
   144         public void Open()
   145         {
   146             iCallback = new Callback(MainForm);
   147             iClient = new Client(iCallback);
   148         }
   149 
   150         /// <summary>
   151         /// Terminate our server connection.
   152         /// </summary>
   153         public void Close()
   154         {
   155             iClient.Close();
   156             iClient = null;
   157             iCallback.Dispose();
   158             iCallback = null;
   159         }
   160 
   161         /// <summary>
   162         /// Tells whether a server connection is available.
   163         /// </summary>
   164         /// <returns>True if a server connection is available. False otherwise.</returns>
   165         public bool IsReady()
   166         {
   167             return (iClient != null && iCallback != null && iClient.IsReady());
   168         }
   169 
   170         /// <summary>
   171         /// Check if our server connection is available and attempt reset it if it isn't.
   172         /// This is notably dealing with timed out connections.
   173         /// </summary>
   174         public void CheckConnection()
   175         {
   176             if (!IsReady() && !resetingConnection)
   177             {
   178                 //Try to reconnect
   179                 Open();
   180 
   181                 //Avoid stack overflow in case of persisting failure
   182                 resetingConnection = true;
   183 
   184                 try
   185                 {
   186                     //On reconnect there is a bunch of properties we need to reset
   187                     if (Name != "")
   188                     {
   189                         iClient.SetName(Name);
   190                     }
   191 
   192                     SetLayout(Layout);
   193                     iClient.SetFields(Fields);
   194                 }
   195                 finally
   196                 {
   197                     //Make sure our this state does not get out of sync
   198                     resetingConnection = true;
   199                 }
   200             }
   201         }
   202 
   203         public void SetName(string aClientName)
   204         {
   205             Name = aClientName;
   206             CheckConnection();
   207             iClient.SetName(aClientName);
   208         }
   209 
   210 
   211         public void SetLayout(TableLayout aLayout)
   212         {
   213             Layout = aLayout;
   214             CheckConnection();
   215             iClient.SetLayout(aLayout);
   216         }
   217 
   218         /// <summary>
   219         /// Set the specified field.
   220         /// </summary>
   221         /// <param name="aField"></param>
   222         /// <returns>True if the specified field was set client side. False means you need to redefine all your fields using CreateFields.</returns>
   223         public bool SetField(DataField aField)
   224         {
   225             int i = 0;
   226             bool fieldFound = false;
   227             foreach (DataField field in Fields)
   228             {
   229                 if (field.Index == aField.Index)
   230                 {
   231                     //Update our field then
   232                     Fields[i] = aField;
   233                     fieldFound = true;
   234                     break;
   235                 }
   236                 i++;
   237             }
   238 
   239             if (!fieldFound)
   240             {
   241                 //Field not found, make to use SetFields with all your fields at least once after setting your layout.
   242                 return false;
   243             }
   244 
   245             CheckConnection();
   246             iClient.SetField(aField);
   247             return true;
   248         }
   249 
   250         /// <summary>
   251         /// Use this function when updating existing fields.
   252         /// </summary>
   253         /// <param name="aFields"></param>
   254         public bool SetFields(System.Collections.Generic.IList<DataField> aFields)
   255         {
   256             int fieldFoundCount = 0;
   257             foreach (DataField fieldUpdate in aFields)
   258             {
   259                 int i = 0;
   260                 foreach (DataField existingField in Fields)
   261                 {
   262                     if (existingField.Index == fieldUpdate.Index)
   263                     {
   264                         //Update our field then
   265                         Fields[i] = fieldUpdate;
   266                         fieldFoundCount++;
   267                         //Move on to the next field
   268                         break;
   269                     }
   270                     i++;
   271                 }
   272             }
   273 
   274             //
   275             if (fieldFoundCount!=aFields.Count)
   276             {
   277                 //Field not found, make sure to use SetFields with all your fields at least once after setting your layout.
   278                 return false;
   279             }
   280 
   281             CheckConnection();
   282             iClient.SetFields(aFields);
   283             return true;
   284         }
   285 
   286         /// <summary>
   287         /// Use this function when creating your fields.
   288         /// </summary>
   289         /// <param name="aFields"></param>
   290         public void CreateFields(System.Collections.Generic.IList<DataField> aFields)
   291         {
   292             Fields = aFields;
   293             CheckConnection();
   294             iClient.SetFields(aFields);
   295         }
   296 
   297         public int ClientCount()
   298         {
   299             CheckConnection();
   300             return iClient.ClientCount();
   301         }
   302 
   303 
   304 
   305     }
   306 
   307 
   308 }