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, see <https://www.gnu.org/licenses/>. *
16 ***************************************************************************/
17
28#include <chrono>
29#include <thread>
30
31#include "model/dbus_server.h"
32#include "model/logger.h"
33
35struct DbusCtx {
36 GMainLoop* loop;
37 DbusServer* handler;
38 DbusCtx(GMainLoop* l, DbusServer* h) : loop(l), handler(h) {}
39};
40
41static const GDBusInterfaceVTable interface_vtable = {HandleMethodCall};
42
49static gpointer static_user_data = 0;
50
51static void OnNameAcquired(GDBusConnection*, const gchar* /* name */,
52 gpointer user_data) {
53 DEBUG_LOG << "OnNameAcquired";
54 auto ctx = static_cast<DbusCtx*>(user_data);
55 ctx->handler->SetMainInstance(true);
56}
57
58static void OnNameReleased(GDBusConnection*, const gchar* /* name */,
59 gpointer user_data) {
60 auto ctx = static_cast<DbusCtx*>(user_data);
61 ctx->handler->SetMainInstance(false);
62}
63
65static void OnBusAcquired(GDBusConnection* connection, const gchar* /* name */,
66 gpointer user_data) {
67 DEBUG_LOG << "OnBusAcquired";
68 auto ctx = static_cast<DbusCtx*>(user_data);
69 g_dbus_connection_register_object(
70 connection, kDbusObject, ctx->handler->introspection_data->interfaces[0],
71 &interface_vtable, user_data, 0 /* user_data_free_func */, 0);
72}
73
74static void HandleMethodCall(GDBusConnection*, const gchar* /* sender */,
75 const gchar* /* Object path */,
76 const gchar* /* interface name */,
77 const gchar* method_name, GVariant* parameters,
78 GDBusMethodInvocation* invocation,
79 gpointer /* user_data */) {
80 // gpointer udata = g_dbus_method_invocation_get_user_data(invocation);
81 auto ctx = static_cast<DbusCtx*>(static_user_data);
82 if (0 == g_strcmp0(method_name, "Ping")) {
83 GVariant* args[2];
84 args[0] = g_variant_new_uint32(21614);
85 args[1] = g_variant_new_boolean(true);
86 g_dbus_method_invocation_return_value(invocation,
87 g_variant_new_tuple(args, 2));
88 } else if (0 == g_strcmp0(method_name, "Raise")) {
89 if (ctx) ctx->handler->on_raise.Notify();
90 g_dbus_method_invocation_return_value(invocation, 0);
91 } else if (0 == g_strcmp0(method_name, "Quit")) {
92 if (ctx) ctx->handler->on_quit.Notify();
93 g_dbus_method_invocation_return_value(invocation, 0);
94 } else if (ctx && 0 == g_strcmp0(method_name, "Open")) {
95 const gchar* path;
96 g_variant_get(parameters, "(&s)", &path);
97 bool ok = ctx->handler->open_file_cb(std::string(path));
98 GVariant* params[1];
99 params[0] = g_variant_new_boolean(ok);
100 g_dbus_method_invocation_return_value(invocation,
101 g_variant_new_tuple(params, 1));
102
103 } else if (ctx && g_strcmp0(method_name, "GetRestEndpoint") == 0) {
104 GVariant* params[1];
105 params[0] =
106 g_variant_new_string(ctx->handler->get_rest_api_endpoint_cb().c_str());
107 g_dbus_method_invocation_return_value(invocation,
108 g_variant_new_tuple(params, 1));
109 }
110}
111
112DbusServer* DbusServer::s_instance = nullptr;
113
114DbusServer& DbusServer::GetInstance() {
115 if (!s_instance) s_instance = new DbusServer();
116 return *s_instance;
117}
118
120 delete s_instance;
121 s_instance = nullptr;
122}
123
124DbusServer::DbusServer()
125 : LocalServerApi(),
126 introspection_data(0),
127 m_is_main_instance(false),
128 m_owner_id(0) {
129 introspection_data = g_dbus_node_info_new_for_xml(introspection_xml, 0);
130 g_assert(introspection_data != 0);
131
132 auto flags = static_cast<GBusNameOwnerFlags>(
133 G_BUS_NAME_OWNER_FLAGS_NONE | G_BUS_NAME_OWNER_FLAGS_DO_NOT_QUEUE);
134
135 auto ctx = new DbusCtx(0, this);
136 auto deleter = [](gpointer p) { delete static_cast<DbusCtx*>(p); };
137 static_user_data = ctx;
138 m_owner_id =
139 g_bus_own_name(G_BUS_TYPE_SESSION, kDbusName, flags, OnBusAcquired,
140 OnNameAcquired, OnNameReleased, ctx, deleter);
141 DEBUG_LOG << "DbusServer::DbusServer, m_owner_id: " << m_owner_id;
142}
143
144DbusServer::~DbusServer() {
145 if (m_owner_id) g_bus_unown_name(m_owner_id);
146 m_owner_id = 0;
147 g_dbus_node_info_unref(introspection_data);
148}
149
151 using namespace std::literals::chrono_literals;
152 int i = 0;
153 do {
154 wxYield();
155 std::this_thread::sleep_for(5ms);
156 } while (!m_is_main_instance && i++ < 200);
157 wxYield();
158}
Basic interface to low-level DBus library.
Definition dbus_server.h:91
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:63
DBus interface header file.
Enhanced logging interface on top of wx/log.h.
Event handler context.