diff dep/animone/src/strategist.cc @ 258:862d0d8619f6

*: HUUUGE changes animia has been renamed to animone, so instead of thinking of a health condition, you think of a beautiful flower :) I've also edited some of the code for animone, but I have no idea if it even works or not because I don't have a mac or windows machine lying around. whoops! ... anyway, all of the changes divergent from Anisthesia are now licensed under BSD. it's possible that I could even rewrite most of the code to where I don't even have to keep the MIT license, but that's thinking too far into the future I've been slacking off on implementing the anime seasons page, mostly out of laziness. I think I'd have to create another db file specifically for the seasons anyway, this code is being pushed *primarily* because the hard drive it's on is failing! yay :)
author Paper <paper@paper.us.eu.org>
date Mon, 01 Apr 2024 02:43:44 -0400
parents
children 9a04802848c0
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dep/animone/src/strategist.cc	Mon Apr 01 02:43:44 2024 -0400
@@ -0,0 +1,111 @@
+#include <regex>
+
+#include "animone.h"
+#include "animone/fd.h"
+#include "animone/strategies.h"
+#include "animone/util.h"
+
+#include <iostream>
+
+/* this was STUPIDLY slow in Anisthesia, oops! */
+
+namespace animone::internal {
+
+static bool ApplyWindowTitleFormat(const std::string& format, std::string& title) {
+	if (format.empty())
+		return false;
+
+	const std::regex pattern(format);
+	std::smatch match;
+	std::regex_match(title, match, pattern);
+
+	// Use the first non-empty match result, because the regular expression may
+	// contain multiple sub-expressions.
+	for (size_t i = 1; i < match.size(); ++i) {
+		if (!match.str(i).empty()) {
+			title = match.str(i);
+			return true;
+		}
+	}
+
+	// Results are empty, but the match was successful
+	if (!match.empty()) {
+		title.clear();
+		return true;
+	}
+
+	return true;
+}
+
+static MediaInfoType InferMediaInformationType(const std::string& str) {
+	const std::regex path_pattern(R"(^(?:[A-Za-z]:[/\\]|\\\\)[^<>:"/\\|?*]+)");
+	return (std::regex_search(str, path_pattern)) ? MediaInfoType::File : MediaInfoType::Unknown;
+}
+
+static bool AddMedia(Result& result, const MediaInfo media_information) {
+	if (media_information.value.empty())
+		return false;
+
+	Media media;
+	media.information.push_back(media_information);
+	result.media.push_back(std::move(media));
+
+	return true;
+}
+
+static bool ApplyWindowTitleStrategy(std::vector<Result>& results) {
+	bool success = false;
+
+	for (auto& result : results) {
+		auto title = result.window.text;
+		if (title.empty())
+			continue;
+
+		ApplyWindowTitleFormat(result.player.window_title_format, title);
+
+		success |= AddMedia(result, {InferMediaInformationType(title), title});
+	}
+
+	return success;
+}
+
+static bool ApplyOpenFilesStrategy(std::vector<Result>& results) {
+	bool success = false;
+
+	/* map pids to our results, saves time with open_file_proc */
+	std::unordered_map<pid_t, Result*> pid_map;
+	pid_map.reserve(results.size());
+
+	std::set<pid_t> pids;
+
+	for (Result& result : results) {
+		const pid_t pid = result.process.pid;
+		if (!pid)
+			continue;
+
+		pid_map.insert({pid, &result});
+		pids.insert(pid);
+	}
+
+	auto open_file_proc = [&](const OpenFile& file) -> bool {
+		success |= AddMedia(*pid_map[file.pid], {MediaInfoType::File, file.path});
+		return true;
+	};
+
+	EnumerateOpenFiles(pids, open_file_proc);
+
+	return success;
+}
+
+bool ApplyStrategies(std::vector<Result>& results) {
+	bool success = false;
+
+	success |= ApplyWindowTitleStrategy(results);
+	success |= ApplyOpenFilesStrategy(results);
+
+	return success;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+} // namespace animone::internal