Subversion Repositories Kolibri OS

Rev

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