sdl

FORK: Simple Directmedia Layer
git clone https://git.neptards.moe/neptards/sdl.git
Log | Files | Refs

SDL_androidaudio.c (6269B)


      1 /*
      2   Simple DirectMedia Layer
      3   Copyright (C) 1997-2020 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 #include "../../SDL_internal.h"
     22 
     23 #if SDL_AUDIO_DRIVER_ANDROID
     24 
     25 /* Output audio to Android */
     26 
     27 #include "SDL_audio.h"
     28 #include "../SDL_audio_c.h"
     29 #include "SDL_androidaudio.h"
     30 
     31 #include "../../core/android/SDL_android.h"
     32 
     33 #include <android/log.h>
     34 
     35 static SDL_AudioDevice* audioDevice = NULL;
     36 static SDL_AudioDevice* captureDevice = NULL;
     37 
     38 static int
     39 ANDROIDAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
     40 {
     41     SDL_AudioFormat test_format;
     42 
     43     SDL_assert((captureDevice == NULL) || !iscapture);
     44     SDL_assert((audioDevice == NULL) || iscapture);
     45 
     46     if (iscapture) {
     47         captureDevice = this;
     48     } else {
     49         audioDevice = this;
     50     }
     51 
     52     this->hidden = (struct SDL_PrivateAudioData *) SDL_calloc(1, (sizeof *this->hidden));
     53     if (this->hidden == NULL) {
     54         return SDL_OutOfMemory();
     55     }
     56 
     57     test_format = SDL_FirstAudioFormat(this->spec.format);
     58     while (test_format != 0) { /* no "UNKNOWN" constant */
     59         if ((test_format == AUDIO_U8) ||
     60 			(test_format == AUDIO_S16) ||
     61 			(test_format == AUDIO_F32)) {
     62             this->spec.format = test_format;
     63             break;
     64         }
     65         test_format = SDL_NextAudioFormat();
     66     }
     67 
     68     if (test_format == 0) {
     69         /* Didn't find a compatible format :( */
     70         return SDL_SetError("No compatible audio format!");
     71     }
     72 
     73     if (Android_JNI_OpenAudioDevice(iscapture, &this->spec) < 0) {
     74         return -1;
     75     }
     76 
     77     SDL_CalculateAudioSpec(&this->spec);
     78 
     79     return 0;
     80 }
     81 
     82 static void
     83 ANDROIDAUDIO_PlayDevice(_THIS)
     84 {
     85     Android_JNI_WriteAudioBuffer();
     86 }
     87 
     88 static Uint8 *
     89 ANDROIDAUDIO_GetDeviceBuf(_THIS)
     90 {
     91     return Android_JNI_GetAudioBuffer();
     92 }
     93 
     94 static int
     95 ANDROIDAUDIO_CaptureFromDevice(_THIS, void *buffer, int buflen)
     96 {
     97     return Android_JNI_CaptureAudioBuffer(buffer, buflen);
     98 }
     99 
    100 static void
    101 ANDROIDAUDIO_FlushCapture(_THIS)
    102 {
    103     Android_JNI_FlushCapturedAudio();
    104 }
    105 
    106 static void
    107 ANDROIDAUDIO_CloseDevice(_THIS)
    108 {
    109     /* At this point SDL_CloseAudioDevice via close_audio_device took care of terminating the audio thread
    110        so it's safe to terminate the Java side buffer and AudioTrack
    111      */
    112     Android_JNI_CloseAudioDevice(this->iscapture);
    113     if (this->iscapture) {
    114         SDL_assert(captureDevice == this);
    115         captureDevice = NULL;
    116     } else {
    117         SDL_assert(audioDevice == this);
    118         audioDevice = NULL;
    119     }
    120     SDL_free(this->hidden);
    121 }
    122 
    123 static int
    124 ANDROIDAUDIO_Init(SDL_AudioDriverImpl * impl)
    125 {
    126     /* Set the function pointers */
    127     impl->OpenDevice = ANDROIDAUDIO_OpenDevice;
    128     impl->PlayDevice = ANDROIDAUDIO_PlayDevice;
    129     impl->GetDeviceBuf = ANDROIDAUDIO_GetDeviceBuf;
    130     impl->CloseDevice = ANDROIDAUDIO_CloseDevice;
    131     impl->CaptureFromDevice = ANDROIDAUDIO_CaptureFromDevice;
    132     impl->FlushCapture = ANDROIDAUDIO_FlushCapture;
    133 
    134     /* and the capabilities */
    135     impl->HasCaptureSupport = SDL_TRUE;
    136     impl->OnlyHasDefaultOutputDevice = 1;
    137     impl->OnlyHasDefaultCaptureDevice = 1;
    138 
    139     return 1;   /* this audio target is available. */
    140 }
    141 
    142 AudioBootStrap ANDROIDAUDIO_bootstrap = {
    143     "android", "SDL Android audio driver", ANDROIDAUDIO_Init, 0
    144 };
    145 
    146 /* Pause (block) all non already paused audio devices by taking their mixer lock */
    147 void ANDROIDAUDIO_PauseDevices(void)
    148 {
    149     /* TODO: Handle multiple devices? */
    150     struct SDL_PrivateAudioData *private;
    151     if(audioDevice != NULL && audioDevice->hidden != NULL) {
    152         private = (struct SDL_PrivateAudioData *) audioDevice->hidden;
    153         if (SDL_AtomicGet(&audioDevice->paused)) {
    154             /* The device is already paused, leave it alone */
    155             private->resume = SDL_FALSE;
    156         }
    157         else {
    158             SDL_LockMutex(audioDevice->mixer_lock);
    159             SDL_AtomicSet(&audioDevice->paused, 1);
    160             private->resume = SDL_TRUE;
    161         }
    162     }
    163 
    164     if(captureDevice != NULL && captureDevice->hidden != NULL) {
    165         private = (struct SDL_PrivateAudioData *) captureDevice->hidden;
    166         if (SDL_AtomicGet(&captureDevice->paused)) {
    167             /* The device is already paused, leave it alone */
    168             private->resume = SDL_FALSE;
    169         }
    170         else {
    171             SDL_LockMutex(captureDevice->mixer_lock);
    172             SDL_AtomicSet(&captureDevice->paused, 1);
    173             private->resume = SDL_TRUE;
    174         }
    175     }
    176 }
    177 
    178 /* Resume (unblock) all non already paused audio devices by releasing their mixer lock */
    179 void ANDROIDAUDIO_ResumeDevices(void)
    180 {
    181     /* TODO: Handle multiple devices? */
    182     struct SDL_PrivateAudioData *private;
    183     if(audioDevice != NULL && audioDevice->hidden != NULL) {
    184         private = (struct SDL_PrivateAudioData *) audioDevice->hidden;
    185         if (private->resume) {
    186             SDL_AtomicSet(&audioDevice->paused, 0);
    187             private->resume = SDL_FALSE;
    188             SDL_UnlockMutex(audioDevice->mixer_lock);
    189         }
    190     }
    191 
    192     if(captureDevice != NULL && captureDevice->hidden != NULL) {
    193         private = (struct SDL_PrivateAudioData *) captureDevice->hidden;
    194         if (private->resume) {
    195             SDL_AtomicSet(&captureDevice->paused, 0);
    196             private->resume = SDL_FALSE;
    197             SDL_UnlockMutex(captureDevice->mixer_lock);
    198         }
    199     }
    200 }
    201 
    202 #else 
    203 
    204 void ANDROIDAUDIO_ResumeDevices(void) {}
    205 void ANDROIDAUDIO_PauseDevices(void) {}
    206 
    207 #endif /* SDL_AUDIO_DRIVER_ANDROID */
    208 
    209 /* vi: set ts=4 sw=4 expandtab: */
    210