diff --git a/applications/gui2/src/modules/addsource.cpp b/applications/gui2/src/modules/addsource.cpp index f584274c5fb9de9dec745709481ea663506be4f5..897af5be79658ffb4bc0ac1c951e14bbb636f51e 100644 --- a/applications/gui2/src/modules/addsource.cpp +++ b/applications/gui2/src/modules/addsource.cpp @@ -29,6 +29,10 @@ std::vector<std::string> AddCtrl::getNetSources() { return std::move(io->feed()->availableNetworkSources()); } +std::vector<std::string> AddCtrl::getFileSources() { + return std::move(io->feed()->availableFileSources()); +} + std::string AddCtrl::getSourceName(const std::string &uri) { return io->feed()->getName(uri); } diff --git a/applications/gui2/src/modules/addsource.hpp b/applications/gui2/src/modules/addsource.hpp index e243a2ec2f793c27a764a289d62a79469d789a1c..25064abe8a420b5ff3950b4728b16a871609a6c8 100644 --- a/applications/gui2/src/modules/addsource.hpp +++ b/applications/gui2/src/modules/addsource.hpp @@ -22,6 +22,7 @@ public: ftl::Configurable *add(const std::string &uri); std::vector<std::string> getNetSources(); + std::vector<std::string> getFileSources(); std::string getSourceName(const std::string &uri); bool isSourceActive(const std::string &uri); diff --git a/applications/gui2/src/views/addsource.cpp b/applications/gui2/src/views/addsource.cpp index c67f3e5f662ce9326b1e23fa381bb688b18214da..a1115d743f14b8160e0e46d02e71eefd63b928e9 100644 --- a/applications/gui2/src/views/addsource.cpp +++ b/applications/gui2/src/views/addsource.cpp @@ -83,6 +83,20 @@ void AddSourceWindow::rebuild() { { {"ftl", "FTL Captures"} }, true)); close(); }); + + auto filesrcs = ctrl_->getFileSources(); + + for (auto &s : filesrcs) { + button = new Button(filebuttons, ctrl_->getSourceName(s)); + if (ctrl_->isSourceActive(s)) { + button->setBackgroundColor(Color(0, 255, 0, 25)); + } + + button->setCallback([this, s]() { + ctrl_->add(s); + close(); + }); + } } void AddSourceWindow::close() { diff --git a/components/common/cpp/include/ftl/configuration.hpp b/components/common/cpp/include/ftl/configuration.hpp index 1111e229e1f2564d8af4de9878a1af1e8c18523d..7ad81440b1abdcd4d4d2d6cf4a68d7be55be7c1c 100644 --- a/components/common/cpp/include/ftl/configuration.hpp +++ b/components/common/cpp/include/ftl/configuration.hpp @@ -24,6 +24,10 @@ bool create_directory(const std::string &path); bool is_video(const std::string &file); std::vector<std::string> directory_listing(const std::string &path); +nlohmann::json loadJSON(const std::string &path); + +bool saveJSON(const std::string &path, nlohmann::json &json); + namespace config { typedef nlohmann::json json_t; diff --git a/components/common/cpp/src/configuration.cpp b/components/common/cpp/src/configuration.cpp index 11115402284a3a0ad5db5e15f48c6eade77141b1..5e7bd0ea23122034eefbb71292318ac105f63bf5 100644 --- a/components/common/cpp/src/configuration.cpp +++ b/components/common/cpp/src/configuration.cpp @@ -33,6 +33,7 @@ using ftl::config::json_t; using std::ifstream; +using std::ofstream; using std::string; using std::map; using std::vector; @@ -175,6 +176,42 @@ optional<string> ftl::config::locateFile(const string &name) { return {}; } +nlohmann::json ftl::loadJSON(const std::string &path) { + ifstream i(path.c_str()); + //i.open(path); + if (i.is_open()) { + try { + nlohmann::json t; + i >> t; + return t; + } catch (nlohmann::json::parse_error& e) { + LOG(ERROR) << "Parse error in loading JSON: " << e.what(); + return {}; + } catch (...) { + LOG(ERROR) << "Unknown error opening JSON file: " << path; + } + return {}; + } else { + return {}; + } +} + +bool ftl::saveJSON(const std::string &path, nlohmann::json &json) { + ofstream o(path.c_str()); + //i.open(path); + if (o.is_open()) { + try { + o << json; + return true; + } catch (...) { + LOG(ERROR) << "Unknown error saving JSON file: " << path; + } + return false; + } else { + return false; + } +} + /** * Combine one json config with another patch json config. */ diff --git a/components/streams/include/ftl/streams/feed.hpp b/components/streams/include/ftl/streams/feed.hpp index cf24ffa61cf3e15e3acd7881f0b1a83122307b25..0cb76a61452b87749ec9843a4bdd7d9d4bed4507 100644 --- a/components/streams/include/ftl/streams/feed.hpp +++ b/components/streams/include/ftl/streams/feed.hpp @@ -54,7 +54,6 @@ public: }; private: - // public methods acquire lock if necessary, private methods assume locking // managed by caller std::mutex mtx_; diff --git a/components/streams/src/feed.cpp b/components/streams/src/feed.cpp index 7891818a9eface84487496cbfc23ebbdd2724cd2..6c294181691ac0edd32dd79750442a03fd099310 100644 --- a/components/streams/src/feed.cpp +++ b/components/streams/src/feed.cpp @@ -9,6 +9,8 @@ using ftl::stream::Feed; using ftl::codecs::Channel; +static nlohmann::json feed_config; + //////////////////////////////////////////////////////////////////////////////// Feed::Filter::Filter(Feed* feed, const std::unordered_set<uint32_t>& sources, const std::unordered_set<Channel>& channels) : @@ -46,6 +48,8 @@ Feed::Filter &Feed::Filter::select(const std::unordered_set<ftl::codecs::Channel Feed::Feed(nlohmann::json &config, ftl::net::Universe*net) : ftl::Configurable(config), net_(net) { + feed_config = ftl::loadJSON(FTL_LOCAL_CONFIG_ROOT "/feed.json"); + pool_ = std::make_unique<ftl::data::Pool>(3,5); stream_ = std::unique_ptr<ftl::stream::Muxer> @@ -142,6 +146,8 @@ Feed::Feed(nlohmann::json &config, ftl::net::Universe*net) : Feed::~Feed() { std::unique_lock<std::mutex> lk(mtx_); + ftl::saveJSON(FTL_LOCAL_CONFIG_ROOT "/feed.json", feed_config); + receiver_.reset(); // Note: Force destruction first to remove filters this way for (auto* filter : filters_) { @@ -285,7 +291,14 @@ std::vector<std::string> Feed::availableNetworkSources() { } std::vector<std::string> Feed::availableFileSources() { - return {}; + std::vector<std::string> files; + auto &recent_files = feed_config["recent_files"]; + + for (auto &f : recent_files.items()) { + files.push_back(f.key()); + } + + return files; } std::vector<std::string> Feed::availableDeviceSources() { @@ -319,7 +332,7 @@ std::string Feed::getName(const std::string &puri) { } else if (uri.getScheme() == ftl::URI::SCHEME_DEVICE) { return "Device"; } else if (uri.getScheme() == ftl::URI::SCHEME_FILE) { - // TODO: Parse last part of file name - extension + return feed_config["recent_files"][uri.getBaseURI()].value("name", "FTLFile"); } return "No Name"; @@ -365,6 +378,12 @@ uint32_t Feed::add(const std::string &path) { fstream->set("filename", uri.getPath()); } + auto &recent_files = feed_config["recent_files"]; + auto &file_details = recent_files[uri.getBaseURI()]; + std::string fname = uri.getPathSegment(-1); + file_details["name"] = fname.substr(0, fname.find_last_of('.')); + file_details["last_open"] = ftl::timer::get_time(); + // TODO: URI normalization; should happen in add(,,) or add(,,,) take // ftl::URI instead of std::string as argument. Note the bug above. // TODO: write unit test for uri parsing