summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cscript4
-rw-r--r--src/lib/config.cc4
-rw-r--r--src/lib/config.h10
-rw-r--r--src/lib/dcpomatic_sentry.cc58
-rw-r--r--src/lib/dcpomatic_sentry.h26
-rw-r--r--src/lib/wscript4
-rw-r--r--src/tools/dcpomatic.cc19
-rw-r--r--src/wx/full_config_dialog.cc3
-rw-r--r--src/wx/general_preferences_page.cc21
-rw-r--r--src/wx/general_preferences_page.h9
-rw-r--r--wscript7
11 files changed, 165 insertions, 0 deletions
diff --git a/cscript b/cscript
index 757663691..03fe71b87 100644
--- a/cscript
+++ b/cscript
@@ -583,6 +583,10 @@ def configure_options(target, options, for_package=False):
):
opt += ' --enable-grok'
+
+ if target.platform == 'windows':
+ opt += ' --enable-sentry'
+
if build_with_cpp17(target):
opt += ' --c++17'
diff --git a/src/lib/config.cc b/src/lib/config.cc
index 267831341..e07be6b3d 100644
--- a/src/lib/config.cc
+++ b/src/lib/config.cc
@@ -222,6 +222,7 @@ Config::set_defaults()
_player_http_server_port = 8080;
_relative_paths = false;
_layout_for_short_screen = false;
+ _enable_crash_reporting = false;
_allowed_dcp_frame_rates.clear();
_allowed_dcp_frame_rates.push_back(24);
@@ -668,6 +669,7 @@ try
_player_http_server_port = f.optional_number_child<int>("PlayerHTTPServerPort").get_value_or(8080);
_relative_paths = f.optional_bool_child("RelativePaths").get_value_or(false);
_layout_for_short_screen = f.optional_bool_child("LayoutForShortScreen").get_value_or(false);
+ _enable_crash_reporting = f.optional_bool_child("EnableCrashReporting").get_value_or(false);
#ifdef DCPOMATIC_GROK
if (auto grok = f.optional_node_child("Grok")) {
@@ -1157,6 +1159,8 @@ Config::write_config() const
cxml::add_text_child(root, "RelativePaths", _relative_paths ? "1" : "0");
/* [XML] LayoutForShortScreen 1 to set up DCP-o-matic as if the screen were less than 800 pixels high */
cxml::add_text_child(root, "LayoutForShortScreen", _layout_for_short_screen ? "1" : "0");
+ /* [XML] EnableCrashReporting 1 to make DCP-o-matic automatically upload crash reports for analysis */
+ cxml::add_text_child(root, "EnableCrashReporting", _enable_crash_reporting ? "1" : "0");
#ifdef DCPOMATIC_GROK
_grok.as_xml(cxml::add_child(root, "Grok"));
diff --git a/src/lib/config.h b/src/lib/config.h
index 582e90cf9..afa22ab68 100644
--- a/src/lib/config.h
+++ b/src/lib/config.h
@@ -122,6 +122,7 @@ public:
GROK,
#endif
CINEMAS_FILE,
+ ENABLE_CRASH_REPORTING,
OTHER
};
@@ -689,6 +690,10 @@ public:
return _layout_for_short_screen;
}
+ bool enable_crash_reporting() {
+ return _enable_crash_reporting;
+ }
+
/* SET (mostly) */
void set_master_encoding_threads(int n) {
@@ -1265,6 +1270,10 @@ public:
maybe_set(_layout_for_short_screen, layout);
}
+ void set_enable_crash_reporting(bool error) {
+ maybe_set(_enable_crash_reporting, error, ENABLE_CRASH_REPORTING);
+ }
+
void changed(Property p = OTHER);
boost::signals2::signal<void (Property)> Changed;
@@ -1512,6 +1521,7 @@ private:
int _player_http_server_port;
bool _relative_paths;
bool _layout_for_short_screen;
+ bool _enable_crash_reporting;
#ifdef DCPOMATIC_GROK
Grok _grok;
diff --git a/src/lib/dcpomatic_sentry.cc b/src/lib/dcpomatic_sentry.cc
new file mode 100644
index 000000000..e2f3ce9d5
--- /dev/null
+++ b/src/lib/dcpomatic_sentry.cc
@@ -0,0 +1,58 @@
+/*
+ Copyright (C) 2025 Carl Hetherington <cth@carlh.net>
+
+ This file is part of DCP-o-matic.
+
+ DCP-o-matic is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ DCP-o-matic is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with DCP-o-matic. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+
+#include "config.h"
+#include "dcpomatic_sentry.h"
+#include "version.h"
+#include <sentry.h>
+#include <fmt/format.h>
+
+
+void
+maybe_setup_sentry()
+{
+ if (!Config::instance()->enable_crash_reporting()) {
+ return;
+ }
+
+ auto *options = sentry_options_new();
+ sentry_options_set_dsn(options, "https://aa14795ff538105836cfc663e1079fb1@o4510456286347264.ingest.de.sentry.io/4510456326651984");
+ // This is also the default-path. For further information and recommendations:
+ // https://docs.sentry.io/platforms/native/configuration/options/#database-path
+ sentry_options_set_database_path(options, State::write_path("sentry-database").string().c_str());
+ sentry_options_set_release(options, fmt::format("dcpomatic@{}", dcpomatic_version).c_str());
+#ifdef DCPOMATIC_DEBUG
+ sentry_options_set_debug(options, 1);
+#else
+ sentry_options_set_debug(options, 0);
+#endif
+ sentry_init(options);
+
+ sentry_close();
+}
+
+
+void
+closedown_sentry()
+{
+ sentry_close();
+}
+
diff --git a/src/lib/dcpomatic_sentry.h b/src/lib/dcpomatic_sentry.h
new file mode 100644
index 000000000..d7c07543d
--- /dev/null
+++ b/src/lib/dcpomatic_sentry.h
@@ -0,0 +1,26 @@
+/*
+ Copyright (C) 2025 Carl Hetherington <cth@carlh.net>
+
+ This file is part of DCP-o-matic.
+
+ DCP-o-matic is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ DCP-o-matic is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with DCP-o-matic. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+
+#include <boost/filesystem.hpp>
+
+
+void maybe_setup_sentry();
+void closedown_sentry();
diff --git a/src/lib/wscript b/src/lib/wscript
index a6a6d96fc..2c0136ed1 100644
--- a/src/lib/wscript
+++ b/src/lib/wscript
@@ -272,6 +272,10 @@ def build(bld):
if bld.env.ENABLE_GROK:
obj.source += ' grok_j2k_encoder_thread.cc grok/util.cc'
+
+ if bld.env.ENABLE_SENTRY:
+ obj.source += ' dcpomatic_sentry.cc'
+ obj.uselib += ' SENTRY'
if bld.env.TARGET_WINDOWS_64 or bld.env.TARGET_WINDOWS_32:
obj.uselib += ' WINSOCK2 DBGHELP SHLWAPI MSWSOCK BOOST_LOCALE SETUPAPI OLE32 UUID'
diff --git a/src/tools/dcpomatic.cc b/src/tools/dcpomatic.cc
index 01543b190..b8975834c 100644
--- a/src/tools/dcpomatic.cc
+++ b/src/tools/dcpomatic.cc
@@ -76,6 +76,9 @@
#include "lib/email.h"
#include "lib/encode_server_finder.h"
#include "lib/exceptions.h"
+#ifdef DCPOMATIC_SENTRY
+#include "lib/dcpomatic_sentry.h"
+#endif
#include "lib/ffmpeg_film_encoder.h"
#include "lib/film.h"
#include "lib/font_config.h"
@@ -1214,6 +1217,10 @@ private:
ev.Skip ();
JobManager::drop ();
+
+#ifdef DCPOMATIC_SENTRY
+ closedown_sentry();
+#endif
}
void active_jobs_changed()
@@ -1502,6 +1509,14 @@ private:
if (what == Config::GROK) {
setup_grok_library_path();
}
+#elif DCPOMATIC_SENTRY
+ if (what == Config::ENABLE_CRASH_REPORTING) {
+ if (Config::instance()->enable_crash_reporting()) {
+ maybe_setup_sentry();
+ } else {
+ closedown_sentry();
+ }
+ }
#else
LIBDCP_UNUSED(what);
#endif
@@ -1703,6 +1718,10 @@ private:
*/
Config::Bad.connect (boost::bind(&App::config_bad, this, _1));
+#ifdef DCPOMATIC_SENTRY
+ maybe_setup_sentry();
+#endif
+
signal_manager = new wxSignalManager (this);
_frame = new DOMFrame(variant::wx::dcpomatic());
diff --git a/src/wx/full_config_dialog.cc b/src/wx/full_config_dialog.cc
index eff3fdee2..3ebd8092d 100644
--- a/src/wx/full_config_dialog.cc
+++ b/src/wx/full_config_dialog.cc
@@ -144,6 +144,9 @@ private:
++r;
add_update_controls(table, r);
+#ifdef DCPOMATIC_SENTRY
+ add_crash_reporting_controls(table, r);
+#endif
_default_add_file_location->add_entry(_("Same place as last time"));
_default_add_file_location->add_entry(_("Same place as project"));
diff --git a/src/wx/general_preferences_page.cc b/src/wx/general_preferences_page.cc
index beed9012f..2404289e2 100644
--- a/src/wx/general_preferences_page.cc
+++ b/src/wx/general_preferences_page.cc
@@ -205,6 +205,27 @@ GeneralPage::add_update_controls(wxGridBagSizer* table, int& r)
_check_for_test_updates->bind(&GeneralPage::check_for_test_updates_changed, this);
}
+
+#ifdef DCPOMATIC_SENTRY
+void
+GeneralPage::add_crash_reporting_controls(wxGridBagSizer* table, int& r)
+{
+ _enable_crash_reporting = new CheckBox(_panel, _("Automatically upload crash reports"));
+ table->Add(_enable_crash_reporting, wxGBPosition(r, 0), wxGBSpan(1, 2));
+ ++r;
+
+ _enable_crash_reporting->bind(&GeneralPage::enable_crash_reporting_changed, this);
+}
+
+
+void
+GeneralPage::enable_crash_reporting_changed()
+{
+ Config::instance()->set_enable_crash_reporting(_enable_crash_reporting->get());
+}
+#endif
+
+
void
GeneralPage::config_changed()
{
diff --git a/src/wx/general_preferences_page.h b/src/wx/general_preferences_page.h
index d871c2506..ed63f356b 100644
--- a/src/wx/general_preferences_page.h
+++ b/src/wx/general_preferences_page.h
@@ -48,6 +48,9 @@ protected:
void add_language_controls(wxGridBagSizer* table, int& r);
void add_config_file_controls(wxGridBagSizer* table, int& r);
void add_update_controls(wxGridBagSizer* table, int& r);
+#ifdef DCPOMATIC_SENTRY
+ void add_crash_reporting_controls(wxGridBagSizer* table, int& r);
+#endif
void config_changed() override;
private:
@@ -59,6 +62,9 @@ private:
void export_cinemas_file();
void check_for_updates_changed();
void check_for_test_updates_changed();
+#ifdef DCPOMATIC_SENTRY
+ void enable_crash_reporting_changed();
+#endif
CheckBox* _set_language = nullptr;
wxChoice* _language = nullptr;
@@ -66,6 +72,9 @@ private:
FilePickerCtrl* _cinemas_file = nullptr;
CheckBox* _check_for_updates = nullptr;
CheckBox* _check_for_test_updates = nullptr;
+#ifdef DCPOMATIC_SENTRY
+ CheckBox* _enable_crash_reporting = nullptr;
+#endif
};
diff --git a/wscript b/wscript
index bcfe22b44..74ac828b6 100644
--- a/wscript
+++ b/wscript
@@ -81,6 +81,7 @@ def options(opt):
opt.add_option('--disable-more-warnings', action='store_true', default=False, help='disable some warnings raised by Xcode 15 with the 2.16 branch')
opt.add_option('--c++17', action='store_true', default=False, help='build with C++17 and libxml++-4.0')
opt.add_option('--variant', help="build with variant")
+ opt.add_option('--enable-sentry', action='store_true', default=False, help='build with Sentry to report errors')
def configure(conf):
conf.load('compiler_cxx')
@@ -113,6 +114,7 @@ def configure(conf):
conf.env.STATIC_DCPOMATIC = conf.options.static_dcpomatic
conf.env.ENABLE_DISK = conf.options.enable_disk
conf.env.ENABLE_GROK = conf.options.enable_grok
+ conf.env.ENABLE_SENTRY = conf.options.enable_sentry
if conf.options.destdir == '':
conf.env.INSTALL_PREFIX = conf.options.prefix
else:
@@ -186,6 +188,9 @@ def configure(conf):
if conf.options.enable_grok:
conf.env.append_value('CXXFLAGS', '-DDCPOMATIC_GROK')
+ if conf.options.enable_sentry:
+ conf.env.append_value('CXXFLAGS', '-DDCPOMATIC_SENTRY')
+
if conf.options.use_lld:
try:
conf.find_program('ld.lld')
@@ -703,6 +708,8 @@ def configure(conf):
conf.find_program('msgfmt', var='MSGFMT')
conf.check(header_name='valgrind/memcheck.h', mandatory=False)
+ if conf.env.ENABLE_SENTRY:
+ conf.check(header_name='sentry.h', uselib_store='SENTRY', lib=['sentry'], mandatory=True)
datadir = conf.env.DATADIR
if not datadir: