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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
26 #include <libxml/tree.h>
27 #include <glib/gi18n.h>
29 #include <libgnomevfs/gnome-vfs-uri.h>
31 #include "rb-static-playlist-source.h"
32 #include "rb-library-browser.h"
35 #include "rb-stock-icons.h"
36 #include "rb-file-helpers.h"
37 #include "rb-playlist-xml.h"
39 static GObject
*rb_static_playlist_source_constructor (GType type
, guint n_construct_properties
,
40 GObjectConstructParam
*construct_properties
);
41 static void rb_static_playlist_source_dispose (GObject
*object
);
42 static void rb_static_playlist_source_finalize (GObject
*object
);
45 static GList
* impl_cut (RBSource
*source
);
46 static void impl_paste (RBSource
*asource
, GList
*entries
);
47 static void impl_delete (RBSource
*source
);
48 static void impl_search (RBSource
*asource
, const char *search_text
);
49 static void impl_browser_toggled (RBSource
*source
, gboolean enabled
);
50 static void impl_reset_filters (RBSource
*asource
);
51 static gboolean
impl_receive_drag (RBSource
*source
, GtkSelectionData
*data
);
52 static GList
*impl_get_search_actions (RBSource
*source
);
53 static guint
impl_want_uri (RBSource
*source
, const char *uri
);
55 static GPtrArray
*construct_query_from_selection (RBStaticPlaylistSource
*source
);
57 /* playlist methods */
58 static void impl_save_contents_to_xml (RBPlaylistSource
*source
,
62 static GList
*impl_get_property_views (RBSource
*source
);
63 void rb_static_playlist_source_browser_views_activated_cb (GtkWidget
*widget
,
64 RBStaticPlaylistSource
*source
);
65 static void rb_static_playlist_source_browser_changed_cb (RBLibraryBrowser
*entry
,
67 RBStaticPlaylistSource
*source
);
69 static void rb_static_playlist_source_do_query (RBStaticPlaylistSource
*source
);
71 static void rb_static_playlist_source_add_id_list (RBStaticPlaylistSource
*source
,
73 static void rb_static_playlist_source_add_uri_list (RBStaticPlaylistSource
*source
,
75 static void rb_static_playlist_source_row_inserted (GtkTreeModel
*model
,
78 RBStaticPlaylistSource
*source
);
79 static void rb_static_playlist_source_non_entry_dropped (GtkTreeModel
*model
,
82 RBStaticPlaylistSource
*source
);
84 static void search_action_changed (GtkRadioAction
*action
,
85 GtkRadioAction
*current
,
88 static GtkRadioActionEntry rb_static_playlist_source_radio_actions
[] =
90 { "StaticPlaylistSearchAll", NULL
, N_("All"), NULL
, N_("Search all fields"), 0 },
91 { "StaticPlaylistSearchArtists", NULL
, N_("Artists"), NULL
, N_("Search artists"), 1 },
92 { "StaticPlaylistSearchAlbums", NULL
, N_("Albums"), NULL
, N_("Search albums"), 2 },
93 { "StaticPlaylistSearchTitles", NULL
, N_("Titles"), NULL
, N_("Search titles"), 3 }
96 G_DEFINE_TYPE (RBStaticPlaylistSource
, rb_static_playlist_source
, RB_TYPE_PLAYLIST_SOURCE
)
97 #define RB_STATIC_PLAYLIST_SOURCE_GET_PRIVATE(object) (G_TYPE_INSTANCE_GET_PRIVATE ((object), \
98 RB_TYPE_STATIC_PLAYLIST_SOURCE, \
99 RBStaticPlaylistSourcePrivate))
103 RhythmDBQueryModel
*base_model
;
104 RhythmDBQueryModel
*filter_model
;
107 RBLibraryBrowser
*browser
;
108 gboolean browser_shown
;
112 GtkActionGroup
*action_group
;
113 RhythmDBPropType search_prop
;
114 gboolean dispose_has_run
;
115 } RBStaticPlaylistSourcePrivate
;
117 static gpointer playlist_pixbuf
= NULL
;
120 rb_static_playlist_source_class_init (RBStaticPlaylistSourceClass
*klass
)
122 GObjectClass
*object_class
= G_OBJECT_CLASS (klass
);
123 RBSourceClass
*source_class
= RB_SOURCE_CLASS (klass
);
124 RBPlaylistSourceClass
*playlist_class
= RB_PLAYLIST_SOURCE_CLASS (klass
);
126 object_class
->constructor
= rb_static_playlist_source_constructor
;
127 object_class
->dispose
= rb_static_playlist_source_dispose
;
128 object_class
->finalize
= rb_static_playlist_source_finalize
;
130 source_class
->impl_can_cut
= (RBSourceFeatureFunc
) rb_true_function
;
131 source_class
->impl_can_paste
= (RBSourceFeatureFunc
) rb_true_function
;
132 source_class
->impl_can_delete
= (RBSourceFeatureFunc
) rb_true_function
;
133 source_class
->impl_cut
= impl_cut
;
134 source_class
->impl_paste
= impl_paste
;
135 source_class
->impl_delete
= impl_delete
;
136 source_class
->impl_receive_drag
= impl_receive_drag
;
137 source_class
->impl_can_search
= (RBSourceFeatureFunc
) rb_true_function
;
138 source_class
->impl_search
= impl_search
;
139 source_class
->impl_reset_filters
= impl_reset_filters
;
140 source_class
->impl_can_browse
= (RBSourceFeatureFunc
) rb_true_function
;
141 source_class
->impl_browser_toggled
= impl_browser_toggled
;
142 source_class
->impl_get_property_views
= impl_get_property_views
;
143 source_class
->impl_get_search_actions
= impl_get_search_actions
;
144 source_class
->impl_want_uri
= impl_want_uri
;
146 playlist_class
->impl_save_contents_to_xml
= impl_save_contents_to_xml
;
148 g_type_class_add_private (klass
, sizeof (RBStaticPlaylistSourcePrivate
));
152 rb_static_playlist_source_init (RBStaticPlaylistSource
*source
)
154 if (playlist_pixbuf
== NULL
) {
156 gtk_icon_size_lookup (GTK_ICON_SIZE_LARGE_TOOLBAR
, &size
, NULL
);
157 playlist_pixbuf
= gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
158 GNOME_MEDIA_PLAYLIST
,
161 if (playlist_pixbuf
) {
162 g_object_add_weak_pointer (playlist_pixbuf
,
163 (gpointer
*) &playlist_pixbuf
);
165 rb_source_set_pixbuf (RB_SOURCE (source
), playlist_pixbuf
);
167 /* drop the initial reference to the icon */
168 g_object_unref (playlist_pixbuf
);
171 rb_source_set_pixbuf (RB_SOURCE (source
), playlist_pixbuf
);
176 rb_static_playlist_source_dispose (GObject
*object
)
178 RBStaticPlaylistSourcePrivate
*priv
= RB_STATIC_PLAYLIST_SOURCE_GET_PRIVATE (object
);
180 if (priv
->dispose_has_run
) {
181 /* If dispose did already run, return. */
182 rb_debug ("Dispose has already run for static playlist source %p", object
);
185 /* Make sure dispose does not run twice. */
186 priv
->dispose_has_run
= TRUE
;
188 rb_debug ("Disposing static playlist source %p", object
);
190 if (priv
->base_model
!= NULL
) {
191 g_object_unref (priv
->base_model
);
192 priv
->base_model
= NULL
;
195 if (priv
->filter_model
!= NULL
) {
196 g_object_unref (priv
->filter_model
);
199 G_OBJECT_CLASS (rb_static_playlist_source_parent_class
)->dispose (object
);
203 rb_static_playlist_source_finalize (GObject
*object
)
205 RBStaticPlaylistSourcePrivate
*priv
= RB_STATIC_PLAYLIST_SOURCE_GET_PRIVATE (object
);
207 rb_debug ("Finalizing static playlist source %p", object
);
209 g_free (priv
->search_text
);
211 if (priv
->action_group
!= NULL
) {
212 g_object_unref (priv
->action_group
);
215 G_OBJECT_CLASS (rb_static_playlist_source_parent_class
)->finalize (object
);
219 rb_static_playlist_source_constructor (GType type
,
220 guint n_construct_properties
,
221 GObjectConstructParam
*construct_properties
)
223 GObjectClass
*parent_class
= G_OBJECT_CLASS (rb_static_playlist_source_parent_class
);
224 RBStaticPlaylistSource
*source
= RB_STATIC_PLAYLIST_SOURCE (
225 parent_class
->constructor (type
, n_construct_properties
, construct_properties
));
226 RBStaticPlaylistSourcePrivate
*priv
= RB_STATIC_PLAYLIST_SOURCE_GET_PRIVATE (source
);
227 RBPlaylistSource
*psource
= RB_PLAYLIST_SOURCE (source
);
230 RhythmDBEntryType entry_type
;
232 priv
->base_model
= rb_playlist_source_get_query_model (RB_PLAYLIST_SOURCE (psource
));
233 g_object_set (priv
->base_model
, "show-hidden", TRUE
, NULL
);
234 g_object_ref (priv
->base_model
);
236 priv
->paned
= gtk_vpaned_new ();
238 g_object_get (source
, "shell", &shell
, NULL
);
239 priv
->action_group
= _rb_source_register_action_group (RB_SOURCE (source
),
240 "StaticPlaylistActions",
243 gtk_action_group_add_radio_actions (priv
->action_group
,
244 rb_static_playlist_source_radio_actions
,
245 G_N_ELEMENTS (rb_static_playlist_source_radio_actions
),
247 (GCallback
)search_action_changed
,
249 priv
->search_prop
= RHYTHMDB_PROP_SEARCH_MATCH
;
251 g_object_unref (shell
);
253 g_object_get (source
, "entry-type", &entry_type
, NULL
);
254 priv
->browser
= rb_library_browser_new (rb_playlist_source_get_db (RB_PLAYLIST_SOURCE (source
)),
256 g_boxed_free (RHYTHMDB_TYPE_ENTRY_TYPE
, entry_type
);
257 gtk_paned_pack1 (GTK_PANED (priv
->paned
), GTK_WIDGET (priv
->browser
), TRUE
, FALSE
);
258 g_signal_connect_object (priv
->browser
, "notify::output-model",
259 G_CALLBACK (rb_static_playlist_source_browser_changed_cb
),
262 rb_library_browser_set_model (priv
->browser
, priv
->base_model
, FALSE
);
263 rb_static_playlist_source_do_query (source
);
265 /* reparent the entry view */
266 songs
= rb_source_get_entry_view (RB_SOURCE (source
));
267 g_object_ref (songs
);
268 gtk_container_remove (GTK_CONTAINER (source
), GTK_WIDGET (songs
));
269 gtk_paned_pack2 (GTK_PANED (priv
->paned
), GTK_WIDGET (songs
), TRUE
, FALSE
);
270 gtk_container_add (GTK_CONTAINER (source
), priv
->paned
);
271 g_object_unref (songs
);
273 /* watch these to find out when things are dropped into the entry view */
274 g_signal_connect_object (priv
->base_model
, "row-inserted",
275 G_CALLBACK (rb_static_playlist_source_row_inserted
),
277 g_signal_connect_object (priv
->base_model
, "non-entry-dropped",
278 G_CALLBACK (rb_static_playlist_source_non_entry_dropped
),
281 gtk_widget_show_all (GTK_WIDGET (source
));
283 return G_OBJECT (source
);
287 rb_static_playlist_source_new (RBShell
*shell
, const char *name
, gboolean local
, RhythmDBEntryType entry_type
)
292 return RB_SOURCE (g_object_new (RB_TYPE_STATIC_PLAYLIST_SOURCE
,
296 "entry-type", entry_type
,
297 "sourcelist-group", RB_SOURCELIST_GROUP_PERSISTANT
,
302 rb_static_playlist_source_load_from_xml (RBStaticPlaylistSource
*source
, xmlNodePtr node
)
306 for (child
= node
->children
; child
; child
= child
->next
) {
309 if (xmlNodeIsText (child
))
312 if (xmlStrcmp (child
->name
, RB_PLAYLIST_LOCATION
))
315 location
= xmlNodeGetContent (child
);
316 rb_static_playlist_source_add_location (source
,
317 (char *) location
, -1);
323 rb_static_playlist_source_new_from_xml (RBShell
*shell
, xmlNodePtr node
)
325 RBSource
*psource
= rb_static_playlist_source_new (shell
,
328 RHYTHMDB_ENTRY_TYPE_SONG
);
329 RBStaticPlaylistSource
*source
= RB_STATIC_PLAYLIST_SOURCE (psource
);
331 rb_static_playlist_source_load_from_xml (source
, node
);
333 return RB_SOURCE (source
);
337 impl_cut (RBSource
*asource
)
339 RBStaticPlaylistSource
*source
= RB_STATIC_PLAYLIST_SOURCE (asource
);
340 RBEntryView
*songs
= rb_source_get_entry_view (asource
);
341 GList
*sel
= rb_entry_view_get_selected_entries (songs
);
344 for (tem
= sel
; tem
; tem
= tem
->next
)
345 rb_static_playlist_source_remove_entry (source
, (RhythmDBEntry
*) tem
->data
);
351 impl_paste (RBSource
*asource
, GList
*entries
)
353 RBStaticPlaylistSource
*source
= RB_STATIC_PLAYLIST_SOURCE (asource
);
355 for (; entries
; entries
= g_list_next (entries
))
356 rb_static_playlist_source_add_entry (source
, entries
->data
, -1);
360 impl_delete (RBSource
*asource
)
362 RBEntryView
*songs
= rb_source_get_entry_view (asource
);
363 RBStaticPlaylistSource
*source
= RB_STATIC_PLAYLIST_SOURCE (asource
);
366 sel
= rb_entry_view_get_selected_entries (songs
);
367 for (tem
= sel
; tem
!= NULL
; tem
= tem
->next
) {
368 rb_static_playlist_source_remove_entry (source
, (RhythmDBEntry
*) tem
->data
);
370 g_list_foreach (sel
, (GFunc
)rhythmdb_entry_unref
, NULL
);
375 impl_reset_filters (RBSource
*source
)
377 RBStaticPlaylistSourcePrivate
*priv
= RB_STATIC_PLAYLIST_SOURCE_GET_PRIVATE (source
);
378 gboolean changed
= FALSE
;
380 if (rb_library_browser_reset (priv
->browser
))
383 if (priv
->search_text
!= NULL
) {
385 g_free (priv
->search_text
);
386 priv
->search_text
= NULL
;
390 rb_static_playlist_source_do_query (RB_STATIC_PLAYLIST_SOURCE (source
));
391 rb_source_notify_filter_changed (source
);
396 impl_search (RBSource
*source
, const char *search_text
)
398 RBStaticPlaylistSourcePrivate
*priv
= RB_STATIC_PLAYLIST_SOURCE_GET_PRIVATE (source
);
399 char *old_search_text
= NULL
;
401 if (search_text
!= NULL
&& search_text
[0] == '\0')
404 if (search_text
== NULL
&& priv
->search_text
== NULL
)
406 if (search_text
!= NULL
&& priv
->search_text
!= NULL
407 && !strcmp (search_text
, priv
->search_text
))
410 old_search_text
= priv
->search_text
;
411 if (search_text
== NULL
) {
412 priv
->search_text
= NULL
;
414 priv
->search_text
= g_strdup (search_text
);
416 g_free (old_search_text
);
418 rb_debug ("doing search for \"%s\"", priv
->search_text
? priv
->search_text
: "(NULL)");
420 rb_static_playlist_source_do_query (RB_STATIC_PLAYLIST_SOURCE (source
));
424 impl_get_property_views (RBSource
*source
)
426 RBStaticPlaylistSourcePrivate
*priv
= RB_STATIC_PLAYLIST_SOURCE_GET_PRIVATE (source
);
429 ret
= rb_library_browser_get_property_views (priv
->browser
);
434 impl_browser_toggled (RBSource
*source
, gboolean enabled
)
436 RBStaticPlaylistSourcePrivate
*priv
= RB_STATIC_PLAYLIST_SOURCE_GET_PRIVATE (source
);
438 priv
->browser_shown
= enabled
;
441 gtk_widget_show (GTK_WIDGET (priv
->browser
));
443 gtk_widget_hide (GTK_WIDGET (priv
->browser
));
447 construct_query_from_selection (RBStaticPlaylistSource
*source
)
449 RBStaticPlaylistSourcePrivate
*priv
= RB_STATIC_PLAYLIST_SOURCE_GET_PRIVATE (source
);
450 RBPlaylistSource
*psource
= RB_PLAYLIST_SOURCE (source
);
451 RhythmDB
*db
= rb_playlist_source_get_db (RB_PLAYLIST_SOURCE (psource
));
452 GPtrArray
*query
= NULL
;
454 query
= g_ptr_array_new();
456 if (priv
->search_text
) {
457 rhythmdb_query_append (db
,
459 RHYTHMDB_QUERY_PROP_LIKE
, priv
->search_prop
, priv
->search_text
,
467 rb_static_playlist_source_do_query (RBStaticPlaylistSource
*source
)
469 RBStaticPlaylistSourcePrivate
*priv
= RB_STATIC_PLAYLIST_SOURCE_GET_PRIVATE (source
);
470 RBPlaylistSource
*psource
= RB_PLAYLIST_SOURCE (source
);
471 RhythmDB
*db
= rb_playlist_source_get_db (psource
);
474 if (priv
->filter_model
!= NULL
) {
475 g_object_unref (priv
->filter_model
);
477 priv
->filter_model
= rhythmdb_query_model_new_empty (db
);
478 g_object_set (priv
->filter_model
, "base-model", priv
->base_model
, NULL
);
480 query
= construct_query_from_selection (source
);
481 g_object_set (priv
->filter_model
, "query", query
, NULL
);
482 rhythmdb_query_free (query
);
484 rhythmdb_query_model_reapply_query (priv
->filter_model
, TRUE
);
485 rb_library_browser_set_model (priv
->browser
, priv
->filter_model
, FALSE
);
489 rb_static_playlist_source_browser_changed_cb (RBLibraryBrowser
*browser
,
491 RBStaticPlaylistSource
*source
)
493 RBEntryView
*songs
= rb_source_get_entry_view (RB_SOURCE (source
));
494 RhythmDBQueryModel
*query_model
;
496 g_object_get (browser
, "output-model", &query_model
, NULL
);
497 rb_entry_view_set_model (songs
, query_model
);
498 rb_playlist_source_set_query_model (RB_PLAYLIST_SOURCE (source
), query_model
);
499 g_object_unref (query_model
);
501 rb_source_notify_filter_changed (RB_SOURCE (source
));
505 impl_receive_drag (RBSource
*asource
, GtkSelectionData
*data
)
508 RBStaticPlaylistSource
*source
= RB_STATIC_PLAYLIST_SOURCE (asource
);
510 if (data
->type
== gdk_atom_intern ("text/uri-list", TRUE
) ||
511 data
->type
== gdk_atom_intern ("application/x-rhythmbox-entry", TRUE
)) {
512 list
= rb_uri_list_parse ((char *)data
->data
);
516 if (data
->type
== gdk_atom_intern ("text/uri-list", TRUE
))
517 rb_static_playlist_source_add_uri_list (source
, list
);
519 rb_static_playlist_source_add_id_list (source
, list
);
520 rb_list_deep_free (list
);
527 impl_save_contents_to_xml (RBPlaylistSource
*source
,
530 RBStaticPlaylistSourcePrivate
*priv
= RB_STATIC_PLAYLIST_SOURCE_GET_PRIVATE (source
);
533 xmlSetProp (node
, RB_PLAYLIST_TYPE
, RB_PLAYLIST_STATIC
);
535 if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (priv
->base_model
), &iter
))
539 xmlNodePtr child_node
= xmlNewChild (node
, NULL
, RB_PLAYLIST_LOCATION
, NULL
);
540 RhythmDBEntry
*entry
;
542 const char *location
;
544 gtk_tree_model_get (GTK_TREE_MODEL (priv
->base_model
), &iter
, 0, &entry
, -1);
546 location
= rhythmdb_entry_get_string (entry
, RHYTHMDB_PROP_LOCATION
);
547 encoded
= xmlEncodeEntitiesReentrant (NULL
, BAD_CAST location
);
549 xmlNodeSetContent (child_node
, encoded
);
552 rhythmdb_entry_unref (entry
);
553 } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (priv
->base_model
), &iter
));
557 rb_static_playlist_source_add_id_list (RBStaticPlaylistSource
*source
,
560 RBPlaylistSource
*psource
= RB_PLAYLIST_SOURCE (source
);
564 g_return_if_fail (list
!= NULL
);
566 for (i
= list
; i
!= NULL
; i
= i
->next
) {
567 RhythmDBEntry
*entry
;
569 id
= strtoul ((const char *)i
->data
, NULL
, 0);
573 entry
= rhythmdb_entry_lookup_by_id (rb_playlist_source_get_db (psource
), id
);
575 rb_debug ("received id %d, but can't find the entry", id
);
579 rb_static_playlist_source_add_entry (source
, entry
, -1);
584 rb_static_playlist_source_add_uri_list (RBStaticPlaylistSource
*source
,
587 GList
*i
, *uri_list
= NULL
;
588 RBPlaylistSource
*psource
= RB_PLAYLIST_SOURCE (source
);
589 RhythmDBEntry
*entry
;
591 g_return_if_fail (list
!= NULL
);
593 for (i
= list
; i
!= NULL
; i
= g_list_next (i
)) {
594 char *uri
= (char *) i
->data
;
595 uri_list
= g_list_prepend (uri_list
, rb_canonicalise_uri (uri
));
598 uri_list
= g_list_reverse (uri_list
);
599 if (uri_list
== NULL
)
602 for (i
= uri_list
; i
!= NULL
; i
= i
->next
) {
605 entry
= rhythmdb_entry_lookup_by_location (rb_playlist_source_get_db (psource
), uri
);
607 rhythmdb_add_uri (rb_playlist_source_get_db (psource
), uri
);
609 rb_static_playlist_source_add_location (source
, uri
, -1);
614 g_list_free (uri_list
);
618 rb_static_playlist_source_add_location_internal (RBStaticPlaylistSource
*source
,
619 const char *location
,
623 RhythmDBEntry
*entry
;
624 RBPlaylistSource
*psource
= RB_PLAYLIST_SOURCE (source
);
625 if (rb_playlist_source_location_in_map (psource
, location
))
628 db
= rb_playlist_source_get_db (psource
);
629 entry
= rhythmdb_entry_lookup_by_location (db
, location
);
631 RBStaticPlaylistSourcePrivate
*priv
= RB_STATIC_PLAYLIST_SOURCE_GET_PRIVATE (source
);
632 RhythmDBEntryType entry_type
;
634 g_object_get (source
, "entry-type", &entry_type
, NULL
);
635 if (entry_type
!= RHYTHMDB_ENTRY_TYPE_INVALID
&&
636 rhythmdb_entry_get_entry_type (entry
) != entry_type
) {
637 g_boxed_free (RHYTHMDB_TYPE_ENTRY_TYPE
, entry_type
);
638 rb_debug ("attempting to add an entry of the wrong type to playlist");
642 rhythmdb_entry_ref (entry
);
643 rhythmdb_query_model_add_entry (priv
->base_model
, entry
, index
);
644 rhythmdb_entry_unref (entry
);
646 g_boxed_free (RHYTHMDB_TYPE_ENTRY_TYPE
, entry_type
);
649 rb_playlist_source_add_to_map (psource
, location
);
651 rb_playlist_source_mark_dirty (psource
);
655 rb_static_playlist_source_add_location_cb (const char *uri
,
657 RBStaticPlaylistSource
*source
)
660 rb_static_playlist_source_add_location_internal (source
, uri
, -1);
664 rb_static_playlist_source_add_location (RBStaticPlaylistSource
*source
,
665 const char *location
,
669 RhythmDBEntry
*entry
;
671 db
= rb_playlist_source_get_db (RB_PLAYLIST_SOURCE (source
));
672 entry
= rhythmdb_entry_lookup_by_location (db
, location
);
674 /* if there is an entry, it won't be a directory */
675 if (entry
== NULL
&& rb_uri_is_directory (location
))
676 rb_uri_handle_recursively (location
,
677 (RBUriRecurseFunc
) rb_static_playlist_source_add_location_cb
,
681 rb_static_playlist_source_add_location_internal (source
, location
, index
);
686 rb_static_playlist_source_add_locations (RBStaticPlaylistSource
*source
,
691 for (l
= locations
; l
; l
= l
->next
) {
692 const gchar
*uri
= (const gchar
*)l
->data
;
693 rb_static_playlist_source_add_location (source
, uri
, -1);
698 rb_static_playlist_source_remove_location (RBStaticPlaylistSource
*source
,
699 const char *location
)
701 RBPlaylistSource
*psource
= RB_PLAYLIST_SOURCE (source
);
703 RhythmDBEntry
*entry
;
705 g_return_if_fail (rb_playlist_source_location_in_map (psource
, location
));
707 db
= rb_playlist_source_get_db (psource
);
708 entry
= rhythmdb_entry_lookup_by_location (db
, location
);
711 RhythmDBQueryModel
*model
= rb_playlist_source_get_query_model (psource
);
713 /* if this fails, the model and the playlist are out of sync */
714 g_assert (rhythmdb_query_model_remove_entry (model
, entry
));
715 rb_playlist_source_mark_dirty (psource
);
720 rb_static_playlist_source_add_entry (RBStaticPlaylistSource
*source
,
721 RhythmDBEntry
*entry
,
724 const char *location
;
726 location
= rhythmdb_entry_get_string (entry
, RHYTHMDB_PROP_LOCATION
);
727 rb_static_playlist_source_add_location_internal (source
, location
, index
);
731 rb_static_playlist_source_remove_entry (RBStaticPlaylistSource
*source
,
732 RhythmDBEntry
*entry
)
734 const char *location
;
736 location
= rhythmdb_entry_get_string (entry
, RHYTHMDB_PROP_LOCATION
);
737 rb_static_playlist_source_remove_location (source
, location
);
741 rb_static_playlist_source_move_entry (RBStaticPlaylistSource
*source
,
742 RhythmDBEntry
*entry
,
745 RBPlaylistSource
*psource
= RB_PLAYLIST_SOURCE (source
);
746 RhythmDBQueryModel
*model
= rb_playlist_source_get_query_model (psource
);
747 rhythmdb_query_model_move_entry (model
, entry
, index
);
749 rb_playlist_source_mark_dirty (psource
);
753 rb_static_playlist_source_non_entry_dropped (GtkTreeModel
*model
,
756 RBStaticPlaylistSource
*source
)
758 g_assert (g_utf8_strlen (uri
, -1) > 0);
760 rhythmdb_add_uri (rb_playlist_source_get_db (RB_PLAYLIST_SOURCE (source
)), uri
);
761 rb_static_playlist_source_add_location (source
, uri
, position
);
765 rb_static_playlist_source_row_inserted (GtkTreeModel
*model
,
768 RBStaticPlaylistSource
*source
)
770 RhythmDBEntry
*entry
;
772 gtk_tree_model_get (model
, iter
, 0, &entry
, -1);
774 rb_static_playlist_source_add_entry (source
, entry
, -1);
776 rhythmdb_entry_unref (entry
);
780 impl_get_search_actions (RBSource
*source
)
782 GList
*actions
= NULL
;
784 actions
= g_list_prepend (actions
, g_strdup ("StaticPlaylistSearchTitles"));
785 actions
= g_list_prepend (actions
, g_strdup ("StaticPlaylistSearchAlbums"));
786 actions
= g_list_prepend (actions
, g_strdup ("StaticPlaylistSearchArtists"));
787 actions
= g_list_prepend (actions
, g_strdup ("StaticPlaylistSearchAll"));
792 static RhythmDBPropType
793 search_action_to_prop (GtkAction
*action
)
796 RhythmDBPropType prop
;
798 name
= gtk_action_get_name (action
);
801 prop
= RHYTHMDB_PROP_SEARCH_MATCH
;
802 } else if (strcmp (name
, "StaticPlaylistSearchAll") == 0) {
803 prop
= RHYTHMDB_PROP_SEARCH_MATCH
;
804 } else if (strcmp (name
, "StaticPlaylistSearchArtists") == 0) {
805 prop
= RHYTHMDB_PROP_ARTIST_FOLDED
;
806 } else if (strcmp (name
, "StaticPlaylistSearchAlbums") == 0) {
807 prop
= RHYTHMDB_PROP_ALBUM_FOLDED
;
808 } else if (strcmp (name
, "StaticPlaylistSearchTitles") == 0) {
809 prop
= RHYTHMDB_PROP_TITLE_FOLDED
;
811 prop
= RHYTHMDB_PROP_SEARCH_MATCH
;
818 search_action_changed (GtkRadioAction
*action
,
819 GtkRadioAction
*current
,
822 RBStaticPlaylistSource
*source
;
823 RBStaticPlaylistSourcePrivate
*priv
;
826 g_object_get (shell
, "selected-source", &source
, NULL
);
827 priv
= RB_STATIC_PLAYLIST_SOURCE_GET_PRIVATE (source
);
829 active
= gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (current
));
833 priv
->search_prop
= search_action_to_prop (GTK_ACTION (current
));
834 rb_static_playlist_source_do_query (source
);
835 rb_source_notify_filter_changed (RB_SOURCE (source
));
838 if (source
!= NULL
) {
839 g_object_unref (source
);
844 impl_want_uri (RBSource
*source
, const char *uri
)
846 /* take anything local, on smb, or sftp */
847 if (rb_uri_is_local (uri
) ||
848 g_str_has_prefix (uri
, "smb://") ||
849 g_str_has_prefix (uri
, "sftp://"))
850 return 25; /* less than what the library returns */