File indexing completed on 2023-09-24 08:50:33
0001 /* 0002 * This file is part of WorkMan, the civilized CD player library 0003 * Copyright (C) 1991-1997 by Steven Grimm <koreth@midwinter.com> 0004 * Copyright (C) by Dirk Försterling <milliByte@DeathsDoor.com> 0005 * 0006 * This library is free software; you can redistribute it and/or 0007 * modify it under the terms of the GNU Library General Public 0008 * License as published by the Free Software Foundation; either 0009 * version 2 of the License, or (at your option) any later version. 0010 * 0011 * This library is distributed in the hope that it will be useful, 0012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0014 * Library General Public License for more details. 0015 * 0016 * You should have received a copy of the GNU Library General Public 0017 * License along with this library; if not, write to the Free 0018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 0019 * 0020 * 0021 * IRIX specific. 0022 * 0023 * Taken from the kscd distribution 0024 * 0025 * Paul Kendall 0026 * paul@orion.co.nz, or 0027 * paul@kcbbs.gen.nz 0028 */ 0029 0030 #if defined(sgi) || defined(__sgi) 0031 0032 #include "include/wm_config.h" 0033 0034 /* 0035 * Yes, it was designed for WorkMan 1.4b3 0036 * Because I did start over from 1.3a, I disable it here. 0037 * There is no guarantee of getting working code by defining 0038 * CDDA yourself. 0039 * 0040 */ 0041 #undef CDDA 0042 /*#define CDDA*/ 0043 0044 #include <sys/types.h> 0045 #include <sys/time.h> 0046 #include <stdio.h> 0047 #include <ctype.h> 0048 #include <string.h> 0049 #include <fcntl.h> 0050 #include <stdlib.h> 0051 #include <unistd.h> 0052 #include <signal.h> 0053 #include <sigfpe.h> 0054 #include <dmedia/cdaudio.h> 0055 #include <dmedia/audio.h> 0056 #include <errno.h> 0057 0058 #include "include/wm_struct.h" 0059 #include "include/wm_cdtext.h" 0060 0061 #define WM_MSG_CLASS WM_MSG_CLASS_PLATFORM 0062 0063 void *malloc(); 0064 char *strchr(); 0065 0066 int min_volume = 0; 0067 int max_volume = 255; 0068 0069 #ifdef CDDA 0070 static int playing = STOPPED; 0071 static CDPLAYER *icd; 0072 static CDPARSER *icdp; 0073 static CDFRAME cdbuf[12]; 0074 static ALport audioport; 0075 static ALconfig aconfig; 0076 static struct itimerval audiotimer = { {0,0}, {0,25000} }; 0077 static int cdtrack=0; 0078 static int cdframe=0; 0079 static int cdstopframe=0; 0080 0081 /* 0082 * Platform specific internal functions for CDDA 0083 */ 0084 void 0085 cbprognum(void *arg, CDDATATYPES type, CDPROGNUM* prognum) 0086 { 0087 cdtrack = prognum->value; 0088 } /* cbprognum() */ 0089 0090 void 0091 cbabstime(void *arg, CDDATATYPES type, struct cdtimecode* atime) 0092 { 0093 cdframe = CDtctoframe(atime); 0094 if( cdframe == cdstopframe ) 0095 playing = STOPPED; 0096 } /* cbabstime() */ 0097 0098 void 0099 cbplayaudio(void *arg, CDDATATYPES type, short* audio) 0100 { 0101 if(playing != PLAYING) return; 0102 ALwritesamps(audioport, audio, CDDA_NUMSAMPLES); 0103 } /* cbplayaudio() */ 0104 0105 static void 0106 alarmsignal() 0107 { 0108 int n, i; 0109 if(playing != PLAYING) return; 0110 if( ALgetfilled(audioport) < CDDA_NUMSAMPLES*8 ) 0111 { 0112 /* Only get more samples and play them if we're getting low 0113 * this ensures that the CD stays close to the sound 0114 */ 0115 n = CDreadda(icd, cdbuf, 12); 0116 if( n == 0 ) return; 0117 for( i=0 ; i<12 ; i++ ) 0118 CDparseframe(icdp, &cdbuf[i]); 0119 } 0120 signal(SIGALRM, alarmsignal); 0121 setitimer(ITIMER_REAL, &audiotimer, NULL); 0122 } /* alarmsignal() */ 0123 #endif 0124 0125 /*--------------------------------------------------------* 0126 * Initialize the drive. A no-op for the generic driver. 0127 *--------------------------------------------------------*/ 0128 int 0129 gen_init( struct wm_drive *d ) 0130 { 0131 #ifdef CDDA 0132 long Param[4]; 0133 /* Set the audio rate to 44100Hz 16bit 2s-comp stereo */ 0134 aconfig = ALnewconfig(); 0135 ALsetwidth(aconfig, AL_SAMPLE_16); 0136 ALsetsampfmt(aconfig, AL_SAMPFMT_TWOSCOMP); 0137 ALsetchannels(aconfig, 2); 0138 Param[0] = AL_OUTPUT_RATE; Param[1] = AL_RATE_44100; 0139 Param[2] = AL_CHANNEL_MODE; Param[3] = AL_STEREO; 0140 ALsetparams(AL_DEFAULT_DEVICE, Param, 4); 0141 audioport = ALopenport("KDE KSCD Audio", "w", aconfig); 0142 0143 /* setup cdparser */ 0144 icdp = CDcreateparser(); 0145 CDaddcallback(icdp, cd_audio, (CDCALLBACKFUNC)cbplayaudio, 0); 0146 CDaddcallback(icdp, cd_pnum, (CDCALLBACKFUNC)cbprognum, 0); 0147 CDaddcallback(icdp, cd_atime, (CDCALLBACKFUNC)cbabstime, 0); 0148 0149 /* Lets handle those floating point exceptions expeditiously. */ 0150 sigfpe_[_UNDERFL].repls = _ZERO; 0151 handle_sigfpes(_ON, _EN_UNDERFL, NULL, _ABORT_ON_ERROR, NULL); 0152 #endif 0153 return 0; 0154 } /* gen_init() */ 0155 0156 /*-------------------------------------------------------------* 0157 * Open the CD and figure out which kind of drive is attached. 0158 *-------------------------------------------------------------*/ 0159 int 0160 gen_open( struct wm_drive *d ) 0161 { 0162 CDSTATUS s; 0163 0164 if (d->fd < 0) /* Device already open? */ 0165 { 0166 d->daux = CDopen(d->cd_device, "r"); 0167 if (d->daux == 0) { 0168 return -6; 0169 } 0170 0171 d->fd = 1; 0172 #ifdef CDDA 0173 icd = d->daux; 0174 #endif 0175 } else { 0176 wm_lib_message(WM_MSG_LEVEL_DEBUG|WM_MSG_CLASS, "gen_open(): [device is open (fd=%d)]\n", d->fd); 0177 } 0178 0179 CDgetstatus(d->daux, &s); 0180 if( s.state == CD_NODISC || s.state == CD_ERROR ) 0181 return 1; 0182 0183 return 0; 0184 } /* gen_open() */ 0185 0186 /*----------------------------------* 0187 * Send a SCSI command out the bus. 0188 *----------------------------------*/ 0189 int 0190 gen_scsi( struct wm_drive *d, unsigned char *xcdb, int cdblen, 0191 char *retbuf, int retbuflen, int getreply) 0192 { 0193 return -1; 0194 } /* gen_scsi() */ 0195 0196 int 0197 gen_close( struct wm_drive *d ) 0198 { 0199 if(d->fd != -1) { 0200 wm_lib_message(WM_MSG_LEVEL_DEBUG|WM_MSG_CLASS, "closing the device\n"); 0201 close(d->fd); 0202 d->fd = -1; 0203 } 0204 return 0; 0205 } 0206 0207 /*--------------------------------------------------------------------------* 0208 * Get the current status of the drive: the current play mode, the absolute 0209 * position from start of disc (in frames), and the current track and index 0210 * numbers if the CD is playing or paused. 0211 *--------------------------------------------------------------------------*/ 0212 int 0213 gen_get_drive_status( struct wm_drive *d, int oldmode, 0214 int *mode, int *pos, int *track, 0215 int *index ) 0216 { 0217 #ifdef CDDA 0218 *mode = playing; 0219 *track = cdtrack; 0220 *pos = cdframe; 0221 *index = 0; 0222 #else 0223 CDSTATUS s; 0224 if( CDgetstatus(d->daux, &s)==0 ) 0225 return -1; 0226 *pos = CDmsftoframe(s.min,s.sec,s.frame); 0227 *track = s.track; 0228 *index = 0; 0229 switch( s.state ) 0230 { 0231 case CD_READY: *mode = WM_CDM_STOPPED; 0232 break; 0233 case CD_STILL: 0234 case CD_PAUSED: *mode = WM_CDM_PAUSED; 0235 break; 0236 case CD_PLAYING: *mode = WM_CDM_PLAYING; 0237 break; 0238 default: *mode = WM_CDM_UNKNOWN; 0239 } 0240 #endif 0241 return 0; 0242 } /* gen_get_drive_status() */ 0243 0244 /*-------------------------------------* 0245 * Get the number of tracks on the CD. 0246 *-------------------------------------*/ 0247 int 0248 gen_get_trackcount( struct wm_drive *d, int *tracks ) 0249 { 0250 CDSTATUS s; 0251 if( CDgetstatus(d->daux, &s)==0 ) 0252 return -1; 0253 *tracks = s.last; 0254 return 0; 0255 } /* gen_get_trackcount() */ 0256 0257 /*---------------------------------------------------------* 0258 * Get the start time and mode (data or audio) of a track. 0259 *---------------------------------------------------------*/ 0260 int 0261 gen_get_trackinfo( struct wm_drive *d, int track, int *data, int *startframe) 0262 { 0263 CDTRACKINFO i; 0264 int ret = CDgettrackinfo(d->daux, track, &i); 0265 if( ret == 0 ) 0266 return -1; 0267 *data = 0; 0268 *startframe = CDmsftoframe(i.start_min,i.start_sec,i.start_frame); 0269 return 0; 0270 } /* gen_get_trackinfo() */ 0271 0272 /*-------------------------------------* 0273 * Get the number of frames on the CD. 0274 *-------------------------------------*/ 0275 int 0276 gen_get_cdlen( struct wm_drive *d, int *frames ) 0277 { 0278 CDSTATUS s; 0279 if( CDgetstatus(d->daux, &s)==0 ) 0280 return -1; 0281 *frames = CDmsftoframe(s.total_min,s.total_sec,s.total_frame); 0282 return 0; 0283 } /* gen_get_cdlen() */ 0284 0285 /*------------------------------------------------------------* 0286 * Play the CD from one position to another (both in frames.) 0287 *------------------------------------------------------------*/ 0288 int 0289 gen_play( struct wm_drive *d, int start, int end ) 0290 { 0291 #ifdef CDDA 0292 int m, s, f; 0293 CDframetomsf(start, &m, &s, &f); 0294 CDseek(icd, m, s, f); 0295 cdstopframe = end; 0296 playing = PLAYING; 0297 signal(SIGALRM, alarmsignal); 0298 setitimer(ITIMER_REAL, &audiotimer, NULL); 0299 #else 0300 int m, s, f; 0301 CDframetomsf(start, &m, &s, &f); 0302 CDplayabs(d->daux, m, s, f, 1); 0303 #endif 0304 return 0; 0305 } /* gen_play() */ 0306 0307 /*---------------* 0308 * Pause the CD. 0309 *---------------*/ 0310 int 0311 gen_pause( struct wm_drive *d ) 0312 { 0313 #ifdef CDDA 0314 playing = WM_CDM_PAUSED; 0315 #else 0316 CDSTATUS s; 0317 if( CDgetstatus(d->daux, &s)==0 ) 0318 return -1; 0319 if(s.state == CD_PLAYING) 0320 CDtogglepause(d->daux); 0321 #endif 0322 return 0; 0323 } /* gen_pause() */ 0324 0325 /*-------------------------------------------------* 0326 * Resume playing the CD (assuming it was paused.) 0327 *-------------------------------------------------*/ 0328 int 0329 gen_resume( struct wm_drive *d ) 0330 { 0331 #ifdef CDDA 0332 playing = WM_CDM_PLAYING; 0333 signal(SIGALRM, alarmsignal); 0334 setitimer(ITIMER_REAL, &audiotimer, NULL); 0335 #else 0336 CDSTATUS s; 0337 if( CDgetstatus(d->daux, &s)==0 ) 0338 return -1; 0339 if(s.state == CD_PAUSED) 0340 CDtogglepause(d->daux); 0341 #endif 0342 return 0; 0343 } /* gen_resume() */ 0344 0345 /*--------------* 0346 * Stop the CD. 0347 *--------------*/ 0348 int 0349 gen_stop( struct wm_drive *d ) 0350 { 0351 #ifdef CDDA 0352 playing = WM_CDM_STOPPED; 0353 #else 0354 CDstop(d->daux); 0355 #endif 0356 return 0; 0357 } /* gen_stop() */ 0358 0359 /*----------------------------------------* 0360 * Eject the current CD, if there is one. 0361 *----------------------------------------*/ 0362 int 0363 gen_eject( struct wm_drive *d ) 0364 { 0365 #ifdef CDDA 0366 playing = WM_CDM_STOPPED; 0367 #endif 0368 CDeject(d->daux); 0369 return 0; 0370 } /* gen_eject() */ 0371 0372 /*----------------------------------------* 0373 * Close the CD tray 0374 * 0375 * Please edit and send changes to 0376 * milliByte@Deathsdoor.com 0377 *----------------------------------------*/ 0378 0379 int 0380 gen_closetray(struct wm_drive *d) 0381 { 0382 return -1; 0383 } /* gen_closetray() */ 0384 0385 /*---------------------------------------------------------------------* 0386 * Set the volume level for the left and right channels. Their values 0387 * range from 0 to 100. 0388 *---------------------------------------------------------------------*/ 0389 int 0390 gen_set_volume( struct wm_drive *d, int left, int right ) 0391 { 0392 long Param[4]; 0393 Param[0] = AL_LEFT_SPEAKER_GAIN; Param[1] = left*255/100; 0394 Param[2] = AL_RIGHT_SPEAKER_GAIN; Param[3] = right*255/100; 0395 ALsetparams(AL_DEFAULT_DEVICE, Param, 4); 0396 return 0; 0397 } /* gen_set_volume() */ 0398 0399 /*---------------------------------------------------------------------* 0400 * Read the initial volume from the drive, if available. Each channel 0401 * ranges from 0 to 100, with -1 indicating data not available. 0402 *---------------------------------------------------------------------*/ 0403 int 0404 gen_get_volume( struct wm_drive *d, int *left, int *right ) 0405 { 0406 long Param[4]; 0407 Param[0] = AL_LEFT_SPEAKER_GAIN; Param[1] = 0; 0408 Param[2] = AL_RIGHT_SPEAKER_GAIN; Param[3] = 0; 0409 ALgetparams(AL_DEFAULT_DEVICE, Param, 4); 0410 *left = Param[1] * 100 / 255; 0411 *right = Param[3] * 100 / 255; 0412 return 0; 0413 } /* gen_get_volume() */ 0414 0415 #endif 0416