00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #ifndef NO_SOUND
00031
00032 #include "oggplayer.h"
00033 #include <gccore.h>
00034 #include <unistd.h>
00035 #include <string.h>
00036
00037
00038
00039 static struct
00040 {
00041 char *mem;
00042 int size;
00043 int pos;
00044 } file[4];
00045
00046 static int f_read(void * punt, int bytes, int blocks, int *f)
00047 {
00048 int b;
00049 int c;
00050 int d;
00051
00052 if (bytes * blocks <= 0)
00053 return 0;
00054
00055 blocks = bytes * blocks;
00056 c = 0;
00057
00058 while (blocks > 0)
00059 {
00060 b = blocks;
00061 if (b > 4096)
00062 b = 4096;
00063
00064 if (*f >= 0x666 && *f <= 0x669)
00065 {
00066 d = (*f) - 0x666;
00067 if (file[d].size == 0)
00068 return -1;
00069 if ((file[d].pos + b) > file[d].size)
00070 b = file[d].size - file[d].pos;
00071 if (b > 0)
00072 {
00073 memcpy(punt, file[d].mem + file[d].pos, b);
00074 file[d].pos += b;
00075 }
00076 }
00077 else
00078 b = read(*f, ((char *) punt) + c, b);
00079
00080 if (b <= 0)
00081 {
00082 return c / bytes;
00083 }
00084 c += b;
00085 blocks -= b;
00086 }
00087 return c / bytes;
00088 }
00089
00090 static int f_seek(int *f, ogg_int64_t offset, int mode)
00091 {
00092 if(f==NULL) return(-1);
00093
00094 int k, d;
00095 mode &= 3;
00096 if (*f >= 0x666 && *f <= 0x669)
00097 {
00098 d = (*f) - 0x666;
00099 k = 0;
00100
00101 if (file[d].size == 0)
00102 return -1;
00103
00104 if (mode == 0)
00105 {
00106 if ((offset) >= file[d].size)
00107 {
00108 file[d].pos = file[d].size;
00109 k = -1;
00110 }
00111 else if ((offset) < 0)
00112 {
00113 file[d].pos = 0;
00114 k = -1;
00115 }
00116 else
00117 file[d].pos = offset;
00118 }
00119 if (mode == 1)
00120 {
00121 if ((file[d].pos + offset) >= file[d].size)
00122 {
00123 file[d].pos = file[d].size;
00124 k = -1;
00125 }
00126 else if ((file[d].pos + offset) < 0)
00127 {
00128 file[d].pos = 0;
00129 k = -1;
00130 }
00131 else
00132 file[d].pos += offset;
00133 }
00134 if (mode == 2)
00135 {
00136
00137 if ((file[d].size + offset) >= file[d].size)
00138 {
00139 file[d].pos = file[d].size;
00140 k = -1;
00141 }
00142 else if ((file[d].size + offset) < 0)
00143 {
00144 file[d].pos = 0;
00145 k = -1;
00146 }
00147 else
00148 file[d].pos = file[d].size + offset;
00149 }
00150
00151 }
00152 else
00153 k = lseek(*f, (int) offset, mode);
00154
00155 if (k < 0)
00156 k = -1;
00157 else
00158 k = 0;
00159 return k;
00160 }
00161
00162 static int f_close(int *f)
00163 {
00164 int d;
00165 if (*f >= 0x666 && *f <= 0x669)
00166 {
00167 d = (*f) - 0x666;
00168 file[d].size = 0;
00169 file[d].pos = 0;
00170 if (file[d].mem)
00171 {
00172 file[d].mem = (void *) 0;
00173 }
00174 return 0;
00175 }
00176 else
00177 return close(*f);
00178 return 0;
00179 }
00180
00181 static long f_tell(int *f)
00182 {
00183 int k, d;
00184
00185 if (*f >= 0x666 && *f <= 0x669)
00186 {
00187 d = (*f) - 0x666;
00188 k = file[d].pos;
00189 }
00190 else
00191 k = lseek(*f, 0, 1);
00192
00193 return (long) k;
00194 }
00195
00196 static int mem_open(char * ogg, int size)
00197 {
00198 static int one = 1;
00199 int n;
00200 if (one)
00201 {
00202 one = 0;
00203 for (n = 0; n < 4; n++)
00204 file[n].size = 0;
00205 }
00206
00207 for (n = 0; n < 4; n++)
00208 {
00209 if (file[n].size == 0)
00210 {
00211 file[n].mem = ogg;
00212 file[n].size = size;
00213 file[n].pos = 0;
00214 return (0x666 + n);
00215 }
00216 }
00217 return -1;
00218 }
00219
00220 static int mem_close(int fd)
00221 {
00222 if (fd >= 0x666 && fd <= 0x669)
00223 {
00224 fd -= 0x666;
00225 file[fd].size = 0;
00226 return 0;
00227 }
00228 else
00229 return f_close(&fd);
00230 }
00231
00232 static ov_callbacks callbacks = {
00233 (size_t (*)(void *, size_t, size_t, void *)) f_read,
00234 (int (*)(void *, ogg_int64_t, int)) f_seek,
00235 (int (*)(void *)) f_close,
00236 (long (*)(void *)) f_tell
00237 };
00238
00239
00240
00241 #define READ_SAMPLES 4096 // samples that it must read before to send
00242 #define MAX_PCMOUT 4096 // minimum size to read ogg samples
00243 typedef struct
00244 {
00245 OggVorbis_File vf;
00246 vorbis_info *vi;
00247 int current_section;
00248
00249
00250 int fd;
00251 int mode;
00252 int eof;
00253 int flag;
00254 int volume;
00255 int seek_time;
00256
00257
00258 short pcmout[2][READ_SAMPLES + MAX_PCMOUT * 2];
00259 int pcmout_pos;
00260 int pcm_indx;
00261
00262 } private_data_ogg;
00263
00264 static private_data_ogg private_ogg;
00265
00266
00267
00268 #define STACKSIZE 8192
00269
00270 static u8 oggplayer_stack[STACKSIZE];
00271 static lwpq_t oggplayer_queue = LWP_TQUEUE_NULL;
00272 static lwp_t h_oggplayer = LWP_THREAD_NULL;
00273 static int ogg_thread_running = 0;
00274
00275 static void ogg_add_callback(int voice)
00276 {
00277 if (!ogg_thread_running)
00278 {
00279 ASND_StopVoice(0);
00280 return;
00281 }
00282
00283 if (private_ogg.flag & 128)
00284 return;
00285
00286 if (private_ogg.pcm_indx >= READ_SAMPLES)
00287 {
00288 if (ASND_AddVoice(0,
00289 (void *) private_ogg.pcmout[private_ogg.pcmout_pos],
00290 private_ogg.pcm_indx << 1) == 0)
00291 {
00292 private_ogg.pcmout_pos ^= 1;
00293 private_ogg.pcm_indx = 0;
00294 private_ogg.flag = 0;
00295 LWP_ThreadSignal(oggplayer_queue);
00296 }
00297 }
00298 else
00299 {
00300 if (private_ogg.flag & 64)
00301 {
00302 private_ogg.flag &= ~64;
00303 LWP_ThreadSignal(oggplayer_queue);
00304 }
00305 }
00306 }
00307
00308 static void * ogg_player_thread(private_data_ogg * priv)
00309 {
00310 int first_time = 1;
00311 long ret;
00312
00313
00314 LWP_InitQueue(&oggplayer_queue);
00315
00316 priv[0].vi = ov_info(&priv[0].vf, -1);
00317
00318 ASND_Pause(0);
00319
00320 priv[0].pcm_indx = 0;
00321 priv[0].pcmout_pos = 0;
00322 priv[0].eof = 0;
00323 priv[0].flag = 0;
00324 priv[0].current_section = 0;
00325
00326 ogg_thread_running = 1;
00327
00328 while (!priv[0].eof && ogg_thread_running)
00329 {
00330 if (priv[0].flag)
00331 LWP_ThreadSleep(oggplayer_queue);
00332
00333 if (priv[0].flag == 0)
00334 {
00335 if (ASND_TestPointer(0, priv[0].pcmout[priv[0].pcmout_pos])
00336 && ASND_StatusVoice(0) != SND_UNUSED)
00337 {
00338 priv[0].flag |= 64;
00339 continue;
00340 }
00341 if (priv[0].pcm_indx < READ_SAMPLES)
00342 {
00343 priv[0].flag = 3;
00344
00345 if (priv[0].seek_time >= 0)
00346 {
00347 ov_time_seek(&priv[0].vf, priv[0].seek_time);
00348 priv[0].seek_time = -1;
00349 }
00350
00351 ret
00352 = ov_read(
00353 &priv[0].vf,
00354 (void *) &priv[0].pcmout[priv[0].pcmout_pos][priv[0].pcm_indx],
00355 MAX_PCMOUT,&priv[0].current_section);
00356 priv[0].flag &= 192;
00357 if (ret == 0)
00358 {
00359
00360 if (priv[0].mode & 1)
00361 ov_time_seek(&priv[0].vf, 0);
00362 else
00363 priv[0].eof = 1;
00364 }
00365 else if (ret < 0)
00366 {
00367
00368
00369 if (ret != OV_HOLE)
00370 {
00371 if (priv[0].mode & 1)
00372 ov_time_seek(&priv[0].vf, 0);
00373 else
00374 priv[0].eof = 1;
00375 }
00376 }
00377 else
00378 {
00379
00380
00381 priv[0].pcm_indx += ret >> 1;
00382 }
00383 }
00384 else
00385 priv[0].flag = 1;
00386 }
00387
00388 if (priv[0].flag == 1)
00389 {
00390 if (ASND_StatusVoice(0) == SND_UNUSED || first_time)
00391 {
00392 first_time = 0;
00393 if (priv[0].vi->channels == 2)
00394 {
00395 ASND_SetVoice(0, VOICE_STEREO_16BIT, priv[0].vi->rate, 0,
00396 (void *) priv[0].pcmout[priv[0].pcmout_pos],
00397 priv[0].pcm_indx << 1, priv[0].volume,
00398 priv[0].volume, ogg_add_callback);
00399 priv[0].pcmout_pos ^= 1;
00400 priv[0].pcm_indx = 0;
00401 priv[0].flag = 0;
00402 }
00403 else
00404 {
00405 ASND_SetVoice(0, VOICE_MONO_16BIT, priv[0].vi->rate, 0,
00406 (void *) priv[0].pcmout[priv[0].pcmout_pos],
00407 priv[0].pcm_indx << 1, priv[0].volume,
00408 priv[0].volume, ogg_add_callback);
00409 priv[0].pcmout_pos ^= 1;
00410 priv[0].pcm_indx = 0;
00411 priv[0].flag = 0;
00412 }
00413 }
00414 }
00415 usleep(100);
00416 }
00417 ov_clear(&priv[0].vf);
00418 priv[0].fd = -1;
00419 priv[0].pcm_indx = 0;
00420
00421 return 0;
00422 }
00423
00424 void StopOgg()
00425 {
00426 ASND_StopVoice(0);
00427 ogg_thread_running = 0;
00428
00429 if(h_oggplayer != LWP_THREAD_NULL)
00430 {
00431 if(oggplayer_queue != LWP_TQUEUE_NULL)
00432 LWP_ThreadSignal(oggplayer_queue);
00433 LWP_JoinThread(h_oggplayer, NULL);
00434 h_oggplayer = LWP_THREAD_NULL;
00435 }
00436 if(oggplayer_queue != LWP_TQUEUE_NULL)
00437 {
00438 LWP_CloseQueue(oggplayer_queue);
00439 oggplayer_queue = LWP_TQUEUE_NULL;
00440 }
00441 }
00442
00443 int PlayOgg(char * buf, int buflen, int time_pos, int mode)
00444 {
00445 StopOgg();
00446
00447 private_ogg.fd = mem_open(buf, buflen);
00448
00449 if (private_ogg.fd < 0)
00450 {
00451 private_ogg.fd = -1;
00452 return -1;
00453 }
00454
00455 private_ogg.mode = mode;
00456 private_ogg.eof = 0;
00457 private_ogg.volume = 127;
00458 private_ogg.flag = 0;
00459 private_ogg.seek_time = -1;
00460
00461 if (time_pos > 0)
00462 private_ogg.seek_time = time_pos;
00463
00464 if (ov_open_callbacks((void *) &private_ogg.fd, &private_ogg.vf, NULL, 0, callbacks) < 0)
00465 {
00466 mem_close(private_ogg.fd);
00467 private_ogg.fd = -1;
00468 ogg_thread_running = 0;
00469 return -1;
00470 }
00471
00472 if (LWP_CreateThread(&h_oggplayer, (void *) ogg_player_thread,
00473 &private_ogg, oggplayer_stack, STACKSIZE, 80) == -1)
00474 {
00475 ogg_thread_running = 0;
00476 ov_clear(&private_ogg.vf);
00477 private_ogg.fd = -1;
00478 return -1;
00479 }
00480 return 0;
00481 }
00482
00483 void PauseOgg(int pause)
00484 {
00485 if (pause)
00486 {
00487 private_ogg.flag |= 128;
00488 }
00489 else
00490 {
00491 if (private_ogg.flag & 128)
00492 {
00493 private_ogg.flag |= 64;
00494 private_ogg.flag &= ~128;
00495 if (ogg_thread_running > 0)
00496 {
00497 LWP_ThreadSignal(oggplayer_queue);
00498 }
00499 }
00500 }
00501 }
00502
00503 int StatusOgg()
00504 {
00505 if (ogg_thread_running == 0)
00506 return -1;
00507 else if (private_ogg.eof)
00508 return 255;
00509 else if (private_ogg.flag & 128)
00510 return 2;
00511 else
00512 return 1;
00513 }
00514
00515 void SetVolumeOgg(int volume)
00516 {
00517 private_ogg.volume = volume;
00518 ASND_ChangeVolumeVoice(0, volume, volume);
00519 }
00520
00521 s32 GetTimeOgg()
00522 {
00523 int ret;
00524 if (ogg_thread_running == 0 || private_ogg.fd < 0)
00525 return 0;
00526 ret = ((s32) ov_time_tell(&private_ogg.vf));
00527 if (ret < 0)
00528 ret = 0;
00529
00530 return ret;
00531 }
00532
00533 void SetTimeOgg(s32 time_pos)
00534 {
00535 if (time_pos >= 0)
00536 private_ogg.seek_time = time_pos;
00537 }
00538
00539 #endif