5f4aa2b260f17a9149f7b040d86c5cd1ebf417cc
[divverent/darkplaces.git] / cd_bsd.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // Quake is a trademark of Id Software, Inc., (c) 1996 Id Software, Inc. All
21 // rights reserved.
22
23 #include <sys/types.h>
24 #include <sys/cdio.h>
25 #include <sys/ioctl.h>
26
27 #include <errno.h>
28 #include <fcntl.h>
29 #include <paths.h>
30 #include <unistd.h>
31 #include <util.h>
32
33 #include "quakedef.h"
34
35
36 static int cdfile = -1;
37 static char cd_dev[64] = _PATH_DEV "cd0";
38
39
40 void CDAudio_SysEject (void)
41 {
42         if (cdfile == -1)
43                 return;
44
45         ioctl(cdfile, CDIOCALLOW);
46         if (ioctl(cdfile, CDIOCEJECT) == -1)
47                 Con_DPrint("ioctl CDIOCEJECT failed\n");
48 }
49
50
51 void CDAudio_SysCloseDoor (void)
52 {
53         if (cdfile == -1)
54                 return;
55
56         ioctl(cdfile, CDIOCALLOW);
57         if (ioctl(cdfile, CDIOCCLOSE) == -1)
58                 Con_DPrint("ioctl CDIOCCLOSE failed\n");
59 }
60
61 int CDAudio_SysGetAudioDiskInfo (void)
62 {
63         struct ioc_toc_header tochdr;
64
65         if (cdfile == -1)
66                 return -1;
67
68         if (ioctl(cdfile, CDIOREADTOCHEADER, &tochdr) == -1)
69         {
70                 Con_DPrint("ioctl CDIOREADTOCHEADER failed\n");
71                 return -1;
72         }
73
74         if (tochdr.starting_track < 1)
75         {
76                 Con_DPrint("CDAudio: no music tracks\n");
77                 return -1;
78         }
79
80         return tochdr.ending_track;
81 }
82
83
84 float CDAudio_SysGetVolume (void)
85 {
86         struct ioc_vol vol;
87
88         if (cdfile == -1)
89                 return -1.0f;
90
91         if (ioctl (cdfile, CDIOCGETVOL, &vol) == -1)
92         {
93                 Con_DPrint("ioctl CDIOCGETVOL failed\n");
94                 return -1.0f;
95         }
96
97         return (vol.vol[0] + vol.vol[1]) / 2.0f / 255.0f;
98 }
99
100
101 void CDAudio_SysSetVolume (float volume)
102 {
103         struct ioc_vol vol;
104
105         if (cdfile == -1)
106                 return;
107
108         vol.vol[0] = vol.vol[1] = volume * 255;
109         vol.vol[2] = vol.vol[3] = 0;
110
111         if (ioctl (cdfile, CDIOCSETVOL, &vol) == -1)
112                 Con_DPrintf ("ioctl CDIOCSETVOL failed\n");
113 }
114
115
116 int CDAudio_SysPlay (qbyte track)
117 {
118         struct ioc_read_toc_entry rte;
119         struct cd_toc_entry entry;
120         struct ioc_play_track ti;
121
122         if (cdfile == -1)
123                 return -1;
124
125         // don't try to play a non-audio track
126         rte.address_format = CD_MSF_FORMAT;
127         rte.starting_track = track;
128         rte.data_len = sizeof(entry);
129         rte.data = &entry;
130         if (ioctl(cdfile, CDIOREADTOCENTRYS, &rte) == -1)
131         {
132                 Con_DPrint("ioctl CDIOREADTOCENTRYS failed\n");
133                 return -1;
134         }
135         if (entry.control & 4)  // if it's a data track
136         {
137                 Con_Printf("CDAudio: track %i is not audio\n", track);
138                 return -1;
139         }
140
141         if (cdPlaying)
142                 CDAudio_Stop();
143
144         ti.start_track = track;
145         ti.end_track = track;
146         ti.start_index = 1;
147         ti.end_index = 99;
148
149         if (ioctl(cdfile, CDIOCPLAYTRACKS, &ti) == -1)
150         {
151                 Con_DPrint("ioctl CDIOCPLAYTRACKS failed\n");
152                 return -1;
153         }
154
155         if (ioctl(cdfile, CDIOCRESUME) == -1)
156         {
157                 Con_DPrint("ioctl CDIOCRESUME failed\n");
158                 return -1;
159         }
160
161         return 0;
162 }
163
164
165 int CDAudio_SysStop (void)
166 {
167         if (cdfile == -1)
168                 return -1;
169
170         if (ioctl(cdfile, CDIOCSTOP) == -1)
171         {
172                 Con_DPrintf("ioctl CDIOCSTOP failed (%d)\n", errno);
173                 return -1;
174         }
175         ioctl(cdfile, CDIOCALLOW);
176
177         return 0;
178 }
179
180 int CDAudio_SysPause (void)
181 {
182         if (cdfile == -1)
183                 return -1;
184
185         if (ioctl(cdfile, CDIOCPAUSE) == -1)
186         {
187                 Con_DPrint("ioctl CDIOCPAUSE failed\n");
188                 return -1;
189         }
190
191         return 0;
192 }
193
194
195 int CDAudio_SysResume (void)
196 {
197         if (cdfile == -1)
198                 return -1;
199
200         if (ioctl(cdfile, CDIOCRESUME) == -1)
201                 Con_DPrint("ioctl CDIOCRESUME failed\n");
202
203         return 0;
204 }
205
206 int CDAudio_SysUpdate (void)
207 {
208         static time_t lastchk = 0;
209         struct ioc_read_subchannel subchnl;
210         struct cd_sub_channel_info data;
211
212         if (cdPlaying && lastchk < time(NULL))
213         {
214                 lastchk = time(NULL) + 2; //two seconds between chks
215
216                 bzero(&subchnl, sizeof(subchnl));
217                 subchnl.data = &data;
218                 subchnl.data_len = sizeof(data);
219                 subchnl.address_format = CD_MSF_FORMAT;
220                 subchnl.data_format = CD_CURRENT_POSITION;
221
222                 if (ioctl(cdfile, CDIOCREADSUBCHANNEL, &subchnl) == -1)
223                 {
224                         Con_DPrint("ioctl CDIOCREADSUBCHANNEL failed\n");
225                         cdPlaying = false;
226                         return -1;
227                 }
228                 if (data.header.audio_status != CD_AS_PLAY_IN_PROGRESS &&
229                         data.header.audio_status != CD_AS_PLAY_PAUSED)
230                 {
231                         cdPlaying = false;
232                         if (cdPlayLooping)
233                                 CDAudio_Play(cdPlayTrack, true);
234                 }
235                 else
236                         cdPlayTrack = data.what.position.track_number;
237         }
238
239         return 0;
240 }
241
242 void CDAudio_SysInit (void)
243 {
244         int i;
245
246         if ((i = COM_CheckParm("-cddev")) != 0 && i < com_argc - 1)
247                 strlcpy(cd_dev, com_argv[i + 1], sizeof(cd_dev));
248 }
249
250 int CDAudio_SysStartup (void)
251 {
252         char buff [80];
253
254         if ((cdfile = opendisk(cd_dev, O_RDONLY, buff, sizeof(buff), 0)) == -1)
255         {
256                 Con_DPrintf("CDAudio_SysStartup: open of \"%s\" failed (%i)\n",
257                                         cd_dev, errno);
258                 cdfile = -1;
259                 return -1;
260         }
261
262         return 0;
263 }
264
265 void CDAudio_SysShutdown (void)
266 {
267         close(cdfile);
268         cdfile = -1;
269 }