diff --git a/CMakeLists.txt b/CMakeLists.txt index d6b3c10..74bd467 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -179,8 +179,10 @@ add_library(glight-object OBJECT ${THEATREFILES} ${SYSTEMFILES} ${GUIFILES} ${EXTERNALFILES}) add_executable(glight $ glight.cpp) +add_executable(glight-cli $ glight-cli.cpp) target_link_directories(glight PRIVATE ${GTKMM_LIBDIR} ${LIBOLA_LIBDIR}) +target_link_directories(glight-cli PRIVATE ${GTKMM_LIBDIR} ${LIBOLA_LIBDIR}) set(GLIGHT_LIBRARIES ${FLACPP_LIBRARIES} @@ -192,6 +194,7 @@ set(GLIGHT_LIBRARIES ${CMAKE_THREAD_LIBS_INIT}) target_link_libraries(glight ${GLIGHT_LIBRARIES}) +target_link_libraries(glight-cli ${GLIGHT_LIBRARIES}) if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.30") cmake_policy(SET CMP0167 NEW) @@ -265,5 +268,5 @@ set(CPACK_DEBIAN_PACKAGE_SECTION misc) include(CPack) -install(TARGETS glight RUNTIME DESTINATION bin) +install(TARGETS glight glight-cli RUNTIME DESTINATION bin) install(DIRECTORY data/icons data/applications DESTINATION share ) diff --git a/README.md b/README.md index d32335c..d62cb76 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ Glight is specifically aimed at shows or events in which the lighting is control ## Installation The source of Glight can be downloaded from Github, currently from https://github.com/aroffringa/glight/. Glight has a few dependencies. Fortunately, these are all available as precompiled packages in Debian, Ubuntu and most other distributions. Apart from system tools such as cmake, these are the important dependencies: -- [Gtkmm](https://www.gtkmm.org/), the C++ interface to GTK+. `libgtkmm-3.0-dev` on Debian and Ubuntu. +- [Gtkmm](https://www.gtkmm.org/), the C++ interface to GTK+. `libgtkmm-4.0-dev` on Debian and Ubuntu. - [Aubio](https://aubio.org/). `libaubio-dev` on Debian and Ubuntu. - [Flac++](https://xiph.org/flac/). `libflac++-dev` on Debian and Ubuntu. - [Alsa library](https://www.alsa-project.org/). `libasound2-dev` on Debian and Ubuntu. diff --git a/glight-cli.cpp b/glight-cli.cpp new file mode 100644 index 0000000..b981748 --- /dev/null +++ b/glight-cli.cpp @@ -0,0 +1,35 @@ +#include +#include + +#include "system/reader.h" +#include "system/settings.h" +#include "theatre/management.h" + +namespace glight { + +void RunCli(const std::string filename) { + const glight::system::Settings settings = glight::system::LoadSettings(); + glight::theatre::Management management(settings); + glight::system::Read(filename, management); + management.GetUniverses().Open(); + management.Run(); + std::cout << "Press enter to exit.\n"; + std::cin.get(); + management.BlackOut(false, 0.0f); + std::cout << "Stopping...\n"; + // There is some time required for the black out to take effect. + usleep(400000); +} + +} // namespace glight + +int main(int argc, char* argv[]) { + if (argc <= 1) { + std::cout << "Syntax: glight-cli \n\n" + "glight-cli can output a previously created gshow file " + "without requiring a graphical desktop.\n"; + return 0; + } + + glight::RunCli(argv[1]); +} diff --git a/glight.cpp b/glight.cpp index 4cf2528..3bb8fbd 100644 --- a/glight.cpp +++ b/glight.cpp @@ -1,11 +1,14 @@ #include #include +#include + #include "gui/application.h" #include "system/writer.h" int main(int argc, char *argv[]) { + Glib::set_init_to_users_preferred_locale(false); glight::gui::Application application; application.Run(argc, argv); diff --git a/gui/application.cpp b/gui/application.cpp index 3e30e22..331c1cf 100644 --- a/gui/application.cpp +++ b/gui/application.cpp @@ -8,6 +8,9 @@ namespace glight::gui { +Application::Application() + : Gtk::Application("org.glight", Gio::Application::Flags::HANDLES_OPEN) {} + void Application::Run(int argc, char *argv[]) { MainWindow window; if (argc > 1) { diff --git a/gui/application.h b/gui/application.h index 0f17241..f17d9f7 100644 --- a/gui/application.h +++ b/gui/application.h @@ -7,8 +7,7 @@ namespace glight::gui { class Application : public Gtk::Application { public: - Application() - : Gtk::Application("org.glight", Gio::Application::Flags::HANDLES_OPEN) {} + Application(); void Run(int argc, char *argv[]); }; diff --git a/gui/components/colorsequencewidget.cpp b/gui/components/colorsequencewidget.cpp index b9b84a0..921de7c 100644 --- a/gui/components/colorsequencewidget.cpp +++ b/gui/components/colorsequencewidget.cpp @@ -84,8 +84,8 @@ ColorSequenceWidget::ColorSequenceWidget(Gtk::Window *parent, _widgets.emplace_back(std::make_unique(_parent, true)); _box.append(*_widgets.back()); + _widgets.back()->set_hexpand(true); _widgets.back()->SignalColorChanged().connect([&]() { OnColorChange(0); }); - _widgets.back()->show(); _scrolledWindow.set_expand(true); _scrolledWindow.set_child(_box); diff --git a/gui/windows/addfixturewindow.cpp b/gui/windows/addfixturewindow.cpp index ff3c6b7..9224099 100644 --- a/gui/windows/addfixturewindow.cpp +++ b/gui/windows/addfixturewindow.cpp @@ -33,6 +33,7 @@ AddFixtureWindow::AddFixtureWindow() { grid_.set_column_spacing(2); stock_or_project_box_.append(stock_button_); + stock_button_.set_active(true); stock_button_.set_hexpand(true); stock_button_.signal_toggled().connect([&]() { onStockProjectToggled(); }); diff --git a/gui/windows/effectpropertieswindow.cpp b/gui/windows/effectpropertieswindow.cpp index 80b765d..ea2eb34 100644 --- a/gui/windows/effectpropertieswindow.cpp +++ b/gui/windows/effectpropertieswindow.cpp @@ -30,7 +30,6 @@ EffectPropertiesWindow::EffectPropertiesWindow(theatre::Effect& effect) _addConnectionButton.set_image_from_icon_name("list-add"); _addConnectionButton.signal_clicked().connect( sigc::mem_fun(*this, &EffectPropertiesWindow::onAddConnectionClicked)); - _connectionsButtonBox.set_homogeneous(true); _connectionsButtonBox.set_orientation(Gtk::Orientation::VERTICAL); _connectionsButtonBox.append(_addConnectionButton); @@ -58,12 +57,15 @@ EffectPropertiesWindow::EffectPropertiesWindow(theatre::Effect& effect) _connectionsScrolledWindow.set_policy(Gtk::PolicyType::NEVER, Gtk::PolicyType::AUTOMATIC); + _connectionsScrolledWindow.set_expand(true); _connectionsBox.append(_connectionsScrolledWindow); + _connectionsBox.set_expand(true); _connectionsFrame.set_child(_connectionsBox); + _connectionsFrame.set_expand(true); _mainHBox.append(_connectionsFrame); _propertiesFrame.set_child(_propertiesBox); - + _propertiesFrame.set_expand(true); _mainHBox.append(_propertiesFrame); _topBox.append(_mainHBox); @@ -107,10 +109,12 @@ void EffectPropertiesWindow::onAddConnectionClicked() { InputSelectDialog& dialog = static_cast(*dialog_); onInputsSelected({dialog.SelectedSourceValue()}); const bool stay_open = dialog.StayOpenRequested(); + if (!stay_open) dialog_.reset(); + } else { dialog_.reset(); - if (stay_open) onAddConnectionClicked(); } }); + dialog_->show(); } void EffectPropertiesWindow::onConnectControllableClicked() { @@ -133,7 +137,9 @@ void EffectPropertiesWindow::onConnectControllableClicked() { } onInputsSelected(sources); } + dialog_.reset(); }); + dialog_->show(); } void EffectPropertiesWindow::onRemoveConnectionClicked() { diff --git a/gui/windows/fixturelistwindow.cpp b/gui/windows/fixturelistwindow.cpp index 6a5bebe..6cfc0d2 100644 --- a/gui/windows/fixturelistwindow.cpp +++ b/gui/windows/fixturelistwindow.cpp @@ -177,10 +177,10 @@ void FixtureListWindow::onSetChannelButtonClicked() { GetSelection(); if (selection.size() == 1) { const system::ObservingPtr &fixture = selection[0]; - dialog_ = Gtk::MessageDialog(*this, "Set DMX channel", false, - Gtk::MessageType::QUESTION, - Gtk::ButtonsType::OK_CANCEL); - Gtk::MessageDialog &dialog = static_cast(dialog_); + dialog_ = std::make_unique( + *this, "Set DMX channel", false, Gtk::MessageType::QUESTION, + Gtk::ButtonsType::OK_CANCEL); + Gtk::MessageDialog &dialog = static_cast(*dialog_); dialog_entry_ = Gtk::Entry(); dialog_entry_.set_text(std::to_string( fixture->Functions().front()->MainChannel().Channel() + 1)); @@ -206,6 +206,7 @@ void FixtureListWindow::onSetChannelButtonClicked() { } } } + dialog_.reset(); }); dialog.show(); } diff --git a/gui/windows/fixturelistwindow.h b/gui/windows/fixturelistwindow.h index b7f44f6..cfde779 100644 --- a/gui/windows/fixturelistwindow.h +++ b/gui/windows/fixturelistwindow.h @@ -101,7 +101,7 @@ class FixtureListWindow : public ChildWindow { Gtk::Button up_button_; Gtk::Button down_button_; Gtk::Button reassign_button_{"Reassign"}; - Gtk::Dialog dialog_; + std::unique_ptr dialog_; Gtk::Entry dialog_entry_; }; diff --git a/system/jsonreader.cpp b/system/jsonreader.cpp index efaa36a..a342d23 100644 --- a/system/jsonreader.cpp +++ b/system/jsonreader.cpp @@ -99,7 +99,17 @@ std::unique_ptr ParseObject(std::istream& stream) { throw std::runtime_error("Extra trailing comma in object"); } } else { - throw std::runtime_error("Expecting name or '}' in object"); + std::string str(0, t); + if (t == 0) str = "null"; + std::string follows; + std::string line; + std::getline(stream, follows); + std::getline(stream, line); + follows += "\n" + line; + std::getline(stream, line); + follows += "\n" + line; + throw std::runtime_error("Expecting name or '}' in object, got '" + str + + "', before:\n" + follows); } } return result; diff --git a/tests/system/tjsonwriter.cpp b/tests/system/tjsonwriter.cpp index 4d65f00..5369d4e 100644 --- a/tests/system/tjsonwriter.cpp +++ b/tests/system/tjsonwriter.cpp @@ -103,11 +103,14 @@ BOOST_AUTO_TEST_CASE(number) { writer.Number(5); writer.Name("day"); writer.Number(8.3); + writer.Name("thousand"); + writer.Number(1000.0); writer.EndObject(); BOOST_CHECK_EQUAL(s.str(), R"("date": { "year": 1982, "month": 5, - "day": 8.3 + "day": 8.3, + "thousand": 1000 })"); }