Commit 2ce82cfe authored by Rafaël Carré's avatar Rafaël Carré

* 6594 : configuration dialog for video codecs

remove a bunch of unused functions
remove a bunch of pointer indirection
remove a bunch of memleaks

video codecs are identified by their name rather than by their payload,
because for most (all?) codecs the payload is dynamic.

remove unused codecs bandwidth information
parent 670123ca
......@@ -82,8 +82,9 @@ typedef struct {
GHashTable * properties;
GPtrArray * credential_information;
/* The codec list */
/* The codec lists */
GQueue *codecs;
GQueue *vcodecs;
guint _messages_number;
} account_t;
......
......@@ -370,7 +370,12 @@ gboolean sflphone_init (GError **error)
history = calltab_init (TRUE, HISTORY);
account_list_init ();
codec_capabilities_load ();
if (!codecs_load ()) {
ERROR ("No codecs found");
dbus_unregister (getpid());
exit (1);
}
conferencelist_init (current_calls);
conferencelist_init (history);
......@@ -391,9 +396,9 @@ void sflphone_fill_ip2ip_profile (void)
ip2ip_profile = (GHashTable *) dbus_get_ip2_ip_details();
}
void sflphone_get_ip2ip_properties (GHashTable **properties)
GHashTable *sflphone_get_ip2ip_properties (void)
{
*properties = ip2ip_profile;
return ip2ip_profile;
}
void
......@@ -1186,83 +1191,86 @@ sflphone_rec_call()
void sflphone_fill_codec_list ()
{
guint account_list_size;
guint i;
account_t *current = NULL;
DEBUG ("SFLphone: Fill codec list");
account_list_size = account_list_get_size ();
guint i, account_list_size = account_list_get_size ();
for (i=0; i<account_list_size; i++) {
current = account_list_get_nth (i);
if (current) {
sflphone_fill_codec_list_per_account (&current);
}
account_t *current = account_list_get_nth (i);
if (current)
sflphone_fill_codec_list_per_account (current);
}
}
void sflphone_fill_codec_list_per_account (account_t **account)
static void sflphone_fill_codec_list_per_account_cat (account_t *account, gboolean is_audio)
{
gchar **order;
gchar** pl;
GQueue *codeclist;
gboolean active = FALSE;
order = (gchar**) dbus_get_active_audio_codec_list ( (*account)->accountID);
codeclist = (*account)->codecs;
order = is_audio
? dbus_get_active_audio_codec_list (account->accountID)
: dbus_get_active_video_codec_list (account->accountID);
if (is_audio) {
if (!account->codecs)
account->codecs = g_queue_new();
codeclist = account->codecs;
} else {
if (!account->vcodecs)
account->vcodecs = g_queue_new();
codeclist = account->vcodecs;
}
// First clean the list
codec_list_clear (&codeclist);
g_queue_clear (codeclist);
if (! (*order))
ERROR ("SFLphone: No codec list provided");
GQueue* codecs = is_audio ? get_audio_codecs_list() : get_video_codecs_list();
gchar **pl;
for (pl=order; *pl; pl++) {
codec_t * cpy = NULL;
// Each account will have a copy of the system-wide capabilities
codec_create_new_from_caps (codec_list_get_by_payload ( (gconstpointer) (size_t) atoi (*pl), NULL), &cpy);
if (cpy) {
cpy->is_active = TRUE;
codec_list_add (cpy, &codeclist);
} else
ERROR ("SFLphone: Couldn't find codec");
codec_t *orig;
if (is_audio)
orig = codec_list_get_by_payload (atoi(*pl), codecs);
else
orig = codec_list_get_by_name(*pl, codecs);
codec_t *c = codec_create_new_from_caps (orig);
if (c)
g_queue_push_tail (codeclist, (gpointer) c);
else
ERROR ("SFLphone: Couldn't find codec %s %p", *pl, orig);
g_free(*pl);
}
g_free(order);
// Test here if we just added some active codec.
active = (codeclist->length == 0) ? TRUE : FALSE;
guint caps_size = codec_list_get_size (), i=0;
// if no codecs were added, activate them all
gboolean active = codeclist->length == 0;
guint i, caps_size = g_queue_get_length(codecs);
for (i=0; i<caps_size; i++) {
codec_t * current_cap = capabilities_get_nth (i);
codec_t * codec = g_queue_peek_nth (codecs, i);
gboolean found;
// Check if this codec has already been enabled for this account
if (codec_list_get_by_payload ( (gconstpointer) (size_t) (current_cap->_payload), codeclist) == NULL) {
// codec_t *cpy;
// codec_create_new_from_caps (current_cap, &cpy);
current_cap->is_active = active;
codec_list_add (current_cap, &codeclist);
} else {
if (is_audio)
found = codec_list_get_by_payload (codec->payload, codeclist) != NULL;
else
found = codec_list_get_by_name(codec->name, codeclist) != NULL;
if (!found) {
codec->is_active = active;
g_queue_push_tail (codeclist, (gpointer)codec);
}
}
}
(*account)->codecs = codeclist;
void sflphone_fill_codec_list_per_account (account_t *account)
{
sflphone_fill_codec_list_per_account_cat(account, TRUE);
sflphone_fill_codec_list_per_account_cat(account, FALSE);
}
void sflphone_fill_call_list (void)
{
gchar** calls = (gchar**) dbus_get_call_list();
gchar** calls = dbus_get_call_list();
GHashTable *call_details;
callable_obj_t *c;
gchar *callID;
......
......@@ -172,7 +172,7 @@ void sflphone_fill_ip2ip_profile (void);
* @return The internal hash table representing
* the settings for the ip2ip profile.
*/
void sflphone_get_ip2ip_properties (GHashTable **properties);
GHashTable *sflphone_get_ip2ip_properties (void);
/**
* Initialize the accounts data structure
......@@ -192,7 +192,7 @@ void sflphone_set_current_account();
*/
void sflphone_fill_codec_list ();
void sflphone_fill_codec_list_per_account (account_t **);
void sflphone_fill_codec_list_per_account (account_t *);
void sflphone_add_participant();
......
......@@ -96,19 +96,13 @@ gchar* call_get_peer_number (const gchar *format)
gchar* call_get_audio_codec (callable_obj_t *obj)
{
gchar *audio_codec = "";
codec_t *codec;
gchar *format ="";
int samplerate;
gchar *format = NULL;
if (obj) {
audio_codec = dbus_get_current_audio_codec_name (obj);
codec = codec_list_get_by_name (audio_codec, NULL);
if (codec) {
samplerate = codec->sample_rate;
format = g_markup_printf_escaped ("%s/%i", audio_codec, samplerate);
}
gchar *audio_codec = dbus_get_current_audio_codec_name (obj);
codec_t *codec = codec_list_get_by_name (audio_codec, get_audio_codecs_list());
if (codec)
format = g_markup_printf_escaped ("%s/%s", audio_codec, codec->sample_rate);
g_free(audio_codec);
}
return format;
......
This diff is collapsed.
......@@ -39,17 +39,15 @@
typedef struct {
/** Payload of the codec */
gint _payload;
gint payload;
/** Tells if the codec has been activated */
gboolean is_active;
/** String description */
gchar * name;
/** Sample rate */
int sample_rate;
gchar * sample_rate;
/** Bitrate */
gdouble _bitrate;
/** Bandwidth */
gdouble _bandwidth;
gchar * bitrate;
} codec_t;
/** @struct codec_t
......@@ -58,49 +56,16 @@ typedef struct {
* This match how the server internally works and the dbus API to save and retrieve the codecs details.
*/
/**
* This function initialize a specific codec list.
*/
void codec_list_init (GQueue **q);
/**
* This function initialize the system wide codec list.
* @return FALSE if initialization failed
*/
void codec_capabilities_load (void);
/**
* This function empty and free a specific codec list.
*/
void codec_list_clear (GQueue **q);
gboolean codecs_load (void);
/**
* This function empty and free the system wide codec list.
*/
void system_codec_list_clear (void);
/**
* This function append an codec to list.
* @param c The codec you want to add
*/
void codec_list_add (codec_t * c, GQueue **q);
/**
* Set a codec active. An active codec will be used for codec negociation
* @param name The string description of the codec
*/
void codec_set_active (codec_t **c);
/**
* Set a codec inactive. An active codec won't be used for codec negociation
* @param name The string description of the codec
*/
void codec_set_inactive (codec_t **c);
/**
* Return the number of codecs in the list
* @return guint The number of codecs in the list
*/
guint codec_list_get_size();
void codecs_unload (void);
/**
* Return the codec structure that corresponds to the string description
......@@ -109,14 +74,6 @@ guint codec_list_get_size();
*/
codec_t * codec_list_get_by_name (gconstpointer name, GQueue *q);
/**
* Return the codec at the nth position in the list
* @param index The position of the codec you want
* @return codec_t* A codec or NULL
*/
codec_t* codec_list_get_nth (guint index, GQueue *q);
codec_t* capabilities_get_nth (guint index);
/**
* Set the prefered codec first in the codec list
* @param index The position in the list of the prefered codec
......@@ -126,54 +83,22 @@ void codec_set_prefered_order (guint index, GQueue *q);
/**
* Move the codec from an unit up in the codec_list
* @param index The current index in the list
* @param q
* @param up true if moving upwards
*/
void codec_list_move_codec_up (guint index, GQueue **q);
/**
* Move the codec from an unit down in the codec_list
* @param index The current index in the list
*/
void codec_list_move_codec_down (guint index, GQueue **q);
void codec_list_move (guint index, GQueue *q, gboolean up);
/**
* Notify modifications on codecs to the server
*/
void codec_list_update_to_daemon (account_t *acc);
codec_t* codec_list_get_by_payload (gconstpointer payload, GQueue *q);
codec_t* codec_list_get_by_payload (int payload, GQueue *q);
GQueue* get_system_codec_list (void);
GQueue* get_video_codecs_list (void);
/**
* Instanciate a new codecs with the given payload.
* Fetches codec specification through D-Bus
*
* @param payload The unique RTP payload
* @param active Whether or not this codec should active (checked)
* @param c A pointer to receive the new codec instance
*/
void codec_create_new (gint payload, gboolean active, codec_t **c);
/*
* Instanciate a new codec with the given specification
*
* @param payload The unique RTP payload
* @param specs A list of codec specifications. Ordered: name, sample rate, bit rate, bandwith
* @param active Whether or not this codec should active (checked)
* @param c A pointer to receive the new codec instance
*/
void codec_create_new_with_specs (gint payload, gchar **specs, gboolean active, codec_t **c);
void codec_create_new_from_caps (codec_t *original, codec_t **copy);
/*
* Attach a codec list to a specific account
*
* @param acc A pointer on the account to modify
*/
void account_create_codec_list (account_t **acc);
GQueue* get_audio_codecs_list (void);
codec_t *codec_create_new_from_caps (codec_t *original);
#endif
......@@ -1254,7 +1254,7 @@ static GtkWidget* create_audiocodecs_configuration (account_t *currentAccount)
return ret;
}
GtkWidget* create_videocodecs_configuration (account_t **a)
GtkWidget* create_videocodecs_configuration (account_t *a)
{
// Main widget
......@@ -1329,7 +1329,7 @@ void show_account_window (account_t * currentAccount)
currentAccount = g_new0 (account_t, 1);
currentAccount->properties = dbus_get_account_details (NULL);
currentAccount->accountID = "new";
sflphone_fill_codec_list_per_account (&currentAccount);
sflphone_fill_codec_list_per_account (currentAccount);
}
dialog = GTK_DIALOG (gtk_dialog_new_with_buttons (_ ("Account settings"),
......@@ -1367,7 +1367,7 @@ void show_account_window (account_t * currentAccount)
gtk_notebook_page_num (GTK_NOTEBOOK (notebook), audiocodecs_tab);
/* Video Codecs */
videocodecs_tab = create_videocodecs_configuration (&currentAccount);
videocodecs_tab = create_videocodecs_configuration (currentAccount);
gtk_notebook_append_page (GTK_NOTEBOOK (notebook), videocodecs_tab, gtk_label_new (_ ("Video")));
gtk_notebook_page_num (GTK_NOTEBOOK (notebook), videocodecs_tab);
......
......@@ -70,40 +70,35 @@ static void active_is_always_recording (void);
*/
static void preferences_dialog_fill_codec_list (account_t *a)
{
GtkListStore *codecStore;
GtkTreeIter iter;
GQueue *current;
// Get model of view and clear it
codecStore = GTK_LIST_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (codecTreeView)));
gtk_list_store_clear (codecStore);
current = a ? a->codecs : get_system_codec_list ();
GQueue *list = a ? a->codecs : get_audio_codecs_list ();
// Insert codecs
unsigned int i;
for (i = 0; i < current->length; i++) {
codec_t *c = codec_list_get_nth (i, current);
for (i = 0; i < list->length; i++) {
codec_t *c = g_queue_peek_nth (list, i);
if (c) {
DEBUG ("%s", c->name);
gtk_list_store_append (codecStore, &iter);
gchar *samplerate = g_strdup_printf ("%d kHz", c->sample_rate/1000);
gchar *bitrate = g_strdup_printf ("%.1f kbps", c->_bitrate);
gchar *bw = g_strdup_printf ("%.1f kbps", c->_bandwidth);
gchar *samplerate = g_strdup_printf ("%s kHz", c->sample_rate);
gchar *bitrate = g_strdup_printf ("%s kbps", c->bitrate);
gtk_list_store_set (codecStore, &iter,
COLUMN_CODEC_ACTIVE, c->is_active,
COLUMN_CODEC_NAME, c->name,
COLUMN_CODEC_NAME, c->name,
COLUMN_CODEC_FREQUENCY, samplerate,
COLUMN_CODEC_BITRATE, bitrate,
COLUMN_CODEC_BANDWIDTH, bw,
-1);
g_free(samplerate);
g_free(bitrate);
g_free(bw);
}
}
}
......@@ -533,11 +528,11 @@ codec_active_toggled (GtkCellRendererToggle *renderer UNUSED, gchar *path, gpoin
printf ("%i\n", g_queue_get_length (acc->codecs));
if ( (g_strcasecmp (name,"speex") ==0) && (g_strcasecmp (srate,"8 kHz") ==0))
codec = codec_list_get_by_payload ( (gconstpointer) 110, acc->codecs);
codec = codec_list_get_by_payload (110, acc->codecs);
else if ( (g_strcasecmp (name,"speex") ==0) && (g_strcasecmp (srate,"16 kHz") ==0))
codec = codec_list_get_by_payload ( (gconstpointer) 111, acc->codecs);
codec = codec_list_get_by_payload (111, acc->codecs);
else if ( (g_strcasecmp (name,"speex") ==0) && (g_strcasecmp (srate,"32 kHz") ==0))
codec = codec_list_get_by_payload ( (gconstpointer) 112, acc->codecs);
codec = codec_list_get_by_payload (112, acc->codecs);
else
codec = codec_list_get_by_name ( (gconstpointer) name, acc->codecs);
......@@ -552,11 +547,7 @@ codec_active_toggled (GtkCellRendererToggle *renderer UNUSED, gchar *path, gpoin
gtk_tree_path_free (treePath);
// Modify codec queue to represent change
if (active) {
codec_set_active (&codec);
} else {
codec_set_inactive (&codec);
}
codec->is_active = active;
}
/**
......@@ -572,19 +563,11 @@ static void codec_move (gboolean moveUp, gpointer data)
GtkTreeSelection *selection;
GtkTreePath *treePath;
gchar *path;
account_t *acc;
GQueue *acc_q;
// Get view, model and selection of codec store
model = gtk_tree_view_get_model (GTK_TREE_VIEW (codecTreeView));
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (codecTreeView));
// Retrieve the user data
acc = (account_t*) data;
if (acc)
acc_q = acc->codecs;
// Find selected iteration and create a copy
gtk_tree_selection_get_selected (GTK_TREE_SELECTION (selection), &model, &iter);
iter2 = gtk_tree_iter_copy (&iter);
......@@ -592,8 +575,7 @@ static void codec_move (gboolean moveUp, gpointer data)
// Find path of iteration
path = gtk_tree_model_get_string_from_iter (GTK_TREE_MODEL (model), &iter);
treePath = gtk_tree_path_new_from_string (path);
gint *indices = gtk_tree_path_get_indices (treePath);
gint indice = indices[0];
gint indice = *gtk_tree_path_get_indices (treePath);
// Depending on button direction get new path
if (moveUp)
......@@ -616,11 +598,7 @@ static void codec_move (gboolean moveUp, gpointer data)
g_free (path);
// Perpetuate changes in codec queue
if (moveUp)
codec_list_move_codec_up (indice, &acc_q);
else
codec_list_move_codec_down (indice, &acc_q);
codec_list_move (indice, ((account_t*)data)->codecs, moveUp);
}
/**
......@@ -700,11 +678,6 @@ GtkWidget* audiocodecs_box (account_t *a)
treeViewColumn = gtk_tree_view_column_new_with_attributes (_ ("Bitrate"), renderer, "text", COLUMN_CODEC_BITRATE, NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (codecTreeView), treeViewColumn);
// Frequency column
renderer = gtk_cell_renderer_text_new();
treeViewColumn = gtk_tree_view_column_new_with_attributes (_ ("Bandwidth"), renderer, "text", COLUMN_CODEC_BANDWIDTH, NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (codecTreeView), treeViewColumn);
g_object_unref (G_OBJECT (codecStore));
gtk_container_add (GTK_CONTAINER (scrolledWindow), codecTreeView);
......
......@@ -36,6 +36,7 @@
#include "dbus.h"
#include "video/video_preview.h"
#include <assert.h>
#include "codeclist.h"
#include <clutter/clutter.h>
#include <clutter-gtk/clutter-gtk.h>
......@@ -75,7 +76,6 @@ enum {
COLUMN_CODEC_ACTIVE,
COLUMN_CODEC_NAME,
COLUMN_CODEC_BITRATE,
COLUMN_CODEC_BANDWIDTH,
CODEC_COLUMN_COUNT
};
......@@ -171,39 +171,35 @@ preview_button_clicked(GtkButton *button, gpointer data UNUSED)
/**
* Fills the tree list with supported codecs
*/
static void preferences_dialog_fill_codec_list (account_t **a UNUSED)
static void preferences_dialog_fill_codec_list (account_t *a)
{
GtkListStore *codecStore;
gchar **video_codecs = NULL, **specs = NULL;
GtkTreeIter iter;
glong payload;
// Get model of view and clear it
codecStore = GTK_LIST_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (codecTreeView)));
gtk_list_store_clear (codecStore);
// This is a global list inherited by all accounts
video_codecs = (gchar**) dbus_video_codec_list ();
if (video_codecs != NULL) {
// Add the codecs in the list
for (; *video_codecs; video_codecs++) {
payload = atol (*video_codecs);
specs = (gchar **) dbus_video_codec_details (payload);
DEBUG("%s\n", *video_codecs);
DEBUG("%s\n", specs[0]);
DEBUG("%d\n", payload);
// Insert codecs
gtk_list_store_append (codecStore, &iter);
gtk_list_store_set (codecStore, &iter,
COLUMN_CODEC_ACTIVE, TRUE, // Active
COLUMN_CODEC_NAME, specs[0], // Name
COLUMN_CODEC_BITRATE, g_strdup_printf ("%.1f kbps", 1000.0), // Bitrate (kbps)
COLUMN_CODEC_BANDWIDTH, g_strdup_printf ("%.1f kbps", 1000.0), // Bandwidth (kpbs)
-1);
}
GQueue *list = a ? a->vcodecs : get_video_codecs_list ();
// Add the codecs in the list
unsigned i;
for (i = 0 ; i < list->length; i++) {
codec_t *c = g_queue_peek_nth (list, i);
if (c) {
printf("%s", c->name);
gtk_list_store_append (codecStore, &iter);
gchar *bitrate = g_strdup_printf ("%s kbps", c->bitrate);
gtk_list_store_set (codecStore, &iter,
COLUMN_CODEC_ACTIVE, c->is_active,
COLUMN_CODEC_NAME, c->name,
COLUMN_CODEC_BITRATE, bitrate,
-1);
g_free(bitrate);
}
}
}
......@@ -212,9 +208,8 @@ static void preferences_dialog_fill_codec_list (account_t **a UNUSED)
* and in configuration files
*/
static void
codec_active_toggled (GtkCellRendererToggle *renderer UNUSED, gchar *path UNUSED, gpointer data UNUSED)
codec_active_toggled (GtkCellRendererToggle *renderer UNUSED, gchar *path, gpointer data)
{
#if 0
GtkTreeIter iter;
GtkTreePath *treePath;
GtkTreeModel *model;
......@@ -241,9 +236,9 @@ codec_active_toggled (GtkCellRendererToggle *renderer UNUSED, gchar *path UNUSED
-1);
printf ("%s\n", name);
printf ("%i\n", g_queue_get_length (acc->codecs));
printf ("%i\n", g_queue_get_length (acc->vcodecs));
codec = codec_list_get_by_name ( (gconstpointer) name, acc->codecs);
codec = codec_list_get_by_name ( (gconstpointer) name, acc->vcodecs);
// Toggle active value
active = !active;
......@@ -256,19 +251,14 @@ codec_active_toggled (GtkCellRendererToggle *renderer UNUSED, gchar *path UNUSED
gtk_tree_path_free (treePath);
// Modify codec queue to represent change
if (active) {
codec_set_active (&codec);
} else {
codec_set_inactive (&codec);
}
#endif
codec->is_active = active;
}
/**
* Move codec in list depending on direction and selected codec and
* update changes in the daemon list and the configuration files
*/
static void codec_move (gboolean moveUp, gpointer data UNUSED)
static void codec_move (gboolean moveUp, gpointer data)
{
GtkTreeIter iter;
......@@ -277,19 +267,11 @@ static void codec_move (gboolean moveUp, gpointer data UNUSED)
GtkTreeSelection *selection;
GtkTreePath *treePath;
gchar *path;
//account_t *acc;
//GQueue *acc_q;
// Get view, model and selection of codec store
model = gtk_tree_view_get_model (GTK_TREE_VIEW (codecTreeView));
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (codecTreeView));
// Retrieve the user data
//acc = (account_t*) data;
//if (acc)
// acc_q = acc->codecs;
// Find selected iteration and create a copy
gtk_tree_selection_get_selected (GTK_TREE_SELECTION (selection), &model, &iter);
iter2 = gtk_tree_iter_copy (&iter);
......@@ -297,8 +279,8 @@ static void codec_move (gboolean moveUp, gpointer data UNUSED)
// Find path of iteration
path = gtk_tree_model_get_string_from_iter (GTK_TREE_MODEL (model), &iter);
treePath = gtk_tree_path_new_from_string (path);
//gint *indices = gtk_tree_path_get_indices (treePath);
//gint indice = indices[0];
gint *indices = gtk_tree_path_get_indices (treePath);
gint indice = indices[0];
// Depending on button direction get new path
if (moveUp)
......@@ -320,13 +302,8 @@ static void codec_move (gboolean moveUp, gpointer data UNUSED)
gtk_tree_iter_free (iter2);
g_free (path);
#if 0
// Perpetuate changes in codec queue
if (moveUp)
codec_list_move_codec_up (indice, &acc_q);
else
codec_list_move_codec_down (indice, &acc_q);
#endif
codec_list_move (indice, ((account_t*)data)->vcodecs, moveUp);
}
/**
......@@ -347,7 +324,7 @@ static void codec_move_down (GtkButton *button UNUSED, gpointer data)
codec_move (FALSE, data);
}
GtkWidget* videocodecs_box (account_t **a)
GtkWidget* videocodecs_box (account_t *a)
{
GtkWidget *ret;
GtkWidget *scrolledWindow;
......@@ -388,7 +365,7 @@ GtkWidget* videocodecs_box (account_t **a)
gtk_tree_view_append_column (GTK_TREE_VIEW (codecTreeView), treeViewColumn);
// Toggle codec active property on clicked
g_signal_connect (G_OBJECT (renderer), "toggled", G_CALLBACK (codec_active_toggled), (gpointer) *a);
g_signal_connect (G_OBJECT (renderer), "toggled", G_CALLBACK (codec_active_toggled), (gpointer) a);
// Name column
renderer = gtk_cell_renderer_text_new();
......@@ -400,11 +377,6 @@ GtkWidget* videocodecs_box (account_t **a)
treeViewColumn = gtk_tree_view_column_new_with_attributes (_ ("Bitrate"), renderer, "text", COLUMN_CODEC_BITRATE, NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (codecTreeView), treeViewColumn);
// Bandwidth column
renderer = gtk_cell_renderer_text_new();
treeViewColumn = gtk_tree_view_column_new_with_attributes (_ ("Bandwidth"