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