diff --git a/docs/build.rst b/docs/build.rst index bdc5f1152..673aca87e 100644 --- a/docs/build.rst +++ b/docs/build.rst @@ -29,7 +29,7 @@ Build-time dependencies: * gcc or clang * pkg-config * For building on Linux in addition to the above dependencies you might also need to install the ``-dev`` packages for: - ``libdbus-1-dev``, ``libxcursor-dev``, ``libxrandr-dev``, ``libxi-dev``, ``libxinerama-dev``, ``libgl1-mesa-dev``, ``libxkbcommon-x11-dev``, ``libfontconfig-dev``, ``libcanberra-dev`` and ``libpython-dev``. + ``libdbus-1-dev``, ``libxcursor-dev``, ``libxrandr-dev``, ``libxi-dev``, ``libxinerama-dev``, ``libgl1-mesa-dev``, ``libxkbcommon-x11-dev``, ``libfontconfig-dev``, and ``libpython-dev``, if they are not already installed by your distro. Install and run from source diff --git a/kitty/desktop.c b/kitty/desktop.c index 3348aab4c..5084ad279 100644 --- a/kitty/desktop.c +++ b/kitty/desktop.c @@ -7,7 +7,6 @@ #include "data-types.h" #include -#include #define FUNC(name, restype, ...) typedef restype (*name##_func)(__VA_ARGS__); static name##_func name = NULL #define LOAD_FUNC(handle, name) {\ @@ -90,15 +89,56 @@ static PyMethodDef module_methods[] = { {NULL, NULL, 0, NULL} /* Sentinel */ }; -static ca_context *canberra_ctx = NULL; +static void* libcanberra_handle = NULL; +static void *canberra_ctx = NULL; +FUNC(ca_context_create, int, void**); +FUNC(ca_context_destroy, int, void*); +typedef int (*ca_context_play_func)(void*, uint32_t, ...); static ca_context_play_func ca_context_play = NULL; + +static PyObject* +load_libcanberra_functions(void) { + LOAD_FUNC(libcanberra_handle, ca_context_create); + LOAD_FUNC(libcanberra_handle, ca_context_play); + LOAD_FUNC(libcanberra_handle, ca_context_destroy); + return NULL; +} + +static void +load_libcanberra(void) { + static const char* libname = "libcanberra.so"; + // some installs are missing the .so symlink, so try the full name + static const char* libname2 = "libcanberra.so.0"; + static const char* libname3 = "libcanberra.so.0.2.5"; + static bool done = false; + if (done) return; + done = true; + libcanberra_handle = dlopen(libname, RTLD_LAZY); + if (libcanberra_handle == NULL) libsn_handle = dlopen(libname2, RTLD_LAZY); + if (libcanberra_handle == NULL) libsn_handle = dlopen(libname3, RTLD_LAZY); + if (libcanberra_handle == NULL) { + fprintf(stderr, "Failed to load %s, cannot play beep sound, with error: %s\n", libname, dlerror()); + return; + } + load_libcanberra_functions(); + if (PyErr_Occurred()) { + PyErr_Print(); + dlclose(libcanberra_handle); libcanberra_handle = NULL; + } + if (ca_context_create(&canberra_ctx) != 0) { + fprintf(stderr, "Failed to create libcanberra context, cannot play beep sound\n"); + ca_context_destroy(canberra_ctx); canberra_ctx = NULL; + dlclose(libcanberra_handle); libcanberra_handle = NULL; + } +} void play_canberra_sound(const char *which_sound, const char *event_id) { - if (canberra_ctx == NULL) ca_context_create(&canberra_ctx); + load_libcanberra(); + if (libcanberra_handle == NULL || canberra_ctx == NULL) return; ca_context_play( canberra_ctx, 0, - CA_PROP_EVENT_ID, which_sound, - CA_PROP_EVENT_DESCRIPTION, event_id, + "event.id", which_sound, + "event.description", event_id, NULL ); } @@ -109,6 +149,7 @@ finalize(void) { libsn_handle = NULL; if (canberra_ctx) ca_context_destroy(canberra_ctx); canberra_ctx = NULL; + if (libcanberra_handle) dlclose(libcanberra_handle); } bool diff --git a/setup.py b/setup.py index 29020a557..257727cb5 100755 --- a/setup.py +++ b/setup.py @@ -270,9 +270,6 @@ def kitty_env(): gl_libs = ['-framework', 'OpenGL'] if is_macos else pkg_config('gl', '--libs') libpng = pkg_config('libpng', '--libs') ans.ldpaths += pylib + font_libs + gl_libs + libpng - if not is_macos: - cflags.extend(pkg_config('libcanberra', '--cflags-only-I')) - ans.ldpaths += pkg_config('libcanberra', '--libs') if is_macos: ans.ldpaths.extend('-framework Cocoa'.split()) else: