aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEli Zaretskii2025-12-07 11:31:40 +0200
committerEli Zaretskii2025-12-07 11:31:40 +0200
commit300c6dc2f979ba358b44493cf871db2d49ae0a89 (patch)
tree8c73d30e3288e1746430de3ee7abde8a1785af59
parent2d459d8377a2604a6ee5abc3531c9776eadc008b (diff)
downloademacs-300c6dc2f979ba358b44493cf871db2d49ae0a89.tar.gz
emacs-300c6dc2f979ba358b44493cf871db2d49ae0a89.zip
Allow volume control of system audio device on MS-Windows
* src/sound.c (Fw32_sound_volume): New function. * etc/NEWS: Announce it.
-rw-r--r--etc/NEWS5
-rw-r--r--src/sound.c67
2 files changed, 72 insertions, 0 deletions
diff --git a/etc/NEWS b/etc/NEWS
index 9f47cd57eac..455377f524c 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -3720,6 +3720,11 @@ In addition to ':file FILE' for playing a sound from a file, ':data
3720DATA' can now be used to play a sound from memory. 3720DATA' can now be used to play a sound from memory.
3721 3721
3722--- 3722---
3723** New primitive 'w32-sound-volume'.
3724This primitive allows to get and set the volume of the system's default
3725audio device (or the "optimal device", if there are several devices).
3726
3727---
3723** The MS-DOS port of Emacs now supports more recent releases of GCC and Binutils. 3728** The MS-DOS port of Emacs now supports more recent releases of GCC and Binutils.
3724Accordingly, we have revised our recommendations for a suitable DJGPP 3729Accordingly, we have revised our recommendations for a suitable DJGPP
3725toolchain to GCC 14.2.0 and Binutils 2.35.1 in lieu of GCC 3.4.x and 3730toolchain to GCC 14.2.0 and Binutils 2.35.1 in lieu of GCC 3.4.x and
diff --git a/src/sound.c b/src/sound.c
index 38f1b0c356c..6d833306d63 100644
--- a/src/sound.c
+++ b/src/sound.c
@@ -1357,6 +1357,70 @@ do_play_sound (const char *psz_file_or_data, unsigned long ui_volume, bool in_me
1357 return i_result; 1357 return i_result;
1358} 1358}
1359 1359
1360DEFUN ("w32-sound-volume", Fw32_sound_volume, Sw32_sound_volume, 0, 1, 0,
1361 doc: /* Get or set the MS-Windows audio volume setting.
1362If VOLUME is specified, it should be the volume to set, either an integer
1363in the range [0, 100], or a float in the range [0, 1.0]. Value of zero
1364means mute the audio, value of 100 or 1.0 means maximum volume.
1365When called with the VOLUME argument nil or omitted, just return the
1366current volume setting.
1367The return value is the integer volume setting before the change, if any. */)
1368 (Lisp_Object volume)
1369{
1370 DWORD ui_volume, ui_volume_orig;
1371 MMRESULT mm_result = MMSYSERR_NOERROR;
1372
1373 if (FIXNUMP (volume))
1374 ui_volume = XFIXNUM (volume);
1375 else if (FLOATP (volume))
1376 ui_volume = XFLOAT_DATA (volume) * 100;
1377 else if (BIGNUMP (volume))
1378 {
1379 double dvolume = bignum_to_double (volume);
1380 if (dvolume < 0)
1381 ui_volume = 0;
1382 else if (dvolume > 100.0)
1383 ui_volume = 100;
1384 else
1385 ui_volume = dvolume + 0.5;
1386 }
1387 else if (!NILP (volume))
1388 wrong_type_argument (Qnumberp, volume);
1389
1390 mm_result = waveOutGetVolume ((HWAVEOUT) WAVE_MAPPER, &ui_volume_orig);
1391 if (mm_result == MMSYSERR_NOERROR)
1392 {
1393 /* Look only at the low 16 bits, assuming left and right channels
1394 have identical volume settings. */
1395 ui_volume_orig &= 0xFFFF;
1396 /* The value is between 0 and 0xFFFF, convert to our scale. */
1397 ui_volume_orig = ui_volume_orig * 100.0 / 65535.0 + 0.5;
1398 }
1399 else
1400 {
1401 SOUND_WARNING (waveOutGetErrorText, mm_result,
1402 "waveOutGetVolume: failed to obtain the original"
1403 " volume level of the WAVE_MAPPER device.");
1404 ui_volume_orig = 100;
1405 }
1406 if (!NILP (volume))
1407 {
1408 if (ui_volume > 100)
1409 ui_volume = 100;
1410 /* Set the same volume for left and right channels. */
1411 ui_volume = ui_volume * 0xFFFF / 100;
1412 ui_volume = (ui_volume << 16) + ui_volume;
1413 mm_result = waveOutSetVolume ((HWAVEOUT) WAVE_MAPPER, ui_volume);
1414 if (mm_result != MMSYSERR_NOERROR)
1415 {
1416 SOUND_WARNING (waveOutGetErrorText, mm_result,
1417 "waveOutSetVolume: failed to set the volume level"
1418 " of the WAVE_MAPPER device.");
1419 }
1420 }
1421 return make_fixnum (ui_volume_orig);
1422}
1423
1360/* END: Windows specific functions */ 1424/* END: Windows specific functions */
1361 1425
1362#endif /* WINDOWSNT */ 1426#endif /* WINDOWSNT */
@@ -1482,6 +1546,9 @@ syms_of_sound (void)
1482 DEFSYM (Qplay_sound_functions, "play-sound-functions"); 1546 DEFSYM (Qplay_sound_functions, "play-sound-functions");
1483 1547
1484 defsubr (&Splay_sound_internal); 1548 defsubr (&Splay_sound_internal);
1549#ifdef WINDOWSNT
1550 defsubr (&Sw32_sound_volume);
1551#endif
1485} 1552}
1486 1553
1487#endif /* HAVE_SOUND */ 1554#endif /* HAVE_SOUND */