1 /*
2 * Browsing in Grilo.
3 * Shows the first BROWSE_CHUNK_SIZE elements of each browsable source
4 *
5 * XXX: No pagination yet! See grilo-test-ui. It's somewhat complicated.
6 */
7
8 #include <grilo.h>
9 #include <gio/gio.h>
10 #include <glib.h>
11 #include <glib/gprintf.h>
12 #include "../libs/pls/grl-pls.h"
13
14 #define GRL_LOG_DOMAIN_DEFAULT example_log_domain
15 GRL_LOG_DOMAIN_STATIC(example_log_domain);
16
17 #define BROWSE_CHUNK_SIZE 10
18
19 static void source_browser (gpointer data,
20 gpointer user_data);
21 static void element_browser (gpointer data,
22 gpointer user_data);
23
24 static void
element_browser(gpointer data,gpointer user_data)25 element_browser (gpointer data,
26 gpointer user_data)
27 {
28 GrlMedia *media = GRL_MEDIA (data);
29 GrlSource *source = GRL_SOURCE (user_data);
30
31 /* Check if we got a valid media object as some plugins may call the callback
32 with a NULL media under certain circumstances (for example when they
33 cannot estimate the number of remaining results and they find suddenly they
34 don't have any more results to send) */
35 if (!media) {
36 g_debug ("Media element is NULL!");
37 goto out;
38 }
39
40 const gchar *title = grl_media_get_title (media);
41
42 /* If the media is a container, that means we will browse it again */
43 if (grl_media_is_container (media)) {
44 guint childcount = grl_media_get_childcount (media);
45 g_debug ("\t Got '%s' (container with %d elements)", title, childcount);
46
47 source_browser (source, media);
48 } else {
49 const gchar *url = grl_media_get_url (media);
50 const gchar *mime = grl_media_get_mime (media);
51 GDateTime *date = grl_media_get_modification_date (media);
52 time_t rawdate = g_date_time_to_unix(date);
53 g_printf ("\t Got '%s', of type '%s', ctime is '%s'\n", title, mime, ctime(&rawdate));
54 g_printf ("\t\t URL: %s\n", url);
55 }
56
57 out:
58 g_object_unref (media);
59 }
60
61 static void
source_browser(gpointer data,gpointer user_data)62 source_browser (gpointer data,
63 gpointer user_data)
64 {
65 GrlSource *source = GRL_SOURCE (data);
66 GrlMedia *media = GRL_MEDIA (user_data);
67 GList *media_elements;
68 GError *error = NULL;
69 GList *keys;
70 GrlOperationOptions *options = NULL;
71 GrlCaps *caps;
72
73 keys = grl_metadata_key_list_new (GRL_METADATA_KEY_TITLE,
74 GRL_METADATA_KEY_URL,
75 GRL_METADATA_KEY_MODIFICATION_DATE,
76 GRL_METADATA_KEY_MIME,
77 GRL_METADATA_KEY_CHILDCOUNT,
78 NULL);
79
80 g_debug ("Detected new source available: '%s'",
81 grl_source_get_name (source));
82
83 if (!(grl_source_supported_operations (source) & GRL_OP_BROWSE))
84 goto out;
85
86 g_debug ("Browsing source: %s", grl_source_get_name (source));
87 /* Here is how you can browse a source, you have to provide:
88 1) The source you want to browse contents from.
89 2) The container object you want to browse (NULL for the root container)
90 3) A list of metadata keys we are interested in.
91 4) Options to control certain aspects of the browse operation.
92 5) A callback that the framework will invoke for each available result
93 6) User data for the callback
94 It returns an operation identifier that you can use to match results
95 with the corresponding request (we ignore it here) */
96
97 caps = grl_source_get_caps (source, GRL_OP_BROWSE);
98 options = grl_operation_options_new (caps);
99 grl_operation_options_set_count (options, BROWSE_CHUNK_SIZE);
100 grl_operation_options_set_resolution_flags (options, GRL_RESOLVE_IDLE_RELAY);
101 media_elements = grl_pls_browse_sync (GRL_SOURCE (source),
102 media, keys,
103 options,
104 NULL,
105 &error);
106 if (!media_elements) {
107 g_debug ("No elements found for source: %s!",
108 grl_source_get_name (source));
109 goto out;
110 }
111
112 if (error)
113 g_error ("Failed to browse source: %s", error->message);
114
115 g_list_foreach (media_elements, element_browser, source);
116
117 out:
118 g_list_free (keys);
119 g_clear_object (&options);
120 }
121
122 static void
load_plugins(gchar * playlist)123 load_plugins (gchar* playlist)
124 {
125 GrlRegistry *registry;
126 GrlSource *source;
127 GError *error = NULL;
128 GList *keys;
129 GrlOperationOptions *options;
130 GrlCaps *caps;
131 GrlMedia* media;
132 gboolean pls_media;
133 const gchar *mime;
134
135 registry = grl_registry_get_default ();
136 grl_registry_load_all_plugins (registry, FALSE, NULL);
137
138 /* Activate plugin */
139 if (!grl_registry_activate_plugin_by_id (registry, "grl-filesystem", &error))
140 g_error ("Failed to load plugin: %s", error->message);
141
142 source = grl_registry_lookup_source (registry, "grl-filesystem");
143 if (!source)
144 g_error ("Unable to load grl-filesystem plugin");
145
146 if (!(grl_source_supported_operations (source) & GRL_OP_MEDIA_FROM_URI))
147 g_error ("Unable to get media from URI");
148
149 keys = grl_metadata_key_list_new (GRL_METADATA_KEY_TITLE, GRL_METADATA_KEY_URL, GRL_METADATA_KEY_MIME, NULL);
150 if (!keys)
151 g_error ("Unable to create key list");
152
153 caps = grl_source_get_caps (source, GRL_OP_MEDIA_FROM_URI);
154 if (!caps)
155 g_error ("Unable to get source caps");
156
157 options = grl_operation_options_new (caps);
158 if (!options)
159 g_error ("Unable to create operation options");
160
161 media = grl_source_get_media_from_uri_sync (source, playlist, keys, options, &error);
162 if (!media)
163 g_error ("Unable to get GrlMedia for playlist %s", playlist);
164
165 g_object_unref (options);
166
167 mime = grl_media_get_mime (media);
168
169 pls_media = grl_pls_media_is_playlist (media);
170
171 g_printf("Got Media for %s - mime=%s\n", playlist, mime);
172 g_printf("\tgrl_pls_media_is_playlist = %d\n", pls_media);
173
174 if (pls_media) {
175 source_browser (source, media);
176 }
177
178 g_object_unref (media);
179 g_object_unref (source);
180 }
181
182 static void
config_plugins(gchar * chosen_test_path)183 config_plugins (gchar* chosen_test_path)
184 {
185 GrlRegistry *registry;
186 GrlConfig *config;
187
188 registry = grl_registry_get_default ();
189
190 /* Configure plugin */
191 config = grl_config_new ("grl-filesystem", "Filesystem");
192 grl_config_set_string (config, "base-path", chosen_test_path);
193 grl_registry_add_config (registry, config, NULL);
194
195 g_printf ("config_plugin with %s\n", chosen_test_path);
196 }
197
198 gint
main(int argc,gchar * argv[])199 main (int argc,
200 gchar *argv[])
201 {
202 gchar *chosen_test_path;
203 gchar *file_uri;
204 GError *error = NULL;
205
206 grl_init (&argc, &argv);
207 GRL_LOG_DOMAIN_INIT (example_log_domain, "example");
208
209 if (argc != 2) {
210 g_printf ("Usage: %s <path to browse>\n", argv[0]);
211 return 1;
212 }
213
214 chosen_test_path = argv[1];
215 GFile *file = g_file_new_for_path (chosen_test_path);
216 if (!file) {
217 g_printf ("Invalid file/directory %s\n", argv[1]);
218 return 1;
219 }
220
221 GFileInfo *info = g_file_query_info (file,
222 G_FILE_ATTRIBUTE_STANDARD_TYPE,
223 0,
224 NULL,
225 &error);
226 if (!info) {
227 g_printf ("Invalid file/directory information\n");
228 return 1;
229 }
230
231 if (g_file_info_get_file_type (info) != G_FILE_TYPE_REGULAR) {
232 return 1;
233 }
234
235 gchar *dirname = g_path_get_dirname(chosen_test_path);
236 config_plugins (dirname);
237 g_free (dirname);
238
239 file_uri = g_filename_to_uri (chosen_test_path, NULL, &error);
240
241 g_object_unref (file);
242 g_object_unref (info);
243 load_plugins (file_uri);
244 g_free (file_uri);
245
246 return 0;
247 }
248