1 /*
2  * cdrom.c: This file handles all the CDROM routines, in BitchX
3  *
4  * Written by Tom Zickel
5  * a.k.a. IceBreak on the irc
6  *
7  * Copyright(c) 1996
8  * Modified Colten Edwards aka panasync.
9  *
10  */
11 
12 /* Version 0.2 22/07/97 written by IceBreak (ice_break@hotmail.com) */
13 /* 0.2: Finnally I rewrote the playing method inside the cdrom player to work
14  *      with msf instead of lba, and frames instead of tracks, this should fix
15  *      all the compability problems that the cdroms player had with some
16  *      cdroms. I also fixed some bugs and better problem messages.
17  * FreeBSD support added by Eric A. Griff aka setjmp!eagriff@*.global2000.net
18  *
19 */
20 
21 #include "irc.h"
22 static char cvsrevision[] = "$Id: cdrom.c 3 2008-02-25 09:49:14Z keaston $";
23 CVS_REVISION(cdrom_c)
24 #include "struct.h"
25 
26 #include "ircaux.h"
27 #include "cdrom.h"
28 #include "output.h"
29 #include "misc.h"
30 #include "vars.h"
31 #define MAIN_SOURCE
32 #include "modval.h"
33 
34 #define cparse(s) convert_output_format(s, NULL, NULL)
35 
36 static int drive = 0;
37 
38 static char cdrom_prompt[]="%gC%Gd%gROM%w";
39 
40 #ifndef __FreeBSD__
41 static struct cdrom_tochdr hdr;
42 static struct cdrom_ti ti;
43 #else
44 static struct ioc_toc_header hdr;
45 #endif
46 
47 static struct cdrom_etocentry TocEntry[101];
48 
49 int cd_init(char *);
50 
51 #ifndef __FreeBSD__
play_chunk(int start,int end)52 void play_chunk(int start, int end)
53 {
54 	struct cdrom_msf msf;
55 
56 	end--;
57 	if (start >= end)
58 		start = end-1;
59 
60 	msf.cdmsf_min0 = start / (60*75);
61 	msf.cdmsf_sec0 = (start % (60*75)) / 75;
62 	msf.cdmsf_frame0 = start % 75;
63 	msf.cdmsf_min1 = end / (60*75);
64 	msf.cdmsf_sec1 = (end % (60*75)) / 75;
65 	msf.cdmsf_frame1 = end % 75;
66 
67 	if (ioctl(drive, CDROMSTART))
68 	{
69 		put_it("%s: Could not start the cdrom",cparse(cdrom_prompt));
70 		return;
71 	}
72 	if (ioctl(drive, CDROMPLAYMSF, &msf))
73 	{
74 		put_it("%s: Could not play the track",cparse(cdrom_prompt));
75 		return;
76 	}
77 }
78 #endif
79 
check_cdrom_str(void)80 static int check_cdrom_str(void)
81 {
82 char *str;
83 	if ((str = get_string_var(CD_DEVICE_VAR)))
84 	{
85 		if (!drive)
86 			cd_init(str);
87 		return 1;
88 	}
89 	put_it("%s: /SET CD_DEVICE  - The name of the CDROM device",cparse(cdrom_prompt));
90 	return 0;
91 }
92 
cd_init(char * dev)93 int cd_init(char *dev)
94 {
95 #if 0
96 unsigned char msf_ent[3];
97 unsigned char msf1_ent[3];
98 #endif
99 int i, pos;
100 
101 	if (((drive = open(dev, 0)) < 0))
102 	{
103 		if (errno == EACCES)
104 			put_it("%s: you dont have access to the cdrom driver",cparse(cdrom_prompt));
105 		return (-1);
106 	}
107 
108 	if (ioctl(drive, CDROMREADTOCHDR, &hdr))
109 	{
110 		put_it("%s: Can't get TocHeader",cparse(cdrom_prompt));
111 		return (-2);
112 	}
113 
114 #ifndef __FreeBSD__
115 	for (i=1;i<=hdr.cdth_trk1+1;i++)
116 	{
117 		if (i!=hdr.cdth_trk1+1)
118 			TocEntry[i].cdte_track = i;
119 		else
120 			TocEntry[i].cdte_track = CDROM_LEADOUT;
121 		TocEntry[i].cdte_format = CDROM_MSF;
122 		if (ioctl(drive,CDROMREADTOCENTRY,&TocEntry[i]))
123 			put_it("%s: Can't get TocEntry #%d",cparse(cdrom_prompt), i);
124 		else
125 		{
126 			TocEntry[i].avoid=TocEntry[i].cdte_ctrl & CDROM_DATA_TRACK ? 1 : 0;
127 			TocEntry[i].m_length = TocEntry[i].cdte_addr.msf.minute * 60 + TocEntry[i].cdte_addr.msf.second;
128 			TocEntry[i].m_start = TocEntry[i].m_length * 75 + TocEntry[i].cdte_addr.msf.frame;
129 		}
130 	}
131 
132 	pos = TocEntry[1].m_length;
133 
134 	for (i=1;i<=hdr.cdth_trk1+1;i++)
135 	{
136 		TocEntry[i].m_length = TocEntry[i+1].m_length - pos;
137 		pos = TocEntry[i+1].m_length;
138 		if (TocEntry[i].avoid)
139 			TocEntry[i].m_length = (TocEntry[i+1].m_start - TocEntry[i+1].m_start) *2;
140 	}
141 	return (hdr.cdth_trk1);
142 #else
143 	for (i = hdr.starting_track; i <= hdr.ending_track; i++)
144 	{
145 		TocEntry[i].avoid=0;
146 		TocEntry[i].m_start=1;
147 		TocEntry[i].m_length=1;
148 	}
149 	return (hdr.ending_track);
150 #endif
151 }
152 
check_mount(char * device)153 static int check_mount(char *device)
154 {
155 #ifndef __FreeBSD__
156 FILE *fp;
157 struct mntent *mnt;
158 
159 	if ((fp = setmntent(MOUNTED, "r")) == NULL)
160 		return 0;
161 
162 	while ((mnt = getmntent (fp)) != NULL)
163 	{
164 		if (!strcmp (mnt->mnt_type, "iso9660") && !strcmp (mnt->mnt_fsname, device))
165 		{
166 			endmntent(fp);
167 			return 0;
168 		}
169 	}
170 	endmntent (fp);
171 #else
172 struct statfs *mntinfo;
173 int i,count;
174 
175 	if(!(count=getmntinfo(&mntinfo,MNT_WAIT|MOUNT_CD9660)))
176 		return 0;
177 
178 	for(i=0; i<count; i++)
179 		if(strstr(mntinfo[i].f_mntfromname,device))
180 			return 0;
181 #endif
182 	return 1;
183 }
184 
set_cd_device(Window * win,char * str,int blah)185 void set_cd_device(Window *win, char *str, int blah)
186 {
187 	if (drive)
188   		close(drive);
189 	if (!str || !check_mount(str))
190 	{
191 		put_it("%s: ERROR: CDROM is already mounted, please unmount, and try again",cparse(cdrom_prompt));
192 		set_string_var(CD_DEVICE_VAR,NULL);
193 		return;
194 	}
195 
196 	if (cd_init(str) < 0)
197 	{
198 		put_it("%s: ERROR: Could not initalize the CDROM, check if a disk is inside",cparse(cdrom_prompt));
199 		set_string_var(CD_DEVICE_VAR,NULL);
200 		return;
201 	}
202 	put_it("%s: CDROM device is now set to - %s",cparse(cdrom_prompt),str);
203 	set_string_var(CD_DEVICE_VAR,str);
204 }
205 
BUILT_IN_COMMAND(cd_stop)206 BUILT_IN_COMMAND(cd_stop)
207 {
208 	if (!check_cdrom_str())
209 		return;
210 
211 	if (ioctl(drive,CDROMSTOP))
212 		put_it("%s: Couldnt stop the cdrom",cparse(cdrom_prompt));
213 	else
214 		put_it("%s: Stopped playing cdrom",cparse(cdrom_prompt));
215 }
216 
BUILT_IN_COMMAND(cd_eject)217 BUILT_IN_COMMAND(cd_eject)
218 {
219 	if (!check_cdrom_str())
220 		return;
221 
222 	if (!drive)
223 		return;
224 	if (ioctl(drive,CDROMEJECT))
225 		put_it("%s: Couldnt eject the cdrom tray",cparse(cdrom_prompt));
226 	else
227 		put_it("%s: Ejected cdrom tray",cparse(cdrom_prompt));
228 	close(drive);
229 	drive=0;
230 }
231 
BUILT_IN_COMMAND(cd_play)232 BUILT_IN_COMMAND(cd_play)
233 {
234 int tn;
235 char *trackn;
236 
237 #ifndef __FreeBSD__
238 unsigned char first, last;
239 struct cdrom_tochdr tocHdr;
240 #else
241 struct ioc_play_track cdrom_play_args;
242 int result;
243 #endif
244 
245 	if (!check_cdrom_str() || !drive)
246 		return;
247 
248 	if (args && *args)
249 	{
250 		trackn = next_arg(args, &args);
251 		tn = atoi(trackn);
252 
253 #ifndef __FreeBSD__
254 	        if (ioctl(drive,CDROMREADTOCHDR,&tocHdr))
255 	        {
256 	        	put_it("%s: Couldnt get cdrom heder",cparse(cdrom_prompt));
257 	        	return;
258 	        }
259 
260 	        first = tocHdr.cdth_trk0;
261 	        last = tocHdr.cdth_trk1;
262 	        ti.cdti_trk0=tn;
263 
264 	        if (ti.cdti_trk0<first)
265 	        	ti.cdti_trk0=first;
266 	        if (ti.cdti_trk0>last)
267 	        	ti.cdti_trk0=last;
268 
269 	        ti.cdti_ind0=0;
270 	        ti.cdti_trk1=last;
271 	        ti.cdti_ind1=0;
272 #else
273 		if (tn < hdr.starting_track)
274 			tn=hdr.starting_track;
275 		if (tn > hdr.ending_track)
276  			tn=hdr.ending_track;
277 #endif
278 
279 	        if (TocEntry[tn].avoid==0)
280 	        {
281 #ifndef __FreeBSD__
282 			play_chunk(TocEntry[tn].m_start,TocEntry[last+1].m_start - 1);
283 #else
284 			cdrom_play_args.start_track=tn;
285 			cdrom_play_args.start_index=1;
286 			cdrom_play_args.end_track=hdr.ending_track;
287 			cdrom_play_args.end_index=1;
288 			(void)ioctl(drive,CDIOCPLAYTRACKS,&cdrom_play_args);
289 #endif
290 		        put_it("%s: Playing track number #%d",cparse(cdrom_prompt),tn);
291 	        }
292 	        else
293 	        	put_it("%s: Cannot play track #%d (Might be data track)",cparse(cdrom_prompt),tn);
294 	}
295         else
296 	        put_it("%s: Usage: /cdplay <track number>",cparse(cdrom_prompt));
297 
298 }
299 
BUILT_IN_COMMAND(cd_list)300 BUILT_IN_COMMAND(cd_list)
301 {
302 int i;
303 
304 	if (!check_cdrom_str())
305 		return;
306 #ifndef __FreeBSD__
307 	for (i=1;i<=hdr.cdth_trk1;i++)
308 #else
309 	for (i = hdr.starting_track; i < hdr.ending_track; i++)
310 #endif
311 	{
312 		put_it("%s: Track #%02d: %02d:%02d:%02d %02d:%02d:%02d",
313 			cparse(cdrom_prompt),
314 			i,
315 			TocEntry[i].m_length / (60*75),
316 			(TocEntry[i].m_length % (60*75)) / 75,
317 			TocEntry[i].m_length % 75,
318 			TocEntry[i].m_start / (60*75),
319 			(TocEntry[i].m_start % (60*75)) /75,
320 			TocEntry[i].m_start % 75
321 			);
322 	}
323 }
324 
BUILT_IN_COMMAND(cd_volume)325 BUILT_IN_COMMAND(cd_volume)
326 {
327 char *left, *right;
328 #ifndef __FreeBSD__
329 struct cdrom_volctrl volctrl;
330 #else
331 struct ioc_vol volctrl;
332 #endif
333 
334 	if (!check_cdrom_str())
335 		return;
336 
337 	if (args && *args)
338 	{
339 		left=next_arg(args, &args);
340 		right=next_arg(args, &args);
341 		ioctl(drive, CDROMVOLREAD, &volctrl);
342 		if (left && *left)
343 #ifndef __FreeBSD__
344 			volctrl.channel0 = atoi(left);
345 #else
346 			volctrl.vol[0] = atoi(left);
347 #endif
348 		if (right && *right)
349 #ifndef __FreeBSD__
350 			volctrl.channel1 = atoi(right);
351 #else
352 			volctrl.vol[1] = atoi(right);
353 #endif
354 		if (ioctl(drive,CDROMVOLCTRL,&volctrl))
355 			put_it("%s: Couldnt set cdrom volume",cparse(cdrom_prompt));
356 		else
357 			put_it("%s: CDROM Volume is now <%d> <%d>",cparse(cdrom_prompt),
358 #ifndef __FreeBSD__
359 			volctrl.channel0,volctrl.channel1);
360 #else
361 			volctrl.vol[0],volctrl.vol[1]);
362 #endif
363 	}
364 	else
365 		put_it("%s: Usage: /cdvol <left> <right>",cparse(cdrom_prompt));
366 }
367 
BUILT_IN_COMMAND(cd_pause)368 BUILT_IN_COMMAND(cd_pause)
369 {
370 static int cpause = 0;
371 	if (!check_cdrom_str())
372 		return;
373 	if (ioctl(drive, !cpause?CDROMPAUSE:CDROMRESUME))
374 		put_it("%s: Couldnt pause/resume your cdrom",cparse(cdrom_prompt));
375 	else
376 		put_it("%s: %s",cparse(cdrom_prompt),!cpause?"Your cdrom has been paused":"Your cdrom has been resumed");
377 	cpause ^= 1;
378 }
379 
BUILT_IN_COMMAND(cd_help)380 BUILT_IN_COMMAND(cd_help)
381 {
382 	put_it("%s: CDPLAY            - Play a CDROM Track Number",cparse(cdrom_prompt));
383 	put_it("%s: CDSTOP            - Make the CDROM Stop playing",cparse(cdrom_prompt));
384 	put_it("%s: CDEJECT           - Eject the CDROM Tray",cparse(cdrom_prompt));
385 	put_it("%s: CDVOL             - Set's the CDROM Volume",cparse(cdrom_prompt));
386 	put_it("%s: CDLIST            - List of CDROM tracks",cparse(cdrom_prompt));
387 	put_it("%s: CDPAUSE           - Pause/resume the CDROM",cparse(cdrom_prompt));
388 }
389 
390 #if 0
391 char	*status_cdrom(window)
392 	Window	*window;
393 {
394 	static	char	text[BIG_BUFFER_SIZE];
395 
396 	if ((drive) && (get_string_var(CD_DEVICE_VAR)))
397 	{
398 		rc=ioctl(drive,CDROMSUBCHNL,&subchnl);
399 		strcpy(text,"[CD:");
400 		if (subchnl.cdsc_audiostatus==CDROM_AUDIO_PLAY)
401 		{
402 			strcat(text,"P");
403 			strcat(text,":");
404 			strcat(text,ltoa((long)subchnl.cdsc_trk));
405 		} else {
406 			strcat(text,"S");
407 		}
408 		strcat(text,"]");
409 		return(text);
410 	}
411 	else
412 		return (empty_string);
413 }
414 #endif
415