/*
This file is part of Ingen.
Copyright 2007-2015 David Robillard
Ingen is free software: you can redistribute it and/or modify it under the
terms of the GNU Affero General Public License as published by the Free
Software Foundation, either version 3 of the License, or any later version.
Ingen is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU Affero General Public License for details.
You should have received a copy of the GNU Affero General Public License
along with Ingen. If not, see .
*/
#include "ThreadedLoader.hpp"
#include "App.hpp"
#include "ingen/Log.hpp"
#include "ingen/Parser.hpp"
#include "ingen/Properties.hpp"
#include "ingen/Serialiser.hpp"
#include "ingen/URI.hpp"
#include "ingen/World.hpp"
#include "ingen/client/GraphModel.hpp"
#include "raul/Path.hpp"
#include "raul/Semaphore.hpp"
#include "raul/Symbol.hpp"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
namespace ingen {
class Interface;
namespace gui {
ThreadedLoader::ThreadedLoader(App& app, std::shared_ptr engine)
: _app(app)
, _engine(std::move(engine))
, _thread(&ThreadedLoader::run, this)
{
if (!parser()) {
app.log().warn("Parser unavailable, graph loading disabled\n");
}
}
ThreadedLoader::~ThreadedLoader()
{
_exit_flag = true;
_sem.post();
if (_thread.joinable()) {
_thread.join();
}
}
std::shared_ptr
ThreadedLoader::parser()
{
return _app.world().parser();
}
void
ThreadedLoader::run()
{
while (_sem.wait() && !_exit_flag) {
const std::lock_guard lock{_mutex};
while (!_events.empty()) {
_events.front()();
_events.pop_front();
}
}
}
void
ThreadedLoader::load_graph(bool merge,
const FilePath& file_path,
const std::optional& engine_parent,
const std::optional& engine_symbol,
const std::optional& engine_data)
{
const std::lock_guard lock{_mutex};
Glib::ustring engine_base = "";
if (engine_parent) {
if (merge) {
engine_base = *engine_parent;
} else {
engine_base = engine_parent->base();
}
}
_events.emplace_back(sigc::hide_return(
sigc::bind(sigc::mem_fun(this, &ThreadedLoader::load_graph_event),
file_path,
engine_parent,
engine_symbol,
engine_data)));
_sem.post();
}
void
ThreadedLoader::load_graph_event(
const FilePath& file_path,
const std::optional& engine_parent,
const std::optional& engine_symbol,
const std::optional& engine_data)
{
const std::lock_guard lock{_app.world().rdf_mutex()};
_app.world().parser()->parse_file(_app.world(),
*_app.world().interface(),
file_path,
engine_parent,
engine_symbol,
engine_data);
}
void
ThreadedLoader::save_graph(
const std::shared_ptr& model,
const URI& uri)
{
const std::lock_guard lock{_mutex};
_events.emplace_back(sigc::hide_return(
sigc::bind(sigc::mem_fun(this, &ThreadedLoader::save_graph_event),
model,
uri)));
_sem.post();
}
void
ThreadedLoader::save_graph_event(
const std::shared_ptr& model,
const URI& uri)
{
assert(uri.scheme() == "file");
if (_app.serialiser()) {
const std::lock_guard lock{_app.world().rdf_mutex()};
if (uri.string().find(".ingen") != std::string::npos) {
_app.serialiser()->write_bundle(model, uri);
} else {
_app.serialiser()->start_to_file(model->path(), uri.file_path());
_app.serialiser()->serialise(model);
_app.serialiser()->finish();
}
}
}
} // namespace gui
} // namespace ingen