1 /*
2  *   libdi - CD Audio Device Interface Library
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 __LIBDI_H__
22 #define __LIBDI_H__
23 
24 #ifndef lint
25 static char *_libdi_h_ident_ = "@(#)libdi.h	6.94 04/03/05";
26 #endif
27 
28 /* Max number of libdi modules */
29 #define MAX_METHODS	4
30 
31 /*
32  * Supported libdi methods
33  *
34  * Comment out any of these to remove support for a method.
35  * Removing unused methods can reduce the executable
36  * binary size and run-time memory usage.  At least one
37  * method must be defined.
38  *
39  * Note: If compiling for DEMO_ONLY or on a non-supported OS
40  * platform, DI_SCSIPT must be defined.
41  */
42 #if !defined(__QNX__)
43 #define DI_SCSIPT	0	/* SCSI pass-through method */
44 #endif
45 #if defined(_SUNOS4) || defined(_SOLARIS) || \
46     defined(_LINUX)  || defined(__QNX__)
47 #define DI_SLIOC	1	/* SunOS/Solaris/Linux/QNX ioctl method */
48 #endif
49 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
50 #define DI_FBIOC	2	/* FreeBSD/NetBSD/OpenBSD ioctl method */
51 #endif
52 #if defined(_AIX) && defined(AIX_IDE)
53 #define DI_AIXIOC	3	/* AIX IDE ioctl method */
54 #endif
55 
56 
57 /*
58  * Multi-CD medium change methods
59  */
60 #define MAX_CHG_METHODS	4
61 
62 #define CHG_NONE	0	/* Changer controls not supported */
63 #define CHG_SCSI_LUN	1	/* SCSI LUN addressing method */
64 #define CHG_SCSI_MEDCHG	2	/* SCSI Medium changer device method */
65 #define CHG_OS_IOCTL	3	/* OS-ioctl method */
66 
67 
68 /* Application name */
69 #define APPNAME		"CD audio"
70 
71 
72 /* Play audio format codes */
73 #define ADDR_BLK	0x01	/* block address specified */
74 #define ADDR_MSF	0x02	/* MSF address specified */
75 #define ADDR_TRKIDX	0x04	/* track/index numbers specified */
76 #define ADDR_OPTEND	0x80	/* End address can be ignored */
77 
78 
79 /* Slider control flags */
80 #define WARP_VOL	0x1	/* Set volume slider thumb */
81 #define WARP_BAL	0x2	/* Set balance slider thumb */
82 
83 
84 /* Device capabilities: These should match similar defines in cdda_d/cdda.h */
85 #define CAPAB_PLAYAUDIO	0x01	/* Can play CD audio */
86 #define CAPAB_RDCDDA	0x02	/* Can read CDDA from drive */
87 #define CAPAB_WRDEV	0x10	/* Can write audio stream to sound device */
88 #define CAPAB_WRFILE	0x20	/* Can write audio stream to file */
89 #define CAPAB_WRPIPE	0x40	/* Can pipe audio stream to a program */
90 
91 
92 /* Misc constants */
93 #define MAX_SRCH_BLKS	225	/* max search play blks per sample */
94 #define MAX_RECOVERR	20	/* Max number of err recovery tries */
95 #define ERR_SKIPBLKS	10	/* Number of frame to skip on error */
96 #define ERR_CLRTHRESH	1500	/* If there hasn't been any errors
97 				 * for this many blocks of audio
98 				 * playback, then the previous errors
99 				 * count is cleared.
100 				 */
101 #define CLIP_FRAMES	10	/* Frames to clip from end */
102 #define DEF_CACHE_TIMEOUT 7	/* Default local cache timeout (days) */
103 #define DEF_SRV_TIMEOUT	60	/* Default service timeout (seconds) */
104 
105 
106 
107 /* CDDB/Program macros */
108 #define DBCLEAR(s, b)		{					\
109 	if (di_clinfo != NULL && di_clinfo->dbclear != NULL)		\
110 		di_clinfo->dbclear((s), (b));				\
111 }
112 #define DBGET(s)		{					\
113 	if (di_clinfo != NULL && di_clinfo->dbget != NULL)		\
114 		di_clinfo->dbget(s);					\
115 }
116 #define PROGCLEAR(s)		{					\
117 	if (di_clinfo != NULL && di_clinfo->progclear != NULL)		\
118 		di_clinfo->progclear(s);				\
119 }
120 #define PROGGET(s)		{					\
121 	if (di_clinfo != NULL && di_clinfo->progget != NULL)		\
122 		di_clinfo->progget(s);					\
123 }
124 #define STOPSCAN(s)		{					\
125 	if (di_clinfo != NULL && di_clinfo->chgr_scan_stop != NULL)	\
126 		di_clinfo->chgr_scan_stop(s);				\
127 }
128 
129 
130 /* Message dialog macros */
131 #define DI_FATAL(msg)		{					\
132 	if (di_clinfo != NULL && di_clinfo->fatal_msg != NULL)		\
133 		di_clinfo->fatal_msg(app_data.str_fatal, (msg));	\
134 	else {								\
135 		(void) fprintf(errfp, "Fatal: %s\n", (msg));		\
136 		_exit(1);						\
137 	}								\
138 }
139 #define DI_WARNING(msg)		{					\
140 	if (di_clinfo != NULL && di_clinfo->warning_msg != NULL)	\
141 		di_clinfo->warning_msg(app_data.str_warning, (msg));	\
142 	else								\
143 		(void) fprintf(errfp, "Warning: %s\n", (msg));		\
144 }
145 #define DI_INFO(msg)		{					\
146 	if (di_clinfo != NULL && di_clinfo->info_msg != NULL)		\
147 		di_clinfo->info_msg(app_data.str_info, (msg));		\
148 	else								\
149 		(void) fprintf(errfp, "Info: %s\n", (msg));		\
150 }
151 #define DI_INFO2(msg, txt)	{					\
152 	if (di_clinfo != NULL && di_clinfo->info2_msg != NULL)		\
153 		di_clinfo->info2_msg(app_data.str_info, (msg), (txt));	\
154 	else								\
155 		(void) fprintf(errfp, "Info: %s\n%s\n", (msg), (txt));	\
156 }
157 
158 
159 /* GUI macros */
160 #define DO_BEEP()		{					\
161 	if (di_clinfo != NULL && di_clinfo->beep != NULL)		\
162 		di_clinfo->beep();					\
163 }
164 #define SET_LOCK_BTN(state)	{					\
165 	if (di_clinfo != NULL && di_clinfo->set_lock_btn != NULL)	\
166 		di_clinfo->set_lock_btn(state);				\
167 }
168 #define SET_SHUFFLE_BTN(state)	{					\
169 	if (di_clinfo != NULL && di_clinfo->set_shuffle_btn != NULL)	\
170 		di_clinfo->set_shuffle_btn(state);			\
171 }
172 #define SET_VOL_SLIDER(val)	{					\
173 	if (di_clinfo != NULL && di_clinfo->set_vol_slider != NULL)	\
174 		di_clinfo->set_vol_slider(val);				\
175 }
176 #define SET_BAL_SLIDER(val)	{					\
177 	if (di_clinfo != NULL && di_clinfo->set_bal_slider != NULL)	\
178 		di_clinfo->set_bal_slider(val);				\
179 }
180 #define DPY_ALL(s)		{					\
181 	if (di_clinfo != NULL && di_clinfo->dpy_all != NULL)		\
182 		di_clinfo->dpy_all(s);					\
183 }
184 #define DPY_DISC(s)		{					\
185 	if (di_clinfo != NULL && di_clinfo->dpy_disc != NULL)		\
186 		di_clinfo->dpy_disc(s);				\
187 }
188 #define DPY_TRACK(s)		{					\
189 	if (di_clinfo != NULL && di_clinfo->dpy_track != NULL)		\
190 		di_clinfo->dpy_track(s);				\
191 }
192 #define DPY_INDEX(s)		{					\
193 	if (di_clinfo != NULL && di_clinfo->dpy_index != NULL)		\
194 		di_clinfo->dpy_index(s);				\
195 }
196 #define DPY_TIME(s, b)		{					\
197 	if (di_clinfo != NULL && di_clinfo->dpy_time != NULL)		\
198 		di_clinfo->dpy_time((s), (b));				\
199 }
200 #define DPY_PROGMODE(s, b)		{				\
201 	if (di_clinfo != NULL && di_clinfo->dpy_progmode != NULL)	\
202 		di_clinfo->dpy_progmode((s), (b));			\
203 }
204 #define DPY_PLAYMODE(s, b)		{				\
205 	if (di_clinfo != NULL && di_clinfo->dpy_playmode != NULL)	\
206 		di_clinfo->dpy_playmode((s), (b));			\
207 }
208 #define DPY_RPTCNT(s)		{					\
209 	if (di_clinfo != NULL && di_clinfo->dpy_rptcnt != NULL)		\
210 		di_clinfo->dpy_rptcnt(s);				\
211 }
212 
213 
214 /*
215  * CD-TEXT information structures
216  */
217 typedef struct {
218 	char		*title;			/* Title */
219 	char		*performer;		/* Performer name */
220 	char		*songwriter;		/* Songwriter name */
221 	char		*composer;		/* Composer name */
222 	char		*arranger;		/* Arranger name */
223 	char		*message;		/* Message */
224 	char		*catno;			/* UPC/EAN or ISRC code */
225 } di_cdtext_inf_t;
226 
227 typedef struct {
228 	bool_t		cdtext_valid;		/* Has CD-TEXT data */
229 	bool_t		rsvd[3];		/* reserved */
230 	char		*ident;			/* Disc identification info */
231 	di_cdtext_inf_t	disc;			/* Disc information */
232 	di_cdtext_inf_t	track[MAXTRACK];	/* Track information */
233 } di_cdtext_t;
234 
235 
236 /*
237  * Jump table structure for libdi interface
238  */
239 typedef struct {
240 	void		(*load_cdtext)(curstat_t *, di_cdtext_t *);
241 	bool_t		(*playmode)(curstat_t *);
242 	bool_t		(*check_disc)(curstat_t *);
243 	void		(*status_upd)(curstat_t *);
244 	void		(*lock)(curstat_t *, bool_t);
245 	void		(*repeat)(curstat_t *, bool_t);
246 	void		(*shuffle)(curstat_t *, bool_t);
247 	void		(*load_eject)(curstat_t *);
248 	void		(*ab)(curstat_t *);
249 	void		(*sample)(curstat_t *);
250 	void		(*level)(curstat_t *, byte_t, bool_t);
251 	void		(*play_pause)(curstat_t *);
252 	void		(*stop)(curstat_t *, bool_t);
253 	void		(*chgdisc)(curstat_t *);
254 	void		(*prevtrk)(curstat_t *);
255 	void		(*nexttrk)(curstat_t *);
256 	void		(*previdx)(curstat_t *);
257 	void		(*nextidx)(curstat_t *);
258 	void		(*rew)(curstat_t *, bool_t);
259 	void		(*ff)(curstat_t *, bool_t);
260 	void		(*warp)(curstat_t *);
261 	void		(*route)(curstat_t *);
262 	void		(*mute_on)(curstat_t *);
263 	void		(*mute_off)(curstat_t *);
264 	void		(*cddajitter)(curstat_t *);
265 	void		(*debug)(void);
266 	void		(*start)(curstat_t *);
267 	void		(*icon)(curstat_t *, bool_t);
268 	void		(*halt)(curstat_t *);
269 	char *		(*methodstr)(void);
270 } di_tbl_t;
271 
272 
273 /*
274  * Jump table for libdi initialization
275  */
276 typedef struct {
277 	void	(*init)(curstat_t *, di_tbl_t *);
278 } diinit_tbl_t;
279 
280 
281 /*
282  * Callbacks into the application
283  */
284 typedef struct {
285 	word32_t	capab;		/* Device capabilities bitmask */
286 	curstat_t *	(*curstat_addr)(void);			/* Required */
287 	void		(*quit)(curstat_t *);			/* Required */
288 	long		(*timeout)(word32_t, void (*)(), byte_t *);
289 	void		(*untimeout)(long);
290 	void		(*dbclear)(curstat_t *, bool_t);
291 	void		(*dbget)(curstat_t *);
292 	void		(*progclear)(curstat_t *);
293 	void		(*progget)(curstat_t *);
294 	void		(*chgr_scan_stop)(curstat_t *);
295 	bool_t		(*mkoutpath)(curstat_t *);
296 	bool_t		(*ckpipeprog)(curstat_t *);
297 	void		(*fatal_msg)(char *, char *);
298 	void		(*warning_msg)(char *, char *);
299 	void		(*info_msg)(char *, char *);
300 	void		(*info2_msg)(char *, char *, char *);
301 	void		(*beep)(void);
302 	void		(*set_lock_btn)(bool_t);
303 	void		(*set_shuffle_btn)(bool_t);
304 	void		(*set_vol_slider)(int);
305 	void		(*set_bal_slider)(int);
306 	void		(*dpy_all)(curstat_t *);
307 	void		(*dpy_disc)(curstat_t *);
308 	void		(*dpy_track)(curstat_t *);
309 	void		(*dpy_index)(curstat_t *);
310 	void		(*dpy_time)(curstat_t *, bool_t);
311 	void		(*dpy_progmode)(curstat_t *, bool_t);
312 	void		(*dpy_playmode)(curstat_t *, bool_t);
313 	void		(*dpy_rptcnt)(curstat_t *);
314 } di_client_t;
315 
316 
317 /* Used for the role field of di_dev_t */
318 #define DI_ROLE_MAIN	1		/* main control thread */
319 #define DI_ROLE_READER	2		/* CD reader thread */
320 
321 
322 /*
323  * Device descriptor structure, returned by pthru_open()
324  */
325 typedef struct di_dev {
326 	int		fd;		/* primary file descriptor */
327 	int		fd2;		/* secondary file descriptor */
328 	int		role;		/* enable I/O for which role */
329 	word32_t	flags;		/* flags */
330 	char		*path;		/* path name string */
331 	char		*auxpath;	/* secondary path name string */
332 	void		*auxdesc;	/* secondary descriptor */
333 	int		bus;		/* bus number */
334 	int		target;		/* target id number */
335 	int		lun;		/* logical unit number */
336 	int		val;		/* platform-specific field */
337 	int		val2;		/* platform-specific field */
338 } di_dev_t;
339 
340 
341 /*
342  * Public function prototypes: libdi external calling interface.
343  */
344 extern void		di_init(di_client_t *);
345 extern bool_t		di_bitrate_valid(int);
346 extern void		di_load_cdtext(curstat_t *, di_cdtext_t *);
347 extern void		di_clear_cdtext(di_cdtext_t *);
348 extern bool_t		di_playmode(curstat_t *);
349 extern bool_t		di_check_disc(curstat_t *);
350 extern void		di_status_upd(curstat_t *);
351 extern void		di_lock(curstat_t *, bool_t);
352 extern void		di_repeat(curstat_t *, bool_t);
353 extern void		di_shuffle(curstat_t *, bool_t);
354 extern void		di_load_eject(curstat_t *);
355 extern void		di_ab(curstat_t *);
356 extern void		di_sample(curstat_t *);
357 extern void		di_level(curstat_t *, byte_t, bool_t);
358 extern void		di_play_pause(curstat_t *);
359 extern void		di_stop(curstat_t *, bool_t);
360 extern void		di_chgdisc(curstat_t *);
361 extern void		di_prevtrk(curstat_t *);
362 extern void		di_nexttrk(curstat_t *);
363 extern void		di_previdx(curstat_t *);
364 extern void		di_nextidx(curstat_t *);
365 extern void		di_rew(curstat_t *, bool_t);
366 extern void		di_ff(curstat_t *, bool_t);
367 extern void		di_warp(curstat_t *);
368 extern void		di_route(curstat_t *);
369 extern void		di_mute_on(curstat_t *);
370 extern void		di_mute_off(curstat_t *);
371 extern void		di_cddajitter(curstat_t *);
372 extern void		di_debug(void);
373 extern void		di_start(curstat_t *);
374 extern void		di_icon(curstat_t *, bool_t);
375 extern void		di_halt(curstat_t *);
376 extern void		di_dump_curstat(curstat_t *);
377 extern void		di_common_parmload(char *, bool_t, bool_t);
378 extern void		di_devspec_parmload(char *, bool_t, bool_t);
379 extern void		di_common_parmsave(char *);
380 extern void		di_devspec_parmsave(char *);
381 extern bool_t		di_devlock(curstat_t *, char *);
382 extern void		di_devunlock(curstat_t *);
383 extern di_dev_t		*di_devalloc(char *);
384 extern void		di_devfree(di_dev_t *);
385 extern char		*di_methodstr(void);
386 extern bool_t		di_isdemo(void);
387 extern int		di_curtrk_pos(curstat_t *);
388 extern int		di_curprog_pos(curstat_t *);
389 extern void		di_clear_cdinfo(curstat_t *, bool_t);
390 extern byte_t		di_get_cdinfo(curstat_t *);
391 extern bool_t		di_prepare_cdda(curstat_t *);
392 extern void		di_reset_curstat(curstat_t *, bool_t, bool_t);
393 extern void		di_reset_shuffle(curstat_t *);
394 
395 #endif	/* __LIBDI_H__ */
396 
397