No issues found
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
2 *
3 * Copyright (C) 2011 Jonathan Matthew
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
8 * any later version.
9 *
10 * The Rhythmbox authors hereby grant permission for non-GPL compatible
11 * GStreamer plugins to be used and distributed together with GStreamer
12 * and Rhythmbox. This permission is above and beyond the permissions granted
13 * by the GPL license by which Rhythmbox is covered. If you modify this code
14 * you may extend this exception to your version of the code, but you are not
15 * obligated to do so. If you do not wish to do so, delete this exception
16 * statement from your version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
26 */
27
28 #include "config.h"
29
30 #include <glib.h>
31 #include <glib-object.h>
32 #include <glib/gi18n-lib.h>
33 #include <gmodule.h>
34 #include <gtk/gtk.h>
35
36 #include <grilo.h>
37
38 #include "rb-plugin-macros.h"
39 #include "rb-debug.h"
40 #include "rb-shell.h"
41 #include "rb-shell-player.h"
42 #include "rb-grilo-source.h"
43 #include "rb-display-page-group.h"
44 #include "rb-ext-db.h"
45
46 #define RB_TYPE_GRILO_PLUGIN (rb_grilo_plugin_get_type ())
47 #define RB_GRILO_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), RB_TYPE_GRILO_PLUGIN, RBGriloPlugin))
48 #define RB_GRILO_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), RB_TYPE_GRILO_PLUGIN, RBGriloPluginClass))
49 #define RB_IS_GRILO_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), RB_TYPE_GRILO_PLUGIN))
50 #define RB_IS_GRILO_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), RB_TYPE_GRILO_PLUGIN))
51 #define RB_GRILO_PLUGIN_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), RB_TYPE_GRILO_PLUGIN, RBGriloPluginClass))
52
53 static const char *ignored_plugins[] = {
54 "grl-apple-trailers",
55 "grl-bliptv",
56 "grl-bookmarks",
57 "grl-filesystem",
58 "grl-flickr",
59 "grl-optical-media",
60 "grl-podcasts",
61 "grl-tracker",
62 "grl-vimeo",
63 "grl-youtube"
64 };
65
66 typedef struct
67 {
68 PeasExtensionBase parent;
69
70 GrlRegistry *registry;
71 GHashTable *sources;
72 RBShellPlayer *shell_player;
73 gulong emit_cover_art_id;
74 RBExtDB *art_store;
75 } RBGriloPlugin;
76
77 typedef struct
78 {
79 PeasExtensionBaseClass parent_class;
80 } RBGriloPluginClass;
81
82 G_MODULE_EXPORT void peas_register_types (PeasObjectModule *module);
83 GType rb_grilo_plugin_get_type (void) G_GNUC_CONST;
84
85 static void rb_grilo_plugin_init (RBGriloPlugin *plugin);
86
87 RB_DEFINE_PLUGIN(RB_TYPE_GRILO_PLUGIN, RBGriloPlugin, rb_grilo_plugin,)
88
89 static void
90 rb_grilo_plugin_init (RBGriloPlugin *plugin)
91 {
92 rb_debug ("RBGriloPlugin initialising");
93 }
94
95 static void
96 rb_grilo_plugin_source_deleted (RBGriloSource *source, RBGriloPlugin *plugin)
97 {
98 GrlSource *grilo_source;
99
100 g_object_get (source, "media-source", &grilo_source, NULL);
101 g_hash_table_remove (plugin->sources, grilo_source);
102 g_object_unref (grilo_source);
103 }
104
105 static void
106 grilo_source_added_cb (GrlRegistry *registry, GrlSource *grilo_source, RBGriloPlugin *plugin)
107 {
108 GrlPlugin *grilo_plugin;
109 GrlSupportedOps ops;
110 const GList *keys;
111 RBSource *source;
112 RBShell *shell;
113 int i;
114
115 grilo_plugin = grl_source_get_plugin (grilo_source);
116 for (i = 0; i < G_N_ELEMENTS (ignored_plugins); i++) {
117 if (g_str_equal (ignored_plugins[i], grl_plugin_get_id (grilo_plugin))) {
118 rb_debug ("grilo source %s is blacklisted",
119 grl_source_get_name (grilo_source));
120 return;
121 }
122 }
123
124 ops = grl_source_supported_operations (grilo_source);
125 if (((ops & GRL_OP_BROWSE) == 0) && ((ops & GRL_OP_SEARCH) == 0)) {
126 rb_debug ("grilo source %s is not interesting",
127 grl_source_get_name (grilo_source));
128 return;
129 }
130
131 keys = grl_source_supported_keys (grilo_source);
132 if (g_list_find ((GList *)keys, GINT_TO_POINTER (GRL_METADATA_KEY_URL)) == NULL) {
133 rb_debug ("grilo source %s doesn't do urls", grl_source_get_name (grilo_source));
134 return;
135 }
136
137 rb_debug ("new grilo source: %s", grl_source_get_name (grilo_source));
138
139 source = rb_grilo_source_new (G_OBJECT (plugin), grilo_source);
140 g_hash_table_insert (plugin->sources, g_object_ref (grilo_source), g_object_ref_sink (source));
141
142 /* probably put some sources under 'shared', some under 'stores'? */
143 g_object_get (plugin, "object", &shell, NULL);
144 rb_shell_append_display_page (shell, RB_DISPLAY_PAGE (source), RB_DISPLAY_PAGE_GROUP_SHARED);
145 g_object_unref (shell);
146 }
147
148 static void
149 playing_song_changed_cb (RBShellPlayer *player, RhythmDBEntry *entry, RBGriloPlugin *plugin)
150 {
151 const char *uri;
152 RhythmDBEntryType *entry_type;
153 RBGriloEntryData *data;
154
155 if (entry == NULL)
156 return;
157
158 entry_type = rhythmdb_entry_get_entry_type (entry);
159 if (RB_IS_GRILO_ENTRY_TYPE (entry_type) == FALSE) {
160 return;
161 }
162
163 data = RHYTHMDB_ENTRY_GET_TYPE_DATA (entry, RBGriloEntryData);
164 uri = grl_data_get_string (data->grilo_data, GRL_METADATA_KEY_THUMBNAIL);
165 if (uri != NULL) {
166 RBExtDBKey *key;
167
168 key = rb_ext_db_key_create_storage ("album", rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ALBUM));
169 rb_ext_db_key_add_field (key, "artist", rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_ARTIST));
170
171 rb_ext_db_store_uri (plugin->art_store,
172 key,
173 RB_EXT_DB_SOURCE_SEARCH,
174 uri);
175 rb_ext_db_key_free (key);
176 }
177 }
178
179 static void
180 impl_activate (PeasActivatable *plugin)
181 {
182 RBGriloPlugin *pi = RB_GRILO_PLUGIN (plugin);
183 GError *error = NULL;
184 RBShell *shell;
185
186 pi->sources = g_hash_table_new_full (g_direct_hash,
187 g_direct_equal,
188 g_object_unref,
189 g_object_unref);
190
191 grl_init (0, NULL);
192 pi->registry = grl_registry_get_default ();
193 g_signal_connect (pi->registry, "source-added", G_CALLBACK (grilo_source_added_cb), pi);
194 if (grl_registry_load_all_plugins (pi->registry, &error) == FALSE) {
195 g_warning ("Failed to load Grilo plugins: %s", error->message);
196 g_clear_error (&error);
197 }
198
199 g_object_get (plugin, "object", &shell, NULL);
200 g_object_get (shell, "shell-player", &pi->shell_player, NULL);
201 g_object_unref (shell);
202
203 g_signal_connect (pi->shell_player, "playing-song-changed", G_CALLBACK (playing_song_changed_cb), pi);
204
205 pi->art_store = rb_ext_db_new ("album-art");
206 }
207
208 static void
209 _delete_cb (GrlSource *grilo_source,
210 RBSource *source,
211 RBGriloPlugin *plugin)
212 {
213 /* block the source deleted handler so we don't modify the hash table
214 * while iterating it.
215 */
216 g_signal_handlers_block_by_func (source, rb_grilo_plugin_source_deleted, plugin);
217 rb_display_page_delete_thyself (RB_DISPLAY_PAGE (source));
218 }
219
220 static void
221 impl_deactivate (PeasActivatable *bplugin)
222 {
223 RBGriloPlugin *plugin = RB_GRILO_PLUGIN (bplugin);
224
225 g_hash_table_foreach (plugin->sources, (GHFunc)_delete_cb, plugin);
226 g_hash_table_destroy (plugin->sources);
227 plugin->sources = NULL;
228
229 g_object_unref (plugin->registry);
230 plugin->registry = NULL;
231
232 if (plugin->emit_cover_art_id != 0) {
233 g_source_remove (plugin->emit_cover_art_id);
234 plugin->emit_cover_art_id = 0;
235 }
236 g_signal_handlers_disconnect_by_func (plugin->shell_player, G_CALLBACK (playing_song_changed_cb), plugin);
237 g_object_unref (plugin->shell_player);
238 plugin->shell_player = NULL;
239
240 g_object_unref (plugin->art_store);
241 plugin->art_store = NULL;
242 }
243
244 G_MODULE_EXPORT void
245 peas_register_types (PeasObjectModule *module)
246 {
247 rb_grilo_plugin_register_type (G_TYPE_MODULE (module));
248 _rb_grilo_source_register_type (G_TYPE_MODULE (module));
249 peas_object_module_register_extension_type (module,
250 PEAS_TYPE_ACTIVATABLE,
251 RB_TYPE_GRILO_PLUGIN);
252 }