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 #ifdef __linux__
12 #define CDROM_VERSION "0.02"
13
14 #include "irc.h"
15 #include "struct.h"
16 #include "ircaux.h"
17 #define MODULE_CDROM
18 #include "cdrom.h"
19 #include "output.h"
20 #include "misc.h"
21 #include "vars.h"
22
23 #include "module.h"
24 #define INIT_MODULE
25 #include "modval.h"
26
27 #define cparse(s) convert_output_format(s, NULL, NULL)
28
29 static int drive = 0;
30
31 static char cdrom_prompt[]="%gC%Gd%gROM%w";
32
33 #ifndef __FreeBSD__
34 static struct cdrom_tochdr hdr;
35 static struct cdrom_ti ti;
36 #else
37 static struct ioc_toc_header hdr;
38 #include <sys/disklabel.h>
39 #define MOUNT_CD9660 FS_ISO9660
40 #endif
41
42 static struct cdrom_etocentry TocEntry[101];
43
44 static char *cd_device = NULL;
45
46 static int cd_init(char *);
47
48 #ifndef __FreeBSD__
play_chunk(int start,int end)49 void play_chunk(int start, int end)
50 {
51 struct cdrom_msf msf;
52
53 end--;
54 if (start >= end)
55 start = end-1;
56
57 msf.cdmsf_min0 = start / (60*75);
58 msf.cdmsf_sec0 = (start % (60*75)) / 75;
59 msf.cdmsf_frame0 = start % 75;
60 msf.cdmsf_min1 = end / (60*75);
61 msf.cdmsf_sec1 = (end % (60*75)) / 75;
62 msf.cdmsf_frame1 = end % 75;
63
64 if (ioctl(drive, CDROMSTART))
65 {
66 put_it("%s: Could not start the cdrom",cparse(cdrom_prompt));
67 return;
68 }
69 if (ioctl(drive, CDROMPLAYMSF, &msf))
70 {
71 put_it("%s: Could not play the track",cparse(cdrom_prompt));
72 return;
73 }
74 }
75 #endif
76
check_cdrom_str(void)77 static int check_cdrom_str(void)
78 {
79 if (cd_device)
80 return 1;
81 put_it("%s: /CDDEVICE - The name of the CDROM device",cparse(cdrom_prompt));
82 return 0;
83 }
84
85 #if 0
86 static void lba2msf(int lba, unsigned char *msf)
87 {
88 #if !defined(CD_BLOCK_OFFSET)
89 #define CD_BLOCK_OFFSET CD_MSF_OFFSET
90 #endif
91 lba += CD_BLOCK_OFFSET;
92 msf[0] = lba / (CD_SECS*CD_FRAMES);
93 lba %= CD_SECS*CD_FRAMES;
94 msf[1] = lba / CD_FRAMES;
95 msf[2] = lba % CD_FRAMES;
96 }
97 #endif
98
cd_init(char * dev)99 int cd_init(char *dev)
100 {
101 int i, rc, pos;
102
103 if (!dev || ((drive = open(dev, O_RDONLY)) < 0))
104 return (-1);
105
106 if ((rc = ioctl(drive, CDROMREADTOCHDR, &hdr)) == -1)
107 {
108 put_it("%s: can't get TocHeader (error %d).",cparse(cdrom_prompt), rc);
109 return (-2);
110 }
111
112 #ifndef __FreeBSD__
113 for (i=1;i<=hdr.cdth_trk1+1;i++)
114 {
115 if (i!=hdr.cdth_trk1+1)
116 TocEntry[i].cdte_track = i;
117 else
118 TocEntry[i].cdte_track = CDROM_LEADOUT;
119 TocEntry[i].cdte_format = CDROM_MSF;
120 if (ioctl(drive,CDROMREADTOCENTRY,&TocEntry[i]))
121 put_it("%s: Can't get TocEntry #%d",cparse(cdrom_prompt), i);
122 else
123 {
124 TocEntry[i].avoid=TocEntry[i].cdte_ctrl & CDROM_DATA_TRACK ? 1 : 0;
125 TocEntry[i].m_length = TocEntry[i].cdte_addr.msf.minute * 60 + TocEntry[i].cdte_addr.msf.second;
126 TocEntry[i].m_start = TocEntry[i].m_length * 75 + TocEntry[i].cdte_addr.msf.frame;
127 }
128 }
129
130 pos = TocEntry[1].m_length;
131
132 for (i=1;i<=hdr.cdth_trk1+1;i++)
133 {
134 TocEntry[i].m_length = TocEntry[i+1].m_length - pos;
135 pos = TocEntry[i+1].m_length;
136 if (TocEntry[i].avoid)
137 TocEntry[i].m_length = (TocEntry[i+1].m_start - TocEntry[i+1].m_start) *2;
138 }
139 return (hdr.cdth_trk1);
140 #else
141 for (i = hdr.starting_track; i <= hdr.ending_track; i++)
142 {
143 TocEntry[i].avoid=0;
144 TocEntry[i].m_start=1;
145 TocEntry[i].m_length=1;
146 }
147 return (hdr.ending_track);
148 #endif
149 }
150
check_mount(char * device)151 static int check_mount(char *device)
152 {
153 #ifndef __FreeBSD__
154 FILE *fp;
155 struct mntent *mnt;
156
157 if ((fp = setmntent(MOUNTED, "r")) == NULL)
158 return 0;
159
160 while ((mnt = getmntent (fp)) != NULL)
161 {
162 if (!strcmp (mnt->mnt_type, "iso9660") && !strcmp (mnt->mnt_fsname, device))
163 {
164 endmntent(fp);
165 return 0;
166 }
167 }
168 endmntent (fp);
169 #else
170 struct statfs *mntinfo;
171 int i,count;
172
173 if (!(count = getmntinfo(&mntinfo,MNT_WAIT|MOUNT_CD9660)))
174 return 0;
175
176 for(i = 0; i < count; i++)
177 if (strstr(mntinfo[i].f_mntfromname,device) && !stricmp(mntinfo[i].f_dstypename, "iso9660"))
178 return 0;
179 #endif
180 return 1;
181 }
182
BUILT_IN_DLL(set_cd_device)183 BUILT_IN_DLL(set_cd_device)
184 {
185 char *str;
186 int code;
187 if (!(str = next_arg(args , &args)))
188 {
189 return;
190 }
191 if (drive)
192 close(drive);
193 if (!str || !check_mount(str))
194 {
195 put_it("%s: ERROR: CDROM is already mounted, please unmount, and try again",cparse(cdrom_prompt));
196 new_free(&cd_device);
197 return;
198 }
199
200 if ((code = cd_init(str)) < 0)
201 {
202 put_it("%s: ERROR(%d): Could not initalize the CDROM, check if a disk is inside",cparse(cdrom_prompt), code);
203 new_free(&cd_device);
204 return;
205 }
206 put_it("%s: CDROM device is now set to - %s",cparse(cdrom_prompt),str);
207 malloc_strcpy(&cd_device, str);
208 }
209
BUILT_IN_DLL(cd_stop)210 BUILT_IN_DLL(cd_stop)
211 {
212 if (!check_cdrom_str())
213 return;
214 if (!ioctl(drive, CDROMSTOP))
215 put_it("%s: Stopped playing cdrom",cparse(cdrom_prompt));
216 else
217 put_it("%s: Stopped playing cdrom",cparse(cdrom_prompt));
218 }
219
BUILT_IN_DLL(cd_eject)220 BUILT_IN_DLL(cd_eject)
221 {
222 if (!check_cdrom_str() || !drive)
223 return;
224
225 if (!ioctl(drive,CDROMEJECT))
226 put_it("%s: ejected cdrom tray",cparse(cdrom_prompt));
227 else
228 put_it("%s: Stopped playing cdrom",cparse(cdrom_prompt));
229 close(drive);
230 drive=0;
231 }
232
BUILT_IN_DLL(cd_play)233 BUILT_IN_DLL(cd_play)
234 {
235
236 int tn;
237 char *trackn;
238 #ifndef __FreeBSD__
239 unsigned char first, last;
240 struct cdrom_tochdr tocHdr;
241 #else
242 struct ioc_play_track cdrom_play_args;
243 int result;
244 #endif
245
246 if (!check_cdrom_str() || !drive)
247 return;
248
249 if (args && *args)
250 {
251 trackn=next_arg(args, &args);
252 tn=atoi(trackn);
253
254 #ifndef __FreeBSD__
255 if ((ioctl(drive,CDROMREADTOCHDR,&tocHdr)))
256 {
257 put_it("%s: Couldnt get cdrom heder",cparse(cdrom_prompt));
258 return;
259 }
260
261 first = tocHdr.cdth_trk0;
262 last = tocHdr.cdth_trk1;
263 ti.cdti_trk0=tn;
264
265 if (ti.cdti_trk0<first)
266 ti.cdti_trk0=first;
267 if (ti.cdti_trk0>last)
268 ti.cdti_trk0=last;
269
270 ti.cdti_ind0=0;
271 ti.cdti_trk1=last;
272 ti.cdti_ind1=0;
273 #else
274 if (tn < hdr.starting_track)
275 tn=hdr.starting_track;
276 if (tn > hdr.ending_track)
277 tn=hdr.ending_track;
278 #endif
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_DLL(cd_list)300 BUILT_IN_DLL(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_DLL(cd_volume)325 BUILT_IN_DLL(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 if (!check_cdrom_str())
334 return;
335
336 if (args && *args)
337 {
338 left=next_arg(args, &args);
339 right=next_arg(args, &args);
340 ioctl(drive, CDROMVOLREAD, &volctrl);
341 if (left && *left)
342 #ifndef __FreeBSD__
343 volctrl.channel0 = atoi(left);
344 #else
345 volctrl.vol[0] = atoi(left);
346 #endif
347 if (right && *right)
348 #ifndef __FreeBSD__
349 volctrl.channel1 = atoi(right);
350 #else
351 volctrl.vol[1] = atoi(right);
352 #endif
353 if (ioctl(drive,CDROMVOLCTRL,&volctrl))
354 put_it("%s: Couldnt set cdrom volume",cparse(cdrom_prompt));
355 else
356 put_it("%s: CDROM Volume is now <%d> <%d>",cparse(cdrom_prompt),
357 #ifndef __FreeBSD__
358 volctrl.channel0,volctrl.channel1);
359 #else
360 volctrl.vol[0],volctrl.vol[1]);
361 #endif
362 }
363 else
364 put_it("%s: Usage: /cdvol <left> <right>",cparse(cdrom_prompt));
365 }
366
BUILT_IN_DLL(cd_pause)367 BUILT_IN_DLL(cd_pause)
368 {
369 static int cpause = 0;
370 if (!check_cdrom_str())
371 return;
372 if (ioctl(drive, !cpause?CDROMPAUSE:CDROMRESUME))
373 put_it("%s: Couldnt pause/resume your cdrom",cparse(cdrom_prompt));
374 else
375 put_it("%s: %s",cparse(cdrom_prompt),!cpause?"Your cdrom has been paused":"Your cdrom has been resumed");
376 cpause ^= 1;
377 }
378
BUILT_IN_DLL(cd_help)379 BUILT_IN_DLL(cd_help)
380 {
381 put_it("%s: CDPLAY - Play a CDROM Track Number",cparse(cdrom_prompt));
382 put_it("%s: CDSTOP - Make the CDROM Stop playing",cparse(cdrom_prompt));
383 put_it("%s: CDEJECT - Eject the CDROM Tray",cparse(cdrom_prompt));
384 put_it("%s: CDVOL - Set's the CDROM Volume",cparse(cdrom_prompt));
385 put_it("%s: CDLIST - List of CDROM tracks",cparse(cdrom_prompt));
386 put_it("%s: CDPAUSE - Pause/resume the CDROM",cparse(cdrom_prompt));
387 }
388
Cdrom_Version(IrcCommandDll ** interp)389 char *Cdrom_Version (IrcCommandDll **interp)
390 {
391 return CDROM_VERSION;
392 }
393
Cdrom_Init(IrcCommandDll ** interp,Function_ptr * global_table)394 int Cdrom_Init(IrcCommandDll **interp, Function_ptr *global_table)
395 {
396 char *name = "cdrom";
397 initialize_module(name);
398 add_module_proc(COMMAND_PROC, name, "cdstop", NULL, 0, 0, cd_stop, NULL);
399 add_module_proc(COMMAND_PROC, name, "cdplay", NULL, 0, 0, cd_play, NULL);
400 add_module_proc(COMMAND_PROC, name, "cdeject", NULL, 0, 0, cd_eject, NULL);
401 add_module_proc(COMMAND_PROC, name, "cdlist", NULL, 0, 0, cd_list, NULL);
402 add_module_proc(COMMAND_PROC, name, "cdhelp", NULL, 0, 0, cd_help, NULL);
403 add_module_proc(COMMAND_PROC, name, "cdvolume", NULL, 0, 0, cd_volume, NULL);
404 add_module_proc(COMMAND_PROC, name, "cdpause", NULL, 0, 0, cd_pause, NULL);
405 add_module_proc(COMMAND_PROC, name, "cddevice", NULL, 0, 0, set_cd_device, NULL);
406 put_it("%s: Module loaded and ready. /cddevice <dev> to start", cparse(cdrom_prompt));
407 put_it("%s: /cdhelp for list of new commands.", cparse(cdrom_prompt));
408 return 0;
409 }
410 #endif
411