mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-01-30 09:49:26 +00:00
merge patch for notification bubbles + 2nd call incoming tone notification
This commit is contained in:
parent
fb0dfb524b
commit
26df0c6d83
8 changed files with 249 additions and 31 deletions
22
configure.ac
22
configure.ac
|
|
@ -145,6 +145,28 @@ else
|
|||
echo "GTK interface compilation is disabled."
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE(notify,
|
||||
[ --enable-notify=[yes/no] Enable libnotify support [default=yes]],
|
||||
[case "${enableval}" in
|
||||
yes) notify=true ;;
|
||||
no) notify=false ;;
|
||||
*) AC_MSG_ERROR(bad value ${enableval} for --enable-notify) ;;
|
||||
esac],[notify=true])
|
||||
|
||||
dnl conditionnal build of the notify library
|
||||
if test "$gtk_ui" = "true" ; then
|
||||
if test "$notify" = "true"; then
|
||||
PKG_CHECK_MODULES([NOTIFY], [libnotify >= 0.7.0 ], [found_notify=yes], foo=bar)
|
||||
case "$found_notify" in
|
||||
yes)
|
||||
AC_SUBST(NOTIFY_CFLAGS)
|
||||
AC_SUBST(NOTIFY_LIBS)
|
||||
AC_DEFINE([HAVE_NOTIFY],[1],[NOTIFY support])
|
||||
esac
|
||||
else
|
||||
echo "Libnotify support is disabled."
|
||||
fi
|
||||
fi
|
||||
|
||||
dnl os-specific problems not handled by existing macros.
|
||||
case "$host_os" in
|
||||
|
|
|
|||
|
|
@ -195,7 +195,8 @@ static void call_received(SalOp *h){
|
|||
ms_message("the local ring is already started");
|
||||
}
|
||||
}else{
|
||||
/*TODO : play a tone within the context of the current call */
|
||||
/* play a tone within the context of the current call */
|
||||
linphone_core_play_tone(lc);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -2313,7 +2313,6 @@ int linphone_core_accept_call(LinphoneCore *lc, LinphoneCall *call)
|
|||
ms_message("ring stopped");
|
||||
lc->ringstream=NULL;
|
||||
}
|
||||
|
||||
linphone_core_get_default_proxy(lc,&cfg);
|
||||
dest_proxy=cfg;
|
||||
dest_proxy=linphone_core_lookup_known_proxy(lc,call->log->to);
|
||||
|
|
@ -2369,6 +2368,11 @@ static void terminate_call(LinphoneCore *lc, LinphoneCall *call){
|
|||
ring_stop(lc->ringstream);
|
||||
lc->ringstream=NULL;
|
||||
}
|
||||
|
||||
/*stop any dtmf tone still playing */
|
||||
ms_message("test");
|
||||
linphone_core_stop_dtmf(lc);
|
||||
|
||||
linphone_call_stop_media_streams(call);
|
||||
if (lc->vtable.display_status!=NULL)
|
||||
lc->vtable.display_status(lc,_("Call ended") );
|
||||
|
|
@ -3684,6 +3688,25 @@ void linphone_core_play_dtmf(LinphoneCore *lc, char dtmf, int duration_ms){
|
|||
else ms_filter_call_method(f, MS_DTMF_GEN_START, &dtmf);
|
||||
}
|
||||
|
||||
/**
|
||||
* @ingroup media_parameters
|
||||
* Plays a repeated tone to the local user until next further call to #linphone_core_stop_dtmf()
|
||||
* @param lc #LinphoneCore
|
||||
**/
|
||||
void linphone_core_play_tone(LinphoneCore *lc){
|
||||
MSFilter *f=get_dtmf_gen(lc);
|
||||
MSDtmfGenCustomTone def;
|
||||
if (f==NULL){
|
||||
ms_error("No dtmf generator at this time !");
|
||||
return;
|
||||
}
|
||||
def.duration=300;
|
||||
def.frequency=500;
|
||||
def.amplitude=1;
|
||||
def.interval=800;
|
||||
ms_filter_call_method(f, MS_DTMF_GEN_PLAY_CUSTOM,&def);
|
||||
}
|
||||
|
||||
/**
|
||||
* @ingroup media_parameters
|
||||
*
|
||||
|
|
|
|||
|
|
@ -210,6 +210,8 @@ int linphone_proxy_config_normalize_number(LinphoneProxyConfig *cfg, const char
|
|||
|
||||
void linphone_core_text_received(LinphoneCore *lc, const char *from, const char *msg);
|
||||
|
||||
void linphone_core_play_tone(LinphoneCore *lc);
|
||||
|
||||
void linphone_call_init_media_streams(LinphoneCall *call);
|
||||
void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_muted, bool_t send_ringbacktone);
|
||||
void linphone_call_stop_media_streams(LinphoneCall *call);
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ linphone_SOURCES= \
|
|||
linphone_LDADD=$(ORTP_LIBS) \
|
||||
$(MEDIASTREAMER_LIBS) \
|
||||
$(top_builddir)/coreapi/liblinphone.la \
|
||||
$(LIBGTK_LIBS) $(LIBGTKMAC_LIBS) $(INTLLIBS)
|
||||
$(LIBGTK_LIBS) $(NOTIFY_LIBS) $(LIBGTKMAC_LIBS) $(INTLLIBS)
|
||||
|
||||
|
||||
if BUILD_WIN32
|
||||
|
|
|
|||
147
gtk/main.c
147
gtk/main.c
|
|
@ -36,6 +36,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#define chdir _chdir
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_NOTIFY
|
||||
#include <libnotify/notify.h>
|
||||
#endif
|
||||
|
||||
#define LINPHONE_ICON "linphone.png"
|
||||
|
||||
const char *this_program_ident_string="linphone_ident_string=" LINPHONE_VERSION;
|
||||
|
|
@ -56,6 +60,7 @@ static void linphone_gtk_call_log_updated(LinphoneCore *lc, LinphoneCallLog *cl)
|
|||
static void linphone_gtk_refer_received(LinphoneCore *lc, const char *refer_to);
|
||||
static void linphone_gtk_call_state_changed(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState cs, const char *msg);
|
||||
static gboolean linphone_gtk_auto_answer(LinphoneCall *call);
|
||||
static void linphone_gtk_status_icon_set_blinking(gboolean val);
|
||||
|
||||
|
||||
static gboolean verbose=0;
|
||||
|
|
@ -622,6 +627,24 @@ static void completion_add_text(GtkEntry *entry, const char *text){
|
|||
save_uri_history();
|
||||
}
|
||||
|
||||
|
||||
static void linphone_gtk_show_main_window(){
|
||||
GtkWidget *w=linphone_gtk_get_main_window();
|
||||
LinphoneCore *lc=linphone_gtk_get_core();
|
||||
if (linphone_core_video_enabled(lc)){
|
||||
linphone_core_enable_video_preview(lc,linphone_gtk_get_ui_config_int("videoselfview",
|
||||
VIDEOSELFVIEW_DEFAULT));
|
||||
}
|
||||
gtk_widget_show(w);
|
||||
gtk_window_present(GTK_WINDOW(w));
|
||||
}
|
||||
|
||||
static void linphone_gtk_show(LinphoneCore *lc){
|
||||
#ifndef HAVE_NOTIFY
|
||||
linphone_gtk_show_main_window();
|
||||
#endif
|
||||
}
|
||||
|
||||
void linphone_gtk_call_terminated(LinphoneCall *call, const char *error){
|
||||
GtkWidget *mw=linphone_gtk_get_main_window();
|
||||
if (linphone_core_get_calls(linphone_gtk_get_core())==NULL){
|
||||
|
|
@ -749,6 +772,7 @@ void linphone_gtk_answer_clicked(GtkWidget *button){
|
|||
if (call){
|
||||
linphone_core_pause_all_calls(linphone_gtk_get_core());
|
||||
linphone_core_accept_call(linphone_gtk_get_core(),call);
|
||||
linphone_gtk_show_main_window(); /* useful when the button is clicked on a notification */
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -759,7 +783,7 @@ void linphone_gtk_enable_video(GtkWidget *w){
|
|||
gtk_widget_set_sensitive(selfview_item,val);
|
||||
if (val){
|
||||
linphone_core_enable_video_preview(linphone_gtk_get_core(),
|
||||
linphone_gtk_get_ui_config_int("videoselfview",VIDEOSELFVIEW_DEFAULT));
|
||||
linphone_gtk_get_ui_config_int("videoselfview",VIDEOSELFVIEW_DEFAULT));
|
||||
}else{
|
||||
linphone_core_enable_video_preview(linphone_gtk_get_core(),FALSE);
|
||||
}
|
||||
|
|
@ -783,21 +807,6 @@ void linphone_gtk_used_identity_changed(GtkWidget *w){
|
|||
if (sel) g_free(sel);
|
||||
}
|
||||
|
||||
static void linphone_gtk_show_main_window(){
|
||||
GtkWidget *w=linphone_gtk_get_main_window();
|
||||
LinphoneCore *lc=linphone_gtk_get_core();
|
||||
if (linphone_core_video_enabled(lc)){
|
||||
linphone_core_enable_video_preview(lc,linphone_gtk_get_ui_config_int("videoselfview",
|
||||
VIDEOSELFVIEW_DEFAULT));
|
||||
}
|
||||
gtk_widget_show(w);
|
||||
gtk_window_present(GTK_WINDOW(w));
|
||||
}
|
||||
|
||||
static void linphone_gtk_show(LinphoneCore *lc){
|
||||
linphone_gtk_show_main_window();
|
||||
}
|
||||
|
||||
static void linphone_gtk_notify_recv(LinphoneCore *lc, LinphoneFriend * fid){
|
||||
linphone_gtk_show_friends();
|
||||
}
|
||||
|
|
@ -938,6 +947,54 @@ static void linphone_gtk_call_log_updated(LinphoneCore *lc, LinphoneCallLog *cl)
|
|||
if (w) linphone_gtk_call_log_update(w);
|
||||
}
|
||||
|
||||
#ifdef HAVE_NOTIFY
|
||||
static void make_notification(const char *title, const char *body){
|
||||
NotifyNotification *n;
|
||||
n = notify_notification_new(title,body,linphone_gtk_get_ui_config("icon",LINPHONE_ICON));
|
||||
if (n && !notify_notification_show(n,NULL))
|
||||
ms_error("Failed to send notification.");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static void linphone_gtk_notify(LinphoneCall *call, const char *msg){
|
||||
#ifdef HAVE_NOTIFY
|
||||
if (!notify_is_initted())
|
||||
if (!notify_init ("Linphone")) ms_error("Libnotify failed to init.");
|
||||
#endif
|
||||
if (!call) {
|
||||
#ifdef HAVE_NOTIFY
|
||||
if (!notify_notification_show(notify_notification_new("Linphone",msg,NULL),NULL))
|
||||
ms_error("Failed to send notification.");
|
||||
#else
|
||||
linphone_gtk_show_main_window();
|
||||
#endif
|
||||
} else if (!gtk_window_is_active((GtkWindow*)linphone_gtk_get_main_window())) {
|
||||
#ifdef HAVE_NOTIFY
|
||||
char *body=NULL;
|
||||
char *remote=call!=NULL ? linphone_call_get_remote_address_as_string(call) : NULL;
|
||||
switch(linphone_call_get_state(call)){
|
||||
case LinphoneCallError:
|
||||
make_notification(_("Call error"),body=g_markup_printf_escaped("<span size=\"large\">%s</span>\n%s",msg,remote));
|
||||
break;
|
||||
case LinphoneCallEnd:
|
||||
make_notification(_("Call ended"),body=g_markup_printf_escaped("<span size=\"large\">%s</span>",remote));
|
||||
break;
|
||||
case LinphoneCallIncomingReceived:
|
||||
make_notification(_("Incoming call"),body=g_markup_printf_escaped("<span size=\"large\">%s</span>",remote));
|
||||
break;
|
||||
case LinphoneCallPausedByRemote:
|
||||
make_notification(_("Call paused"),body=g_markup_printf_escaped("<span size=\"large\">by %s</span>",remote));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (body) g_free(body);
|
||||
if (remote) g_free(remote);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static void linphone_gtk_call_state_changed(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState cs, const char *msg){
|
||||
switch(cs){
|
||||
case LinphoneCallOutgoingInit:
|
||||
|
|
@ -954,10 +1011,12 @@ static void linphone_gtk_call_state_changed(LinphoneCore *lc, LinphoneCall *call
|
|||
break;
|
||||
case LinphoneCallEnd:
|
||||
linphone_gtk_in_call_view_terminate(call,NULL);
|
||||
linphone_gtk_status_icon_set_blinking(FALSE);
|
||||
break;
|
||||
case LinphoneCallIncomingReceived:
|
||||
linphone_gtk_create_in_call_view (call);
|
||||
linphone_gtk_in_call_view_set_incoming(call,!all_other_calls_paused (call,linphone_core_get_calls(lc)));
|
||||
linphone_gtk_status_icon_set_blinking(TRUE);
|
||||
if (auto_answer) {
|
||||
linphone_call_ref(call);
|
||||
g_timeout_add(2000,(GSourceFunc)linphone_gtk_auto_answer ,call);
|
||||
|
|
@ -974,10 +1033,12 @@ static void linphone_gtk_call_state_changed(LinphoneCore *lc, LinphoneCall *call
|
|||
break;
|
||||
case LinphoneCallConnected:
|
||||
linphone_gtk_enable_hold_button (call,TRUE,TRUE);
|
||||
linphone_gtk_status_icon_set_blinking(FALSE);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
linphone_gtk_notify(call, msg);
|
||||
linphone_gtk_update_call_buttons (call);
|
||||
}
|
||||
|
||||
|
|
@ -1060,18 +1121,49 @@ static GtkStatusIcon *icon=NULL;
|
|||
|
||||
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);
|
||||
g_object_unref(G_OBJECT(pbuf));
|
||||
gtk_status_icon_set_name(icon,title);
|
||||
g_signal_connect_swapped(G_OBJECT(icon),"activate",(GCallback)linphone_gtk_show_main_window,linphone_gtk_get_main_window());
|
||||
g_signal_connect(G_OBJECT(icon),"popup-menu",(GCallback)icon_popup_menu,NULL);
|
||||
title=linphone_gtk_get_ui_config("title",_("Linphone - a video internet phone"));
|
||||
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);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void linphone_gtk_status_icon_set_blinking(gboolean val){
|
||||
guint tout;
|
||||
tout=(unsigned)GPOINTER_TO_INT(g_object_get_data(G_OBJECT(icon),"timeout"));
|
||||
if (val && tout==0){
|
||||
tout=g_timeout_add(1000,(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_load_identities(void){
|
||||
|
|
@ -1348,9 +1440,11 @@ void linphone_gtk_log_handler(OrtpLogLevel lev, const char *fmt, va_list args){
|
|||
|
||||
|
||||
static void linphone_gtk_refer_received(LinphoneCore *lc, const char *refer_to){
|
||||
GtkEntry * uri_bar =GTK_ENTRY(linphone_gtk_get_widget(
|
||||
GtkEntry * uri_bar =GTK_ENTRY(linphone_gtk_get_widget(
|
||||
linphone_gtk_get_main_window(), "uribar"));
|
||||
linphone_gtk_show_main_window();
|
||||
char *text;
|
||||
linphone_gtk_notify(NULL,(text=ms_strdup_printf(_("We are transferred to %s"),refer_to)));
|
||||
g_free(text);
|
||||
gtk_entry_set_text(uri_bar, refer_to);
|
||||
linphone_gtk_start_call(linphone_gtk_get_main_window());
|
||||
}
|
||||
|
|
@ -1359,16 +1453,19 @@ static void linphone_gtk_check_soundcards(){
|
|||
const char **devices=linphone_core_get_sound_devices(linphone_gtk_get_core());
|
||||
if (devices==NULL || devices[0]==NULL){
|
||||
linphone_gtk_display_something(GTK_MESSAGE_WARNING,
|
||||
_("No sound cards have been detected on this computer.\n"
|
||||
"You won't be able to send or receive audio calls."));
|
||||
_("No sound cards have been detected on this computer.\n"
|
||||
"You won't be able to send or receive audio calls."));
|
||||
}
|
||||
}
|
||||
|
||||
static void linphone_gtk_quit(void){
|
||||
gdk_threads_leave();
|
||||
linphone_gtk_destroy_log_window();
|
||||
linphone_core_destroy(the_core);
|
||||
linphone_gtk_log_uninit();
|
||||
linphone_gtk_destroy_log_window();
|
||||
linphone_core_destroy(the_core);
|
||||
linphone_gtk_log_uninit();
|
||||
#ifdef HAVE_NOTIFY
|
||||
notify_uninit();
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef HAVE_GTK_OSX
|
||||
|
|
|
|||
77
gtk/main.ui
77
gtk/main.ui
|
|
@ -2,6 +2,66 @@
|
|||
<interface>
|
||||
<requires lib="gtk+" version="2.16"/>
|
||||
<!-- interface-naming-policy toplevel-contextual -->
|
||||
<object class="GtkWindow" id="dummy_conf_window">
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkFrame" id="callee_frame">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label_xalign">0</property>
|
||||
<property name="shadow_type">none</property>
|
||||
<child>
|
||||
<object class="GtkAlignment" id="conf_alignment1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="left_padding">12</property>
|
||||
<child>
|
||||
<object class="GtkHBox" id="conf_hbox3">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkProgressBar" id="sound_indicator">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="hangup_button">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<signal name="clicked" handler="linphone_gtk_conf_hangup_clicked" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child type="label">
|
||||
<object class="GtkLabel" id="callee_name_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes"><b>Callee name</b></property>
|
||||
<property name="use_markup">True</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<object class="GtkWindow" id="dummy_in_call_window">
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
|
|
@ -90,7 +150,6 @@
|
|||
<object class="GtkHButtonBox" id="mute_pause_buttons">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="layout_style">spread</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="incall_mute">
|
||||
<property name="label" translatable="yes">Mute</property>
|
||||
|
|
@ -106,6 +165,20 @@
|
|||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="incall_merge">
|
||||
<property name="label" translatable="yes">Merge to conference</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<signal name="clicked" handler="linphone_gtk_merge_to_conference" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="hold_call">
|
||||
<property name="label" translatable="yes">Pause</property>
|
||||
|
|
@ -118,7 +191,7 @@
|
|||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">1</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit 90be72f669f3c5067c571b0f29f22eda21166006
|
||||
Subproject commit a73e55293ed2b551cf12bfc85d812fa659fb25da
|
||||
Loading…
Add table
Reference in a new issue