2
/* Ekiga -- A VoIP and Video-Conferencing application
3
* Copyright (C) 2000-2006 Damien Sandras
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation; either version 2 of the License, or
8
* (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
20
* Ekiga is licensed under the GPL license and as a special exception,
21
* you have permission to link or otherwise combine this program with the
22
* programs OPAL, OpenH323 and PWLIB, and distribute the combination,
23
* without applying the requirements of the GNU GPL to the OPAL, OpenH323
24
* and PWLIB programs, as long as you do follow the requirements of the
25
* GNU GPL for all the rest of the software thus combined.
30
* codecsbox.c - description
31
* -------------------------------
32
* begin : Sat Sep 2 2006
33
* copyright : (C) 2000-2006 by Damien Sandras
34
* description : Contains a codecs box widget
39
#include "codecsbox.h"
42
#include "codec-description.h"
46
/* Columns for the codecs page */
51
COLUMN_CODEC_CLOCKRATE,
52
COLUMN_CODEC_PROTOCOLS,
53
COLUMN_CODEC_CONFIG_NAME,
54
COLUMN_CODEC_SELECTABLE,
59
struct _CodecsBoxPrivate
61
Ekiga::Call::StreamType type;
62
GtkWidget *codecs_list;
67
static GObjectClass *parent_class = NULL;
70
/* Static functions */
71
static void codecs_box_set_codecs (CodecsBox *self,
76
static void codec_toggled_cb (GtkCellRendererToggle *cell,
80
static void codec_moved_cb (GtkWidget *widget,
83
static GSList *codecs_box_to_gm_conf_list (CodecsBox *self);
86
/* Static functions and declarations */
87
static void codecs_box_class_init (gpointer g_class,
90
static void codecs_box_init (CodecsBox *);
92
static void codecs_box_dispose (GObject *obj);
94
static void codecs_box_finalize (GObject *obj);
96
static void codecs_box_get_property (GObject *obj,
101
static void codecs_box_set_property (GObject *obj,
109
codecs_box_set_codecs (CodecsBox *self,
112
GtkTreeSelection *selection = NULL;
113
GtkTreeModel *model = NULL;
116
GSList *codecs_data = NULL;
117
GSList *codecs_data_iter = NULL;
119
gchar *selected_codec = NULL;
120
unsigned select_rate = 0;
121
bool selected = false;
123
g_return_if_fail (self != NULL);
125
model = gtk_tree_view_get_model (GTK_TREE_VIEW (self->priv->codecs_list));
128
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (self->priv->codecs_list));
130
if (gtk_tree_selection_get_selected (selection, &model, &iter))
131
gtk_tree_model_get (GTK_TREE_MODEL (model), &iter,
132
COLUMN_CODEC_NAME, &selected_codec,
133
COLUMN_CODEC_CLOCKRATE, &select_rate, -1);
134
gtk_list_store_clear (GTK_LIST_STORE (model));
136
codecs_data_iter = codecs_data;
137
while (codecs_data_iter) {
139
Ekiga::CodecDescription desc = Ekiga::CodecDescription ((char *) codecs_data_iter->data);
141
if ((self->priv->type == Ekiga::Call::Audio && desc.audio)
142
|| (self->priv->type == Ekiga::Call::Video && !desc.audio)) {
143
std::stringstream rate;
144
std::stringstream protocols;
146
for (std::list<std::string>::iterator it = desc.protocols.begin ();
147
it != desc.protocols.end ();
149
if (it != desc.protocols.begin ())
154
rate << desc.rate / 1000 << " kHz";
156
gtk_list_store_append (GTK_LIST_STORE (model), &iter);
157
gtk_list_store_set (GTK_LIST_STORE (model), &iter,
158
COLUMN_CODEC_ACTIVE, desc.active,
159
COLUMN_CODEC_NAME, desc.name.c_str (),
160
COLUMN_CODEC_CLOCKRATE, rate.str ().c_str (),
161
COLUMN_CODEC_PROTOCOLS, protocols.str ().c_str (),
162
COLUMN_CODEC_CONFIG_NAME, desc.str ().c_str (),
163
COLUMN_CODEC_AUDIO, desc.audio,
164
COLUMN_CODEC_SELECTABLE, "true",
167
if (selected_codec && desc.name == selected_codec
168
&& select_rate && desc.rate == select_rate) {
171
gtk_tree_selection_select_iter (selection, &iter);
175
codecs_data_iter = g_slist_next (codecs_data_iter);
178
if (!selected && gtk_tree_model_get_iter_first (GTK_TREE_MODEL (model), &iter))
179
gtk_tree_selection_select_iter (selection, &iter);
184
codec_toggled_cb (G_GNUC_UNUSED GtkCellRendererToggle *cell,
188
CodecsBox *self = NULL;
190
GtkTreeModel *model = NULL;
191
GtkTreePath *path = NULL;
194
GSList *codecs_data = NULL;
196
gboolean fixed = FALSE;
198
g_return_if_fail (data != NULL);
199
g_return_if_fail (IS_CODECS_BOX (data));
201
self = CODECS_BOX (data);
203
model = gtk_tree_view_get_model (GTK_TREE_VIEW (self->priv->codecs_list));
204
path = gtk_tree_path_new_from_string (path_str);
206
/* Update the tree model */
207
gtk_tree_model_get_iter (model, &iter, path);
208
gtk_tree_model_get (model, &iter, COLUMN_CODEC_ACTIVE, &fixed, -1);
209
gtk_list_store_set (GTK_LIST_STORE (model), &iter,
210
COLUMN_CODEC_ACTIVE, fixed^1, -1);
211
gtk_tree_path_free (path);
213
/* Update the gmconf key */
214
codecs_data = codecs_box_to_gm_conf_list (self);
215
if (self->priv->type == Ekiga::Call::Audio)
216
gm_conf_set_string_list ("/apps/ekiga/codecs/audio/media_list", codecs_data);
217
else if (self->priv->type == Ekiga::Call::Video)
218
gm_conf_set_string_list ("/apps/ekiga/codecs/video/media_list", codecs_data);
219
g_slist_foreach (codecs_data, (GFunc) g_free, NULL);
220
g_slist_free (codecs_data);
225
codec_moved_cb (GtkWidget *widget,
228
CodecsBox *self = NULL;
231
GtkTreeIter *iter2 = NULL;
232
GtkTreeModel *model = NULL;
233
GtkTreeSelection *selection = NULL;
234
GtkTreePath *tree_path = NULL;
236
GSList *codecs_data = NULL;
238
gchar *path_str = NULL;
240
g_return_if_fail (data != NULL);
241
g_return_if_fail (IS_CODECS_BOX (data));
243
self = CODECS_BOX (data);
245
model = gtk_tree_view_get_model (GTK_TREE_VIEW (self->priv->codecs_list));
246
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (self->priv->codecs_list));
247
if (!gtk_tree_selection_get_selected (GTK_TREE_SELECTION (selection),
251
/* Update the tree view */
252
iter2 = gtk_tree_iter_copy (&iter);
253
path_str = gtk_tree_model_get_string_from_iter (GTK_TREE_MODEL (model),
255
tree_path = gtk_tree_path_new_from_string (path_str);
256
if (!strcmp ((gchar *) g_object_get_data (G_OBJECT (widget), "operation"),
258
gtk_tree_path_prev (tree_path);
260
gtk_tree_path_next (tree_path);
262
gtk_tree_model_get_iter (GTK_TREE_MODEL (model), &iter, tree_path);
263
if (gtk_list_store_iter_is_valid (GTK_LIST_STORE (model), &iter)
264
&& gtk_list_store_iter_is_valid (GTK_LIST_STORE (model), iter2))
265
gtk_list_store_swap (GTK_LIST_STORE (model), &iter, iter2);
267
/* Scroll to the new position */
268
gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (self->priv->codecs_list),
269
tree_path, NULL, FALSE, 0, 0);
271
gtk_tree_path_free (tree_path);
272
gtk_tree_iter_free (iter2);
275
/* Update the gmconf key */
276
codecs_data = codecs_box_to_gm_conf_list (self);
277
if (self->priv->type == Ekiga::Call::Audio)
278
gm_conf_set_string_list ("/apps/ekiga/codecs/audio/media_list", codecs_data);
279
else if (self->priv->type == Ekiga::Call::Video)
280
gm_conf_set_string_list ("/apps/ekiga/codecs/video/media_list", codecs_data);
281
g_slist_foreach (codecs_data, (GFunc) g_free, NULL);
282
g_slist_free (codecs_data);
287
codecs_box_to_gm_conf_list (CodecsBox *self)
289
GtkTreeModel *model = NULL;
294
gchar *protocols = NULL;
295
gboolean active = false;
296
gboolean audio = false;
298
GSList *codecs_data = NULL;
300
g_return_val_if_fail (self != NULL, NULL);
301
g_return_val_if_fail (IS_CODECS_BOX (self), NULL);
303
model = gtk_tree_view_get_model (GTK_TREE_VIEW (self->priv->codecs_list));
304
if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (model), &iter)) {
308
gtk_tree_model_get (model, &iter,
309
COLUMN_CODEC_ACTIVE, &active,
310
COLUMN_CODEC_NAME, &name,
311
COLUMN_CODEC_CLOCKRATE, &rate,
312
COLUMN_CODEC_PROTOCOLS, &protocols,
313
COLUMN_CODEC_AUDIO, &audio,
316
Ekiga::CodecDescription desc;
317
desc = Ekiga::CodecDescription (name, atoi (rate) * 1000, audio, protocols, active);
318
codecs_data = g_slist_append (codecs_data, g_strdup (desc.str ().c_str ()));
324
} while (gtk_tree_model_iter_next (GTK_TREE_MODEL (model), &iter));
332
codecs_list_changed_nt (G_GNUC_UNUSED gpointer id,
336
CodecsBox *self = CODECS_BOX (data);
338
GSList *list = gm_conf_entry_get_list (entry);
339
GSList *current_list = codecs_box_to_gm_conf_list (self);
340
Ekiga::CodecList clist (list);
341
Ekiga::CodecList curlist (current_list);
343
if (clist != curlist)
344
codecs_box_set_codecs (self, list);
346
g_slist_foreach (list, (GFunc) g_free, NULL);
349
g_slist_foreach (current_list, (GFunc) g_free, NULL);
350
g_slist_free (current_list);
355
codecs_box_class_init (gpointer g_class,
356
gpointer /*class_data*/)
358
GObjectClass *gobject_class = NULL;
359
GParamSpec *spec = NULL;
361
parent_class = (GObjectClass *) g_type_class_peek_parent (g_class);
363
gobject_class = (GObjectClass *) g_class;
364
gobject_class->dispose = codecs_box_dispose;
365
gobject_class->finalize = codecs_box_finalize;
366
gobject_class->get_property = codecs_box_get_property;
367
gobject_class->set_property = codecs_box_set_property;
369
spec = g_param_spec_int ("type", "Type", "Type",
370
0, 1, 0, (GParamFlags) G_PARAM_READWRITE);
371
g_object_class_install_property (gobject_class, TYPE, spec);
376
codecs_box_init (CodecsBox *self)
378
GtkWidget *image = NULL;
379
GtkWidget *scroll_window = NULL;
380
GtkWidget *button = NULL;
382
GtkWidget *buttons_vbox = NULL;
383
GtkWidget *alignment = NULL;
385
GtkListStore *list_store = NULL;
386
GtkCellRenderer *renderer = NULL;
387
GtkTreeViewColumn *column = NULL;
389
g_return_if_fail (self != NULL);
390
g_return_if_fail (IS_CODECS_BOX (self));
392
self->priv = new CodecsBoxPrivate;
393
self->priv->type = Ekiga::Call::Audio;
395
gtk_box_set_spacing (GTK_BOX (self), 6);
396
gtk_box_set_homogeneous (GTK_BOX (self), FALSE);
398
self->priv->codecs_list = gtk_tree_view_new ();
400
list_store = gtk_list_store_new (COLUMN_CODEC_NUMBER,
409
gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (self->priv->codecs_list), TRUE);
410
gtk_tree_view_set_reorderable (GTK_TREE_VIEW (self->priv->codecs_list), TRUE);
411
gtk_tree_view_set_search_column (GTK_TREE_VIEW (self->priv->codecs_list),0);
412
gtk_tree_view_set_model (GTK_TREE_VIEW (self->priv->codecs_list),
413
GTK_TREE_MODEL (list_store));
414
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (self->priv->codecs_list), FALSE);
417
renderer = gtk_cell_renderer_toggle_new ();
418
column = gtk_tree_view_column_new_with_attributes (NULL,
423
gtk_tree_view_column_add_attribute (column, renderer,
424
"activatable", COLUMN_CODEC_SELECTABLE);
425
gtk_tree_view_column_set_fixed_width (GTK_TREE_VIEW_COLUMN (column), 25);
426
gtk_tree_view_append_column (GTK_TREE_VIEW (self->priv->codecs_list), column);
427
g_signal_connect (G_OBJECT (renderer), "toggled",
428
G_CALLBACK (codec_toggled_cb),
431
renderer = gtk_cell_renderer_text_new ();
432
column = gtk_tree_view_column_new_with_attributes (NULL,
437
gtk_tree_view_append_column (GTK_TREE_VIEW (self->priv->codecs_list), column);
438
g_object_set (G_OBJECT (renderer), "weight", "bold", NULL);
440
renderer = gtk_cell_renderer_text_new ();
441
column = gtk_tree_view_column_new_with_attributes (NULL,
444
COLUMN_CODEC_CLOCKRATE,
446
gtk_tree_view_append_column (GTK_TREE_VIEW (self->priv->codecs_list), column);
448
renderer = gtk_cell_renderer_text_new ();
449
column = gtk_tree_view_column_new_with_attributes (NULL,
452
COLUMN_CODEC_PROTOCOLS,
454
gtk_tree_view_append_column (GTK_TREE_VIEW (self->priv->codecs_list), column);
456
scroll_window = gtk_scrolled_window_new (FALSE, FALSE);
457
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll_window),
459
GTK_POLICY_AUTOMATIC);
460
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scroll_window),
462
gtk_widget_set_size_request (scroll_window, -1, 120);
463
gtk_container_add (GTK_CONTAINER (scroll_window),
464
GTK_WIDGET (self->priv->codecs_list));
465
gtk_box_pack_start (GTK_BOX (self), scroll_window, TRUE, TRUE, 0);
469
alignment = gtk_alignment_new (1, 0.5, 0, 0);
470
buttons_vbox = gtk_vbox_new (TRUE, 6);
472
gtk_container_add (GTK_CONTAINER (alignment), buttons_vbox);
474
image = gtk_image_new_from_stock (GTK_STOCK_GO_UP, GTK_ICON_SIZE_MENU);
475
button = gtk_button_new ();
476
gtk_container_add (GTK_CONTAINER (button), image);
477
gtk_widget_set_tooltip_text (button, _("Move selected codec priority upwards"));
478
gtk_box_pack_start (GTK_BOX (buttons_vbox), button, FALSE, FALSE, 0);
479
g_object_set_data (G_OBJECT (button), "operation", (gpointer) "up");
480
g_signal_connect (G_OBJECT (button), "clicked",
481
G_CALLBACK (codec_moved_cb),
484
image = gtk_image_new_from_stock (GTK_STOCK_GO_DOWN, GTK_ICON_SIZE_MENU);
485
button = gtk_button_new ();
486
gtk_container_add (GTK_CONTAINER (button), image);
487
gtk_widget_set_tooltip_text (button, _("Move selected codec priority downwards"));
488
gtk_box_pack_start (GTK_BOX (buttons_vbox), button, FALSE, FALSE, 0);
489
g_object_set_data (G_OBJECT (button), "operation", (gpointer) "down");
490
g_signal_connect (G_OBJECT (button), "clicked",
491
G_CALLBACK (codec_moved_cb),
494
gtk_box_pack_start (GTK_BOX (self), alignment, FALSE, FALSE, 0);
496
gtk_widget_show_all (GTK_WIDGET (self));
501
codecs_box_dispose (GObject *obj)
503
CodecsBox *self = NULL;
505
self = CODECS_BOX (obj);
507
self->priv->codecs_list = NULL;
509
parent_class->dispose (obj);
514
codecs_box_finalize (GObject *obj)
516
parent_class->finalize (obj);
521
codecs_box_get_property (GObject *obj,
526
CodecsBox *self = NULL;
528
self = CODECS_BOX (obj);
533
g_value_set_int (value, self->priv->type);
537
G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, spec);
544
codecs_box_set_property (GObject *obj,
549
CodecsBox *self = NULL;
552
self = CODECS_BOX (obj);
557
self->priv->type = (Ekiga::Call::StreamType) g_value_get_int (value);
561
G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, spec);
565
if (self->priv->type == Ekiga::Call::Audio)
566
list = gm_conf_get_string_list ("/apps/ekiga/codecs/audio/media_list");
567
else if (self->priv->type == Ekiga::Call::Video)
568
list = gm_conf_get_string_list ("/apps/ekiga/codecs/video/media_list");
570
codecs_box_set_codecs (self, list);
572
g_slist_foreach (list, (GFunc) g_free, NULL);
575
if (self->priv->type == Ekiga::Call::Audio)
576
gm_conf_notifier_add ("/apps/ekiga/codecs/audio/media_list", codecs_list_changed_nt, GTK_WIDGET (self));
578
gm_conf_notifier_add ("/apps/ekiga/codecs/video/media_list", codecs_list_changed_nt, GTK_WIDGET (self));
582
/* Global functions */
584
codecs_box_get_type (void)
586
static GType codecs_box_type = 0;
588
if (codecs_box_type == 0)
590
static const GTypeInfo codecs_box_info =
592
sizeof (CodecsBoxClass),
595
(GClassInitFunc) codecs_box_class_init,
600
(GInstanceInitFunc) codecs_box_init,
605
g_type_register_static (GTK_TYPE_HBOX,
611
return codecs_box_type;
618
return GTK_WIDGET (CODECS_BOX (g_object_new (CODECS_BOX_TYPE, NULL)));
623
codecs_box_new_with_type (Ekiga::Call::StreamType type)
625
GtkWidget *codecs_box = NULL;
627
codecs_box = codecs_box_new ();
628
g_object_set (G_OBJECT (codecs_box), "type", type, NULL);