From b89851b1d3708b3017e5cfcfbe33c6a4419f7c4f Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Mon, 12 Mar 2012 16:21:39 +0100 Subject: [PATCH] implement hotpluging of usb devices for linux, and update ortp --- configure.ac | 3 ++ coreapi/linphonecore.c | 57 ++++++++++++++++++++++++++++------- coreapi/linphonecore.h | 2 ++ gtk/linphone.h | 5 ++++ gtk/main.c | 2 ++ gtk/parameters.ui | 1 + gtk/propertybox.c | 48 +++++++++++++++++++++++------- gtk/utils.c | 67 ++++++++++++++++++++++++++++++++++++++++++ oRTP | 2 +- 9 files changed, 165 insertions(+), 22 deletions(-) diff --git a/configure.ac b/configure.ac index 023236f83..ce3604451 100644 --- a/configure.ac +++ b/configure.ac @@ -442,6 +442,9 @@ if test "$build_wizard" = "true" ; then AC_DEFINE( BUILD_WIZARD, 1, [Define if wizard enabled] ) fi +AC_CHECK_HEADERS(libudev.h) +AC_CHECK_LIB(udev,udev_new) + ################################################## # Stricter build options (after external packages) ################################################## diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index e7d778b60..938c35baf 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -748,17 +748,13 @@ static void codecs_config_read(LinphoneCore *lc) linphone_core_update_allocated_audio_bandwidth(lc); } -static void video_config_read(LinphoneCore *lc){ -#ifdef VIDEO_ENABLED - int capture, display, self_view; -#endif - const char *str; - int ndev; - const char **devices; +static void build_video_devices_table(LinphoneCore *lc){ const MSList *elem; int i; - LinphoneVideoPolicy vpol; - + int ndev; + const char **devices; + if (lc->video_conf.cams) + ms_free(lc->video_conf.cams); /* retrieve all video devices */ elem=ms_web_cam_manager_get_list(ms_web_cam_manager_get()); ndev=ms_list_size(elem); @@ -768,6 +764,16 @@ static void video_config_read(LinphoneCore *lc){ } devices[ndev]=NULL; lc->video_conf.cams=devices; +} + +static void video_config_read(LinphoneCore *lc){ +#ifdef VIDEO_ENABLED + int capture, display, self_view; +#endif + const char *str; + LinphoneVideoPolicy vpol; + + build_video_devices_table(lc); str=lp_config_get_string(lc->config,"video","device",NULL); if (str && str[0]==0) str=NULL; @@ -3049,7 +3055,6 @@ const char * linphone_core_get_capture_device(LinphoneCore *lc) * @param lc The LinphoneCore object **/ const char** linphone_core_get_sound_devices(LinphoneCore *lc){ - build_sound_devices_table(lc); return lc->sound_conf.cards; } @@ -3063,6 +3068,38 @@ const char** linphone_core_get_video_devices(const LinphoneCore *lc){ return lc->video_conf.cams; } +/** + * Update detection of sound devices. + * + * Use this function when the application is notified of USB plug events, so that + * list of available hardwares for sound playback and capture is updated. + **/ +void linphone_core_reload_sound_devices(LinphoneCore *lc){ + const char *ringer,*playback,*capture; + ringer=linphone_core_get_ringer_device(lc); + playback=linphone_core_get_playback_device(lc); + capture=linphone_core_get_capture_device(lc); + ms_snd_card_manager_reload(ms_snd_card_manager_get()); + build_sound_devices_table(lc); + linphone_core_set_ringer_device(lc,ringer); + linphone_core_set_playback_device(lc,playback); + linphone_core_set_capture_device(lc,capture); +} + +/** + * Update detection of camera devices. + * + * Use this function when the application is notified of USB plug events, so that + * list of available hardwares for video capture is updated. + **/ +void linphone_core_reload_video_devices(LinphoneCore *lc){ + const char *devid; + devid=linphone_core_get_video_device(lc); + ms_web_cam_manager_reload(ms_web_cam_manager_get()); + build_video_devices_table(lc); + linphone_core_set_video_device(lc,devid); +} + char linphone_core_get_sound_source(LinphoneCore *lc) { return lc->sound_conf.source; diff --git a/coreapi/linphonecore.h b/coreapi/linphonecore.h index 2c0aa1665..bb4a84b0b 100644 --- a/coreapi/linphonecore.h +++ b/coreapi/linphonecore.h @@ -874,6 +874,7 @@ int linphone_core_set_relay_addr(LinphoneCore *lc, const char *addr); /* sound functions */ /* returns a null terminated static array of string describing the sound devices */ const char** linphone_core_get_sound_devices(LinphoneCore *lc); +void linphone_core_reload_sound_devices(LinphoneCore *lc); bool_t linphone_core_sound_device_can_capture(LinphoneCore *lc, const char *device); bool_t linphone_core_sound_device_can_playback(LinphoneCore *lc, const char *device); int linphone_core_get_ring_level(LinphoneCore *lc); @@ -958,6 +959,7 @@ bool_t linphone_core_self_view_enabled(const LinphoneCore *lc); /* returns a null terminated static array of string describing the webcams */ +void linphone_core_reload_video_devices(LinphoneCore *lc); const char** linphone_core_get_video_devices(const LinphoneCore *lc); int linphone_core_set_video_device(LinphoneCore *lc, const char *id); const char *linphone_core_get_video_device(const LinphoneCore *lc); diff --git a/gtk/linphone.h b/gtk/linphone.h index 03410b1a5..7074bc87d 100644 --- a/gtk/linphone.h +++ b/gtk/linphone.h @@ -67,6 +67,8 @@ void linphone_gtk_show_friends(void); void linphone_gtk_show_contact(LinphoneFriend *lf); void linphone_gtk_set_my_presence(LinphoneOnlineStatus ss); void linphone_gtk_show_parameters(void); +void linphone_gtk_fill_soundcards(GtkWidget *pb); +void linphone_gtk_fill_webcams(GtkWidget *pb); void linphone_gtk_load_identities(void); void linphone_gtk_create_chatroom(const char *with); void linphone_gtk_text_received(LinphoneCore *lc, LinphoneChatRoom *room, const LinphoneAddress *from, const char *message); @@ -126,3 +128,6 @@ void linphone_gtk_log_uninit(); bool_t linphone_gtk_init_instance(const char *app_name, const char *addr_to_call); void linphone_gtk_uninit_instance(void); +void linphone_gtk_monitor_usb(void); +void linphone_gtk_unmonitor_usb(void); + diff --git a/gtk/main.c b/gtk/main.c index b986b4eba..60c4556d7 100644 --- a/gtk/main.c +++ b/gtk/main.c @@ -1666,6 +1666,7 @@ static void linphone_gtk_quit(void){ static gboolean quit_done=FALSE; if (!quit_done){ quit_done=TRUE; + linphone_gtk_unmonitor_usb(); g_source_remove_by_user_data(linphone_gtk_get_core()); linphone_gtk_uninit_instance(); linphone_gtk_destroy_log_window(); @@ -1824,6 +1825,7 @@ int main(int argc, char *argv[]){ } if (linphone_gtk_get_ui_config_int("update_check_menu",0)==0) linphone_gtk_check_for_new_version(); + linphone_gtk_monitor_usb(); gtk_main(); linphone_gtk_quit(); diff --git a/gtk/parameters.ui b/gtk/parameters.ui index b5b0b8c6f..b8f4adbdc 100644 --- a/gtk/parameters.ui +++ b/gtk/parameters.ui @@ -166,6 +166,7 @@ GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK Settings linphone2.png + True diff --git a/gtk/propertybox.c b/gtk/propertybox.c index f8187860d..5af25a5c4 100644 --- a/gtk/propertybox.c +++ b/gtk/propertybox.c @@ -870,18 +870,49 @@ static void linphone_gtk_show_media_encryption(GtkWidget *pb){ g_object_unref(G_OBJECT(model)); } -void linphone_gtk_show_parameters(void){ - GtkWidget *pb=linphone_gtk_create_window("parameters"); +void linphone_gtk_parameters_destroyed(GtkWidget *pb){ + GtkWidget *mw=linphone_gtk_get_main_window(); + g_object_set_data(G_OBJECT(mw),"parameters",NULL); +} + +void linphone_gtk_fill_soundcards(GtkWidget *pb){ LinphoneCore *lc=linphone_gtk_get_core(); const char **sound_devices=linphone_core_get_sound_devices(lc); + linphone_gtk_fill_combo_box(linphone_gtk_get_widget(pb,"playback_device"), sound_devices, + linphone_core_get_playback_device(lc),CAP_PLAYBACK); + linphone_gtk_fill_combo_box(linphone_gtk_get_widget(pb,"ring_device"), sound_devices, + linphone_core_get_ringer_device(lc),CAP_PLAYBACK); + linphone_gtk_fill_combo_box(linphone_gtk_get_widget(pb,"capture_device"), sound_devices, + linphone_core_get_capture_device(lc), CAP_CAPTURE); +} + +void linphone_gtk_fill_webcams(GtkWidget *pb){ + LinphoneCore *lc=linphone_gtk_get_core(); + linphone_gtk_fill_combo_box(linphone_gtk_get_widget(pb,"webcams"),linphone_core_get_video_devices(lc), + linphone_core_get_video_device(lc),CAP_IGNORE); +} + +void linphone_gtk_show_parameters(void){ + GtkWidget *mw=linphone_gtk_get_main_window(); + GtkWidget *pb=(GtkWidget*)g_object_get_data(G_OBJECT(mw),"parameters"); + LinphoneCore *lc=linphone_gtk_get_core(); const char *tmp; LinphoneAddress *contact; LinphoneFirewallPolicy pol; - GtkWidget *codec_list=linphone_gtk_get_widget(pb,"codec_list"); + GtkWidget *codec_list; int mtu; int ui_advanced; LCSipTransports tr; + if (pb==NULL) { + pb=linphone_gtk_create_window("parameters"); + g_object_set_data(G_OBJECT(mw),"parameters",pb); + }else { + gtk_widget_show(pb); + return; + } + codec_list=linphone_gtk_get_widget(pb,"codec_list"); + /* NETWORK CONFIG */ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(pb,"ipv6_enabled")), linphone_core_ipv6_enabled(lc)); @@ -939,14 +970,9 @@ void linphone_gtk_show_parameters(void){ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(pb,"dtmf_sipinfo")), linphone_core_get_use_info_for_dtmf(lc)); /* MUTIMEDIA CONFIG */ - linphone_gtk_fill_combo_box(linphone_gtk_get_widget(pb,"playback_device"), sound_devices, - linphone_core_get_playback_device(lc),CAP_PLAYBACK); - linphone_gtk_fill_combo_box(linphone_gtk_get_widget(pb,"ring_device"), sound_devices, - linphone_core_get_ringer_device(lc),CAP_PLAYBACK); - linphone_gtk_fill_combo_box(linphone_gtk_get_widget(pb,"capture_device"), sound_devices, - linphone_core_get_capture_device(lc), CAP_CAPTURE); - linphone_gtk_fill_combo_box(linphone_gtk_get_widget(pb,"webcams"),linphone_core_get_video_devices(lc), - linphone_core_get_video_device(lc),CAP_IGNORE); + linphone_gtk_fill_soundcards(pb); + linphone_gtk_fill_webcams(pb); + linphone_gtk_fill_video_sizes(linphone_gtk_get_widget(pb,"video_size")); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(pb,"echo_cancelation")), linphone_core_echo_cancellation_enabled(lc)); diff --git a/gtk/utils.c b/gtk/utils.c index 69ae435a1..b8db633d8 100644 --- a/gtk/utils.c +++ b/gtk/utils.c @@ -97,3 +97,70 @@ GtkWidget * _gtk_image_new_from_memory_at_scale(const void *data, gint len, gint g_object_unref(G_OBJECT(pbuf)); return image; } + +void linphone_gtk_reload_sound_devices(void){ + GtkWidget *mw=linphone_gtk_get_main_window(); + GtkWidget *pb=(GtkWidget*)g_object_get_data(G_OBJECT(mw),"parameters"); + linphone_core_reload_sound_devices(linphone_gtk_get_core()); + linphone_gtk_fill_soundcards(pb); +} + +void linphone_gtk_reload_video_devices(void){ + GtkWidget *mw=linphone_gtk_get_main_window(); + GtkWidget *pb=(GtkWidget*)g_object_get_data(G_OBJECT(mw),"parameters"); + linphone_core_reload_video_devices(linphone_gtk_get_core()); + linphone_gtk_fill_webcams(pb); +} + +#ifdef HAVE_LIBUDEV_H + +static struct udev *udevroot=NULL; +static struct udev_monitor *monitor=NULL; +static GIOChannel *monitor_channel=NULL; +static guint monitor_src_id; + +#include + +static gboolean on_monitor_data(GIOChannel *chan, GIOCondition cond, void *userdata){ + struct udev_device *dev=udev_monitor_receive_device(monitor); + const char *subsys=udev_device_get_subsystem(dev); + const char *type=udev_device_get_action(dev); + g_message("USB event arrived for class %s of action type %s",subsys,type); + if (strcmp(subsys,"sound")==0) linphone_gtk_reload_sound_devices(); + if (strcmp(subsys,"video4linux")==0) linphone_gtk_reload_video_devices(); + udev_device_unref(dev); + return TRUE; +} + +void linphone_gtk_monitor_usb(void){ + int fd; + udevroot=udev_new(); + if (!udevroot) return; + monitor=udev_monitor_new_from_netlink(udevroot,"udev"); + udev_monitor_filter_add_match_subsystem_devtype(monitor,"sound",NULL); + udev_monitor_filter_add_match_subsystem_devtype(monitor,"video4linux",NULL); + fd=udev_monitor_get_fd(monitor); + monitor_channel=g_io_channel_unix_new(fd); + monitor_src_id=g_io_add_watch(monitor_channel,G_IO_IN,on_monitor_data,NULL); + udev_monitor_enable_receiving(monitor); +} + +void linphone_gtk_unmonitor_usb(void){ + if (monitor) udev_monitor_unref(monitor); + if (udevroot) udev_unref(udevroot); + if (monitor_channel) { + g_source_remove(monitor_src_id); + g_io_channel_unref(monitor_channel); + } +} + +#else + +void linphone_gtk_monitor_usb(void){ +} +void linphone_gtk_unmonitor_usb(void){ +} + +#endif + + diff --git a/oRTP b/oRTP index 97acf505e..3fb614e2e 160000 --- a/oRTP +++ b/oRTP @@ -1 +1 @@ -Subproject commit 97acf505e76962fe8efa586335fd5c042c2b44fe +Subproject commit 3fb614e2ed15803f2c96c223cceb5545a60f2431