File indexing completed on 2024-04-28 08:46:55
0001 /* 0002 * This file is part of WorkMan, the civilized CD player library 0003 * Copyright (C) 1991-1997 by Steven Grimm <koreth@midwinter.com> 0004 * Copyright (C) by Dirk Försterling <milliByte@DeathsDoor.com> 0005 * 0006 * This library is free software; you can redistribute it and/or 0007 * modify it under the terms of the GNU Library General Public 0008 * License as published by the Free Software Foundation; either 0009 * version 2 of the License, or (at your option) any later version. 0010 * 0011 * This library is distributed in the hope that it will be useful, 0012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0014 * Library General Public License for more details. 0015 * 0016 * You should have received a copy of the GNU Library General Public 0017 * License along with this library; if not, write to the Free 0018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 0019 * 0020 * 0021 * Sony NEWS-specific drive control routines. 0022 */ 0023 0024 #if defined( __sony_news) || defined(sony_news) 0025 0026 #include <errno.h> 0027 #include <stdio.h> 0028 #include <fcntl.h> 0029 #include <ustat.h> 0030 #include <CD.h> 0031 #include <sys/types.h> 0032 #include <sys/param.h> 0033 #include <sys/stat.h> 0034 #include <sys/time.h> 0035 0036 #include "include/wm_config.h" 0037 #include "include/wm_struct.h" 0038 #include "include/wm_cdtext.h" 0039 0040 #define WM_MSG_CLASS WM_MSG_CLASS_PLATFORM 0041 0042 void *malloc(); 0043 char *strchr(); 0044 0045 extern int intermittent_dev; 0046 0047 int min_volume = 128; 0048 int max_volume = 255; 0049 0050 /* 0051 * Initialize the drive. A no-op for the generic driver. 0052 */ 0053 int 0054 gen_init( struct wm_drive *d ) 0055 { 0056 return 0; 0057 } /* gen_init() */ 0058 0059 /* 0060 * Open the CD device and figure out what kind of drive is attached. 0061 */ 0062 int 0063 gen_open( struct wm_drive *d ) 0064 { 0065 if (d->fd > -1) { /* Device already open? */ 0066 wm_lib_message(WM_MSG_LEVEL_DEBUG|WM_MSG_CLASS, "gen_open(): [device is open (fd=%d)]\n", d->fd); 0067 return 0; 0068 } 0069 0070 intermittent_dev = 1; 0071 0072 if ((d->fd = CD_Open(d->cd_device, 0)) < 0) { 0073 /* Solaris 2.2 volume manager moves links around */ 0074 if (errno == ENOENT && intermittent_dev) 0075 return 0; 0076 0077 if (errno == EACCES) 0078 return -EACCES; 0079 else if (errno != EIO) /* defined at top */ 0080 return -6; 0081 0082 /* No CD in drive. */ 0083 return 1; 0084 } 0085 0086 return 0; 0087 } /* gen_open() */ 0088 0089 /* 0090 * Pass SCSI commands to the device. 0091 */ 0092 int 0093 gen_scsi(struct wm_drive *d, unsigned char *cdb, int cdblen, 0094 unsigned char *buf, int buflen, int getreply) 0095 { 0096 /* NEWS can't do SCSI passthrough... or can it? */ 0097 return -1; 0098 } /* gen_scsi() */ 0099 0100 int 0101 gen_close( struct wm_drive *d ) 0102 { 0103 int ret = 0; 0104 if(d->fd != -1) { 0105 wm_lib_message(WM_MSG_LEVEL_DEBUG|WM_MSG_CLASS, "closing the device.\n"); 0106 ret = CD_Close(d->fd); 0107 d->fd = -1; 0108 wm_susleep(3000000); 0109 } 0110 return ret; 0111 } 0112 0113 /* 0114 * Get the current status of the drive: the current play mode, the absolute 0115 * position from start of disc (in frames), and the current track and index 0116 * numbers if the CD is playing or paused. 0117 */ 0118 int 0119 gen_get_drive_status( struct wm_drive *d, int oldmode, 0120 int *mode, int *pos, int *track, int *index) 0121 { 0122 struct CD_Status sc; 0123 0124 /* If we can't get status, the CD is ejected, so default to that. */ 0125 *mode = WM_CDM_EJECTED; 0126 0127 /* Is the device open? */ 0128 if (d->fd < 0) { 0129 switch (d->proto.open(d)) { 0130 case -1: /* error */ 0131 return -1; 0132 0133 case 1: /* retry */ 0134 return 0; 0135 } 0136 } 0137 0138 /* Disc is ejected. Close the device. */ 0139 if (CD_GetStatus(d->fd, &sc)) { 0140 gen_close(d); 0141 return 0; 0142 } 0143 0144 switch (sc.status) { 0145 case CDSTAT_PLAY: 0146 *mode = WM_CDM_PLAYING; 0147 break; 0148 0149 case CDSTAT_PAUSE: 0150 if (oldmode == WM_CDM_PLAYING || oldmode == WM_CDM_PAUSED) 0151 *mode = WM_CDM_PAUSED; 0152 else 0153 *mode = WM_CDM_STOPPED; 0154 break; 0155 0156 case CDSTAT_STOP: 0157 if (oldmode == WM_CDM_PLAYING) { 0158 *mode = WM_CDM_TRACK_DONE; /* waiting for next track. */ 0159 break; 0160 } 0161 /* fall through */ 0162 0163 default: 0164 *mode = WM_CDM_STOPPED; 0165 break; 0166 } 0167 0168 switch(*mode) { 0169 case WM_CDM_PLAYING: 0170 case WM_CDM_PAUSED: 0171 *track = sc.tno; 0172 *index = sc.index; 0173 *pos = sc.baddr; 0174 break; 0175 } 0176 0177 return 0; 0178 } /* gen_get_drive_status() */ 0179 0180 /* 0181 * Get the number of tracks on the CD. 0182 */ 0183 int 0184 gen_get_trackcount(struct wm_drive *d, int *tracks) 0185 { 0186 struct CD_Capacity cc; 0187 0188 if (CD_GetCapacity(d->fd, &cc)) 0189 return -1; 0190 0191 *tracks = cc.etrack - 1; 0192 return 0; 0193 } /* gen_get_trackcount() */ 0194 0195 /* 0196 * Get the start time and mode (data or audio) of a track. 0197 */ 0198 int 0199 gen_get_trackinfo( struct wm_drive *d, int track, int *data, int *startframe ) 0200 { 0201 struct CD_TOCinfo hdr; 0202 struct CD_TOCdata ent; 0203 0204 hdr.strack = track; 0205 hdr.ntrack = 1; 0206 hdr.data = &ent; 0207 if (CD_ReadTOC(d->fd, &hdr)) 0208 return (-1); 0209 0210 *data = (ent.control & 4) ? 1 : 0; 0211 *startframe = ent.baddr; 0212 0213 return 0; 0214 } /* gen_get_trackinfo */ 0215 0216 /* 0217 * Get the number of frames on the CD. 0218 */ 0219 int 0220 gen_get_cdlen( struct wm_drive *d, int *frames ) 0221 { 0222 int tmp; 0223 0224 if ((d->get_trackcount)(d, &tmp)) 0225 return -1; 0226 0227 return gen_get_trackinfo(d, tmp + 1, &tmp, frames); 0228 } /* gen_get_cdlen() */ 0229 0230 0231 /* 0232 * Play the CD from one position to another (both in frames.) 0233 */ 0234 int 0235 gen_play( struct wm_drive *d, int start, int end ) 0236 { 0237 struct CD_PlayAddr msf; 0238 0239 msf.addrmode = CD_MSF; 0240 msf.addr.msf.startmsf.min = start / (60*75); 0241 msf.addr.msf.startmsf.sec = (start % (60*75)) / 75; 0242 msf.addr.msf.startmsf.frame = start % 75; 0243 msf.addr.msf.endmsf.min = end / (60*75); 0244 msf.addr.msf.endmsf.sec = (end % (60*75)) / 75; 0245 msf.addr.msf.endmsf.frame = end % 75; 0246 0247 if (CD_Play(d->fd, &msf)) { 0248 wm_lib_message(WM_MSG_LEVEL_ERROR|WM_MSG_CLASS, 0249 "wm_cd_play_chunk(%d,%d)\n",start,end); 0250 wm_lib_message(WM_MSG_LEVEL_ERROR|WM_MSG_CLASS, 0251 "msf = %d:%d:%d %d:%d:%d\n", 0252 msf.addr.msf.startmsf.min, 0253 msf.addr.msf.startmsf.sec, 0254 msf.addr.msf.startmsf.frame, 0255 msf.addr.msf.endmsf.min, 0256 msf.addr.msf.endmsf.sec, 0257 msf.addr.msf.endmsf.frame); 0258 wm_lib_message(WM_MSG_LEVEL_ERROR|WM_MSG_CLASS, 0259 "CD_Play"); 0260 return -1; 0261 } 0262 0263 return 0; 0264 } /* gen_play() */ 0265 0266 /* 0267 * Pause the CD. 0268 */ 0269 int 0270 gen_pause( struct wm_drive *d ) 0271 { 0272 CD_Pause(d->fd); 0273 return 0; 0274 } /* gen_pause() */ 0275 0276 /* 0277 * Resume playing the CD (assuming it was paused.) 0278 */ 0279 int 0280 gen_resume( struct wm_drive *d ) 0281 { 0282 CD_Restart(d->fd); 0283 return 0; 0284 } /* gen_resume() */ 0285 0286 /* 0287 * Stop the CD. 0288 */ 0289 int 0290 gen_stop( struct wm_drive *d ) 0291 { 0292 CD_Stop(d->fd); 0293 return 0; 0294 } /* gen_stop() */ 0295 0296 /* 0297 * Eject the current CD, if there is one. 0298 */ 0299 int 0300 gen_eject( struct wm_drive *d ) 0301 { 0302 struct stat stbuf; 0303 struct ustat ust; 0304 0305 if (fstat(d->fd, &stbuf) != 0) 0306 return -2; 0307 0308 /* Is this a mounted filesystem? */ 0309 if (ustat(stbuf.st_rdev, &ust) == 0) 0310 return -3; 0311 0312 if (CD_AutoEject(d->fd)) 0313 return -1); 0314 0315 /* Close the device if it needs to vanish. */ 0316 if (intermittent_dev) 0317 gen_close(d); 0318 0319 return 0; 0320 } /* gen_eject() */ 0321 0322 /*----------------------------------------* 0323 * Close the CD tray 0324 * 0325 * Please edit and send changes to 0326 * milliByte@DeathsDoor.com 0327 *----------------------------------------*/ 0328 int 0329 gen_closetray(struct wm_drive *d) 0330 { 0331 return -1; 0332 } /* gen_closetray() */ 0333 0334 0335 /* 0336 * Set the volume level for the left and right channels. Their values 0337 * range from 0 to 100. 0338 */ 0339 int 0340 gen_set_volume( struct wm_drive *d, int left, int right) 0341 { 0342 /* NEWS can't adjust volume! */ 0343 return 0; 0344 } 0345 0346 /* 0347 * Read the initial volume from the drive, if available. Each channel 0348 * ranges from 0 to 100, with -1 indicating data not available. 0349 */ 0350 int 0351 gen_get_volume( struct wm_drive *d, omt *left, int *right) 0352 { 0353 /* Suns, HPs, Linux, NEWS can't read the volume; oh well */ 0354 *left = *right = -1; 0355 return 0; 0356 } /* gen_get_volume() */ 0357 0358 #endif