comparison 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
comparison
equal deleted inserted replaced
257:699a20c57dc8 258:862d0d8619f6
1 #include <regex>
2
3 #include "animone.h"
4 #include "animone/fd.h"
5 #include "animone/strategies.h"
6 #include "animone/util.h"
7
8 #include <iostream>
9
10 /* this was STUPIDLY slow in Anisthesia, oops! */
11
12 namespace animone::internal {
13
14 static bool ApplyWindowTitleFormat(const std::string& format, std::string& title) {
15 if (format.empty())
16 return false;
17
18 const std::regex pattern(format);
19 std::smatch match;
20 std::regex_match(title, match, pattern);
21
22 // Use the first non-empty match result, because the regular expression may
23 // contain multiple sub-expressions.
24 for (size_t i = 1; i < match.size(); ++i) {
25 if (!match.str(i).empty()) {
26 title = match.str(i);
27 return true;
28 }
29 }
30
31 // Results are empty, but the match was successful
32 if (!match.empty()) {
33 title.clear();
34 return true;
35 }
36
37 return true;
38 }
39
40 static MediaInfoType InferMediaInformationType(const std::string& str) {
41 const std::regex path_pattern(R"(^(?:[A-Za-z]:[/\\]|\\\\)[^<>:"/\\|?*]+)");
42 return (std::regex_search(str, path_pattern)) ? MediaInfoType::File : MediaInfoType::Unknown;
43 }
44
45 static bool AddMedia(Result& result, const MediaInfo media_information) {
46 if (media_information.value.empty())
47 return false;
48
49 Media media;
50 media.information.push_back(media_information);
51 result.media.push_back(std::move(media));
52
53 return true;
54 }
55
56 static bool ApplyWindowTitleStrategy(std::vector<Result>& results) {
57 bool success = false;
58
59 for (auto& result : results) {
60 auto title = result.window.text;
61 if (title.empty())
62 continue;
63
64 ApplyWindowTitleFormat(result.player.window_title_format, title);
65
66 success |= AddMedia(result, {InferMediaInformationType(title), title});
67 }
68
69 return success;
70 }
71
72 static bool ApplyOpenFilesStrategy(std::vector<Result>& results) {
73 bool success = false;
74
75 /* map pids to our results, saves time with open_file_proc */
76 std::unordered_map<pid_t, Result*> pid_map;
77 pid_map.reserve(results.size());
78
79 std::set<pid_t> pids;
80
81 for (Result& result : results) {
82 const pid_t pid = result.process.pid;
83 if (!pid)
84 continue;
85
86 pid_map.insert({pid, &result});
87 pids.insert(pid);
88 }
89
90 auto open_file_proc = [&](const OpenFile& file) -> bool {
91 success |= AddMedia(*pid_map[file.pid], {MediaInfoType::File, file.path});
92 return true;
93 };
94
95 EnumerateOpenFiles(pids, open_file_proc);
96
97 return success;
98 }
99
100 bool ApplyStrategies(std::vector<Result>& results) {
101 bool success = false;
102
103 success |= ApplyWindowTitleStrategy(results);
104 success |= ApplyOpenFilesStrategy(results);
105
106 return success;
107 }
108
109 ////////////////////////////////////////////////////////////////////////////////
110
111 } // namespace animone::internal