2
* This file is part of WorkMan, the civilized CD player library
3
* Copyright (C) 1991-1997 by Steven Grimm <koreth@midwinter.com>
4
* Copyright (C) by Dirk Försterling <milliByte@DeathsDoor.com>
6
* This library is free software; you can redistribute it and/or
7
* modify it under the terms of the GNU Library General Public
8
* License as published by the Free Software Foundation; either
9
* version 2 of the License, or (at your option) any later version.
11
* This library is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
* Library General Public License for more details.
16
* You should have received a copy of the GNU Library General Public
17
* License along with this library; if not, write to the Free
18
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23
* Taken from the kscd distribution
26
* paul@orion.co.nz, or
30
#if defined(sgi) || defined(__sgi)
32
#include "include/wm_config.h"
35
* Yes, it was designed for WorkMan 1.4b3
36
* Because I did start over from 1.3a, I disable it here.
37
* There is no guarantee of getting working code by defining
44
#include <sys/types.h>
54
#include <dmedia/cdaudio.h>
55
#include <dmedia/audio.h>
58
#include "include/wm_struct.h"
59
#include "include/wm_cdtext.h"
61
#define WM_MSG_CLASS WM_MSG_CLASS_PLATFORM
70
static int playing = STOPPED;
72
static CDPARSER *icdp;
73
static CDFRAME cdbuf[12];
74
static ALport audioport;
75
static ALconfig aconfig;
76
static struct itimerval audiotimer = { {0,0}, {0,25000} };
79
static int cdstopframe=0;
82
* Platform specific internal functions for CDDA
85
cbprognum(void *arg, CDDATATYPES type, CDPROGNUM* prognum)
87
cdtrack = prognum->value;
91
cbabstime(void *arg, CDDATATYPES type, struct cdtimecode* atime)
93
cdframe = CDtctoframe(atime);
94
if( cdframe == cdstopframe )
99
cbplayaudio(void *arg, CDDATATYPES type, short* audio)
101
if(playing != PLAYING) return;
102
ALwritesamps(audioport, audio, CDDA_NUMSAMPLES);
103
} /* cbplayaudio() */
109
if(playing != PLAYING) return;
110
if( ALgetfilled(audioport) < CDDA_NUMSAMPLES*8 )
112
/* Only get more samples and play them if we're getting low
113
* this ensures that the CD stays close to the sound
115
n = CDreadda(icd, cdbuf, 12);
117
for( i=0 ; i<12 ; i++ )
118
CDparseframe(icdp, &cdbuf[i]);
120
signal(SIGALRM, alarmsignal);
121
setitimer(ITIMER_REAL, &audiotimer, NULL);
122
} /* alarmsignal() */
125
/*--------------------------------------------------------*
126
* Initialize the drive. A no-op for the generic driver.
127
*--------------------------------------------------------*/
129
gen_init( struct wm_drive *d )
133
/* Set the audio rate to 44100Hz 16bit 2s-comp stereo */
134
aconfig = ALnewconfig();
135
ALsetwidth(aconfig, AL_SAMPLE_16);
136
ALsetsampfmt(aconfig, AL_SAMPFMT_TWOSCOMP);
137
ALsetchannels(aconfig, 2);
138
Param[0] = AL_OUTPUT_RATE; Param[1] = AL_RATE_44100;
139
Param[2] = AL_CHANNEL_MODE; Param[3] = AL_STEREO;
140
ALsetparams(AL_DEFAULT_DEVICE, Param, 4);
141
audioport = ALopenport("KDE KSCD Audio", "w", aconfig);
144
icdp = CDcreateparser();
145
CDaddcallback(icdp, cd_audio, (CDCALLBACKFUNC)cbplayaudio, 0);
146
CDaddcallback(icdp, cd_pnum, (CDCALLBACKFUNC)cbprognum, 0);
147
CDaddcallback(icdp, cd_atime, (CDCALLBACKFUNC)cbabstime, 0);
149
/* Lets handle those floating point exceptions expeditiously. */
150
sigfpe_[_UNDERFL].repls = _ZERO;
151
handle_sigfpes(_ON, _EN_UNDERFL, NULL, _ABORT_ON_ERROR, NULL);
156
/*-------------------------------------------------------------*
157
* Open the CD and figure out which kind of drive is attached.
158
*-------------------------------------------------------------*/
160
gen_open( struct wm_drive *d )
164
if (d->fd < 0) /* Device already open? */
166
d->daux = CDopen(d->cd_device, "r");
176
wm_lib_message(WM_MSG_LEVEL_DEBUG|WM_MSG_CLASS, "gen_open(): [device is open (fd=%d)]\n", d->fd);
179
CDgetstatus(d->daux, &s);
180
if( s.state == CD_NODISC || s.state == CD_ERROR )
186
/*----------------------------------*
187
* Send a SCSI command out the bus.
188
*----------------------------------*/
190
gen_scsi( struct wm_drive *d, unsigned char *xcdb, int cdblen,
191
char *retbuf, int retbuflen, int getreply)
197
gen_close( struct wm_drive *d )
200
wm_lib_message(WM_MSG_LEVEL_DEBUG|WM_MSG_CLASS, "closing the device\n");
207
/*--------------------------------------------------------------------------*
208
* Get the current status of the drive: the current play mode, the absolute
209
* position from start of disc (in frames), and the current track and index
210
* numbers if the CD is playing or paused.
211
*--------------------------------------------------------------------------*/
213
gen_get_drive_status( struct wm_drive *d, int oldmode,
214
int *mode, int *pos, int *track,
224
if( CDgetstatus(d->daux, &s)==0 )
226
*pos = CDmsftoframe(s.min,s.sec,s.frame);
231
case CD_READY: *mode = WM_CDM_STOPPED;
234
case CD_PAUSED: *mode = WM_CDM_PAUSED;
236
case CD_PLAYING: *mode = WM_CDM_PLAYING;
238
default: *mode = WM_CDM_UNKNOWN;
242
} /* gen_get_drive_status() */
244
/*-------------------------------------*
245
* Get the number of tracks on the CD.
246
*-------------------------------------*/
248
gen_get_trackcount( struct wm_drive *d, int *tracks )
251
if( CDgetstatus(d->daux, &s)==0 )
255
} /* gen_get_trackcount() */
257
/*---------------------------------------------------------*
258
* Get the start time and mode (data or audio) of a track.
259
*---------------------------------------------------------*/
261
gen_get_trackinfo( struct wm_drive *d, int track, int *data, int *startframe)
264
int ret = CDgettrackinfo(d->daux, track, &i);
268
*startframe = CDmsftoframe(i.start_min,i.start_sec,i.start_frame);
270
} /* gen_get_trackinfo() */
272
/*-------------------------------------*
273
* Get the number of frames on the CD.
274
*-------------------------------------*/
276
gen_get_cdlen( struct wm_drive *d, int *frames )
279
if( CDgetstatus(d->daux, &s)==0 )
281
*frames = CDmsftoframe(s.total_min,s.total_sec,s.total_frame);
283
} /* gen_get_cdlen() */
285
/*------------------------------------------------------------*
286
* Play the CD from one position to another (both in frames.)
287
*------------------------------------------------------------*/
289
gen_play( struct wm_drive *d, int start, int end )
293
CDframetomsf(start, &m, &s, &f);
294
CDseek(icd, m, s, f);
297
signal(SIGALRM, alarmsignal);
298
setitimer(ITIMER_REAL, &audiotimer, NULL);
301
CDframetomsf(start, &m, &s, &f);
302
CDplayabs(d->daux, m, s, f, 1);
311
gen_pause( struct wm_drive *d )
314
playing = WM_CDM_PAUSED;
317
if( CDgetstatus(d->daux, &s)==0 )
319
if(s.state == CD_PLAYING)
320
CDtogglepause(d->daux);
325
/*-------------------------------------------------*
326
* Resume playing the CD (assuming it was paused.)
327
*-------------------------------------------------*/
329
gen_resume( struct wm_drive *d )
332
playing = WM_CDM_PLAYING;
333
signal(SIGALRM, alarmsignal);
334
setitimer(ITIMER_REAL, &audiotimer, NULL);
337
if( CDgetstatus(d->daux, &s)==0 )
339
if(s.state == CD_PAUSED)
340
CDtogglepause(d->daux);
349
gen_stop( struct wm_drive *d )
352
playing = WM_CDM_STOPPED;
359
/*----------------------------------------*
360
* Eject the current CD, if there is one.
361
*----------------------------------------*/
363
gen_eject( struct wm_drive *d )
366
playing = WM_CDM_STOPPED;
372
/*----------------------------------------*
375
* Please edit and send changes to
376
* milliByte@Deathsdoor.com
377
*----------------------------------------*/
380
gen_closetray(struct wm_drive *d)
383
} /* gen_closetray() */
385
/*---------------------------------------------------------------------*
386
* Set the volume level for the left and right channels. Their values
387
* range from 0 to 100.
388
*---------------------------------------------------------------------*/
390
gen_set_volume( struct wm_drive *d, int left, int right )
393
Param[0] = AL_LEFT_SPEAKER_GAIN; Param[1] = left*255/100;
394
Param[2] = AL_RIGHT_SPEAKER_GAIN; Param[3] = right*255/100;
395
ALsetparams(AL_DEFAULT_DEVICE, Param, 4);
397
} /* gen_set_volume() */
399
/*---------------------------------------------------------------------*
400
* Read the initial volume from the drive, if available. Each channel
401
* ranges from 0 to 100, with -1 indicating data not available.
402
*---------------------------------------------------------------------*/
404
gen_get_volume( struct wm_drive *d, int *left, int *right )
407
Param[0] = AL_LEFT_SPEAKER_GAIN; Param[1] = 0;
408
Param[2] = AL_RIGHT_SPEAKER_GAIN; Param[3] = 0;
409
ALgetparams(AL_DEFAULT_DEVICE, Param, 4);
410
*left = Param[1] * 100 / 255;
411
*right = Param[3] * 100 / 255;
413
} /* gen_get_volume() */