diff options
| author | Eli Zaretskii | 2025-12-07 11:31:40 +0200 |
|---|---|---|
| committer | Eli Zaretskii | 2025-12-07 11:31:40 +0200 |
| commit | 300c6dc2f979ba358b44493cf871db2d49ae0a89 (patch) | |
| tree | 8c73d30e3288e1746430de3ee7abde8a1785af59 | |
| parent | 2d459d8377a2604a6ee5abc3531c9776eadc008b (diff) | |
| download | emacs-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/NEWS | 5 | ||||
| -rw-r--r-- | src/sound.c | 67 |
2 files changed, 72 insertions, 0 deletions
| @@ -3720,6 +3720,11 @@ In addition to ':file FILE' for playing a sound from a file, ':data | |||
| 3720 | DATA' can now be used to play a sound from memory. | 3720 | DATA' can now be used to play a sound from memory. |
| 3721 | 3721 | ||
| 3722 | --- | 3722 | --- |
| 3723 | ** New primitive 'w32-sound-volume'. | ||
| 3724 | This primitive allows to get and set the volume of the system's default | ||
| 3725 | audio 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. |
| 3724 | Accordingly, we have revised our recommendations for a suitable DJGPP | 3729 | Accordingly, we have revised our recommendations for a suitable DJGPP |
| 3725 | toolchain to GCC 14.2.0 and Binutils 2.35.1 in lieu of GCC 3.4.x and | 3730 | toolchain 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 | ||
| 1360 | DEFUN ("w32-sound-volume", Fw32_sound_volume, Sw32_sound_volume, 0, 1, 0, | ||
| 1361 | doc: /* Get or set the MS-Windows audio volume setting. | ||
| 1362 | If VOLUME is specified, it should be the volume to set, either an integer | ||
| 1363 | in the range [0, 100], or a float in the range [0, 1.0]. Value of zero | ||
| 1364 | means mute the audio, value of 100 or 1.0 means maximum volume. | ||
| 1365 | When called with the VOLUME argument nil or omitted, just return the | ||
| 1366 | current volume setting. | ||
| 1367 | The 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 */ |