Mercurial > minori
annotate src/library/library.cc @ 410:eb554255ea5f default tip
*: no crash
| author | Paper <paper@tflc.us> |
|---|---|
| date | Thu, 02 Apr 2026 01:09:09 -0400 |
| parents | 8d06825d96d1 |
| children |
| rev | line source |
|---|---|
|
222
b9f111d84d95
*: move to semver, remove old macos build, add library files
Paper <paper@paper.us.eu.org>
parents:
diff
changeset
|
1 #include "library/library.h" |
|
b9f111d84d95
*: move to semver, remove old macos build, add library files
Paper <paper@paper.us.eu.org>
parents:
diff
changeset
|
2 #include "core/anime_db.h" |
| 258 | 3 #include "core/session.h" |
|
222
b9f111d84d95
*: move to semver, remove old macos build, add library files
Paper <paper@paper.us.eu.org>
parents:
diff
changeset
|
4 #include "core/strings.h" |
|
b9f111d84d95
*: move to semver, remove old macos build, add library files
Paper <paper@paper.us.eu.org>
parents:
diff
changeset
|
5 |
|
b9f111d84d95
*: move to semver, remove old macos build, add library files
Paper <paper@paper.us.eu.org>
parents:
diff
changeset
|
6 #include "anitomy/anitomy.h" |
|
b9f111d84d95
*: move to semver, remove old macos build, add library files
Paper <paper@paper.us.eu.org>
parents:
diff
changeset
|
7 |
|
b9f111d84d95
*: move to semver, remove old macos build, add library files
Paper <paper@paper.us.eu.org>
parents:
diff
changeset
|
8 #include <filesystem> |
| 258 | 9 #include <string> |
|
222
b9f111d84d95
*: move to semver, remove old macos build, add library files
Paper <paper@paper.us.eu.org>
parents:
diff
changeset
|
10 #include <unordered_map> |
|
b9f111d84d95
*: move to semver, remove old macos build, add library files
Paper <paper@paper.us.eu.org>
parents:
diff
changeset
|
11 |
|
223
84e0a3c4737a
library: implement menu bar buttons
Paper <mrpapersonic@gmail.com>
parents:
222
diff
changeset
|
12 #include <iostream> |
|
84e0a3c4737a
library: implement menu bar buttons
Paper <mrpapersonic@gmail.com>
parents:
222
diff
changeset
|
13 |
|
84e0a3c4737a
library: implement menu bar buttons
Paper <mrpapersonic@gmail.com>
parents:
222
diff
changeset
|
14 namespace Library { |
|
84e0a3c4737a
library: implement menu bar buttons
Paper <mrpapersonic@gmail.com>
parents:
222
diff
changeset
|
15 |
|
382
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
369
diff
changeset
|
16 Database::Database() |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
369
diff
changeset
|
17 { |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
369
diff
changeset
|
18 /* Do this immediately :) */ |
| 398 | 19 /* Nevermind, this causes an immediate segfault on Windows |
|
382
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
369
diff
changeset
|
20 UpdateWatchers(); |
| 398 | 21 */ |
|
409
8d06825d96d1
library: refresh in a separate thread
Paper <paper@tflc.us>
parents:
398
diff
changeset
|
22 /* Also, this would be completely useless as the paths in |
|
8d06825d96d1
library: refresh in a separate thread
Paper <paper@tflc.us>
parents:
398
diff
changeset
|
23 * the config are not filled until after main() is |
|
8d06825d96d1
library: refresh in a separate thread
Paper <paper@tflc.us>
parents:
398
diff
changeset
|
24 * called. */ |
|
382
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
369
diff
changeset
|
25 } |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
369
diff
changeset
|
26 |
| 410 | 27 Database::~Database() |
| 28 { | |
| 29 /* Wait */ | |
| 30 if (refresh_thread_.joinable()) | |
| 31 refresh_thread_.join(); | |
| 32 } | |
| 33 | |
|
382
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
369
diff
changeset
|
34 void Database::UpdateWatchers() |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
369
diff
changeset
|
35 { |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
369
diff
changeset
|
36 /* TODO also need to remove unused watchers */ |
| 398 | 37 |
|
382
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
369
diff
changeset
|
38 for (const auto &p : session.config.library.paths) { |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
369
diff
changeset
|
39 if (watchers_.count(p)) |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
369
diff
changeset
|
40 continue; |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
369
diff
changeset
|
41 |
| 393 | 42 watchers_[p].reset( |
| 43 Filesystem::GetRecursiveFilesystemWatcher(reinterpret_cast<void *>(this), p, Database::StaticEventHandler)); | |
|
382
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
369
diff
changeset
|
44 } |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
369
diff
changeset
|
45 } |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
369
diff
changeset
|
46 |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
369
diff
changeset
|
47 bool Database::GetPathAnimeAndEpisode(const std::string &basename, int *aid, int *ep) |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
369
diff
changeset
|
48 { |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
369
diff
changeset
|
49 anitomy::Anitomy anitomy; |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
369
diff
changeset
|
50 anitomy.Parse(basename); |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
369
diff
changeset
|
51 |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
369
diff
changeset
|
52 const auto &elements = anitomy.elements(); |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
369
diff
changeset
|
53 |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
369
diff
changeset
|
54 const std::string title = Strings::ToUtf8String(elements.get(anitomy::kElementAnimeTitle)); |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
369
diff
changeset
|
55 |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
369
diff
changeset
|
56 const int id = Anime::db.LookupAnimeTitle(title); |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
369
diff
changeset
|
57 if (id <= 0 || (find_id_ && find_id_.value() != id)) |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
369
diff
changeset
|
58 return false; |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
369
diff
changeset
|
59 |
| 393 | 60 const int episode = Strings::ToInt<int>(Strings::ToUtf8String(elements.get(anitomy::kElementEpisodeNumber))); |
|
382
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
369
diff
changeset
|
61 |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
369
diff
changeset
|
62 *aid = id; |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
369
diff
changeset
|
63 *ep = episode; |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
369
diff
changeset
|
64 return true; |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
369
diff
changeset
|
65 } |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
369
diff
changeset
|
66 |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
369
diff
changeset
|
67 void Database::EventHandler(const std::filesystem::path &path, Filesystem::IWatcher::Event event) |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
369
diff
changeset
|
68 { |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
369
diff
changeset
|
69 std::string bname = path.filename().u8string(); |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
369
diff
changeset
|
70 int aid, ep; |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
369
diff
changeset
|
71 |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
369
diff
changeset
|
72 if (!GetPathAnimeAndEpisode(bname, &aid, &ep)) |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
369
diff
changeset
|
73 return; |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
369
diff
changeset
|
74 |
|
409
8d06825d96d1
library: refresh in a separate thread
Paper <paper@tflc.us>
parents:
398
diff
changeset
|
75 /* Lock the items mutex */ |
|
8d06825d96d1
library: refresh in a separate thread
Paper <paper@tflc.us>
parents:
398
diff
changeset
|
76 const std::lock_guard<std::recursive_mutex> lock(items_mutex_); |
|
8d06825d96d1
library: refresh in a separate thread
Paper <paper@tflc.us>
parents:
398
diff
changeset
|
77 |
|
382
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
369
diff
changeset
|
78 switch (event) { |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
369
diff
changeset
|
79 case Filesystem::IWatcher::Created: |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
369
diff
changeset
|
80 items[aid][ep] = path; |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
369
diff
changeset
|
81 break; |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
369
diff
changeset
|
82 case Filesystem::IWatcher::Deleted: |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
369
diff
changeset
|
83 /* kill it off */ |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
369
diff
changeset
|
84 items[aid].erase(ep); |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
369
diff
changeset
|
85 if (items[aid].empty()) |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
369
diff
changeset
|
86 items.erase(aid); |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
369
diff
changeset
|
87 break; |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
369
diff
changeset
|
88 } |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
369
diff
changeset
|
89 } |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
369
diff
changeset
|
90 |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
369
diff
changeset
|
91 void Database::StaticEventHandler(void *opaque, const std::filesystem::path &path, Filesystem::IWatcher::Event event) |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
369
diff
changeset
|
92 { |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
369
diff
changeset
|
93 /* Forward to class function */ |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
369
diff
changeset
|
94 reinterpret_cast<Database *>(opaque)->EventHandler(path, event); |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
369
diff
changeset
|
95 } |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
369
diff
changeset
|
96 |
| 369 | 97 std::optional<std::filesystem::path> Database::GetAnimeFolder(int id) |
| 98 { | |
|
366
886f66775f31
animone: add preliminary AT-SPI stuff
Paper <paper@tflc.us>
parents:
347
diff
changeset
|
99 // this function sucks, but it's the most I can really do for now. |
|
886f66775f31
animone: add preliminary AT-SPI stuff
Paper <paper@tflc.us>
parents:
347
diff
changeset
|
100 // |
|
886f66775f31
animone: add preliminary AT-SPI stuff
Paper <paper@tflc.us>
parents:
347
diff
changeset
|
101 // in the future the Refresh() function should look for directories |
|
886f66775f31
animone: add preliminary AT-SPI stuff
Paper <paper@tflc.us>
parents:
347
diff
changeset
|
102 // as well that fit the anime name and *also* have episodes in them. |
|
886f66775f31
animone: add preliminary AT-SPI stuff
Paper <paper@tflc.us>
parents:
347
diff
changeset
|
103 // it should give each of these directories a rating by how many |
|
886f66775f31
animone: add preliminary AT-SPI stuff
Paper <paper@tflc.us>
parents:
347
diff
changeset
|
104 // episodes are contained in them. whichever directory has more episodes |
|
886f66775f31
animone: add preliminary AT-SPI stuff
Paper <paper@tflc.us>
parents:
347
diff
changeset
|
105 // wins, or the first found if there is an equal amount. |
|
886f66775f31
animone: add preliminary AT-SPI stuff
Paper <paper@tflc.us>
parents:
347
diff
changeset
|
106 |
|
409
8d06825d96d1
library: refresh in a separate thread
Paper <paper@tflc.us>
parents:
398
diff
changeset
|
107 /* TODO use a shared lock instead */ |
|
8d06825d96d1
library: refresh in a separate thread
Paper <paper@tflc.us>
parents:
398
diff
changeset
|
108 const std::lock_guard<std::recursive_mutex> lock(items_mutex_); |
|
8d06825d96d1
library: refresh in a separate thread
Paper <paper@tflc.us>
parents:
398
diff
changeset
|
109 |
| 369 | 110 for (const auto &[anime_id, episodes] : items) { |
|
366
886f66775f31
animone: add preliminary AT-SPI stuff
Paper <paper@tflc.us>
parents:
347
diff
changeset
|
111 if (id != anime_id) |
|
886f66775f31
animone: add preliminary AT-SPI stuff
Paper <paper@tflc.us>
parents:
347
diff
changeset
|
112 continue; |
|
886f66775f31
animone: add preliminary AT-SPI stuff
Paper <paper@tflc.us>
parents:
347
diff
changeset
|
113 |
|
382
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
369
diff
changeset
|
114 for (const auto &[episode, path] : episodes) |
|
366
886f66775f31
animone: add preliminary AT-SPI stuff
Paper <paper@tflc.us>
parents:
347
diff
changeset
|
115 return path.parent_path(); |
|
886f66775f31
animone: add preliminary AT-SPI stuff
Paper <paper@tflc.us>
parents:
347
diff
changeset
|
116 |
|
886f66775f31
animone: add preliminary AT-SPI stuff
Paper <paper@tflc.us>
parents:
347
diff
changeset
|
117 break; |
|
886f66775f31
animone: add preliminary AT-SPI stuff
Paper <paper@tflc.us>
parents:
347
diff
changeset
|
118 } |
|
886f66775f31
animone: add preliminary AT-SPI stuff
Paper <paper@tflc.us>
parents:
347
diff
changeset
|
119 |
|
886f66775f31
animone: add preliminary AT-SPI stuff
Paper <paper@tflc.us>
parents:
347
diff
changeset
|
120 return std::nullopt; |
|
886f66775f31
animone: add preliminary AT-SPI stuff
Paper <paper@tflc.us>
parents:
347
diff
changeset
|
121 } |
|
886f66775f31
animone: add preliminary AT-SPI stuff
Paper <paper@tflc.us>
parents:
347
diff
changeset
|
122 |
|
409
8d06825d96d1
library: refresh in a separate thread
Paper <paper@tflc.us>
parents:
398
diff
changeset
|
123 void Database::RefreshThread() |
|
8d06825d96d1
library: refresh in a separate thread
Paper <paper@tflc.us>
parents:
398
diff
changeset
|
124 { |
|
8d06825d96d1
library: refresh in a separate thread
Paper <paper@tflc.us>
parents:
398
diff
changeset
|
125 for (const auto &w : watchers_) |
|
8d06825d96d1
library: refresh in a separate thread
Paper <paper@tflc.us>
parents:
398
diff
changeset
|
126 w.second->Process(); |
|
8d06825d96d1
library: refresh in a separate thread
Paper <paper@tflc.us>
parents:
398
diff
changeset
|
127 } |
|
8d06825d96d1
library: refresh in a separate thread
Paper <paper@tflc.us>
parents:
398
diff
changeset
|
128 |
|
8d06825d96d1
library: refresh in a separate thread
Paper <paper@tflc.us>
parents:
398
diff
changeset
|
129 /* TODO the threading code for this could be better */ |
| 369 | 130 void Database::Refresh(std::optional<int> find_id) |
| 131 { | |
|
409
8d06825d96d1
library: refresh in a separate thread
Paper <paper@tflc.us>
parents:
398
diff
changeset
|
132 /* Join the thread if it was already run */ |
|
8d06825d96d1
library: refresh in a separate thread
Paper <paper@tflc.us>
parents:
398
diff
changeset
|
133 if (refresh_thread_.joinable()) |
|
8d06825d96d1
library: refresh in a separate thread
Paper <paper@tflc.us>
parents:
398
diff
changeset
|
134 refresh_thread_.join(); |
|
8d06825d96d1
library: refresh in a separate thread
Paper <paper@tflc.us>
parents:
398
diff
changeset
|
135 |
|
8d06825d96d1
library: refresh in a separate thread
Paper <paper@tflc.us>
parents:
398
diff
changeset
|
136 /* This is terrible */ |
|
382
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
369
diff
changeset
|
137 find_id_ = find_id; |
|
222
b9f111d84d95
*: move to semver, remove old macos build, add library files
Paper <paper@paper.us.eu.org>
parents:
diff
changeset
|
138 |
|
382
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
369
diff
changeset
|
139 UpdateWatchers(); |
|
222
b9f111d84d95
*: move to semver, remove old macos build, add library files
Paper <paper@paper.us.eu.org>
parents:
diff
changeset
|
140 |
|
409
8d06825d96d1
library: refresh in a separate thread
Paper <paper@tflc.us>
parents:
398
diff
changeset
|
141 refresh_thread_ = std::thread(&Database::RefreshThread, this); |
|
222
b9f111d84d95
*: move to semver, remove old macos build, add library files
Paper <paper@paper.us.eu.org>
parents:
diff
changeset
|
142 } |
|
223
84e0a3c4737a
library: implement menu bar buttons
Paper <mrpapersonic@gmail.com>
parents:
222
diff
changeset
|
143 |
| 369 | 144 void Database::Refresh() |
| 145 { | |
|
366
886f66775f31
animone: add preliminary AT-SPI stuff
Paper <paper@tflc.us>
parents:
347
diff
changeset
|
146 Refresh(std::nullopt); |
|
886f66775f31
animone: add preliminary AT-SPI stuff
Paper <paper@tflc.us>
parents:
347
diff
changeset
|
147 } |
|
886f66775f31
animone: add preliminary AT-SPI stuff
Paper <paper@tflc.us>
parents:
347
diff
changeset
|
148 |
| 369 | 149 void Database::Refresh(int id) |
| 150 { | |
|
366
886f66775f31
animone: add preliminary AT-SPI stuff
Paper <paper@tflc.us>
parents:
347
diff
changeset
|
151 Refresh(std::optional<int>(id)); |
|
886f66775f31
animone: add preliminary AT-SPI stuff
Paper <paper@tflc.us>
parents:
347
diff
changeset
|
152 } |
|
886f66775f31
animone: add preliminary AT-SPI stuff
Paper <paper@tflc.us>
parents:
347
diff
changeset
|
153 |
|
409
8d06825d96d1
library: refresh in a separate thread
Paper <paper@tflc.us>
parents:
398
diff
changeset
|
154 std::optional<std::filesystem::path> Database::GetAnimeEpisodePath(int anime, int episode) |
|
8d06825d96d1
library: refresh in a separate thread
Paper <paper@tflc.us>
parents:
398
diff
changeset
|
155 { |
|
8d06825d96d1
library: refresh in a separate thread
Paper <paper@tflc.us>
parents:
398
diff
changeset
|
156 const std::lock_guard<std::recursive_mutex> lock(items_mutex_); |
|
8d06825d96d1
library: refresh in a separate thread
Paper <paper@tflc.us>
parents:
398
diff
changeset
|
157 |
|
8d06825d96d1
library: refresh in a separate thread
Paper <paper@tflc.us>
parents:
398
diff
changeset
|
158 if (items.find(anime) == items.end() || items[anime].find(episode) == items[anime].end()) |
|
8d06825d96d1
library: refresh in a separate thread
Paper <paper@tflc.us>
parents:
398
diff
changeset
|
159 return std::nullopt; |
|
8d06825d96d1
library: refresh in a separate thread
Paper <paper@tflc.us>
parents:
398
diff
changeset
|
160 |
|
8d06825d96d1
library: refresh in a separate thread
Paper <paper@tflc.us>
parents:
398
diff
changeset
|
161 return items[anime][episode]; |
|
8d06825d96d1
library: refresh in a separate thread
Paper <paper@tflc.us>
parents:
398
diff
changeset
|
162 } |
|
8d06825d96d1
library: refresh in a separate thread
Paper <paper@tflc.us>
parents:
398
diff
changeset
|
163 |
|
383
27c462bc7815
make the "Now Playing" page actually work
Paper <paper@tflc.us>
parents:
382
diff
changeset
|
164 // TODO export to JSON on exit |
|
366
886f66775f31
animone: add preliminary AT-SPI stuff
Paper <paper@tflc.us>
parents:
347
diff
changeset
|
165 |
|
328
71396ecb6f7e
library: convert to class + database
Paper <paper@paper.us.eu.org>
parents:
319
diff
changeset
|
166 Database db; |
|
71396ecb6f7e
library: convert to class + database
Paper <paper@paper.us.eu.org>
parents:
319
diff
changeset
|
167 |
| 258 | 168 } // namespace Library |
