diff options
author | Juan A. Suarez Romero <jasuarez@igalia.com> | 2010-03-12 21:24:39 +0100 |
---|---|---|
committer | Juan A. Suarez Romero <jasuarez@igalia.com> | 2010-03-12 21:24:39 +0100 |
commit | e230523509d075223ec53adcbb02bebf1dce084c (patch) | |
tree | 530b6b345694f2badffb1f5d82903a6441d793c7 | |
parent | a800d4b946e352b4f530d5b446b32d539469c3d1 (diff) | |
parent | b6a2a65689f0563d0990bbdb8fa57d297d61329f (diff) | |
download | grilo-plugins-e230523509d075223ec53adcbb02bebf1dce084c.tar.gz |
Merge commit 'grilo-plugins-0.1.4' into debian
-rw-r--r-- | NEWS | 23 | ||||
-rw-r--r-- | configure.ac | 42 | ||||
-rw-r--r-- | src/Makefile.am | 6 | ||||
-rw-r--r-- | src/apple-trailers/grl-apple-trailers.c | 36 | ||||
-rw-r--r-- | src/bookmarks/grl-bookmarks.c | 60 | ||||
-rw-r--r-- | src/fake-metadata/grl-fake-metadata.c | 65 | ||||
-rw-r--r-- | src/filesystem/grl-filesystem.c | 50 | ||||
-rw-r--r-- | src/flickr/grl-flickr.c | 77 | ||||
-rw-r--r-- | src/jamendo/grl-jamendo.c | 96 | ||||
-rw-r--r-- | src/lastfm-albumart/grl-lastfm-albumart.c | 20 | ||||
-rw-r--r-- | src/metadata-store/Makefile.am | 26 | ||||
-rw-r--r-- | src/metadata-store/grl-metadata-store.c | 681 | ||||
-rw-r--r-- | src/metadata-store/grl-metadata-store.h | 75 | ||||
-rw-r--r-- | src/podcasts/grl-podcasts.c | 160 | ||||
-rw-r--r-- | src/shoutcast/grl-shoutcast.c | 54 | ||||
-rw-r--r-- | src/upnp/grl-upnp.c | 55 | ||||
-rw-r--r-- | src/youtube/TODO | 6 | ||||
-rw-r--r-- | src/youtube/grl-youtube.c | 93 | ||||
-rw-r--r-- | test/main.c | 140 |
19 files changed, 1375 insertions, 390 deletions
@@ -1,4 +1,23 @@ -New in 0.1.3 +NEW in 0.1.4 +============ + + * General + * Updates related with changes in Grilo API + + * Bookmarks + * Small improvements + + * Flickr plugin + * Use the new configuration system + + * Metadata-Store plugin + * New plugin where to save metadata + + * Podcasts plugin + * Small improvements + + +NEW in 0.1.3 ============ * General @@ -10,7 +29,7 @@ New in 0.1.3 * Bookmarks plugin * Small improvements - * Podcats plugin + * Podcasts plugin * Small improvements * Shoutcast plugin diff --git a/configure.ac b/configure.ac index cd3542a..dde5f14 100644 --- a/configure.ac +++ b/configure.ac @@ -6,7 +6,7 @@ # Copyright (C) 2010 Igalia S.L.. All rights reserved. m4_define([prj_name], [grilo-plugins]) -m4_define([prj_version], [0.1.3]) +m4_define([prj_version], [0.1.4]) AC_INIT([prj_name], [prj_version]) @@ -65,7 +65,7 @@ AC_DEFINE_UNQUOTED(GRL_PLUGINS_DIR, "$GRL_PLUGINS_DIR", [Plugins directory]) PKG_CHECK_MODULES(DEPS, glib-2.0 \ gobject-2.0 \ gmodule-2.0 \ - grilo-0.1 >= 0.1.3) + grilo-0.1 >= 0.1.4) AC_SUBST(DEPS_CFLAGS) AC_SUBST(DEPS_LIBS) @@ -149,8 +149,8 @@ AM_CONDITIONAL([DEBUG], [test "x$enable_debug" = "xyes"]) AC_ARG_ENABLE(fakemetadata, AC_HELP_STRING([--enable-fakemetadata], - [enable Fake Metadata plugin (default: yes)]),, - [enable_fakemetadata=yes]) + [enable Fake Metadata plugin (default: no)]),, + [enable_fakemetadata=no]) AM_CONDITIONAL([FAKEMETADATA_PLUGIN], [test "x$enable_fakemetadata" = "xyes"]) GRL_PLUGINS_ALL="$GRL_PLUGINS_ALL fakemetadata" @@ -321,7 +321,7 @@ fi # ---------------------------------------------------------- AC_ARG_ENABLE(flickr, - AC_HELP_STRING([--flickr], + AC_HELP_STRING([--enable-flickr], [enable Flickr plugin (default: auto)]), [ case "$enableval" in @@ -502,6 +502,37 @@ then fi # ---------------------------------------------------------- +# BUILD METADATA-STORE PLUGIN +# ---------------------------------------------------------- + +AC_ARG_ENABLE(metadata-store, + AC_HELP_STRING([--enable-metadata-store], + [enable Metadata Store plugin (default: auto)]), + [ + case "$enableval" in + yes) + if test "x$HAVE_SQLITE" = "xno"; then + AC_MSG_ERROR([sqlite3 not found, install it or use --disable-metadata-store]) + fi + ;; + esac + ], + [ + if test "x$HAVE_SQLITE" = "xyes"; then + enable_metadata_store=yes + else + enable_metadata_store=no + fi + ]) + +AM_CONDITIONAL([METADATA_STORE_PLUGIN], [test "x$enable_metadata_store" = "xyes"]) +GRL_PLUGINS_ALL="$GRL_PLUGINS_ALL metadata-store" +if test "x$enable_metadata_store" = "xyes" +then + GRL_PLUGINS_ENABLED="$GRL_PLUGINS_ENABLED metadata-store" +fi + +# ---------------------------------------------------------- # GETTEXT # ---------------------------------------------------------- @@ -536,6 +567,7 @@ AC_CONFIG_FILES([ src/bookmarks/Makefile src/shoutcast/Makefile src/apple-trailers/Makefile + src/metadata-store/Makefile test/Makefile debian/grilo-0.1-plugins.install ]) diff --git a/src/Makefile.am b/src/Makefile.am index fc8dc4f..c45f9d3 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -51,7 +51,11 @@ if APPLE_TRAILERS_PLUGIN SUBDIRS += apple-trailers endif -DIST_SUBDIRS = youtube fake-metadata filesystem jamendo lastfm-albumart upnp flickr podcasts bookmarks shoutcast apple-trailers +if METADATA_STORE_PLUGIN +SUBDIRS += metadata-store +endif + +DIST_SUBDIRS = youtube fake-metadata filesystem jamendo lastfm-albumart upnp flickr podcasts bookmarks shoutcast apple-trailers metadata-store MAINTAINERCLEANFILES = \ *.in \ diff --git a/src/apple-trailers/grl-apple-trailers.c b/src/apple-trailers/grl-apple-trailers.c index f0bb2d7..37afc4d 100644 --- a/src/apple-trailers/grl-apple-trailers.c +++ b/src/apple-trailers/grl-apple-trailers.c @@ -73,7 +73,8 @@ typedef struct { static GrlAppleTrailersSource *grl_apple_trailers_source_new (void); gboolean grl_apple_trailers_plugin_init (GrlPluginRegistry *registry, - const GrlPluginInfo *plugin); + const GrlPluginInfo *plugin, + GList *configs); static const GList *grl_apple_trailers_source_supported_keys (GrlMetadataSource *source); @@ -87,7 +88,8 @@ static void grl_apple_trailers_source_cancel (GrlMediaSource *source, gboolean grl_apple_trailers_plugin_init (GrlPluginRegistry *registry, - const GrlPluginInfo *plugin) + const GrlPluginInfo *plugin, + GList *configs) { g_debug ("apple_trailers_plugin_init\n"); @@ -189,10 +191,10 @@ runtime_to_seconds (const gchar *runtime) return seconds; } -static GrlContentMedia * +static GrlMedia * build_media_from_movie (xmlNodePtr node) { - GrlContentMedia * media; + GrlMedia * media; gchar *movie_author; gchar *movie_date; gchar *movie_description; @@ -203,7 +205,7 @@ build_media_from_movie (xmlNodePtr node) gchar *movie_title; gchar *movie_url; - media = grl_content_video_new (); + media = grl_media_video_new (); movie_id = (gchar *) xmlGetProp (node, (const xmlChar *) "id"); @@ -223,17 +225,17 @@ build_media_from_movie (xmlNodePtr node) movie_url = get_node_value (node_dup, "/movieinfo/preview/large"); xmlFreeDoc (xml_doc); - grl_content_media_set_id (media, movie_id); - grl_content_media_set_author (media, movie_author); - grl_content_media_set_date (media, movie_date); - grl_content_media_set_description (media, movie_description); - grl_content_media_set_duration (media, runtime_to_seconds (movie_duration)); - grl_content_media_set_title (media, movie_title); - grl_content_set_string (GRL_CONTENT (media), - GRL_METADATA_KEY_GENRE, - movie_genre); - grl_content_media_set_thumbnail (media, movie_thumbnail); - grl_content_media_set_url (media, movie_url); + grl_media_set_id (media, movie_id); + grl_media_set_author (media, movie_author); + grl_media_set_date (media, movie_date); + grl_media_set_description (media, movie_description); + grl_media_set_duration (media, runtime_to_seconds (movie_duration)); + grl_media_set_title (media, movie_title); + grl_data_set_string (GRL_DATA (media), + GRL_METADATA_KEY_GENRE, + movie_genre); + grl_media_set_thumbnail (media, movie_thumbnail); + grl_media_set_url (media, movie_url); g_free (movie_id); g_free (movie_author); @@ -251,7 +253,7 @@ build_media_from_movie (xmlNodePtr node) static gboolean send_movie_info (OperationData *op_data) { - GrlContentMedia *media; + GrlMedia *media; gboolean last = FALSE; if (op_data->cancelled) { diff --git a/src/bookmarks/grl-bookmarks.c b/src/bookmarks/grl-bookmarks.c index 8b3c1aa..e341288 100644 --- a/src/bookmarks/grl-bookmarks.c +++ b/src/bookmarks/grl-bookmarks.c @@ -177,7 +177,8 @@ static void grl_bookmarks_source_remove (GrlMediaSource *source, static gboolean grl_bookmarks_plugin_init (GrlPluginRegistry *registry, - const GrlPluginInfo *plugin) + const GrlPluginInfo *plugin, + GList *configs) { g_debug ("grl_bookmarks_plugin_init\n"); @@ -313,10 +314,10 @@ mime_is_audio (const gchar *mime) return mime && strstr (mime, "audio") != NULL; } -static GrlContentMedia * -build_media_from_stmt (GrlContentMedia *content, sqlite3_stmt *sql_stmt) +static GrlMedia * +build_media_from_stmt (GrlMedia *content, sqlite3_stmt *sql_stmt) { - GrlContentMedia *media = NULL; + GrlMedia *media = NULL; gchar *id; gchar *title; gchar *url; @@ -341,30 +342,30 @@ build_media_from_stmt (GrlContentMedia *content, sqlite3_stmt *sql_stmt) if (!media) { if (type == BOOKMARK_TYPE_CATEGORY) { - media = GRL_CONTENT_MEDIA (grl_content_box_new ()); + media = GRL_MEDIA (grl_media_box_new ()); } else if (mime_is_audio (mime)) { - media = GRL_CONTENT_MEDIA (grl_content_media_new ()); + media = GRL_MEDIA (grl_media_new ()); } else if (mime_is_video (mime)) { - media = GRL_CONTENT_MEDIA (grl_content_media_new ()); + media = GRL_MEDIA (grl_media_new ()); } else { - media = GRL_CONTENT_MEDIA (grl_content_media_new ()); + media = GRL_MEDIA (grl_media_new ()); } } - grl_content_media_set_id (media, id); - grl_content_media_set_title (media, title); + grl_media_set_id (media, id); + grl_media_set_title (media, title); if (url) { - grl_content_media_set_url (media, url); + grl_media_set_url (media, url); } if (desc) { - grl_content_media_set_description (media, desc); + grl_media_set_description (media, desc); } if (date) { - grl_content_media_set_date (media, date); + grl_media_set_date (media, date); } if (type == BOOKMARK_TYPE_CATEGORY) { - grl_content_box_set_childcount (GRL_CONTENT_BOX (media), childcount); + grl_media_box_set_childcount (GRL_MEDIA_BOX (media), childcount); } return media; @@ -384,10 +385,10 @@ bookmark_metadata (GrlMediaSourceMetadataSpec *ms) db = GRL_BOOKMARKS_SOURCE (ms->source)->priv->db; - id = grl_content_media_get_id (ms->media); + id = grl_media_get_id (ms->media); if (!id) { /* Root category: special case */ - grl_content_media_set_title (ms->media, ""); + grl_media_set_title (ms->media, ""); ms->callback (ms->source, ms->media, ms->user_data, NULL); return; } @@ -430,7 +431,7 @@ produce_bookmarks_from_sql (OperationSpec *os, const gchar *sql) gint r; sqlite3_stmt *sql_stmt = NULL; sqlite3 *db; - GrlContentMedia *media; + GrlMedia *media; GError *error = NULL; GList *medias = NULL; guint count = 0; @@ -475,7 +476,7 @@ produce_bookmarks_from_sql (OperationSpec *os, const gchar *sql) medias = g_list_reverse (medias); iter = medias; while (iter) { - media = GRL_CONTENT_MEDIA (iter->data); + media = GRL_MEDIA (iter->data); os->callback (os->source, os->operation_id, media, @@ -556,8 +557,8 @@ remove_bookmark (sqlite3 *db, const gchar *bookmark_id, GError **error) static void store_bookmark (sqlite3 *db, - GrlContentBox *parent, - GrlContentMedia *bookmark, + GrlMediaBox *parent, + GrlMedia *bookmark, GError **error) { gint r; @@ -570,20 +571,21 @@ store_bookmark (sqlite3 *db, const gchar *mime; gchar *date; guint type; + gchar *id; g_debug ("store_bookmark"); - title = grl_content_media_get_title (bookmark); - url = grl_content_media_get_url (bookmark); - desc = grl_content_media_get_description (bookmark); - mime = grl_content_media_get_mime (bookmark); + title = grl_media_get_title (bookmark); + url = grl_media_get_url (bookmark); + desc = grl_media_get_description (bookmark); + mime = grl_media_get_mime (bookmark); g_get_current_time (&now); date = g_time_val_to_iso8601 (&now); if (!parent) { parent_id = "0"; } else { - parent_id = grl_content_media_get_id (parent); + parent_id = grl_media_get_id (parent); } if (!parent_id) { parent_id = "0"; @@ -604,7 +606,7 @@ store_bookmark (sqlite3 *db, g_debug ("URL: '%s'", url); - if (GRL_IS_CONTENT_BOX (bookmark)) { + if (GRL_IS_MEDIA_BOX (bookmark)) { type = BOOKMARK_TYPE_CATEGORY; } else { type = BOOKMARK_TYPE_STREAM; @@ -646,6 +648,10 @@ store_bookmark (sqlite3 *db, } sqlite3_finalize (sql_stmt); + + id = g_strdup_printf ("%llu", sqlite3_last_insert_rowid (db)); + grl_media_set_id (bookmark, id); + g_free (id); } /* ================== API Implementation ================ */ @@ -690,7 +696,7 @@ grl_bookmarks_source_browse (GrlMediaSource *source, os = g_new0 (OperationSpec, 1); os->source = bs->source; os->operation_id = bs->browse_id; - os->media_id = grl_content_media_get_id (bs->container); + os->media_id = grl_media_get_id (bs->container); os->count = bs->count; os->skip = bs->skip; os->callback = bs->callback; diff --git a/src/fake-metadata/grl-fake-metadata.c b/src/fake-metadata/grl-fake-metadata.c index d0bacae..25e0e17 100644 --- a/src/fake-metadata/grl-fake-metadata.c +++ b/src/fake-metadata/grl-fake-metadata.c @@ -49,20 +49,27 @@ static GrlFakeMetadataSource *grl_fake_metadata_source_new (void); static void grl_fake_metadata_source_resolve (GrlMetadataSource *source, GrlMetadataSourceResolveSpec *rs); +static void grl_fake_metadata_source_set_metadata (GrlMetadataSource *source, + GrlMetadataSourceSetMetadataSpec *sms); + static const GList *grl_fake_metadata_source_supported_keys (GrlMetadataSource *source); static const GList *grl_fake_metadata_source_key_depends (GrlMetadataSource *source, GrlKeyID key_id); +static const GList *grl_fake_metadata_source_writable_keys (GrlMetadataSource *source); + gboolean grl_fake_metadata_source_plugin_init (GrlPluginRegistry *registry, - const GrlPluginInfo *plugin); + const GrlPluginInfo *plugin, + GList *configs); /* =================== GrlFakeMetadata Plugin =============== */ gboolean grl_fake_metadata_source_plugin_init (GrlPluginRegistry *registry, - const GrlPluginInfo *plugin) + const GrlPluginInfo *plugin, + GList *configs) { g_debug ("grl_fake_metadata_source_plugin_init"); GrlFakeMetadataSource *source = grl_fake_metadata_source_new (); @@ -102,6 +109,8 @@ grl_fake_metadata_source_class_init (GrlFakeMetadataSourceClass * klass) metadata_class->supported_keys = grl_fake_metadata_source_supported_keys; metadata_class->key_depends = grl_fake_metadata_source_key_depends; metadata_class->resolve = grl_fake_metadata_source_resolve; + metadata_class->set_metadata = grl_fake_metadata_source_set_metadata; + metadata_class->writable_keys = grl_fake_metadata_source_writable_keys; } static void @@ -116,37 +125,37 @@ G_DEFINE_TYPE (GrlFakeMetadataSource, /* ======================= Utilities ==================== */ static void -fill_metadata (GrlContentMedia *media, GrlKeyID key_id) +fill_metadata (GrlMedia *media, GrlKeyID key_id) { switch (key_id) { case GRL_METADATA_KEY_AUTHOR: - grl_content_media_set_author (media, "fake author"); + grl_media_set_author (media, "fake author"); break; case GRL_METADATA_KEY_ARTIST: - grl_content_set_string (GRL_CONTENT (media), - GRL_METADATA_KEY_ARTIST, "fake artist"); + grl_data_set_string (GRL_DATA (media), + GRL_METADATA_KEY_ARTIST, "fake artist"); break; case GRL_METADATA_KEY_ALBUM: - grl_content_set_string (GRL_CONTENT (media), - GRL_METADATA_KEY_ALBUM, "fake album"); + grl_data_set_string (GRL_DATA (media), + GRL_METADATA_KEY_ALBUM, "fake album"); break; case GRL_METADATA_KEY_GENRE: - grl_content_set_string (GRL_CONTENT (media), - GRL_METADATA_KEY_GENRE, "fake genre"); + grl_data_set_string (GRL_DATA (media), + GRL_METADATA_KEY_GENRE, "fake genre"); break; case GRL_METADATA_KEY_DESCRIPTION: - grl_content_media_set_description (media, "fake description"); + grl_media_set_description (media, "fake description"); break; case GRL_METADATA_KEY_DURATION: - grl_content_media_set_duration (media, 99); + grl_media_set_duration (media, 99); break; case GRL_METADATA_KEY_DATE: - grl_content_set_string (GRL_CONTENT (media), - GRL_METADATA_KEY_DATE, "01/01/1970"); + grl_data_set_string (GRL_DATA (media), + GRL_METADATA_KEY_DATE, "01/01/1970"); break; case GRL_METADATA_KEY_THUMBNAIL: - grl_content_media_set_thumbnail (media, - "http://fake.thumbnail.com/fake-image.jpg"); + grl_media_set_thumbnail (media, + "http://fake.thumbnail.com/fake-image.jpg"); break; default: break; @@ -200,6 +209,19 @@ grl_fake_metadata_source_key_depends (GrlMetadataSource *source, return NULL; } +static const GList * +grl_fake_metadata_source_writable_keys (GrlMetadataSource *source) +{ + static GList *keys = NULL; + if (!keys) { + keys = grl_metadata_key_list_new (GRL_METADATA_KEY_ALBUM, + GRL_METADATA_KEY_ARTIST, + GRL_METADATA_KEY_GENRE, + NULL); + } + return keys; +} + static void grl_fake_metadata_source_resolve (GrlMetadataSource *source, GrlMetadataSourceResolveSpec *rs) @@ -211,9 +233,18 @@ grl_fake_metadata_source_resolve (GrlMetadataSource *source, iter = rs->keys; while (iter) { GrlKeyID key_id = POINTER_TO_GRLKEYID (iter->data); - fill_metadata (GRL_CONTENT_MEDIA (rs->media), key_id); + fill_metadata (GRL_MEDIA (rs->media), key_id); iter = g_list_next (iter); } rs->callback (source, rs->media, rs->user_data, NULL); } + +static void +grl_fake_metadata_source_set_metadata (GrlMetadataSource *source, + GrlMetadataSourceSetMetadataSpec *sms) +{ + g_debug ("grl_fake_metadata_source_set_metadata"); + g_debug (" Faking set metadata for %d keys!", g_list_length (sms->keys)); + sms->callback (sms->source, sms->media, NULL, sms->user_data, NULL); +} diff --git a/src/filesystem/grl-filesystem.c b/src/filesystem/grl-filesystem.c index db3bc6a..7ad140d 100644 --- a/src/filesystem/grl-filesystem.c +++ b/src/filesystem/grl-filesystem.c @@ -79,7 +79,8 @@ typedef struct { static GrlFilesystemSource *grl_filesystem_source_new (void); gboolean grl_filesystem_plugin_init (GrlPluginRegistry *registry, - const GrlPluginInfo *plugin); + const GrlPluginInfo *plugin, + GList *configs); static const GList *grl_filesystem_source_supported_keys (GrlMetadataSource *source); @@ -94,7 +95,8 @@ static void grl_filesystem_source_browse (GrlMediaSource *source, gboolean grl_filesystem_plugin_init (GrlPluginRegistry *registry, - const GrlPluginInfo *plugin) + const GrlPluginInfo *plugin, + GList *configs) { g_debug ("filesystem_plugin_init\n"); @@ -234,7 +236,7 @@ file_is_valid_content (const gchar *path, gboolean fast) static void set_container_childcount (const gchar *path, - GrlContentMedia *media, + GrlMedia *media, gboolean fast) { GDir *dir; @@ -276,15 +278,15 @@ set_container_childcount (const gchar *path, g_dir_close (dir); - grl_content_box_set_childcount (GRL_CONTENT_BOX (media), count); + grl_media_box_set_childcount (GRL_MEDIA_BOX (media), count); } -static GrlContentMedia * -create_content (GrlContentMedia *content, +static GrlMedia * +create_content (GrlMedia *content, const gchar *path, gboolean only_fast) { - GrlContentMedia *media = NULL; + GrlMedia *media = NULL; gchar *str; const gchar *mime; GError *error = NULL; @@ -304,7 +306,7 @@ create_content (GrlContentMedia *content, if (error) { g_warning ("Failed to get info for file '%s': %s", path, error->message); if (!media) { - media = grl_content_media_new (); + media = grl_media_new (); } /* Title */ @@ -312,56 +314,56 @@ create_content (GrlContentMedia *content, if (!str) { str = (gchar *) path; } - grl_content_media_set_title (media, str); + grl_media_set_title (media, str); g_error_free (error); } else { mime = g_file_info_get_content_type (info); if (!media) { if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) { - media = GRL_CONTENT_MEDIA (grl_content_box_new ()); + media = GRL_MEDIA (grl_media_box_new ()); } else { if (mime_is_video (mime)) { - media = grl_content_video_new (); + media = grl_media_video_new (); } else if (mime_is_audio (mime)) { - media = grl_content_audio_new (); + media = grl_media_audio_new (); } else if (mime_is_image (mime)) { - media = grl_content_image_new (); + media = grl_media_image_new (); } else { - media = grl_content_media_new (); + media = grl_media_new (); } } } - if (!GRL_IS_CONTENT_BOX (media)) { - grl_content_media_set_mime (GRL_CONTENT (media), mime); + if (!GRL_IS_MEDIA_BOX (media)) { + grl_media_set_mime (GRL_DATA (media), mime); } /* Title */ str = (gchar *) g_file_info_get_display_name (info); - grl_content_media_set_title (media, str); + grl_media_set_title (media, str); /* Date */ GTimeVal time; gchar *time_str; g_file_info_get_modification_time (info, &time); time_str = g_time_val_to_iso8601 (&time); - grl_content_media_set_date (GRL_CONTENT (media), time_str); + grl_media_set_date (GRL_DATA (media), time_str); g_free (time_str); g_object_unref (info); } /* ID */ - grl_content_media_set_id (media, path); + grl_media_set_id (media, path); /* URL */ str = g_strconcat ("file://", path, NULL); - grl_content_media_set_url (media, str); + grl_media_set_url (media, str); g_free (str); /* Childcount */ - if (GRL_IS_CONTENT_BOX (media)) { + if (GRL_IS_MEDIA_BOX (media)) { set_container_childcount (path, media, only_fast); } @@ -383,7 +385,7 @@ browse_emit_idle (gpointer user_data) count = 0; do { gchar *entry_path; - GrlContentMedia *content; + GrlMedia *content; entry_path = (gchar *) idle_data->current->data; content = create_content (NULL, @@ -520,7 +522,7 @@ grl_filesystem_source_browse (GrlMediaSource *source, g_debug ("grl_filesystem_source_browse"); - id = grl_content_media_get_id (bs->container); + id = grl_media_get_id (bs->container); path = id ? id : G_DIR_SEPARATOR_S; produce_from_path (bs, path); } @@ -534,7 +536,7 @@ grl_filesystem_source_metadata (GrlMediaSource *source, g_debug ("grl_filesystem_source_metadata"); - id = grl_content_media_get_id (ms->media); + id = grl_media_get_id (ms->media); path = id ? id : G_DIR_SEPARATOR_S; if (g_file_test (path, G_FILE_TEST_EXISTS)) { diff --git a/src/flickr/grl-flickr.c b/src/flickr/grl-flickr.c index 4c52b16..11ac1e3 100644 --- a/src/flickr/grl-flickr.c +++ b/src/flickr/grl-flickr.c @@ -43,13 +43,6 @@ #undef G_LOG_DOMAIN #define G_LOG_DOMAIN "grl-flickr" -/* ----- Security tokens ---- */ - -#define FLICKR_KEY "fa037bee8120a921b34f8209d715a2fa" -#define FLICKR_SECRET "9f6523b9c52e3317" -#define FLICKR_FROB "416-357-743" -#define FLICKR_TOKEN "72157623286932154-c90318d470e96a29" - /* --- Plugin information --- */ #define PLUGIN_ID "grl-flickr" @@ -77,7 +70,8 @@ struct _GrlFlickrSourcePrivate { static GrlFlickrSource *grl_flickr_source_new (void); gboolean grl_flickr_plugin_init (GrlPluginRegistry *registry, - const GrlPluginInfo *plugin); + const GrlPluginInfo *plugin, + GList *configs); static const GList *grl_flickr_source_supported_keys (GrlMetadataSource *source); @@ -91,19 +85,45 @@ static void grl_flickr_source_search (GrlMediaSource *source, gboolean grl_flickr_plugin_init (GrlPluginRegistry *registry, - const GrlPluginInfo *plugin) + const GrlPluginInfo *plugin, + GList *configs) { + const gchar *flickr_key; + const gchar *flickr_secret; + const gchar *flickr_token; + const GrlConfig *config; + gint config_count; + g_debug ("flickr_plugin_init\n"); - GrlFlickrSource *source = grl_flickr_source_new (); - if (source) { - grl_plugin_registry_register_source (registry, - plugin, - GRL_MEDIA_PLUGIN (source)); - return TRUE; - } else { + if (!configs) { + g_warning ("Missing configuration"); return FALSE; } + + config_count = g_list_length (configs); + if (config_count > 1) { + g_warning ("Provided %d configs, but will only use one", config_count); + } + + config = GRL_CONFIG (configs->data); + + flickr_key = grl_config_get_api_key (config); + flickr_token = grl_config_get_api_token (config); + flickr_secret = grl_config_get_api_secret (config); + + if (!flickr_key || ! flickr_token || !flickr_secret) { + g_warning ("Required configuration keys not set up"); + return FALSE; + } + + GrlFlickrSource *source = grl_flickr_source_new (); + source->priv->flickr = g_flickr_new (flickr_key, flickr_token, flickr_secret); + + grl_plugin_registry_register_source (registry, + plugin, + GRL_MEDIA_PLUGIN (source)); + return TRUE; } GRL_PLUGIN_REGISTER (grl_flickr_plugin_init, @@ -147,7 +167,6 @@ static void grl_flickr_source_init (GrlFlickrSource *source) { source->priv = GRL_FLICKR_SOURCE_GET_PRIVATE (source); - source->priv->flickr = g_flickr_new (FLICKR_KEY, FLICKR_TOKEN, FLICKR_SECRET); } G_DEFINE_TYPE (GrlFlickrSource, grl_flickr_source, GRL_TYPE_MEDIA_SOURCE); @@ -155,7 +174,7 @@ G_DEFINE_TYPE (GrlFlickrSource, grl_flickr_source, GRL_TYPE_MEDIA_SOURCE); /* ======================= Utilities ==================== */ static void -update_media (GrlContentMedia *media, GHashTable *photo) +update_media (GrlMedia *media, GHashTable *photo) { gchar *author; gchar *date; @@ -189,32 +208,32 @@ update_media (GrlContentMedia *media, GHashTable *photo) } if (author) { - grl_content_media_set_author (media, author); + grl_media_set_author (media, author); } if (date) { - grl_content_media_set_date (media, date); + grl_media_set_date (media, date); } if (description) { - grl_content_media_set_description (media, description); + grl_media_set_description (media, description); } if (id) { - grl_content_media_set_id (media, id); + grl_media_set_id (media, id); } if (thumbnail) { - grl_content_media_set_thumbnail (media, thumbnail); + grl_media_set_thumbnail (media, thumbnail); g_free (thumbnail); } if (title) { - grl_content_media_set_title (media, title); + grl_media_set_title (media, title); } if (url) { - grl_content_media_set_url (media, url); + grl_media_set_url (media, url); g_free (url); } } @@ -234,7 +253,7 @@ getInfo_cb (GFlickr *f, GHashTable *photo, gpointer user_data) static void search_cb (GFlickr *f, GList *photolist, gpointer user_data) { - GrlContentMedia *media; + GrlMedia *media; SearchData *sd = (SearchData *) user_data; gchar *media_type; @@ -256,9 +275,9 @@ search_cb (GFlickr *f, GList *photolist, gpointer user_data) while (photolist && sd->ss->count) { media_type = g_hash_table_lookup (photolist->data, "photo_media"); if (strcmp (media_type, "photo") == 0) { - media = grl_content_image_new (); + media = grl_media_image_new (); } else { - media = grl_content_video_new (); + media = grl_media_video_new (); } update_media (media, photolist->data); sd->ss->callback (sd->ss->source, @@ -306,7 +325,7 @@ grl_flickr_source_metadata (GrlMediaSource *source, { const gchar *id; - if (!ms->media || (id = grl_content_media_get_id (ms->media)) == NULL) { + if (!ms->media || (id = grl_media_get_id (ms->media)) == NULL) { ms->callback (ms->source, ms->media, ms->user_data, NULL); return; } diff --git a/src/jamendo/grl-jamendo.c b/src/jamendo/grl-jamendo.c index 5137c3c..fef13c5 100644 --- a/src/jamendo/grl-jamendo.c +++ b/src/jamendo/grl-jamendo.c @@ -141,7 +141,8 @@ typedef struct { static GrlJamendoSource *grl_jamendo_source_new (void); gboolean grl_jamendo_plugin_init (GrlPluginRegistry *registry, - const GrlPluginInfo *plugin); + const GrlPluginInfo *plugin, + GList *configs); static const GList *grl_jamendo_source_supported_keys (GrlMetadataSource *source); @@ -164,7 +165,8 @@ static void grl_jamendo_source_cancel (GrlMediaSource *source, gboolean grl_jamendo_plugin_init (GrlPluginRegistry *registry, - const GrlPluginInfo *plugin) + const GrlPluginInfo *plugin, + GList *configs) { g_debug ("jamendo_plugin_init\n"); @@ -409,7 +411,7 @@ xml_parse_entry (xmlDocPtr doc, xmlNodePtr entry) } static void -update_media_from_entry (GrlContentMedia *media, const Entry *entry) +update_media_from_entry (GrlMedia *media, const Entry *entry) { gchar *id; @@ -420,90 +422,90 @@ update_media_from_entry (GrlContentMedia *media, const Entry *entry) } /* Common fields */ - grl_content_media_set_id (media, id); + grl_media_set_id (media, id); g_free (id); if (entry->artist_name) { - grl_content_set_string (GRL_CONTENT (media), - GRL_METADATA_KEY_ARTIST, - entry->artist_name); + grl_data_set_string (GRL_DATA (media), + GRL_METADATA_KEY_ARTIST, + entry->artist_name); } if (entry->album_name) { - grl_content_set_string (GRL_CONTENT (media), - GRL_METADATA_KEY_ALBUM, - entry->album_name); + grl_data_set_string (GRL_DATA (media), + GRL_METADATA_KEY_ALBUM, + entry->album_name); } /* Fields for artist */ if (entry->category == JAMENDO_ARTIST_CAT) { if (entry->artist_name) { - grl_content_media_set_title (media, entry->artist_name); + grl_media_set_title (media, entry->artist_name); } if (entry->artist_genre) { - grl_content_set_string (GRL_CONTENT (media), - GRL_METADATA_KEY_GENRE, - entry->artist_genre); + grl_data_set_string (GRL_DATA (media), + GRL_METADATA_KEY_GENRE, + entry->artist_genre); } if (entry->artist_url) { - grl_content_media_set_site (media, entry->artist_url); + grl_media_set_site (media, entry->artist_url); } if (entry->artist_image) { - grl_content_media_set_thumbnail (media, entry->artist_image); + grl_media_set_thumbnail (media, entry->artist_image); } /* Fields for album */ } else if (entry->category == JAMENDO_ALBUM_CAT) { if (entry->album_name) { - grl_content_media_set_title (media, entry->album_name); + grl_media_set_title (media, entry->album_name); } if (entry->album_genre) { - grl_content_set_string (GRL_CONTENT (media), - GRL_METADATA_KEY_GENRE, - entry->album_genre); + grl_data_set_string (GRL_DATA (media), + GRL_METADATA_KEY_GENRE, + entry->album_genre); } if (entry->album_url) { - grl_content_media_set_site (media, entry->album_url); + grl_media_set_site (media, entry->album_url); } if (entry->album_image) { - grl_content_media_set_thumbnail (media, entry->album_image); + grl_media_set_thumbnail (media, entry->album_image); } if (entry->album_duration) { - grl_content_media_set_duration (media, atoi (entry->album_duration)); + grl_media_set_duration (media, atoi (entry->album_duration)); } /* Fields for track */ } else if (entry->category == JAMENDO_TRACK_CAT) { if (entry->track_name) { - grl_content_media_set_title (media, entry->track_name); + grl_media_set_title (media, entry->track_name); } if (entry->album_genre) { - grl_content_audio_set_genre (GRL_CONTENT_AUDIO (media), - entry->album_genre); + grl_media_audio_set_genre (GRL_MEDIA_AUDIO (media), + entry->album_genre); } if (entry->track_url) { - grl_content_media_set_site (media, entry->track_url); + grl_media_set_site (media, entry->track_url); } if (entry->album_image) { - grl_content_media_set_thumbnail (media, entry->album_image); + grl_media_set_thumbnail (media, entry->album_image); } if (entry->track_stream) { - grl_content_media_set_url (media, entry->track_stream); + grl_media_set_url (media, entry->track_stream); } if (entry->track_duration) { - grl_content_media_set_duration (media, atoi (entry->track_duration)); + grl_media_set_duration (media, atoi (entry->track_duration)); } } } @@ -513,7 +515,7 @@ xml_parse_entries_idle (gpointer user_data) { XmlParseEntries *xpe = (XmlParseEntries *) user_data; gboolean parse_more; - GrlContentMedia *media; + GrlMedia *media; Entry *entry; g_debug ("xml_parse_entries_idle"); @@ -523,9 +525,9 @@ xml_parse_entries_idle (gpointer user_data) if (parse_more) { entry = xml_parse_entry (xpe->doc, xpe->node); if (entry->category == JAMENDO_TRACK_CAT) { - media = grl_content_audio_new (); + media = grl_media_audio_new (); } else { - media = grl_content_box_new (); + media = grl_media_box_new (); } update_media_from_entry (media, entry); @@ -642,7 +644,7 @@ read_done_cb (GObject *source_object, error = g_error_new (GRL_ERROR, GRL_ERROR_METADATA_FAILED, "Unable to get information: '%s'", - grl_content_media_get_id (xpe->spec.ms->media)); + grl_media_get_id (xpe->spec.ms->media)); } goto invoke_cb; } @@ -703,14 +705,14 @@ read_url_async (const gchar *url, gpointer user_data) } static void -update_media_from_root (GrlContentMedia *media) +update_media_from_root (GrlMedia *media) { - grl_content_media_set_title (media, JAMENDO_ROOT_NAME); - grl_content_box_set_childcount (GRL_CONTENT_BOX (media), 2); + grl_media_set_title (media, JAMENDO_ROOT_NAME); + grl_media_box_set_childcount (GRL_MEDIA_BOX (media), 2); } static void -update_media_from_artists (GrlContentMedia *media) +update_media_from_artists (GrlMedia *media) { Entry *entry; @@ -722,7 +724,7 @@ update_media_from_artists (GrlContentMedia *media) } static void -update_media_from_albums (GrlContentMedia *media) +update_media_from_albums (GrlMedia *media) { Entry *entry; @@ -736,13 +738,13 @@ update_media_from_albums (GrlContentMedia *media) static void send_toplevel_categories (GrlMediaSourceBrowseSpec *bs) { - GrlContentMedia *media; + GrlMedia *media; - media = grl_content_box_new (); + media = grl_media_box_new (); update_media_from_artists (media); bs->callback (bs->source, bs->browse_id, media, 1, bs->user_data, NULL); - media = grl_content_box_new (); + media = grl_media_box_new (); update_media_from_albums (media); bs->callback (bs->source, bs->browse_id, media, 0, bs->user_data, NULL); } @@ -831,15 +833,15 @@ grl_jamendo_source_metadata (GrlMediaSource *source, g_debug ("grl_jamendo_source_metadata"); if (!ms->media || - !grl_content_key_is_known (GRL_CONTENT (ms->media), - GRL_METADATA_KEY_ID)) { + !grl_data_key_is_known (GRL_DATA (ms->media), + GRL_METADATA_KEY_ID)) { /* Get info from root */ if (!ms->media) { - ms->media = grl_content_box_new (); + ms->media = grl_media_box_new (); } update_media_from_root (ms->media); } else { - id = grl_content_media_get_id (ms->media); + id = grl_media_get_id (ms->media); id_split = g_strsplit (id, JAMENDO_ID_SEP, 0); if (g_strv_length (id_split) == 0) { @@ -942,7 +944,7 @@ grl_jamendo_source_browse (GrlMediaSource *source, g_debug ("grl_jamendo_source_browse"); - container_id = grl_content_media_get_id (bs->container); + container_id = grl_media_get_id (bs->container); if (!container_id) { /* Root category: return top-level predefined categories */ diff --git a/src/lastfm-albumart/grl-lastfm-albumart.c b/src/lastfm-albumart/grl-lastfm-albumart.c index 8a2dbc3..40bfa7e 100644 --- a/src/lastfm-albumart/grl-lastfm-albumart.c +++ b/src/lastfm-albumart/grl-lastfm-albumart.c @@ -69,14 +69,16 @@ static const GList *grl_lastfm_albumart_source_key_depends (GrlMetadataSource *s GrlKeyID key_id); gboolean grl_lastfm_albumart_source_plugin_init (GrlPluginRegistry *registry, - const GrlPluginInfo *plugin); + const GrlPluginInfo *plugin, + GList *configs); /* =================== Last.FM-AlbumArt Plugin =============== */ gboolean grl_lastfm_albumart_source_plugin_init (GrlPluginRegistry *registry, - const GrlPluginInfo *plugin) + const GrlPluginInfo *plugin, + GList *configs) { g_debug ("grl_lastfm_albumart_source_plugin_init"); GrlLastfmAlbumartSource *source = grl_lastfm_albumart_source_new (); @@ -199,9 +201,9 @@ read_done_cb (GObject *source_object, image = xml_get_image (content); g_free (content); if (image) { - grl_content_set_string (GRL_CONTENT (rs->media), - GRL_METADATA_KEY_THUMBNAIL, - image); + grl_data_set_string (GRL_DATA (rs->media), + GRL_METADATA_KEY_THUMBNAIL, + image); g_free (image); } @@ -286,11 +288,11 @@ grl_lastfm_albumart_source_resolve (GrlMetadataSource *source, g_debug ("No supported key was requested"); rs->callback (source, rs->media, rs->user_data, NULL); } else { - artist = grl_content_get_string (GRL_CONTENT (rs->media), - GRL_METADATA_KEY_ARTIST); + artist = grl_data_get_string (GRL_DATA (rs->media), + GRL_METADATA_KEY_ARTIST); - album = grl_content_get_string (GRL_CONTENT (rs->media), - GRL_METADATA_KEY_ALBUM); + album = grl_data_get_string (GRL_DATA (rs->media), + GRL_METADATA_KEY_ALBUM); if (!artist || !album) { g_debug ("Missing dependencies"); diff --git a/src/metadata-store/Makefile.am b/src/metadata-store/Makefile.am new file mode 100644 index 0000000..4f6e9d2 --- /dev/null +++ b/src/metadata-store/Makefile.am @@ -0,0 +1,26 @@ +# +# Makefile.am +# +# Author: Iago Toral Quiroga <itoral@igalia.com> +# +# Copyright (C) 2010 Igalia S.L. All rights reserved. + +lib_LTLIBRARIES = libgrlmetadatastore.la + +libgrlmetadatastore_la_CFLAGS = \ + $(DEPS_CFLAGS) \ + $(SQLITE_CFLAGS) + +libgrlmetadatastore_la_LIBADD = \ + $(DEPS_LIBS) \ + $(SQLITE_LIBS) + +libgrlmetadatastore_la_SOURCES = grl-metadata-store.c grl-metadata-store.h + +libdir=$(GRL_PLUGINS_DIR) + +MAINTAINERCLEANFILES = \ + *.in \ + *~ + +DISTCLEANFILES = $(MAINTAINERCLEANFILES) diff --git a/src/metadata-store/grl-metadata-store.c b/src/metadata-store/grl-metadata-store.c new file mode 100644 index 0000000..0899fbf --- /dev/null +++ b/src/metadata-store/grl-metadata-store.c @@ -0,0 +1,681 @@ +/* + * Copyright (C) 2010 Igalia S.L. + * + * Contact: Iago Toral Quiroga <itoral@igalia.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <grilo.h> +#include <sqlite3.h> +#include <string.h> + +#include "grl-metadata-store.h" + +#define GRL_METADATA_STORE_GET_PRIVATE(object) \ + (G_TYPE_INSTANCE_GET_PRIVATE((object), \ + GRL_METADATA_STORE_SOURCE_TYPE, \ + GrlMetadataStorePrivate)) + +#undef G_LOG_DOMAIN +#define G_LOG_DOMAIN "grl-metadata-store" + +#define PLUGIN_ID "grl-metadata-store" +#define PLUGIN_NAME "Metadata Store" +#define PLUGIN_DESC "A plugin for storing extra metadata information" + +#define SOURCE_ID "grl-metadata-store" +#define SOURCE_NAME "Metadata Store" +#define SOURCE_DESC "A plugin for storing extra metadata information" + +#define AUTHOR "Igalia S.L." +#define LICENSE "LGPL" +#define SITE "http://www.igalia.com" + +#define GRL_SQL_DB ".grl-metadata-store" + +#define GRL_SQL_CREATE_TABLE_STORE \ + "CREATE TABLE IF NOT EXISTS store (" \ + "source_id TEXT," \ + "media_id TEXT," \ + "play_count INTEGER," \ + "rating REAL," \ + "last_position INTEGER," \ + "last_played DATE)" + +#define GRL_SQL_GET_METADATA \ + "SELECT * FROM store " \ + "WHERE source_id='%s' AND media_id='%s' " \ + "LIMIT 1" + +#define GRL_SQL_UPDATE_METADATA \ + "UPDATE store SET %s " \ + "WHERE source_id=? AND media_id=?" + +#define GRL_SQL_INSERT_METADATA \ + "INSERT INTO store " \ + "(%s source_id, media_id) VALUES " \ + "(%s ?, ?)" + +struct _GrlMetadataStorePrivate { + sqlite3 *db; +}; + +enum { + STORE_SOURCE_ID = 0, + STORE_MEDIA_ID, + STORE_PLAY_COUNT, + STORE_RATING, + STORE_LAST_POSITION, + STORE_LAST_PLAYED, +}; + +static GrlMetadataStoreSource *grl_metadata_store_source_new (void); + +static void grl_metadata_store_source_resolve (GrlMetadataSource *source, + GrlMetadataSourceResolveSpec *rs); + +static void grl_metadata_store_source_set_metadata (GrlMetadataSource *source, + GrlMetadataSourceSetMetadataSpec *sms); + +static const GList *grl_metadata_store_source_supported_keys (GrlMetadataSource *source); + +static const GList *grl_metadata_store_source_key_depends (GrlMetadataSource *source, + GrlKeyID key_id); +static const GList *grl_metadata_store_source_writable_keys (GrlMetadataSource *source); + +gboolean grl_metadata_store_source_plugin_init (GrlPluginRegistry *registry, + const GrlPluginInfo *plugin, + GList *configs); + + +/* =================== GrlMetadataStore Plugin =============== */ + +gboolean +grl_metadata_store_source_plugin_init (GrlPluginRegistry *registry, + const GrlPluginInfo *plugin, + GList *configs) +{ + g_debug ("grl_metadata_store_source_plugin_init"); + GrlMetadataStoreSource *source = grl_metadata_store_source_new (); + grl_plugin_registry_register_source (registry, + plugin, + GRL_MEDIA_PLUGIN (source)); + return TRUE; +} + +GRL_PLUGIN_REGISTER (grl_metadata_store_source_plugin_init, + NULL, + PLUGIN_ID, + PLUGIN_NAME, + PLUGIN_DESC, + PACKAGE_VERSION, + AUTHOR, + LICENSE, + SITE); + +/* ================== GrlMetadataStore GObject ================ */ + +static GrlMetadataStoreSource * +grl_metadata_store_source_new (void) +{ + g_debug ("grl_metadata_store_source_new"); + return g_object_new (GRL_METADATA_STORE_SOURCE_TYPE, + "source-id", SOURCE_ID, + "source-name", SOURCE_NAME, + "source-desc", SOURCE_DESC, + NULL); +} + +static void +grl_metadata_store_source_class_init (GrlMetadataStoreSourceClass * klass) +{ + GrlMetadataSourceClass *metadata_class = GRL_METADATA_SOURCE_CLASS (klass); + metadata_class->supported_keys = grl_metadata_store_source_supported_keys; + metadata_class->key_depends = grl_metadata_store_source_key_depends; + metadata_class->writable_keys = grl_metadata_store_source_writable_keys; + metadata_class->resolve = grl_metadata_store_source_resolve; + metadata_class->set_metadata = grl_metadata_store_source_set_metadata; + + g_type_class_add_private (klass, sizeof (GrlMetadataStorePrivate)); +} + +static void +grl_metadata_store_source_init (GrlMetadataStoreSource *source) +{ + gint r; + const gchar *home; + gchar *db_path; + gchar *sql_error = NULL; + + source->priv = GRL_METADATA_STORE_GET_PRIVATE (source); + memset (source->priv, 0, sizeof (GrlMetadataStorePrivate)); + + home = g_getenv ("HOME"); + if (!home) { + g_warning ("$HOME not set, cannot open database"); + return; + } + + g_debug ("Opening database connection..."); + db_path = g_strconcat (home, G_DIR_SEPARATOR_S, GRL_SQL_DB, NULL); + r = sqlite3_open (db_path, &source->priv->db); + if (r) { + g_critical ("Failed to open database '%s': %s", + db_path, sqlite3_errmsg (source->priv->db)); + sqlite3_close (source->priv->db); + return; + } + g_debug (" OK"); + + g_debug ("Checking database tables..."); + r = sqlite3_exec (source->priv->db, GRL_SQL_CREATE_TABLE_STORE, + NULL, NULL, &sql_error); + + if (r) { + if (sql_error) { + g_warning ("Failed to create database tables: %s", sql_error); + sqlite3_free (sql_error); + sql_error = NULL; + } else { + g_warning ("Failed to create database tables."); + } + sqlite3_close (source->priv->db); + return; + } + g_debug (" OK"); + + g_free (db_path); +} + +G_DEFINE_TYPE (GrlMetadataStoreSource, grl_metadata_store_source, + GRL_TYPE_METADATA_SOURCE); + +/* ======================= Utilities ==================== */ + +static sqlite3_stmt * +query_metadata_store (sqlite3 *db, + const gchar *source_id, + const gchar *media_id) +{ + gint r; + sqlite3_stmt *sql_stmt = NULL; + gchar *sql; + + g_debug ("get_metadata"); + + sql = g_strdup_printf (GRL_SQL_GET_METADATA, source_id, media_id); + g_debug ("%s", sql); + r = sqlite3_prepare_v2 (db, sql, strlen (sql), &sql_stmt, NULL); + g_free (sql); + + if (r != SQLITE_OK) { + g_warning ("Failed to get metadata: %s", sqlite3_errmsg (db)); + return NULL; + } + + return sql_stmt; +} + +static void +fill_metadata (GrlMedia *media, GList *keys, sqlite3_stmt *stmt) +{ + GList *iter; + gint play_count, last_position; + gdouble rating; + gchar *last_played, *rating_str; + gint r; + + while ((r = sqlite3_step (stmt)) == SQLITE_BUSY); + + if (r != SQLITE_ROW) { + /* No info in DB for this item, bail out silently */ + sqlite3_finalize (stmt); + return; + } + + iter = keys; + while (iter) { + GrlKeyID key_id = POINTER_TO_GRLKEYID (iter->data); + switch (key_id) { + case GRL_METADATA_KEY_PLAY_COUNT: + play_count = sqlite3_column_int (stmt, STORE_PLAY_COUNT); + grl_media_set_play_count (media, play_count); + break; + case GRL_METADATA_KEY_RATING: + rating = sqlite3_column_double (stmt, STORE_RATING); + rating_str = g_strdup_printf ("%.2f", rating); + grl_media_set_rating (media, rating_str, "5"); + g_free (rating_str); + break; + case GRL_METADATA_KEY_LAST_PLAYED: + last_played = (gchar *) sqlite3_column_text (stmt, STORE_LAST_PLAYED); + grl_media_set_last_played (media, last_played); + break; + case GRL_METADATA_KEY_LAST_POSITION: + last_position = sqlite3_column_int (stmt, STORE_LAST_POSITION); + grl_media_set_last_position (media, last_position); + break; + default: + break; + } + iter = g_list_next (iter); + } + + sqlite3_finalize (stmt); +} + +static const gchar * +get_column_name_from_key_id (GrlKeyID key_id) +{ + static const gchar *col_names[] = {"rating", "last_played", "last_position", + "play_count"}; + switch (key_id) { + case GRL_METADATA_KEY_RATING: + return col_names[0]; + case GRL_METADATA_KEY_LAST_PLAYED: + return col_names[1]; + case GRL_METADATA_KEY_LAST_POSITION: + return col_names[2]; + case GRL_METADATA_KEY_PLAY_COUNT: + return col_names[3]; + default: + return NULL; + } +} + +static gboolean +bind_and_exec (sqlite3 *db, + const gchar *sql, + const gchar *source_id, + const gchar *media_id, + GList *col_names, + GList *keys, + GrlMedia *media) +{ + gint r; + const gchar *char_value; + gint int_value; + double double_value; + GList *iter_names, *iter_keys; + guint count; + sqlite3_stmt *stmt; + + /* Create statement from sql */ + g_debug ("%s", sql); + r = sqlite3_prepare_v2 (db, sql, strlen (sql), &stmt, NULL); + + if (r != SQLITE_OK) { + g_warning ("Failed to update metadata for '%s - %s': %s", + source_id, media_id, sqlite3_errmsg (db)); + sqlite3_finalize (stmt); + return FALSE; + } + + /* Bind column values */ + count = 1; + iter_names = col_names; + iter_keys = keys; + while (iter_names) { + if (iter_names->data) { + GrlKeyID key_id = POINTER_TO_GRLKEYID (iter_keys->data); + switch (key_id) { + case GRL_METADATA_KEY_RATING: + char_value = grl_media_get_rating (media); + if (char_value) { + double_value = g_ascii_strtod (char_value, NULL); + } else { + double_value = 0; + } + sqlite3_bind_double (stmt, count, double_value); + break; + case GRL_METADATA_KEY_PLAY_COUNT: + int_value = grl_media_get_play_count (media); + sqlite3_bind_int (stmt, count, int_value); + break; + case GRL_METADATA_KEY_LAST_POSITION: + int_value = grl_media_get_last_position (media); + sqlite3_bind_int (stmt, count, int_value); + break; + case GRL_METADATA_KEY_LAST_PLAYED: + char_value = grl_media_get_last_played (media); + sqlite3_bind_text (stmt, count, char_value, -1, SQLITE_STATIC); + break; + default: + break; + } + count++; + } + iter_keys = g_list_next (iter_keys); + iter_names = g_list_next (iter_names); + } + + sqlite3_bind_text (stmt, count++, source_id, -1, SQLITE_STATIC); + sqlite3_bind_text (stmt, count++, media_id, -1, SQLITE_STATIC); + + /* execute query */ + while ((r = sqlite3_step (stmt)) == SQLITE_BUSY); + + sqlite3_finalize (stmt); + + return (r == SQLITE_DONE); +} + +static gboolean +prepare_and_exec_update (sqlite3 *db, + const gchar *source_id, + const gchar *media_id, + GList *col_names, + GList *keys, + GrlMedia *media) +{ + gchar *sql; + gint r; + GList *iter_names; + GString *sql_buf; + gchar *sql_set; + guint count; + + g_debug ("prepare_and_exec_update"); + + /* Prepare sql "set" for update query */ + count = 0; + sql_buf = g_string_new (""); + iter_names = col_names; + while (iter_names) { + gchar *col_name = (gchar *) iter_names->data; + if (col_name) { + if (count > 0) { + g_string_append (sql_buf, " AND "); + } + g_string_append_printf (sql_buf, "%s=?", col_name); + count++; + } + iter_names = g_list_next (iter_names); + } + sql_set = g_string_free (sql_buf, FALSE); + + /* Execute query */ + sql = g_strdup_printf (GRL_SQL_UPDATE_METADATA, sql_set); + r = bind_and_exec (db, sql, source_id, media_id, col_names, keys, media); + g_free (sql); + g_free (sql_set); + + return r; +} + +static gboolean +prepare_and_exec_insert (sqlite3 *db, + const gchar *source_id, + const gchar *media_id, + GList *col_names, + GList *keys, + GrlMedia *media) +{ + gchar *sql; + gint r; + GList *iter_names; + GString *sql_buf_cols, *sql_buf_values; + gchar *sql_cols, *sql_values; + + g_debug ("prepare_and_exec_insert"); + + /* Prepare sql for insert query */ + sql_buf_cols = g_string_new (""); + sql_buf_values = g_string_new (""); + iter_names = col_names; + while (iter_names) { + gchar *col_name = (gchar *) iter_names->data; + if (col_name) { + g_string_append_printf (sql_buf_cols, "%s, ", col_name); + g_string_append (sql_buf_values, "?, "); + } + iter_names = g_list_next (iter_names); + } + sql_cols = g_string_free (sql_buf_cols, FALSE); + sql_values = g_string_free (sql_buf_values, FALSE); + + /* Execute query */ + sql = g_strdup_printf (GRL_SQL_INSERT_METADATA, sql_cols, sql_values); + r = bind_and_exec (db, sql, source_id, media_id, col_names, keys, media); + g_free (sql); + g_free (sql_cols); + g_free (sql_values); + + return r; +} + +static GList * +write_keys (sqlite3 *db, + const gchar *source_id, + const gchar *media_id, + GrlMetadataSourceSetMetadataSpec *sms, + GError **error) +{ + GList *col_names = NULL; + GList *iter; + GList *failed_keys = NULL; + guint supported_keys = 0; + gint r; + + /* Get DB column names for each key to be updated */ + iter = sms->keys; + while (iter) { + GrlKeyID key_id = POINTER_TO_GRLKEYID (iter->data); + const gchar *col_name = get_column_name_from_key_id (key_id); + if (!col_name) { + g_warning ("Key %u is not supported for writing, ignoring...", key_id); + failed_keys = g_list_prepend (failed_keys, GRLKEYID_TO_POINTER (key_id)); + } else { + supported_keys++; + } + col_names = g_list_prepend (col_names, (gchar *) col_name); + iter = g_list_next (iter); + } + col_names = g_list_reverse (col_names); + + if (supported_keys == 0) { + g_warning ("Failed to update metadata, none of the specified " + "keys is writable"); + *error = g_error_new (GRL_ERROR, + GRL_ERROR_SET_METADATA_FAILED, + "Failed to update metadata, " + "specified keys are not writable"); + goto done; + } + + r = prepare_and_exec_update (db, + source_id, + media_id, + col_names, + sms->keys, + sms->media); + + if (!r) { + g_warning ("Failed to update metadata for '%s - %s': %s", + source_id, media_id, sqlite3_errmsg (db)); + g_list_free (failed_keys); + failed_keys = g_list_copy (sms->keys); + *error = g_error_new (GRL_ERROR, + GRL_ERROR_SET_METADATA_FAILED, + "Failed to update metadata"); + goto done; + } + + if (sqlite3_changes (db) == 0) { + /* We have to create the row */ + r = prepare_and_exec_insert (db, + source_id, + media_id, + col_names, + sms->keys, + sms->media); + } + + if (!r) { + g_warning ("Failed to update metadata for '%s - %s': %s", + source_id, media_id, sqlite3_errmsg (db)); + g_list_free (failed_keys); + failed_keys = g_list_copy (sms->keys); + *error = g_error_new (GRL_ERROR, + GRL_ERROR_SET_METADATA_FAILED, + "Failed to update metadata"); + goto done; + } + + done: + g_list_free (col_names); + return failed_keys; +} + +/* ================== API Implementation ================ */ + +static const GList * +grl_metadata_store_source_supported_keys (GrlMetadataSource *source) +{ + static GList *keys = NULL; + if (!keys) { + keys = grl_metadata_key_list_new (GRL_METADATA_KEY_RATING, + GRL_METADATA_KEY_PLAY_COUNT, + GRL_METADATA_KEY_LAST_PLAYED, + GRL_METADATA_KEY_LAST_POSITION, + NULL); + } + return keys; +} + +static const GList * +grl_metadata_store_source_writable_keys (GrlMetadataSource *source) +{ + static GList *keys = NULL; + if (!keys) { + keys = grl_metadata_key_list_new (GRL_METADATA_KEY_RATING, + GRL_METADATA_KEY_PLAY_COUNT, + GRL_METADATA_KEY_LAST_PLAYED, + GRL_METADATA_KEY_LAST_POSITION, + NULL); + } + return keys; +} + +static const GList * +grl_metadata_store_source_key_depends (GrlMetadataSource *source, + GrlKeyID key_id) +{ + static GList *deps = NULL; + if (!deps) { + deps = grl_metadata_key_list_new (GRL_METADATA_KEY_ID, NULL); + } + + switch (key_id) { + case GRL_METADATA_KEY_RATING: + case GRL_METADATA_KEY_PLAY_COUNT: + case GRL_METADATA_KEY_LAST_PLAYED: + case GRL_METADATA_KEY_LAST_POSITION: + return deps; + default: + break; + } + + return NULL; +} + +static void +grl_metadata_store_source_resolve (GrlMetadataSource *source, + GrlMetadataSourceResolveSpec *rs) +{ + g_debug ("grl_metadata_store_source_resolve"); + + const gchar *source_id, *media_id; + sqlite3_stmt *stmt; + GError *error = NULL; + + source_id = grl_media_get_source (rs->media); + media_id = grl_media_get_id (rs->media); + + /* We need the source id */ + if (!source_id) { + g_warning ("Failed to resolve metadata: source-id not available"); + error = g_error_new (GRL_ERROR, + GRL_ERROR_RESOLVE_FAILED, + "source-id not available, cannot resolve metadata."); + rs->callback (rs->source, rs->media, rs->user_data, error); + g_error_free (error); + return; + } + + /* Special case for root categories */ + if (!media_id) { + media_id = ""; + } + + stmt = query_metadata_store (GRL_METADATA_STORE_SOURCE (source)->priv->db, + source_id, media_id); + if (stmt) { + fill_metadata (rs->media, rs->keys, stmt); + rs->callback (rs->source, rs->media, rs->user_data, NULL); + } else { + g_warning ("Failed to resolve metadata"); + error = g_error_new (GRL_ERROR, + GRL_ERROR_RESOLVE_FAILED, + "Failed to resolve metadata."); + rs->callback (rs->source, rs->media, rs->user_data, error); + g_error_free (error); + } +} + +static void +grl_metadata_store_source_set_metadata (GrlMetadataSource *source, + GrlMetadataSourceSetMetadataSpec *sms) +{ + g_debug ("grl_metadata_store_source_set_metadata"); + + const gchar *media_id, *source_id; + GError *error = NULL; + GList *failed_keys = NULL; + + source_id = grl_media_get_source (sms->media); + media_id = grl_media_get_id (sms->media); + + /* We need the source id */ + if (!source_id) { + g_warning ("Failed to update metadata: source-id not available"); + error = g_error_new (GRL_ERROR, + GRL_ERROR_SET_METADATA_FAILED, + "source-id not available, cannot update metadata."); + failed_keys = g_list_copy (sms->keys); + } else { + /* Special case for root categories */ + if (!media_id) { + media_id = ""; + } + + failed_keys = write_keys (GRL_METADATA_STORE_SOURCE (source)->priv->db, + source_id, media_id, sms, &error); + } + + sms->callback (sms->source, sms->media, failed_keys, sms->user_data, error); + + if (error) { + g_error_free (error); + } + g_list_free (failed_keys); +} diff --git a/src/metadata-store/grl-metadata-store.h b/src/metadata-store/grl-metadata-store.h new file mode 100644 index 0000000..47df494 --- /dev/null +++ b/src/metadata-store/grl-metadata-store.h @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2010 Igalia S.L. + * + * Contact: Iago Toral Quiroga <itoral@igalia.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifndef _GRL_METADATA_STORE_SOURCE_H_ +#define _GRL_METADATA_STORE_SOURCE_H_ + +#include <grilo.h> + +#define GRL_METADATA_STORE_SOURCE_TYPE \ + (grl_metadata_store_source_get_type ()) + +#define GRL_METADATA_STORE_SOURCE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + GRL_METADATA_STORE_SOURCE_TYPE, \ + GrlMetadataStoreSource)) + +#define GRL_IS_METADATA_STORE_SOURCE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ + GRL_METADATA_STORE_SOURCE_TYPE)) + +#define GRL_METADATA_STORE_SOURCE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), \ + GRL_METADATA_STORE_SOURCE_TYPE, \ + GrlMetadataStoreSourceClass)) + +#define GRL_IS_METADATA_STORE_SOURCE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), \ + GRL_METADATA_STORE_SOURCE_TYPE)) + +#define GRL_METADATA_STORE_SOURCE_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), \ + GRL_METADATA_STORE_SOURCE_TYPE, \ + GrlMetadataStoreSourceClass)) + +typedef struct _GrlMetadataStorePrivate GrlMetadataStorePrivate; +typedef struct _GrlMetadataStoreSource GrlMetadataStoreSource; + +struct _GrlMetadataStoreSource { + + GrlMetadataSource parent; + + /*< private >*/ + GrlMetadataStorePrivate *priv; +}; + +typedef struct _GrlMetadataStoreSourceClass GrlMetadataStoreSourceClass; + +struct _GrlMetadataStoreSourceClass { + + GrlMetadataSourceClass parent_class; + +}; + +GType grl_metadata_store_source_get_type (void); + +#endif /* _GRL_METADATA_STORE_SOURCE_H_ */ diff --git a/src/podcasts/grl-podcasts.c b/src/podcasts/grl-podcasts.c index bec5145..12ee7ee 100644 --- a/src/podcasts/grl-podcasts.c +++ b/src/podcasts/grl-podcasts.c @@ -210,7 +210,7 @@ typedef struct { guint parse_count; guint parse_index; guint parse_valid_index; - GrlContentMedia *last_media; + GrlMedia *last_media; } OperationSpecParse; static GrlPodcastsSource *grl_podcasts_source_new (void); @@ -236,7 +236,8 @@ static void grl_podcasts_source_remove (GrlMediaSource *source, static gboolean grl_podcasts_plugin_init (GrlPluginRegistry *registry, - const GrlPluginInfo *plugin) + const GrlPluginInfo *plugin, + GList *configs) { g_debug ("podcasts_plugin_init\n"); @@ -502,8 +503,8 @@ get_site_from_url (const gchar *url) return g_strndup (url, p - url); } -static GrlContentMedia * -build_media (GrlContentMedia *content, +static GrlMedia * +build_media (GrlMedia *content, gboolean is_podcast, const gchar *id, const gchar *title, @@ -514,7 +515,7 @@ build_media (GrlContentMedia *content, guint duration, guint childcount) { - GrlContentMedia *media = NULL; + GrlMedia *media = NULL; gchar *site; if (content) { @@ -523,52 +524,52 @@ build_media (GrlContentMedia *content, if (is_podcast) { if (!media) { - media = GRL_CONTENT_MEDIA (grl_content_box_new ()); + media = GRL_MEDIA (grl_media_box_new ()); } - grl_content_media_set_id (media, id); + grl_media_set_id (media, id); if (desc) - grl_content_media_set_description (media, desc); - grl_content_box_set_childcount (GRL_CONTENT_BOX (media), childcount); + grl_media_set_description (media, desc); + grl_media_box_set_childcount (GRL_MEDIA_BOX (media), childcount); } else { if (!media) { if (mime_is_audio (mime)) { - media = grl_content_audio_new (); + media = grl_media_audio_new (); } else if (mime_is_video (mime)) { - media = grl_content_video_new (); + media = grl_media_video_new (); } else { - media = grl_content_media_new (); + media = grl_media_new (); } } - grl_content_media_set_id (media, url); + grl_media_set_id (media, url); if (date) - grl_content_media_set_date (media, date); + grl_media_set_date (media, date); if (desc) - grl_content_media_set_description (media, desc); + grl_media_set_description (media, desc); if (mime) - grl_content_media_set_mime (media, mime); + grl_media_set_mime (media, mime); if (duration > 0) { - grl_content_media_set_duration (media, duration); + grl_media_set_duration (media, duration); } } - grl_content_media_set_title (media, title); - grl_content_media_set_url (media, url); + grl_media_set_title (media, title); + grl_media_set_url (media, url); site = get_site_from_url (url); if (site) { - grl_content_media_set_site (media, site); + grl_media_set_site (media, site); g_free (site); } return media; } -static GrlContentMedia * +static GrlMedia * build_media_from_entry (Entry *entry) { - GrlContentMedia *media; + GrlMedia *media; gint duration; duration = duration_to_seconds (entry->duration); @@ -579,12 +580,12 @@ build_media_from_entry (Entry *entry) return media; } -static GrlContentMedia * -build_media_from_stmt (GrlContentMedia *content, +static GrlMedia * +build_media_from_stmt (GrlMedia *content, sqlite3_stmt *sql_stmt, gboolean is_podcast) { - GrlContentMedia *media; + GrlMedia *media; gchar *id; gchar *title; gchar *url; @@ -624,7 +625,7 @@ produce_podcast_contents_from_db (OperationSpec *os) sqlite3_stmt *sql_stmt = NULL; GList *iter, *medias = NULL; guint count = 0; - GrlContentMedia *media; + GrlMedia *media; gint r; GError *error = NULL; @@ -673,7 +674,7 @@ produce_podcast_contents_from_db (OperationSpec *os) medias = g_list_reverse (medias); iter = medias; while (iter) { - media = GRL_CONTENT_MEDIA (iter->data); + media = GRL_MEDIA (iter->data); os->callback (os->source, os->operation_id, media, @@ -760,19 +761,20 @@ remove_stream (sqlite3 *db, const gchar *url, GError **error) } static void -store_podcast (sqlite3 *db, GrlContentMedia *podcast, GError **error) +store_podcast (sqlite3 *db, GrlMedia *podcast, GError **error) { gint r; sqlite3_stmt *sql_stmt = NULL; const gchar *title; const gchar *url; const gchar *desc; + gchar *id; g_debug ("store_podcast"); - title = grl_content_media_get_title (podcast); - url = grl_content_media_get_url (podcast); - desc = grl_content_media_get_description (podcast); + title = grl_media_get_title (podcast); + url = grl_media_get_url (podcast); + desc = grl_media_get_description (podcast); g_debug ("%s", GRL_SQL_STORE_PODCAST); r = sqlite3_prepare_v2 (db, @@ -807,6 +809,10 @@ store_podcast (sqlite3 *db, GrlContentMedia *podcast, GError **error) } sqlite3_finalize (sql_stmt); + + id = g_strdup_printf ("%llu", sqlite3_last_insert_rowid (db)); + grl_media_set_id (podcast, id); + g_free (id); } static void @@ -909,7 +915,7 @@ parse_entry_idle (gpointer user_data) OperationSpecParse *osp = (OperationSpecParse *) user_data; xmlNodeSetPtr nodes; guint remaining; - GrlContentMedia *media; + GrlMedia *media; nodes = osp->xpathObj->nodesetval; @@ -1083,40 +1089,52 @@ read_feed_cb (gchar *xmldata, gpointer user_data) } } -static void -produce_podcast_contents (OperationSpec *os) +static sqlite3_stmt * +get_podcast_info (sqlite3 *db, const gchar *podcast_id) { gint r; sqlite3_stmt *sql_stmt = NULL; - sqlite3 *db; - GError *error = NULL; gchar *sql; - gchar *url; - g_debug ("produce_podcast_contents"); + g_debug ("get_podcast_info"); - /* First we get some information about the podcast */ - db = GRL_PODCASTS_SOURCE (os->source)->priv->db; - sql = g_strdup_printf (GRL_SQL_GET_PODCAST_BY_ID, os->media_id); + sql = g_strdup_printf (GRL_SQL_GET_PODCAST_BY_ID, podcast_id); g_debug ("%s", sql); r = sqlite3_prepare_v2 (db, sql, strlen (sql), &sql_stmt, NULL); g_free (sql); if (r != SQLITE_OK) { g_warning ("Failed to retrieve podcast '%s': %s", - os->media_id, sqlite3_errmsg (db)); - error = g_error_new (GRL_ERROR, - os->error_code, - "Failed to retrieve podcast information"); - os->callback (os->source, os->operation_id, NULL, 0, os->user_data, error); - g_error_free (error); - g_free (os); - return; + podcast_id, sqlite3_errmsg (db)); + return NULL; } while ((r = sqlite3_step (sql_stmt)) == SQLITE_BUSY); if (r == SQLITE_ROW) { + return sql_stmt; + } else { + g_warning ("Failed to retrieve podcast information: %s", + sqlite3_errmsg (db)); + sqlite3_finalize (sql_stmt); + return NULL; + } +} + +static void +produce_podcast_contents (OperationSpec *os) +{ + sqlite3_stmt *sql_stmt = NULL; + sqlite3 *db; + GError *error; + gchar *url; + + g_debug ("produce_podcast_contents"); + + /* First we get some information about the podcast */ + db = GRL_PODCASTS_SOURCE (os->source)->priv->db; + sql_stmt = get_podcast_info (db, os->media_id); + if (sql_stmt) { gchar *lr_str; GTimeVal lr; GTimeVal now; @@ -1138,9 +1156,8 @@ produce_podcast_contents (OperationSpec *os) produce_podcast_contents_from_db (os); g_free (os); } + sqlite3_finalize (sql_stmt); } else { - g_warning ("Failed to retrieve podcast information: %s", - sqlite3_errmsg (db)); error = g_error_new (GRL_ERROR, os->error_code, "Failed to retrieve podcast information"); @@ -1149,7 +1166,6 @@ produce_podcast_contents (OperationSpec *os) g_free (os); } - sqlite3_finalize (sql_stmt); } static void @@ -1158,7 +1174,7 @@ produce_podcasts (OperationSpec *os) gint r; sqlite3_stmt *sql_stmt = NULL; sqlite3 *db; - GrlContentMedia *media; + GrlMedia *media; GError *error = NULL; GList *medias = NULL; guint count = 0; @@ -1218,7 +1234,7 @@ produce_podcasts (OperationSpec *os) medias = g_list_reverse (medias); iter = medias; while (iter) { - media = GRL_CONTENT_MEDIA (iter->data); + media = GRL_MEDIA (iter->data); os->callback (os->source, os->operation_id, media, @@ -1251,7 +1267,7 @@ stream_metadata (GrlMediaSourceMetadataSpec *ms) db = GRL_PODCASTS_SOURCE (ms->source)->priv->db; - id = grl_content_media_get_id (ms->media); + id = grl_media_get_id (ms->media); sql = g_strdup_printf (GRL_SQL_GET_PODCAST_STREAM, id); g_debug ("%s", sql); r = sqlite3_prepare_v2 (db, sql, strlen (sql), &sql_stmt, NULL); @@ -1287,45 +1303,29 @@ stream_metadata (GrlMediaSourceMetadataSpec *ms) static void podcast_metadata (GrlMediaSourceMetadataSpec *ms) { - gint r; sqlite3_stmt *sql_stmt = NULL; sqlite3 *db; GError *error = NULL; - gchar *sql; const gchar *id; g_debug ("podcast_metadata"); db = GRL_PODCASTS_SOURCE (ms->source)->priv->db; - id = grl_content_media_get_id (ms->media); + id = grl_media_get_id (ms->media); if (!id) { /* Root category: special case */ - grl_content_media_set_title (ms->media, ""); + grl_media_set_title (ms->media, ""); ms->callback (ms->source, ms->media, ms->user_data, NULL); return; } - sql = g_strdup_printf (GRL_SQL_GET_PODCAST_BY_ID, id); - g_debug ("%s", sql); - r = sqlite3_prepare_v2 (db, sql, strlen (sql), &sql_stmt, NULL); - g_free (sql); + sql_stmt = get_podcast_info (db, id); - if (r != SQLITE_OK) { - g_warning ("Failed to get podcast: %s", sqlite3_errmsg (db)); - error = g_error_new (GRL_ERROR, - GRL_ERROR_METADATA_FAILED, - "Failed to get podcast metadata"); - ms->callback (ms->source, ms->media, ms->user_data, error); - g_error_free (error); - return; - } - - while ((r = sqlite3_step (sql_stmt)) == SQLITE_BUSY); - - if (r == SQLITE_ROW) { + if (sql_stmt) { build_media_from_stmt (ms->media, sql_stmt, TRUE); ms->callback (ms->source, ms->media, ms->user_data, NULL); + sqlite3_finalize (sql_stmt); } else { g_warning ("Failed to get podcast: %s", sqlite3_errmsg (db)); error = g_error_new (GRL_ERROR, @@ -1334,8 +1334,6 @@ podcast_metadata (GrlMediaSourceMetadataSpec *ms) ms->callback (ms->source, ms->media, ms->user_data, error); g_error_free (error); } - - sqlite3_finalize (sql_stmt); } static gboolean @@ -1385,7 +1383,7 @@ grl_podcasts_source_browse (GrlMediaSource *source, os = g_new0 (OperationSpec, 1); os->source = bs->source; os->operation_id = bs->browse_id; - os->media_id = grl_content_media_get_id (bs->container); + os->media_id = grl_media_get_id (bs->container); os->count = bs->count; os->skip = bs->skip; os->callback = bs->callback; @@ -1490,7 +1488,7 @@ grl_podcasts_source_metadata (GrlMediaSource *source, g_error_free (error); } - media_id = grl_content_media_get_id (ms->media); + media_id = grl_media_get_id (ms->media); if (!media_id || media_id_is_podcast (media_id)) { podcast_metadata (ms); } else { @@ -1503,7 +1501,7 @@ grl_podcasts_source_store (GrlMediaSource *source, GrlMediaSourceStoreSpec *ss) { g_debug ("grl_podcasts_source_store"); GError *error = NULL; - if (GRL_IS_CONTENT_BOX (ss->media)) { + if (GRL_IS_MEDIA_BOX (ss->media)) { error = g_error_new (GRL_ERROR, GRL_ERROR_STORE_FAILED, "Cannot create containers. Only feeds are accepted."); diff --git a/src/shoutcast/grl-shoutcast.c b/src/shoutcast/grl-shoutcast.c index 041799e..ea1ddc5 100644 --- a/src/shoutcast/grl-shoutcast.c +++ b/src/shoutcast/grl-shoutcast.c @@ -65,7 +65,7 @@ #define SITE "http://www.igalia.com" typedef struct { - GrlContentMedia *media; + GrlMedia *media; GrlMediaSource *source; GrlMediaSourceMetadataCb metadata_cb; GrlMediaSourceResultCb result_cb; @@ -85,7 +85,8 @@ typedef struct { static GrlShoutcastSource *grl_shoutcast_source_new (void); gboolean grl_shoutcast_plugin_init (GrlPluginRegistry *registry, - const GrlPluginInfo *plugin); + const GrlPluginInfo *plugin, + GList *configs); static const GList *grl_shoutcast_source_supported_keys (GrlMetadataSource *source); @@ -105,7 +106,8 @@ static void grl_shoutcast_source_cancel (GrlMediaSource *source, gboolean grl_shoutcast_plugin_init (GrlPluginRegistry *registry, - const GrlPluginInfo *plugin) + const GrlPluginInfo *plugin, + GList *configs) { g_debug ("shoutcast_plugin_init\n"); @@ -185,35 +187,35 @@ xml_count_nodes (xmlNodePtr node) return count; } -static GrlContentMedia * +static GrlMedia * build_media_from_genre (OperationData *op_data) { - GrlContentMedia *media; + GrlMedia *media; gchar *genre_name; if (op_data->media) { media = op_data->media; } else { - media = grl_content_box_new (); + media = grl_media_box_new (); } genre_name = (gchar *) xmlGetProp (op_data->xml_entries, (const xmlChar *) "name"); - grl_content_media_set_id (media, genre_name); - grl_content_media_set_title (media, genre_name); - grl_content_set_string (GRL_CONTENT (media), - GRL_METADATA_KEY_GENRE, - genre_name); + grl_media_set_id (media, genre_name); + grl_media_set_title (media, genre_name); + grl_data_set_string (GRL_DATA (media), + GRL_METADATA_KEY_GENRE, + genre_name); g_free (genre_name); return media; } -static GrlContentMedia * +static GrlMedia * build_media_from_station (OperationData *op_data) { - GrlContentMedia *media; + GrlMedia *media; gchar *media_id; gchar *media_url; gchar *station_bitrate; @@ -238,16 +240,16 @@ build_media_from_station (OperationData *op_data) if (op_data->media) { media = op_data->media; } else { - media = grl_content_audio_new (); + media = grl_media_audio_new (); } - grl_content_media_set_id (media, media_id); - grl_content_media_set_title (media, station_name); - grl_content_media_set_mime (media, station_mime); - grl_content_audio_set_genre (GRL_CONTENT_AUDIO (media), station_genre); - grl_content_media_set_url (media, media_url); - grl_content_audio_set_bitrate (GRL_CONTENT_AUDIO (media), - atoi (station_bitrate)); + grl_media_set_id (media, media_id); + grl_media_set_title (media, station_name); + grl_media_set_mime (media, station_mime); + grl_media_audio_set_genre (GRL_MEDIA_AUDIO (media), station_genre); + grl_media_set_url (media, media_url); + grl_media_audio_set_bitrate (GRL_MEDIA_AUDIO (media), + atoi (station_bitrate)); g_free (station_name); g_free (station_mime); @@ -261,7 +263,7 @@ build_media_from_station (OperationData *op_data) } static gboolean -send_media (OperationData *op_data, GrlContentMedia *media) +send_media (OperationData *op_data, GrlMedia *media) { if (!op_data->cancelled) { op_data->result_cb (op_data->source, @@ -364,7 +366,7 @@ xml_parse_result (const gchar *str, OperationData *op_data) error = g_error_new (GRL_ERROR, op_data->error_code, "Can not find media '%s'", - grl_content_media_get_id (op_data->media)); + grl_media_get_id (op_data->media)); } if (xpath_res) { xmlXPathFreeObject (xpath_res); @@ -522,11 +524,11 @@ grl_shoutcast_source_metadata (GrlMediaSource *source, repeat the Pop browsing and get the result with station id 1321. If it doesn't exist (think in results obtained from a search), we do nothing */ - media_id = grl_content_media_get_id (ms->media); + media_id = grl_media_get_id (ms->media); /* Check if we need to report about root category */ if (!media_id) { - grl_content_media_set_title (ms->media, "SHOUTcast"); + grl_media_set_title (ms->media, "SHOUTcast"); } else { data = g_new0 (OperationData, 1); data->source = source; @@ -587,7 +589,7 @@ grl_shoutcast_source_browse (GrlMediaSource *source, data->user_data = bs->user_data; data->error_code = GRL_ERROR_BROWSE_FAILED; - container_id = grl_content_media_get_id (bs->container); + container_id = grl_media_get_id (bs->container); /* If it's root category send list of genres; else send list of radios */ if (!container_id) { diff --git a/src/upnp/grl-upnp.c b/src/upnp/grl-upnp.c index 815ec13..af2166b 100644 --- a/src/upnp/grl-upnp.c +++ b/src/upnp/grl-upnp.c @@ -102,7 +102,8 @@ static gchar *build_source_id (const gchar *udn); static GrlUpnpSource *grl_upnp_source_new (const gchar *id, const gchar *name); gboolean grl_upnp_plugin_init (GrlPluginRegistry *registry, - const GrlPluginInfo *plugin); + const GrlPluginInfo *plugin, + GList *configs); static void grl_upnp_source_finalize (GObject *plugin); @@ -134,7 +135,9 @@ static GHashTable *filter_key_mapping = NULL; /* =================== UPnP Plugin =============== */ gboolean -grl_upnp_plugin_init (GrlPluginRegistry *registry, const GrlPluginInfo *plugin) +grl_upnp_plugin_init (GrlPluginRegistry *registry, + const GrlPluginInfo *plugin, + GList *configs) { GError *error = NULL; GUPnPContext *context; @@ -757,43 +760,43 @@ get_value_for_key (GrlKeyID key_id, } static void -set_metadata_value (GrlContentMedia *media, +set_metadata_value (GrlMedia *media, GrlKeyID key_id, const gchar *value) { switch (key_id) { case GRL_METADATA_KEY_TITLE: - grl_content_media_set_title (media, value); + grl_media_set_title (media, value); break; case GRL_METADATA_KEY_ARTIST: - grl_content_audio_set_artist (media, value); + grl_media_audio_set_artist (media, value); break; case GRL_METADATA_KEY_ALBUM: - grl_content_audio_set_album (media, value); + grl_media_audio_set_album (media, value); break; case GRL_METADATA_KEY_GENRE: - grl_content_audio_set_genre (media, value); + grl_media_audio_set_genre (media, value); break; case GRL_METADATA_KEY_URL: - grl_content_media_set_url (media, value); + grl_media_set_url (media, value); break; case GRL_METADATA_KEY_MIME: - grl_content_media_set_mime (media, value); + grl_media_set_mime (media, value); break; case GRL_METADATA_KEY_DATE: - grl_content_media_set_date (media, value); + grl_media_set_date (media, value); break; case GRL_METADATA_KEY_DURATION: { gint duration = didl_h_mm_ss_to_int (value); if (duration >= 0) { - grl_content_media_set_duration (media, duration); + grl_media_set_duration (media, duration); } } break; case GRL_METADATA_KEY_CHILDCOUNT: - if (value && GRL_IS_CONTENT_BOX (media)) { - grl_content_box_set_childcount (GRL_CONTENT_BOX (media), atoi (value)); + if (value && GRL_IS_MEDIA_BOX (media)) { + grl_media_box_set_childcount (GRL_MEDIA_BOX (media), atoi (value)); } break; default: @@ -801,8 +804,8 @@ set_metadata_value (GrlContentMedia *media, } } -static GrlContentMedia * -build_media_from_didl (GrlContentMedia *content, +static GrlMedia * +build_media_from_didl (GrlMedia *content, #ifdef GUPNPAV_OLD_VERSION xmlNode *didl_node, #else @@ -818,7 +821,7 @@ build_media_from_didl (GrlContentMedia *content, const gchar *class; #endif - GrlContentMedia *media = NULL; + GrlMedia *media = NULL; GList *didl_props; GList *iter; @@ -834,28 +837,28 @@ build_media_from_didl (GrlContentMedia *content, if (GUPNP_IS_DIDL_LITE_CONTAINER (didl_node)) { #endif - media = grl_content_box_new (); + media = grl_media_box_new (); } else { if (!media) { class = gupnp_didl_lite_object_get_upnp_class (didl_node); if (class) { if (g_str_has_prefix (class, "object.item.audioItem")) { - media = grl_content_audio_new (); + media = grl_media_audio_new (); } else if (g_str_has_prefix (class, "object.item.videoItem")) { - media = grl_content_video_new (); + media = grl_media_video_new (); } else if (g_str_has_prefix (class, "object.item.imageItem")) { - media = grl_content_image_new (); + media = grl_media_image_new (); } else { - media = grl_content_media_new (); + media = grl_media_new (); } } else { - media = grl_content_media_new (); + media = grl_media_new (); } } } id = gupnp_didl_lite_object_get_id (didl_node); - grl_content_media_set_id (media, id); + grl_media_set_id (media, id); didl_props = didl_get_supported_resources (didl_node); @@ -887,7 +890,7 @@ gupnp_browse_result_cb (GUPnPDIDLLiteParser *parser, #endif gpointer user_data) { - GrlContentMedia *media; + GrlMedia *media; struct OperationSpec *os = (struct OperationSpec *) user_data; if (gupnp_didl_lite_object_get_id (didl)) { media = build_media_from_didl (NULL, didl, os->keys); @@ -1100,7 +1103,7 @@ grl_upnp_source_browse (GrlMediaSource *source, GrlMediaSourceBrowseSpec *bs) os->callback = bs->callback; os->user_data = bs->user_data; - container_id = (gchar *) grl_content_media_get_id (bs->container); + container_id = (gchar *) grl_media_get_id (bs->container); if (!container_id) { container_id = "0"; } @@ -1198,7 +1201,7 @@ grl_upnp_source_metadata (GrlMediaSource *source, g_debug ("filter: '%s'", upnp_filter); - id = (gchar *) grl_content_media_get_id (ms->media); + id = (gchar *) grl_media_get_id (ms->media); if (!id) { id = "0"; } diff --git a/src/youtube/TODO b/src/youtube/TODO index e69de29..409835c 100644 --- a/src/youtube/TODO +++ b/src/youtube/TODO @@ -0,0 +1,6 @@ +- Consider using libgdata. +- Fix get_metadata() for standard feeds. +- Consider implementing store() -> video upload. +- Consider implementing configuration (personal account) + -> Could add new category for browsing (my videos) + -> would enable store() and remove() operations. diff --git a/src/youtube/grl-youtube.c b/src/youtube/grl-youtube.c index 7521aa4..b88f6a6 100644 --- a/src/youtube/grl-youtube.c +++ b/src/youtube/grl-youtube.c @@ -189,7 +189,8 @@ typedef enum { static GrlYoutubeSource *grl_youtube_source_new (void); gboolean grl_youtube_plugin_init (GrlPluginRegistry *registry, - const GrlPluginInfo *plugin); + const GrlPluginInfo *plugin, + GList *configs); static const GList *grl_youtube_source_supported_keys (GrlMetadataSource *source); @@ -241,7 +242,8 @@ CategoryInfo *categories_dir = NULL; gboolean grl_youtube_plugin_init (GrlPluginRegistry *registry, - const GrlPluginInfo *plugin) + const GrlPluginInfo *plugin, + GList *config) { g_debug ("youtube_plugin_init\n"); @@ -437,17 +439,17 @@ read_url (const gchar *url) } } -static GrlContentMedia * -build_media_from_entry (GrlContentMedia *content, +static GrlMedia * +build_media_from_entry (GrlMedia *content, const Entry *entry, const GList *keys) { - GrlContentMedia *media; + GrlMedia *media; gchar *url; GList *iter; if (!content) { - media = grl_content_video_new (); + media = grl_media_video_new (); } else { media = content; } @@ -457,40 +459,40 @@ build_media_from_entry (GrlContentMedia *content, GrlKeyID key_id = POINTER_TO_GRLKEYID (iter->data); switch (key_id) { case GRL_METADATA_KEY_ID: - grl_content_media_set_id (media, entry->id); + grl_media_set_id (media, entry->id); break; case GRL_METADATA_KEY_TITLE: - grl_content_media_set_title (media, entry->title); + grl_media_set_title (media, entry->title); break; case GRL_METADATA_KEY_AUTHOR: - grl_content_media_set_author (media, entry->author); + grl_media_set_author (media, entry->author); break; case GRL_METADATA_KEY_DESCRIPTION: - grl_content_media_set_description (media, entry->description); + grl_media_set_description (media, entry->description); break; case GRL_METADATA_KEY_THUMBNAIL: - grl_content_media_set_thumbnail (media, entry->thumbnail); + grl_media_set_thumbnail (media, entry->thumbnail); break; case GRL_METADATA_KEY_DATE: - grl_content_media_set_date (media, entry->published); + grl_media_set_date (media, entry->published); break; case GRL_METADATA_KEY_DURATION: - grl_content_media_set_duration (media, atoi (entry->duration)); + grl_media_set_duration (media, atoi (entry->duration)); break; case GRL_METADATA_KEY_MIME: - grl_content_media_set_mime (media, YOUTUBE_VIDEO_MIME); + grl_media_set_mime (media, YOUTUBE_VIDEO_MIME); break; case GRL_METADATA_KEY_SITE: - grl_content_media_set_site (media, YOUTUBE_SITE_URL); + grl_media_set_site (media, YOUTUBE_SITE_URL); break; case GRL_METADATA_KEY_RATING: - grl_content_media_set_rating (media, entry->rating, "5.00"); + grl_media_set_rating (media, entry->rating, "5.00"); break; case GRL_METADATA_KEY_URL: if (!entry->restricted) { url = get_video_url (entry->id); if (url) { - grl_content_media_set_url (media, url); + grl_media_set_url (media, url); } g_free (url); } @@ -624,7 +626,7 @@ parse_entries_idle (gpointer user_data) Entry *entry = g_new0 (Entry, 1); parse_entry (pei->doc, pei->node, entry); if (0) print_entry (entry); - GrlContentMedia *media = + GrlMedia *media = build_media_from_entry (NULL, entry, pei->os->keys); free_entry (entry); @@ -776,7 +778,7 @@ parse_feed (OperationSpec *os, const gchar *str, GError **error) return; } -static GrlContentMedia * +static GrlMedia * parse_metadata_entry (GrlMediaSourceMetadataSpec *os, xmlDocPtr doc, xmlNodePtr node, @@ -784,7 +786,7 @@ parse_metadata_entry (GrlMediaSourceMetadataSpec *os, { xmlNs *ns; guint total_results = 0; - GrlContentMedia *media = NULL; + GrlMedia *media = NULL; /* First checkout search information looking for totalResults */ while (node && !total_results) { @@ -804,23 +806,28 @@ parse_metadata_entry (GrlMediaSourceMetadataSpec *os, node = node->next; } - /* Should have exactly 1 result */ - if (total_results != 1) { + if (total_results <= 0) { *error = g_error_new (GRL_ERROR, GRL_ERROR_MEDIA_NOT_FOUND, "Could not find requested media"); return NULL; } - /* Now go for the entry data */ while (node && xmlStrcmp (node->name, (const xmlChar *) "entry")) { node = node->next; } if (node) { + const gchar *target_id = grl_media_get_id (os->media); Entry *entry = g_new0 (Entry, 1); parse_entry (doc, node, entry); if (0) print_entry (entry); - build_media_from_entry (os->media, entry, os->keys); + if (!strcmp (entry->id, target_id)) { + build_media_from_entry (os->media, entry, os->keys); + } else { + /* FIXME: The query using the video id at target text resulted in various + matches and the one we were looking for was not the first one */ + g_warning ("Metadata query did not match expected target"); + } free_entry (entry); } @@ -1010,7 +1017,7 @@ get_container_url (const gchar *container_id) } static void -set_category_childcount (GrlContentBox *content, +set_category_childcount (GrlMediaBox *content, CategoryInfo *dir, guint index) { @@ -1045,48 +1052,48 @@ set_category_childcount (GrlContentBox *content, } if (set_childcount) { - grl_content_box_set_childcount (content, childcount); + grl_media_box_set_childcount (content, childcount); } } -static GrlContentMedia * -produce_container_from_directory (GrlContentMedia *media, +static GrlMedia * +produce_container_from_directory (GrlMedia *media, CategoryInfo *dir, guint index, gboolean set_childcount) { - GrlContentMedia *content; + GrlMedia *content; if (!media) { /* Create mode */ - content = grl_content_box_new (); + content = grl_media_box_new (); } else { /* Update mode */ content = media; } if (!dir) { - grl_content_media_set_id (content, NULL); - grl_content_media_set_title (content, YOUTUBE_ROOT_NAME); + grl_media_set_id (content, NULL); + grl_media_set_title (content, YOUTUBE_ROOT_NAME); } else { - grl_content_media_set_id (content, dir[index].id); - grl_content_media_set_title (content, dir[index].name); + grl_media_set_id (content, dir[index].id); + grl_media_set_title (content, dir[index].name); } - grl_content_media_set_site (content, YOUTUBE_SITE_URL); + grl_media_set_site (content, YOUTUBE_SITE_URL); if (set_childcount) { - set_category_childcount (GRL_CONTENT_BOX (content), dir, index); + set_category_childcount (GRL_MEDIA_BOX (content), dir, index); } return content; } -static GrlContentMedia * -produce_container_from_directory_by_id (GrlContentMedia *media, +static GrlMedia * +produce_container_from_directory_by_id (GrlMedia *media, CategoryInfo *dir, const gchar *id, gboolean set_childcount) { - GrlContentMedia *content; + GrlMedia *content; guint index = 0; while (dir[index].id && strcmp (dir[index].id, id)) index++; @@ -1123,7 +1130,7 @@ classify_media_id (const gchar *media_id) static gboolean produce_from_directory_idle (gpointer user_data) { - GrlContentMedia *content; + GrlMedia *content; ProduceFromDirectoryIdle *pfdi = (ProduceFromDirectoryIdle *) user_data; if (!pfdi->os->cancelled) { @@ -1342,7 +1349,7 @@ grl_youtube_source_browse (GrlMediaSource *source, g_debug ("grl_youtube_source_browse"); - container_id = grl_content_media_get_id (bs->container); + container_id = grl_media_get_id (bs->container); os = g_new0 (OperationSpec, 1); os->source = bs->source; @@ -1410,14 +1417,14 @@ grl_youtube_source_metadata (GrlMediaSource *source, { gchar *url; GError *error = NULL; - GrlContentMedia *media = NULL; + GrlMedia *media = NULL; YoutubeMediaType media_type; gboolean set_childcount; const gchar *id; g_debug ("grl_youtube_source_metadata"); - id = grl_content_media_get_id (ms->media); + id = grl_media_get_id (ms->media); media_type = classify_media_id (id); /* Do not compute childcount for expensive categories diff --git a/test/main.c b/test/main.c index d86a723..32de62c 100644 --- a/test/main.c +++ b/test/main.c @@ -51,10 +51,21 @@ print_supported_ops (GrlMetadataSource *source) if (caps & GRL_OP_QUERY) { g_debug (" + Query"); } + if (caps & GRL_OP_STORE_PARENT) { + g_debug (" + Store (parent)"); + } else if (caps & GRL_OP_STORE) { + g_debug (" + Store"); + } + if (caps & GRL_OP_REMOVE) { + g_debug (" + Remove"); + } + if (caps & GRL_OP_SET_METADATA) { + g_debug (" + Set Metadata"); + } } static void -print_metadata (gpointer key, GrlContent *content) +print_metadata (gpointer key, GrlData *content) { GrlKeyID key_id = POINTER_TO_GRLKEYID(key); @@ -66,7 +77,7 @@ print_metadata (gpointer key, GrlContent *content) const GrlMetadataKey *mkey = grl_plugin_registry_lookup_metadata_key (registry, key_id); - const GValue *value = grl_content_get (content, key_id); + const GValue *value = grl_data_get (content, key_id); if (value && G_VALUE_HOLDS_STRING (value)) { g_debug ("\t%s: %s", GRL_METADATA_KEY_GET_NAME (mkey), g_value_get_string (value)); @@ -76,28 +87,28 @@ print_metadata (gpointer key, GrlContent *content) } } -static GrlContentMedia * +static GrlMedia * media_from_id (const gchar *id) { - GrlContentMedia *media; - media = grl_content_media_new (); - grl_content_media_set_id (media, id); + GrlMedia *media; + media = grl_media_new (); + grl_media_set_id (media, id); return media; } -static GrlContentMedia * +static GrlMedia * box_from_id (const gchar *id) { - GrlContentMedia *media; - media = grl_content_box_new (); - grl_content_media_set_id (media, id); + GrlMedia *media; + media = grl_media_box_new (); + grl_media_set_id (media, id); return media; } static void browse_cb (GrlMediaSource *source, guint browse_id, - GrlContentMedia *media, + GrlMedia *media, guint remaining, gpointer user_data, const GError *error) @@ -118,10 +129,10 @@ browse_cb (GrlMediaSource *source, } g_debug ("\tContainer: %s", - GRL_IS_CONTENT_BOX(media) ? "yes" : "no"); + GRL_IS_MEDIA_BOX(media) ? "yes" : "no"); - keys = grl_content_get_keys (GRL_CONTENT (media)); - g_list_foreach (keys, (GFunc) print_metadata, GRL_CONTENT (media)); + keys = grl_data_get_keys (GRL_DATA (media)); + g_list_foreach (keys, (GFunc) print_metadata, GRL_DATA (media)); g_list_free (keys); g_object_unref (media); @@ -132,7 +143,7 @@ browse_cb (GrlMediaSource *source, static void metadata_cb (GrlMediaSource *source, - GrlContentMedia *media, + GrlMedia *media, gpointer user_data, const GError *error) { @@ -146,13 +157,13 @@ metadata_cb (GrlMediaSource *source, } g_debug (" Got metadata for object '%s'", - grl_content_media_get_id (GRL_CONTENT_MEDIA (media))); + grl_media_get_id (GRL_MEDIA (media))); g_debug ("\tContainer: %s", - GRL_IS_CONTENT_BOX(media) ? "yes" : "no"); + GRL_IS_MEDIA_BOX(media) ? "yes" : "no"); - keys = grl_content_get_keys (GRL_CONTENT (media)); - g_list_foreach (keys, (GFunc) print_metadata, GRL_CONTENT (media)); + keys = grl_data_get_keys (GRL_DATA (media)); + g_list_foreach (keys, (GFunc) print_metadata, GRL_DATA (media)); g_list_free (keys); g_object_unref (media); @@ -161,13 +172,26 @@ metadata_cb (GrlMediaSource *source, static void resolve_cb (GrlMetadataSource *source, - GrlContentMedia *media, + GrlMedia *media, gpointer user_data, const GError *error) { metadata_cb (NULL, media, user_data, error); } +static void +set_cb (GrlMetadataSource *source, + GrlMedia *media, + GList *failed_keys, + gpointer user_data, + const GError *error) +{ + if (error) { + g_critical ("%s: %d keys not written", + error->message, g_list_length (failed_keys)); + } +} + gint main (void) { @@ -182,7 +206,8 @@ main (void) "grl-shoutcast:*," "grl-apple-trailers:*," "grl-lastfm-albumart:*," - "grl-flickr:*"); + "grl-flickr:*," + "grl-metadata-store:*"); keys = grl_metadata_key_list_new (GRL_METADATA_KEY_ID, GRL_METADATA_KEY_TITLE, @@ -197,6 +222,10 @@ main (void) GRL_METADATA_KEY_DURATION, GRL_METADATA_KEY_CHILDCOUNT, GRL_METADATA_KEY_MIME, + GRL_METADATA_KEY_PLAY_COUNT, + GRL_METADATA_KEY_LAST_PLAYED, + GRL_METADATA_KEY_LAST_POSITION, + GRL_METADATA_KEY_RATING, NULL); g_debug ("start"); @@ -220,6 +249,12 @@ main (void) "../src/lastfm-albumart/.libs/libgrllastfm-albumart.so"); grl_plugin_registry_load (registry, "../src/flickr/.libs/libgrlflickr.so"); + grl_plugin_registry_load (registry, + "../src/metadata-store/.libs/libgrlmetadatastore.so"); + grl_plugin_registry_load (registry, + "../src/bookmarks/.libs/libgrlbookmarks.so"); + grl_plugin_registry_load (registry, + "../src/podcasts/.libs/libgrlpodcasts.so"); g_debug ("Obtaining sources"); @@ -255,33 +290,48 @@ main (void) (GrlMetadataSource *) grl_plugin_registry_lookup_source (registry, "grl-lastfm-albumart"); + GrlMetadataSource *metadata_store = + (GrlMetadataSource *) grl_plugin_registry_lookup_source (registry, + "grl-metadata-store"); + + GrlMediaSource *bookmarks = + (GrlMediaSource *) grl_plugin_registry_lookup_source (registry, + "grl-bookmarks"); + + GrlMediaSource *podcasts = + (GrlMediaSource *) grl_plugin_registry_lookup_source (registry, + "grl-podcasts"); + g_assert (youtube); g_assert (fs); - g_assert (flickr); g_assert (jamendo); g_assert (shoutcast); g_assert (apple_trailers); - g_assert (fake); g_assert (lastfm); - + g_assert (metadata_store); + g_assert (bookmarks); + g_assert (podcasts); g_debug ("Supported operations"); print_supported_ops (GRL_METADATA_SOURCE (youtube)); print_supported_ops (GRL_METADATA_SOURCE (fs)); - print_supported_ops (GRL_METADATA_SOURCE (flickr)); + if (flickr) print_supported_ops (GRL_METADATA_SOURCE (flickr)); print_supported_ops (GRL_METADATA_SOURCE (jamendo)); print_supported_ops (GRL_METADATA_SOURCE (apple_trailers)); print_supported_ops (GRL_METADATA_SOURCE (shoutcast)); - print_supported_ops (fake); + if (fake) print_supported_ops (fake); + print_supported_ops (GRL_METADATA_SOURCE (podcasts)); + print_supported_ops (GRL_METADATA_SOURCE (bookmarks)); print_supported_ops (lastfm); + print_supported_ops (metadata_store); g_debug ("testing"); if (0) grl_media_source_browse (youtube, NULL, keys, 0, 5, GRL_RESOLVE_IDLE_RELAY , browse_cb, NULL); if (0) grl_media_source_browse (youtube, NULL, keys, 0, 5, GRL_RESOLVE_IDLE_RELAY , browse_cb, NULL); if (0) grl_media_source_browse (youtube, media_from_id ("standard-feeds/most-viewed"), keys, 0, 10, GRL_RESOLVE_FAST_ONLY , browse_cb, NULL); - if (0) grl_media_source_browse (youtube, media_from_id ("categories/Sports"), keys, 0, 173, GRL_RESOLVE_FAST_ONLY, browse_cb, NULL); - if (0) grl_media_source_search (youtube, "igalia", keys, 6, 10, GRL_RESOLVE_FAST_ONLY, browse_cb, NULL); + if (0) grl_media_source_browse (youtube, media_from_id ("categories/Sports"), keys, 0, 5, GRL_RESOLVE_FAST_ONLY, browse_cb, NULL); + if (0) grl_media_source_search (youtube, "igalia", keys, 0, 3, GRL_RESOLVE_FULL | GRL_RESOLVE_FAST_ONLY, browse_cb, NULL); if (0) grl_media_source_search (youtube, "igalia", keys, 1, 10, GRL_RESOLVE_FULL | GRL_RESOLVE_IDLE_RELAY | GRL_RESOLVE_FAST_ONLY, browse_cb, NULL); if (0) grl_media_source_metadata (youtube, NULL, keys, 0, metadata_cb, NULL); if (0) grl_media_source_metadata (youtube, NULL, keys, GRL_RESOLVE_IDLE_RELAY | GRL_RESOLVE_FAST_ONLY | GRL_RESOLVE_FULL, metadata_cb, NULL); @@ -314,17 +364,35 @@ main (void) if (0) grl_media_source_metadata (shoutcast, box_from_id("2424hs"), keys, 0, metadata_cb, NULL); if (0) grl_media_source_metadata (shoutcast, media_from_id("American/556687"), keys, 0, metadata_cb, NULL); if (0) grl_media_source_metadata (shoutcast, media_from_id("American/556682"), keys, 0, metadata_cb, NULL); - if (1) grl_media_source_browse (apple_trailers, NULL, keys, 0, 5, GRL_RESOLVE_IDLE_RELAY , browse_cb, NULL); + if (0) grl_media_source_browse (apple_trailers, NULL, keys, 0, 5, GRL_RESOLVE_IDLE_RELAY , browse_cb, NULL); if (0) { - GrlContentMedia *media = media_from_id ("test"); - grl_content_set_string (GRL_CONTENT (media), - GRL_METADATA_KEY_ARTIST, - "roxette"); - grl_content_set_string (GRL_CONTENT (media), - GRL_METADATA_KEY_ALBUM, - "pop hits"); + GrlMedia *media = media_from_id ("test"); + grl_data_set_string (GRL_DATA (media), + GRL_METADATA_KEY_ARTIST, + "roxette"); + grl_data_set_string (GRL_DATA (media), + GRL_METADATA_KEY_ALBUM, + "pop hits"); grl_metadata_source_resolve (lastfm, keys, media, GRL_RESOLVE_IDLE_RELAY, resolve_cb, NULL); } + if (1) { + GrlMedia *media = media_from_id ("test-id"); + grl_media_set_source (media, "some-source-id"); + grl_media_set_play_count (media, 68); + grl_media_set_rating (media, "4.5", "5"); + grl_media_set_last_position (media, 60); + grl_media_set_last_played (media, "19/11/2009"); + GList *keys_to_write = grl_metadata_key_list_new (GRL_METADATA_KEY_PLAY_COUNT, + GRL_METADATA_KEY_RATING, + GRL_METADATA_KEY_LAST_POSITION, + GRL_METADATA_KEY_ALBUM, + GRL_METADATA_KEY_LAST_PLAYED, + GRL_METADATA_KEY_TITLE, + GRL_METADATA_KEY_GENRE, + NULL); + grl_metadata_source_set_metadata (metadata_store, media, keys_to_write, + GRL_WRITE_FULL, set_cb, NULL); + } g_debug ("Running main loop"); |