File: cdromlinux.h

package info (click to toggle)
xmms-cdread 0.14a-6
  • links: PTS
  • area: main
  • in suites: woody
  • size: 832 kB
  • ctags: 269
  • sloc: sh: 7,705; ansic: 3,052; makefile: 65
file content (173 lines) | stat: -rw-r--r-- 3,844 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
/*\
|*| PLatform dependent code for accessing CDROM units.
|*| For now, Linux and FreeBSD
\*/
#ifndef CDROMLINUX_H
#define CDROMLINUX_H
/*\
|*| Linux specific code
\*/

#define GET_LBA(entry) ((entry.cdte_format == CDROM_LBA) ? \
				entry.cdte_addr.lba : \
					((entry.cdte_addr.msf.minute * 60 + \
					entry.cdte_addr.msf.second) * 75 + \
					entry.cdte_addr.msf.frame))

/*\
|*| Open cdrom device
|*|  Return -1 on error.
\*/
static int
cdrom_open(const char *device, int *flags)
{
	int fd;
	fd = open(device, O_RDONLY|O_NONBLOCK);
	if (fd < 0) return -1;
	if (!(*flags & FLAG_FAIL_SPD) &&
	    (ioctl(fd, CDROM_SELECT_SPEED, cd_cfg.cdrom_speed) < 0)) {
		if (errno == ENOTTY) {
			close(fd);
			return -1;
		}
		*flags |= FLAG_FAIL_SPD;
	}
	return fd;
}

/*\
|*| Close cdrom device
|*|  Return -1 on error.
\*/
static int
cdrom_close(int cdfd)
{
	return close(cdfd);
}

/*\ Read the toc into:
|*|  cd->first_trk .. cd->last_trk
|*|  cd->lba[..], cd->data[..]
|*|
|*| Return -1 on error.
\*/
static int
cdrom_read_toc(struct cd_struct *cd, int cdfd)
{
	int i;
	struct cdrom_tochdr toc_hdr;
	struct cdrom_tocentry entry;

	if (ioctl(cdfd, CDROMREADTOCHDR, &toc_hdr) < 0) {
		cd->first_trk = 1;
		cd->last_trk = 0;
		return -1;
	}
	cd->first_trk = toc_hdr.cdth_trk0;
	cd->last_trk = toc_hdr.cdth_trk1;
	i = cd->last_trk + 1;
	entry.cdte_track = CDROM_LEADOUT;
	entry.cdte_format = CDROM_MSF;
	ioctl(cdfd, CDROMREADTOCENTRY, &entry);
	cd->lba[i] = GET_LBA(entry);
	cd->data[i] = entry.cdte_ctrl & 4;
	while (--i >= cd->first_trk) {
		entry.cdte_track = i;
		entry.cdte_format = CDROM_MSF;
		ioctl(cdfd, CDROMREADTOCENTRY, &entry);
		cd->lba[i] = GET_LBA(entry);
		cd->data[i] = entry.cdte_ctrl & 4;
	}
	return 0;
}

/*\ Read btw frames of audio data into buf,
|*|  from device cdfd, at position lba
|*|  Return number of successfully read frames, -1 on error.
\*/
static int
cdrom_read_audio(int cdfd, int lba, char *buf, int btw)
{
	int rtr = 3;
	do {
		struct cdrom_read_audio cdra;
		cdra.buf = buf;
		cdra.nframes = btw;
		cdra.addr.msf.minute = lba / (75 * 60);
		cdra.addr.msf.second = (lba / 75) % 60;
		cdra.addr.msf.frame = lba % 75;
		cdra.addr_format = CDROM_MSF;
		if (ioctl(cdfd, CDROMREADAUDIO, &cdra) >= 0)
			return cdra.nframes;
	} while (--rtr >= 0);
	return -1;
}

/*\ Play audio from lba address from, to lba address to
|*|  return -1 on failure
\*/
static int
cdrom_play_lba(int cdfd, int from, int to)
{
	struct cdrom_msf cmsf;
	cmsf.cdmsf_min0 = from / (75 * 60);
	cmsf.cdmsf_sec0 = (from / 75) % 60;
	cmsf.cdmsf_frame0 = from % 75;
	cmsf.cdmsf_min1 = to / (75 * 60);
	cmsf.cdmsf_sec1 = (to / 75) % 60;
	cmsf.cdmsf_frame1 = to % 75;
	return ioctl(cdfd, CDROMPLAYMSF, &cmsf);
}

/*\ Stop audio playback
|*|  return -1 on failure
\*/ 
static int
cdrom_stop(int cdfd)
{
	/*\ CDROMPAUSE: Rude hack, because stop takes so long.
	|*|             It looks like it actually stops the disc spinning..
	\*/
	if (cdfd >= 0) return ioctl(cdfd, CDROMPAUSE, 0);
	return 0;
}

/*\ Pause/resume audio playback
|*|  return -1 on failure
\*/
static int
cdrom_pause(int cdfd, short p)
{
	return ioctl(cdfd, p ? CDROMPAUSE : CDROMRESUME);
}

/*\ Get currently playing relative time
|*|  return -1 on failure
|*|  (Closes cdfd if not playing)
\*/
static gint32
cdrom_get_time(struct cd_struct *cd)
{
	gint32 f;
	struct cdrom_subchnl cdsc;

	if (cd->cdfd < 0)
		return -1;
	cdsc.cdsc_format = CDROM_MSF;
	if (ioctl(cd->cdfd, CDROMSUBCHNL, &cdsc) < 0)
		return -2;
	if (cdsc.cdsc_audiostatus == CDROM_AUDIO_ERROR)
		return -2;
	if (cdsc.cdsc_audiostatus == CDROM_AUDIO_COMPLETED)
		return -1;
	f = ((cdsc.cdsc_absaddr.msf.minute * 60 +
		cdsc.cdsc_absaddr.msf.second) * 75 +
		cdsc.cdsc_absaddr.msf.frame);
	if (f > (end_lba - 20))
		return -1;
	f -= cd->lba[cur_trk];
	if (f < 0) f = 0;
	return (f * 40) / 3;
}

#endif /*\ CDROMLINUX_H \*/