diff options
author | Bram Moolenaar <Bram@vim.org> | 2019-06-17 22:19:33 +0200 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2019-06-17 22:19:33 +0200 |
commit | 9b283523f2f75b45feef902b8713808e883d9c19 (patch) | |
tree | 83a7c31221221362b997e6938381d4de61db52d3 /src/sound.c | |
parent | 394c5d8870b15150fc91a4c058dc571fd5eaa97e (diff) | |
download | vim-git-9b283523f2f75b45feef902b8713808e883d9c19.tar.gz |
patch 8.1.1565: MS-Windows: no sound supportv8.1.1565
Problem: MS-Windows: no sound support.
Solution: Add sound support for MS-Windows. (Yasuhiro Matsumoto, Ken Takata,
closes #4522)
Diffstat (limited to 'src/sound.c')
-rw-r--r-- | src/sound.c | 196 |
1 files changed, 189 insertions, 7 deletions
diff --git a/src/sound.c b/src/sound.c index e28ccff90..70f4425e9 100644 --- a/src/sound.c +++ b/src/sound.c @@ -13,17 +13,18 @@ #include "vim.h" -#if (defined(FEAT_SOUND) && defined(HAVE_CANBERRA)) || defined(PROTO) - -#include <canberra.h> +#if defined(FEAT_SOUND) || defined(PROTO) static long sound_id = 0; -static ca_context *context = NULL; typedef struct soundcb_S soundcb_T; struct soundcb_S { callback_T snd_callback; +#ifdef MSWIN + MCIDEVICEID snd_device_id; + long snd_id; +#endif soundcb_T *snd_next; }; @@ -75,6 +76,15 @@ delete_sound_callback(soundcb_T *soundcb) } } +#if defined(HAVE_CANBERRA) || defined(PROTO) + +/* + * Sound implementation for Linux/Unix/Mac using libcanberra. + */ +# include <canberra.h> + +static ca_context *context = NULL; + static void sound_callback( ca_context *c UNUSED, @@ -188,7 +198,7 @@ f_sound_clear(typval_T *argvars UNUSED, typval_T *rettv UNUSED) } } -#if defined(EXITFREE) || defined(PROTO) +# if defined(EXITFREE) || defined(PROTO) void sound_free(void) { @@ -197,6 +207,178 @@ sound_free(void) while (first_callback != NULL) delete_sound_callback(first_callback); } -#endif +# endif + +#elif defined(MSWIN) + +/* + * Sound implementation for MS-Windows. + */ + +static HWND g_hWndSound = NULL; + + static LRESULT CALLBACK +sound_wndproc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + soundcb_T *p; + + switch (message) + { + case MM_MCINOTIFY: + for (p = first_callback; p != NULL; p = p->snd_next) + if (p->snd_device_id == (MCIDEVICEID) lParam) + { + typval_T argv[3]; + typval_T rettv; + int dummy; + char buf[32]; + + vim_snprintf(buf, sizeof(buf), "close sound%06ld", + p->snd_id); + mciSendString(buf, NULL, 0, 0); + + argv[0].v_type = VAR_NUMBER; + argv[0].vval.v_number = p->snd_id; + argv[1].v_type = VAR_NUMBER; + argv[1].vval.v_number = + wParam == MCI_NOTIFY_SUCCESSFUL ? 0 + : wParam == MCI_NOTIFY_ABORTED ? 1 : 2; + argv[2].v_type = VAR_UNKNOWN; + + call_callback(&p->snd_callback, -1, + &rettv, 2, argv, NULL, 0L, 0L, &dummy, TRUE, NULL); + clear_tv(&rettv); + + delete_sound_callback(p); + redraw_after_callback(TRUE); + + } + break; + } + + return DefWindowProc(hwnd, message, wParam, lParam); +} + + static HWND +sound_window() +{ + if (g_hWndSound == NULL) + { + LPCSTR clazz = "VimSound"; + WNDCLASS wndclass = { + 0, sound_wndproc, 0, 0, g_hinst, NULL, 0, 0, NULL, clazz }; + RegisterClass(&wndclass); + g_hWndSound = CreateWindow(clazz, NULL, 0, 0, 0, 0, 0, + HWND_MESSAGE, NULL, g_hinst, NULL); + } + + return g_hWndSound; +} + + void +f_sound_playevent(typval_T *argvars, typval_T *rettv) +{ + WCHAR *wp; + + rettv->v_type = VAR_NUMBER; + rettv->vval.v_number = 0; + + wp = enc_to_utf16(tv_get_string(&argvars[0]), NULL); + if (wp == NULL) + return; + + PlaySoundW(wp, NULL, SND_ASYNC | SND_ALIAS); + free(wp); + + rettv->vval.v_number = ++sound_id; +} + + void +f_sound_playfile(typval_T *argvars, typval_T *rettv) +{ + long newid = sound_id + 1; + size_t len; + char_u *p, *esc; + WCHAR *wp; + soundcb_T *soundcb; + char buf[32]; + MCIERROR err; + + rettv->v_type = VAR_NUMBER; + rettv->vval.v_number = 0; + + esc = vim_strsave_shellescape(tv_get_string(&argvars[0]), FALSE, FALSE); + + len = STRLEN(esc) + 5 + 18 + 1; + p = alloc(len); + if (p == NULL) + { + free(esc); + return; + } + vim_snprintf((char *)p, len, "open %s alias sound%06ld", esc, newid); + free(esc); + + wp = enc_to_utf16((char_u *)p, NULL); + free(p); + if (wp == NULL) + return; + + err = mciSendStringW(wp, NULL, 0, sound_window()); + free(wp); + if (err != 0) + return; + + vim_snprintf(buf, sizeof(buf), "play sound%06ld notify", newid); + err = mciSendString(buf, NULL, 0, sound_window()); + if (err != 0) + goto failure; + + sound_id = newid; + rettv->vval.v_number = sound_id; + + soundcb = get_sound_callback(&argvars[1]); + if (soundcb != NULL) + { + vim_snprintf(buf, sizeof(buf), "sound%06ld", newid); + soundcb->snd_id = newid; + soundcb->snd_device_id = mciGetDeviceID(buf); + } + return; + +failure: + vim_snprintf(buf, sizeof(buf), "close sound%06ld", newid); + mciSendString(buf, NULL, 0, NULL); +} + + void +f_sound_stop(typval_T *argvars, typval_T *rettv UNUSED) +{ + long id = tv_get_number(&argvars[0]); + char buf[32]; + + vim_snprintf(buf, sizeof(buf), "stop sound%06ld", id); + mciSendString(buf, NULL, 0, NULL); +} + + void +f_sound_clear(typval_T *argvars UNUSED, typval_T *rettv UNUSED) +{ + PlaySound(NULL, NULL, 0); + mciSendString("close all", NULL, 0, NULL); +} + +# if defined(EXITFREE) + void +sound_free(void) +{ + CloseWindow(g_hWndSound); + + while (first_callback != NULL) + delete_sound_callback(first_callback); +} +# endif + +#endif // MSWIN -#endif // FEAT_SOUND && HAVE_CANBERRA +#endif // FEAT_SOUND |