Deleted Added
full compact
cdcontrol.c (13889) cdcontrol.c (13985)
1/*
2 * Compact Disc Control Utility by Serge V. Vakulenko <vak@cronyx.ru>.
3 * Based on the non-X based CD player by Jean-Marc Zucconi and
4 * Andrey A. Chernov.
5 *
1/*
2 * Compact Disc Control Utility by Serge V. Vakulenko <vak@cronyx.ru>.
3 * Based on the non-X based CD player by Jean-Marc Zucconi and
4 * Andrey A. Chernov.
5 *
6 * $Id: cdcontrol.c,v 1.9 1996/02/03 15:07:32 ache Exp $
6 * Fixed and further modified on 5-Sep-1995 by Jukka Ukkonen <jau@funet.fi>.
7 *
8 * 11-Sep-1995: Jukka A. Ukkonen <jau@funet.fi>
9 * A couple of further fixes to my own earlier "fixes".
10 *
11 * 18-Sep-1995: Jukka A. Ukkonen <jau@funet.fi>
12 * Added an ability to specify addresses relative to the
13 * beginning of a track. This is in fact a variation of
14 * doing the simple play_msf() call.
15 *
16 * 11-Oct-1995: Serge V.Vakulenko <vak@cronyx.ru>
17 * New eject algorithm.
18 * Some code style reformatting.
19 *
20 * $Id: cdcontrol.c,v 1.10 1996/02/03 15:21:30 ache Exp $
7 */
21 */
22
23#include <ctype.h>
8#include <stdio.h>
9#include <stdlib.h>
10#include <string.h>
11#include <unistd.h>
12#include <errno.h>
13#include <sys/file.h>
14#include <sys/cdio.h>
15#include <sys/ioctl.h>
16
17#define VERSION "2.0"
18
24#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
27#include <unistd.h>
28#include <errno.h>
29#include <sys/file.h>
30#include <sys/cdio.h>
31#include <sys/ioctl.h>
32
33#define VERSION "2.0"
34
19/*
20 * Audio Status Codes
21 */
22#define ASTS_INVALID 0x00 /* Audio status byte not valid */
23#define ASTS_PLAYING 0x11 /* Audio play operation in progress */
24#define ASTS_PAUSED 0x12 /* Audio play operation paused */
25#define ASTS_COMPLETED 0x13 /* Audio play operation successfully completed */
26#define ASTS_ERROR 0x14 /* Audio play operation stopped due to error */
27#define ASTS_VOID 0x15 /* No current audio status to return */
35#define ASTS_INVALID 0x00 /* Audio status byte not valid */
36#define ASTS_PLAYING 0x11 /* Audio play operation in progress */
37#define ASTS_PAUSED 0x12 /* Audio play operation paused */
38#define ASTS_COMPLETED 0x13 /* Audio play operation successfully completed */
39#define ASTS_ERROR 0x14 /* Audio play operation stopped due to error */
40#define ASTS_VOID 0x15 /* No current audio status to return */
28
41
42#ifndef DEFAULT_CD_DRIVE
43# define DEFAULT_CD_DRIVE "/dev/cd0c"
44#endif
45
46#ifndef DEFAULT_CD_PARTITION
47# define DEFAULT_CD_PARTITION "c"
48#endif
49
50#define CMD_DEBUG 1
51#define CMD_EJECT 2
52#define CMD_HELP 3
53#define CMD_INFO 4
54#define CMD_PAUSE 5
55#define CMD_PLAY 6
56#define CMD_QUIT 7
57#define CMD_RESUME 8
58#define CMD_STOP 9
59#define CMD_VOLUME 10
60#define CMD_CLOSE 11
61#define CMD_RESET 12
62#define CMD_SET 13
63#define CMD_STATUS 14
64
29struct cmdtab {
30 int command;
31 char *name;
65struct cmdtab {
66 int command;
67 char *name;
68 unsigned min;
32 char *args;
33} cmdtab[] = {
69 char *args;
70} cmdtab[] = {
34#define CMD_DEBUG 1
35 { CMD_DEBUG, "Debug", "on | off", },
36#define CMD_EJECT 2
37 { CMD_EJECT, "Eject", "", },
38#define CMD_HELP 3
39 { CMD_HELP, "?", 0, },
40 { CMD_HELP, "Help", "", },
41#define CMD_INFO 4
42 { CMD_INFO, "I", 0, },
43 { CMD_INFO, "Info", "", },
44#define CMD_INJECT 5
45 { CMD_INJECT, "INJect", "", },
46#define CMD_PAUSE 6
47 { CMD_PAUSE, "PAuse", "", },
48#define CMD_PLAY 7
49 { CMD_PLAY, "P", 0, },
50 { CMD_PLAY, "Play", "min1:sec1[.fr1] [min2:sec2[.fr2]]", },
51 { CMD_PLAY, "Play", "track1[.index1] [track2.[index2]]", },
52 { CMD_PLAY, "Play", "[#block [len]]", },
53#define CMD_QUIT 8
54 { CMD_QUIT, "Quit", "", },
55#define CMD_RESET 9
56 { CMD_RESET, "RESEt", "", },
57#define CMD_RESUME 10
58 { CMD_RESUME, "R", 0, },
59 { CMD_RESUME, "Resume", "", },
60#define CMD_SET 11
61 { CMD_SET, "SEt", "msf | lba", },
62#define CMD_STATUS 12
63 { CMD_STATUS, "S", 0, },
64 { CMD_STATUS, "Status", "", },
65#define CMD_STOP 13
66 { CMD_STOP, "STOp", "", },
67#define CMD_VOLUME 14
68 { CMD_VOLUME, "Volume", "<l> <r> | left | right | mute | mono | stereo", },
69 { 0, 0, },
71{ CMD_CLOSE, "close", 1, "" },
72{ CMD_DEBUG, "debug", 1, "on | off" },
73{ CMD_EJECT, "eject", 1, "" },
74{ CMD_HELP, "?", 1, 0 },
75{ CMD_HELP, "help", 1, "" },
76{ CMD_INFO, "info", 1, "" },
77{ CMD_PAUSE, "pause", 2, "" },
78{ CMD_PLAY, "play", 1, "min1:sec1[.fram1] [min2:sec2[.fram2]]" },
79{ CMD_PLAY, "play", 1, "track1[.index1] [track2[.index2]]" },
80{ CMD_PLAY, "play", 1, "tr1 m1:s1[.f1] [[tr2] [m2:s2[.f2]]]" },
81{ CMD_PLAY, "play", 1, "[#block [len]]" },
82{ CMD_QUIT, "quit", 1, "" },
83{ CMD_RESET, "reset", 4, "" },
84{ CMD_RESUME, "resume", 1, "" },
85{ CMD_SET, "set", 2, "msf | lba" },
86{ CMD_STATUS, "status", 1, "" },
87{ CMD_STOP, "stop", 3, "" },
88{ CMD_VOLUME, "volume", 1, "<l> <r> | left | right | mute | mono | stereo" },
89{ 0, }
70};
71
90};
91
72struct cd_toc_entry toc_buffer[100];
92struct cd_toc_entry toc_buffer[100];
73
93
74char *cdname;
75int fd = -1;
76int verbose = 1;
77int msf = 1;
94const char *cdname;
95int fd = -1;
96int verbose = 1;
97int msf = 1;
78
98
79extern char *optarg;
80extern int optind;
99extern char *__progname;
81
100
82int setvol (int, int);
83int read_toc_entrys (int);
84int play_msf (int, int, int, int, int, int);
85int play_track (int, int, int, int);
86int get_vol (int *, int *);
87int status (int *, int *, int *, int *);
88int open_cd (void);
89int play (char *arg);
90int info (char *arg);
91int pstatus (char *arg);
92char *input (int*);
93void prtrack (struct cd_toc_entry *e, int lastflag);
94void lba2msf (int lba, u_char *m, u_char *s, u_char *f);
95int msf2lba (u_char m, u_char s, u_char f);
96int play_blocks (int blk, int len);
97int run (int cmd, char *arg);
98char *parse (char *buf, int *cmd);
101int setvol __P((int, int));
102int read_toc_entrys __P((int));
103int play_msf __P((int, int, int, int, int, int));
104int play_track __P((int, int, int, int));
105int get_vol __P((int *, int *));
106int status __P((int *, int *, int *, int *));
107int open_cd __P((void));
108int play __P((char *arg));
109int info __P((char *arg));
110int pstatus __P((char *arg));
111char *input __P((int *));
112void prtrack __P((struct cd_toc_entry *e, int lastflag));
113void lba2msf __P((unsigned long lba,
114 u_char *m, u_char *s, u_char *f));
115unsigned int msf2lba __P((u_char m, u_char s, u_char f));
116int play_blocks __P((int blk, int len));
117int run __P((int cmd, char *arg));
118char *parse __P((char *buf, int *cmd));
99
119
100extern int errno;
101
102void help ()
103{
104 struct cmdtab *c;
120void help ()
121{
122 struct cmdtab *c;
123 char *s, n;
124 int i;
105
106 for (c=cmdtab; c->name; ++c) {
107 if (! c->args)
108 continue;
125
126 for (c=cmdtab; c->name; ++c) {
127 if (! c->args)
128 continue;
109 printf ("\t%s", c->name);
129 printf("\t");
130 for (i = c->min, s = c->name; *s; s++, i--) {
131 if (i > 0)
132 n = toupper(*s);
133 else
134 n = *s;
135 putchar(n);
136 }
110 if (*c->args)
111 printf (" %s", c->args);
112 printf ("\n");
113 }
137 if (*c->args)
138 printf (" %s", c->args);
139 printf ("\n");
140 }
141 printf ("\n\tThe word \"play\" is not required for the play commands.\n");
142 printf ("\tThe plain target address is taken as a synonym for play.\n");
114}
115
116void usage ()
117{
143}
144
145void usage ()
146{
118 printf ("Usage:\n\tcdcontrol [ -vs ] [ -f disc ] [ command args... ]\n");
147 printf ("Usage:\n\t%s [ -vs ] [ -f disc ] [ command args... ]\n", __progname);
119 printf ("Options:\n");
120 printf ("\t-v - verbose mode\n");
121 printf ("\t-s - silent mode\n");
148 printf ("Options:\n");
149 printf ("\t-v - verbose mode\n");
150 printf ("\t-s - silent mode\n");
122 printf ("\t-f disc - device name such as /dev/cd0c\n");
123 printf ("\tDISC - shell variable with device name\n");
151 printf ("\t-f disc - a block device name such as /dev/cd0c\n");
152 printf ("\tMUSIC_CD - shell variable with device name\n");
124 printf ("Commands:\n");
125 help ();
126 exit (1);
127}
128
129int main (int argc, char **argv)
130{
131 int cmd;
132 char *arg;
133
153 printf ("Commands:\n");
154 help ();
155 exit (1);
156}
157
158int main (int argc, char **argv)
159{
160 int cmd;
161 char *arg;
162
134 cdname = getenv ("DISC");
163 cdname = getenv ("MUSIC_CD");
135 if (! cdname)
164 if (! cdname)
165 cdname = getenv ("CD_DRIVE");
166 if (! cdname)
167 cdname = getenv ("DISC");
168 if (! cdname)
136 cdname = getenv ("CDPLAY");
137
138 for (;;) {
139 switch (getopt (argc, argv, "svhf:")) {
140 case EOF:
141 break;
142 case 's':
143 verbose = 0;

--- 8 unchanged lines hidden (view full) ---

152 default:
153 usage ();
154 }
155 break;
156 }
157 argc -= optind;
158 argv += optind;
159
169 cdname = getenv ("CDPLAY");
170
171 for (;;) {
172 switch (getopt (argc, argv, "svhf:")) {
173 case EOF:
174 break;
175 case 's':
176 verbose = 0;

--- 8 unchanged lines hidden (view full) ---

185 default:
186 usage ();
187 }
188 break;
189 }
190 argc -= optind;
191 argv += optind;
192
160 if (argc > 0 && strcasecmp (*argv, "help") == 0)
193 if (argc > 0 && ! strcasecmp (*argv, "help"))
161 usage ();
162
163 if (! cdname) {
194 usage ();
195
196 if (! cdname) {
164 fprintf (stderr, "No CD device name specified.\n");
165 usage ();
197 cdname = DEFAULT_CD_DRIVE;
198 fprintf (stderr,
199 "No CD device name specified. Defaulting to %s.\n", cdname);
166 }
167
168 if (argc > 0) {
169 char buf[80], *p;
170 int len;
171
200 }
201
202 if (argc > 0) {
203 char buf[80], *p;
204 int len;
205
172 for (p=buf; argc-- > 0; ++argv) {
206 for (p=buf; argc-->0; ++argv) {
173 len = strlen (*argv);
207 len = strlen (*argv);
208
174 if (p + len >= buf + sizeof (buf) - 1)
175 usage ();
209 if (p + len >= buf + sizeof (buf) - 1)
210 usage ();
211
176 if (p > buf)
177 *p++ = ' ';
212 if (p > buf)
213 *p++ = ' ';
214
178 strcpy (p, *argv);
179 p += len;
180 }
181 *p = 0;
182 arg = parse (buf, &cmd);
215 strcpy (p, *argv);
216 p += len;
217 }
218 *p = 0;
219 arg = parse (buf, &cmd);
183 return run (cmd, arg);
220 return (run (cmd, arg));
184 }
185
186 if (verbose == 1)
187 verbose = isatty (0);
221 }
222
223 if (verbose == 1)
224 verbose = isatty (0);
225
188 if (verbose) {
226 if (verbose) {
189 printf ("Compact Disc Control Utility, Version %s\n", VERSION);
227 printf ("Compact Disc Control utility, version %s\n", VERSION);
190 printf ("Type `?' for command list\n\n");
191 }
192
193 for (;;) {
194 arg = input (&cmd);
195 if (run (cmd, arg) < 0) {
196 if (verbose)
228 printf ("Type `?' for command list\n\n");
229 }
230
231 for (;;) {
232 arg = input (&cmd);
233 if (run (cmd, arg) < 0) {
234 if (verbose)
197 perror ("cdcontrol");
235 perror (__progname);
198 close (fd);
199 fd = -1;
200 }
201 fflush (stdout);
202 }
203}
204
205int run (int cmd, char *arg)
206{
207 int l, r, rc;
208
209 switch (cmd) {
236 close (fd);
237 fd = -1;
238 }
239 fflush (stdout);
240 }
241}
242
243int run (int cmd, char *arg)
244{
245 int l, r, rc;
246
247 switch (cmd) {
248
210 case CMD_QUIT:
211 exit (0);
212
249 case CMD_QUIT:
250 exit (0);
251
213 default:
214 case CMD_HELP:
215 help ();
216 return (0);
217
218 case CMD_INFO:
252 case CMD_INFO:
219 if (fd<0 && ! open_cd ()) return (0);
253 if (fd < 0 && ! open_cd ())
254 return (0);
255
220 return info (arg);
221
222 case CMD_STATUS:
256 return info (arg);
257
258 case CMD_STATUS:
223 if (fd<0 && ! open_cd ()) return (0);
259 if (fd < 0 && ! open_cd ())
260 return (0);
261
224 return pstatus (arg);
225
226 case CMD_PAUSE:
262 return pstatus (arg);
263
264 case CMD_PAUSE:
227 if (fd<0 && ! open_cd ()) return (0);
265 if (fd < 0 && ! open_cd ())
266 return (0);
267
228 return ioctl (fd, CDIOCPAUSE);
229
230 case CMD_RESUME:
268 return ioctl (fd, CDIOCPAUSE);
269
270 case CMD_RESUME:
231 if (fd<0 && ! open_cd ()) return (0);
271 if (fd < 0 && ! open_cd ())
272 return (0);
273
232 return ioctl (fd, CDIOCRESUME);
233
234 case CMD_STOP:
274 return ioctl (fd, CDIOCRESUME);
275
276 case CMD_STOP:
235 if (fd<0 && ! open_cd ()) return (0);
236 return ioctl (fd, CDIOCSTOP);
277 if (fd < 0 && ! open_cd ())
278 return (0);
237
279
280 rc = ioctl (fd, CDIOCSTOP);
281
282 (void) ioctl (fd, CDIOCALLOW);
283
284 return (rc);
285
238 case CMD_RESET:
286 case CMD_RESET:
239 if (fd<0 && ! open_cd ()) return (0);
287 if (fd < 0 && ! open_cd ())
288 return (0);
289
240 rc = ioctl (fd, CDIOCRESET);
241 if (rc < 0)
242 return rc;
243 close(fd);
244 fd = -1;
245 return (0);
246
247 case CMD_DEBUG:
290 rc = ioctl (fd, CDIOCRESET);
291 if (rc < 0)
292 return rc;
293 close(fd);
294 fd = -1;
295 return (0);
296
297 case CMD_DEBUG:
248 if (fd<0 && ! open_cd ()) return (0);
249 if (strcasecmp (arg, "on") == 0)
298 if (fd < 0 && ! open_cd ())
299 return (0);
300
301 if (! strcasecmp (arg, "on"))
250 return ioctl (fd, CDIOCSETDEBUG);
302 return ioctl (fd, CDIOCSETDEBUG);
251 if (strcasecmp (arg, "off") == 0)
303
304 if (! strcasecmp (arg, "off"))
252 return ioctl (fd, CDIOCCLRDEBUG);
305 return ioctl (fd, CDIOCCLRDEBUG);
253 printf ("Invalid command arguments\n");
306
307 printf ("%s: Invalid command arguments\n", __progname);
308
254 return (0);
255
256 case CMD_EJECT:
309 return (0);
310
311 case CMD_EJECT:
257 if (fd<0 && ! open_cd ()) return (0);
312 if (fd < 0 && ! open_cd ())
313 return (0);
314
258 (void) ioctl (fd, CDIOCALLOW);
259 rc = ioctl (fd, CDIOCEJECT);
260 if (rc < 0)
261 return (rc);
262 return (0);
263
315 (void) ioctl (fd, CDIOCALLOW);
316 rc = ioctl (fd, CDIOCEJECT);
317 if (rc < 0)
318 return (rc);
319 return (0);
320
264 case CMD_INJECT:
265 if (fd<0 && ! open_cd ()) return (0);
321 case CMD_CLOSE:
322 if (fd < 0 && ! open_cd ())
323 return (0);
324
325 (void) ioctl (fd, CDIOCALLOW);
266 rc = ioctl (fd, CDIOCCLOSE);
267 if (rc < 0)
268 return (rc);
269 close(fd);
270 fd = -1;
271 return (0);
272
273 case CMD_PLAY:
326 rc = ioctl (fd, CDIOCCLOSE);
327 if (rc < 0)
328 return (rc);
329 close(fd);
330 fd = -1;
331 return (0);
332
333 case CMD_PLAY:
274 if (fd<0 && ! open_cd ()) return (0);
334 if (fd < 0 && ! open_cd ())
335 return (0);
336
337 while (isspace (*arg))
338 arg++;
339
275 return play (arg);
276
277 case CMD_SET:
340 return play (arg);
341
342 case CMD_SET:
278 if (strcasecmp (arg, "msf") == 0)
343 if (! strcasecmp (arg, "msf"))
279 msf = 1;
344 msf = 1;
280 else if (strcasecmp (arg, "lba") == 0)
345 else if (! strcasecmp (arg, "lba"))
281 msf = 0;
282 else
346 msf = 0;
347 else
283 printf ("Invalid command arguments\n");
348 printf ("%s: Invalid command arguments\n", __progname);
284 return (0);
285
286 case CMD_VOLUME:
349 return (0);
350
351 case CMD_VOLUME:
287 if (fd<0 && ! open_cd ()) return (0);
352 if (fd < 0 && !open_cd ())
353 return (0);
288
354
289 if (strcasecmp (arg, "left") == 0)
355 if (! strncasecmp (arg, "left", strlen(arg)))
290 return ioctl (fd, CDIOCSETLEFT);
356 return ioctl (fd, CDIOCSETLEFT);
291 else if (strcasecmp (arg, "right") == 0)
357
358 if (! strncasecmp (arg, "right", strlen(arg)))
292 return ioctl (fd, CDIOCSETRIGHT);
359 return ioctl (fd, CDIOCSETRIGHT);
293 else if (strcasecmp (arg, "mute") == 0)
294 return ioctl (fd, CDIOCSETMUTE);
295 else if (strcasecmp (arg, "mono") == 0)
360
361 if (! strncasecmp (arg, "mono", strlen(arg)))
296 return ioctl (fd, CDIOCSETMONO);
362 return ioctl (fd, CDIOCSETMONO);
297 else if (strcasecmp (arg, "stereo") == 0)
363
364 if (! strncasecmp (arg, "stereo", strlen(arg)))
298 return ioctl (fd, CDIOCSETSTERIO);
299
365 return ioctl (fd, CDIOCSETSTERIO);
366
367 if (! strncasecmp (arg, "mute", strlen(arg)))
368 return ioctl (fd, CDIOCSETMUTE);
369
300 if (2 != sscanf (arg, "%d %d", &l, &r)) {
370 if (2 != sscanf (arg, "%d %d", &l, &r)) {
301 printf ("Invalid command arguments\n");
371 printf ("%s: Invalid command arguments\n", __progname);
302 return (0);
303 }
372 return (0);
373 }
374
304 return setvol (l, r);
375 return setvol (l, r);
376
377 default:
378 case CMD_HELP:
379 help ();
380 return (0);
381
305 }
306}
307
308int play (char *arg)
309{
310 struct ioc_toc_header h;
311 int rc, n, start, end = 0, istart = 1, iend = 1;
312
313 rc = ioctl (fd, CDIOREADTOCHEADER, &h);
382 }
383}
384
385int play (char *arg)
386{
387 struct ioc_toc_header h;
388 int rc, n, start, end = 0, istart = 1, iend = 1;
389
390 rc = ioctl (fd, CDIOREADTOCHEADER, &h);
391
314 if (rc < 0)
315 return (rc);
316
317 n = h.ending_track - h.starting_track + 1;
318 rc = read_toc_entrys ((n + 1) * sizeof (struct cd_toc_entry));
392 if (rc < 0)
393 return (rc);
394
395 n = h.ending_track - h.starting_track + 1;
396 rc = read_toc_entrys ((n + 1) * sizeof (struct cd_toc_entry));
397
319 if (rc < 0)
320 return (rc);
321
398 if (rc < 0)
399 return (rc);
400
322 if (! *arg)
323 /*
324 * Play the whole disc
325 */
401 if (! arg || ! *arg)
402 /* Play the whole disc */
326 return play_blocks (0, msf2lba (toc_buffer[n].addr.msf.minute,
403 return play_blocks (0, msf2lba (toc_buffer[n].addr.msf.minute,
327 toc_buffer[n].addr.msf.second,
328 toc_buffer[n].addr.msf.frame));
404 toc_buffer[n].addr.msf.second,
405 toc_buffer[n].addr.msf.frame));
329
330 if (strchr (arg, '#')) {
406
407 if (strchr (arg, '#')) {
331 /*
332 * Play block #blk [ len ]
333 */
408 /* Play block #blk [ len ] */
334 int blk, len = 0;
335
336 if (2 != sscanf (arg, "#%d%d", &blk, &len) &&
409 int blk, len = 0;
410
411 if (2 != sscanf (arg, "#%d%d", &blk, &len) &&
337 1 != sscanf (arg, "#%d", &blk)) {
338err: printf ("Invalid command arguments\n");
339 return (0);
340 }
412 1 != sscanf (arg, "#%d", &blk))
413 goto Clean_up;
414
341 if (len == 0)
415 if (len == 0)
342 len = msf2lba (toc_buffer[n].addr.msf.minute,
343 toc_buffer[n].addr.msf.second,
344 toc_buffer[n].addr.msf.frame) - blk;
416 len = msf2lba (toc_buffer[n].addr.msf.minute,
417 toc_buffer[n].addr.msf.second,
418 toc_buffer[n].addr.msf.frame) - blk;
345 return play_blocks (blk, len);
346 }
347
348 if (strchr (arg, ':')) {
349 /*
350 * Play MSF m1:s1 [ .f1 ] [ m2:s2 [ .f2 ] ]
419 return play_blocks (blk, len);
420 }
421
422 if (strchr (arg, ':')) {
423 /*
424 * Play MSF m1:s1 [ .f1 ] [ m2:s2 [ .f2 ] ]
425 *
426 * Will now also undestand timed addresses relative
427 * to the beginning of a track in the form...
428 *
429 * tr1 m1:s1[.f1] [[tr2] [m2:s2[.f2]]]
351 */
430 */
352 int m1, m2 = 0, s1, s2 = 0, f1 = 0, f2 = 0;
431 unsigned tr1, tr2;
432 unsigned m1, m2, s1, s2, f1, f2;
353
433
354 if (6 != sscanf (arg, "%d:%d.%d%d:%d.%d", &m1, &s1, &f1, &m2, &s2, &f2) &&
434 tr2 = m2 = s2 = f2 = f1 = 0;
435 if (8 == sscanf (arg, "%d %d:%d.%d %d %d:%d.%d",
436 &tr1, &m1, &s1, &f1, &tr2, &m2, &s2, &f2))
437 goto Play_Relative_Addresses;
438
439 tr2 = m2 = s2 = f2 = f1 = 0;
440 if (7 == sscanf (arg, "%d %d:%d %d %d:%d.%d",
441 &tr1, &m1, &s1, &tr2, &m2, &s2, &f2))
442 goto Play_Relative_Addresses;
443
444 tr2 = m2 = s2 = f2 = f1 = 0;
445 if (7 == sscanf (arg, "%d %d:%d.%d %d %d:%d",
446 &tr1, &m1, &s1, &f1, &tr2, &m2, &s2))
447 goto Play_Relative_Addresses;
448
449 tr2 = m2 = s2 = f2 = f1 = 0;
450 if (7 == sscanf (arg, "%d %d:%d.%d %d:%d.%d",
451 &tr1, &m1, &s1, &f1, &m2, &s2, &f2))
452 goto Play_Relative_Addresses;
453
454 tr2 = m2 = s2 = f2 = f1 = 0;
455 if (6 == sscanf (arg, "%d %d:%d.%d %d:%d",
456 &tr1, &m1, &s1, &f1, &m2, &s2))
457 goto Play_Relative_Addresses;
458
459 tr2 = m2 = s2 = f2 = f1 = 0;
460 if (6 == sscanf (arg, "%d %d:%d %d:%d.%d",
461 &tr1, &m1, &s1, &m2, &s2, &f2))
462 goto Play_Relative_Addresses;
463
464 tr2 = m2 = s2 = f2 = f1 = 0;
465 if (6 == sscanf (arg, "%d %d:%d.%d %d %d",
466 &tr1, &m1, &s1, &f1, &tr2, &m2))
467 goto Play_Relative_Addresses;
468
469 tr2 = m2 = s2 = f2 = f1 = 0;
470 if (5 == sscanf (arg, "%d %d:%d %d:%d", &tr1, &m1, &s1, &m2, &s2))
471 goto Play_Relative_Addresses;
472
473 tr2 = m2 = s2 = f2 = f1 = 0;
474 if (5 == sscanf (arg, "%d %d:%d %d %d",
475 &tr1, &m1, &s1, &tr2, &m2))
476 goto Play_Relative_Addresses;
477
478 tr2 = m2 = s2 = f2 = f1 = 0;
479 if (5 == sscanf (arg, "%d %d:%d.%d %d",
480 &tr1, &m1, &s1, &f1, &tr2))
481 goto Play_Relative_Addresses;
482
483 tr2 = m2 = s2 = f2 = f1 = 0;
484 if (4 == sscanf (arg, "%d %d:%d %d", &tr1, &m1, &s1, &tr2))
485 goto Play_Relative_Addresses;
486
487 tr2 = m2 = s2 = f2 = f1 = 0;
488 if (4 == sscanf (arg, "%d %d:%d.%d", &tr1, &m1, &s1, &f1))
489 goto Play_Relative_Addresses;
490
491 tr2 = m2 = s2 = f2 = f1 = 0;
492 if (3 == sscanf (arg, "%d %d:%d", &tr1, &m1, &s1))
493 goto Play_Relative_Addresses;
494
495 tr2 = m2 = s2 = f2 = f1 = 0;
496 goto Try_Absolute_Timed_Addresses;
497
498Play_Relative_Addresses:
499 if (! tr1)
500 tr1 = 1;
501 else if (tr1 > n)
502 tr1 = n;
503
504 if ((m1 > toc_buffer[tr1].addr.msf.minute)
505 || ((m1 == toc_buffer[tr1].addr.msf.minute)
506 && ((s1 > toc_buffer[tr1].addr.msf.second)
507 || ((s1 == toc_buffer[tr1].addr.msf.second)
508 && (f1 > toc_buffer[tr1].addr.msf.frame))))) {
509 printf ("Track %d is not that long.\n", tr1);
510 return (0);
511 }
512
513 tr1--;
514
515 f1 += toc_buffer[tr1].addr.msf.frame;
516 if (f1 >= 75) {
517 s1 += f1 / 75;
518 f1 %= 75;
519 }
520
521 s1 += toc_buffer[tr1].addr.msf.second;
522 if (s1 >= 60) {
523 m1 += s1 / 60;
524 s1 %= 60;
525 }
526
527 m1 += toc_buffer[tr1].addr.msf.minute;
528
529 if (! tr2) {
530 if (m2 || s2 || f2) {
531 tr2 = tr1;
532 f2 += f1;
533 if (f2 >= 75) {
534 s2 += f2 / 75;
535 f2 %= 75;
536 }
537
538 s2 += s1;
539 if (s2 > 60) {
540 m2 += s2 / 60;
541 s2 %= 60;
542 }
543
544 m2 += m1;
545 } else {
546 tr2 = n;
547 m2 = toc_buffer[n].addr.msf.minute;
548 s2 = toc_buffer[n].addr.msf.second;
549 f2 = toc_buffer[n].addr.msf.frame;
550 }
551 } else if (tr2 > n) {
552 tr2 = n;
553 m2 = s2 = f2 = 0;
554 } else {
555 if (m2 || s2 || f2)
556 tr2--;
557 f2 += toc_buffer[tr2].addr.msf.frame;
558 if (f2 >= 75) {
559 s2 += f2 / 75;
560 f2 %= 75;
561 }
562
563 s2 += toc_buffer[tr2].addr.msf.second;
564 if (s2 > 60) {
565 m2 += s2 / 60;
566 s2 %= 60;
567 }
568
569 m2 += toc_buffer[tr2].addr.msf.minute;
570 }
571
572 if ((tr2 < n)
573 && ((m2 > toc_buffer[n].addr.msf.minute)
574 || ((m2 == toc_buffer[n].addr.msf.minute)
575 && ((s2 > toc_buffer[n].addr.msf.second)
576 || ((s2 == toc_buffer[n].addr.msf.second)
577 && (f2 > toc_buffer[n].addr.msf.frame)))))) {
578 printf ("The playing time of the disc is not that long.\n");
579 return (0);
580 }
581 return (play_msf (m1, s1, f1, m2, s2, f2));
582
583Try_Absolute_Timed_Addresses:
584 if (6 != sscanf (arg, "%d:%d.%d%d:%d.%d",
585 &m1, &s1, &f1, &m2, &s2, &f2) &&
355 5 != sscanf (arg, "%d:%d.%d%d:%d", &m1, &s1, &f1, &m2, &s2) &&
356 5 != sscanf (arg, "%d:%d%d:%d.%d", &m1, &s1, &m2, &s2, &f2) &&
357 3 != sscanf (arg, "%d:%d.%d", &m1, &s1, &f1) &&
358 4 != sscanf (arg, "%d:%d%d:%d", &m1, &s1, &m2, &s2) &&
359 2 != sscanf (arg, "%d:%d", &m1, &s1))
586 5 != sscanf (arg, "%d:%d.%d%d:%d", &m1, &s1, &f1, &m2, &s2) &&
587 5 != sscanf (arg, "%d:%d%d:%d.%d", &m1, &s1, &m2, &s2, &f2) &&
588 3 != sscanf (arg, "%d:%d.%d", &m1, &s1, &f1) &&
589 4 != sscanf (arg, "%d:%d%d:%d", &m1, &s1, &m2, &s2) &&
590 2 != sscanf (arg, "%d:%d", &m1, &s1))
360 goto err;
591 goto Clean_up;
592
361 if (m2 == 0) {
362 m2 = toc_buffer[n].addr.msf.minute;
363 s2 = toc_buffer[n].addr.msf.second;
364 f2 = toc_buffer[n].addr.msf.frame;
365 }
366 return play_msf (m1, s1, f1, m2, s2, f2);
367 }
368
369 /*
370 * Play track trk1 [ .idx1 ] [ trk2 [ .idx2 ] ]
371 */
372 if (4 != sscanf (arg, "%d.%d%d.%d", &start, &istart, &end, &iend) &&
373 3 != sscanf (arg, "%d.%d%d", &start, &istart, &end) &&
374 3 != sscanf (arg, "%d%d.%d", &start, &end, &iend) &&
375 2 != sscanf (arg, "%d.%d", &start, &istart) &&
376 2 != sscanf (arg, "%d%d", &start, &end) &&
377 1 != sscanf (arg, "%d", &start))
593 if (m2 == 0) {
594 m2 = toc_buffer[n].addr.msf.minute;
595 s2 = toc_buffer[n].addr.msf.second;
596 f2 = toc_buffer[n].addr.msf.frame;
597 }
598 return play_msf (m1, s1, f1, m2, s2, f2);
599 }
600
601 /*
602 * Play track trk1 [ .idx1 ] [ trk2 [ .idx2 ] ]
603 */
604 if (4 != sscanf (arg, "%d.%d%d.%d", &start, &istart, &end, &iend) &&
605 3 != sscanf (arg, "%d.%d%d", &start, &istart, &end) &&
606 3 != sscanf (arg, "%d%d.%d", &start, &end, &iend) &&
607 2 != sscanf (arg, "%d.%d", &start, &istart) &&
608 2 != sscanf (arg, "%d%d", &start, &end) &&
609 1 != sscanf (arg, "%d", &start))
378 goto err;
610 goto Clean_up;
611
379 if (end == 0)
380 end = n;
612 if (end == 0)
613 end = n;
381 return play_track (start, istart, end, iend);
614 return (play_track (start, istart, end, iend));
615
616Clean_up:
617 printf ("%s: Invalid command arguments\n", __progname);
618 return (0);
382}
383
384char *strstatus (int sts)
385{
386 switch (sts) {
387 case ASTS_INVALID: return ("invalid");
388 case ASTS_PLAYING: return ("playing");
389 case ASTS_PAUSED: return ("paused");

--- 66 unchanged lines hidden (view full) ---

456 perror ("getting toc header");
457 return (rc);
458 }
459
460 n = h.ending_track - h.starting_track + 1;
461 rc = read_toc_entrys ((n + 1) * sizeof (struct cd_toc_entry));
462 if (rc < 0)
463 return (rc);
619}
620
621char *strstatus (int sts)
622{
623 switch (sts) {
624 case ASTS_INVALID: return ("invalid");
625 case ASTS_PLAYING: return ("playing");
626 case ASTS_PAUSED: return ("paused");

--- 66 unchanged lines hidden (view full) ---

693 perror ("getting toc header");
694 return (rc);
695 }
696
697 n = h.ending_track - h.starting_track + 1;
698 rc = read_toc_entrys ((n + 1) * sizeof (struct cd_toc_entry));
699 if (rc < 0)
700 return (rc);
701
464 if (verbose) {
465 printf ("track start duration block length type\n");
466 printf ("-------------------------------------------------\n");
467 }
702 if (verbose) {
703 printf ("track start duration block length type\n");
704 printf ("-------------------------------------------------\n");
705 }
706
468 for (i = 0; i < n; i++) {
469 printf ("%5d ", toc_buffer[i].track);
470 prtrack (toc_buffer + i, 0);
471 }
472 printf ("%5d ", toc_buffer[n].track);
473 prtrack (toc_buffer + n, 1);
474 return (0);
475}
476
707 for (i = 0; i < n; i++) {
708 printf ("%5d ", toc_buffer[i].track);
709 prtrack (toc_buffer + i, 0);
710 }
711 printf ("%5d ", toc_buffer[n].track);
712 prtrack (toc_buffer + n, 1);
713 return (0);
714}
715
477void lba2msf (int lba, u_char *m, u_char *s, u_char *f)
716void lba2msf (unsigned long lba, u_char *m, u_char *s, u_char *f)
478{
717{
479 lba += 150; /* block start offset */
480 lba &= 0xffffff; /* negative lbas use only 24 bits */
718 lba += 150; /* block start offset */
719 lba &= 0xffffff; /* negative lbas use only 24 bits */
481 *m = lba / (60 * 75);
482 lba %= (60 * 75);
483 *s = lba / 75;
484 *f = lba % 75;
485}
486
720 *m = lba / (60 * 75);
721 lba %= (60 * 75);
722 *s = lba / 75;
723 *f = lba % 75;
724}
725
487int msf2lba (u_char m, u_char s, u_char f)
726unsigned int msf2lba (u_char m, u_char s, u_char f)
488{
489 return (((m * 60) + s) * 75 + f) - 150;
490}
491
492void prtrack (struct cd_toc_entry *e, int lastflag)
493{
494 int block, next, len;
495 u_char m, s, f;

--- 22 unchanged lines hidden (view full) ---

518 e[1].addr.msf.frame);
519 else
520 next = ntohl(e[1].addr.lba);
521 len = next - block;
522 lba2msf (len, &m, &s, &f);
523
524 /* Print duration, block, length, type */
525 printf ("%2d:%02d.%02d %6d %6d %5s\n", m, s, f, block, len,
727{
728 return (((m * 60) + s) * 75 + f) - 150;
729}
730
731void prtrack (struct cd_toc_entry *e, int lastflag)
732{
733 int block, next, len;
734 u_char m, s, f;

--- 22 unchanged lines hidden (view full) ---

757 e[1].addr.msf.frame);
758 else
759 next = ntohl(e[1].addr.lba);
760 len = next - block;
761 lba2msf (len, &m, &s, &f);
762
763 /* Print duration, block, length, type */
764 printf ("%2d:%02d.%02d %6d %6d %5s\n", m, s, f, block, len,
526 e->control & 4 ? "data" : "audio");
765 (e->control & 4) ? "data" : "audio");
527}
528
529int play_track (int tstart, int istart, int tend, int iend)
530{
531 struct ioc_play_track t;
532
533 t.start_track = tstart;
534 t.start_index = istart;
535 t.end_track = tend;
536 t.end_index = iend;
766}
767
768int play_track (int tstart, int istart, int tend, int iend)
769{
770 struct ioc_play_track t;
771
772 t.start_track = tstart;
773 t.start_index = istart;
774 t.end_track = tend;
775 t.end_index = iend;
776
537 return ioctl (fd, CDIOCPLAYTRACKS, &t);
538}
539
540int play_blocks (int blk, int len)
541{
777 return ioctl (fd, CDIOCPLAYTRACKS, &t);
778}
779
780int play_blocks (int blk, int len)
781{
542 struct ioc_play_blocks t;
782 struct ioc_play_blocks t;
543
544 t.blk = blk;
545 t.len = len;
783
784 t.blk = blk;
785 t.len = len;
786
546 return ioctl (fd, CDIOCPLAYBLOCKS, &t);
547}
548
787 return ioctl (fd, CDIOCPLAYBLOCKS, &t);
788}
789
549int setvol (int l, int r)
790int setvol (int left, int right)
550{
791{
551 struct ioc_vol v;
792 struct ioc_vol v;
552
793
553 v.vol[0] = l;
554 v.vol[1] = r;
794 v.vol[0] = left;
795 v.vol[1] = right;
555 v.vol[2] = 0;
556 v.vol[3] = 0;
796 v.vol[2] = 0;
797 v.vol[3] = 0;
798
557 return ioctl (fd, CDIOCSETVOL, &v);
558}
559
560int read_toc_entrys (int len)
561{
562 struct ioc_read_toc_entry t;
563
564 t.address_format = msf ? CD_MSF_FORMAT : CD_LBA_FORMAT;
565 t.starting_track = 0;
566 t.data_len = len;
567 t.data = toc_buffer;
799 return ioctl (fd, CDIOCSETVOL, &v);
800}
801
802int read_toc_entrys (int len)
803{
804 struct ioc_read_toc_entry t;
805
806 t.address_format = msf ? CD_MSF_FORMAT : CD_LBA_FORMAT;
807 t.starting_track = 0;
808 t.data_len = len;
809 t.data = toc_buffer;
568 return ioctl (fd, CDIOREADTOCENTRYS, (char *) &t);
810
811 return (ioctl (fd, CDIOREADTOCENTRYS, (char *) &t));
569}
570
571int play_msf (int start_m, int start_s, int start_f,
812}
813
814int play_msf (int start_m, int start_s, int start_f,
572 int end_m, int end_s, int end_f)
815 int end_m, int end_s, int end_f)
573{
816{
574 struct ioc_play_msf a;
817 struct ioc_play_msf a;
575
576 a.start_m = start_m;
577 a.start_s = start_s;
578 a.start_f = start_f;
579 a.end_m = end_m;
580 a.end_s = end_s;
581 a.end_f = end_f;
818
819 a.start_m = start_m;
820 a.start_s = start_s;
821 a.start_f = start_f;
822 a.end_m = end_m;
823 a.end_s = end_s;
824 a.end_f = end_f;
825
582 return ioctl (fd, CDIOCPLAYMSF, (char *) &a);
583}
584
585int status (int *trk, int *min, int *sec, int *frame)
586{
587 struct ioc_read_subchannel s;
588 struct cd_sub_channel_info data;
589 u_char mm, ss, ff;
590
591 bzero (&s, sizeof (s));
592 s.data = &data;
593 s.data_len = sizeof (data);
594 s.address_format = msf ? CD_MSF_FORMAT : CD_LBA_FORMAT;
595 s.data_format = CD_CURRENT_POSITION;
826 return ioctl (fd, CDIOCPLAYMSF, (char *) &a);
827}
828
829int status (int *trk, int *min, int *sec, int *frame)
830{
831 struct ioc_read_subchannel s;
832 struct cd_sub_channel_info data;
833 u_char mm, ss, ff;
834
835 bzero (&s, sizeof (s));
836 s.data = &data;
837 s.data_len = sizeof (data);
838 s.address_format = msf ? CD_MSF_FORMAT : CD_LBA_FORMAT;
839 s.data_format = CD_CURRENT_POSITION;
840
596 if (ioctl (fd, CDIOCREADSUBCHANNEL, (char *) &s) < 0)
597 return -1;
841 if (ioctl (fd, CDIOCREADSUBCHANNEL, (char *) &s) < 0)
842 return -1;
843
598 *trk = s.data->what.position.track_number;
599 if (msf) {
600 *min = s.data->what.position.reladdr.msf.minute;
601 *sec = s.data->what.position.reladdr.msf.second;
602 *frame = s.data->what.position.reladdr.msf.frame;
603 } else {
604 lba2msf(ntohl(s.data->what.position.reladdr.lba),
605 &mm, &ss, &ff);
606 *min = mm;
607 *sec = ss;
608 *frame = ff;
609 }
844 *trk = s.data->what.position.track_number;
845 if (msf) {
846 *min = s.data->what.position.reladdr.msf.minute;
847 *sec = s.data->what.position.reladdr.msf.second;
848 *frame = s.data->what.position.reladdr.msf.frame;
849 } else {
850 lba2msf(ntohl(s.data->what.position.reladdr.lba),
851 &mm, &ss, &ff);
852 *min = mm;
853 *sec = ss;
854 *frame = ff;
855 }
856
610 return s.data->header.audio_status;
611}
612
613char *input (int *cmd)
614{
615 static char buf[80];
616 char *p;
617
618 do {
619 if (verbose)
857 return s.data->header.audio_status;
858}
859
860char *input (int *cmd)
861{
862 static char buf[80];
863 char *p;
864
865 do {
866 if (verbose)
620 fprintf (stderr, "cd> ");
867 fprintf (stderr, "%s> ", __progname);
621 if (! fgets (buf, sizeof (buf), stdin)) {
622 *cmd = CMD_QUIT;
868 if (! fgets (buf, sizeof (buf), stdin)) {
869 *cmd = CMD_QUIT;
623 return 0;
870 fprintf (stderr, "\r\n");
871 return (0);
624 }
625 p = parse (buf, cmd);
626 } while (! p);
627 return (p);
628}
629
630char *parse (char *buf, int *cmd)
631{
632 struct cmdtab *c;
633 char *p;
634 int len;
635
872 }
873 p = parse (buf, cmd);
874 } while (! p);
875 return (p);
876}
877
878char *parse (char *buf, int *cmd)
879{
880 struct cmdtab *c;
881 char *p;
882 int len;
883
636 for (p=buf; *p; ++p)
637 if (*p == '\t')
638 *p = ' ';
639 else if (*p == '\n')
640 *p = 0;
884 for (p=buf; isspace (*p); p++)
885 continue;
641
886
642 for (p=buf; *p; ++p)
643 if (*p == ' ') {
644 *p++ = 0;
645 break;
646 }
647 while (*p == ' ')
648 ++p;
887 if (isdigit (*p) || (p[0] == '#' && isdigit (p[1]))) {
888 *cmd = CMD_PLAY;
889 return (p);
890 }
649
891
650 len = strlen (buf);
892 for (buf = p; *p && ! isspace (*p); p++)
893 continue;
894
895 len = p - buf;
651 if (! len)
652 return (0);
896 if (! len)
897 return (0);
653 *cmd = -1;
654 for (c=cmdtab; c->name; ++c) {
655 /* Try short command form. */
656 if (! c->args && len == strlen (c->name) &&
657 strncasecmp (buf, c->name, len) == 0) {
658 *cmd = c->command;
659 break;
660 }
661
898
662 /* Try long form. */
663 if (strncasecmp (buf, c->name, len) != 0)
899 if (*p) { /* It must be a spacing character! */
900 char *q;
901
902 *p++ = 0;
903 for (q=p; *q && *q != '\n' && *q != '\r'; q++)
664 continue;
904 continue;
905 *q = 0;
906 }
665
907
666 /* Check inambiguity. */
667 if (*cmd != -1 && *cmd != c->command) {
668 fprintf (stderr, "Ambiguous command\n");
669 return (0);
670 }
671 *cmd = c->command;
908 *cmd = -1;
909 for (c=cmdtab; c->name; ++c) {
910 /* Is it an exact match? */
911 if (! strcasecmp (buf, c->name)) {
912 *cmd = c->command;
913 break;
914 }
915
916 /* Try short hand forms then... */
917 if (len >= c->min && ! strncasecmp (buf, c->name, len)) {
918 if (*cmd != -1 && *cmd != c->command) {
919 fprintf (stderr, "Ambiguous command\n");
920 return (0);
921 }
922 *cmd = c->command;
923 }
672 }
924 }
925
673 if (*cmd == -1) {
926 if (*cmd == -1) {
674 fprintf (stderr, "Invalid command, enter ``help'' for command list\n");
927 fprintf (stderr, "%s: Invalid command, enter ``help'' for commands.\n",
928 __progname);
675 return (0);
676 }
929 return (0);
930 }
931
932 while (isspace (*p))
933 p++;
677 return p;
678}
679
680int open_cd ()
681{
682 char devbuf[80];
683
684 if (fd > -1)
685 return (1);
934 return p;
935}
936
937int open_cd ()
938{
939 char devbuf[80];
940
941 if (fd > -1)
942 return (1);
943
686 if (*cdname == '/')
687 strcpy (devbuf, cdname);
688 else if (*cdname == 'r')
689 sprintf (devbuf, "/dev/%s", cdname);
690 else
691 sprintf (devbuf, "/dev/r%s", cdname);
944 if (*cdname == '/')
945 strcpy (devbuf, cdname);
946 else if (*cdname == 'r')
947 sprintf (devbuf, "/dev/%s", cdname);
948 else
949 sprintf (devbuf, "/dev/r%s", cdname);
950
692 fd = open (devbuf, O_RDONLY);
951 fd = open (devbuf, O_RDONLY);
952
693 if (fd < 0 && errno == ENOENT) {
953 if (fd < 0 && errno == ENOENT) {
694 strcat (devbuf, "c");
954 strcat (devbuf, DEFAULT_CD_PARTITION);
695 fd = open (devbuf, O_RDONLY);
696 }
955 fd = open (devbuf, O_RDONLY);
956 }
957
697 if (fd < 0) {
958 if (fd < 0) {
698 if (errno != ENXIO) {
699 perror (devbuf);
700 exit (1);
959 if (errno == ENXIO) {
960 /* ENXIO has an overloaded meaning here.
961 * The original "Device not configured" should
962 * be interpreted as "No disc in drive %s". */
963 fprintf (stderr, "%s: No disc in drive %s.\n", __progname, devbuf);
964 return (0);
701 }
965 }
702 /* open says 'Device not configured' if no cd in */
703 fprintf (stderr, "open: No CD in\n");
704 return (0);
966 perror (devbuf);
967 exit (1);
705 }
706 return (1);
707}
968 }
969 return (1);
970}