initial code steps for websocket OSC
This commit is contained in:
parent
76e23d1675
commit
4febf7f818
|
@ -32,6 +32,7 @@
|
|||
#include <pbd/pthread_utils.h>
|
||||
#include <pbd/file_utils.h>
|
||||
#include <pbd/failed_constructor.h>
|
||||
#include "pbd/i18n.h"
|
||||
|
||||
#include "ardour/amp.h"
|
||||
#include "ardour/session.h"
|
||||
|
@ -58,7 +59,7 @@
|
|||
#include "osc_route_observer.h"
|
||||
#include "osc_global_observer.h"
|
||||
#include "osc_cue_observer.h"
|
||||
#include "pbd/i18n.h"
|
||||
#include "ws_osc.h"
|
||||
|
||||
using namespace ARDOUR;
|
||||
using namespace std;
|
||||
|
@ -81,16 +82,19 @@ static void error_callback(int, const char *, const char *)
|
|||
}
|
||||
#endif
|
||||
|
||||
OSC::OSC (Session& s, uint32_t port)
|
||||
OSC::OSC (Session& s, uint32_t port, int32_t ws_port)
|
||||
: ControlProtocol (s, X_("Open Sound Control (OSC)"))
|
||||
, AbstractUI<OSCUIRequest> (name())
|
||||
, local_server (0)
|
||||
, remote_server (0)
|
||||
, ws_server (0)
|
||||
, _port(port)
|
||||
, _ws_port(ws_port)
|
||||
, _ok (true)
|
||||
, _shutdown (false)
|
||||
, _osc_server (0)
|
||||
, _osc_unix_server (0)
|
||||
, _osc_ws_server (0)
|
||||
, _debugmode (Off)
|
||||
, address_only (false)
|
||||
, remote_port ("8000")
|
||||
|
@ -220,6 +224,15 @@ OSC::start ()
|
|||
|
||||
PBD::info << "OSC @ " << get_server_url () << endmsg;
|
||||
|
||||
if (_ws_port > 0) {
|
||||
try {
|
||||
_osc_ws_server = new WSOSCServer (this, _ws_port, string(), string());
|
||||
PBD::info << "OSC-WebSocket @ " << _ws_port << endmsg;
|
||||
} catch (...) {
|
||||
_osc_ws_server = 0;
|
||||
}
|
||||
}
|
||||
|
||||
std::string url_file;
|
||||
|
||||
if (find_file (ardour_config_search_path(), "osc_url", url_file)) {
|
||||
|
@ -258,6 +271,12 @@ OSC::start ()
|
|||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
OSC::attach (Glib::RefPtr<IOSource> src)
|
||||
{
|
||||
src->attach (_main_loop->get_context());
|
||||
}
|
||||
|
||||
void
|
||||
OSC::thread_init ()
|
||||
{
|
||||
|
@ -580,7 +599,7 @@ OSC::register_callbacks()
|
|||
REGISTER_CALLBACK (serv, "/select/eq_q", "if", sel_eq_q);
|
||||
REGISTER_CALLBACK (serv, "/select/eq_shape", "if", sel_eq_shape);
|
||||
|
||||
/* These commands require the route index in addition to the arg; TouchOSC (et al) can't use these */
|
||||
/* These commands require the route index in addition to the arg; TouchOSC (et al) can't use these */
|
||||
REGISTER_CALLBACK (serv, "/strip/mute", "ii", route_mute);
|
||||
REGISTER_CALLBACK (serv, "/strip/solo", "ii", route_solo);
|
||||
REGISTER_CALLBACK (serv, "/strip/solo_iso", "ii", route_solo_iso);
|
||||
|
@ -607,7 +626,7 @@ OSC::register_callbacks()
|
|||
REGISTER_CALLBACK (serv, "/strip/send/enable", "iif", route_set_send_enable);
|
||||
REGISTER_CALLBACK(serv, "/strip/name", "is", route_rename);
|
||||
REGISTER_CALLBACK(serv, "/strip/sends", "i", route_get_sends);
|
||||
REGISTER_CALLBACK(serv, "/strip/receives", "i", route_get_receives);
|
||||
REGISTER_CALLBACK(serv, "/strip/receives", "i", route_get_receives);
|
||||
REGISTER_CALLBACK(serv, "/strip/plugin/list", "i", route_plugin_list);
|
||||
REGISTER_CALLBACK(serv, "/strip/plugin/descriptor", "ii", route_plugin_descriptor);
|
||||
REGISTER_CALLBACK(serv, "/strip/plugin/reset", "ii", route_plugin_reset);
|
||||
|
@ -4530,4 +4549,3 @@ OSC::cue_get_sorted_stripables(boost::shared_ptr<Stripable> aux, uint32_t id, lo
|
|||
|
||||
return sorted;
|
||||
}
|
||||
|
||||
|
|
|
@ -66,10 +66,12 @@ struct OSCUIRequest : public BaseUI::BaseRequestObject {
|
|||
~OSCUIRequest() {}
|
||||
};
|
||||
|
||||
class WSOSCServer;
|
||||
|
||||
class OSC : public ARDOUR::ControlProtocol, public AbstractUI<OSCUIRequest>
|
||||
{
|
||||
public:
|
||||
OSC (ARDOUR::Session&, uint32_t port);
|
||||
OSC (ARDOUR::Session&, uint32_t port, int32_t ws_port = -1);
|
||||
virtual ~OSC();
|
||||
|
||||
static OSC* instance() { return _instance; }
|
||||
|
@ -174,21 +176,26 @@ class OSC : public ARDOUR::ControlProtocol, public AbstractUI<OSCUIRequest>
|
|||
std::string get_remote_port () { return remote_port; }
|
||||
void set_remote_port (std::string pt) { remote_port = pt; }
|
||||
|
||||
void attach (Glib::RefPtr<Glib::IOSource>);
|
||||
|
||||
protected:
|
||||
void thread_init ();
|
||||
void do_request (OSCUIRequest*);
|
||||
|
||||
GSource* local_server;
|
||||
GSource* remote_server;
|
||||
GSource* ws_server;
|
||||
|
||||
bool osc_input_handler (Glib::IOCondition, lo_server);
|
||||
|
||||
private:
|
||||
uint32_t _port;
|
||||
int32_t _ws_port;
|
||||
volatile bool _ok;
|
||||
volatile bool _shutdown;
|
||||
lo_server _osc_server;
|
||||
lo_server _osc_unix_server;
|
||||
WSOSCServer* _osc_ws_server;
|
||||
std::string _osc_unix_socket_path;
|
||||
std::string _osc_url_file;
|
||||
OSCDebugMode _debugmode;
|
||||
|
|
125
libs/surfaces/osc/ws_osc.cc
Normal file
125
libs/surfaces/osc/ws_osc.cc
Normal file
|
@ -0,0 +1,125 @@
|
|||
#include <glibmm.h>
|
||||
|
||||
#include "osc.h"
|
||||
#include "ws_osc.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace ArdourSurface;
|
||||
using namespace Glib;
|
||||
|
||||
// 0 for unlimited
|
||||
#define MAX_BUFFER_SIZE 0
|
||||
|
||||
static int callback_main( struct lws *wsi,
|
||||
enum lws_callback_reasons reason,
|
||||
void *user,
|
||||
void *in,
|
||||
size_t len )
|
||||
{
|
||||
#if 0
|
||||
int fd;
|
||||
unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 512 + LWS_SEND_BUFFER_POST_PADDING];
|
||||
unsigned char *p = &buf[LWS_SEND_BUFFER_PRE_PADDING];
|
||||
|
||||
switch( reason ) {
|
||||
case LWS_CALLBACK_ESTABLISHED:
|
||||
self->onConnectWrapper( lws_get_socket_fd( wsi ) );
|
||||
lws_callback_on_writable( wsi );
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_SERVER_WRITEABLE:
|
||||
fd = lws_get_socket_fd( wsi );
|
||||
while( !self->connections[fd]->buffer.empty( ) )
|
||||
{
|
||||
string message = self->connections[fd]->buffer.front( );
|
||||
int charsSent = lws_write( wsi, (unsigned char*)message.c_str( ), message.length( ), LWS_WRITE_TEXT );
|
||||
if( charsSent < message.length( ) )
|
||||
self->onErrorWrapper( fd, string( "Error writing to socket" ) );
|
||||
else
|
||||
// Only pop the message if it was sent successfully.
|
||||
self->connections[fd]->buffer.pop_front( );
|
||||
}
|
||||
lws_callback_on_writable( wsi );
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_RECEIVE:
|
||||
self->onMessage( lws_get_socket_fd( wsi ), string( (const char *)in ) );
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_CLOSED:
|
||||
self->onDisconnectWrapper( lws_get_socket_fd( wsi ) );
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct lws_protocols protocols[] = {
|
||||
{
|
||||
"/",
|
||||
callback_main,
|
||||
0, // user data struct not used
|
||||
MAX_BUFFER_SIZE,
|
||||
},{ NULL, NULL, 0, 0 } // terminator
|
||||
};
|
||||
|
||||
WSOSCServer::WSOSCServer (OSC* o, int32_t p, string const & cpath, string const & kpath)
|
||||
: osc (o)
|
||||
, port (p)
|
||||
, cert_path (cpath)
|
||||
, key_path (kpath)
|
||||
, context (0)
|
||||
{
|
||||
lws_set_log_level( 0, lwsl_emit_syslog ); // We'll do our own logging, thank you.
|
||||
|
||||
struct lws_context_creation_info info;
|
||||
|
||||
memset( &info, 0, sizeof info );
|
||||
info.port = port;
|
||||
info.iface = NULL;
|
||||
info.protocols = protocols;
|
||||
|
||||
if (cert_path.empty( ) && !key_path.empty( ) ) {
|
||||
info.ssl_cert_filepath = cert_path.c_str( );
|
||||
info.ssl_private_key_filepath = key_path.c_str( );
|
||||
} else {
|
||||
info.ssl_cert_filepath = 0;
|
||||
info.ssl_private_key_filepath = 0;
|
||||
}
|
||||
info.gid = -1;
|
||||
info.uid = -1;
|
||||
info.options = 0;
|
||||
|
||||
// keep alive
|
||||
info.ka_time = 60; // 60 seconds until connection is suspicious
|
||||
info.ka_probes = 10; // 10 probes after ^ time
|
||||
info.ka_interval = 10; // 10s interval for sending probes
|
||||
context = lws_create_context( &info );
|
||||
|
||||
if (!context) {
|
||||
}
|
||||
}
|
||||
|
||||
WSOSCServer::~WSOSCServer ()
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
WSOSCServer::event_handler (IOCondition, int)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
WSOSCServer::add_fd (int fd)
|
||||
{
|
||||
Glib::RefPtr<IOSource> src = IOSource::create (fd, IO_IN|IO_OUT|IO_HUP|IO_ERR);
|
||||
src->connect (sigc::bind (sigc::mem_fun (*this, &WSOSCServer::event_handler), fd));
|
||||
osc->attach (src);
|
||||
GSource* s = src->gobj();
|
||||
g_source_ref (s);
|
||||
sources.push_back (src);
|
||||
}
|
57
libs/surfaces/osc/ws_osc.h
Normal file
57
libs/surfaces/osc/ws_osc.h
Normal file
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Copyright (C) 2017 Paul Davis
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ardour_wsosc_h
|
||||
#define ardour_wsosc_h
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <stdint.h>
|
||||
#include <libwebsockets.h>
|
||||
|
||||
#include <glibmm.h>
|
||||
|
||||
namespace ArdourSurface {
|
||||
|
||||
class OSC;
|
||||
|
||||
class WSOSCServer
|
||||
{
|
||||
public:
|
||||
WSOSCServer (OSC*, int32_t port, std::string const & cert_path, std::string const & key_path);
|
||||
~WSOSCServer ();
|
||||
|
||||
private:
|
||||
OSC* osc;
|
||||
int port;
|
||||
std::string cert_path;
|
||||
std::string key_path;
|
||||
struct lws_context* context;
|
||||
|
||||
typedef std::vector<Glib::RefPtr<Glib::IOSource> > Sources;
|
||||
Sources sources;
|
||||
|
||||
void add_fd (int fd);
|
||||
bool event_handler (Glib::IOCondition, int);
|
||||
};
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif // ardour_wsosc_h
|
|
@ -23,6 +23,7 @@ def build(bld):
|
|||
osc_cue_observer.cc
|
||||
interface.cc
|
||||
osc_gui.cc
|
||||
ws_osc.cc
|
||||
'''
|
||||
obj.export_includes = ['.']
|
||||
obj.defines = [ 'PACKAGE="ardour_osc"' ]
|
||||
|
@ -30,7 +31,7 @@ def build(bld):
|
|||
obj.includes = ['.', './osc']
|
||||
obj.name = 'libardour_osc'
|
||||
obj.target = 'ardour_osc'
|
||||
obj.uselib = 'LO GTKMM GTK GDK'
|
||||
obj.uselib = 'LO GTKMM GTK GDK WEBSOCKETS'
|
||||
obj.use = 'libardour libardour_cp libgtkmm2ext libpbd'
|
||||
obj.install_path = os.path.join(bld.env['LIBDIR'], 'surfaces')
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user