Merge pull request #204 from jhasse/android-byte-order
[openal-soft.git] / Alc / backends / null.c
blob2c2db54ef05d42f02363f47993838d0cd648df7e
1 /**
2 * OpenAL cross platform audio library
3 * Copyright (C) 2010 by Chris Robinson
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 * Or go to http://www.gnu.org/copyleft/lgpl.html
21 #include "config.h"
23 #include <stdlib.h>
24 #ifdef HAVE_WINDOWS_H
25 #include <windows.h>
26 #endif
28 #include "alMain.h"
29 #include "alu.h"
30 #include "threads.h"
31 #include "compat.h"
33 #include "backends/base.h"
36 typedef struct ALCnullBackend {
37 DERIVE_FROM_TYPE(ALCbackend);
39 ATOMIC(int) killNow;
40 althrd_t thread;
41 } ALCnullBackend;
43 static int ALCnullBackend_mixerProc(void *ptr);
45 static void ALCnullBackend_Construct(ALCnullBackend *self, ALCdevice *device);
46 static DECLARE_FORWARD(ALCnullBackend, ALCbackend, void, Destruct)
47 static ALCenum ALCnullBackend_open(ALCnullBackend *self, const ALCchar *name);
48 static ALCboolean ALCnullBackend_reset(ALCnullBackend *self);
49 static ALCboolean ALCnullBackend_start(ALCnullBackend *self);
50 static void ALCnullBackend_stop(ALCnullBackend *self);
51 static DECLARE_FORWARD2(ALCnullBackend, ALCbackend, ALCenum, captureSamples, void*, ALCuint)
52 static DECLARE_FORWARD(ALCnullBackend, ALCbackend, ALCuint, availableSamples)
53 static DECLARE_FORWARD(ALCnullBackend, ALCbackend, ClockLatency, getClockLatency)
54 static DECLARE_FORWARD(ALCnullBackend, ALCbackend, void, lock)
55 static DECLARE_FORWARD(ALCnullBackend, ALCbackend, void, unlock)
56 DECLARE_DEFAULT_ALLOCATORS(ALCnullBackend)
58 DEFINE_ALCBACKEND_VTABLE(ALCnullBackend);
61 static const ALCchar nullDevice[] = "No Output";
64 static void ALCnullBackend_Construct(ALCnullBackend *self, ALCdevice *device)
66 ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
67 SET_VTABLE2(ALCnullBackend, ALCbackend, self);
69 ATOMIC_INIT(&self->killNow, AL_TRUE);
73 static int ALCnullBackend_mixerProc(void *ptr)
75 ALCnullBackend *self = (ALCnullBackend*)ptr;
76 ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
77 struct timespec now, start;
78 ALuint64 avail, done;
79 const long restTime = (long)((ALuint64)device->UpdateSize * 1000000000 /
80 device->Frequency / 2);
82 SetRTPriority();
83 althrd_setname(althrd_current(), MIXER_THREAD_NAME);
85 done = 0;
86 if(altimespec_get(&start, AL_TIME_UTC) != AL_TIME_UTC)
88 ERR("Failed to get starting time\n");
89 return 1;
91 while(!ATOMIC_LOAD(&self->killNow, almemory_order_acquire) &&
92 ATOMIC_LOAD(&device->Connected, almemory_order_acquire))
94 if(altimespec_get(&now, AL_TIME_UTC) != AL_TIME_UTC)
96 ERR("Failed to get current time\n");
97 return 1;
100 avail = (now.tv_sec - start.tv_sec) * device->Frequency;
101 avail += (ALint64)(now.tv_nsec - start.tv_nsec) * device->Frequency / 1000000000;
102 if(avail < done)
104 /* Oops, time skipped backwards. Reset the number of samples done
105 * with one update available since we (likely) just came back from
106 * sleeping. */
107 done = avail - device->UpdateSize;
110 if(avail-done < device->UpdateSize)
111 al_nssleep(restTime);
112 else while(avail-done >= device->UpdateSize)
114 ALCnullBackend_lock(self);
115 aluMixData(device, NULL, device->UpdateSize);
116 ALCnullBackend_unlock(self);
117 done += device->UpdateSize;
121 return 0;
125 static ALCenum ALCnullBackend_open(ALCnullBackend *self, const ALCchar *name)
127 ALCdevice *device;
129 if(!name)
130 name = nullDevice;
131 else if(strcmp(name, nullDevice) != 0)
132 return ALC_INVALID_VALUE;
134 device = STATIC_CAST(ALCbackend, self)->mDevice;
135 alstr_copy_cstr(&device->DeviceName, name);
137 return ALC_NO_ERROR;
140 static ALCboolean ALCnullBackend_reset(ALCnullBackend *self)
142 SetDefaultWFXChannelOrder(STATIC_CAST(ALCbackend, self)->mDevice);
143 return ALC_TRUE;
146 static ALCboolean ALCnullBackend_start(ALCnullBackend *self)
148 ATOMIC_STORE(&self->killNow, AL_FALSE, almemory_order_release);
149 if(althrd_create(&self->thread, ALCnullBackend_mixerProc, self) != althrd_success)
150 return ALC_FALSE;
151 return ALC_TRUE;
154 static void ALCnullBackend_stop(ALCnullBackend *self)
156 int res;
158 if(ATOMIC_EXCHANGE(&self->killNow, AL_TRUE, almemory_order_acq_rel))
159 return;
160 althrd_join(self->thread, &res);
164 typedef struct ALCnullBackendFactory {
165 DERIVE_FROM_TYPE(ALCbackendFactory);
166 } ALCnullBackendFactory;
167 #define ALCNULLBACKENDFACTORY_INITIALIZER { { GET_VTABLE2(ALCnullBackendFactory, ALCbackendFactory) } }
169 ALCbackendFactory *ALCnullBackendFactory_getFactory(void);
171 static ALCboolean ALCnullBackendFactory_init(ALCnullBackendFactory *self);
172 static DECLARE_FORWARD(ALCnullBackendFactory, ALCbackendFactory, void, deinit)
173 static ALCboolean ALCnullBackendFactory_querySupport(ALCnullBackendFactory *self, ALCbackend_Type type);
174 static void ALCnullBackendFactory_probe(ALCnullBackendFactory *self, enum DevProbe type);
175 static ALCbackend* ALCnullBackendFactory_createBackend(ALCnullBackendFactory *self, ALCdevice *device, ALCbackend_Type type);
176 DEFINE_ALCBACKENDFACTORY_VTABLE(ALCnullBackendFactory);
179 ALCbackendFactory *ALCnullBackendFactory_getFactory(void)
181 static ALCnullBackendFactory factory = ALCNULLBACKENDFACTORY_INITIALIZER;
182 return STATIC_CAST(ALCbackendFactory, &factory);
186 static ALCboolean ALCnullBackendFactory_init(ALCnullBackendFactory* UNUSED(self))
188 return ALC_TRUE;
191 static ALCboolean ALCnullBackendFactory_querySupport(ALCnullBackendFactory* UNUSED(self), ALCbackend_Type type)
193 if(type == ALCbackend_Playback)
194 return ALC_TRUE;
195 return ALC_FALSE;
198 static void ALCnullBackendFactory_probe(ALCnullBackendFactory* UNUSED(self), enum DevProbe type)
200 switch(type)
202 case ALL_DEVICE_PROBE:
203 AppendAllDevicesList(nullDevice);
204 break;
205 case CAPTURE_DEVICE_PROBE:
206 break;
210 static ALCbackend* ALCnullBackendFactory_createBackend(ALCnullBackendFactory* UNUSED(self), ALCdevice *device, ALCbackend_Type type)
212 if(type == ALCbackend_Playback)
214 ALCnullBackend *backend;
215 NEW_OBJ(backend, ALCnullBackend)(device);
216 if(!backend) return NULL;
217 return STATIC_CAST(ALCbackend, backend);
220 return NULL;