13
0

Add zeroconf/mdns support

This commit is contained in:
Robin Gareus 2022-12-02 13:32:08 +01:00
parent aae15e3c90
commit c53b19c039
Signed by: rgareus
GPG Key ID: A090BCE02CF57F04
6 changed files with 260 additions and 1 deletions

View File

@ -0,0 +1,58 @@
/*
* Copyright (C) 2022 Robin Gareus <robin@gareus.org>
*
* 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.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <cstdint>
#include <string>
#ifdef __APPLE__
#include <dns_sd.h>
#include <glibmm/iochannel.h>
#include <glibmm/main.h>
#endif
#include "ardour/libardour_visibility.h"
#include "ardour/system_exec.h"
namespace ARDOUR {
class LIBARDOUR_API ZeroConf
{
public:
ZeroConf (std::string const& type = "_osc._udp", uint16_t port = 3819, std::string const& host = "");
~ZeroConf ();
private:
bool start ();
void stop ();
std::string _type;
uint16_t _port;
std::string _host;
#ifdef __APPLE__
static gboolean event (GIOChannel*, GIOCondition, gpointer);
DNSServiceRef _ref;
guint _source_id;
GIOChannel* _gio_channel;
#else
SystemExec* _avahi;
#endif
};
}; // namespace ARDOUR

View File

@ -282,7 +282,8 @@ libardour_sources = [
'vca_manager.cc', 'vca_manager.cc',
'video_tools_paths.cc', 'video_tools_paths.cc',
'vumeterdsp.cc', 'vumeterdsp.cc',
'worker.cc' 'worker.cc',
'zeroconf.cc'
] ]
def options(opt): def options(opt):

166
libs/ardour/zeroconf.cc Normal file
View File

@ -0,0 +1,166 @@
/*
* Copyright (C) 2022 Robin Gareus <robin@gareus.org>
*
* 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.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "pbd/compose.h"
#include "pbd/error.h"
#include "pbd/file_utils.h"
#include "ardour/filesystem_paths.h"
#include "ardour/zeroconf.h"
#include "pbd/i18n.h"
using namespace ARDOUR;
ZeroConf::ZeroConf (std::string const& type, uint16_t port, std::string const& host)
: _type (type)
, _port (port)
, _host (host)
#ifdef __APPLE__
, _source_id (0)
, _gio_channel (NULL)
#else
, _avahi (NULL)
#endif
{
start ();
}
ZeroConf::~ZeroConf ()
{
stop ();
}
#ifdef __APPLE__
void
ZeroConf::stop ()
{
if (_gio_channel) {
g_source_remove (_source_id);
g_io_channel_unref (_gio_channel);
}
DNSServiceRefDeallocate (_ref);
}
static void
dns_callback (DNSServiceRef sdref,
DNSServiceFlags flags,
DNSServiceErrorType errorCode,
const char* name,
const char* regtype,
const char* domain, void* context)
{
if (errorCode == kDNSServiceErr_NoError) {
PBD::info << string_compose (_("ZeroConf registered: %1 %2 %3"), name, regtype, domain) << endmsg;
} else {
PBD::info << _("ZeroConf registration failed") << endmsg;
}
}
gboolean
ZeroConf::event (GIOChannel* source,
GIOCondition condition,
gpointer data)
{
ZeroConf* self = reinterpret_cast<ZeroConf*> (data);
// assert (_fd == g_io_channel_unix_get_fd (source));
if (condition & ~G_IO_IN) {
/* remove on error */
return false;
} else {
if (DNSServiceProcessResult (self->_ref) != kDNSServiceErr_NoError) {
/* ZeroConf Error in data callback */
return false;
}
return true;
}
}
bool
ZeroConf::start ()
{
if (kDNSServiceErr_NoError != DNSServiceRegister (&_ref, /*flags*/ 0, /*interfaceIndex*/ 0, /*name*/ NULL, _type.c_str (),
/*domain*/ NULL, _host.empty () ? NULL : _host.c_str (), g_htons (_port),
/*txtlen*/ 0, /*TXT*/ NULL, dns_callback, this)) {
return false;
}
int fd = DNSServiceRefSockFD (_ref);
_gio_channel = g_io_channel_unix_new (fd);
_source_id = g_io_add_watch (_gio_channel, (GIOCondition) (G_IO_IN | G_IO_ERR | G_IO_HUP), ZeroConf::event, this);
return true;
}
#elif defined PLATFORM_WINDOWS
/* in theory dns_sd API also works on Windows 10+
* windns.h and dnsapi.dll
*/
bool
ZeroConf::start ()
{
return false;
}
bool
ZeroConf::stop ()
{
}
#else
bool
ZeroConf::start ()
{
std::string avahi_exec;
PBD::Searchpath sp (ARDOUR::ardour_dll_directory ());
if (!PBD::find_file (sp, "ardour-avahi.sh", avahi_exec)) {
PBD::warning << "ardour-avahi.sh was not found." << endmsg;
return false;
}
char** argp;
char tmp[128];
argp = (char**)calloc (5, sizeof (char*));
argp[0] = strdup (avahi_exec.c_str ());
snprintf (tmp, sizeof (tmp), "%d", _port);
argp[1] = strdup (tmp);
argp[2] = strdup (_type.c_str ());
snprintf (tmp, sizeof (tmp), "%d", getpid ());
argp[3] = strdup (tmp);
argp[4] = 0;
_avahi = new ARDOUR::SystemExec (avahi_exec, argp);
if (_avahi->start (SystemExec::ShareWithParent)) {
return false;
}
return false;
}
void
ZeroConf::stop ()
{
ARDOUR::SystemExec* tmp = _avahi;
_avahi = 0;
delete tmp;
}
#endif

24
tools/avahi.sh Executable file
View File

@ -0,0 +1,24 @@
#!/bin/sh
set -e
test -n "`which avahi-publish`"
test -n "`which tail`"
PORT=$1
TYPE=$2
test -n "$PORT"
test -n "$TYPE"
if test -n "$3"; then
PARENT_PID=$3
else
PARENT_PID=$$
fi
avahi-publish -s Ardour-$PARENT_PID "$TYPE" "$PORT" &
CHILD_PID=$!
trap "kill -- $CHILD_PID" EXIT
tail --pid=$PARENT_PID -f 2>/dev/null

View File

@ -506,6 +506,9 @@ EOF
chmod +x $APPLIB/ardour-util.sh chmod +x $APPLIB/ardour-util.sh
fi fi
cp $BUILD_ROOT/avahi.sh $APPLIB/ardour-avahi.sh
chmod +x $APPLIB/ardour-avahi.sh
OURLIBDIR=$BUILD_ROOT/libs OURLIBDIR=$BUILD_ROOT/libs
OURLIBS=$OURLIBDIR/ctrl-interface/midi_surface:$OURLIBDIR/ctrl-interface/control_protocol:$OURLIBDIR/ardour:$OURLIBDIR/midi++2:$OURLIBDIR/pbd:$OURLIBDIR/gtkmm2ext:$OURLIBDIR/glibmm2:$OURLIBDIR/canvas:$OURLIBDIR/widgets:$OURLIBDIR/waveview:$OURLIBDIR/evoral:$OURLIBDIR/evoral/src/libsmf:$OURLIBDIR/audiographer:$OURLIBDIR/temporal:$OURLIBDIR/libltc:$OURLIBDIR/qm-dsp:$OURLIBDIR/ardouralsautil:$OURLIBDIR/ptformat:$BUILD_ROOT/gtk2_ardour OURLIBS=$OURLIBDIR/ctrl-interface/midi_surface:$OURLIBDIR/ctrl-interface/control_protocol:$OURLIBDIR/ardour:$OURLIBDIR/midi++2:$OURLIBDIR/pbd:$OURLIBDIR/gtkmm2ext:$OURLIBDIR/glibmm2:$OURLIBDIR/canvas:$OURLIBDIR/widgets:$OURLIBDIR/waveview:$OURLIBDIR/evoral:$OURLIBDIR/evoral/src/libsmf:$OURLIBDIR/audiographer:$OURLIBDIR/temporal:$OURLIBDIR/libltc:$OURLIBDIR/qm-dsp:$OURLIBDIR/ardouralsautil:$OURLIBDIR/ptformat:$BUILD_ROOT/gtk2_ardour

View File

@ -10,6 +10,7 @@ import platform as PLATFORM
from waflib.Tools import winres from waflib.Tools import winres
from waflib.Build import Context from waflib.Build import Context
from waflib.Build import BuildContext from waflib.Build import BuildContext
import waflib.Utils as Utils
# Fixup OSX 10.5/10.6 builds # Fixup OSX 10.5/10.6 builds
# prefer gcc, g++ 4.x over ancient clang-1.5 # prefer gcc, g++ 4.x over ancient clang-1.5
@ -1619,6 +1620,12 @@ def build(bld):
bld.recurse('tools/sanity_check') bld.recurse('tools/sanity_check')
bld.recurse('tools/gccabicheck') bld.recurse('tools/gccabicheck')
obj = bld(features = 'subst')
obj.source = 'tools/avahi.sh'
obj.target = 'libs/ardour-avahi.sh'
obj.chmod = Utils.O755
obj.install_path = bld.env['LIBDIR']
bld.recurse('libs/clearlooks-newer') bld.recurse('libs/clearlooks-newer')
for i in children: for i in children: