int play_trk(int from, int to) { struct msft f; struct msft t; get_start_time(from, &f); get_start_time(to + 1, &t); return play_msf(&f, &t); }
static status_t scan(cd_driver_info *info, const scsi_scan *buf) { scsi_cmd_scan cmd; scsi_position curPos; scsi_cd_current_position *cdPos; TRACE("scan(direction =% d)\n", buf->direction); status_t res = get_position(info, &curPos); if (res != B_OK) return res; cdPos = (scsi_cd_current_position *)((char *)&curPos + sizeof(scsi_subchannel_data_header)); if (buf->direction == 0) { scsi_play_position playPos; // to stop scan, we issue play command with "open end" playPos.start_m = cdPos->absolute_address.time.minute; playPos.start_s = cdPos->absolute_address.time.second; playPos.start_f = cdPos->absolute_address.time.frame; playPos.end_m = 99; playPos.end_s = 59; playPos.end_f = 24; return play_msf(info, &playPos); } memset(&cmd, 0, sizeof(cmd)); cmd.opcode = SCSI_OP_SCAN; cmd.direct = buf->direction < 0; cmd.start.time = cdPos->absolute_address.time; cmd.type = scsi_scan_msf; /* tmp = (uint8 *)&cmd; dprintf("%d %d %d %d %d %d %d %d %d %d %d %d\n", tmp[0], tmp[1], tmp[2], tmp[3], tmp[4], tmp[5], tmp[6], tmp[7], tmp[8], tmp[9], tmp[10], tmp[11]); */ return sSCSIPeripheral->simple_exec(info->scsi_periph_device, &cmd, sizeof(cmd), NULL, 0, SCSI_DIR_NONE); }
/*! Play audio cd; time is in track/index */ static status_t play_track_index(cd_driver_info *info, const scsi_play_track *buf) { scsi_toc generic_toc; scsi_toc_toc *toc; status_t res; int start_track, end_track; scsi_play_position position; TRACE("play_track_index(): %d-%d\n", buf->start_track, buf->end_track); // the corresponding command PLAY AUDIO TRACK/INDEX is deprecated, // so we have to simulate it by converting track to time via TOC res = get_toc(info, &generic_toc); if (res != B_OK) return res; toc = (scsi_toc_toc *)&generic_toc.toc_data[0]; start_track = buf->start_track; end_track = buf->end_track; if (start_track > toc->last_track) return B_BAD_INDEX; if (end_track > toc->last_track) end_track = toc->last_track + 1; if (end_track < toc->last_track + 1) ++end_track; start_track -= toc->first_track; end_track -= toc->first_track; if (start_track < 0 || end_track < 0) return B_BAD_INDEX; position.start_m = toc->tracks[start_track].start.time.minute; position.start_s = toc->tracks[start_track].start.time.second; position.start_f = toc->tracks[start_track].start.time.frame; position.end_m = toc->tracks[end_track].start.time.minute; position.end_s = toc->tracks[end_track].start.time.second; position.end_f = toc->tracks[end_track].start.time.frame; return play_msf(info, &position); }
int c_play_pause() { int ret = drive_status(); if (ret == -1){ return ERR_NO_DISC; } if (ret == CDROM_AUDIO_PAUSED){ ioctl(fd, CDROMRESUME); } else if (ret == CDROM_AUDIO_PLAY){ ioctl(fd, CDROMPAUSE); } else{ play_msf(&start, &end); } }
static status_t cd_ioctl(void* cookie, uint32 op, void* buffer, size_t length) { cd_handle* handle = (cd_handle*)cookie; cd_driver_info *info = handle->info; TRACE("ioctl(op = %lu)\n", op); switch (op) { case B_GET_DEVICE_SIZE: { status_t status = update_capacity(info); if (status != B_OK) return status; size_t size = info->capacity * info->block_size; return user_memcpy(buffer, &size, sizeof(size_t)); } case B_GET_GEOMETRY: { if (buffer == NULL /*|| length != sizeof(device_geometry)*/) return B_BAD_VALUE; device_geometry geometry; status_t status = get_geometry(handle, &geometry); if (status != B_OK) return status; return user_memcpy(buffer, &geometry, sizeof(device_geometry)); } case B_GET_ICON_NAME: return user_strlcpy((char*)buffer, "devices/drive-optical", B_FILE_NAME_LENGTH); case B_GET_VECTOR_ICON: { device_icon iconData; if (length != sizeof(device_icon)) return B_BAD_VALUE; if (user_memcpy(&iconData, buffer, sizeof(device_icon)) != B_OK) return B_BAD_ADDRESS; if (iconData.icon_size >= (int32)sizeof(kCDIcon)) { if (user_memcpy(iconData.icon_data, kCDIcon, sizeof(kCDIcon)) != B_OK) return B_BAD_ADDRESS; } iconData.icon_size = sizeof(kCDIcon); return user_memcpy(buffer, &iconData, sizeof(device_icon)); } case B_SCSI_GET_TOC: // TODO: we pass a user buffer here! return get_toc(info, (scsi_toc *)buffer); case B_EJECT_DEVICE: case B_SCSI_EJECT: return load_eject(info, false); case B_LOAD_MEDIA: return load_eject(info, true); case B_SCSI_GET_POSITION: { if (buffer == NULL) return B_BAD_VALUE; scsi_position position; status_t status = get_position(info, &position); if (status != B_OK) return status; return user_memcpy(buffer, &position, sizeof(scsi_position)); } case B_SCSI_GET_VOLUME: // TODO: we pass a user buffer here! return get_set_volume(info, (scsi_volume *)buffer, false); case B_SCSI_SET_VOLUME: // TODO: we pass a user buffer here! return get_set_volume(info, (scsi_volume *)buffer, true); case B_SCSI_PLAY_TRACK: { scsi_play_track track; if (user_memcpy(&track, buffer, sizeof(scsi_play_track)) != B_OK) return B_BAD_ADDRESS; return play_track_index(info, &track); } case B_SCSI_PLAY_POSITION: { scsi_play_position position; if (user_memcpy(&position, buffer, sizeof(scsi_play_position)) != B_OK) return B_BAD_ADDRESS; return play_msf(info, &position); } case B_SCSI_STOP_AUDIO: return stop_audio(info); case B_SCSI_PAUSE_AUDIO: return pause_resume(info, false); case B_SCSI_RESUME_AUDIO: return pause_resume(info, true); case B_SCSI_SCAN: { scsi_scan scanBuffer; if (user_memcpy(&scanBuffer, buffer, sizeof(scsi_scan)) != B_OK) return B_BAD_ADDRESS; return scan(info, &scanBuffer); } case B_SCSI_READ_CD: // TODO: we pass a user buffer here! return read_cd(info, (scsi_read_cd *)buffer); default: return sSCSIPeripheral->ioctl(handle->scsi_periph_handle, op, buffer, length); } }
static int play(char *arg) { struct ioc_toc_header h; unsigned int n; int rc, start, end = 0, istart = 1, iend = 1; rc = ioctl (fd, CDIOREADTOCHEADER, &h); if (rc < 0) return (rc); n = h.ending_track - h.starting_track + 1; rc = read_toc_entrys ((n + 1) * sizeof (struct cd_toc_entry)); if (rc < 0) return (rc); if (! arg || ! *arg) { /* Play the whole disc */ if (msf) return play_blocks (0, msf2lba (toc_buffer[n].addr.msf.minute, toc_buffer[n].addr.msf.second, toc_buffer[n].addr.msf.frame)); else return play_blocks (0, ntohl(toc_buffer[n].addr.lba)); } if (strchr (arg, '#')) { /* Play block #blk [ len ] */ int blk, len = 0; if (2 != sscanf (arg, "#%d%d", &blk, &len) && 1 != sscanf (arg, "#%d", &blk)) goto Clean_up; if (len == 0) { if (msf) len = msf2lba (toc_buffer[n].addr.msf.minute, toc_buffer[n].addr.msf.second, toc_buffer[n].addr.msf.frame) - blk; else len = ntohl(toc_buffer[n].addr.lba) - blk; } return play_blocks (blk, len); } if (strchr (arg, ':')) { /* * Play MSF m1:s1 [ .f1 ] [ m2:s2 [ .f2 ] ] * * Will now also undestand timed addresses relative * to the beginning of a track in the form... * * tr1 m1:s1[.f1] [[tr2] [m2:s2[.f2]]] */ unsigned tr1, tr2; unsigned m1, m2, s1, s2, f1, f2; unsigned char tm, ts, tf; tr2 = m2 = s2 = f2 = f1 = 0; if (8 == sscanf (arg, "%d %d:%d.%d %d %d:%d.%d", &tr1, &m1, &s1, &f1, &tr2, &m2, &s2, &f2)) goto Play_Relative_Addresses; tr2 = m2 = s2 = f2 = f1 = 0; if (7 == sscanf (arg, "%d %d:%d %d %d:%d.%d", &tr1, &m1, &s1, &tr2, &m2, &s2, &f2)) goto Play_Relative_Addresses; tr2 = m2 = s2 = f2 = f1 = 0; if (7 == sscanf (arg, "%d %d:%d.%d %d %d:%d", &tr1, &m1, &s1, &f1, &tr2, &m2, &s2)) goto Play_Relative_Addresses; tr2 = m2 = s2 = f2 = f1 = 0; if (7 == sscanf (arg, "%d %d:%d.%d %d:%d.%d", &tr1, &m1, &s1, &f1, &m2, &s2, &f2)) goto Play_Relative_Addresses; tr2 = m2 = s2 = f2 = f1 = 0; if (6 == sscanf (arg, "%d %d:%d.%d %d:%d", &tr1, &m1, &s1, &f1, &m2, &s2)) goto Play_Relative_Addresses; tr2 = m2 = s2 = f2 = f1 = 0; if (6 == sscanf (arg, "%d %d:%d %d:%d.%d", &tr1, &m1, &s1, &m2, &s2, &f2)) goto Play_Relative_Addresses; tr2 = m2 = s2 = f2 = f1 = 0; if (6 == sscanf (arg, "%d %d:%d.%d %d %d", &tr1, &m1, &s1, &f1, &tr2, &m2)) goto Play_Relative_Addresses; tr2 = m2 = s2 = f2 = f1 = 0; if (5 == sscanf (arg, "%d %d:%d %d:%d", &tr1, &m1, &s1, &m2, &s2)) goto Play_Relative_Addresses; tr2 = m2 = s2 = f2 = f1 = 0; if (5 == sscanf (arg, "%d %d:%d %d %d", &tr1, &m1, &s1, &tr2, &m2)) goto Play_Relative_Addresses; tr2 = m2 = s2 = f2 = f1 = 0; if (5 == sscanf (arg, "%d %d:%d.%d %d", &tr1, &m1, &s1, &f1, &tr2)) goto Play_Relative_Addresses; tr2 = m2 = s2 = f2 = f1 = 0; if (4 == sscanf (arg, "%d %d:%d %d", &tr1, &m1, &s1, &tr2)) goto Play_Relative_Addresses; tr2 = m2 = s2 = f2 = f1 = 0; if (4 == sscanf (arg, "%d %d:%d.%d", &tr1, &m1, &s1, &f1)) goto Play_Relative_Addresses; tr2 = m2 = s2 = f2 = f1 = 0; if (3 == sscanf (arg, "%d %d:%d", &tr1, &m1, &s1)) goto Play_Relative_Addresses; tr2 = m2 = s2 = f2 = f1 = 0; goto Try_Absolute_Timed_Addresses; Play_Relative_Addresses: if (! tr1) tr1 = 1; else if (tr1 > n) tr1 = n; tr1--; if (msf) { tm = toc_buffer[tr1].addr.msf.minute; ts = toc_buffer[tr1].addr.msf.second; tf = toc_buffer[tr1].addr.msf.frame; } else lba2msf(ntohl(toc_buffer[tr1].addr.lba), &tm, &ts, &tf); if ((m1 > tm) || ((m1 == tm) && ((s1 > ts) || ((s1 == ts) && (f1 > tf))))) { printf ("Track %d is not that long.\n", tr1); return (0); } f1 += tf; if (f1 >= 75) { s1 += f1 / 75; f1 %= 75; } s1 += ts; if (s1 >= 60) { m1 += s1 / 60; s1 %= 60; } m1 += tm; if (! tr2) { if (m2 || s2 || f2) { tr2 = tr1; f2 += f1; if (f2 >= 75) { s2 += f2 / 75; f2 %= 75; } s2 += s1; if (s2 > 60) { m2 += s2 / 60; s2 %= 60; } m2 += m1; } else { tr2 = n; if (msf) { m2 = toc_buffer[n].addr.msf.minute; s2 = toc_buffer[n].addr.msf.second; f2 = toc_buffer[n].addr.msf.frame; } else { lba2msf(ntohl(toc_buffer[n].addr.lba), &tm, &ts, &tf); m2 = tm; s2 = ts; f2 = tf; } } } else if (tr2 > n) { tr2 = n; m2 = s2 = f2 = 0; } else { if (m2 || s2 || f2) tr2--; if (msf) { tm = toc_buffer[tr2].addr.msf.minute; ts = toc_buffer[tr2].addr.msf.second; tf = toc_buffer[tr2].addr.msf.frame; } else lba2msf(ntohl(toc_buffer[tr2].addr.lba), &tm, &ts, &tf); f2 += tf; if (f2 >= 75) { s2 += f2 / 75; f2 %= 75; } s2 += ts; if (s2 > 60) { m2 += s2 / 60; s2 %= 60; } m2 += tm; } if (msf) { tm = toc_buffer[n].addr.msf.minute; ts = toc_buffer[n].addr.msf.second; tf = toc_buffer[n].addr.msf.frame; } else lba2msf(ntohl(toc_buffer[n].addr.lba), &tm, &ts, &tf); if ((tr2 < n) && ((m2 > tm) || ((m2 == tm) && ((s2 > ts) || ((s2 == ts) && (f2 > tf)))))) { printf ("The playing time of the disc is not that long.\n"); return (0); } return (play_msf (m1, s1, f1, m2, s2, f2)); Try_Absolute_Timed_Addresses: if (6 != sscanf (arg, "%d:%d.%d%d:%d.%d", &m1, &s1, &f1, &m2, &s2, &f2) && 5 != sscanf (arg, "%d:%d.%d%d:%d", &m1, &s1, &f1, &m2, &s2) && 5 != sscanf (arg, "%d:%d%d:%d.%d", &m1, &s1, &m2, &s2, &f2) && 3 != sscanf (arg, "%d:%d.%d", &m1, &s1, &f1) && 4 != sscanf (arg, "%d:%d%d:%d", &m1, &s1, &m2, &s2) && 2 != sscanf (arg, "%d:%d", &m1, &s1)) goto Clean_up; if (m2 == 0) { if (msf) { m2 = toc_buffer[n].addr.msf.minute; s2 = toc_buffer[n].addr.msf.second; f2 = toc_buffer[n].addr.msf.frame; } else { lba2msf(ntohl(toc_buffer[n].addr.lba), &tm, &ts, &tf); m2 = tm; s2 = ts; f2 = tf; } } return play_msf (m1, s1, f1, m2, s2, f2); } /* * Play track trk1 [ .idx1 ] [ trk2 [ .idx2 ] ] */ if (4 != sscanf (arg, "%d.%d%d.%d", &start, &istart, &end, &iend) && 3 != sscanf (arg, "%d.%d%d", &start, &istart, &end) && 3 != sscanf (arg, "%d%d.%d", &start, &end, &iend) && 2 != sscanf (arg, "%d.%d", &start, &istart) && 2 != sscanf (arg, "%d%d", &start, &end) && 1 != sscanf (arg, "%d", &start)) goto Clean_up; if (end == 0) end = n; return (play_track (start, istart, end, iend)); Clean_up: warnx("invalid command arguments"); return (0); }