Add mDNS service publishing on Linux for the remote control.

This commit is contained in:
John Maguire 2013-01-16 14:56:31 +01:00
parent 5ba67850fb
commit 0e226cc34b
6 changed files with 197 additions and 4 deletions

View File

@ -213,12 +213,13 @@ set(SOURCES
musicbrainz/chromaprinter.cpp
musicbrainz/musicbrainzclient.cpp
musicbrainz/tagfetcher.cpp
networkremote/networkremotehelper.cpp
networkremote/networkremote.cpp
networkremote/incomingdataparser.cpp
networkremote/networkremote.cpp
networkremote/networkremotehelper.cpp
networkremote/outgoingdatacreator.cpp
networkremote/remoteclient.cpp
networkremote/zeroconf.cpp
playlist/dynamicplaylistcontrols.cpp
playlist/playlist.cpp
@ -905,6 +906,34 @@ if(HAVE_DBUS)
dbus/org.gnome.SettingsDaemon.MediaKeys.xml
dbus/gnomesettingsdaemon)
# org.freedesktop.Avahi.Server interface
add_custom_command(
OUTPUT
${CMAKE_CURRENT_BINARY_DIR}/dbus/avahiserver.cpp
${CMAKE_CURRENT_BINARY_DIR}/dbus/avahiserver.h
COMMAND ${QT_DBUSXML2CPP_EXECUTABLE}
dbus/org.freedesktop.Avahi.Server.xml
-p ${CMAKE_CURRENT_BINARY_DIR}/dbus/avahiserver
-i dbus/metatypes.h
DEPENDS dbus/org.freedesktop.Avahi.Server.xml
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
list(APPEND HEADERS ${CMAKE_CURRENT_BINARY_DIR}/dbus/avahiserver.h)
list(APPEND SOURCES ${CMAKE_CURRENT_BINARY_DIR}/dbus/avahiserver.cpp)
# org.freedesktop.Avahi.EntryGroup interface
add_custom_command(
OUTPUT
${CMAKE_CURRENT_BINARY_DIR}/dbus/avahientrygroup.cpp
${CMAKE_CURRENT_BINARY_DIR}/dbus/avahientrygroup.h
COMMAND ${QT_DBUSXML2CPP_EXECUTABLE}
dbus/org.freedesktop.Avahi.EntryGroup.xml
-p ${CMAKE_CURRENT_BINARY_DIR}/dbus/avahientrygroup
-i dbus/metatypes.h
DEPENDS dbus/org.freedesktop.Avahi.EntryGroup.xml
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
list(APPEND HEADERS ${CMAKE_CURRENT_BINARY_DIR}/dbus/avahientrygroup.h)
list(APPEND SOURCES ${CMAKE_CURRENT_BINARY_DIR}/dbus/avahientrygroup.cpp)
# DeviceKit DBUS interfaces
if(HAVE_DEVICEKIT)
qt4_add_dbus_interface(SOURCES
@ -928,6 +957,7 @@ optional_source(HAVE_DBUS
core/mpris.cpp
core/mpris1.cpp
core/mpris2.cpp
networkremote/avahi.cpp
ui/dbusscreensaver.cpp
HEADERS
core/mpris.h

View File

@ -0,0 +1,96 @@
#include "avahi.h"
#include <QDBusConnection>
#include "core/closure.h"
#include "core/logging.h"
#include "dbus/avahientrygroup.h"
#include "dbus/avahiserver.h"
namespace {
void LogCommit(QDBusPendingReply<> reply) {
qLog(Debug) << "Remote interface published on Avahi:" << reply.error();
}
void Commit(OrgFreedesktopAvahiEntryGroupInterface* interface) {
QDBusPendingReply<> reply = interface->Commit();
QDBusPendingCallWatcher* watcher = new QDBusPendingCallWatcher(reply);
QObject::connect(
watcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
watcher, SLOT(deleteLater()));
QObject::connect(
watcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
interface, SLOT(deleteLater()));
NewClosure(
watcher,
SIGNAL(finished(QDBusPendingCallWatcher*)),
&LogCommit,
reply);
}
void AddService(
const QString domain,
const QString type,
const QString name,
quint16 port,
QDBusPendingReply<QDBusObjectPath> path_reply) {
if (path_reply.isError()) {
qLog(Warning)
<< "Failed to create Avahi entry group:"
<< path_reply.error();
qLog(Info)
<< "This might be because 'disable-user-service-publishing'"
<< "is set to 'yes' in avahi-daemon.conf";
return;
}
qLog(Debug) << path_reply.error();
OrgFreedesktopAvahiEntryGroupInterface* entry_group_interface =
new OrgFreedesktopAvahiEntryGroupInterface(
"org.freedesktop.Avahi",
path_reply.value().path(),
QDBusConnection::systemBus());
QDBusPendingReply<> reply = entry_group_interface->AddService(
-1, // Interface (all)
-1, // Protocol (v4 & v6)
0, // Flags
name, // Service name, eg. Clementine
type, // Service type, eg. _clementine._tcp
domain, // Domain, eg. local
QString::null, // Hostname (filled in by Avahi)
port, // Port our service is running on
QList<QByteArray>()); // TXT record
QDBusPendingCallWatcher* watcher = new QDBusPendingCallWatcher(reply);
NewClosure(
watcher,
SIGNAL(finished(QDBusPendingCallWatcher*)),
&Commit,
entry_group_interface);
QObject::connect(
watcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
watcher, SLOT(deleteLater()));
}
} // namespace
void Avahi::Publish(
const QString& domain,
const QString& type,
const QString& name,
quint16 port) {
OrgFreedesktopAvahiServerInterface server_interface(
"org.freedesktop.Avahi",
"/",
QDBusConnection::systemBus());
QDBusPendingReply<QDBusObjectPath> reply = server_interface.EntryGroupNew();
QDBusPendingCallWatcher* watcher = new QDBusPendingCallWatcher(reply);
NewClosure(
watcher,
SIGNAL(finished(QDBusPendingCallWatcher*)),
&AddService,
domain, type, name, port, reply);
QObject::connect(
watcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
watcher, SLOT(deleteLater()));
}

15
src/networkremote/avahi.h Normal file
View File

@ -0,0 +1,15 @@
#ifndef AVAHI_H
#define AVAHI_H
#include "zeroconf.h"
class Avahi : public Zeroconf {
public:
virtual void Publish(
const QString& domain,
const QString& type,
const QString& name,
quint16 port);
};
#endif // AVAHI_H

View File

@ -15,11 +15,13 @@
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
*/
#include "networkremote.h"
#include "core/logging.h"
#include "covers/currentartloader.h"
#include "networkremote/zeroconf.h"
#include "playlist/playlistmanager.h"
#include "networkremote.h"
#include <QDataStream>
#include <QSettings>
@ -87,6 +89,11 @@ void NetworkRemote::StartServer() {
server_ipv6_->listen(QHostAddress::AnyIPv6, port_);
qLog(Info) << "Listening on port " << port_;
if (Zeroconf::GetZeroconf()) {
Zeroconf::GetZeroconf()->Publish(
"local", "_clementine._tcp", "Clementine", port_);
}
}
void NetworkRemote::StopServer() {

View File

@ -0,0 +1,23 @@
#include "zeroconf.h"
#include "config.h"
#ifdef HAVE_DBUS
#include "avahi.h"
#endif
Zeroconf* Zeroconf::sInstance = NULL;
Zeroconf::~Zeroconf() {
}
Zeroconf* Zeroconf::GetZeroconf() {
if (!sInstance) {
#ifdef HAVE_DBUS
sInstance = new Avahi;
#endif // HAVE_DBUS
}
return sInstance;
}

View File

@ -0,0 +1,22 @@
#ifndef ZEROCONF_H
#define ZEROCONF_H
#include <QString>
class Zeroconf {
public:
virtual ~Zeroconf();
virtual void Publish(
const QString& domain,
const QString& type,
const QString& name,
quint16 port) = 0;
static Zeroconf* GetZeroconf();
private:
static Zeroconf* sInstance;
};
#endif // ZEROCONF_H