Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-3.0-or-later
2 : : // SPDX-FileCopyrightText: Andy Holmes <andrew.g.r.holmes@gmail.com>
3 : :
4 : : #define G_LOG_DOMAIN "valent-presenter-plugin"
5 : :
6 : : #include "config.h"
7 : :
8 : : #include <glib/gi18n.h>
9 : : #include <gio/gio.h>
10 : : #include <json-glib/json-glib.h>
11 : : #include <valent.h>
12 : :
13 : : #include "valent-presenter-plugin.h"
14 : :
15 : :
16 : : struct _ValentPresenterPlugin
17 : : {
18 : : ValentDevicePlugin parent_instance;
19 : :
20 : : ValentInputAdapter *local_adapter;
21 : : unsigned int local_state : 1;
22 : : };
23 : :
24 [ + + + - ]: 47 : G_DEFINE_FINAL_TYPE (ValentPresenterPlugin, valent_presenter_plugin, VALENT_TYPE_DEVICE_PLUGIN)
25 : :
26 : : static void
27 : 4 : on_primary_adapter_changed (ValentComponent *component,
28 : : GParamSpec *pspec,
29 : : ValentPresenterPlugin *self)
30 : : {
31 [ - + ]: 4 : g_assert (VALENT_IS_INPUT (component));
32 [ + - ]: 4 : g_assert (VALENT_IS_PRESENTER_PLUGIN (self));
33 : :
34 [ - + ]: 4 : g_clear_object (&self->local_adapter);
35 : 4 : g_object_get (component, "primary-adapter", &self->local_adapter, NULL);
36 : 4 : }
37 : :
38 : : static void
39 : 16 : valent_presenter_plugin_watch_local_state (ValentPresenterPlugin *self,
40 : : gboolean watch)
41 : : {
42 : 16 : ValentInput *input = valent_input_get_default ();
43 : :
44 [ - + ]: 16 : g_assert (VALENT_IS_PRESENTER_PLUGIN (self));
45 : :
46 [ + + ]: 16 : if (self->local_state == watch)
47 : : return;
48 : :
49 [ + + ]: 8 : if (watch)
50 : : {
51 : 4 : g_signal_connect_object (input,
52 : : "notify::primary-adapter",
53 : : G_CALLBACK (on_primary_adapter_changed),
54 : : self,
55 : : G_CONNECT_DEFAULT);
56 : 4 : on_primary_adapter_changed (VALENT_COMPONENT (input), NULL, self);
57 : 4 : self->local_state = TRUE;
58 : : }
59 : : else
60 : : {
61 : 4 : g_signal_handlers_disconnect_by_data (input, self);
62 : 4 : self->local_state = FALSE;
63 : : }
64 : : }
65 : :
66 : : static void
67 : 2 : valent_presenter_plugin_handle_presenter (ValentPresenterPlugin *self,
68 : : JsonNode *packet)
69 : : {
70 : 2 : double dx, dy;
71 : 2 : gboolean stop;
72 : :
73 [ - + ]: 2 : g_assert (VALENT_IS_PRESENTER_PLUGIN (self));
74 [ + - ]: 2 : g_assert (VALENT_IS_PACKET (packet));
75 : :
76 : : /* NOTE: these are gyroscope motion deltas, but they're translated to pointer
77 : : * deltas due to lack of a virtual "laser pointer". */
78 [ + - + - ]: 4 : if (valent_packet_get_double (packet, "dx", &dx) &&
79 : 2 : valent_packet_get_double (packet, "dy", &dy))
80 : : {
81 [ - + ]: 2 : if (self->local_adapter == NULL)
82 : : {
83 : 0 : g_warning ("%s(): No input adapter available", G_STRFUNC);
84 : 2 : return;
85 : : }
86 : :
87 : 2 : valent_input_adapter_pointer_motion (self->local_adapter, dx * 1000, dy * 1000);
88 : 2 : return;
89 : : }
90 : :
91 : : /* NOTE: this signifies that no more gyroscope deltas are incoming, so the
92 : : * "laser pointer" can be turned off. */
93 [ # # ]: 0 : if (valent_packet_get_boolean (packet, "stop", &stop))
94 : : {
95 : : VALENT_NOTE ("The \"stop\" field is not supported");
96 : : return;
97 : : }
98 : : }
99 : :
100 : : static void
101 : 1 : valent_presenter_plugin_send_motion (ValentPresenterPlugin *self,
102 : : double dx,
103 : : double dy)
104 : : {
105 : 2 : g_autoptr (JsonBuilder) builder = NULL;
106 [ - + ]: 1 : g_autoptr (JsonNode) packet = NULL;
107 : :
108 [ - + ]: 1 : g_assert (VALENT_IS_PRESENTER_PLUGIN (self));
109 : :
110 : 1 : valent_packet_init (&builder, "kdeconnect.presenter");
111 : 1 : json_builder_set_member_name (builder, "dx");
112 : 1 : json_builder_add_double_value (builder, dx);
113 : 1 : json_builder_set_member_name (builder, "dy");
114 : 1 : json_builder_add_double_value (builder, dy);
115 : 1 : packet = valent_packet_end (&builder);
116 : :
117 [ + - ]: 1 : valent_device_plugin_queue_packet (VALENT_DEVICE_PLUGIN (self), packet);
118 : 1 : }
119 : :
120 : : static void
121 : 1 : valent_presenter_plugin_send_stop (ValentPresenterPlugin *self)
122 : : {
123 : 2 : g_autoptr (JsonBuilder) builder = NULL;
124 [ - + ]: 1 : g_autoptr (JsonNode) packet = NULL;
125 : :
126 [ - + ]: 1 : g_assert (VALENT_IS_PRESENTER_PLUGIN (self));
127 : :
128 : 1 : valent_packet_init (&builder, "kdeconnect.presenter");
129 : 1 : json_builder_set_member_name (builder, "stop");
130 : 1 : json_builder_add_boolean_value (builder, TRUE);
131 : 1 : packet = valent_packet_end (&builder);
132 : :
133 [ + - ]: 1 : valent_device_plugin_queue_packet (VALENT_DEVICE_PLUGIN (self), packet);
134 : 1 : }
135 : :
136 : : /*
137 : : * GActions
138 : : */
139 : : static void
140 : 8 : valent_presenter_plugin_toggle_actions (ValentPresenterPlugin *self,
141 : : gboolean available)
142 : : {
143 : 8 : GAction *action;
144 : :
145 [ - + ]: 8 : g_assert (VALENT_IS_PRESENTER_PLUGIN (self));
146 : :
147 : 8 : action = g_action_map_lookup_action (G_ACTION_MAP (self), "pointer");
148 : 8 : g_simple_action_set_enabled (G_SIMPLE_ACTION (action), available);
149 : 8 : }
150 : :
151 : : static void
152 : 2 : presenter_pointer_action (GSimpleAction *action,
153 : : GVariant *parameter,
154 : : gpointer user_data)
155 : : {
156 : 2 : ValentPresenterPlugin *self = VALENT_PRESENTER_PLUGIN (user_data);
157 : 2 : double dx = 0.0;
158 : 2 : double dy = 0.0;
159 : 2 : unsigned int mask = 0;
160 : :
161 [ - + ]: 2 : g_assert (VALENT_IS_PRESENTER_PLUGIN (self));
162 : :
163 : 2 : g_variant_get (parameter, "(ddu)", &dx, &dy, &mask);
164 : :
165 [ + + - + : 2 : if (!G_APPROX_VALUE (dx, 0.0, 0.01) || !G_APPROX_VALUE (dy, 0.0, 0.01))
+ - - + -
- - + ]
166 : 1 : valent_presenter_plugin_send_motion (self, dx, dy);
167 : :
168 [ + + ]: 2 : if (mask != 0)
169 : 1 : valent_presenter_plugin_send_stop (self);
170 : 2 : }
171 : :
172 : : static const GActionEntry actions[] = {
173 : : {"pointer", presenter_pointer_action, "(ddu)", NULL, NULL}
174 : : };
175 : :
176 : : /*
177 : : * ValentDevicePlugin
178 : : */
179 : : static void
180 : 8 : valent_presenter_plugin_update_state (ValentDevicePlugin *plugin,
181 : : ValentDeviceState state)
182 : : {
183 : 8 : ValentPresenterPlugin *self = VALENT_PRESENTER_PLUGIN (plugin);
184 : :
185 : 8 : gboolean available;
186 : :
187 [ - + ]: 8 : g_assert (VALENT_IS_PRESENTER_PLUGIN (self));
188 : :
189 [ + + ]: 8 : available = (state & VALENT_DEVICE_STATE_CONNECTED) != 0 &&
190 [ - + ]: 4 : (state & VALENT_DEVICE_STATE_PAIRED) != 0;
191 : :
192 : 8 : valent_presenter_plugin_watch_local_state (self, available);
193 : 8 : valent_presenter_plugin_toggle_actions (self, available);
194 : 8 : }
195 : :
196 : : static void
197 : 2 : valent_presenter_plugin_handle_packet (ValentDevicePlugin *plugin,
198 : : const char *type,
199 : : JsonNode *packet)
200 : : {
201 : 2 : ValentPresenterPlugin *self = VALENT_PRESENTER_PLUGIN (plugin);
202 : :
203 [ - + ]: 2 : g_assert (VALENT_IS_PRESENTER_PLUGIN (self));
204 [ + - ]: 2 : g_assert (type != NULL);
205 [ + - ]: 2 : g_assert (VALENT_IS_PACKET (packet));
206 : :
207 [ + - ]: 2 : if (g_str_equal (type, "kdeconnect.presenter"))
208 : 2 : valent_presenter_plugin_handle_presenter (self, packet);
209 : : else
210 : 2 : g_assert_not_reached ();
211 : 2 : }
212 : :
213 : : /*
214 : : * ValentObject
215 : : */
216 : : static void
217 : 8 : valent_presenter_plugin_destroy (ValentObject *object)
218 : : {
219 : 8 : ValentPresenterPlugin *self = VALENT_PRESENTER_PLUGIN (object);
220 : :
221 : 8 : valent_presenter_plugin_watch_local_state (self, FALSE);
222 : :
223 : 8 : VALENT_OBJECT_CLASS (valent_presenter_plugin_parent_class)->destroy (object);
224 : 8 : }
225 : :
226 : : /*
227 : : * GObject
228 : : */
229 : : static void
230 : 4 : valent_presenter_plugin_constructed (GObject *object)
231 : : {
232 : 4 : ValentDevicePlugin *plugin = VALENT_DEVICE_PLUGIN (object);
233 : :
234 : 4 : G_OBJECT_CLASS (valent_presenter_plugin_parent_class)->constructed (object);
235 : :
236 : 4 : g_action_map_add_action_entries (G_ACTION_MAP (plugin),
237 : : actions,
238 : : G_N_ELEMENTS (actions),
239 : : plugin);
240 : 4 : }
241 : :
242 : : static void
243 : 1 : valent_presenter_plugin_class_init (ValentPresenterPluginClass *klass)
244 : : {
245 : 1 : GObjectClass *object_class = G_OBJECT_CLASS (klass);
246 : 1 : ValentObjectClass *vobject_class = VALENT_OBJECT_CLASS (klass);
247 : 1 : ValentDevicePluginClass *plugin_class = VALENT_DEVICE_PLUGIN_CLASS (klass);
248 : :
249 : 1 : object_class->constructed = valent_presenter_plugin_constructed;
250 : :
251 : 1 : vobject_class->destroy = valent_presenter_plugin_destroy;
252 : :
253 : 1 : plugin_class->handle_packet = valent_presenter_plugin_handle_packet;
254 : 1 : plugin_class->update_state = valent_presenter_plugin_update_state;
255 : : }
256 : :
257 : : static void
258 : 4 : valent_presenter_plugin_init (ValentPresenterPlugin *self)
259 : : {
260 : 4 : }
261 : :
|