Skip to content

Commit 4ca6021

Browse files
authored
Make fader setting possible in the CLI (#506)
* Add cli program to set faders * Set faders in CLI * Add ncurses to docker * Fix compilation of test
1 parent 669fd6f commit 4ca6021

37 files changed

+362
-180
lines changed

CMakeLists.txt

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ pkg_check_modules(ALSA alsa REQUIRED)
1010
pkg_check_modules(LIBOLA libola REQUIRED)
1111

1212
find_package(Threads REQUIRED)
13+
find_package(Curses)
1314

1415
find_library(AUBIO_LIBRARY NAMES aubio)
1516
find_path(AUBIO_INCLUDE_DIR NAMES aubio/aubio.h)
@@ -64,12 +65,14 @@ set(CMAKE_CXX_EXTENSIONS NO)
6465

6566
add_definitions(-DGLIGHT_INSTALL_PATH="${CMAKE_INSTALL_PREFIX}")
6667

67-
include_directories(SYSTEM ${GTKMM_INCLUDE_DIRS})
68-
include_directories(SYSTEM ${SIGCXX2_INCLUDE_DIRS})
69-
include_directories(SYSTEM ${FLACPP_INCLUDE_DIRS})
70-
include_directories(SYSTEM ${ALSA_INCLUDE_DIRS})
71-
include_directories(SYSTEM ${LIBOLA_INCLUDE_DIRS})
72-
include_directories(SYSTEM ${AUBIO_INCLUDE_DIR})
68+
include_directories(SYSTEM
69+
${GTKMM_INCLUDE_DIRS}
70+
${SIGCXX2_INCLUDE_DIRS}
71+
${FLACPP_INCLUDE_DIRS}
72+
${ALSA_INCLUDE_DIRS}
73+
${LIBOLA_INCLUDE_DIRS}
74+
${AUBIO_INCLUDE_DIR}
75+
${CURSES_INCLUDE_DIRS})
7376

7477
set(GUIFILES
7578
gui/application.cpp
@@ -108,7 +111,6 @@ set(GUIFILES
108111
gui/mainwindow/mainmenu.cpp
109112
gui/mainwindow/mainwindow.cpp
110113
gui/mainwindow/objectlistframe.cpp
111-
gui/state/faderstate.cpp
112114
gui/windows/addfixturewindow.cpp
113115
gui/windows/chasepropertieswindow.cpp
114116
gui/windows/designwizard.cpp
@@ -136,6 +138,7 @@ set(SYSTEMFILES
136138
system/writer.cpp
137139
system/midi/controller.cpp
138140
system/midi/manager.cpp
141+
uistate/faderstate.cpp
139142
)
140143

141144
set(THEATREFILES
@@ -176,13 +179,9 @@ include_directories(external/hsluv)
176179
include_directories($<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>)
177180

178181
add_library(glight-object OBJECT
179-
${THEATREFILES} ${SYSTEMFILES} ${GUIFILES} ${EXTERNALFILES})
182+
${THEATREFILES} ${SYSTEMFILES} ${EXTERNALFILES})
180183

181-
add_executable(glight $<TARGET_OBJECTS:glight-object> glight.cpp)
182-
add_executable(glight-cli $<TARGET_OBJECTS:glight-object> glight-cli.cpp)
183-
184-
target_link_directories(glight PRIVATE ${GTKMM_LIBDIR} ${LIBOLA_LIBDIR})
185-
target_link_directories(glight-cli PRIVATE ${GTKMM_LIBDIR} ${LIBOLA_LIBDIR})
184+
add_library(glight-graphical OBJECT ${GUIFILES})
186185

187186
set(GLIGHT_LIBRARIES
188187
${FLACPP_LIBRARIES}
@@ -193,16 +192,28 @@ set(GLIGHT_LIBRARIES
193192
${LIBOLA_LIBRARIES}
194193
${CMAKE_THREAD_LIBS_INIT})
195194

195+
add_executable(glight $<TARGET_OBJECTS:glight-graphical> $<TARGET_OBJECTS:glight-object> glight.cpp)
196+
target_link_directories(glight PRIVATE ${GTKMM_LIBDIR} ${LIBOLA_LIBDIR})
196197
target_link_libraries(glight ${GLIGHT_LIBRARIES})
197-
target_link_libraries(glight-cli ${GLIGHT_LIBRARIES})
198+
199+
add_executable(glight-player $<TARGET_OBJECTS:glight-object> glight-player.cpp)
200+
target_link_directories(glight-player PRIVATE ${GTKMM_LIBDIR} ${LIBOLA_LIBDIR})
201+
target_link_libraries(glight-player ${GLIGHT_LIBRARIES})
202+
203+
if(Curses_FOUND)
204+
add_executable(glight-cli $<TARGET_OBJECTS:glight-object> glight-cli.cpp)
205+
target_link_directories(glight-cli PRIVATE ${GTKMM_LIBDIR} ${LIBOLA_LIBDIR})
206+
target_link_libraries(glight-cli ${GLIGHT_LIBRARIES} ${CURSES_LIBRARIES})
207+
endif()
198208

199209
if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.30")
200-
cmake_policy(SET CMP0167 NEW)
210+
cmake_policy(SET CMP0167 NEW)
201211
endif()
202212
find_package(Boost COMPONENTS unit_test_framework)
203213
if(Boost_FOUND)
204214
include_directories(SYSTEM ${Boost_INCLUDE_DIR})
205215
add_executable(runtests EXCLUDE_FROM_ALL
216+
$<TARGET_OBJECTS:glight-graphical>
206217
$<TARGET_OBJECTS:glight-object>
207218
tests/runtests.cpp
208219
tests/gui/tunits.cpp
@@ -269,5 +280,5 @@ set(CPACK_DEBIAN_PACKAGE_SECTION misc)
269280

270281
include(CPack)
271282

272-
install(TARGETS glight glight-cli RUNTIME DESTINATION bin)
283+
install(TARGETS glight glight-player RUNTIME DESTINATION bin)
273284
install(DIRECTORY data/icons data/applications DESTINATION share )

glight-cli.cpp

Lines changed: 111 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,137 @@
11
#include <iostream>
22
#include <string>
33

4+
#include <ncurses.h>
5+
46
#include "system/reader.h"
57
#include "system/settings.h"
8+
69
#include "theatre/management.h"
710

11+
#include "uistate/uistate.h"
12+
813
namespace glight {
914

15+
using uistate::FaderControlType;
16+
using uistate::FaderSetState;
17+
using uistate::FaderState;
18+
using uistate::UIState;
19+
20+
namespace {
21+
22+
struct TextFader {
23+
std::string label;
24+
theatre::SourceValue* source;
25+
size_t line;
26+
};
27+
28+
std::string Trim(const std::string& input, size_t width) {
29+
if (input.size() < width) return input;
30+
if (width > 5) {
31+
return input.substr(0, width - 2) + "..";
32+
} else {
33+
return input.substr(0, width);
34+
}
35+
}
36+
37+
std::vector<TextFader> InitializeFaders(const UIState& state) {
38+
std::vector<TextFader> result;
39+
size_t n_lines = 0;
40+
for (const std::unique_ptr<FaderSetState>& fader_set : state.FaderSets()) {
41+
mvprintw(n_lines, 0, fader_set->name.c_str()); // TODO trim
42+
++n_lines;
43+
44+
for (const std::unique_ptr<FaderState>& fader : fader_set->faders) {
45+
if (fader->GetFaderType() == FaderControlType::Fader) {
46+
theatre::SourceValue* source = nullptr;
47+
if (!fader->GetSourceValues().empty())
48+
source = fader->GetSourceValues()[0];
49+
if (source) {
50+
TextFader& new_fader = result.emplace_back();
51+
new_fader.label = source->Name();
52+
new_fader.source = source;
53+
new_fader.line = n_lines;
54+
++n_lines;
55+
}
56+
}
57+
}
58+
}
59+
return result;
60+
}
61+
62+
void PrintState(const std::vector<TextFader>& faders, size_t width,
63+
size_t height) {
64+
for (const TextFader& fader : faders) {
65+
if (fader.line >= height) break;
66+
const theatre::ControlValue value = fader.source->A().Value();
67+
const std::string check_box = value ? "[X] " : "[ ] ";
68+
mvprintw(fader.line, 1, (check_box + Trim(fader.label, width - 5)).c_str());
69+
}
70+
}
71+
1072
void RunCli(const std::string filename) {
1173
const glight::system::Settings settings = glight::system::LoadSettings();
1274
glight::theatre::Management management(settings);
13-
glight::system::Read(filename, management);
75+
UIState state;
76+
glight::system::Read(filename, management, &state);
1477
management.GetUniverses().Open();
1578
management.Run();
16-
std::cout << "Press enter to exit.\n";
17-
std::cin.get();
79+
80+
initscr();
81+
82+
int height;
83+
int width;
84+
getmaxyx(stdscr, height, width);
85+
keypad(stdscr, TRUE);
86+
noecho();
87+
88+
std::vector<TextFader> faders = InitializeFaders(state);
89+
PrintState(faders, width, height);
90+
91+
size_t selected_fader = 0;
92+
bool running = true;
93+
do {
94+
move(faders[selected_fader].line, 2);
95+
const int c = getch();
96+
switch (c) {
97+
case KEY_UP:
98+
if (selected_fader > 0) --selected_fader;
99+
break;
100+
case KEY_DOWN:
101+
if (selected_fader + 1 < faders.size()) ++selected_fader;
102+
break;
103+
case ' ': {
104+
TextFader& fader = faders[selected_fader];
105+
theatre::ControlValue value = fader.source->A().Value();
106+
if (value) {
107+
value = theatre::ControlValue::Zero();
108+
printw(" ");
109+
} else {
110+
value = theatre::ControlValue::Max();
111+
printw("X");
112+
}
113+
fader.source->A().Set(value);
114+
} break;
115+
case 'q':
116+
running = false;
117+
break;
118+
}
119+
} while (running);
120+
121+
endwin();
122+
18123
management.BlackOut(false, 0.0f);
19-
std::cout << "Stopping...\n";
20124
// There is some time required for the black out to take effect.
21125
usleep(400000);
22126
}
23127

128+
} // namespace
24129
} // namespace glight
25130

26131
int main(int argc, char* argv[]) {
27132
if (argc <= 1) {
28-
std::cout << "Syntax: glight-cli <show-file>\n\n"
29-
"glight-cli can output a previously created gshow file "
133+
std::cout << "Syntax: glight-player <show-file>\n\n"
134+
"glight-player can play a previously created gshow file "
30135
"without requiring a graphical desktop.\n";
31136
return 0;
32137
}

glight-player.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#include <iostream>
2+
#include <string>
3+
4+
#include "system/reader.h"
5+
#include "system/settings.h"
6+
#include "theatre/management.h"
7+
8+
namespace glight {
9+
10+
void RunPlayer(const std::string filename) {
11+
const glight::system::Settings settings = glight::system::LoadSettings();
12+
glight::theatre::Management management(settings);
13+
glight::system::Read(filename, management);
14+
management.GetUniverses().Open();
15+
management.Run();
16+
std::cout << "Press enter to exit.\n";
17+
std::cin.get();
18+
management.BlackOut(false, 0.0f);
19+
std::cout << "Stopping...\n";
20+
// There is some time required for the black out to take effect.
21+
usleep(400000);
22+
}
23+
24+
} // namespace glight
25+
26+
int main(int argc, char* argv[]) {
27+
if (argc <= 1) {
28+
std::cout << "Syntax: glight-player <show-file>\n\n"
29+
"glight-player can play a previously created gshow file "
30+
"without requiring a graphical desktop.\n";
31+
return 0;
32+
}
33+
34+
glight::RunPlayer(argv[1]);
35+
}

gui/faders/colorcontrolwidget.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
#include "controlmenu.h"
44
#include "faderwindow.h"
55

6-
#include "gui/state/faderstate.h"
6+
#include "uistate/faderstate.h"
77

88
#include "gui/dialogs/controllableselectiondialog.h"
99

@@ -19,8 +19,8 @@ namespace glight::gui {
1919
using theatre::Color;
2020

2121
ColorControlWidget::ColorControlWidget(FaderWindow &fader_window,
22-
FaderState &state, ControlMode mode,
23-
char key)
22+
uistate::FaderState &state,
23+
ControlMode mode, char key)
2424
: ControlWidget(fader_window, state, mode),
2525
color_selector_(&fader_window, false) {
2626
color_selector_.SignalColorChanged().connect([&]() { OnColorChanged(); });

gui/faders/colorcontrolwidget.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ namespace glight::gui {
1313

1414
class ColorControlWidget final : public ControlWidget {
1515
public:
16-
ColorControlWidget(FaderWindow &fader_window, FaderState &state,
16+
ColorControlWidget(FaderWindow &fader_window, uistate::FaderState &state,
1717
ControlMode mode, char key);
1818
~ColorControlWidget();
1919

gui/faders/combocontrolwidget.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
#include "controlmenu.h"
66
#include "faderwindow.h"
77

8-
#include "gui/state/faderstate.h"
8+
#include "uistate/faderstate.h"
99

1010
#include "gui/dialogs/inputselectdialog.h"
1111
#include "gui/dialogs/stringinputdialog.h"
@@ -23,8 +23,8 @@ using theatre::ControlValue;
2323
using theatre::SourceValue;
2424

2525
ComboControlWidget::ComboControlWidget(FaderWindow &fader_window,
26-
FaderState &state, ControlMode mode,
27-
char key)
26+
uistate::FaderState &state,
27+
ControlMode mode, char key)
2828
: ControlWidget(fader_window, state, mode) {
2929
set_orientation(Gtk::Orientation::VERTICAL);
3030
append(description_label_);

gui/faders/combocontrolwidget.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ namespace glight::gui {
1212

1313
class ComboControlWidget final : public ControlWidget {
1414
public:
15-
ComboControlWidget(FaderWindow &fader_window, FaderState &state,
15+
ComboControlWidget(FaderWindow &fader_window, uistate::FaderState &state,
1616
ControlMode mode, char key);
1717
~ComboControlWidget();
1818

gui/faders/controlmenu.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
#include "controlmenu.h"
22

33
#include "gui/menufunctions.h"
4-
#include "gui/state/faderstate.h"
4+
#include "uistate/faderstate.h"
55

66
namespace glight::gui {
77

8-
ControlMenu::ControlMenu(const FaderState& state)
8+
ControlMenu::ControlMenu(const uistate::FaderState& state)
99
: actions_(Gio::SimpleActionGroup::create()) {
1010
auto menu = Gio::Menu::create();
1111
assign_section_ = Gio::Menu::create();

gui/faders/controlmenu.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,15 @@
1212

1313
#include <gtkmm/popovermenu.h>
1414

15-
namespace glight::gui {
16-
15+
namespace glight::uistate {
1716
class FaderState;
17+
}
18+
19+
namespace glight::gui {
1820

1921
class ControlMenu : public Gtk::PopoverMenu {
2022
public:
21-
ControlMenu(const FaderState& state);
23+
ControlMenu(const uistate::FaderState& state);
2224

2325
bool DisplayName() const { return GetState(display_name_); }
2426
bool DisplayFlashButton() const { return GetState(display_flash_button_); }

gui/faders/controlwidget.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
#include "gui/faders/controlmenu.h"
1111
#include "gui/faders/faderwindow.h"
1212

13-
#include "gui/state/faderstate.h"
13+
#include "uistate/faderstate.h"
1414

1515
#include "theatre/management.h"
1616
#include "theatre/presetvalue.h"
@@ -20,8 +20,8 @@ namespace glight::gui {
2020

2121
using theatre::SourceValue;
2222

23-
ControlWidget::ControlWidget(FaderWindow& fader_window, FaderState& state,
24-
ControlMode mode)
23+
ControlWidget::ControlWidget(FaderWindow& fader_window,
24+
uistate::FaderState& state, ControlMode mode)
2525
: _mode(mode),
2626
_state(state),
2727
fader_window_(fader_window),

0 commit comments

Comments
 (0)