SDL  2.0
SDL_haikuaudio.cc
Go to the documentation of this file.
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_HAIKU
24 
25 /* Allow access to the audio stream on Haiku */
26 
27 #include <SoundPlayer.h>
28 #include <signal.h>
29 
30 #include "../../main/haiku/SDL_BeApp.h"
31 
32 extern "C"
33 {
34 
35 #include "SDL_audio.h"
36 #include "../SDL_audio_c.h"
37 #include "../SDL_sysaudio.h"
38 #include "SDL_haikuaudio.h"
39 
40 }
41 
42 
43 /* !!! FIXME: have the callback call the higher level to avoid code dupe. */
44 /* The Haiku callback for handling the audio buffer */
45 static void
46 FillSound(void *device, void *stream, size_t len,
47  const media_raw_audio_format & format)
48 {
51 
52  /* Only do something if audio is enabled */
53  if (!SDL_AtomicGet(&audio->enabled) || SDL_AtomicGet(&audio->paused)) {
54  if (audio->stream) {
56  }
57  SDL_memset(stream, audio->spec.silence, len);
58  return;
59  }
60 
61  SDL_assert(audio->spec.size == len);
62 
63  if (audio->stream == NULL) { /* no conversion necessary. */
64  SDL_LockMutex(audio->mixer_lock);
67  } else { /* streaming/converting */
68  const int stream_len = audio->callbackspec.size;
69  const int ilen = (int) len;
70  while (SDL_AudioStreamAvailable(audio->stream) < ilen) {
71  callback(audio->callbackspec.userdata, audio->work_buffer, stream_len);
72  if (SDL_AudioStreamPut(audio->stream, audio->work_buffer, stream_len) == -1) {
74  SDL_AtomicSet(&audio->enabled, 0);
75  break;
76  }
77  }
78 
79  const int got = SDL_AudioStreamGet(audio->stream, stream, ilen);
80  SDL_assert((got < 0) || (got == ilen));
81  if (got != ilen) {
82  SDL_memset(stream, audio->spec.silence, len);
83  }
84  }
85 }
86 
87 static void
88 HAIKUAUDIO_CloseDevice(_THIS)
89 {
90  if (_this->hidden->audio_obj) {
91  _this->hidden->audio_obj->Stop();
92  delete _this->hidden->audio_obj;
93  }
94  delete _this->hidden;
95 }
96 
97 
98 static const int sig_list[] = {
99  SIGHUP, SIGINT, SIGQUIT, SIGPIPE, SIGALRM, SIGTERM, SIGWINCH, 0
100 };
101 
102 static inline void
103 MaskSignals(sigset_t * omask)
104 {
105  sigset_t mask;
106  int i;
107 
108  sigemptyset(&mask);
109  for (i = 0; sig_list[i]; ++i) {
110  sigaddset(&mask, sig_list[i]);
111  }
112  sigprocmask(SIG_BLOCK, &mask, omask);
113 }
114 
115 static inline void
116 UnmaskSignals(sigset_t * omask)
117 {
118  sigprocmask(SIG_SETMASK, omask, NULL);
119 }
120 
121 
122 static int
123 HAIKUAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
124 {
125  int valid_datatype = 0;
126  media_raw_audio_format format;
127  SDL_AudioFormat test_format = SDL_FirstAudioFormat(_this->spec.format);
128 
129  /* Initialize all variables that we clean on shutdown */
130  _this->hidden = new SDL_PrivateAudioData;
131  if (_this->hidden == NULL) {
132  return SDL_OutOfMemory();
133  }
134  SDL_zerop(_this->hidden);
135 
136  /* Parse the audio format and fill the Be raw audio format */
137  SDL_zero(format);
138  format.byte_order = B_MEDIA_LITTLE_ENDIAN;
139  format.frame_rate = (float) _this->spec.freq;
140  format.channel_count = _this->spec.channels; /* !!! FIXME: support > 2? */
141  while ((!valid_datatype) && (test_format)) {
142  valid_datatype = 1;
143  _this->spec.format = test_format;
144  switch (test_format) {
145  case AUDIO_S8:
146  format.format = media_raw_audio_format::B_AUDIO_CHAR;
147  break;
148 
149  case AUDIO_U8:
150  format.format = media_raw_audio_format::B_AUDIO_UCHAR;
151  break;
152 
153  case AUDIO_S16LSB:
154  format.format = media_raw_audio_format::B_AUDIO_SHORT;
155  break;
156 
157  case AUDIO_S16MSB:
158  format.format = media_raw_audio_format::B_AUDIO_SHORT;
159  format.byte_order = B_MEDIA_BIG_ENDIAN;
160  break;
161 
162  case AUDIO_S32LSB:
163  format.format = media_raw_audio_format::B_AUDIO_INT;
164  break;
165 
166  case AUDIO_S32MSB:
167  format.format = media_raw_audio_format::B_AUDIO_INT;
168  format.byte_order = B_MEDIA_BIG_ENDIAN;
169  break;
170 
171  case AUDIO_F32LSB:
172  format.format = media_raw_audio_format::B_AUDIO_FLOAT;
173  break;
174 
175  case AUDIO_F32MSB:
176  format.format = media_raw_audio_format::B_AUDIO_FLOAT;
177  format.byte_order = B_MEDIA_BIG_ENDIAN;
178  break;
179 
180  default:
181  valid_datatype = 0;
182  test_format = SDL_NextAudioFormat();
183  break;
184  }
185  }
186 
187  if (!valid_datatype) { /* shouldn't happen, but just in case... */
188  return SDL_SetError("Unsupported audio format");
189  }
190 
191  /* Calculate the final parameters for this audio specification */
193 
194  format.buffer_size = _this->spec.size;
195 
196  /* Subscribe to the audio stream (creates a new thread) */
197  sigset_t omask;
198  MaskSignals(&omask);
199  _this->hidden->audio_obj = new BSoundPlayer(&format, "SDL Audio",
200  FillSound, NULL, _this);
201  UnmaskSignals(&omask);
202 
203  if (_this->hidden->audio_obj->Start() == B_NO_ERROR) {
204  _this->hidden->audio_obj->SetHasData(true);
205  } else {
206  return SDL_SetError("Unable to start Be audio");
207  }
208 
209  /* We're running! */
210  return 0;
211 }
212 
213 static void
214 HAIKUAUDIO_Deinitialize(void)
215 {
216  SDL_QuitBeApp();
217 }
218 
219 static int
220 HAIKUAUDIO_Init(SDL_AudioDriverImpl * impl)
221 {
222  /* Initialize the Be Application, if it's not already started */
223  if (SDL_InitBeApp() < 0) {
224  return 0;
225  }
226 
227  /* Set the function pointers */
228  impl->OpenDevice = HAIKUAUDIO_OpenDevice;
229  impl->CloseDevice = HAIKUAUDIO_CloseDevice;
230  impl->Deinitialize = HAIKUAUDIO_Deinitialize;
231  impl->ProvidesOwnCallbackThread = 1;
232  impl->OnlyHasDefaultOutputDevice = 1;
233 
234  return 1; /* this audio target is available. */
235 }
236 
237 extern "C"
238 {
240 }
242  "haiku", "Haiku BSoundPlayer", HAIKUAUDIO_Init, 0
243 };
244 
245 #endif /* SDL_AUDIO_DRIVER_HAIKU */
246 
247 /* vi: set ts=4 sw=4 expandtab: */
int SDL_InitBeApp(void)
void SDL_QuitBeApp(void)
#define _THIS
#define SDL_assert(condition)
Definition: SDL_assert.h:171
void SDL_CalculateAudioSpec(SDL_AudioSpec *spec)
Definition: SDL_audio.c:1689
SDL_AudioFormat SDL_FirstAudioFormat(SDL_AudioFormat format)
Definition: SDL_audio.c:1650
SDL_AudioFormat SDL_NextAudioFormat(void)
Definition: SDL_audio.c:1662
#define AUDIO_S16LSB
Definition: SDL_audio.h:92
#define AUDIO_F32MSB
Definition: SDL_audio.h:113
#define AUDIO_S32MSB
Definition: SDL_audio.h:104
#define AUDIO_S16MSB
Definition: SDL_audio.h:94
Uint16 SDL_AudioFormat
Audio format flags.
Definition: SDL_audio.h:64
#define AUDIO_U8
Definition: SDL_audio.h:89
#define AUDIO_S8
Definition: SDL_audio.h:90
#define AUDIO_S32LSB
Definition: SDL_audio.h:103
#define AUDIO_F32LSB
Definition: SDL_audio.h:112
void(* SDL_AudioCallback)(void *userdata, Uint8 *stream, int len)
Definition: SDL_audio.h:163
#define SDL_AtomicSet
#define SDL_SetError
#define SDL_memset
#define SDL_AudioStreamGet
#define SDL_AudioStreamClear
#define SDL_LockMutex
#define SDL_AudioStreamAvailable
#define SDL_AudioStreamPut
#define SDL_AtomicGet
#define SDL_UnlockMutex
#define SDL_OutOfMemory()
Definition: SDL_error.h:88
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: SDL_opengl.h:1572
GLuint GLuint stream
GLenum GLsizei len
GLenum GLint GLuint mask
#define SDL_zero(x)
Definition: SDL_stdinc.h:426
uint8_t Uint8
Definition: SDL_stdinc.h:185
#define SDL_zerop(x)
Definition: SDL_stdinc.h:427
AudioBootStrap HAIKUAUDIO_bootstrap
static SDL_VideoDevice * _this
Definition: SDL_video.c:126
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
Definition: SDL_x11sym.h:50
#define NULL
Definition: begin_code.h:163
EGLImageKHR EGLint EGLint * handle
Definition: eglext.h:937
static SDL_AudioDeviceID device
Definition: loopwave.c:37
static const int sig_list[]
Definition: SDL_systhread.c:66
SDL_AudioSpec callbackspec
Definition: SDL_sysaudio.h:141
Uint8 * work_buffer
Definition: SDL_sysaudio.h:153
SDL_atomic_t enabled
Definition: SDL_sysaudio.h:148
SDL_AudioStream * stream
Definition: SDL_sysaudio.h:144
SDL_atomic_t paused
Definition: SDL_sysaudio.h:149
SDL_AudioSpec spec
Definition: SDL_sysaudio.h:138
SDL_mutex * mixer_lock
Definition: SDL_sysaudio.h:159
void(* CloseDevice)(_THIS)
Definition: SDL_sysaudio.h:78
void(* Deinitialize)(void)
Definition: SDL_sysaudio.h:82
int(* OpenDevice)(_THIS, void *handle, const char *devname, int iscapture)
Definition: SDL_sysaudio.h:68
Uint32 size
Definition: SDL_audio.h:186
SDL_AudioCallback callback
Definition: SDL_audio.h:187
Uint8 silence
Definition: SDL_audio.h:183
void * userdata
Definition: SDL_audio.h:188
static Uint32 callback(Uint32 interval, void *param)
Definition: testtimer.c:34
typedef int(__stdcall *FARPROC)()