258
|
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
|