Subversion Repositories Kolibri OS

Rev

Rev 9202 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
8210 maxcodehac 1
#include "SDL_audio.h"
9288 turbocat 2
#include 
3
#include 
8210 maxcodehac 4
#include 
5
#include 
6
#include 
7
#include 
8
 
9
static void GetNotify(__u32* event)
10
{
11
        __asm__("int $0x40" :: "a"(68),"b"(14),"c"(event));
12
}
13
static int CreateThread(void* fn, char* p_stack)
14
{
15
        int res;
16
        __asm__("int $0x40" : "=a"(res) : "a"(51),"b"(1),"c"(fn),"d"(p_stack));
17
        return res;
18
}
19
static char pinfo[1024];
20
static int GetProcessInfo(int slot)
21
{
22
	int res;
23
	__asm__("int $0x40" : "=a"(res) : "a"(9),"b"(pinfo),"c"(slot));
24
	return res;
25
}
26
static void ActivateWnd(int slot)
27
{
28
	__asm__("int $0x40" :: "a"(18),"b"(3),"c"(slot));
29
}
30
static void Yield(void)
31
{
32
	__asm__("int $0x40" :: "a"(68),"b"(1));
33
}
34
 
35
static int bInitialized=0;
36
static SNDBUF hBuff=0;
37
static char* data=NULL;
38
static int audio_tid=0;
39
static int main_slot;
40
static __u32 main_tid;
41
static char audio_thread_stack[40960];
42
static __u32 used_format=0;
43
static volatile int mix_size=0;
44
 
45
static void (*callback)(void* userdata, Uint8* stream, int len);
46
static void* userdata;
47
 
48
int SDL_AudioInit(const char* driver_name)
49
{
50
	if (bInitialized)
51
	{
52
		SDL_SetError("audio already initialized");
53
		return -1;
54
	}
55
	int ver;
56
	if (InitSound(&ver))
57
	{
58
        	SDL_printf("Warning: cannot load drivers, sound output will be disabled\n");
59
        	return 0;
60
        }
61
        bInitialized = 1;
62
	return 0;
63
}
64
 
65
void SDL_AudioQuit(void)
66
{
67
}
68
 
69
char* SDL_AudioDriverName(char* namebuf, int maxlen)
70
{
71
        if (!bInitialized)
72
                return NULL;
73
        strncpy(namebuf,"KolibriAudio",maxlen);
74
        return namebuf;
75
}
76
 
77
#define AUDIO_SUSPEND 1
78
#define AUDIO_RESUME 2
79
#define AUDIO_DIE 3
80
static volatile int audio_command=0,audio_response=0,bLocked=0,bInCallback=0;
81
static void audio_thread(void)
82
{
83
	SDL_printf("audio_thread created\n");
84
        int bPaused;
85
        __u32 event[6];
86
        // initialize
87
        if (CreateBuffer(used_format|PCM_RING, 0, &hBuff))
88
        {
89
                audio_response=1;
8494 maxcodehac 90
                exit(0);
8210 maxcodehac 91
        }
92
        GetBufferSize(hBuff, &mix_size);
93
        SDL_printf("buffer created, size is %d\n",mix_size);
94
        mix_size >>= 1;
95
        data = malloc(mix_size);
96
        audio_response=1;
8494 maxcodehac 97
        if (!data) exit(0);
8210 maxcodehac 98
        // wait for resume
99
        while (audio_command!=AUDIO_RESUME)
100
                Yield();
101
        // initialize
102
/*        bInCallback=1;
103
        callback(userdata,data,mix_size);
104
        SetBuffer(hBuff,data,0,mix_size);
105
        callback(userdata,data,mix_size);
106
        SetBuffer(hBuff,data,mix_size,mix_size);
107
        bInCallback=0;*/
108
        audio_command=0;
109
        bPaused=0;
110
        audio_response=1;
111
        PlayBuffer(hBuff,0);
112
        // main loop
113
        for (;;)
114
        {
115
                if (audio_command==AUDIO_RESUME)
116
                {
117
                	PlayBuffer(hBuff,0);
118
                        audio_command = 0;
119
                        bPaused = 0;
120
                        audio_response = 1;
121
                }
122
                else if (audio_command==AUDIO_SUSPEND)
123
                {
124
                	StopBuffer(hBuff);
125
                        audio_command = 0;
126
                        bPaused = 1;
127
                        audio_response = 1;
128
                }
129
                else if (audio_command==AUDIO_DIE)
130
                {
131
                        audio_response = 1;
132
                        StopBuffer(hBuff);
133
                        DestroyBuffer(hBuff);
8494 maxcodehac 134
                        exit(0);
8210 maxcodehac 135
                }
136
                else
137
                {
138
                	GetProcessInfo(main_slot);
139
                	if (pinfo[0x32]==9 || *(__u32*)(pinfo+0x1E)!=main_tid)
140
                	{
141
                		audio_command = AUDIO_DIE;
142
                		continue;
143
                	}
144
                }
145
                if (bPaused)
9288 turbocat 146
                        delay(5);
8210 maxcodehac 147
                else
148
                {
149
                        GetNotify(event);
150
                        if (event[0] != 0xFF000001)
151
                        	continue;
152
                        while (bLocked)
153
                                Yield();
154
                        bInCallback=1;
155
                        callback(userdata,data,mix_size);
156
                        bInCallback=0;
157
                        SetBuffer(hBuff,data,event[3],mix_size);
158
                }
159
        }
160
}
161
 
162
int SDL_OpenAudio(SDL_AudioSpec* desired, SDL_AudioSpec* obtained)
163
{
164
        if (!bInitialized)
165
        {
166
                SDL_SetError("Audio device was not initialized");
167
                return -1;
168
        }
169
        if (!obtained)
170
        {
171
                SDL_SetError("Audio format: software emulation is not supported");
172
                return -1;
173
        }
174
        if (used_format)
175
        {
176
                SDL_SetError("Audio device was already opened");
177
                return -1;
178
        }
179
        memcpy(obtained,desired,sizeof(SDL_AudioSpec));
180
        switch (desired->freq)
181
        {
182
 
183
#define HANDLE_FREQ(freq,symb)                          \
184
        case freq:                                      \
185
                switch (desired->channels)              \
186
                {                                       \
187
                case 1:                                 \
188
                        switch (desired->format)        \
189
                        {                               \
190
                        case AUDIO_U8:                  \
191
                        case AUDIO_S8:                  \
192
                                used_format = PCM_1_8_##symb;   \
193
                                break;                  \
194
                        case AUDIO_U16SYS:              \
195
                        case AUDIO_S16SYS:              \
196
                                used_format = PCM_1_16_##symb;  \
197
                                break;                  \
198
                        }                               \
199
                        break;                          \
200
                case 2:                                 \
201
                        switch (desired->format)        \
202
                        {                               \
203
                        case AUDIO_U8:                  \
204
                        case AUDIO_S8:                  \
205
                                used_format = PCM_2_8_##symb;   \
206
                                break;                  \
207
                        case AUDIO_U16SYS:              \
208
                        case AUDIO_S16SYS:              \
209
                                used_format = PCM_2_16_##symb;  \
210
                                break;                  \
211
                        }                               \
212
                        break;                          \
213
                }                                       \
214
                break;
215
 
216
        HANDLE_FREQ(48000,48);
217
        HANDLE_FREQ(44100,44);
218
        HANDLE_FREQ(32000,32);
219
        HANDLE_FREQ(24000,24);
220
        HANDLE_FREQ(22050,22);
221
        HANDLE_FREQ(16000,16);
222
        HANDLE_FREQ(12000,12);
223
        HANDLE_FREQ(11025,11);
224
        HANDLE_FREQ(8000,8);
225
        }
226
        if (!used_format)
227
        {
228
                SDL_SetError("Unknown audio format");
229
                return -1;
230
        }
231
        callback=desired->callback;
232
        userdata=desired->userdata;
233
        GetProcessInfo(-1);
234
        main_tid = *(__u32*)(pinfo+0x1E);
235
        for (main_slot=0;;main_slot++)
236
        {
237
                GetProcessInfo(main_slot);
238
                if (pinfo[0x32]!=9 && *(__u32*)(pinfo+0x1E)==main_tid)
239
        	        break;
240
        }
241
        audio_tid=CreateThread(audio_thread,audio_thread_stack+40960);
242
        if (audio_tid<0)
243
        {
244
                SDL_SetError("Cannot create audio thread");
245
                return -1;
246
        }
247
        ActivateWnd(main_slot);
248
        while (!audio_response)
249
                Yield();
250
        if (!hBuff)
251
        {
252
                SDL_SetError("Cannot create audio buffer");
253
                return -1;
254
        }
255
        if (!data)
256
        {
257
                SDL_SetError("Cannot allocate audio buffer");
258
                return -1;
259
        }
260
        obtained->silence = (desired->format == AUDIO_U8 ? 0x80 : 0);
261
        obtained->size = mix_size;
262
        obtained->samples = obtained->size / obtained->channels;
263
        if (desired->format == AUDIO_U16SYS || desired->format == AUDIO_S16SYS)
264
                obtained->samples /= 2;
265
        SDL_printf("obtained size is %d, samples %d\n",obtained->size,
266
        obtained->samples);
267
        return 0;
268
}
269
void SDL_CloseAudio(void)
270
{
271
        if (!audio_tid) return;
272
        audio_response = 0;
273
        audio_command = AUDIO_DIE;
274
        while (!audio_response)
275
                Yield();
276
        free(data);
277
        used_format = 0;
278
}
279
 
280
void SDL_PauseAudio(int pause_on)
281
{
282
	if (!audio_tid) return;
283
        audio_response = 0;
284
        audio_command = pause_on?AUDIO_SUSPEND:AUDIO_RESUME;
285
        while (!audio_response)
286
                Yield();
287
}
288
void SDL_LockAudio(void)
289
{
290
	if (!audio_tid) return;
291
        bLocked = 1;
292
        while (bInCallback)
293
                Yield();
294
}
295
void SDL_UnlockAudio(void)
296
{
297
        bLocked = 0;
298
}