2 * Copyright (C) 2006 Paul Davis
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
31 #include <glibmm/miscutils.h>
32 #include <boost/signals2.hpp>
34 #include <pbd/pthread_utils.h>
35 #include <pbd/file_utils.h>
36 #include <pbd/filesystem.h>
37 #include <pbd/failed_constructor.h>
39 #include "ardour/session.h"
40 #include "ardour/route.h"
41 #include "ardour/audio_track.h"
42 #include "ardour/midi_track.h"
43 #include "ardour/dB.h"
44 #include "ardour/filesystem_paths.h"
45 #include "ardour/panner.h"
46 #include "ardour/plugin.h"
49 #include "osc_controllable.h"
50 #include "osc_route_observer.h"
53 using namespace ARDOUR
;
57 #include "pbd/abstract_ui.cc" // instantiate template
59 #define ui_bind(f, ...) boost::protect (boost::bind (f, __VA_ARGS__))
61 OSC
* OSC::_instance
= 0;
64 static void error_callback(int num
, const char *m
, const char *path
)
66 fprintf(stderr
, "liblo server error %d in path %s: %s\n", num
, path
, m
);
69 static void error_callback(int, const char *, const char *)
75 OSC::OSC (Session
& s
, uint32_t port
)
76 : ControlProtocol (s
, "OSC", this)
77 , AbstractUI
<OSCUIRequest
> ("osc")
84 _namespace_root
= "/ardour";
85 _send_route_changes
= true;
91 // "Application Hooks"
93 session
->Exported
.connect (*this, MISSING_INVALIDATOR
, ui_bind (&OSC::session_exported
, this, _1
, _2
), this);
103 OSC::do_request (OSCUIRequest
* req
)
105 if (req
->type
== CallSlot
) {
107 call_slot (MISSING_INVALIDATOR
, req
->the_slot
);
109 } else if (req
->type
== Quit
) {
116 OSC::set_active (bool yn
)
126 OSC::get_active () const
128 return _osc_server
!= 0;
132 OSC::set_feedback (bool yn
)
134 _send_route_changes
= yn
;
139 OSC::get_feedback () const
141 return _send_route_changes
;
150 /* already started */
154 for (int j
=0; j
< 20; ++j
) {
155 snprintf(tmpstr
, sizeof(tmpstr
), "%d", _port
);
157 //if ((_osc_server = lo_server_new_with_proto (tmpstr, LO_TCP, error_callback))) {
161 if ((_osc_server
= lo_server_new (tmpstr
, error_callback
))) {
166 cerr
<< "can't get osc at port: " << _port
<< endl
;
172 #ifdef ARDOUR_OSC_UNIX_SERVER
174 // APPEARS sluggish for now
176 // attempt to create unix socket server too
178 snprintf(tmpstr
, sizeof(tmpstr
), "/tmp/sooperlooper_XXXXXX");
179 int fd
= mkstemp(tmpstr
);
185 _osc_unix_server
= lo_server_new (tmpstr
, error_callback
);
187 if (_osc_unix_server
) {
188 _osc_unix_socket_path
= tmpstr
;
193 cerr
<< "OSC @ " << get_server_url () << endl
;
195 PBD::sys::path url_file
;
197 if (find_file_in_search_path (ardour_search_path() + system_config_search_path(),
198 "osc_url", url_file
)) {
200 _osc_url_file
= url_file
.to_string();
202 urlfile
.open(_osc_url_file
.c_str(), ios::trunc
);
205 urlfile
<< get_server_url () << endl
;
208 cerr
<< "Couldn't write '" << _osc_url_file
<< "'" <<endl
;
212 register_callbacks();
214 // lo_server_thread_add_method(_sthread, NULL, NULL, OSC::_dummy_handler, this);
216 /* startup the event loop thread */
226 pthread_set_name (X_("OSC"));
228 if (_osc_unix_server
) {
229 Glib::RefPtr
<IOSource
> src
= IOSource::create (lo_server_get_socket_fd (_osc_unix_server
), IO_IN
|IO_HUP
|IO_ERR
);
230 src
->connect (sigc::bind (sigc::mem_fun (*this, &OSC::osc_input_handler
), _osc_unix_server
));
231 src
->attach (_main_loop
->get_context());
232 local_server
= src
->gobj();
233 g_source_ref (local_server
);
237 Glib::RefPtr
<IOSource
> src
= IOSource::create (lo_server_get_socket_fd (_osc_server
), IO_IN
|IO_HUP
|IO_ERR
);
238 src
->connect (sigc::bind (sigc::mem_fun (*this, &OSC::osc_input_handler
), _osc_server
));
239 src
->attach (_main_loop
->get_context());
240 remote_server
= src
->gobj();
241 g_source_ref (remote_server
);
244 PBD::notify_gui_about_thread_creation (X_("gui"), pthread_self(), X_("OSC"), 2048);
245 SessionEvent::create_per_thread_pool (X_("OSC"), 128);
254 g_source_destroy (local_server
);
255 g_source_unref (local_server
);
260 g_source_destroy (remote_server
);
261 g_source_unref (remote_server
);
268 int fd
= lo_server_get_socket_fd(_osc_server
);
272 lo_server_free (_osc_server
);
276 if (_osc_unix_server
) {
277 int fd
= lo_server_get_socket_fd(_osc_unix_server
);
281 lo_server_free (_osc_unix_server
);
282 _osc_unix_server
= 0;
285 if (!_osc_unix_socket_path
.empty()) {
286 unlink (_osc_unix_socket_path
.c_str());
289 if (!_osc_url_file
.empty() ) {
290 unlink (_osc_url_file
.c_str() );
293 // Delete any active route observers
294 for (RouteObservers::iterator x
= route_observers
.begin(); x
!= route_observers
.end();) {
296 OSCRouteObserver
* rc
;
298 if ((rc
= dynamic_cast<OSCRouteObserver
*>(*x
)) != 0) {
300 x
= route_observers
.erase (x
);
310 OSC::register_callbacks()
315 srvs
[0] = _osc_server
;
316 srvs
[1] = _osc_unix_server
;
318 for (size_t i
= 0; i
< 2; ++i
) {
326 /* this is a special catchall handler */
328 lo_server_add_method (serv
, 0, 0, _catchall
, this);
330 #define REGISTER_CALLBACK(serv,path,types, function) lo_server_add_method (serv, path, types, OSC::_ ## function, this)
332 REGISTER_CALLBACK (serv
, "/routes/list", "", routes_list
);
333 REGISTER_CALLBACK (serv
, "/ardour/add_marker", "", add_marker
);
334 REGISTER_CALLBACK (serv
, "/ardour/access_action", "s", access_action
);
335 REGISTER_CALLBACK (serv
, "/ardour/loop_toggle", "", loop_toggle
);
336 REGISTER_CALLBACK (serv
, "/ardour/goto_start", "", goto_start
);
337 REGISTER_CALLBACK (serv
, "/ardour/goto_end", "", goto_end
);
338 REGISTER_CALLBACK (serv
, "/ardour/rewind", "", rewind
);
339 REGISTER_CALLBACK (serv
, "/ardour/ffwd", "", ffwd
);
340 REGISTER_CALLBACK (serv
, "/ardour/transport_stop", "", transport_stop
);
341 REGISTER_CALLBACK (serv
, "/ardour/transport_play", "", transport_play
);
342 REGISTER_CALLBACK (serv
, "/ardour/transport_frame", "", transport_frame
);
343 REGISTER_CALLBACK (serv
, "/ardour/set_transport_speed", "f", set_transport_speed
);
344 REGISTER_CALLBACK (serv
, "/ardour/locate", "ii", locate
);
345 REGISTER_CALLBACK (serv
, "/ardour/save_state", "", save_state
);
346 REGISTER_CALLBACK (serv
, "/ardour/prev_marker", "", prev_marker
);
347 REGISTER_CALLBACK (serv
, "/ardour/next_marker", "", next_marker
);
348 REGISTER_CALLBACK (serv
, "/ardour/undo", "", undo
);
349 REGISTER_CALLBACK (serv
, "/ardour/redo", "", redo
);
350 REGISTER_CALLBACK (serv
, "/ardour/toggle_punch_in", "", toggle_punch_in
);
351 REGISTER_CALLBACK (serv
, "/ardour/toggle_punch_out", "", toggle_punch_out
);
352 REGISTER_CALLBACK (serv
, "/ardour/rec_enable_toggle", "", rec_enable_toggle
);
353 REGISTER_CALLBACK (serv
, "/ardour/toggle_all_rec_enables", "", toggle_all_rec_enables
);
355 REGISTER_CALLBACK (serv
, "/ardour/routes/mute", "ii", route_mute
);
356 REGISTER_CALLBACK (serv
, "/ardour/routes/solo", "ii", route_solo
);
357 REGISTER_CALLBACK (serv
, "/ardour/routes/recenable", "ii", route_recenable
);
358 REGISTER_CALLBACK (serv
, "/ardour/routes/gainabs", "if", route_set_gain_abs
);
359 REGISTER_CALLBACK (serv
, "/ardour/routes/gaindB", "if", route_set_gain_dB
);
360 REGISTER_CALLBACK (serv
, "/ardour/routes/pan_stereo_position", "if", route_set_pan_stereo_position
);
361 REGISTER_CALLBACK (serv
, "/ardour/routes/pan_stereo_width", "if", route_set_pan_stereo_width
);
362 REGISTER_CALLBACK (serv
, "/ardour/routes/plugin/parameter", "iiif", route_plugin_parameter
);
363 REGISTER_CALLBACK (serv
, "/ardour/routes/plugin/parameter/print", "iii", route_plugin_parameter_print
);
367 /* still not-really-standardized query interface */
368 //REGISTER_CALLBACK (serv, "/ardour/*/#current_value", "", current_value);
369 //REGISTER_CALLBACK (serv, "/ardour/set", "", set);
371 // un/register_update args= s:ctrl s:returl s:retpath
372 //lo_server_add_method(serv, "/register_update", "sss", OSC::global_register_update_handler, this);
373 //lo_server_add_method(serv, "/unregister_update", "sss", OSC::global_unregister_update_handler, this);
374 //lo_server_add_method(serv, "/register_auto_update", "siss", OSC::global_register_auto_update_handler, this);
375 //lo_server_add_method(serv, "/unregister_auto_update", "sss", OSC::_global_unregister_auto_update_handler, this);
381 OSC::osc_input_handler (IOCondition ioc
, lo_server srv
)
388 lo_server_recv (srv
);
395 OSC::get_server_url()
401 urlstr
= lo_server_get_url (_osc_server
);
410 OSC::get_unix_server_url()
415 if (_osc_unix_server
) {
416 urlstr
= lo_server_get_url (_osc_unix_server
);
425 OSC::listen_to_route (boost::shared_ptr
<Route
> route
, lo_address addr
)
427 /* avoid duplicate listens */
429 for (RouteObservers::iterator x
= route_observers
.begin(); x
!= route_observers
.end(); ++x
) {
431 OSCRouteObserver
* ro
;
433 if ((ro
= dynamic_cast<OSCRouteObserver
*>(*x
)) != 0) {
435 int res
= strcmp(lo_address_get_hostname(ro
->address()), lo_address_get_hostname(addr
));
437 if (ro
->route() == route
&& res
== 0) {
443 OSCRouteObserver
* o
= new OSCRouteObserver (route
, addr
);
444 route_observers
.push_back (o
);
446 route
->DropReferences
.connect (*this, MISSING_INVALIDATOR
, boost::bind (&OSC::drop_route
, this, boost::weak_ptr
<Route
> (route
)), this);
450 OSC::drop_route (boost::weak_ptr
<Route
> wr
)
452 boost::shared_ptr
<Route
> r
= wr
.lock ();
458 for (RouteObservers::iterator x
= route_observers
.begin(); x
!= route_observers
.end();) {
460 OSCRouteObserver
* rc
;
462 if ((rc
= dynamic_cast<OSCRouteObserver
*>(*x
)) != 0) {
464 if (rc
->route() == r
) {
466 x
= route_observers
.erase (x
);
477 OSC::end_listen (boost::shared_ptr
<Route
> r
, lo_address addr
)
479 RouteObservers::iterator x
;
481 // Remove the route observers
482 for (x
= route_observers
.begin(); x
!= route_observers
.end();) {
484 OSCRouteObserver
* ro
;
486 if ((ro
= dynamic_cast<OSCRouteObserver
*>(*x
)) != 0) {
488 int res
= strcmp(lo_address_get_hostname(ro
->address()), lo_address_get_hostname(addr
));
490 if (ro
->route() == r
&& res
== 0) {
492 x
= route_observers
.erase (x
);
505 OSC::current_value_query (const char* path
, size_t len
, lo_arg
**argv
, int argc
, lo_message msg
)
509 subpath
= (char*) malloc (len
-15+1);
510 memcpy (subpath
, path
, len
-15);
511 subpath
[len
-15] = '\0';
513 send_current_value (subpath
, argv
, argc
, msg
);
519 OSC::send_current_value (const char* path
, lo_arg
** argv
, int argc
, lo_message msg
)
525 lo_message reply
= lo_message_new ();
526 boost::shared_ptr
<Route
> r
;
529 lo_message_add_string (reply
, path
);
532 lo_message_add_string (reply
, "bad syntax");
535 r
= session
->route_by_remote_id (id
);
538 lo_message_add_string (reply
, "not found");
541 if (strcmp (path
, "/routes/state") == 0) {
543 if (boost::dynamic_pointer_cast
<AudioTrack
>(r
)) {
544 lo_message_add_string (reply
, "AT");
545 } else if (boost::dynamic_pointer_cast
<MidiTrack
>(r
)) {
546 lo_message_add_string (reply
, "MT");
548 lo_message_add_string (reply
, "B");
551 lo_message_add_string (reply
, r
->name().c_str());
552 lo_message_add_int32 (reply
, r
->n_inputs().n_audio());
553 lo_message_add_int32 (reply
, r
->n_outputs().n_audio());
554 lo_message_add_int32 (reply
, r
->muted());
555 lo_message_add_int32 (reply
, r
->soloed());
557 } else if (strcmp (path
, "/routes/mute") == 0) {
559 lo_message_add_int32 (reply
, (float) r
->muted());
561 } else if (strcmp (path
, "/routes/solo") == 0) {
563 lo_message_add_int32 (reply
, r
->soloed());
568 lo_send_message (lo_message_get_source (msg
), "#reply", reply
);
569 lo_message_free (reply
);
573 OSC::_catchall (const char *path
, const char *types
, lo_arg
**argv
, int argc
, void *data
, void *user_data
)
575 return ((OSC
*)user_data
)->catchall (path
, types
, argv
, argc
, data
);
579 OSC::catchall (const char *path
, const char *types
, lo_arg
**argv
, int argc
, lo_message msg
)
582 int ret
= 1; /* unhandled */
584 //cerr << "Received a message, path = " << path << " types = \""
585 // << (types ? types : "NULL") << '"' << endl;
587 /* 15 for /#current_value plus 2 for /<path> */
591 if (len
>= 17 && !strcmp (&path
[len
-15], "/#current_value")) {
592 current_value_query (path
, len
, argv
, argc
, msg
);
595 } else if (strcmp (path
, "/routes/listen") == 0) {
597 cerr
<< "set up listener\n";
599 lo_message reply
= lo_message_new ();
602 lo_message_add_string (reply
, "syntax error");
604 for (int n
= 0; n
< argc
; ++n
) {
606 boost::shared_ptr
<Route
> r
= session
->route_by_remote_id (argv
[n
]->i
);
609 lo_message_add_string (reply
, "not found");
610 cerr
<< "no such route\n";
613 cerr
<< "add listener\n";
614 listen_to_route (r
, lo_message_get_source (msg
));
615 lo_message_add_int32 (reply
, argv
[n
]->i
);
620 lo_send_message (lo_message_get_source (msg
), "#reply", reply
);
621 lo_message_free (reply
);
625 } else if (strcmp (path
, "/routes/ignore") == 0) {
627 for (int n
= 0; n
< argc
; ++n
) {
629 boost::shared_ptr
<Route
> r
= session
->route_by_remote_id (argv
[n
]->i
);
632 end_listen (r
, lo_message_get_source (msg
));
648 // "Application Hook" Handlers //
650 OSC::session_loaded (Session
& s
)
652 lo_address listener
= lo_address_new (NULL
, "7770");
653 lo_send (listener
, "/session/loaded", "ss", s
.path().c_str(), s
.name().c_str());
657 OSC::session_exported (std::string path
, std::string name
)
659 lo_address listener
= lo_address_new (NULL
, "7770");
660 lo_send (listener
, "/session/exported", "ss", path
.c_str(), name
.c_str());
663 // end "Application Hook" Handlers //
668 OSC::current_value (const char */
*path*/
, const char */
*types*/
, lo_arg
**/
*argv*/
, int /*argc*/, void */
*data*/
, void* /*user_data*/)
673 if (argc
< 3 || types
== 0 || strlen (types
) < 3 || types
[0] != 's' || types
[1] != 's' || types
[2] != s
) {
677 const char *returl
= argv
[1]->s
;
678 lo_address addr
= find_or_cache_addr (returl
);
680 const char *retpath
= argv
[2]->s
;
683 if (strcmp (argv
[0]->s
, "transport_frame") == 0) {
686 lo_send (addr
, retpath
, "i", session
->transport_frame());
689 } else if (strcmp (argv
[0]->s
, "transport_speed") == 0) {
692 lo_send (addr
, retpath
, "i", session
->transport_frame());
695 } else if (strcmp (argv
[0]->s
, "transport_locked") == 0) {
698 lo_send (addr
, retpath
, "i", session
->transport_frame());
701 } else if (strcmp (argv
[0]->s
, "punch_in") == 0) {
704 lo_send (addr
, retpath
, "i", session
->transport_frame());
707 } else if (strcmp (argv
[0]->s
, "punch_out") == 0) {
710 lo_send (addr
, retpath
, "i", session
->transport_frame());
713 } else if (strcmp (argv
[0]->s
, "rec_enable") == 0) {
716 lo_send (addr
, retpath
, "i", session
->transport_frame());
728 OSC::routes_list (lo_message msg
)
730 for (int n
= 0; n
< (int) session
->nroutes(); ++n
) {
732 boost::shared_ptr
<Route
> r
= session
->route_by_remote_id (n
);
736 lo_message reply
= lo_message_new ();
738 if (boost::dynamic_pointer_cast
<AudioTrack
>(r
)) {
739 lo_message_add_string (reply
, "AT");
740 } else if (boost::dynamic_pointer_cast
<MidiTrack
>(r
)) {
741 lo_message_add_string (reply
, "MT");
743 lo_message_add_string (reply
, "B");
746 lo_message_add_string (reply
, r
->name().c_str());
747 lo_message_add_int32 (reply
, r
->n_inputs().n_audio());
748 lo_message_add_int32 (reply
, r
->n_outputs().n_audio());
749 lo_message_add_int32 (reply
, r
->muted());
750 lo_message_add_int32 (reply
, r
->soloed());
751 lo_message_add_int32 (reply
, r
->remote_control_id());
753 if (boost::dynamic_pointer_cast
<AudioTrack
>(r
)
754 || boost::dynamic_pointer_cast
<MidiTrack
>(r
)) {
756 boost::shared_ptr
<Track
> t
= boost::dynamic_pointer_cast
<Track
>(r
);
757 lo_message_add_int32 (reply
, t
->record_enabled());
760 //Automatically listen to routes listed
761 listen_to_route(r
, lo_message_get_source (msg
));
763 lo_send_message (lo_message_get_source (msg
), "#reply", reply
);
764 lo_message_free (reply
);
768 // Send end of listing message
769 lo_message reply
= lo_message_new ();
771 lo_message_add_string (reply
, "end_route_list");
772 lo_message_add_int64 (reply
, session
->frame_rate());
773 lo_message_add_int64 (reply
, session
->current_end_frame());
775 lo_send_message (lo_message_get_source (msg
), "#reply", reply
);
777 lo_message_free (reply
);
781 OSC::transport_frame (lo_message msg
)
783 framepos_t pos
= session
->transport_frame ();
785 lo_message reply
= lo_message_new ();
786 lo_message_add_int64 (reply
, pos
);
788 lo_send_message (lo_message_get_source (msg
), "/ardour/transport_frame", reply
);
790 lo_message_free (reply
);
794 OSC::route_mute (int rid
, int yn
)
796 if (!session
) return -1;
798 boost::shared_ptr
<Route
> r
= session
->route_by_remote_id (rid
);
801 r
->set_mute (yn
, this);
808 OSC::route_solo (int rid
, int yn
)
810 if (!session
) return -1;
812 boost::shared_ptr
<Route
> r
= session
->route_by_remote_id (rid
);
815 r
->set_solo (yn
, this);
822 OSC::route_recenable (int rid
, int yn
)
824 if (!session
) return -1;
826 boost::shared_ptr
<Route
> r
= session
->route_by_remote_id (rid
);
829 r
->set_record_enabled (yn
, this);
836 OSC::route_set_gain_abs (int rid
, float level
)
838 if (!session
) return -1;
840 boost::shared_ptr
<Route
> r
= session
->route_by_remote_id (rid
);
843 r
->set_gain (level
, this);
850 OSC::route_set_gain_dB (int rid
, float dB
)
852 if (!session
) return -1;
854 boost::shared_ptr
<Route
> r
= session
->route_by_remote_id (rid
);
857 r
->set_gain (dB_to_coefficient (dB
), this);
864 OSC::route_set_pan_stereo_position (int rid
, float pos
)
866 if (!session
) return -1;
868 boost::shared_ptr
<Route
> r
= session
->route_by_remote_id (rid
);
871 boost::shared_ptr
<Panner
> panner
= r
->panner();
873 panner
->set_position (pos
);
882 OSC::route_set_pan_stereo_width (int rid
, float pos
)
884 if (!session
) return -1;
886 boost::shared_ptr
<Route
> r
= session
->route_by_remote_id (rid
);
889 boost::shared_ptr
<Panner
> panner
= r
->panner();
891 panner
->set_width (pos
);
900 OSC::route_plugin_parameter (int rid
, int piid
, int par
, float val
)
906 boost::shared_ptr
<Route
> r
= session
->route_by_remote_id (rid
);
912 boost::shared_ptr
<Processor
> redi
=r
->nth_processor (piid
);
918 boost::shared_ptr
<PluginInsert
> pi
;
920 if (!(pi
= boost::dynamic_pointer_cast
<PluginInsert
>(redi
))) {
924 boost::shared_ptr
<ARDOUR::Plugin
> pip
= pi
->plugin();
927 uint32_t controlid
= pip
->nth_parameter (par
,ok
);
933 Plugin::ParameterDescriptor pd
;
934 pi
->plugin()->get_parameter_descriptor (controlid
,pd
);
936 if (val
>= pd
.lower
&& val
< pd
.upper
) {
938 boost::shared_ptr
<AutomationControl
> c
= pi
->automation_control (Evoral::Parameter(PluginAutomation
, 0, controlid
));;
939 cerr
<< "parameter:" << redi
->describe_parameter(controlid
) << " val:" << val
<< "\n";
947 OSC::route_plugin_parameter_print (int rid
, int piid
, int par
)
953 boost::shared_ptr
<Route
> r
= session
->route_by_remote_id (rid
);
959 boost::shared_ptr
<Processor
> redi
=r
->nth_processor (piid
);
965 boost::shared_ptr
<PluginInsert
> pi
;
967 if (!(pi
= boost::dynamic_pointer_cast
<PluginInsert
>(redi
))) {
971 boost::shared_ptr
<ARDOUR::Plugin
> pip
= pi
->plugin();
974 uint32_t controlid
= pip
->nth_parameter (par
,ok
);
980 Plugin::ParameterDescriptor pd
;
982 if (pi
->plugin()->get_parameter_descriptor (controlid
, pd
) == 0) {
983 boost::shared_ptr
<AutomationControl
> c
= pi
->automation_control (Evoral::Parameter(PluginAutomation
, 0, controlid
));
985 cerr
<< "parameter: " << redi
->describe_parameter(controlid
) << "\n";
986 cerr
<< "current value: " << c
->get_value ();
987 cerr
<< "lower value: " << pd
.lower
<< "\n";
988 cerr
<< "upper value: " << pd
.upper
<< "\n";
997 return *(new XMLNode ("OSC"));
1001 OSC::set_state (const XMLNode
&, int /*version*/)