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