summaryrefslogtreecommitdiff
path: root/src/sound.c
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2019-06-17 22:19:33 +0200
committerBram Moolenaar <Bram@vim.org>2019-06-17 22:19:33 +0200
commit9b283523f2f75b45feef902b8713808e883d9c19 (patch)
tree83a7c31221221362b997e6938381d4de61db52d3 /src/sound.c
parent394c5d8870b15150fc91a4c058dc571fd5eaa97e (diff)
downloadvim-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.c196
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