1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * arch-tag: Implementation of playlist source object
5 * Copyright (C) 2002 Jorn Baayen <jorn@nl.linux.org>
6 * Copyright (C) 2003 Colin Walters <walters@gnome.org>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
29 #include <libxml/tree.h>
30 #include <glib/gi18n.h>
32 #include <libgnomevfs/gnome-vfs-uri.h>
33 #include <totem-pl-parser.h>
35 #include "rb-entry-view.h"
36 #include "rb-search-entry.h"
37 #include "rb-file-helpers.h"
38 #include "rb-preferences.h"
39 #include "rb-dialog.h"
41 #include "rb-playlist-source.h"
43 #include "eel-gconf-extensions.h"
44 #include "rb-song-info.h"
46 #include "rb-playlist-xml.h"
47 #include "rb-static-playlist-source.h"
48 #include "rb-auto-playlist-source.h"
50 static void rb_playlist_source_class_init (RBPlaylistSourceClass
*klass
);
51 static void rb_playlist_source_init (RBPlaylistSource
*source
);
52 static GObject
*rb_playlist_source_constructor (GType type
,
53 guint n_construct_properties
,
54 GObjectConstructParam
*construct_properties
);
55 static void rb_playlist_source_dispose (GObject
*object
);
56 static void rb_playlist_source_finalize (GObject
*object
);
57 static void rb_playlist_source_set_property (GObject
*object
,
61 static void rb_playlist_source_get_property (GObject
*object
,
67 static char *impl_get_browser_key (RBSource
*source
);
68 static RBEntryView
*impl_get_entry_view (RBSource
*source
);
69 static void impl_song_properties (RBSource
*source
);
70 static gboolean
impl_show_popup (RBSource
*source
);
72 static void rb_playlist_source_songs_show_popup_cb (RBEntryView
*view
,
74 RBPlaylistSource
*playlist_view
);
75 static void rb_playlist_source_drop_cb (GtkWidget
*widget
,
76 GdkDragContext
*context
,
79 GtkSelectionData
*data
,
84 static void rb_playlist_source_row_deleted (GtkTreeModel
*model
,
86 RBPlaylistSource
*playlist
);
87 static void default_show_entry_view_popup (RBPlaylistSource
*source
,
90 static void rb_playlist_source_entry_added_cb (RhythmDB
*db
, RhythmDBEntry
*entry
,
91 RBPlaylistSource
*source
);
92 static void rb_playlist_source_track_cell_data_func (GtkTreeViewColumn
*column
, GtkCellRenderer
*renderer
,
93 GtkTreeModel
*tree_model
, GtkTreeIter
*iter
,
94 RBPlaylistSource
*source
);
96 #define PLAYLIST_SOURCE_SONGS_POPUP_PATH "/PlaylistViewPopup"
97 #define PLAYLIST_SOURCE_POPUP_PATH "/PlaylistSourcePopup"
99 struct RBPlaylistSourcePrivate
105 RhythmDBQueryModel
*model
;
111 gboolean dispose_has_run
;
116 #define RB_PLAYLIST_SOURCE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), RB_TYPE_PLAYLIST_SOURCE, RBPlaylistSourcePrivate))
126 static const GtkTargetEntry target_uri
[] = { { "text/uri-list", 0, 0 } };
128 G_DEFINE_ABSTRACT_TYPE (RBPlaylistSource
, rb_playlist_source
, RB_TYPE_SOURCE
);
131 rb_playlist_source_class_init (RBPlaylistSourceClass
*klass
)
133 GObjectClass
*object_class
= G_OBJECT_CLASS (klass
);
134 RBSourceClass
*source_class
= RB_SOURCE_CLASS (klass
);
136 object_class
->dispose
= rb_playlist_source_dispose
;
137 object_class
->finalize
= rb_playlist_source_finalize
;
138 object_class
->constructor
= rb_playlist_source_constructor
;
140 object_class
->set_property
= rb_playlist_source_set_property
;
141 object_class
->get_property
= rb_playlist_source_get_property
;
143 source_class
->impl_get_browser_key
= impl_get_browser_key
;
144 source_class
->impl_get_entry_view
= impl_get_entry_view
;
145 source_class
->impl_can_rename
= (RBSourceFeatureFunc
) rb_true_function
;
146 source_class
->impl_can_search
= (RBSourceFeatureFunc
) rb_false_function
;
147 source_class
->impl_can_cut
= (RBSourceFeatureFunc
) rb_false_function
;
148 source_class
->impl_can_copy
= (RBSourceFeatureFunc
) rb_true_function
;
149 source_class
->impl_can_delete
= (RBSourceFeatureFunc
) rb_false_function
;
150 source_class
->impl_can_add_to_queue
= (RBSourceFeatureFunc
) rb_true_function
;
151 source_class
->impl_can_move_to_trash
= (RBSourceFeatureFunc
) rb_true_function
;
152 source_class
->impl_song_properties
= impl_song_properties
;
153 source_class
->impl_can_pause
= (RBSourceFeatureFunc
) rb_true_function
;
154 source_class
->impl_show_popup
= impl_show_popup
;
156 klass
->impl_show_entry_view_popup
= default_show_entry_view_popup
;
158 g_object_class_install_property (object_class
,
160 g_param_spec_object ("db",
165 g_object_class_install_property (object_class
,
167 g_param_spec_boolean ("dirty",
169 "whether this playlist should be saved",
172 g_object_class_install_property (object_class
,
174 g_param_spec_boolean ("is-local",
176 "whether this playlist is attached to the local library",
178 G_PARAM_READWRITE
| G_PARAM_CONSTRUCT_ONLY
));
180 g_type_class_add_private (klass
, sizeof (RBPlaylistSourcePrivate
));
184 rb_playlist_source_init (RBPlaylistSource
*source
)
186 source
->priv
= RB_PLAYLIST_SOURCE_GET_PRIVATE (source
);
190 rb_playlist_source_set_db (RBPlaylistSource
*source
,
193 if (source
->priv
->db
!= NULL
) {
194 g_signal_handlers_disconnect_by_func (source
->priv
->db
,
195 rb_playlist_source_entry_added_cb
,
197 g_object_unref (source
->priv
->db
);
201 source
->priv
->db
= db
;
203 if (source
->priv
->db
!= NULL
) {
204 g_object_ref (source
->priv
->db
);
205 g_signal_connect_object (G_OBJECT (source
->priv
->db
), "entry_added",
206 G_CALLBACK (rb_playlist_source_entry_added_cb
),
213 rb_playlist_source_constructor (GType type
,
214 guint n_construct_properties
,
215 GObjectConstructParam
*construct_properties
)
217 GObject
*shell_player
;
218 RBPlaylistSource
*source
;
219 RBPlaylistSourceClass
*klass
;
222 RhythmDBQueryModel
*query_model
;
224 klass
= RB_PLAYLIST_SOURCE_CLASS (g_type_class_peek (RB_TYPE_PLAYLIST_SOURCE
));
226 source
= RB_PLAYLIST_SOURCE (G_OBJECT_CLASS (rb_playlist_source_parent_class
)->
227 constructor (type
, n_construct_properties
, construct_properties
));
229 g_object_get (source
, "shell", &shell
, NULL
);
230 g_object_get (shell
, "db", &db
, NULL
);
231 shell_player
= rb_shell_get_player (shell
);
232 rb_playlist_source_set_db (source
, db
);
234 g_object_unref (shell
);
236 source
->priv
->entries
= g_hash_table_new_full (rb_refstring_hash
, rb_refstring_equal
,
237 (GDestroyNotify
)rb_refstring_unref
, NULL
);
239 source
->priv
->songs
= rb_entry_view_new (source
->priv
->db
,
243 query_model
= rhythmdb_query_model_new_empty (source
->priv
->db
);
244 rb_playlist_source_set_query_model (source
, query_model
);
245 g_object_unref (query_model
);
248 const char *title
= "";
249 const char *strings
[3] = {0};
251 GtkTreeViewColumn
*column
= gtk_tree_view_column_new ();
252 GtkCellRenderer
*renderer
= gtk_cell_renderer_text_new ();
254 g_object_set(renderer
,
255 "style", PANGO_STYLE_OBLIQUE
,
256 "weight", PANGO_WEIGHT_LIGHT
,
260 gtk_tree_view_column_pack_start (column
, renderer
, TRUE
);
262 gtk_tree_view_column_set_resizable (column
, TRUE
);
263 gtk_tree_view_column_set_sizing (column
, GTK_TREE_VIEW_COLUMN_FIXED
);
267 rb_entry_view_set_fixed_column_width (source
->priv
->songs
, column
, renderer
,
269 gtk_tree_view_column_set_cell_data_func (column
, renderer
,
270 (GtkTreeCellDataFunc
)
271 rb_playlist_source_track_cell_data_func
,
273 rb_entry_view_insert_column_custom (source
->priv
->songs
, column
, title
,
274 "PlaylistTrack", NULL
, 0, 0);
277 rb_entry_view_append_column (source
->priv
->songs
, RB_ENTRY_VIEW_COL_TRACK_NUMBER
, FALSE
);
278 rb_entry_view_append_column (source
->priv
->songs
, RB_ENTRY_VIEW_COL_TITLE
, TRUE
);
279 rb_entry_view_append_column (source
->priv
->songs
, RB_ENTRY_VIEW_COL_GENRE
, FALSE
);
280 rb_entry_view_append_column (source
->priv
->songs
, RB_ENTRY_VIEW_COL_ARTIST
, FALSE
);
281 rb_entry_view_append_column (source
->priv
->songs
, RB_ENTRY_VIEW_COL_ALBUM
, FALSE
);
282 rb_entry_view_append_column (source
->priv
->songs
, RB_ENTRY_VIEW_COL_YEAR
, FALSE
);
283 rb_entry_view_append_column (source
->priv
->songs
, RB_ENTRY_VIEW_COL_DURATION
, FALSE
);
284 rb_entry_view_append_column (source
->priv
->songs
, RB_ENTRY_VIEW_COL_QUALITY
, FALSE
);
285 rb_entry_view_append_column (source
->priv
->songs
, RB_ENTRY_VIEW_COL_RATING
, FALSE
);
286 rb_entry_view_append_column (source
->priv
->songs
, RB_ENTRY_VIEW_COL_PLAY_COUNT
, FALSE
);
287 rb_entry_view_append_column (source
->priv
->songs
, RB_ENTRY_VIEW_COL_LAST_PLAYED
, FALSE
);
288 rb_entry_view_append_column (source
->priv
->songs
, RB_ENTRY_VIEW_COL_FIRST_SEEN
, FALSE
);
289 rb_entry_view_set_columns_clickable (source
->priv
->songs
, FALSE
);
291 rb_playlist_source_setup_entry_view (source
, source
->priv
->songs
);
293 gtk_container_add (GTK_CONTAINER (source
), GTK_WIDGET (source
->priv
->songs
));
295 gtk_widget_show_all (GTK_WIDGET (source
));
297 return G_OBJECT (source
);
301 rb_playlist_source_dispose (GObject
*object
)
303 RBPlaylistSource
*source
= RB_PLAYLIST_SOURCE (object
);
305 if (source
->priv
->dispose_has_run
) {
306 /* If dispose did already run, return. */
307 rb_debug ("Dispose has already run for playlist source %p", object
);
310 /* Make sure dispose does not run twice. */
311 source
->priv
->dispose_has_run
= TRUE
;
313 rb_debug ("Disposing playlist source %p", source
);
315 if (source
->priv
->db
!= NULL
) {
316 g_object_unref (source
->priv
->db
);
317 source
->priv
->db
= NULL
;
320 if (source
->priv
->model
!= NULL
) {
321 g_object_unref (source
->priv
->model
);
324 G_OBJECT_CLASS (rb_playlist_source_parent_class
)->dispose (object
);
328 rb_playlist_source_finalize (GObject
*object
)
330 RBPlaylistSource
*source
;
332 g_return_if_fail (object
!= NULL
);
333 g_return_if_fail (RB_IS_PLAYLIST_SOURCE (object
));
335 source
= RB_PLAYLIST_SOURCE (object
);
336 g_return_if_fail (source
->priv
!= NULL
);
338 rb_debug ("Finalizing playlist source %p", source
);
340 g_hash_table_destroy (source
->priv
->entries
);
342 g_free (source
->priv
->title
);
345 G_OBJECT_CLASS (rb_playlist_source_parent_class
)->finalize (object
);
349 rb_playlist_source_set_property (GObject
*object
,
354 RBPlaylistSource
*source
= RB_PLAYLIST_SOURCE (object
);
358 source
->priv
->is_local
= g_value_get_boolean (value
);
361 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
367 rb_playlist_source_get_property (GObject
*object
,
372 RBPlaylistSource
*source
= RB_PLAYLIST_SOURCE (object
);
376 g_value_set_object (value
, source
->priv
->db
);
379 g_value_set_boolean (value
, source
->priv
->dirty
);
382 g_value_set_boolean (value
, source
->priv
->is_local
);
385 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
391 default_show_entry_view_popup (RBPlaylistSource
*source
,
396 _rb_source_show_popup (RB_SOURCE (source
), PLAYLIST_SOURCE_SONGS_POPUP_PATH
);
400 rb_playlist_source_songs_show_popup_cb (RBEntryView
*view
,
402 RBPlaylistSource
*source
)
404 RBPlaylistSourceClass
*klass
= RB_PLAYLIST_SOURCE_GET_CLASS (source
);
405 if (klass
->impl_show_entry_view_popup
)
406 klass
->impl_show_entry_view_popup (source
, view
, over_entry
);
410 impl_get_browser_key (RBSource
*source
)
416 impl_get_entry_view (RBSource
*asource
)
418 RBPlaylistSource
*source
= RB_PLAYLIST_SOURCE (asource
);
420 return source
->priv
->songs
;
424 impl_song_properties (RBSource
*asource
)
426 RBPlaylistSource
*source
= RB_PLAYLIST_SOURCE (asource
);
427 GtkWidget
*song_info
= NULL
;
429 g_return_if_fail (source
->priv
->songs
!= NULL
);
431 song_info
= rb_song_info_new (asource
, NULL
);
433 gtk_widget_show_all (song_info
);
435 rb_debug ("failed to create dialog, or no selection!");
439 impl_show_popup (RBSource
*asource
)
441 _rb_source_show_popup (asource
, PLAYLIST_SOURCE_POPUP_PATH
);
446 rb_playlist_source_drop_cb (GtkWidget
*widget
,
447 GdkDragContext
*context
,
450 GtkSelectionData
*data
,
455 RBPlaylistSource
*source
= RB_PLAYLIST_SOURCE (user_data
);
456 GtkTargetList
*tlist
;
459 tlist
= gtk_target_list_new (target_uri
, G_N_ELEMENTS (target_uri
));
460 target
= gtk_drag_dest_find_target (widget
, context
, tlist
);
461 gtk_target_list_unref (tlist
);
463 if (target
== GDK_NONE
)
466 rb_source_receive_drag (RB_SOURCE (source
), data
);
468 gtk_drag_finish (context
, TRUE
, FALSE
, time
);
471 #ifndef TOTEM_PL_PARSER_CHECK_VERSION
473 playlist_iter_func (GtkTreeModel
*model
,
479 RhythmDBEntry
*entry
;
481 gtk_tree_model_get (model
, iter
, 0, &entry
, -1);
484 *uri
= rhythmdb_entry_dup_string (entry
, RHYTHMDB_PROP_LOCATION
);
487 *title
= rhythmdb_entry_dup_string (entry
, RHYTHMDB_PROP_TITLE
);
491 rhythmdb_entry_unref (entry
);
496 playlist_iter_func (GtkTreeModel
*model
,
500 gboolean
*custom_title
,
503 RhythmDBEntry
*entry
;
505 gtk_tree_model_get (model
, iter
, 0, &entry
, -1);
508 *uri
= rhythmdb_entry_dup_string (entry
, RHYTHMDB_PROP_LOCATION
);
511 *title
= rhythmdb_entry_dup_string (entry
, RHYTHMDB_PROP_TITLE
);
513 if (custom_title
!= NULL
) {
514 *custom_title
= FALSE
;
518 rhythmdb_entry_unref (entry
);
521 #endif /* TOTEM_PL_PARSER_CHECK_VERSION */
524 rb_playlist_source_save_playlist (RBPlaylistSource
*source
,
528 TotemPlParser
*playlist
;
529 GError
*error
= NULL
;
532 g_return_if_fail (RB_IS_PLAYLIST_SOURCE (source
));
534 rb_debug ("saving playlist");
535 playlist
= totem_pl_parser_new ();
537 g_object_get (source
, "name", &name
, NULL
);
539 totem_pl_parser_write_with_title (playlist
, GTK_TREE_MODEL (source
->priv
->model
),
540 playlist_iter_func
, uri
, name
,
541 m3u_format
? TOTEM_PL_PARSER_M3U
: TOTEM_PL_PARSER_PLS
,
545 rb_error_dialog (NULL
, _("Couldn't save playlist"),
546 "%s", error
->message
);
549 /* Adapted from yelp-toc-pager.c */
551 xml_get_and_trim_names (xmlNodePtr node
)
553 xmlNodePtr cur
, keep
= NULL
;
554 xmlChar
*keep_lang
= NULL
;
556 int j
, keep_pri
= INT_MAX
;
558 const gchar
* const * langs
= g_get_language_names ();
562 for (cur
= node
->children
; cur
; cur
= cur
->next
) {
563 if (! xmlStrcmp (cur
->name
, RB_PLAYLIST_NAME
)) {
564 xmlChar
*cur_lang
= NULL
;
565 int cur_pri
= INT_MAX
;
567 cur_lang
= xmlNodeGetLang (cur
);
570 for (j
= 0; langs
[j
]; j
++) {
571 if (g_str_equal (cur_lang
, langs
[j
])) {
577 cur_pri
= INT_MAX
- 1;
580 if (cur_pri
<= keep_pri
) {
586 value
= xmlNodeGetContent (cur
);
588 keep_lang
= cur_lang
;
598 /* Delete all RB_PLAYLIST_NAME nodes */
599 cur
= node
->children
;
601 xmlNodePtr
this = cur
;
603 if (! xmlStrcmp (this->name
, RB_PLAYLIST_NAME
)) {
604 xmlUnlinkNode (this);
613 get_playlist_name_from_xml (xmlNodePtr node
)
617 /* try to get and trim elements */
618 name
= xml_get_and_trim_names (node
);
624 /* try the attribute */
625 name
= xmlGetProp (node
, RB_PLAYLIST_NAME
);
631 rb_playlist_source_new_from_xml (RBShell
*shell
,
634 RBSource
*source
= NULL
;
638 g_return_val_if_fail (RB_IS_SHELL (shell
), NULL
);
640 /* Try to get name from XML and remove translated names */
641 name
= get_playlist_name_from_xml (node
);
643 tmp
= xmlGetProp (node
, RB_PLAYLIST_TYPE
);
645 if (!xmlStrcmp (tmp
, RB_PLAYLIST_AUTOMATIC
))
646 source
= rb_auto_playlist_source_new_from_xml (shell
, node
);
647 else if (!xmlStrcmp (tmp
, RB_PLAYLIST_STATIC
))
648 source
= rb_static_playlist_source_new_from_xml (shell
, node
);
649 else if (!xmlStrcmp (tmp
, RB_PLAYLIST_QUEUE
)) {
650 RBStaticPlaylistSource
*queue
;
652 g_object_get (shell
, "queue-source", &queue
, NULL
);
653 rb_static_playlist_source_load_from_xml (queue
, node
);
654 g_object_unref (queue
);
656 g_warning ("attempting to load playlist '%s' of unknown type '%s'", name
, tmp
);
659 if (source
!= NULL
) {
660 g_object_set (G_OBJECT (source
), "name", name
, NULL
);
670 rb_playlist_source_save_to_xml (RBPlaylistSource
*source
,
671 xmlNodePtr parent_node
)
675 RBPlaylistSourceClass
*klass
= RB_PLAYLIST_SOURCE_GET_CLASS (source
);
677 g_return_if_fail (RB_IS_PLAYLIST_SOURCE (source
));
679 node
= xmlNewChild (parent_node
, NULL
, RB_PLAYLIST_PLAYLIST
, NULL
);
680 g_object_get (source
, "name", &name
, NULL
);
681 xmlSetProp (node
, RB_PLAYLIST_NAME
, name
);
684 klass
->impl_save_contents_to_xml (source
, node
);
686 source
->priv
->dirty
= FALSE
;
690 rb_playlist_source_row_deleted (GtkTreeModel
*model
,
692 RBPlaylistSource
*source
)
694 RhythmDBEntry
*entry
;
695 RBRefString
*location
;
697 entry
= rhythmdb_query_model_tree_path_to_entry (RHYTHMDB_QUERY_MODEL (model
),
700 location
= rhythmdb_entry_get_refstring (entry
, RHYTHMDB_PROP_LOCATION
);
701 if (g_hash_table_remove (source
->priv
->entries
, location
))
702 source
->priv
->dirty
= TRUE
;
704 rb_refstring_unref (location
);
705 rhythmdb_entry_unref (entry
);
709 rb_playlist_source_entry_added_cb (RhythmDB
*db
,
710 RhythmDBEntry
*entry
,
711 RBPlaylistSource
*source
)
713 RBRefString
*location
;
715 location
= rhythmdb_entry_get_refstring (entry
, RHYTHMDB_PROP_LOCATION
);
717 if (g_hash_table_lookup (source
->priv
->entries
, location
)) {
718 rhythmdb_query_model_add_entry (source
->priv
->model
, entry
, -1);
719 source
->priv
->dirty
= TRUE
;
722 rb_refstring_unref (location
);
726 rb_playlist_source_track_cell_data_func (GtkTreeViewColumn
*column
,
727 GtkCellRenderer
*renderer
,
728 GtkTreeModel
*tree_model
,
730 RBPlaylistSource
*source
)
735 gtk_tree_model_get (tree_model
, iter
, 1, &val
, -1);
738 str
= g_strdup_printf ("%d", val
);
742 g_object_set (G_OBJECT (renderer
), "text", str
, NULL
);
747 rb_playlist_source_setup_entry_view (RBPlaylistSource
*source
,
748 RBEntryView
*entry_view
)
750 g_return_if_fail (RB_IS_PLAYLIST_SOURCE (source
));
752 g_signal_connect_object (entry_view
, "show_popup",
753 G_CALLBACK (rb_playlist_source_songs_show_popup_cb
), source
, 0);
754 g_signal_connect_object (entry_view
, "drag_data_received",
755 G_CALLBACK (rb_playlist_source_drop_cb
), source
, 0);
756 gtk_drag_dest_set (GTK_WIDGET (entry_view
),
757 GTK_DEST_DEFAULT_ALL
,
759 G_N_ELEMENTS (target_uri
),
764 rb_playlist_source_set_query_model (RBPlaylistSource
*source
,
765 RhythmDBQueryModel
*model
)
767 g_return_if_fail (RB_IS_PLAYLIST_SOURCE (source
));
769 if (source
->priv
->model
!= NULL
) {
770 /* if the query model is replaced, the set of entries in
771 * the playlist will change, so we should mark the playlist dirty.
773 source
->priv
->dirty
= TRUE
;
774 g_signal_handlers_disconnect_by_func (source
->priv
->model
,
775 G_CALLBACK (rb_playlist_source_row_deleted
),
777 g_object_unref (source
->priv
->model
);
780 source
->priv
->model
= model
;
782 if (source
->priv
->model
!= NULL
) {
783 g_object_ref (source
->priv
->model
);
784 g_signal_connect_object (source
->priv
->model
, "row_deleted",
785 G_CALLBACK (rb_playlist_source_row_deleted
), source
, 0);
788 rb_entry_view_set_model (source
->priv
->songs
, RHYTHMDB_QUERY_MODEL (source
->priv
->model
));
790 g_object_set (source
, "query-model", source
->priv
->model
, NULL
);
794 rb_playlist_source_get_db (RBPlaylistSource
*source
)
796 g_return_val_if_fail (RB_IS_PLAYLIST_SOURCE (source
), NULL
);
798 return source
->priv
->db
;
802 rb_playlist_source_get_query_model (RBPlaylistSource
*source
)
804 g_return_val_if_fail (RB_IS_PLAYLIST_SOURCE (source
), NULL
);
806 return source
->priv
->model
;
810 rb_playlist_source_mark_dirty (RBPlaylistSource
*source
)
812 g_return_if_fail (RB_IS_PLAYLIST_SOURCE (source
));
814 source
->priv
->dirty
= TRUE
;
818 rb_playlist_source_location_in_map (RBPlaylistSource
*source
,
819 const char *location
)
824 g_return_val_if_fail (RB_IS_PLAYLIST_SOURCE (source
), FALSE
);
826 refstr
= rb_refstring_find (location
);
827 if (refstr
== NULL
) {
831 found
= (g_hash_table_lookup (source
->priv
->entries
, refstr
) != NULL
);
832 rb_refstring_unref (refstr
);
838 rb_playlist_source_add_to_map (RBPlaylistSource
*source
,
839 const char *location
)
843 g_return_val_if_fail (RB_IS_PLAYLIST_SOURCE (source
), FALSE
);
845 refstr
= rb_refstring_new (location
);
846 if (g_hash_table_lookup (source
->priv
->entries
, refstr
)) {
847 rb_refstring_unref (refstr
);
851 g_hash_table_insert (source
->priv
->entries
,
852 refstr
, GINT_TO_POINTER (1));