295
#include <hal/libhal.h>
297
static LibHalContext *hal = NULL;
299
static gboolean check_hal (void)
303
DBusConnection *dbus = dbus_bus_get (DBUS_BUS_SYSTEM, NULL);
306
hal = libhal_ctx_new ();
309
libhal_ctx_set_dbus_connection (hal, dbus);
314
get_hal_property (const char *dev, const char *dev_tag, const char *prop_tag)
317
char **devs = libhal_manager_find_device_string_match
318
(hal, dev_tag, dev, &count, NULL);
323
libhal_free_string_array (devs);
327
char *prop = libhal_device_get_property_string (hal, devs[0], prop_tag, NULL);
328
char *ret = (prop && prop[0]) ? strdup (prop) : NULL;
329
libhal_free_string (prop);
330
libhal_free_string_array (devs);
335
get_hal_device_info (const char *dev)
337
if (!check_hal () || !dev)
340
int ldev = strlen (dev);
341
char buf[FILENAME_MAX + ldev + 1];
342
strcpy (buf, dev); /* safe! */
345
ldev = strrchr (buf, '/') - buf + 1;
346
int tmp = readlink (dev, buf + ldev, FILENAME_MAX - 1);
348
strcpy (buf, dev); /* safe! */
349
else if (buf[ldev] == '/')
351
memmove (buf, buf + ldev, tmp);
358
while ((p = strstr (buf, "//")))
359
memmove (p, p + 1, strlen (p));
360
while ((p = strstr (buf, "/./")))
361
memmove (p, p + 2, strlen (p) - 1);
362
while ((p = strstr (buf, "/../")))
365
while (--q >= buf && *q != '/')
367
memmove (q, p + 3, strlen (p) - 2);
372
#ifdef HAL_DEVICE_FILE_PREFIX
373
char *const buf_unprefixed =
374
strncmp (buf, HAL_DEVICE_FILE_PREFIX, sizeof (HAL_DEVICE_FILE_PREFIX) - 1)
375
? "" : buf + sizeof (HAL_DEVICE_FILE_PREFIX) - 2;
377
char *const buf_unprefixed = buf;
380
return get_hal_property (buf, "block.device", "storage.model")
381
? : get_hal_property (buf, "block.device", "info.product")
382
? : get_hal_property (buf_unprefixed, HAL_DEVICE_FILE_PROPERTY, "info.product")
383
/* FIXME - BSD etc. */
388
display_hal_device_info (GtkWidget *widget, const char *dev)
390
GtkLabel *info = g_object_get_data (G_OBJECT (widget), "extra");
393
char *hal = get_hal_device_info (dev);
394
char *content = g_markup_printf_escaped ("<small>%s</small>", hal ? : "");
395
gtk_label_set_markup (info, content);
400
#endif /* WITH_HAL */
292
402
static void file_cb (GtkWidget *widget, int response, gpointer data)
294
404
xine_cfg_entry_t entry;
295
gchar *key = (gchar *) data;
405
gchar *key = g_object_get_data (data, "cfg");
297
407
if (update_lock || response != GTK_RESPONSE_ACCEPT)
317
431
file_cb (widget, GTK_RESPONSE_ACCEPT, data);
320
static void file_map_cb (GtkWidget *fcb, gpointer key)
322
if (!g_object_get_data (fcb, "gxine"))
324
g_signal_connect (fcb, "current-folder-changed",
325
G_CALLBACK(file_activate_cb), key);
326
g_object_set_data (fcb, "gxine", fcb);
435
static void file_preview_cb (GtkFileChooser *fc, gpointer data)
437
GtkLabel *info = GTK_LABEL (gtk_file_chooser_get_preview_widget (fc));
438
char *file = gtk_file_chooser_get_preview_filename (fc);
440
file = gtk_file_chooser_get_filename (fc);
441
char *content = get_hal_device_info (file);
442
gtk_label_set_text (info, content ? : "");
448
static void file_map_cb (GtkFileChooser *fcb, gpointer fc)
450
if (!g_object_get_data (fc, "gxine"))
452
g_signal_connect_swapped (fcb, "current-folder-changed",
453
G_CALLBACK(file_activate_cb), fc);
454
g_object_set_data (fc, "gxine", fc);
457
file_preview_cb (fcb, fc);
462
default_item_cb (GtkWidget *w, gpointer key)
464
xine_cfg_entry_t entry;
465
xine_config_lookup_entry (xine, key, &entry);
466
if (entry.type == XINE_CONFIG_TYPE_STRING)
467
entry.str_value = entry.str_default;
469
entry.num_value = entry.num_default;
470
preferences_update_entry (&entry);
473
static inline GtkWidget *
474
create_item_default (const xine_cfg_entry_t * entry)
477
gboolean alloc = FALSE;
481
case XINE_CONFIG_TYPE_ENUM:
482
tip = entry->enum_values[entry->num_default];
485
case XINE_CONFIG_TYPE_RANGE:
486
case XINE_CONFIG_TYPE_NUM:
488
tip = g_strdup_printf ("%d", entry->num_default);
491
case XINE_CONFIG_TYPE_BOOL:
492
tip = entry->num_default ? "✓" : "✗";
495
case XINE_CONFIG_TYPE_STRING:
496
tip = entry->str_default;
503
GtkWidget *widget = ui_button_new_stock (GTK_STOCK_CLEAR);
504
gtk_tooltips_set_tip (tooltips, widget, tip, NULL);
508
g_signal_connect ((GObject *) widget, "clicked",
509
G_CALLBACK (default_item_cb), (gpointer) entry->key);
514
revert_item_cb (GtkWidget *w, gpointer key)
516
xine_cfg_entry_t entry;
517
xine_config_lookup_entry (xine, key, &entry);
518
if (entry.type == XINE_CONFIG_TYPE_STRING)
519
entry.str_value = g_object_get_data ((GObject *) w, "revert");
521
entry.num_value = (int) (intptr_t) g_object_get_data ((GObject *) w, "revert");
522
preferences_update_entry (&entry);
525
static inline GtkWidget *
526
create_item_revert (const xine_cfg_entry_t *entry)
530
gboolean alloc = FALSE;
534
case XINE_CONFIG_TYPE_ENUM:
535
tip = entry->enum_values[entry->num_value];
536
value = entry->num_value;
539
case XINE_CONFIG_TYPE_RANGE:
540
case XINE_CONFIG_TYPE_NUM:
542
tip = g_strdup_printf ("%d", entry->num_value);
543
value = entry->num_value;
546
case XINE_CONFIG_TYPE_BOOL:
547
tip = entry->num_value ? "✓" : "✗";
548
value = entry->num_value;
551
case XINE_CONFIG_TYPE_STRING:
552
tip = entry->str_value;
553
value = (intptr_t) strdup (entry->str_value);
560
GtkWidget *widget = ui_button_new_stock (GTK_STOCK_REVERT_TO_SAVED);
561
g_object_set_data ((GObject *) widget, "revert", (void *) value);
562
g_signal_connect ((GObject *) widget, "clicked",
563
G_CALLBACK (revert_item_cb), (gpointer) entry->key);
564
gtk_tooltips_set_tip (tooltips, widget, tip, NULL);
330
571
static GtkWidget *create_item_editable (const xine_cfg_entry_t *entry)
353
594
case XINE_CONFIG_TYPE_STRING:
354
595
if (xine_check_version (1, 1, 4) && entry->num_value)
356
widget = gtk_file_chooser_dialog_new (entry->key, GTK_WINDOW (prefs_dialog),
597
GtkWidget *fc = gtk_file_chooser_dialog_new (entry->key, GTK_WINDOW (prefs_dialog),
357
598
entry->num_value == 3 /* XINE_CONFIG_STRING_IS_DIRECTORY_NAME */
358
599
? GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER
359
600
: GTK_FILE_CHOOSER_ACTION_OPEN,
360
601
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
361
602
GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
363
gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (widget), TRUE);
604
widget = gtk_file_chooser_button_new_with_dialog (fc);
605
gtk_file_chooser_set_local_only ((GtkFileChooser *) fc, TRUE);
365
607
if (stat (entry->str_value, &st))
370
612
entry->key, entry->str_value);
373
gtk_file_chooser_set_filename ((GtkFileChooser *) widget, entry->str_value);
374
g_object_connect (G_OBJECT(widget),
375
"signal::response", G_CALLBACK(file_cb), (gchar *)entry->key,
376
"signal::file-activated", G_CALLBACK(file_activate_cb), (gchar *)entry->key,
615
gtk_file_chooser_set_filename ((GtkFileChooser *) fc, entry->str_value);
617
gtk_file_chooser_set_use_preview_label ((GtkFileChooser *) fc, FALSE);
618
GtkWidget *preview = g_object_new (GTK_TYPE_LABEL, "angle", 90.0,
619
"selectable", FALSE, NULL);
620
gtk_file_chooser_set_preview_widget ((GtkFileChooser *) fc, preview);
622
g_object_connect (G_OBJECT(fc),
623
"signal::response", G_CALLBACK(file_cb), widget,
624
"signal::file-activated", G_CALLBACK(file_activate_cb), widget,
626
"signal::update-preview", G_CALLBACK(file_preview_cb), widget,
627
"signal::map", G_CALLBACK(file_preview_cb), fc,
378
widget = gtk_file_chooser_button_new_with_dialog (widget);
379
g_signal_connect (G_OBJECT(widget), "map", G_CALLBACK(file_map_cb), (gchar *)entry->key);
630
g_signal_connect_after (G_OBJECT(widget), "map", G_CALLBACK(file_map_cb), fc);
383
634
widget = gtk_entry_new();
384
g_object_set_data (G_OBJECT(widget), "cfg", (gpointer)entry->key);
385
635
g_object_connect (G_OBJECT(widget),
386
636
"signal::key-press-event", G_CALLBACK(entry_keypress_cb), (gchar *)entry->key,
387
637
"signal::focus-out-event", G_CALLBACK(entry_cb), (gchar *)entry->key,
389
639
gtk_entry_set_text (GTK_ENTRY(widget), entry->str_value);
641
g_object_set_data (G_OBJECT(widget), "cfg", (gpointer)entry->key);
396
647
GtkObject *adj = gtk_adjustment_new (entry->num_value, entry->range_min,
397
648
entry->range_max, 1.0, 10.0, 0.0);
398
widget = gtk_hscale_new (GTK_ADJUSTMENT(adj));
399
gtk_scale_set_draw_value (GTK_SCALE(widget), TRUE);
400
gtk_scale_set_value_pos (GTK_SCALE(widget), GTK_POS_TOP);
401
gtk_scale_set_digits (GTK_SCALE(widget), 0);
649
widget = ui_hscale_new (adj, GTK_POS_TOP, 0);
650
gtk_widget_set_size_request (widget, 128, -1);
402
651
g_signal_connect (adj, "value-changed",
403
652
G_CALLBACK (range_cb), (gchar *)entry->key);
449
695
labeltext = g_markup_printf_escaped ("<b>• <i>%s</i></b>\n%s",
450
696
labelkey, entry->description);
452
label = gtk_label_new (labeltext);
698
label = ui_label_new_with_markup (labeltext);
453
699
free (labeltext);
455
gtk_label_set_use_markup (GTK_LABEL(label), TRUE);
456
701
gtk_label_set_line_wrap (GTK_LABEL(label), TRUE);
702
gtk_label_set_line_wrap_mode (GTK_LABEL(label), PANGO_WRAP_WORD);
457
703
gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
458
704
gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
709
static GtkWidget *create_item_extra (const xine_cfg_entry_t *entry)
713
case XINE_CONFIG_TYPE_STRING:
715
if (entry->num_value == 2 /* XINE_CONFIG_STRING_IS_DEVICE_NAME */)
716
return gtk_label_new (NULL);
463
723
static GNode *create_item (const xine_cfg_entry_t *entry)
465
725
pref_item_t *item = malloc (sizeof (pref_item_t));
466
726
item->notebook = NULL;
727
item->todefault = create_item_default (entry);
728
item->revert = create_item_revert (entry);
467
729
item->editable = create_item_editable (entry);
468
730
item->label = create_item_label (entry);
731
GtkWidget *extra = create_item_extra (entry);
733
g_object_set_data (G_OBJECT (item->editable), "extra", extra);
469
734
item->separator = gtk_hseparator_new ();
470
735
item->exp = entry->exp_level;
471
736
return g_node_new (item);
634
898
/* we have a config item */
635
899
int r = g_node_child_position (node->parent, node) * 2;
636
900
GtkTable *table = GTK_TABLE(parent->page.table);
637
gtk_table_attach (table, pref->item.editable, 0, 1, r, r + 1,
638
GTK_EXPAND | GTK_FILL, GTK_SHRINK, 2, 5);
639
gtk_table_attach (table, pref->item.label, 1, 4, r, r + 1,
901
gtk_table_attach (table, pref->item.todefault, 0, 1, r, r + 1,
902
GTK_FILL, GTK_SHRINK, 2, 5);
903
gtk_table_attach (table, pref->item.revert, 1, 2, r, r + 1,
904
GTK_FILL, GTK_SHRINK, 2, 5);
905
GtkWidget *extra = g_object_get_data (G_OBJECT (pref->item.editable), "extra");
908
GtkBox *box = GTK_BOX (gtk_vbox_new (2, FALSE));
909
gtk_table_attach (table, (GtkWidget *) box, 2, 3, r, r + 1,
910
GTK_EXPAND | GTK_FILL, GTK_SHRINK, 2, 5);
911
gtk_box_pack_start_defaults (box, pref->item.editable);
912
gtk_box_pack_start_defaults (box, extra);
914
xine_cfg_entry_t entry;
915
const char *key = g_object_get_data (G_OBJECT (pref->item.editable), "cfg");
916
if (xine_config_lookup_entry (xine, key, &entry))
917
display_hal_device_info (pref->item.editable, entry.str_value);
921
gtk_table_attach (table, pref->item.editable, 2, 3, r, r + 1,
922
GTK_EXPAND | GTK_FILL, GTK_SHRINK, 2, 5);
923
gtk_table_attach (table, pref->item.label, 3, 6, r, r + 1,
640
924
GTK_EXPAND | GTK_FILL, GTK_SHRINK, 5, 5);
641
gtk_table_attach (table, pref->item.separator, 0, 4, r + 1, r + 2,
925
gtk_table_attach (table, pref->item.separator, 0, 6, r + 1, r + 2,
642
926
GTK_EXPAND | GTK_FILL, GTK_SHRINK | GTK_FILL, 5, 5);
927
g_signal_connect (pref->item.todefault, "focus",
928
G_CALLBACK (focus_item_cb), node);
929
g_signal_connect (pref->item.revert, "focus",
930
G_CALLBACK (focus_item_cb), node);
643
931
g_signal_connect (pref->item.editable, "focus",
644
focus_item_cb, node);
932
G_CALLBACK (focus_item_cb), node);
745
1033
gtk_box_pack_start_defaults (GTK_BOX(GTK_DIALOG(prefs_dialog)->vbox),
746
1034
prefs_notebook);
748
GtkWidget *w = gtk_label_new (_("Items marked “<b>• <i>like this</i></b>” require "
749
"gxine to be restarted to take effect."));
750
gtk_label_set_use_markup (GTK_LABEL(w), TRUE);
1036
GtkWidget *w = ui_label_new_with_markup
1037
(_("Items marked “<b>• <i>like this</i></b>” require "
1038
"gxine to be restarted to take effect."));
751
1039
gtk_box_pack_end (GTK_BOX(GTK_DIALOG(prefs_dialog)->vbox), w,
752
1040
FALSE, FALSE, 2);
754
gtk_widget_show_all (prefs_notebook);
1043
static gpointer preferences_first_show (gpointer unused)
1045
static int value = 0;
756
1046
xine_cfg_entry_t entry;
1048
gtk_widget_show_all (GTK_DIALOG (prefs_dialog)->vbox);
757
1049
if (xine_config_lookup_entry (xine, "gui.experience_level", &entry))
760
1050
value = entry.num_value;
761
select_show_pref_widgets (&value);
1052
select_show_pref_widgets (&value);