analyzer.reset(new Analyzer);
+ global_mixer->set_theme_menu_callback(bind(&MainWindow::setup_theme_menu, this));
+ setup_theme_menu();
+
struct sigaction act;
memset(&act, 0, sizeof(act));
act.sa_handler = schedule_cut_signal;
}
}
+void MainWindow::setup_theme_menu()
+{
+ std::vector<Theme::MenuEntry> theme_menu_entries = global_mixer->get_theme_menu();
+
+ if (theme_menu != nullptr) {
+ ui->menuBar->removeAction(theme_menu->menuAction());
+ theme_menu = nullptr;
+ }
+
+ if (!theme_menu_entries.empty()) {
+ theme_menu = new QMenu("&Theme");
+ for (const Theme::MenuEntry &entry : theme_menu_entries) {
+ QAction *action = theme_menu->addAction(QString::fromStdString(entry.text));
+ connect(action, &QAction::triggered, [entry] {
+ global_mixer->theme_menu_entry_clicked(entry.lua_ref);
+ });
+ }
+ ui->menuBar->insertMenu(ui->menu_Help->menuAction(), theme_menu);
+ }
+}
+
void MainWindow::limiter_threshold_knob_changed(int value)
{
float threshold_dbfs = value * 0.1f;
void set_white_balance(int channel_number, int x, int y);
void update_cutoff_labels(float cutoff_hz);
void update_eq_label(unsigned bus_index, EQBand band, float gain_db);
+ void setup_theme_menu();
// Called from DiskSpaceEstimator.
void report_disk_space(off_t free_bytes, double estimated_seconds_left);
Ui::MainWindow *ui;
QLabel *disk_free_label;
+ QMenu *theme_menu = nullptr;
QPushButton *transition_btn1, *transition_btn2, *transition_btn3;
std::vector<Ui::Display *> previews;
std::vector<Ui::AudioMiniView *> audio_miniviews;
extern Mixer *global_mixer;
+Theme *get_theme_updata(lua_State* L)
+{
+ luaL_checktype(L, lua_upvalueindex(1), LUA_TLIGHTUSERDATA);
+ return (Theme *)lua_touserdata(L, lua_upvalueindex(1));
+}
+
+int ThemeMenu_set(lua_State *L)
+{
+ Theme *theme = get_theme_updata(L);
+ return theme->set_theme_menu(L);
+}
+
namespace {
// Contains basically the same data as InputState, but does not hold on to
return 1;
}
-Theme *get_theme_updata(lua_State* L)
-{
- luaL_checktype(L, lua_upvalueindex(1), LUA_TLIGHTUSERDATA);
- return (Theme *)lua_touserdata(L, lua_upvalueindex(1));
-}
-
Effect *get_effect(lua_State *L, int idx)
{
if (luaL_testudata(L, idx, "WhiteBalanceEffect") ||
{ NULL, NULL }
};
+const luaL_Reg ThemeMenu_funcs[] = {
+ { "set", ThemeMenu_set },
+ { NULL, NULL }
+};
+
} // namespace
LiveInputWrapper::LiveInputWrapper(Theme *theme, EffectChain *chain, bmusb::PixelFormat pixel_format, bool override_bounce, bool deinterlace)
register_class("MultiplyEffect", MultiplyEffect_funcs);
register_class("MixEffect", MixEffect_funcs);
register_class("InputStateInfo", InputStateInfo_funcs);
+ register_class("ThemeMenu", ThemeMenu_funcs);
// Run script. Search through all directories until we find a file that will load
// (as in, does not return LUA_ERRFILE); then run it. We store load errors
}
assert(lua_gettop(L) == 0);
}
+
+int Theme::set_theme_menu(lua_State *L)
+{
+ for (const Theme::MenuEntry &entry : theme_menu) {
+ luaL_unref(L, LUA_REGISTRYINDEX, entry.lua_ref);
+ }
+ theme_menu.clear();
+
+ int num_elements = lua_gettop(L);
+ for (int i = 1; i <= num_elements; ++i) {
+ lua_rawgeti(L, i, 1);
+ const string text = checkstdstring(L, -1);
+ lua_pop(L, 1);
+
+ lua_rawgeti(L, i, 2);
+ luaL_checktype(L, -1, LUA_TFUNCTION);
+ int ref = luaL_ref(L, LUA_REGISTRYINDEX);
+
+ theme_menu.push_back(MenuEntry{ text, ref });
+ }
+ lua_pop(L, num_elements);
+ assert(lua_gettop(L) == 0);
+
+ if (theme_menu_callback != nullptr) {
+ theme_menu_callback();
+ }
+
+ return 0;
+}
+
+void Theme::theme_menu_entry_clicked(int lua_ref)
+{
+ lua_rawgeti(L, LUA_REGISTRYINDEX, lua_ref);
+ if (lua_pcall(L, 0, 0, 0) != 0) {
+ fprintf(stderr, "error running menu callback: %s\n", lua_tostring(L, -1));
+ exit(1);
+ }
+}
}
#endif
+ struct MenuEntry {
+ std::string text;
+ int lua_ref;
+ };
+ std::vector<MenuEntry> get_theme_menu() { return theme_menu; } // Can be empty for no menu.
+ void theme_menu_entry_clicked(int lua_ref);
+
+ // Will be invoked every time the theme sets a new menu.
+ // Is not invoked for a menu that exists at the time of the callback.
+ void set_theme_menu_callback(std::function<void()> callback)
+ {
+ theme_menu_callback = callback;
+ }
+
private:
void register_constants();
void register_class(const char *class_name, const luaL_Reg *funcs);
+ int set_theme_menu(lua_State *L);
std::mutex m;
lua_State *L; // Protected by <m>.
std::vector<std::pair<LiveInputWrapper *, CEFCapture *>> html_signal_connections;
#endif
+ std::vector<MenuEntry> theme_menu;
+ std::function<void()> theme_menu_callback;
+
friend class LiveInputWrapper;
+ friend int ThemeMenu_set(lua_State *L);
};
// LiveInputWrapper is a facade on top of an YCbCrInput, exposed to