From 985d1a2fbc5af098c9223ae377b042ff2b98d1bb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Rafa=C3=ABl=20Carr=C3=A9?=
 <rafael.carre@savoirfairelinux.com>
Date: Thu, 30 Jun 2011 11:27:41 -0400
Subject: [PATCH] * #6226 * #6179 : Rework v4l2 classes / preferences

VideoV4l2List doesn't store the current settings anymore
Preferences are actually saved and restored
Properties (channel, size, rate) are all stored as strings
remove VideoV4l2Rate (it was only a float)

VideoV4l2List will have a thread monitoring devices insertion/removal with udev and will notify the preferences code in the daemon, and the client

Fix bug in VideoV4l2Channel::GetSizes() : mix class member and local variable (idx)

Print error messages in client dbus functions
Return NULL strings in client dbus functions in case of error, instead of uninitialized strings
---
 sflphone-client-gnome/src/config/videoconf.c  | 216 +++++++++++-------
 .../dbus/configurationmanager-introspec.xml   |  40 +++-
 sflphone-client-gnome/src/dbus/dbus.c         | 100 ++++----
 sflphone-client-gnome/src/dbus/dbus.h         |  22 +-
 .../dbus/configurationmanager-introspec.xml   |  40 +++-
 .../src/dbus/configurationmanager.cpp         |  28 +--
 .../src/dbus/configurationmanager.h           |  22 +-
 sflphone-common/src/managerimpl.cpp           |  48 ++--
 sflphone-common/src/managerimpl.h             |  22 +-
 sflphone-common/src/preferences.cpp           |  66 +++---
 sflphone-common/src/preferences.h             |  80 ++++---
 sflphone-common/src/video/test/test_v4l2.cpp  |  72 ++----
 .../src/video/test/test_video_preview.cpp     |  12 +-
 sflphone-common/src/video/video_v4l2.cpp      | 105 +++------
 sflphone-common/src/video/video_v4l2.h        |  29 +--
 sflphone-common/src/video/video_v4l2_list.cpp |  85 +++++--
 sflphone-common/src/video/video_v4l2_list.h   |  23 +-
 17 files changed, 543 insertions(+), 467 deletions(-)

diff --git a/sflphone-client-gnome/src/config/videoconf.c b/sflphone-client-gnome/src/config/videoconf.c
index 97ab06fae4..f85977ad95 100644
--- a/sflphone-client-gnome/src/config/videoconf.c
+++ b/sflphone-client-gnome/src/config/videoconf.c
@@ -35,16 +35,17 @@
 #include "eel-gconf-extensions.h"
 #include "dbus.h"
 #include "video/video_preview.h"
+#include <assert.h>
 
 #include <clutter/clutter.h>
 
 static GtkWidget *v4l2Device;
-static GtkWidget *v4l2Input;
+static GtkWidget *v4l2Channel;
 static GtkWidget *v4l2Size;
 static GtkWidget *v4l2Rate;
 
 static GtkListStore *v4l2DeviceList;
-static GtkListStore *v4l2InputList;
+static GtkListStore *v4l2ChannelList;
 static GtkListStore *v4l2SizeList;
 static GtkListStore *v4l2RateList;
 
@@ -465,6 +466,42 @@ GtkWidget* videocodecs_box (account_t **a)
     return ret;
 }
 
+static char *get_active_text(GtkComboBox *box)
+{
+    char *text = NULL;
+    int comboBoxIndex = gtk_combo_box_get_active (box);
+    if (comboBoxIndex >= 0) {
+        GtkTreeIter iter;
+        gtk_combo_box_get_active_iter (box, &iter);
+        gtk_tree_model_get (gtk_combo_box_get_model (box), &iter, 0, &text, -1);
+    }
+    return text;
+}
+
+/* Return 0 if string was found in the combo box, != 0 if the string was not found */
+static int set_combo_index_from_str(GtkComboBox *box, const char *str, size_t max)
+{
+    assert(str);
+
+    GtkTreeModel *model = gtk_combo_box_get_model (box);
+    GtkTreeIter iter;
+    unsigned idx = 0;
+    gtk_tree_model_get_iter_first(model, &iter);
+    do {
+        char *boxstr;
+        gtk_tree_model_get(model, &iter, 0, &boxstr, -1);
+        if (boxstr && !strcmp(boxstr, str))
+            break;
+    } while (idx++ < max && gtk_tree_model_iter_next(model, &iter));
+
+    if (idx >= max)
+        return 1;
+
+    gtk_combo_box_set_active(box, idx);
+    return 0;
+}
+
+
 /**
  * Fill video input device rate store
  */
@@ -473,25 +510,39 @@ preferences_dialog_fill_video_input_device_rate_list()
 {
 
     GtkTreeIter iter;
-    gchar** list;
+    gchar** list = NULL;
 
     gtk_list_store_clear (v4l2RateList);
 
+    gchar *dev  = get_active_text(GTK_COMBO_BOX(v4l2Device));
+    gchar *chan = get_active_text(GTK_COMBO_BOX(v4l2Channel));
+    gchar *size = get_active_text(GTK_COMBO_BOX(v4l2Size));
+
     // Call dbus to retreive list
-    list = dbus_get_video_input_device_rate_list();
+    if (dev && chan && size)
+      list = dbus_get_video_input_device_rate_list(dev, chan, size);
 
     // For each device name included in list
     int c;
 
-    if (list) {
+    if (list && *list) {
         for (c=0; *list ; c++, list++) {
             gtk_list_store_append (v4l2RateList, &iter);
             gtk_list_store_set (v4l2RateList, &iter, 0, *list, 1, c, -1);
         }
-        gtk_combo_box_set_active(GTK_COMBO_BOX(v4l2Rate), dbus_get_video_input_device_rate());
+
+        char *rate = dbus_get_video_input_device_rate();
+        if (!rate || !*rate || set_combo_index_from_str(GTK_COMBO_BOX(v4l2Rate), rate, c)) {
+            // if setting is invalid, choose first entry
+            gtk_combo_box_set_active(GTK_COMBO_BOX(v4l2Rate), 0);
+            dbus_set_video_input_rate(get_active_text(GTK_COMBO_BOX(v4l2Rate)));
+        }
+        free(rate);
     }
-    else
+    else {
         ERROR("No video rate list found for device");
+        free(list);
+    }
 }
 
 
@@ -501,20 +552,9 @@ preferences_dialog_fill_video_input_device_rate_list()
 static void
 select_video_input_device_rate (GtkComboBox* comboBox, gpointer data UNUSED)
 {
-    GtkTreeModel* model;
-    GtkTreeIter iter;
-    int comboBoxIndex;
-    int deviceIndex;
-
-    comboBoxIndex = gtk_combo_box_get_active (comboBox);
-
-    if (comboBoxIndex >= 0) {
-        model = gtk_combo_box_get_model (comboBox);
-        gtk_combo_box_get_active_iter (comboBox, &iter);
-        gtk_tree_model_get (model, &iter, 1, &deviceIndex, -1);
-
-        dbus_set_video_input_rate (deviceIndex);
-    }
+    char *str = get_active_text(comboBox);
+    if (str)
+        dbus_set_video_input_rate(str);
 }
 
 /**
@@ -525,14 +565,18 @@ preferences_dialog_fill_video_input_device_size_list()
 {
 
     GtkTreeIter iter;
-    gchar** list;
+    gchar** list = NULL;
 
     gtk_list_store_clear (v4l2SizeList);
 
+    gchar *dev  = get_active_text(GTK_COMBO_BOX(v4l2Device));
+    gchar *chan = get_active_text(GTK_COMBO_BOX(v4l2Channel));
+
     // Call dbus to retreive list
-    list = dbus_get_video_input_device_size_list();
+    if (dev && chan)
+        list = dbus_get_video_input_device_size_list(dev, chan);
 
-    if (list) {
+    if (list && *list) {
         // For each device name included in list
         int c;
 
@@ -540,10 +584,18 @@ preferences_dialog_fill_video_input_device_size_list()
             gtk_list_store_append (v4l2SizeList, &iter);
             gtk_list_store_set (v4l2SizeList, &iter, 0, *list, 1, c, -1);
         }
-        gtk_combo_box_set_active(GTK_COMBO_BOX(v4l2Size), dbus_get_video_input_device_size());
+        char *size = dbus_get_video_input_device_size();
+        if (!size || !*size || set_combo_index_from_str(GTK_COMBO_BOX(v4l2Size), size, c)) {
+            // if setting is invalid, choose first entry
+            gtk_combo_box_set_active(GTK_COMBO_BOX(v4l2Size), 0);
+            dbus_set_video_input_size(get_active_text(GTK_COMBO_BOX(v4l2Size)));
+        }
+        free(size);
     }
-    else
+    else {
+        free(list);
         ERROR("No device size list found");
+    }
 }
 
 /**
@@ -552,21 +604,11 @@ preferences_dialog_fill_video_input_device_size_list()
 static void
 select_video_input_device_size (GtkComboBox* comboBox, gpointer data UNUSED)
 {
-    GtkTreeModel* model;
-    GtkTreeIter iter;
-    int comboBoxIndex;
-    int deviceIndex;
-
-    comboBoxIndex = gtk_combo_box_get_active (comboBox);
-
-    if (comboBoxIndex >= 0) {
-        model = gtk_combo_box_get_model (comboBox);
-        gtk_combo_box_get_active_iter (comboBox, &iter);
-        gtk_tree_model_get (model, &iter, 1, &deviceIndex, -1);
-
-        dbus_set_video_input_size (deviceIndex);
+    char *str = get_active_text(comboBox);
+    if (str) {
+        dbus_set_video_input_size(str);
+        preferences_dialog_fill_video_input_device_rate_list();
     }
-    preferences_dialog_fill_video_input_device_rate_list();
 }
 
 /**
@@ -577,25 +619,36 @@ preferences_dialog_fill_video_input_device_channel_list()
 {
 
     GtkTreeIter iter;
-    gchar** list;
+    gchar** list = NULL;
+
+    gtk_list_store_clear (v4l2ChannelList);
 
-    gtk_list_store_clear (v4l2InputList);
+    gchar *dev = get_active_text(GTK_COMBO_BOX(v4l2Device));
 
     // Call dbus to retreive list
-    list = dbus_get_video_input_device_channel_list();
+    if (dev)
+        list = dbus_get_video_input_device_channel_list(dev);
 
     if (list && *list) {
         // For each device name included in list
         int c;
 
         for (c=0; *list ; c++, list++) {
-            gtk_list_store_append (v4l2InputList, &iter);
-            gtk_list_store_set (v4l2InputList, &iter, 0, *list, 1, c, -1);
+            gtk_list_store_append (v4l2ChannelList, &iter);
+            gtk_list_store_set (v4l2ChannelList, &iter, 0, *list, 1, c, -1);
         }
-        gtk_combo_box_set_active(GTK_COMBO_BOX(v4l2Input), dbus_get_video_input_device_channel());
+        char *channel = dbus_get_video_input_device_channel();
+        if (!channel || !*channel || set_combo_index_from_str(GTK_COMBO_BOX(v4l2Channel), channel, c)) {
+            // if setting is invalid, choose first entry
+            gtk_combo_box_set_active(GTK_COMBO_BOX(v4l2Channel), 0);
+            dbus_set_video_input_device_channel(get_active_text(GTK_COMBO_BOX(v4l2Channel)));
+        }
+        free(channel);
+    }
+    else {
+        free(list);
+        ERROR("No channel list found");
     }
-    else
-        ERROR("No channel list found\n");
 }
 
 /**
@@ -604,21 +657,11 @@ preferences_dialog_fill_video_input_device_channel_list()
 static void
 select_video_input_device_channel (GtkComboBox* comboBox, gpointer data UNUSED)
 {
-    GtkTreeModel* model;
-    GtkTreeIter iter;
-    int comboBoxIndex;
-    int deviceIndex;
-
-    comboBoxIndex = gtk_combo_box_get_active (comboBox);
-
-    if (comboBoxIndex >= 0) {
-        model = gtk_combo_box_get_model (comboBox);
-        gtk_combo_box_get_active_iter (comboBox, &iter);
-        gtk_tree_model_get (model, &iter, 1, &deviceIndex, -1);
-
-        dbus_set_video_input_device_channel (deviceIndex);
+    char *str = get_active_text(comboBox);
+    if (str) {
+        dbus_set_video_input_device_channel (str);
+        preferences_dialog_fill_video_input_device_size_list();
     }
-    preferences_dialog_fill_video_input_device_size_list();
 }
 
 /**
@@ -629,7 +672,7 @@ preferences_dialog_fill_video_input_device_list()
 {
 
     GtkTreeIter iter;
-    gchar** list;
+    gchar** list = NULL;
 
     gtk_list_store_clear (v4l2DeviceList);
 
@@ -642,11 +685,18 @@ preferences_dialog_fill_video_input_device_list()
             gtk_list_store_append (v4l2DeviceList, &iter);
             gtk_list_store_set (v4l2DeviceList, &iter, 0, *list, 1, c, -1);
         }
-        gtk_combo_box_set_active(GTK_COMBO_BOX(v4l2Device), dbus_get_video_input_device());
+        char *dev = dbus_get_video_input_device();
+        if (!dev || !*dev || set_combo_index_from_str(GTK_COMBO_BOX(v4l2Device), dev, c)) {
+            // if setting is invalid, choose first entry
+            gtk_combo_box_set_active(GTK_COMBO_BOX(v4l2Device), 0);
+            dbus_set_video_input_device(get_active_text(GTK_COMBO_BOX(v4l2Device)));
+        }
+        free(dev);
         return 0;
     }
     else {
-        ERROR("No device list found\n");
+        ERROR("No device list found");
+        free(list);
         return 1;
     }
 }
@@ -657,21 +707,11 @@ preferences_dialog_fill_video_input_device_list()
 static void
 select_video_input_device (GtkComboBox* comboBox, gpointer data UNUSED)
 {
-    GtkTreeModel* model;
-    GtkTreeIter iter;
-    int comboBoxIndex;
-    int deviceIndex;
-
-    comboBoxIndex = gtk_combo_box_get_active (comboBox);
-
-    if (comboBoxIndex >= 0) {
-        model = gtk_combo_box_get_model (comboBox);
-        gtk_combo_box_get_active_iter (comboBox, &iter);
-        gtk_tree_model_get (model, &iter, 1, &deviceIndex, -1);
-
-        dbus_set_video_input_device (deviceIndex);
+    char *str = get_active_text(comboBox);
+    if (str) {
+        dbus_set_video_input_device (str);
+        preferences_dialog_fill_video_input_device_channel_list();
     }
-    preferences_dialog_fill_video_input_device_channel_list();
 }
 
 GtkWidget* v4l2_box ()
@@ -709,21 +749,21 @@ GtkWidget* v4l2_box ()
 
 
     // Set choices of input
-    item = gtk_label_new (_ ("Input"));
-    v4l2InputList = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT);
-    v4l2Input = gtk_combo_box_new_with_model (GTK_TREE_MODEL (v4l2InputList));
-    gtk_label_set_mnemonic_widget (GTK_LABEL (item), v4l2Input);
-    g_signal_connect (G_OBJECT (v4l2Input), "changed", G_CALLBACK (select_video_input_device_channel), v4l2Input);
+    item = gtk_label_new (_ ("Channel"));
+    v4l2ChannelList = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT);
+    v4l2Channel = gtk_combo_box_new_with_model (GTK_TREE_MODEL (v4l2ChannelList));
+    gtk_label_set_mnemonic_widget (GTK_LABEL (item), v4l2Channel);
+    g_signal_connect (G_OBJECT (v4l2Channel), "changed", G_CALLBACK (select_video_input_device_channel), v4l2Channel);
     gtk_table_attach (GTK_TABLE (table), item, 0, 1, 1, 2, GTK_FILL | GTK_EXPAND, GTK_SHRINK, 0, 0);
 
     preferences_dialog_fill_video_input_device_channel_list();
 
     // Set rendering
     renderer = gtk_cell_renderer_text_new();
-    gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (v4l2Input), renderer, TRUE);
-    gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (v4l2Input), renderer, "text", 0, NULL);
-    gtk_table_attach (GTK_TABLE (table), v4l2Input, 1, 2, 1, 2, GTK_FILL | GTK_EXPAND, GTK_SHRINK, 0, 0);
-    gtk_widget_show (v4l2Input);
+    gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (v4l2Channel), renderer, TRUE);
+    gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (v4l2Channel), renderer, "text", 0, NULL);
+    gtk_table_attach (GTK_TABLE (table), v4l2Channel, 1, 2, 1, 2, GTK_FILL | GTK_EXPAND, GTK_SHRINK, 0, 0);
+    gtk_widget_show (v4l2Channel);
 
 
     // Set choices of sizes
diff --git a/sflphone-client-gnome/src/dbus/configurationmanager-introspec.xml b/sflphone-client-gnome/src/dbus/configurationmanager-introspec.xml
index 75f0522775..2b85864c4a 100755
--- a/sflphone-client-gnome/src/dbus/configurationmanager-introspec.xml
+++ b/sflphone-client-gnome/src/dbus/configurationmanager-introspec.xml
@@ -478,6 +478,10 @@
 		   <tp:docstring>
 		   </tp:docstring>
 		   <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorString"/>
+		   <arg type="s" name="device" direction="in">
+			   <tp:docstring>
+			   </tp:docstring>
+		   </arg>
 		   <arg type="as" name="list" direction="out">
 			   <tp:docstring>
 			   </tp:docstring>
@@ -488,6 +492,14 @@
 		   <tp:docstring>
 		   </tp:docstring>
 		   <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorString"/>
+		   <arg type="s" name="device" direction="in">
+			   <tp:docstring>
+			   </tp:docstring>
+		   </arg>
+		   <arg type="s" name="channel" direction="in">
+			   <tp:docstring>
+			   </tp:docstring>
+		   </arg>
 		   <arg type="as" name="list" direction="out">
 			   <tp:docstring>
 			   </tp:docstring>
@@ -498,6 +510,18 @@
 		   <tp:docstring>
 		   </tp:docstring>
 		   <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorString"/>
+		   <arg type="s" name="device" direction="in">
+			   <tp:docstring>
+			   </tp:docstring>
+		   </arg>
+		   <arg type="s" name="channel" direction="in">
+			   <tp:docstring>
+			   </tp:docstring>
+		   </arg>
+		   <arg type="s" name="size" direction="in">
+			   <tp:docstring>
+			   </tp:docstring>
+		   </arg>
 		   <arg type="as" name="list" direction="out">
 			   <tp:docstring>
 			   </tp:docstring>
@@ -507,7 +531,7 @@
 	   <method name="getVideoInputDevice" tp:name-for-bindings="getVideoInputDevice">
 		   <tp:docstring>
 		   </tp:docstring>
-		   <arg type="i" name="index" direction="out">
+		   <arg type="s" name="device" direction="out">
 			   <tp:docstring>
 			   </tp:docstring>
 		   </arg>
@@ -516,7 +540,7 @@
 	   <method name="getVideoInputDeviceChannel" tp:name-for-bindings="getVideoInputDeviceChannel">
 		   <tp:docstring>
 		   </tp:docstring>
-		   <arg type="i" name="index" direction="out">
+		   <arg type="s" name="channel" direction="out">
 			   <tp:docstring>
 			   </tp:docstring>
 		   </arg>
@@ -525,7 +549,7 @@
 	   <method name="getVideoInputDeviceSize" tp:name-for-bindings="getVideoInputDeviceSize">
 		   <tp:docstring>
 		   </tp:docstring>
-		   <arg type="i" name="index" direction="out">
+		   <arg type="s" name="size" direction="out">
 			   <tp:docstring>
 			   </tp:docstring>
 		   </arg>
@@ -534,7 +558,7 @@
 	   <method name="getVideoInputDeviceRate" tp:name-for-bindings="getVideoInputDeviceRate">
 		   <tp:docstring>
 		   </tp:docstring>
-		   <arg type="i" name="index" direction="out">
+		   <arg type="s" name="rate" direction="out">
 			   <tp:docstring>
 			   </tp:docstring>
 		   </arg>
@@ -543,7 +567,7 @@
 	   <method name="setVideoInputDevice" tp:name-for-bindings="setVideoInputDevice">
 		   <tp:docstring>
 		   </tp:docstring>
-		   <arg type="i" name="index" direction="in">
+		   <arg type="s" name="device" direction="in">
 			   <tp:docstring>
 			   </tp:docstring>
 		   </arg>
@@ -552,7 +576,7 @@
 	   <method name="setVideoInputDeviceChannel" tp:name-for-bindings="setVideoInputDeviceChannel">
 		   <tp:docstring>
 		   </tp:docstring>
-		   <arg type="i" name="index" direction="in">
+		   <arg type="s" name="channel" direction="in">
 			   <tp:docstring>
 			   </tp:docstring>
 		   </arg>
@@ -561,7 +585,7 @@
 	   <method name="setVideoInputDeviceSize" tp:name-for-bindings="setVideoInputDeviceSize">
 		   <tp:docstring>
 		   </tp:docstring>
-		   <arg type="i" name="index" direction="in">
+		   <arg type="s" name="size" direction="in">
 			   <tp:docstring>
 			   </tp:docstring>
 		   </arg>
@@ -570,7 +594,7 @@
 	   <method name="setVideoInputDeviceRate" tp:name-for-bindings="setVideoInputDeviceRate">
 		   <tp:docstring>
 		   </tp:docstring>
-		   <arg type="i" name="index" direction="in">
+		   <arg type="s" name="rate" direction="in">
 			   <tp:docstring>
 			   </tp:docstring>
 		   </arg>
diff --git a/sflphone-client-gnome/src/dbus/dbus.c b/sflphone-client-gnome/src/dbus/dbus.c
index d49fb41640..959c365a4e 100644
--- a/sflphone-client-gnome/src/dbus/dbus.c
+++ b/sflphone-client-gnome/src/dbus/dbus.c
@@ -1353,7 +1353,7 @@ dbus_set_account_details (account_t *a)
 gchar*
 dbus_add_account (account_t *a)
 {
-    gchar* accountId;
+    gchar* accountId = NULL;
     GError *error = NULL;
     org_sflphone_SFLphone_ConfigurationManager_add_account (
         configurationManagerProxy, a->properties, &accountId, &error);
@@ -1489,7 +1489,7 @@ dbus_audio_codec_details (int payload)
 {
 
     GError *error = NULL;
-    gchar ** array;
+    gchar ** array = NULL;
     org_sflphone_SFLphone_ConfigurationManager_get_audio_codec_details (
         configurationManagerProxy, payload, &array, &error);
 
@@ -1507,7 +1507,7 @@ dbus_video_codec_details (int payload)
 {
 
     GError *error = NULL;
-    gchar ** array;
+    gchar ** array = NULL;
     org_sflphone_SFLphone_ConfigurationManager_get_video_codec_details (
         configurationManagerProxy, payload, &array, &error);
 
@@ -1543,7 +1543,7 @@ gchar**
 dbus_get_active_audio_codec_list (gchar *accountID)
 {
 
-    gchar ** array;
+    gchar ** array = NULL;
     GError *error = NULL;
     org_sflphone_SFLphone_ConfigurationManager_get_active_audio_codec_list (
         configurationManagerProxy, accountID, &array, &error);
@@ -1617,7 +1617,7 @@ dbus_set_audio_plugin (gchar* audioPlugin)
 gchar**
 dbus_get_audio_output_device_list()
 {
-    gchar** array;
+    gchar** array = NULL;
     GError* error = NULL;
     org_sflphone_SFLphone_ConfigurationManager_get_audio_output_device_list (
         configurationManagerProxy, &array, &error);
@@ -1684,7 +1684,7 @@ dbus_set_audio_ringtone_device (const int index)
 gchar**
 dbus_get_audio_input_device_list()
 {
-    gchar** array;
+    gchar** array = NULL;
     GError* error = NULL;
     org_sflphone_SFLphone_ConfigurationManager_get_audio_input_device_list (
         configurationManagerProxy, &array, &error);
@@ -1703,7 +1703,7 @@ dbus_get_audio_input_device_list()
 gchar**
 dbus_get_current_audio_devices_index()
 {
-    gchar** array;
+    gchar** array = NULL;
     GError* error = NULL;
     org_sflphone_SFLphone_ConfigurationManager_get_current_audio_devices_index (
         configurationManagerProxy, &array, &error);
@@ -1876,7 +1876,7 @@ dbus_set_echo_cancel_delay(int delay)
 gchar*
 dbus_get_ringtone_choice (const gchar *accountID)
 {
-    gchar* tone;
+    gchar* tone = NULL;
     GError* error = NULL;
     org_sflphone_SFLphone_ConfigurationManager_get_ringtone_choice (
         configurationManagerProxy, accountID, &tone, &error);
@@ -2115,7 +2115,7 @@ gchar*
 dbus_get_record_path (void)
 {
     GError* error = NULL;
-    gchar *path;
+    gchar *path = NULL;
     org_sflphone_SFLphone_ConfigurationManager_get_record_path (
         configurationManagerProxy, &path, &error);
 
@@ -2201,90 +2201,90 @@ dbus_get_audio_manager (void)
         configurationManagerProxy, &api, &error);
 
     if (error) {
-        ERROR ("Error calling dbus_get_audio_manager");
+        ERROR ("Error calling dbus_get_audio_manager: %s", error->message);
         g_error_free (error);
     }
 
     return api;
 }
 
-unsigned
+gchar *
 dbus_get_video_input_device_channel ()
 {
-    gint index;
+    gchar *str = NULL;
     GError* error = NULL;
 
     org_sflphone_SFLphone_ConfigurationManager_get_video_input_device_channel(
-        configurationManagerProxy, &index, &error);
+        configurationManagerProxy, &str, &error);
 
     if (error) {
-        ERROR ("Error calling dbus_get_video_input_device_channel");
+        ERROR ("Error calling dbus_get_video_input_device_channel: %s", error->message);
         g_error_free (error);
     }
 
-    return index;
+    return str;
 }
 
-unsigned
+gchar *
 dbus_get_video_input_device_size ()
 {
-    gint index;
+    gchar *str = NULL;
     GError* error = NULL;
 
     org_sflphone_SFLphone_ConfigurationManager_get_video_input_device_size(
-        configurationManagerProxy, &index, &error);
+        configurationManagerProxy, &str, &error);
 
     if (error) {
-        ERROR ("Error calling dbus_get_video_input_device_size");
+        ERROR ("Error calling dbus_get_video_input_device_size: %s", error->message);
         g_error_free (error);
     }
 
-    return index;
+    return str;
 }
 
-unsigned
+gchar *
 dbus_get_video_input_device_rate ()
 {
-    gint index;
+    gchar *str = NULL;
     GError* error = NULL;
 
     org_sflphone_SFLphone_ConfigurationManager_get_video_input_device_rate(
-        configurationManagerProxy, &index, &error);
+        configurationManagerProxy, &str, &error);
 
     if (error) {
-        ERROR ("Error calling dbus_get_video_input_device_rate");
+        ERROR ("Error calling dbus_get_video_input_device_rate: %s", error->message);
         g_error_free (error);
     }
 
-    return index;
+    return str;
 }
 
-unsigned
+gchar *
 dbus_get_video_input_device ()
 {
-    gint index;
+    gchar *str = NULL;
     GError* error = NULL;
 
     org_sflphone_SFLphone_ConfigurationManager_get_video_input_device(
-        configurationManagerProxy, &index, &error);
+        configurationManagerProxy, &str, &error);
 
     if (error) {
-        ERROR ("Error calling dbus_get_video_input_device");
+        ERROR ("Error calling dbus_get_video_input_device: %s", error->message);
         g_error_free (error);
     }
 
-    return index;
+    return str;
 }
 
 /**
- * Set video input device from its index
+ * Set video input device
  */
 void
-dbus_set_video_input_device (const int index)
+dbus_set_video_input_device (const gchar *device)
 {
     GError* error = NULL;
     org_sflphone_SFLphone_ConfigurationManager_set_video_input_device(
-        configurationManagerProxy, index, &error);
+        configurationManagerProxy, device, &error);
 
     if (error) {
         ERROR ("Failed to call set_video_input_device() on ConfigurationManager: %s", error->message);
@@ -2293,14 +2293,14 @@ dbus_set_video_input_device (const int index)
 }
 
 /**
- * Set video input device input from its index
+ * Set video input device channel
  */
 void
-dbus_set_video_input_device_channel (const int index)
+dbus_set_video_input_device_channel (const gchar *channel)
 {
     GError* error = NULL;
     org_sflphone_SFLphone_ConfigurationManager_set_video_input_device_channel(
-        configurationManagerProxy, index, &error);
+        configurationManagerProxy, channel, &error);
 
     if (error) {
         ERROR ("Failed to call set_video_input_device_channel() on ConfigurationManager: %s", error->message);
@@ -2309,14 +2309,14 @@ dbus_set_video_input_device_channel (const int index)
 }
 
 /**
- * Set video input size from its index
+ * Set video input size
  */
 void
-dbus_set_video_input_size (const int index)
+dbus_set_video_input_size (const gchar *size)
 {
     GError* error = NULL;
     org_sflphone_SFLphone_ConfigurationManager_set_video_input_device_size(
-        configurationManagerProxy, index, &error);
+        configurationManagerProxy, size, &error);
 
     if (error) {
         ERROR ("Failed to call set_video_input_device_size() on ConfigurationManager: %s", error->message);
@@ -2325,14 +2325,14 @@ dbus_set_video_input_size (const int index)
 }
 
 /**
- * Set video input rate from its index
+ * Set video input rate
  */
 void
-dbus_set_video_input_rate (const int index)
+dbus_set_video_input_rate (const gchar *rate)
 {
     GError* error = NULL;
     org_sflphone_SFLphone_ConfigurationManager_set_video_input_device_rate(
-        configurationManagerProxy, index, &error);
+        configurationManagerProxy, rate, &error);
 
     if (error) {
         ERROR ("Failed to call set_video_input_device_rate() on ConfigurationManager: %s", error->message);
@@ -2368,13 +2368,13 @@ dbus_get_video_input_device_list()
  * Get a list of inputs supported by the video input device
  */
 gchar**
-dbus_get_video_input_device_channel_list()
+dbus_get_video_input_device_channel_list(const gchar *dev)
 {
     gchar** array = NULL;
     GError* error = NULL;
 
     if (!org_sflphone_SFLphone_ConfigurationManager_get_video_input_device_channel_list (
-                configurationManagerProxy, &array, &error)) {
+                configurationManagerProxy, dev, &array, &error)) {
         if (error->domain == DBUS_GERROR && error->code
                 == DBUS_GERROR_REMOTE_EXCEPTION) {
             ERROR ("Caught remote method (get_video_input_device_channel_list) exception  %s: %s", dbus_g_error_get_name (error), error->message);
@@ -2391,13 +2391,13 @@ dbus_get_video_input_device_channel_list()
  * Get a list of resolutions supported by the video input
  */
 gchar**
-dbus_get_video_input_device_size_list()
+dbus_get_video_input_device_size_list(const gchar *dev, const gchar *channel)
 {
-    gchar** array;
+    gchar** array = NULL;
     GError* error = NULL;
 
     if (!org_sflphone_SFLphone_ConfigurationManager_get_video_input_device_size_list (
-                configurationManagerProxy, &array, &error)) {
+                configurationManagerProxy, dev, channel, &array, &error)) {
         if (error->domain == DBUS_GERROR && error->code
                 == DBUS_GERROR_REMOTE_EXCEPTION) {
             ERROR ("Caught remote method (get_video_input_device_size_list) exception  %s: %s", dbus_g_error_get_name (error), error->message);
@@ -2416,13 +2416,13 @@ dbus_get_video_input_device_size_list()
  * Get a list of frame rates supported by the video input resolution
  */
 gchar**
-dbus_get_video_input_device_rate_list()
+dbus_get_video_input_device_rate_list(const gchar *dev, const gchar *channel, const gchar *size)
 {
-    gchar** array;
+    gchar** array = NULL;
     GError* error = NULL;
 
     if (!org_sflphone_SFLphone_ConfigurationManager_get_video_input_device_rate_list (
-                configurationManagerProxy, &array, &error)) {
+                configurationManagerProxy, dev, channel, size, &array, &error)) {
         if (error->domain == DBUS_GERROR && error->code
                 == DBUS_GERROR_REMOTE_EXCEPTION) {
             ERROR ("Caught remote method (get_video_input_device_rate_list) exception  %s: %s", dbus_g_error_get_name (error), error->message);
diff --git a/sflphone-client-gnome/src/dbus/dbus.h b/sflphone-client-gnome/src/dbus/dbus.h
index a2938ff203..4d54124610 100644
--- a/sflphone-client-gnome/src/dbus/dbus.h
+++ b/sflphone-client-gnome/src/dbus/dbus.h
@@ -442,18 +442,18 @@ int dbus_get_audio_manager (void);
  */
 void dbus_set_audio_manager (int api);
 
-void dbus_set_video_input_device (const int index);
-void dbus_set_video_input_device_channel (const int index);
-void dbus_set_video_input_size (const int index);
-void dbus_set_video_input_rate (const int index);
-unsigned dbus_get_video_input_device ();
-unsigned dbus_get_video_input_device_channel ();
-unsigned dbus_get_video_input_device_size ();
-unsigned dbus_get_video_input_device_rate ();
+void dbus_set_video_input_device (const gchar *dev);
+void dbus_set_video_input_device_channel (const gchar *channel);
+void dbus_set_video_input_size (const char *size);
+void dbus_set_video_input_rate (const gchar *rate);
+gchar *dbus_get_video_input_device ();
+gchar *dbus_get_video_input_device_channel ();
+gchar *dbus_get_video_input_device_size ();
+gchar *dbus_get_video_input_device_rate ();
 gchar **dbus_get_video_input_device_list();
-gchar **dbus_get_video_input_device_channel_list();
-gchar **dbus_get_video_input_device_size_list();
-gchar **dbus_get_video_input_device_rate_list();
+gchar **dbus_get_video_input_device_channel_list(const gchar *dev);
+gchar **dbus_get_video_input_device_size_list(const gchar *dev, const gchar *channel);
+gchar **dbus_get_video_input_device_rate_list(const gchar *dev, const gchar *channel, const gchar *size);
 
 
 /**
diff --git a/sflphone-common/src/dbus/configurationmanager-introspec.xml b/sflphone-common/src/dbus/configurationmanager-introspec.xml
index 75f0522775..2b85864c4a 100755
--- a/sflphone-common/src/dbus/configurationmanager-introspec.xml
+++ b/sflphone-common/src/dbus/configurationmanager-introspec.xml
@@ -478,6 +478,10 @@
 		   <tp:docstring>
 		   </tp:docstring>
 		   <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorString"/>
+		   <arg type="s" name="device" direction="in">
+			   <tp:docstring>
+			   </tp:docstring>
+		   </arg>
 		   <arg type="as" name="list" direction="out">
 			   <tp:docstring>
 			   </tp:docstring>
@@ -488,6 +492,14 @@
 		   <tp:docstring>
 		   </tp:docstring>
 		   <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorString"/>
+		   <arg type="s" name="device" direction="in">
+			   <tp:docstring>
+			   </tp:docstring>
+		   </arg>
+		   <arg type="s" name="channel" direction="in">
+			   <tp:docstring>
+			   </tp:docstring>
+		   </arg>
 		   <arg type="as" name="list" direction="out">
 			   <tp:docstring>
 			   </tp:docstring>
@@ -498,6 +510,18 @@
 		   <tp:docstring>
 		   </tp:docstring>
 		   <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="VectorString"/>
+		   <arg type="s" name="device" direction="in">
+			   <tp:docstring>
+			   </tp:docstring>
+		   </arg>
+		   <arg type="s" name="channel" direction="in">
+			   <tp:docstring>
+			   </tp:docstring>
+		   </arg>
+		   <arg type="s" name="size" direction="in">
+			   <tp:docstring>
+			   </tp:docstring>
+		   </arg>
 		   <arg type="as" name="list" direction="out">
 			   <tp:docstring>
 			   </tp:docstring>
@@ -507,7 +531,7 @@
 	   <method name="getVideoInputDevice" tp:name-for-bindings="getVideoInputDevice">
 		   <tp:docstring>
 		   </tp:docstring>
-		   <arg type="i" name="index" direction="out">
+		   <arg type="s" name="device" direction="out">
 			   <tp:docstring>
 			   </tp:docstring>
 		   </arg>
@@ -516,7 +540,7 @@
 	   <method name="getVideoInputDeviceChannel" tp:name-for-bindings="getVideoInputDeviceChannel">
 		   <tp:docstring>
 		   </tp:docstring>
-		   <arg type="i" name="index" direction="out">
+		   <arg type="s" name="channel" direction="out">
 			   <tp:docstring>
 			   </tp:docstring>
 		   </arg>
@@ -525,7 +549,7 @@
 	   <method name="getVideoInputDeviceSize" tp:name-for-bindings="getVideoInputDeviceSize">
 		   <tp:docstring>
 		   </tp:docstring>
-		   <arg type="i" name="index" direction="out">
+		   <arg type="s" name="size" direction="out">
 			   <tp:docstring>
 			   </tp:docstring>
 		   </arg>
@@ -534,7 +558,7 @@
 	   <method name="getVideoInputDeviceRate" tp:name-for-bindings="getVideoInputDeviceRate">
 		   <tp:docstring>
 		   </tp:docstring>
-		   <arg type="i" name="index" direction="out">
+		   <arg type="s" name="rate" direction="out">
 			   <tp:docstring>
 			   </tp:docstring>
 		   </arg>
@@ -543,7 +567,7 @@
 	   <method name="setVideoInputDevice" tp:name-for-bindings="setVideoInputDevice">
 		   <tp:docstring>
 		   </tp:docstring>
-		   <arg type="i" name="index" direction="in">
+		   <arg type="s" name="device" direction="in">
 			   <tp:docstring>
 			   </tp:docstring>
 		   </arg>
@@ -552,7 +576,7 @@
 	   <method name="setVideoInputDeviceChannel" tp:name-for-bindings="setVideoInputDeviceChannel">
 		   <tp:docstring>
 		   </tp:docstring>
-		   <arg type="i" name="index" direction="in">
+		   <arg type="s" name="channel" direction="in">
 			   <tp:docstring>
 			   </tp:docstring>
 		   </arg>
@@ -561,7 +585,7 @@
 	   <method name="setVideoInputDeviceSize" tp:name-for-bindings="setVideoInputDeviceSize">
 		   <tp:docstring>
 		   </tp:docstring>
-		   <arg type="i" name="index" direction="in">
+		   <arg type="s" name="size" direction="in">
 			   <tp:docstring>
 			   </tp:docstring>
 		   </arg>
@@ -570,7 +594,7 @@
 	   <method name="setVideoInputDeviceRate" tp:name-for-bindings="setVideoInputDeviceRate">
 		   <tp:docstring>
 		   </tp:docstring>
-		   <arg type="i" name="index" direction="in">
+		   <arg type="s" name="rate" direction="in">
 			   <tp:docstring>
 			   </tp:docstring>
 		   </arg>
diff --git a/sflphone-common/src/dbus/configurationmanager.cpp b/sflphone-common/src/dbus/configurationmanager.cpp
index e09d34863c..ac2631485c 100644
--- a/sflphone-common/src/dbus/configurationmanager.cpp
+++ b/sflphone-common/src/dbus/configurationmanager.cpp
@@ -645,57 +645,57 @@ std::vector<std::string> ConfigurationManager::getVideoInputDeviceList()
     return Manager::instance().getVideoInputDeviceList();
 }
 
-std::vector<std::string> ConfigurationManager::getVideoInputDeviceChannelList()
+std::vector<std::string> ConfigurationManager::getVideoInputDeviceChannelList(const std::string &dev)
 {
-    return Manager::instance().getVideoInputDeviceChannelList();
+    return Manager::instance().getVideoInputDeviceChannelList(dev);
 }
 
-std::vector<std::string> ConfigurationManager::getVideoInputDeviceSizeList()
+std::vector<std::string> ConfigurationManager::getVideoInputDeviceSizeList(const std::string &dev, const std::string &channel)
 {
-    return Manager::instance().getVideoInputDeviceSizeList();
+    return Manager::instance().getVideoInputDeviceSizeList(dev, channel);
 }
 
-std::vector<std::string> ConfigurationManager::getVideoInputDeviceRateList()
+std::vector<std::string> ConfigurationManager::getVideoInputDeviceRateList(const std::string &dev, const std::string &channel, const std::string &size)
 {
-    return Manager::instance().getVideoInputDeviceRateList();
+    return Manager::instance().getVideoInputDeviceRateList(dev, channel, size);
 }
 
-int32_t ConfigurationManager::getVideoInputDevice()
+std::string ConfigurationManager::getVideoInputDevice()
 {
     return Manager::instance().getVideoInputDevice();
 }
 
-int32_t ConfigurationManager::getVideoInputDeviceChannel()
+std::string ConfigurationManager::getVideoInputDeviceChannel()
 {
     return Manager::instance().getVideoInputDeviceChannel();
 }
 
-int32_t ConfigurationManager::getVideoInputDeviceSize()
+std::string ConfigurationManager::getVideoInputDeviceSize()
 {
     return Manager::instance().getVideoInputDeviceSize();
 }
 
-int32_t ConfigurationManager::getVideoInputDeviceRate()
+std::string ConfigurationManager::getVideoInputDeviceRate()
 {
     return Manager::instance().getVideoInputDeviceRate();
 }
 
-void ConfigurationManager::setVideoInputDevice(const int32_t& api)
+void ConfigurationManager::setVideoInputDevice(const std::string& api)
 {
     Manager::instance().setVideoInputDevice(api);
 }
 
-void ConfigurationManager::setVideoInputDeviceChannel(const int32_t& api)
+void ConfigurationManager::setVideoInputDeviceChannel(const std::string& api)
 {
     Manager::instance().setVideoInputDeviceChannel(api);
 }
 
-void ConfigurationManager::setVideoInputDeviceSize(const int32_t& api)
+void ConfigurationManager::setVideoInputDeviceSize(const std::string& api)
 {
     Manager::instance().setVideoInputDeviceSize(api);
 }
 
-void ConfigurationManager::setVideoInputDeviceRate(const int32_t& api)
+void ConfigurationManager::setVideoInputDeviceRate(const std::string& api)
 {
     Manager::instance().setVideoInputDeviceRate(api);
 }
diff --git a/sflphone-common/src/dbus/configurationmanager.h b/sflphone-common/src/dbus/configurationmanager.h
index ddfc4551dc..d001d9872d 100644
--- a/sflphone-common/src/dbus/configurationmanager.h
+++ b/sflphone-common/src/dbus/configurationmanager.h
@@ -112,17 +112,17 @@ class ConfigurationManager
         int getEchoCancelDelay(void);
 
         std::vector<std::string> getVideoInputDeviceList();
-        std::vector<std::string> getVideoInputDeviceChannelList();
-        std::vector<std::string> getVideoInputDeviceSizeList();
-        std::vector<std::string> getVideoInputDeviceRateList();
-        void setVideoInputDevice(const int32_t& api);
-        void setVideoInputDeviceChannel(const int32_t& api);
-        void setVideoInputDeviceSize(const int32_t& api);
-        void setVideoInputDeviceRate(const int32_t& api);
-        int32_t getVideoInputDevice();
-        int32_t getVideoInputDeviceChannel();
-        int32_t getVideoInputDeviceSize();
-        int32_t getVideoInputDeviceRate();
+        std::vector<std::string> getVideoInputDeviceChannelList(const std::string &dev);
+        std::vector<std::string> getVideoInputDeviceSizeList(const std::string &dev, const std::string &channel);
+        std::vector<std::string> getVideoInputDeviceRateList(const std::string &dev, const std::string &channel, const std::string &size);
+        void setVideoInputDevice(const std::string& api);
+        void setVideoInputDeviceChannel(const std::string& api);
+        void setVideoInputDeviceSize(const std::string& api);
+        void setVideoInputDeviceRate(const std::string& api);
+        std::string getVideoInputDevice();
+        std::string getVideoInputDeviceChannel();
+        std::string getVideoInputDeviceSize();
+        std::string getVideoInputDeviceRate();
 
         std::vector< std::string > getToneLocaleList();
         std::vector< std::string > getPlaybackDeviceList();
diff --git a/sflphone-common/src/managerimpl.cpp b/sflphone-common/src/managerimpl.cpp
index 9e57888c9c..0d82d324eb 100644
--- a/sflphone-common/src/managerimpl.cpp
+++ b/sflphone-common/src/managerimpl.cpp
@@ -51,8 +51,6 @@
 #include "iax/iaxvoiplink.h"
 #include "manager.h"
 #include "dbus/configurationmanager.h"
-#include "video/video_v4l2.h"
-#include "video/video_v4l2_list.h"
 
 #include "conference.h"
 
@@ -2863,62 +2861,62 @@ std::vector<std::string> ManagerImpl::getCurrentAudioDevicesIndex ()
 
 std::vector<std::string> ManagerImpl::getVideoInputDeviceList()
 {
-    return videoPreference.v4l2_list->getDeviceList();
+    return videoPreference.getDeviceList();
 }
 
-std::vector<std::string> ManagerImpl::getVideoInputDeviceChannelList()
+std::vector<std::string> ManagerImpl::getVideoInputDeviceChannelList(const std::string &dev)
 {
-    return videoPreference.v4l2_list->getDevice().getChannelList();
+    return videoPreference.getChannelList(dev);
 }
 
-std::vector<std::string> ManagerImpl::getVideoInputDeviceSizeList()
+std::vector<std::string> ManagerImpl::getVideoInputDeviceSizeList(const std::string &dev, const std::string &channel)
 {
-    return videoPreference.v4l2_list->getDevice().getChannel().getSizeList();
+    return videoPreference.getSizeList(dev, channel);
 }
 
-std::vector<std::string> ManagerImpl::getVideoInputDeviceRateList()
+std::vector<std::string> ManagerImpl::getVideoInputDeviceRateList(const std::string &dev, const std::string &channel, const std::string &size)
 {
-    return videoPreference.v4l2_list->getDevice().getChannel().getSize().getRateList();
+    return videoPreference.getRateList(dev, channel, size);
 }
 
-int32_t ManagerImpl::getVideoInputDevice()
+std::string ManagerImpl::getVideoInputDevice()
 {
-    return videoPreference.v4l2_list->getDeviceIndex();
+    return videoPreference.getDevice();
 }
 
-int32_t ManagerImpl::getVideoInputDeviceChannel()
+std::string ManagerImpl::getVideoInputDeviceChannel()
 {
-    return videoPreference.v4l2_list->getDevice().getChannelIndex();
+    return videoPreference.getChannel();
 }
 
-int32_t ManagerImpl::getVideoInputDeviceSize()
+std::string ManagerImpl::getVideoInputDeviceSize()
 {
-    return videoPreference.v4l2_list->getDevice().getChannel().getSizeIndex();
+    return videoPreference.getSize();
 }
 
-int32_t ManagerImpl::getVideoInputDeviceRate()
+std::string ManagerImpl::getVideoInputDeviceRate()
 {
-    return videoPreference.v4l2_list->getDevice().getChannel().getSize().getRateIndex();
+    return videoPreference.getRate();
 }
 
-void ManagerImpl::setVideoInputDevice(const int32_t& api)
+void ManagerImpl::setVideoInputDevice(const std::string& api)
 {
-    videoPreference.v4l2_list->setDevice(api);
+    videoPreference.setDevice(api);
 }
 
-void ManagerImpl::setVideoInputDeviceChannel(const int32_t& api)
+void ManagerImpl::setVideoInputDeviceChannel(const std::string& api)
 {
-    videoPreference.v4l2_list->getDevice().setChannel(api);
+    videoPreference.setChannel(api);
 }
 
-void ManagerImpl::setVideoInputDeviceSize(const int32_t& api)
+void ManagerImpl::setVideoInputDeviceSize(const std::string& api)
 {
-    videoPreference.v4l2_list->getDevice().getChannel().setSize(api);
+    videoPreference.setSize(api);
 }
 
-void ManagerImpl::setVideoInputDeviceRate(const int32_t& api)
+void ManagerImpl::setVideoInputDeviceRate(const std::string& api)
 {
-    videoPreference.v4l2_list->getDevice().getChannel().getSize().setRate(api);
+    videoPreference.setRate(api);
 }
 
 int ManagerImpl::isIax2Enabled (void)
diff --git a/sflphone-common/src/managerimpl.h b/sflphone-common/src/managerimpl.h
index f6b37327a8..043f203849 100644
--- a/sflphone-common/src/managerimpl.h
+++ b/sflphone-common/src/managerimpl.h
@@ -680,63 +680,63 @@ class ManagerImpl
          * Get the list of available inputs for the current V4L2 device 
          * @return std::vector<std::string> A list of the V4L2 inputs
          */
-        std::vector<std::string> getVideoInputDeviceChannelList();
+        std::vector<std::string> getVideoInputDeviceChannelList(const std::string &dev);
 
         /**
          * Get the list of available resolutions for the current V4L2 device/input pair
          * @return std::vector<std::string> A list of frame sizes
          */
-        std::vector<std::string> getVideoInputDeviceSizeList();
+        std::vector<std::string> getVideoInputDeviceSizeList(const std::string &dev, const std::string &channel);
 
         /**
          * Get the list of available frame rates for the current V4L2 device/input/resolution
          * @return std::vector<std::string> A list of the possible frame rates
          */
-        std::vector<std::string> getVideoInputDeviceRateList();
+        std::vector<std::string> getVideoInputDeviceRateList(const std::string &dev, const std::string &channel, const std::string &size);
 
         /**
          * Get video input device index
          */
-        int32_t getVideoInputDevice();
+        std::string getVideoInputDevice();
 
         /**
          * Get video input device input index
          */
-        int32_t getVideoInputDeviceChannel();
+        std::string getVideoInputDeviceChannel();
 
         /**
          * Get video input device size index
          */
-        int32_t getVideoInputDeviceSize();
+        std::string getVideoInputDeviceSize();
 
         /**
          * Get video input device rate index
          */
-        int32_t getVideoInputDeviceRate();
+        std::string getVideoInputDeviceRate();
 
         /**
          * Set video input device
          * @param index The index of the V4L2 device
          */
-        void setVideoInputDevice(const int32_t& api);
+        void setVideoInputDevice(const std::string& api);
 
         /**
          * Set v4l2 input
          * @param index The index of the V4L2 input 
          */
-        void setVideoInputDeviceChannel(const int32_t& api);
+        void setVideoInputDeviceChannel(const std::string& api);
 
         /**
          * Set video input resolution
          * @param index The index of the resolution in the list of supported sizes
          */
-        void setVideoInputDeviceSize(const int32_t& api);
+        void setVideoInputDeviceSize(const std::string& api);
 
         /**
          * Set video input frame rate
          * @param index The index of the frame rate in the list of supported rates
          */
-        void setVideoInputDeviceRate(const int32_t& api);
+        void setVideoInputDeviceRate(const std::string& api);
 
         /**
          * Convert a list of payload in a special format, readable by the server.
diff --git a/sflphone-common/src/preferences.cpp b/sflphone-common/src/preferences.cpp
index 75182e4fb6..6fe87ba984 100644
--- a/sflphone-common/src/preferences.cpp
+++ b/sflphone-common/src/preferences.cpp
@@ -665,20 +665,31 @@ void AudioPreference::unserialize (Conf::MappingNode *map)
 
 }
 
-
-
 VideoPreference::VideoPreference() :
-    _videoDevice(0)
-    , _videoInput(0)
-    , _videoSize(0)
-    , _videoRate(0)
+    _Device("")
+    , _Channel("")
+    , _Size("")
+    , _Rate("")
 {
-    v4l2_list = new sfl_video::VideoV4l2List();
+	_v4l2_list = new VideoV4l2List();
+	_v4l2_list->start();
 }
 
 VideoPreference::~VideoPreference()
 {
-    delete v4l2_list;
+	delete _v4l2_list;
+}
+
+std::map<std::string, std::string> VideoPreference::getVideoSettings(void) {
+    std::map<std::string, std::string> map;
+    std::stringstream ss;
+    map["input"] = _v4l2_list->getDeviceNode(_Device);
+    ss << _v4l2_list->getChannelNum(_Device, _Channel);
+    map["channel"] = ss.str();
+    map["video_size"] = _Size;
+    map["framerate"] = _Rate;
+
+    return map;
 }
 
 void VideoPreference::serialize (Conf::YamlEmitter *emitter)
@@ -690,23 +701,15 @@ void VideoPreference::serialize (Conf::YamlEmitter *emitter)
 
     Conf::MappingNode preferencemap (NULL);
 
-    std::stringstream devstr;
-    devstr << _videoDevice;
-    Conf::ScalarNode videoDevice(devstr.str());
-    std::stringstream inputstr;
-    inputstr << _videoInput;
-    Conf::ScalarNode videoInput(inputstr.str());
-    std::stringstream sizestr;
-    sizestr << _videoDevice;
-    Conf::ScalarNode videoSize(sizestr.str());
-    std::stringstream frameratestr;
-    frameratestr << _videoDevice;
-    Conf::ScalarNode videoRate (frameratestr.str());
-
-    preferencemap.setKeyValue (videoDeviceKey, &videoDevice);
-    preferencemap.setKeyValue (videoInputKey, &videoInput);
-    preferencemap.setKeyValue (videoSizeKey, &videoSize);
-    preferencemap.setKeyValue (videoRateKey, &videoRate);
+    Conf::ScalarNode Device(_Device);
+    Conf::ScalarNode Channel(_Channel);
+    Conf::ScalarNode Size(_Size);
+    Conf::ScalarNode Rate (_Rate);
+
+    preferencemap.setKeyValue (videoDeviceKey, &Device);
+    preferencemap.setKeyValue (videoChannelKey, &Channel);
+    preferencemap.setKeyValue (videoSizeKey, &Size);
+    preferencemap.setKeyValue (videoRateKey, &Rate);
 
     emitter->serializeVideoPreference (&preferencemap);
 
@@ -723,20 +726,21 @@ void VideoPreference::unserialize (Conf::MappingNode *map)
 
 
     val = (Conf::ScalarNode *) (map->getValue (videoDeviceKey));
-    if (val)
-        _videoDevice = atoi(val->getValue().data());
+    if (val) {
+        _Device = val->getValue().data();
+    }
 
-    val = (Conf::ScalarNode *) (map->getValue (videoInputKey));
+    val = (Conf::ScalarNode *) (map->getValue (videoChannelKey));
     if (val)
-        _videoInput = atoi(val->getValue().data());
+        _Channel = val->getValue().data();
 
     val = (Conf::ScalarNode *) (map->getValue (videoSizeKey));
     if (val)
-        _videoSize = atoi(val->getValue().data());
+        _Size = val->getValue().data();
 
     val = (Conf::ScalarNode *) (map->getValue (videoRateKey));
     if (val)
-        _videoRate = atoi(val->getValue().data());
+        _Rate = val->getValue().data();
 }
 
 
diff --git a/sflphone-common/src/preferences.h b/sflphone-common/src/preferences.h
index d10c1afdc9..137dd3e2fb 100644
--- a/sflphone-common/src/preferences.h
+++ b/sflphone-common/src/preferences.h
@@ -96,7 +96,7 @@ const Conf::Key echoDelayKey ("echoDelayLength");
 
 // video preferences
 const Conf::Key videoDeviceKey ("v4l2Dev");
-const Conf::Key videoInputKey ("v4l2Input");
+const Conf::Key videoChannelKey ("v4l2Channel");
 const Conf::Key videoSizeKey ("v4l2Size");
 const Conf::Key videoRateKey ("v4l2Rate");
 
@@ -599,69 +599,67 @@ class VideoPreference : public Serializable
 
         virtual void unserialize (Conf::MappingNode *map);
 
-        std::map<std::string, std::string> getVideoSettings(void) {
-            std::map<std::string, std::string> map;
-            VideoV4l2Device &dev = v4l2_list->getDevice();
-            map["input"] = dev.device;
-            std::stringstream channelstr;
-            channelstr << dev.getChannelIndex();
-            map["channel"] = channelstr.str();
-            VideoV4l2Channel &chan = dev.getChannel();
-            VideoV4l2Size &size = chan.getSize();
-            std::stringstream ss;
-            ss << size.width << "x" << size.height;
-            map["video_size"] = ss.str();
-            VideoV4l2Rate &rate = size.getRate();
+        std::map<std::string, std::string> getVideoSettings(void);
 
-            std::stringstream framestr;
-            framestr << rate.den << "/" << rate.num;
-            map["framerate"] = framestr.str();
+        const std::string &getDevice(void) {
+            return _Device;
+        }
 
-            return map;
+        void setDevice(const std::string &device) {
+            _Device = device;
         }
 
-        int getVideoDevice(void) {
-            return _videoDevice;
+        const std::string & getChannel(void) {
+            return _Channel;
         }
 
-        void setVideoDevice(int device) {
-            _videoDevice = device;
+        void setChannel(const std::string & input) {
+            _Channel = input;
         }
 
-        int getVideoInput(void) {
-            return _videoInput;
+        const std::string & getSize(void) {
+            return _Size;
         }
 
-        void setVideoInput(int input) {
-            _videoInput = input;
+        void setSize(const std::string & size) {
+            _Size = size;
         }
 
-        int getVideoSize(void) {
-            return _videoSize;
+        const std::string & getRate(void) {
+            return _Rate;
         }
 
-        void setVideoSize(int size) {
-            _videoSize = size;
+        void setRate(const std::string & rate) {
+            _Rate = rate;
         }
 
-        int getVideoRate(void) {
-            return _videoRate;
+        std::vector<std::string> getDeviceList() {
+        	return _v4l2_list->getDeviceList();
         }
 
-        void setVideoRate(int rate) {
-            _videoRate = rate;
+        std::vector<std::string> getChannelList(const std::string &dev) {
+        	return _v4l2_list->getChannelList(dev);
         }
 
-        // V4L2 devices
-        sfl_video::VideoV4l2List *v4l2_list;
+        std::vector<std::string> getSizeList(const std::string &dev, const std::string &channel) {
+        	return _v4l2_list->getSizeList(dev, channel);
+        }
+
+        std::vector<std::string> getRateList(const std::string &dev, const std::string &channel, const std::string &size) {
+        	return _v4l2_list->getRateList(dev, channel, size);
+        }
+
+
     private:
 
-        int _videoDevice;
-        int _videoInput;
-        int _videoSize;
-        int _videoRate;
-};
+        // V4L2 devices
+        sfl_video::VideoV4l2List *_v4l2_list;
 
+        std::string _Device;
+        std::string _Channel;
+        std::string _Size;
+        std::string _Rate;
+};
 
 class ShortcutPreferences : public Serializable
 {
diff --git a/sflphone-common/src/video/test/test_v4l2.cpp b/sflphone-common/src/video/test/test_v4l2.cpp
index 60518af8cb..394f0b2219 100644
--- a/sflphone-common/src/video/test/test_v4l2.cpp
+++ b/sflphone-common/src/video/test/test_v4l2.cpp
@@ -36,64 +36,40 @@
 using namespace std;
 
 #include "video_v4l2_list.h"
-#include "video_v4l2.h"
+//#include "video_v4l2.h"
 using namespace sfl_video;
 
 int main()
 {
-    int idx;
     VideoV4l2List list;
-    std::vector<std::string> v = list.getDeviceList();
-    idx = list.getDeviceIndex();
-    if (idx < 0) {
-    	cout << "No devices found!" << endl;
-    	return 0;
-    }
-    list.setDevice(idx);
-
-    size_t i, n = v.size();
-    assert(idx < n);
-    for (i=0; i<n; i++) {
-        cout << ((idx == i) ? " * " : "   ");
-        cout << v[i] << endl;
-    }
+    std::vector<std::string> devlist = list.getDeviceList();
 
-    VideoV4l2Device &dev = list.getDevice();
-    idx = dev.getChannelIndex();
-    dev.setChannel(idx);
-    v = dev.getChannelList();
+    for (size_t i=0; i<devlist.size(); i++) {
+        const std::string &dev = devlist[i];
+        cout << dev << endl;
 
-    n = v.size();
-    assert(idx < n);
-    for (i=0; i<n; i++) {
-        cout << ((idx == i) ? " * " : "   ");
-        cout << "\t" << v[i] << endl;
-    }
-
-    VideoV4l2Channel &chan = dev.getChannel();
-    VideoV4l2Size &size = chan.getSize();
-    idx = chan.getSizeIndex();
-    chan.setSize(idx);
-    v = chan.getSizeList();
-
-    n = v.size();
-    assert(idx < n);
-    for (i=0; i<n; i++) {
-        cout << ((idx == i) ? " * " : "   ");
-        cout << "\t\t" << v[i] << endl;
-    }
+        std::vector<std::string> channellist = list.getChannelList(dev);
+        for (size_t i=0; i<channellist.size(); i++) {
+            const std::string &chan = channellist[i];
+            cout << '\t' << chan << endl;
 
-    //VideoV4l2Rate &rate = chan.getRate();
-    idx = size.getRateIndex();
-    size.setRate(idx);
-    v = size.getRateList();
+            std::vector<std::string> sizelist = list.getSizeList(dev, chan);
+            for (size_t i=0; i<sizelist.size(); i++) {
+                const std::string &size = sizelist[i];
+                cout << "\t\t" << size << endl;
 
-    n = v.size();
-    assert(idx < n);
-    for (i=0; i<n; i++) {
-        cout << ((idx == i) ? " * " : "   ");
-        cout << "\t\t\t" << v[i] << endl;
+                std::vector<std::string> ratelist = list.getRateList(dev, chan, size);
+                for (size_t i=0; i<ratelist.size(); i++) {
+                    const std::string &rate = ratelist[i];
+                    cout << "\t\t\t" << rate << endl;
+                }
+                cout << endl;
+            }
+            cout << endl;
+        }
+        cout << endl;
     }
+    cout << endl;
 
     return 0;
 }
diff --git a/sflphone-common/src/video/test/test_video_preview.cpp b/sflphone-common/src/video/test/test_video_preview.cpp
index 3d890016b5..949f71aa46 100644
--- a/sflphone-common/src/video/test/test_video_preview.cpp
+++ b/sflphone-common/src/video/test/test_video_preview.cpp
@@ -31,10 +31,20 @@
 #include <unistd.h> // for sleep
 #include "test_video_preview.h"
 #include "video_preview.h"
+#include <map>
+#include <string>
+
+using namespace std;
 
 void VideoPreviewTest::testPreview()
 {
-    sfl_video::VideoPreview preview("/dev/video0");
+    std::map<std::string, std::string> args;
+    args["input"] = "/dev/video0";
+    args["format"] = "rgb24";
+    args["width"] = "640";
+    args["height"] = "480";
+
+    sfl_video::VideoPreview preview(args);
     preview.start();
     sleep(10);
     preview.stop();
diff --git a/sflphone-common/src/video/video_v4l2.cpp b/sflphone-common/src/video/video_v4l2.cpp
index 29ac3b60f3..af93b3c560 100644
--- a/sflphone-common/src/video/video_v4l2.cpp
+++ b/sflphone-common/src/video/video_v4l2.cpp
@@ -109,9 +109,9 @@ static const unsigned pixelformats_supported[] = {
  *
  * Other entries in the array are YUV formats
  *
- * RGB / grey / palette formats are not supported because most cameras support 
+ * RGB / grey / palette formats are not supported because most cameras support
  * YUV input
- * 
+ *
  */
 
 static unsigned int pixelformat_score(unsigned pixelformat)
@@ -124,7 +124,7 @@ static unsigned int pixelformat_score(unsigned pixelformat)
     return UINT_MAX - 1;
 }
 
-VideoV4l2Size::VideoV4l2Size(unsigned height, unsigned width) : height(height), width(width), _currentRate(0) {}
+VideoV4l2Size::VideoV4l2Size(unsigned height, unsigned width) : height(height), width(width) {}
 
 std::vector<std::string> VideoV4l2Size::getRateList()
 {
@@ -134,33 +134,14 @@ std::vector<std::string> VideoV4l2Size::getRateList()
 	size_t n = rates.size();
 	unsigned i;
 	for (i = 0 ; i < n ; i++) {
-		VideoV4l2Rate rate = rates[i];
 		std::stringstream ss;
-		ss << (float)rate.den / rate.num;
+		ss << rates[i];
 		v.push_back(ss.str());
 	}
 
 	return v;
 }
 
-void VideoV4l2Size::setRate(unsigned index)
-{
-    if (index >= rates.size())
-        index = rates.size() - 1;
-    _currentRate = index;
-}
-
-unsigned VideoV4l2Size::getRateIndex()
-{
-    return _currentRate;
-}
-
-VideoV4l2Rate &VideoV4l2Size::getRate()
-{
-    return rates[_currentRate];
-}
-
-
 
 void VideoV4l2Size::GetFrameRates(int fd, unsigned int pixel_format)
 {
@@ -172,8 +153,7 @@ void VideoV4l2Size::GetFrameRates(int fd, unsigned int pixel_format)
     };
 
     if (ioctl(fd, VIDIOC_ENUM_FRAMEINTERVALS, &frmival)) {
-        VideoV4l2Rate rate(1, 25);
-        rates.push_back(rate);
+        rates.push_back(25);
         _error("could not query frame interval for size");
         return;
     }
@@ -181,26 +161,24 @@ void VideoV4l2Size::GetFrameRates(int fd, unsigned int pixel_format)
     switch(frmival.type) {
     case V4L2_FRMIVAL_TYPE_DISCRETE:
         do {
-            VideoV4l2Rate rate(frmival.discrete.numerator,
-                           frmival.discrete.denominator);
-            rates.push_back(rate);
+            rates.push_back(frmival.discrete.denominator/frmival.discrete.numerator);
             frmival.index++;
         } while (!ioctl(fd, VIDIOC_ENUM_FRAMEINTERVALS, &frmival));
         break;
     case V4L2_FRMIVAL_TYPE_CONTINUOUS:
-        rates.push_back(VideoV4l2Rate(1,25));
+        rates.push_back(25);
         // TODO
         _error("Continuous Frame Intervals not supported");
         break;
     case V4L2_FRMIVAL_TYPE_STEPWISE:
-        rates.push_back(VideoV4l2Rate(1, 25));
+        rates.push_back(25);
         // TODO
         _error("Stepwise Frame Intervals not supported");
         break;
     }
 }
 
-VideoV4l2Channel::VideoV4l2Channel(unsigned idx, const char *s) : idx(idx), name(s), _currentSize(0) { }
+VideoV4l2Channel::VideoV4l2Channel(unsigned idx, const char *s) : idx(idx), name(s) { }
 
 void VideoV4l2Channel::SetFourcc(unsigned code)
 {
@@ -216,13 +194,6 @@ const char * VideoV4l2Channel::GetFourcc()
 	return fourcc;
 }
 
-void VideoV4l2Channel::setSize(unsigned index)
-{
-    if (index >= sizes.size())
-        index = sizes.size() - 1;
-    _currentSize = index;
-}
-
 std::vector<std::string> VideoV4l2Channel::getSizeList(void)
 {
     std::vector<std::string> v;
@@ -240,17 +211,6 @@ std::vector<std::string> VideoV4l2Channel::getSizeList(void)
 }
 
 
-unsigned VideoV4l2Channel::getSizeIndex()
-{
-    return _currentSize;
-}
-
-VideoV4l2Size &VideoV4l2Channel::getSize()
-{
-    return sizes[_currentSize];
-}
-
-
 
 unsigned int VideoV4l2Channel::GetSizes(int fd, unsigned int pixelformat)
 {
@@ -301,26 +261,27 @@ void VideoV4l2Channel::GetFormat(int fd)
         throw std::runtime_error("VIDIOC_S_INPUT failed");
 
     struct v4l2_fmtdesc fmt;
-    fmt.index = idx = 0;
+    unsigned fmt_index;
+    fmt.index = fmt_index = 0;
     fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 
     unsigned int best_score = UINT_MAX;
     unsigned int best_idx = 0;
     unsigned int pixelformat = 0;
     while (!ioctl(fd, VIDIOC_ENUM_FMT, &fmt)) {
-        if (idx != fmt.index)
+        if (fmt_index != fmt.index)
             break;
-       
+
         unsigned int score = pixelformat_score(fmt.pixelformat);
         if (score < best_score) {
             pixelformat = fmt.pixelformat;
-            best_idx = idx;
+            best_idx = fmt_index;
             best_score = score;
         }
 
-        fmt.index = ++idx;
+        fmt.index = ++fmt_index;
     }
-    if (idx == 0)
+    if (fmt_index == 0)
         throw std::runtime_error("Could not enumerate formats");
 
     fmt.index = best_idx;
@@ -329,7 +290,20 @@ void VideoV4l2Channel::GetFormat(int fd)
     SetFourcc(pixelformat);
 }
 
-VideoV4l2Device::VideoV4l2Device(int fd, const std::string &device) : _currentChannel(0)
+VideoV4l2Size VideoV4l2Channel::getSize(const std::string &name)
+{
+	for (size_t i = 0; i < sizes.size(); i++) {
+		std::stringstream ss;
+		ss << sizes[i].width << "x" << sizes[i].height;
+		if (ss.str() == name)
+			return sizes[i];
+	}
+
+	throw std::runtime_error("No size found");
+}
+
+
+VideoV4l2Device::VideoV4l2Device(int fd, const std::string &device)
 {
     unsigned idx;
 
@@ -341,7 +315,6 @@ VideoV4l2Device::VideoV4l2Device(int fd, const std::string &device) : _currentCh
         throw std::runtime_error("not a capture device");
 
     name = std::string((const char*)cap.card);
-    _error("%s", name.c_str());
 
     struct v4l2_input input;
     input.index = idx = 0;
@@ -373,21 +346,13 @@ std::vector<std::string> VideoV4l2Device::getChannelList(void)
     return v;
 }
 
-void VideoV4l2Device::setChannel(unsigned index)
-{
-    if (index >= channels.size())
-        index = channels.size() - 1;
-    _currentChannel = index;
-}
-
-unsigned VideoV4l2Device::getChannelIndex()
+VideoV4l2Channel &VideoV4l2Device::getChannel(const std::string &name)
 {
-    return _currentChannel;
-}
+	for (size_t i = 0; i < channels.size(); i++)
+		if (channels[i].name == name)
+			return channels[i];
 
-VideoV4l2Channel &VideoV4l2Device::getChannel()
-{
-    return channels[_currentChannel];
+	throw std::runtime_error("No channel found");
 }
 
 
diff --git a/sflphone-common/src/video/video_v4l2.h b/sflphone-common/src/video/video_v4l2.h
index 647316fda9..68497c8a9a 100644
--- a/sflphone-common/src/video/video_v4l2.h
+++ b/sflphone-common/src/video/video_v4l2.h
@@ -45,14 +45,6 @@ extern "C" {
 
 namespace sfl_video {
 
-class VideoV4l2Rate {
-    public:
-        VideoV4l2Rate(unsigned num, unsigned den) : den(den), num(num) {}
-
-        unsigned den;
-        unsigned num;
-};
-
 class VideoV4l2Size {
     public:
         VideoV4l2Size(unsigned height, unsigned width);
@@ -63,17 +55,11 @@ class VideoV4l2Size {
         void GetFrameRates(int fd, unsigned int pixel_format);
         std::vector<std::string> getRateList();
 
-
-        void setRate(unsigned index);
-        unsigned getRateIndex();
-        VideoV4l2Rate &getRate();
-
         unsigned height;
         unsigned width;
 
     private:
-        std::vector<VideoV4l2Rate> rates;
-        unsigned _currentRate;
+        std::vector<float> rates;
 };
 
 class VideoV4l2Channel {
@@ -92,12 +78,8 @@ class VideoV4l2Channel {
         void SetFourcc(unsigned code);
         const char * GetFourcc();
 
-        void setSize(unsigned index);
-
         std::vector<std::string> getSizeList(void);
-        unsigned getSizeIndex();
-
-        VideoV4l2Size &getSize();
+        VideoV4l2Size getSize(const std::string &name);
 
         unsigned idx;
         std::string name;
@@ -105,7 +87,6 @@ class VideoV4l2Channel {
     private:
         std::vector<VideoV4l2Size> sizes;
         char fourcc[5];
-        unsigned _currentSize;
 };
 
 class VideoV4l2Device {
@@ -119,13 +100,11 @@ class VideoV4l2Device {
         std::string name;
 
         std::vector<std::string> getChannelList(void);
-        void setChannel(unsigned index);
-        unsigned getChannelIndex();
-        VideoV4l2Channel &getChannel();
+
+        VideoV4l2Channel &getChannel(const std::string &name);
 
     private:
         std::vector<VideoV4l2Channel> channels;
-        unsigned _currentChannel;
 };
 
 } // namespace sfl_video
diff --git a/sflphone-common/src/video/video_v4l2_list.cpp b/sflphone-common/src/video/video_v4l2_list.cpp
index c944309335..b7675a1a58 100644
--- a/sflphone-common/src/video/video_v4l2_list.cpp
+++ b/sflphone-common/src/video/video_v4l2_list.cpp
@@ -39,6 +39,8 @@
 #include <stdexcept> // for std::runtime_error
 #include <sstream>
 
+#include <cc++/thread.h>
+
 #include "logger.h"
 
 #ifdef HAVE_UDEV
@@ -57,7 +59,7 @@ extern "C" {
 
 namespace sfl_video {
 
-VideoV4l2List::VideoV4l2List() : _currentDevice(-1)
+VideoV4l2List::VideoV4l2List()
 {
 #ifdef HAVE_UDEV
     struct udev *udev;
@@ -153,7 +155,6 @@ int GetNumber(const std::string &name, size_t *sharp)
 	for (size_t c = len; c; --c) {
 		if (name[c] == '#') {
 			unsigned i;
-			printf("looking `%s'\n", name.substr(c).c_str());
 			if (sscanf(name.substr(c).c_str(), "#%u", &i) != 1)
 				return -1;
 			*sharp = c;
@@ -166,7 +167,7 @@ int GetNumber(const std::string &name, size_t *sharp)
 
 void GiveUniqueName(VideoV4l2Device &dev, const std::vector<VideoV4l2Device> &devices)
 {
-    const std::string &name = dev.name;
+	const std::string &name = dev.name;
     start:
     for (size_t i = 0; i < devices.size(); i++) {
 		if (name == devices[i].name) {
@@ -186,8 +187,43 @@ void GiveUniqueName(VideoV4l2Device &dev, const std::vector<VideoV4l2Device> &de
 
 } // end anonymous namespace
 
+VideoV4l2List::~VideoV4l2List()
+{
+	terminate();
+}
+
+void VideoV4l2List::run()
+{
+	sleep(1000000);
+	_mutex.enter();
+	//FIXME : notify preferences change
+	_mutex.leave();
+}
+
+void VideoV4l2List::finalize()
+{
+
+}
+
+void VideoV4l2List::delDevice(const std::string &node)
+{
+	ost::MutexLock lock(_mutex);
+    std::vector<std::string> v;
+
+    size_t n = devices.size();
+    unsigned i;
+    for (i = 0 ; i < n ; i++) {
+        if (devices[i].device == node) {
+        	devices.erase(devices.begin() + i);
+        	// update preferences
+        	return;
+        }
+    }
+}
+
 bool VideoV4l2List::addDevice(const std::string &dev)
 {
+	ost::MutexLock lock(_mutex);
     int fd = open(dev.c_str(), O_RDWR);
     if (fd == -1)
         return false;
@@ -196,23 +232,32 @@ bool VideoV4l2List::addDevice(const std::string &dev)
     VideoV4l2Device v(fd, s);
     GiveUniqueName(v, devices);
     devices.push_back(v);
-    if (_currentDevice < 0)
-    	_currentDevice = 0;
 
-    close(fd);
+    ::close(fd);
     return true;
 }
 
-void VideoV4l2List::setDevice(unsigned index)
+std::vector<std::string> VideoV4l2List::getChannelList(const std::string &dev)
+{
+	ost::MutexLock lock(_mutex);
+	return getDevice(dev).getChannelList();
+}
+
+std::vector<std::string> VideoV4l2List::getSizeList(const std::string &dev, const std::string &channel)
 {
-    if (index >= devices.size())
-        index = devices.size() - 1;
+	ost::MutexLock lock(_mutex);
+	return getDevice(dev).getChannel(channel).getSizeList();
+}
 
-    _currentDevice = index;
+std::vector<std::string> VideoV4l2List::getRateList(const std::string &dev, const std::string &channel, const std::string &size)
+{
+	ost::MutexLock lock(_mutex);
+	return getDevice(dev).getChannel(channel).getSize(size).getRateList();
 }
 
 std::vector<std::string> VideoV4l2List::getDeviceList(void)
 {
+	ost::MutexLock lock(_mutex);
     std::vector<std::string> v;
 
     size_t n = devices.size();
@@ -232,23 +277,27 @@ std::vector<std::string> VideoV4l2List::getDeviceList(void)
     return v;
 }
 
-int VideoV4l2List::getDeviceIndex(const std::string &name)
+VideoV4l2Device &VideoV4l2List::getDevice(const std::string &name)
 {
-	for (size_t i = 0; i < devices.size(); i++)
+	ost::MutexLock lock(_mutex);
+	for (size_t i = 0; i < devices.size(); i++) {
 		if (devices[i].name == name)
-			return i;
+			return devices[i];
+	}
 
-	return -1;
+	throw std::runtime_error("No device found");
 }
 
-int VideoV4l2List::getDeviceIndex()
+unsigned VideoV4l2List::getChannelNum(const std::string &dev, const std::string &name)
 {
-    return _currentDevice;
+	ost::MutexLock lock(_mutex);
+	return getDevice(dev).getChannel(name).idx;
 }
 
-VideoV4l2Device &VideoV4l2List::getDevice()
+const std::string &VideoV4l2List::getDeviceNode(const std::string &name)
 {
-    return devices[_currentDevice];
+	ost::MutexLock lock(_mutex);
+	return getDevice(name).device;
 }
 
 } // namespace sfl_video
diff --git a/sflphone-common/src/video/video_v4l2_list.h b/sflphone-common/src/video/video_v4l2_list.h
index 9e076b8afb..51f413b67d 100644
--- a/sflphone-common/src/video/video_v4l2_list.h
+++ b/sflphone-common/src/video/video_v4l2_list.h
@@ -33,28 +33,37 @@
 
 #include <string>
 #include <vector>
-
+#include <cc++/thread.h>
 #include "video_v4l2.h"
 
+
 namespace sfl_video {
 
-class VideoV4l2List {
+class VideoV4l2List : public ost::Thread {
     public:
         VideoV4l2List();
+        ~VideoV4l2List();
+
+        virtual void run();
+        virtual void finalize();
 
-        void setDevice(unsigned index);
-        int getDeviceIndex(void);
-        int getDeviceIndex(const std::string &name);
         std::vector<std::string> getDeviceList(void);
-        VideoV4l2Device &getDevice(void);
+        std::vector<std::string> getChannelList(const std::string &dev);
+        std::vector<std::string> getSizeList(const std::string &dev, const std::string &channel);
+        std::vector<std::string> getRateList(const std::string &dev, const std::string &channel, const std::string &size);
+
+        VideoV4l2Device &getDevice(const std::string &name);
+        const std::string &getDeviceNode(const std::string &name);
+        unsigned getChannelNum(const std::string &dev, const std::string &name);
 
     private:
         /**
          * @throw std::runtime_error
          */
+        void delDevice(const std::string &node);
         bool addDevice(const std::string &dev);
         std::vector<VideoV4l2Device> devices;
-        int _currentDevice;
+        ost::Mutex _mutex;
 };
 
 } // namespace sfl_video
-- 
GitLab