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 lint
22 static char *_cdda_c_ident_ = "@(#)cdda.c	7.99 04/04/20";
23 #endif
24 
25 #include "common_d/appenv.h"
26 #include "common_d/util.h"
27 #include "libdi_d/libdi.h"
28 #include "cdda_d/cdda.h"
29 #include "cdda_d/common.h"
30 #include "cdda_d/sysvipc.h"
31 #include "cdda_d/pthr.h"
32 #include "cdda_d/rd_scsi.h"
33 #include "cdda_d/rd_sol.h"
34 #include "cdda_d/rd_linux.h"
35 #include "cdda_d/rd_fbsd.h"
36 #include "cdda_d/rd_aix.h"
37 #include "cdda_d/wr_oss.h"
38 #include "cdda_d/wr_sol.h"
39 #include "cdda_d/wr_irix.h"
40 #include "cdda_d/wr_hpux.h"
41 #include "cdda_d/wr_aix.h"
42 #include "cdda_d/wr_alsa.h"
43 #include "cdda_d/wr_osf1.h"
44 #include "cdda_d/wr_fp.h"
45 #include "cdda_d/wr_gen.h"
46 
47 
48 extern appdata_t	app_data;
49 extern FILE		*errfp;
50 
51 
52 cdda_client_t		*cdda_clinfo;		/* Client information struct */
53 
54 
55 #ifdef HAS_LAME
56 #include "cdda_d/if_lame.h"
57 char	*lameprogs[] = { "lame", "notlame", NULL };
58 char	*lamepath;
59 #endif	/* HAS_LAME */
60 
61 
62 #ifdef HAS_FAAC
63 #include "cdda_d/if_faac.h"
64 char	*faacprogs[] = { "faac", NULL };
65 char	*faacpath;
66 #endif	/* HAS_FAAC */
67 
68 
69 /*
70  * Cdda method call table
71  * This array must correspond to the CDDA_xxx definitions found in the
72  * cdda.h file, and the index is specified by the cddaMethod parameter.
73  */
74 struct {
75 	word32_t (*capab)(void);
76 	void	 (*preinit)(void);
77 	bool_t	 (*init)(curstat_t *);
78 	void	 (*halt)(di_dev_t *, curstat_t *);
79 	bool_t	 (*play)(di_dev_t *, curstat_t *, int, int);
80 	bool_t	 (*pause_resume)(di_dev_t *, curstat_t *, bool_t);
81 	bool_t	 (*stop)(di_dev_t *, curstat_t *);
82 	int	 (*vol)(di_dev_t *, curstat_t *, int, bool_t);
83 	bool_t	 (*chroute)(di_dev_t *, curstat_t *);
84 	void	 (*cdda_att)(curstat_t *);
85 	void	 (*outport)(void);
86 	bool_t	 (*getstatus)(di_dev_t *, curstat_t *, cdstat_t *);
87 	void	 (*debug)(word32_t);
88 	void	 (*info)(char *);
89 	int	 (*initipc)(cd_state_t *);
90 	void	 (*waitsem)(int, int);
91 	void	 (*postsem)(int, int);
92 	void	 (*yield)(void);
93 	void	 (*kill)(thid_t, int);
94 } cdda_calltbl[] = {
95 	{ NULL, NULL, NULL, NULL, NULL, NULL,
96 	  NULL, NULL, NULL, NULL, NULL },		/* CDDA_NONE */
97 	{ cdda_sysvipc_capab,
98 	  cdda_sysvipc_preinit,
99 	  cdda_sysvipc_init,
100 	  cdda_sysvipc_halt,
101 	  cdda_sysvipc_play,
102 	  cdda_sysvipc_pause_resume,
103 	  cdda_sysvipc_stop,
104 	  cdda_sysvipc_vol,
105 	  cdda_sysvipc_chroute,
106 	  cdda_sysvipc_att,
107 	  cdda_sysvipc_outport,
108 	  cdda_sysvipc_getstatus,
109 	  cdda_sysvipc_debug,
110 	  cdda_sysvipc_info,
111 	  cdda_sysvipc_initipc,
112 	  cdda_sysvipc_waitsem,
113 	  cdda_sysvipc_postsem,
114 	  cdda_sysvipc_yield,
115 	  cdda_sysvipc_kill },				/* CDDA_SYSVIPC */
116 	{ cdda_pthr_capab,
117 	  cdda_pthr_preinit,
118 	  cdda_pthr_init,
119 	  cdda_pthr_halt,
120 	  cdda_pthr_play,
121 	  cdda_pthr_pause_resume,
122 	  cdda_pthr_stop,
123 	  cdda_pthr_vol,
124 	  cdda_pthr_chroute,
125 	  cdda_pthr_att,
126 	  cdda_pthr_outport,
127 	  cdda_pthr_getstatus,
128 	  cdda_pthr_debug,
129 	  cdda_pthr_info,
130 	  cdda_pthr_initipc,
131 	  cdda_pthr_waitsem,
132 	  cdda_pthr_postsem,
133 	  cdda_pthr_yield,
134 	  cdda_pthr_kill }				/* CDDA_PTHREADS */
135 };
136 
137 
138 /* Call table to branch into a read-method.  The array index must
139  * correspond to the cddaReadMethod parameter.
140  */
141 cdda_rd_tbl_t	cdda_rd_calltbl[] = {
142 	{ NULL, NULL, NULL },				/* CDDA_RD_NONE */
143 	{ scsi_rinit,
144 	  scsi_read,
145 	  scsi_rdone,
146 	  scsi_rinfo },					/* CDDA_RD_SCSIPT */
147 	{ sol_rinit,
148 	  sol_read,
149 	  sol_rdone,
150 	  sol_rinfo },					/* CDDA_RD_SOL */
151 	{ linux_rinit,
152 	  linux_read,
153 	  linux_rdone,
154 	  linux_rinfo },				/* CDDA_RD_LINUX */
155 	{ fbsd_rinit,
156 	  fbsd_read,
157 	  fbsd_rdone,
158 	  fbsd_rinfo },					/* CDDA_RD_FBSD */
159 	{ aix_rinit,
160 	  aix_read,
161 	  aix_rdone,
162 	  aix_rinfo }					/* CDDA_RD_AIX */
163 };
164 
165 
166 /* Call table to branch into a write-method.  The array index must
167  * correspond to the cddaWriteMethod parameter.
168  */
169 cdda_wr_tbl_t	cdda_wr_calltbl[] = {
170 	{ NULL, NULL, NULL },				/* CDDA_WR_NONE */
171 	{ oss_winit,
172 	  oss_write,
173 	  oss_wdone,
174 	  oss_winfo },					/* CDDA_WR_OSS */
175 	{ sol_winit,
176 	  sol_write,
177 	  sol_wdone,
178 	  sol_winfo },					/* CDDA_WR_SOL */
179 	{ irix_winit,
180 	  irix_write,
181 	  irix_wdone,
182 	  irix_winfo },					/* CDDA_WR_IRIX */
183 	{ hpux_winit,
184 	  hpux_write,
185 	  hpux_wdone,
186 	  hpux_winfo },					/* CDDA_WR_HPUX */
187 	{ aix_winit,
188 	  aix_write,
189 	  aix_wdone,
190 	  aix_winfo },					/* CDDA_WR_AIX */
191 	{ alsa_winit,
192 	  alsa_write,
193 	  alsa_wdone,
194 	  alsa_winfo },					/* CDDA_WR_ALSA */
195 	{ osf1_winit,
196 	  osf1_write,
197 	  osf1_wdone,
198 	  osf1_winfo },					/* CDDA_WR_OSF1 */
199 	{ fp_winit,
200 	  fp_write,
201 	  fp_wdone,
202 	  fp_winfo }					/* CDDA_WR_FP */
203 };
204 
205 
206 /* Initialization done flag */
207 STATIC bool_t		cdda_initted = FALSE;
208 
209 /* File format description table */
210 STATIC filefmt_t	cdda_ffmt_tbl[MAX_FILEFMTS] = {
211     { FILEFMT_RAW,	"RAW",		".raw",  "CDDA Raw (LE)"             },
212     { FILEFMT_AU,	"AU",		".au",   "Sun/Next Audio"            },
213     { FILEFMT_WAV,	"WAV",		".wav",  "Wave"                      },
214     { FILEFMT_AIFF,	"AIFF",		".aiff", "Apple/SGI Audio"           },
215     { FILEFMT_AIFC,	"AIFF-C",	".aifc", "Apple/SGI Audio"           },
216     { FILEFMT_MP3,	"MP3",		".mp3",  "MPEG-1 Layer 3"            },
217     { FILEFMT_OGG,	"Ogg Vorbis",	".ogg",  "Ogg Vorbis"                },
218     { FILEFMT_FLAC,	"FLAC",		".flac", "Free Lossless Audio CODEC" },
219     { FILEFMT_AAC,	"AAC",		".aac",  "Advanced Audio Coding"     },
220     { FILEFMT_MP4,	"MP4",		".mp4",  "MP4"                       },
221 };
222 
223 /* Internal supported bitrates table for MP3 and OggVorbis */
224 #define NBITRATES	16
225 
226 STATIC int		_bitrates[NBITRATES] = {
227 	0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, -1
228 };
229 
230 STATIC int		cdda_nbitrates = 0;
231 
232 
233 /*********************
234  * Private functions *
235  *********************/
236 
237 
238 /*
239  * cdda_bitrates_init
240  *	Initialize the number of supported bitrates for MP3 and OggVorbis
241  *	output.
242  *
243  * Args:
244  *	None.
245  *
246  * Return:
247  *	Nothing.
248  */
249 STATIC void
cdda_bitrates_init(void)250 cdda_bitrates_init(void)
251 {
252 	cdda_nbitrates = NBITRATES - 1;
253 }
254 
255 
256 /**********************
257  *  Public functions  *
258  **********************/
259 
260 
261 /*
262  * cdda_capab
263  *	Query configured CDDA subsystem capabilities
264  *
265  * Args:
266  *	None.
267  *
268  * Return:
269  *	Bitmask of supported features
270  */
271 word32_t
cdda_capab(void)272 cdda_capab(void)
273 {
274 	word32_t	ret,
275 			(*func)(void);
276 
277 	if (app_data.cdda_method == CDDA_NONE)
278 		return 0;
279 
280 	if (app_data.cdda_method < CDDA_NONE ||
281 	    app_data.cdda_method >= CDDA_METHODS) {
282 		CDDA_WARNING(app_data.str_cddainit_fail);
283 		DBGPRN(DBG_GEN)(errfp, "Warning: %s\n",
284 				  app_data.str_cddainit_fail);
285 		return 0;
286 	}
287 
288 	func = cdda_calltbl[app_data.cdda_method].capab;
289 	if (func != NULL)
290 		ret = (*func)();
291 	else {
292 		CDDA_WARNING(app_data.str_cddainit_fail);
293 		DBGPRN(DBG_GEN)(errfp, "Warning: %s\n",
294 				  app_data.str_cddainit_fail);
295 		ret = 0;
296 	}
297 
298 	return (ret);
299 }
300 
301 
302 /*
303  * cdda_preinit
304  *	Early program startup initialization function.
305  *
306  * Args:
307  *	None.
308  *
309  * Return:
310  *	Nothing.
311  */
312 void
cdda_preinit(void)313 cdda_preinit(void)
314 {
315 	void	(*func)(void);
316 
317 	func = cdda_calltbl[app_data.cdda_method].preinit;
318 	if (func != NULL)
319 		(*func)();
320 }
321 
322 
323 /*
324  * cdda_init
325  *	Initialize the CDDA subsystem.
326  *
327  * Args:
328  *	s   - Pointer to the curstat_t structure.
329  *	clp - Pointer to cdda subsystem client registration info structure.
330  *
331  * Return:
332  *	FALSE - failure
333  *	TRUE  - success
334  */
335 bool_t
cdda_init(curstat_t * s,cdda_client_t * clp)336 cdda_init(curstat_t *s, cdda_client_t *clp)
337 {
338 	bool_t	ret,
339 		(*func)(curstat_t *);
340 
341 	if (cdda_initted)
342 		return TRUE;
343 
344 	cdda_clinfo = (cdda_client_t *)(void *) MEM_ALLOC(
345 		"cdda_client_t",
346 		sizeof(cdda_client_t)
347 	);
348 	if (cdda_clinfo == NULL)
349 		return FALSE;
350 
351 	(void) memcpy(cdda_clinfo, clp, sizeof(cdda_client_t));
352 
353 	if (app_data.cdda_method <= CDDA_NONE ||
354 	    app_data.cdda_method >= CDDA_METHODS)
355 		return FALSE;
356 
357 	func = cdda_calltbl[app_data.cdda_method].init;
358 	if (func != NULL)
359 		ret = (*func)(s);
360 	else
361 		ret = FALSE;
362 
363 	cdda_initted = ret;
364 	return ret;
365 }
366 
367 
368 /*
369  * cdda_halt
370  *	Shuts down the CDDA subsystem.
371  *
372  * Args:
373  *	devp - Device descriptor
374  *	s  - Pointer to the curstat_t structure
375  *
376  * Return:
377  *	Nothing.
378  */
379 void
cdda_halt(di_dev_t * devp,curstat_t * s)380 cdda_halt(di_dev_t *devp, curstat_t *s)
381 {
382 	void	(*func)(di_dev_t *, curstat_t *);
383 
384 	if (!cdda_initted)
385 		return;
386 
387 	func = cdda_calltbl[app_data.cdda_method].halt;
388 	if (func != NULL)
389 		(*func)(devp, s);
390 
391 	cdda_initted = FALSE;
392 }
393 
394 
395 /*
396  * cdda_play
397  *	Start playing.  No error checking is done on the output file path
398  *	or pipe program strings here.  The caller should pre-check these.
399  *
400  * Args:
401  *	devp - Device descriptor
402  *	s  - Pointer to the curstat_t structure
403  *	start_lba - Start logical block address
404  *	end_lba   - End logical block address
405  *
406  * Return:
407  *	FALSE - failure
408  *	TRUE  - success
409  */
410 bool_t
cdda_play(di_dev_t * devp,curstat_t * s,sword32_t start_lba,sword32_t end_lba)411 cdda_play(di_dev_t *devp, curstat_t *s, sword32_t start_lba, sword32_t end_lba)
412 {
413 	bool_t	(*func)(di_dev_t *, curstat_t *, sword32_t, sword32_t);
414 
415 	if (!cdda_initted)
416 		return FALSE;
417 
418 	/* If start == end, just return success */
419 	if (start_lba == end_lba)
420 		return TRUE;
421 
422 	func = cdda_calltbl[app_data.cdda_method].play;
423 	if (func != NULL)
424 		return (*func)(devp, s, start_lba, end_lba);
425 
426 	return FALSE;
427 }
428 
429 
430 /*
431  * cdda_pause_resume
432  *	Pause/resume playback
433  *
434  * Args:
435  *	devp   - Device descriptor
436  *	s      - Pointer to the curstat_t structure
437  *	resume - Whether to resume playback
438  *
439  * Return:
440  *	FALSE - failure
441  *	TRUE  - success
442  */
443 bool_t
cdda_pause_resume(di_dev_t * devp,curstat_t * s,bool_t resume)444 cdda_pause_resume(di_dev_t *devp, curstat_t *s, bool_t resume)
445 {
446 	bool_t	(*func)(di_dev_t *, curstat_t *, bool_t);
447 
448 	if (!cdda_initted)
449 		return FALSE;
450 
451 	func = cdda_calltbl[app_data.cdda_method].pause_resume;
452 	if (func != NULL)
453 		return (*func)(devp, s, resume);
454 
455 	return FALSE;
456 }
457 
458 
459 /*
460  * cdda_stop
461  *	Stop playback
462  *
463  * Args:
464  *	devp - Device descriptor
465  *	s    - Pointer to the curstat_t structure
466  *
467  * Return:
468  *	FALSE - failure
469  *	TRUE  - success
470  */
471 bool_t
cdda_stop(di_dev_t * devp,curstat_t * s)472 cdda_stop(di_dev_t *devp, curstat_t *s)
473 {
474 	bool_t	(*func)(di_dev_t *, curstat_t *);
475 
476 	if (!cdda_initted)
477 		return FALSE;
478 
479 	func = cdda_calltbl[app_data.cdda_method].stop;
480 	if (func != NULL)
481 		return (*func)(devp, s);
482 
483 	return FALSE;
484 }
485 
486 
487 /*
488  * cdda_vol
489  *	Change volume setting
490  *
491  * Args:
492  *	devp  - Device descriptor
493  *	s     - Pointer to the curstat_t structure
494  *	vol   - Desired volume level
495  *	query - Whether querying or setting the volume
496  *
497  * Return:
498  *	The volume level
499  */
500 int
cdda_vol(di_dev_t * devp,curstat_t * s,int vol,bool_t query)501 cdda_vol(di_dev_t *devp, curstat_t *s, int vol, bool_t query)
502 {
503 	int	(*func)(di_dev_t *, curstat_t *, int, bool_t);
504 
505 	if (!cdda_initted)
506 		return FALSE;
507 
508 	func = cdda_calltbl[app_data.cdda_method].vol;
509 	if (func != NULL)
510 		return (*func)(devp, s, vol, query);
511 
512 	return -1;
513 }
514 
515 
516 /*
517  * cdda_chroute
518  *	Change channel routing setting
519  *
520  * Args:
521  *	devp - Device descriptor
522  *	s    - Pointer to the curstat_t structure
523  *
524  * Return:
525  *	FALSE - failure
526  *	TRUE  - success
527  */
528 bool_t
cdda_chroute(di_dev_t * devp,curstat_t * s)529 cdda_chroute(di_dev_t *devp, curstat_t *s)
530 {
531 	bool_t	(*func)(di_dev_t *, curstat_t *);
532 
533 	if (!cdda_initted)
534 		return FALSE;
535 
536 	func = cdda_calltbl[app_data.cdda_method].chroute;
537 	if (func != NULL)
538 		return (*func)(devp, s);
539 
540 	return FALSE;
541 }
542 
543 
544 /*
545  * cdda_att
546  *	Change CDDA attenuator setting
547  *
548  * Args:
549  *	s - Pointer to the curstat_t structure
550  *
551  * Return:
552  *	Nothing.
553  */
554 void
cdda_att(curstat_t * s)555 cdda_att(curstat_t *s)
556 {
557 	void	(*func)(curstat_t *);
558 
559 	if (!cdda_initted)
560 		return;
561 
562 	func = cdda_calltbl[app_data.cdda_method].cdda_att;
563 	if (func != NULL)
564 		(*func)(s);
565 }
566 
567 
568 /*
569  * cdda_outport
570  *	Change CDDA output port setting
571  *
572  * Args:
573  *	None.
574  *
575  * Return:
576  *	Nothing.
577  */
578 void
cdda_outport(void)579 cdda_outport(void)
580 {
581 	void	(*func)(void);
582 
583 	if (!cdda_initted)
584 		return;
585 
586 	func = cdda_calltbl[app_data.cdda_method].outport;
587 	if (func != NULL)
588 		(*func)();
589 }
590 
591 
592 /*
593  * cdda_getstatus
594  *	Get playback status
595  *
596  * Args:
597  *	devp - Device descriptor
598  *	s    - Pointer to the curstat_t structure
599  *	sp - cdstat_t return info structure
600  *
601  * Return:
602  *	FALSE - failure
603  *	TRUE  - success
604  */
605 bool_t
cdda_getstatus(di_dev_t * devp,curstat_t * s,cdstat_t * sp)606 cdda_getstatus(di_dev_t *devp, curstat_t *s, cdstat_t *sp)
607 {
608 	bool_t	(*func)(di_dev_t *, curstat_t *, cdstat_t *);
609 
610 	if (!cdda_initted)
611 		return FALSE;
612 
613 	func = cdda_calltbl[app_data.cdda_method].getstatus;
614 	if (func != NULL)
615 		return (*func)(devp, s, sp);
616 
617 	return FALSE;
618 }
619 
620 
621 /*
622  * cdda_debug
623  *	Debug level change notification function
624  *
625  * Args:
626  *	lev - The new debug level
627  *
628  * Return:
629  *	Nothing.
630  */
631 void
cdda_debug(word32_t lev)632 cdda_debug(word32_t lev)
633 {
634 	void	(*func)(word32_t);
635 
636 	if (!cdda_initted)
637 		return;
638 
639 	func = cdda_calltbl[app_data.cdda_method].debug;
640 	if (func != NULL)
641 		(*func)(lev);
642 }
643 
644 
645 /*
646  * cdda_info
647  *	Obtain CDDA configuration information
648  *
649  * Args:
650  *	None.
651  *
652  * Return:
653  *	Pointer to an informational text string buffer.
654  */
655 char *
cdda_info(void)656 cdda_info(void)
657 {
658 	void		(*func)(char *);
659 	static bool_t	first = TRUE;
660 	static char	str[STR_BUF_SZ * 2];
661 
662 	if (first) {
663 		/* Set up info string */
664 		first = FALSE;
665 		(void) strcpy(str, "CDDA method: ");
666 
667 		if (app_data.cdda_method < CDDA_NONE ||
668 		    app_data.cdda_method >= CDDA_METHODS) {
669 			(void) strcat(str, "not configured\n");
670 		}
671 		else {
672 			func = cdda_calltbl[app_data.cdda_method].info;
673 			if (func == NULL)
674 				(void) strcat(str, "not configured\n");
675 			else
676 				(*func)(str);
677 		}
678 	}
679 
680 	return (str);
681 }
682 
683 
684 /*
685  * cdda_initipc
686  *	Set up inter-process/thread shared memory and sychronization
687  *	based on mode.
688  *
689  * Args:
690  *	Pointer to the cd_state_t structure
691  *
692  * Return:
693  *	Nothing.
694  */
695 int
cdda_initipc(cd_state_t * cdp)696 cdda_initipc(cd_state_t *cdp)
697 {
698 	int	(*func)(cd_state_t *);
699 
700 	if (!cdda_initted)
701 		return -1;
702 
703 	func = cdda_calltbl[app_data.cdda_method].initipc;
704 	if (func != NULL)
705 		return (*func)(cdp);
706 	else
707 		return -1;
708 }
709 
710 
711 /*
712  * cdda_waitsem
713  *	Wait for a semaphore.
714  *
715  * Args:
716  *	id  - Semaphore id
717  *	sem - Semaphore to wait on
718  *
719  * Return:
720  *	Nothing.
721  */
722 void
cdda_waitsem(int id,int sem)723 cdda_waitsem(int id, int sem)
724 {
725 	void	(*func)(int, int);
726 
727 	if (!cdda_initted)
728 		return;
729 
730 	func = cdda_calltbl[app_data.cdda_method].waitsem;
731 	if (func != NULL)
732 		(*func)(id, sem);
733 }
734 
735 
736 /*
737  * cdda_postsem
738  *	Release a semaphore.
739  *
740  * Args:
741  *	id  - Semaphore id
742  *	sem - Semaphore to release
743  *
744  * Return:
745  *	Nothing.
746  */
747 void
cdda_postsem(int id,int sem)748 cdda_postsem(int id, int sem)
749 {
750 	void	(*func)(int, int);
751 
752 	if (!cdda_initted)
753 		return;
754 
755 	func = cdda_calltbl[app_data.cdda_method].postsem;
756 	if (func != NULL)
757 		(*func)(id, sem);
758 }
759 
760 
761 /*
762  * cdda_yield
763  *	Let other processes/threads run.
764  *
765  * Args:
766  *	None.
767  *
768  * Return:
769  *	Nothing.
770  */
771 void
cdda_yield(void)772 cdda_yield(void)
773 {
774 	void	(*func)(void);
775 
776 	if (!cdda_initted)
777 		return;
778 
779 	func = cdda_calltbl[app_data.cdda_method].yield;
780 	if (func != NULL)
781 		(*func)();
782 }
783 
784 
785 /*
786  * cdda_kill
787  *	Terminate a process or thread, depending on the configured mode.
788  *
789  * Args:
790  *	id - The process or thread id
791  *	sig - The signal
792  *
793  * Return:
794  *	Nothing.
795  */
796 void
cdda_kill(thid_t id,int sig)797 cdda_kill(thid_t id, int sig)
798 {
799 	void	(*func)(thid_t, int);
800 
801 	if (!cdda_initted)
802 		return;
803 
804 	func = cdda_calltbl[app_data.cdda_method].kill;
805 	if (func != NULL)
806 		(*func)(id, sig);
807 }
808 
809 
810 /*
811  * cdda_filefmt_supp
812  *	Given a CDDA output file format value, return a boolean indicating
813  *	whether that format is supported in this compilation.
814  *
815  * Args:
816  *	fmt - The format value
817  *
818  * Return:
819  *	TRUE  - Format supported
820  *	FALSE - Format not supported
821  */
822 bool_t
cdda_filefmt_supp(int fmt)823 cdda_filefmt_supp(int fmt)
824 {
825 	static bool_t	vorb_first = TRUE;
826 	static bool_t	flac_first = TRUE;
827 	static bool_t	lame_first = TRUE;
828 	static bool_t	faac_first = TRUE;
829 #ifdef HAS_LAME
830 	unsigned int	lame_ver;
831 #endif
832 #ifdef HAS_FAAC
833 	static bool_t	aacsupp = FALSE,
834 			mp4supp = FALSE;
835 	unsigned int	faac_ver;
836 #endif
837 
838 	switch (fmt) {
839 	case FILEFMT_RAW:
840 	case FILEFMT_AU:
841 	case FILEFMT_WAV:
842 	case FILEFMT_AIFF:
843 	case FILEFMT_AIFC:
844 		return TRUE;
845 
846 	case FILEFMT_MP3:
847 #ifdef HAS_LAME
848 		if (lame_first) {
849 			int	i;
850 
851 			lame_first = FALSE;
852 
853 			if ((lamepath = getenv("LAME_PATH")) != NULL) {
854 				/* Check if specified program is executable */
855 				if (!util_checkcmd(lamepath))
856 					lamepath = NULL;
857 			}
858 			else for (i = 0; lameprogs[i] != NULL; i++) {
859 				lamepath = util_findcmd(lameprogs[i]);
860 				if (lamepath != NULL)
861 					break;
862 			}
863 
864 			if (lamepath == NULL) {
865 				DBGPRN(DBG_GEN|DBG_SND)(errfp,
866 					"\nLAME encoder:\n"
867 					"\tProgram:\t\t\tNot found\n"
868 					"\tMP3 file format disabled\n"
869 				);
870 			}
871 			else if (!if_lame_verchk(lamepath, &lame_ver)) {
872 				lamepath = NULL;
873 			}
874 			else {
875 				DBGPRN(DBG_GEN|DBG_SND)(errfp,
876 					"\nLAME encoder:\n"
877 					"\tProgram:\t\t\t%s\n"
878 					"\tVersion:\t\t\t%u.%u.%u\n",
879 					lamepath,
880 					ENCVER_MAJ(lame_ver),
881 					ENCVER_MIN(lame_ver),
882 					ENCVER_TINY(lame_ver)
883 				);
884 			}
885 		}
886 
887 		return ((bool_t) (lamepath != NULL));
888 #else
889 		if (lame_first) {
890 			lame_first = FALSE;
891 			DBGPRN(DBG_GEN|DBG_SND)(errfp,
892 				"\nLAME encoder:\n"
893 				"\tInterface:\t\t\tDisabled\n"
894 				"\tMP3 file format disabled\n"
895 			);
896 		}
897 		return FALSE;
898 #endif	/* HAS_LAME */
899 
900 	case FILEFMT_OGG:
901 #ifdef HAS_VORBIS
902 		if (vorb_first) {
903 			vorb_first = FALSE;
904 			DBGPRN(DBG_GEN|DBG_SND)(errfp,
905 				"\nOgg Vorbis encoder:\n"
906 				"\tEmbedded:\t\t\tTrue\n"
907 			);
908 		}
909 		return TRUE;
910 #else
911 		if (vorb_first) {
912 			vorb_first = FALSE;
913 			DBGPRN(DBG_GEN|DBG_SND)(errfp,
914 				"\nOgg Vorbis encoder:\n"
915 				"\tEmbedded:\t\t\tFalse\n"
916 				"\tOgg Vorbis file format disabled\n"
917 			);
918 		}
919 		return FALSE;
920 #endif	/* HAS_VORBIS */
921 
922 	case FILEFMT_FLAC:
923 #ifdef HAS_FLAC
924 		if (flac_first) {
925 			flac_first = FALSE;
926 			DBGPRN(DBG_GEN|DBG_SND)(errfp,
927 				"\nFLAC encoder:\n"
928 				"\tEmbedded:\t\t\tTrue\n"
929 			);
930 		}
931 		return TRUE;
932 #else
933 		if (flac_first) {
934 			flac_first = FALSE;
935 			DBGPRN(DBG_GEN|DBG_SND)(errfp,
936 				"\nFLAC encoder:\n"
937 				"\tEmbedded:\t\t\tFalse\n"
938 				"\tFLAC file format disabled\n"
939 			);
940 		}
941 		return FALSE;
942 #endif
943 
944 	case FILEFMT_AAC:
945 	case FILEFMT_MP4:
946 #ifdef HAS_FAAC
947 		if (faac_first) {
948 			int	i;
949 
950 			faac_first = FALSE;
951 
952 			if ((faacpath = getenv("FAAC_PATH")) != NULL) {
953 				/* Check if specified program is executable */
954 				if (!util_checkcmd(faacpath))
955 					faacpath = NULL;
956 			}
957 			else for (i = 0; faacprogs[i] != NULL; i++) {
958 				faacpath = util_findcmd(faacprogs[i]);
959 				if (faacpath != NULL)
960 					break;
961 			}
962 
963 			if (faacpath == NULL) {
964 				DBGPRN(DBG_GEN|DBG_SND)(errfp,
965 					"\nFAAC encoder:\n"
966 					"\tProgram:\t\t\tNot found\n"
967 					"\tMPEG-2/4 file formats disabled\n"
968 				);
969 			}
970 			else if (!if_faac_verchk(faacpath, &faac_ver,
971 						 &mp4supp)) {
972 				faacpath = NULL;
973 			}
974 			else {
975 				aacsupp = TRUE;
976 
977 				DBGPRN(DBG_GEN|DBG_SND)(errfp,
978 					"\nFAAC encoder:\n"
979 					"\tProgram:\t\t\t%s\n"
980 					"\tVersion:\t\t\t%u.%u.%u\n"
981 					"\tAAC support:\t\t\t%s\n"
982 					"\tMP4 support:\t\t\t%s\n",
983 					faacpath,
984 					ENCVER_MAJ(faac_ver),
985 					ENCVER_MIN(faac_ver),
986 					ENCVER_TINY(faac_ver),
987 					aacsupp ? "True" : "False",
988 					mp4supp ? "True" : "False"
989 				);
990 			}
991 		}
992 
993 		if (fmt == FILEFMT_MP4)
994 			return (mp4supp);
995 		else
996 			return (aacsupp);
997 #else
998 		if (faac_first) {
999 			faac_first = FALSE;
1000 			DBGPRN(DBG_GEN|DBG_SND)(errfp,
1001 				"\nFAAC encoder:\n"
1002 				"\tInterface:\t\t\tDisabled\n"
1003 				"\tAAC/MP4 file formats disabled\n"
1004 			);
1005 		}
1006 		return FALSE;
1007 #endif	/* HAS_FAAC */
1008 
1009 	default:
1010 		return FALSE;
1011 	}
1012 	/*NOTREACHED*/
1013 }
1014 
1015 
1016 /*
1017  * cdda_filefmt
1018  *	Given a CDDA file format code, return a pointer to an
1019  *	associated filefmt_t structure.
1020  *
1021  * Args:
1022  *	fmt - The file format code
1023  *
1024  * Return:
1025  *	Pointer to the filefmt_t structure, or NULL if fmt is invalid.
1026  */
1027 filefmt_t *
cdda_filefmt(int fmt)1028 cdda_filefmt(int fmt)
1029 {
1030 	if (fmt < 0 || fmt >= MAX_FILEFMTS)
1031 		return NULL;
1032 
1033 	return (&cdda_ffmt_tbl[fmt]);
1034 }
1035 
1036 
1037 /*
1038  * cdda_bitrates
1039  *	Return the number of supported bitrates for MP3 and OggVorbis
1040  *
1041  * Args:
1042  *	None.
1043  *
1044  * Return:
1045  *	The number of supported bitrates
1046  */
1047 int
cdda_bitrates(void)1048 cdda_bitrates(void)
1049 {
1050 	if (cdda_nbitrates == 0)
1051 		cdda_bitrates_init();
1052 
1053 	return (cdda_nbitrates);
1054 }
1055 
1056 
1057 /*
1058  * cdda_bitrate_val
1059  *	Given a bitrate index, return the actual bitrate value
1060  *
1061  * Args:
1062  *	idx - The bitrate table index
1063  *
1064  * Return:
1065  *	The bitrate in kb/s
1066  */
1067 int
cdda_bitrate_val(int idx)1068 cdda_bitrate_val(int idx)
1069 {
1070 	if (cdda_nbitrates == 0)
1071 		cdda_bitrates_init();
1072 
1073 	if (idx < 0 || idx >= cdda_nbitrates)
1074 		return -1;
1075 
1076 	return (_bitrates[idx]);
1077 }
1078 
1079 
1080 /*
1081  * cdda_bitrate_name
1082  *	Given a bitrate index, return the actual bitrate name string
1083  *
1084  * Args:
1085  *	idx - The bitrate table index
1086  *
1087  * Return:
1088  *	Pointer to the bitrate string.  This points to an internal buffer
1089  *	that is overwritten on each call.
1090  */
1091 char *
cdda_bitrate_name(int idx)1092 cdda_bitrate_name(int idx)
1093 {
1094 	static char	name[8];
1095 
1096 	if (cdda_nbitrates == 0)
1097 		cdda_bitrates_init();
1098 
1099 	if (idx < 0 || idx >= cdda_nbitrates)
1100 		return NULL;
1101 
1102 	(void) sprintf(name, "%d", _bitrates[idx]);
1103 	return (name);
1104 }
1105 
1106 
1107 /*
1108  * cdda_heartbeat_interval
1109  *	Compute the number of CDDA read/write loop iterations per
1110  *	hearbeat.  This is based on the read chunk size.
1111  *
1112  * Args:
1113  *	fps - The current transfer rate in frames per second
1114  *
1115  * Return:
1116  *	A integer loop iteration count.
1117  */
1118 int
cdda_heartbeat_interval(int fps)1119 cdda_heartbeat_interval(int fps)
1120 {
1121 	return ((fps / app_data.cdda_readchkblks) + 1);
1122 }
1123 
1124 
1125 /*
1126  * cdda_heartbeat
1127  *	Set a heartbeat timestamp in the location specified.  This is
1128  *	used to check if either a CDDA read or write thread is hung or
1129  *	dead.
1130  *
1131  * Args:
1132  *	hbloc  - pointer to location where the timestamp is to be written.
1133  *	hbtype - CDDA_HB_READER or CDDA_HB_WRITER
1134  *
1135  * Return:
1136  *	Nothing.
1137  */
1138 void
cdda_heartbeat(time_t * hbloc,int hbtype)1139 cdda_heartbeat(time_t *hbloc, int hbtype)
1140 {
1141 	if (hbloc == NULL)
1142 		return;
1143 
1144 	*hbloc = time(NULL);
1145 
1146 	DBGPRN(DBG_SND)(errfp, "\nCDDA thread heartbeat: %s\n",
1147 		(hbtype == CDDA_HB_READER) ? "reader" : "writer");
1148 }
1149 
1150