added loading screen
This commit is contained in:
1 parent
881b52748e
commit
50a1ddca62
10 files changed
+249
-1
No files matched your search
@@ -793,6 +793,86 @@ void apply_stored_settings(Config& cfg) {
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
/// The loading window and its builder. File scope because its life spans two calls made from two
|
||||
/// translation units -- `main()` raises it, `run_ui()` takes it down once the real window is up --
|
||||
/// and there is exactly one of it: the gap it covers happens once per run.
|
||||
GtkWidget* g_loading_window = nullptr;
|
||||
GtkBuilder* g_loading_ui = nullptr;
|
||||
|
||||
/// Runs the default main context for `ms`, the chooser's nested-loop idiom again. Pumping pending
|
||||
/// events with `g_main_context_iteration()` is not enough: a window needs a frame-clock cycle to be
|
||||
/// mapped and drawn, and the frame clock only ticks while a loop runs.
|
||||
void pump_main_context(unsigned ms) {
|
||||
GMainLoop* loop = g_main_loop_new(nullptr, FALSE);
|
||||
g_timeout_add(
|
||||
ms,
|
||||
+[](gpointer user) {
|
||||
g_main_loop_quit(static_cast<GMainLoop*>(user));
|
||||
return G_SOURCE_REMOVE;
|
||||
},
|
||||
loop);
|
||||
g_main_loop_run(loop);
|
||||
g_main_loop_unref(loop);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void loading_show(const Config& cfg) {
|
||||
if (g_loading_window != nullptr) return;
|
||||
g_loading_ui = gtk_builder_new_from_resource("/org/udpscope/ui/loading.ui");
|
||||
g_loading_window = GTK_WIDGET(gtk_builder_get_object(g_loading_ui, "loading_window"));
|
||||
GtkWidget* title = GTK_WIDGET(gtk_builder_get_object(g_loading_ui, "loading_title"));
|
||||
GtkWidget* detail = GTK_WIDGET(gtk_builder_get_object(g_loading_ui, "loading_detail"));
|
||||
if (g_loading_window == nullptr || title == nullptr || detail == nullptr) {
|
||||
std::fprintf(stderr, "[sources] loading ui: loading.ui is missing an id this code reads\n");
|
||||
std::fflush(stderr);
|
||||
g_loading_window = nullptr;
|
||||
g_clear_object(&g_loading_ui);
|
||||
return;
|
||||
}
|
||||
|
||||
// The wording names the *wait*, not the destination: "connecting" with nothing else said is what
|
||||
// this window was accused of being, and the buffer size is the number that explains the ten
|
||||
// seconds.
|
||||
std::string head;
|
||||
std::string sub;
|
||||
if (cfg.open_waveform.empty()) {
|
||||
head = "Connecting to " + cfg.server + ":" + std::to_string(cfg.port);
|
||||
if (!cfg.multicast.empty()) head += " (" + cfg.multicast + ")";
|
||||
char buf[128];
|
||||
std::snprintf(buf, sizeof(buf), "planning the %.0f MB sample buffer", cfg.buffer_mb);
|
||||
sub = buf;
|
||||
} else {
|
||||
const std::size_t slash = cfg.open_waveform.rfind('/');
|
||||
head = "Opening " + (slash == std::string::npos ? cfg.open_waveform
|
||||
: cfg.open_waveform.substr(slash + 1));
|
||||
sub = "reading the recording";
|
||||
}
|
||||
gtk_label_set_text(GTK_LABEL(title), head.c_str());
|
||||
gtk_label_set_text(GTK_LABEL(detail), sub.c_str());
|
||||
gtk_window_present(GTK_WINDOW(g_loading_window));
|
||||
// Painted *here*, before the caller blocks. Everything this window covers -- the buffer
|
||||
// allocation, the first CONFIG, a recording read -- runs on a thread that never returns to a main
|
||||
// loop, so a window presented and not yet drawn would be an empty rectangle for the whole wait,
|
||||
// which is the defect this is meant to fix rather than restate.
|
||||
pump_main_context(180);
|
||||
std::fprintf(stderr, "[sources] loading: title='%s' detail='%s'\n", head.c_str(), sub.c_str());
|
||||
std::fflush(stderr);
|
||||
}
|
||||
|
||||
void loading_hide() {
|
||||
if (g_loading_window == nullptr) return;
|
||||
GtkWidget* w = g_loading_window;
|
||||
g_loading_window = nullptr; // before the destroy, as the chooser's own close does
|
||||
gtk_window_destroy(GTK_WINDOW(w));
|
||||
// The window belonged to the builder's object list, so the builder goes after the destroy.
|
||||
g_clear_object(&g_loading_ui);
|
||||
std::fprintf(stderr, "[sources] loading: closed\n");
|
||||
std::fflush(stderr);
|
||||
}
|
||||
|
||||
bool choose_source(Config& cfg) {
|
||||
const std::vector<KnownSource> known = known_sources();
|
||||
|
||||
|
||||
Reference in new issue
Block a user