File indexing completed on 2024-04-14 04:49:19

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