~ubuntu-branches/ubuntu/utopic/rhythmbox/utopic-proposed

« back to all changes in this revision

Viewing changes to shell/rb-playlist-manager.c

Tags: upstream-0.9.2
ImportĀ upstreamĀ versionĀ 0.9.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
1
2
/*
2
3
 *  arch-tag: Implementation of Rhythmbox playlist management object
3
4
 *
4
 
 *  Copyright (C) 2003 Colin Walters <walters@gnome.org>
 
5
 *  Copyright (C) 2003,2004 Colin Walters <walters@gnome.org>
5
6
 *
6
7
 *  This program is free software; you can redistribute it and/or modify
7
8
 *  it under the terms of the GNU General Public License as published by
22
23
#include <config.h>
23
24
#include <gtk/gtk.h>
24
25
#include <libgnome/gnome-i18n.h>
25
 
#include <bonobo/bonobo-ui-util.h>
26
26
#include <libxml/tree.h>
27
27
#include <libgnomevfs/gnome-vfs.h>
28
28
#include <libgnomevfs/gnome-vfs-mime-utils.h>
29
29
#include <string.h>
 
30
#include <stdio.h>      /* rename() */
 
31
#include <unistd.h>     /* unlink() */
30
32
 
31
33
#include "rb-playlist-manager.h"
32
34
#include "rb-playlist-source.h"
 
35
#include "rb-recorder.h"
33
36
#include "rb-sourcelist.h"
 
37
#include "rb-sourcelist-model.h"
34
38
#include "rb-query-creator.h"
35
 
#include "rb-playlist.h"
 
39
#include "totem-pl-parser.h"
36
40
 
37
 
#include "rb-bonobo-helpers.h"
38
41
#include "rb-file-helpers.h"
39
42
#include "rb-debug.h"
40
43
#include "rb-dialog.h"
42
45
#include "rb-stock-icons.h"
43
46
#include "eel-gconf-extensions.h"
44
47
 
 
48
#define RB_PLAYLIST_MGR_VERSION (xmlChar *) "1.0"
 
49
#define RB_PLAYLIST_MGR_PL (xmlChar *) "rhythmdb-playlists"
 
50
 
45
51
static void rb_playlist_manager_class_init (RBPlaylistManagerClass *klass);
46
52
static void rb_playlist_manager_init (RBPlaylistManager *mgr);
47
53
static void rb_playlist_manager_finalize (GObject *object);
53
59
                                              guint prop_id,
54
60
                                              GValue *value,
55
61
                                              GParamSpec *pspec);
56
 
static void rb_playlist_manager_cmd_load_playlist (BonoboUIComponent *component,
57
 
                                                   RBPlaylistManager *mgr,
58
 
                                                   const char *verbname);
59
 
static void rb_playlist_manager_cmd_save_playlist (BonoboUIComponent *component,
60
 
                                                   RBPlaylistManager *mgr,
61
 
                                                   const char *verbname);
62
 
static void rb_playlist_manager_cmd_new_playlist (BonoboUIComponent *component,
63
 
                                                  RBPlaylistManager *mgr,
64
 
                                                  const char *verbname);
65
 
static void rb_playlist_manager_cmd_new_automatic_playlist (BonoboUIComponent *component,
66
 
                                                            RBPlaylistManager *mgr,
67
 
                                                            const char *verbname);
68
 
static void rb_playlist_manager_cmd_delete_playlist (BonoboUIComponent *component,
69
 
                                                     RBPlaylistManager *mgr,
70
 
                                                     const char *verbname);
71
 
static void rb_playlist_manager_cmd_edit_automatic_playlist (BonoboUIComponent *component,
72
 
                                                             RBPlaylistManager *mgr,
73
 
                                                             const char *verbname);
74
 
static void handle_playlist_entry_into_playlist_cb (RBPlaylist *playlist, const char *uri, const char *title,
75
 
                                                    const char *genre, RBPlaylistManager *mgr);
 
62
static void rb_playlist_manager_cmd_load_playlist (GtkAction *action,
 
63
                                                   RBPlaylistManager *mgr);
 
64
static void rb_playlist_manager_cmd_save_playlist (GtkAction *action,
 
65
                                                   RBPlaylistManager *mgr);
 
66
static void rb_playlist_manager_cmd_burn_playlist (GtkAction *action,
 
67
                                                   RBPlaylistManager *mgr);
 
68
static void rb_playlist_manager_cmd_new_playlist (GtkAction *action,
 
69
                                                  RBPlaylistManager *mgr);
 
70
static void rb_playlist_manager_cmd_new_automatic_playlist (GtkAction *action,
 
71
                                                            RBPlaylistManager *mgr);
 
72
static void rb_playlist_manager_cmd_rename_playlist (GtkAction *action,
 
73
                                                     RBPlaylistManager *mgr);
 
74
static void rb_playlist_manager_cmd_delete_playlist (GtkAction *action,
 
75
                                                     RBPlaylistManager *mgr);
 
76
static void rb_playlist_manager_cmd_edit_automatic_playlist (GtkAction *action,
 
77
                                                             RBPlaylistManager *mgr);
76
78
static gboolean reap_dead_playlist_threads (RBPlaylistManager *mgr);
 
79
static void rb_playlist_manager_playlist_entries_changed (RBEntryView *entry_view,
 
80
                                                           RhythmDBEntry *entry,
 
81
                                                           RBPlaylistManager *mgr);
77
82
 
78
83
struct RBPlaylistManagerPrivate
79
84
{
80
85
        RhythmDB *db;
 
86
        RBShell *shell;
81
87
        RBSource *selected_source;
82
88
 
83
89
        RBSourceList *sourcelist;
84
90
 
85
 
        BonoboUIComponent *component;
 
91
        GtkActionGroup *actiongroup;
 
92
        GtkUIManager *uimanager;
 
93
 
86
94
        RBLibrarySource *libsource;
87
95
        RBIRadioSource *iradio_source;
88
96
        GtkWindow *window;
89
97
 
90
 
        GList *playlists;
91
 
 
92
98
        guint playlist_serial;
93
99
 
94
100
        RBPlaylistSource *loading_playlist;
110
116
enum
111
117
{
112
118
        PROP_0,
113
 
        PROP_WINDOW,
114
 
        PROP_COMPONENT,
 
119
        PROP_SHELL,
115
120
        PROP_SOURCE,
116
 
        PROP_DB,
117
121
        PROP_SOURCELIST,
118
122
        PROP_LIBRARY_SOURCE,
119
123
        PROP_IRADIO_SOURCE,
122
126
enum
123
127
{
124
128
        PLAYLIST_ADDED,
 
129
        PLAYLIST_CREATED,
125
130
        PLAYLIST_LOAD_START,
126
131
        PLAYLIST_LOAD_FINISH,
127
132
        LAST_SIGNAL,
129
134
 
130
135
static guint rb_playlist_manager_signals[LAST_SIGNAL] = { 0 };
131
136
 
132
 
#define CMD_PATH_PLAYLIST_DELETE   "/commands/FileDeletePlaylist"
133
 
#define CMD_PATH_PLAYLIST_SAVE   "/commands/SavePlaylist"
134
 
 
135
 
static BonoboUIVerb rb_playlist_manager_verbs[] =
 
137
static GtkActionEntry rb_playlist_manager_actions [] =
136
138
{
137
 
        BONOBO_UI_VERB ("NewPlaylist",  (BonoboUIVerbFn) rb_playlist_manager_cmd_new_playlist),
138
 
        BONOBO_UI_VERB ("NewAutomaticPlaylist",  (BonoboUIVerbFn) rb_playlist_manager_cmd_new_automatic_playlist),
139
 
        BONOBO_UI_VERB ("LoadPlaylist", (BonoboUIVerbFn) rb_playlist_manager_cmd_load_playlist),
140
 
        BONOBO_UI_VERB ("SavePlaylist", (BonoboUIVerbFn) rb_playlist_manager_cmd_save_playlist),
141
 
        BONOBO_UI_VERB ("FileDeletePlaylist",(BonoboUIVerbFn) rb_playlist_manager_cmd_delete_playlist),
142
 
        BONOBO_UI_VERB ("DeletePlaylist",  (BonoboUIVerbFn) rb_playlist_manager_cmd_delete_playlist),
143
 
        BONOBO_UI_VERB ("EditAutomaticPlaylist",  (BonoboUIVerbFn) rb_playlist_manager_cmd_edit_automatic_playlist),
144
 
        BONOBO_UI_VERB_END
 
139
        /* Submenu of Music */
 
140
        { "Playlist", NULL, N_("_Playlist") },
 
141
 
 
142
        { "MusicPlaylistNewPlaylist", GNOME_MEDIA_PLAYLIST, N_("_New Playlist..."), "<control>N",
 
143
          N_("Create a new playlist"),
 
144
          G_CALLBACK (rb_playlist_manager_cmd_new_playlist) },
 
145
        { "MusicPlaylistNewAutomaticPlaylist", GNOME_MEDIA_AUTO_PLAYLIST, N_("New _Automatic Playlist..."), NULL,
 
146
          N_("Create a new automatically updating playlist"),
 
147
          G_CALLBACK (rb_playlist_manager_cmd_new_automatic_playlist) },
 
148
        { "MusicPlaylistLoadPlaylist", NULL, N_("_Load from File..."), NULL,
 
149
          N_("Choose a playlist to be loaded"),
 
150
          G_CALLBACK (rb_playlist_manager_cmd_load_playlist) },
 
151
        { "MusicPlaylistSavePlaylist", GTK_STOCK_SAVE_AS, N_("_Save to File..."), NULL,
 
152
          N_("Save a playlist to a file"),
 
153
          G_CALLBACK (rb_playlist_manager_cmd_save_playlist) },
 
154
        { "MusicPlaylistBurnPlaylist", GTK_STOCK_CDROM, N_("_Create Audio CD..."), NULL,
 
155
          N_("Create an audio CD from playlist"),
 
156
          G_CALLBACK (rb_playlist_manager_cmd_burn_playlist) },
 
157
        { "MusicPlaylistRenamePlaylist", NULL, N_("_Rename..."), NULL,
 
158
          N_("Rename playlist"),
 
159
          G_CALLBACK (rb_playlist_manager_cmd_rename_playlist) },
 
160
        { "MusicPlaylistDeletePlaylist", GTK_STOCK_REMOVE, N_("_Delete"), NULL,
 
161
          N_("Delete playlist"),
 
162
          G_CALLBACK (rb_playlist_manager_cmd_delete_playlist) },
 
163
        { "EditAutomaticPlaylist", GTK_STOCK_PROPERTIES, N_("_Edit"), NULL,
 
164
          N_("Change this automatic playlist"),
 
165
          G_CALLBACK (rb_playlist_manager_cmd_edit_automatic_playlist) },
145
166
};
 
167
static guint rb_playlist_manager_n_actions = G_N_ELEMENTS (rb_playlist_manager_actions);
146
168
 
147
169
static GObjectClass *parent_class = NULL;
148
170
 
193
215
                                                              "RBSource object",
194
216
                                                              RB_TYPE_SOURCE,
195
217
                                                              G_PARAM_READWRITE));
 
218
 
196
219
        g_object_class_install_property (object_class,
197
 
                                         PROP_WINDOW,
198
 
                                         g_param_spec_object ("window",
199
 
                                                              "window",
200
 
                                                              "toplevel window",
201
 
                                                              GTK_TYPE_WINDOW,
 
220
                                         PROP_SHELL,
 
221
                                         g_param_spec_object ("shell",
 
222
                                                              "RBShell",
 
223
                                                              "RBShell object",
 
224
                                                              RB_TYPE_SHELL,
202
225
                                                              G_PARAM_READWRITE));
203
226
 
204
 
        g_object_class_install_property (object_class,
205
 
                                         PROP_COMPONENT,
206
 
                                         g_param_spec_object ("component",
207
 
                                                              "BonoboUIComponent",
208
 
                                                              "BonoboUIComponent object",
209
 
                                                              BONOBO_TYPE_UI_COMPONENT,
210
 
                                                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
211
227
 
212
228
        g_object_class_install_property (object_class,
213
 
                                         PROP_DB,
214
 
                                         g_param_spec_object ("db",
215
 
                                                              "RhythmDB",
216
 
                                                              "RhythmDB database",
217
 
                                                              RHYTHMDB_TYPE,
218
 
                                                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
219
 
        g_object_class_install_property (object_class,
220
229
                                         PROP_LIBRARY_SOURCE,
221
230
                                         g_param_spec_object ("library_source",
222
231
                                                              "Library source",
247
256
                              g_cclosure_marshal_VOID__OBJECT,
248
257
                              G_TYPE_NONE,
249
258
                              1, G_TYPE_OBJECT);
 
259
        
 
260
        rb_playlist_manager_signals[PLAYLIST_CREATED] =
 
261
                g_signal_new ("playlist_created",
 
262
                              RB_TYPE_PLAYLIST_MANAGER,
 
263
                              G_SIGNAL_RUN_LAST,
 
264
                              G_STRUCT_OFFSET (RBPlaylistManagerClass, playlist_created),
 
265
                              NULL, NULL,
 
266
                              g_cclosure_marshal_VOID__OBJECT,
 
267
                              G_TYPE_NONE,
 
268
                              1, G_TYPE_OBJECT);
250
269
 
251
270
        rb_playlist_manager_signals[PLAYLIST_LOAD_START] =
252
271
                g_signal_new ("load_start",
329
348
        g_mutex_free (mgr->priv->saving_mutex);
330
349
        g_cond_free (mgr->priv->saving_condition);
331
350
 
332
 
        g_list_free (mgr->priv->playlists);
333
 
 
334
351
        g_free (mgr->priv);
335
352
 
336
353
        G_OBJECT_CLASS (parent_class)->finalize (object);
337
354
}
338
355
 
339
356
static void
 
357
rb_playlist_manager_set_uimanager (RBPlaylistManager *mgr, 
 
358
                                   GtkUIManager *uimanager)
 
359
{
 
360
 
 
361
        if (mgr->priv->uimanager != NULL) {
 
362
                if (mgr->priv->actiongroup != NULL) {
 
363
                        gtk_ui_manager_remove_action_group (mgr->priv->uimanager,
 
364
                                                            mgr->priv->actiongroup);
 
365
                }
 
366
                g_object_unref (G_OBJECT (mgr->priv->uimanager));
 
367
                mgr->priv->uimanager = NULL;
 
368
        }
 
369
 
 
370
        mgr->priv->uimanager = uimanager;
 
371
 
 
372
        if (mgr->priv->actiongroup == NULL) {
 
373
                mgr->priv->actiongroup = gtk_action_group_new ("PlaylistActions");
 
374
                gtk_action_group_set_translation_domain (mgr->priv->actiongroup,
 
375
                                                         GETTEXT_PACKAGE);
 
376
                gtk_action_group_add_actions (mgr->priv->actiongroup,
 
377
                                              rb_playlist_manager_actions,
 
378
                                              rb_playlist_manager_n_actions,
 
379
                                              mgr);
 
380
        }
 
381
        
 
382
        gtk_ui_manager_insert_action_group (mgr->priv->uimanager,
 
383
                                            mgr->priv->actiongroup,
 
384
                                            0);
 
385
}
 
386
 
 
387
static void
340
388
rb_playlist_manager_set_property (GObject *object,
341
389
                                  guint prop_id,
342
390
                                  const GValue *value,
349
397
        case PROP_SOURCE:
350
398
        {
351
399
                gboolean playlist_active;
 
400
                gboolean playlist_automatic = FALSE;
 
401
                gboolean playlist_local = FALSE;
 
402
                GtkAction *action;
 
403
 
 
404
                if (mgr->priv->selected_source != NULL)
 
405
                        g_signal_handlers_disconnect_by_func (G_OBJECT (rb_source_get_entry_view (mgr->priv->selected_source)),
 
406
                                                              G_CALLBACK (rb_playlist_manager_playlist_entries_changed),
 
407
                                                              mgr);
352
408
 
353
409
                mgr->priv->selected_source = g_value_get_object (value);
354
 
 
355
 
                playlist_active = g_list_find (mgr->priv->playlists,
356
 
                                               mgr->priv->selected_source) != NULL;
357
 
                rb_bonobo_set_sensitive (mgr->priv->component, CMD_PATH_PLAYLIST_SAVE,
358
 
                                         playlist_active);
359
 
                rb_bonobo_set_sensitive (mgr->priv->component, CMD_PATH_PLAYLIST_DELETE,
360
 
                                         playlist_active);
361
 
                break;
362
 
        }
363
 
        case PROP_COMPONENT:
364
 
                mgr->priv->component = g_value_get_object (value);
365
 
                bonobo_ui_component_add_verb_list_with_data (mgr->priv->component,
366
 
                                                             rb_playlist_manager_verbs,
367
 
                                                             mgr);
368
 
                break;
369
 
        case PROP_DB:
370
 
                mgr->priv->db = g_value_get_object (value);
371
 
                break;
 
410
                playlist_active = RB_IS_PLAYLIST_SOURCE (mgr->priv->selected_source);
 
411
                if (playlist_active) {
 
412
                        g_object_get (G_OBJECT (mgr->priv->selected_source), "automatic", &playlist_automatic, NULL);
 
413
                        g_object_get (G_OBJECT (mgr->priv->selected_source), "is-local", &playlist_local, NULL);
 
414
                }
 
415
 
 
416
                action = gtk_action_group_get_action (mgr->priv->actiongroup,
 
417
                                                      "MusicPlaylistSavePlaylist");
 
418
                g_object_set (G_OBJECT (action), "sensitive", playlist_local, NULL);
 
419
                action = gtk_action_group_get_action (mgr->priv->actiongroup,
 
420
                                                      "MusicPlaylistDeletePlaylist");
 
421
                g_object_set (G_OBJECT (action), "sensitive", playlist_local, NULL);
 
422
                action = gtk_action_group_get_action (mgr->priv->actiongroup,
 
423
                                                      "EditAutomaticPlaylist");
 
424
                g_object_set (G_OBJECT (action), "sensitive", playlist_automatic, NULL);
 
425
                action = gtk_action_group_get_action (mgr->priv->actiongroup,
 
426
                                                      "MusicPlaylistRenamePlaylist");
 
427
                g_object_set (G_OBJECT (action), "sensitive", playlist_local, NULL);
 
428
                {
 
429
                        gboolean recorder_active;
 
430
                        int num_tracks = rb_entry_view_get_num_entries (rb_source_get_entry_view (mgr->priv->selected_source));
 
431
 
 
432
                        recorder_active = playlist_active && rb_recorder_enabled ()
 
433
                                        && (num_tracks > 0);
 
434
                        action = gtk_action_group_get_action (mgr->priv->actiongroup, "MusicPlaylistBurnPlaylist");
 
435
                        g_object_set (G_OBJECT (action), "sensitive", recorder_active, NULL);
 
436
                        
 
437
                        if (playlist_active && rb_recorder_enabled ()) {
 
438
                                /* monitor for changes, to enable/disable the burn menu item */
 
439
                                g_signal_connect_object (G_OBJECT (rb_source_get_entry_view (mgr->priv->selected_source)),
 
440
                                                         "entry-added", G_CALLBACK (rb_playlist_manager_playlist_entries_changed), mgr, 0);
 
441
                                g_signal_connect_object (G_OBJECT (rb_source_get_entry_view (mgr->priv->selected_source)),
 
442
                                                         "entry-deleted", G_CALLBACK (rb_playlist_manager_playlist_entries_changed), mgr, 0);
 
443
                        }
 
444
                }
 
445
                break;
 
446
        }
 
447
        case PROP_SHELL:
 
448
        {
 
449
                GtkUIManager *uimanager;
 
450
                mgr->priv->shell = g_value_get_object (value);
 
451
                g_object_get (G_OBJECT (mgr->priv->shell), 
 
452
                              "ui-manager", &uimanager, 
 
453
                              "db", &mgr->priv->db,
 
454
                              NULL);
 
455
                rb_playlist_manager_set_uimanager (mgr, uimanager);
 
456
                        
 
457
                              
 
458
                break;
 
459
        }
372
460
        case PROP_SOURCELIST:
373
461
                mgr->priv->sourcelist = g_value_get_object (value);
 
462
                mgr->priv->window = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (mgr->priv->sourcelist)));
374
463
                break;
375
464
        case PROP_LIBRARY_SOURCE:
376
465
                mgr->priv->libsource = g_value_get_object (value);
378
467
        case PROP_IRADIO_SOURCE:
379
468
                mgr->priv->iradio_source = g_value_get_object (value);
380
469
                break;
381
 
        case PROP_WINDOW:
382
 
                mgr->priv->window = g_value_get_object (value);
383
 
                break;
384
470
        default:
385
471
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
386
472
                break;
400
486
        case PROP_SOURCE:
401
487
                g_value_set_object (value, mgr->priv->selected_source);
402
488
                break;
403
 
        case PROP_COMPONENT:
404
 
                g_value_set_object (value, mgr->priv->component);
405
 
                break;
406
 
        case PROP_DB:
407
 
                g_value_set_object (value, mgr->priv->db);
 
489
        case PROP_SHELL:
 
490
                g_value_set_object (value, mgr->priv->shell);
408
491
                break;
409
492
        case PROP_SOURCELIST:
410
493
                g_value_set_object (value, mgr->priv->sourcelist);
415
498
        case PROP_IRADIO_SOURCE:
416
499
                g_value_set_object (value, mgr->priv->iradio_source);
417
500
                break;
418
 
        case PROP_WINDOW:
419
 
                g_value_set_object (value, mgr->priv->window);
420
 
                break;
421
501
        default:
422
502
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
423
503
                break;
436
516
}
437
517
 
438
518
RBPlaylistManager *
439
 
rb_playlist_manager_new (BonoboUIComponent *component, GtkWindow *window,
440
 
                         RhythmDB *db, RBSourceList *sourcelist,
 
519
rb_playlist_manager_new (RBShell *shell,
 
520
                         RBSourceList *sourcelist,
441
521
                         RBLibrarySource *libsource,
442
522
                         RBIRadioSource *iradio_source)
443
523
{
444
 
        RBPlaylistManager *mgr = g_object_new (RB_TYPE_PLAYLIST_MANAGER,
445
 
                                               "component", component,
446
 
                                               "window", window,
447
 
                                               "db", db,
448
 
                                               "sourcelist", sourcelist,
449
 
                                               "library_source", libsource,
450
 
                                               "iradio_source", iradio_source,
451
 
                                               NULL);
452
 
 
453
 
        g_return_val_if_fail (mgr->priv != NULL, NULL);
454
 
 
455
 
        return mgr;
456
 
}
457
 
 
458
 
const char *
459
 
rb_playlist_manager_parse_file (RBPlaylistManager *mgr, const char *uri)
 
524
        return g_object_new (RB_TYPE_PLAYLIST_MANAGER,
 
525
                             "shell", shell,
 
526
                             "sourcelist", sourcelist,
 
527
                             "library_source", libsource,
 
528
                             "iradio_source", iradio_source,
 
529
                             NULL);
 
530
}
 
531
 
 
532
GQuark
 
533
rb_playlist_manager_error_quark (void)
 
534
{
 
535
        static GQuark quark = 0;
 
536
        if (!quark)
 
537
                quark = g_quark_from_static_string ("rb_playlist_manager_error");
 
538
 
 
539
        return quark;
 
540
}
 
541
 
 
542
static void
 
543
handle_playlist_entry_cb (TotemPlParser *playlist, const char *uri_maybe,
 
544
                          const char *title,
 
545
                          const char *genre, RBPlaylistManager *mgr)
 
546
{
 
547
        char *uri = rb_canonicalise_uri (uri_maybe);
 
548
        gint entry_type;
 
549
 
 
550
        g_return_if_fail (uri != NULL);
 
551
 
 
552
        entry_type = rb_shell_guess_type_for_uri (mgr->priv->shell, uri);
 
553
        if (entry_type < 0) {
 
554
                return;
 
555
        }
 
556
 
 
557
        rb_shell_add_uri (mgr->priv->shell,
 
558
                          entry_type,
 
559
                          uri,
 
560
                          title,
 
561
                          genre,
 
562
                          NULL);
 
563
 
 
564
        if (entry_type == RHYTHMDB_ENTRY_TYPE_SONG) {
 
565
                if (!mgr->priv->loading_playlist) {
 
566
                        mgr->priv->loading_playlist =
 
567
                                RB_PLAYLIST_SOURCE (rb_playlist_manager_new_playlist (mgr, NULL, FALSE));
 
568
                }
 
569
                rb_playlist_source_add_location (mgr->priv->loading_playlist, uri);
 
570
        }
 
571
 
 
572
        g_free (uri);
 
573
}
 
574
 
 
575
static void
 
576
playlist_load_start_cb (TotemPlParser *parser, const char *title, RBPlaylistManager *mgr)
 
577
{
 
578
        rb_debug ("loading new playlist %s", title);
 
579
 
 
580
        if (!mgr->priv->loading_playlist) {
 
581
                mgr->priv->loading_playlist =
 
582
                        RB_PLAYLIST_SOURCE (rb_playlist_manager_new_playlist (mgr, title, FALSE));
 
583
        }
 
584
}
 
585
 
 
586
static void
 
587
playlist_load_end_cb (TotemPlParser *parser, const char *title, RBPlaylistManager *mgr)
 
588
{
 
589
        rb_debug ("finished loading playlist %s", title);
 
590
        mgr->priv->loading_playlist = NULL;
 
591
}
 
592
 
 
593
gboolean
 
594
rb_playlist_manager_parse_file (RBPlaylistManager *mgr, const char *uri, GError **error)
460
595
{
461
596
        rb_debug ("loading playlist from %s", uri);
462
597
 
466
601
        g_signal_emit (G_OBJECT (mgr), rb_playlist_manager_signals[PLAYLIST_LOAD_START], 0);
467
602
 
468
603
        {
469
 
                RBPlaylist *parser = rb_playlist_new ();
 
604
                TotemPlParser *parser = totem_pl_parser_new ();
470
605
 
471
606
                g_signal_connect_object (G_OBJECT (parser), "entry",
472
 
                                         G_CALLBACK (handle_playlist_entry_into_playlist_cb),
473
 
                                         mgr, 0);
474
 
 
475
 
                if (!rb_playlist_parse (parser, uri))
476
 
                        rb_error_dialog (_("Couldn't parse playlist"));
 
607
                                         G_CALLBACK (handle_playlist_entry_cb),
 
608
                                         mgr, 0);
 
609
 
 
610
                g_signal_connect_object (G_OBJECT (parser), "playlist-start",
 
611
                                         G_CALLBACK (playlist_load_start_cb),
 
612
                                         mgr, 0);
 
613
 
 
614
                g_signal_connect_object (G_OBJECT (parser), "playlist-end",
 
615
                                         G_CALLBACK (playlist_load_end_cb),
 
616
                                         mgr, 0);
 
617
                
 
618
                if (totem_pl_parser_parse (parser, uri, FALSE) != TOTEM_PL_PARSER_RESULT_SUCCESS) {
 
619
                        g_set_error (error,
 
620
                                     RB_PLAYLIST_MANAGER_ERROR,
 
621
                                     RB_PLAYLIST_MANAGER_ERROR_PARSE,
 
622
                                     "%s",
 
623
                                     _("The playlist file may be in an unknown format or corrupted."));
 
624
                        return FALSE;
 
625
                }
477
626
                mgr->priv->loading_playlist = NULL;
478
627
 
479
628
                g_object_unref (G_OBJECT (parser));
480
629
        }
481
630
 
482
631
        g_signal_emit (G_OBJECT (mgr), rb_playlist_manager_signals[PLAYLIST_LOAD_FINISH], 0);
483
 
        return mgr->priv->firsturi;
484
 
}
485
 
 
486
 
static void
487
 
rb_playlist_manager_source_deleted_cb (RBSource *source, RBPlaylistManager *mgr)
488
 
{
489
 
        rb_debug ("removing playlist %p", source);
490
 
        mgr->priv->playlists = g_list_remove (mgr->priv->playlists, source);
 
632
        return TRUE;
491
633
}
492
634
 
493
635
static void
494
636
append_new_playlist_source (RBPlaylistManager *mgr, RBPlaylistSource *source)
495
637
{
496
 
        mgr->priv->playlists = g_list_append (mgr->priv->playlists, source);
497
 
        g_signal_connect_object (G_OBJECT (source), "deleted",
498
 
                                 G_CALLBACK (rb_playlist_manager_source_deleted_cb), mgr, 0);
499
638
        g_signal_emit (G_OBJECT (mgr), rb_playlist_manager_signals[PLAYLIST_ADDED], 0,
500
639
                       source);
501
640
}
524
663
                if (xmlNodeIsText (child))
525
664
                        continue;
526
665
 
527
 
                playlist = rb_playlist_source_new_from_xml (mgr->priv->db,
 
666
                playlist = rb_playlist_source_new_from_xml (mgr->priv->shell,
528
667
                                                            child);
529
668
                append_new_playlist_source (mgr, RB_PLAYLIST_SOURCE (playlist));
530
669
        }
551
690
        file = g_build_filename (rb_dot_dir (), "playlists.xml", NULL);
552
691
        tmpname = g_strconcat (file, ".tmp", NULL);
553
692
        
554
 
        xmlSaveFormatFile (tmpname, data->doc, 1);
555
 
        rename (tmpname, file);
 
693
        if (xmlSaveFormatFile (tmpname, data->doc, 1) != -1) {
 
694
                rename (tmpname, file);
 
695
        } else {
 
696
                rb_debug ("error in xmlSaveFormatFile(), not saving");
 
697
                unlink (tmpname);
 
698
        }
556
699
        xmlFreeDoc (data->doc);
557
700
        g_free (tmpname);
558
701
        g_free (file);
560
703
        g_mutex_lock (data->mgr->priv->saving_mutex);
561
704
 
562
705
        data->mgr->priv->saving = FALSE;
 
706
        data->mgr->priv->dirty = FALSE;
563
707
 
564
708
        g_cond_signal (data->mgr->priv->saving_condition);
565
709
        g_mutex_unlock (data->mgr->priv->saving_mutex);
571
715
        return NULL;
572
716
}
573
717
 
574
 
static void
575
 
save_source_iter_to_xml (GtkTreeModel *model, GtkTreeIter *iter,
576
 
                         xmlNodePtr root)
577
 
{
578
 
        RBSource *source;
579
 
        gtk_tree_model_get (model, iter, RB_SOURCELIST_MODEL_COLUMN_SOURCE,
580
 
                            &source, -1);
581
 
        if (RB_IS_PLAYLIST_SOURCE (source)) {
582
 
                char *name;
583
 
                g_object_get (source, "name", &name, NULL);
584
 
                rb_debug ("saving playlist %s", name);
585
 
                g_free (name);
586
 
                rb_playlist_source_save_to_xml (RB_PLAYLIST_SOURCE (source),
587
 
                                                root);
588
 
        }
589
 
}
590
 
 
591
718
void
592
719
rb_playlist_manager_save_playlists (RBPlaylistManager *mgr, gboolean force)
593
720
{
594
721
        xmlNodePtr root;
595
722
        struct RBPlaylistManagerSaveThreadData *data;
596
723
        GtkTreeIter iter;
 
724
        GtkTreeModel *fmodel;
597
725
        GtkTreeModel *model;
598
726
 
599
727
        rb_debug ("saving the playlists");
600
728
 
601
 
        if (!force && !mgr->priv->dirty) {
602
 
                rb_debug ("no save needed, ignoring");
603
 
                return;
 
729
        g_object_get (G_OBJECT (mgr->priv->sourcelist), "model", &fmodel, NULL);
 
730
        model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (fmodel));
 
731
        g_object_unref (fmodel);
 
732
        
 
733
        if (!force) {
 
734
                gboolean dirty = FALSE;
 
735
 
 
736
                if (gtk_tree_model_get_iter_first (model, &iter)) {
 
737
                        do {
 
738
                                RBSource *source;
 
739
                                gboolean local;
 
740
                                GValue v = {0,};
 
741
                                gtk_tree_model_get_value (model,
 
742
                                                          &iter,
 
743
                                                          RB_SOURCELIST_MODEL_COLUMN_SOURCE,
 
744
                                                          &v);
 
745
                                source = g_value_get_pointer (&v);
 
746
                                if (RB_IS_PLAYLIST_SOURCE (source) == FALSE)
 
747
                                        continue;
 
748
 
 
749
                                g_object_get (G_OBJECT (source), 
 
750
                                              "dirty", &dirty, 
 
751
                                              "is-local", &local, 
 
752
                                              NULL);
 
753
                                if (local && dirty) {
 
754
                                        break;
 
755
                                }
 
756
                        } while (gtk_tree_model_iter_next (model, &iter));
 
757
                }
 
758
 
 
759
                if (!dirty) {
 
760
                        /* hmm, don't like taking saving_mutex twice like this */
 
761
                        g_mutex_lock (mgr->priv->saving_mutex);
 
762
                        dirty = mgr->priv->dirty;
 
763
                        g_mutex_unlock (mgr->priv->saving_mutex);
 
764
                }
 
765
 
 
766
                if (!dirty) {
 
767
                        rb_debug ("no save needed, ignoring");
 
768
                        return;
 
769
                }
604
770
        }
605
 
 
 
771
        
606
772
        g_mutex_lock (mgr->priv->saving_mutex);
607
773
 
608
774
        while (mgr->priv->saving)
614
780
 
615
781
        data = g_new0 (struct RBPlaylistManagerSaveThreadData, 1);
616
782
        data->mgr = mgr;
617
 
        data->doc = xmlNewDoc ("1.0");
 
783
        data->doc = xmlNewDoc (RB_PLAYLIST_MGR_VERSION);
618
784
 
619
 
        root = xmlNewDocNode (data->doc, NULL, "rhythmdb-playlists", NULL);
 
785
        root = xmlNewDocNode (data->doc, NULL, RB_PLAYLIST_MGR_PL, NULL);
620
786
        xmlDocSetRootElement (data->doc, root);
621
 
 
622
 
        model = rb_sourcelist_get_model (mgr->priv->sourcelist);
 
787
        
623
788
        if (gtk_tree_model_get_iter_first (model, &iter)) {
624
789
                do {
625
 
                        save_source_iter_to_xml (model, &iter, root);
 
790
                        RBSource *source;
 
791
                        GValue v = {0,};
 
792
                        gboolean local;
 
793
 
 
794
                        gtk_tree_model_get_value (model,
 
795
                                                  &iter,
 
796
                                                  RB_SOURCELIST_MODEL_COLUMN_SOURCE,
 
797
                                                  &v);
 
798
                        source = g_value_get_pointer (&v);
 
799
                        if (RB_IS_PLAYLIST_SOURCE (source) == FALSE)
 
800
                                continue;
 
801
 
 
802
                        g_object_get (G_OBJECT (source), "is-local", &local, 
 
803
                                      NULL);
 
804
                        if (local) {
 
805
 
 
806
                                rb_playlist_source_save_to_xml (RB_PLAYLIST_SOURCE (source), root);
 
807
                        }
626
808
                } while (gtk_tree_model_iter_next (model, &iter));
627
809
        }
628
810
 
642
824
 
643
825
RBSource *
644
826
rb_playlist_manager_new_playlist (RBPlaylistManager *mgr,
645
 
                                  const char *suggested_name, gboolean automatic)
 
827
                                  const char *suggested_name, 
 
828
                                  gboolean automatic)
646
829
{
647
 
        RBSource *playlist = RB_SOURCE (rb_playlist_source_new (mgr->priv->db, automatic));
648
 
        GTimeVal serial;
649
 
        char *internal;
650
 
 
651
 
 
652
 
        g_get_current_time (&serial);
653
 
        internal = g_strdup_printf ("<playlist:%ld:%ld>", serial.tv_sec,
654
 
                                    serial.tv_usec);
 
830
        RBSource *playlist = RB_SOURCE (rb_playlist_source_new (mgr->priv->shell, 
 
831
                                                                automatic, 
 
832
                                                                TRUE, 
 
833
                                                                RHYTHMDB_ENTRY_TYPE_SONG));
655
834
        
656
835
        g_object_set (G_OBJECT (playlist),
657
836
                      "name", suggested_name ? suggested_name : "",
658
 
                      "internal-name", internal,
659
837
                      NULL);
660
 
        g_free (internal);
661
838
        append_new_playlist_source (mgr, RB_PLAYLIST_SOURCE (playlist));
662
839
        rb_sourcelist_edit_source_name (mgr->priv->sourcelist, playlist);
663
840
        rb_playlist_manager_set_dirty (mgr);
 
841
        
 
842
        g_signal_emit (G_OBJECT (mgr), rb_playlist_manager_signals[PLAYLIST_CREATED], 0,
 
843
                       playlist);
664
844
 
665
845
        return playlist;
666
846
}
667
847
 
 
848
GList *
 
849
rb_playlist_manager_get_playlists (RBPlaylistManager *mgr)
 
850
{
 
851
        GList *playlists = NULL;
 
852
        GtkTreeIter iter;
 
853
        GtkTreeModel *fmodel;
 
854
        GtkTreeModel *model;
 
855
        
 
856
        g_object_get (G_OBJECT (mgr->priv->sourcelist), "model", &fmodel, NULL);
 
857
        model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (fmodel));
 
858
        g_object_unref (fmodel);
 
859
        
 
860
        if (gtk_tree_model_get_iter_first (model, &iter)) {
 
861
                do {
 
862
                        RBSource *source;
 
863
                        GValue v = {0,};
 
864
                        gboolean local;
 
865
 
 
866
                        gtk_tree_model_get_value (model,
 
867
                                                  &iter,
 
868
                                                  RB_SOURCELIST_MODEL_COLUMN_SOURCE,
 
869
                                                  &v);
 
870
                        source = g_value_get_pointer (&v);
 
871
                        if (RB_IS_PLAYLIST_SOURCE (source) == FALSE)
 
872
                                continue;
 
873
                        g_object_get (G_OBJECT (source), "is-local", &local, 
 
874
                                      NULL);
 
875
                        if (local) {
 
876
                                playlists = g_list_prepend (playlists, source);
 
877
                        }
 
878
 
 
879
                } while (gtk_tree_model_iter_next (model, &iter));
 
880
        }
 
881
        
 
882
        return playlists;
 
883
}
 
884
 
668
885
static void
669
 
rb_playlist_manager_cmd_new_playlist (BonoboUIComponent *component,
670
 
                                      RBPlaylistManager *mgr,
671
 
                                      const char *verbname)
 
886
rb_playlist_manager_cmd_new_playlist (GtkAction *action,
 
887
                                      RBPlaylistManager *mgr)
672
888
{
673
889
        rb_playlist_manager_new_playlist (mgr, NULL, FALSE);
674
890
}
679
895
                                            RBQueryCreator *creator)
680
896
{
681
897
        RBQueryCreatorLimitType type;
682
 
        guint limit, limit_count = 0, limit_size = 0;
 
898
        guint limit, limit_count = 0, limit_size = 0, limit_time = 0;
 
899
        const char *sort_key;
 
900
        gint sort_direction;
683
901
 
684
902
        rb_query_creator_get_limit (creator, &type, &limit);
685
903
        if (type == RB_QUERY_CREATOR_LIMIT_COUNT)
686
904
                limit_count = limit;
687
905
        else if (type == RB_QUERY_CREATOR_LIMIT_MB)
688
906
                limit_size = limit;
 
907
        else if (type == RB_QUERY_CREATOR_LIMIT_SECONDS)
 
908
                limit_time = limit;
 
909
        else
 
910
                g_assert_not_reached ();
 
911
 
 
912
        rb_query_creator_get_sort_order (creator, &sort_key, &sort_direction);
 
913
 
689
914
        rb_playlist_source_set_query (playlist,
690
915
                                      rb_query_creator_get_query (creator),
691
 
                                      limit_count, limit_size);
 
916
                                      limit_count, limit_size, limit_time,
 
917
                                      sort_key, sort_direction);
692
918
}
693
919
 
694
920
static void
695
 
rb_playlist_manager_cmd_new_automatic_playlist (BonoboUIComponent *component,
696
 
                                                RBPlaylistManager *mgr,
697
 
                                                const char *verbname)
 
921
rb_playlist_manager_cmd_new_automatic_playlist (GtkAction *action,
 
922
                                                RBPlaylistManager *mgr)
698
923
{
699
924
        RBQueryCreator *creator = RB_QUERY_CREATOR (rb_query_creator_new (mgr->priv->db));
700
925
        RBSource *playlist;
717
942
}
718
943
 
719
944
static void
720
 
rb_playlist_manager_cmd_edit_automatic_playlist (BonoboUIComponent *component,
721
 
                                                 RBPlaylistManager *mgr,
722
 
                                                 const char *verbname)
 
945
rb_playlist_manager_cmd_edit_automatic_playlist (GtkAction *action,
 
946
                                                 RBPlaylistManager *mgr)
723
947
{
724
948
        RBQueryCreator *creator;
725
949
        RBPlaylistSource *playlist;
726
950
        GPtrArray *query;
727
 
        guint limit_count = 0, limit_size = 0;
 
951
        guint limit_count = 0, limit_size = 0, limit_time = 0;
 
952
        const char *sort_key;
 
953
        gint sort_direction;
728
954
        
729
955
 
730
956
        playlist = RB_PLAYLIST_SOURCE (mgr->priv->selected_source);
731
 
        rb_playlist_source_get_query (playlist, &query, &limit_count, &limit_size);
 
957
        rb_playlist_source_get_query (playlist, &query, &limit_count, &limit_size, &limit_time, &sort_key, &sort_direction);
732
958
 
733
959
        creator = RB_QUERY_CREATOR (rb_query_creator_new_from_query (mgr->priv->db,
734
960
                                                                     query,
735
 
                                                                     limit_count,
736
 
                                                                     limit_size));      
 
961
                                                                     limit_count, limit_size, limit_time,
 
962
                                                                     sort_key, sort_direction));
737
963
 
738
964
        gtk_dialog_run (GTK_DIALOG (creator));
739
965
 
742
968
}
743
969
 
744
970
static void
745
 
rb_playlist_manager_cmd_delete_playlist (BonoboUIComponent *component,
746
 
                                         RBPlaylistManager *mgr,
747
 
                                         const char *verbname)
 
971
rb_playlist_manager_cmd_rename_playlist (GtkAction *action,
 
972
                                         RBPlaylistManager *mgr)
 
973
{
 
974
        rb_debug ("Renaming playlist %p", mgr->priv->selected_source);
 
975
 
 
976
        rb_sourcelist_edit_source_name (mgr->priv->sourcelist, mgr->priv->selected_source);
 
977
        rb_playlist_manager_set_dirty (mgr);
 
978
}
 
979
 
 
980
static void
 
981
rb_playlist_manager_cmd_delete_playlist (GtkAction *action,
 
982
                                         RBPlaylistManager *mgr)
748
983
{
749
984
        rb_debug ("Deleting playlist %p", mgr->priv->selected_source);
750
985
        
758
993
                           RBPlaylistManager *mgr)
759
994
{
760
995
        char *escaped_file = NULL;
 
996
        GError *error = NULL;
761
997
 
762
 
        if (response_id != GTK_RESPONSE_OK) {
 
998
        if (response_id != GTK_RESPONSE_ACCEPT) {
763
999
                gtk_widget_destroy (GTK_WIDGET (dialog));
764
1000
                return;
765
1001
        }
766
1002
 
767
 
#ifndef HAVE_GTK_2_3
768
 
        {
769
 
        char *file = NULL;
770
 
        file = g_strdup (gtk_file_selection_get_filename (GTK_FILE_SELECTION (dialog)));
771
 
        escaped_file = gnome_vfs_get_uri_from_local_path (file);
772
 
        g_free (file);
773
 
        }
774
 
#else
775
1003
        escaped_file = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (dialog));
776
 
#endif
777
1004
 
778
1005
        gtk_widget_destroy (GTK_WIDGET (dialog));
779
1006
 
780
1007
        if (escaped_file == NULL)
781
1008
                return;
782
1009
 
783
 
        rb_playlist_manager_parse_file (mgr, escaped_file);
 
1010
        if (!rb_playlist_manager_parse_file (mgr, escaped_file, &error)) {
 
1011
                rb_error_dialog (NULL, _("Couldn't read playlist"),
 
1012
                                 error->message);
 
1013
                g_error_free (error);
 
1014
        }
 
1015
 
784
1016
        g_free (escaped_file);
785
1017
        rb_playlist_manager_set_dirty (mgr);
786
1018
}
787
1019
 
788
1020
static void
789
 
rb_playlist_manager_cmd_load_playlist (BonoboUIComponent *component,
790
 
                                       RBPlaylistManager *mgr,
791
 
                                       const char *verbname)
 
1021
rb_playlist_manager_cmd_load_playlist (GtkAction *action,
 
1022
                                       RBPlaylistManager *mgr)
792
1023
{
793
1024
        GtkWidget *dialog;
794
1025
 
795
 
        dialog = rb_ask_file (_("Load playlist"), NULL,
796
 
                              GTK_WINDOW (mgr->priv->window));
 
1026
        dialog = rb_file_chooser_new (_("Load Playlist"),
 
1027
                                      GTK_WINDOW (mgr->priv->window),
 
1028
                                      GTK_FILE_CHOOSER_ACTION_OPEN,
 
1029
                                      TRUE);
797
1030
 
798
1031
        g_signal_connect_object (G_OBJECT (dialog), "response",
799
1032
                                 G_CALLBACK (load_playlist_response_cb), mgr, 0);
804
1037
                           int response_id,
805
1038
                           RBPlaylistManager *mgr)
806
1039
{
807
 
        char *file;
 
1040
        char *file = NULL;
808
1041
 
809
 
        if (response_id != GTK_RESPONSE_OK) {
 
1042
        if (response_id != GTK_RESPONSE_ACCEPT) {
810
1043
                gtk_widget_destroy (GTK_WIDGET (dialog));
811
1044
                return;
812
1045
        }
813
1046
 
814
 
#ifndef HAVE_GTK_2_3
815
 
        file = g_strdup (gtk_file_selection_get_filename (GTK_FILE_SELECTION (dialog)));
816
 
#else
817
1047
        file = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (dialog));
818
 
#endif
819
1048
 
820
1049
        gtk_widget_destroy (GTK_WIDGET (dialog));
821
1050
 
827
1056
}
828
1057
 
829
1058
static void
830
 
rb_playlist_manager_cmd_save_playlist (BonoboUIComponent *component,
831
 
                                       RBPlaylistManager *mgr,
832
 
                                       const char *verbname)
 
1059
rb_playlist_manager_cmd_save_playlist (GtkAction *action,
 
1060
                                       RBPlaylistManager *mgr)
833
1061
{
834
1062
        GtkWidget *dialog;
835
1063
    
836
 
        dialog = rb_ask_file_save (_("Save playlist"), NULL,
837
 
                                   GTK_WINDOW (mgr->priv->window));
 
1064
        dialog = rb_file_chooser_new (_("Save Playlist"),
 
1065
                                      GTK_WINDOW (mgr->priv->window),
 
1066
                                      GTK_FILE_CHOOSER_ACTION_SAVE,
 
1067
                                      TRUE);
838
1068
 
839
1069
        g_signal_connect_object (G_OBJECT (dialog), "response",
840
1070
                                 G_CALLBACK (save_playlist_response_cb),
842
1072
}
843
1073
 
844
1074
static void
845
 
add_uri_to_playlist (RBPlaylistManager *mgr, RBPlaylistSource *playlist, const char *uri, const char *title)
 
1075
rb_playlist_manager_cmd_burn_playlist (GtkAction *action,
 
1076
                                       RBPlaylistManager *mgr)
846
1077
{
847
 
        GError *error = NULL;
848
 
        GnomeVFSURI *vfsuri = gnome_vfs_uri_new (uri);
849
 
        const char *scheme = gnome_vfs_uri_get_scheme (vfsuri);
850
 
 
851
 
        if (rb_uri_is_iradio (scheme)) {
852
 
                rb_iradio_source_add_station (mgr->priv->iradio_source, uri, title, NULL);
853
 
                goto out;
854
 
        }
855
 
 
856
 
        rhythmdb_add_song (mgr->priv->db, uri, &error);
857
 
        if (error) {
858
 
                rb_debug ("error loading URI %s", uri);
859
 
                goto out; /* FIXME */
860
 
        }
861
 
 
862
 
        rb_playlist_source_add_location (playlist, uri);
863
 
out:
864
 
        gnome_vfs_uri_unref (vfsuri);
 
1078
        rb_playlist_source_burn_playlist (RB_PLAYLIST_SOURCE (mgr->priv->selected_source));
865
1079
}
866
1080
 
867
1081
static void
868
 
handle_playlist_entry_into_playlist_cb (RBPlaylist *playlist, const char *uri_maybe,
869
 
                                        const char *title,
870
 
                                        const char *genre, RBPlaylistManager *mgr)
 
1082
rb_playlist_manager_playlist_entries_changed (RBEntryView *entry_view, RhythmDBEntry *entry, RBPlaylistManager *mgr)
871
1083
{
872
 
        char *uri;
873
 
 
874
 
        if (uri_maybe[0] == '/') {
875
 
                uri = gnome_vfs_get_uri_from_local_path (uri_maybe);
876
 
                if (uri == NULL) {
877
 
                        rb_debug ("Error processing absolute filename: %s", uri_maybe);
878
 
                        return;
879
 
                }
880
 
        } else {
881
 
                GnomeVFSURI *vfsuri = gnome_vfs_uri_new (uri_maybe);
882
 
                if (!vfsuri) {
883
 
                        rb_debug ("Error processing probable URI: %s", uri_maybe);
884
 
                        return;
885
 
                }
886
 
                uri = gnome_vfs_uri_to_string (vfsuri, GNOME_VFS_URI_HIDE_NONE);
887
 
                gnome_vfs_uri_unref (vfsuri);
888
 
        }
889
 
        
890
 
        if (!mgr->priv->firsturi)
891
 
                mgr->priv->firsturi = g_strdup (uri);
892
 
        if (rb_uri_is_iradio (uri)) {
893
 
                rb_iradio_source_add_station (mgr->priv->iradio_source,
894
 
                                              uri, title, genre);
895
 
                g_free (uri);
896
 
                return;
897
 
        }
898
 
 
899
 
        if (!mgr->priv->loading_playlist) {
900
 
                mgr->priv->loading_playlist =
901
 
                        RB_PLAYLIST_SOURCE (rb_playlist_manager_new_playlist (mgr, NULL, FALSE));
902
 
        }
903
 
        add_uri_to_playlist (mgr, mgr->priv->loading_playlist, uri, title);
904
 
        g_free (uri);
 
1084
        int num_tracks = rb_entry_view_get_num_entries (entry_view);
 
1085
        GtkAction *action = gtk_action_group_get_action (mgr->priv->actiongroup, "MusicPlaylistBurnPlaylist");
 
1086
 
 
1087
        g_object_set (G_OBJECT (action), "sensitive", (num_tracks > 0), NULL);
905
1088
}