OpenCPN Partial API docs
Loading...
Searching...
No Matches
dbus_server.cpp
Go to the documentation of this file.
1/***************************************************************************
2 * Copyright (C) 2023 Alec Leamas *
3 * *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
8 * *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program; if not, write to the *
16 * Free Software Foundation, Inc., *
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
18 ***************************************************************************/
19
30#include <iostream> // Debug junk
31#include <chrono>
32#include <thread>
33
34#include "model/dbus_server.h"
35#include "model/logger.h"
36
38struct DbusCtx {
39 GMainLoop* loop;
40 DbusServer* handler;
41 DbusCtx(GMainLoop* l, DbusServer* h) : loop(l), handler(h) {}
42};
43
44static const GDBusInterfaceVTable interface_vtable = {HandleMethodCall};
45
52static gpointer static_user_data = 0;
53
54static void OnNameAcquired(GDBusConnection*, const gchar* /* name */,
55 gpointer user_data) {
56 DEBUG_LOG << "OnNameAcquired";
57 auto ctx = static_cast<DbusCtx*>(user_data);
58 ctx->handler->SetMainInstance(true);
59}
60
61static void OnNameReleased(GDBusConnection*, const gchar* /* name */,
62 gpointer user_data) {
63 auto ctx = static_cast<DbusCtx*>(user_data);
64 ctx->handler->SetMainInstance(false);
65}
66
68static void OnBusAcquired(GDBusConnection* connection, const gchar* /* name */,
69 gpointer user_data) {
70 DEBUG_LOG << "OnBusAcquired";
71 auto ctx = static_cast<DbusCtx*>(user_data);
72 g_dbus_connection_register_object(
73 connection, kDbusObject, ctx->handler->introspection_data->interfaces[0],
74 &interface_vtable, user_data, 0 /* user_data_free_func */, 0);
75}
76
77static void HandleMethodCall(GDBusConnection*, const gchar* /* sender */,
78 const gchar* /* Object path */,
79 const gchar* /* interface name */,
80 const gchar* method_name, GVariant* parameters,
81 GDBusMethodInvocation* invocation,
82 gpointer /* user_data */) {
83 // gpointer udata = g_dbus_method_invocation_get_user_data(invocation);
84 auto ctx = static_cast<DbusCtx*>(static_user_data);
85 if (0 == g_strcmp0(method_name, "Ping")) {
86 GVariant* args[2];
87 args[0] = g_variant_new_uint32(21614);
88 args[1] = g_variant_new_boolean(true);
89 g_dbus_method_invocation_return_value(invocation,
90 g_variant_new_tuple(args, 2));
91 } else if (0 == g_strcmp0(method_name, "Raise")) {
92 if (ctx) ctx->handler->on_raise.Notify();
93 g_dbus_method_invocation_return_value(invocation, 0);
94 } else if (0 == g_strcmp0(method_name, "Quit")) {
95 if (ctx) ctx->handler->on_quit.Notify();
96 g_dbus_method_invocation_return_value(invocation, 0);
97 } else if (ctx && 0 == g_strcmp0(method_name, "Open")) {
98 const gchar* path;
99 g_variant_get(parameters, "(&s)", &path);
100 bool ok = ctx->handler->open_file_cb(std::string(path));
101 GVariant* params[1];
102 params[0] = g_variant_new_boolean(ok);
103 g_dbus_method_invocation_return_value(invocation,
104 g_variant_new_tuple(params, 1));
105
106 } else if (ctx && g_strcmp0(method_name, "GetRestEndpoint") == 0) {
107 GVariant* params[1];
108 params[0] =
109 g_variant_new_string(ctx->handler->get_rest_api_endpoint_cb().c_str());
110 g_dbus_method_invocation_return_value(invocation,
111 g_variant_new_tuple(params, 1));
112 }
113}
114
115DbusServer* DbusServer::s_instance = nullptr;
116
117DbusServer& DbusServer::GetInstance() {
118 if (!s_instance) s_instance = new DbusServer();
119 return *s_instance;
120}
121
123 delete s_instance;
124 s_instance = nullptr;
125}
126
127DbusServer::DbusServer()
128 : LocalServerApi(),
129 introspection_data(0),
130 m_is_main_instance(false),
131 m_owner_id(0) {
132 introspection_data = g_dbus_node_info_new_for_xml(introspection_xml, 0);
133 g_assert(introspection_data != 0);
134
135 auto flags = static_cast<GBusNameOwnerFlags>(
136 G_BUS_NAME_OWNER_FLAGS_NONE | G_BUS_NAME_OWNER_FLAGS_DO_NOT_QUEUE);
137
138 auto ctx = new DbusCtx(0, this);
139 auto deleter = [](gpointer p) { delete static_cast<DbusCtx*>(p); };
140 static_user_data = ctx;
141 m_owner_id =
142 g_bus_own_name(G_BUS_TYPE_SESSION, kDbusName, flags, OnBusAcquired,
143 OnNameAcquired, OnNameReleased, ctx, deleter);
144 DEBUG_LOG << "DbusServer::DbusServer, m_owner_id: " << m_owner_id;
145}
146
147DbusServer::~DbusServer() {
148 if (m_owner_id) g_bus_unown_name(m_owner_id);
149 m_owner_id = 0;
150 g_dbus_node_info_unref(introspection_data);
151}
152
154 using namespace std::literals::chrono_literals;
155 int i = 0;
156 do {
157 wxYield();
158 std::this_thread::sleep_for(5ms);
159 } while (!m_is_main_instance && i++ < 200);
160 wxYield();
161}
Basic interface to low-level DBus library.
Definition dbus_server.h:92
GDBusNodeInfo * introspection_data
Callback context.
static void Disconnect()
Clear current singleton instance and disconnect from session bus.
void WaitUntilValid() override
Wait until ready.
Base interface for local server command handling.
Definition local_api.h:61
DBus interface header file.
Enhanced logging interface on top of wx/log.h.
Event handler context.