xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

sun_bell.c (5780B)


      1 /* Copyright (c) 2004-2005, Oracle and/or its affiliates. All rights reserved.
      2  *
      3  * Permission is hereby granted, free of charge, to any person obtaining a
      4  * copy of this software and associated documentation files (the "Software"),
      5  * to deal in the Software without restriction, including without limitation
      6  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      7  * and/or sell copies of the Software, and to permit persons to whom the
      8  * Software is furnished to do so, subject to the following conditions:
      9  *
     10  * The above copyright notice and this permission notice (including the next
     11  * paragraph) shall be included in all copies or substantial portions of the
     12  * Software.
     13  *
     14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     17  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     19  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     20  * DEALINGS IN THE SOFTWARE.
     21  */
     22 
     23 #ifdef HAVE_XORG_CONFIG_H
     24 #include <xorg-config.h>
     25 #endif
     26 
     27 #include <sys/audio.h>
     28 #include <sys/uio.h>
     29 #include <limits.h>
     30 #include <math.h>
     31 #include <xserver_poll.h>
     32 
     33 #include "xf86.h"
     34 #include "xf86Priv.h"
     35 #include "xf86_OSlib.h"
     36 
     37 #define BELL_RATE       48000   /* Samples per second */
     38 #define BELL_HZ         50      /* Fraction of a second i.e. 1/x */
     39 #define BELL_MS         (1000/BELL_HZ)  /* MS */
     40 #define BELL_SAMPLES    (BELL_RATE / BELL_HZ)
     41 #define BELL_MIN        3       /* Min # of repeats */
     42 
     43 #define AUDIO_DEVICE    "/dev/audio"
     44 
     45 void
     46 xf86OSRingBell(int loudness, int pitch, int duration)
     47 {
     48     static short samples[BELL_SAMPLES];
     49     static short silence[BELL_SAMPLES]; /* "The Sound of Silence" */
     50     static int lastFreq;
     51     int cnt;
     52     int i;
     53     int written;
     54     int repeats;
     55     int freq;
     56     audio_info_t audioInfo;
     57     struct iovec iov[IOV_MAX];
     58     int iovcnt;
     59     double ampl, cyclen, phase;
     60     int audioFD;
     61 
     62     if ((loudness <= 0) || (pitch <= 0) || (duration <= 0)) {
     63         return;
     64     }
     65 
     66     lastFreq = 0;
     67     memset(silence, 0, sizeof(silence));
     68 
     69     audioFD = open(AUDIO_DEVICE, O_WRONLY | O_NONBLOCK);
     70     if (audioFD == -1) {
     71         xf86Msg(X_ERROR, "Bell: cannot open audio device \"%s\": %s\n",
     72                 AUDIO_DEVICE, strerror(errno));
     73         return;
     74     }
     75 
     76     freq = pitch;
     77     freq = min(freq, (BELL_RATE / 2) - 1);
     78     freq = max(freq, 2 * BELL_HZ);
     79 
     80     /*
     81      * Ensure full waves per buffer
     82      */
     83     freq -= freq % BELL_HZ;
     84 
     85     if (freq != lastFreq) {
     86         lastFreq = freq;
     87         ampl = 16384.0;
     88 
     89         cyclen = (double) freq / (double) BELL_RATE;
     90         phase = 0.0;
     91 
     92         for (i = 0; i < BELL_SAMPLES; i++) {
     93             samples[i] = (short) (ampl * sin(2.0 * M_PI * phase));
     94             phase += cyclen;
     95             if (phase >= 1.0)
     96                 phase -= 1.0;
     97         }
     98     }
     99 
    100     repeats = (duration + (BELL_MS / 2)) / BELL_MS;
    101     repeats = max(repeats, BELL_MIN);
    102 
    103     loudness = max(0, loudness);
    104     loudness = min(loudness, 100);
    105 
    106 #ifdef DEBUG
    107     ErrorF("BELL : freq %d volume %d duration %d repeats %d\n",
    108            freq, loudness, duration, repeats);
    109 #endif
    110 
    111     AUDIO_INITINFO(&audioInfo);
    112     audioInfo.play.encoding = AUDIO_ENCODING_LINEAR;
    113     audioInfo.play.sample_rate = BELL_RATE;
    114     audioInfo.play.channels = 2;
    115     audioInfo.play.precision = 16;
    116     audioInfo.play.gain = min(AUDIO_MAX_GAIN, AUDIO_MAX_GAIN * loudness / 100);
    117 
    118     if (ioctl(audioFD, AUDIO_SETINFO, &audioInfo) < 0) {
    119         xf86Msg(X_ERROR,
    120                 "Bell: AUDIO_SETINFO failed on audio device \"%s\": %s\n",
    121                 AUDIO_DEVICE, strerror(errno));
    122         close(audioFD);
    123         return;
    124     }
    125 
    126     iovcnt = 0;
    127 
    128     for (cnt = 0; cnt <= repeats; cnt++) {
    129         if (cnt == repeats) {
    130             /* Insert a bit of silence so that multiple beeps are distinct and
    131              * not compressed into a single tone.
    132              */
    133             iov[iovcnt].iov_base = (char *) silence;
    134             iov[iovcnt++].iov_len = sizeof(silence);
    135         }
    136         else {
    137             iov[iovcnt].iov_base = (char *) samples;
    138             iov[iovcnt++].iov_len = sizeof(samples);
    139         }
    140         if ((iovcnt >= IOV_MAX) || (cnt == repeats)) {
    141             written = writev(audioFD, iov, iovcnt);
    142 
    143             if ((written < ((int) (sizeof(samples) * iovcnt)))) {
    144                 /* audio buffer was full! */
    145 
    146                 int naptime;
    147 
    148                 if (written == -1) {
    149                     if (errno != EAGAIN) {
    150                         xf86Msg(X_ERROR,
    151                                 "Bell: writev failed on audio device \"%s\": %s\n",
    152                                 AUDIO_DEVICE, strerror(errno));
    153                         close(audioFD);
    154                         return;
    155                     }
    156                     i = iovcnt;
    157                 }
    158                 else {
    159                     i = ((sizeof(samples) * iovcnt) - written)
    160                         / sizeof(samples);
    161                 }
    162                 cnt -= i;
    163 
    164                 /* sleep a little to allow audio buffer to drain */
    165                 naptime = BELL_MS * i;
    166                 xserver_poll(NULL, 0, naptime);
    167 
    168                 i = ((sizeof(samples) * iovcnt) - written) % sizeof(samples);
    169                 iovcnt = 0;
    170                 if ((written != -1) && (i > 0)) {
    171                     iov[iovcnt].iov_base = ((char *) samples) + i;
    172                     iov[iovcnt++].iov_len = sizeof(samples) - i;
    173                 }
    174             }
    175             else {
    176                 iovcnt = 0;
    177             }
    178         }
    179     }
    180 
    181     close(audioFD);
    182     return;
    183 }