zynaddsubfx

ZynAddSubFX open source synthesizer
Log | Files | Refs | Submodules | LICENSE

Client.C (12216B)


      1 
      2 /*******************************************************************************/
      3 /* Copyright (C) 2012 Jonathan Moore Liles                                     */
      4 /*                                                                             */
      5 /* This program is free software; you can redistribute it and/or modify it     */
      6 /* under the terms of the GNU General Public License as published by the       */
      7 /* Free Software Foundation; either version 2 of the License, or (at your      */
      8 /* option) any later version.                                                  */
      9 /*                                                                             */
     10 /* This program is distributed in the hope that it will be useful, but WITHOUT */
     11 /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       */
     12 /* FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for   */
     13 /* more details.                                                               */
     14 /*                                                                             */
     15 /* You should have received a copy of the GNU General Public License along     */
     16 /* with This program; see the file COPYING.  If not,write to the Free Software */
     17 /* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
     18 /*******************************************************************************/
     19 
     20 #include "Client.H"
     21 #include <string.h>
     22 #include <sys/types.h>
     23 #include <unistd.h>
     24 #include <stdlib.h>
     25 
     26 #pragma GCC diagnostic ignored "-Wunused-parameter"
     27 
     28 namespace NSM
     29 {
     30 /************************/
     31 /* OSC Message Handlers */
     32 /************************/
     33 
     34 #undef OSC_REPLY
     35 #undef OSC_REPLY_ERR
     36 
     37 #define OSC_REPLY(value) lo_send_from(((NSM::Client *)user_data)->nsm_addr, \
     38                                       ((NSM::Client *)user_data)->_server, \
     39                                       LO_TT_IMMEDIATE, \
     40                                       "/reply", \
     41                                       "ss", \
     42                                       path, \
     43                                       value)
     44 
     45 #define OSC_REPLY_ERR(errcode, value) lo_send_from( \
     46         ((NSM::Client *)user_data)->nsm_addr, \
     47         ((NSM::Client *)user_data)->_server, \
     48         LO_TT_IMMEDIATE, \
     49         "/error", \
     50         "sis", \
     51         path, \
     52         errcode, \
     53         value)
     54 
     55     Client::Client()
     56     {
     57         nsm_addr      = 0;
     58         nsm_client_id = 0;
     59         _session_manager_name = 0;
     60         nsm_is_active = false;
     61         _server = 0;
     62         _st     = 0;
     63     }
     64 
     65     Client::~Client()
     66     {
     67         if(_st)
     68             stop();
     69 
     70         if(_st)
     71             lo_server_thread_free(_st);
     72         else
     73             lo_server_free(_server);
     74     }
     75 
     76     void
     77     Client::announce(const char *application_name,
     78                      const char *capabilities,
     79                      const char *process_name)
     80     {
     81         // MESSAGE( "Announcing to NSM" );
     82 
     83         lo_address to = lo_address_new_from_url(nsm_url);
     84 
     85         if(!to)
     86             //    MESSAGE( "Bad address" );
     87             return;
     88 
     89         int pid = (int)getpid();
     90 
     91         lo_send_from(to,
     92                      _server,
     93                      LO_TT_IMMEDIATE,
     94                      "/nsm/server/announce",
     95                      "sssiii",
     96                      application_name,
     97                      capabilities,
     98                      process_name,
     99                      1,
    100                      /* api_major_version */
    101                      0,
    102                      /* api_minor_version */
    103                      pid);
    104 
    105         lo_address_free(to);
    106     }
    107 
    108     void
    109     Client::progress(float p)
    110     {
    111         if(nsm_is_active)
    112             lo_send_from(nsm_addr,
    113                          _server,
    114                          LO_TT_IMMEDIATE,
    115                          "/nsm/client/progress",
    116                          "f",
    117                          p);
    118     }
    119 
    120     void
    121     Client::is_dirty(void)
    122     {
    123         if(nsm_is_active)
    124             lo_send_from(nsm_addr,
    125                          _server,
    126                          LO_TT_IMMEDIATE,
    127                          "/nsm/client/is_dirty",
    128                          "");
    129     }
    130 
    131     void
    132     Client::is_clean(void)
    133     {
    134         if(nsm_is_active)
    135             lo_send_from(nsm_addr,
    136                          _server,
    137                          LO_TT_IMMEDIATE,
    138                          "/nsm/client/is_clean",
    139                          "");
    140     }
    141 
    142     void
    143     Client::message(int priority, const char *msg)
    144     {
    145         if(nsm_is_active)
    146             lo_send_from(nsm_addr,
    147                          _server,
    148                          LO_TT_IMMEDIATE,
    149                          "/nsm/client/message",
    150                          "is",
    151                          priority,
    152                          msg);
    153     }
    154 
    155 
    156     void
    157     Client::broadcast(lo_message msg)
    158     {
    159         if(nsm_is_active)
    160             lo_send_message_from(nsm_addr,
    161                                  _server,
    162                                  "/nsm/server/broadcast",
    163                                  msg);
    164     }
    165 
    166     void
    167     Client::check(int timeout)
    168     {
    169         if(lo_server_wait(_server, timeout))
    170             while(lo_server_recv_noblock(_server, 0)) {}
    171     }
    172 
    173     void
    174     Client::start()
    175     {
    176         lo_server_thread_start(_st);
    177     }
    178 
    179     void
    180     Client::stop()
    181     {
    182         lo_server_thread_stop(_st);
    183     }
    184 
    185     int
    186     Client::init(const char *nsm_url)
    187     {
    188         this->nsm_url = nsm_url;
    189 
    190         lo_address addr = lo_address_new_from_url(nsm_url);
    191         int proto = lo_address_get_protocol(addr);
    192         lo_address_free(addr);
    193 
    194         _server = lo_server_new_with_proto(NULL, proto, NULL);
    195 
    196         if(!_server)
    197             return -1;
    198 
    199         lo_server_add_method(_server, "/error", "sis", &Client::osc_error, this);
    200         lo_server_add_method(_server,
    201                              "/reply",
    202                              "ssss",
    203                              &Client::osc_announce_reply,
    204                              this);
    205         lo_server_add_method(_server,
    206                              "/nsm/client/open",
    207                              "sss",
    208                              &Client::osc_open,
    209                              this);
    210         lo_server_add_method(_server,
    211                              "/nsm/client/save",
    212                              "",
    213                              &Client::osc_save,
    214                              this);
    215         lo_server_add_method(_server,
    216                              "/nsm/client/session_is_loaded",
    217                              "",
    218                              &Client::osc_session_is_loaded,
    219                              this);
    220         lo_server_add_method(_server, NULL, NULL, &Client::osc_broadcast, this);
    221 
    222         return 0;
    223     }
    224 
    225     int
    226     Client::init_thread(const char *nsm_url)
    227     {
    228         this->nsm_url = nsm_url;
    229 
    230         lo_address addr = lo_address_new_from_url(nsm_url);
    231         int proto = lo_address_get_protocol(addr);
    232         lo_address_free(addr);
    233 
    234         _st     = lo_server_thread_new_with_proto(NULL, proto, NULL);
    235         _server = lo_server_thread_get_server(_st);
    236 
    237         if(!_server || !_st)
    238             return -1;
    239 
    240         lo_server_thread_add_method(_st,
    241                                     "/error",
    242                                     "sis",
    243                                     &Client::osc_error,
    244                                     this);
    245         lo_server_thread_add_method(_st,
    246                                     "/reply",
    247                                     "ssss",
    248                                     &Client::osc_announce_reply,
    249                                     this);
    250         lo_server_thread_add_method(_st,
    251                                     "/nsm/client/open",
    252                                     "sss",
    253                                     &Client::osc_open,
    254                                     this);
    255         lo_server_thread_add_method(_st,
    256                                     "/nsm/client/save",
    257                                     "",
    258                                     &Client::osc_save,
    259                                     this);
    260         lo_server_thread_add_method(_st,
    261                                     "/nsm/client/session_is_loaded",
    262                                     "",
    263                                     &Client::osc_session_is_loaded,
    264                                     this);
    265         lo_server_thread_add_method(_st,
    266                                     NULL,
    267                                     NULL,
    268                                     &Client::osc_broadcast,
    269                                     this);
    270 
    271         return 0;
    272     }
    273 
    274 /************************/
    275 /* OSC Message Handlers */
    276 /************************/
    277 
    278     int
    279     Client::osc_broadcast(const char *path,
    280                           const char *types,
    281                           lo_arg **argv,
    282                           int argc,
    283                           lo_message msg,
    284                           void *user_data)
    285     {
    286         return ((NSM::Client *)user_data)->command_broadcast(path, msg);
    287     }
    288 
    289     int
    290     Client::osc_save(const char *path,
    291                      const char *types,
    292                      lo_arg **argv,
    293                      int argc,
    294                      lo_message msg,
    295                      void *user_data)
    296     {
    297         char *out_msg = NULL;
    298 
    299         int r = ((NSM::Client *)user_data)->command_save(&out_msg);
    300 
    301         if(r)
    302             OSC_REPLY_ERR(r, (out_msg ? out_msg : ""));
    303         else
    304             OSC_REPLY("OK");
    305 
    306         if(out_msg)
    307             free(out_msg);
    308 
    309         return 0;
    310     }
    311 
    312     int
    313     Client::osc_open(const char *path,
    314                      const char *types,
    315                      lo_arg **argv,
    316                      int argc,
    317                      lo_message msg,
    318                      void *user_data)
    319     {
    320         char *out_msg = NULL;
    321 
    322         NSM::Client *nsm = (NSM::Client *)user_data;
    323 
    324         nsm->nsm_client_id = strdup(&argv[2]->s);
    325 
    326         int r = ((NSM::Client *)user_data)->command_open(&argv[0]->s,
    327                                                          &argv[1]->s,
    328                                                          &argv[2]->s,
    329                                                          &out_msg);
    330 
    331         if(r)
    332             OSC_REPLY_ERR(r, (out_msg ? out_msg : ""));
    333         else
    334             OSC_REPLY("OK");
    335 
    336         if(out_msg)
    337             free(out_msg);
    338 
    339         return 0;
    340     }
    341 
    342     int
    343     Client::osc_session_is_loaded(const char *path,
    344                                   const char *types,
    345                                   lo_arg **argv,
    346                                   int argc,
    347                                   lo_message msg,
    348                                   void *user_data)
    349     {
    350         NSM::Client *nsm = (NSM::Client *)user_data;
    351 
    352         nsm->command_session_is_loaded();
    353 
    354         return 0;
    355     }
    356 
    357     int
    358     Client::osc_error(const char *path,
    359                       const char *types,
    360                       lo_arg **argv,
    361                       int argc,
    362                       lo_message msg,
    363                       void *user_data)
    364     {
    365         if(strcmp(&argv[0]->s, "/nsm/server/announce"))
    366             return -1;
    367 
    368         NSM::Client *nsm = (NSM::Client *)user_data;
    369 
    370 
    371 //        WARNING( "Failed to register with NSM: %s", &argv[2]->s );
    372         nsm->nsm_is_active = false;
    373 
    374         nsm->command_active(nsm->nsm_is_active);
    375 
    376         return 0;
    377     }
    378 
    379     int
    380     Client::osc_announce_reply(const char *path,
    381                                const char *types,
    382                                lo_arg **argv,
    383                                int argc,
    384                                lo_message msg,
    385                                void *user_data)
    386     {
    387         if(strcmp(&argv[0]->s, "/nsm/server/announce"))
    388             return -1;
    389 
    390         NSM::Client *nsm = (NSM::Client *)user_data;
    391 
    392 //        MESSAGE( "Successfully registered. NSM says: %s", &argv[1]->s );
    393         nsm->nsm_is_active = true;
    394         nsm->_session_manager_name = strdup(&argv[2]->s);
    395         nsm->nsm_addr =
    396             lo_address_new_from_url(lo_address_get_url(lo_message_get_source(
    397                                                            msg)));
    398 
    399         nsm->command_active(nsm->nsm_is_active);
    400 
    401         return 0;
    402     }
    403 };