src/audio/nacl/SDL_naclaudio.c
author Ryan C. Gordon
Tue, 24 Jan 2017 16:18:25 -0500
changeset 10850 c9dc0068b0e7
parent 10765 61312c8c59fe
child 10997 b6315b6bc32f
permissions -rw-r--r--
configure: report libsamplerate support status.
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
     4 
     5   This software is provided 'as-is', without any express or implied
     6   warranty.  In no event will the authors be held liable for any damages
     7   arising from the use of this software.
     8 
     9   Permission is granted to anyone to use this software for any purpose,
    10   including commercial applications, and to alter it and redistribute it
    11   freely, subject to the following restrictions:
    12 
    13   1. The origin of this software must not be misrepresented; you must not
    14      claim that you wrote the original software. If you use this software
    15      in a product, an acknowledgment in the product documentation would be
    16      appreciated but is not required.
    17   2. Altered source versions must be plainly marked as such, and must not be
    18      misrepresented as being the original software.
    19   3. This notice may not be removed or altered from any source distribution.
    20 */
    21 
    22 #include "../../SDL_internal.h"
    23 
    24 #if SDL_AUDIO_DRIVER_NACL
    25 
    26 #include "SDL_naclaudio.h"
    27 
    28 #include "SDL_audio.h"
    29 #include "SDL_mutex.h"
    30 #include "../SDL_audio_c.h"
    31 #include "../SDL_audiodev_c.h"
    32 
    33 #include "ppapi/c/pp_errors.h"
    34 #include "ppapi/c/pp_instance.h"
    35 #include "ppapi_simple/ps.h"
    36 #include "ppapi_simple/ps_interface.h"
    37 #include "ppapi_simple/ps_event.h"
    38 
    39 /* The tag name used by NACL audio */
    40 #define NACLAUDIO_DRIVER_NAME         "nacl"
    41 
    42 #define SAMPLE_FRAME_COUNT 4096
    43 
    44 /* Audio driver functions */
    45 static void nacl_audio_callback(void* samples, uint32_t buffer_size, PP_TimeDelta latency, void* data);
    46 
    47 /* FIXME: Make use of latency if needed */
    48 static void nacl_audio_callback(void* stream, uint32_t buffer_size, PP_TimeDelta latency, void* data) {
    49     const int len = (int) buffer_size;
    50     SDL_AudioDevice* _this = (SDL_AudioDevice*) data;
    51     SDL_AudioCallback callback = _this->spec.callback;
    52     
    53     SDL_LockMutex(private->mutex);  /* !!! FIXME: is this mutex necessary? */
    54 
    55     /* Only do something if audio is enabled */
    56     if (!SDL_AtomicGet(&_this->enabled) || SDL_AtomicGet(&_this->paused)) {
    57         if (_this->stream) {
    58             SDL_AudioStreamClear(_this->stream);
    59         }
    60         SDL_memset(stream, _this->spec.silence, len);
    61         return;
    62     }
    63 
    64     SDL_assert(_this->spec.size == len);
    65 
    66     if (_this->stream == NULL) {  /* no conversion necessary. */
    67         SDL_LockMutex(_this->mixer_lock);
    68         callback(_this->spec.userdata, stream, len);
    69         SDL_UnlockMutex(_this->mixer_lock);
    70     } else {  /* streaming/converting */
    71         const int stream_len = _this->callbackspec.size;
    72         while (SDL_AudioStreamAvailable(_this->stream) < len) {
    73             callback(_this->spec.userdata, _this->work_buffer, stream_len);
    74             if (SDL_AudioStreamPut(_this->stream, _this->work_buffer, stream_len) == -1) {
    75                 SDL_AudioStreamClear(_this->stream);
    76                 SDL_AtomicSet(&_this->enabled, 0);
    77                 break;
    78             }
    79         }
    80 
    81         const int got = SDL_AudioStreamGet(_this->stream, stream, len);
    82         SDL_assert((got < 0) || (got == len));
    83         if (got != len) {
    84             SDL_memset(stream, _this->spec.silence, len);
    85         }
    86     }
    87 
    88     SDL_UnlockMutex(private->mutex);
    89 }
    90 
    91 static void NACLAUDIO_CloseDevice(SDL_AudioDevice *device) {
    92     const PPB_Core *core = PSInterfaceCore();
    93     const PPB_Audio *ppb_audio = PSInterfaceAudio();
    94     SDL_PrivateAudioData *hidden = (SDL_PrivateAudioData *) device->hidden;
    95     
    96     ppb_audio->StopPlayback(hidden->audio);
    97     SDL_DestroyMutex(hidden->mutex);
    98     core->ReleaseResource(hidden->audio);
    99 }
   100 
   101 static int
   102 NACLAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture) {
   103     PP_Instance instance = PSGetInstanceId();
   104     const PPB_Audio *ppb_audio = PSInterfaceAudio();
   105     const PPB_AudioConfig *ppb_audiocfg = PSInterfaceAudioConfig();
   106     
   107     private = (SDL_PrivateAudioData *) SDL_calloc(1, (sizeof *private));
   108     if (private == NULL) {
   109         SDL_OutOfMemory();
   110         return 0;
   111     }
   112     
   113     private->mutex = SDL_CreateMutex();
   114     _this->spec.freq = 44100;
   115     _this->spec.format = AUDIO_S16LSB;
   116     _this->spec.channels = 2;
   117     _this->spec.samples = ppb_audiocfg->RecommendSampleFrameCount(
   118         instance, 
   119         PP_AUDIOSAMPLERATE_44100, 
   120         SAMPLE_FRAME_COUNT);
   121     
   122     /* Calculate the final parameters for this audio specification */
   123     SDL_CalculateAudioSpec(&_this->spec);
   124     
   125     private->audio = ppb_audio->Create(
   126         instance,
   127         ppb_audiocfg->CreateStereo16Bit(instance, PP_AUDIOSAMPLERATE_44100, _this->spec.samples),
   128         nacl_audio_callback, 
   129         _this);
   130     
   131     /* Start audio playback while we are still on the main thread. */
   132     ppb_audio->StartPlayback(private->audio);
   133     
   134     return 1;
   135 }
   136 
   137 static int
   138 NACLAUDIO_Init(SDL_AudioDriverImpl * impl)
   139 {
   140     if (PSGetInstanceId() == 0) {
   141         return 0;
   142     }
   143     
   144     /* Set the function pointers */
   145     impl->OpenDevice = NACLAUDIO_OpenDevice;
   146     impl->CloseDevice = NACLAUDIO_CloseDevice;
   147     impl->OnlyHasDefaultOutputDevice = 1;
   148     impl->ProvidesOwnCallbackThread = 1;
   149     /*
   150      *    impl->WaitDevice = NACLAUDIO_WaitDevice;
   151      *    impl->GetDeviceBuf = NACLAUDIO_GetDeviceBuf;
   152      *    impl->PlayDevice = NACLAUDIO_PlayDevice;
   153      *    impl->Deinitialize = NACLAUDIO_Deinitialize;
   154      */
   155     
   156     return 1;
   157 }
   158 
   159 AudioBootStrap NACLAUDIO_bootstrap = {
   160     NACLAUDIO_DRIVER_NAME, "SDL NaCl Audio Driver",
   161     NACLAUDIO_Init, 0
   162 };
   163 
   164 #endif /* SDL_AUDIO_DRIVER_NACL */
   165 
   166 /* vi: set ts=4 sw=4 expandtab: */