Index: trunk/FACT++/src/RemoteControl.cc
===================================================================
--- trunk/FACT++/src/RemoteControl.cc	(revision 14125)
+++ trunk/FACT++/src/RemoteControl.cc	(revision 14126)
@@ -49,13 +49,11 @@
 
     // If we have not cd'ed to a server show only the line start
-    if (fCurrentServer.empty())
+    if (fCurrentServer.empty() || !fImp)
         return beg + "> ";
 
     // Check if we have cd'ed to a valid server
-    const ClientList::const_iterator l = fClientList.find(fCurrentServer);
-    if (l==fClientList.end())
+    const pair<int32_t, string> state = fImp->GetServerState(fCurrentServer);
+    if (state.first==-256)
         return beg + "> ";
-
-    const State state = GetState(fCurrentServer, l->second->GetState());
 
     // The server
@@ -63,9 +61,9 @@
 
     // If no match found or something wrong found just output the server
-    if (state.index<-1)
+    if (state.first<-1)
         return beg + " " + serv + "> ";
 
     // If everything found add the state to the server
-    return beg + " " + serv + ":\033[32m\033[1m" + state.name + "\033[0m> ";
+    return beg + " " + serv + ":\033[32m\033[1m" + state.second + "\033[0m> ";
 }
 
@@ -77,19 +75,16 @@
 
     // If we have not cd'ed to a server show only the line start
-    if (fCurrentServer.empty())
+    if (fCurrentServer.empty() || !fImp)
         return beg + "> ";
 
-    // Check if we have cd'ed to a valid server
-    const ClientList::const_iterator l = fClientList.find(fCurrentServer);
-    if (l==fClientList.end())
+    const pair<int32_t, string> state = fImp->GetServerState(fCurrentServer);
+    if (state.first==-256)
         return beg + "> ";//Form("\n[%d] \033[34m\033[1m%s\033[0m> ", GetLine(), fCurrentServer.c_str());
 
-    const State state = GetState(fCurrentServer, l->second->GetState());
-
     // If no match found or something wrong found just output the server
-    if (state.index<-1)
+    if (state.first<-1)
         return beg + " " + fCurrentServer + "> ";
 
     // If everything found add the state to the server
-    return beg + " " + fCurrentServer + ":" + state.name + "> ";
+    return beg + " " + fCurrentServer + ":" + state.second + "> ";
 }
Index: trunk/FACT++/src/RemoteControl.h
===================================================================
--- trunk/FACT++/src/RemoteControl.h	(revision 14125)
+++ trunk/FACT++/src/RemoteControl.h	(revision 14126)
@@ -1,6 +1,4 @@
 #ifndef FACT_RemoteControl
 #define FACT_RemoteControl
-
-#include "InterpreterV8.h"
 
 // **************************************************************************
@@ -18,7 +16,9 @@
 **/
 // **************************************************************************
-#include "DimNetwork.h"
-
-class RemoteControlImp : public DimNetwork
+#include <string>
+
+using namespace std;
+
+class RemoteControlImp
 {
 protected:
@@ -29,12 +29,13 @@
 protected:
     // Redirect asynchronous output to the output window
-    RemoteControlImp(std::ostream &out, std::ostream &in) :
-        DimNetwork(out), lout(in)
-    {
-    }
+    RemoteControlImp(std::ostream &, std::ostream &in) : lout(in)
+    {
+    }
+    virtual ~RemoteControlImp() { }
     bool ProcessCommand(const std::string &str);
+
+    virtual bool HasServer(const std::string &) { return false; }
+    virtual bool SendDimCommand(ostream &, std::string &, const std::string &) { return false; }
 };
-
-
 
 // **************************************************************************
@@ -55,18 +56,20 @@
 **/
 // **************************************************************************
-#include "WindowLog.h"
+#include "StateMachineDimControl.h"
+
+#include "InterpreterV8.h"
 #include "ReadlineColor.h"
+#include "Event.h"
 #include "tools.h"
-#include "MainImp.h"
 
 template <class T>
 class RemoteControl : public T, public RemoteControlImp, public InterpreterV8
 {
-private:
-    MessageImp *fImp;
+protected:
+    StateMachineDimControl *fImp;
 
     void SetSection(int s) { if (fImp) fImp->Write(Time(), "", s); }
 
-    int Write(const Time &time, const std::string &txt, int qos=kMessage)
+    int Write(const Time &time, const std::string &txt, int qos=MessageImp::kMessage)
     {
         if (!fImp)
@@ -76,4 +79,6 @@
 
     void exitHandler(int code) { if (dynamic_cast<MainImp*>(fImp)) dynamic_cast<MainImp*>(fImp)->Stop(code); else exit(code); }
+
+    // ==================== Readline tab-completion =====================
 
     static void append(std::string &str)
@@ -121,44 +126,49 @@
     }
 
-    void RemoveServer(std::string s)
-    {
-        DimNetwork::RemoveServer(s);
-        if (fCurrentServer==s)
-        {
+    void EventHook()
+    {
+        if (fImp && !fImp->HasServer(fCurrentServer))
             fCurrentServer = "";
-            T::UpdatePrompt();
-        }
-    }
-
-    void RemoveAllServers()
-    {
-        DimNetwork::RemoveAllServers();
-        fCurrentServer = "";
-        T::UpdatePrompt();
-    }
-
-    // ===========================================================================
-
-    virtual void JsLoad(const std::string &)         { SetSection(-2); }
-    virtual void JsStart(const std::string &)        { SetSection(-1); }
-    virtual void JsEnd(const std::string &)          { SetSection(-3); }
-    virtual bool JsSend(const std::string &str)      { return ProcessCommand(str); }
-    virtual void JsPrint(const std::string &msg)     { fImp->Comment(msg); }
-    virtual void JsException(const std::string &str) { fImp->Error(str); }
-
-    int JsState(const string &server)
-    {
-        const ClientList::const_iterator l = fClientList.find(server);
-        return l==fClientList.end() ? -256 : l->second->GetState();
-    }
-
-    string JsName(const string &server)
-    {
-
-        const ClientList::const_iterator l = fClientList.find(server);
-        if (l==fClientList.end())
-            return "";
-
-        return GetState(server, l->second->GetState()).name;
+
+        T::EventHook();
+    }
+
+    // ===== Interface to access the DIM network through the StateMachine ====
+
+    bool HasServer(const std::string &server) { return fImp ? fImp->HasServer(server) : false; }
+    vector<string> GetServerList() const { return fImp ? fImp->GetServerList() : vector<string>(); }
+    vector<string> GetCommandList(const string &server) const { return fImp ? fImp->GetCommandList(server) : vector<string>(); }
+    vector<string> GetCommandList() const { return fImp ? fImp->GetCommandList() : vector<string>(); }
+    int PrintStates(std::ostream &out, const std::string &serv="") const { return fImp ? fImp->PrintStates(out, serv) : 0; }
+    int PrintDescription(std::ostream &out, bool iscmd, const std::string &serv="", const std::string &service="") const
+    { return fImp ? fImp->PrintDescription(out, iscmd, serv, service) : 0; }
+    bool SendDimCommand(ostream &out, std::string &server, const std::string &str)
+    {
+        try
+        {
+            if (fImp)
+                fImp->SendDimCommand(server, str, out);
+            //lout << kGreen << "Command emitted successfully to " << server << "." << endl;
+            return true;
+        }
+        catch (const runtime_error &e)
+        {
+            lout << kRed << e.what() << endl;
+            return false;
+        }
+    }
+
+    // ============ Pseudo-callback interface for the JavaScrip engine =======
+
+    virtual void  JsLoad(const std::string &)         { SetSection(-2); }
+    virtual void  JsStart(const std::string &)        { SetSection(-1); }
+    virtual void  JsEnd(const std::string &)          { UnsubscribeAll(); SetSection(-3); }
+    virtual bool  JsSend(const std::string &str)      { return ProcessCommand(str); }
+    virtual void  JsPrint(const std::string &msg)     { if (fImp) fImp->Comment(msg.empty()?" ":msg); }
+    virtual void  JsException(const std::string &str) { if (fImp) fImp->Error(str.empty()?" ":str); }
+
+    pair<int32_t, string> JsState(const std::string &server)
+    {
+        return fImp ? fImp->GetServerState(server) : make_pair(-256, string());
     }
 
@@ -167,17 +177,22 @@
         const Time timeout = Time()+boost::posix_time::millisec(ms==0?1:ms);
 
-        T::GetStreamOut().Display(true);
-        T::GetStreamOut().SetBacklog(false);
-        T::GetStreamOut().SetNullOutput(false);
+        T::Lock();
+
         while (timeout>Time() && !T::IsScriptStopped())
             usleep(1);
-        T::GetStreamOut().SetNullOutput(true);
-        T::GetStreamOut().SetBacklog(true);
+
+        T::Unlock();
     }
 
     int JsWait(const string &server, int32_t state, uint32_t ms)
     {
-        const ClientList::const_iterator l = fClientList.find(server);
-        if (l==fClientList.end())
+        if (!fImp)
+        {
+            lout << kRed << "RemoteControl class not fully initialized." << endl;
+            T::StopScript();
+            return -1;
+        }
+
+        if (!HasServer(server))
         {
             lout << kRed << "Server '" << server << "' not found." << endl;
@@ -186,17 +201,98 @@
         }
 
+        T::Lock();
+
         const Time timeout = ms<=0 ? Time(Time::none) : Time()+boost::posix_time::millisec(ms);
 
-        T::GetStreamOut().Display(true);
-        T::GetStreamOut().SetBacklog(false);
-        T::GetStreamOut().SetNullOutput(false);
-        while (l->second->GetState()!=state && timeout>Time() && !T::IsScriptStopped())
+        int rc = 0;
+        while (timeout>Time() && !T::IsScriptStopped())
+        {
+            const pair<int32_t, string> st = fImp->GetServerState(server);
+            if (st.first==-256)
+            {
+                lout << kRed << "Server '" << server << "' disconnected." << endl;
+                T::StopScript();
+                return -1;
+            }
+            if (st.first==state)
+            {
+                rc = 1;
+                break;
+            }
+
             usleep(1);
-        T::GetStreamOut().SetNullOutput(true);
-        T::GetStreamOut().SetBacklog(true);
-
-        return l->second->GetState()==state;
-    }
-
+        }
+        T::Unlock();
+
+        return rc;
+    }
+
+    vector<Description> JsDescription(const string &service)
+    {
+        return fImp ? fImp->GetDescription(service) :  vector<Description>();
+    }
+
+    // Keep a copy of the data for access by V8
+    map<string, EventImp *> fEvents;   // For unsibscription
+    map<string, pair<uint64_t, Event>> fData;
+
+    std::mutex fMutex;
+
+    pair<uint64_t, EventImp *> JsGetEvent(const std::string &service)
+    {
+        const lock_guard<mutex> lock(fMutex);
+
+        const auto it = fData.find(service);
+
+        return it==fData.end() ? make_pair(uint64_t(0), (Event*)0) : make_pair(it->second.first, &it->second.second);
+    }
+
+    void Handle(const EventImp &evt, const string &service)
+    {
+        const lock_guard<mutex> lock(fMutex);
+
+        const auto it = fData.find(service);
+        if (it==fData.end())
+            fData[service] = make_pair(0, static_cast<Event>(evt));
+        else
+        {
+            it->second.first++;
+            it->second.second = static_cast<Event>(evt);
+        }
+    }
+
+    void *JsSubscribe(const std::string &service)
+    {
+        if (!fImp)
+            return 0;
+
+        // Do not subscribe twice
+        if (fEvents.find(service)!=fEvents.end())
+            return 0;
+
+        return fEvents[service] = &fImp->Subscribe(service)(fImp->Wrap(bind(&RemoteControl<T>::Handle, this, placeholders::_1, service)));
+    }
+
+    bool JsUnsubscribe(const std::string &service)
+    {
+        if (!fImp)
+            return false;
+
+        const auto it = fEvents.find(service);
+        if (it==fEvents.end())
+            return false;
+
+        fImp->Unsubscribe(it->second);
+        fEvents.erase(it);
+
+        return true;
+    }
+
+    void UnsubscribeAll()
+    {
+        for (auto it=fEvents.begin(); it!=fEvents.end(); it++)
+            fImp->Unsubscribe(it->second);
+        fEvents.clear();
+    }
 
     // ===========================================================================
@@ -215,5 +311,4 @@
         lout << " " << kUnderline << "Specific commands:\n";
         lout << kBold << "   h,help <arg> " << kReset << "List help text for given server or command.\n";
-//        lout << kBold << "   s,servers    " << kReset << "List all servers which are connected." << endl;
         lout << kBold << "   svc,services " << kReset << "List all services in the network.\n";
         lout << kBold << "   st,states    " << kReset << "List all states in the network.\n";
@@ -342,5 +437,5 @@
     }
 
-    void SetReceiver(MessageImp &imp) { fImp = &imp; }
+    void SetReceiver(StateMachineDimControl &imp) { fImp = &imp; }
 };
 
