From fa62fcd320feb6486b86acfab930efc5f5f584e4 Mon Sep 17 00:00:00 2001 From: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com> Date: Fri, 30 May 2008 17:29:01 -0400 Subject: [PATCH] Enable/Disable pulseaudio volume control from the GUI --- sflphone-gtk/src/audioconf.c | 60 +++--- sflphone-gtk/src/audioconf.h | 1 + sflphone-gtk/src/configurationmanager-glue.h | 75 +++++++ sflphone-gtk/src/configwindow.c | 215 ++++--------------- sflphone-gtk/src/dbus.c | 26 +++ sflphone-gtk/src/dbus.h | 11 + src/audio/alsalayer.cpp | 4 +- src/audio/alsalayer.h | 17 ++ src/audio/audiolayer.h | 1 + src/audio/audiostream.cpp | 8 +- src/audio/audiostream.h | 7 +- src/audio/pulselayer.cpp | 48 ++++- src/audio/pulselayer.h | 134 +++++++++--- src/dbus/configurationmanager-glue.h | 33 +++ src/dbus/configurationmanager-introspec.xml | 7 + src/dbus/configurationmanager.cpp | 13 ++ src/dbus/configurationmanager.h | 2 + src/managerimpl.cpp | 21 +- src/managerimpl.h | 4 + src/user_cfg.h | 2 + 20 files changed, 431 insertions(+), 258 deletions(-) diff --git a/sflphone-gtk/src/audioconf.c b/sflphone-gtk/src/audioconf.c index 374a4f33c6..3e194d2f79 100644 --- a/sflphone-gtk/src/audioconf.c +++ b/sflphone-gtk/src/audioconf.c @@ -19,7 +19,6 @@ #include <audioconf.h> - GtkListStore *pluginlist; GtkListStore *outputlist; GtkListStore *inputlist; @@ -128,7 +127,6 @@ config_window_fill_output_audio_device_list() gtk_list_store_set(outputlist, &iter, 0, *list, 1, index, -1); c++; } - } /** @@ -205,35 +203,35 @@ config_window_fill_input_audio_device_list() select_active_input_audio_device() { if( SHOW_ALSA_CONF) -{ - - GtkTreeModel* model; - GtkTreeIter iter; - gchar** devices; - int currentDeviceIndex; - int deviceIndex; + { - // Select active input device on server - devices = dbus_get_current_audio_devices_index(); - currentDeviceIndex = atoi(devices[1]); - model = gtk_combo_box_get_model(GTK_COMBO_BOX(input)); + GtkTreeModel* model; + GtkTreeIter iter; + gchar** devices; + int currentDeviceIndex; + int deviceIndex; - // Find the currently set input device - gtk_tree_model_get_iter_first(model, &iter); - do { - gtk_tree_model_get(model, &iter, 1, &deviceIndex, -1); - if(deviceIndex == currentDeviceIndex) - { - // Set current iteration the active one - gtk_combo_box_set_active_iter(GTK_COMBO_BOX(input), &iter); - return; - } - } while(gtk_tree_model_iter_next(model, &iter)); + // Select active input device on server + devices = dbus_get_current_audio_devices_index(); + currentDeviceIndex = atoi(devices[1]); + model = gtk_combo_box_get_model(GTK_COMBO_BOX(input)); - // No index was found, select first one - g_print("Warning : No active input device found"); - gtk_combo_box_set_active(GTK_COMBO_BOX(input), 0); -} + // Find the currently set input device + gtk_tree_model_get_iter_first(model, &iter); + do { + gtk_tree_model_get(model, &iter, 1, &deviceIndex, -1); + if(deviceIndex == currentDeviceIndex) + { + // Set current iteration the active one + gtk_combo_box_set_active_iter(GTK_COMBO_BOX(input), &iter); + return; + } + } while(gtk_tree_model_iter_next(model, &iter)); + + // No index was found, select first one + g_print("Warning : No active input device found"); + gtk_combo_box_set_active(GTK_COMBO_BOX(input), 0); + } } /** @@ -291,7 +289,6 @@ select_active_output_audio_plugin() // No index was found, select first one g_print("Warning : No active output device found\n"); gtk_combo_box_set_active(GTK_COMBO_BOX(plugin), 0); - //update_combo_box("default"); } @@ -407,7 +404,6 @@ codec_active_toggled(GtkCellRendererToggle *renderer, gchar *path, gpointer data codec_list_update_to_daemon(); } - /** * Move codec in list depending on direction and selected codec and * update changes in the daemon list and the configuration files @@ -756,7 +752,6 @@ GtkWidget* ringtones_box() return ret; } - GtkWidget* create_audio_configuration() { // Main widget @@ -787,10 +782,11 @@ GtkWidget* create_audio_configuration() alsabox = alsa_box(); gtk_container_add( GTK_CONTAINER(alsa_conf) , alsabox ); } - + // Box for the codecs codecs_conf = gtk_frame_new(_("Codecs")); gtk_box_pack_start(GTK_BOX(ret), codecs_conf, FALSE, FALSE, 0); + gtk_widget_set_size_request(GTK_WIDGET(codecs_conf), -1, 200); gtk_widget_show( codecs_conf ); box = codecs_box(); gtk_container_add( GTK_CONTAINER(codecs_conf) , box ); diff --git a/sflphone-gtk/src/audioconf.h b/sflphone-gtk/src/audioconf.h index ab1f8411be..26e28aa771 100644 --- a/sflphone-gtk/src/audioconf.h +++ b/sflphone-gtk/src/audioconf.h @@ -26,6 +26,7 @@ GtkWidget* create_audio_configuration(); GtkWidget* api_box(); GtkWidget* alsa_box(); +GtkWidget* pulse_box(); GtkWidget* codecs_box(); GtkWidget* ringtone_box(); diff --git a/sflphone-gtk/src/configurationmanager-glue.h b/sflphone-gtk/src/configurationmanager-glue.h index 54d2b22e17..9e54d25286 100644 --- a/sflphone-gtk/src/configurationmanager-glue.h +++ b/sflphone-gtk/src/configurationmanager-glue.h @@ -1851,6 +1851,81 @@ org_sflphone_SFLphone_ConfigurationManager_switch_popup_mode_async (DBusGProxy * stuff->userdata = userdata; return dbus_g_proxy_begin_call (proxy, "switchPopupMode", org_sflphone_SFLphone_ConfigurationManager_switch_popup_mode_async_callback, stuff, g_free, G_TYPE_INVALID); } +static +#ifdef G_HAVE_INLINE +inline +#endif +gboolean +org_sflphone_SFLphone_ConfigurationManager_set_pulse_app_volume_control (DBusGProxy *proxy, GError **error) + +{ + return dbus_g_proxy_call (proxy, "setPulseAppVolumeControl", error, G_TYPE_INVALID, G_TYPE_INVALID); +} + +typedef void (*org_sflphone_SFLphone_ConfigurationManager_set_pulse_app_volume_control_reply) (DBusGProxy *proxy, GError *error, gpointer userdata); + +static void +org_sflphone_SFLphone_ConfigurationManager_set_pulse_app_volume_control_async_callback (DBusGProxy *proxy, DBusGProxyCall *call, void *user_data) +{ + DBusGAsyncData *data = (DBusGAsyncData*) user_data; + GError *error = NULL; + dbus_g_proxy_end_call (proxy, call, &error, G_TYPE_INVALID); + (*(org_sflphone_SFLphone_ConfigurationManager_set_pulse_app_volume_control_reply)data->cb) (proxy, error, data->userdata); + return; +} + +static +#ifdef G_HAVE_INLINE +inline +#endif +DBusGProxyCall* +org_sflphone_SFLphone_ConfigurationManager_set_pulse_app_volume_control_async (DBusGProxy *proxy, org_sflphone_SFLphone_ConfigurationManager_set_pulse_app_volume_control_reply callback, gpointer userdata) + +{ + DBusGAsyncData *stuff; + stuff = g_new (DBusGAsyncData, 1); + stuff->cb = G_CALLBACK (callback); + stuff->userdata = userdata; + return dbus_g_proxy_begin_call (proxy, "setPulseAppVolumeControl", org_sflphone_SFLphone_ConfigurationManager_set_pulse_app_volume_control_async_callback, stuff, g_free, G_TYPE_INVALID); +} +static +#ifdef G_HAVE_INLINE +inline +#endif +gboolean +org_sflphone_SFLphone_ConfigurationManager_get_pulse_app_volume_control (DBusGProxy *proxy, gint* OUT_state, GError **error) + +{ + return dbus_g_proxy_call (proxy, "getPulseAppVolumeControl", error, G_TYPE_INVALID, G_TYPE_INT, OUT_state, G_TYPE_INVALID); +} + +typedef void (*org_sflphone_SFLphone_ConfigurationManager_get_pulse_app_volume_control_reply) (DBusGProxy *proxy, gint OUT_state, GError *error, gpointer userdata); + +static void +org_sflphone_SFLphone_ConfigurationManager_get_pulse_app_volume_control_async_callback (DBusGProxy *proxy, DBusGProxyCall *call, void *user_data) +{ + DBusGAsyncData *data = (DBusGAsyncData*) user_data; + GError *error = NULL; + gint OUT_state; + dbus_g_proxy_end_call (proxy, call, &error, G_TYPE_INT, &OUT_state, G_TYPE_INVALID); + (*(org_sflphone_SFLphone_ConfigurationManager_get_pulse_app_volume_control_reply)data->cb) (proxy, OUT_state, error, data->userdata); + return; +} + +static +#ifdef G_HAVE_INLINE +inline +#endif +DBusGProxyCall* +org_sflphone_SFLphone_ConfigurationManager_get_pulse_app_volume_control_async (DBusGProxy *proxy, org_sflphone_SFLphone_ConfigurationManager_get_pulse_app_volume_control_reply callback, gpointer userdata) + +{ + DBusGAsyncData *stuff; + stuff = g_new (DBusGAsyncData, 1); + stuff->cb = G_CALLBACK (callback); + stuff->userdata = userdata; + return dbus_g_proxy_begin_call (proxy, "getPulseAppVolumeControl", org_sflphone_SFLphone_ConfigurationManager_get_pulse_app_volume_control_async_callback, stuff, g_free, G_TYPE_INVALID); +} #endif /* defined DBUS_GLIB_CLIENT_WRAPPERS_org_sflphone_SFLphone_ConfigurationManager */ G_END_DECLS diff --git a/sflphone-gtk/src/configwindow.c b/sflphone-gtk/src/configwindow.c index 471dcb1b58..090c4d6551 100644 --- a/sflphone-gtk/src/configwindow.c +++ b/sflphone-gtk/src/configwindow.c @@ -323,7 +323,11 @@ account_move_down(GtkButton *button, gpointer data) account_move(FALSE, data); } - +static void +set_pulse_app_volume_control( void ) +{ + dbus_set_pulse_app_volume_control(); +} /** * Account settings tab @@ -442,165 +446,6 @@ create_accounts_tab() return ret; } -/** - * Audio settings tab - */ -GtkWidget* -create_audio_tab () -{ -/* GtkWidget *ret; - - GtkWidget *deviceFrame; - GtkWidget *deviceBox; - GtkWidget *deviceTable; - GtkWidget *codecFrame; - GtkWidget *codecBox; - GtkWidget *enableTone; - GtkWidget *fileChooser; - - GtkWidget *titleLabel; - GtkWidget *refreshButton; - GtkCellRenderer *renderer; - - GtkWidget *codecTable; - - // Main widget - ret = gtk_vbox_new(FALSE, 10); - gtk_container_set_border_width(GTK_CONTAINER(ret), 10); - - // Device section label - deviceFrame = gtk_frame_new(_("Devices")); - gtk_box_pack_start(GTK_BOX(ret), deviceFrame, FALSE, FALSE, 0); - gtk_widget_show( deviceFrame ); - - - // Main device widget - deviceBox = gtk_hbox_new(FALSE, 10); - gtk_widget_show( deviceBox ); - - gtk_container_add( GTK_CONTAINER(deviceFrame) , deviceBox); - - // Main device widget - deviceTable = gtk_table_new(4, 3, FALSE); - gtk_table_set_col_spacing(GTK_TABLE(deviceTable), 0, 40); - gtk_box_pack_start(GTK_BOX(deviceBox), deviceTable, TRUE, TRUE, 0); - gtk_widget_show(deviceTable); - - // Device : Audio manager - // Create title label - - titleLabel = gtk_label_new("Alsa plug-IN:"); - gtk_misc_set_alignment(GTK_MISC(titleLabel), 0, 0.5); - gtk_table_attach(GTK_TABLE(deviceTable), titleLabel, 0, 1, 0, 1, GTK_FILL | GTK_EXPAND, GTK_SHRINK, 0, 0); - gtk_widget_show(titleLabel); - // Set choices of audio managers - inputAudioPluginStore = gtk_list_store_new(1, G_TYPE_STRING); - config_window_fill_input_audio_plugin_list(); - comboBox = gtk_combo_box_new_with_model(GTK_TREE_MODEL(inputAudioPluginStore)); - gtk_combo_box_set_active(GTK_COMBO_BOX(comboBox), 0); - gtk_label_set_mnemonic_widget(GTK_LABEL(titleLabel), comboBox); - g_signal_connect(G_OBJECT(comboBox), "changed", G_CALLBACK(select_input_audio_plugin), comboBox); - - // Set rendering - renderer = gtk_cell_renderer_text_new(); - gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(comboBox), renderer, TRUE); - gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(comboBox), renderer, "text", 0, NULL); - gtk_table_attach(GTK_TABLE(deviceTable), comboBox, 1, 2, 0, 1, GTK_FILL | GTK_EXPAND, GTK_SHRINK, 0, 0); - gtk_widget_show(comboBox); - - // Create title label - titleLabel = gtk_label_new(_("ALSA plugin")); - gtk_misc_set_alignment(GTK_MISC(titleLabel), 0, 0.5); - gtk_table_attach(GTK_TABLE(deviceTable), titleLabel, 1, 2, 0, 1, GTK_FILL | GTK_EXPAND, GTK_SHRINK, 0, 0); - gtk_widget_show(titleLabel); - // Set choices of audio managers - outputAudioPluginStore = gtk_list_store_new(1, G_TYPE_STRING); - config_window_fill_output_audio_plugin_list(); - pluginComboBox = gtk_combo_box_new_with_model(GTK_TREE_MODEL(outputAudioPluginStore)); - select_active_output_audio_plugin(); - gtk_label_set_mnemonic_widget(GTK_LABEL(titleLabel), pluginComboBox); - g_signal_connect(G_OBJECT(pluginComboBox), "changed", G_CALLBACK(select_output_audio_plugin), pluginComboBox); - - // Set rendering - renderer = gtk_cell_renderer_text_new(); - gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(pluginComboBox), renderer, TRUE); - gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(pluginComboBox), renderer, "text", 0, NULL); - gtk_table_attach(GTK_TABLE(deviceTable), pluginComboBox, 2, 3, 0, 1, GTK_FILL | GTK_EXPAND, GTK_SHRINK, 0, 0); - gtk_widget_show(pluginComboBox); - - // Device : Output device - // Create title label - titleLabel = gtk_label_new(_("Output peripheral")); - gtk_misc_set_alignment(GTK_MISC(titleLabel), 0, 0.5); - gtk_table_attach(GTK_TABLE(deviceTable), titleLabel, 1, 2, 1, 2, GTK_FILL | GTK_EXPAND, GTK_SHRINK, 0, 0); - gtk_widget_show(titleLabel); - // Set choices of output devices - outputAudioDeviceManagerStore = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_INT); - config_window_fill_output_audio_device_list(); - outputDeviceComboBox = gtk_combo_box_new_with_model(GTK_TREE_MODEL(outputAudioDeviceManagerStore)); - select_active_output_audio_device(); - gtk_label_set_mnemonic_widget(GTK_LABEL(titleLabel), outputDeviceComboBox); - //g_signal_connect(G_OBJECT(outputDeviceComboBox), "changed", G_CALLBACK(select_audio_output_device), outputDeviceComboBox); - - // Set rendering - renderer = gtk_cell_renderer_text_new(); - gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(outputDeviceComboBox), renderer, TRUE); - gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(outputDeviceComboBox), renderer, "text", 0, NULL); - gtk_table_attach(GTK_TABLE(deviceTable), outputDeviceComboBox, 2, 3, 1, 2, GTK_FILL | GTK_EXPAND, GTK_SHRINK, 0, 0); - gtk_widget_show(outputDeviceComboBox); - - // Device : Input device - // Create title label - titleLabel = gtk_label_new(_("Input peripheral")); - gtk_misc_set_alignment(GTK_MISC(titleLabel), 0, 0.5); - gtk_table_attach(GTK_TABLE(deviceTable), titleLabel, 1, 2, 2, 3, GTK_FILL | GTK_EXPAND, GTK_SHRINK, 0, 0); - gtk_widget_show(titleLabel); - // Set choices of output devices - inputAudioDeviceManagerStore = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_INT); - config_window_fill_input_audio_device_list(); - inputDeviceComboBox = gtk_combo_box_new_with_model(GTK_TREE_MODEL(inputAudioDeviceManagerStore)); - select_active_input_audio_device(); - gtk_label_set_mnemonic_widget(GTK_LABEL(titleLabel), inputDeviceComboBox); - //g_signal_connect(G_OBJECT(inputDeviceComboBox), "changed", G_CALLBACK(select_audio_input_device), inputDeviceComboBox); - - // Set rendering - renderer = gtk_cell_renderer_text_new(); - gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(inputDeviceComboBox), renderer, TRUE); - gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(inputDeviceComboBox), renderer, "text", 0, NULL); - gtk_table_attach(GTK_TABLE(deviceTable), inputDeviceComboBox, 2, 3, 2, 3, GTK_FILL | GTK_EXPAND, GTK_SHRINK, 0, 0); - gtk_widget_show(inputDeviceComboBox); - - // Create detect button - refreshButton = gtk_button_new_with_label(_("Detect all")); - gtk_button_set_image(GTK_BUTTON(refreshButton), gtk_image_new_from_stock(GTK_STOCK_REFRESH, GTK_ICON_SIZE_BUTTON)); - gtk_table_attach(GTK_TABLE(deviceTable), refreshButton, 2, 3, 3, 4, GTK_EXPAND, GTK_EXPAND, 0, 0); - // Set event on selection - g_signal_connect(G_OBJECT(refreshButton), "clicked", G_CALLBACK(detect_all_audio_settings), NULL); - - //select_active_output_audio_plugin(); - // Codec section label - codecFrame = gtk_frame_new(_("Codecs")); - gtk_box_pack_start(GTK_BOX(ret), codecFrame, FALSE, FALSE, 0); - gtk_widget_show(codecFrame); - - // Main codec widget - codecBox = gtk_hbox_new(FALSE, 10); - gtk_widget_show(codecBox); - - gtk_container_add( GTK_CONTAINER( codecFrame ) , codecBox ); - // Codec : List - codecTable = create_codec_table(); - gtk_widget_set_size_request(GTK_WIDGET(codecTable), -1, 150); - gtk_box_pack_start(GTK_BOX(codecBox), codecTable, TRUE, TRUE, 0); - gtk_widget_show(codecTable); -*/ - - // Show all - //gtk_widget_show_all(ret); - - //return ret; -} - GtkWidget* create_general_settings () { @@ -609,14 +454,14 @@ create_general_settings () GtkWidget *notifFrame; GtkWidget *notifBox; GtkWidget *notifAll; - GtkWidget *notifMails; + GtkWidget *widg; GtkWidget *trayFrame; GtkWidget *trayBox; GtkWidget *trayItem; - GtkWidget *historyFrame; - GtkWidget *historyBox; + GtkWidget *frame; + GtkWidget *vbox; GtkWidget *value; GtkWidget *label; GtkWidget *cleanButton; @@ -639,10 +484,10 @@ create_general_settings () gtk_box_pack_start( GTK_BOX(notifBox) , notifAll , TRUE , TRUE , 1); g_signal_connect(G_OBJECT( notifAll ) , "clicked" , G_CALLBACK( set_notif_level ) , NULL ); - notifMails = gtk_check_button_new_with_mnemonic( _("_Notify voice mails")); - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(notifMails), dbus_get_mail_notify() ); - gtk_box_pack_start( GTK_BOX(notifBox) , notifMails , TRUE , TRUE , 1); - g_signal_connect(G_OBJECT( notifMails ) , "clicked" , G_CALLBACK( set_mail_notif ) , NULL); + widg = gtk_check_button_new_with_mnemonic( _("_Notify voice mails")); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(widg), dbus_get_mail_notify() ); + gtk_box_pack_start( GTK_BOX(notifBox) , widg , TRUE , TRUE , 1); + g_signal_connect(G_OBJECT( widg ) , "clicked" , G_CALLBACK( set_mail_notif ) , NULL); // System Tray option frame trayFrame = gtk_frame_new(_("System Tray Icon")); @@ -667,29 +512,44 @@ create_general_settings () gtk_box_pack_start( GTK_BOX(trayBox) , trayItem , TRUE , TRUE , 1); g_signal_connect(G_OBJECT( trayItem ) , "clicked" , G_CALLBACK( start_hidden ) , NULL); - historyFrame = gtk_frame_new(_("Calls History")); - gtk_box_pack_start(GTK_BOX(ret), historyFrame, FALSE, FALSE, 0); - gtk_widget_show( historyFrame ); + /** HISTORY CONFIGURATION */ + frame = gtk_frame_new(_("Calls History")); + gtk_box_pack_start(GTK_BOX(ret), frame, FALSE, FALSE, 0); + gtk_widget_show( frame ); - historyBox = gtk_vbox_new(FALSE, 10); - gtk_widget_show( historyBox ); - gtk_container_add( GTK_CONTAINER(historyFrame) , historyBox); + vbox = gtk_vbox_new(FALSE, 10); + gtk_widget_show( vbox ); + gtk_container_add( GTK_CONTAINER(frame) , vbox); label = gtk_label_new_with_mnemonic(_("_Maximum number of calls")); - gtk_box_pack_start( GTK_BOX(historyBox) , label , TRUE , TRUE , 0); + gtk_box_pack_start( GTK_BOX(vbox) , label , TRUE , TRUE , 0); value = gtk_hscale_new_with_range(0.0 , 50.0 , 5.0); gtk_label_set_mnemonic_widget (GTK_LABEL (label), value); gtk_scale_set_digits( GTK_SCALE(value) , 0); gtk_scale_set_value_pos( GTK_SCALE(value) , GTK_POS_RIGHT); gtk_range_set_value( GTK_RANGE( value ) , dbus_get_max_calls()); - gtk_box_pack_start( GTK_BOX(historyBox) , value , TRUE , TRUE , 0); + gtk_box_pack_start( GTK_BOX(vbox) , value , TRUE , TRUE , 0); g_signal_connect( G_OBJECT( value) , "value-changed" , G_CALLBACK( update_max_value ) , NULL); cleanButton = gtk_button_new_from_stock( GTK_STOCK_CLEAR ); - gtk_box_pack_end( GTK_BOX(historyBox) , cleanButton , FALSE , TRUE , 0); + gtk_box_pack_end( GTK_BOX(vbox) , cleanButton , FALSE , TRUE , 0); g_signal_connect( G_OBJECT( cleanButton ) , "clicked" , G_CALLBACK( clean_history ) , NULL); + /** PULSEAUDIO CONFIGURATION */ + frame = gtk_frame_new( _("PulseAudio sound server")); + gtk_box_pack_start(GTK_BOX(ret), frame, FALSE, FALSE, 0); + gtk_widget_show( frame ); + + vbox = gtk_vbox_new(FALSE, 10); + gtk_widget_show( vbox ); + gtk_container_add( GTK_CONTAINER(frame) , vbox); + + widg = gtk_check_button_new_with_mnemonic( _("_Control running applications's volume")); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(widg), dbus_get_pulse_app_volume_control() ); + gtk_box_pack_start( GTK_BOX(vbox) , widg , TRUE , TRUE , 1); + g_signal_connect(G_OBJECT( widg ) , "clicked" , G_CALLBACK( set_pulse_app_volume_control ) , NULL); + gtk_widget_show_all(ret); return ret; @@ -732,7 +592,6 @@ show_config_window () gtk_notebook_page_num(GTK_NOTEBOOK(notebook), tab); // Audio tab - //tab = create_audio_tab(); tab = create_audio_configuration(); gtk_notebook_append_page(GTK_NOTEBOOK(notebook), tab, gtk_label_new(_("Audio Settings"))); gtk_notebook_page_num(GTK_NOTEBOOK(notebook), tab); @@ -740,8 +599,6 @@ show_config_window () gtk_notebook_set_current_page( GTK_NOTEBOOK( notebook) , 1); gtk_dialog_run(dialog); - //gtk_widget_show( GTK_WIDGET(dialog) ); - //g_signal_connect_swapped( dialog , "response" , G_CALLBACK( gtk_widget_destroy ), dialog ); dialogOpen = FALSE; diff --git a/sflphone-gtk/src/dbus.c b/sflphone-gtk/src/dbus.c index b1487c896e..0d42a41e6b 100644 --- a/sflphone-gtk/src/dbus.c +++ b/sflphone-gtk/src/dbus.c @@ -1456,3 +1456,29 @@ dbus_get_audio_manager( void ) return api; } + +void +dbus_set_pulse_app_volume_control( void ) +{ + GError* error = NULL; + org_sflphone_SFLphone_ConfigurationManager_set_pulse_app_volume_control( + configurationManagerProxy, + &error); + if(error) + { + g_error_free(error); + } +} + +int +dbus_get_pulse_app_volume_control( void ) +{ + int state; + GError* error = NULL; + org_sflphone_SFLphone_ConfigurationManager_get_pulse_app_volume_control( + configurationManagerProxy, + &state, + &error); + return state; +} + diff --git a/sflphone-gtk/src/dbus.h b/sflphone-gtk/src/dbus.h index af5ebe51e3..34e6b5f000 100644 --- a/sflphone-gtk/src/dbus.h +++ b/sflphone-gtk/src/dbus.h @@ -267,6 +267,17 @@ int dbus_is_ringtone_enabled( void ); */ void dbus_ringtone_enabled( void ); +/** + * ConfigurationManager - Set PA behaviour for the other sound streams + * Inverse current value + */ +void dbus_set_pulse_app_volume_control( void ); + +/** + * ConfigurationManager - Get PA behaviour for the other sound streams + */ +int dbus_get_pulse_app_volume_control( void ); + /** * ConfigurationManager - Get the ringtone * @return gchar* The file name selected as a ringtone diff --git a/src/audio/alsalayer.cpp b/src/audio/alsalayer.cpp index c1ea3e63e0..c8d735969d 100644 --- a/src/audio/alsalayer.cpp +++ b/src/audio/alsalayer.cpp @@ -221,8 +221,8 @@ AlsaLayer::isStreamStopped (void) } -void -AlsaLayer::reducePulseAppsVolume( void ){} +void AlsaLayer::reducePulseAppsVolume( void ){} +void AlsaLayer::restorePulseAppsVolume( void ){} ////////////////////////////////////////////////////////////////////////////////////////////// ///////////////// ALSA PRIVATE FUNCTIONS //////////////////////////////////////////////// diff --git a/src/audio/alsalayer.h b/src/audio/alsalayer.h index 2b82bbe11c..efa6125748 100644 --- a/src/audio/alsalayer.h +++ b/src/audio/alsalayer.h @@ -181,9 +181,26 @@ class AlsaLayer : public AudioLayer { */ std::string getAudioPlugin( void ) { return _audioPlugin; } + /** + * UNUSED in ALSA layer + */ int putInCache( char code, void *buffer, int toCopy ); + + /** + * UNUSED in ALSA layer + */ int putMain(void* buffer, int toCopy); + + /** + * UNUSED in ALSA layer + */ void reducePulseAppsVolume( void ); + + /** + * UNUSED in ALSA layer + */ + void restorePulseAppsVolume( void ); + private: /** diff --git a/src/audio/audiolayer.h b/src/audio/audiolayer.h index 0b0f768167..f162ff6e50 100644 --- a/src/audio/audiolayer.h +++ b/src/audio/audiolayer.h @@ -184,6 +184,7 @@ class AudioLayer { virtual std::string getAudioPlugin( void ) = 0; virtual void reducePulseAppsVolume( void ) = 0; + virtual void restorePulseAppsVolume( void ) = 0; /** * Write accessor to the error state diff --git a/src/audio/audiostream.cpp b/src/audio/audiostream.cpp index 1f57b2f174..a9f6e7345a 100644 --- a/src/audio/audiostream.cpp +++ b/src/audio/audiostream.cpp @@ -21,7 +21,7 @@ static pa_channel_map channel_map ; -AudioStream::AudioStream( pa_context* context, int type, std::string desc ) +AudioStream::AudioStream( pa_context* context, int type, std::string desc, double vol ) { _streamType = type; _streamDescription = desc; @@ -30,8 +30,8 @@ AudioStream::AudioStream( pa_context* context, int type, std::string desc ) sample_spec.channels = 1; channel_map.channels = 1; flag = PA_STREAM_AUTO_TIMING_UPDATE ; - volume = PA_VOLUME_NORM; - + _volume = PA_VOLUME_NORM * vol / 100 ; + _audiostream = createStream( context ); } @@ -87,7 +87,7 @@ AudioStream::createStream( pa_context* c ) if( _streamType == PLAYBACK_STREAM ){ pa_stream_connect_playback( s , NULL , NULL , PA_STREAM_INTERPOLATE_TIMING, - pa_cvolume_set(&cv, sample_spec.channels , volume) , NULL ); + pa_cvolume_set(&cv, sample_spec.channels , _volume) , NULL ); } else if( _streamType == CAPTURE_STREAM ){ pa_stream_connect_record( s , NULL , NULL , PA_STREAM_START_CORKED ); diff --git a/src/audio/audiostream.h b/src/audio/audiostream.h index d31c2df930..16bab21ec4 100644 --- a/src/audio/audiostream.h +++ b/src/audio/audiostream.h @@ -45,7 +45,7 @@ class AudioStream { * @param type The type of audio stream * @param desc The stream name */ - AudioStream(pa_context* context , int type, std::string desc); + AudioStream(pa_context* context , int type, std::string desc, double vol); /** * Destructor @@ -85,6 +85,9 @@ class AudioStream { */ std::string getStreamName( void ) { return _streamDescription; } + void setVolume( double pc ); + pa_volume_t getVolume( void ) { return _volume; } + private: /** * Create the audio stream into the given context @@ -128,7 +131,7 @@ class AudioStream { */ pa_stream_flags_t flag; pa_sample_spec sample_spec ; - pa_volume_t volume; + pa_volume_t _volume; }; diff --git a/src/audio/pulselayer.cpp b/src/audio/pulselayer.cpp index 6dfd1fe27c..a34f1f99c5 100644 --- a/src/audio/pulselayer.cpp +++ b/src/audio/pulselayer.cpp @@ -102,13 +102,13 @@ void PulseLayer::context_state_callback( pa_context* c, void* user_data ) void PulseLayer::createStreams( pa_context* c ) { - playback = new AudioStream(c, PLAYBACK_STREAM, "SFLphone out"); + playback = new AudioStream(c, PLAYBACK_STREAM, "SFLphone out", _manager->getSpkrVolume()); pa_stream_set_write_callback( playback->pulseStream() , audioCallback, this); //pa_stream_set_overflow_callback( playback , overflow , this); - record = new AudioStream(c, CAPTURE_STREAM, "SFLphone in"); + record = new AudioStream(c, CAPTURE_STREAM, "SFLphone in", _manager->getMicVolume()); pa_stream_set_read_callback( record->pulseStream() , audioCallback, this); //pa_stream_set_underflow_callback( record , underflow , this); - cache = new AudioStream(c, UPLOAD_STREAM, "Cache samples"); + cache = new AudioStream(c, UPLOAD_STREAM, "Cache samples", _manager->getSpkrVolume()); pa_threaded_mainloop_signal(m , 0); } @@ -119,10 +119,6 @@ PulseLayer::openDevice(int indexIn, int indexOut, int sampleRate, int frameSize _sampleRate = sampleRate; _frameSize = frameSize; - _debug(" Setting PulseLayer: device in=%2d, out=%2d\n", indexIn, indexOut); - _debug(" : nb channel in=%2d, out=%2d\n", _inChannel, _outChannel); - _debug(" : sample rate=%5d\n", _sampleRate ); - m = pa_threaded_mainloop_new(); assert(m); @@ -267,6 +263,8 @@ PulseLayer::processData( void ) int urgentAvail; // number of data right and data left int normalAvail; // number of data right and data left + + // Handle the mic also if( (record->pulseStream()) && pa_stream_get_state( record->pulseStream()) == PA_STREAM_READY) { @@ -344,7 +342,7 @@ static void retrieve_client_list(pa_context *c, const pa_client_info *i, int eol _debug("\t\tDriver : %s\n" , i->driver); } -static void retrieve_sink_list(pa_context *c, const pa_sink_input_info *i, int eol, void *userdata) +static void reduce_sink_list(pa_context *c, const pa_sink_input_info *i, int eol, void *userdata) { PulseLayer* pulse = (PulseLayer*) userdata; AudioStream* s = pulse->getPlaybackStream(); @@ -360,10 +358,32 @@ static void retrieve_sink_list(pa_context *c, const pa_sink_input_info *i, int e } } +static void restore_sink_list(pa_context *c, const pa_sink_input_info *i, int eol, void *userdata) +{ + PulseLayer* pulse = (PulseLayer*) userdata; + AudioStream* s = pulse->getPlaybackStream(); + //_debug("my app index = %d\n",pa_stream_get_index(pulse->getPlaybackStream()->pulseStream())); + if( !eol ){ + _debug("Sink Info: index : %i\n" , i->index); + _debug("\t\tSink name : -%s-\n" , i->name); + _debug("\t\tClient : %i\n" , i->client); + _debug("\t\tVolume : %i\n" , i->volume.values[0]); + _debug("\t\tChannels : %i\n" , i->volume.channels); + if( strcmp( i->name , s->getStreamName().c_str()) != 0) + pulse->restoreAppVolume( i->index , i->volume.channels); + } +} + void PulseLayer::reducePulseAppsVolume( void ) { - pa_context_get_sink_input_info_list( context , retrieve_sink_list , this ); + pa_context_get_sink_input_info_list( context , reduce_sink_list , this ); +} + +void +PulseLayer::restorePulseAppsVolume( void ) +{ + pa_context_get_sink_input_info_list( context , restore_sink_list , this ); } void @@ -387,7 +407,17 @@ PulseLayer::reduceAppVolume( int index , int channels ) pa_cvolume_set( &volume , channels , vol); _debug("Mute Index %i\n" , index); pa_context_set_sink_input_volume( context, index, &volume, on_success, this) ; +} + +void +PulseLayer::restoreAppVolume( int index, int channels ) +{ + pa_cvolume volume; + pa_volume_t vol = PA_VOLUME_NORM; + pa_cvolume_set( &volume , channels , vol); + _debug("Restore Index %i\n" , index); + pa_context_set_sink_input_volume( context, index, &volume, on_success, this) ; } diff --git a/src/audio/pulselayer.h b/src/audio/pulselayer.h index 9ce53a0d11..17fb909007 100644 --- a/src/audio/pulselayer.h +++ b/src/audio/pulselayer.h @@ -49,30 +49,54 @@ class PulseLayer : public AudioLayer { bool openDevice(int indexIn, int indexOut, int sampleRate, int frameSize , int stream, std::string plugin) ; void startStream(void); + void stopStream(void); /** - * Check if the capture is running - * @return true if the state of the capture handle equals SND_PCM_STATE_RUNNING - * false otherwise + * UNUSED in pulseaudio layer */ bool isCaptureActive( void ) { return true; } + + /** + * UNUSED in pulseaudio layer + */ bool isStreamActive (void); + /** + * Flush the main ringbuffer, reserved for the voice + */ void flushMain(); + int putMain(void* buffer, int toCopy); + int putUrgent(void* buffer, int toCopy); + + /** + * UNUSED in pulseaudio layer + */ int putInCache( char code, void* buffer , int toCopy ); + + /** + * Query the capture device for number of bytes available in the hardware ring buffer + * @return int The number of bytes available + */ int canGetMic(); + + /** + * Get data from the capture device + * @param buffer The buffer for data + * @param toCopy The number of bytes to get + * @return int The number of bytes acquired ( 0 if an error occured) + */ int getMic(void *, int); + + /** + * Flush the mic ringbuffer + */ void flushMic(); /** - * Send samples to the audio device. - * @param buffer The buffer containing the data to be played ( voice and DTMF ) - * @param toCopy The number of samples, in bytes - * @param isTalking If whether or not the conversation is running - * @return int The number of bytes played + * UNUSED in pulseaudio layer */ int playSamples(void* buffer, int toCopy, bool isTalking) ; @@ -83,12 +107,7 @@ class PulseLayer : public AudioLayer { static void context_state_callback( pa_context* c, void* user_data ); /** - * Scan the sound card available on the system - * @param stream To indicate whether we are looking for capture devices or playback devices - * SFL_PCM_CAPTURE - * SFL_PCM_PLAYBACK - * SFL_PCM_BOTH - * @return std::vector<std::string> The vector containing the string description of the card + * UNUSED in pulseaudio layer */ std::vector<std::string> getSoundCardsInfo( int stream ) { std::vector<std::string> tmp; @@ -96,34 +115,54 @@ class PulseLayer : public AudioLayer { } /** - * Check if the given index corresponds to an existing sound card and supports the specified streaming mode - * @param card An index - * @param stream The stream mode - * SFL_PCM_CAPTURE - * SFL_PCM_PLAYBACK - * SFL_PCM_BOTH - * @return bool True if it exists and supports the mode - * false otherwise + * UNUSED in pulseaudio layer */ bool soundCardIndexExist( int card , int stream ) { return true; } /** - * An index is associated with its string description - * @param description The string description - * @return int Its index + * UNUSED in pulseaudio layer */ int soundCardGetIndex( std::string description ) { return 0;} /** - * Get the current audio plugin. - * @return std::string The name of the audio plugin + * UNUSED in pulseaudio layer */ std::string getAudioPlugin( void ) { return "default"; } + /** + * Reduce volume of every audio applications connected to the same sink + */ void reducePulseAppsVolume( void ); + + /** + * Restore the volume of every audio applications connected to the same sink to PA_VOLUME_NORM + */ + void restorePulseAppsVolume( void ); + + /** + * Reduce volume of one particular application + * @param index The index of the stream + * @param channels The stream's number of channels + */ void reduceAppVolume( int index , int channels ); + + /** + * Restore to PA_VOLUME_NORM the volume of one particular application + * @param index The index of the stream + * @param channels The stream's number of channels + */ + void restoreAppVolume( int index , int channels ); + /** + * Accessor + * @return AudioStream* The pointer on the playback AudioStream object + */ AudioStream* getPlaybackStream(){ return playback;} + + /** + * Accessor + * @return AudioStream* The pointer on the record AudioStream object + */ AudioStream* getRecordStream(){ return record;} private: @@ -132,27 +171,64 @@ class PulseLayer : public AudioLayer { */ void closeCaptureStream( void ); + /** + * Write data from the ring buffer to the harware and read data from the hardware + */ void processData( void ); + + /** + * Create the audio streams into the given context + * @param c The pulseaudio context + */ void createStreams( pa_context* c ); + /** * Drop the pending frames and close the playback device */ void closePlaybackStream( void ); + /** + * Establishes the connection with the local pulseaudio server + */ void connectPulseServer( void ); + /** + * Get some information about the pulseaudio server + */ void serverinfo( void ); - /** Ringbuffers for data */ + /** + * Ringbuffer for incoming voice data (playback) + */ RingBuffer _mainSndRingBuffer; + + /** + * Ringbuffer for dtmf data + */ RingBuffer _urgentRingBuffer; + + /** + * Ringbuffer for outgoing voice data (mic) + */ RingBuffer _micRingBuffer; - /** PulseAudio streams and context */ + /** PulseAudio context and asynchronous loop */ pa_context* context; pa_threaded_mainloop* m; + + /** + * A stream object to handle the pulseaudio playback stream + */ AudioStream* playback; + + /** + * A stream object to handle the pulseaudio capture stream + */ AudioStream* record; + + /** + * A stream object to handle the pulseaudio upload stream + */ AudioStream* cache; }; diff --git a/src/dbus/configurationmanager-glue.h b/src/dbus/configurationmanager-glue.h index f2cbbbeb89..5defe82eb7 100644 --- a/src/dbus/configurationmanager-glue.h +++ b/src/dbus/configurationmanager-glue.h @@ -69,6 +69,8 @@ public: register_method(ConfigurationManager, isStartHidden, _isStartHidden_stub); register_method(ConfigurationManager, popupMode, _popupMode_stub); register_method(ConfigurationManager, switchPopupMode, _switchPopupMode_stub); + register_method(ConfigurationManager, setPulseAppVolumeControl, _setPulseAppVolumeControl_stub); + register_method(ConfigurationManager, getPulseAppVolumeControl, _getPulseAppVolumeControl_stub); } ::DBus::IntrospectedInterface* const introspect() const @@ -315,6 +317,15 @@ public: { { 0, 0, 0 } }; + static ::DBus::IntrospectedArgument setPulseAppVolumeControl_args[] = + { + { 0, 0, 0 } + }; + static ::DBus::IntrospectedArgument getPulseAppVolumeControl_args[] = + { + { "state", "i", false }, + { 0, 0, 0 } + }; static ::DBus::IntrospectedArgument parametersChanged_args[] = { { "list", "a{ss}", false }, @@ -380,6 +391,8 @@ public: { "isStartHidden", isStartHidden_args }, { "popupMode", popupMode_args }, { "switchPopupMode", switchPopupMode_args }, + { "setPulseAppVolumeControl", setPulseAppVolumeControl_args }, + { "getPulseAppVolumeControl", getPulseAppVolumeControl_args }, { 0, 0 } }; static ::DBus::IntrospectedMethod ConfigurationManager_signals[] = @@ -463,6 +476,8 @@ public: virtual ::DBus::Int32 isStartHidden( ) = 0; virtual ::DBus::Int32 popupMode( ) = 0; virtual void switchPopupMode( ) = 0; + virtual void setPulseAppVolumeControl( ) = 0; + virtual ::DBus::Int32 getPulseAppVolumeControl( ) = 0; public: @@ -959,6 +974,24 @@ private: ::DBus::ReturnMessage reply(call); return reply; } + ::DBus::Message _setPulseAppVolumeControl_stub( const ::DBus::CallMessage& call ) + { + ::DBus::MessageIter ri = call.reader(); + + setPulseAppVolumeControl(); + ::DBus::ReturnMessage reply(call); + return reply; + } + ::DBus::Message _getPulseAppVolumeControl_stub( const ::DBus::CallMessage& call ) + { + ::DBus::MessageIter ri = call.reader(); + + ::DBus::Int32 argout1 = getPulseAppVolumeControl(); + ::DBus::ReturnMessage reply(call); + ::DBus::MessageIter wi = reply.writer(); + wi << argout1; + return reply; + } }; } } } diff --git a/src/dbus/configurationmanager-introspec.xml b/src/dbus/configurationmanager-introspec.xml index 9a8c87455e..624260b763 100644 --- a/src/dbus/configurationmanager-introspec.xml +++ b/src/dbus/configurationmanager-introspec.xml @@ -203,6 +203,13 @@ <method name="switchPopupMode"> </method> + <method name="setPulseAppVolumeControl"> + </method> + + <method name="getPulseAppVolumeControl"> + <arg type="i" name="state" direction="out"/> + </method> + <!-- ///////////////////////////// --> <signal name="parametersChanged"> <arg type="a{ss}" name="list" direction="out"/> diff --git a/src/dbus/configurationmanager.cpp b/src/dbus/configurationmanager.cpp index 26ea486dae..2e6a8c6ee1 100644 --- a/src/dbus/configurationmanager.cpp +++ b/src/dbus/configurationmanager.cpp @@ -362,3 +362,16 @@ ConfigurationManager::getMailNotify( void ) _debug("Manager received getMailNotify\n"); return Manager::instance().getMailNotify( ); } + +::DBus::Int32 +ConfigurationManager::getPulseAppVolumeControl( void ) +{ + return Manager::instance().getPulseAppVolumeControl(); +} + +void +ConfigurationManager::setPulseAppVolumeControl( void ) +{ + Manager::instance().setPulseAppVolumeControl(); +} + diff --git a/src/dbus/configurationmanager.h b/src/dbus/configurationmanager.h index 8dda655d95..82f9c7f237 100644 --- a/src/dbus/configurationmanager.h +++ b/src/dbus/configurationmanager.h @@ -93,6 +93,8 @@ public: void setNotify( void ); ::DBus::Int32 getMailNotify( void ); void setMailNotify( void ); + ::DBus::Int32 getPulseAppVolumeControl( void ); + void setPulseAppVolumeControl( void ); }; diff --git a/src/managerimpl.cpp b/src/managerimpl.cpp index 61c81f1235..b7f595cab2 100644 --- a/src/managerimpl.cpp +++ b/src/managerimpl.cpp @@ -276,6 +276,9 @@ ManagerImpl::hangupCall(const CallID& id) removeCallAccount(id); switchCall(""); + if( getConfigInt( PREFERENCES , CONFIG_PA_VOLUME_CTRL ) ) + _audiodriver->restorePulseAppsVolume(); + return returnValue; } @@ -582,7 +585,8 @@ ManagerImpl::incomingCall(Call* call, const AccountID& accountId) _dbus->getCallManager()->incomingCall(accountId, call->getCallId(), from); // Reduce volume of the other pulseaudio-connected audio applications - _audiodriver->reducePulseAppsVolume(); + if( getConfigInt( PREFERENCES , CONFIG_PA_VOLUME_CTRL ) ) + _audiodriver->reducePulseAppsVolume(); return true; } @@ -633,6 +637,8 @@ ManagerImpl::peerHungupCall(const CallID& id) removeWaitingCall(id); removeCallAccount(id); + if( getConfigInt( PREFERENCES , CONFIG_PA_VOLUME_CTRL ) ) + _audiodriver->restorePulseAppsVolume(); } //THREAD=VoIP @@ -1020,6 +1026,7 @@ ManagerImpl::initConfigFile (void) fill_config_int(CONFIG_HISTORY , DFT_MAX_CALLS); fill_config_int(REGISTRATION_EXPIRE , DFT_EXPIRE_VALUE); fill_config_int(CONFIG_AUDIO , DFT_AUDIO_MANAGER); + fill_config_int(CONFIG_PA_VOLUME_CTRL , YES_STR); // Loads config from ~/.sflphone/sflphonedrc or so.. if (createSettingsPath() == 1) { @@ -1451,6 +1458,18 @@ ManagerImpl::getMailNotify( void ) return getConfigInt( PREFERENCES , CONFIG_MAIL_NOTIFY ); } +::DBus::Int32 +ManagerImpl::getPulseAppVolumeControl( void ) +{ + return getConfigInt( PREFERENCES , CONFIG_PA_VOLUME_CTRL ); +} + +void +ManagerImpl::setPulseAppVolumeControl( void ) +{ + (getConfigInt( PREFERENCES , CONFIG_PA_VOLUME_CTRL ) == 1)? setConfig( PREFERENCES , CONFIG_PA_VOLUME_CTRL , NO_STR) : setConfig( PREFERENCES , CONFIG_PA_VOLUME_CTRL , YES_STR) ; +} + void ManagerImpl::setAudioManager( const DBus::Int32& api ) { diff --git a/src/managerimpl.h b/src/managerimpl.h index 94212b4009..ac765583e2 100644 --- a/src/managerimpl.h +++ b/src/managerimpl.h @@ -559,6 +559,10 @@ class ManagerImpl { void setAudioManager( const DBus::Int32& api ); void switchAudioManager( void ); + + void setPulseAppVolumeControl( void ); + ::DBus::Int32 getPulseAppVolumeControl( void ); + /** * Get the desktop mail notification level * @return int The mail notification level diff --git a/src/user_cfg.h b/src/user_cfg.h index 9597b094ed..25a0cc953b 100644 --- a/src/user_cfg.h +++ b/src/user_cfg.h @@ -60,6 +60,7 @@ #define CONFIG_ZEROCONF "Zeroconf.enable" /** Zero configuration networking module */ #define REGISTRATION_EXPIRE "Registration.expire" /** Registration expire value */ #define CONFIG_AUDIO "Audio.api" /** Audio manager (ALSA or pulseaudio) */ +#define CONFIG_PA_VOLUME_CTRL "Pulseaudio.volumeCtrl" /** Whether or not PA should modify volume of other applications on the same sink */ #define SIGNALISATION "VoIPLink" /** Section Signalisation */ #define PLAY_DTMF "DTMF.playDtmf" /** Whether or not should play dtmf */ @@ -87,6 +88,7 @@ #define DFT_EXPIRE_VALUE "180" /** Default expire value for registration */ #define DFT_AUDIO_MANAGER "1" /** Default audio manager */ + #ifdef USE_ZEROCONF #define CONFIG_ZEROCONF_DEFAULT_STR "1" /** Default Zero configuration networking module value */ #else -- GitLab