diff --git a/src/sysprof/sysprof-application.c b/src/sysprof/sysprof-application.c index c3334d95..0f430836 100644 --- a/src/sysprof/sysprof-application.c +++ b/src/sysprof/sysprof-application.c @@ -24,6 +24,7 @@ #include "sysprof-application.h" #include "sysprof-credits.h" #include "sysprof-greeter.h" +#include "sysprof-recording-template.h" #include "sysprof-window.h" struct _SysprofApplication @@ -67,12 +68,15 @@ sysprof_application_open (GApplication *app, int n_files, const char *hint) { + g_autoptr(SysprofRecordingTemplate) template = NULL; g_assert (SYSPROF_IS_APPLICATION (app)); g_assert (files != NULL || n_files == 0); + template = sysprof_recording_template_new_from_file (NULL, NULL); + for (guint i = 0; i < n_files; i++) - sysprof_window_open (SYSPROF_APPLICATION (app), files[i]); + sysprof_window_open (SYSPROF_APPLICATION (app), template, files[i]); } static int @@ -147,7 +151,7 @@ sysprof_about (GSimpleAction *action, g_assert (variant == NULL); windows = gtk_application_get_windows (app); - + if (windows == NULL) { g_warning ("No windows found to show about dialog"); diff --git a/src/sysprof/sysprof-greeter.c b/src/sysprof/sysprof-greeter.c index 6dd975b1..caec226d 100644 --- a/src/sysprof/sysprof-greeter.c +++ b/src/sysprof/sysprof-greeter.c @@ -32,6 +32,7 @@ #include "sysprof-recording-pad.h" #include "sysprof-recording-template.h" #include "sysprof-stack-size.h" +#include "sysprof-util.h" #include "sysprof-window.h" G_DEFINE_AUTOPTR_CLEANUP_FUNC (SysprofCaptureWriter, sysprof_capture_writer_unref) @@ -63,12 +64,6 @@ struct _SysprofGreeter GtkLabel *user_stacks_caption; }; -static GFile * -get_state_file (void) -{ - return g_file_new_build_filename (g_get_user_data_dir (), APP_ID_S, "recording-template.json", NULL); -} - static GObject * sysprof_greeter_get_internal_child (GtkBuildable *buildable, GtkBuilder *builder, @@ -192,7 +187,7 @@ sysprof_greeter_record_cb (GObject *object, } else { - GtkWidget *pad = sysprof_recording_pad_new (recording); + GtkWidget *pad = sysprof_recording_pad_new (recording, self->recording_template); gtk_window_present (GTK_WINDOW (pad)); } @@ -221,7 +216,7 @@ sysprof_greeter_create_profiler (SysprofGreeter *self, if (!(profiler = sysprof_recording_template_apply (self->recording_template, error))) return NULL; - state_file = get_state_file (); + state_file = _get_default_state_file (); dir = g_file_get_parent (state_file); if (!g_file_query_exists (dir, NULL)) @@ -353,7 +348,9 @@ sysprof_greeter_select_file_action (GtkWidget *widget, const char *action_name, GVariant *param) { - sysprof_window_open_file (GTK_WINDOW (widget)); + SysprofGreeter *self = SYSPROF_GREETER (widget); + + sysprof_window_open_file (GTK_WINDOW (widget), self->recording_template); } static char * @@ -580,7 +577,7 @@ static void sysprof_greeter_init (SysprofGreeter *self) { g_autoptr(GListModel) power_profiles = sysprof_power_profiles_new (); - g_autoptr(GFile) state_file = get_state_file (); + g_autoptr(GFile) state_file = _get_default_state_file (); GtkListBoxRow *row; if (!(self->recording_template = sysprof_recording_template_new_from_file (state_file, NULL))) diff --git a/src/sysprof/sysprof-recording-pad.c b/src/sysprof/sysprof-recording-pad.c index f3b39c30..f9319f1c 100644 --- a/src/sysprof/sysprof-recording-pad.c +++ b/src/sysprof/sysprof-recording-pad.c @@ -29,18 +29,20 @@ struct _SysprofRecordingPad { - AdwWindow parent_instance; + AdwWindow parent_instance; - SysprofRecording *recording; + SysprofRecording *recording; + SysprofRecordingTemplate *template; - GtkButton *stop_button; + GtkButton *stop_button; - guint closed : 1; + guint closed : 1; }; enum { PROP_0, PROP_RECORDING, + PROP_TEMPLATE, N_PROPS }; @@ -124,7 +126,7 @@ sysprof_recording_pad_wait_cb (GObject *object, else if (-1 != (fd = sysprof_recording_dup_fd (self->recording))) { lseek (fd, 0, SEEK_SET); - sysprof_window_open_fd (SYSPROF_APPLICATION_DEFAULT, fd); + sysprof_window_open_fd (SYSPROF_APPLICATION_DEFAULT, self->template, fd); } if (!self->closed) @@ -154,6 +156,7 @@ sysprof_recording_pad_dispose (GObject *object) SysprofRecordingPad *self = (SysprofRecordingPad *)object; g_clear_object (&self->recording); + g_clear_object (&self->template); G_OBJECT_CLASS (sysprof_recording_pad_parent_class)->dispose (object); } @@ -172,6 +175,10 @@ sysprof_recording_pad_get_property (GObject *object, g_value_set_object (value, self->recording); break; + case PROP_TEMPLATE: + g_value_set_object (value, self->template); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } @@ -191,6 +198,10 @@ sysprof_recording_pad_set_property (GObject *object, self->recording = g_value_dup_object (value); break; + case PROP_TEMPLATE: + self->template = g_value_dup_object (value); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } @@ -215,6 +226,11 @@ sysprof_recording_pad_class_init (SysprofRecordingPadClass *klass) SYSPROF_TYPE_RECORDING, (G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); + properties [PROP_TEMPLATE] = + g_param_spec_object ("template", NULL, NULL, + SYSPROF_TYPE_RECORDING_TEMPLATE, + (G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); + g_object_class_install_properties (object_class, N_PROPS, properties); gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/sysprof/sysprof-recording-pad.ui"); @@ -232,12 +248,15 @@ sysprof_recording_pad_init (SysprofRecordingPad *self) } GtkWidget * -sysprof_recording_pad_new (SysprofRecording *recording) +sysprof_recording_pad_new (SysprofRecording *recording, + SysprofRecordingTemplate *template) { g_return_val_if_fail (SYSPROF_IS_RECORDING (recording), NULL); + g_return_val_if_fail (!template || SYSPROF_IS_RECORDING_TEMPLATE (template), NULL); return g_object_new (SYSPROF_TYPE_RECORDING_PAD, "application", SYSPROF_APPLICATION_DEFAULT, "recording", recording, + "template", template, NULL); } diff --git a/src/sysprof/sysprof-recording-pad.h b/src/sysprof/sysprof-recording-pad.h index e7080ed2..edeffe10 100644 --- a/src/sysprof/sysprof-recording-pad.h +++ b/src/sysprof/sysprof-recording-pad.h @@ -24,12 +24,15 @@ #include +#include "sysprof-recording-template.h" + G_BEGIN_DECLS #define SYSPROF_TYPE_RECORDING_PAD (sysprof_recording_pad_get_type()) G_DECLARE_FINAL_TYPE (SysprofRecordingPad, sysprof_recording_pad, SYSPROF, RECORDING_PAD, AdwWindow) -GtkWidget *sysprof_recording_pad_new (SysprofRecording *recording); +GtkWidget *sysprof_recording_pad_new (SysprofRecording *recording, + SysprofRecordingTemplate *template); G_END_DECLS diff --git a/src/sysprof/sysprof-recording-template.c b/src/sysprof/sysprof-recording-template.c index 9ecbad8d..204dc2f9 100644 --- a/src/sysprof/sysprof-recording-template.c +++ b/src/sysprof/sysprof-recording-template.c @@ -23,6 +23,7 @@ #include #include "sysprof-recording-template.h" +#include "sysprof-util.h" #define DEFAULT_STACK_SIZE (4096*4) @@ -687,10 +688,14 @@ sysprof_recording_template_new_from_file (GFile *file, GError **error) { g_autoptr(JsonParser) parser = NULL; + g_autoptr(GFile) state_file = NULL; SysprofRecordingTemplate *self; JsonNode *root; - g_return_val_if_fail (G_IS_FILE (file), NULL); + g_return_val_if_fail (!file || G_IS_FILE (file), NULL); + + if (file == NULL) + file = state_file = _get_default_state_file (); parser = json_parser_new (); @@ -743,3 +748,51 @@ sysprof_recording_template_save (SysprofRecordingTemplate *self, return json_generator_to_stream (generator, G_OUTPUT_STREAM (stream), NULL, error); } + +SysprofDocumentLoader * +sysprof_recording_template_create_loader (SysprofRecordingTemplate *self, + int fd, + GError **error) +{ + g_autoptr(SysprofDocumentLoader) loader = NULL; + g_autoptr(SysprofMultiSymbolizer) multi = NULL; + g_autoptr(SysprofElfSymbolizer) elf = NULL; + + g_return_val_if_fail (SYSPROF_IS_RECORDING_TEMPLATE (self), NULL); + + if (!(loader = sysprof_document_loader_new_for_fd (fd, error))) + return NULL; + + multi = sysprof_multi_symbolizer_new (); + + elf = SYSPROF_ELF_SYMBOLIZER (sysprof_elf_symbolizer_new ()); + /* TODO: add extra-debug-directories property and use that to + * call sysprof_elf_symbolizer_set_external_debug_dirs(elf,...) + */ + + /* Add in order of priority */ + sysprof_multi_symbolizer_take (multi, sysprof_bundled_symbolizer_new ()); + sysprof_multi_symbolizer_take (multi, sysprof_kallsyms_symbolizer_new ()); + sysprof_multi_symbolizer_take (multi, SYSPROF_SYMBOLIZER (g_steal_pointer (&elf))); + sysprof_multi_symbolizer_take (multi, sysprof_jitmap_symbolizer_new ()); + + sysprof_document_loader_set_symbolizer (loader, SYSPROF_SYMBOLIZER (multi)); + +#if HAVE_DEBUGINFOD +#if 0 + /* TODO: add enable-debuginfod property. */ + if (self->enable_debuginfod) +#endif + { + g_autoptr(SysprofSymbolizer) debuginfod = NULL; + g_autoptr(GError) debuginfod_error = NULL; + + if (!(debuginfod = sysprof_debuginfod_symbolizer_new (&debuginfod_error))) + g_warning ("Failed to create debuginfod symbolizer: %s", debuginfod_error->message); + else + sysprof_multi_symbolizer_take (multi, g_steal_pointer (&debuginfod)); + } +#endif + + return g_steal_pointer (&loader); +} diff --git a/src/sysprof/sysprof-recording-template.h b/src/sysprof/sysprof-recording-template.h index f03bc639..dbaf96c1 100644 --- a/src/sysprof/sysprof-recording-template.h +++ b/src/sysprof/sysprof-recording-template.h @@ -43,5 +43,8 @@ SysprofRecordingTemplate *sysprof_recording_template_new_from_file (GFile gboolean sysprof_recording_template_save (SysprofRecordingTemplate *self, GFile *file, GError **error); +SysprofDocumentLoader *sysprof_recording_template_create_loader (SysprofRecordingTemplate *self, + int fd, + GError **error); G_END_DECLS diff --git a/src/sysprof/sysprof-util.c b/src/sysprof/sysprof-util.c index bb4c8b1c..070a6b55 100644 --- a/src/sysprof/sysprof-util.c +++ b/src/sysprof/sysprof-util.c @@ -66,3 +66,9 @@ _gtk_widget_hide_with_fade (GtkWidget *widget) g_memdup2 (&begin_time, sizeof begin_time), g_free); } + +GFile * +_get_default_state_file (void) +{ + return g_file_new_build_filename (g_get_user_data_dir (), APP_ID_S, "recording-template.json", NULL); +} diff --git a/src/sysprof/sysprof-util.h b/src/sysprof/sysprof-util.h index 53aa5cb4..6d577090 100644 --- a/src/sysprof/sysprof-util.h +++ b/src/sysprof/sysprof-util.h @@ -24,6 +24,7 @@ G_BEGIN_DECLS -void _gtk_widget_hide_with_fade (GtkWidget *widget); +void _gtk_widget_hide_with_fade (GtkWidget *widget); +GFile *_get_default_state_file (void); G_END_DECLS diff --git a/src/sysprof/sysprof-window.c b/src/sysprof/sysprof-window.c index 5fd6e9a1..e81e264b 100644 --- a/src/sysprof/sysprof-window.c +++ b/src/sysprof/sysprof-window.c @@ -20,7 +20,11 @@ #include "config.h" +#include +#include + #include +#include #include "sysprof-counters-section.h" #include "sysprof-cpu-section.h" @@ -34,6 +38,7 @@ #include "sysprof-memory-section.h" #include "sysprof-metadata-section.h" #include "sysprof-network-section.h" +#include "sysprof-pair.h" #include "sysprof-processes-section.h" #include "sysprof-samples-section.h" #include "sysprof-sidebar.h" @@ -133,7 +138,9 @@ sysprof_window_open_file_cb (GObject *object, gpointer user_data) { GtkFileDialog *dialog = (GtkFileDialog *)object; - g_autoptr(GtkWindow) transient_for = user_data; + g_autoptr(SysprofRecordingTemplate) template = NULL; + g_autoptr(GtkWindow) transient_for = NULL; + g_autoptr(SysprofPair) pair = user_data; g_autoptr(GError) error = NULL; g_autoptr(GFile) file = NULL; @@ -141,11 +148,19 @@ sysprof_window_open_file_cb (GObject *object, g_assert (G_IS_ASYNC_RESULT (result)); g_assert (!transient_for || GTK_IS_WINDOW (transient_for)); + g_object_get (pair, + "first", &transient_for, + "second", &template, + NULL); + + g_assert (!transient_for || GTK_IS_WIDGET (transient_for)); + g_assert (!template || SYSPROF_IS_RECORDING_TEMPLATE (template)); + if ((file = gtk_file_dialog_open_finish (dialog, result, &error))) { if (g_file_is_native (file)) { - sysprof_window_open (SYSPROF_APPLICATION_DEFAULT, file); + sysprof_window_open (SYSPROF_APPLICATION_DEFAULT, template, file); if (transient_for && !SYSPROF_IS_WINDOW (transient_for)) gtk_window_destroy (transient_for); @@ -168,7 +183,8 @@ sysprof_window_open_file_cb (GObject *object, } void -sysprof_window_open_file (GtkWindow *parent) +sysprof_window_open_file (GtkWindow *parent, + SysprofRecordingTemplate *template) { g_autoptr(GtkFileDialog) dialog = NULL; g_autoptr(GtkFileFilter) filter = NULL; @@ -192,7 +208,10 @@ sysprof_window_open_file (GtkWindow *parent) parent, NULL, sysprof_window_open_file_cb, - parent ? g_object_ref (parent) : NULL); + g_object_new (SYSPROF_TYPE_PAIR, + "first", parent, + "second", template, + NULL)); } static void @@ -200,7 +219,12 @@ sysprof_window_open_capture_action (GtkWidget *widget, const char *action_name, GVariant *param) { - sysprof_window_open_file (GTK_WINDOW (widget)); + g_autoptr(SysprofRecordingTemplate) template = NULL; + + /* Open for default state file so we can apply settings */ + template = sysprof_recording_template_new_from_file (NULL, NULL); + + sysprof_window_open_file (GTK_WINDOW (widget), template); } static void @@ -780,25 +804,47 @@ sysprof_window_create (SysprofApplication *app, } void -sysprof_window_open (SysprofApplication *app, - GFile *file) +sysprof_window_open (SysprofApplication *app, + SysprofRecordingTemplate *template, + GFile *file) { g_autoptr(SysprofDocumentLoader) loader = NULL; + g_autoptr(SysprofRecordingTemplate) alt_template = NULL; + g_autoptr(GError) error = NULL; + g_autofd int fd = -1; SysprofWindow *self; + const char *path; g_return_if_fail (SYSPROF_IS_APPLICATION (app)); + g_return_if_fail (!template || SYSPROF_IS_RECORDING_TEMPLATE (template)); g_return_if_fail (G_IS_FILE (file)); - if (!g_file_is_native (file) || - !(loader = sysprof_document_loader_new (g_file_peek_path (file)))) + if (template == NULL) + template = alt_template = sysprof_recording_template_new (); + + if (!g_file_is_native (file)) { g_autofree char *uri = g_file_get_uri (file); g_warning ("Cannot open non-native file \"%s\"", uri); return; } + path = g_file_peek_path (file); + + if (-1 == (fd = open (path, O_RDONLY))) + { + int errsv = errno; + g_critical ("Failed to open %s: %s", path, g_strerror (errsv)); + return; + } + + if (!(loader = sysprof_recording_template_create_loader (template, fd, &error))) + { + g_critical ("Failed to create loader: %s", error->message); + return; + } + g_application_hold (G_APPLICATION (app)); - sysprof_window_apply_loader_settings (loader); self = sysprof_window_create (app, loader); sysprof_document_loader_load_async (loader, NULL, @@ -808,18 +854,25 @@ sysprof_window_open (SysprofApplication *app, } void -sysprof_window_open_fd (SysprofApplication *app, - int fd) +sysprof_window_open_fd (SysprofApplication *app, + SysprofRecordingTemplate *template, + int fd) { + g_autoptr(SysprofRecordingTemplate) alt_template = NULL; g_autoptr(SysprofDocumentLoader) loader = NULL; g_autoptr(GError) error = NULL; SysprofWindow *self; g_return_if_fail (SYSPROF_IS_APPLICATION (app)); + g_return_if_fail (!template || SYSPROF_IS_RECORDING_TEMPLATE (template)); + g_return_if_fail (fd > -1); - if (!(loader = sysprof_document_loader_new_for_fd (fd, &error))) + if (template == NULL) + template = alt_template = sysprof_recording_template_new (); + + if (!(loader = sysprof_recording_template_create_loader (template, fd, &error))) { - g_critical ("Failed to dup FD: %s", error->message); + g_critical ("Failed to create loader: %s", error->message); return; } diff --git a/src/sysprof/sysprof-window.h b/src/sysprof/sysprof-window.h index 4da9a635..fa44b0ec 100644 --- a/src/sysprof/sysprof-window.h +++ b/src/sysprof/sysprof-window.h @@ -25,6 +25,7 @@ #include #include "sysprof-application.h" +#include "sysprof-recording-template.h" #include "sysprof-session.h" G_BEGIN_DECLS @@ -33,14 +34,17 @@ G_BEGIN_DECLS G_DECLARE_FINAL_TYPE (SysprofWindow, sysprof_window, SYSPROF, WINDOW, AdwApplicationWindow) -GtkWidget *sysprof_window_new (SysprofApplication *app, - SysprofDocument *document); -void sysprof_window_open_file (GtkWindow *transient_for); -void sysprof_window_open (SysprofApplication *app, - GFile *file); -void sysprof_window_open_fd (SysprofApplication *app, - int fd); -SysprofDocument *sysprof_window_get_document (SysprofWindow *self); -SysprofSession *sysprof_window_get_session (SysprofWindow *self); +GtkWidget *sysprof_window_new (SysprofApplication *app, + SysprofDocument *document); +void sysprof_window_open_file (GtkWindow *transient_for, + SysprofRecordingTemplate *template); +void sysprof_window_open (SysprofApplication *app, + SysprofRecordingTemplate *template, + GFile *file); +void sysprof_window_open_fd (SysprofApplication *app, + SysprofRecordingTemplate *template, + int fd); +SysprofDocument *sysprof_window_get_document (SysprofWindow *self); +SysprofSession *sysprof_window_get_session (SysprofWindow *self); G_END_DECLS