libpsynth 0.2.1
/home/raskolnikov/dev/psynth/trunk/src/psynth/net/osc_server.hpp
Go to the documentation of this file.
00001 /***************************************************************************
00002  *                                                                         *
00003  *   PSYCHOSYNTH                                                           *
00004  *   ===========                                                           *
00005  *                                                                         *
00006  *   Copyright (C) 2007 Juan Pedro Bolivar Puente                          *
00007  *                                                                         *
00008  *   This program is free software: you can redistribute it and/or modify  *
00009  *   it under the terms of the GNU General Public License as published by  *
00010  *   the Free Software Foundation, either version 3 of the License, or     *
00011  *   (at your option) any later version.                                   *
00012  *                                                                         *
00013  *   This program is distributed in the hope that it will be useful,       *
00014  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00015  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00016  *   GNU General Public License for more details.                          *
00017  *                                                                         *
00018  *   You should have received a copy of the GNU General Public License     *
00019  *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
00020  *                                                                         *
00021  ***************************************************************************/
00022 
00023 #ifndef PSYNTH_OSCSERVER_H
00024 #define PSYNTH_OSCSERVER_H
00025 
00026 #include <list>
00027 
00028 #include <psynth/net/osc_misc.hpp>
00029 #include <psynth/net/osc_controller.hpp>
00030 
00031 #define PSYNTH_DEFAULT_SERVER_PORT     8191
00032 #define PSYNTH_DEFAULT_SERVER_PORT_STR "8191"
00033 
00034 namespace psynth
00035 {
00036 
00037 class osc_server;
00038 
00039 enum osc_server_client_error {
00040     SCE_NONE = 0,
00041     SCE_CLIENT_TIMEOUT
00042 };
00043 
00044 enum osc_server_error {
00045     SE_NONE = 0,
00046     SE_PORT_BINDING
00047 };
00048 
00049 class osc_server_listener
00050 {
00051     
00052 public:
00053     virtual ~osc_server_listener() {}
00054     virtual bool handle_server_start_listening (osc_server* server) = 0;
00055     virtual bool handle_server_stop_listening (osc_server* server, osc_server_error err) = 0;
00056     virtual bool handle_server_client_connect (osc_server* server, int client_id) = 0;
00057     virtual bool handle_server_client_disconnect (osc_server* server, int client_id,
00058                                                   osc_server_client_error cause) = 0;
00059 };
00060 
00061 class osc_server_subject
00062 {
00063     std::list<osc_server_listener*> m_list;
00064 
00065 protected:
00066     void notify_server_start_listening (osc_server* server);
00067     void notify_server_stop_listening (osc_server* server, osc_server_error err);
00068     void notify_server_client_disconnect (osc_server* server, int client_id,
00069                                           osc_server_client_error cause);
00070     void notify_server_client_connect (osc_server* server, int client_id);
00071     
00072 public:
00073     void add_listener (osc_server_listener* l) {
00074         m_list.push_back(l);
00075     }
00076 
00077     void delete_listener (osc_server_listener* l) {
00078         m_list.remove(l);
00079     }
00080 };
00081 
00082 class osc_server : public osc_controller,
00083                    public osc_server_subject
00084 {
00085 public:
00086     enum state {
00087         IDLE,
00088         LISTENING
00089     };
00090 
00091 private:
00092     const static int SERVER_ID = 0;
00093 
00094     struct slot {
00095         int id;
00096         int last_alive_recv;
00097         int last_alive_sent;
00098         
00099         slot(int id = 0) :
00100             id(id), last_alive_recv(0), last_alive_sent(0) {};
00101     };
00102 
00103     struct lo_address_lt_func {
00104         bool operator() (lo_address a, lo_address b) {
00105             return lo_address_cmp(a, b) < 0;
00106         }
00107     };
00108 
00109     typedef std::map<lo_address, slot, lo_address_lt_func> slot_map; 
00110     slot_map m_slots;
00111     
00112     lo_server m_server;
00113     bool m_listening;
00114     int m_nextid;
00115     state m_state;
00116     
00117     LO_HANDLER (osc_server, alive);
00118     LO_HANDLER (osc_server, connect);
00119     LO_HANDLER (osc_server, get_state);
00120     LO_HANDLER (osc_server, disconnect);
00121 
00122     void add_methods ();
00123     
00124 public:
00125     
00126     osc_server();
00127     ~osc_server();
00128 
00129     bool is_listening () {
00130         return m_listening;
00131     };
00132 
00133     state get_state () {
00134         return m_state;
00135     }
00136     
00137     void listen (const char* port);
00138     void stop ();
00139     void close ();
00140 
00141     /* time_out < 0 for blocking operation. */
00142     int receive (int time_out = 0);
00143     int update (int msec);
00144 };
00145 
00146 } /* namespace psynth */
00147 
00148 #endif /* PSYNTH_OSCSERVER_H */
00149