OpenCPN Partial API docs
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 
38 struct DbusCtx {
39  GMainLoop* loop;
40  DbusServer* handler;
41  DbusCtx(GMainLoop* l, DbusServer* h) : loop(l), handler(h) {}
42 };
43 
44 static const GDBusInterfaceVTable interface_vtable = {HandleMethodCall};
45 
52 static gpointer static_user_data = 0;
53 
54 static 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 
61 static 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 
68 static 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 
77 static 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 
115 DbusServer* DbusServer::s_instance = nullptr;
116 
117 DbusServer& 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 
127 DbusServer::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 = g_bus_own_name(G_BUS_TYPE_SESSION, kDbusName, flags,
142  OnBusAcquired, OnNameAcquired, OnNameReleased,
143  ctx, deleter);
144  DEBUG_LOG << "DbusServer::DbusServer, m_owner_id: " << m_owner_id;
145 }
146 
147 DbusServer::~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 
153 
155  using namespace std::literals::chrono_literals;
156  int i = 0;
157  do {
158  wxYield();
159  std::this_thread::sleep_for(5ms);
160  } while (!m_is_main_instance && i++ < 200);
161  wxYield();
162 }
Basic interface to low-level DBus library.
Definition: dbus_server.h:94
GDBusNodeInfo * introspection_data
Callback context.
Definition: dbus_server.h:123
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:62
DBus interface header file.
Event handler context.
Definition: dbus_server.cpp:38