Commit 65834b0c authored by François Grisez's avatar François Grisez
Browse files

Merge branch 'dev_status_icon'

parents 04c7c090 a188779a
......@@ -64,6 +64,8 @@ set(SOURCE_FILES
main.c
propertybox.c
singleinstance.c
status_icon.c
status_notifier.c
support.c
update.c
utils.c
......
......@@ -55,6 +55,8 @@ linphone_SOURCES= \
config-fetching.c \
audio_assistant.c \
videowindow.c \
status_icon.c \
status_notifier.c \
linphone.h
if BUILD_WIZARD
linphone_SOURCES+= \
......
......@@ -55,6 +55,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include <locale.h>
#endif
#include "status_icon.h"
const char *this_program_ident_string="linphone_ident_string=" LINPHONE_VERSION;
......@@ -1496,15 +1497,6 @@ void linphone_gtk_link_to_website(GtkWidget *item){
linphone_gtk_open_browser(home);
}
#ifndef HAVE_GTK_OSX
static GtkStatusIcon *icon=NULL;
static void icon_popup_menu(GtkStatusIcon *status_icon, guint button, guint activate_time, gpointer user_data){
GtkWidget *menu=(GtkWidget*)g_object_get_data(G_OBJECT(status_icon),"menu");
gtk_menu_popup(GTK_MENU(menu),NULL,NULL,gtk_status_icon_position_menu,status_icon,button,activate_time);
}
static GtkWidget *create_icon_menu(){
GtkWidget *menu=gtk_menu_new();
GtkWidget *menu_item;
......@@ -1538,11 +1530,14 @@ static GtkWidget *create_icon_menu(){
return menu;
}
#ifndef HAVE_GTK_OSX
void linphone_gtk_save_main_window_position(GtkWindow* mw, GdkEvent *event, gpointer data){
gtk_window_get_position(GTK_WINDOW(mw), &main_window_x, &main_window_y);
}
#endif
static void handle_icon_click() {
static void handle_icon_click(LinphoneStatusIcon *si, void *user_data) {
#ifndef HAVE_GTK_OSX
GtkWidget *mw=linphone_gtk_get_main_window();
if (!gtk_window_is_active((GtkWindow*)mw)) {
if(!gtk_widget_is_drawable(mw)){
......@@ -1554,67 +1549,43 @@ static void handle_icon_click() {
linphone_gtk_save_main_window_position((GtkWindow*)mw, NULL, NULL);
gtk_widget_hide(mw);
}
#endif
}
static void linphone_gtk_init_status_icon(){
const char *icon_path=linphone_gtk_get_ui_config("icon",LINPHONE_ICON);
const char *call_icon_path=linphone_gtk_get_ui_config("start_call_icon","startcall-green.png");
GdkPixbuf *pbuf=create_pixbuf(icon_path);
GtkWidget *menu=create_icon_menu();
const char *title;
title=linphone_gtk_get_ui_config("title",_("Linphone - a video internet phone"));
icon=gtk_status_icon_new_from_pixbuf(pbuf);
#if GTK_CHECK_VERSION(2,20,2)
gtk_status_icon_set_name(icon,title);
#endif
g_signal_connect_swapped(G_OBJECT(icon),"activate",(GCallback)handle_icon_click,NULL);
g_signal_connect(G_OBJECT(icon),"popup-menu",(GCallback)icon_popup_menu,NULL);
gtk_status_icon_set_tooltip(icon,title);
gtk_status_icon_set_visible(icon,TRUE);
g_object_set_data(G_OBJECT(icon),"menu",menu);
g_object_weak_ref(G_OBJECT(icon),(GWeakNotify)gtk_widget_destroy,menu);
g_object_set_data(G_OBJECT(icon),"icon",pbuf);
g_object_weak_ref(G_OBJECT(icon),(GWeakNotify)g_object_unref,pbuf);
pbuf=create_pixbuf(call_icon_path);
g_object_set_data(G_OBJECT(icon),"call_icon",pbuf);
}
static gboolean do_icon_blink(GtkStatusIcon *gi){
GdkPixbuf *call_icon=g_object_get_data(G_OBJECT(gi),"call_icon");
GdkPixbuf *normal_icon=g_object_get_data(G_OBJECT(gi),"icon");
GdkPixbuf *cur_icon=gtk_status_icon_get_pixbuf(gi);
if (cur_icon==call_icon){
gtk_status_icon_set_from_pixbuf(gi,normal_icon);
}else{
gtk_status_icon_set_from_pixbuf(gi,call_icon);
static void linphone_gtk_status_icon_initialised_cb(LinphoneStatusIconParams *params) {
LinphoneStatusIcon *icon = linphone_status_icon_get();
if(icon) {
linphone_status_icon_start(icon, params);
}
linphone_status_icon_params_unref(params);
}
static void linphone_gtk_init_status_icon(void) {
GtkWidget *menu = create_icon_menu();
LinphoneStatusIconParams *params = linphone_status_icon_params_new();
linphone_status_icon_params_set_menu(params, menu);
linphone_status_icon_params_set_title(params, _("Linphone"));
linphone_status_icon_params_set_description(params, _("A video internet phone"));
linphone_status_icon_params_set_on_click_cb(params, handle_icon_click, NULL);
g_object_unref(G_OBJECT(menu));
if(linphone_status_icon_init(
(LinphoneStatusIconReadyCb)linphone_gtk_status_icon_initialised_cb,
params)) {
LinphoneStatusIcon *icon = linphone_status_icon_get();
if(icon) {
linphone_status_icon_start(icon, params);
}
linphone_status_icon_params_unref(params);
}
return TRUE;
}
#endif
void linphone_gtk_status_icon_set_blinking(gboolean val){
#ifdef HAVE_GTK_OSX
static gint attention_id;
GtkosxApplication *theMacApp=gtkosx_application_get();
if (val)
attention_id=gtkosx_application_attention_request(theMacApp,CRITICAL_REQUEST);
else gtkosx_application_cancel_attention_request(theMacApp,attention_id);
#else
if (icon!=NULL){
guint tout;
tout=(unsigned)GPOINTER_TO_INT(g_object_get_data(G_OBJECT(icon),"timeout"));
if (val && tout==0){
tout=g_timeout_add(500,(GSourceFunc)do_icon_blink,icon);
g_object_set_data(G_OBJECT(icon),"timeout",GINT_TO_POINTER(tout));
}else if (!val && tout!=0){
GdkPixbuf *normal_icon=g_object_get_data(G_OBJECT(icon),"icon");
g_source_remove(tout);
g_object_set_data(G_OBJECT(icon),"timeout",NULL);
gtk_status_icon_set_from_pixbuf(icon,normal_icon);
}
void linphone_gtk_status_icon_set_blinking(gboolean val) {
LinphoneStatusIcon *icon = linphone_status_icon_get();
if(icon) {
linphone_status_icon_enable_blinking(icon, val);
}
#endif
}
void linphone_gtk_options_activate(GtkWidget *item){
......@@ -2018,13 +1989,10 @@ static void linphone_gtk_quit(void){
quit_done=TRUE;
linphone_gtk_quit_core();
linphone_gtk_uninit_instance();
#ifndef HAVE_GTK_OSX
g_object_unref(icon);
icon=NULL;
#endif
#ifdef HAVE_NOTIFY
notify_uninit();
#endif
linphone_status_icon_uninit();
gtk_widget_destroy(the_ui);
the_ui=NULL;
gdk_threads_leave();
......@@ -2242,10 +2210,6 @@ core_start:
goto core_start;
}
if (config_file) g_free(config_file);
#ifndef HAVE_GTK_OSX
/*workaround a bug on win32 that makes status icon still present in the systray even after program exit.*/
if (icon) gtk_status_icon_set_visible(icon,FALSE);
#endif
free(progpath);
/*output a translated "hello" string to the terminal, which allows the builder to check that translations are working.*/
if (selftest){
......
/*
linphone, gtk-glade interface.
Copyright (C) 2015 Belledonne Communications <info@belledonne-communications.com>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "status_icon.h"
#include "linphone.h"
#ifdef HAVE_GTK_OSX
#include <gtkosxapplication.h>
#endif
#include "status_notifier.h"
typedef struct __LinphoneStatusIconDesc _LinphoneStatusIconDesc;
static LinphoneStatusIcon *_linphone_status_icon_instance = NULL;
static const _LinphoneStatusIconDesc *_linphone_status_icon_selected_desc = NULL;
static const _LinphoneStatusIconDesc *_linphone_status_icon_impls[];
struct _LinphoneStatusIconParams {
char *title;
char *desc;
GtkWidget *menu;
LinphoneStatusIconOnClickCallback on_click_cb;
void *user_data;
int ref;
};
LinphoneStatusIconParams *linphone_status_icon_params_new(void) {
return g_new0(LinphoneStatusIconParams, 1);
}
LinphoneStatusIconParams *linphone_status_icon_params_ref(LinphoneStatusIconParams *obj) {
obj->ref++;
return obj;
}
void linphone_status_icon_params_unref(LinphoneStatusIconParams *obj) {
obj->ref--;
if(obj->ref < 0) {
if(obj->title) g_free(obj->title);
if(obj->menu) g_object_unref(obj->menu);
g_free(obj);
}
}
void linphone_status_icon_params_set_title(LinphoneStatusIconParams *obj, const char *title) {
if(obj->title) g_free(obj->title);
if(title) obj->title = g_strdup(title);
else obj->title = NULL;
}
void linphone_status_icon_params_set_description(LinphoneStatusIconParams *obj, const char *desc) {
if(obj->desc) g_free(obj->desc);
if(desc) obj->desc = g_strdup(desc);
else obj->desc = NULL;
}
void linphone_status_icon_params_set_menu(LinphoneStatusIconParams *obj, GtkWidget *menu) {
if(obj->menu) g_object_unref(obj->menu);
if(menu) obj->menu = g_object_ref(menu);
else obj->menu = NULL;
}
void linphone_status_icon_params_set_on_click_cb(LinphoneStatusIconParams *obj, LinphoneStatusIconOnClickCallback cb, void *user_data) {
obj->on_click_cb = cb;
obj->user_data = user_data;
}
typedef void (*LinphoneStatusIconDescInitFunc)(LinphoneStatusIcon *obj);
typedef void (*LinphoneStatusIconDescUninitFunc)(LinphoneStatusIcon *obj);
typedef void (*LinphoneStatusIconDescStartFunc)(LinphoneStatusIcon *obj);
typedef void (*LinphoneStatusIconDescEnableBlinkingFunc)(LinphoneStatusIcon *obj, gboolean enable);
typedef void (*LinphoneStatusIconDescIsSupportedResultCb)(const _LinphoneStatusIconDesc *obj, gboolean result, void *user_data);
typedef gboolean (*LinphoneStatusIconDescIsSupportedFunc)(
const _LinphoneStatusIconDesc *desc,
gboolean *result,
LinphoneStatusIconDescIsSupportedResultCb cb,
void *user_data
);
typedef void (*LinphoneStatusIconDescFindResultCb)(const _LinphoneStatusIconDesc *desc, void *user_data);
struct __LinphoneStatusIconDesc {
const char *impl_name;
LinphoneStatusIconDescInitFunc init;
LinphoneStatusIconDescUninitFunc uninit;
LinphoneStatusIconDescStartFunc start;
LinphoneStatusIconDescEnableBlinkingFunc enable_blinking;
LinphoneStatusIconDescIsSupportedFunc is_supported;
};
static gboolean _linphone_status_icon_desc_is_supported(
const _LinphoneStatusIconDesc *desc,
gboolean *result,
LinphoneStatusIconDescIsSupportedResultCb cb,
void *user_data) {
return desc->is_supported(desc, result, cb, user_data);
}
typedef struct {
int i;
LinphoneStatusIconDescFindResultCb cb;
void *user_data;
} _LinphoneStatusIconDescSearchCtx;
static void _linphone_status_icon_desc_is_supprted_result_cb(
const _LinphoneStatusIconDesc *desc,
gboolean result,
_LinphoneStatusIconDescSearchCtx *ctx) {
if(!result) {
ctx->i++;
for(; _linphone_status_icon_impls[ctx->i]; ctx->i++) {
if(_linphone_status_icon_desc_is_supported(
_linphone_status_icon_impls[ctx->i],
&result,
(LinphoneStatusIconDescIsSupportedResultCb)_linphone_status_icon_desc_is_supprted_result_cb,
ctx)) {
if(result) break;
} else return;
}
}
if(ctx->cb) ctx->cb(_linphone_status_icon_impls[ctx->i], ctx->user_data);
g_free(ctx);
}
static gboolean _linphone_status_icon_find_first_available_impl(
const _LinphoneStatusIconDesc **desc,
LinphoneStatusIconDescFindResultCb cb,
void *user_data) {
gboolean result;
_LinphoneStatusIconDescSearchCtx *ctx = g_new0(_LinphoneStatusIconDescSearchCtx, 1);
ctx->cb = cb;
ctx->user_data = user_data;
for(ctx->i=0; _linphone_status_icon_impls[ctx->i]; ctx->i++) {
if(_linphone_status_icon_desc_is_supported(
_linphone_status_icon_impls[ctx->i],
&result,
(LinphoneStatusIconDescIsSupportedResultCb)_linphone_status_icon_desc_is_supprted_result_cb,
ctx)) {
if(result) {
*desc = _linphone_status_icon_impls[ctx->i];
goto sync_return;
}
} else {
return 0;
}
}
*desc = NULL;
sync_return:
g_free(ctx);
return 1;
}
struct _LinphoneStatusIcon {
const _LinphoneStatusIconDesc *desc;
LinphoneStatusIconParams *params;
void *data;
};
static LinphoneStatusIcon *_linphone_status_icon_new(const _LinphoneStatusIconDesc *desc) {
LinphoneStatusIcon *si = (LinphoneStatusIcon *)g_new0(LinphoneStatusIcon, 1);
si->desc = desc;
if(desc->init) desc->init(si);
return si;
}
static void _linphone_status_icon_free(LinphoneStatusIcon *obj) {
if(obj->desc->uninit) obj->desc->uninit(obj->data);
g_free(obj);
}
const char *linphone_status_icon_get_implementation_name(const LinphoneStatusIcon *obj) {
return obj->desc->impl_name;
}
void linphone_status_icon_start(LinphoneStatusIcon *obj, LinphoneStatusIconParams *params) {
obj->params = linphone_status_icon_params_ref(params);
obj->desc->start(obj);
}
void linphone_status_icon_enable_blinking(LinphoneStatusIcon *obj, gboolean enable) {
obj->desc->enable_blinking(obj, enable);
}
static void _linphone_status_icon_notify_click(LinphoneStatusIcon *obj) {
if(obj->params->on_click_cb) {
obj->params->on_click_cb(obj, obj->params->user_data);
}
}
void _linphone_status_icon_init_cb(const _LinphoneStatusIconDesc *desc, void *user_data) {
void **ctx = (void **)user_data;
LinphoneStatusIconReadyCb cb = (LinphoneStatusIconReadyCb)ctx[0];
_linphone_status_icon_selected_desc = desc;
if(cb) cb(ctx[1]);
g_free(ctx);
}
gboolean linphone_status_icon_init(LinphoneStatusIconReadyCb ready_cb, void *user_data) {
const _LinphoneStatusIconDesc *desc;
void **ctx = g_new(void *, 2);
ctx[0] = ready_cb;
ctx[1] = user_data;
if(_linphone_status_icon_find_first_available_impl(&desc, _linphone_status_icon_init_cb, ctx)) {
_linphone_status_icon_selected_desc = desc;
g_free(ctx);
return 1;
} else return 0;
}
void linphone_status_icon_uninit(void) {
if(_linphone_status_icon_instance) _linphone_status_icon_free(_linphone_status_icon_instance);
}
LinphoneStatusIcon *linphone_status_icon_get(void) {
if(_linphone_status_icon_instance == NULL) {
if(_linphone_status_icon_selected_desc)
_linphone_status_icon_instance = _linphone_status_icon_new(_linphone_status_icon_selected_desc);
}
return _linphone_status_icon_instance;
}
/* GtkStatusIcon implementation */
#ifndef HAVE_GTK_OSX
static void _linphone_status_icon_impl_gtk_on_click_cb(LinphoneStatusIcon *si) {
_linphone_status_icon_notify_click(si);
}
static void _linphone_status_icon_impl_gtk_popup_menu(GtkStatusIcon *status_icon, guint button, guint activate_time, LinphoneStatusIcon *si){
GtkWidget *menu = si->params->menu;
gtk_menu_popup(GTK_MENU(menu),NULL,NULL,gtk_status_icon_position_menu,status_icon,button,activate_time);
}
static void _linphone_status_icon_impl_gtk_init(LinphoneStatusIcon *si) {
const char *icon_path=linphone_gtk_get_ui_config("icon",LINPHONE_ICON);
const char *call_icon_path=linphone_gtk_get_ui_config("start_call_icon","startcall-green.png");
GdkPixbuf *pbuf=create_pixbuf(icon_path);
GtkStatusIcon *icon=gtk_status_icon_new_from_pixbuf(pbuf);
g_signal_connect_swapped(G_OBJECT(icon),"activate", G_CALLBACK(_linphone_status_icon_impl_gtk_on_click_cb), si);
g_signal_connect(G_OBJECT(icon), "popup-menu", G_CALLBACK(_linphone_status_icon_impl_gtk_popup_menu), si);
g_object_set_data(G_OBJECT(icon),"icon",pbuf);
g_object_unref(pbuf);
pbuf=create_pixbuf(call_icon_path);
g_object_set_data(G_OBJECT(icon),"call_icon",pbuf);
g_object_unref(pbuf);
si->data = icon;
}
// static void _linphone_status_icon_impl_gtk_uninit(LinphoneStatusIcon *si) {
// g_object_unref((GtkStatusIcon *)si->data);
// }
static void _linphone_status_icon_impl_gtk_start(LinphoneStatusIcon *si) {
GtkStatusIcon *icon = GTK_STATUS_ICON(si->data);
#if GTK_CHECK_VERSION(2,20,2)
char *name = g_strdup_printf("%s - %s", si->params->title, si->params->desc);
gtk_status_icon_set_name(icon, name);
g_free(name);
#endif
gtk_status_icon_set_visible(icon,TRUE);
}
static gboolean _linphone_status_icon_impl_gtk_do_icon_blink_cb(GtkStatusIcon *gi){
GdkPixbuf *call_icon=g_object_get_data(G_OBJECT(gi),"call_icon");
GdkPixbuf *normal_icon=g_object_get_data(G_OBJECT(gi),"icon");
GdkPixbuf *cur_icon=gtk_status_icon_get_pixbuf(gi);
if (cur_icon==call_icon){
gtk_status_icon_set_from_pixbuf(gi,normal_icon);
}else{
gtk_status_icon_set_from_pixbuf(gi,call_icon);
}
return TRUE;
}
static void _linphone_status_icon_impl_enable_blinking(LinphoneStatusIcon *si, gboolean val) {
GtkStatusIcon *icon = GTK_STATUS_ICON(si->data);
guint tout;
tout=(unsigned)GPOINTER_TO_INT(g_object_get_data(G_OBJECT(icon),"timeout"));
if (val && tout==0){
tout=g_timeout_add(500,(GSourceFunc)_linphone_status_icon_impl_gtk_do_icon_blink_cb,icon);
g_object_set_data(G_OBJECT(icon),"timeout",GINT_TO_POINTER(tout));
}else if (!val && tout!=0){
GdkPixbuf *normal_icon=g_object_get_data(G_OBJECT(icon),"icon");
g_source_remove(tout);
g_object_set_data(G_OBJECT(icon),"timeout",NULL);
gtk_status_icon_set_from_pixbuf(icon,normal_icon);
}
}
static gboolean _linphone_status_icon_impl_is_supported(
const _LinphoneStatusIconDesc *desc,
gboolean *result,
LinphoneStatusIconDescIsSupportedResultCb cb,
void *user_data) {
*result = 1;
return 1;
}
static const _LinphoneStatusIconDesc _linphone_status_icon_impl_gtk_desc = {
.impl_name = "gtk_status_icon",
.init = _linphone_status_icon_impl_gtk_init,
.uninit = NULL,
.start = _linphone_status_icon_impl_gtk_start,
.enable_blinking = _linphone_status_icon_impl_enable_blinking,
.is_supported = _linphone_status_icon_impl_is_supported
};
#endif
/* GtkosxApplication implementation */
#ifdef HAVE_GTK_OSX
static void _linphone_status_icon_impl_gtkosx_app_enable_blinking(LinphoneStatusIcon *si, gboolean val) {
GtkosxApplication *theMacApp=gtkosx_application_get();
gint *attention_id = (gint *)&si->data;
if (val && *attention_id == 0) {
*attention_id=gtkosx_application_attention_request(theMacApp,CRITICAL_REQUEST);
} else if(!val && *attention_id != 0) {
gtkosx_application_cancel_attention_request(theMacApp, *attention_id);
*attention_id = 0;
}
}
static gboolean _linphone_status_icon_impl_gtkosx_app_is_supported(
const _LinphoneStatusIconDesc *desc,
gboolean *result,
LinphoneStatusIconDescIsSupportedResultCb cb,
void *user_data) {
*result = 1;
return 1;
}
static const _LinphoneStatusIconDesc _linphone_status_icon_impl_gtkosx_app_desc = {
.impl_name = "gtkosx_application",
.init = NULL,
.uninit = NULL,
.start = NULL,
.enable_blinking = _linphone_status_icon_impl_gtkosx_app_enable_blinking,
.is_supported = _linphone_status_icon_impl_gtkosx_app_is_supported
};
#endif
/* Implementation based on the StatusNotifier Freedesktop standard */
typedef struct {
int x;
int y;
} _LinphoneStatusIconPosition;
static void _linphone_status_icon_impl_sn_init(LinphoneStatusIcon *si) {
si->data = bc_status_notifier_new();
}
static void _linphone_status_icon_impl_sn_uninit(LinphoneStatusIcon *si) {
bc_status_notifier_unref((BcStatusNotifier *)si->data);
}
static void _linphone_status_icon_impl_sn_activated_cb(BcStatusNotifier *sn, int x, int y, void *user_data) {
LinphoneStatusIcon *si = (LinphoneStatusIcon *)user_data;
_linphone_status_icon_notify_click(si);
}
static void _linphone_status_icon_impr_sn_get_position(GtkMenu *menu, int *x, int *y, gboolean *push_in, gpointer data) {
_LinphoneStatusIconPosition *pos = (_LinphoneStatusIconPosition *)data;
*x = pos->x;
*y = pos->y;
*push_in = TRUE;
}
static void _linphone_status_icon_impl_sn_menu_called_cb(BcStatusNotifier *sn, int x, int y, void *user_data) {
LinphoneStatusIcon *si = (LinphoneStatusIcon *)user_data;
GtkWidget *menu = si->params->menu;
_LinphoneStatusIconPosition pos = {x, y};
gtk_menu_popup(
GTK_MENU(menu),
NULL,
NULL,
_linphone_status_icon_impr_sn_get_position,
&pos,
0,
gtk_get_current_event_time()
);
}
static void _linphone_status_icon_impl_sn_start(LinphoneStatusIcon *si) {
BcStatusNotifier *sn = (BcStatusNotifier *)si->data;
BcStatusNotifierParams *params;
BcStatusNotifierToolTip *tooltip = bc_status_notifier_tool_tip_new("linphone", si->params->title, si->params->desc);
BcStatusNotifierSignalsVTable vtable = {NULL};
vtable.activate_called_cb = _linphone_status_icon_impl_sn_activated_cb;
vtable.context_menu_called_cb = _linphone_status_icon_impl_sn_menu_called_cb;
params = bc_status_notifier_params_new();
bc_status_notifier_params_set_dbus_prefix(params, "org.kde");
bc_status_notifier_params_set_category(params, BcStatusNotifierCategoryCommunications);
bc_status_notifier_params_set_id(params, "linphone");
bc_status_notifier_params_set_title(params, si->params->title);
bc_status_notifier_params_set_icon_name(params, "linphone");
bc_status_notifier_params_set_tool_tip(params, tooltip);
bc_status_notifier_params_set_vtable(params, &vtable, si);
bc_status_notifier_start(sn, params, NULL, NULL);
bc_status_notifier_tool_tip_unref(tooltip);
bc_status_notifier_params_unref(params);
}
static void _linphone_status_icon_impl_sn_enable_blinking(LinphoneStatusIcon *si, gboolean val) {