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