]> sjero.net Git - linphone/commitdiff
merge patch for notification bubbles + 2nd call incoming tone notification
authorSimon Morlat <simon.morlat@linphone.org>
Fri, 16 Sep 2011 15:17:00 +0000 (17:17 +0200)
committerSimon Morlat <simon.morlat@linphone.org>
Fri, 16 Sep 2011 15:17:00 +0000 (17:17 +0200)
configure.ac
coreapi/callbacks.c
coreapi/linphonecore.c
coreapi/private.h
gtk/Makefile.am
gtk/main.c
gtk/main.ui
mediastreamer2

index 5fe32ef33749bfb48803e49b16cae3162c9b43a9..7c231b20a519eeddb5c1df056f50c12c27ee97b1 100644 (file)
@@ -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
index 1f00b19954bb16a2678fcfcc21292fae387727cf..a49c1a96869a1e13f78c15f1bf3c8a7771cf50a9 100644 (file)
@@ -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);
        }
 
        
index b042a1398a06c74311a0ba85f8ec731d63cd9136..bf656c810318ae4b9f2846ea9d6a48ceffe2d9d6 100644 (file)
@@ -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
  *
index bb1fb883b8445cc12a600ea379d531fca06bee71..47592514fbf7be096a9d479bec00bbd75c8d48c5 100644 (file)
@@ -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);
index c51234eb395418437505e9a7ad35d77c19840d8e..56ac4a33640c1860e5d18ea0dcae7269ad6e0ef8 100644 (file)
@@ -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
index e8313628f532a208b765b59c4fc0f4c3c0801101..ac4e632aa5f86ae74ed7883f72e34e428fc2ee45 100644 (file)
@@ -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
index ea9c596b0779175199081aad9b02a85bd9749e3c..7a57073ac5b0a5973f70725fe209493fa5bcc35e 100644 (file)
@@ -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">&lt;b&gt;Callee name&lt;/b&gt;</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>
                   <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>
                         <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>
                       <packing>
                         <property name="expand">False</property>
                         <property name="fill">False</property>
-                        <property name="position">1</property>
+                        <property name="position">2</property>
                       </packing>
                     </child>
                   </object>
index 90be72f669f3c5067c571b0f29f22eda21166006..a73e55293ed2b551cf12bfc85d812fa659fb25da 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 90be72f669f3c5067c571b0f29f22eda21166006
+Subproject commit a73e55293ed2b551cf12bfc85d812fa659fb25da