1 /** @file assetobserver.cpp  Utility for observing available assets.
2  *
3  * @authors Copyright (c) 2014-2017 Jaakko Keränen <jaakko.keranen@iki.fi>
4  *
5  * @par License
6  * LGPL: http://www.gnu.org/licenses/lgpl.html
7  *
8  * <small>This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU Lesser General Public License as published by
10  * the Free Software Foundation; either version 3 of the License, or (at your
11  * option) any later version. This program is distributed in the hope that it
12  * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
13  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
14  * General Public License for more details. You should have received a copy of
15  * the GNU Lesser General Public License along with this program; if not, see:
16  * http://www.gnu.org/licenses</small>
17  */
18 
19 #include "de/filesys/AssetObserver"
20 #include "de/App"
21 #include "de/FileSystem"
22 #include "de/LinkFile"
23 #include "de/Loop"
24 #include <regex>
25 
26 namespace de {
27 namespace filesys {
28 
29 static const std::string PREFIX = "asset";
30 
DENG2_PIMPL(AssetObserver)31 DENG2_PIMPL(AssetObserver)
32 , DENG2_OBSERVES(FileIndex, Addition)
33 , DENG2_OBSERVES(FileIndex, Removal)
34 {
35     const std::regex pattern;
36     LoopCallback mainCall;
37 
38     static FileIndex const &linkIndex() {
39         return App::fileSystem().indexFor(DENG2_TYPE_NAME(LinkFile));
40     }
41 
42     static String assetIdentifier(File const &link) {
43         DENG2_ASSERT(link.name().beginsWith(String::fromStdString(PREFIX + ".")));
44         return link.name().mid(6);
45     }
46 
47     Impl(Public *i, String const &regex)
48         : Base(i)
49         , pattern(PREFIX + "\\." + regex.toStdString(), std::regex::icase)
50     {
51         // We will observe available model assets.
52         linkIndex().audienceForAddition() += this;
53         linkIndex().audienceForRemoval()  += this;
54     }
55 
56     void fileAdded(File const &link, FileIndex const &)
57     {
58         // Only matching assets cause notifications.
59         if (!std::regex_match(link.name().toStdString(), pattern)) return;
60 
61         String const ident = assetIdentifier(link);
62         mainCall.enqueue([this, ident] ()
63         {
64             DENG2_FOR_PUBLIC_AUDIENCE2(Availability, i)
65             {
66                 i->assetAvailabilityChanged(ident, Added);
67             }
68         });
69     }
70 
71     void fileRemoved(File const &link, FileIndex const &)
72     {
73         // Only matching assets cause notifications.
74         if (!std::regex_match(link.name().toStdString(), pattern)) return;
75 
76         DENG2_FOR_PUBLIC_AUDIENCE2(Availability, i)
77         {
78             i->assetAvailabilityChanged(assetIdentifier(link), Removed);
79         }
80     }
81 
82     DENG2_PIMPL_AUDIENCE(Availability)
83 };
84 
DENG2_AUDIENCE_METHOD(AssetObserver,Availability)85 DENG2_AUDIENCE_METHOD(AssetObserver, Availability)
86 
87 AssetObserver::AssetObserver(String const &regexPattern)
88     : d(new Impl(this, regexPattern))
89 {}
90 
91 } // namespace filesys
92 } // namespace de
93