From e7ab8d25251920eb8fb71c86d7f69a244548bc02 Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Tue, 27 Sep 2011 22:21:32 +0200 Subject: [PATCH] display audio levels in gtk interface --- coreapi/linphonecall.c | 8 +-- gtk/friendlist.c | 2 + gtk/incall_view.c | 71 +++++++++++++++++++++++-- gtk/main.c | 3 +- gtk/main.ui | 116 ++++++++++++++++++++++++++++------------- mediastreamer2 | 2 +- pixmaps/Makefile.am | 3 +- pixmaps/mic_active.png | Bin 1712 -> 961 bytes pixmaps/mic_muted.png | Bin 2098 -> 1197 bytes pixmaps/speaker.png | Bin 0 -> 455 bytes 10 files changed, 159 insertions(+), 46 deletions(-) create mode 100644 pixmaps/speaker.png diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index 215248f3b..8ab925cf4 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -1268,9 +1268,9 @@ bool_t linphone_call_echo_limiter_enabled(const LinphoneCall *call){ **/ float linphone_call_get_play_volume(LinphoneCall *call){ AudioStream *st=call->audiostream; - if (st && st->volsend){ + if (st && st->volrecv){ float vol=0; - ms_filter_call_method(st->volsend,MS_VOLUME_GET,&vol); + ms_filter_call_method(st->volrecv,MS_VOLUME_GET,&vol); return vol; } @@ -1283,9 +1283,9 @@ float linphone_call_get_play_volume(LinphoneCall *call){ **/ float linphone_call_get_record_volume(LinphoneCall *call){ AudioStream *st=call->audiostream; - if (st && st->volrecv){ + if (st && st->volsend && !call->audio_muted && call->state==LinphoneCallStreamsRunning){ float vol=0; - ms_filter_call_method(st->volrecv,MS_VOLUME_GET,&vol); + ms_filter_call_method(st->volsend,MS_VOLUME_GET,&vol); return vol; } diff --git a/gtk/friendlist.c b/gtk/friendlist.c index 075bbd99a..9dacac717 100644 --- a/gtk/friendlist.c +++ b/gtk/friendlist.c @@ -198,7 +198,9 @@ static void update_star(GtkEntry *entry, gboolean is_known){ unstarred=g_object_get_data(G_OBJECT(entry),"unstarred_icon"); if (is_known && (active==unstarred)){ gtk_entry_set_icon_from_pixbuf(entry,GTK_ENTRY_ICON_SECONDARY,starred); + gtk_entry_set_icon_tooltip_text(GTK_ENTRY(entry),GTK_ENTRY_ICON_SECONDARY,NULL); }else if ((!is_known) && (active==starred)){ + gtk_entry_set_icon_tooltip_text(GTK_ENTRY(entry),GTK_ENTRY_ICON_SECONDARY,_("Add to addressbook")); gtk_entry_set_icon_from_pixbuf(entry,GTK_ENTRY_ICON_SECONDARY,unstarred); } } diff --git a/gtk/incall_view.c b/gtk/incall_view.c index 6a2dc0cda..0fc8a5545 100644 --- a/gtk/incall_view.c +++ b/gtk/incall_view.c @@ -319,6 +319,67 @@ static gboolean linphone_gtk_in_call_view_refresh(LinphoneCall *call){ return TRUE; } +typedef float (*get_volume_t)(void *data); + +typedef struct _volume_ctx{ + GtkWidget *widget; + get_volume_t get_volume; + void *data; + float last_value; +}volume_ctx_t; + +#define UNSIGNIFICANT_VOLUME (-26) +#define SMOOTH 0.15 + +static gboolean update_audio_meter(volume_ctx_t *ctx){ + float volume_db=ctx->get_volume(ctx->data); + float frac=(volume_db-UNSIGNIFICANT_VOLUME)/(float)(-UNSIGNIFICANT_VOLUME+3.0); + if (frac<0) frac=0; + if (frac>1.0) frac=1.0; + if (fraclast_value){ + frac=(frac*SMOOTH)+(ctx->last_value*(1-SMOOTH)); + } + ctx->last_value=frac; + //g_message("volume_db=%f, frac=%f",volume_db,frac); + gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(ctx->widget),frac); + return TRUE; +} + +static void on_audio_meter_destroy(guint task_id){ + g_source_remove(task_id); +} + +void linphone_gtk_init_audio_meter(GtkWidget *w, get_volume_t get_volume, void *data){ + guint task_id=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w),"task_id")); + if (task_id==0){ + volume_ctx_t *ctx=g_new(volume_ctx_t,1); + ctx->widget=w; + ctx->get_volume=get_volume; + ctx->data=data; + ctx->last_value=0; + g_object_set_data_full(G_OBJECT(w),"ctx",ctx,g_free); + task_id=g_timeout_add(50,(GSourceFunc)update_audio_meter,ctx); + g_object_set_data_full(G_OBJECT(w),"task_id",GINT_TO_POINTER(task_id),(GDestroyNotify)on_audio_meter_destroy); + } +} + +void linphone_gtk_in_call_view_enable_audio_view(LinphoneCall *call){ + GtkWidget *callview=(GtkWidget*)linphone_call_get_user_pointer(call); + GtkWidget *audio_view=linphone_gtk_get_widget(callview,"incall_audioview"); + //GtkWidget *mic=linphone_gtk_get_widget(callview,"incall_mic_icon"); + GtkWidget *spk=linphone_gtk_get_widget(callview,"incall_spk_icon"); + GtkWidget *mic_level=linphone_gtk_get_widget(callview,"mic_audiolevel"); + GtkWidget *spk_level=linphone_gtk_get_widget(callview,"spk_audiolevel"); + GdkPixbuf *pbuf; + //gtk_image_set_from_pixbuf(GTK_IMAGE(mic),(pbuf=create_pixbuf("mic_active.png"))); + //g_object_unref(pbuf); + gtk_image_set_from_pixbuf(GTK_IMAGE(spk),(pbuf=create_pixbuf("speaker.png"))); + g_object_unref(pbuf); + linphone_gtk_init_audio_meter(mic_level,(get_volume_t)linphone_call_get_record_volume,call); + linphone_gtk_init_audio_meter(spk_level,(get_volume_t)linphone_call_get_play_volume,call); + gtk_widget_show_all(audio_view); +} + void linphone_gtk_in_call_view_set_in_call(LinphoneCall *call){ GtkWidget *callview=(GtkWidget*)linphone_call_get_user_pointer(call); GtkWidget *status=linphone_gtk_get_widget(callview,"in_call_status"); @@ -340,6 +401,7 @@ void linphone_gtk_in_call_view_set_in_call(LinphoneCall *call){ taskid=g_timeout_add(250,(GSourceFunc)linphone_gtk_in_call_view_refresh,call); g_object_set_data(G_OBJECT(callview),"taskid",GINT_TO_POINTER(taskid)); } + linphone_gtk_in_call_view_enable_audio_view(call); } void linphone_gtk_in_call_view_set_paused(LinphoneCall *call){ @@ -383,6 +445,7 @@ void linphone_gtk_in_call_view_terminate(LinphoneCall *call, const char *error_m linphone_gtk_get_ui_config("stop_call_icon","stopcall-red.png"),FALSE); gtk_widget_hide(linphone_gtk_get_widget(callview,"answer_decline_panel")); + gtk_widget_hide(linphone_gtk_get_widget(callview,"incall_audioview")); linphone_gtk_enable_mute_button( GTK_BUTTON(linphone_gtk_get_widget(callview,"incall_mute")),FALSE); linphone_gtk_enable_hold_button(call,FALSE,TRUE); @@ -394,14 +457,14 @@ void linphone_gtk_draw_mute_button(GtkButton *button, gboolean active){ g_object_set_data(G_OBJECT(button),"active",GINT_TO_POINTER(active)); if (active){ GtkWidget *image=create_pixmap("mic_muted.png"); - gtk_button_set_label(GTK_BUTTON(button),_("Unmute")); + /*gtk_button_set_label(GTK_BUTTON(button),_("Unmute"));*/ if (image!=NULL) { gtk_button_set_image(GTK_BUTTON(button),image); gtk_widget_show(image); } }else{ GtkWidget *image=create_pixmap("mic_active.png"); - gtk_button_set_label(GTK_BUTTON(button),_("Mute")); + /*gtk_button_set_label(GTK_BUTTON(button),_("Mute"));*/ if (image!=NULL) { gtk_button_set_image(GTK_BUTTON(button),image); gtk_widget_show(image); @@ -417,7 +480,8 @@ void linphone_gtk_mute_clicked(GtkButton *button){ void linphone_gtk_enable_mute_button(GtkButton *button, gboolean sensitive) { - gtk_widget_set_sensitive(GTK_WIDGET(button),sensitive); + /*gtk_widget_set_sensitive(GTK_WIDGET(button),sensitive);*/ + gtk_widget_set_visible(GTK_WIDGET(button),sensitive); linphone_gtk_draw_mute_button(button,FALSE); } @@ -459,5 +523,6 @@ void linphone_gtk_enable_hold_button(LinphoneCall *call, gboolean sensitive, gbo g_return_if_fail(callview!=NULL); button=linphone_gtk_get_widget(callview,"hold_call"); gtk_widget_set_sensitive(GTK_WIDGET(button),sensitive); + gtk_widget_set_visible(GTK_WIDGET(button),sensitive); linphone_gtk_draw_hold_button(GTK_BUTTON(button),!holdon); } diff --git a/gtk/main.c b/gtk/main.c index be32459e5..e3a7b2742 100644 --- a/gtk/main.c +++ b/gtk/main.c @@ -321,6 +321,7 @@ GtkWidget *linphone_gtk_create_widget(const char *filename, const char *widget_n return NULL; } g_object_set_data(G_OBJECT(w),"builder",builder); + g_signal_connect_swapped(G_OBJECT(w),"destroy",(GCallback)g_object_unref,builder); gtk_builder_connect_signals(builder,w); return w; } @@ -1554,13 +1555,13 @@ static void linphone_gtk_check_soundcards(){ static void linphone_gtk_quit(void){ linphone_gtk_uninit_instance(); - gdk_threads_leave(); linphone_gtk_destroy_log_window(); linphone_core_destroy(the_core); linphone_gtk_log_uninit(); #ifdef HAVE_NOTIFY notify_uninit(); #endif + gdk_threads_leave(); } #ifdef HAVE_GTK_OSX diff --git a/gtk/main.ui b/gtk/main.ui index 6bd4cf9da..1a8fe13c6 100644 --- a/gtk/main.ui +++ b/gtk/main.ui @@ -80,11 +80,35 @@ True False - + True False - + + True + False + + + + + + True + True + 0 + + + + + True + False + label + center + + + True + True + 1 + @@ -94,15 +118,62 @@ - - True + False - label - center + + + True + True + False + half + + + + True + False + 0 + + + + + True + False + + + False + False + 1 + + + + + True + False + gtk-missing-image + 1 + + + True + False + 2 + + + + + True + False + + + False + False + end + 3 + + - True - True + False + False 1 @@ -147,32 +218,6 @@ 2 - - - True - False - - - Mute - True - True - True - False - - - - False - False - 0 - - - - - False - False - 3 - - True @@ -182,7 +227,6 @@ Pause - True True True False @@ -198,7 +242,7 @@ False False - 4 + 3 diff --git a/mediastreamer2 b/mediastreamer2 index 85886f326..aadeaaa8b 160000 --- a/mediastreamer2 +++ b/mediastreamer2 @@ -1 +1 @@ -Subproject commit 85886f326d404708368f72f69c8e0b67af417da1 +Subproject commit aadeaaa8b2de3b1e0cb9ffd5a0a22a85335e7951 diff --git a/pixmaps/Makefile.am b/pixmaps/Makefile.am index 8a9201275..60194fcd8 100644 --- a/pixmaps/Makefile.am +++ b/pixmaps/Makefile.am @@ -13,6 +13,7 @@ status-red.png \ status-offline.png \ contact-orange.png dialer-orange.png history-orange.png\ startcall-green.png stopcall-red.png addcall-green.png linphone.icns \ -contact_starred.png contact_unstarred.png +contact_starred.png contact_unstarred.png \ +speaker.png EXTRA_DIST=$(pixmap_DATA) diff --git a/pixmaps/mic_active.png b/pixmaps/mic_active.png index 6625269932c25f6b9567d12822b961634a9b33b7..349daad4b1907b349f31bc59826e39156b6be9d1 100644 GIT binary patch literal 961 zcmV;y13vtTP)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2ipl7 z6cHAJ2Wd_K00TiuL_t(I%axQ(Pb5_ohM#-u-m0Ry8)v46;EW3s63B$uCN9)PhYcq9 zCxE5I#J%xj=b9B;0t+^i3?Z&f*zgNP-AJpLumF{&wVRKjtL`~2plWDlH7B`A)vZ%c z&Uw!V09#vI+%fxx2Y|V`IRM=H`Z`NXOKfg#emOrs|CRUNhzLbd5JDh?Kv5KkNcCRc zg%CJCKE7UCTl;KpZ}0n7tAzpB-roLhVPWB0=bWl4s%lgf5vf2Tf-wdW;noKcQB^ga zPKTA1l}`^24t_9=MkDTYI^D6cv6_gO5>kS!wTzFC6GGtRil7+a@Xtf6v6Ww*=hSL7@;p}nXN=+U@)A{jtq^&hlNULvf{KEH>z6Ny<77nJ ze!tIfIJ~KHsmEPY)!RFzC~_3N1#0!(T1yl~_x!<@nptZx#$c_*Imgu06oc~tAryon zCxo033bHJt_5OPpWANVNoWpyMh`a)pl{3arN>Fdq81(z(AxBiPHX?~reC+A_5(p4Q5vl?2 zVjA_gaL(hM$NL!P9jZbc$HZ}5wO0i!Q!WKAwdr=d7s;W#*PBIt_ zc=+HE-R>E2obdGNJ0m_KH+sU&qH+8C``1@jS0qWIMNybC;_`<^qk)K$Bngd1gEUP? zfB;F7aD06HA3y}i)zy`0x7(jIn@zm;RR!ZXCP@;`&d$j5oXN>avMeJ>64Ep!O;fTg zV|RC#wY9a+hr{8orX06+yZy!D;^H^;dOay;v|Oxrm+QS}b8v9b+u7Oqy5H|V2Vi-5 jnR^z!;i-a}ot@=>Fx65#NfBt700000NkvXXu0mjfxbwTT literal 1712 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 Eg0SB?-~a#s literal 2098 zcmV-22+jA2P)eMvBj>h>`bx4~rR_KQzj%h_>nGukO1InNv zqTGA#J(qLNo)2)2_X6t7e3;qE%Gr;#*Z!~nUTg2OB_Ra=&!SG%dFITSG`HIw|FX%! zVDPzPx~@BQP18gu6dKsQd$$jW@K_3G;M}=$Yhz+!j^yX(=X*RJ*|IEz5LlM=TzT2J zWm%Y}Nnc-IpuWETd~a`WSz}}4y-5J->gwKDyLRo@F%KTNlk)Qc5JF&&+x4m1cApJs z;<#m5jE;^n^xy#(zxk%^;>C+UYi@4t1CYmoC|OxqCq09MZfngNZXY^?VHl2#j*do% zuImJYK{QQ6(=-Bs0D(Y&U@%B97i$rdie09#Y3SGx~^jw2GP;cBqb%0n3#y$?Z)Tx5eNj( zb=?7IOJ{L0bFW-ME-xoGHkM_}mK9#Oa3K!HgYe0dC(~tF#xzal?bt!9VUSf>NxNn7 zlbt&wsFWm$q@<+rJ_{s>iHX7Ga?#n@NmNvnvjvuA(O+6h?swnOSzAlY^5y8dPC`OL z;_&dW#{nROkWAA=k|Zq4Vopg3cMO9$H8pez!K@EI#Ih_5!(duU3Z`i~!7RoXlNAY% z$AjPRM^#mX5Iig^V^L!xZ50(n7ZjlDdU)_k4gg@>=vZp$x=!-D@A9LjvADLD7ENPX zQ4xN>pXB5uf<|a8*n}7Zz*v36H$rDeCtk0Y(dufJH#Kp!v=k{Ti%0kFp{gpev9VZ| zVB#I*OUM7}GMx7adPQ zF~)*r8YI-!QSieLT-~`7rJw-QG?8VQ@G>O>b`DQ`>{X)?5>)qrv zH1ch6F^MZyAcR1YBoswKk|ZQa0&u=l0+40dQMSc2O=ixV3BbUnO?0FtG52s4cZ5Yo zaS;f?yzu8Sn!3whH&*Ptc{R|EcqN( zF^fw+qRlj!Ur|FF0@^y5d;U-Kep*e;!bKQ{MO0K2Bfb$#)5Ps|M>u4k56|6#a79Uy zaJ${Kx3@DrJ3i!u{H7XqpBHR8>V$ln8sW zEI%JWxT0MT2PVWAfV<_NFsJTI9vwYGc5yL^tkB|ekzQ8D&5{z_Ki_~50!2}r0Gzn^ z3mLE#!zanIjNk7k?yIkuU0=`R-yJ9C{rAT~O5|5mas!E_)z#dRCA7jq+-|pXCrn&C z9DodC2a)adRO0b?Xy12$mG$*p*}9eV&0A0u6-knvZ5w^-Exs)*WXY#T={x-;adB~| zsyazrE>}dhO*#i`gy9i8aO@Zh{&0q_Pku}8h7DZ0bcu|N3=$I)357y*b#)O826_F| z@42yOFK?VZ%gvM&TwAtG^8BSSFj29mvXb1>r}_KGALIGy>r6|T#_F_G`uiU;Fff3k zDC8{2A@kK&X>V`m$@=wN7lLKSkJF;6q-@?CVb6AKN&t4w+H$w5iuqrB!JYm4$=bS= zP$)#tKkngjyGT!;PR@dCWJ#g*b}J1HjYyJ2c6K(=d3m%%MX~6}5n2_6lrSb<2*73l zpsT8ic_&ZORbEb3QIQkbvu4f0=kxJ+Xqb#wGB8bx=H?qLS+WGL*Xu-n=B{1*O_Eqx zT}`_zllJ!8OjXqJG!Zrf03B6T%sFv_?(%YGZ;!nB?EDr&;BvWvQPR@VNK8y5Iy&0X z6GAX&&mL~eG7Bmz=~PwH-+9OR>yji%H~{p6ICL>LOMOOnLHhYxx5=nD!2oRyX3gRqB5US8gs($dne*RNk69~T!l>2{oGH2hWzzwamNhPQ8AzfR4O zBe$BGntu88>C;w+0f3DgH#SvNRIG1kXgIif_3D*guQxjU=@tG2`%n7}!=R(1WANIw zYk%(U?yfB?EWBf{D@{bZYSpUfo}Qj*LWo!(^7rMxETK?HSeB*Dm@(sVOG}HNum|cS c0RQXqFAmv4C9|wQ)Bpeg07*qoM6N<$f*l|7IRF3v diff --git a/pixmaps/speaker.png b/pixmaps/speaker.png new file mode 100644 index 0000000000000000000000000000000000000000..acc92dbcf275cc3ccb8c02a8ac60fa48d70ddf3f GIT binary patch literal 455 zcmV;&0XY7NP)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2ipl7 z6cPu+ni_uq00BoyL_t(I%k7lEO2beThrb&|MAE_FkWGhBap=-fmu6_8;L@R^#3xX2 zb12<9**EFp&^Pb_ickVs;+8G31SIXv&2=dbYP7A6{lS65J)95DJ%3=UpX4|W0IgQb z_%p0ls{zn#HqXK^eA*aPtyUS2#{dk6!;8se@)iU^0_?90ab5SzTfg7G_I+RazOSd# z>1!EKltFvFp4(_NPL)z*S$6I?&XtrB0HxHdUa#9g_Bn62glBX*okyiqMQe@Lnlw#6 zf?Dg+>dJt7Ns<&od|$vOK(Z|3Ux89eQ5416Q?XO_hk2eK#c@0j!|)}JV{O~^;bO5s zDMe8f^U-MZ0OTuo8K?l}(m!su+xOjW_tG#7LkKbRJa4To1EfnsYaIz8ZlWj(JkPr` xP4nN@*|IF_b}$$`ueB+^=m0nYjP1Du;2jAJgl;WPqa^?U002ovPDHLkV1jF=y>I{k literal 0 HcmV?d00001