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