diff --git a/client.pro b/client.pro index 7e60c5659..006a47513 100644 --- a/client.pro +++ b/client.pro @@ -27,6 +27,7 @@ contains(BLACK_CONFIG, BlackSim) { } contains(BLACK_CONFIG, XPlane) { + SUBDIRS += src/blacksim/xplane/xbus/xbus.pro SUBDIRS += src/blacksim/xplane/plugin/plugin_xplane.pro } } diff --git a/src/blacksim/xplane/xbus/main.cpp b/src/blacksim/xplane/xbus/main.cpp new file mode 100644 index 000000000..eb1b56b53 --- /dev/null +++ b/src/blacksim/xplane/xbus/main.cpp @@ -0,0 +1,45 @@ +/* Copyright (C) 2013 VATSIM Community / contributors + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#define _CRT_SECURE_NO_WARNINGS +#include "stub.h" +#include "utils.h" +#include + +QSharedPointer g_qApp; +XBus::CStub *g_stub; + +PLUGIN_API int XPluginStart(char *o_name, char *o_sig, char *o_desc) +{ + std::strcpy(o_name, "X-Bus"); + std::strcpy(o_sig, "net.vatsim.XBus"); + std::strcpy(o_desc, "Allows pilot client to connect to X-Plane via D-Bus"); + return 1; +} + +PLUGIN_API void XPluginStop() +{ +} + +PLUGIN_API int XPluginEnable() +{ + g_qApp = QSharedApplication::sharedInstance(); + QXPlaneEventLoop::exec(); + g_stub = new XBus::CStub; + return 1; +} + +PLUGIN_API void XPluginDisable() +{ + delete g_stub; + g_qApp.reset(); +} + +PLUGIN_API void XPluginReceiveMessage(XPLMPluginID from, long msg, void *param) +{ + Q_UNUSED(from); + Q_UNUSED(msg); + Q_UNUSED(param); +} diff --git a/src/blacksim/xplane/xbus/stub.h b/src/blacksim/xplane/xbus/stub.h new file mode 100644 index 000000000..bc66a75a5 --- /dev/null +++ b/src/blacksim/xplane/xbus/stub.h @@ -0,0 +1,27 @@ +/* Copyright (C) 2013 VATSIM Community / contributors + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef BLACKSIM_XBUS_STUB_H +#define BLACKSIM_XBUS_STUB_H + +/*! + * \file + */ + +/*! + * \namespace XBus + */ + +namespace XBus +{ + /*! + * stub + */ + class CStub + { + }; +} + +#endif // guard diff --git a/src/blacksim/xplane/xbus/utils.h b/src/blacksim/xplane/xbus/utils.h new file mode 100644 index 000000000..488ca6c29 --- /dev/null +++ b/src/blacksim/xplane/xbus/utils.h @@ -0,0 +1,87 @@ +/* Copyright (C) 2013 VATSIM Community / contributors + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef BLACKSIM_XBUS_UTILS_H +#define BLACKSIM_XBUS_UTILS_H + +#include +#include +#include +#include +#include + +/*! + * \file + */ + +/*! + * QApplication subclass used by XBus. + * + * Only one instance of QApplication is allowed per process, so if any other + * X-Plane plugin, completely unrelated to this pilot client, wants to use the + * Qt framework, they can simply copy & paste this class into their project + * and both X-Plane plugins will be able to share a single QApplication safely. + */ +class QSharedApplication : public QApplication +{ + Q_OBJECT + + QWeakPointer m_weakptr; + + QSharedApplication(QSharedPointer &ptr, int argc, char **argv) : QApplication(argc, argv) + { + ptr.reset(this); + m_weakptr = ptr; + } + +public: + static QSharedPointer sharedInstance() + { + QSharedPointer ptr; + if (! instance()) + { + static int argc = 1; + static char *argv[] = { "X-Plane" }; + new QSharedApplication(ptr, argc, argv); + } + return qobject_cast(instance())->m_weakptr; + } +}; + +/*! + * Runs the Qt event loop inside the X-Plane event loop. + */ +class QXPlaneEventLoop : public QObject +{ + Q_OBJECT + + QXPlaneEventLoop(QObject *parent) : QObject(parent) + { + XPLMRegisterFlightLoopCallback(callback, -1, nullptr); + } + + ~QXPlaneEventLoop() + { + XPLMUnregisterFlightLoopCallback(callback, nullptr); + } + + static float callback(float, float, int, void *) + { + QApplication::processEvents(); + QApplication::sendPostedEvents(); + return -1; + } + +public: + static void exec() + { + if (! QApplication::instance()->findChild()) + { + new QXPlaneEventLoop(QApplication::instance()); + } + } +}; + +#endif // guard diff --git a/src/blacksim/xplane/xbus/xbus.pro b/src/blacksim/xplane/xbus/xbus.pro new file mode 100644 index 000000000..ff60b5d56 --- /dev/null +++ b/src/blacksim/xplane/xbus/xbus.pro @@ -0,0 +1,71 @@ +include (../../../../config.pri) +include (../../../../build.pri) + +QT += core gui widgets dbus network + +TEMPLATE = lib + +CONFIG += shared +CONFIG += blackmisc + +LIBS += -lXPLM + +DEPENDPATH += . ../../../../src +INCLUDEPATH += . ../../../../src + +SOURCES += *.cpp +HEADERS += *.h + +#win32:!win32-g++*: PRE_TARGETDEPS += ../../../../lib/blackmisc.lib + + +# Required by X-Plane SDK +DEFINES += XPLM200=1 +win32:DEFINES += IBM +linux:DEFINES += LIN +macx:DEFINES += APL + +# X-Plane plugins must follow a prescribed filename and directory structure. +# CPU architecture detection copied from externals.pri; +# TODO: refactor so detection is is done in only one place. +TARGET_EXT = .xpl +win32:TARGET = win +linux:TARGET = lin +macx:TARGET = mac +win32:contains(QMAKE_TARGET.arch, x86_64) { + DESTDIR = ../../../../xbus/64 +} +win32:contains(QMAKE_TARGET.arch, x86) { + DESTDIR = ../../../../xbus/32 +} +win32-g++ { + WIN_FIND = $$(SYSTEMROOT)\system32\find + MINGW64 = $$system($$QMAKE_CXX -Q --help=target | $$WIN_FIND \"-m64\") + contains(MINGW64,[enabled]) { + DESTDIR = ../../../../xbus/64 + } + else { + DESTDIR = ../../../../xbus/32 + } +} +linux-g++ { + GCC64 = $$system($$QMAKE_CXX -Q --help=target | grep m64) + contains(GCC64,[enabled]) { + DESTDIR = ../../../../xbus/64 + } + else { + DESTDIR = ../../../../xbus/32 + } +} +linux-g++-64 { + DESTDIR = ../../../../xbus/64 +} +linux-g++-32 { + DESTDIR = ../../../../xbus/32 +} +macx { + # a single dylib file contains both 32bit and 64bit binaries + DESTDIR = ../../../../xbus +} + +include (../../../../libraries.pri)