1 /*
2  *   cdda - CD Digital Audio support
3  *
4  *   Copyright (C) 1993-2004  Ti Kan
5  *   E-mail: xmcd@amb.org
6  *
7  *   This program is free software; you can redistribute it and/or modify
8  *   it under the terms of the GNU General Public License as published by
9  *   the Free Software Foundation; either version 2 of the License, or
10  *   (at your option) any later version.
11  *
12  *   This program is distributed in the hope that it will be useful,
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *   GNU General Public License for more details.
16  *
17  *   You should have received a copy of the GNU General Public License
18  *   along with this program; if not, write to the Free Software
19  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  */
21 #ifndef __CDDA_H__
22 #define __CDDA_H__
23 
24 #ifndef lint
25 static char *_cdda_h_ident_ = "@(#)cdda.h	7.114 04/03/05";
26 #endif
27 
28 
29 /*
30  * Whether to enable the SYSV IPC and/or the POSIX threads support
31  * based on OS feature capability.
32  */
33 #if defined(SVR4) || defined(SYSV) || defined(_LINUX) || \
34     defined(_SUNOS4) || defined(_SOLARIS) || defined(sgi) || \
35     defined(__hpux) || defined(_AIX) || \
36     defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || \
37     defined(__bsdi__) || defined(_OSF1)
38 #define HAS_SYSVIPC
39 #endif
40 
41 #if defined(_POSIX_THREADS) && !defined(NO_PTHREADS)
42 /* If <unistd.h> defines _POSIX_THREADS, then POSIX 1003.1c threads
43  * are supported.  NO_PTHREADS allows a user to disable POSIX thread
44  * support code from the makefile.
45  */
46 #define HAS_PTHREADS
47 #endif
48 
49 #ifdef HAS_PTHREADS
50 /* Hack: Some platforms lack the necessary pthread_cancel(3) */
51 #include <pthread.h>
52 #ifndef PTHREAD_CANCELED
53 #undef HAS_PTHREADS
54 #endif
55 #endif
56 
57 
58 /*
59  * CDDA methods
60  */
61 #define CDDA_METHODS	3	/* Total number of CDDA methods */
62 
63 #define CDDA_NONE	0	/* Don't use CDDA method */
64 #ifdef HAS_SYSVIPC
65 #define CDDA_SYSVIPC	1	/* SYSV IPC method */
66 #endif
67 #ifdef HAS_PTHREADS
68 #define CDDA_PTHREADS	2	/* POSIX threads method */
69 #endif
70 
71 
72 /*
73  * CDDA read methods
74  */
75 #define CDDA_RD_METHODS	6	/* Total number of CDDA read methods */
76 
77 #define CDDA_RD_NONE	0	/* Don't use CDDA read method */
78 #define CDDA_RD_SCSIPT	1	/* SCSI pass-through method */
79 #ifdef _SOLARIS
80 #define CDDA_RD_SOL	2	/* Solaris ioctl method */
81 #endif
82 #ifdef _LINUX
83 #define CDDA_RD_LINUX	3	/* Linux ioctl method */
84 #endif
85 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
86 #define CDDA_RD_FBSD	4	/* FreeBSD/OpenBSD/NetBSD ioctl method */
87 #endif
88 #if defined(_AIX) && defined(AIX_IDE)
89 #define CDDA_RD_AIX	5	/* AIX ATAPI/IDE ioctl method */
90 #endif
91 
92 
93 /*
94  * CDDA write methods
95  */
96 #define CDDA_WR_METHODS	9	/* Total number of CDDA write methods */
97 
98 #define CDDA_WR_NONE	0	/* Don't use CDDA write method */
99 #ifndef __VMS
100 #define CDDA_WR_OSS	1	/* OSS & Linux sound driver method */
101 #endif
102 #ifdef _SOLARIS
103 #define CDDA_WR_SOL	2	/* Solaris audio driver method */
104 #endif
105 #ifdef sgi
106 #define CDDA_WR_IRIX	3	/* IRIX audio driver method */
107 #endif
108 #ifdef __hpux
109 #define CDDA_WR_HPUX	4	/* HP-UX audio driver method */
110 #endif
111 #ifdef _AIX
112 #define CDDA_WR_AIX	5	/* AIX Ultimedia audio driver method */
113 #endif
114 #if defined(_LINUX) && defined(HAS_ALSA)
115 #define CDDA_WR_ALSA	6	/* ALSA sound driver method */
116 #endif
117 #if defined(_OSF1) || defined(__VMS)
118 #define CDDA_WR_OSF1	7	/* Tru64 UNIX and OpenVMS MME method */
119 #endif
120 #define CDDA_WR_FP	8	/* File & pipe method: No audio playback */
121 
122 
123 /* Whether a CDDA method is configured */
124 #if defined(CDDA_SYSVIPC) || defined(CDDA_PTHREADS)
125 #define CDDA_SUPPORTED
126 #endif
127 
128 
129 /* Check for ALSA version due to API changes */
130 #ifdef CDDA_WR_ALSA
131 #include <alsa/asoundlib.h>
132 #if !defined(SND_LIB_MAJOR) || !defined(SND_LIB_MINOR) || \
133     (SND_LIB_MAJOR == 0 && SND_LIB_MINOR < 9)
134 #undef CDDA_WR_ALSA		/* ALSA version prior to 0.9.0 not supported */
135 #endif
136 #endif	/* CDDA_WR_ALSA */
137 
138 
139 /* Basic CDDA read unit (number of bytes per CDDA sector) */
140 #define	CDDA_BLKSZ		2352
141 
142 /* Default CDDA read size: Note that different platforms' CDROM drivers
143  * may impose different limits which require that this be externally
144  * tuned via the cddaReadChunkBlocks parameter.
145  */
146 #define	DEF_CDDA_CHUNK_BLKS	8			/* 8 blocks */
147 #define MIN_CDDA_CHUNK_BLKS	1			/* 1 block */
148 #define MAX_CDDA_CHUNK_BLKS	(3 * FRAME_PER_SEC)	/* 3 seconds */
149 
150 /* CDDA data is queued up in memory. Here we define (in
151  * seconds) the amount of queued data. This is not a
152  * modifiable resource.
153  */
154 #define	DEF_CDDA_BUFFER_SECS	5
155 
156 /* During jitter correction we search through DEFAULT_SEARCH_BLOCKS
157  * for a match.  This is not a modifiable resource.
158  */
159 #define	DEF_CDDA_SRCH_BLKS	2
160 
161 /* In order to perform jitter correction we need to
162  * read more CDDA data than we "need". Below we define
163  * the amount of extra data required. So each CDDA
164  * read will comprise CHUNK_BLOCKS + OLAP_BLOCKS.
165  */
166 #define	DEF_CDDA_OLAP_BLKS	(DEF_CDDA_SRCH_BLKS * 2)
167 
168 /* We have found a match when DEFAULT_STR_LENGTH bytes are
169  * identical in the data and the overlap.
170  */
171 #define	DEF_CDDA_STR_LEN	20
172 
173 /* Maximum number of interrupts before system call fails */
174 #define	CDDA_INTR_MAX		200
175 
176 /* Maximum number of times to retry a failed CDDA read */
177 #define MAX_CDDAREAD_RETRIES	3
178 
179 /* CDDA heartbeat types */
180 #define CDDA_HB_READER		1		/* Reader */
181 #define CDDA_HB_WRITER		2		/* Writer */
182 
183 /* Reader/writer heartbeat timeout values in seconds */
184 #define MIN_HB_TIMEOUT		5		/* Minimum */
185 #define DEF_HB_TIMEOUT		15		/* Default */
186 
187 /* Number of heartbeat checks to skip after a pause/resume operation,
188  * in order to allow the reader and writer threads to catch up.
189  */
190 #define CDDA_HB_SKIP		5
191 
192 /* CDDA supported features bitmask values, returned by cdda_capab()
193  * These should match the similar CAPAB_xxx defines in libdi_d/libdi.h
194  */
195 #define CDDA_READAUDIO		0x02
196 #define CDDA_WRITEDEV		0x10
197 #define CDDA_WRITEFILE		0x20
198 #define CDDA_WRITEPIPE		0x40
199 
200 /* CDDA audio output port bitmask values */
201 #define CDDA_OUT_SPEAKER	0x01		/* Internal speaker */
202 #define CDDA_OUT_HEADPHONE	0x02		/* Headphone */
203 #define CDDA_OUT_LINEOUT	0x04		/* Line Out */
204 
205 /* Read and write process priority flags */
206 #define CDDA_RDPRI		0x01		/* Elevate read priority */
207 #define CDDA_WRPRI		0x02		/* Elevate write priority */
208 
209 /* Macros for encoder version storage */
210 #define ENCVER_MK(x,y,z)	(((x) * 1000000) + ((y) * 1000) + (z))
211 #define ENCVER_MAJ(v)		((v) / 1000000)
212 #define ENCVER_MIN(v)		(((v) / 1000) % 1000)
213 #define ENCVER_TINY(v)		((v) % 1000)
214 
215 
216 /* Call table structure for branching into a read-method. */
217 typedef struct cdda_rd_tbl {
218 	word32_t 	(*readinit)(void);
219 	bool_t	 	(*readfunc)(di_dev_t *);
220 	void	 	(*readdone)(bool_t);
221 	void	 	(*readinfo)(char *);
222 } cdda_rd_tbl_t;
223 
224 
225 /* Call table structure for branching into a write-method. */
226 typedef struct cdda_wr_tbl {
227 	word32_t 	(*writeinit)(void);
228 	bool_t	 	(*writefunc)(curstat_t *);
229 	void	 	(*writedone)(bool_t);
230 	void	 	(*writeinfo)(char *);
231 } cdda_wr_tbl_t;
232 
233 
234 /* Generic thread or process ID type */
235 typedef void *		thid_t;
236 
237 
238 /* Buffer for audio data transfer */
239 typedef struct cd_buffer {
240 	int		occupied;
241 	unsigned int	nextin;
242 	unsigned int	nextout;
243 	byte_t		*olap;
244 	byte_t		*data;
245 	byte_t		*b;
246 } cd_buffer_t;
247 
248 
249 /* Various sizes */
250 typedef struct cd_size {
251 	/* Chunk */
252 	unsigned int	chunk_blocks;
253 	unsigned int	chunk_bytes;
254 
255 	/* Buffer */
256 	unsigned int	buffer_chunks;
257 	unsigned int	buffer_blocks;
258 	unsigned int	buffer_bytes;
259 
260 	/* Overlap */
261 	unsigned int	olap_blocks;
262 	unsigned int	olap_bytes;
263 
264 	/* Searching */
265 	unsigned int	search_blocks;
266 	unsigned int	search_bytes;
267 	unsigned int	str_length;
268 
269 	/* Overall size */
270 	size_t		size;
271 } cd_size_t;
272 
273 
274 /* CD info */
275 typedef struct cd_info {
276 	int		state;			/* CDSTAT_PLAYING, etc. */
277 	int		chroute;		/* CHROUTE_NORMAL etc. */
278 	int		att;			/* CDDA attenuator value */
279 	int		outport;		/* CDDA output port */
280 	int		vol_taper;		/* Volume control taper */
281 	int		vol;			/* Current volume level */
282 	int		vol_left;		/* Current left vol % */
283 	int		vol_right;		/* Current right vol % */
284 	int		jitter;			/* 1 = on, 0 = off */
285 	int		cdda_done;		/* 1 = yes, 0 = no */
286 	word32_t	debug;			/* Debug level */
287 
288 	sword32_t	start_lba;		/* Start position */
289 	sword32_t	end_lba;		/* End position */
290 	word32_t	frm_played;		/* Frames written */
291 	word32_t	frm_per_sec;		/* Frames per sec stats */
292 	size_t		trk_len;		/* Track length in bytes */
293 	int		trk_idx;		/* Current track array index */
294 
295 	thid_t		reader;			/* Reader thread id */
296 	thid_t		writer;			/* Writer thread id */
297 
298 	time_t		reader_hb;		/* Reader heartbeat */
299 	time_t		writer_hb;		/* Writer heartbeat */
300 	int		reader_hb_timeout;	/* reader heartbeat timeout */
301 	int		writer_hb_timeout;	/* writer heartbeat timeout */
302 
303 	char		msgbuf[ERR_BUF_SZ];	/* Message buffer */
304 } cd_info_t;
305 
306 
307 /* CD state structure - pointers to the size, info and buffer areas */
308 typedef struct cd_state {
309 	cd_size_t	*cds;			/* Sizes */
310 	cd_info_t	*i;			/* Info */
311 	cd_buffer_t	*cdb;			/* Data buffer */
312 } cd_state_t ;
313 
314 
315 /* Message dialog macros */
316 #define CDDA_FATAL(msg)		{					\
317 	if (cdda_clinfo != NULL && cdda_clinfo->fatal_msg != NULL)	\
318 		cdda_clinfo->fatal_msg(app_data.str_fatal, (msg));	\
319 	else {								\
320 		(void) fprintf(errfp, "Fatal: %s\n", (msg));		\
321 		_exit(1);						\
322 	}								\
323 }
324 #define CDDA_WARNING(msg)	{					\
325 	if (cdda_clinfo != NULL && cdda_clinfo->warning_msg != NULL)	\
326 		cdda_clinfo->warning_msg(app_data.str_warning, (msg));	\
327 	else								\
328 		(void) fprintf(errfp, "Warning: %s\n", (msg));		\
329 }
330 #define CDDA_INFO(msg)		{					\
331 	if (cdda_clinfo != NULL && cdda_clinfo->info_msg != NULL)	\
332 		cdda_clinfo->info_msg(app_data.str_info, (msg));	\
333 	else								\
334 		(void) fprintf(errfp, "Info: %s\n", (msg));		\
335 }
336 #define CDDA_INFO2(msg, txt)	{					\
337 	if (cdda_clinfo != NULL && cdda_clinfo->info2_msg != NULL)	\
338 		cdda_clinfo->info2_msg(app_data.str_info,(msg),(txt));	\
339 	else								\
340 		(void) fprintf(errfp, "Info: %s\n%s\n", (msg), (txt));	\
341 }
342 
343 
344 /* Client registration structure */
345 typedef struct cdda_client {
346 	curstat_t *	(*curstat_addr)(void);
347 	void		(*fatal_msg)(char *, char *);
348 	void		(*warning_msg)(char *, char *);
349 	void		(*info_msg)(char *, char *);
350 	void		(*info2_msg)(char *, char *, char *);
351 } cdda_client_t;
352 
353 
354 /* File format description structure */
355 typedef struct filefmt {
356 	int		fmt;			/* Format code */
357 	char		*name;			/* Format name */
358 	char		*suf;			/* File Suffix */
359 	char		*desc;			/* Description */
360 } filefmt_t;
361 
362 
363 /* Function prototypes */
364 extern word32_t		cdda_capab(void);
365 extern void		cdda_preinit(void);
366 extern bool_t		cdda_init(curstat_t *, cdda_client_t *);
367 extern void		cdda_halt(di_dev_t *, curstat_t *);
368 extern bool_t		cdda_play(di_dev_t *, curstat_t *, sword32_t,
369 				  sword32_t);
370 extern bool_t		cdda_pause_resume(di_dev_t *, curstat_t *, bool_t);
371 extern bool_t		cdda_stop(di_dev_t *, curstat_t *);
372 extern int		cdda_vol(di_dev_t *, curstat_t *, int, bool_t);
373 extern bool_t		cdda_chroute(di_dev_t *, curstat_t *);
374 extern void		cdda_att(curstat_t *);
375 extern void		cdda_outport(void);
376 extern bool_t		cdda_getstatus(di_dev_t *, curstat_t *, cdstat_t *);
377 extern void		cdda_debug(word32_t);
378 extern char		*cdda_info(void);
379 extern int		cdda_initipc(cd_state_t *);
380 extern void		cdda_waitsem(int, int);
381 extern void		cdda_postsem(int, int);
382 extern void		cdda_yield(void);
383 extern void		cdda_kill(thid_t, int);
384 extern bool_t		cdda_filefmt_supp(int);
385 extern filefmt_t	*cdda_filefmt(int);
386 extern int		cdda_bitrates(void);
387 extern int		cdda_bitrate_val(int);
388 extern char		*cdda_bitrate_name(int);
389 extern int		cdda_heartbeat_interval(int);
390 extern void		cdda_heartbeat(time_t *, int);
391 
392 #endif	/* __CDDA_H__ */
393 
394