OSC GUI: Add Strip types and feedback check boxes
[ardour.git] / gtk2_ardour / nsmclient.cc
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
18 /*******************************************************************************/
19
20 #include "nsmclient.h"
21 #include <string.h>
22 #include <sys/types.h>
23 #include <unistd.h>
24 #include <stdlib.h>
25
26 #ifndef COMPILER_MSVC
27 #pragma GCC diagnostic ignored "-Wunused-parameter"
28 #else
29 #include <process.h>  // Needed for 'getpid()'
30
31 #include <lo/lo_osc_types.h>
32 #define LO_TT_IMMEDIATE lo_get_tt_immediate()
33 lo_timetag lo_get_tt_immediate() { lo_timetag tt = {0U,1U}; return tt; }
34 #endif
35
36 namespace NSM
37 {
38
39 /************************/
40 /* OSC Message Handlers */
41 /************************/
42
43 #undef OSC_REPLY
44 #undef OSC_REPLY_ERR
45
46 #define OSC_REPLY( value ) lo_send_from( ((NSM::Client*)user_data)->nsm_addr, ((NSM::Client*)user_data)->_server, LO_TT_IMMEDIATE, "/reply", "ss", path, value )
47
48 #define OSC_REPLY_ERR( errcode, value ) lo_send_from( ((NSM::Client*)user_data)->nsm_addr, ((NSM::Client*)user_data)->_server, LO_TT_IMMEDIATE, "/error", "sis", path, errcode, value )
49
50     Client::Client ( )
51     {
52         nsm_addr = 0;
53         _nsm_client_id = 0;
54         _nsm_client_path = 0;
55         _session_manager_name = 0;
56         nsm_url = "";
57         nsm_is_active = false;
58         _server = 0;
59         _st = 0;
60     }
61
62     Client::~Client ( )
63     {
64         if ( _st )
65             stop();
66
67         if ( _st )
68             lo_server_thread_free( _st );
69         else
70             lo_server_free ( _server );
71     }
72
73     void
74     Client::announce ( const char *application_name, const char *capabilities, const char *process_name )
75     {
76
77         lo_address to = lo_address_new_from_url( nsm_url );
78
79         if ( ! to )
80         {
81             return;
82         }
83
84         int pid = (int)getpid();
85
86         lo_send_from( to, _server, LO_TT_IMMEDIATE, "/nsm/server/announce", "sssiii",
87                             application_name,
88                             capabilities,
89                             process_name,
90                             1, /* api_major_version */
91                             0, /* api_minor_version */
92                             pid );
93
94         lo_address_free( to );
95     }
96
97     void
98     Client::progress ( float p )
99     {
100         if ( nsm_is_active )
101         {
102             lo_send_from( nsm_addr, _server, LO_TT_IMMEDIATE, "/nsm/client/progress", "f", p );
103         }
104     }
105
106     void
107     Client::is_dirty ( void )
108     {
109         if ( nsm_is_active )
110         {
111             lo_send_from( nsm_addr, _server, LO_TT_IMMEDIATE, "/nsm/client/is_dirty", "" );
112         }
113     }
114
115     void
116     Client::is_clean ( void )
117     {
118         if ( nsm_is_active )
119         {
120             lo_send_from( nsm_addr, _server, LO_TT_IMMEDIATE, "/nsm/client/is_clean", "" );
121         }
122     }
123
124     void
125     Client::message ( int priority, const char *msg )
126     {
127         if ( nsm_is_active )
128         {
129             lo_send_from( nsm_addr, _server, LO_TT_IMMEDIATE, "/nsm/client/message", "is", priority, msg );
130         }
131     }
132
133
134     void
135     Client::broadcast ( lo_message msg )
136     {
137         if ( nsm_is_active )
138         {
139             lo_send_message_from( nsm_addr, _server, "/nsm/server/broadcast", msg );
140         }
141     }
142
143     void
144     Client::check ( int timeout )
145     {
146         if ( lo_server_wait( _server, timeout ) )
147             while ( lo_server_recv_noblock( _server, 0 ) ) {}
148     }
149
150     void
151     Client::start ( )
152     {
153         lo_server_thread_start( _st );
154     }
155
156     void
157     Client::stop ( )
158     {
159         lo_server_thread_stop( _st );
160     }
161
162     int
163     Client::init ( const char *nsm_url )
164     {
165         this->nsm_url = nsm_url;
166
167         lo_address addr = lo_address_new_from_url( nsm_url );
168         int proto = lo_address_get_protocol( addr );
169         lo_address_free( addr );
170
171         _server = lo_server_new_with_proto( NULL, proto, NULL );
172
173         if ( ! _server )
174             return -1;
175
176         lo_server_add_method( _server, "/error", "sis", &Client::osc_error, this );
177         lo_server_add_method( _server, "/reply", "ssss", &Client::osc_announce_reply, this );
178         lo_server_add_method( _server, "/nsm/client/open", "sss", &Client::osc_open, this );
179         lo_server_add_method( _server, "/nsm/client/save", "", &Client::osc_save, this );
180         lo_server_add_method( _server, "/nsm/client/session_is_loaded", "", &Client::osc_session_is_loaded, this );
181         lo_server_add_method( _server, NULL, NULL, &Client::osc_broadcast, this );
182
183         return 0;
184     }
185
186     int
187     Client::init_thread ( const char *nsm_url )
188     {
189         this->nsm_url = nsm_url;
190
191         lo_address addr = lo_address_new_from_url( nsm_url );
192         int proto = lo_address_get_protocol( addr );
193         lo_address_free( addr );
194
195         _st = lo_server_thread_new_with_proto( NULL, proto, NULL );
196         _server = lo_server_thread_get_server( _st );
197
198         if ( ! _server || ! _st )
199             return -1;
200
201         lo_server_thread_add_method( _st, "/error", "sis", &Client::osc_error, this );
202         lo_server_thread_add_method( _st, "/reply", "ssss", &Client::osc_announce_reply, this );
203         lo_server_thread_add_method( _st, "/nsm/client/open", "sss", &Client::osc_open, this );
204         lo_server_thread_add_method( _st, "/nsm/client/save", "", &Client::osc_save, this );
205         lo_server_thread_add_method( _st, "/nsm/client/session_is_loaded", "", &Client::osc_session_is_loaded, this );
206         lo_server_thread_add_method( _st, NULL, NULL, &Client::osc_broadcast, this );
207
208         return 0;
209     }
210
211 /************************/
212 /* OSC Message Handlers */
213 /************************/
214
215     int
216     Client::osc_broadcast ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data )
217     {
218         return ((NSM::Client*)user_data)->command_broadcast( path, msg );
219     }
220
221     int
222     Client::osc_save ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data )
223     {
224         char *out_msg = NULL;
225
226         int r = ((NSM::Client*)user_data)->command_save(&out_msg);
227
228         if ( r )
229             OSC_REPLY_ERR( r, ( out_msg ? out_msg : "") );
230         else
231             OSC_REPLY( "OK" );
232
233         if ( out_msg )
234             free( out_msg );
235
236          return 0;
237     }
238
239     int
240     Client::osc_open ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data )
241     {
242         char *out_msg = NULL;
243
244         NSM::Client *nsm = (NSM::Client*)user_data;
245
246         nsm->_nsm_client_id = strdup( &argv[2]->s );
247         nsm->_nsm_client_path = strdup( &argv[0]->s );
248
249         int r = ((NSM::Client*)user_data)->command_open( &argv[0]->s, &argv[1]->s, &argv[2]->s, &out_msg);
250
251         if ( r )
252             OSC_REPLY_ERR( r, ( out_msg ? out_msg : "") );
253         else
254             OSC_REPLY( "OK" );
255
256         if ( out_msg )
257             free( out_msg );
258
259         return 0;
260     }
261
262     int
263     Client::osc_session_is_loaded ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data )
264     {
265         NSM::Client *nsm = (NSM::Client*)user_data;
266
267         nsm->command_session_is_loaded();
268
269         return 0;
270     }
271
272     int
273     Client::osc_error ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data )
274     {
275         if ( strcmp( &argv[0]->s, "/nsm/server/announce" ) )
276             return -1;
277
278         NSM::Client *nsm = (NSM::Client*)user_data;
279
280
281         nsm->nsm_is_active = false;
282
283         nsm->command_active( nsm->nsm_is_active );
284
285         return 0;
286     }
287
288     int
289     Client::osc_announce_reply ( const char *path, const char *types, lo_arg **argv, int argc, lo_message msg, void *user_data )
290     {
291         if ( strcmp( &argv[0]->s, "/nsm/server/announce" ) )
292             return -1;
293
294         NSM::Client *nsm = (NSM::Client*)user_data;
295
296         nsm->nsm_is_active = true;
297         nsm->_session_manager_name = strdup( &argv[2]->s );
298         nsm->nsm_addr = lo_address_new_from_url( lo_address_get_url( lo_message_get_source( msg ) ));
299
300         nsm->command_active( nsm->nsm_is_active );
301
302         return 0;
303     }
304 };