1 /*
2 linphone, gtk-glade interface.
3 Copyright (C) 2015 Belledonne Communications <info@belledonne-communications.com>
4
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 */
19
20 #include "status_icon.h"
21 #include "linphone.h"
22
23 #ifdef HAVE_GTK_OSX
24 #include <gtkosxapplication.h>
25 #endif
26
27 #if !defined(_WIN32) && !defined(__APPLE__) && GLIB_CHECK_VERSION(2, 26, 0)
28 #define STATUS_NOTIFIER_IS_USABLE 1
29 #endif
30
31 #include "status_notifier.h"
32 #include <mediastreamer2/mscommon.h>
33
34 typedef struct __LinphoneStatusIconDesc _LinphoneStatusIconDesc;
35
36 static LinphoneStatusIcon *_linphone_status_icon_instance = NULL;
37 static const _LinphoneStatusIconDesc *_linphone_status_icon_selected_desc = NULL;
38 static GSList *_linphone_status_icon_impls = NULL;
39
40
41 struct _LinphoneStatusIconParams {
42 char *title;
43 char *desc;
44 GtkWidget *menu;
45 LinphoneStatusIconOnClickCallback on_click_cb;
46 void *user_data;
47 int ref;
48 };
49
linphone_status_icon_params_new(void)50 LinphoneStatusIconParams *linphone_status_icon_params_new(void) {
51 return g_new0(LinphoneStatusIconParams, 1);
52 }
53
linphone_status_icon_params_ref(LinphoneStatusIconParams * obj)54 LinphoneStatusIconParams *linphone_status_icon_params_ref(LinphoneStatusIconParams *obj) {
55 obj->ref++;
56 return obj;
57 }
58
linphone_status_icon_params_unref(LinphoneStatusIconParams * obj)59 void linphone_status_icon_params_unref(LinphoneStatusIconParams *obj) {
60 obj->ref--;
61 if(obj->ref < 0) {
62 if(obj->title) g_free(obj->title);
63 if(obj->menu) g_object_unref(obj->menu);
64 if(obj->desc) g_free(obj->desc);
65 g_free(obj);
66 }
67 }
68
linphone_status_icon_params_set_title(LinphoneStatusIconParams * obj,const char * title)69 void linphone_status_icon_params_set_title(LinphoneStatusIconParams *obj, const char *title) {
70 if(obj->title) g_free(obj->title);
71 if(title) obj->title = g_strdup(title);
72 else obj->title = NULL;
73 }
74
linphone_status_icon_params_set_description(LinphoneStatusIconParams * obj,const char * desc)75 void linphone_status_icon_params_set_description(LinphoneStatusIconParams *obj, const char *desc) {
76 if(obj->desc) g_free(obj->desc);
77 if(desc) obj->desc = g_strdup(desc);
78 else obj->desc = NULL;
79 }
80
linphone_status_icon_params_set_menu(LinphoneStatusIconParams * obj,GtkWidget * menu)81 void linphone_status_icon_params_set_menu(LinphoneStatusIconParams *obj, GtkWidget *menu) {
82 if(obj->menu) g_object_unref(obj->menu);
83 if(menu) obj->menu = g_object_ref_sink(menu);
84 else obj->menu = NULL;
85 }
86
linphone_status_icon_params_set_on_click_cb(LinphoneStatusIconParams * obj,LinphoneStatusIconOnClickCallback cb,void * user_data)87 void linphone_status_icon_params_set_on_click_cb(LinphoneStatusIconParams *obj, LinphoneStatusIconOnClickCallback cb, void *user_data) {
88 obj->on_click_cb = cb;
89 obj->user_data = user_data;
90 }
91
92
93 typedef void (*LinphoneStatusIconDescInitFunc)(LinphoneStatusIcon *obj);
94 typedef void (*LinphoneStatusIconDescUninitFunc)(LinphoneStatusIcon *obj);
95 typedef void (*LinphoneStatusIconDescStartFunc)(LinphoneStatusIcon *obj);
96 typedef void (*LinphoneStatusIconDescEnableBlinkingFunc)(LinphoneStatusIcon *obj, gboolean enable);
97 typedef void (*LinphoneStatusIconDescIsSupportedResultCb)(const _LinphoneStatusIconDesc *obj, gboolean result, void *user_data);
98 typedef gboolean (*LinphoneStatusIconDescIsSupportedFunc)(
99 const _LinphoneStatusIconDesc *desc,
100 gboolean *result,
101 LinphoneStatusIconDescIsSupportedResultCb cb,
102 void *user_data
103 );
104 typedef void (*LinphoneStatusIconDescFindResultCb)(const _LinphoneStatusIconDesc *desc, void *user_data);
105
106 struct __LinphoneStatusIconDesc {
107 const char *impl_name;
108 LinphoneStatusIconDescInitFunc init;
109 LinphoneStatusIconDescUninitFunc uninit;
110 LinphoneStatusIconDescStartFunc start;
111 LinphoneStatusIconDescEnableBlinkingFunc enable_blinking;
112 LinphoneStatusIconDescIsSupportedFunc is_supported;
113 };
114
_linphone_status_icon_desc_is_supported(const _LinphoneStatusIconDesc * desc,gboolean * result,LinphoneStatusIconDescIsSupportedResultCb cb,void * user_data)115 static gboolean _linphone_status_icon_desc_is_supported(
116 const _LinphoneStatusIconDesc *desc,
117 gboolean *result,
118 LinphoneStatusIconDescIsSupportedResultCb cb,
119 void *user_data) {
120
121 return desc->is_supported(desc, result, cb, user_data);
122 }
123
124 typedef struct {
125 GSList *i;
126 LinphoneStatusIconDescFindResultCb cb;
127 void *user_data;
128 } _LinphoneStatusIconDescSearchCtx;
129
_linphone_status_icon_desc_is_supported_result_cb(const _LinphoneStatusIconDesc * desc,gboolean result,_LinphoneStatusIconDescSearchCtx * ctx)130 static void _linphone_status_icon_desc_is_supported_result_cb(
131 const _LinphoneStatusIconDesc *desc,
132 gboolean result,
133 _LinphoneStatusIconDescSearchCtx *ctx) {
134
135 if(!result) {
136 ctx->i = g_slist_next(ctx->i);
137 for(; ctx->i; ctx->i = g_slist_next(ctx->i)) {
138 if(_linphone_status_icon_desc_is_supported(
139 (const _LinphoneStatusIconDesc *)g_slist_nth_data(ctx->i, 0),
140 &result,
141 (LinphoneStatusIconDescIsSupportedResultCb)_linphone_status_icon_desc_is_supported_result_cb,
142 ctx)) {
143
144 if(result) break;
145 } else return;
146 }
147 }
148
149 if(ctx->i) {
150 const _LinphoneStatusIconDesc *desc = (const _LinphoneStatusIconDesc *)g_slist_nth_data(ctx->i, 0);
151 ms_message("StatusIcon: found implementation: %s", desc->impl_name);
152 if(ctx->cb) ctx->cb(desc, ctx->user_data);
153 } else {
154 g_warning("StatusIcon: no implementation found");
155 }
156
157 g_free(ctx);
158 }
159
_linphone_status_icon_find_first_available_impl(const _LinphoneStatusIconDesc ** desc,LinphoneStatusIconDescFindResultCb cb,void * user_data)160 static gboolean _linphone_status_icon_find_first_available_impl(
161 const _LinphoneStatusIconDesc **desc,
162 LinphoneStatusIconDescFindResultCb cb,
163 void *user_data) {
164
165 gboolean result;
166 _LinphoneStatusIconDescSearchCtx *ctx = g_new0(_LinphoneStatusIconDescSearchCtx, 1);
167 ctx->cb = cb;
168 ctx->user_data = user_data;
169
170 ms_message("StatusIcon: looking for implementation...");
171
172 for(ctx->i=_linphone_status_icon_impls; ctx->i; ctx->i = g_slist_next(ctx->i)) {
173 if(_linphone_status_icon_desc_is_supported(
174 (const _LinphoneStatusIconDesc *)g_slist_nth_data(ctx->i, 0),
175 &result,
176 (LinphoneStatusIconDescIsSupportedResultCb)_linphone_status_icon_desc_is_supported_result_cb,
177 ctx)) {
178
179 if(result) {
180 *desc = (const _LinphoneStatusIconDesc *)g_slist_nth_data(ctx->i, 0);
181 ms_message("StatusIcon: found implementation: %s", (*desc)->impl_name);
182 goto sync_return;
183 }
184 } else {
185 return 0;
186 }
187 }
188 g_warning("StatusIcon: no implementation found");
189 *desc = NULL;
190
191 sync_return:
192 g_free(ctx);
193 return 1;
194 }
195
196
197 struct _LinphoneStatusIcon {
198 const _LinphoneStatusIconDesc *desc;
199 LinphoneStatusIconParams *params;
200 void *data;
201 };
202
_linphone_status_icon_new(const _LinphoneStatusIconDesc * desc)203 static LinphoneStatusIcon *_linphone_status_icon_new(const _LinphoneStatusIconDesc *desc) {
204 LinphoneStatusIcon *si = (LinphoneStatusIcon *)g_new0(LinphoneStatusIcon, 1);
205 si->desc = desc;
206 if(desc->init) desc->init(si);
207 return si;
208 }
209
_linphone_status_icon_free(LinphoneStatusIcon * obj)210 static void _linphone_status_icon_free(LinphoneStatusIcon *obj) {
211 if(obj->desc->uninit) obj->desc->uninit(obj);
212 if(obj->params) linphone_status_icon_params_unref(obj->params);
213 g_free(obj);
214 }
215
linphone_status_icon_get_implementation_name(const LinphoneStatusIcon * obj)216 const char *linphone_status_icon_get_implementation_name(const LinphoneStatusIcon *obj) {
217 return obj->desc->impl_name;
218 }
219
linphone_status_icon_start(LinphoneStatusIcon * obj,LinphoneStatusIconParams * params)220 void linphone_status_icon_start(LinphoneStatusIcon *obj, LinphoneStatusIconParams *params) {
221 ms_message("StatusIcon: starting status icon");
222 obj->params = linphone_status_icon_params_ref(params);
223 if(obj->desc->start) obj->desc->start(obj);
224 }
225
linphone_status_icon_enable_blinking(LinphoneStatusIcon * obj,gboolean enable)226 void linphone_status_icon_enable_blinking(LinphoneStatusIcon *obj, gboolean enable) {
227 ms_message("StatusIcon: blinking set to %s", enable ? "TRUE" : "FALSE");
228 if(obj->desc->enable_blinking) obj->desc->enable_blinking(obj, enable);
229 }
230
_linphone_status_icon_notify_click(LinphoneStatusIcon * obj)231 static void _linphone_status_icon_notify_click(LinphoneStatusIcon *obj) {
232 if(obj->params->on_click_cb) {
233 obj->params->on_click_cb(obj, obj->params->user_data);
234 }
235 }
236
237
_linphone_status_icon_init_cb(const _LinphoneStatusIconDesc * desc,void * user_data)238 void _linphone_status_icon_init_cb(const _LinphoneStatusIconDesc *desc, void *user_data) {
239 void **ctx = (void **)user_data;
240 LinphoneStatusIconReadyCb cb = (LinphoneStatusIconReadyCb)ctx[0];
241 _linphone_status_icon_selected_desc = desc;
242 if(cb) cb(ctx[1]);
243 g_free(ctx);
244 }
245
246 #ifdef STATUS_NOTIFIER_IS_USABLE
247 static const _LinphoneStatusIconDesc _linphone_status_icon_impl_status_notifier;
248 #endif
249 #ifdef HAVE_GTK_OSX
250 static const _LinphoneStatusIconDesc _linphone_status_icon_impl_gtkosx_app_desc;
251 #else
252 static const _LinphoneStatusIconDesc _linphone_status_icon_impl_gtk_desc;
253 #endif
254
_linphone_status_icon_create_implementations_list(void)255 void _linphone_status_icon_create_implementations_list(void) {
256 #ifdef STATUS_NOTIFIER_IS_USABLE
257 _linphone_status_icon_impls = g_slist_append(_linphone_status_icon_impls, (void *)&_linphone_status_icon_impl_status_notifier);
258 #endif
259 #if HAVE_GTK_OSX
260 _linphone_status_icon_impls = g_slist_append(_linphone_status_icon_impls, (void *)&_linphone_status_icon_impl_gtkosx_app_desc);
261 #else
262 _linphone_status_icon_impls = g_slist_append(_linphone_status_icon_impls, (void *)&_linphone_status_icon_impl_gtk_desc);
263 #endif
264 }
265
linphone_status_icon_init(LinphoneStatusIconReadyCb ready_cb,void * user_data)266 gboolean linphone_status_icon_init(LinphoneStatusIconReadyCb ready_cb, void *user_data) {
267 const _LinphoneStatusIconDesc *desc;
268 void **ctx;
269
270 ms_message("StatusIcon: Initialising");
271
272 _linphone_status_icon_create_implementations_list();
273
274 ctx = g_new(void *, 2);
275 ctx[0] = ready_cb;
276 ctx[1] = user_data;
277
278 if(_linphone_status_icon_find_first_available_impl(&desc, _linphone_status_icon_init_cb, ctx)) {
279 _linphone_status_icon_selected_desc = desc;
280 g_free(ctx);
281 return 1;
282 } else return 0;
283 }
284
linphone_status_icon_uninit(void)285 void linphone_status_icon_uninit(void) {
286 if(_linphone_status_icon_instance) {
287 _linphone_status_icon_free(_linphone_status_icon_instance);
288 _linphone_status_icon_instance = NULL;
289 }
290 if(_linphone_status_icon_impls) {
291 g_slist_free(_linphone_status_icon_impls);
292 _linphone_status_icon_impls = NULL;
293 }
294 _linphone_status_icon_selected_desc = NULL;
295 }
296
linphone_status_icon_get(void)297 LinphoneStatusIcon *linphone_status_icon_get(void) {
298 if(_linphone_status_icon_instance == NULL) {
299 if(_linphone_status_icon_selected_desc)
300 ms_message("StatusIcon: instanciating singleton");
301 _linphone_status_icon_instance = _linphone_status_icon_new(_linphone_status_icon_selected_desc);
302 }
303 return _linphone_status_icon_instance;
304 }
305
306
307 /* GtkStatusIcon implementation */
308 #ifndef HAVE_GTK_OSX
_linphone_status_icon_impl_gtk_on_click_cb(LinphoneStatusIcon * si)309 static void _linphone_status_icon_impl_gtk_on_click_cb(LinphoneStatusIcon *si) {
310 _linphone_status_icon_notify_click(si);
311 }
312
_linphone_status_icon_impl_gtk_popup_menu(GtkStatusIcon * status_icon,guint button,guint activate_time,LinphoneStatusIcon * si)313 static void _linphone_status_icon_impl_gtk_popup_menu(GtkStatusIcon *status_icon, guint button, guint activate_time, LinphoneStatusIcon *si){
314 GtkWidget *menu = si->params->menu;
315 gtk_menu_popup(GTK_MENU(menu),NULL,NULL,gtk_status_icon_position_menu,status_icon,button,activate_time);
316 }
317
_linphone_status_icon_impl_gtk_init(LinphoneStatusIcon * si)318 static void _linphone_status_icon_impl_gtk_init(LinphoneStatusIcon *si) {
319 const char *icon_name=linphone_gtk_get_ui_config("icon_name",LINPHONE_ICON_NAME);
320 const char *blinking_icon_name=linphone_gtk_get_ui_config("binking_status_icon_name","linphone-start-call");
321 GtkStatusIcon *icon=gtk_status_icon_new_from_icon_name(icon_name);
322 g_signal_connect_swapped(G_OBJECT(icon),"activate", G_CALLBACK(_linphone_status_icon_impl_gtk_on_click_cb), si);
323 g_signal_connect(G_OBJECT(icon), "popup-menu", G_CALLBACK(_linphone_status_icon_impl_gtk_popup_menu), si);
324 g_object_set_data_full(G_OBJECT(icon), "icon", g_strdup(icon_name), g_free);
325 g_object_set_data_full(G_OBJECT(icon), "call_icon", g_strdup(blinking_icon_name), g_free);
326 si->data = icon;
327 }
328
_linphone_status_icon_impl_gtk_uninit(LinphoneStatusIcon * si)329 static void _linphone_status_icon_impl_gtk_uninit(LinphoneStatusIcon *si) {
330 GtkStatusIcon *icon = GTK_STATUS_ICON(si->data);
331 gtk_status_icon_set_visible(icon, FALSE);
332 }
333
_linphone_status_icon_impl_gtk_start(LinphoneStatusIcon * si)334 static void _linphone_status_icon_impl_gtk_start(LinphoneStatusIcon *si) {
335 GtkStatusIcon *icon = GTK_STATUS_ICON(si->data);
336 #if GTK_CHECK_VERSION(2,20,2)
337 char *name = g_strdup_printf("%s - %s", si->params->title, si->params->desc);
338 gtk_status_icon_set_name(icon, name);
339 g_free(name);
340 #endif
341 gtk_status_icon_set_visible(icon,TRUE);
342 }
343
_linphone_status_icon_impl_gtk_do_icon_blink_cb(GtkStatusIcon * gi)344 static gboolean _linphone_status_icon_impl_gtk_do_icon_blink_cb(GtkStatusIcon *gi){
345 const gchar *call_icon = (const gchar *)g_object_get_data(G_OBJECT(gi),"call_icon");
346 const gchar *normal_icon = (const gchar *)g_object_get_data(G_OBJECT(gi),"icon");
347 const gchar *cur_icon = (const gchar *)gtk_status_icon_get_icon_name(gi);
348 if (cur_icon == call_icon){
349 gtk_status_icon_set_from_icon_name(gi,normal_icon);
350 }else{
351 gtk_status_icon_set_from_icon_name(gi,call_icon);
352 }
353 return TRUE;
354 }
355
_linphone_status_icon_impl_enable_blinking(LinphoneStatusIcon * si,gboolean val)356 static void _linphone_status_icon_impl_enable_blinking(LinphoneStatusIcon *si, gboolean val) {
357 GtkStatusIcon *icon = GTK_STATUS_ICON(si->data);
358 guint tout;
359 tout=(unsigned)GPOINTER_TO_INT(g_object_get_data(G_OBJECT(icon),"timeout"));
360 if (val && tout==0){
361 tout=g_timeout_add(500,(GSourceFunc)_linphone_status_icon_impl_gtk_do_icon_blink_cb,icon);
362 g_object_set_data(G_OBJECT(icon),"timeout",GINT_TO_POINTER(tout));
363 }else if (!val && tout!=0){
364 const gchar *normal_icon = (const gchar *)g_object_get_data(G_OBJECT(icon),"icon");
365 g_source_remove(tout);
366 g_object_set_data(G_OBJECT(icon),"timeout",NULL);
367 gtk_status_icon_set_from_icon_name(icon,normal_icon);
368 }
369 }
370
_linphone_status_icon_impl_is_supported(const _LinphoneStatusIconDesc * desc,gboolean * result,LinphoneStatusIconDescIsSupportedResultCb cb,void * user_data)371 static gboolean _linphone_status_icon_impl_is_supported(
372 const _LinphoneStatusIconDesc *desc,
373 gboolean *result,
374 LinphoneStatusIconDescIsSupportedResultCb cb,
375 void *user_data) {
376
377 *result = 1;
378 return 1;
379 }
380
381 static const _LinphoneStatusIconDesc _linphone_status_icon_impl_gtk_desc = {
382 "gtk_status_icon",
383 _linphone_status_icon_impl_gtk_init,
384 _linphone_status_icon_impl_gtk_uninit,
385 _linphone_status_icon_impl_gtk_start,
386 _linphone_status_icon_impl_enable_blinking,
387 _linphone_status_icon_impl_is_supported
388 };
389 #endif
390
391
392 /* GtkosxApplication implementation */
393 #ifdef HAVE_GTK_OSX
_linphone_status_icon_impl_gtkosx_app_enable_blinking(LinphoneStatusIcon * si,gboolean val)394 static void _linphone_status_icon_impl_gtkosx_app_enable_blinking(LinphoneStatusIcon *si, gboolean val) {
395 GtkosxApplication *theMacApp=gtkosx_application_get();
396 gint *attention_id = (gint *)&si->data;
397 if (val) {
398 *attention_id=gtkosx_application_attention_request(theMacApp, CRITICAL_REQUEST);
399 } else if (*attention_id != 0) {
400 gtkosx_application_cancel_attention_request(theMacApp, *attention_id);
401 *attention_id = 0;
402 }
403 }
404
_linphone_status_icon_impl_gtkosx_app_is_supported(const _LinphoneStatusIconDesc * desc,gboolean * result,LinphoneStatusIconDescIsSupportedResultCb cb,void * user_data)405 static gboolean _linphone_status_icon_impl_gtkosx_app_is_supported(
406 const _LinphoneStatusIconDesc *desc,
407 gboolean *result,
408 LinphoneStatusIconDescIsSupportedResultCb cb,
409 void *user_data) {
410
411 *result = 1;
412 return 1;
413 }
414
415 static const _LinphoneStatusIconDesc _linphone_status_icon_impl_gtkosx_app_desc = {
416 .impl_name = "gtkosx_application",
417 .init = NULL,
418 .uninit = NULL,
419 .start = NULL,
420 .enable_blinking = _linphone_status_icon_impl_gtkosx_app_enable_blinking,
421 .is_supported = _linphone_status_icon_impl_gtkosx_app_is_supported
422 };
423 #endif
424
425
426 /* Implementation based on the StatusNotifier Freedesktop standard */
427 #ifdef STATUS_NOTIFIER_IS_USABLE
428 typedef struct {
429 int x;
430 int y;
431 } _LinphoneStatusIconPosition;
432
_linphone_status_icon_impl_sn_init(LinphoneStatusIcon * si)433 static void _linphone_status_icon_impl_sn_init(LinphoneStatusIcon *si) {
434 si->data = bc_status_notifier_new();
435 }
436
437 // static void _linphone_status_icon_impl_sn_uninit(LinphoneStatusIcon *si) {
438 // bc_status_notifier_unref((BcStatusNotifier *)si->data);
439 // }
440
_linphone_status_icon_impl_sn_activated_cb(BcStatusNotifier * sn,int x,int y,void * user_data)441 static void _linphone_status_icon_impl_sn_activated_cb(BcStatusNotifier *sn, int x, int y, void *user_data) {
442 LinphoneStatusIcon *si = (LinphoneStatusIcon *)user_data;
443 _linphone_status_icon_notify_click(si);
444 }
445
_linphone_status_icon_impr_sn_get_position(GtkMenu * menu,int * x,int * y,gboolean * push_in,gpointer data)446 static void _linphone_status_icon_impr_sn_get_position(GtkMenu *menu, int *x, int *y, gboolean *push_in, gpointer data) {
447 _LinphoneStatusIconPosition *pos = (_LinphoneStatusIconPosition *)data;
448 *x = pos->x;
449 *y = pos->y;
450 *push_in = TRUE;
451 }
452
_linphone_status_icon_impl_sn_menu_called_cb(BcStatusNotifier * sn,int x,int y,void * user_data)453 static void _linphone_status_icon_impl_sn_menu_called_cb(BcStatusNotifier *sn, int x, int y, void *user_data) {
454 LinphoneStatusIcon *si = (LinphoneStatusIcon *)user_data;
455 GtkWidget *menu = si->params->menu;
456 _LinphoneStatusIconPosition pos = {x, y};
457 gtk_menu_popup(
458 GTK_MENU(menu),
459 NULL,
460 NULL,
461 _linphone_status_icon_impr_sn_get_position,
462 &pos,
463 0,
464 gtk_get_current_event_time()
465 );
466 }
467
_linphone_status_icon_impl_sn_start(LinphoneStatusIcon * si)468 static void _linphone_status_icon_impl_sn_start(LinphoneStatusIcon *si) {
469 BcStatusNotifier *sn = (BcStatusNotifier *)si->data;
470 BcStatusNotifierParams *params;
471 BcStatusNotifierToolTip *tooltip = bc_status_notifier_tool_tip_new("linphone", si->params->title, si->params->desc);
472 BcStatusNotifierSignalsVTable vtable = {NULL};
473
474 vtable.activate_called_cb = _linphone_status_icon_impl_sn_activated_cb;
475 vtable.context_menu_called_cb = _linphone_status_icon_impl_sn_menu_called_cb;
476
477 params = bc_status_notifier_params_new();
478 bc_status_notifier_params_set_dbus_prefix(params, "org.kde");
479 bc_status_notifier_params_set_category(params, BcStatusNotifierCategoryCommunications);
480 bc_status_notifier_params_set_id(params, "linphone");
481 bc_status_notifier_params_set_title(params, si->params->title);
482 bc_status_notifier_params_set_icon_name(params, "linphone");
483 bc_status_notifier_params_set_tool_tip(params, tooltip);
484 bc_status_notifier_params_set_vtable(params, &vtable, si);
485
486 bc_status_notifier_start(sn, params, NULL, NULL);
487
488 bc_status_notifier_tool_tip_unref(tooltip);
489 bc_status_notifier_params_unref(params);
490 }
491
_linphone_status_icon_impl_sn_enable_blinking(LinphoneStatusIcon * si,gboolean val)492 static void _linphone_status_icon_impl_sn_enable_blinking(LinphoneStatusIcon *si, gboolean val) {
493 BcStatusNotifier *sn = (BcStatusNotifier *)si->data;
494 if(val) {
495 bc_status_notifier_update_status(sn, BcStatusNotifierStatusNeedsAttention);
496 } else {
497 bc_status_notifier_update_status(sn, BcStatusNotifierStatusPassive);
498 }
499 }
500
_linphone_status_icon_impl_is_supported_cb(const char * prefix,gboolean result,void ** data)501 static void _linphone_status_icon_impl_is_supported_cb(const char *prefix, gboolean result, void **data) {
502 _LinphoneStatusIconDesc *desc = (_LinphoneStatusIconDesc *)data[0];
503 LinphoneStatusIconDescIsSupportedResultCb cb = (LinphoneStatusIconDescIsSupportedResultCb)data[1];
504 if(cb) cb(desc, result, data[2]);
505 g_free(data);
506 g_free(desc);
507 }
508
_linphone_status_icon_impl_sn_is_supported(const _LinphoneStatusIconDesc * desc,gboolean * result,LinphoneStatusIconDescIsSupportedResultCb cb,void * user_data)509 static gboolean _linphone_status_icon_impl_sn_is_supported(
510 const _LinphoneStatusIconDesc *desc,
511 gboolean *result,
512 LinphoneStatusIconDescIsSupportedResultCb cb,
513 void *user_data) {
514
515 _LinphoneStatusIconDesc *desc2;
516 void **data;
517 const char *desktop = g_getenv("XDG_CURRENT_DESKTOP");
518
519 if(desktop == NULL || g_strcmp0(desktop, "KDE") != 0) {
520 *result = FALSE;
521 return TRUE;
522 }
523
524 desc2 = g_new(_LinphoneStatusIconDesc, 1);
525 *desc2 = *desc;
526 data = g_new(void *, 3);
527 data[0] = desc2;
528 data[1] = cb;
529 data[2] = user_data;
530 bc_status_notifier_is_supported(
531 "org.kde",
532 (BcStatusNotifierSupportDetectionCb)_linphone_status_icon_impl_is_supported_cb,
533 data
534 );
535 return FALSE;
536 }
537
538 static const _LinphoneStatusIconDesc _linphone_status_icon_impl_status_notifier = {
539 .impl_name = "status_notifier",
540 .init = _linphone_status_icon_impl_sn_init,
541 .uninit = NULL,
542 .start = _linphone_status_icon_impl_sn_start,
543 .enable_blinking = _linphone_status_icon_impl_sn_enable_blinking,
544 .is_supported = _linphone_status_icon_impl_sn_is_supported
545 };
546 #endif
547