Subversion Repositories Kolibri OS

Rev

Rev 6347 | Go to most recent revision | Details | Last modification | View Log | RSS feed

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