Commits

Tim van der Molen committed 250f3c6

Introduce the update-metadata command.

  • Participants
  • Parent commits 923b90f

Comments (0)

Files changed (5)

 COMMAND_EXEC_PROTOTYPE(stop);
 COMMAND_EXEC_PROTOTYPE(unbind_key);
 COMMAND_PARSE_PROTOTYPE(unbind_key);
+COMMAND_EXEC_PROTOTYPE(update_metadata);
 
 static struct command command_list[] = {
 	{
 		command_unbind_key_parse,
 		command_unbind_key_exec,
 		free
+	},
+	{
+		"update-metadata",
+		command_generic_parse,
+		command_update_metadata_exec,
+		NULL
 	}
 };
 
 	*datap = data;
 	return 0;
 }
+
+/* ARGSUSED */
+static void
+command_update_metadata_exec(UNUSED void *datap)
+{
+	track_update_metadata();
+	screen_print();
+}
 	/* Set the duration variable. */
 	if (player_track == NULL)
 		vars[PLAYER_FMT_DURATION].value.number = 0;
-	else
+	else {
+		track_lock_metadata();
 		vars[PLAYER_FMT_DURATION].value.number =
 		    player_track->duration;
+		track_unlock_metadata();
+	}
 
 	XPTHREAD_MUTEX_UNLOCK(&player_track_mtx);
 
 	struct format *format;
 
 	option_lock();
+	track_lock_metadata();
 	format = option_get_format("player-track-format");
 	screen_player_track_printf(format, player_track);
+	track_unlock_metadata();
 	option_unlock();
 }
 
 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
-.Dd April 2, 2013
+.Dd May 2, 2013
 .Dt SIREN 1
 .Os
 .Sh NAME
 quits.
 .It Ic save-metadata
 Save the metadata cache to disk.
-The metadata is automatically saved when
+The metadata cache is automatically saved when
 .Nm
 quits.
 .It Xo
 arguments are analogous to those of the
 .Ic bind-key
 command.
+.It Ic update-metadata
+Update the metadata cache.
 .El
 .Sh OPTIONS
 The appearance and behaviour of
 void		 track_end(void);
 struct track	*track_get(const char *, const struct ip *) NONNULL(1);
 void		 track_init(void);
+void		 track_lock_metadata(void);
 int		 track_search(const struct track *, const char *);
+void		 track_unlock_metadata(void);
+void		 track_update_metadata(void);
 int		 track_write_cache(void);
 
 void		 view_activate_entry(void);
 
 #include <limits.h>
 #include <stdlib.h>
+#include <stdint.h>
 #include <string.h>
 #include <strings.h>
 #include <unistd.h>
 
 RB_PROTOTYPE(track_tree, track_entry, entries, track_cmp_entry)
 
+static pthread_mutex_t	 track_metadata_mtx = PTHREAD_MUTEX_INITIALIZER;
 static struct track_tree track_tree = RB_INITIALIZER(track_tree);
+static size_t		 track_nentries;
 static int		 track_tree_modified;
 static char		*track_cache_file;
 
 static void
 track_add_entry(struct track_entry *te)
 {
+	if (track_nentries == SIZE_MAX) {
+		track_free_entry(te);
+		return;
+	}
+
 	if (RB_INSERT(track_tree, &track_tree, te) != NULL) {
 		/* This should not happen. */
 		LOG_ERRX("%s: track already in tree", te->track.path);
 		track_free_entry(te);
+		return;
 	}
+
+	track_nentries++;
 }
 
 int
 	te->track.duration = 0;
 }
 
+void
+track_lock_metadata(void)
+{
+	XPTHREAD_MUTEX_LOCK(&track_metadata_mtx);
+}
+
 static void
 track_read_cache(void)
 {
 {
 	(void)RB_REMOVE(track_tree, &track_tree, te);
 	track_free_entry(te);
+	track_nentries--;
 }
 
 int
 	return -1;
 }
 
+void
+track_unlock_metadata(void)
+{
+	XPTHREAD_MUTEX_UNLOCK(&track_metadata_mtx);
+}
+
+void
+track_update_metadata(void)
+{
+	struct track_entry	*te;
+	size_t			 i;
+
+	i = 1;
+	RB_FOREACH(te, track_tree, &track_tree) {
+		msg_info("Updating track %zu of %zu (%zu%%)", i,
+		    track_nentries, 100 * i / track_nentries);
+		i++;
+
+		if (access(te->track.path, F_OK) == -1)
+			continue;
+
+		if (te->track.ip == NULL) {
+			te->track.ip = plugin_find_ip(te->track.path);
+			if (te->track.ip == NULL) {
+				LOG_ERRX("%s: no input plug-in found",
+				    te->track.path);
+				continue;
+			}
+		}
+
+		track_lock_metadata();
+		track_free_metadata(te);
+		track_init_metadata(te);
+		(void)te->track.ip->get_metadata(&te->track);
+		track_unlock_metadata();
+	}
+
+	track_tree_modified = 1;
+}
+
 int
 track_write_cache(void)
 {