You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

296 lines
9.9 KiB

'use strict';
const pkg = imports.package;
pkg.require({
'Gdk': '3.0'
, 'Gio': '2.0'
, 'GLib': '2.0'
, 'GObject': '2.0'
, 'Gtk': '3.0'
});
const {Gdk, Gio, GLib, Gtk, GObject, Avahi, AvahiCore} = imports.gi;
const Signals = imports.signals;
// address.h
const PROTO_UNSPEC = -1;
const IF_UNSPEC = -1;
// AvahiLookupFlags
const LOOKUP_USE_WIDE_AREA = 1;
const LOOKUP_USE_MULTICAST = 2;
const LOOKUP_NO_TXT = 4;
const LOOKUP_NO_ADDRESS = 8;
// AvahiLookupResultFlags
const LOOKUP_RESULT_CACHED = 1;
const LOOKUP_RESULT_WIDE_AREA = 2;
const LOOKUP_RESULT_MULTICAST = 4;
const LOOKUP_RESULT_LOCAL = 8;
const LOOKUP_RESULT_OUR_OWN = 16;
const LOOKUP_RESULT_STATIC = 32;
const DNS_TYPE_A = 0x01;
const DNS_TYPE_NS = 0x02;
const DNS_TYPE_CNAME = 0x05;
const DNS_TYPE_SOA = 0x06;
const DNS_TYPE_PTR = 0x0C;
const DNS_TYPE_HINFO = 0x0D;
const DNS_TYPE_MX = 0x0F;
const DNS_TYPE_TXT = 0x10;
const DNS_TYPE_AAAA = 0x1C;
const DNS_TYPE_SRV = 0x2;
const DNS_CLASS_IN = 0x01;
//log(imports.gi.GIRepository.Repository.get_default().is_registered('AvahiCore', '0.6'));
const SNAPCAST_AVAHI_TCP = '_snapcast-tcp._tcp';
const SNAPCAST_AVAHI_STREAM = '_snapcast-stream._tcp';
const SNAPCAST_AVAHI_RCP = '_snapcast-rpc._tcp';
var AvahiSnapcast = class {
constructor() {
this.servers = {};
}
enable() {
this.aclient = new Avahi.Client({flags: Avahi.ClientFlags.GA_CLIENT_FLAG_NO_FAIL});
this.aclient.connect('state-changed', () => {
log('AVAHI: state-changed')
});
this.aclient.start();
this.abrowser = Avahi.ServiceBrowser.new_full(-1, AvahiCore.Protocol.INET, SNAPCAST_AVAHI_TCP, 'local', 0);
this.abrowser.attach(this.aclient);
this.abrowser.connect('all-for-now', () => {
log('AVAHI: all-for-now')
this.emit('all-for-now');
});
this.abrowser.connect('removed-service', (browser, if_index, protocol, name, service, domain, flags) => {
this.removeServer(name);
});
this.abrowser.connect('cache-exhausted', () => {log('AVAHI: cache exhausted')});
this.abrowser.connect('new-service', (browser, if_index, protocol, name, service, domain, flags) => {
log('AVAHI: new-service')
let aresolver = Avahi.ServiceResolver.new(if_index, protocol, name, service, domain, AvahiCore.Protocol.INET, 0);
aresolver.attach(this.aclient);
aresolver.connect('found', (resolver, if_index, protocol, name, service, domain, hostname, address, port, txt, flags, e) => {
let ip = Gio.Resolver.get_default().lookup_by_name(hostname, null)[0].to_string();
this.addServer(name, hostname, domain, ip, port);
});
});
}
addServer(name, hostname, domain, ip, port) {
if (name in this.servers) {
return;
}
this.servers[name] = {
name: name
, hostname: hostname
, domain: domain
, ip: ip
, port: port
}
log('AVAHI NEW: ' + JSON.stringify(this.servers[name]));
this.emit('added', this.servers[name]);
}
removeServer(name) {
if (name in this.servers) {
delete this.servers[name];
log('AVAHI REMOVE: ' + name);
this.emit('removed', name);
}
}
server(name) {
return this.servers[name];
}
};
Signals.addSignalMethods(AvahiSnapcast.prototype);
/*
const avahiInterface = '<node>\
<interface name="org.freedesktop.Avahi.Server">\
<method name="GetVersionString">\
<arg name="version" type="s" direction="out"/>\
</method>\
<method name="GetAPIVersion">\
<arg name="version" type="u" direction="out"/>\
</method>\
<method name="GetHostName">\
<arg name="name" type="s" direction="out"/>\
</method>\
<method name="SetHostName">\
<arg name="name" type="s" direction="in"/>\
</method>\
<method name="GetHostNameFqdn">\
<arg name="name" type="s" direction="out"/>\
</method>\
<method name="GetDomainName">\
<arg name="name" type="s" direction="out"/>\
</method>\
<method name="IsNSSSupportAvailable">\
<arg name="yes" type="b" direction="out"/>\
</method>\
<method name="GetState">\
<arg name="state" type="i" direction="out"/>\
</method>\
<signal name="StateChanged">\
<arg name="state" type="i"/>\
<arg name="error" type="s"/>\
</signal>\
<method name="GetLocalServiceCookie">\
<arg name="cookie" type="u" direction="out"/>\
</method>\
<method name="GetAlternativeHostName">\
<arg name="name" type="s" direction="in"/>\
<arg name="name" type="s" direction="out"/>\
</method>\
<method name="GetAlternativeServiceName">\
<arg name="name" type="s" direction="in"/>\
<arg name="name" type="s" direction="out"/>\
</method>\
<method name="GetNetworkInterfaceNameByIndex">\
<arg name="index" type="i" direction="in"/>\
<arg name="name" type="s" direction="out"/>\
</method>\
<method name="GetNetworkInterfaceIndexByName">\
<arg name="name" type="s" direction="in"/>\
<arg name="index" type="i" direction="out"/>\
</method>\
<method name="ResolveHostName">\
<arg name="interface" type="i" direction="in"/>\
<arg name="protocol" type="i" direction="in"/>\
<arg name="name" type="s" direction="in"/>\
<arg name="aprotocol" type="i" direction="in"/>\
<arg name="flags" type="u" direction="in"/>\
<arg name="interface" type="i" direction="out"/>\
<arg name="protocol" type="i" direction="out"/>\
<arg name="name" type="s" direction="out"/>\
<arg name="aprotocol" type="i" direction="out"/>\
<arg name="address" type="s" direction="out"/>\
<arg name="flags" type="u" direction="out"/>\
</method>\
<method name="ResolveAddress">\
<arg name="interface" type="i" direction="in"/>\
<arg name="protocol" type="i" direction="in"/>\
<arg name="address" type="s" direction="in"/>\
<arg name="flags" type="u" direction="in"/>\
<arg name="interface" type="i" direction="out"/>\
<arg name="protocol" type="i" direction="out"/>\
<arg name="aprotocol" type="i" direction="out"/>\
<arg name="address" type="s" direction="out"/>\
<arg name="name" type="s" direction="out"/>\
<arg name="flags" type="u" direction="out"/>\
</method>\
<method name="ResolveService">\
<arg name="interface" type="i" direction="in"/>\
<arg name="protocol" type="i" direction="in"/>\
<arg name="name" type="s" direction="in"/>\
<arg name="type" type="s" direction="in"/>\
<arg name="domain" type="s" direction="in"/>\
<arg name="aprotocol" type="i" direction="in"/>\
<arg name="flags" type="u" direction="in"/>\
<arg name="interface" type="i" direction="out"/>\
<arg name="protocol" type="i" direction="out"/>\
<arg name="name" type="s" direction="out"/>\
<arg name="type" type="s" direction="out"/>\
<arg name="domain" type="s" direction="out"/>\
<arg name="host" type="s" direction="out"/>\
<arg name="aprotocol" type="i" direction="out"/>\
<arg name="address" type="s" direction="out"/>\
<arg name="port" type="q" direction="out"/>\
<arg name="txt" type="aay" direction="out"/>\
<arg name="flags" type="u" direction="out"/>\
</method>\
<method name="EntryGroupNew">\
<arg name="path" type="o" direction="out"/>\
</method>\
<method name="DomainBrowserNew">\
<arg name="interface" type="i" direction="in"/>\
<arg name="protocol" type="i" direction="in"/>\
<arg name="domain" type="s" direction="in"/>\
<arg name="btype" type="i" direction="in"/>\
<arg name="flags" type="u" direction="in"/>\
<arg name="path" type="o" direction="out"/>\
</method>\
<method name="ServiceTypeBrowserNew">\
<arg name="interface" type="i" direction="in"/>\
<arg name="protocol" type="i" direction="in"/>\
<arg name="domain" type="s" direction="in"/>\
<arg name="flags" type="u" direction="in"/>\
<arg name="path" type="o" direction="out"/>\
</method>\
<method name="ServiceBrowserNew">\
<arg name="interface" type="i" direction="in"/>\
<arg name="protocol" type="i" direction="in"/>\
<arg name="type" type="s" direction="in"/>\
<arg name="domain" type="s" direction="in"/>\
<arg name="flags" type="u" direction="in"/>\
<arg name="path" type="o" direction="out"/>\
</method>\
<method name="ServiceResolverNew">\
<arg name="interface" type="i" direction="in"/>\
<arg name="protocol" type="i" direction="in"/>\
<arg name="name" type="s" direction="in"/>\
<arg name="type" type="s" direction="in"/>\
<arg name="domain" type="s" direction="in"/>\
<arg name="aprotocol" type="i" direction="in"/>\
<arg name="flags" type="u" direction="in"/>\
<arg name="path" type="o" direction="out"/>\
</method>\
<method name="HostNameResolverNew">\
<arg name="interface" type="i" direction="in"/>\
<arg name="protocol" type="i" direction="in"/>\
<arg name="name" type="s" direction="in"/>\
<arg name="aprotocol" type="i" direction="in"/>\
<arg name="flags" type="u" direction="in"/>\
<arg name="path" type="o" direction="out"/>\
</method>\
<method name="AddressResolverNew">\
<arg name="interface" type="i" direction="in"/>\
<arg name="protocol" type="i" direction="in"/>\
<arg name="address" type="s" direction="in"/>\
<arg name="flags" type="u" direction="in"/>\
<arg name="path" type="o" direction="out"/>\
</method>\
<method name="RecordBrowserNew">\
<arg name="interface" type="i" direction="in"/>\
<arg name="protocol" type="i" direction="in"/>\
<arg name="name" type="s" direction="in"/>\
<arg name="clazz" type="q" direction="in"/>\
<arg name="type" type="q" direction="in"/>\
<arg name="flags" type="u" direction="in"/>\
<arg name="path" type="o" direction="out"/>\
</method>\
</interface>\
</node>';
var Avahi = class Avahi {
constructor() {
const avahiProxy = Gio.DBusProxy.makeProxyWrapper(avahiInterface);
this.proxy = new avahiProxy(
Gio.DBus.system
, 'org.freedesktop.Avahi'
, '/'
);
}
}
let derp = new Avahi();
let path = derp.proxy.ServiceBrowserNewSync(-1, -1, '_tcp', 'local', 0);
var iface = 'org.freedesktop.Avahi.DomainBrowser';
derp.proxy.connectSignal('ItemNew', function(proxy, result) {
log(proxy);
});
derp.proxy.connectSignal('AllForNow', function(proxy, result) {
log(proxy);
});
derp.proxy.connectSignal('StateChanged', function(proxy, result) {
log(proxy);
});
*/
//let loop = new GLib.MainLoop(null, false);
//loop.run();