From: Simon Morlat Date: Fri, 22 Feb 2013 16:21:50 +0000 (+0100) Subject: add call recording feature to conference X-Git-Url: http://sjero.net/git/?p=linphone;a=commitdiff_plain;h=08eb7e6fbe356d80d6dfd4b3e877d43435372ec6 add call recording feature to conference fix broken gtk conference interface. --- diff --git a/coreapi/conference.c b/coreapi/conference.c index a125673a..16be6261 100644 --- a/coreapi/conference.c +++ b/coreapi/conference.c @@ -55,22 +55,38 @@ static void remove_local_endpoint(LinphoneConference *ctx){ } } +static int linphone_conference_get_size(LinphoneConference *conf){ + if (conf->conf == NULL) { + return 0; + } + return ms_audio_conference_get_size(conf->conf) - (conf->record_endpoint ? 1 : 0); +} + static int remote_participants_count(LinphoneConference *ctx) { - if (!ctx->conf || ms_audio_conference_get_size(ctx->conf)==0) return 0; - if (!ctx->local_participant) return ms_audio_conference_get_size(ctx->conf); - return ms_audio_conference_get_size(ctx->conf) -1; + int count=linphone_conference_get_size(ctx); + if (count==0) return 0; + if (!ctx->local_participant) return count; + return count -1; } void linphone_core_conference_check_uninit(LinphoneCore *lc){ LinphoneConference *ctx=&lc->conf_ctx; if (ctx->conf){ - ms_message("conference_check_uninit(): nmembers=%i",ms_audio_conference_get_size(ctx->conf)); - if (remote_participants_count(ctx)==1){ + int remote_count=remote_participants_count(ctx); + ms_message("conference_check_uninit(): size=%i",linphone_conference_get_size(ctx)); + if (remote_count==1){ convert_conference_to_call(lc); } - if (ms_audio_conference_get_size(ctx->conf)==1 && ctx->local_participant!=NULL){ - remove_local_endpoint(ctx); + if (remote_count==0){ + if (ctx->local_participant!=NULL) + remove_local_endpoint(ctx); + if (ctx->record_endpoint){ + ms_audio_conference_remove_member(ctx->conf,ctx->record_endpoint); + ms_audio_endpoint_destroy(ctx->record_endpoint); + ctx->record_endpoint=NULL; + } } + if (ms_audio_conference_get_size(ctx->conf)==0){ ms_audio_conference_destroy(ctx->conf); ctx->conf=NULL; @@ -381,10 +397,37 @@ int linphone_core_terminate_conference(LinphoneCore *lc) { * @returns the number of participants to the conference **/ int linphone_core_get_conference_size(LinphoneCore *lc) { - if (lc->conf_ctx.conf == NULL) { - return 0; + LinphoneConference *conf=&lc->conf_ctx; + return linphone_conference_get_size(conf); +} + + +int linphone_core_start_conference_recording(LinphoneCore *lc, const char *path){ + LinphoneConference *conf=&lc->conf_ctx; + if (conf->conf == NULL) { + ms_warning("linphone_core_start_conference_recording(): no conference now."); + return -1; + } + if (conf->record_endpoint==NULL){ + conf->record_endpoint=ms_audio_endpoint_new_recorder(); + ms_audio_conference_add_member(conf->conf,conf->record_endpoint); } - return ms_audio_conference_get_size(lc->conf_ctx.conf); + ms_audio_recorder_endpoint_start(conf->record_endpoint,path); + return 0; +} + +int linphone_core_stop_conference_recording(LinphoneCore *lc){ + LinphoneConference *conf=&lc->conf_ctx; + if (conf->conf == NULL) { + ms_warning("linphone_core_stop_conference_recording(): no conference now."); + return -1; + } + if (conf->record_endpoint==NULL){ + ms_warning("linphone_core_stop_conference_recording(): no record active."); + return -1; + } + ms_audio_recorder_endpoint_stop(conf->record_endpoint); + return 0; } /** diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index d9d199c3..23759047 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -92,12 +92,7 @@ int lc_callback_obj_invoke(LCCallbackObj *obj, LinphoneCore *lc){ /*prevent a gcc bug with %c*/ static size_t my_strftime(char *s, size_t max, const char *fmt, const struct tm *tm){ -#if !defined(_WIN32_WCE) return strftime(s, max, fmt, tm); -#else - return 0; - /*FIXME*/ -#endif /*_WIN32_WCE*/ } static void set_call_log_date(LinphoneCallLog *cl, time_t start_time){ @@ -120,7 +115,7 @@ LinphoneCallLog * linphone_call_log_new(LinphoneCall *call, LinphoneAddress *fro set_call_log_date(cl,cl->start_date_time); cl->from=from; cl->to=to; - cl->status=LinphoneCallAborted; /*default status*/ + cl->status=LinphoneCallAborted; /*default status*/ return cl; } diff --git a/coreapi/linphonecore.h b/coreapi/linphonecore.h index 78193aaa..2c216864 100644 --- a/coreapi/linphonecore.h +++ b/coreapi/linphonecore.h @@ -1368,6 +1368,8 @@ float linphone_core_get_conference_local_input_volume(LinphoneCore *lc); int linphone_core_terminate_conference(LinphoneCore *lc); int linphone_core_get_conference_size(LinphoneCore *lc); +int linphone_core_start_conference_recording(LinphoneCore *lc, const char *path); +int linphone_core_stop_conference_recording(LinphoneCore *lc); int linphone_core_get_max_calls(LinphoneCore *lc); void linphone_core_set_max_calls(LinphoneCore *lc, int max); diff --git a/coreapi/private.h b/coreapi/private.h index c0b467ce..41d453df 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -530,6 +530,7 @@ struct _LinphoneConference{ MSAudioConference *conf; AudioStream *local_participant; MSAudioEndpoint *local_endpoint; + MSAudioEndpoint *record_endpoint; RtpProfile *local_dummy_profile; bool_t local_muted; }; diff --git a/gtk/call_statistics.ui b/gtk/call_statistics.ui index 6ed8bd9b..c6f71deb 100644 --- a/gtk/call_statistics.ui +++ b/gtk/call_statistics.ui @@ -1,34 +1,71 @@ - + + False 5 Call statistics dialog - + True + False 2 + + + True + False + end + + + + + + gtk-close + True + True + True + False + True + + + False + False + 1 + + + + + False + True + end + 0 + + True + False 0 none True + False 12 True - 6 + False + 7 2 True True + False Audio codec @@ -38,6 +75,7 @@ True + False Video codec @@ -49,6 +87,7 @@ True + False Audio IP bandwidth usage @@ -60,6 +99,7 @@ True + False 1 @@ -69,6 +109,7 @@ True + False 1 @@ -80,6 +121,7 @@ True + False 1 @@ -91,6 +133,7 @@ True + False Audio Media connectivity @@ -102,6 +145,7 @@ True + False 1 @@ -113,6 +157,7 @@ True + False Video IP bandwidth usage @@ -124,6 +169,7 @@ True + False 1 @@ -135,6 +181,7 @@ True + False Video Media connectivity @@ -145,6 +192,7 @@ True + False 1 @@ -153,6 +201,29 @@ 6 + + + True + False + Round trip time + + + 6 + 7 + + + + + True + False + + + 1 + 2 + 6 + 7 + + @@ -160,6 +231,7 @@ True + False <b>Call statistics and information</b> True @@ -171,34 +243,6 @@ 1 - - - True - end - - - - - - gtk-close - True - True - True - True - - - False - False - 1 - - - - - False - end - 0 - - diff --git a/gtk/conference.c b/gtk/conference.c index dddb3cec..08262c77 100644 --- a/gtk/conference.c +++ b/gtk/conference.c @@ -27,6 +27,11 @@ #define PADDING_PIXELS 4 +/* + * conferencee_box = a vbox where participants are added or removed + * conf_frame = the conference tab + */ + static GtkWidget *create_conference_label(void){ GtkWidget *box=gtk_hbox_new(FALSE,0); gtk_box_pack_start(GTK_BOX(box),gtk_image_new_from_stock(GTK_STOCK_ADD,GTK_ICON_SIZE_MENU),FALSE,FALSE,0); @@ -46,34 +51,21 @@ static void init_local_participant(GtkWidget *participant){ linphone_gtk_init_audio_meter(sound_meter, (get_volume_t) linphone_core_get_conference_local_input_volume, linphone_gtk_get_core()); } -static GtkWidget *get_conference_tab(GtkWidget *mw){ - GtkWidget *box=(GtkWidget*)g_object_get_data(G_OBJECT(mw),"conference_tab"); - GtkWidget *conf_frame=(GtkWidget*)g_object_get_data(G_OBJECT(mw),"conf_frame"); - if(conf_frame!=NULL){ - if (box==NULL){ - GtkWidget *conf_box=linphone_gtk_get_widget(conf_frame,"conf_box"); - box=gtk_vbox_new(FALSE,0); - GtkWidget *participant=linphone_gtk_create_widget("main","callee_frame"); - gtk_box_set_homogeneous(GTK_BOX(box),TRUE); - init_local_participant(participant); - gtk_box_pack_start(GTK_BOX(box),participant,FALSE,FALSE,PADDING_PIXELS); - gtk_widget_show(box); - g_object_set_data(G_OBJECT(mw),"conference_tab",box); - gtk_box_pack_start(GTK_BOX(conf_box),box,FALSE,FALSE,PADDING_PIXELS); - } - } +static GtkWidget *get_conferencee_box(GtkWidget *mw){ + GtkWidget *box=(GtkWidget*)g_object_get_data(G_OBJECT(mw),"conferencee_box"); return box; } static GtkWidget *find_conferencee_from_call(LinphoneCall *call){ GtkWidget *mw=linphone_gtk_get_main_window(); - get_conference_tab(mw); - GtkWidget *conf_frame=(GtkWidget *)g_object_get_data(G_OBJECT(mw),"conf_frame"); - GtkWidget *conf_box=linphone_gtk_get_widget(conf_frame,"conf_box"); + GtkWidget *conferencee_box=get_conferencee_box(mw); GList *elem; GtkWidget *ret=NULL; + + if (conferencee_box==NULL) return NULL; + if (call!=NULL){ - GList *l=gtk_container_get_children(GTK_CONTAINER(conf_box)); + GList *l=gtk_container_get_children(GTK_CONTAINER(conferencee_box)); for(elem=l;elem!=NULL;elem=elem->next){ GtkWidget *frame=(GtkWidget*)elem->data; if (call==g_object_get_data(G_OBJECT(frame),"call")){ @@ -87,28 +79,53 @@ static GtkWidget *find_conferencee_from_call(LinphoneCall *call){ return ret; } -void linphone_gtk_set_in_conference(LinphoneCall *call){ +static GtkWidget * create_conference_panel(void){ GtkWidget *mw=linphone_gtk_get_main_window(); + GtkWidget *conf_frame=linphone_gtk_create_widget("main","conf_frame"); + GtkWidget *conf_box=linphone_gtk_get_widget(conf_frame,"conf_box"); + GtkWidget *button_conf=linphone_gtk_get_widget(conf_frame,"terminate_conf"); + GtkWidget *image=create_pixmap("stopcall-small.png"); + GtkWidget *box; GtkWidget *viewswitch=linphone_gtk_get_widget(mw,"viewswitch"); + + gtk_button_set_image(GTK_BUTTON(button_conf),image); + g_signal_connect_swapped(G_OBJECT(button_conf),"clicked",(GCallback)linphone_gtk_terminate_call,NULL); + g_object_set_data(G_OBJECT(mw),"conf_frame",(gpointer)conf_frame); + + box=gtk_vbox_new(FALSE,0); + GtkWidget *participant=linphone_gtk_create_widget("main","callee_frame"); + gtk_widget_show(participant); + gtk_box_set_homogeneous(GTK_BOX(box),TRUE); + init_local_participant(participant); + gtk_box_pack_start(GTK_BOX(box),participant,FALSE,FALSE,PADDING_PIXELS); + gtk_widget_show(box); + g_object_set_data(G_OBJECT(mw),"conferencee_box",box); + gtk_box_pack_start(GTK_BOX(conf_box),box,FALSE,FALSE,PADDING_PIXELS); + + gtk_notebook_append_page(GTK_NOTEBOOK(viewswitch),conf_frame, + create_conference_label()); + return conf_frame; +} + +void linphone_gtk_set_in_conference(LinphoneCall *call){ + GtkWidget *mw=linphone_gtk_get_main_window(); GtkWidget *conf_frame=(GtkWidget *)g_object_get_data(G_OBJECT(mw),"conf_frame"); - g_object_set_data(G_OBJECT(mw),"is_conf",GINT_TO_POINTER(TRUE)); + GtkWidget *viewswitch=linphone_gtk_get_widget(mw,"viewswitch"); + if(conf_frame==NULL){ - conf_frame=linphone_gtk_create_widget("main","conf_frame"); - GtkWidget *button_conf=linphone_gtk_get_widget(conf_frame,"terminate_conf"); - GtkWidget *image=create_pixmap("stopcall-small.png"); - gtk_button_set_image(GTK_BUTTON(button_conf),image); - g_signal_connect_swapped(G_OBJECT(button_conf),"clicked",(GCallback)linphone_gtk_terminate_call,NULL); - g_object_set_data(G_OBJECT(mw),"conf_frame",(gpointer)conf_frame); - gtk_notebook_append_page(GTK_NOTEBOOK(viewswitch),conf_frame, - create_conference_label()); + conf_frame=create_conference_panel(); } - GtkWidget *participant=find_conferencee_from_call(call); - GtkWidget *conf_box=linphone_gtk_get_widget(conf_frame,"conf_box"); + GtkWidget *participant=find_conferencee_from_call(call); + if (participant==NULL){ - const LinphoneAddress *addr=linphone_call_get_remote_address(call); - participant=linphone_gtk_create_widget("main","callee_frame"); + /*create and add it */ + GtkWidget *conferencee_box=get_conferencee_box(mw); GtkWidget *sound_meter; + const LinphoneAddress *addr=linphone_call_get_remote_address(call); gchar *markup; + + participant=linphone_gtk_create_widget("main","callee_frame"); + gtk_widget_show(participant); if (linphone_address_get_display_name(addr)!=NULL){ markup=g_strdup_printf("%s",linphone_address_get_display_name(addr)); }else{ @@ -119,11 +136,11 @@ void linphone_gtk_set_in_conference(LinphoneCall *call){ gtk_label_set_markup(GTK_LABEL(linphone_gtk_get_widget(participant,"callee_name_label")),markup); g_free(markup); sound_meter=linphone_gtk_get_widget(participant,"sound_indicator"); - linphone_gtk_init_audio_meter(sound_meter, (get_volume_t) linphone_call_get_play_volume, call); - gtk_box_pack_start(GTK_BOX(conf_box),participant,FALSE,FALSE,PADDING_PIXELS); + linphone_gtk_init_audio_meter(sound_meter, (get_volume_t) linphone_call_get_play_volume, call); + gtk_box_pack_start(GTK_BOX(conferencee_box),participant,FALSE,FALSE,PADDING_PIXELS); g_object_set_data_full(G_OBJECT(participant),"call",linphone_call_ref(call),(GDestroyNotify)linphone_call_unref); gtk_notebook_set_current_page(GTK_NOTEBOOK(viewswitch), - gtk_notebook_page_num(GTK_NOTEBOOK(viewswitch),conf_frame)); + gtk_notebook_page_num(GTK_NOTEBOOK(viewswitch),conf_frame)); } } @@ -135,24 +152,26 @@ void linphone_gtk_terminate_conference_participant(LinphoneCall *call){ } void linphone_gtk_unset_from_conference(LinphoneCall *call){ - GtkWidget *mw=linphone_gtk_get_main_window(); - GtkWidget *conf_frame=(GtkWidget *)g_object_get_data(G_OBJECT(mw),"conf_frame"); - GtkWidget *conf_box=linphone_gtk_get_widget(conf_frame,"conf_box"); - GtkWidget *frame; - if (conf_box==NULL) return; /*conference tab already destroyed*/ - frame=find_conferencee_from_call(call); - GList *children; + GtkWidget *frame=find_conferencee_from_call(call); + if (frame){ + GtkWidget *mw=linphone_gtk_get_main_window(); + GtkWidget *conf_frame=(GtkWidget *)g_object_get_data(G_OBJECT(mw),"conf_frame"); + GtkWidget *conferencee_box=g_object_get_data(G_OBJECT(mw),"conferencee_box"); + GList *children; + + g_message("Removing a participant from conference"); gtk_widget_destroy(frame); + children=gtk_container_get_children(GTK_CONTAINER(conferencee_box)); + if (g_list_length(children)==1){ /* only local participant */ + /*the conference is terminated */ + g_message("The conference is terminated"); + g_object_set_data(G_OBJECT(mw),"conferencee_box",NULL); + gtk_widget_destroy(conf_frame); + g_object_set_data(G_OBJECT(mw),"conf_frame",NULL); + } + g_list_free(children); } - children=gtk_container_get_children(GTK_CONTAINER(conf_box)); - if (g_list_length(children)==2){ - /*the conference is terminated */ - gtk_widget_destroy(conf_box); - g_object_set_data(G_OBJECT(mw),"conference_tab",NULL); - } - gtk_widget_destroy(conf_frame); - g_list_free(children); - g_object_set_data(G_OBJECT(mw),"is_conf",GINT_TO_POINTER(FALSE)); - g_object_set_data(G_OBJECT(mw),"conf_frame",NULL); } + + diff --git a/gtk/incall_view.c b/gtk/incall_view.c index 60aa7cb1..0a64a104 100644 --- a/gtk/incall_view.c +++ b/gtk/incall_view.c @@ -50,7 +50,8 @@ LinphoneCall *linphone_gtk_get_currently_displayed_call(gboolean *is_conf){ if (page!=NULL){ LinphoneCall *call=(LinphoneCall*)g_object_get_data(G_OBJECT(page),"call"); if (call==NULL){ - if (GPOINTER_TO_INT(g_object_get_data(G_OBJECT(main_window),"is_conf"))){ + GtkWidget *conf_frame=(GtkWidget *)g_object_get_data(G_OBJECT(main_window),"conf_frame"); + if (conf_frame==page){ if (is_conf) *is_conf=TRUE; return NULL; @@ -75,25 +76,28 @@ static GtkWidget *make_tab_header(int number){ } void update_tab_header(LinphoneCall *call,gboolean pause){ - GtkWidget *w=(GtkWidget*)linphone_call_get_user_pointer(call); - GtkWidget *main_window=linphone_gtk_get_main_window(); - GtkNotebook *notebook=GTK_NOTEBOOK(linphone_gtk_get_widget(main_window,"viewswitch")); - gint call_index=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w),"call_index")); - GtkWidget *new_label=gtk_hbox_new (FALSE,0); - GtkWidget *i=NULL; - if(pause){ -i=gtk_image_new_from_stock(GTK_STOCK_MEDIA_PAUSE,GTK_ICON_SIZE_SMALL_TOOLBAR); - } else { - i=create_pixmap ("startcall-small.png"); - } + GtkWidget *w=(GtkWidget*)linphone_call_get_user_pointer(call); + GtkWidget *main_window=linphone_gtk_get_main_window(); + GtkNotebook *notebook=GTK_NOTEBOOK(linphone_gtk_get_widget(main_window,"viewswitch")); + gint call_index=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w),"call_index")); + GtkWidget *new_label=gtk_hbox_new (FALSE,0); + GtkWidget *i=NULL; GtkWidget *l; - gchar *text=g_strdup_printf(_("Call #%i"),call_index); + gchar *text; + + if(pause){ + i=gtk_image_new_from_stock(GTK_STOCK_MEDIA_PAUSE,GTK_ICON_SIZE_SMALL_TOOLBAR); + } else { + i=create_pixmap ("startcall-small.png"); + } + + text=g_strdup_printf(_("Call #%i"),call_index); l=gtk_label_new (text); gtk_box_pack_start (GTK_BOX(new_label),i,FALSE,FALSE,0); gtk_box_pack_end(GTK_BOX(new_label),l,TRUE,TRUE,0); - gtk_notebook_set_tab_label(notebook,w,new_label); - gtk_widget_show_all(new_label); + gtk_notebook_set_tab_label(notebook,w,new_label); + gtk_widget_show_all(new_label); } static void linphone_gtk_in_call_set_animation_image(GtkWidget *callview, const char *image_name, gboolean is_stock){ @@ -157,8 +161,7 @@ void transfer_button_clicked(GtkWidget *button, gpointer call_ref){ g_signal_connect_swapped(G_OBJECT(menu_item),"activate",(GCallback)linphone_gtk_transfer_call,other_call); } } - gtk_menu_popup(GTK_MENU(menu),NULL,NULL,NULL,NULL,0, - gtk_get_current_event_time()); + gtk_menu_popup(GTK_MENU(menu),NULL,NULL,NULL,NULL,0,gtk_get_current_event_time()); gtk_widget_show(menu); } @@ -178,7 +181,6 @@ static void conference_button_clicked(GtkWidget *button, gpointer call_ref){ gtk_widget_set_sensitive(button,FALSE); g_object_set_data(G_OBJECT(linphone_gtk_get_main_window()),"conf_frame",NULL); linphone_core_add_all_to_conference(linphone_gtk_get_core()); - //linphone_core_add_to_conference(linphone_gtk_get_core(),(LinphoneCall*)call_ref); } @@ -202,7 +204,6 @@ static void show_used_codecs(GtkWidget *callstats, LinphoneCall *call){ GtkWidget *acodec_ui=linphone_gtk_get_widget(callstats,"audio_codec"); GtkWidget *vcodec_ui=linphone_gtk_get_widget(callstats,"video_codec"); if (acodec){ - char tmp[64]={0}; snprintf(tmp,sizeof(tmp)-1,"%s/%i/%i",acodec->mime_type,acodec->clock_rate,acodec->channels); gtk_label_set_label(GTK_LABEL(acodec_ui),tmp); @@ -252,28 +253,40 @@ static const char *upnp_state_to_string(LinphoneUpnpState ice_state){ static void _refresh_call_stats(GtkWidget *callstats, LinphoneCall *call){ const LinphoneCallStats *as=linphone_call_get_audio_stats(call); const LinphoneCallStats *vs=linphone_call_get_video_stats(call); - const char *audio_media_connectivity = _("Direct"); - const char *video_media_connectivity = _("Direct"); + const char *audio_media_connectivity = _("Direct or through server"); + const char *video_media_connectivity = _("Direct or through server"); + gboolean has_video=linphone_call_params_video_enabled(linphone_call_get_current_params(call)); gchar *tmp=g_strdup_printf(_("download: %f\nupload: %f (kbit/s)"), as->download_bandwidth,as->upload_bandwidth); + gtk_label_set_markup(GTK_LABEL(linphone_gtk_get_widget(callstats,"audio_bandwidth_usage")),tmp); g_free(tmp); - tmp=g_strdup_printf(_("download: %f\nupload: %f (kbit/s)"), - vs->download_bandwidth,vs->upload_bandwidth); + if (has_video) + tmp=g_strdup_printf(_("download: %f\nupload: %f (kbit/s)"),vs->download_bandwidth,vs->upload_bandwidth); + else tmp=NULL; gtk_label_set_markup(GTK_LABEL(linphone_gtk_get_widget(callstats,"video_bandwidth_usage")),tmp); - g_free(tmp); + if (tmp) g_free(tmp); if(as->upnp_state != LinphoneUpnpStateNotAvailable && as->upnp_state != LinphoneUpnpStateIdle) { audio_media_connectivity = upnp_state_to_string(as->upnp_state); } else if(as->ice_state != LinphoneIceStateNotActivated) { audio_media_connectivity = ice_state_to_string(as->ice_state); } gtk_label_set_text(GTK_LABEL(linphone_gtk_get_widget(callstats,"audio_media_connectivity")),audio_media_connectivity); - if(vs->upnp_state != LinphoneUpnpStateNotAvailable && vs->upnp_state != LinphoneUpnpStateIdle) { - video_media_connectivity = upnp_state_to_string(vs->upnp_state); - } else if(vs->ice_state != LinphoneIceStateNotActivated) { - video_media_connectivity = ice_state_to_string(vs->ice_state); - } + + if (has_video){ + if(vs->upnp_state != LinphoneUpnpStateNotAvailable && vs->upnp_state != LinphoneUpnpStateIdle) { + video_media_connectivity = upnp_state_to_string(vs->upnp_state); + } else if(vs->ice_state != LinphoneIceStateNotActivated) { + video_media_connectivity = ice_state_to_string(vs->ice_state); + } + }else video_media_connectivity=NULL; gtk_label_set_text(GTK_LABEL(linphone_gtk_get_widget(callstats,"video_media_connectivity")),video_media_connectivity); + + if (as->round_trip_delay>0){ + tmp=g_strdup_printf(_("%.3f seconds"),as->round_trip_delay); + gtk_label_set_text(GTK_LABEL(linphone_gtk_get_widget(callstats,"round_trip_time")),tmp); + g_free(tmp); + } } static gboolean refresh_call_stats(GtkWidget *callstats){ @@ -689,6 +702,9 @@ void linphone_gtk_in_call_view_set_in_call(LinphoneCall *call){ if (in_conf){ linphone_gtk_set_in_conference(call); gtk_widget_set_sensitive(linphone_gtk_get_widget(callview,"incall_mute"),FALSE); + }else{ + linphone_gtk_unset_from_conference(call); /*in case it was previously*/ + gtk_widget_set_sensitive(linphone_gtk_get_widget(callview,"incall_mute"),TRUE); } gtk_widget_show_all(linphone_gtk_get_widget(callview,"buttons_panel")); if (!in_conf) gtk_widget_show_all(linphone_gtk_get_widget(callview,"record_hbox")); @@ -857,18 +873,46 @@ void linphone_gtk_call_statistics_closed(GtkWidget *call_stats){ void linphone_gtk_record_call_toggled(GtkWidget *button){ gboolean active=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)); - LinphoneCall *call=linphone_gtk_get_currently_displayed_call(NULL); - GtkWidget *callview=(GtkWidget*)linphone_call_get_user_pointer (call); - const LinphoneCallParams *params=linphone_call_get_current_params(call); - const char *filepath=linphone_call_params_get_record_file(params); - gchar *message=g_strdup_printf(_("Recording into %s %s"),filepath,active ? "" : _("(Paused)")); + gboolean is_conf=FALSE; + const char *filepath; + gchar *message; + LinphoneCore *lc=linphone_gtk_get_core(); + LinphoneCall *call=linphone_gtk_get_currently_displayed_call(&is_conf); + GtkWidget *callview; + GtkWidget *label; + if (call){ + callview=(GtkWidget*)linphone_call_get_user_pointer (call); + const LinphoneCallParams *params=linphone_call_get_current_params(call); + filepath=linphone_call_params_get_record_file(params); + label=linphone_gtk_get_widget(callview,"record_status"); + }else if (is_conf){ + GtkWidget *mw=linphone_gtk_get_main_window(); + callview=(GtkWidget *)g_object_get_data(G_OBJECT(linphone_gtk_get_main_window()),"conf_frame"); + label=linphone_gtk_get_widget(callview,"conf_record_status"); + filepath=(const char*)g_object_get_data(G_OBJECT(mw),"conf_record_path"); + if (filepath==NULL){ + filepath=linphone_gtk_get_record_path(NULL,TRUE); + g_object_set_data_full(G_OBJECT(mw),"conf_record_path",(char*)filepath,g_free); + } + }else{ + g_warning("linphone_gtk_record_call_toggled(): bug."); + return; + } + message=g_strdup_printf(_("Recording into\n%s %s"),filepath,active ? "" : _("(Paused)")); if (active){ - linphone_call_start_recording(call); + if (call) + linphone_call_start_recording(call); + else + linphone_core_start_conference_recording(lc,filepath); }else { - linphone_call_stop_recording(call); + if (call) + linphone_call_stop_recording(call); + else + linphone_core_stop_conference_recording(lc); + } - gtk_label_set_markup(GTK_LABEL(linphone_gtk_get_widget(callview,"record_status")),message); + gtk_label_set_markup(GTK_LABEL(label),message); g_free(message); } diff --git a/gtk/linphone.h b/gtk/linphone.h index abb39512..f9597849 100644 --- a/gtk/linphone.h +++ b/gtk/linphone.h @@ -149,3 +149,5 @@ void linphone_gtk_uninit_instance(void); void linphone_gtk_monitor_usb(void); void linphone_gtk_unmonitor_usb(void); +gchar *linphone_gtk_get_record_path(const LinphoneAddress *address, gboolean is_conference); + diff --git a/gtk/main.c b/gtk/main.c index 94d94f66..2f34cd4d 100644 --- a/gtk/main.c +++ b/gtk/main.c @@ -750,14 +750,35 @@ static void linphone_gtk_update_call_buttons(LinphoneCall *call){ } } -gchar *linphone_gtk_get_call_record_path(LinphoneAddress *address){ +gchar *linphone_gtk_get_record_path(const LinphoneAddress *address, gboolean is_conference){ const char *dir=g_get_user_special_dir(G_USER_DIRECTORY_MUSIC); - const char *id=linphone_address_get_username(address); + const char *id="unknown"; char filename[256]={0}; - if (id==NULL) id=linphone_address_get_domain(address); - snprintf(filename,sizeof(filename)-1,"%s-%lu-%s-record.wav", - linphone_gtk_get_ui_config("title","Linphone"), - (unsigned long)time(NULL),id); + char date[64]={0}; + time_t curtime=time(NULL); + struct tm loctime; + +#ifdef WIN32 + loctime=*localtime(&curtime); +#else + localtime_r(&curtime,&loctime); +#endif + snprintf(date,sizeof(date)-1,"%i%02i%02i-%02i%02i",loctime.tm_year+1900,loctime.tm_mon+1,loctime.tm_mday, loctime.tm_hour, loctime.tm_min); + + if (address){ + id=linphone_address_get_username(address); + if (id==NULL) id=linphone_address_get_domain(address); + } + if (is_conference){ + snprintf(filename,sizeof(filename)-1,"%s-conference-%s.wav", + linphone_gtk_get_ui_config("title","Linphone"), + date); + }else{ + snprintf(filename,sizeof(filename)-1,"%s-call-%s-%s.wav", + linphone_gtk_get_ui_config("title","Linphone"), + date, + id); + } return g_build_filename(dir,filename,NULL); } @@ -768,7 +789,7 @@ static gboolean linphone_gtk_start_call_do(GtkWidget *uri_bar){ if (addr!=NULL){ LinphoneCallParams *params=linphone_core_create_default_call_parameters(lc); - gchar *record_file=linphone_gtk_get_call_record_path(addr); + gchar *record_file=linphone_gtk_get_record_path(addr,FALSE); linphone_call_params_set_record_file(params,record_file); linphone_core_invite_address_with_params(lc,addr,params); completion_add_text(GTK_ENTRY(uri_bar),entered); @@ -781,24 +802,34 @@ static gboolean linphone_gtk_start_call_do(GtkWidget *uri_bar){ return FALSE; } + +static void accept_incoming_call(LinphoneCall *call){ + LinphoneCore *lc=linphone_gtk_get_core(); + LinphoneCallParams *params=linphone_core_create_default_call_parameters(lc); + gchar *record_file=linphone_gtk_get_record_path(linphone_call_get_remote_address(call),FALSE); + linphone_call_params_set_record_file(params,record_file); + linphone_core_accept_call_with_params(lc,call,params); + linphone_call_params_destroy(params); +} + static gboolean linphone_gtk_auto_answer(LinphoneCall *call){ - if (linphone_call_get_state(call)==LinphoneCallIncomingReceived){ - linphone_core_accept_call (linphone_gtk_get_core(),call); + LinphoneCallState state=linphone_call_get_state(call); + if (state==LinphoneCallIncomingReceived || state==LinphoneCallIncomingEarlyMedia){ + accept_incoming_call(call); linphone_call_unref(call); } return FALSE; } void linphone_gtk_start_call(GtkWidget *w){ - LinphoneCore *lc=linphone_gtk_get_core(); - LinphoneCall *call; + LinphoneCall *call=linphone_gtk_get_currently_displayed_call(NULL); /*change into in-call mode, then do the work later as it might block a bit */ GtkWidget *mw=gtk_widget_get_toplevel(w); GtkWidget *uri_bar=linphone_gtk_get_widget(mw,"uribar"); + LinphoneCallState state= call ? linphone_call_get_state(call) : LinphoneCallIdle; - call=linphone_gtk_get_currently_displayed_call(NULL); - if (call!=NULL && linphone_call_get_state(call)==LinphoneCallIncomingReceived){ - linphone_core_accept_call(lc,call); + if (state == LinphoneCallIncomingReceived || state == LinphoneCallIncomingEarlyMedia){ + accept_incoming_call(call); }else{ /*immediately disable the button and delay a bit the execution the linphone_core_invite() so that we don't freeze the button. linphone_core_invite() might block for some hundreds of milliseconds*/ @@ -831,7 +862,7 @@ void linphone_gtk_decline_clicked(GtkWidget *button){ void linphone_gtk_answer_clicked(GtkWidget *button){ LinphoneCall *call=linphone_gtk_get_currently_displayed_call(NULL); if (call){ - linphone_core_accept_call(linphone_gtk_get_core(),call); + accept_incoming_call(call); linphone_gtk_show_main_window(); /* useful when the button is clicked on a notification */ } } diff --git a/gtk/main.ui b/gtk/main.ui index b42470e5..e1c8c912 100644 --- a/gtk/main.ui +++ b/gtk/main.ui @@ -215,9 +215,6 @@ True False - - - True @@ -242,9 +239,53 @@ True True end + 0 + + + + + True + False + + + gtk-media-record + True + True + True + False + True + + + + False + False + 0 + + + + + True + False + True + char + + + True + True + 1 + + + + + False + False + end 1 + + + diff --git a/gtk/propertybox.c b/gtk/propertybox.c index 5aee3f43..8481bef7 100644 --- a/gtk/propertybox.c +++ b/gtk/propertybox.c @@ -972,7 +972,8 @@ static void linphone_gtk_show_media_encryption(GtkWidget *pb){ } g_signal_connect(G_OBJECT(combo),"changed",(GCallback)linphone_gtk_media_encryption_changed,NULL); } - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(pb,"media_encryption_mandatory")),linphone_core_is_media_encryption_mandatory(lc)); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(pb,"media_encryption_mandatory")), + linphone_core_is_media_encryption_mandatory(lc)); g_object_unref(G_OBJECT(model)); } @@ -1015,10 +1016,8 @@ void linphone_gtk_show_parameters(void){ if (pb==NULL) { pb=linphone_gtk_create_window("parameters"); g_object_set_data(G_OBJECT(mw),"parameters",pb); - ms_error("linphone_gtk_show_paramters: create"); }else { gtk_widget_show(pb); - ms_error("linphone_gtk_show_parameters: show"); return; } codec_list=linphone_gtk_get_widget(pb,"codec_list"); @@ -1028,21 +1027,21 @@ void linphone_gtk_show_parameters(void){ linphone_core_ipv6_enabled(lc)); linphone_core_get_sip_transports(lc,&tr); - if (tr.tcp_port > 0) { - gtk_combo_box_set_active(GTK_COMBO_BOX(linphone_gtk_get_widget(pb,"proto_combo")), 1); - gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(pb,"proto_port")), + if (tr.tcp_port > 0) { + gtk_combo_box_set_active(GTK_COMBO_BOX(linphone_gtk_get_widget(pb,"proto_combo")), 1); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(pb,"proto_port")), tr.tcp_port); - } - else if (tr.tls_port > 0) { - gtk_combo_box_set_active(GTK_COMBO_BOX(linphone_gtk_get_widget(pb,"proto_combo")), 2); - gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(pb,"proto_port")), + } + else if (tr.tls_port > 0) { + gtk_combo_box_set_active(GTK_COMBO_BOX(linphone_gtk_get_widget(pb,"proto_combo")), 2); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(pb,"proto_port")), tr.tls_port); - } - else { - gtk_combo_box_set_active(GTK_COMBO_BOX(linphone_gtk_get_widget(pb,"proto_combo")), 0); - gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(pb,"proto_port")), + } + else { + gtk_combo_box_set_active(GTK_COMBO_BOX(linphone_gtk_get_widget(pb,"proto_combo")), 0); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(pb,"proto_port")), tr.udp_port); - } + } linphone_core_get_audio_port_range(lc, &min_port, &max_port); gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(pb, "audio_min_rtp_port")), min_port); diff --git a/gtk/update.c b/gtk/update.c old mode 100755 new mode 100644 diff --git a/linphone.kdevelop b/linphone.kdevelop deleted file mode 100644 index 2cb0437f..00000000 --- a/linphone.kdevelop +++ /dev/null @@ -1,558 +0,0 @@ - - - - Simon Morlat - simon.morlat@linphone.org - [3.1.2] - KDevCustomProject - C - - linphone - . - false - - - - - - executable - gtk-glade/linphone - - - - false - false - false - false - false - - - - *.java - *.h - *.H - *.hh - *.hxx - *.hpp - *.c - *.C - *.cc - *.cpp - *.c++ - *.cxx - - - config.h - exosip - exosip/eXosip2.h - exosip/eXosip.c - exosip/eXosip_cfg.h - exosip/eXosip.h - exosip/eXutils.c - exosip/jauth.c - exosip/jcallback.c - exosip/jcall.c - exosip/jdialog.c - exosip/jevents.c - exosip/jfreinds.c - exosip/jidentity.c - exosip/jnotify.c - exosip/jpipe.c - exosip/jpipe.h - exosip/jpublish.c - exosip/jreg.c - exosip/jrequest.c - exosip/jresponse.c - exosip/jsubscribe.c - exosip/jsubscribers.c - exosip/misc.c - exosip/sdp_offans.c - exosip/udp.c - gnome - gnome/addressbook.c - gnome/addressbook.h - gnome/applet.c - gnome/callbacks.c - gnome/callbacks.h - gnome/friends.c - gnome/friends.h - gnome/gui_utils.c - gnome/gui_utils.h - gnome/interface.c - gnome/interface.h - gnome/linphone.c - gnome/linphone.h - gnome/main.c - gnome/presence.c - gnome/presence.h - gnome/propertybox.c - gnome/propertybox.h - gnome/support.c - gnome/support.h - gsmlib - gsmlib/code.c - gsmlib/config.h - gsmlib/debug.c - gsmlib/decode.c - gsmlib/gsmadd.c - gsmlib/gsm_create.c - gsmlib/gsm_decode.c - gsmlib/gsm_destroy.c - gsmlib/gsm_encode.c - gsmlib/gsm_explode.c - gsmlib/gsm.h - gsmlib/gsm_implode.c - gsmlib/gsm_option.c - gsmlib/gsm_print.c - gsmlib/gsm_wrapper.c - gsmlib/gsm_wrapper.h - gsmlib/long_term.c - gsmlib/lpc.c - gsmlib/preprocess.c - gsmlib/private.h - gsmlib/proto.h - gsmlib/rpe.c - gsmlib/short_term.c - gsmlib/table.c - gsmlib/toast.h - gsmlib/unproto.h - gtk - gtk/addressbook.c - gtk/addressbook.h - gtk/applet.c - gtk/callbacks.c - gtk/callbacks.h - gtk/friends.c - gtk/friends.h - gtk/gui_utils.c - gtk/gui_utils.h - gtk/interface.c - gtk/interface.h - gtk/linphone.c - gtk/linphone.h - gtk/main.c - gtk/presence.c - gtk/presence.h - gtk/propertybox.c - gtk/propertybox.h - gtk/support.c - gtk/support.h - intl - intl/bindtextdom.c - intl/cat-compat.c - intl/dcgettext.c - intl/dgettext.c - intl/explodename.c - intl/finddomain.c - intl/gettext.c - intl/gettext.h - intl/gettextP.h - intl/hash-string.h - intl/intl-compat.c - intl/l10nflist.c - intl/libgettext.h - intl/loadinfo.h - intl/loadmsgcat.c - intl/localealias.c - intl/textdomain.c - lpc10-1.5 - lpc10-1.5/analys.c - lpc10-1.5/bitio.c - lpc10-1.5/bsynz.c - lpc10-1.5/chanwr.c - lpc10-1.5/dcbias.c - lpc10-1.5/decode.c - lpc10-1.5/deemp.c - lpc10-1.5/difmag.c - lpc10-1.5/dyptrk.c - lpc10-1.5/encode.c - lpc10-1.5/energy.c - lpc10-1.5/f2c.h - lpc10-1.5/f2clib.c - lpc10-1.5/ham84.c - lpc10-1.5/hp100.c - lpc10-1.5/invert.c - lpc10-1.5/irc2pc.c - lpc10-1.5/ivfilt.c - lpc10-1.5/lpc10.h - lpc10-1.5/lpc10_wrapper.c - lpc10-1.5/lpc10_wrapper.h - lpc10-1.5/lpcdec.c - lpc10-1.5/lpcenc.c - lpc10-1.5/lpcini.c - lpc10-1.5/lpfilt.c - lpc10-1.5/median.c - lpc10-1.5/mload.c - lpc10-1.5/onset.c - lpc10-1.5/pitsyn.c - lpc10-1.5/placea.c - lpc10-1.5/placev.c - lpc10-1.5/preemp.c - lpc10-1.5/prepro.c - lpc10-1.5/random.c - lpc10-1.5/rcchk.c - lpc10-1.5/synths.c - lpc10-1.5/tbdm.c - lpc10-1.5/voicin.c - lpc10-1.5/vparms.c - media_api - media_api/apitest.c - media_api/apitest.h - media_api/basiccall.c - media_api/basiccall.h - media_api/callmember.c - media_api/callmember.h - media_api/common.h - media_api/media_api.c - media_api/media_api.h - media_api/mediaflow.c - media_api/mediaflow.h - mediastreamer - mediastreamer/affine.c - mediastreamer/affine.h - mediastreamer/alsacard.c - mediastreamer/alsacard.h - mediastreamer/audiostream.c - mediastreamer/g711common.h - mediastreamer/hpuxsndcard.c - mediastreamer/jackcard.c - mediastreamer/jackcard.h - mediastreamer/mediastream.c - mediastreamer/mediastream.h - mediastreamer/msAlawdec.c - mediastreamer/msAlawdec.h - mediastreamer/msAlawenc.c - mediastreamer/msAlawenc.h - mediastreamer/msavdecoder.c - mediastreamer/msavdecoder.h - mediastreamer/msavencoder.c - mediastreamer/msavencoder.h - mediastreamer/msbuffer.c - mediastreamer/msbuffer.h - mediastreamer/ms.c - mediastreamer/mscodec.c - mediastreamer/mscodec.h - mediastreamer/mscopy.c - mediastreamer/mscopy.h - mediastreamer/msfdispatcher.c - mediastreamer/msfdispatcher.h - mediastreamer/msfifo.c - mediastreamer/msfifo.h - mediastreamer/msfilter.c - mediastreamer/msfilter.h - mediastreamer/msGSMdecoder.c - mediastreamer/msGSMdecoder.h - mediastreamer/msGSMencoder.c - mediastreamer/msGSMencoder.h - mediastreamer/ms.h - mediastreamer/msLPC10decoder.c - mediastreamer/msLPC10decoder.h - mediastreamer/msLPC10encoder.c - mediastreamer/msLPC10encoder.h - mediastreamer/msMUlawdec.c - mediastreamer/msMUlawdec.h - mediastreamer/msMUlawenc.c - mediastreamer/msMUlawenc.h - mediastreamer/msnosync.c - mediastreamer/msnosync.h - mediastreamer/msossread.c - mediastreamer/msossread.h - mediastreamer/msosswrite.c - mediastreamer/msosswrite.h - mediastreamer/msqdispatcher.c - mediastreamer/msqdispatcher.h - mediastreamer/msqueue.c - mediastreamer/msqueue.h - mediastreamer/msread.c - mediastreamer/msread.h - mediastreamer/msringplayer.c - mediastreamer/msringplayer.h - mediastreamer/msrtprecv.c - mediastreamer/msrtprecv.h - mediastreamer/msrtpsend.c - mediastreamer/msrtpsend.h - mediastreamer/mssdlout.c - mediastreamer/mssdlout.h - mediastreamer/mssmpeg.c - mediastreamer/mssmpeg.h - mediastreamer/mssoundread.c - mediastreamer/mssoundread.h - mediastreamer/mssoundwrite.c - mediastreamer/mssoundwrite.h - mediastreamer/msspeexdec.c - mediastreamer/msspeexdec.h - mediastreamer/msspeexenc.c - mediastreamer/msspeexenc.h - mediastreamer/mssync.c - mediastreamer/mssync.h - mediastreamer/mstcpclient.c - mediastreamer/mstcpclient.h - mediastreamer/mstcpserv.c - mediastreamer/mstcpserv.h - mediastreamer/mstimer.c - mediastreamer/mstimer.h - mediastreamer/mstruespeechdecoder.c - mediastreamer/mstruespeechdecoder.h - mediastreamer/mstruespeechencoder.c - mediastreamer/mstruespeechencoder.h - mediastreamer/msutils.h - mediastreamer/msv4l.c - mediastreamer/msv4l.h - mediastreamer/msvideooutput.c - mediastreamer/msvideooutput.h - mediastreamer/msvideosource.c - mediastreamer/msvideosource.h - mediastreamer/mswrite.c - mediastreamer/mswrite.h - mediastreamer/msxine.c - mediastreamer/msxine.h - mediastreamer/osscard.c - mediastreamer/osscard.h - mediastreamer/rfc2429.h - mediastreamer/ring_test.c - mediastreamer/sndcard.c - mediastreamer/sndcard.h - mediastreamer/test_alaw.c - mediastreamer/test.c - mediastreamer/test_gsm.c - mediastreamer/test_lpc10.c - mediastreamer/test_mulaw.c - mediastreamer/test_rtprecv.c - mediastreamer/test_smpeg.c - mediastreamer/test_speex.c - mediastreamer/test_truespeech.c - mediastreamer/test_v4l.c - mediastreamer/test_videostream.c - mediastreamer/test_xine.c - mediastreamer/videoclient.c - mediastreamer/videoserver.c - mediastreamer/videostream.c - mediastreamer/waveheader.h - po - po/cat-id-tbl.c - win32acm - win32acm/afl.c - win32acm/com.h - win32acm/config.h - win32acm/cpudetect.c - win32acm/cpudetect.h - win32acm/cputable.h - win32acm/driver.c - win32acm/driver.h - win32acm/elfdll.c - win32acm/ext.c - win32acm/ext.h - win32acm/ldt_keeper.c - win32acm/ldt_keeper.h - win32acm/loader.h - win32acm/module.c - win32acm/mp_msg.c - win32acm/mp_msg.h - win32acm/pe_image.c - win32acm/pe_resource.c - win32acm/registry.c - win32acm/registry.h - win32acm/resource.c - win32acm/test_truespeech.c - win32acm/win32.c - win32acm/win32codec.c - win32acm/win32codec.h - win32acm/win32.h - win32acm/wine - win32acm/wine/basetsd.h - win32acm/wine/debugtools.h - win32acm/wine/driver.h - win32acm/wine/elfdll.h - win32acm/wine/heap.h - win32acm/wine/ldt.h - win32acm/wine/mmreg.h - win32acm/wine/module.h - win32acm/wine/msacmdrv.h - win32acm/wine/msacm.h - win32acm/wine/ntdef.h - win32acm/wine/pe_image.h - win32acm/wine/poppack.h - win32acm/wine/pshpack1.h - win32acm/wine/pshpack2.h - win32acm/wine/pshpack4.h - win32acm/wine/pshpack8.h - win32acm/wine/vfw.h - win32acm/wine/winbase.h - win32acm/wine/windef.h - win32acm/wine/windows.h - win32acm/wine/winerror.h - win32acm/wine/winestring.h - win32acm/wine/winnt.h - win32acm/wine/winreg.h - win32acm/wine/winuser.h - win32acm/wineacm.h - win32acm/wrapper.h - builddate.h - - - make - - - - 0 - - - - default - - - - - - true - 0 - 0 - false - - - - default - - - - - - - - - - - - - true - false - false - false - - - false - true - 10 - - - - - ada - ada_bugs_gcc - bash - bash_bugs - clanlib - fortran_bugs_gcc - gnome1 - gnustep - gtk - gtk_bugs - haskell - haskell_bugs_ghc - java_bugs_gcc - java_bugs_sun - kde2book - libstdc++ - opengl - pascal_bugs_fp - php - php_bugs - perl - perl_bugs - python - python_bugs - qt-kdev3 - ruby - ruby_bugs - sdl - stl - sw - w3c-dom-level2-html - w3c-svg - w3c-uaag10 - wxwidgets_bugs - - - Guide to the Qt Translation Tools - Qt Assistant Manual - Qt Designer Manual - Qt Reference Documentation - qmake User Guide - - - KDE Libraries (Doxygen) - - - - - - - - - - - - false - 3 - 3 - - EmbeddedKDevDesigner - - - - - - - false - true - true - 250 - 400 - 250 - false - 0 - true - true - false - std=_GLIBCXX_STD;__gnu_cxx=std - true - false - false - false - false - true - true - false - .; - - - - set - m_,_ - theValue - true - true - - - false - true - Vertical - - - - - false - false - - - *.o,*.lo,CVS - false - - - - - .h - .cpp - - -