PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
audsrv_rpc.c
Go to the documentation of this file.
1/*
2# _____ ___ ____ ___ ____
3# ____| | ____| | | |____|
4# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
5#-----------------------------------------------------------------------
6# Copyright 2005, ps2dev - http://www.ps2dev.org
7# Licenced under GNU Library General Public License version 2
8# Review ps2sdk README & LICENSE files for further details.
9*/
10
16#include <stdio.h>
17#include <kernel.h>
18#include <sifrpc.h>
19#include <tamtypes.h>
20#include <string.h>
21#include <iopheap.h>
22
23#include <audsrv.h>
24#include "audsrv_rpc.h"
25
26#define MIN(a,b) ((a) <= (b)) ? (a) : (b)
27
28/* rpc mambo jambo */
29static struct t_SifRpcClientData cd0;
30static unsigned int sbuff[4096] __attribute__((aligned (64)));
31static struct t_SifRpcDataQueue cb_queue;
32static struct t_SifRpcServerData cb_srv;
33static unsigned char rpc_server_stack[0x1800] __attribute__((aligned (16)));
34
35extern void *_gp;
36
37static int initialized = 0;
38static int rpc_server_thread_id;
39static int audsrv_error = AUDSRV_ERR_NOERROR;
40static int completion_sema;
41
42static audsrv_callback_t on_cdda_stop = NULL;
43static void *on_cdda_stop_arg = NULL;
44
45static audsrv_callback_t on_fillbuf = NULL;
46static void *on_fillbuf_arg = NULL;
47
48static const unsigned short vol_values[26] =
49{
50 0x0000,
51 0x0000, 0x0096, 0x0190, 0x0230, 0x0320,
52 0x042E, 0x0532, 0x05FA, 0x06C2, 0x088E,
53 0x09F6, 0x0BC2, 0x0DC0, 0x0FF0, 0x118A,
54 0x1482, 0x1752, 0x1B4E, 0x1F40, 0x2378,
55 0x28D2, 0x2EFE, 0x34F8, 0x3A5C, 0x3FFF
56};
57
61static void set_error(int err)
62{
63 audsrv_error = err;
64}
65
67{
68 return audsrv_error;
69}
70
76static int call_rpc_1(int func, int arg)
77{
78 int ret;
79
80 WaitSema(completion_sema);
81
82 sbuff[0] = arg;
83 SifCallRpc(&cd0, func, 0, sbuff, 1*4, sbuff, 4, NULL, NULL);
84
85 ret = sbuff[0];
86 SignalSema(completion_sema);
87
88 set_error(ret);
89
90 return ret;
91}
92
99static int call_rpc_2(int func, int arg1, int arg2)
100{
101 int ret;
102
103 WaitSema(completion_sema);
104
105 sbuff[0] = arg1;
106 sbuff[1] = arg2;
107 SifCallRpc(&cd0, func, 0, sbuff, 2*4, sbuff, 4, NULL, NULL);
108
109 ret = sbuff[0];
110 SignalSema(completion_sema);
111
112 set_error(ret);
113
114 return ret;
115}
116
124static int call_rpc_3(int func, int arg1, int arg2, int arg3)
125{
126 int ret;
127
128 WaitSema(completion_sema);
129
130 sbuff[0] = arg1;
131 sbuff[1] = arg2;
132 sbuff[2] = arg3;
133 SifCallRpc(&cd0, func, 0, sbuff, 3*4, sbuff, 4, NULL, NULL);
134
135 ret = sbuff[0];
136 SignalSema(completion_sema);
137
138 set_error(ret);
139
140 return ret;
141}
142
144{
145 WaitSema(completion_sema);
146
147 SifCallRpc(&cd0, AUDSRV_QUIT, 0, sbuff, 1*4, sbuff, 4, NULL, NULL);
149
150 SifRemoveRpc(&cb_srv, &cb_queue);
151 SifRemoveRpcQueue(&cb_queue);
152 TerminateThread(rpc_server_thread_id);
153 DeleteThread(rpc_server_thread_id);
154
155 DeleteSema(completion_sema);
156 return 0;
157}
158
160{
161 int ret;
162
163 WaitSema(completion_sema);
164
165 sbuff[0] = fmt->freq;
166 sbuff[1] = fmt->bits;
167 sbuff[2] = fmt->channels;
168 SifCallRpc(&cd0, AUDSRV_SET_FORMAT, 0, sbuff, 3*4, sbuff, 4, NULL, NULL);
169
170 ret = sbuff[0];
171 SignalSema(completion_sema);
172
173 set_error(ret);
174
175 return ret;
176}
177
178int audsrv_wait_audio(int bytes)
179{
180 return call_rpc_1(AUDSRV_WAIT_AUDIO, bytes);
181}
182
183int audsrv_set_volume(int volume)
184{
185 if (volume > MAX_VOLUME)
186 {
187 volume = MAX_VOLUME;
188 }
189 else if (volume < MIN_VOLUME)
190 {
191 volume = MIN_VOLUME;
192 }
193
194 return call_rpc_1(AUDSRV_SET_VOLUME, vol_values[volume/4]);
195}
196
197int audsrv_play_cd(int track)
198{
199 return call_rpc_1(AUDSRV_PLAY_CD, track);
200}
201
202int audsrv_play_sectors(int start, int end)
203{
204 return call_rpc_2(AUDSRV_PLAY_SECTORS, start, end);
205}
206
208{
209 int ret;
210 ret = call_rpc_1(AUDSRV_STOP_CD, 0);
211 return ret;
212}
213
215{
216 return call_rpc_1(AUDSRV_GET_CDPOS, 0);
217}
218
220{
221 return call_rpc_1(AUDSRV_GET_TRACKPOS, 0);
222}
223
225{
226 return call_rpc_1(AUDSRV_GET_NUMTRACKS, 0);
227}
228
230{
231 return call_rpc_1(AUDSRV_GET_TRACKOFFSET, track);
232}
233
235{
236 return call_rpc_1(AUDSRV_PAUSE_CD, 0);
237}
238
240{
241 return call_rpc_1(AUDSRV_RESUME_CD, 0);
242}
243
245{
246 return call_rpc_1(AUDSRV_GET_CD_TYPE, 0);
247}
248
250{
251 return call_rpc_1(AUDSRV_GET_CD_STATUS, 0);
252}
253
254int audsrv_play_audio(const char *chunk, int bytes)
255{
256 int maxcopy;
257 int sent = 0;
258
260 maxcopy = sizeof(sbuff) - sizeof(int);
261 while (bytes > 0)
262 {
263 int copy, copied;
264 int packet_size;
265
266 WaitSema(completion_sema);
267
268 copy = MIN(bytes, maxcopy);
269 sbuff[0] = copy;
270 memcpy(&sbuff[1], chunk, copy);
271 packet_size = copy + sizeof(int);
272 SifCallRpc(&cd0, AUDSRV_PLAY_AUDIO, 0, sbuff, packet_size, sbuff, 1*4, NULL, NULL);
273
274 copied = sbuff[0];
275 SignalSema(completion_sema);
276
277 if (copied < 0)
278 {
279 /* there was an error */
280 set_error(-copied);
281 break;
282 }
283
284 chunk = chunk + copy;
285 bytes = bytes - copy;
286 sent = sent + copied;
287 }
288
289 return sent;
290}
291
293{
294 int ret;
295 ret = call_rpc_1(AUDSRV_STOP_AUDIO, 0);
296 return ret;
297}
298
299static void *audsrv_ee_rpc_handler(int fnum, void *buffer, int len)
300{
301 (void)len;
302
303 switch(fnum){
304 case AUDSRV_FILLBUF_CALLBACK:
305 if (on_fillbuf != NULL)
306 on_fillbuf(on_fillbuf_arg);
307 break;
308 case AUDSRV_CDDA_CALLBACK:
309 if (on_cdda_stop != NULL)
310 on_cdda_stop(on_cdda_stop_arg);
311 break;
312 }
313
314 return buffer;
315}
316
317static void rpc_server_thread(void *arg)
318{
319 static unsigned char cb_rpc_buffer[64] __attribute__((__aligned__(64)));
320
321 (void)arg;
322
323 SifSetRpcQueue(&cb_queue, GetThreadId());
324 SifRegisterRpc(&cb_srv, AUDSRV_IRX, &audsrv_ee_rpc_handler, cb_rpc_buffer, NULL, NULL, &cb_queue);
325 SifRpcLoop(&cb_queue);
326}
327
329{
330 ee_sema_t compSema;
331 ee_thread_t rpcThread;
332 int ret;
333
334 if (initialized)
335 {
336 /* already done */
337 return 0;
338 }
339
340 memset(&cd0, '\0', sizeof(cd0));
341
342 while (1)
343 {
344 if (SifBindRpc(&cd0, AUDSRV_IRX, 0) < 0)
345 {
346 set_error(AUDSRV_ERR_RPC_FAILED);
347 return -1;
348 }
349
350 if (cd0.server != 0)
351 {
352 break;
353 }
354
355 nopdelay();
356 }
357
358 compSema.init_count = 1;
359 compSema.max_count = 1;
360 compSema.option = 0;
361 completion_sema = CreateSema(&compSema);
362 if (completion_sema < 0)
363 {
364 set_error(AUDSRV_ERR_FAILED_TO_CREATE_SEMA);
365 return -1;
366 }
367
368 /* Create RPC server */
369 rpcThread.attr = 0;
370 rpcThread.option = 0;
371 rpcThread.func = &rpc_server_thread;
372 rpcThread.stack = rpc_server_stack;
373 rpcThread.stack_size = sizeof(rpc_server_stack);
374 rpcThread.gp_reg = &_gp;
375 rpcThread.initial_priority = 0x60;
376 rpc_server_thread_id = CreateThread(&rpcThread);
377 StartThread(rpc_server_thread_id, NULL);
378
379 SifCallRpc(&cd0, AUDSRV_INIT, 0, sbuff, 64, sbuff, 64, NULL, NULL);
380 ret = sbuff[0];
381 if (ret != 0)
382 {
383 set_error(ret);
384 return ret;
385 }
386
387 /* initialize IOP heap (for adpcm samples) */
388 SifInitIopHeap();
389
391 return AUDSRV_ERR_NOERROR;
392}
393
395{
396 return call_rpc_1(AUDSRV_INIT_ADPCM, 0);
397}
398
399int audsrv_adpcm_set_volume_and_pan(int ch, int volume, int pan)
400{
401 if (volume > MAX_VOLUME)
402 {
403 volume = MAX_VOLUME;
404 }
405 else if (volume < MIN_VOLUME)
406 {
407 volume = MIN_VOLUME;
408 }
409
410 if (pan > 100)
411 {
412 pan = 100;
413 }
414 else if (pan < -100)
415 {
416 pan = -100;
417 }
418
419 int volumel = volume;
420 int volumer = volume;
421
422 if (pan < 0)
423 volumer = volumer * (100 + pan) / 100;
424 else if (pan > 0)
425 volumel = volumel * (100 - pan) / 100;
426
427 return call_rpc_3(AUDSRV_ADPCM_SET_VOLUME, ch, vol_values[volumel/4], vol_values[volumer/4]);
428}
429
430int audsrv_load_adpcm(audsrv_adpcm_t *adpcm, void *buffer, int size)
431{
432 void* iop_addr;
433 SifDmaTransfer_t sifdma;
434 int id, ret;
435
436 iop_addr = SifAllocIopHeap(size);
437 if (iop_addr == 0)
438 {
439 return -AUDSRV_ERR_OUT_OF_MEMORY;
440 }
441
442 sifdma.src = buffer;
443 sifdma.dest = iop_addr;
444 sifdma.size = size;
445 sifdma.attr = 0;
446
447 /* send by dma */
448 while((id = SifSetDma(&sifdma, 1)) == 0);
449 while(SifDmaStat(id) >= 0);
450
451 WaitSema(completion_sema);
452
453 sbuff[0] = (int)iop_addr;
454 sbuff[1] = size;
455 sbuff[2] = (int)adpcm; /* use as id */
456
457 SifCallRpc(&cd0, AUDSRV_LOAD_ADPCM, 0, sbuff, 12, sbuff, 16, NULL, NULL);
458
459 if(sbuff[0] != 0)
460 {
461 adpcm->buffer = 0;
462 ret = sbuff[0];
463 }
464 else
465 {
466 adpcm->buffer = buffer;
467 adpcm->size = size;
468 adpcm->pitch = sbuff[1];
469 adpcm->loop = sbuff[2];
470 adpcm->channels = sbuff[3];
471 ret = AUDSRV_ERR_NOERROR;
472 }
473
474 SignalSema(completion_sema);
475
476 SifFreeIopHeap(iop_addr);
477
478 return ret;
479}
480
482{
483 /* on iop side, the sample id is like the pointer on ee side */
484 return call_rpc_2(AUDSRV_PLAY_ADPCM, ch, (u32)adpcm);
485}
486
488{
489 return call_rpc_2(AUDSRV_IS_ADPCM_PLAYING, ch, (u32)adpcm);
490}
491
493{
494 /* on iop side, the sample id is like the pointer on ee side */
495 return call_rpc_1(AUDSRV_FREE_ADPCM, (u32)adpcm);
496}
497
499{
500 switch(audsrv_get_error())
501 {
503 return "No error";
504
505 case AUDSRV_ERR_NOT_INITIALIZED:
506 return "Not initialized";
507
508 case AUDSRV_ERR_OUT_OF_MEMORY:
509 return "Out of IOP memory";
510
511 case AUDSRV_ERR_RPC_FAILED:
512 return "RPC operation failed";
513
514 case AUDSRV_ERR_FORMAT_NOT_SUPPORTED:
515 return "Format not supported";
516
517 case AUDSRV_ERR_NO_DISC:
518 return "No disc in drive";
519 }
520
521 return "Unknown error";
522}
523
524int audsrv_on_cdda_stop(audsrv_callback_t cb, void *arg)
525{
526 on_cdda_stop = cb;
527 on_cdda_stop_arg = arg;
528 return AUDSRV_ERR_NOERROR;
529}
530
531int audsrv_on_fillbuf(int amount, audsrv_callback_t cb, void *arg)
532{
533 int err;
534
535 on_fillbuf = 0;
536 on_fillbuf_arg = 0;
537
538 err = call_rpc_1(AUDSRV_SET_THRESHOLD, amount);
539 if (err != 0)
540 {
541 return err;
542 }
543
544 on_fillbuf = cb;
545 on_fillbuf_arg = arg;
546 return AUDSRV_ERR_NOERROR;
547}
548
550{
551 return call_rpc_1(AUDSRV_AVAILABLE, 0);
552}
553
555{
556 return call_rpc_1(AUDSRV_QUEUED, 0);
557}
558
int audsrv_queued()
Definition audsrv_rpc.c:554
int audsrv_play_sectors(int start, int end)
Definition audsrv_rpc.c:202
int audsrv_get_numtracks()
Definition audsrv_rpc.c:224
static int call_rpc_2(int func, int arg1, int arg2)
Definition audsrv_rpc.c:99
int audsrv_is_adpcm_playing(int ch, audsrv_adpcm_t *adpcm)
Definition audsrv_rpc.c:487
int audsrv_get_error()
Definition audsrv_rpc.c:66
int audsrv_resume_cd()
Definition audsrv_rpc.c:239
int audsrv_init()
Definition audsrv_rpc.c:328
int audsrv_pause_cd()
Definition audsrv_rpc.c:234
static int call_rpc_1(int func, int arg)
Definition audsrv_rpc.c:76
int audsrv_adpcm_set_volume_and_pan(int ch, int volume, int pan)
Definition audsrv_rpc.c:399
int audsrv_get_cd_type()
Definition audsrv_rpc.c:244
static int call_rpc_3(int func, int arg1, int arg2, int arg3)
Definition audsrv_rpc.c:124
int audsrv_play_audio(const char *chunk, int bytes)
Definition audsrv_rpc.c:254
int audsrv_on_cdda_stop(audsrv_callback_t cb, void *arg)
Definition audsrv_rpc.c:524
int audsrv_adpcm_init()
Definition audsrv_rpc.c:394
int audsrv_stop_audio()
Definition audsrv_rpc.c:292
int audsrv_ch_play_adpcm(int ch, audsrv_adpcm_t *adpcm)
Definition audsrv_rpc.c:481
int audsrv_play_cd(int track)
Definition audsrv_rpc.c:197
int audsrv_available()
Definition audsrv_rpc.c:549
int audsrv_get_trackpos()
Definition audsrv_rpc.c:219
int audsrv_load_adpcm(audsrv_adpcm_t *adpcm, void *buffer, int size)
Definition audsrv_rpc.c:430
const char * audsrv_get_error_string()
Definition audsrv_rpc.c:498
int audsrv_set_volume(int volume)
Definition audsrv_rpc.c:183
int audsrv_get_cdpos()
Definition audsrv_rpc.c:214
int audsrv_free_adpcm(audsrv_adpcm_t *adpcm)
Definition audsrv_rpc.c:492
int audsrv_stop_cd()
Definition audsrv_rpc.c:207
int audsrv_on_fillbuf(int amount, audsrv_callback_t cb, void *arg)
Definition audsrv_rpc.c:531
int audsrv_wait_audio(int bytes)
Definition audsrv_rpc.c:178
static void set_error(int err)
Definition audsrv_rpc.c:61
int audsrv_get_track_offset(int track)
Definition audsrv_rpc.c:229
int audsrv_set_format(struct audsrv_fmt_t *fmt)
Definition audsrv_rpc.c:159
int audsrv_get_cd_status()
Definition audsrv_rpc.c:249
int audsrv_quit()
Definition audsrv_rpc.c:143
#define AUDSRV_INIT_ADPCM
Definition audsrv_rpc.h:50
#define AUDSRV_PLAY_CD
Definition audsrv_rpc.h:37
#define AUDSRV_INIT
Definition audsrv_rpc.h:20
#define AUDSRV_ERR_NOERROR
Definition audsrv.h:28
#define MAX_VOLUME
Definition audsrv.h:25
#define MIN_VOLUME
Definition audsrv.h:22
int channels
Definition audsrv.h:48