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 #include "irc.h"
13 #include "ircaux.h"
14 #include "./cdrom.h"
15 #include "output.h"
16 #include "misc.h"
17 #include "vars.h"
18 
19 #define cparse(s) convert_output_format(s, NULL, NULL)
20 
21 static int drive = 0;
22 
23 static char cdrom_prompt[]="%gC%Gd%gROM%w";
24 
25 static struct cdrom_tochdr hdr;
26 static struct cdrom_etocentry TocEntry[101];
27 static struct cdrom_ti ti;
28 
29 static char *cd_device = NULL;
30 
31 
check_cdrom_str(void)32 static int check_cdrom_str(void)
33 {
34 	if (cd_device)
35 		return 1;
36 	put_it("%s: CD_DEVICE (/SET)  - The name of the CDROM device",cparse(cdrom_prompt));
37 	return 0;
38 }
39 
lba2msf(int lba,unsigned char * msf)40 static void lba2msf(int lba, unsigned char *msf)
41 {
42 	lba += CD_BLOCK_OFFSET;
43 	msf[0] = lba / (CD_SECS*CD_FRAMES);
44 	lba %= CD_SECS*CD_FRAMES;
45 	msf[1] = lba / CD_FRAMES;
46 	msf[2] = lba % CD_FRAMES;
47 }
48 
cd_init(char * dev)49 int cd_init(char *dev)
50 {
51 unsigned char msf_ent[3];
52 unsigned char msf1_ent[3];
53 int i, rc;
54 
55 	if (!dev || ((drive = open(dev, O_RDWR)) < 0))
56 		return (-1);
57 
58 	if ((rc = ioctl(drive, CDROMREADTOCHDR, &hdr)) == -1)
59 	{
60 		put_it("%s: can't get TocHeader (error %d).",cparse(cdrom_prompt), rc);
61 		return (-2);
62 	}
63 
64 	for (i=1;i<=hdr.cdth_trk1+1;i++)
65 	{
66 		if (i!=hdr.cdth_trk1+1)
67 			TocEntry[i].cdte_track = i;
68 		else
69 			TocEntry[i].cdte_track = CDROM_LEADOUT;
70 		TocEntry[i].cdte_format = CDROM_LBA;
71 		TocEntry[i].avoid=TocEntry[i].cdte_ctrl & CDROM_DATA_TRACK ? 1 : 0;
72 		if ((rc = ioctl(drive,CDROMREADTOCENTRY,&TocEntry[i])) != 0)
73 			put_it("%s: can't get TocEntry #%d (error %d).",cparse(cdrom_prompt), i,rc);
74 		else
75 			lba2msf(TocEntry[i].cdte_addr.lba,&msf_ent[0]);
76 	}
77 
78 	for (i=1;i<=hdr.cdth_trk1+1;i++)
79 	{
80 		ioctl(drive,CDROMREADTOCENTRY,&TocEntry[i]);
81 		lba2msf(TocEntry[i].cdte_addr.lba,&msf_ent[0]);
82 		ioctl(drive,CDROMREADTOCENTRY,&TocEntry[i+1]);
83 		lba2msf(TocEntry[i+1].cdte_addr.lba,&msf1_ent[0]);
84 		TocEntry[i].length = (msf1_ent[0] * 60 + msf1_ent[1])-
85 			(msf_ent[0] * 60 + msf_ent[1]);
86 	}
87 	return (hdr.cdth_trk1);
88 }
89 
check_mount(char * device)90 static int check_mount(char *device)
91 {
92 FILE *fp;
93 struct mntent *mnt;
94 
95 	if ((fp = setmntent(MOUNTED, "r")) == NULL)
96 		return 0;
97 
98 	while ((mnt = getmntent (fp)) != NULL)
99 	{
100 		if ((strcmp (mnt->mnt_type, "iso9660") == 0) && (strcmp (mnt->mnt_fsname, device) == 0))
101 		{
102 			endmntent(fp);
103 			return 0;
104 		}
105 	}
106 	endmntent (fp);
107 	return 1;
108 }
109 
set_cd_device(IrcCommandDll * interp,char * command,char * args,char * subargs)110 void set_cd_device(IrcCommandDll *interp, char *command, char *args, char *subargs)
111 {
112 char *str;
113 int code;
114 	if (!(str = next_arg(args , &args)))
115 	{
116 		return;
117 	}
118 	if (drive)
119   		close(drive);
120 	if (check_mount(str) == 0)
121 	{
122 		put_it("%s: ERROR: CDROM is already mounted, please unmount, and try again",cparse(cdrom_prompt));
123 		new_free(&cd_device);
124 		return;
125 	}
126 
127 	if ((code = cd_init(str)) < 0)
128 	{
129 		put_it("%s: ERROR(%d): Could not initalize the CDROM, check if a disk is inside",cparse(cdrom_prompt), code);
130 		new_free(&cd_device);
131 		return;
132 	}
133 	put_it("%s: CDROM device is now set to - %s",cparse(cdrom_prompt),str);
134 	malloc_strcpy(&cd_device, str);
135 }
136 
cd_stop(IrcCommandDll * interp,char * command,char * args,char * subargs)137 void cd_stop(IrcCommandDll *interp, char *command, char *args, char *subargs)
138 {
139 	if (!check_cdrom_str())
140 		return;
141 	put_it("%s: Stopped playing cdrom",cparse(cdrom_prompt));
142 	ioctl(drive,CDROMSTOP);
143 }
144 
cd_eject(IrcCommandDll * interp,char * command,char * args,char * subargs)145 void cd_eject(IrcCommandDll *interp, char *command, char *args, char *subargs)
146 {
147 	if (!check_cdrom_str())
148 		return;
149 
150 	put_it("%s: ejected cdrom tray",cparse(cdrom_prompt));
151 	ioctl(drive,CDROMEJECT);
152 	close(drive);
153 	drive=0;
154 }
155 
cd_play(IrcCommandDll * interp,char * command,char * args,char * subargs)156 void cd_play(IrcCommandDll *interp, char *command, char *args, char *subargs)
157 {
158 
159 int tn;
160 char *trackn;
161 unsigned char first, last;
162 struct cdrom_tochdr tocHdr;
163 
164 	if (!check_cdrom_str() || !drive)
165 		return;
166 
167 	if (args && *args)
168 	{
169 		trackn=next_arg(args, &args);
170 		tn=atoi(trackn);
171 
172 	        ioctl(drive,CDROMREADTOCHDR,&tocHdr);
173 
174 	        first = tocHdr.cdth_trk0;
175 	        last = tocHdr.cdth_trk1;
176 	        ti.cdti_trk0=tn;
177 
178 	        if (ti.cdti_trk0<first)
179 	        	ti.cdti_trk0=first;
180 	        if (ti.cdti_trk0>last)
181 	        	ti.cdti_trk0=last;
182 
183 	        ti.cdti_ind0=0;
184 	        ti.cdti_trk1=last;
185 	        ti.cdti_ind1=0;
186 
187 	        if (TocEntry[tn].avoid==0)
188 	        {
189 			ioctl(drive,CDROMSTOP);
190 			ioctl(drive,CDROMPLAYTRKIND,&ti);
191 		        put_it("%s: Playing track number #%d",cparse(cdrom_prompt),tn);
192 	        }
193 	        else
194 	        	put_it("%s: Cannot play track #%d (Might be data track)",cparse(cdrom_prompt),tn);
195 	}
196         else
197 	        put_it("%s: Usage: /cdplay <track number>",cparse(cdrom_prompt));
198 
199 }
200 
cd_list(IrcCommandDll * interp,char * command,char * args,char * subargs)201 void cd_list(IrcCommandDll *interp, char *command, char *args, char *subargs)
202 {
203 int i;
204 unsigned char msf_ent[3];
205 struct cdrom_subchnl subchnl;
206 
207 	if (!check_cdrom_str())
208 		return;
209 	ioctl(drive,CDROMSUBCHNL,&subchnl);
210 	for (i=1;i<=hdr.cdth_trk1;i++)
211 	{
212 		if ((subchnl.cdsc_audiostatus==CDROM_AUDIO_PLAY) && (subchnl.cdsc_trk == i))
213 		{
214 			lba2msf(TocEntry[i].cdte_addr.lba,&msf_ent[0]);
215 			put_it("%s: Track #%02d: %02d:%02d %02d:%02d (*)",
216 				cparse(cdrom_prompt),
217 				TocEntry[i].cdte_track,
218 				msf_ent[0],
219 				msf_ent[1],
220 				(TocEntry[i].length/60) % 60,
221 				TocEntry[i].length % 60);
222 		}
223 		else
224 		{
225 			lba2msf(TocEntry[i].cdte_addr.lba,&msf_ent[0]);
226 			put_it("%s: Track #%02d: %02d:%02d %02d:%02d",
227 				cparse(cdrom_prompt),
228 				TocEntry[i].cdte_track,
229 				msf_ent[0],
230 				msf_ent[1],
231 				(TocEntry[i].length/60) % 60,
232 				TocEntry[i].length % 60);
233 		}
234 	}
235 }
236 
cd_volume(IrcCommandDll * interp,char * command,char * args,char * subargs)237 void cd_volume(IrcCommandDll *interp, char *command, char *args, char *subargs)
238 {
239 char *left, *right;
240 struct cdrom_volctrl volctrl;
241 
242 	if (!check_cdrom_str())
243 		return;
244 
245 	if (args && *args)
246 	{
247 		left=next_arg(args, &args);
248 		right=next_arg(args, &args);
249 		if (left && *left)
250 			volctrl.channel0=atoi(left);
251 		if (right && *right)
252 			volctrl.channel1=atoi(right);
253 		ioctl(drive,CDROMVOLCTRL,&volctrl);
254 		put_it("%s: CDROM Volume is now <%d> <%d>",cparse(cdrom_prompt),volctrl.channel0,volctrl.channel1);
255 	}
256 	else
257 		put_it("%s: Usage: /cdvol <left> <right>",cparse(cdrom_prompt));
258 }
259 
cd_pause(IrcCommandDll * interp,char * command,char * args,char * subargs)260 void cd_pause(IrcCommandDll *interp, char *command, char *args, char *subargs)
261 {
262 static int cpause = 0;
263 	if (!check_cdrom_str())
264 		return;
265 	ioctl(drive, !cpause?CDROMPAUSE:CDROMRESUME);
266 	cpause ^= 1;
267 }
268 
cd_help(IrcCommandDll * interp,char * command,char * args,char * subargs)269 void cd_help(IrcCommandDll *interp, char *command, char *args, char *subargs)
270 {
271 	put_it("%s: CDPLAY            - Play a CDROM Track Number",cparse(cdrom_prompt));
272 	put_it("%s: CDSTOP            - Make the CDROM Stop playing",cparse(cdrom_prompt));
273 	put_it("%s: CDEJECT           - Eject the CDROM Tray",cparse(cdrom_prompt));
274 	put_it("%s: CDVOL             - Set's the CDROM Volume",cparse(cdrom_prompt));
275 	put_it("%s: CDLIST            - List of CDROM tracks",cparse(cdrom_prompt));
276 	put_it("%s: CDPAUSE           - Pause/resume the CDROM",cparse(cdrom_prompt));
277 }
278 
279 int
Cdrom_Init(interp)280 Cdrom_Init(interp)
281     IrcCommandDll **interp;		/* Interpreter in which the package is
282 				 * to be made available. */
283 {
284 	IrcCommandDll *new;
285 	new = (IrcCommandDll *) new_malloc(sizeof(IrcCommandDll));
286 	new->name = m_strdup("cdstop");
287 	new->func = cd_stop;
288 	add_to_list((List **)interp, (List *)new);
289 	new = (IrcCommandDll *) new_malloc(sizeof(IrcCommandDll));
290 	new->name = m_strdup("cdplay");
291 	new->func = cd_play;
292 	add_to_list((List **)interp, (List *)new);
293 	new = (IrcCommandDll *) new_malloc(sizeof(IrcCommandDll));
294 	new->name = m_strdup("cdeject");
295 	new->func = cd_eject;
296 	add_to_list((List **)interp, (List *)new);
297 	new = (IrcCommandDll *) new_malloc(sizeof(IrcCommandDll));
298 	new->name = m_strdup("cdlist");
299 	new->func = cd_list;
300 	add_to_list((List **)interp, (List *)new);
301 	new = (IrcCommandDll *) new_malloc(sizeof(IrcCommandDll));
302 	new->name = m_strdup("cdhelp");
303 	new->func = cd_help;
304 	add_to_list((List **)interp, (List *)new);
305 	new = (IrcCommandDll *) new_malloc(sizeof(IrcCommandDll));
306 	new->name = m_strdup("cdvolume");
307 	new->func = cd_volume;
308 	add_to_list((List **)interp, (List *)new);
309 	new = (IrcCommandDll *) new_malloc(sizeof(IrcCommandDll));
310 	new->name = m_strdup("cdpause");
311 	new->func = cd_pause;
312 	add_to_list((List **)interp, (List *)new);
313 	new = (IrcCommandDll *) new_malloc(sizeof(IrcCommandDll));
314 	new->name = m_strdup("cddevice");
315 	new->func = set_cd_device;
316 	add_to_list((List **)interp, (List *)new);
317 	put_it("%s: Module loaded and ready. /cddevice <dev> to start", cparse(cdrom_prompt));
318 	put_it("%s: /cdhelp for list of new commands.", cparse(cdrom_prompt));
319 	return 0;
320 }