1 /*
2 * Copyright (C) 2007, Jamie McCracken <jamiemcc@gnome.org>
3 * Copyright (C) 2008, Nokia <ivan.frade@nokia.com>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 */
20
21 #include "config-miners.h"
22
23 #include <string.h>
24 #include <stdlib.h>
25
26 #include <glib.h>
27 #include <glib/gstdio.h>
28 #include <gio/gio.h>
29
30 #include <totem-pl-parser.h>
31
32 #include <libtracker-extract/tracker-extract.h>
33 #include <libtracker-extract/tracker-guarantee.h>
34
35 #define PLAYLIST_PROPERTY_NO_TRACKS "entryCounter"
36 #define PLAYLIST_PROPERTY_DURATION "listDuration"
37 /*
38 FIXME Decide what to do with this in nepomuk
39 #define PLAYLIST_PROPERTY_CALCULATED "Playlist:ValidDuration"
40 */
41
42 #define PLAYLIST_DEFAULT_NO_TRACKS 0
43 #define PLAYLIST_DEFAULT_DURATION 0
44
45 typedef struct {
46 guint32 track_counter;
47 gint64 total_time;
48 gchar *title;
49 TrackerResource *metadata;
50 } PlaylistMetadata;
51
52 static void
playlist_started(TotemPlParser * parser,gchar * to_uri,TotemPlParserMetadata * to_metadata,gpointer user_data)53 playlist_started (TotemPlParser *parser,
54 gchar *to_uri,
55 TotemPlParserMetadata *to_metadata,
56 gpointer user_data)
57 {
58 PlaylistMetadata *data;
59
60 data = (PlaylistMetadata *) user_data;
61
62 /* Avoid looking up every time */
63 data->title = g_strdup (g_hash_table_lookup (to_metadata, TOTEM_PL_PARSER_FIELD_TITLE));
64 }
65
66 static void
entry_parsed(TotemPlParser * parser,gchar * to_uri,GHashTable * to_metadata,gpointer user_data)67 entry_parsed (TotemPlParser *parser,
68 gchar *to_uri,
69 GHashTable *to_metadata,
70 gpointer user_data)
71 {
72 TrackerResource *entry;
73 PlaylistMetadata *data;
74
75 data = (PlaylistMetadata *) user_data;
76 data->track_counter++;
77
78 if (data->track_counter > 1000) {
79 /* limit playlists to 1000 entries for query performance reasons */
80 g_message ("Playlist has > 1000 entries. Ignoring for performance reasons.");
81 return;
82 }
83
84 entry = tracker_resource_new (NULL);
85 tracker_resource_set_uri (entry, "rdf:type", "nfo:MediaFileListEntry");
86 tracker_resource_set_string (entry, "nfo:entryUrl", to_uri);
87 tracker_resource_set_int (entry, "nfo:listPosition", data->track_counter);
88
89 if (data->track_counter == 1) {
90 /* This causes all existing relations to be deleted, when we serialize
91 * to SPARQL. */
92 tracker_resource_set_relation (data->metadata, "nfo:hasMediaFileListEntry", entry);
93 } else {
94 tracker_resource_add_relation (data->metadata, "nfo:hasMediaFileListEntry", entry);
95 }
96 g_object_unref (entry);
97
98 if (to_metadata) {
99 gchar *duration;
100
101 duration = g_hash_table_lookup (to_metadata, TOTEM_PL_PARSER_FIELD_DURATION);
102
103 if (duration == NULL) {
104 duration = g_hash_table_lookup (to_metadata, TOTEM_PL_PARSER_FIELD_DURATION_MS);
105 }
106
107 if (duration != NULL) {
108 gint64 secs = totem_pl_parser_parse_duration (duration, FALSE);
109
110 if (secs > 0) {
111 data->total_time += secs;
112 }
113 }
114 }
115 }
116
117 G_MODULE_EXPORT gboolean
tracker_extract_get_metadata(TrackerExtractInfo * info)118 tracker_extract_get_metadata (TrackerExtractInfo *info)
119 {
120 TotemPlParser *pl;
121 TrackerResource *metadata;
122 PlaylistMetadata data;
123 GFile *file;
124 gchar *uri;
125
126 pl = totem_pl_parser_new ();
127 file = tracker_extract_info_get_file (info);
128 uri = g_file_get_uri (file);
129
130 metadata = data.metadata = tracker_resource_new (NULL);
131
132 data.track_counter = PLAYLIST_DEFAULT_NO_TRACKS;
133 data.total_time = PLAYLIST_DEFAULT_DURATION;
134 data.title = NULL;
135
136 g_object_set (pl, "recurse", FALSE, "disable-unsafe", TRUE, NULL);
137
138 g_signal_connect (G_OBJECT (pl), "playlist-started", G_CALLBACK (playlist_started), &data);
139 g_signal_connect (G_OBJECT (pl), "entry-parsed", G_CALLBACK (entry_parsed), &data);
140
141 tracker_resource_add_uri (metadata, "rdf:type", "nmm:Playlist");
142 tracker_resource_add_uri (metadata, "rdf:type", "nfo:MediaList");
143
144 if (totem_pl_parser_parse (pl, uri, FALSE) == TOTEM_PL_PARSER_RESULT_SUCCESS) {
145 if (data.title != NULL) {
146 g_message ("Playlist title:'%s'", data.title);
147 tracker_resource_set_string (metadata, "nie:title", data.title);
148 g_free (data.title);
149 } else {
150 g_message ("Playlist has no title, attempting to get one from filename");
151 tracker_guarantee_resource_title_from_file (metadata, "nie:title", NULL, uri, NULL);
152 }
153
154 if (data.total_time > 0) {
155 tracker_resource_set_int64 (metadata, "nfo:listDuration", data.total_time);
156 }
157
158 if (data.track_counter > 0) {
159 tracker_resource_set_int64 (metadata, "nfo:entryCounter", data.track_counter);
160 }
161 } else {
162 g_warning ("Playlist could not be parsed, no error given");
163 }
164
165 g_object_unref (pl);
166 g_free (uri);
167
168 tracker_extract_info_set_resource (info, metadata);
169 g_object_unref (metadata);
170
171 return TRUE;
172 }
173