1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3
* Copyright (C) 2002 Jorn Baayen <jorn@nl.linux.org>
4
* Copyright (C) 2003 Colin Walters <walters@gnome.org>
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24
#include <libgnome/gnome-i18n.h>
25
#include <libgnomevfs/gnome-vfs-uri.h>
26
#include <libxml/tree.h>
28
#include "rb-static-playlist-source.h"
31
#include "rb-stock-icons.h"
32
#include "rb-file-helpers.h"
33
#include "rb-playlist-xml.h"
35
static GObject *rb_static_playlist_source_constructor (GType type, guint n_construct_properties,
36
GObjectConstructParam *construct_properties);
39
static GdkPixbuf *impl_get_pixbuf (RBSource *source);
40
static GList * impl_cut (RBSource *source);
41
static void impl_paste (RBSource *asource, GList *entries);
42
static void impl_delete (RBSource *source);
43
static gboolean impl_receive_drag (RBSource *source, GtkSelectionData *data);
45
/* playlist methods */
46
static void impl_save_contents_to_xml (RBPlaylistSource *source,
50
static void rb_static_playlist_source_add_list_uri (RBStaticPlaylistSource *source,
52
static void rb_static_playlist_source_row_inserted (GtkTreeModel *model,
55
RBStaticPlaylistSource *source);
56
static void rb_static_playlist_source_non_entry_dropped (GtkTreeModel *model,
59
RBStaticPlaylistSource *source);
61
G_DEFINE_TYPE (RBStaticPlaylistSource, rb_static_playlist_source, RB_TYPE_PLAYLIST_SOURCE)
64
rb_static_playlist_source_class_init (RBStaticPlaylistSourceClass *klass)
67
GObjectClass *object_class = G_OBJECT_CLASS (klass);
68
RBSourceClass *source_class = RB_SOURCE_CLASS (klass);
69
RBPlaylistSourceClass *playlist_class = RB_PLAYLIST_SOURCE_CLASS (klass);
71
object_class->constructor = rb_static_playlist_source_constructor;
73
source_class->impl_can_cut = (RBSourceFeatureFunc) rb_true_function;
74
source_class->impl_can_copy = (RBSourceFeatureFunc) rb_true_function;
75
source_class->impl_can_delete = (RBSourceFeatureFunc) rb_true_function;
76
source_class->impl_cut = impl_cut;
77
source_class->impl_paste = impl_paste;
78
source_class->impl_delete = impl_delete;
79
source_class->impl_get_pixbuf = impl_get_pixbuf;
80
source_class->impl_receive_drag = impl_receive_drag;
82
playlist_class->impl_save_contents_to_xml = impl_save_contents_to_xml;
84
gtk_icon_size_lookup (GTK_ICON_SIZE_LARGE_TOOLBAR, &size, NULL);
85
klass->pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
92
rb_static_playlist_source_init (RBStaticPlaylistSource *source)
97
rb_static_playlist_source_constructor (GType type, guint n_construct_properties,
98
GObjectConstructParam *construct_properties)
100
GObjectClass *parent_class = G_OBJECT_CLASS (rb_static_playlist_source_parent_class);
101
RBStaticPlaylistSource *source = RB_STATIC_PLAYLIST_SOURCE (
102
parent_class->constructor (type, n_construct_properties, construct_properties));
103
RhythmDBQueryModel *model = rb_playlist_source_get_query_model (RB_PLAYLIST_SOURCE (source));
105
/* watch these to find out when things are dropped into the entry view */
106
g_signal_connect_object (G_OBJECT (model), "row-inserted",
107
G_CALLBACK (rb_static_playlist_source_row_inserted),
109
g_signal_connect_object (G_OBJECT (model), "non-entry-dropped",
110
G_CALLBACK (rb_static_playlist_source_non_entry_dropped),
113
return G_OBJECT (source);
117
rb_static_playlist_source_new (RBShell *shell, const char *name, gboolean local, RhythmDBEntryType entry_type)
122
return RB_SOURCE (g_object_new (RB_TYPE_STATIC_PLAYLIST_SOURCE,
126
"entry-type", entry_type,
131
rb_static_playlist_source_new_from_xml (RBShell *shell, xmlNodePtr node)
133
RBSource *psource = rb_static_playlist_source_new (shell,
136
RHYTHMDB_ENTRY_TYPE_SONG);
137
RBStaticPlaylistSource *source = RB_STATIC_PLAYLIST_SOURCE (psource);
140
for (child = node->children; child; child = child->next) {
143
if (xmlNodeIsText (child))
146
if (xmlStrcmp (child->name, RB_PLAYLIST_LOCATION))
149
location = xmlNodeGetContent (child);
150
rb_static_playlist_source_add_location (source,
151
(char *) location, -1);
154
return RB_SOURCE (source);
158
impl_get_pixbuf (RBSource *asource)
160
RBStaticPlaylistSourceClass *klass = RB_STATIC_PLAYLIST_SOURCE_GET_CLASS (asource);
161
return klass->pixbuf;
166
impl_cut (RBSource *asource)
168
RBStaticPlaylistSource *source = RB_STATIC_PLAYLIST_SOURCE (asource);
169
RBEntryView *songs = rb_source_get_entry_view (asource);
170
GList *sel = rb_entry_view_get_selected_entries (songs);
173
for (tem = sel; tem; tem = tem->next)
174
rb_static_playlist_source_remove_entry (source, (RhythmDBEntry *) tem->data);
180
impl_paste (RBSource *asource, GList *entries)
182
RBStaticPlaylistSource *source = RB_STATIC_PLAYLIST_SOURCE (asource);
184
for (; entries; entries = g_list_next (entries))
185
rb_static_playlist_source_add_entry (source, entries->data, -1);
189
impl_delete (RBSource *asource)
191
RBEntryView *songs = rb_source_get_entry_view (asource);
192
RBStaticPlaylistSource *source = RB_STATIC_PLAYLIST_SOURCE (asource);
195
sel = rb_entry_view_get_selected_entries (songs);
196
for (tem = sel; tem != NULL; tem = tem->next) {
197
rb_static_playlist_source_remove_entry (source, (RhythmDBEntry *) tem->data);
203
impl_receive_drag (RBSource *asource, GtkSelectionData *data)
206
RBStaticPlaylistSource *source = RB_STATIC_PLAYLIST_SOURCE (asource);
208
if (data->type == gdk_atom_intern ("text/uri-list", TRUE)) {
209
list = gnome_vfs_uri_list_parse ((char *) data->data);
212
rb_static_playlist_source_add_list_uri (source, list);
221
impl_save_contents_to_xml (RBPlaylistSource *source,
225
RhythmDBQueryModel *model = rb_playlist_source_get_query_model (source);
227
xmlSetProp (node, RB_PLAYLIST_TYPE, RB_PLAYLIST_STATIC);
229
if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (model), &iter))
233
xmlNodePtr child_node = xmlNewChild (node, NULL, RB_PLAYLIST_LOCATION, NULL);
234
RhythmDBEntry *entry;
237
gtk_tree_model_get (GTK_TREE_MODEL (model), &iter, 0, &entry, -1);
239
encoded = xmlEncodeEntitiesReentrant (NULL, BAD_CAST entry->location);
241
xmlNodeSetContent (child_node, encoded);
243
} while (gtk_tree_model_iter_next (GTK_TREE_MODEL (model), &iter));
247
rb_static_playlist_source_add_list_uri (RBStaticPlaylistSource *source,
250
GList *i, *uri_list = NULL;
251
RBPlaylistSource *psource = RB_PLAYLIST_SOURCE (source);
253
g_return_if_fail (list != NULL);
255
for (i = list; i != NULL; i = g_list_next (i))
256
uri_list = g_list_prepend (uri_list, gnome_vfs_uri_to_string ((const GnomeVFSURI *) i->data, 0));
257
uri_list = g_list_reverse (uri_list);
259
gnome_vfs_uri_list_free (list);
261
if (uri_list == NULL)
264
for (i = uri_list; i != NULL; i = i->next) {
267
rhythmdb_add_uri (rb_playlist_source_get_db (psource), uri);
268
rb_static_playlist_source_add_location (source, uri, -1);
273
g_list_free (uri_list);
277
rb_static_playlist_source_add_location_internal (RBStaticPlaylistSource *source,
278
const char *location,
282
RhythmDBEntry *entry;
283
RBPlaylistSource *psource = RB_PLAYLIST_SOURCE (source);
284
if (rb_playlist_source_location_in_map (psource, location))
287
db = rb_playlist_source_get_db (psource);
288
entry = rhythmdb_entry_lookup_by_location (db, location);
290
RhythmDBQueryModel *model = rb_playlist_source_get_query_model (psource);
291
RhythmDBEntryType entry_type;
293
g_object_get (G_OBJECT (source), "entry-type", &entry_type, NULL);
294
if (entry_type != -1 &&
295
rhythmdb_entry_get_ulong (entry, RHYTHMDB_PROP_TYPE) != entry_type) {
296
rb_debug ("attempting to add an entry of the wrong type to playlist");
300
rhythmdb_entry_ref (db, entry);
301
rhythmdb_query_model_add_entry (model, entry, index);
302
rhythmdb_entry_unref (db, entry);
305
rb_playlist_source_add_to_map (psource, location);
307
rb_playlist_source_mark_dirty (psource);
311
rb_static_playlist_source_add_location_swapped (const char *uri,
312
RBStaticPlaylistSource *source)
314
rb_static_playlist_source_add_location_internal (source, uri, -1);
319
rb_static_playlist_source_add_location (RBStaticPlaylistSource *source,
320
const char *location,
324
RhythmDBEntry *entry;
326
db = rb_playlist_source_get_db (RB_PLAYLIST_SOURCE (source));
327
entry = rhythmdb_entry_lookup_by_location (db, location);
329
/* if there is an entry, it won't be a directory */
330
if (entry == NULL && rb_uri_is_directory (location))
331
rb_uri_handle_recursively (location,
332
(GFunc) rb_static_playlist_source_add_location_swapped,
336
rb_static_playlist_source_add_location_internal (source, location, index);
341
rb_static_playlist_source_add_locations (RBStaticPlaylistSource *source,
346
for (l = locations; l; l = l->next) {
347
const gchar *uri = (const gchar *)l->data;
348
rb_static_playlist_source_add_location (source, uri, -1);
353
rb_static_playlist_source_remove_location (RBStaticPlaylistSource *source,
354
const char *location)
356
RBPlaylistSource *psource = RB_PLAYLIST_SOURCE (source);
358
RhythmDBEntry *entry;
360
g_return_if_fail (rb_playlist_source_location_in_map (psource, location));
362
db = rb_playlist_source_get_db (psource);
363
entry = rhythmdb_entry_lookup_by_location (db, location);
366
RhythmDBQueryModel *model = rb_playlist_source_get_query_model (psource);
368
/* if this fails, the model and the playlist are out of sync */
369
g_assert (rhythmdb_query_model_remove_entry (model, entry));
370
rb_playlist_source_mark_dirty (psource);
375
rb_static_playlist_source_add_entry (RBStaticPlaylistSource *source,
376
RhythmDBEntry *entry,
379
rb_static_playlist_source_add_location_internal (source, entry->location, index);
383
rb_static_playlist_source_remove_entry (RBStaticPlaylistSource *source,
384
RhythmDBEntry *entry)
386
rb_static_playlist_source_remove_location (source, entry->location);
390
rb_static_playlist_source_move_entry (RBStaticPlaylistSource *source,
391
RhythmDBEntry *entry,
394
RBPlaylistSource *psource = RB_PLAYLIST_SOURCE (source);
395
RhythmDBQueryModel *model = rb_playlist_source_get_query_model (psource);
396
rhythmdb_query_model_move_entry (model, entry, index);
398
rb_playlist_source_mark_dirty (psource);
403
rb_static_playlist_source_non_entry_dropped (GtkTreeModel *model,
406
RBStaticPlaylistSource *source)
408
g_assert (g_utf8_strlen (uri, -1) > 0);
410
rhythmdb_add_uri (rb_playlist_source_get_db (RB_PLAYLIST_SOURCE (source)), uri);
411
rb_static_playlist_source_add_location (source, uri, position);
415
rb_static_playlist_source_row_inserted (GtkTreeModel *model,
418
RBStaticPlaylistSource *source)
420
RhythmDBEntry *entry;
422
gtk_tree_model_get (model, iter, 0, &entry, -1);
424
rb_static_playlist_source_add_entry (source, entry, -1);