~ubuntu-branches/ubuntu/oneiric/rhythmbox/oneiric

« back to all changes in this revision

Viewing changes to sources/rb-library-source.c

  • Committer: Bazaar Package Importer
  • Author(s): Rico Tzschichholz
  • Date: 2011-07-29 16:41:38 UTC
  • mto: This revision was merged to the branch mainline in revision 191.
  • Revision ID: james.westby@ubuntu.com-20110729164138-wwicy8nqalm18ck7
Tags: upstream-2.90.1~20110802
ImportĀ upstreamĀ versionĀ 2.90.1~20110802

Show diffs side-by-side

added added

removed removed

Lines of Context:
39
39
 * the library from another source, and the preferred audio encoding
40
40
 * to use.
41
41
 *
42
 
 * If multiple library locations are set in GConf, the library source
 
42
 * If multiple library locations are configured, the library source
43
43
 * creates a child source for each location, which will only show
44
44
 * files found under that location.
45
45
 */
51
51
#include <gtk/gtk.h>
52
52
#include <glib/gi18n.h>
53
53
#include <glib-object.h>
 
54
#include <gst/pbutils/install-plugins.h>
54
55
 
55
56
#include "rb-track-transfer-batch.h"
56
57
#include "rb-track-transfer-queue.h"
57
 
#include <libgnome-media-profiles/gnome-media-profiles.h>
58
 
#include <libgnome-media-profiles/audio-profile-choose.h>
59
58
 
60
59
#include "rhythmdb.h"
61
60
#include "rb-debug.h"
63
62
#include "rb-builder-helpers.h"
64
63
#include "rb-file-helpers.h"
65
64
#include "rb-util.h"
66
 
#include "eel-gconf-extensions.h"
67
65
#include "rb-library-source.h"
68
66
#include "rb-auto-playlist-source.h"
69
67
#include "rb-encoder.h"
70
68
#include "rb-missing-plugins.h"
 
69
#include "rb-gst-media-types.h"
71
70
 
72
71
static void rb_library_source_class_init (RBLibrarySourceClass *klass);
73
72
static void rb_library_source_init (RBLibrarySource *source);
80
79
static gboolean impl_receive_drag (RBDisplayPage *source, GtkSelectionData *data);
81
80
static void impl_get_status (RBDisplayPage *source, char **text, char **progress_text, float *progress);
82
81
 
83
 
static char *impl_get_browser_key (RBSource *source);
84
 
static char *impl_get_paned_key (RBBrowserSource *source);
85
82
static gboolean impl_can_paste (RBSource *asource);
86
83
static RBTrackTransferBatch *impl_paste (RBSource *source, GList *entries);
87
84
static guint impl_want_uri (RBSource *source, const char *uri);
93
90
                          gpointer data,
94
91
                          GDestroyNotify destroy_data);
95
92
 
96
 
static void rb_library_source_ui_prefs_sync (RBLibrarySource *source);
97
 
static void rb_library_source_preferences_sync (RBLibrarySource *source);
98
 
 
99
 
static void rb_library_source_library_location_changed (GConfClient *client,
100
 
                                                    guint cnxn_id,
101
 
                                                    GConfEntry *entry,
102
 
                                                    RBLibrarySource *source);
103
 
static void rb_library_source_layout_path_changed (GConfClient *client,
104
 
                                                   guint cnxn_id,
105
 
                                                   GConfEntry *entry,
106
 
                                                   RBLibrarySource *source);
107
 
static void rb_library_source_layout_filename_changed (GConfClient *client,
108
 
                                                       guint cnxn_id,
109
 
                                                       GConfEntry *entry,
110
 
                                                       RBLibrarySource *source);
111
 
static void rb_library_source_edit_profile_clicked_cb (GtkButton *button,
112
 
                                                       RBLibrarySource *source);
113
 
static void rb_library_source_ui_pref_changed (GConfClient *client,
114
 
                                               guint cnxn_id,
115
 
                                               GConfEntry *entry,
116
 
                                               RBLibrarySource *source);
 
93
static void library_settings_changed_cb (GSettings *settings, const char *key, RBLibrarySource *source);
 
94
static void db_settings_changed_cb (GSettings *settings, const char *key, RBLibrarySource *source);
117
95
static gboolean rb_library_source_library_location_cb (GtkEntry *entry,
118
96
                                                       GdkEventFocus *event,
119
97
                                                       RBLibrarySource *source);
120
 
static void rb_library_source_watch_toggled_cb (GtkToggleButton *button,
121
 
                                                RBLibrarySource *source);
122
98
static void rb_library_source_sync_child_sources (RBLibrarySource *source);
123
99
static void rb_library_source_path_changed_cb (GtkComboBox *box,
124
100
                                                RBLibrarySource *source);
126
102
                                                   RBLibrarySource *source);
127
103
static void rb_library_source_format_changed_cb (GtkWidget *widget,
128
104
                                                 RBLibrarySource *source);
129
 
static void layout_example_label_update (RBLibrarySource *source);
 
105
static void rb_library_source_install_plugins_cb (GtkWidget *widget,
 
106
                                                  RBLibrarySource *source);
 
107
static void update_layout_example_label (RBLibrarySource *source);
130
108
static RhythmDBImportJob *maybe_create_import_job (RBLibrarySource *source);
131
109
 
132
 
#define CONF_UI_LIBRARY_DIR CONF_PREFIX "/ui/library"
133
 
#define CONF_STATE_LIBRARY_DIR CONF_PREFIX "/state/library"
134
 
#define CONF_STATE_LIBRARY_SORTING CONF_PREFIX "/state/library/sorting"
135
 
#define CONF_STATE_PANED_POSITION CONF_PREFIX "/state/library/paned_position"
136
 
#define CONF_STATE_SHOW_BROWSER   CONF_PREFIX "/state/library/show_browser"
137
 
 
138
110
typedef struct {
139
111
        char *title;
140
112
        char *path;
176
148
        GtkWidget *layout_filename_menu;
177
149
        GtkWidget *preferred_format_menu;
178
150
        GtkWidget *layout_example_label;
 
151
        GtkWidget *install_plugins_button;
 
152
        GtkTreeModel *profile_model;
179
153
 
180
154
        GList *import_jobs;
181
155
        guint start_import_job_id;
182
156
 
183
 
        guint library_location_notify_id;
184
 
        guint ui_dir_notify_id;
185
 
        guint layout_path_notify_id;
186
 
        guint layout_filename_notify_id;
 
157
        GSettings *settings;
 
158
        GSettings *db_settings;
187
159
};
188
160
 
189
161
#define RB_LIBRARY_SOURCE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), RB_TYPE_LIBRARY_SOURCE, RBLibrarySourcePrivate))
206
178
        page_class->receive_drag = impl_receive_drag;
207
179
        page_class->get_status = impl_get_status;
208
180
 
209
 
        source_class->impl_get_browser_key = impl_get_browser_key;
210
181
        source_class->impl_can_copy = (RBSourceFeatureFunc) rb_true_function;
211
182
        source_class->impl_can_paste = (RBSourceFeatureFunc) impl_can_paste;
212
183
        source_class->impl_paste = impl_paste;
213
184
        source_class->impl_want_uri = impl_want_uri;
214
185
        source_class->impl_add_uri = impl_add_uri;
215
186
 
216
 
        browser_source_class->impl_get_paned_key = impl_get_paned_key;
217
187
        browser_source_class->impl_has_drop_support = (RBBrowserSourceFeatureFunc) rb_true_function;
218
188
 
219
189
        g_type_class_add_private (klass, sizeof (RBLibrarySourcePrivate));
220
 
 
221
 
        gnome_media_profiles_init (eel_gconf_client_get_global ());
222
190
}
223
191
 
224
192
static void
243
211
                source->priv->db = NULL;
244
212
        }
245
213
 
246
 
        if (source->priv->ui_dir_notify_id != 0) {
247
 
                eel_gconf_notification_remove (source->priv->ui_dir_notify_id);
248
 
                source->priv->ui_dir_notify_id = 0;
249
 
        }
250
 
 
251
 
        if (source->priv->library_location_notify_id != 0) {
252
 
                eel_gconf_notification_remove (source->priv->library_location_notify_id);
253
 
                source->priv->library_location_notify_id = 0;
254
 
        }
255
 
 
256
 
        if (source->priv->layout_path_notify_id != 0) {
257
 
                eel_gconf_notification_remove (source->priv->layout_path_notify_id);
258
 
                source->priv->layout_path_notify_id = 0;
259
 
        }
260
 
 
261
 
        if (source->priv->layout_filename_notify_id != 0) {
262
 
                eel_gconf_notification_remove (source->priv->layout_filename_notify_id);
263
 
                source->priv->layout_filename_notify_id = 0;
 
214
        if (source->priv->settings) {
 
215
                g_object_unref (source->priv->settings);
 
216
                source->priv->settings = NULL;
 
217
        }
 
218
 
 
219
        if (source->priv->db_settings) {
 
220
                g_object_unref (source->priv->db_settings);
 
221
                source->priv->db_settings = NULL;
264
222
        }
265
223
 
266
224
        if (source->priv->import_jobs != NULL) {
298
256
        G_OBJECT_CLASS (rb_library_source_parent_class)->finalize (object);
299
257
}
300
258
 
301
 
static gboolean
302
 
add_child_sources_idle (RBLibrarySource *source)
303
 
{
304
 
        GDK_THREADS_ENTER ();
305
 
        rb_library_source_sync_child_sources (source);
306
 
        GDK_THREADS_LEAVE ();
307
 
 
308
 
        return FALSE;
309
 
}
310
 
 
311
259
static void
312
260
db_load_complete_cb (RhythmDB *db, RBLibrarySource *source)
313
261
{
321
269
        RBLibrarySource *source;
322
270
        RBShell *shell;
323
271
        RBEntryView *songs;
324
 
        GSList *list;
 
272
        char **locations;
325
273
 
326
274
        RB_CHAIN_GOBJECT_METHOD (rb_library_source_parent_class, constructed, object);
327
275
        source = RB_LIBRARY_SOURCE (object);
329
277
        g_object_get (source, "shell", &shell, NULL);
330
278
        g_object_get (shell, "db", &source->priv->db, NULL);
331
279
 
 
280
        source->priv->settings = g_settings_new ("org.gnome.rhythmbox.library");
 
281
        g_signal_connect_object (source->priv->settings, "changed", G_CALLBACK (library_settings_changed_cb), source, 0);
 
282
 
 
283
        source->priv->db_settings = g_settings_new ("org.gnome.rhythmbox.rhythmdb");
 
284
        g_signal_connect_object (source->priv->db_settings, "changed", G_CALLBACK (db_settings_changed_cb), source, 0);
 
285
 
332
286
        g_signal_connect_object (source->priv->db, "load-complete", G_CALLBACK (db_load_complete_cb), source, 0);
333
287
 
334
 
        rb_library_source_ui_prefs_sync (source);
335
 
 
336
288
        /* Set up the default library location if there's no library location set */
337
 
        list = eel_gconf_get_string_list (CONF_LIBRARY_LOCATION);
338
 
        if (g_slist_length (list) == 0) {
 
289
        locations = g_settings_get_strv (source->priv->db_settings, "locations");
 
290
        if (g_strv_length (locations) == 0) {
339
291
                char *music_dir_uri;
340
292
 
341
293
                music_dir_uri = g_filename_to_uri (rb_music_dir (), NULL, NULL);
342
294
                if (music_dir_uri != NULL) {
343
 
                        list = g_slist_prepend (list, music_dir_uri);
344
 
                        eel_gconf_set_string_list (CONF_LIBRARY_LOCATION, list);
345
 
                }
346
 
        } else {
347
 
                /* ensure all library locations are URIs and not file paths */
348
 
                GSList *t;
349
 
                gboolean update = FALSE;
350
 
                for (t = list; t != NULL; t = t->next) {
351
 
                        char *location;
352
 
 
353
 
                        location = (char *)t->data;
354
 
                        if (location[0] == '/') {
355
 
                                char *uri = g_filename_to_uri (location, NULL, NULL);
356
 
                                if (uri != NULL) {
357
 
                                        rb_debug ("converting library location path %s to URI %s", location, uri);
358
 
                                        g_free (location);
359
 
                                        t->data = uri;
360
 
                                        update = TRUE;
361
 
                                }
362
 
                        }
363
 
                }
364
 
 
365
 
                if (update) {
366
 
                        eel_gconf_set_string_list (CONF_LIBRARY_LOCATION, list);
 
295
                        const char *set_locations[2];
 
296
                        set_locations[0] = music_dir_uri;
 
297
                        set_locations[1] = NULL;
 
298
                        g_settings_set_strv (source->priv->db_settings, "locations", set_locations);
 
299
 
 
300
                        g_free (music_dir_uri);
367
301
                }
368
302
        }
369
 
        rb_slist_deep_free (list);
370
 
 
371
 
        source->priv->library_location_notify_id =
372
 
                eel_gconf_notification_add (CONF_LIBRARY_LOCATION,
373
 
                                    (GConfClientNotifyFunc) rb_library_source_library_location_changed, source);
374
 
 
375
 
        source->priv->ui_dir_notify_id =
376
 
                eel_gconf_notification_add (CONF_UI_LIBRARY_DIR,
377
 
                                    (GConfClientNotifyFunc) rb_library_source_ui_pref_changed, source);
 
303
        g_strfreev (locations);
378
304
 
379
305
        songs = rb_source_get_entry_view (RB_SOURCE (source));
380
306
 
382
308
        rb_entry_view_append_column (songs, RB_ENTRY_VIEW_COL_LAST_PLAYED, FALSE);
383
309
        rb_entry_view_append_column (songs, RB_ENTRY_VIEW_COL_FIRST_SEEN, FALSE);
384
310
 
385
 
        g_idle_add ((GSourceFunc)add_child_sources_idle, source);
 
311
        rb_library_source_sync_child_sources (source);
386
312
 
387
313
        g_object_unref (shell);
388
314
}
400
326
{
401
327
        RBSource *source;
402
328
        GdkPixbuf *icon;
 
329
        GSettings *settings;
403
330
        gint size;
404
331
 
405
332
        gtk_icon_size_lookup (RB_SOURCE_ICON_SIZE, &size, NULL);
407
334
                                         "audio-x-generic",
408
335
                                         size,
409
336
                                         0, NULL);
 
337
        settings = g_settings_new ("org.gnome.rhythmbox.library");
410
338
        source = RB_SOURCE (g_object_new (RB_TYPE_LIBRARY_SOURCE,
411
339
                                          "name", _("Music"),
412
340
                                          "entry-type", RHYTHMDB_ENTRY_TYPE_SONG,
413
 
                                          "sorting-key", CONF_STATE_LIBRARY_SORTING,
414
341
                                          "shell", shell,
415
342
                                          "pixbuf", icon,
416
343
                                          "populate", FALSE,            /* wait until the database is loaded */
 
344
                                          "settings", g_settings_get_child (settings, "source"),
417
345
                                          NULL));
418
346
        if (icon != NULL) {
419
347
                g_object_unref (icon);
420
348
        }
 
349
        g_object_unref (settings);
421
350
 
422
351
        rb_shell_register_entry_type_for_source (shell, source, RHYTHMDB_ENTRY_TYPE_SONG);
423
352
 
425
354
}
426
355
 
427
356
static void
428
 
rb_library_source_edit_profile_clicked_cb (GtkButton *button, RBLibrarySource *source)
 
357
rb_library_source_profile_settings_clicked_cb (GtkButton *button, RBLibrarySource *source)
429
358
{
430
 
        GtkWidget *dialog;
431
 
 
432
 
        dialog = gm_audio_profiles_edit_new (eel_gconf_client_get_global (),
433
 
                                             GTK_WINDOW (source->priv->shell_prefs));
434
 
        gtk_widget_show_all (dialog);
435
 
        gtk_dialog_run (GTK_DIALOG (dialog));
 
359
        /* do something.  not much idea what yet. */
436
360
}
437
361
 
438
362
static void
463
387
        gtk_widget_destroy (GTK_WIDGET (dialog));
464
388
}
465
389
 
 
390
static void
 
391
update_library_locations (RBLibrarySource *source)
 
392
{
 
393
        char **locations;
 
394
 
 
395
        if (source->priv->library_location_entry == NULL) {
 
396
                return;
 
397
        }
 
398
 
 
399
        locations = g_settings_get_strv (source->priv->db_settings, "locations");
 
400
 
 
401
        /* don't trigger the change notification */
 
402
        g_signal_handlers_block_by_func (G_OBJECT (source->priv->library_location_entry),
 
403
                                         G_CALLBACK (rb_library_source_library_location_cb),
 
404
                                         source);
 
405
 
 
406
        if (g_strv_length (locations) == 1) {
 
407
                char *path;
 
408
 
 
409
                gtk_widget_set_sensitive (source->priv->library_location_entry, TRUE);
 
410
 
 
411
                path = g_uri_unescape_string (locations[0], NULL);
 
412
                gtk_entry_set_text (GTK_ENTRY (source->priv->library_location_entry), path);
 
413
                g_free (path);
 
414
        } else if (g_strv_length (locations) == 0) {
 
415
                /* no library directories */
 
416
                gtk_widget_set_sensitive (source->priv->library_location_entry, TRUE);
 
417
                gtk_entry_set_text (GTK_ENTRY (source->priv->library_location_entry), "");
 
418
        } else {
 
419
                /* multiple library directories */
 
420
                gtk_widget_set_sensitive (source->priv->library_location_entry, FALSE);
 
421
                gtk_entry_set_text (GTK_ENTRY (source->priv->library_location_entry), _("Multiple locations set"));
 
422
        }
 
423
 
 
424
        g_signal_handlers_unblock_by_func (G_OBJECT (source->priv->library_location_entry),
 
425
                                           G_CALLBACK (rb_library_source_library_location_cb),
 
426
                                           source);
 
427
 
 
428
        g_strfreev (locations);
 
429
}
 
430
 
 
431
static void
 
432
update_layout_path (RBLibrarySource *source)
 
433
{
 
434
        char *value;
 
435
        int active;
 
436
        int i;
 
437
 
 
438
        value = g_settings_get_string (source->priv->settings, "layout-path");
 
439
 
 
440
        active = -1;
 
441
        for (i = 0; library_layout_paths[i].path != NULL; i++) {
 
442
                if (g_strcmp0 (library_layout_paths[i].path, value) == 0) {
 
443
                        active = i;
 
444
                        break;
 
445
                }
 
446
        }
 
447
 
 
448
        g_free (value);
 
449
        if (source->priv->layout_path_menu != NULL) {
 
450
                gtk_combo_box_set_active (GTK_COMBO_BOX (source->priv->layout_path_menu), active);
 
451
        }
 
452
 
 
453
        update_layout_example_label (source);
 
454
}
 
455
 
 
456
static void
 
457
update_layout_filename (RBLibrarySource *source)
 
458
{
 
459
        char *value;
 
460
        int active;
 
461
        int i;
 
462
 
 
463
        value = g_settings_get_string (source->priv->settings, "layout-filename");
 
464
 
 
465
        active = -1;
 
466
        for (i = 0; library_layout_filenames[i].path != NULL; i++) {
 
467
                if (strcmp (library_layout_filenames[i].path, value) == 0) {
 
468
                        active = i;
 
469
                        break;
 
470
                }
 
471
        }
 
472
        g_free (value);
 
473
 
 
474
        gtk_combo_box_set_active (GTK_COMBO_BOX (source->priv->layout_filename_menu), active);
 
475
 
 
476
        update_layout_example_label (source);
 
477
}
 
478
 
 
479
static void
 
480
update_preferred_media_type (RBLibrarySource *source)
 
481
{
 
482
        GtkTreeIter iter;
 
483
        gboolean done;
 
484
        char *str;
 
485
 
 
486
        done = FALSE;
 
487
        str = g_settings_get_string (source->priv->settings, "preferred-media-type");
 
488
        if (gtk_tree_model_get_iter_first (source->priv->profile_model, &iter)) {
 
489
                do {
 
490
                        char *media_type;
 
491
 
 
492
                        gtk_tree_model_get (source->priv->profile_model, &iter,
 
493
                                            0, &media_type,
 
494
                                            -1);
 
495
                        if (g_strcmp0 (media_type, str) == 0) {
 
496
                                gtk_combo_box_set_active_iter (GTK_COMBO_BOX (source->priv->preferred_format_menu), &iter);
 
497
                                done = TRUE;
 
498
                        }
 
499
                        g_free (media_type);
 
500
                } while (done == FALSE && gtk_tree_model_iter_next (source->priv->profile_model, &iter));
 
501
        }
 
502
 
 
503
        if (done == FALSE) {
 
504
                gtk_combo_box_set_active_iter (GTK_COMBO_BOX (source->priv->preferred_format_menu), NULL);
 
505
        }
 
506
 
 
507
        g_free (str);
 
508
}
 
509
 
 
510
static void
 
511
db_settings_changed_cb (GSettings *settings, const char *key, RBLibrarySource *source)
 
512
{
 
513
        if (g_strcmp0 (key, "locations") == 0) {
 
514
                update_library_locations (source);
 
515
                rb_library_source_sync_child_sources (source);
 
516
        }
 
517
}
 
518
 
 
519
static void
 
520
library_settings_changed_cb (GSettings *settings, const char *key, RBLibrarySource *source)
 
521
{
 
522
        if (g_strcmp0 (key, "layout-path") == 0) {
 
523
                rb_debug ("layout path changed");
 
524
                update_layout_path (source);
 
525
        } else if (g_strcmp0 (key, "layout-filename") == 0) {
 
526
                rb_debug ("layout filename changed");
 
527
                update_layout_filename (source);
 
528
        } else if (g_strcmp0 (key, "preferred-media-type") == 0) {
 
529
                rb_debug ("preferred media type changed");
 
530
                update_preferred_media_type (source);
 
531
        }
 
532
}
 
533
 
466
534
static GtkWidget *
467
535
impl_get_config_widget (RBDisplayPage *asource, RBShellPreferences *prefs)
468
536
{
469
537
        RBLibrarySource *source = RB_LIBRARY_SOURCE (asource);
 
538
        GtkCellRenderer *renderer;
 
539
        GstEncodingTarget *target;
470
540
        GtkBuilder *builder;
471
541
        GObject *tmp;
472
542
        GObject *label;
 
543
        const GList *p;
473
544
        int i;
474
545
 
475
546
        if (source->priv->config_widget)
496
567
                          asource);
497
568
 
498
569
        source->priv->watch_library_check = GTK_WIDGET (gtk_builder_get_object (builder, "watch_library_check"));
499
 
        g_signal_connect (G_OBJECT (source->priv->watch_library_check),
500
 
                          "toggled",
501
 
                          G_CALLBACK (rb_library_source_watch_toggled_cb),
502
 
                          asource);
 
570
        g_settings_bind (source->priv->db_settings, "monitor-library",
 
571
                         source->priv->watch_library_check, "active",
 
572
                         G_SETTINGS_BIND_DEFAULT);
503
573
 
504
574
        rb_builder_boldify_label (builder, "library_structure_label");
505
575
 
531
601
                                                _(library_layout_filenames[i].title));
532
602
        }
533
603
 
534
 
        tmp = gtk_builder_get_object (builder, "edit_profile_button");
 
604
        /* not implemented yet */
 
605
        tmp = gtk_builder_get_object (builder, "profile_settings_button");
535
606
        g_signal_connect (tmp,
536
607
                          "clicked",
537
 
                          G_CALLBACK (rb_library_source_edit_profile_clicked_cb),
 
608
                          G_CALLBACK (rb_library_source_profile_settings_clicked_cb),
538
609
                          asource);
539
 
 
540
 
        tmp = gtk_builder_get_object (builder, "preferred_format_menu_box");
541
 
        label = gtk_builder_get_object (builder, "preferred_format_menu_label");
542
 
        source->priv->preferred_format_menu = gm_audio_profile_choose_new ();
543
 
        gtk_box_pack_start (GTK_BOX (tmp), source->priv->preferred_format_menu, TRUE, TRUE, 0);
544
 
        gtk_label_set_mnemonic_widget (GTK_LABEL (label), source->priv->preferred_format_menu);
 
610
        gtk_widget_set_sensitive (GTK_WIDGET (tmp), FALSE);
 
611
 
 
612
        target = rb_gst_get_default_encoding_target ();
 
613
        source->priv->profile_model = GTK_TREE_MODEL (gtk_tree_store_new (3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER));
 
614
        for (p = gst_encoding_target_get_profiles (target); p != NULL; p = p->next) {
 
615
                GstEncodingProfile *profile = GST_ENCODING_PROFILE (p->data);
 
616
                char *media_type;
 
617
 
 
618
                media_type = rb_gst_encoding_profile_get_media_type (profile);
 
619
                if (media_type == NULL) {
 
620
                        continue;
 
621
                }
 
622
                gtk_tree_store_insert_with_values (GTK_TREE_STORE (source->priv->profile_model),
 
623
                                                   NULL,
 
624
                                                   NULL,
 
625
                                                   -1,
 
626
                                                   0, media_type,
 
627
                                                   1, gst_encoding_profile_get_description (profile),
 
628
                                                   2, profile,
 
629
                                                   -1);
 
630
                g_free (media_type);
 
631
        }
 
632
 
 
633
        source->priv->preferred_format_menu = GTK_WIDGET (gtk_builder_get_object (builder, "format_select_combo"));
 
634
        gtk_combo_box_set_model (GTK_COMBO_BOX (source->priv->preferred_format_menu), source->priv->profile_model);
 
635
        gtk_combo_box_set_entry_text_column (GTK_COMBO_BOX (source->priv->preferred_format_menu), 1);
 
636
        renderer = gtk_cell_renderer_text_new ();
 
637
        gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (source->priv->preferred_format_menu), renderer, TRUE);
 
638
        gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (source->priv->preferred_format_menu), renderer, "text", 1, NULL);
 
639
 
545
640
        g_signal_connect (G_OBJECT (source->priv->preferred_format_menu),
546
641
                          "changed",
547
642
                          G_CALLBACK (rb_library_source_format_changed_cb),
549
644
 
550
645
        source->priv->layout_example_label = GTK_WIDGET (gtk_builder_get_object (builder, "layout_example_label"));
551
646
 
552
 
        rb_library_source_preferences_sync (source);
 
647
        source->priv->install_plugins_button = GTK_WIDGET (gtk_builder_get_object (builder, "install_plugins_button"));
 
648
        gtk_widget_set_no_show_all (source->priv->install_plugins_button, TRUE);
 
649
        g_signal_connect (G_OBJECT (source->priv->install_plugins_button), "clicked", G_CALLBACK (rb_library_source_install_plugins_cb), source);
 
650
 
 
651
        update_library_locations (source);
 
652
        update_preferred_media_type (source);
 
653
 
 
654
        update_layout_path (source);
 
655
        update_layout_filename (source);
553
656
 
554
657
        return source->priv->config_widget;
555
658
}
556
659
 
557
 
static void
558
 
rb_library_source_library_location_changed (GConfClient *client,
559
 
                                            guint cnxn_id,
560
 
                                            GConfEntry *entry,
561
 
                                            RBLibrarySource *source)
562
 
{
563
 
        if (source->priv->config_widget)
564
 
                rb_library_source_preferences_sync (source);
565
 
 
566
 
        rb_library_source_sync_child_sources (source);
567
 
}
568
 
 
569
 
static void
570
 
rb_library_source_ui_prefs_sync (RBLibrarySource *source)
571
 
{
572
 
        if (source->priv->config_widget)
573
 
                rb_library_source_preferences_sync (source);
574
 
}
575
 
 
576
 
static void
577
 
rb_library_source_ui_pref_changed (GConfClient *client,
578
 
                                   guint cnxn_id,
579
 
                                   GConfEntry *entry,
580
 
                                   RBLibrarySource *source)
581
 
{
582
 
        rb_debug ("ui pref changed");
583
 
        rb_library_source_ui_prefs_sync (source);
584
 
}
585
 
 
586
 
static void
587
 
rb_library_source_preferences_sync (RBLibrarySource *source)
588
 
{
589
 
        GSList *list;
590
 
        char *str;
591
 
        GConfClient *gconf_client;
592
 
 
593
 
        rb_debug ("syncing pref dialog state");
594
 
 
595
 
        /* library location */
596
 
        list = eel_gconf_get_string_list (CONF_LIBRARY_LOCATION);
597
 
 
598
 
        /* don't trigger the change notification */
599
 
        g_signal_handlers_block_by_func (G_OBJECT (source->priv->library_location_entry),
600
 
                                         G_CALLBACK (rb_library_source_library_location_cb),
601
 
                                         source);
602
 
 
603
 
        if (g_slist_length (list) == 1) {
604
 
                char *path;
605
 
 
606
 
                gtk_widget_set_sensitive (source->priv->library_location_entry, TRUE);
607
 
 
608
 
                path = g_uri_unescape_string (list->data, NULL);
609
 
                gtk_entry_set_text (GTK_ENTRY (source->priv->library_location_entry), path);
610
 
                g_free (path);
611
 
        } else if (g_slist_length (list) == 0) {
612
 
                /* no library directories */
613
 
                gtk_widget_set_sensitive (source->priv->library_location_entry, TRUE);
614
 
                gtk_entry_set_text (GTK_ENTRY (source->priv->library_location_entry), "");
615
 
        } else {
616
 
                /* multiple library directories */
617
 
                gtk_widget_set_sensitive (source->priv->library_location_entry, FALSE);
618
 
                gtk_entry_set_text (GTK_ENTRY (source->priv->library_location_entry), _("Multiple locations set"));
619
 
        }
620
 
 
621
 
        g_signal_handlers_unblock_by_func (G_OBJECT (source->priv->library_location_entry),
622
 
                                           G_CALLBACK (rb_library_source_library_location_cb),
623
 
                                           source);
624
 
 
625
 
        rb_slist_deep_free (list);
626
 
 
627
 
        /* watch checkbox */
628
 
        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (source->priv->watch_library_check),
629
 
                                      eel_gconf_get_boolean (CONF_MONITOR_LIBRARY));
630
 
 
631
 
        /* preferred format */
632
 
        str = eel_gconf_get_string (CONF_LIBRARY_PREFERRED_FORMAT);
633
 
        if (str) {
634
 
                gm_audio_profile_choose_set_active (source->priv->preferred_format_menu, str);
635
 
                g_free (str);
636
 
        }
637
 
 
638
 
        source->priv->layout_path_notify_id =
639
 
                eel_gconf_notification_add (CONF_LIBRARY_LAYOUT_PATH,
640
 
                                    (GConfClientNotifyFunc) rb_library_source_layout_path_changed, source);
641
 
        source->priv->layout_filename_notify_id =
642
 
                eel_gconf_notification_add (CONF_LIBRARY_LAYOUT_FILENAME,
643
 
                                    (GConfClientNotifyFunc) rb_library_source_layout_filename_changed, source);
644
 
 
645
 
        gconf_client = eel_gconf_client_get_global ();
646
 
        /* layout path */
647
 
        rb_library_source_layout_path_changed (gconf_client, -1,
648
 
                                               gconf_client_get_entry (gconf_client, CONF_LIBRARY_LAYOUT_PATH, NULL, TRUE, NULL),
649
 
                                               source);
650
 
        /* layout filename */
651
 
        rb_library_source_layout_filename_changed (gconf_client, -1,
652
 
                                                   gconf_client_get_entry (gconf_client, CONF_LIBRARY_LAYOUT_FILENAME, NULL, TRUE, NULL),
653
 
                                                   source);
654
 
}
655
 
 
656
660
static gboolean
657
661
rb_library_source_library_location_cb (GtkEntry *entry,
658
662
                                       GdkEventFocus *event,
659
663
                                       RBLibrarySource *source)
660
664
{
661
 
        GSList *list = NULL;
662
665
        const char *path;
 
666
        const char *locations[2] = { NULL, NULL };
663
667
        GFile *file;
664
668
        char *uri;
665
669
 
668
672
        uri = g_file_get_uri (file);
669
673
        g_object_unref (file);
670
674
 
671
 
        if (uri && uri[0])
672
 
                list = g_slist_prepend (NULL, (gpointer)uri);
673
 
 
674
 
        eel_gconf_set_string_list (CONF_LIBRARY_LOCATION, list);
675
 
 
676
 
        rb_slist_deep_free (list);
677
 
 
 
675
        if (uri && uri[0]) {
 
676
                locations[0] = uri;
 
677
        }
 
678
 
 
679
        g_settings_set_strv (source->priv->db_settings, "locations", locations);
 
680
 
 
681
        g_free (uri);
678
682
        return FALSE;
679
683
}
680
684
 
681
 
static void
682
 
rb_library_source_watch_toggled_cb (GtkToggleButton *button, RBLibrarySource *source)
683
 
{
684
 
        gboolean active;
685
 
 
686
 
        active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (source->priv->watch_library_check));
687
 
        eel_gconf_set_boolean (CONF_MONITOR_LIBRARY, active);
688
 
}
689
 
 
690
 
static char *
691
 
impl_get_browser_key (RBSource *source)
692
 
{
693
 
        return g_strdup (CONF_STATE_SHOW_BROWSER);
694
 
}
695
 
 
696
 
static char *
697
 
impl_get_paned_key (RBBrowserSource *status)
698
 
{
699
 
        return g_strdup (CONF_STATE_PANED_POSITION);
700
 
}
701
 
 
702
685
static gboolean
703
686
impl_receive_drag (RBDisplayPage *asource, GtkSelectionData *data)
704
687
{
759
742
        index = gtk_combo_box_get_active (box);
760
743
        if (index >= 0) {
761
744
                path = library_layout_paths[index].path;
762
 
                eel_gconf_set_string (CONF_LIBRARY_LAYOUT_PATH, path);
 
745
 
 
746
                g_settings_set_string (source->priv->settings, "layout-path", path);
763
747
        }
764
748
}
765
749
 
772
756
        index = gtk_combo_box_get_active (box);
773
757
        if (index >= 0) {
774
758
                filename = library_layout_filenames[index].path;
775
 
                eel_gconf_set_string (CONF_LIBRARY_LAYOUT_FILENAME, filename);
 
759
                g_settings_set_string (source->priv->settings, "layout-filename", filename);
776
760
        }
777
761
}
778
762
 
779
763
static void
780
764
rb_library_source_format_changed_cb (GtkWidget *widget, RBLibrarySource *source)
781
765
{
782
 
        GMAudioProfile *profile;
783
 
 
784
 
        profile = gm_audio_profile_choose_get_active (widget);
785
 
        eel_gconf_set_string (CONF_LIBRARY_PREFERRED_FORMAT, gm_audio_profile_get_id (profile));
786
 
        
787
 
        layout_example_label_update (source);
 
766
        GtkTreeIter iter;
 
767
        char *media_type = NULL;
 
768
        GstEncodingProfile *profile;
 
769
        RBEncoder *encoder;
 
770
 
 
771
        /* get selected media type */
 
772
        if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter) == FALSE)
 
773
                return;
 
774
        gtk_tree_model_get (GTK_TREE_MODEL (source->priv->profile_model),
 
775
                            &iter,
 
776
                            0, &media_type,
 
777
                            2, &profile,
 
778
                            -1);
 
779
 
 
780
        g_settings_set_string (source->priv->settings, "preferred-media-type", media_type);
 
781
 
 
782
        update_layout_example_label (source);
 
783
 
 
784
        /* indicate whether additional plugins are required to encode in this format */
 
785
        encoder = rb_encoder_new ();
 
786
        if (rb_encoder_get_missing_plugins (encoder, profile, NULL, NULL)) {
 
787
                rb_debug ("additional plugins are required to encode %s", media_type);
 
788
                gtk_widget_set_visible (source->priv->install_plugins_button, TRUE);
 
789
                /* not a great way to handle this situation; probably should describe
 
790
                 * the plugins that are missing when automatic install isn't available.
 
791
                 */
 
792
                gtk_widget_set_sensitive (source->priv->install_plugins_button,
 
793
                                        gst_install_plugins_supported ());
 
794
        } else {
 
795
                rb_debug ("can encode %s", media_type);
 
796
                gtk_widget_set_visible (source->priv->install_plugins_button, FALSE);
 
797
        }
 
798
        g_free (media_type);
 
799
}
 
800
 
 
801
static void
 
802
plugin_install_done_cb (gpointer inst, gboolean retry, RBLibrarySource *source)
 
803
{
 
804
        rb_library_source_format_changed_cb (source->priv->preferred_format_menu, source);
 
805
}
 
806
 
 
807
static void
 
808
rb_library_source_install_plugins_cb (GtkWidget *widget, RBLibrarySource *source)
 
809
{
 
810
        char *media_type;
 
811
        GstEncodingProfile *profile;
 
812
        RBEncoder *encoder;
 
813
        char **details;
 
814
        GClosure *closure;
 
815
 
 
816
        /* get profile */
 
817
        media_type = g_settings_get_string (source->priv->settings, "preferred-media-type");
 
818
        profile = rb_gst_get_encoding_profile (media_type);
 
819
        if (profile == NULL) {
 
820
                g_warning ("no encoding profile available for %s, so how can we install plugins?",
 
821
                           media_type);
 
822
                g_free (media_type);
 
823
                return;
 
824
        }
 
825
        g_free (media_type);
 
826
 
 
827
        /* get plugin details */
 
828
        encoder = rb_encoder_new ();
 
829
        if (rb_encoder_get_missing_plugins (encoder, profile, &details, NULL) == FALSE) {
 
830
                /* what? */
 
831
                g_object_unref (encoder);
 
832
                return;
 
833
        }
 
834
 
 
835
        /* attempt installation */
 
836
        closure = g_cclosure_new ((GCallback) plugin_install_done_cb,
 
837
                                  g_object_ref (source),
 
838
                                  (GClosureNotify) g_object_unref);
 
839
        g_closure_set_marshal (closure, g_cclosure_marshal_VOID__BOOLEAN);
 
840
 
 
841
        rb_missing_plugins_install ((const char **)details, TRUE, closure);
 
842
 
 
843
        g_closure_sink (closure);
 
844
        g_strfreev (details);
788
845
}
789
846
 
790
847
/*
796
853
 * don't end up being hidden.
797
854
 */
798
855
static char *
799
 
sanitize_path (const char *str)
 
856
sanitize_path (gboolean strip_chars, const char *str)
800
857
{
801
858
        gchar *s;
802
859
 
807
864
        s = g_strdup(str);
808
865
        /* Replace path seperators with a hyphen */
809
866
        g_strdelimit (s, "/", '-');
810
 
        if (eel_gconf_get_boolean (CONF_LIBRARY_STRIP_CHARS)) {
 
867
        if (strip_chars) {
811
868
                /* Replace separators with a hyphen */
812
869
                g_strdelimit (s, "\\:|", '-');
813
870
                /* Replace all other weird characters to whitespace */
821
878
}
822
879
 
823
880
static char *
824
 
sanitize_pattern (const char *pat)
 
881
sanitize_pattern (gboolean strip_chars, const char *pat)
825
882
{
826
 
        if (eel_gconf_get_boolean (CONF_LIBRARY_STRIP_CHARS)) {
 
883
        if (strip_chars) {
827
884
                gchar *s;
828
885
 
829
886
                s = g_strdup (pat);
857
914
 * %tS -- track artist sortname (lowercase)
858
915
 */
859
916
static char *
860
 
filepath_parse_pattern (RhythmDB *db,
 
917
filepath_parse_pattern (RBLibrarySource *source,
861
918
                        const char *pattern,
862
919
                        RhythmDBEntry *entry)
863
920
{
867
924
        GString *s;
868
925
        RBRefString *albumartist;
869
926
        RBRefString *albumartist_sort;
 
927
        gboolean strip_chars;
870
928
 
871
929
        if (pattern == NULL || pattern[0] == 0)
872
930
                return g_strdup (" ");
873
931
 
 
932
        strip_chars = g_settings_get_boolean (source->priv->settings, "strip-chars");
 
933
 
874
934
        /* figure out album artist - use the plain artist field if not specified */
875
935
        albumartist = rhythmdb_entry_get_refstring (entry, RHYTHMDB_PROP_ALBUM_ARTIST);
876
936
        if (albumartist == NULL || g_strcmp0 (rb_refstring_get (albumartist), "") == 0) {
908
968
                         */
909
969
                        switch (*++p) {
910
970
                        case 't':
911
 
                                string = sanitize_path (rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ALBUM));
 
971
                                string = sanitize_path (strip_chars, rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ALBUM));
912
972
                                break;
913
973
                        case 'T':
914
 
                                string = sanitize_path (rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ALBUM_FOLDED));
 
974
                                string = sanitize_path (strip_chars, rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ALBUM_FOLDED));
915
975
                                break;
916
976
                        case 'a':
917
 
                                string = sanitize_path (rb_refstring_get (albumartist));
 
977
                                string = sanitize_path (strip_chars, rb_refstring_get (albumartist));
918
978
                                break;
919
979
                        case 'A':
920
 
                                string = sanitize_path (rb_refstring_get_folded (albumartist));
 
980
                                string = sanitize_path (strip_chars, rb_refstring_get_folded (albumartist));
921
981
                                break;
922
982
                        case 's':
923
 
                                string = sanitize_path (rb_refstring_get (albumartist_sort));
 
983
                                string = sanitize_path (strip_chars, rb_refstring_get (albumartist_sort));
924
984
                                break;
925
985
                        case 'S':
926
 
                                string = sanitize_path (rb_refstring_get_folded (albumartist_sort));
 
986
                                string = sanitize_path (strip_chars, rb_refstring_get_folded (albumartist_sort));
927
987
                                break;
928
988
                        case 'y':
929
989
                                string = g_strdup_printf ("%u", (guint)rhythmdb_entry_get_ulong (entry, RHYTHMDB_PROP_YEAR));
935
995
                                string = g_strdup_printf ("%02u", (guint)rhythmdb_entry_get_ulong (entry, RHYTHMDB_PROP_DISC_NUMBER));
936
996
                                break;
937
997
                        case 'g':
938
 
                                string = sanitize_path (rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_GENRE));
 
998
                                string = sanitize_path (strip_chars, rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_GENRE));
939
999
                                break;
940
1000
                        case 'G':
941
 
                                string = sanitize_path (rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_GENRE_FOLDED));
 
1001
                                string = sanitize_path (strip_chars, rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_GENRE_FOLDED));
942
1002
                                break;
943
1003
                        default:
944
1004
                                string = g_strdup_printf ("%%a%c", *p);
952
1012
                         */
953
1013
                        switch (*++p) {
954
1014
                        case 't':
955
 
                                string = sanitize_path (rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_TITLE));
 
1015
                                string = sanitize_path (strip_chars, rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_TITLE));
956
1016
                                break;
957
1017
                        case 'T':
958
 
                                string = sanitize_path (rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_TITLE_FOLDED));
 
1018
                                string = sanitize_path (strip_chars, rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_TITLE_FOLDED));
959
1019
                                break;
960
1020
                        case 'a':
961
 
                                string = sanitize_path (rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ARTIST));
 
1021
                                string = sanitize_path (strip_chars, rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ARTIST));
962
1022
                                break;
963
1023
                        case 'A':
964
 
                                string = sanitize_path (rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ARTIST_FOLDED));
 
1024
                                string = sanitize_path (strip_chars, rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ARTIST_FOLDED));
965
1025
                                break;
966
1026
                        case 's':
967
 
                                string = sanitize_path (rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ARTIST_SORTNAME));
 
1027
                                string = sanitize_path (strip_chars, rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ARTIST_SORTNAME));
968
1028
                                break;
969
1029
                        case 'S':
970
 
                                string = sanitize_path (rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ARTIST_SORTNAME_FOLDED));
 
1030
                                string = sanitize_path (strip_chars, rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ARTIST_SORTNAME_FOLDED));
971
1031
                                break;
972
1032
                        case 'n':
973
1033
                                /* Track number */
979
1039
                                break;
980
1040
                        default:
981
1041
                                string = g_strdup_printf ("%%t%c", *p);
982
 
                        }
 
1042
                        }
983
1043
 
984
1044
                        break;
985
1045
 
1001
1061
}
1002
1062
 
1003
1063
static void
1004
 
layout_example_label_update (RBLibrarySource *source)
 
1064
update_layout_example_label (RBLibrarySource *source)
1005
1065
{
1006
1066
        char *file_pattern;
1007
1067
        char *path_pattern;
1010
1070
        char *example;
1011
1071
        char *format;
1012
1072
        char *tmp;
1013
 
        GMAudioProfile *profile;
 
1073
        gboolean strip_chars;
 
1074
        char *media_type;
1014
1075
        RhythmDBEntryType *entry_type;
1015
1076
        RhythmDBEntry *sample_entry;
1016
1077
 
1017
 
        profile = gm_audio_profile_choose_get_active (source->priv->preferred_format_menu);
 
1078
        media_type = g_settings_get_string (source->priv->settings, "preferred-media-type");
1018
1079
 
1019
 
        /* TODO: sucky. Replace with get-gconf-key-with-default mojo */
1020
 
        file_pattern = eel_gconf_get_string (CONF_LIBRARY_LAYOUT_FILENAME);
 
1080
        file_pattern = g_settings_get_string (source->priv->settings, "layout-filename");
1021
1081
        if (file_pattern == NULL) {
1022
1082
                file_pattern = g_strdup (library_layout_filenames[0].path);
1023
1083
        }
1024
 
        tmp = sanitize_pattern (file_pattern);
 
1084
        strip_chars = g_settings_get_boolean (source->priv->settings, "strip-chars");
 
1085
        tmp = sanitize_pattern (strip_chars, file_pattern);
1025
1086
        g_free (file_pattern);
1026
1087
        file_pattern = tmp;
1027
1088
 
1028
 
        path_pattern = eel_gconf_get_string (CONF_LIBRARY_LAYOUT_PATH);
 
1089
        path_pattern = g_settings_get_string (source->priv->settings, "layout-path");
1029
1090
        if (path_pattern == NULL) {
1030
1091
                path_pattern = g_strdup (library_layout_paths[0].path);
1031
1092
        }
1034
1095
        sample_entry = rhythmdb_entry_example_new (source->priv->db, entry_type, NULL);
1035
1096
        g_object_unref (entry_type);
1036
1097
 
1037
 
        file_value = filepath_parse_pattern (source->priv->db, file_pattern, sample_entry);
1038
 
        path_value = filepath_parse_pattern (source->priv->db, path_pattern, sample_entry);
 
1098
        file_value = filepath_parse_pattern (source, file_pattern, sample_entry);
 
1099
        path_value = filepath_parse_pattern (source, path_pattern, sample_entry);
1039
1100
        rhythmdb_entry_unref (sample_entry);
1040
1101
 
1041
1102
        example = g_build_filename (G_DIR_SEPARATOR_S, path_value, file_value, NULL);
1049
1110
                              "</b> ",
1050
1111
                              example,
1051
1112
                              ".",
1052
 
                              profile ? gm_audio_profile_get_extension (profile) : "ogg",
 
1113
                              media_type ? rb_gst_media_type_to_extension (media_type) : "ogg",
1053
1114
                              "</i></small>", NULL);
1054
1115
        g_free (example);
 
1116
        g_free (media_type);
1055
1117
 
1056
1118
        gtk_label_set_markup (GTK_LABEL (source->priv->layout_example_label), format);
1057
1119
        g_free (format);
1058
1120
}
1059
1121
 
1060
 
static void
1061
 
rb_library_source_layout_path_changed (GConfClient *client,
1062
 
                                       guint cnxn_id,
1063
 
                                       GConfEntry *entry,
1064
 
                                       RBLibrarySource *source)
1065
 
{
1066
 
        char *value;
1067
 
        int active;
1068
 
        int i;
1069
 
 
1070
 
        g_return_if_fail (entry != NULL);
1071
 
        g_return_if_fail (strcmp (entry->key, CONF_LIBRARY_LAYOUT_PATH) == 0);
1072
 
 
1073
 
        rb_debug ("layout path changed");
1074
 
 
1075
 
        if (entry->value == NULL) {
1076
 
                value = g_strdup (library_layout_paths[0].path);
1077
 
        } else if (entry->value->type == GCONF_VALUE_STRING) {
1078
 
                value = g_strdup (gconf_value_get_string (entry->value));
1079
 
        } else {
1080
 
                return;
1081
 
        }
1082
 
 
1083
 
        active = -1;
1084
 
        for (i = 0; library_layout_paths[i].path != NULL; i++) {
1085
 
                if (strcmp (library_layout_paths[i].path, value) == 0) {
1086
 
                        active = i;
1087
 
                        break;
1088
 
                }
1089
 
        }
1090
 
 
1091
 
        g_free (value);
1092
 
        gtk_combo_box_set_active (GTK_COMBO_BOX (source->priv->layout_path_menu), active);
1093
 
 
1094
 
        layout_example_label_update (source);
1095
 
}
1096
 
 
1097
 
static void
1098
 
rb_library_source_layout_filename_changed (GConfClient *client,
1099
 
                                           guint cnxn_id,
1100
 
                                           GConfEntry *entry,
1101
 
                                           RBLibrarySource *source)
1102
 
{
1103
 
        char *value;
1104
 
        int active;
1105
 
        int i;
1106
 
 
1107
 
        g_return_if_fail (entry != NULL);
1108
 
        g_return_if_fail (strcmp (entry->key, CONF_LIBRARY_LAYOUT_FILENAME) == 0);
1109
 
 
1110
 
        rb_debug ("layout filename changed");
1111
 
 
1112
 
        if (entry->value == NULL) {
1113
 
                value = g_strdup (library_layout_filenames[0].path);
1114
 
        } else if (entry->value->type == GCONF_VALUE_STRING) {
1115
 
                value = g_strdup (gconf_value_get_string (entry->value));
1116
 
        } else {
1117
 
                return;
1118
 
        }
1119
 
 
1120
 
        active = -1;
1121
 
        for (i = 0; library_layout_filenames[i].path != NULL; i++) {
1122
 
                if (strcmp (library_layout_filenames[i].path, value) == 0) {
1123
 
                        active = i;
1124
 
                        break;
1125
 
                }
1126
 
        }
1127
 
        g_free (value);
1128
 
 
1129
 
        gtk_combo_box_set_active (GTK_COMBO_BOX (source->priv->layout_filename_menu), active);
1130
 
 
1131
 
        layout_example_label_update (source);
1132
 
}
1133
 
 
1134
1122
/*
1135
1123
 * Build the absolute filename for the specified track.
1136
1124
 *
1151
1139
        char *filename;
1152
1140
        char *string = NULL;
1153
1141
        char *tmp;
1154
 
        GSList *list;
 
1142
        char **locations;
1155
1143
        char *layout_path;
1156
1144
        char *layout_filename;
1157
 
 
1158
 
        list = eel_gconf_get_string_list (CONF_LIBRARY_LOCATION);
1159
 
        layout_path = eel_gconf_get_string (CONF_LIBRARY_LAYOUT_PATH);
1160
 
        layout_filename = eel_gconf_get_string (CONF_LIBRARY_LAYOUT_FILENAME);
1161
 
 
1162
 
        if (list == NULL || layout_path == NULL || layout_filename == NULL) {
 
1145
        gboolean strip_chars;
 
1146
 
 
1147
        locations = g_settings_get_strv (source->priv->db_settings, "locations");
 
1148
        layout_path = g_settings_get_string (source->priv->settings, "layout-path");
 
1149
        layout_filename = g_settings_get_string (source->priv->settings, "layout-filename");
 
1150
        strip_chars = g_settings_get_boolean (source->priv->settings, "strip-chars");
 
1151
 
 
1152
        if (locations == NULL || layout_path == NULL || layout_filename == NULL) {
1163
1153
                /* emit warning */
1164
 
                rb_debug ("Could not retrieve settings from GConf");
 
1154
                rb_debug ("Could not retrieve library layout settings");
1165
1155
                goto out;
1166
1156
        }
1167
1157
 
1168
 
        tmp = sanitize_pattern (layout_filename);
 
1158
        tmp = sanitize_pattern (strip_chars, layout_filename);
1169
1159
        g_free (layout_filename);
1170
1160
        layout_filename = tmp;
1171
1161
 
1172
 
        realpath = filepath_parse_pattern (source->priv->db, layout_path, entry);
 
1162
        realpath = filepath_parse_pattern (source, layout_path, entry);
1173
1163
 
1174
 
        library_location = g_file_new_for_uri ((const char *)list->data);
 
1164
        library_location = g_file_new_for_uri ((const char *)locations[0]);
1175
1165
        dir = g_file_resolve_relative_path (library_location, realpath);
1176
1166
        g_object_unref (library_location);
1177
1167
        g_free (realpath);
1178
1168
 
1179
 
        realfile = filepath_parse_pattern (source->priv->db, layout_filename, entry);
 
1169
        realfile = filepath_parse_pattern (source, layout_filename, entry);
1180
1170
        if (extension) {
1181
1171
                filename = g_strdup_printf ("%s.%s", realfile, extension);
1182
1172
                g_free (realfile);
1191
1181
        string = g_file_get_uri (dest);
1192
1182
        g_object_unref (dest);
1193
1183
 out:
1194
 
        rb_slist_deep_free (list);
 
1184
        g_strfreev (locations);
1195
1185
        g_free (layout_path);
1196
1186
        g_free (layout_filename);
1197
1187
 
1201
1191
static gboolean
1202
1192
impl_can_paste (RBSource *asource)
1203
1193
{
1204
 
        GSList *list;
 
1194
        RBLibrarySource *source = RB_LIBRARY_SOURCE (asource);
 
1195
        char **locations;
1205
1196
        gboolean can_paste = TRUE;
1206
1197
        char *str;
1207
1198
 
1208
 
        list = eel_gconf_get_string_list (CONF_LIBRARY_LOCATION);
1209
 
        can_paste = (list != NULL);
1210
 
        rb_slist_deep_free (list);
1211
 
 
1212
 
        str = eel_gconf_get_string (CONF_LIBRARY_LAYOUT_PATH);
1213
 
        can_paste &= (str != NULL);
1214
 
        g_free (str);
1215
 
 
1216
 
        str = eel_gconf_get_string (CONF_LIBRARY_LAYOUT_FILENAME);
1217
 
        can_paste &= (str != NULL);
1218
 
        g_free (str);
1219
 
 
1220
 
        str = eel_gconf_get_string (CONF_LIBRARY_PREFERRED_FORMAT);
1221
 
        can_paste &= (str != NULL);
1222
 
        g_free (str);
 
1199
        locations = g_settings_get_strv (source->priv->db_settings, "locations");
 
1200
        can_paste = (g_strv_length (locations) > 0);
 
1201
        g_strfreev (locations);
 
1202
 
 
1203
        str = g_settings_get_string (source->priv->settings, "layout-path");
 
1204
        can_paste &= (str != NULL);
 
1205
        g_free (str);
 
1206
 
 
1207
        str = g_settings_get_string (source->priv->settings, "layout-filename");
 
1208
        can_paste &= (str != NULL);
 
1209
        g_free (str);
 
1210
 
 
1211
        str = g_settings_get_string (source->priv->settings, "preferred-media-type");
 
1212
        can_paste &= (str != NULL);
 
1213
        g_free (str);
 
1214
 
1223
1215
        return can_paste;
1224
1216
}
1225
1217
 
1292
1284
        RhythmDBEntryType *source_entry_type;
1293
1285
        RBTrackTransferBatch *batch;
1294
1286
        gboolean start_batch = FALSE;
 
1287
        GstEncodingTarget *target;
 
1288
        GstEncodingProfile *profile;
 
1289
        char *preferred_media_type;
1295
1290
 
1296
1291
        if (impl_can_paste (asource) == FALSE) {
1297
 
                g_warning ("RBLibrarySource impl_paste called when gconf keys unset");
 
1292
                g_warning ("RBLibrarySource impl_paste called when layout settings unset");
1298
1293
                return NULL;
1299
1294
        }
1300
1295
 
1305
1300
        g_object_get (shell, "track-transfer-queue", &xferq, NULL);
1306
1301
        g_object_unref (shell);
1307
1302
 
1308
 
        batch = rb_track_transfer_batch_new (NULL, NULL, NULL, G_OBJECT (source));
 
1303
        target = gst_encoding_target_new ("rhythmbox-library", "device", "", NULL);
 
1304
 
 
1305
        /* set up profile for user's preferred format */
 
1306
        preferred_media_type = g_settings_get_string (source->priv->settings, "preferred-media-type");
 
1307
        profile = rb_gst_get_encoding_profile (preferred_media_type);
 
1308
        g_free (preferred_media_type);
 
1309
        /* have a preset as part of the user settings too?  would that work for containerful streams,
 
1310
         * where the interesting settings are on the stream inside the container?
 
1311
         */
 
1312
        if (profile != NULL) {
 
1313
                gst_encoding_target_add_profile (target, profile);
 
1314
        }
 
1315
 
 
1316
        /* set up profile for copying, which accepts any format */
 
1317
        profile = GST_ENCODING_PROFILE (gst_encoding_audio_profile_new (gst_caps_new_any (), NULL, NULL, 1));
 
1318
        gst_encoding_profile_set_name (profile, "copy");
 
1319
        gst_encoding_target_add_profile (target, profile);
 
1320
 
 
1321
        batch = rb_track_transfer_batch_new (target, NULL, G_OBJECT (source));
1309
1322
        g_signal_connect_object (batch, "get-dest-uri", G_CALLBACK (get_dest_uri_cb), source, 0);
1310
1323
        g_signal_connect_object (batch, "track-done", G_CALLBACK (track_done_cb), source, 0);
1311
1324
 
1500
1513
                      "entry-type", &entry_type,
1501
1514
                      NULL);
1502
1515
 
1503
 
        file = g_file_new_for_uri (path);               /* ? */
 
1516
        file = g_file_new_for_uri (path);
1504
1517
        name = g_file_get_basename (file);
1505
1518
        g_object_unref (file);
1506
1519
 
1535
1548
static void
1536
1549
rb_library_source_sync_child_sources (RBLibrarySource *source)
1537
1550
{
1538
 
        GSList *list;
 
1551
        char **locations;
 
1552
        int num_locations;
1539
1553
 
1540
 
        list = eel_gconf_get_string_list (CONF_LIBRARY_LOCATION);
 
1554
        locations = g_settings_get_strv (source->priv->db_settings, "locations");
1541
1555
 
1542
1556
        /* FIXME: don't delete and re-create sources that are still there */
1543
1557
        g_list_foreach (source->priv->child_sources, (GFunc)rb_display_page_delete_thyself, NULL);
1544
1558
        g_list_free (source->priv->child_sources);
1545
1559
        source->priv->child_sources = NULL;
1546
1560
 
1547
 
        if (g_slist_length (list) > 1)
1548
 
                g_slist_foreach (list, (GFunc)rb_library_source_add_child_source, source);
1549
 
        rb_slist_deep_free (list);
 
1561
        num_locations = g_strv_length (locations);
 
1562
        if (num_locations > 1) {
 
1563
                int i;
 
1564
                for (i = 0; i < num_locations; i++) {
 
1565
                        rb_library_source_add_child_source (locations[i], source);
 
1566
                }
 
1567
        }
 
1568
        g_strfreev (locations);
1550
1569
}
1551
1570
 
1552
1571
static void