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