Mercurial > minori
view src/library/library.cc @ 383:27c462bc7815
make the "Now Playing" page actually work
| author | Paper <paper@tflc.us> |
|---|---|
| date | Thu, 06 Nov 2025 07:10:58 -0500 |
| parents | 0265e125f680 |
| children |
line wrap: on
line source
#include "library/library.h" #include "core/anime_db.h" #include "core/session.h" #include "core/strings.h" #include "anitomy/anitomy.h" #include <filesystem> #include <string> #include <unordered_map> #include <iostream> namespace Library { Database::Database() { /* Do this immediately :) */ UpdateWatchers(); } void Database::UpdateWatchers() { /* TODO also need to remove unused watchers */ for (const auto &p : session.config.library.paths) { if (watchers_.count(p)) continue; watchers_[p].reset(Filesystem::GetRecursiveFilesystemWatcher(reinterpret_cast<void *>(this), p, Database::StaticEventHandler)); } } bool Database::GetPathAnimeAndEpisode(const std::string &basename, int *aid, int *ep) { anitomy::Anitomy anitomy; anitomy.Parse(basename); const auto &elements = anitomy.elements(); const std::string title = Strings::ToUtf8String(elements.get(anitomy::kElementAnimeTitle)); const int id = Anime::db.LookupAnimeTitle(title); if (id <= 0 || (find_id_ && find_id_.value() != id)) return false; const int episode = Strings::ToInt<int>(Strings::ToUtf8String(elements.get(anitomy::kElementEpisodeNumber))); *aid = id; *ep = episode; return true; } void Database::EventHandler(const std::filesystem::path &path, Filesystem::IWatcher::Event event) { std::string bname = path.filename().u8string(); int aid, ep; if (!GetPathAnimeAndEpisode(bname, &aid, &ep)) return; switch (event) { case Filesystem::IWatcher::Created: items[aid][ep] = path; break; case Filesystem::IWatcher::Deleted: /* kill it off */ items[aid].erase(ep); if (items[aid].empty()) items.erase(aid); break; } } void Database::StaticEventHandler(void *opaque, const std::filesystem::path &path, Filesystem::IWatcher::Event event) { /* Forward to class function */ reinterpret_cast<Database *>(opaque)->EventHandler(path, event); } std::optional<std::filesystem::path> Database::GetAnimeFolder(int id) { // this function sucks, but it's the most I can really do for now. // // in the future the Refresh() function should look for directories // as well that fit the anime name and *also* have episodes in them. // it should give each of these directories a rating by how many // episodes are contained in them. whichever directory has more episodes // wins, or the first found if there is an equal amount. for (const auto &[anime_id, episodes] : items) { if (id != anime_id) continue; for (const auto &[episode, path] : episodes) return path.parent_path(); break; } return std::nullopt; } /* TODO shove this into a separate thread; currently it blocks */ void Database::Refresh(std::optional<int> find_id) { find_id_ = find_id; UpdateWatchers(); for (const auto &w : watchers_) w.second->Process(); } void Database::Refresh() { Refresh(std::nullopt); } void Database::Refresh(int id) { Refresh(std::optional<int>(id)); } // TODO export to JSON on exit Database db; } // namespace Library
