Personal tools
The Open Lighting Project has moved!

We've launched our new site at www.openlighting.org. This wiki will remain and be updated with more technical information.

Difference between revisions of "OLA Client API"

From wiki.openlighting.org

Jump to: navigation, search
Line 1: Line 1:
'''Note:''' This refers to the most recent version of LLA [>= 0.3.0]
+
'''Note:''' This refers to the most recent version of OLA [>= 0.3.0]
  
LLA provides a client library which allows other applications to send/receive DMX as well as control the LLA server. To cater for different application requirements, a ''SimpleClient'' helper class is provided which can be used to perform the client setup / management.  
+
OLA provides a client library which allows other applications to send/receive DMX as well as control the OLA server. To cater for different application requirements, a ''SimpleClient'' helper class is provided which can be used to perform the client setup / management.  
  
 
==Example I: Sending an DMX update==
 
==Example I: Sending an DMX update==
  
This first client simply connects to the LLA Server and sends one DMX update. It's about as simple as you can get because it requires no callbacks and exits immediately. We use two classes in this example, ''lla::SimpleClient'', and ''lla::LlaClient''.
+
This first client simply connects to the OLA Server and sends one DMX update. It's about as simple as you can get because it requires no callbacks and exits immediately. We use two classes in this example, ''ola::SimpleClient'', and ''ola::OlaClient''.
  
  #include <lla/SimpleClient.h>
+
  #include <ola/SimpleClient.h>
 
    
 
    
 
  int main() {
 
  int main() {
Line 13: Line 13:
 
   dmx_t dmx_data[] = {0, 128, 255};
 
   dmx_t dmx_data[] = {0, 128, 255};
 
   
 
   
   lla::SimpleClient simple_client;
+
   ola::SimpleClient simple_client;
 
   if (!simple_client.Setup())
 
   if (!simple_client.Setup())
 
     //setup failed
 
     //setup failed
 
     return -1;
 
     return -1;
 
   
 
   
   // Get the underlying LlaClient
+
   // Get the underlying OlaClient
   lla::LlaClient *client = simple_client.GetClient();
+
   ola::OlaClient *client = simple_client.GetClient();
 
   
 
   
 
   // Send the DMX data  
 
   // Send the DMX data  
Line 26: Line 26:
  
  
The main class used to communicate with the LLA Server is ''LlaClient''. For ease of use, the ''SimpleClient'' class sets up ''LlaClient'' with a connection to an LLA Server running on the localhost:LLA_DEFAULT_PORT. You can call GetClient() on a ''SimpleClient'' instance to get a pointer to the underlying ''LlaClient''.
+
The main class used to communicate with the LLA Server is ''OlaClient''. For ease of use, the ''SimpleClient'' class sets up ''OlaClient'' with a connection to an LLA Server running on the localhost:LLA_DEFAULT_PORT. You can call GetClient() on a ''SimpleClient'' instance to get a pointer to the underlying ''OlaClient''.
  
  
Line 33: Line 33:
 
The previous example only sent a single DMX update before quitting. This next example adds a timeout which sends DMX every 50ms. This introduces a new class ''SelectServer'' which is used for registering timeouts.
 
The previous example only sent a single DMX update before quitting. This next example adds a timeout which sends DMX every 50ms. This introduces a new class ''SelectServer'' which is used for registering timeouts.
  
   #include <lla/network/SelectServer.h>
+
   #include <ola/network/SelectServer.h>
   #include <lla/SimpleClient.h>
+
   #include <ola/SimpleClient.h>
   #include <lla/Closure.h>
+
   #include <ola/Closure.h>
 
    
 
    
 
   // Maximum value of a dmx channel
 
   // Maximum value of a dmx channel
Line 44: Line 44:
 
   class DmxTimeout {
 
   class DmxTimeout {
 
     public:
 
     public:
       DmxTimeout(lla::LlaClient *client): m_tick(0),
+
       DmxTimeout(ola::OlaClient *client): m_tick(0),
 
                                           m_client(client) {}
 
                                           m_client(client) {}
 
    
 
    
Line 61: Line 61:
 
       unsigned int m_tick;
 
       unsigned int m_tick;
 
       dmx_t m_dmx_data[3];
 
       dmx_t m_dmx_data[3];
       lla::LlaClient *m_client;
+
       ola::OlaClient *m_client;
 
   };
 
   };
 
    
 
    
 
   int main() {
 
   int main() {
     lla::SimpleClient simple_client;
+
     ola::SimpleClient simple_client;
 
    
 
    
 
     if (!simple_client.Setup())
 
     if (!simple_client.Setup())
Line 72: Line 72:
 
     // Create a timeout and register it
 
     // Create a timeout and register it
 
     DmxTimeout timeout(simple_client.GetClient());
 
     DmxTimeout timeout(simple_client.GetClient());
     lla::network::SelectServer ss = simple_client.GetSelectServer();
+
     ola::network::SelectServer ss = simple_client.GetSelectServer();
 
     ss->RegisterTimeout(TIMEOUT_MS,
 
     ss->RegisterTimeout(TIMEOUT_MS,
                         lla::NewClosure(&timeout, &DmxTimeout::SendDmx),
+
                         ola::NewClosure(&timeout, &DmxTimeout::SendDmx),
 
                         true); // we want this to repeat
 
                         true); // we want this to repeat
 
    
 
    
Line 90: Line 90:
 
The third example shows how to listen and respond to event from the LLA server.
 
The third example shows how to listen and respond to event from the LLA server.
  
  #include <lla/SimpleClient.h>
+
  #include <ola/SimpleClient.h>
 
   
 
   
 
  static const unsigned int UNIVERSE = 1;
 
  static const unsigned int UNIVERSE = 1;
 
   
 
   
  class OurObserver: public lla::LlaClientObserver {
+
  class OurObserver: public ola::OlaClientObserver {
 
   public:
 
   public:
 
     // Called when new DMX values arrive
 
     // Called when new DMX values arrive
Line 105: Line 105:
 
   
 
   
 
  int main() {
 
  int main() {
   lla::SimpleClient simple_client;
+
   ola::SimpleClient simple_client;
 
   OurObserver observer;
 
   OurObserver observer;
 
   
 
   
Line 111: Line 111:
 
     return -1;
 
     return -1;
 
   
 
   
   lla::LlaClient *client = simple_client.GetClient();
+
   ola::OlaClient *client = simple_client.GetClient();
 
   // Set the observer and register our interest in this universe
 
   // Set the observer and register our interest in this universe
 
   client->SetObserver(&observer);
 
   client->SetObserver(&observer);
   client->RegisterUniverse(UNIVERSE, lla::REGISTER);
+
   client->RegisterUniverse(UNIVERSE, ola::REGISTER);
 
   simple_client.GetSelectServer()->Run();
 
   simple_client.GetSelectServer()->Run();
 
  }
 
  }
  
  
Here we inherit from the ''LlaClientObserver'' class and override the methods we're interested in receiving notification for.
+
Here we inherit from the ''OlaClientObserver'' class and override the methods we're interested in receiving notification for.
  
 
In the main function we set the observer object and register our interest in a universe.
 
In the main function we set the observer object and register our interest in a universe.
Line 130: Line 130:
 
On the other hand, what if you're not connecting to the LLA Server over TCP? Sometimes it may be desirable to embed the LLA server within the main application.
 
On the other hand, what if you're not connecting to the LLA Server over TCP? Sometimes it may be desirable to embed the LLA server within the main application.
  
Bypassing the SimpleClient and using LlaClient directly addresses both these problems.
+
Bypassing the SimpleClient and using OlaClient directly addresses both these problems.
  
  #include <lla/LlaClient.h>
+
  #include <ola/OlaClient.h>
  #include <lla/select_server/SelectServer.h>
+
  #include <ola/select_server/SelectServer.h>
  #include <lla/select_server/Socket.h>
+
  #include <ola/select_server/Socket.h>
 
   
 
   
  using lla::select_server::PipeSocket;
+
  using ola::select_server::PipeSocket;
 
   
 
   
 
  int main() {
 
  int main() {
 
   // Create the select server
 
   // Create the select server
   lla::select_server::SelectServer ss;
+
   ola::select_server::SelectServer ss;
 
   
 
   
 
   // Create the pipe socket to talk to the server on
 
   // Create the pipe socket to talk to the server on
Line 150: Line 150:
 
   ss.AddSocket(pipe_socket);
 
   ss.AddSocket(pipe_socket);
 
   
 
   
   // Setup the LlaClient
+
   // Setup the OlaClient
   lla::LlaClient client(pipe_socket);
+
   ola::OlaClient client(pipe_socket);
 
   if (!client.Setup())
 
   if (!client.Setup())
 
     return -1;
 
     return -1;
Line 159: Line 159:
 
   
 
   
 
   // Once that is done we add the pipe as a new connection
 
   // Once that is done we add the pipe as a new connection
   lla_server->NewConnection(m_pipe_socket->OppositeEnd());
+
   ola_server->NewConnection(m_pipe_socket->OppositeEnd());
 
  }
 
  }
  
  
This example shows how we can create our own instance of a ''ConnectedSocket'' (''PipeSocket'' is a subclass of ''ConnectedSocket'') and pass it to the ''LlaClient'' to use. This code is very similar to what ''SimpleClient'' does under the hood.
+
This example shows how we can create our own instance of a ''ConnectedSocket'' (''PipeSocket'' is a subclass of ''ConnectedSocket'') and pass it to the ''OlaClient'' to use. This code is very similar to what ''SimpleClient'' does under the hood.

Revision as of 21:48, 25 July 2009

Note: This refers to the most recent version of OLA [>= 0.3.0]

OLA provides a client library which allows other applications to send/receive DMX as well as control the OLA server. To cater for different application requirements, a SimpleClient helper class is provided which can be used to perform the client setup / management.

Example I: Sending an DMX update

This first client simply connects to the OLA Server and sends one DMX update. It's about as simple as you can get because it requires no callbacks and exits immediately. We use two classes in this example, ola::SimpleClient, and ola::OlaClient.

#include <ola/SimpleClient.h>
 
int main() {
  // some dummy dmx data
  dmx_t dmx_data[] = {0, 128, 255};

  ola::SimpleClient simple_client;
  if (!simple_client.Setup())
    //setup failed
    return -1;

  // Get the underlying OlaClient
  ola::OlaClient *client = simple_client.GetClient();

  // Send the DMX data 
  client->SendDmx(1, dmx_data, sizeof(dmx_data));
}


The main class used to communicate with the LLA Server is OlaClient. For ease of use, the SimpleClient class sets up OlaClient with a connection to an LLA Server running on the localhost:LLA_DEFAULT_PORT. You can call GetClient() on a SimpleClient instance to get a pointer to the underlying OlaClient.


Example II: Sending multiple updates

The previous example only sent a single DMX update before quitting. This next example adds a timeout which sends DMX every 50ms. This introduces a new class SelectServer which is used for registering timeouts.

 #include <ola/network/SelectServer.h>
 #include <ola/SimpleClient.h>
 #include <ola/Closure.h>
 
 // Maximum value of a dmx channel
 static const unsigned int MAX_DMX = 255;
 // How often to send updates
 static const unsigned int TIMEOUT_MS = 50;
 
 class DmxTimeout {
   public:
     DmxTimeout(ola::OlaClient *client): m_tick(0),
                                         m_client(client) {}
 
     // Called on timeout
     int SendDmx() {
       m_dmx_data[0] = MAX_DMX;
       m_dmx_data[1] = m_tick;
       m_dmx_data[2] = MAX_DMX - m_tick;
       m_client->SendDmx(1, m_dmx_data, sizeof(m_dmx_data));
       m_tick++;
       m_tick %= MAX_DMX + 1;
       // we must return 0 else we get canceled
       return 0;
     }
   private:
     unsigned int m_tick;
     dmx_t m_dmx_data[3];
     ola::OlaClient *m_client;
 };
 
 int main() {
   ola::SimpleClient simple_client;
 
   if (!simple_client.Setup())
     return -1;
 
   // Create a timeout and register it
   DmxTimeout timeout(simple_client.GetClient());
   ola::network::SelectServer ss = simple_client.GetSelectServer();
   ss->RegisterTimeout(TIMEOUT_MS,
                       ola::NewClosure(&timeout, &DmxTimeout::SendDmx),
                       true); // we want this to repeat
 
   // Start the main loop
   ss->Run();
 }


In this example we create DmxTimeout class whose SendDmx() method is called every time the timer expires.

The other important part here is the SelectServer. As well as the RegisterTimeout method we've used above, this can also be used to register sockets so we can respond to network activity. The Run() method starts the main event processing loop which will halt if an error occurs or Terminate() is called.

Example III: Receiving DMX data

The third example shows how to listen and respond to event from the LLA server.

#include <ola/SimpleClient.h>

static const unsigned int UNIVERSE = 1;

class OurObserver: public ola::OlaClientObserver {
  public:
    // Called when new DMX values arrive
    void NewDmx(unsigned int universe, unsigned int length,
                dmx_t *data, const std::string &error) {
      printf("received %d channels for universe %d\n",
             length, universe);
    }
};

int main() {
  ola::SimpleClient simple_client;
  OurObserver observer;

  if (!simple_client.Setup())
    return -1;

  ola::OlaClient *client = simple_client.GetClient();
  // Set the observer and register our interest in this universe
  client->SetObserver(&observer);
  client->RegisterUniverse(UNIVERSE, ola::REGISTER);
  simple_client.GetSelectServer()->Run();
}


Here we inherit from the OlaClientObserver class and override the methods we're interested in receiving notification for.

In the main function we set the observer object and register our interest in a universe.


Example IV: More complex client

The above is all well and good but what if the main application has it's own event processing loop? An example of this is a GTK/Glib application which uses GMainLoop.

On the other hand, what if you're not connecting to the LLA Server over TCP? Sometimes it may be desirable to embed the LLA server within the main application.

Bypassing the SimpleClient and using OlaClient directly addresses both these problems.

#include <ola/OlaClient.h>
#include <ola/select_server/SelectServer.h>
#include <ola/select_server/Socket.h>

using ola::select_server::PipeSocket;

int main() {
  // Create the select server
  ola::select_server::SelectServer ss;

  // Create the pipe socket to talk to the server on
  PipeSocket *pipe_socket = new PipeSocket();
  if (!pipe_socket->Init())
    return -1;

  // Remember to add this socket to the SelectServer
  ss.AddSocket(pipe_socket);

  // Setup the OlaClient
  ola::OlaClient client(pipe_socket);
  if (!client.Setup())
    return -1;

  // At this point the client is setup. We then need to setup the LLAServer
  // ...

  // Once that is done we add the pipe as a new connection
  ola_server->NewConnection(m_pipe_socket->OppositeEnd());
}


This example shows how we can create our own instance of a ConnectedSocket (PipeSocket is a subclass of ConnectedSocket) and pass it to the OlaClient to use. This code is very similar to what SimpleClient does under the hood.