Updated arts driver for 1.3 audio API. SDL-ryan-multiple-audio-device
authorRyan C. Gordon
Fri, 06 Oct 2006 02:40:02 +0000
branchSDL-ryan-multiple-audio-device
changeset 381235d1367020a3
parent 3811 d980c4dcad0f
child 3813 92f7304e50ff
Updated arts driver for 1.3 audio API.
src/audio/arts/SDL_artsaudio.c
src/audio/arts/SDL_artsaudio.h
     1.1 --- a/src/audio/arts/SDL_artsaudio.c	Fri Oct 06 01:13:09 2006 +0000
     1.2 +++ b/src/audio/arts/SDL_artsaudio.c	Fri Oct 06 02:40:02 2006 +0000
     1.3 @@ -40,11 +40,12 @@
     1.4  #define ARTS_DRIVER_NAME         "arts"
     1.5  
     1.6  /* Audio driver functions */
     1.7 -static int ARTS_OpenAudio(_THIS, SDL_AudioSpec * spec);
     1.8 -static void ARTS_WaitAudio(_THIS);
     1.9 -static void ARTS_PlayAudio(_THIS);
    1.10 -static Uint8 *ARTS_GetAudioBuf(_THIS);
    1.11 -static void ARTS_CloseAudio(_THIS);
    1.12 +static int ARTS_OpenDevice(_THIS, const char *devname, int iscapture);
    1.13 +static void ARTS_WaitDevice(_THIS);
    1.14 +static void ARTS_PlayDevice(_THIS);
    1.15 +static Uint8 *ARTS_GetDeviceBuf(_THIS);
    1.16 +static void ARTS_CloseDevice(_THIS);
    1.17 +static void ARTS_WaitDone(_THIS);
    1.18  
    1.19  #ifdef SDL_AUDIO_DRIVER_ARTS_DYNAMIC
    1.20  
    1.21 @@ -52,6 +53,7 @@
    1.22  static void *arts_handle = NULL;
    1.23  static int arts_loaded = 0;
    1.24  
    1.25 +/* !!! FIXME: I hate this SDL_NAME clutter...it makes everything so messy! */
    1.26  static int (*SDL_NAME(arts_init)) (void);
    1.27  static void (*SDL_NAME(arts_free)) (void);
    1.28  static arts_stream_t(*SDL_NAME(arts_play_stream)) (int rate, int bits,
    1.29 @@ -64,20 +66,25 @@
    1.30  static int (*SDL_NAME(arts_write)) (arts_stream_t s, const void *buffer,
    1.31                                      int count);
    1.32  static void (*SDL_NAME(arts_close_stream)) (arts_stream_t s);
    1.33 +static void (*SDL_NAME(arts_close_stream)) (arts_stream_t s);
    1.34 +static const char *(*SDL_NAME(arts_error_text)) (int errorcode);
    1.35  
    1.36 +#define SDL_ARTS_SYM(x) { #x, (void **) (char *) &SDL_NAME(x) }
    1.37  static struct
    1.38  {
    1.39      const char *name;
    1.40      void **func;
    1.41  } arts_functions[] = {
    1.42 -    {
    1.43 -    "arts_init", (void **) &SDL_NAME(arts_init)}, {
    1.44 -    "arts_free", (void **) &SDL_NAME(arts_free)}, {
    1.45 -    "arts_play_stream", (void **) &SDL_NAME(arts_play_stream)}, {
    1.46 -    "arts_stream_set", (void **) &SDL_NAME(arts_stream_set)}, {
    1.47 -    "arts_stream_get", (void **) &SDL_NAME(arts_stream_get)}, {
    1.48 -    "arts_write", (void **) &SDL_NAME(arts_write)}, {
    1.49 -"arts_close_stream", (void **) &SDL_NAME(arts_close_stream)},};
    1.50 +    SDL_ARTS_SYM(arts_init),
    1.51 +    SDL_ARTS_SYM(arts_free),
    1.52 +    SDL_ARTS_SYM(arts_play_stream),
    1.53 +    SDL_ARTS_SYM(arts_stream_set),
    1.54 +    SDL_ARTS_SYM(arts_stream_get),
    1.55 +    SDL_ARTS_SYM(arts_write),
    1.56 +    SDL_ARTS_SYM(arts_close_stream),
    1.57 +    SDL_ARTS_SYM(arts_error_text),
    1.58 +};
    1.59 +#undef SDL_ARTS_SYM
    1.60  
    1.61  static void
    1.62  UnloadARTSLibrary()
    1.63 @@ -94,20 +101,23 @@
    1.64  {
    1.65      int i, retval = -1;
    1.66  
    1.67 -    arts_handle = SDL_LoadObject(arts_library);
    1.68 -    if (arts_handle) {
    1.69 -        arts_loaded = 1;
    1.70 -        retval = 0;
    1.71 -        for (i = 0; i < SDL_arraysize(arts_functions); ++i) {
    1.72 -            *arts_functions[i].func =
    1.73 -                SDL_LoadFunction(arts_handle, arts_functions[i].name);
    1.74 -            if (!*arts_functions[i].func) {
    1.75 -                retval = -1;
    1.76 -                UnloadARTSLibrary();
    1.77 -                break;
    1.78 +    if (!arts_loaded) {
    1.79 +        arts_handle = SDL_LoadObject(arts_library);
    1.80 +        if (arts_handle) {
    1.81 +            arts_loaded = 1;
    1.82 +            retval = 0;
    1.83 +            for (i = 0; i < SDL_arraysize(arts_functions); ++i) {
    1.84 +                *arts_functions[i].func =
    1.85 +                    SDL_LoadFunction(arts_handle, arts_functions[i].name);
    1.86 +                if (!*arts_functions[i].func) {
    1.87 +                    retval = -1;
    1.88 +                    UnloadARTSLibrary();
    1.89 +                    break;
    1.90 +                }
    1.91              }
    1.92          }
    1.93      }
    1.94 +
    1.95      return retval;
    1.96  }
    1.97  
    1.98 @@ -130,114 +140,90 @@
    1.99  /* Audio driver bootstrap functions */
   1.100  
   1.101  static int
   1.102 -Audio_Available(void)
   1.103 +ARTS_Available(void)
   1.104  {
   1.105      int available = 0;
   1.106  
   1.107 -    if (LoadARTSLibrary() < 0) {
   1.108 -        return available;
   1.109 -    }
   1.110 -    if (SDL_NAME(arts_init) () == 0) {
   1.111 +    if (LoadARTSLibrary() == 0) {
   1.112 +        if (SDL_NAME(arts_init) () == 0) {
   1.113  #define ARTS_CRASH_HACK         /* Play a stream so aRts doesn't crash */
   1.114  #ifdef ARTS_CRASH_HACK
   1.115 -        arts_stream_t stream2;
   1.116 -        stream2 = SDL_NAME(arts_play_stream) (44100, 16, 2, "SDL");
   1.117 -        SDL_NAME(arts_write) (stream2, "", 0);
   1.118 -        SDL_NAME(arts_close_stream) (stream2);
   1.119 +            arts_stream_t stream;
   1.120 +            stream = SDL_NAME(arts_play_stream) (44100, 16, 2, "SDL");
   1.121 +            SDL_NAME(arts_write) (stream, "", 0);
   1.122 +            SDL_NAME(arts_close_stream) (stream);
   1.123  #endif
   1.124 -        available = 1;
   1.125 -        SDL_NAME(arts_free) ();
   1.126 +            available = 1;
   1.127 +            SDL_NAME(arts_free) ();
   1.128 +        }
   1.129 +        UnloadARTSLibrary();
   1.130      }
   1.131 -    UnloadARTSLibrary();
   1.132  
   1.133      return available;
   1.134  }
   1.135  
   1.136 -static void
   1.137 -Audio_DeleteDevice(SDL_AudioDevice * device)
   1.138 +
   1.139 +static int
   1.140 +ARTS_Init(SDL_AudioDriverImpl *impl)
   1.141  {
   1.142 -    SDL_free(device->hidden);
   1.143 -    SDL_free(device);
   1.144 -    UnloadARTSLibrary();
   1.145 +    /* Set the function pointers */
   1.146 +    impl->OpenDevice = ARTS_OpenDevice;
   1.147 +    impl->PlayDevice = ARTS_PlayDevice;
   1.148 +    impl->WaitDevice = ARTS_WaitDevice;
   1.149 +    impl->GetDeviceBuf = ARTS_GetDeviceBuf;
   1.150 +    impl->CloseDevice = ARTS_CloseDevice;
   1.151 +    impl->WaitDone = ARTS_WaitDone;
   1.152 +    impl->OnlyHasDefaultOutputDevice = 1;
   1.153 +
   1.154 +    return 1;
   1.155  }
   1.156  
   1.157 -static SDL_AudioDevice *
   1.158 -Audio_CreateDevice(int devindex)
   1.159 -{
   1.160 -    SDL_AudioDevice *this;
   1.161 -
   1.162 -    /* Initialize all variables that we clean on shutdown */
   1.163 -    LoadARTSLibrary();
   1.164 -    this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice));
   1.165 -    if (this) {
   1.166 -        SDL_memset(this, 0, (sizeof *this));
   1.167 -        this->hidden = (struct SDL_PrivateAudioData *)
   1.168 -            SDL_malloc((sizeof *this->hidden));
   1.169 -    }
   1.170 -    if ((this == NULL) || (this->hidden == NULL)) {
   1.171 -        SDL_OutOfMemory();
   1.172 -        if (this) {
   1.173 -            SDL_free(this);
   1.174 -        }
   1.175 -        return (0);
   1.176 -    }
   1.177 -    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
   1.178 -    stream = 0;
   1.179 -
   1.180 -    /* Set the function pointers */
   1.181 -    this->OpenAudio = ARTS_OpenAudio;
   1.182 -    this->WaitAudio = ARTS_WaitAudio;
   1.183 -    this->PlayAudio = ARTS_PlayAudio;
   1.184 -    this->GetAudioBuf = ARTS_GetAudioBuf;
   1.185 -    this->CloseAudio = ARTS_CloseAudio;
   1.186 -
   1.187 -    this->free = Audio_DeleteDevice;
   1.188 -
   1.189 -    return this;
   1.190 -}
   1.191  
   1.192  AudioBootStrap ARTS_bootstrap = {
   1.193 -    ARTS_DRIVER_NAME, "Analog Realtime Synthesizer",
   1.194 -    Audio_Available, Audio_CreateDevice, 0
   1.195 +    ARTS_DRIVER_NAME, "Analog RealTime Synthesizer",
   1.196 +    ARTS_Available, ARTS_Init, 0
   1.197  };
   1.198  
   1.199 +
   1.200  /* This function waits until it is possible to write a full sound buffer */
   1.201  static void
   1.202 -ARTS_WaitAudio(_THIS)
   1.203 +ARTS_WaitDevice(_THIS)
   1.204  {
   1.205      Sint32 ticks;
   1.206  
   1.207      /* Check to see if the thread-parent process is still alive */
   1.208      {
   1.209          static int cnt = 0;
   1.210 -        /* Note that this only works with thread implementations 
   1.211 +        /* Note that this only works with thread implementations
   1.212             that use a different process id for each thread.
   1.213           */
   1.214 -        if (parent && (((++cnt) % 10) == 0)) {  /* Check every 10 loops */
   1.215 -            if (kill(parent, 0) < 0) {
   1.216 +        /* Check every 10 loops */
   1.217 +        if (this->hidden->parent && (((++cnt) % 10) == 0)) {
   1.218 +            if (kill(this->hidden->parent, 0) < 0) {
   1.219                  this->enabled = 0;
   1.220              }
   1.221          }
   1.222      }
   1.223  
   1.224      /* Use timer for general audio synchronization */
   1.225 -    ticks = ((Sint32) (next_frame - SDL_GetTicks())) - FUDGE_TICKS;
   1.226 +    ticks = ((Sint32) (this->hidden->next_frame-SDL_GetTicks())) - FUDGE_TICKS;
   1.227      if (ticks > 0) {
   1.228          SDL_Delay(ticks);
   1.229      }
   1.230  }
   1.231  
   1.232  static void
   1.233 -ARTS_PlayAudio(_THIS)
   1.234 +ARTS_PlayDevice(_THIS)
   1.235  {
   1.236 -    int written;
   1.237 -
   1.238      /* Write the audio data */
   1.239 -    written = SDL_NAME(arts_write) (stream, mixbuf, mixlen);
   1.240 +    int written = SDL_NAME(arts_write) (
   1.241 +                        this->hidden->stream,
   1.242 +                        this->hidden->mixbuf,
   1.243 +                        this->hidden->mixlen);
   1.244  
   1.245      /* If timer synchronization is enabled, set the next write frame */
   1.246 -    if (frame_ticks) {
   1.247 -        next_frame += frame_ticks;
   1.248 +    if (this->hidden->frame_ticks) {
   1.249 +        this->hidden->next_frame += this->hidden->frame_ticks;
   1.250      }
   1.251  
   1.252      /* If we couldn't write, assume fatal error for now */
   1.253 @@ -249,41 +235,66 @@
   1.254  #endif
   1.255  }
   1.256  
   1.257 -static Uint8 *
   1.258 -ARTS_GetAudioBuf(_THIS)
   1.259 +static void
   1.260 +ARTS_WaitDone(_THIS)
   1.261  {
   1.262 -    return (mixbuf);
   1.263 +    /* !!! FIXME: camp here until buffer drains... SDL_Delay(???); */
   1.264  }
   1.265  
   1.266 +
   1.267 +static Uint8 *
   1.268 +ARTS_GetDeviceBuf(_THIS)
   1.269 +{
   1.270 +    return (this->hidden->mixbuf);
   1.271 +}
   1.272 +
   1.273 +
   1.274  static void
   1.275 -ARTS_CloseAudio(_THIS)
   1.276 +ARTS_CloseDevice(_THIS)
   1.277  {
   1.278 -    if (mixbuf != NULL) {
   1.279 -        SDL_FreeAudioMem(mixbuf);
   1.280 -        mixbuf = NULL;
   1.281 +    if (this->hidden != NULL) {
   1.282 +        if (this->hidden->mixbuf != NULL) {
   1.283 +            SDL_FreeAudioMem(this->hidden->mixbuf);
   1.284 +            this->hidden->mixbuf = NULL;
   1.285 +        }
   1.286 +        if (this->hidden->stream) {
   1.287 +            SDL_NAME(arts_close_stream) (this->hidden->stream);
   1.288 +            this->hidden->stream = 0;
   1.289 +        }
   1.290 +        SDL_NAME(arts_free) ();
   1.291 +        SDL_free(this->hidden);
   1.292 +        this->hidden = NULL;
   1.293      }
   1.294 -    if (stream) {
   1.295 -        SDL_NAME(arts_close_stream) (stream);
   1.296 -        stream = 0;
   1.297 -    }
   1.298 -    SDL_NAME(arts_free) ();
   1.299 +    UnloadARTSLibrary();
   1.300  }
   1.301  
   1.302 +
   1.303  static int
   1.304 -ARTS_OpenAudio(_THIS, SDL_AudioSpec * spec)
   1.305 +ARTS_OpenDevice(_THIS, const char *devname, int iscapture)
   1.306  {
   1.307 +    int rc = 0;
   1.308      int bits, frag_spec;
   1.309      SDL_AudioFormat test_format, format;
   1.310  
   1.311 -    /* Reset the timer synchronization flag */
   1.312 -    frame_ticks = 0.0;
   1.313 +    /* Initialize all variables that we clean on shutdown */
   1.314 +    this->hidden = (struct SDL_PrivateAudioData *)
   1.315 +                        SDL_malloc((sizeof *this->hidden));
   1.316 +    if (this->hidden == NULL) {
   1.317 +        SDL_OutOfMemory();
   1.318 +        return 0;
   1.319 +    }
   1.320 +    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
   1.321  
   1.322 -    mixbuf = NULL;
   1.323 +    if (LoadARTSLibrary() < 0) {
   1.324 +        ARTS_CloseDevice(this);
   1.325 +        SDL_SetError("ARTS: failed to load library: %s", SDL_GetError());
   1.326 +        return 0;
   1.327 +    }
   1.328  
   1.329      /* Try for a closest match on audio format */
   1.330      format = 0;
   1.331      bits = 0;
   1.332 -    for (test_format = SDL_FirstAudioFormat(spec->format);
   1.333 +    for (test_format = SDL_FirstAudioFormat(this->spec.format);
   1.334           !format && test_format;) {
   1.335  #ifdef DEBUG_AUDIO
   1.336          fprintf(stderr, "Trying format 0x%4.4x\n", test_format);
   1.337 @@ -306,51 +317,62 @@
   1.338          }
   1.339      }
   1.340      if (format == 0) {
   1.341 +        ARTS_CloseDevice(this);
   1.342          SDL_SetError("Couldn't find any hardware audio formats");
   1.343 -        return (-1);
   1.344 +        return 0;
   1.345      }
   1.346 -    spec->format = test_format;
   1.347 +    this->spec.format = test_format;
   1.348  
   1.349 -    if (SDL_NAME(arts_init) () != 0) {
   1.350 -        SDL_SetError("Unable to initialize ARTS");
   1.351 -        return (-1);
   1.352 +    if ((rc = SDL_NAME(arts_init) ()) != 0) {
   1.353 +        ARTS_CloseDevice(this);
   1.354 +        SDL_SetError( "Unable to initialize ARTS: %s",
   1.355 +                      SDL_NAME(arts_error_text)(rc) );
   1.356 +        return 0;
   1.357      }
   1.358 -    stream =
   1.359 -        SDL_NAME(arts_play_stream) (spec->freq, bits, spec->channels, "SDL");
   1.360 +    this->hidden->stream = SDL_NAME(arts_play_stream) (
   1.361 +                                            this->spec.freq,
   1.362 +                                            bits, this->spec.channels,
   1.363 +                                            "SDL");
   1.364  
   1.365      /* Calculate the final parameters for this audio specification */
   1.366 -    SDL_CalculateAudioSpec(spec);
   1.367 +    SDL_CalculateAudioSpec(&this->spec);
   1.368  
   1.369      /* Determine the power of two of the fragment size */
   1.370 -    for (frag_spec = 0; (0x01 << frag_spec) < spec->size; ++frag_spec);
   1.371 -    if ((0x01 << frag_spec) != spec->size) {
   1.372 +    for (frag_spec = 0; (0x01 << frag_spec) < this->spec.size; ++frag_spec);
   1.373 +    if ((0x01 << frag_spec) != this->spec.size) {
   1.374 +        ARTS_CloseDevice(this);
   1.375          SDL_SetError("Fragment size must be a power of two");
   1.376 -        return (-1);
   1.377 +        return 0;
   1.378      }
   1.379      frag_spec |= 0x00020000;    /* two fragments, for low latency */
   1.380  
   1.381  #ifdef ARTS_P_PACKET_SETTINGS
   1.382 -    SDL_NAME(arts_stream_set) (stream, ARTS_P_PACKET_SETTINGS, frag_spec);
   1.383 +    SDL_NAME(arts_stream_set) (this->hidden->stream,
   1.384 +                                ARTS_P_PACKET_SETTINGS, frag_spec);
   1.385  #else
   1.386 -    SDL_NAME(arts_stream_set) (stream, ARTS_P_PACKET_SIZE,
   1.387 +    SDL_NAME(arts_stream_set) (this->hidden->stream, ARTS_P_PACKET_SIZE,
   1.388                                 frag_spec & 0xffff);
   1.389 -    SDL_NAME(arts_stream_set) (stream, ARTS_P_PACKET_COUNT, frag_spec >> 16);
   1.390 +    SDL_NAME(arts_stream_set) (this->hidden->stream, ARTS_P_PACKET_COUNT,
   1.391 +                               frag_spec >> 16);
   1.392  #endif
   1.393 -    spec->size = SDL_NAME(arts_stream_get) (stream, ARTS_P_PACKET_SIZE);
   1.394 +    this->spec.size = SDL_NAME(arts_stream_get) (this->hidden->stream,
   1.395 +                                                 ARTS_P_PACKET_SIZE);
   1.396  
   1.397      /* Allocate mixing buffer */
   1.398 -    mixlen = spec->size;
   1.399 -    mixbuf = (Uint8 *) SDL_AllocAudioMem(mixlen);
   1.400 -    if (mixbuf == NULL) {
   1.401 -        return (-1);
   1.402 +    this->hidden->mixlen = this->spec.size;
   1.403 +    this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
   1.404 +    if (this->hidden->mixbuf == NULL) {
   1.405 +        ARTS_CloseDevice(this);
   1.406 +        SDL_OutOfMemory();
   1.407 +        return 0;
   1.408      }
   1.409 -    SDL_memset(mixbuf, spec->silence, spec->size);
   1.410 +    SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
   1.411  
   1.412      /* Get the parent process id (we're the parent of the audio thread) */
   1.413 -    parent = getpid();
   1.414 +    this->hidden->parent = getpid();
   1.415  
   1.416      /* We're ready to rock and roll. :-) */
   1.417 -    return (0);
   1.418 +    return 1;
   1.419  }
   1.420  
   1.421  /* vi: set ts=4 sw=4 expandtab: */
     2.1 --- a/src/audio/arts/SDL_artsaudio.h	Fri Oct 06 01:13:09 2006 +0000
     2.2 +++ b/src/audio/arts/SDL_artsaudio.h	Fri Oct 06 02:40:02 2006 +0000
     2.3 @@ -49,13 +49,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 stream			(this->hidden->stream)
     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_artscaudio_h */
    2.16  /* vi: set ts=4 sw=4 expandtab: */