Rename al_string_* functions to alstr_*
[openal-soft.git] / Alc / backends / null.c
blobe8c43782996965a5655f5379d0b9cef9d8855664
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 volatile 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 void ALCnullBackend_close(ALCnullBackend *self);
49 static ALCboolean ALCnullBackend_reset(ALCnullBackend *self);
50 static ALCboolean ALCnullBackend_start(ALCnullBackend *self);
51 static void ALCnullBackend_stop(ALCnullBackend *self);
52 static DECLARE_FORWARD2(ALCnullBackend, ALCbackend, ALCenum, captureSamples, void*, ALCuint)
53 static DECLARE_FORWARD(ALCnullBackend, ALCbackend, ALCuint, availableSamples)
54 static DECLARE_FORWARD(ALCnullBackend, ALCbackend, ClockLatency, getClockLatency)
55 static DECLARE_FORWARD(ALCnullBackend, ALCbackend, void, lock)
56 static DECLARE_FORWARD(ALCnullBackend, ALCbackend, void, unlock)
57 DECLARE_DEFAULT_ALLOCATORS(ALCnullBackend)
59 DEFINE_ALCBACKEND_VTABLE(ALCnullBackend);
62 static const ALCchar nullDevice[] = "No Output";
65 static void ALCnullBackend_Construct(ALCnullBackend *self, ALCdevice *device)
67 ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
68 SET_VTABLE2(ALCnullBackend, ALCbackend, self);
72 static int ALCnullBackend_mixerProc(void *ptr)
74 ALCnullBackend *self = (ALCnullBackend*)ptr;
75 ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
76 struct timespec now, start;
77 ALuint64 avail, done;
78 const long restTime = (long)((ALuint64)device->UpdateSize * 1000000000 /
79 device->Frequency / 2);
81 SetRTPriority();
82 althrd_setname(althrd_current(), MIXER_THREAD_NAME);
84 done = 0;
85 if(altimespec_get(&start, AL_TIME_UTC) != AL_TIME_UTC)
87 ERR("Failed to get starting time\n");
88 return 1;
90 while(!self->killNow && device->Connected)
92 if(altimespec_get(&now, AL_TIME_UTC) != AL_TIME_UTC)
94 ERR("Failed to get current time\n");
95 return 1;
98 avail = (now.tv_sec - start.tv_sec) * device->Frequency;
99 avail += (ALint64)(now.tv_nsec - start.tv_nsec) * device->Frequency / 1000000000;
100 if(avail < done)
102 /* Oops, time skipped backwards. Reset the number of samples done
103 * with one update available since we (likely) just came back from
104 * sleeping. */
105 done = avail - device->UpdateSize;
108 if(avail-done < device->UpdateSize)
109 al_nssleep(restTime);
110 else while(avail-done >= device->UpdateSize)
112 ALCnullBackend_lock(self);
113 aluMixData(device, NULL, device->UpdateSize);
114 ALCnullBackend_unlock(self);
115 done += device->UpdateSize;
119 return 0;
123 static ALCenum ALCnullBackend_open(ALCnullBackend *self, const ALCchar *name)
125 ALCdevice *device;
127 if(!name)
128 name = nullDevice;
129 else if(strcmp(name, nullDevice) != 0)
130 return ALC_INVALID_VALUE;
132 device = STATIC_CAST(ALCbackend, self)->mDevice;
133 alstr_copy_cstr(&device->DeviceName, name);
135 return ALC_NO_ERROR;
138 static void ALCnullBackend_close(ALCnullBackend* UNUSED(self))
142 static ALCboolean ALCnullBackend_reset(ALCnullBackend *self)
144 SetDefaultWFXChannelOrder(STATIC_CAST(ALCbackend, self)->mDevice);
145 return ALC_TRUE;
148 static ALCboolean ALCnullBackend_start(ALCnullBackend *self)
150 self->killNow = 0;
151 if(althrd_create(&self->thread, ALCnullBackend_mixerProc, self) != althrd_success)
152 return ALC_FALSE;
153 return ALC_TRUE;
156 static void ALCnullBackend_stop(ALCnullBackend *self)
158 int res;
160 if(self->killNow)
161 return;
163 self->killNow = 1;
164 althrd_join(self->thread, &res);
168 typedef struct ALCnullBackendFactory {
169 DERIVE_FROM_TYPE(ALCbackendFactory);
170 } ALCnullBackendFactory;
171 #define ALCNULLBACKENDFACTORY_INITIALIZER { { GET_VTABLE2(ALCnullBackendFactory, ALCbackendFactory) } }
173 ALCbackendFactory *ALCnullBackendFactory_getFactory(void);
175 static ALCboolean ALCnullBackendFactory_init(ALCnullBackendFactory *self);
176 static DECLARE_FORWARD(ALCnullBackendFactory, ALCbackendFactory, void, deinit)
177 static ALCboolean ALCnullBackendFactory_querySupport(ALCnullBackendFactory *self, ALCbackend_Type type);
178 static void ALCnullBackendFactory_probe(ALCnullBackendFactory *self, enum DevProbe type);
179 static ALCbackend* ALCnullBackendFactory_createBackend(ALCnullBackendFactory *self, ALCdevice *device, ALCbackend_Type type);
180 DEFINE_ALCBACKENDFACTORY_VTABLE(ALCnullBackendFactory);
183 ALCbackendFactory *ALCnullBackendFactory_getFactory(void)
185 static ALCnullBackendFactory factory = ALCNULLBACKENDFACTORY_INITIALIZER;
186 return STATIC_CAST(ALCbackendFactory, &factory);
190 static ALCboolean ALCnullBackendFactory_init(ALCnullBackendFactory* UNUSED(self))
192 return ALC_TRUE;
195 static ALCboolean ALCnullBackendFactory_querySupport(ALCnullBackendFactory* UNUSED(self), ALCbackend_Type type)
197 if(type == ALCbackend_Playback)
198 return ALC_TRUE;
199 return ALC_FALSE;
202 static void ALCnullBackendFactory_probe(ALCnullBackendFactory* UNUSED(self), enum DevProbe type)
204 switch(type)
206 case ALL_DEVICE_PROBE:
207 AppendAllDevicesList(nullDevice);
208 break;
209 case CAPTURE_DEVICE_PROBE:
210 break;
214 static ALCbackend* ALCnullBackendFactory_createBackend(ALCnullBackendFactory* UNUSED(self), ALCdevice *device, ALCbackend_Type type)
216 if(type == ALCbackend_Playback)
218 ALCnullBackend *backend;
219 NEW_OBJ(backend, ALCnullBackend)(device);
220 if(!backend) return NULL;
221 return STATIC_CAST(ALCbackend, backend);
224 return NULL;