2006-03-20 17:12:09 +00:00
/*
*
* SDL CD Audio functions
*
*
*/
# include <stdio.h>
# include <stdlib.h>
2013-06-30 02:22:56 +00:00
# include <SDL.h>
2006-03-20 17:12:09 +00:00
# ifdef __linux__
# include <sys/ioctl.h>
# include <linux/cdrom.h>
# endif
# include "pstypes.h"
2012-07-07 18:35:06 +00:00
# include "dxxerror.h"
2006-03-20 17:12:09 +00:00
# include "args.h"
# include "rbaudio.h"
2008-04-06 20:23:28 +00:00
# include "console.h"
2009-03-03 12:55:27 +00:00
# include "timer.h"
2006-03-20 17:12:09 +00:00
2010-08-19 15:54:19 +00:00
# define REDBOOK_VOLUME_SCALE 255
2006-03-20 17:12:09 +00:00
static SDL_CD * s_cd = NULL ;
static int initialised = 0 ;
void RBAExit ( )
{
2008-06-15 08:50:05 +00:00
if ( s_cd )
2006-03-20 17:12:09 +00:00
{
SDL_CDStop ( s_cd ) ;
SDL_CDClose ( s_cd ) ;
}
}
void RBAInit ( )
{
2008-06-15 08:50:05 +00:00
int num_cds ;
int i , j ;
2006-03-20 17:12:09 +00:00
if ( initialised ) return ;
if ( SDL_Init ( SDL_INIT_CDROM ) < 0 )
{
2013-04-22 10:37:59 +00:00
Warning ( " RBAudio: SDL library initialisation failed: %s. " , SDL_GetError ( ) ) ;
2006-03-20 17:12:09 +00:00
return ;
}
2008-05-28 10:38:30 +00:00
num_cds = SDL_CDNumDrives ( ) ;
if ( num_cds < 1 )
{
2013-04-22 10:37:59 +00:00
con_printf ( CON_NORMAL , " RBAudio: No cdrom drives found! \n " ) ;
2008-06-15 08:50:05 +00:00
# if defined(__APPLE__) || defined(macintosh)
SDL_QuitSubSystem ( SDL_INIT_CDROM ) ; // necessary for rescanning CDROMs
# endif
2008-05-28 10:38:30 +00:00
return ;
}
for ( i = 0 ; i < num_cds ; i + + )
{
2008-06-15 08:50:05 +00:00
if ( s_cd )
SDL_CDClose ( s_cd ) ;
2008-05-28 10:38:30 +00:00
s_cd = SDL_CDOpen ( i ) ;
if ( s_cd & & CD_INDRIVE ( SDL_CDStatus ( s_cd ) ) )
{
for ( j = 0 ; j < s_cd - > numtracks ; j + + )
{
if ( s_cd - > track [ j ] . type = = SDL_AUDIO_TRACK )
break ;
}
if ( j ! = s_cd - > numtracks )
break ; // we've found an audio CD
}
2008-06-15 08:50:05 +00:00
else if ( s_cd = = NULL )
2013-04-22 10:37:59 +00:00
Warning ( " RBAudio: Could not open cdrom %i for redbook audio:%s \n " , i , SDL_GetError ( ) ) ;
2008-05-28 10:38:30 +00:00
}
2008-06-15 08:50:05 +00:00
2008-05-28 10:38:30 +00:00
if ( i = = num_cds )
{
2013-04-22 10:37:59 +00:00
con_printf ( CON_NORMAL , " RBAudio: No audio CDs found \n " ) ;
2008-06-15 08:50:05 +00:00
if ( s_cd ) // if there's no audio CD, say that there's no redbook and hence play MIDI instead
{
SDL_CDClose ( s_cd ) ;
s_cd = NULL ;
}
# if defined(__APPLE__) || defined(macintosh)
SDL_QuitSubSystem ( SDL_INIT_CDROM ) ; // necessary for rescanning CDROMs
# endif
2008-05-28 10:38:30 +00:00
return ;
}
2008-06-15 08:50:05 +00:00
initialised = 1 ;
2013-04-22 10:37:59 +00:00
RBAList ( ) ;
2008-06-15 08:50:05 +00:00
}
int RBAEnabled ( )
{
return initialised ;
2006-03-20 17:12:09 +00:00
}
int RBAPlayTrack ( int a )
{
2008-06-15 08:50:05 +00:00
if ( ! s_cd ) return - 1 ;
2006-03-20 17:12:09 +00:00
if ( CD_INDRIVE ( SDL_CDStatus ( s_cd ) ) ) {
2010-04-05 11:54:23 +00:00
if ( SDL_CDPlayTracks ( s_cd , a - 1 , 0 , 0 , 0 ) = = 0 )
2013-04-22 10:37:59 +00:00
{
con_printf ( CON_VERBOSE , " RBAudio: Playing track %i \n " , a ) ;
2010-04-05 11:54:23 +00:00
return a ;
2013-04-22 10:37:59 +00:00
}
2006-03-20 17:12:09 +00:00
}
2010-04-05 11:54:23 +00:00
return - 1 ;
2006-03-20 17:12:09 +00:00
}
2013-06-30 20:59:51 +00:00
static void ( * redbook_finished_hook ) ( ) = NULL ;
2009-03-03 12:55:27 +00:00
2006-03-20 17:12:09 +00:00
void RBAStop ( )
{
2008-06-15 08:50:05 +00:00
if ( ! s_cd ) return ;
2006-03-20 17:12:09 +00:00
SDL_CDStop ( s_cd ) ;
2009-03-03 12:55:27 +00:00
redbook_finished_hook = NULL ; // no calling the finished hook - stopped means stopped here
2013-04-22 10:37:59 +00:00
con_printf ( CON_VERBOSE , " RBAudio: Playback stopped \n " ) ;
2006-03-20 17:12:09 +00:00
}
2008-06-15 08:50:05 +00:00
void RBAEjectDisk ( )
{
if ( ! s_cd ) return ;
SDL_CDEject ( s_cd ) ; // play nothing until it tries to load a song
# if defined(__APPLE__) || defined(macintosh)
SDL_QuitSubSystem ( SDL_INIT_CDROM ) ; // necessary for rescanning CDROMs
# endif
initialised = 0 ;
}
2006-03-20 17:12:09 +00:00
void RBASetVolume ( int volume )
{
# ifdef __linux__
int cdfile , level ;
struct cdrom_volctrl volctrl ;
2008-06-15 08:50:05 +00:00
if ( ! s_cd ) return ;
2006-03-20 17:12:09 +00:00
cdfile = s_cd - > id ;
2010-08-19 15:54:19 +00:00
level = volume * REDBOOK_VOLUME_SCALE / 8 ;
2006-03-20 17:12:09 +00:00
2010-08-19 15:54:19 +00:00
if ( ( level < 0 ) | | ( level > REDBOOK_VOLUME_SCALE ) ) {
2013-04-22 10:37:59 +00:00
con_printf ( CON_CRITICAL , " RBAudio: illegal volume value (allowed values 0-%i) \n " , REDBOOK_VOLUME_SCALE ) ;
2006-03-20 17:12:09 +00:00
return ;
}
volctrl . channel0
= volctrl . channel1
= volctrl . channel2
= volctrl . channel3
= level ;
if ( ioctl ( cdfile , CDROMVOLCTRL , & volctrl ) = = - 1 ) {
2013-04-22 10:37:59 +00:00
con_printf ( CON_CRITICAL , " RBAudio: CDROMVOLCTRL ioctl failed \n " ) ;
2006-03-20 17:12:09 +00:00
return ;
}
# endif
}
void RBAPause ( )
{
2008-06-15 08:50:05 +00:00
if ( ! s_cd ) return ;
2006-03-20 17:12:09 +00:00
SDL_CDPause ( s_cd ) ;
2013-04-22 10:37:59 +00:00
con_printf ( CON_VERBOSE , " RBAudio: Playback paused \n " ) ;
2006-03-20 17:12:09 +00:00
}
int RBAResume ( )
{
2008-06-15 08:50:05 +00:00
if ( ! s_cd ) return - 1 ;
2006-03-20 17:12:09 +00:00
SDL_CDResume ( s_cd ) ;
2013-04-22 10:37:59 +00:00
con_printf ( CON_VERBOSE , " RBAudio: Playback resumed \n " ) ;
2006-03-20 17:12:09 +00:00
return 1 ;
}
2008-06-15 08:50:05 +00:00
int RBAPauseResume ( )
{
if ( ! s_cd ) return 0 ;
if ( SDL_CDStatus ( s_cd ) = = CD_PLAYING )
2013-04-22 10:37:59 +00:00
{
2008-06-15 08:50:05 +00:00
SDL_CDPause ( s_cd ) ;
2013-04-22 10:37:59 +00:00
con_printf ( CON_VERBOSE , " RBAudio: Toggle Playback pause \n " ) ;
}
2008-06-15 08:50:05 +00:00
else if ( SDL_CDStatus ( s_cd ) = = CD_PAUSED )
2013-04-22 10:37:59 +00:00
{
2008-06-15 08:50:05 +00:00
SDL_CDResume ( s_cd ) ;
2013-04-22 10:37:59 +00:00
con_printf ( CON_VERBOSE , " RBAudio: Toggle Playback resume \n " ) ;
}
2008-06-15 08:50:05 +00:00
else
return 0 ;
return 1 ;
}
2006-03-20 17:12:09 +00:00
int RBAGetNumberOfTracks ( )
{
2008-06-15 08:50:05 +00:00
if ( ! s_cd ) return - 1 ;
2006-03-20 17:12:09 +00:00
SDL_CDStatus ( s_cd ) ;
2013-04-22 10:37:59 +00:00
con_printf ( CON_VERBOSE , " RBAudio: Found %i tracks on CD \n " , s_cd - > numtracks ) ;
2006-03-20 17:12:09 +00:00
return s_cd - > numtracks ;
}
2009-03-03 12:55:27 +00:00
// check if we need to call the 'finished' hook
// needs to go in all event loops
// a real hook would be ideal, but is currently unsupported by SDL Audio CD
void RBACheckFinishedHook ( )
{
2011-07-16 14:02:22 +00:00
static fix64 last_check_time = 0 ;
2009-03-03 12:55:27 +00:00
if ( ! s_cd ) return ;
2010-12-10 23:18:17 +00:00
if ( ( timer_query ( ) - last_check_time ) > = F2_0 )
2009-03-03 12:55:27 +00:00
{
if ( ( SDL_CDStatus ( s_cd ) = = CD_STOPPED ) & & redbook_finished_hook )
2013-04-22 10:37:59 +00:00
{
con_printf ( CON_VERBOSE , " RBAudio: Playback done, calling finished-hook \n " ) ;
2009-03-03 12:55:27 +00:00
redbook_finished_hook ( ) ;
2013-04-22 10:37:59 +00:00
}
2010-12-10 23:18:17 +00:00
last_check_time = timer_query ( ) ;
2009-03-03 12:55:27 +00:00
}
}
2006-03-20 17:12:09 +00:00
// plays tracks first through last, inclusive
2009-03-03 12:55:27 +00:00
int RBAPlayTracks ( int first , int last , void ( * hook_finished ) ( void ) )
2006-03-20 17:12:09 +00:00
{
2008-06-15 08:50:05 +00:00
if ( ! s_cd )
2006-03-20 17:12:09 +00:00
return 0 ;
if ( CD_INDRIVE ( SDL_CDStatus ( s_cd ) ) )
{
2009-03-03 12:55:27 +00:00
redbook_finished_hook = hook_finished ;
2013-04-22 10:37:59 +00:00
con_printf ( CON_VERBOSE , " RBAudio: Playing tracks %i to %i \n " , first , last ) ;
2010-04-05 11:54:23 +00:00
return SDL_CDPlayTracks ( s_cd , first - 1 , 0 , last - first + 1 , 0 ) = = 0 ;
2006-03-20 17:12:09 +00:00
}
2010-04-05 11:54:23 +00:00
return 0 ;
2006-03-20 17:12:09 +00:00
}
// return the track number currently playing. Useful if RBAPlayTracks()
// is called. Returns 0 if no track playing, else track number
int RBAGetTrackNum ( )
{
2008-06-15 08:50:05 +00:00
if ( ! s_cd )
2006-03-20 17:12:09 +00:00
return 0 ;
if ( SDL_CDStatus ( s_cd ) ! = CD_PLAYING )
return 0 ;
return s_cd - > cur_track + 1 ;
}
int RBAPeekPlayStatus ( )
{
2008-06-15 08:50:05 +00:00
if ( ! s_cd )
return 0 ;
if ( SDL_CDStatus ( s_cd ) = = CD_PLAYING )
return 1 ;
else if ( SDL_CDStatus ( s_cd ) = = CD_PAUSED ) // hack so it doesn't keep restarting paused music
return - 1 ;
return 0 ;
2006-03-20 17:12:09 +00:00
}
static int cddb_sum ( int n )
{
int ret ;
/* For backward compatibility this algorithm must not change */
ret = 0 ;
while ( n > 0 ) {
ret = ret + ( n % 10 ) ;
n = n / 10 ;
}
return ( ret ) ;
}
unsigned long RBAGetDiscID ( )
{
int i , t = 0 , n = 0 ;
2008-06-15 08:50:05 +00:00
if ( ! s_cd )
2006-03-20 17:12:09 +00:00
return 0 ;
/* For backward compatibility this algorithm must not change */
i = 0 ;
while ( i < s_cd - > numtracks ) {
n + = cddb_sum ( s_cd - > track [ i ] . offset / CD_FPS ) ;
i + + ;
}
t = ( s_cd - > track [ s_cd - > numtracks ] . offset / CD_FPS ) -
( s_cd - > track [ 0 ] . offset / CD_FPS ) ;
return ( ( n % 0xff ) < < 24 | t < < 8 | s_cd - > numtracks ) ;
}
2009-03-03 12:55:27 +00:00
void RBAList ( void )
{
int i ;
if ( ! s_cd )
return ;
for ( i = 0 ; i < s_cd - > numtracks ; i + + )
2013-04-22 10:37:59 +00:00
con_printf ( CON_VERBOSE , " RBAudio: CD track %d, type %s, length %d, offset %d " , s_cd - > track [ i ] . id , ( s_cd - > track [ i ] . type = = SDL_AUDIO_TRACK ) ? " audio " : " data " , s_cd - > track [ i ] . length , s_cd - > track [ i ] . offset ) ;
2009-03-03 12:55:27 +00:00
}