Updated esd audio driver for 1.3 API. SDL-ryan-multiple-audio-device
authorRyan C. Gordon <icculus@icculus.org>
Fri, 06 Oct 2006 04:16:11 +0000
branchSDL-ryan-multiple-audio-device
changeset 38153234d6eee011
parent 3814 8e1af9ff0e1f
child 3816 9d070c1a45fa
Updated esd audio driver for 1.3 API.
src/audio/esd/SDL_esdaudio.c
src/audio/esd/SDL_esdaudio.h
     1.1 --- a/src/audio/esd/SDL_esdaudio.c	Fri Oct 06 03:40:57 2006 +0000
     1.2 +++ b/src/audio/esd/SDL_esdaudio.c	Fri Oct 06 04:16:11 2006 +0000
     1.3 @@ -46,39 +46,40 @@
     1.4  #define ESD_DRIVER_NAME		"esd"
     1.5  
     1.6  /* Audio driver functions */
     1.7 -static int ESD_OpenAudio(_THIS, SDL_AudioSpec * spec);
     1.8 -static void ESD_WaitAudio(_THIS);
     1.9 -static void ESD_PlayAudio(_THIS);
    1.10 -static Uint8 *ESD_GetAudioBuf(_THIS);
    1.11 -static void ESD_CloseAudio(_THIS);
    1.12 +static int ESD_OpenDevice(_THIS, const char *devname, int iscapture);
    1.13 +static void ESD_WaitDevice(_THIS);
    1.14 +static void ESD_PlayDevice(_THIS);
    1.15 +static Uint8 *ESD_GetDeviceBuf(_THIS);
    1.16 +static void ESD_CloseDevice(_THIS);
    1.17  
    1.18  #ifdef SDL_AUDIO_DRIVER_ESD_DYNAMIC
    1.19  
    1.20  static const char *esd_library = SDL_AUDIO_DRIVER_ESD_DYNAMIC;
    1.21  static void *esd_handle = NULL;
    1.22 -static int esd_loaded = 0;
    1.23  
    1.24  static int (*SDL_NAME(esd_open_sound)) (const char *host);
    1.25  static int (*SDL_NAME(esd_close)) (int esd);
    1.26  static int (*SDL_NAME(esd_play_stream)) (esd_format_t format, int rate,
    1.27                                           const char *host, const char *name);
    1.28 +
    1.29 +#define SDL_ESD_SYM(x) { #x, (void **) (char *) &SDL_NAME(x) }
    1.30  static struct
    1.31  {
    1.32      const char *name;
    1.33      void **func;
    1.34  } esd_functions[] = {
    1.35 -    {
    1.36 -    "esd_open_sound", (void **) &SDL_NAME(esd_open_sound)}, {
    1.37 -    "esd_close", (void **) &SDL_NAME(esd_close)}, {
    1.38 -"esd_play_stream", (void **) &SDL_NAME(esd_play_stream)},};
    1.39 +    SDL_ESD_SYM(esd_open_sound),
    1.40 +    SDL_ESD_SYM(esd_close),
    1.41 +    SDL_ESD_SYM(esd_play_stream),
    1.42 +};
    1.43 +#undef SDL_ESD_SYM
    1.44  
    1.45  static void
    1.46  UnloadESDLibrary()
    1.47  {
    1.48 -    if (esd_loaded) {
    1.49 +    if (esd_handle != NULL) {
    1.50          SDL_UnloadObject(esd_handle);
    1.51          esd_handle = NULL;
    1.52 -        esd_loaded = 0;
    1.53      }
    1.54  }
    1.55  
    1.56 @@ -87,17 +88,18 @@
    1.57  {
    1.58      int i, retval = -1;
    1.59  
    1.60 -    esd_handle = SDL_LoadObject(esd_library);
    1.61 -    if (esd_handle) {
    1.62 -        esd_loaded = 1;
    1.63 -        retval = 0;
    1.64 -        for (i = 0; i < SDL_arraysize(esd_functions); ++i) {
    1.65 -            *esd_functions[i].func =
    1.66 -                SDL_LoadFunction(esd_handle, esd_functions[i].name);
    1.67 -            if (!*esd_functions[i].func) {
    1.68 -                retval = -1;
    1.69 -                UnloadESDLibrary();
    1.70 -                break;
    1.71 +    if (esd_handle == NULL) {
    1.72 +        esd_handle = SDL_LoadObject(esd_library);
    1.73 +        if (esd_handle) {
    1.74 +            retval = 0;
    1.75 +            for (i = 0; i < SDL_arraysize(esd_functions); ++i) {
    1.76 +                *esd_functions[i].func =
    1.77 +                    SDL_LoadFunction(esd_handle, esd_functions[i].name);
    1.78 +                if (!*esd_functions[i].func) {
    1.79 +                    retval = -1;
    1.80 +                    UnloadESDLibrary();
    1.81 +                    break;
    1.82 +                }
    1.83              }
    1.84          }
    1.85      }
    1.86 @@ -123,79 +125,48 @@
    1.87  /* Audio driver bootstrap functions */
    1.88  
    1.89  static int
    1.90 -Audio_Available(void)
    1.91 +ESD_Available(void)
    1.92  {
    1.93 -    const char *esd_no_spawn = SDL_getenv("ESD_NO_SPAWN");
    1.94 -    int connection = 0;
    1.95      int available = 0;
    1.96 -
    1.97 -    if (esd_no_spawn == NULL) {
    1.98 -        SDL_putenv("ESD_NO_SPAWN=1"); /* Don't start ESD if it's not running */
    1.99 +    if (LoadESDLibrary() == 0) {
   1.100 +        int connection;
   1.101 +        if (SDL_getenv("ESD_NO_SPAWN") == NULL) {
   1.102 +            SDL_putenv("ESD_NO_SPAWN=1"); /* Don't start ESD if it's not running */
   1.103 +        }
   1.104 +        connection = SDL_NAME(esd_open_sound) (NULL);
   1.105 +        if (connection >= 0) {
   1.106 +            available = 1;
   1.107 +            SDL_NAME(esd_close) (connection);
   1.108 +        }
   1.109 +        UnloadESDLibrary();
   1.110      }
   1.111 -
   1.112 -    if (LoadESDLibrary() < 0) {
   1.113 -        return available;
   1.114 -    }
   1.115 -    connection = SDL_NAME(esd_open_sound) (NULL);
   1.116 -    if (connection >= 0) {
   1.117 -        available = 1;
   1.118 -        SDL_NAME(esd_close) (connection);
   1.119 -    }
   1.120 -    UnloadESDLibrary();
   1.121      return available;
   1.122  }
   1.123  
   1.124 -static void
   1.125 -Audio_DeleteDevice(SDL_AudioDevice * device)
   1.126 +
   1.127 +static int
   1.128 +ESD_Init(SDL_AudioDriverImpl *impl)
   1.129  {
   1.130 -    SDL_free(device->hidden);
   1.131 -    SDL_free(device);
   1.132 -    UnloadESDLibrary();
   1.133 +    /* Set the function pointers */
   1.134 +    impl->OpenDevice = ESD_OpenDevice;
   1.135 +    impl->PlayDevice = ESD_PlayDevice;
   1.136 +    impl->WaitDevice = ESD_WaitDevice;
   1.137 +    impl->GetDeviceBuf = ESD_GetDeviceBuf;
   1.138 +    impl->CloseDevice = ESD_CloseDevice;
   1.139 +    impl->OnlyHasDefaultOutputDevice = 1;
   1.140 +
   1.141 +    return 1;
   1.142  }
   1.143  
   1.144 -static SDL_AudioDevice *
   1.145 -Audio_CreateDevice(int devindex)
   1.146 -{
   1.147 -    SDL_AudioDevice *this;
   1.148 -
   1.149 -    /* Initialize all variables that we clean on shutdown */
   1.150 -    LoadESDLibrary();
   1.151 -    this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice));
   1.152 -    if (this) {
   1.153 -        SDL_memset(this, 0, (sizeof *this));
   1.154 -        this->hidden = (struct SDL_PrivateAudioData *)
   1.155 -            SDL_malloc((sizeof *this->hidden));
   1.156 -    }
   1.157 -    if ((this == NULL) || (this->hidden == NULL)) {
   1.158 -        SDL_OutOfMemory();
   1.159 -        if (this) {
   1.160 -            SDL_free(this);
   1.161 -        }
   1.162 -        return (0);
   1.163 -    }
   1.164 -    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
   1.165 -    audio_fd = -1;
   1.166 -
   1.167 -    /* Set the function pointers */
   1.168 -    this->OpenAudio = ESD_OpenAudio;
   1.169 -    this->WaitAudio = ESD_WaitAudio;
   1.170 -    this->PlayAudio = ESD_PlayAudio;
   1.171 -    this->GetAudioBuf = ESD_GetAudioBuf;
   1.172 -    this->CloseAudio = ESD_CloseAudio;
   1.173 -
   1.174 -    this->free = Audio_DeleteDevice;
   1.175 -
   1.176 -    return this;
   1.177 -}
   1.178  
   1.179  AudioBootStrap ESD_bootstrap = {
   1.180      ESD_DRIVER_NAME, "Enlightened Sound Daemon",
   1.181 -    Audio_Available, Audio_CreateDevice, 0
   1.182 +    ESD_Available, ESD_Init, 0
   1.183  };
   1.184  
   1.185  /* This function waits until it is possible to write a full sound buffer */
   1.186  static void
   1.187 -ESD_WaitAudio(_THIS)
   1.188 +ESD_WaitDevice(_THIS)
   1.189  {
   1.190      Sint32 ticks;
   1.191  
   1.192 @@ -205,28 +176,31 @@
   1.193          /* Note that this only works with thread implementations 
   1.194             that use a different process id for each thread.
   1.195           */
   1.196 -        if (parent && (((++cnt) % 10) == 0)) {  /* Check every 10 loops */
   1.197 -            if (kill(parent, 0) < 0) {
   1.198 +        /* Check every 10 loops */
   1.199 +        if (this->hidden->parent && (((++cnt) % 10) == 0)) {
   1.200 +            if (kill(this->hidden->parent, 0) < 0) {
   1.201                  this->enabled = 0;
   1.202              }
   1.203          }
   1.204      }
   1.205  
   1.206      /* Use timer for general audio synchronization */
   1.207 -    ticks = ((Sint32) (next_frame - SDL_GetTicks())) - FUDGE_TICKS;
   1.208 +    ticks = ((Sint32) (this->hidden->next_frame-SDL_GetTicks())) - FUDGE_TICKS;
   1.209      if (ticks > 0) {
   1.210          SDL_Delay(ticks);
   1.211      }
   1.212  }
   1.213  
   1.214  static void
   1.215 -ESD_PlayAudio(_THIS)
   1.216 +ESD_PlayDevice(_THIS)
   1.217  {
   1.218 -    int written;
   1.219 +    int written = 0;
   1.220  
   1.221      /* Write the audio data, checking for EAGAIN on broken audio drivers */
   1.222      do {
   1.223 -        written = write(audio_fd, mixbuf, mixlen);
   1.224 +        written = write(this->hidden->audio_fd,
   1.225 +                        this->hidden->mixbuf,
   1.226 +                        this->hidden->mixlen);
   1.227          if ((written < 0) && ((errno == 0) || (errno == EAGAIN))) {
   1.228              SDL_Delay(1);       /* Let a little CPU time go by */
   1.229          }
   1.230 @@ -235,7 +209,7 @@
   1.231             ((errno == 0) || (errno == EAGAIN) || (errno == EINTR)));
   1.232  
   1.233      /* Set the next write frame */
   1.234 -    next_frame += frame_ticks;
   1.235 +    this->hidden->next_frame += this->hidden->frame_ticks;
   1.236  
   1.237      /* If we couldn't write, assume fatal error for now */
   1.238      if (written < 0) {
   1.239 @@ -244,22 +218,28 @@
   1.240  }
   1.241  
   1.242  static Uint8 *
   1.243 -ESD_GetAudioBuf(_THIS)
   1.244 +ESD_GetDeviceBuf(_THIS)
   1.245  {
   1.246 -    return (mixbuf);
   1.247 +    return (this->hidden->mixbuf);
   1.248  }
   1.249  
   1.250  static void
   1.251 -ESD_CloseAudio(_THIS)
   1.252 +ESD_CloseDevice(_THIS)
   1.253  {
   1.254 -    if (mixbuf != NULL) {
   1.255 -        SDL_FreeAudioMem(mixbuf);
   1.256 -        mixbuf = NULL;
   1.257 +    if (this->hidden != NULL) {
   1.258 +        if (this->hidden->mixbuf != NULL) {
   1.259 +            SDL_FreeAudioMem(this->hidden->mixbuf);
   1.260 +            this->hidden->mixbuf = NULL;
   1.261 +        }
   1.262 +        if (this->hidden->audio_fd >= 0) {
   1.263 +            SDL_NAME(esd_close) (this->hidden->audio_fd);
   1.264 +            this->hidden->audio_fd = -1;
   1.265 +        }
   1.266 +
   1.267 +        SDL_free(this->hidden);
   1.268 +        this->hidden = NULL;
   1.269      }
   1.270 -    if (audio_fd >= 0) {
   1.271 -        SDL_NAME(esd_close) (audio_fd);
   1.272 -        audio_fd = -1;
   1.273 -    }
   1.274 +    UnloadESDLibrary();
   1.275  }
   1.276  
   1.277  /* Try to get the name of the program */
   1.278 @@ -288,59 +268,96 @@
   1.279      return (progname);
   1.280  }
   1.281  
   1.282 +
   1.283  static int
   1.284 -ESD_OpenAudio(_THIS, SDL_AudioSpec * spec)
   1.285 +ESD_OpenDevice(_THIS, const char *devname, int iscapture)
   1.286  {
   1.287 -    esd_format_t format;
   1.288 +    esd_format_t format = (ESD_STREAM | ESD_PLAY);
   1.289 +    SDL_AudioFormat test_format = 0;
   1.290 +    int found = 0;
   1.291 +
   1.292 +    /* Initialize all variables that we clean on shutdown */
   1.293 +    this->hidden = (struct SDL_PrivateAudioData *)
   1.294 +                        SDL_malloc((sizeof *this->hidden));
   1.295 +    if (this->hidden == NULL) {
   1.296 +        SDL_OutOfMemory();
   1.297 +        return 0;
   1.298 +    }
   1.299 +    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
   1.300 +    this->hidden->audio_fd = -1;
   1.301 +
   1.302 +    if (LoadESDLibrary() < 0) {
   1.303 +        ESD_CloseDevice(this);
   1.304 +        SDL_SetError("ESD: failed to load library: %s", SDL_GetError());
   1.305 +        return 0;
   1.306 +    }
   1.307  
   1.308      /* Convert audio spec to the ESD audio format */
   1.309 -    format = (ESD_STREAM | ESD_PLAY);
   1.310 -    switch (spec->format & 0xFF) {
   1.311 -    case 8:
   1.312 -        format |= ESD_BITS8;
   1.313 -        break;
   1.314 -    case 16:
   1.315 -        format |= ESD_BITS16;
   1.316 -        break;
   1.317 -    default:
   1.318 -        SDL_SetError("Unsupported ESD audio format");
   1.319 -        return (-1);
   1.320 +    /* Try for a closest match on audio format */
   1.321 +    for (test_format = SDL_FirstAudioFormat(this->spec.format);
   1.322 +         !found && test_format; test_format = SDL_NextAudioFormat()) {
   1.323 +#ifdef DEBUG_AUDIO
   1.324 +        fprintf(stderr, "Trying format 0x%4.4x\n", test_format);
   1.325 +#endif
   1.326 +        found = 1;
   1.327 +        switch (test_format) {
   1.328 +            case AUDIO_U8:
   1.329 +                format |= ESD_BITS8;
   1.330 +                break;
   1.331 +            case AUDIO_S16SYS:
   1.332 +                format |= ESD_BITS16;
   1.333 +                break;
   1.334 +            default:
   1.335 +                found = 0;
   1.336 +                break;
   1.337 +        }
   1.338      }
   1.339 -    if (spec->channels == 1) {
   1.340 +
   1.341 +    if (!found) {
   1.342 +        ESD_CloseDevice(this);
   1.343 +        SDL_SetError("Couldn't find any hardware audio formats");
   1.344 +        return 0;
   1.345 +    }
   1.346 +
   1.347 +    if (this->spec.channels == 1) {
   1.348          format |= ESD_MONO;
   1.349      } else {
   1.350          format |= ESD_STEREO;
   1.351      }
   1.352  #if 0
   1.353 -    spec->samples = ESD_BUF_SIZE;       /* Darn, no way to change this yet */
   1.354 +    this->spec.samples = ESD_BUF_SIZE;   /* Darn, no way to change this yet */
   1.355  #endif
   1.356  
   1.357      /* Open a connection to the ESD audio server */
   1.358 -    audio_fd =
   1.359 -        SDL_NAME(esd_play_stream) (format, spec->freq, NULL, get_progname());
   1.360 -    if (audio_fd < 0) {
   1.361 +    this->hidden->audio_fd =
   1.362 +        SDL_NAME(esd_play_stream)(format,this->spec.freq,NULL,get_progname());
   1.363 +
   1.364 +    if (this->hidden->audio_fd < 0) {
   1.365 +        ESD_CloseDevice(this);
   1.366          SDL_SetError("Couldn't open ESD connection");
   1.367 -        return (-1);
   1.368 +        return 0;
   1.369      }
   1.370  
   1.371      /* Calculate the final parameters for this audio specification */
   1.372 -    SDL_CalculateAudioSpec(spec);
   1.373 -    frame_ticks = (float) (spec->samples * 1000) / spec->freq;
   1.374 -    next_frame = SDL_GetTicks() + frame_ticks;
   1.375 +    SDL_CalculateAudioSpec(&this->spec);
   1.376 +    this->hidden->frame_ticks = (float) (this->spec.samples*1000) / this->spec.freq;
   1.377 +    this->hidden->next_frame = SDL_GetTicks() + this->hidden->frame_ticks;
   1.378  
   1.379      /* Allocate mixing buffer */
   1.380 -    mixlen = spec->size;
   1.381 -    mixbuf = (Uint8 *) SDL_AllocAudioMem(mixlen);
   1.382 -    if (mixbuf == NULL) {
   1.383 -        return (-1);
   1.384 +    this->hidden->mixlen = this->spec.size;
   1.385 +    this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
   1.386 +    if (this->hidden->mixbuf == NULL) {
   1.387 +        ESD_CloseDevice(this);
   1.388 +        SDL_OutOfMemory();
   1.389 +        return 0;
   1.390      }
   1.391 -    SDL_memset(mixbuf, spec->silence, spec->size);
   1.392 +    SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
   1.393  
   1.394      /* Get the parent process id (we're the parent of the audio thread) */
   1.395 -    parent = getpid();
   1.396 +    this->hidden->parent = getpid();
   1.397  
   1.398      /* We're ready to rock and roll. :-) */
   1.399 -    return (0);
   1.400 +    return 1;
   1.401  }
   1.402  
   1.403  /* vi: set ts=4 sw=4 expandtab: */
     2.1 --- a/src/audio/esd/SDL_esdaudio.h	Fri Oct 06 03:40:57 2006 +0000
     2.2 +++ b/src/audio/esd/SDL_esdaudio.h	Fri Oct 06 04:16:11 2006 +0000
     2.3 @@ -47,13 +47,5 @@
     2.4  };
     2.5  #define FUDGE_TICKS	10      /* The scheduler overhead ticks per frame */
     2.6  
     2.7 -/* Old variable names */
     2.8 -#define audio_fd		(this->hidden->audio_fd)
     2.9 -#define parent			(this->hidden->parent)
    2.10 -#define mixbuf			(this->hidden->mixbuf)
    2.11 -#define mixlen			(this->hidden->mixlen)
    2.12 -#define frame_ticks		(this->hidden->frame_ticks)
    2.13 -#define next_frame		(this->hidden->next_frame)
    2.14 -
    2.15  #endif /* _SDL_esdaudio_h */
    2.16  /* vi: set ts=4 sw=4 expandtab: */