A new option to specify the path to a sound file to use as the bell sound

This commit is contained in:
Kovid Goyal 2021-09-24 07:55:38 +05:30
parent bbdfdb978d
commit c2641458e7
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
10 changed files with 65 additions and 15 deletions

View File

@ -22,6 +22,9 @@ To update |kitty|, :doc:`follow the instructions <binary>`.
the request by default instead of denying by default. See
:opt:`clipboard_control` for details (:iss:`4022`)
- A new option :opt:`bell_path` to specify the path to a sound file
to use as the bell sound
- Fix a regression that caused :option:`kitty --title` to not work when
opening new OS windows using :option:`kitty --single-instance` (:iss:`3893`)

View File

@ -633,12 +633,16 @@ cocoa_set_titlebar_color(void *w, color_type titlebar_color)
} // autoreleasepool
}
static NSSound *beep_sound = nil;
static void
cleanup() {
@autoreleasepool {
if (dockMenu) [dockMenu release];
dockMenu = nil;
if (beep_sound) [beep_sound release];
beep_sound = nil;
#ifndef KITTY_USE_DEPRECATED_MACOS_NOTIFICATION_API
drain_pending_notifications(NO);
@ -662,8 +666,15 @@ cocoa_hide_window_title(void *w)
}
void
cocoa_system_beep(void) {
NSBeep();
cocoa_system_beep(const char *path) {
if (!path) { NSBeep(); return; }
static const char *beep_path = NULL;
if (beep_path != path) {
if (beep_sound) [beep_sound release];
beep_sound = [[NSSound alloc] initWithContentsOfFile:@(path) byReference:YES];
}
if (beep_sound) [beep_sound play];
else NSBeep();
}
static PyMethodDef module_methods[] = {

View File

@ -19,7 +19,7 @@ extern void cocoa_focus_window(void *w);
extern long cocoa_window_number(void *w);
extern void cocoa_create_global_menu(void);
extern void cocoa_hide_window_title(void *w);
extern void cocoa_system_beep(void);
extern void cocoa_system_beep(const char*);
extern void cocoa_set_activation_policy(bool);
extern void cocoa_set_titlebar_color(void *w, color_type color);
extern bool cocoa_alt_option_key_pressed(unsigned long);
@ -1115,9 +1115,10 @@ ring_audio_bell(void) {
if (last_bell_at >= 0 && now - last_bell_at <= ms_to_monotonic_t(100ll)) return;
last_bell_at = now;
#ifdef __APPLE__
cocoa_system_beep();
cocoa_system_beep(OPT(bell_path));
#else
play_canberra_sound("bell", "kitty bell", false);
if (OPT(bell_path)) play_canberra_sound(OPT(bell_path), "kitty bell", true);
else play_canberra_sound("bell", "kitty bell", false);
#endif
}

View File

@ -681,6 +681,13 @@ opt('command_on_bell', 'none',
' The environment variable :envvar:`KITTY_CHILD_CMDLINE` can be used to get the program running in'
' the window in which the bell occurred.'
)
opt('bell_path', 'none',
option_type='config_or_absolute_path', ctype='!bell_path',
long_text='Path to a sound file to play as the bell sound. Must be in a format supported by the'
' operating systems sound API, such as WAV or OGA on Linux (libcanberra) or AIFF, MP3 or WAV on macOS (NSSound)'
)
egr() # }}}
# window {{{

View File

@ -81,6 +81,9 @@ class Parser:
def bell_on_tab(self, val: str, ans: typing.Dict[str, typing.Any]) -> None:
ans['bell_on_tab'] = to_bool(val)
def bell_path(self, val: str, ans: typing.Dict[str, typing.Any]) -> None:
ans['bell_path'] = config_or_absolute_path(val)
def bold_font(self, val: str, ans: typing.Dict[str, typing.Any]) -> None:
ans['bold_font'] = str(val)

View File

@ -434,6 +434,19 @@ convert_from_opts_window_alert_on_bell(PyObject *py_opts, Options *opts) {
Py_DECREF(ret);
}
static void
convert_from_python_bell_path(PyObject *val, Options *opts) {
bell_path(val, opts);
}
static void
convert_from_opts_bell_path(PyObject *py_opts, Options *opts) {
PyObject *ret = PyObject_GetAttrString(py_opts, "bell_path");
if (ret == NULL) return;
convert_from_python_bell_path(ret, opts);
Py_DECREF(ret);
}
static void
convert_from_python_active_border_color(PyObject *val, Options *opts) {
opts->active_border_color = active_border_color(val);
@ -983,6 +996,8 @@ convert_opts_from_python_opts(PyObject *py_opts, Options *opts) {
if (PyErr_Occurred()) return false;
convert_from_opts_window_alert_on_bell(py_opts, opts);
if (PyErr_Occurred()) return false;
convert_from_opts_bell_path(py_opts, opts);
if (PyErr_Occurred()) return false;
convert_from_opts_active_border_color(py_opts, opts);
if (PyErr_Occurred()) return false;
convert_from_opts_inactive_border_color(py_opts, opts);

View File

@ -78,17 +78,22 @@ bglayout(PyObject *layout_name) {
return TILING;
}
static void
background_image(PyObject *src, Options *opts) {
if (opts->background_image) free(opts->background_image);
opts->background_image = NULL;
if (src == Py_None || !PyUnicode_Check(src)) return;
Py_ssize_t sz;
const char *s = PyUnicode_AsUTF8AndSize(src, &sz);
opts->background_image = calloc(sz + 1, 1);
if (opts->background_image) memcpy(opts->background_image, s, sz);
#define STR_SETTER(name) { \
free(opts->name); opts->name = NULL; \
if (src == Py_None || !PyUnicode_Check(src)) return; \
Py_ssize_t sz; \
const char *s = PyUnicode_AsUTF8AndSize(src, &sz); \
opts->name = calloc(sz + 1, 1); \
if (opts->name) memcpy(opts->name, s, sz); \
}
static void
background_image(PyObject *src, Options *opts) { STR_SETTER(background_image); }
static void
bell_path(PyObject *src, Options *opts) { STR_SETTER(bell_path); }
#undef STR_SETTER
static MouseShape
pointer_shape(PyObject *shape_name) {

View File

@ -60,6 +60,7 @@ option_names = ( # {{{
'background_tint',
'bell_border_color',
'bell_on_tab',
'bell_path',
'bold_font',
'bold_italic_font',
'box_drawing_scale',
@ -457,6 +458,7 @@ class Options:
background_tint: float = 0
bell_border_color: Color = Color(red=255, green=90, blue=0)
bell_on_tab: bool = True
bell_path: typing.Optional[str] = None
bold_font: str = 'auto'
bold_italic_font: str = 'auto'
box_drawing_scale: typing.Tuple[float, float, float, float] = (0.001, 1.0, 1.5, 2.0)

View File

@ -1135,7 +1135,9 @@ finalize(void) {
}
if (detached_windows.windows) free(detached_windows.windows);
detached_windows.capacity = 0;
if (OPT(background_image)) free(OPT(background_image));
#define F(x) free(OPT(x)); OPT(x) = NULL;
F(background_image); F(bell_path);
#undef F
// we leak the texture here since it is not guaranteed
// that freeing the texture will work during shutdown and
// the GPU driver should take care of it when the OpenGL context is

View File

@ -40,6 +40,7 @@ typedef struct {
unsigned int macos_option_as_alt;
float macos_thicken_font;
WindowTitleIn macos_show_window_title_in;
char *bell_path;
int adjust_line_height_px, adjust_column_width_px, adjust_baseline_px;
float adjust_line_height_frac, adjust_column_width_frac, adjust_baseline_frac;
float background_opacity, dim_opacity;