home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / x / volume21 / xmcd / part09 < prev    next >
Encoding:
Text File  |  1993-12-19  |  83.5 KB  |  4,355 lines

  1. Newsgroups: comp.sources.x
  2. From: ti@bazooka.amb.org (Ti Kan)
  3. Subject: v21i071:  xmcd - X11/Motif CD audio player, Part09/13
  4. Message-ID: <1993Dec19.194013.24685@sparky.sterling.com>
  5. X-Md4-Signature: afd1d9f9cb1d30cf67c5951e7256be7e
  6. Sender: chris@sparky.sterling.com (Chris Olson)
  7. Organization: Sterling Software
  8. Date: Sun, 19 Dec 1993 19:40:13 GMT
  9. Approved: chris@sterling.com
  10.  
  11. Submitted-by: ti@bazooka.amb.org (Ti Kan)
  12. Posting-number: Volume 21, Issue 71
  13. Archive-name: xmcd/part09
  14. Environment: X11, OSF/Motif
  15.  
  16. #! /bin/sh
  17. # This is a shell archive.  Remove anything before this line, then unpack
  18. # it by saving it into a file and typing "sh file".  To overwrite existing
  19. # files, type "sh file -c".  You can also feed this as standard input via
  20. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  21. # will see the following message at the end:
  22. #        "End of archive 9 (of 13)."
  23. # Contents:  lib_scsipt.c lib_sun.c
  24. # Wrapped by ti@bazooka on Mon Nov  8 10:35:22 1993
  25. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  26. if test -f 'lib_scsipt.c' -a "${1}" != "-c" ; then 
  27.   echo shar: Will not clobber existing file \"'lib_scsipt.c'\"
  28. else
  29. echo shar: Extracting \"'lib_scsipt.c'\" \(71104 characters\)
  30. sed "s/^X//" >'lib_scsipt.c' <<'END_OF_FILE'
  31. X/*
  32. X *   xmcd - Motif(tm) CD Audio Player
  33. X *
  34. X *   Copyright (C) 1993  Ti Kan
  35. X *   E-mail: ti@amb.org
  36. X *
  37. X *   This program is free software; you can redistribute it and/or modify
  38. X *   it under the terms of the GNU General Public License as published by
  39. X *   the Free Software Foundation; either version 2 of the License, or
  40. X *   (at your option) any later version.
  41. X *
  42. X *   This program is distributed in the hope that it will be useful,
  43. X *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  44. X *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  45. X *   GNU General Public License for more details.
  46. X *
  47. X *   You should have received a copy of the GNU General Public License
  48. X *   along with this program; if not, write to the Free Software
  49. X *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  50. X *
  51. X */
  52. X#ifndef LINT
  53. Xstatic char *_lib_scsipt_c_ident_ = "@(#)lib_scsipt.c    1.109 93/09/28";
  54. X#endif
  55. X
  56. X#include <Xm/Xm.h>
  57. X#include "xmcd.h"
  58. X#include "util.h"
  59. X#include "cdfunc.h"
  60. X#include "dbprog.h"
  61. X#include "cdlib.h"
  62. X#include "lib_scsipt.h"
  63. X
  64. X
  65. X#ifndef CDLIB_VERS
  66. X#define CDLIB_VERS    "1.0"        /* Version */
  67. X#endif
  68. X
  69. X
  70. Xextern AppData        app_data;
  71. X
  72. XSTATIC bool_t        run_ab(curstat_t *),
  73. X            run_sample(curstat_t *),
  74. X            run_prog(curstat_t *),
  75. X            run_repeat(curstat_t *),
  76. X            disc_ready(curstat_t *);
  77. XSTATIC void        stat_poll(curstat_t *),
  78. X            insert_poll(curstat_t *);
  79. X
  80. X#ifndef LINT
  81. Xbool_t            lib_scsipt = TRUE;
  82. X#endif
  83. X
  84. Xbool_t            notrom_error = FALSE;
  85. X                    /* Not a CD-ROM error */
  86. X
  87. XSTATIC int        stat_id,    /* Play status poll timer id */
  88. X            insert_id,    /* Disc insert poll timer id */
  89. X            search_id,    /* FF/REW self-running timer id */
  90. X            stat_interval;    /* status poll interval */
  91. XSTATIC byte_t        next_sam;    /* Next SAMPLE track */
  92. XSTATIC bool_t        stat_polling,    /* Current polling play status */
  93. X            insert_polling,    /* Currently polling disc insert */
  94. X            new_progshuf,    /* New program/shuffle sequence */
  95. X            start_search = FALSE;
  96. X                    /* Start FF/REW play segment */
  97. XSTATIC word32_t        ab_start_addr,    /* A->B mode start block */
  98. X            ab_end_addr,    /* A->B mode end block */
  99. X            sav_end_addr;    /* Saved end addr for error recovery */
  100. XSTATIC msf_t        ab_start_msf,    /* A->B mode start MSF */
  101. X            ab_end_msf,    /* A->B mode end MSF */
  102. X            sav_end_msf;    /* Saved end MSF for error recovery */
  103. XSTATIC byte_t        dev_scsiver,    /* Device SCSI version */
  104. X            sav_end_fmt;    /* Saved addr fmt for error recovery */
  105. X
  106. X
  107. X
  108. X/***********************
  109. X *  internal routines  *
  110. X ***********************/
  111. X
  112. X
  113. X/*
  114. X * scsi_rdsubq
  115. X *    Send SCSI-2 Read Subchannel command to the device
  116. X *
  117. X * Args:
  118. X *    buf - Pointer to the return data buffer
  119. X *    fmt - Subchannel data format code
  120. X *        SUB_ALL        Subchannel-Q data
  121. X *        SUB_CURPOS    CD-ROM Current position data
  122. X *        SUB_CATNO    Media catalog number data
  123. X *        SUB_ISRC    Track Intl Standard Recording Code
  124. X *    subq - Whether the CD-ROM should return subchannel-Q data
  125. X *    trkno - Track number from which the ISRC data is read
  126. X *    msf - Whether to use MSF or logical block address format
  127. X *
  128. X * Return:
  129. X *    TRUE - success
  130. X *    FALSE - failure
  131. X */
  132. XSTATIC bool_t
  133. Xscsi_rdsubq(byte_t *buf, byte_t fmt, byte_t subq, int trkno, bool_t msf)
  134. X{
  135. X    int    xfer_len;
  136. X
  137. X    switch (fmt) {
  138. X    case SUB_ALL:
  139. X        xfer_len = 48;
  140. X        break;
  141. X    case SUB_CURPOS:
  142. X        xfer_len = 16;
  143. X        break;
  144. X    case SUB_CATNO:
  145. X    case SUB_ISRC:
  146. X        xfer_len = 24;
  147. X        break;
  148. X    default:
  149. X        return(FALSE);
  150. X    }
  151. X
  152. X    if (xfer_len > SZ_RDSUBQ)
  153. X        xfer_len = SZ_RDSUBQ;
  154. X
  155. X    return(
  156. X        pthru_send(
  157. X            OP_M_RDSUBQ,
  158. X            (word32_t) (fmt << 16 | subq << 30),
  159. X            buf,
  160. X            xfer_len,
  161. X            (byte_t) trkno,
  162. X            xfer_len,
  163. X            (byte_t) (msf << 1),
  164. X            0,
  165. X            READ_OP
  166. X        )
  167. X    );
  168. X}
  169. X
  170. X
  171. X/*
  172. X * scsi_modesense
  173. X *    Send SCSI Mode Sense command to the device
  174. X *
  175. X * Args:
  176. X *    buf - Pointer to the return data buffer
  177. X *    pg_ctrl - Defines the type of parameters to be returned:
  178. X *        0: Current values
  179. X *        1: Changeable values
  180. X *        2: Default values
  181. X *    pg_code - Specifies which page or pages to return:
  182. X *        PG_ERRECOV: Error recovery params page
  183. X *        PG_DISCONN: Disconnect/reconnect params page
  184. X *        PG_CDROMCTL: CD-ROM params page
  185. X *        PG_AUDIOCTL: Audio control params page
  186. X *        PG_ALL: All pages
  187. X *    dbd - Whether to disable the block descriptor return data
  188. X *
  189. X * Return:
  190. X *    TRUE - success
  191. X *    FALSE - failure
  192. X */
  193. XSTATIC bool_t
  194. Xscsi_modesense(byte_t *buf, byte_t pg_ctrl, byte_t pg_code, bool_t dbd)
  195. X{
  196. X    int    xfer_len;
  197. X
  198. X    switch (pg_code) {
  199. X    case PG_ERRECOV:
  200. X        xfer_len = 12;
  201. X        break;
  202. X    case PG_DISCONN:
  203. X        xfer_len = 20;
  204. X        break;
  205. X    case PG_CDROMCTL:
  206. X        xfer_len = 12;
  207. X        break;
  208. X    case PG_AUDIOCTL:
  209. X        xfer_len = 20;
  210. X        break;
  211. X    case PG_ALL:
  212. X        xfer_len = 52;
  213. X        break;
  214. X    default:
  215. X        return(FALSE);
  216. X    }
  217. X
  218. X    if (!dbd)
  219. X        xfer_len += 8;
  220. X
  221. X    return(
  222. X        pthru_send(
  223. X            OP_S_MSENSE,
  224. X            (word32_t) ((pg_ctrl << 6 | pg_code) << 8),
  225. X            buf,
  226. X            xfer_len,
  227. X            0,
  228. X            xfer_len,
  229. X            (byte_t) (dbd ? 0x08 : 0x00),
  230. X            0,
  231. X            READ_OP
  232. X        )
  233. X    );
  234. X}
  235. X
  236. X
  237. X/*
  238. X * scsi_modesel
  239. X *    Send SCSI Mode Select command to the device
  240. X *
  241. X * Args:
  242. X *    buf - Pointer to the data buffer
  243. X *    pg_code - Specifies which page or pages to return:
  244. X *        PG_ERRECOV: Error recovery params page
  245. X *        PG_DISCONN: Disconnect/reconnect params page
  246. X *        PG_CDROMCTL: CD-ROM params page
  247. X *        PG_AUDIOCTL: Audio control params page
  248. X *        PG_ALL: All pages
  249. X *    dbd - Whether the block descriptor data is present
  250. X *
  251. X * Return:
  252. X *    TRUE - success
  253. X *    FALSE - failure
  254. X */
  255. XSTATIC bool_t
  256. Xscsi_modesel(byte_t *buf, byte_t pg_code, bool_t dbd)
  257. X{
  258. X    int    xfer_len;
  259. X
  260. X    switch (pg_code) {
  261. X    case PG_ERRECOV:
  262. X        xfer_len = 12;
  263. X        break;
  264. X    case PG_DISCONN:
  265. X        xfer_len = 20;
  266. X        break;
  267. X    case PG_CDROMCTL:
  268. X        xfer_len = 12;
  269. X        break;
  270. X    case PG_AUDIOCTL:
  271. X        xfer_len = 20;
  272. X        break;
  273. X    case PG_ALL:
  274. X        xfer_len = 52;
  275. X        break;
  276. X    default:
  277. X        return(FALSE);
  278. X    }
  279. X
  280. X    if (!dbd)
  281. X        xfer_len += 8;
  282. X
  283. X    return(
  284. X        pthru_send(
  285. X            OP_S_MSELECT,
  286. X            0,
  287. X            buf,
  288. X            xfer_len,
  289. X            0,
  290. X            xfer_len,
  291. X            0x10,
  292. X            0,
  293. X            WRITE_OP
  294. X        )
  295. X    );
  296. X}
  297. X
  298. X
  299. X/*
  300. X * scsi_inquiry
  301. X *    Send SCSI Inquiry command to the device
  302. X *
  303. X * Args:
  304. X *    buf - Pointer to the return data buffer
  305. X *    len - Maximum number of inquiry data bytes to transfer
  306. X *
  307. X * Return:
  308. X *    TRUE - success
  309. X *    FALSE - failure
  310. X */
  311. XSTATIC bool_t
  312. Xscsi_inquiry(byte_t *buf, int len)
  313. X{
  314. X    return(
  315. X        pthru_send(
  316. X            OP_S_INQUIR,
  317. X            0,
  318. X            buf,
  319. X            len,
  320. X            0,
  321. X            len,
  322. X            0,
  323. X            0,
  324. X            READ_OP
  325. X        )
  326. X    );
  327. X}
  328. X
  329. X
  330. X/*
  331. X * scsi_rdtoc
  332. X *    Send SCSI-2 Read TOC command to the device
  333. X *
  334. X * Args:
  335. X *    buf - Pointer to the return data buffer
  336. X *    msf - Whether to use MSF or logical block address data format
  337. X *    start - Starting track number for which the TOC data is returned
  338. X *
  339. X * Return:
  340. X *    TRUE - success
  341. X *    FALSE - failure
  342. X */
  343. XSTATIC bool_t
  344. Xscsi_rdtoc(byte_t *buf, bool_t msf, int start)
  345. X{
  346. X    int        xfer_len;
  347. X    toc_hdr_t    *thdr;
  348. X
  349. X    /* Read the TOC header first */
  350. X    if (!pthru_send(OP_M_RDTOC, 0, buf, SZ_TOCHDR,
  351. X            (byte_t) start, SZ_TOCHDR,
  352. X            (byte_t) (msf << 1), 0, READ_OP))
  353. X        return(FALSE);
  354. X
  355. X    thdr = (toc_hdr_t *)(void *) buf;
  356. X
  357. X    if (start == 0)
  358. X        start = (int) thdr->first_trk;
  359. X
  360. X    xfer_len = SZ_TOCHDR +
  361. X           (((int) thdr->last_trk - start + 2) * SZ_TOCENT);
  362. X
  363. X    if (xfer_len > SZ_RDTOC)
  364. X        xfer_len = SZ_RDTOC;
  365. X
  366. X    /* Read the appropriate number of bytes of the entire TOC */
  367. X    return(
  368. X        pthru_send(
  369. X            OP_M_RDTOC,
  370. X            0,
  371. X            buf,
  372. X            xfer_len,
  373. X            (byte_t) start,
  374. X            xfer_len,
  375. X            (byte_t) (msf << 1),
  376. X            0,
  377. X            READ_OP
  378. X        )
  379. X    );
  380. X}
  381. X
  382. X
  383. X/*
  384. X * scsi_tst_unit_rdy
  385. X *    Send SCSI Test Unit Ready command to the device
  386. X *
  387. X * Args:
  388. X *    Nothing
  389. X *
  390. X * Return:
  391. X *    TRUE - success
  392. X *    FALSE - failure (drive not ready)
  393. X */
  394. XSTATIC bool_t
  395. Xscsi_tst_unit_rdy(void)
  396. X{
  397. X    return(
  398. X        pthru_send(
  399. X            OP_S_TEST,
  400. X            0,
  401. X            NULL,
  402. X            0,
  403. X            0,
  404. X            0,
  405. X            0,
  406. X            0,
  407. X            READ_OP
  408. X        )
  409. X    );
  410. X}
  411. X
  412. X
  413. X/*
  414. X * scsi_playmsf
  415. X *    Send SCSI-2 Play Audio MSF command to the device
  416. X *
  417. X * Args:
  418. X *    start - Pointer to the starting position MSF data
  419. X *    end - Pointer to the ending position MSF data
  420. X *
  421. X * Return:
  422. X *    TRUE - success
  423. X *    FALSE - failure
  424. X */
  425. XSTATIC bool_t
  426. Xscsi_playmsf(msf_t *start, msf_t *end)
  427. X{
  428. X    word32_t    *addr = (word32_t *)(void *) start;
  429. X    word16_t    *len = (word16_t *)(void *) &end->sec;
  430. X    byte_t        *rsvd = (byte_t *) &end->min;
  431. X
  432. X    if (!app_data.playmsf_supp)
  433. X        return(FALSE);
  434. X
  435. X    start->res = end->res = 0;
  436. X
  437. X    return(
  438. X        pthru_send(
  439. X            OP_M_PLAYMSF,
  440. X            bswap32(*addr),
  441. X            NULL,
  442. X            0,
  443. X            *rsvd,
  444. X            (word32_t) bswap16(*len),
  445. X            0,
  446. X            0,
  447. X            READ_OP
  448. X        )
  449. X    );
  450. X}
  451. X
  452. X
  453. X/*
  454. X * scsi_play10
  455. X *    Send SCSI-2 Play Audio (10) command to the device
  456. X *
  457. X * Args:
  458. X *    start - The starting logical block address
  459. X *    len - The number of logical blocks to play (max=0xffff)
  460. X *
  461. X * Return:
  462. X *    TRUE - success
  463. X *    FALSE - failure
  464. X */
  465. XSTATIC bool_t
  466. Xscsi_play10(word32_t start, word32_t len)
  467. X{
  468. X    if (!app_data.play10_supp || len > 0xffff)
  469. X        return(FALSE);
  470. X
  471. X    return(
  472. X        pthru_send(
  473. X            OP_M_PLAY,
  474. X            start,
  475. X            NULL,
  476. X            0,
  477. X            0,
  478. X            len,
  479. X            0,
  480. X            0,
  481. X            READ_OP
  482. X        )
  483. X    );
  484. X}
  485. X
  486. X
  487. X/*
  488. X * scsi_play12
  489. X *    Send SCSI-2 Play Audio (12) command to the device
  490. X *
  491. X * Args:
  492. X *    start - The starting logical block address
  493. X *    len - The number of logical blocks to play
  494. X *
  495. X * Return:
  496. X *    TRUE - success
  497. X *    FALSE - failure
  498. X */
  499. XSTATIC bool_t
  500. Xscsi_play12(word32_t start, word32_t len)
  501. X{
  502. X    if (!app_data.play12_supp)
  503. X        return(FALSE);
  504. X
  505. X    return(
  506. X        pthru_send(
  507. X            OP_L_PLAY,
  508. X            start,
  509. X            NULL,
  510. X            0,
  511. X            0,
  512. X            len,
  513. X            0,
  514. X            0,
  515. X            READ_OP
  516. X        )
  517. X    );
  518. X}
  519. X
  520. X
  521. X/*
  522. X * scsi_prev_allow
  523. X *    Send SCSI Prevent/Allow Medium Removal command to the device
  524. X *
  525. X * Args:
  526. X *    prevent - Whether to prevent or allow medium removal
  527. X *
  528. X * Return:
  529. X *    TRUE - success
  530. X *    FALSE - failure
  531. X */
  532. XSTATIC bool_t
  533. Xscsi_prev_allow(bool_t prevent)
  534. X{
  535. X    if (!app_data.caddylock_supp)
  536. X        return(FALSE);
  537. X
  538. X    return(
  539. X        pthru_send(
  540. X            OP_S_PREVENT,
  541. X            0,
  542. X            NULL,
  543. X            0,
  544. X            0,
  545. X            prevent,
  546. X            0,
  547. X            0,
  548. X            READ_OP
  549. X        )
  550. X    );
  551. X}
  552. X
  553. X
  554. X/*
  555. X * scsi_start_stop
  556. X *    Send SCSI Start/Stop Unit command to the device
  557. X *
  558. X * Args:
  559. X *    start - Whether to start unit or stop unit
  560. X *    loej - Whether caddy load/eject operation should be performed
  561. X *
  562. X * Return:
  563. X *    TRUE - success
  564. X *    FALSE - failure
  565. X */
  566. XSTATIC bool_t
  567. Xscsi_start_stop(bool_t start, bool_t loej)
  568. X{
  569. X    byte_t    param;
  570. X
  571. X    if (start)
  572. X        param = 0x01;
  573. X    else
  574. X        param = 0x00;
  575. X
  576. X    if (loej)
  577. X        param |= 0x02;
  578. X
  579. X    return(
  580. X        pthru_send(
  581. X            OP_S_START,
  582. X            0,
  583. X            NULL,
  584. X            0,
  585. X            0,
  586. X            param,
  587. X            0,
  588. X            0,
  589. X            READ_OP
  590. X        )
  591. X    );
  592. X}
  593. X
  594. X
  595. X/*
  596. X * scsi_pause_resume
  597. X *    Send SCSI-2 Pause/Resume command to the device
  598. X *
  599. X * Args:
  600. X *    resume - Whether to resume or pause
  601. X *
  602. X * Return:
  603. X *    TRUE - success
  604. X *    FALSE - failure
  605. X */
  606. XSTATIC bool_t
  607. Xscsi_pause_resume(bool_t resume)
  608. X{
  609. X    if (!app_data.pause_supp)
  610. X        return(FALSE);
  611. X
  612. X    return(
  613. X        pthru_send(
  614. X            OP_M_PAUSE,
  615. X            0,
  616. X            NULL,
  617. X            0,
  618. X            0,
  619. X            resume,
  620. X            0,
  621. X            0,
  622. X            READ_OP
  623. X        )
  624. X    );
  625. X}
  626. X
  627. X
  628. X/*
  629. X * scsi_play_trkidx
  630. X *    Send SCSI-2 Play Audio Track/Index command to the device
  631. X *
  632. X * Args:
  633. X *    start_trk - Starting track number
  634. X *    start_idx - Starting index number
  635. X *    end_trk - Ending track number
  636. X *    end_idx - Ending index number
  637. X *
  638. X * Return:
  639. X *    TRUE - success
  640. X *    FALSE - failure
  641. X */
  642. XSTATIC bool_t
  643. Xscsi_play_trkidx(int start_trk, int start_idx, int end_trk, int end_idx)
  644. X{
  645. X    if (!app_data.playti_supp)
  646. X        return(FALSE);
  647. X
  648. X    return(
  649. X        pthru_send(
  650. X            OP_M_PLAYTI,
  651. X            (start_trk << 8) | start_idx,
  652. X            NULL,
  653. X            0,
  654. X            0,
  655. X            (end_trk << 8) | end_idx,
  656. X            0,
  657. X            0,
  658. X            READ_OP
  659. X        )
  660. X    );
  661. X}
  662. X
  663. X
  664. X/*
  665. X * do_playaudio
  666. X *    General top-level play audio function
  667. X *
  668. X * Args:
  669. X *    addr_fmt - The address formats specified:
  670. X *        ADDR_BLK: logical block address
  671. X *        ADDR_MSF: MSF address
  672. X *        ADDR_TRKIDX: Track/index numbers
  673. X *        ADDR_OPTEND: Ending address can be ignored
  674. X *    start_addr - Starting logical block address
  675. X *    end_addr - Ending logical block address
  676. X *    start_msf - Pointer to start address MSF data
  677. X *    end_msf - Pointer to end address MSF data
  678. X *    trk - Starting track number
  679. X *    idx - Starting index number
  680. X *
  681. X * Return:
  682. X *    TRUE - success
  683. X *    FALSE - failure
  684. X */
  685. XSTATIC bool_t
  686. Xdo_playaudio(
  687. X    byte_t        addr_fmt,
  688. X    word32_t    start_addr,
  689. X    word32_t    end_addr,
  690. X    msf_t        *start_msf,
  691. X    msf_t        *end_msf,
  692. X    byte_t        trk,
  693. X    byte_t        idx
  694. X)
  695. X{
  696. X    msf_t        emsf,
  697. X            *emsfp = NULL;
  698. X    bool_t        ret = FALSE;
  699. X
  700. X
  701. X    /* Fix addresses: Some CD-ROM drives will only allow playing to
  702. X     * the last frame minus 1.
  703. X     */
  704. X    if (addr_fmt & ADDR_MSF && end_msf != NULL) {
  705. X        emsf = *end_msf;    /* Structure copy */
  706. X        emsfp = &emsf;
  707. X
  708. X        if (emsfp->frame > 0)
  709. X            emsfp->frame--;
  710. X        else {
  711. X            emsfp->frame = FRAME_PER_SEC - 1;
  712. X            if (emsfp->sec > 0)
  713. X                emsfp->sec--;
  714. X            else {
  715. X                emsfp->sec = 59;
  716. X                if (emsfp->min > 0)
  717. X                    emsfp->min--;
  718. X            }
  719. X        }
  720. X
  721. X        /* Save end address for error recovery */
  722. X        sav_end_msf = *end_msf;
  723. X    }
  724. X    if (addr_fmt & ADDR_BLK) {
  725. X        if (end_addr != 0)
  726. X            end_addr--;
  727. X
  728. X        /* Save end address for error recovery */
  729. X        sav_end_addr = end_addr;
  730. X    }
  731. X
  732. X    /* Save end address format for error recovery */
  733. X    sav_end_fmt = addr_fmt;
  734. X
  735. X#ifdef HITACHI
  736. X    /* ----- Hitachi vendor-unique audio commands ----- */
  737. X
  738. X    if (!ret && app_data.vendor_code == VENDOR_HITACHI)
  739. X        ret = hita_playaudio(
  740. X            addr_fmt,
  741. X            start_addr, end_addr,
  742. X            start_msf, emsfp,
  743. X            trk, idx
  744. X        );
  745. X#endif
  746. X
  747. X#ifdef NEC
  748. X    /* ----- NEC vendor-unique audio commands ----- */
  749. X
  750. X    if (!ret && app_data.vendor_code == VENDOR_NEC)
  751. X        ret = nec_playaudio(
  752. X            addr_fmt,
  753. X            start_addr, end_addr,
  754. X            start_msf, emsfp,
  755. X            trk, idx
  756. X        );
  757. X#endif
  758. X
  759. X#ifdef PIONEER
  760. X    /* ----- Pioneer vendor-unique audio commands ----- */
  761. X
  762. X    if (!ret && app_data.vendor_code == VENDOR_PIONEER)
  763. X        ret = pion_playaudio(
  764. X            addr_fmt,
  765. X            start_addr, end_addr,
  766. X            start_msf, emsfp,
  767. X            trk, idx
  768. X        );
  769. X#endif
  770. X
  771. X#ifdef TOSHIBA
  772. X    /* ----- Toshiba vendor-unique audio commands ----- */
  773. X
  774. X    if (!ret && app_data.vendor_code == VENDOR_TOSHIBA)
  775. X        ret = tosh_playaudio(
  776. X            addr_fmt,
  777. X            start_addr, end_addr,
  778. X            start_msf, emsfp,
  779. X            trk, idx
  780. X        );
  781. X#endif
  782. X
  783. X    /* If the device does not claim SCSI-2 compliance, and the
  784. X     * device-specific configuration is not SCSI-2, then don't
  785. X     * attempt to deliver SCSI-2 commands to the device.
  786. X     */
  787. X    if (!ret && app_data.vendor_code != VENDOR_SCSI2 && dev_scsiver < 2)
  788. X        return(FALSE);
  789. X    
  790. X    /* ----- Standard SCSI-2 audio commands ----- */
  791. X
  792. X    if (!ret && (addr_fmt & ADDR_MSF) && app_data.playmsf_supp)
  793. X        ret = scsi_playmsf(start_msf, emsfp);
  794. X    
  795. X    if (!ret && (addr_fmt & ADDR_BLK) && app_data.play12_supp)
  796. X        ret = scsi_play12(start_addr, end_addr - start_addr);
  797. X    
  798. X    if (!ret && (addr_fmt & ADDR_BLK) && app_data.play10_supp)
  799. X        ret = scsi_play10(start_addr, end_addr - start_addr);
  800. X
  801. X    if (!ret && (addr_fmt & ADDR_TRKIDX) && app_data.playti_supp)
  802. X        ret = scsi_play_trkidx(trk, idx, trk, idx);
  803. X
  804. X    return(ret);
  805. X}
  806. X
  807. X
  808. X/*
  809. X * do_pause_resume
  810. X *    General top-level pause/resume function
  811. X *
  812. X * Args:
  813. X *    resume - Whether to resume or pause
  814. X *
  815. X * Return:
  816. X *    TRUE - success
  817. X *    FALSE - failure
  818. X */
  819. XSTATIC bool_t
  820. Xdo_pause_resume(bool_t resume)
  821. X{
  822. X    bool_t    ret = FALSE;
  823. X
  824. X#ifdef HITACHI
  825. X    /* ----- Hitachi vendor-unique audio commands ----- */
  826. X
  827. X    if (!ret && app_data.vendor_code == VENDOR_HITACHI)
  828. X        ret = hita_pause_resume(resume);
  829. X#endif
  830. X
  831. X#ifdef NEC
  832. X    /* ----- NEC vendor-unique audio commands ----- */
  833. X
  834. X    if (!ret && app_data.vendor_code == VENDOR_NEC)
  835. X        ret = nec_pause_resume(resume);
  836. X#endif
  837. X
  838. X#ifdef PIONEER
  839. X    /* ----- Pioneer vendor-unique audio commands ----- */
  840. X
  841. X    if (!ret && app_data.vendor_code == VENDOR_PIONEER)
  842. X        ret = pion_pause_resume(resume);
  843. X#endif
  844. X
  845. X#ifdef TOSHIBA
  846. X    /* ----- Toshiba vendor-unique audio commands ----- */
  847. X
  848. X    if (!ret && app_data.vendor_code == VENDOR_TOSHIBA)
  849. X        ret = tosh_pause_resume(resume);
  850. X#endif
  851. X
  852. X
  853. X    /* If the device does not claim SCSI-2 compliance, and the
  854. X     * device-specific configuration is not SCSI-2, then don't
  855. X     * attempt to deliver SCSI-2 commands to the device.
  856. X     */
  857. X    if (!ret && app_data.vendor_code != VENDOR_SCSI2 && dev_scsiver < 2)
  858. X        return(FALSE);
  859. X
  860. X    /* ----- Standard SCSI-2 audio commands ----- */
  861. X
  862. X    if (!ret && app_data.pause_supp)
  863. X        ret = scsi_pause_resume(resume);
  864. X
  865. X    return(ret);
  866. X}
  867. X
  868. X
  869. X/*
  870. X * do_start_stop
  871. X *    General top-level start/stop function
  872. X *
  873. X * Args:
  874. X *    start - Whether to start unit or stop unit
  875. X *    loej - Whether caddy load/eject operation should be performed
  876. X *
  877. X * Return:
  878. X *    TRUE - success
  879. X *    FALSE - failure
  880. X */
  881. XSTATIC bool_t
  882. Xdo_start_stop(bool_t start, bool_t loej)
  883. X{
  884. X    bool_t    ret = FALSE;
  885. X
  886. X    if (!app_data.load_supp && start && loej)
  887. X        return(FALSE);
  888. X
  889. X    if (!app_data.eject_supp)
  890. X        loej = 0;
  891. X
  892. X#ifdef HITACHI
  893. X    /* ----- Hitachi vendor-unique audio commands ----- */
  894. X
  895. X    if (!ret && app_data.vendor_code == VENDOR_HITACHI) {
  896. X        if ((ret = hita_start_stop(start, loej)) == TRUE)
  897. X            ret = scsi_start_stop(start, loej);
  898. X    }
  899. X#endif
  900. X
  901. X    /* ----- Standard SCSI-2 audio commands ----- */
  902. X
  903. X    if (!ret)
  904. X        ret = scsi_start_stop(start, loej);
  905. X
  906. X    return(ret);
  907. X}
  908. X
  909. X
  910. X/*
  911. X * get_playstatus
  912. X *    Obtain and update current playback status information
  913. X *
  914. X * Args:
  915. X *    s - Pointer to the curstat_t structure
  916. X *
  917. X * Return:
  918. X *    TRUE - Audio playback is in progress
  919. X *    FALSE - Audio playback stopped or command failure
  920. X */
  921. XSTATIC bool_t
  922. Xget_playstatus(curstat_t *s)
  923. X{
  924. X    bool_t        done,
  925. X            ret = FALSE,
  926. X            err = FALSE;
  927. X    byte_t        buf[SZ_RDSUBQ],
  928. X            audio_status,
  929. X            *cp,
  930. X            *subq_end;
  931. X    word32_t    recov_start_addr;
  932. X    msf_t        recov_start_msf;
  933. X    subq_hdr_t    *h;
  934. X    subq_01_t    *p;
  935. X    static int    errcnt = 0;
  936. X    static word32_t    errblk = 0;
  937. X    static bool_t    in_get_playstatus = FALSE;
  938. X
  939. X
  940. X    /* Lock this routine from multiple entry */
  941. X    if (in_get_playstatus)
  942. X        return(TRUE);
  943. X
  944. X    in_get_playstatus = TRUE;
  945. X
  946. X#ifdef HITACHI
  947. X    /* ----- Hitachi vendor-unique audio commands ----- */
  948. X
  949. X    if (!ret && app_data.vendor_code == VENDOR_HITACHI)
  950. X        ret = hita_get_playstatus(s, &audio_status);
  951. X#endif
  952. X
  953. X#ifdef NEC
  954. X    /* ----- NEC vendor-unique audio commands ----- */
  955. X
  956. X    if (!ret && app_data.vendor_code == VENDOR_NEC)
  957. X        ret = nec_get_playstatus(s, &audio_status);
  958. X#endif
  959. X
  960. X#ifdef PIONEER
  961. X    /* ----- Pioneer vendor-unique audio commands ----- */
  962. X
  963. X    if (!ret && app_data.vendor_code == VENDOR_PIONEER)
  964. X        ret = pion_get_playstatus(s, &audio_status);
  965. X#endif
  966. X
  967. X#ifdef TOSHIBA
  968. X    /* ----- Toshiba vendor-unique audio commands ----- */
  969. X
  970. X    if (!ret && app_data.vendor_code == VENDOR_TOSHIBA)
  971. X        ret = tosh_get_playstatus(s, &audio_status);
  972. X#endif
  973. X
  974. X    /* If the device does not claim SCSI-2 compliance, and the
  975. X     * device-specific configuration is not SCSI-2, then don't
  976. X     * attempt to deliver SCSI-2 commands to the device.
  977. X     */
  978. X    if (!ret && app_data.vendor_code != VENDOR_SCSI2 && dev_scsiver < 2) {
  979. X        in_get_playstatus = FALSE;
  980. X        return(FALSE);
  981. X    }
  982. X
  983. X
  984. X    /* ----- Standard SCSI-2 audio commands ----- */
  985. X
  986. X    if (!ret) {
  987. X        memset(buf, (byte_t) 0, sizeof(buf));
  988. X
  989. X        if (!scsi_rdsubq(buf, 1, 1, 0, TRUE)) {
  990. X            /* Check to see if the disc had been manually ejected */
  991. X            if (!disc_ready(s)) {
  992. X                sav_end_addr = 0;
  993. X                sav_end_msf.min = 0;
  994. X                sav_end_msf.sec = 0;
  995. X                sav_end_msf.frame = 0;
  996. X                sav_end_fmt = 0;
  997. X                errcnt = 0;
  998. X                errblk = 0;
  999. X
  1000. X                in_get_playstatus = FALSE;
  1001. X                return(FALSE);
  1002. X            }
  1003. X
  1004. X            /* The read subchannel command failed for some
  1005. X             * unknown reason.  Just return success and
  1006. X             * hope the next poll succeeds.  We don't want
  1007. X             * to return FALSE here because that would stop
  1008. X             * the poll.
  1009. X             */
  1010. X            in_get_playstatus = FALSE;
  1011. X            return(TRUE);
  1012. X        }
  1013. X
  1014. X        h = (subq_hdr_t *)(void *) buf;
  1015. X        subq_end = (byte_t *) h + bswap16(h->subch_len) + 4;
  1016. X
  1017. X        audio_status = h->audio_status;
  1018. X
  1019. X        /* Check the subchannel data */
  1020. X        for (cp = (byte_t *) h + sizeof(subq_hdr_t);
  1021. X             cp < subq_end && !err;
  1022. X             cp += sizeof(subq_01_t)) {
  1023. X
  1024. X            switch (*cp) {
  1025. X            case SUB_CURPOS:
  1026. X                p = (subq_01_t *)(void *) cp;
  1027. X
  1028. X                if (p->trkno != s->cur_trk) {
  1029. X                    s->cur_trk = p->trkno;
  1030. X                    dpy_track(s);
  1031. X                }
  1032. X
  1033. X                if (p->idxno != s->cur_idx) {
  1034. X                    s->cur_idx = p->idxno;
  1035. X                    s->sav_iaddr = s->cur_tot_addr;
  1036. X                    dpy_index(s);
  1037. X                }
  1038. X
  1039. X                s->cur_tot_min = p->abs_addr.msf.min;
  1040. X                s->cur_tot_sec = p->abs_addr.msf.sec;
  1041. X                s->cur_tot_frame = p->abs_addr.msf.frame;
  1042. X                msftoblk(
  1043. X                    s->cur_tot_min,
  1044. X                    s->cur_tot_sec,
  1045. X                    s->cur_tot_frame,
  1046. X                    &s->cur_tot_addr,
  1047. X                    MSF_OFFSET(s)
  1048. X                );
  1049. X
  1050. X                s->cur_trk_min = p->rel_addr.msf.min;
  1051. X                s->cur_trk_sec = p->rel_addr.msf.sec;
  1052. X                s->cur_trk_frame = p->rel_addr.msf.frame;
  1053. X                msftoblk(
  1054. X                    s->cur_trk_min,
  1055. X                    s->cur_trk_sec,
  1056. X                    s->cur_trk_frame,
  1057. X                    &s->cur_trk_addr,
  1058. X                    0
  1059. X                );
  1060. X
  1061. X                break;
  1062. X            default:
  1063. X                /* Something is wrong with the data */
  1064. X                err = TRUE;
  1065. X                break;
  1066. X            }
  1067. X        }
  1068. X    }
  1069. X
  1070. X    /* Update time display */
  1071. X    dpy_time(s, FALSE);
  1072. X
  1073. X
  1074. X    /* Deal with playback status */
  1075. X    switch (audio_status) {
  1076. X    case AUDIO_PLAYING:
  1077. X    case AUDIO_PAUSED:
  1078. X        done = FALSE;
  1079. X
  1080. X        /* If we haven't encountered an error for a while, then
  1081. X         * clear the error count.
  1082. X         */
  1083. X        if (errcnt > 0 && (s->cur_tot_addr - errblk) > ERR_CLRTHRESH)
  1084. X            errcnt = 0;
  1085. X        break;
  1086. X
  1087. X    case AUDIO_FAILED:
  1088. X        /* Check to see if the disc had been manually ejected */
  1089. X        if (!disc_ready(s)) {
  1090. X            sav_end_addr = 0;
  1091. X            sav_end_msf.min = 0;
  1092. X            sav_end_msf.sec = 0;
  1093. X            sav_end_msf.frame = 0;
  1094. X            sav_end_fmt = 0;
  1095. X            errcnt = 0;
  1096. X            errblk = 0;
  1097. X
  1098. X            in_get_playstatus = FALSE;
  1099. X            return(FALSE);
  1100. X        }
  1101. X
  1102. X        /* Audio playback stopped due to a disc error.  We will
  1103. X         * try to restart the playback by skipping a few frames
  1104. X         * and continuing.  This will cause a glitch in the sound
  1105. X         * but is better than just stopping.
  1106. X         */
  1107. X        done = FALSE;
  1108. X
  1109. X        /* Check for max errors limit */
  1110. X        if (++errcnt > MAX_RECOVERR) {
  1111. X            done = TRUE;
  1112. X            fprintf(stderr, "%s: %s\n",
  1113. X                PROGNAME, app_data.str_maxerr);
  1114. X        }
  1115. X        errblk = s->cur_tot_addr;
  1116. X
  1117. X        if (!done && (sav_end_fmt & ADDR_MSF)) {
  1118. X            if ((int) s->cur_tot_frame <
  1119. X                (FRAME_PER_SEC - ERR_SKIPBLKS)) {
  1120. X                recov_start_msf.min = s->cur_tot_min;
  1121. X                recov_start_msf.sec = s->cur_tot_sec;
  1122. X                recov_start_msf.frame =
  1123. X                    s->cur_tot_frame + ERR_SKIPBLKS;
  1124. X            }
  1125. X            else if ((int) s->cur_tot_sec < 59) {
  1126. X                recov_start_msf.min = s->cur_tot_min;
  1127. X                recov_start_msf.sec = s->cur_tot_sec + 1;
  1128. X                recov_start_msf.frame = ERR_SKIPBLKS -
  1129. X                    (FRAME_PER_SEC - s->cur_tot_frame);
  1130. X            }
  1131. X            else {
  1132. X                recov_start_msf.min = s->cur_tot_min + 1;
  1133. X                recov_start_msf.sec = 0;
  1134. X                recov_start_msf.frame = ERR_SKIPBLKS -
  1135. X                    (FRAME_PER_SEC - s->cur_tot_frame);
  1136. X            }
  1137. X
  1138. X            /* Check to see if we have skipped past
  1139. X             * the end.
  1140. X             */
  1141. X            if (recov_start_msf.min > sav_end_msf.min)
  1142. X                done = TRUE;
  1143. X            else if (recov_start_msf.min == sav_end_msf.min) {
  1144. X                if (recov_start_msf.sec > sav_end_msf.sec)
  1145. X                    done = TRUE;
  1146. X                else if ((recov_start_msf.sec ==
  1147. X                      sav_end_msf.sec) &&
  1148. X                     (recov_start_msf.frame >
  1149. X                      sav_end_msf.frame)) {
  1150. X                    done = TRUE;
  1151. X                }
  1152. X            }
  1153. X        }
  1154. X        else {
  1155. X            recov_start_msf.min = 0;
  1156. X            recov_start_msf.sec = 0;
  1157. X            recov_start_msf.frame = 0;
  1158. X        }
  1159. X
  1160. X        if (!done && (sav_end_fmt & ADDR_BLK)) {
  1161. X            recov_start_addr = s->cur_tot_addr + ERR_SKIPBLKS;
  1162. X
  1163. X            /* Check to see if we have skipped past
  1164. X             * the end.
  1165. X             */
  1166. X            if (recov_start_addr >= sav_end_addr)
  1167. X                done = TRUE;
  1168. X        }
  1169. X        else
  1170. X            recov_start_addr = 0;
  1171. X
  1172. X
  1173. X        /* Restart playback */
  1174. X        if (!done) {
  1175. X            fprintf(stderr, "%s: %s\n",
  1176. X                PROGNAME, app_data.str_recoverr);
  1177. X
  1178. X            do_playaudio(
  1179. X                sav_end_fmt,
  1180. X                recov_start_addr, sav_end_addr,
  1181. X                &recov_start_msf, &sav_end_msf,
  1182. X                0, 0
  1183. X            );
  1184. X
  1185. X            in_get_playstatus = FALSE;
  1186. X            return(TRUE);
  1187. X        }
  1188. X
  1189. X        /*FALLTHROUGH*/
  1190. X    case AUDIO_COMPLETED:
  1191. X    case AUDIO_NOSTATUS:
  1192. X    case AUDIO_NOTVALID:
  1193. X        done = TRUE;
  1194. X
  1195. X        switch (s->mode) {
  1196. X        case M_SAMPLE:
  1197. X            done = !run_sample(s);
  1198. X            break;
  1199. X
  1200. X        case M_AB:
  1201. X            done = !run_ab(s);
  1202. X            break;
  1203. X
  1204. X        case M_PLAY:
  1205. X            if (s->shuffle || s->program)
  1206. X                done = !run_prog(s);
  1207. X
  1208. X            if (s->repeat)
  1209. X                done = !run_repeat(s);
  1210. X
  1211. X            break;
  1212. X        }
  1213. X
  1214. X        break;
  1215. X
  1216. X    default:
  1217. X        /* Something is wrong with the data. */
  1218. X        done = FALSE;
  1219. X    }
  1220. X
  1221. X    if (done) {
  1222. X        /* Reset states */
  1223. X        reset_curstat(s, FALSE);
  1224. X        s->mode = M_STOP;
  1225. X        sav_end_addr = 0;
  1226. X        sav_end_msf.min = sav_end_msf.sec = sav_end_msf.frame = 0;
  1227. X        sav_end_fmt = 0;
  1228. X        errcnt = 0;
  1229. X        errblk = 0;
  1230. X        dpy_all(s);
  1231. X
  1232. X        /* Spin down the disc */
  1233. X        do_start_stop(FALSE, FALSE);
  1234. X
  1235. X        in_get_playstatus = FALSE;
  1236. X        return(FALSE);
  1237. X    }
  1238. X
  1239. X    in_get_playstatus = FALSE;
  1240. X    return(TRUE);
  1241. X}
  1242. X
  1243. X
  1244. X/*
  1245. X * scale_vol
  1246. X *    Scale logical audio volume value (0-100) to the SCSI-2
  1247. X *    Mode Select parameter value (0-0xff) range.
  1248. X *
  1249. X * Args:
  1250. X *    v - The logical volume value
  1251. X *
  1252. X * Return:
  1253. X *    The scaled volume value
  1254. X */
  1255. XSTATIC int
  1256. Xscale_vol(int v)
  1257. X{
  1258. X    /* Convert logical audio volume value to SCSI volume */
  1259. X    return((v * (MAX_SCSIVOL - app_data.base_scsivol) / MAX_VOL) +
  1260. X           app_data.base_scsivol);
  1261. X}
  1262. X
  1263. X
  1264. X/*
  1265. X * unscale_vol
  1266. X *    Scale the SCSI-2 Mode Select audio volume parameter value
  1267. X *    (0-0xff) to the logical volume value (0-100).
  1268. X *
  1269. X * Args:
  1270. X *    v - The SCSI-2 volume value
  1271. X *
  1272. X * Return:
  1273. X *    The logical volume value
  1274. X */
  1275. XSTATIC int
  1276. Xunscale_vol(int v)
  1277. X{
  1278. X    register int    val;
  1279. X
  1280. X    /* Convert SCSI audio volume value to logical volume */
  1281. X    val = (v - app_data.base_scsivol) * MAX_VOL /
  1282. X          (MAX_SCSIVOL - app_data.base_scsivol);
  1283. X
  1284. X    return ((val < 0) ? 0 : val);
  1285. X}
  1286. X
  1287. X
  1288. X/*
  1289. X * config_vol
  1290. X *    Audio volume control function
  1291. X *
  1292. X * Args:
  1293. X *    vol - Logical volume value to set to
  1294. X *    s - Pointer to the curstat_t structure
  1295. X *    query - If TRUE, query current volume only
  1296. X *    warp - Whether to set the volume control slider thumb
  1297. X *        to the appropriate position
  1298. X *
  1299. X * Return:
  1300. X *    The current logical volume value, or -1 on failure.
  1301. X */
  1302. X/*ARGSUSED*/
  1303. XSTATIC int
  1304. Xconfig_vol(int vol, curstat_t *s, bool_t query, bool_t warp)
  1305. X{
  1306. X    byte_t            buf[SZ_MSENSE];
  1307. X    mode_sense_data_t    *ms_data;
  1308. X    audio_pg_t        *audiopg;
  1309. X    bool_t            ret = FALSE;
  1310. X    static bool_t        muted = FALSE;
  1311. X
  1312. X#ifdef HITACHI
  1313. X    /* ----- Hitachi vendor-unique audio commands ----- */
  1314. X
  1315. X    if (!ret && app_data.vendor_code == VENDOR_HITACHI) {
  1316. X        if (!query && (ret = hita_mute((bool_t) (vol < 50))) == TRUE)
  1317. X            muted = (vol < 50);
  1318. X
  1319. X        vol = muted ? 0 : MAX_VOL;
  1320. X
  1321. X        if (warp)
  1322. X            set_vol_slider((byte_t) vol);
  1323. X
  1324. X        return(vol);
  1325. X    }
  1326. X#endif
  1327. X
  1328. X#ifdef NEC
  1329. X    /* ----- NEC vendor-unique audio commands ----- */
  1330. X
  1331. X    if (!ret && app_data.vendor_code == VENDOR_NEC) {
  1332. X        if (!query && (ret = nec_mute((bool_t) (vol < 50))) == TRUE)
  1333. X            muted = (vol < 50);
  1334. X
  1335. X        vol = muted ? 0 : MAX_VOL;
  1336. X
  1337. X        if (warp)
  1338. X            set_vol_slider((byte_t) vol);
  1339. X
  1340. X        return(vol);
  1341. X    }
  1342. X#endif
  1343. X
  1344. X#ifdef TOSHIBA
  1345. X    /* ----- Toshiba vendor-unique audio commands ----- */
  1346. X
  1347. X    if (!ret && app_data.vendor_code == VENDOR_TOSHIBA) {
  1348. X        if (!query && (ret = tosh_mute((bool_t) (vol < 50))) == TRUE)
  1349. X            muted = (vol < 50);
  1350. X
  1351. X        vol = muted ? 0 : MAX_VOL;
  1352. X
  1353. X        if (warp)
  1354. X            set_vol_slider((byte_t) vol);
  1355. X
  1356. X        return(vol);
  1357. X    }
  1358. X#endif
  1359. X
  1360. X
  1361. X    /* ----- SCSI-2 standard audio commands ----- */
  1362. X
  1363. X    if (ret || !app_data.mselvol_supp)
  1364. X        return(0);
  1365. X
  1366. X    memset(buf, (byte_t) 0, SZ_MSENSE);
  1367. X
  1368. X    if (!scsi_modesense(buf, 0, PG_AUDIOCTL, app_data.mselvol_dbd))
  1369. X        return(-1);
  1370. X
  1371. X#ifdef DEBUG
  1372. X    {
  1373. X        int i;
  1374. X
  1375. X        fprintf(stderr, "\nMode Sense data bytes:\n");
  1376. X        for (i = 0; i < SZ_MSENSE; i++)
  1377. X            fprintf(stderr, "0x%02x: 0x%02x\n",
  1378. X                i, *(buf + i));
  1379. X    }
  1380. X#endif
  1381. X    ms_data = (mode_sense_data_t *)(void *) buf;
  1382. X    audiopg = (audio_pg_t *)(void *)
  1383. X        &ms_data->data[ms_data->bdescr_len];
  1384. X
  1385. X    if (audiopg->pg_code == PG_AUDIOCTL) {
  1386. X        if (query) {
  1387. X            if (audiopg->p0_vol > 0)
  1388. X                muted = FALSE;
  1389. X
  1390. X            vol = untaper_vol(unscale_vol((int) audiopg->p0_vol));
  1391. X
  1392. X            if (warp)
  1393. X                set_vol_slider((byte_t) vol);
  1394. X
  1395. X            return(vol);
  1396. X        }
  1397. X        else {
  1398. X            ms_data->data_len = 0x00;
  1399. X
  1400. X            audiopg->p0_vol = scale_vol(taper_vol(vol));
  1401. X            audiopg->p1_vol = scale_vol(taper_vol(vol));
  1402. X
  1403. X#ifdef DEBUG
  1404. X            {
  1405. X                int i;
  1406. X
  1407. X                fprintf(stderr, "\nMode Select data bytes:\n");
  1408. X                for (i = 0; i < SZ_MSENSE; i++)
  1409. X                    fprintf(stderr, "0x%02x: 0x%02x\n",
  1410. X                        i, *(buf + i));
  1411. X            }
  1412. X#endif
  1413. X
  1414. X            if (scsi_modesel(buf, PG_AUDIOCTL,
  1415. X                     app_data.mselvol_dbd)) {
  1416. X                muted = (vol > 0) ? FALSE : TRUE;
  1417. X                return(vol);
  1418. X            }
  1419. X        }
  1420. X    }
  1421. X
  1422. X    return(-1);
  1423. X}
  1424. X
  1425. X
  1426. X/*
  1427. X * get_vendor_model
  1428. X *    Query and update CD-ROM vendor/model/revision information
  1429. X *
  1430. X * Args:
  1431. X *    s - Pointer to the curstat_t structure
  1432. X *
  1433. X * Return:
  1434. X *    Nothing.
  1435. X */
  1436. XSTATIC void
  1437. Xget_vendor_model(curstat_t *s)
  1438. X{
  1439. X    inquiry_data_t    inq;
  1440. X    char        errstr[STR_BUF_SZ];
  1441. X
  1442. X    if (scsi_inquiry((byte_t *) &inq, sizeof(inq))) {
  1443. X        strncpy(s->vendor, (char *) inq.vendor, 8);
  1444. X        s->vendor[8] = '\0';
  1445. X
  1446. X        strncpy(s->prod, (char *) inq.prod, 16);
  1447. X        s->prod[16] = '\0';
  1448. X
  1449. X        strncpy(s->revnum, (char *) inq.revnum, 4);
  1450. X        s->revnum[4] = '\0';
  1451. X
  1452. X        /* Check for errors */
  1453. X        if (inq.type != DEV_ROM || !inq.rmb) {
  1454. X            /* Not a CD-ROM device */
  1455. X            notrom_error = TRUE;
  1456. X            sprintf(errstr, app_data.str_notrom, app_data.device);
  1457. X            cd_fatal_popup(app_data.str_fatal, errstr);
  1458. X            return;
  1459. X        }
  1460. X
  1461. X        /* Check for unsupported drives */
  1462. X        dev_scsiver = (byte_t) (inq.ver & 0x07);
  1463. X        if (dev_scsiver < 2 && app_data.vendor_code == VENDOR_SCSI2) {
  1464. X            /* Not SCSI-2 or later */
  1465. X            sprintf(errstr, app_data.str_notscsi2, app_data.device);
  1466. X            cd_warning_popup(app_data.str_warning, errstr);
  1467. X        }
  1468. X    }
  1469. X}
  1470. X
  1471. X
  1472. X/*
  1473. X * get_toc
  1474. X *    Query and update the CD Table Of Contents
  1475. X *
  1476. X * Args:
  1477. X *    s - Pointer to the curstat_t structure
  1478. X *
  1479. X * Return:
  1480. X *    TRUE - success
  1481. X *    FALSE - failure
  1482. X */
  1483. XSTATIC bool_t
  1484. Xget_toc(curstat_t *s)
  1485. X{
  1486. X    int            i;
  1487. X    byte_t            buf[SZ_RDTOC],
  1488. X                *cp,
  1489. X                *toc_end;
  1490. X    bool_t            ret = FALSE;
  1491. X    toc_hdr_t        *h;
  1492. X    toc_trk_descr_t        *p;
  1493. X
  1494. X
  1495. X#ifdef HITACHI
  1496. X    /* ----- Hitachi vendor-unique audio commands ----- */
  1497. X
  1498. X    if (!ret && app_data.vendor_code == VENDOR_HITACHI)
  1499. X        ret = hita_get_toc(s);
  1500. X#endif
  1501. X
  1502. X#ifdef NEC
  1503. X    /* ----- NEC vendor-unique audio commands ----- */
  1504. X
  1505. X    if (!ret && app_data.vendor_code == VENDOR_NEC)
  1506. X        ret = nec_get_toc(s);
  1507. X#endif
  1508. X
  1509. X#ifdef PIONEER
  1510. X    /* ----- Pioneer vendor-unique audio commands ----- */
  1511. X
  1512. X    if (!ret && app_data.vendor_code == VENDOR_PIONEER)
  1513. X        ret = pion_get_toc(s);
  1514. X#endif
  1515. X
  1516. X#ifdef TOSHIBA
  1517. X    /* ----- Toshiba vendor-unique audio commands ----- */
  1518. X
  1519. X    if (!ret && app_data.vendor_code == VENDOR_TOSHIBA)
  1520. X        ret = tosh_get_toc(s);
  1521. X#endif
  1522. X
  1523. X    if (ret)
  1524. X        return(TRUE);
  1525. X
  1526. X    /* If the device does not claim SCSI-2 compliance, and the
  1527. X     * device-specific configuration is not SCSI-2, then don't
  1528. X     * attempt to deliver SCSI-2 commands to the device.
  1529. X     */
  1530. X    if (!ret && app_data.vendor_code != VENDOR_SCSI2 && dev_scsiver < 2)
  1531. X        return(FALSE);
  1532. X
  1533. X
  1534. X    /* ----- Standard SCSI-2 audio commands ----- */
  1535. X
  1536. X    memset(buf, (byte_t) 0, sizeof(buf));
  1537. X
  1538. X    if (!scsi_rdtoc(buf, TRUE, 0))
  1539. X        return(FALSE);
  1540. X
  1541. X    /* Fill curstat structure with TOC data */
  1542. X    h = (toc_hdr_t *)(void *) buf;
  1543. X    toc_end = (byte_t *) h + bswap16(h->data_len) + 2;
  1544. X
  1545. X    s->first_trk = h->first_trk;
  1546. X    s->last_trk = h->last_trk;
  1547. X
  1548. X    cp = (byte_t *) h + sizeof(toc_hdr_t);
  1549. X
  1550. X    for (i = 0; cp < toc_end && i < MAXTRACK; i++) {
  1551. X        p = (toc_trk_descr_t *)(void *) cp;
  1552. X
  1553. X        s->trkinfo[i].trkno = p->trkno;
  1554. X        s->trkinfo[i].type = (p->trktype == 0) ?
  1555. X            TYP_AUDIO : TYP_DATA;
  1556. X        s->trkinfo[i].min = p->abs_addr.msf.min;
  1557. X        s->trkinfo[i].sec = p->abs_addr.msf.sec;
  1558. X        s->trkinfo[i].frame = p->abs_addr.msf.frame;
  1559. X        msftoblk(
  1560. X            s->trkinfo[i].min,
  1561. X            s->trkinfo[i].sec,
  1562. X            s->trkinfo[i].frame,
  1563. X            &s->trkinfo[i].addr,
  1564. X            MSF_OFFSET(s)
  1565. X        );
  1566. X
  1567. X        if (p->trkno == LEAD_OUT_TRACK ||
  1568. X            s->trkinfo[i-1].trkno == s->last_trk ||
  1569. X            i == (MAXTRACK - 1)) {
  1570. X            s->tot_min = s->trkinfo[i].min;
  1571. X            s->tot_sec = s->trkinfo[i].sec;
  1572. X            s->tot_frame = s->trkinfo[i].frame;
  1573. X            s->tot_trks = i;
  1574. X            s->tot_addr = s->trkinfo[i].addr;
  1575. X
  1576. X            break;
  1577. X        }
  1578. X
  1579. X        cp += sizeof(toc_trk_descr_t);
  1580. X    }
  1581. X
  1582. X    return(TRUE);
  1583. X}
  1584. X
  1585. X
  1586. X/*
  1587. X * start_stat_poll
  1588. X *    Start polling the drive for current playback status
  1589. X *
  1590. X * Args:
  1591. X *    s - Pointer to the curstat_t structure
  1592. X *
  1593. X * Return:
  1594. X *    Nothing.
  1595. X */
  1596. XSTATIC void
  1597. Xstart_stat_poll(curstat_t *s)
  1598. X{
  1599. X    stat_polling = TRUE;
  1600. X
  1601. X    /* Start poll timer */
  1602. X    stat_id = cd_timeout(
  1603. X        stat_interval,
  1604. X        stat_poll,
  1605. X        (byte_t *) s
  1606. X    );
  1607. X}
  1608. X
  1609. X
  1610. X/*
  1611. X * stop_stat_poll
  1612. X *    Stop polling the drive for current playback status
  1613. X *
  1614. X * Args:
  1615. X *    Nothing.
  1616. X *
  1617. X * Return:
  1618. X *    Nothing.
  1619. X */
  1620. XSTATIC void
  1621. Xstop_stat_poll(void)
  1622. X{
  1623. X    if (stat_polling) {
  1624. X        /* Stop poll timer */
  1625. X        cd_untimeout(stat_id);
  1626. X
  1627. X        stat_polling = FALSE;
  1628. X    }
  1629. X}
  1630. X
  1631. X
  1632. X/*
  1633. X * start_insert_poll
  1634. X *    Start polling the drive for disc insertion
  1635. X *
  1636. X * Args:
  1637. X *    s - Pointer to the curstat_t structure
  1638. X *
  1639. X * Return:
  1640. X *    Nothing.
  1641. X */
  1642. XSTATIC void
  1643. Xstart_insert_poll(curstat_t *s)
  1644. X{
  1645. X    if (insert_polling || s->mode != M_NODISC)
  1646. X        return;
  1647. X
  1648. X    insert_polling = TRUE;
  1649. X
  1650. X    /* Start poll timer */
  1651. X    insert_id = cd_timeout(
  1652. X        app_data.ins_interval,
  1653. X        insert_poll,
  1654. X        (byte_t *) s
  1655. X    );
  1656. X}
  1657. X
  1658. X
  1659. X/*
  1660. X * stop_insert_poll
  1661. X *    Stop polling the drive for disc insertion
  1662. X *
  1663. X * Args:
  1664. X *    s - Pointer to the curstat_t structure
  1665. X *
  1666. X * Return:
  1667. X *    Nothing.
  1668. X */
  1669. XSTATIC void
  1670. Xstop_insert_poll(void)
  1671. X{
  1672. X    if (insert_polling) {
  1673. X        /* Stop poll timer */
  1674. X        cd_untimeout(insert_id);
  1675. X
  1676. X        insert_polling = FALSE;
  1677. X    }
  1678. X}
  1679. X
  1680. X
  1681. X/*
  1682. X * stat_poll
  1683. X *    The playback status polling function
  1684. X *
  1685. X * Args:
  1686. X *    s - Pointer to the curstat_t structure
  1687. X *
  1688. X * Return:
  1689. X *    Nothing.
  1690. X */
  1691. XSTATIC void
  1692. Xstat_poll(curstat_t *s)
  1693. X{
  1694. X    if (!stat_polling)
  1695. X        return;
  1696. X
  1697. X    /* Get current audio playback status */
  1698. X    if (get_playstatus(s)) {
  1699. X        /* Register next poll interval */
  1700. X        stat_id = cd_timeout(
  1701. X            stat_interval,
  1702. X            stat_poll,
  1703. X            (byte_t *) s
  1704. X        );
  1705. X    }
  1706. X    else
  1707. X        stat_polling = FALSE;
  1708. X}
  1709. X
  1710. X
  1711. X/*
  1712. X * insert_poll
  1713. X *    The disc insertion polling function
  1714. X *
  1715. X * Args:
  1716. X *    s - Pointer to the curstat_t structure
  1717. X *
  1718. X * Return:
  1719. X *    Nothing.
  1720. X */
  1721. XSTATIC void
  1722. Xinsert_poll(curstat_t *s)
  1723. X{
  1724. X    /* Check to see if a disc is inserted */
  1725. X    if (!disc_ready(s)) {
  1726. X        /* Register next poll interval */
  1727. X        insert_id = cd_timeout(
  1728. X            app_data.ins_interval,
  1729. X            insert_poll,
  1730. X            (byte_t *) s
  1731. X        );
  1732. X    }
  1733. X    else
  1734. X        insert_polling = FALSE;
  1735. X}
  1736. X
  1737. X
  1738. X/*
  1739. X * disc_ready
  1740. X *    Check if the disc is loaded and ready for use, and update
  1741. X *    curstat table.
  1742. X *
  1743. X * Args:
  1744. X *    s - Pointer to the curstat_t structure
  1745. X *
  1746. X * Return:
  1747. X *    TRUE - Disc is ready
  1748. X *    FALSE - Disc is not ready
  1749. X */
  1750. XSTATIC bool_t
  1751. Xdisc_ready(curstat_t *s)
  1752. X{
  1753. X    int        i,
  1754. X            vol;
  1755. X    sword32_t    err;
  1756. X    bool_t        first_open = FALSE;
  1757. X    static bool_t    not_open = TRUE;
  1758. X
  1759. X    /* If device has not been opened, attempt to open it */
  1760. X    if (not_open) {
  1761. X        /* Open CD-ROM device */
  1762. X        if (!pthru_open(app_data.device)) {
  1763. X            dpy_time(s, FALSE);
  1764. X            return(FALSE);
  1765. X        }
  1766. X
  1767. X        not_open = FALSE;
  1768. X        first_open = TRUE;
  1769. X    }
  1770. X
  1771. X    for (i = 0; i < 5; i++) {
  1772. X        if ((err = !scsi_tst_unit_rdy()) == TRUE) {
  1773. X            s->mode = M_NODISC;
  1774. X            dbprog_dbclear(s);
  1775. X        }
  1776. X        else
  1777. X            break;
  1778. X    }
  1779. X
  1780. X    if (!err && first_open) {
  1781. X        first_open = FALSE;
  1782. X
  1783. X        /* Fill in inquiry data */
  1784. X        get_vendor_model(s);
  1785. X
  1786. X        /* Query current volume and warp volume slider to
  1787. X         * appropriate setting
  1788. X         */
  1789. X        if ((vol = config_vol(0, s, TRUE, TRUE)) >= 0)
  1790. X            s->level = (byte_t) vol;
  1791. X        else
  1792. X            s->level = 0;
  1793. X    }
  1794. X
  1795. X    /* Disable front-panel eject button if so specified */
  1796. X    if (!err && app_data.caddy_lock && s->mode == M_NODISC) {
  1797. X        cdlib_lock(s, TRUE);
  1798. X
  1799. X        if (s->caddy_lock)
  1800. X            set_lock_btn(TRUE);
  1801. X    }
  1802. X
  1803. X    /* Read disc table of contents */
  1804. X    if (err || (s->mode == M_NODISC && !get_toc(s))) {
  1805. X        reset_curstat(s, TRUE);
  1806. X        dpy_all(s);
  1807. X
  1808. X        start_insert_poll(s);
  1809. X
  1810. X        return(FALSE);
  1811. X    }
  1812. X
  1813. X    if (s->mode == M_NODISC) {
  1814. X        /* Load CD database entry for this disc */
  1815. X        dbprog_dbget(s);
  1816. X
  1817. X        s->mode = M_STOP;
  1818. X        dpy_all(s);
  1819. X
  1820. X        if (app_data.load_spindown)
  1821. X            /* Spin down disc in case the user isn't going to
  1822. X             * play anything for a while.  This reduces wear and
  1823. X             * tear on the drive.
  1824. X             */
  1825. X            do_start_stop(FALSE, FALSE);
  1826. X    }
  1827. X
  1828. X    return(TRUE);
  1829. X}
  1830. X
  1831. X
  1832. X/*
  1833. X * run_rew
  1834. X *    Run search-rewind operation
  1835. X *
  1836. X * Args:
  1837. X *    s - Pointer to the curstat_t structure
  1838. X *
  1839. X * Return:
  1840. X *    Nothing.
  1841. X */
  1842. XSTATIC void
  1843. Xrun_rew(curstat_t *s)
  1844. X{
  1845. X    int            i,
  1846. X                skip_blks;
  1847. X    word32_t        addr,
  1848. X                end_addr;
  1849. X    static word32_t        start_addr,
  1850. X                seq;
  1851. X
  1852. X    /* Find out where we are */
  1853. X    if (!get_playstatus(s)) {
  1854. X        cd_beep();
  1855. X        return;
  1856. X    }
  1857. X
  1858. X    skip_blks = app_data.skip_blks;
  1859. X    addr = s->cur_tot_addr;
  1860. X
  1861. X    if (start_search) {
  1862. X        start_search = FALSE;
  1863. X        seq = 0;
  1864. X        if (skip_blks < addr)
  1865. X            start_addr = addr - skip_blks;
  1866. X        else
  1867. X            start_addr = 0;
  1868. X    }
  1869. X    else {
  1870. X        if (app_data.skip_spdup > 0 && seq > app_data.skip_spdup)
  1871. X            /* Speed up search */
  1872. X            skip_blks *= 3;
  1873. X
  1874. X        if ((int) (start_addr - skip_blks) > 0)
  1875. X            start_addr -= skip_blks;
  1876. X        else
  1877. X            start_addr = 0;
  1878. X    }
  1879. X
  1880. X    seq++;
  1881. X
  1882. X    if (s->shuffle || s->program) {
  1883. X        if ((i = curtrk_pos(s)) < 0)
  1884. X            i = 0;
  1885. X    }
  1886. X    else
  1887. X        i = 0;
  1888. X
  1889. X    if (start_addr < s->trkinfo[i].addr)
  1890. X        start_addr = s->trkinfo[i].addr;
  1891. X
  1892. X    end_addr = start_addr + MAX_SRCH_BLKS;
  1893. X
  1894. X    /* Play next search interval */
  1895. X    do_playaudio(
  1896. X        ADDR_BLK | ADDR_OPTEND,
  1897. X        start_addr, end_addr,
  1898. X        NULL, NULL,
  1899. X        0, 0
  1900. X    );
  1901. X
  1902. X    search_id = cd_timeout(
  1903. X        app_data.skip_pause,
  1904. X        run_rew,
  1905. X        (byte_t *) s
  1906. X    );
  1907. X}
  1908. X
  1909. X
  1910. X/*
  1911. X * stop_rew
  1912. X *    Stop search-rewind operation
  1913. X *
  1914. X * Args:
  1915. X *    s - Pointer to the curstat_t structure
  1916. X *
  1917. X * Return:
  1918. X *    Nothing.
  1919. X */
  1920. X/*ARGSUSED*/
  1921. XSTATIC void
  1922. Xstop_rew(curstat_t *s)
  1923. X{
  1924. X    cd_untimeout(search_id);
  1925. X}
  1926. X
  1927. X
  1928. X/*
  1929. X * run_ff
  1930. X *    Run search-fast-forward operation
  1931. X *
  1932. X * Args:
  1933. X *    s - Pointer to the curstat_t structure
  1934. X *
  1935. X * Return:
  1936. X *    Nothing.
  1937. X */
  1938. XSTATIC void
  1939. Xrun_ff(curstat_t *s)
  1940. X{
  1941. X    int        i,
  1942. X            skip_blks;
  1943. X    word32_t    addr,
  1944. X            end_addr;
  1945. X    static word32_t    start_addr,
  1946. X            seq;
  1947. X
  1948. X    /* Find out where we are */
  1949. X    if (!get_playstatus(s)) {
  1950. X        cd_beep();
  1951. X        return;
  1952. X    }
  1953. X
  1954. X    skip_blks = app_data.skip_blks;
  1955. X    addr = s->cur_tot_addr;
  1956. X
  1957. X    if (start_search) {
  1958. X        start_search = FALSE;
  1959. X        seq = 0;
  1960. X        start_addr = addr + skip_blks;
  1961. X    }
  1962. X    else {
  1963. X        if (app_data.skip_spdup > 0 && seq > app_data.skip_spdup)
  1964. X            /* Speed up search */
  1965. X            skip_blks *= 3;
  1966. X
  1967. X        start_addr += skip_blks;
  1968. X    }
  1969. X
  1970. X    seq++;
  1971. X
  1972. X    if (s->shuffle || s->program) {
  1973. X        if ((i = curtrk_pos(s)) < 0)
  1974. X            i = s->tot_trks - 1;
  1975. X        else if (s->cur_idx == 0)
  1976. X            /* We're in the lead-in: consider this to be
  1977. X             * within the previous track.
  1978. X             */
  1979. X            i--;
  1980. X    }
  1981. X    else
  1982. X        i = s->tot_trks - 1;
  1983. X
  1984. X    end_addr = start_addr + MAX_SRCH_BLKS;
  1985. X
  1986. X    if (end_addr >= s->trkinfo[i+1].addr) {
  1987. X        end_addr = s->trkinfo[i+1].addr;
  1988. X        start_addr = end_addr - skip_blks;
  1989. X    }
  1990. X
  1991. X    /* Play next search interval */
  1992. X    do_playaudio(
  1993. X        ADDR_BLK | ADDR_OPTEND,
  1994. X        start_addr, end_addr,
  1995. X        NULL, NULL,
  1996. X        0, 0
  1997. X    );
  1998. X
  1999. X    search_id = cd_timeout(
  2000. X        app_data.skip_pause,
  2001. X        run_ff,
  2002. X        (byte_t *) s
  2003. X    );
  2004. X}
  2005. X
  2006. X
  2007. X/*
  2008. X * stop_ff
  2009. X *    Stop search-fast-forward operation
  2010. X *
  2011. X * Args:
  2012. X *    s - Pointer to the curstat_t structure
  2013. X *
  2014. X * Return:
  2015. X *    Nothing.
  2016. X */
  2017. X/*ARGSUSED*/
  2018. XSTATIC void
  2019. Xstop_ff(curstat_t *s)
  2020. X{
  2021. X    cd_untimeout(search_id);
  2022. X}
  2023. X
  2024. X
  2025. X/*
  2026. X * run_ab
  2027. X *    Run a->b segment play operation
  2028. X *
  2029. X * Args:
  2030. X *    s - Pointer to the curstat_t structure
  2031. X *
  2032. X * Return:
  2033. X *    TRUE - success
  2034. X *    FALSE - failure
  2035. X */
  2036. X/*ARGSUSED*/
  2037. XSTATIC bool_t
  2038. Xrun_ab(curstat_t *s)
  2039. X{
  2040. X    return(
  2041. X        do_playaudio(
  2042. X            ADDR_BLK | ADDR_MSF,
  2043. X            ab_start_addr, ab_end_addr,
  2044. X            &ab_start_msf, &ab_end_msf,
  2045. X            0, 0
  2046. X        )
  2047. X    );
  2048. X}
  2049. X
  2050. X
  2051. X/*
  2052. X * run_sample
  2053. X *    Run sample play operation
  2054. X *
  2055. X * Args:
  2056. X *    s - Pointer to the curstat_t structure
  2057. X *
  2058. X * Return:
  2059. X *    TRUE - success
  2060. X *    FALSE - failure
  2061. X */
  2062. XSTATIC bool_t
  2063. Xrun_sample(curstat_t *s)
  2064. X{
  2065. X    if (next_sam < s->tot_trks) {
  2066. X        if (do_playaudio(ADDR_BLK,
  2067. X                 s->trkinfo[next_sam].addr,
  2068. X                 s->trkinfo[next_sam].addr +
  2069. X                 app_data.sample_blks,
  2070. X                 NULL, NULL, 0, 0)) {
  2071. X            next_sam++;
  2072. X            return(TRUE);
  2073. X        }
  2074. X    }
  2075. X
  2076. X    next_sam = 0;
  2077. X    return(FALSE);
  2078. X}
  2079. X
  2080. X
  2081. X/*
  2082. X * run_prog
  2083. X *    Run program/shuffle play operation
  2084. X *
  2085. X * Args:
  2086. X *    s - Pointer to the curstat_t structure
  2087. X *
  2088. X * Return:
  2089. X *    TRUE - success
  2090. X *    FALSE - failure
  2091. X */
  2092. XSTATIC bool_t
  2093. Xrun_prog(curstat_t *s)
  2094. X{
  2095. X    sword32_t    i;
  2096. X    msf_t        start_msf,
  2097. X            end_msf;
  2098. X
  2099. X    if (!s->shuffle && !s->program)
  2100. X        return(FALSE);
  2101. X
  2102. X    if (new_progshuf) {
  2103. X        if (s->shuffle)
  2104. X            /* New shuffle sequence needed */
  2105. X            reset_shuffle(s);
  2106. X        else
  2107. X            /* Program play: simply reset the count */
  2108. X            s->prog_cnt = 0;
  2109. X
  2110. X        new_progshuf = FALSE;
  2111. X    }
  2112. X
  2113. X    if (s->prog_cnt >= s->prog_tot)
  2114. X        /* Done with program/shuffle play cycle */
  2115. X        return(FALSE);
  2116. X
  2117. X    if ((i = curprog_pos(s)) < 0)
  2118. X        return(FALSE);
  2119. X
  2120. X    if (s->trkinfo[i].trkno == LEAD_OUT_TRACK)
  2121. X        return(FALSE);
  2122. X
  2123. X    s->prog_cnt++;
  2124. X    s->cur_trk = s->trkinfo[i].trkno;
  2125. X    s->cur_idx = 1;
  2126. X    s->cur_tot_addr = s->trkinfo[i].addr;
  2127. X    s->cur_trk_addr = 0;
  2128. X    s->cur_tot_min = s->trkinfo[i].min;
  2129. X    s->cur_tot_sec = s->trkinfo[i].sec;
  2130. X    s->cur_tot_frame = s->trkinfo[i].frame;
  2131. X    s->mode = M_PLAY;
  2132. X    dpy_all(s);
  2133. X
  2134. X    if (s->trkinfo[i].type == TYP_DATA)
  2135. X        return(TRUE);
  2136. X
  2137. X    start_msf.min = s->trkinfo[i].min;
  2138. X    start_msf.sec = s->trkinfo[i].sec;
  2139. X    start_msf.frame = s->trkinfo[i].frame;
  2140. X    end_msf.min = s->trkinfo[i+1].min;
  2141. X    end_msf.sec = s->trkinfo[i+1].sec;
  2142. X    end_msf.frame = s->trkinfo[i+1].frame;
  2143. X
  2144. X    return(
  2145. X        do_playaudio(
  2146. X            ADDR_BLK | ADDR_MSF,
  2147. X            s->trkinfo[i].addr, s->trkinfo[i+1].addr,
  2148. X            &start_msf, &end_msf,
  2149. X            0, 0
  2150. X        )
  2151. X    );
  2152. X}
  2153. X
  2154. X
  2155. X/*
  2156. X * run_repeat
  2157. X *    Run repeat play operation
  2158. X *
  2159. X * Args:
  2160. X *    s - Pointer to the curstat_t structure
  2161. X *
  2162. X * Return:
  2163. X *    TRUE - success
  2164. X *    FALSE - failure
  2165. X */
  2166. XSTATIC bool_t
  2167. Xrun_repeat(curstat_t *s)
  2168. X{
  2169. X    msf_t    start_msf,
  2170. X        end_msf;
  2171. X
  2172. X    if (!s->repeat)
  2173. X        return(FALSE);
  2174. X
  2175. X    if (s->shuffle || s->program) {
  2176. X        if (s->prog_cnt < s->prog_tot)
  2177. X            /* Not done with program/shuffle sequence yet */
  2178. X            return(TRUE);
  2179. X
  2180. X        new_progshuf = TRUE;
  2181. X    }
  2182. X    else {
  2183. X        s->cur_trk = s->first_trk;
  2184. X        s->cur_idx = 1;
  2185. X
  2186. X        s->cur_tot_addr = 0;
  2187. X        s->cur_trk_addr = 0;
  2188. X        s->cur_tot_min = 0;
  2189. X        s->cur_tot_sec = 0;
  2190. X        s->cur_tot_frame = 0;
  2191. X        dpy_all(s);
  2192. X
  2193. X        start_msf.min = s->trkinfo[0].min;
  2194. X        start_msf.sec = s->trkinfo[0].sec;
  2195. X        start_msf.frame = s->trkinfo[0].frame;
  2196. X        end_msf.min = s->tot_min;
  2197. X        end_msf.sec = s->tot_sec;
  2198. X        end_msf.frame = s->tot_frame;
  2199. X
  2200. X        if (!do_playaudio(ADDR_BLK | ADDR_MSF,
  2201. X                    s->trkinfo[0].addr, s->tot_addr,
  2202. X                    &start_msf, &end_msf, 0, 0))
  2203. X            return(FALSE);
  2204. X    }
  2205. X
  2206. X    return(TRUE);
  2207. X}
  2208. X
  2209. X
  2210. X
  2211. X/***********************
  2212. X *   public routines   *
  2213. X ***********************/
  2214. X
  2215. X/*
  2216. X * cdlib_check_disc
  2217. X *    Check if disc is ready for use
  2218. X *
  2219. X * Args:
  2220. X *    s - Pointer to the curstat_t structure
  2221. X *
  2222. X * Return:
  2223. X *    TRUE - success
  2224. X *    FALSE - failure
  2225. X */
  2226. Xbool_t
  2227. Xcdlib_check_disc(curstat_t *s)
  2228. X{
  2229. X    return(disc_ready(s));
  2230. X}
  2231. X
  2232. X
  2233. X/*
  2234. X * cdlib_lock
  2235. X *    Caddy lock function
  2236. X *
  2237. X * Args:
  2238. X *    s - Pointer to the curstat_t structure
  2239. X *    enable - whether to enable/disable caddy lock
  2240. X *
  2241. X * Return:
  2242. X *    Nothing.
  2243. X */
  2244. Xvoid
  2245. Xcdlib_lock(curstat_t *s, bool_t enable)
  2246. X{
  2247. X    if (scsi_prev_allow(enable)) {
  2248. X        s->caddy_lock = enable;
  2249. X        return;
  2250. X    }
  2251. X
  2252. X    /* Can't lock the caddy: beep. */
  2253. X    cd_beep();
  2254. X    set_lock_btn((bool_t) !enable);
  2255. X}
  2256. X
  2257. X
  2258. X/*
  2259. X * cdlib_repeat
  2260. X *    Repeat mode function
  2261. X *
  2262. X * Args:
  2263. X *    s - Pointer to the curstat_t structure
  2264. X *    enable - whether to enable/disable repeat mode
  2265. X *
  2266. X * Return:
  2267. X *    Nothing.
  2268. X */
  2269. Xvoid
  2270. Xcdlib_repeat(curstat_t *s, bool_t enable)
  2271. X{
  2272. X    s->repeat = enable;
  2273. X}
  2274. X
  2275. X
  2276. X/*
  2277. X * cdlib_shuffle
  2278. X *    Shuffle mode function
  2279. X *
  2280. X * Args:
  2281. X *    s - Pointer to the curstat_t structure
  2282. X *    enable - whether to enable/disable shuffle mode
  2283. X *
  2284. X * Return:
  2285. X *    Nothing.
  2286. X */
  2287. Xvoid
  2288. Xcdlib_shuffle(curstat_t *s, bool_t enable)
  2289. X{
  2290. X    switch (s->mode) {
  2291. X    case M_STOP:
  2292. X    case M_NODISC:
  2293. X        break;
  2294. X    default:
  2295. X        /* Can't change mode unless when stopped */
  2296. X        cd_beep();
  2297. X        set_shuffle_btn((bool_t) !enable);
  2298. X        return;
  2299. X    }
  2300. X
  2301. X    s->shuffle = enable;
  2302. X}
  2303. X
  2304. X
  2305. X/*
  2306. X * cdlib_load_eject
  2307. X *    CD caddy load and eject function.  If disc caddy is not
  2308. X *    loaded, it will attempt to load it.  Otherwise, it will be
  2309. X *    ejected.
  2310. X *
  2311. X * Args:
  2312. X *    s - Pointer to the curstat_t structure
  2313. X *
  2314. X * Return:
  2315. X *    Nothing.
  2316. X */
  2317. Xvoid
  2318. Xcdlib_load_eject(curstat_t *s)
  2319. X{
  2320. X    bool_t    ret = FALSE;
  2321. X
  2322. X    if (!disc_ready(s)) {
  2323. X        /* Disc not ready: try loading the disc */
  2324. X        if (!do_start_stop(TRUE, TRUE))
  2325. X            cd_beep();
  2326. X
  2327. X        return;
  2328. X    }
  2329. X
  2330. X    /* Eject the disc */
  2331. X
  2332. X    if (!app_data.eject_supp) {
  2333. X        cd_beep();
  2334. X
  2335. X        stop_stat_poll();
  2336. X        reset_curstat(s, TRUE);
  2337. X        s->mode = M_NODISC;
  2338. X
  2339. X        dbprog_dbclear(s);
  2340. X        dpy_all(s);
  2341. X
  2342. X        start_insert_poll(s);
  2343. X        return;
  2344. X    }
  2345. X
  2346. X    /* Unlock caddy if necessary */
  2347. X    if (s->caddy_lock) {
  2348. X        cdlib_lock(s, FALSE);
  2349. X        set_lock_btn(FALSE);
  2350. X    }
  2351. X
  2352. X#ifdef HITACHI
  2353. X    /* ----- Hitachi vendor-unique audio commands ----- */
  2354. X    if (!ret && app_data.vendor_code == VENDOR_HITACHI)
  2355. X        ret = hita_eject();
  2356. X#endif
  2357. X
  2358. X#ifdef NEC
  2359. X    /* ----- NEC vendor-unique audio commands ----- */
  2360. X    if (!ret && app_data.vendor_code == VENDOR_NEC)
  2361. X        ret = nec_eject();
  2362. X#endif
  2363. X
  2364. X#ifdef PIONEER
  2365. X    /* ----- Pioneer vendor-unique audio commands ----- */
  2366. X    if (!ret && app_data.vendor_code == VENDOR_PIONEER)
  2367. X        ret = pion_eject();
  2368. X#endif
  2369. X
  2370. X#ifdef TOSHIBA
  2371. X    /* ----- Toshiba vendor-unique audio commands ----- */
  2372. X    if (!ret && app_data.vendor_code == VENDOR_TOSHIBA)
  2373. X        ret = tosh_eject();
  2374. X#endif
  2375. X
  2376. X    /* ----- Standard SCSI-2 audio commands ----- */
  2377. X    if (!ret)
  2378. X        ret = do_start_stop(FALSE, TRUE);
  2379. X
  2380. X    if (ret) {
  2381. X        stop_stat_poll();
  2382. X        reset_curstat(s, TRUE);
  2383. X        s->mode = M_NODISC;
  2384. X
  2385. X        dbprog_dbclear(s);
  2386. X        dpy_all(s);
  2387. X
  2388. X        start_insert_poll(s);
  2389. X    }
  2390. X    else
  2391. X        cd_beep();
  2392. X}
  2393. X
  2394. X
  2395. X/*
  2396. X * cdlib_ab
  2397. X *    A->B segment play mode function
  2398. X *
  2399. X * Args:
  2400. X *    s - Pointer to the curstat_t structure
  2401. X *
  2402. X * Return:
  2403. X *    Nothing.
  2404. X */
  2405. Xvoid
  2406. Xcdlib_ab(curstat_t *s)
  2407. X{
  2408. X    switch (s->mode) {
  2409. X    case M_SAMPLE:
  2410. X    case M_PLAY:
  2411. X        /* Get current location */
  2412. X        if (!get_playstatus(s)) {
  2413. X            cd_beep();
  2414. X            break;
  2415. X        }
  2416. X
  2417. X        ab_start_addr = s->cur_tot_addr;
  2418. X        ab_start_msf.min = s->cur_tot_min;
  2419. X        ab_start_msf.sec = s->cur_tot_sec;
  2420. X        ab_start_msf.frame = s->cur_tot_frame;
  2421. X
  2422. X        s->mode = M_A;
  2423. X        dpy_playmode(s, FALSE);
  2424. X        break;
  2425. X
  2426. X    case M_A:
  2427. X        /* Get current location */
  2428. X        if (!get_playstatus(s)) {
  2429. X            cd_beep();
  2430. X            break;
  2431. X        }
  2432. X
  2433. X        ab_end_addr = s->cur_tot_addr;
  2434. X        ab_end_msf.min = s->cur_tot_min;
  2435. X        ab_end_msf.sec = s->cur_tot_sec;
  2436. X        ab_end_msf.frame = s->cur_tot_frame;
  2437. X
  2438. X        /* Make sure that the A->B play interval is no less
  2439. X         * than a user-configurable minimum.
  2440. X         */
  2441. X        if ((ab_end_addr - ab_start_addr) < app_data.min_playblks) {
  2442. X            ab_end_addr = ab_start_addr + app_data.min_playblks;
  2443. X            blktomsf(
  2444. X                ab_end_addr,
  2445. X                &ab_end_msf.min,
  2446. X                &ab_end_msf.sec,
  2447. X                &ab_end_msf.frame,
  2448. X                MSF_OFFSET(s)
  2449. X            );
  2450. X        }
  2451. X
  2452. X        if (!run_ab(s)) {
  2453. X            cd_beep();
  2454. X            return;
  2455. X        }
  2456. X
  2457. X        s->mode = M_AB;
  2458. X        dpy_playmode(s, FALSE);
  2459. X        break;
  2460. X
  2461. X    case M_AB:
  2462. X        /* Currently doing A->B playback, just call cdlib_play_pause
  2463. X         * to resume normal playback.
  2464. X         */
  2465. X        cdlib_play_pause(s);
  2466. X        break;
  2467. X
  2468. X    default:
  2469. X        cd_beep();
  2470. X        break;
  2471. X    }
  2472. X}
  2473. X
  2474. X
  2475. X/*
  2476. X * cdlib_sample
  2477. X *    Sample play mode function
  2478. X *
  2479. X * Args:
  2480. X *    s - Pointer to the curstat_t structure
  2481. X *
  2482. X * Return:
  2483. X *    Nothing.
  2484. X */
  2485. Xvoid
  2486. Xcdlib_sample(curstat_t *s)
  2487. X{
  2488. X    int    i;
  2489. X
  2490. X    if (!disc_ready(s)) {
  2491. X        cd_beep();
  2492. X        return;
  2493. X    }
  2494. X
  2495. X    if (s->shuffle || s->program) {
  2496. X        /* Sample is not supported in program/shuffle mode */
  2497. X        cd_beep();
  2498. X        return;
  2499. X    }
  2500. X
  2501. X    switch (s->mode) {
  2502. X    case M_STOP:
  2503. X        start_stat_poll(s);
  2504. X        /*FALLTHROUGH*/
  2505. X    case M_A:
  2506. X    case M_AB:
  2507. X    case M_PLAY:
  2508. X        /* If already playing a track, start sampling the track after
  2509. X         * the current one.  Otherwise, sample from the beginning.
  2510. X         */
  2511. X        if (s->cur_trk > 0 && s->cur_trk != s->last_trk) {
  2512. X            i = curtrk_pos(s) + 1;
  2513. X            s->cur_trk = s->trkinfo[i].trkno;
  2514. X            next_sam = i;
  2515. X        }
  2516. X        else {
  2517. X            s->cur_trk = s->first_trk;
  2518. X            next_sam = 0;
  2519. X        }
  2520. X        
  2521. X        s->cur_idx = 1;
  2522. X
  2523. X        s->mode = M_SAMPLE;
  2524. X        dpy_all(s);
  2525. X
  2526. X        if (!run_sample(s))
  2527. X            return;
  2528. X
  2529. X        break;
  2530. X
  2531. X    case M_SAMPLE:
  2532. X        /* Currently doing Sample playback, just call cdlib_play_pause
  2533. X         * to resume normal playback.
  2534. X         */
  2535. X        cdlib_play_pause(s);
  2536. X        break;
  2537. X
  2538. X    default:
  2539. X        cd_beep();
  2540. X        break;
  2541. X    }
  2542. X}
  2543. X
  2544. X
  2545. X/*
  2546. X * cdlib_level
  2547. X *    Audio volume control function
  2548. X *
  2549. X * Args:
  2550. X *    s - Pointer to the curstat_t structure
  2551. X *    level - The volume level to set to
  2552. X *    drag - Whether this is an update due to the user dragging the
  2553. X *        volume control slider thumb.  If this is FALSE, then
  2554. X *        a final volume setting has been found.
  2555. X *
  2556. X * Return:
  2557. X *    Nothing.
  2558. X */
  2559. Xvoid
  2560. Xcdlib_level(curstat_t *s, byte_t level, bool_t drag)
  2561. X{
  2562. X    int    actual;
  2563. X
  2564. X#ifdef HITACHI
  2565. X    if (app_data.vendor_code == VENDOR_HITACHI && drag)
  2566. X        return;
  2567. X#endif
  2568. X
  2569. X#ifdef NEC
  2570. X    if (app_data.vendor_code == VENDOR_NEC && drag)
  2571. X        return;
  2572. X#endif
  2573. X
  2574. X#ifdef PIONEER
  2575. X    if (app_data.vendor_code == VENDOR_PIONEER && drag)
  2576. X        return;
  2577. X#endif
  2578. X
  2579. X#ifdef TOSHIBA
  2580. X    if (app_data.vendor_code == VENDOR_TOSHIBA && drag)
  2581. X        return;
  2582. X#endif
  2583. X
  2584. X    /* Set volume level */
  2585. X    if ((actual = config_vol((int) level, s, FALSE, TRUE)) >= 0)
  2586. X        s->level = (byte_t) actual;
  2587. X}
  2588. X
  2589. X
  2590. X/*
  2591. X * cdlib_play_pause
  2592. X *    Audio playback and pause function
  2593. X *
  2594. X * Args:
  2595. X *    s - Pointer to the curstat_t structure
  2596. X *
  2597. X * Return:
  2598. X *    Nothing.
  2599. X */
  2600. Xvoid
  2601. Xcdlib_play_pause(curstat_t *s)
  2602. X{
  2603. X    sword32_t    i;
  2604. X    word32_t    start_addr;
  2605. X    msf_t        start_msf,
  2606. X            end_msf;
  2607. X
  2608. X    if (!disc_ready(s)) {
  2609. X        cd_beep();
  2610. X        return;
  2611. X    }
  2612. X
  2613. X    if (s->mode == M_NODISC)
  2614. X        s->mode = M_STOP;
  2615. X
  2616. X    switch (s->mode) {
  2617. X    case M_PLAY:
  2618. X        /* Currently playing: go to pause mode */
  2619. X
  2620. X        if (!do_pause_resume(FALSE)) {
  2621. X            cd_beep();
  2622. X            return;
  2623. X        }
  2624. X        stop_stat_poll();
  2625. X        s->mode = M_PAUSE;
  2626. X        dpy_playmode(s, FALSE);
  2627. X        break;
  2628. X
  2629. X    case M_PAUSE:
  2630. X        /* Currently paused: resume play */
  2631. X
  2632. X        if (!do_pause_resume(TRUE)) {
  2633. X            cd_beep();
  2634. X            return;
  2635. X        }
  2636. X        s->mode = M_PLAY;
  2637. X        dpy_playmode(s, FALSE);
  2638. X        start_stat_poll(s);
  2639. X        break;
  2640. X
  2641. X    case M_STOP:
  2642. X        /* Currently stopped: start play */
  2643. X
  2644. X        if (s->shuffle) {
  2645. X            /* Start shuffle play */
  2646. X            new_progshuf = TRUE;
  2647. X
  2648. X            if (!run_prog(s))
  2649. X                return;
  2650. X        }
  2651. X        else {
  2652. X            /* Start normal play */
  2653. X            if ((i = curtrk_pos(s)) < 0 || s->cur_trk <= 0) {
  2654. X                /* Start play from the beginning */
  2655. X                i = 0;
  2656. X                s->cur_trk = s->first_trk;
  2657. X                start_addr = s->trkinfo[0].addr;
  2658. X                start_msf.min = s->trkinfo[0].min;
  2659. X                start_msf.sec = s->trkinfo[0].sec;
  2660. X                start_msf.frame = s->trkinfo[0].frame;
  2661. X            }
  2662. X            else {
  2663. X                /* User has specified a starting track */
  2664. X                start_addr = s->trkinfo[i].addr;
  2665. X                start_msf.min = s->trkinfo[i].min;
  2666. X                start_msf.sec = s->trkinfo[i].sec;
  2667. X                start_msf.frame = s->trkinfo[i].frame;
  2668. X            }
  2669. X
  2670. X            end_msf.min = s->tot_min;
  2671. X            end_msf.sec = s->tot_sec;
  2672. X            end_msf.frame = s->tot_frame;
  2673. X
  2674. X            s->cur_idx = 1;
  2675. X            s->mode = M_PLAY;
  2676. X            if (s->trkinfo[i].type == TYP_DATA)
  2677. X                dpy_time(s, FALSE);
  2678. X
  2679. X            if (!do_playaudio(ADDR_BLK | ADDR_MSF,
  2680. X                      start_addr, s->tot_addr,
  2681. X                      &start_msf, &end_msf, 0, 0)) {
  2682. X                cd_beep();
  2683. X                s->mode = M_STOP;
  2684. X                return;
  2685. X            }
  2686. X        }
  2687. X
  2688. X        dpy_all(s);
  2689. X        start_stat_poll(s);
  2690. X        break;
  2691. X
  2692. X    case M_A:
  2693. X        /* Just reset mode to play and continue */
  2694. X        s->mode = M_PLAY;
  2695. X        dpy_playmode(s, FALSE);
  2696. X        break;
  2697. X
  2698. X    case M_AB:
  2699. X    case M_SAMPLE:
  2700. X        /* Force update of curstat */
  2701. X        if (!get_playstatus(s)) {
  2702. X            cd_beep();
  2703. X            return;
  2704. X        }
  2705. X
  2706. X        /* Currently doing a->b or sample playback: just resume play */
  2707. X        if (s->shuffle || s->program) {
  2708. X            if ((i = curtrk_pos(s)) < 0 ||
  2709. X                s->trkinfo[i].trkno == LEAD_OUT_TRACK)
  2710. X                return;
  2711. X
  2712. X            start_msf.min = s->cur_tot_min;
  2713. X            start_msf.sec = s->cur_tot_sec;
  2714. X            start_msf.frame = s->cur_tot_frame;
  2715. X            end_msf.min = s->trkinfo[i+1].min;
  2716. X            end_msf.sec = s->trkinfo[i+1].sec;
  2717. X            end_msf.frame = s->trkinfo[i+1].frame;
  2718. X
  2719. X            if (!do_playaudio(ADDR_BLK | ADDR_MSF,
  2720. X                      s->cur_tot_addr,
  2721. X                      s->trkinfo[i+1].addr,
  2722. X                      &start_msf, &end_msf, 0, 0)) {
  2723. X                cd_beep();
  2724. X                return;
  2725. X            }
  2726. X        }
  2727. X        else {
  2728. X            start_msf.min = s->cur_tot_min;
  2729. X            start_msf.sec = s->cur_tot_sec;
  2730. X            start_msf.frame = s->cur_tot_frame;
  2731. X            end_msf.min = s->tot_min;
  2732. X            end_msf.sec = s->tot_sec;
  2733. X            end_msf.frame = s->tot_frame;
  2734. X
  2735. X            if (!do_playaudio(ADDR_BLK | ADDR_MSF,
  2736. X                      s->cur_tot_addr, s->tot_addr,
  2737. X                      &start_msf, &end_msf, 0, 0)) {
  2738. X                cd_beep();
  2739. X                return;
  2740. X            }
  2741. X        }
  2742. X        s->mode = M_PLAY;
  2743. X        dpy_playmode(s, FALSE);
  2744. X        break;
  2745. X
  2746. X    default:
  2747. X        cd_beep();
  2748. X        break;
  2749. X    }
  2750. X}
  2751. X
  2752. X
  2753. X/*
  2754. X * cdlib_stop
  2755. X *    Stop function
  2756. X *
  2757. X * Args:
  2758. X *    s - Pointer to the curstat_t structure
  2759. X *    stop_disc - Whether to actually spin down the disc or just
  2760. X *        update status.
  2761. X *
  2762. X * Return:
  2763. X *    Nothing.
  2764. X */
  2765. Xvoid
  2766. Xcdlib_stop(curstat_t *s, bool_t stop_disc)
  2767. X{
  2768. X    /* The stop_disc parameter will cause the disc to spin down.
  2769. X     * This is usually set to TRUE, but can be FALSE if the caller
  2770. X     * just wants to set the current state to stop but will
  2771. X     * immediately go into play state again.  Not spinning down
  2772. X     * the drive makes things a little faster...
  2773. X     */
  2774. X
  2775. X    if (!disc_ready(s)) {
  2776. X        cd_beep();
  2777. X        return;
  2778. X    }
  2779. X
  2780. X    switch (s->mode) {
  2781. X    case M_PLAY:
  2782. X    case M_PAUSE:
  2783. X    case M_A:
  2784. X    case M_AB:
  2785. X    case M_SAMPLE:
  2786. X    case M_STOP:
  2787. X        /* Currently playing or paused: stop */
  2788. X
  2789. X        if (stop_disc && !do_start_stop(FALSE, FALSE)) {
  2790. X            cd_beep();
  2791. X            return;
  2792. X        }
  2793. X        stop_stat_poll();
  2794. X
  2795. X        reset_curstat(s, FALSE);
  2796. X        s->mode = M_STOP;
  2797. X
  2798. X        dpy_all(s);
  2799. X        break;
  2800. X
  2801. X    default:
  2802. X        cd_beep();
  2803. X        break;
  2804. X    }
  2805. X}
  2806. X
  2807. X
  2808. X/*
  2809. X * cdlib_prevtrk
  2810. X *    Previous track function
  2811. X *
  2812. X * Args:
  2813. X *    s - Pointer to the curstat_t structure
  2814. X *
  2815. X * Return:
  2816. X *    Nothing.
  2817. X */
  2818. Xvoid
  2819. Xcdlib_prevtrk(curstat_t *s)
  2820. X{
  2821. X    sword32_t    i;
  2822. X    word32_t    start_addr;
  2823. X    msf_t        start_msf,
  2824. X            end_msf;
  2825. X    bool_t        go_prev,
  2826. X            paused;
  2827. X
  2828. X    if (!disc_ready(s)) {
  2829. X        cd_beep();
  2830. X        return;
  2831. X    }
  2832. X
  2833. X    switch (s->mode) {
  2834. X    case M_A:
  2835. X    case M_AB:
  2836. X    case M_SAMPLE:
  2837. X        s->mode = M_PLAY;
  2838. X        dpy_playmode(s, FALSE);
  2839. X        /*FALLTHROUGH*/
  2840. X    case M_PLAY:
  2841. X    case M_PAUSE:
  2842. X        paused = (s->mode == M_PAUSE);
  2843. X
  2844. X        /* Find appropriate track to start */
  2845. X        if (s->shuffle || s->program) {
  2846. X            s->prog_cnt--;
  2847. X            i = curprog_pos(s);
  2848. X        }
  2849. X        else
  2850. X            i = curtrk_pos(s);
  2851. X
  2852. X        if (i < 0)
  2853. X            return;
  2854. X
  2855. X        start_addr = s->trkinfo[i].addr;
  2856. X        start_msf.min = s->trkinfo[i].min;
  2857. X        start_msf.sec = s->trkinfo[i].sec;
  2858. X        start_msf.frame = s->trkinfo[i].frame;
  2859. X        s->cur_trk = s->trkinfo[i].trkno;
  2860. X        s->cur_idx = 1;
  2861. X
  2862. X        /* If the current track has been playing for less
  2863. X         * than app_data.prev_threshold blocks, then go
  2864. X         * to the beginning of the previous track (if we
  2865. X         * are not already on the first track).
  2866. X         */
  2867. X        go_prev = FALSE;
  2868. X        if ((s->cur_tot_addr - start_addr) < app_data.prev_threshold)
  2869. X            go_prev = TRUE;
  2870. X
  2871. X        if (go_prev) {
  2872. X            if ((s->shuffle || s->program) && s->prog_cnt > 0) {
  2873. X                s->prog_cnt--;
  2874. X                if ((i = curprog_pos(s)) < 0)
  2875. X                    return;
  2876. X
  2877. X                start_addr = s->trkinfo[i].addr;
  2878. X                start_msf.min = s->trkinfo[i].min;
  2879. X                start_msf.sec = s->trkinfo[i].sec;
  2880. X                start_msf.frame = s->trkinfo[i].frame;
  2881. X                s->cur_trk = s->trkinfo[i].trkno;
  2882. X            }
  2883. X            else if (!s->shuffle && !s->program && i > 0) {
  2884. X                start_addr = s->trkinfo[i-1].addr;
  2885. X                start_msf.min = s->trkinfo[i-1].min;
  2886. X                start_msf.sec = s->trkinfo[i-1].sec;
  2887. X                start_msf.frame = s->trkinfo[i-1].frame;
  2888. X                s->cur_trk = s->trkinfo[i-1].trkno;
  2889. X            }
  2890. X        }
  2891. X
  2892. X        dpy_track(s);
  2893. X        dpy_index(s);
  2894. X
  2895. X        if (s->shuffle || s->program) {
  2896. X            /* Program/Shuffle mode: just stop the playback
  2897. X             * and let run_prog go to the previous track
  2898. X             */
  2899. X
  2900. X            do_start_stop(FALSE, FALSE);
  2901. X        }
  2902. X        else {
  2903. X            if (paused)
  2904. X                /* Mute: so we don't get a transient */
  2905. X                cdlib_mute_on(s);
  2906. X
  2907. X            end_msf.min = s->tot_min;
  2908. X            end_msf.sec = s->tot_sec;
  2909. X            end_msf.frame = s->tot_frame;
  2910. X
  2911. X            if (!do_playaudio(ADDR_BLK | ADDR_MSF,
  2912. X                      start_addr, s->tot_addr,
  2913. X                      &start_msf, &end_msf, 0, 0)) {
  2914. X                cd_beep();
  2915. X                return;
  2916. X            }
  2917. X
  2918. X            if (paused) {
  2919. X                do_pause_resume(FALSE);
  2920. X
  2921. X                /* Restore volume */
  2922. X                cdlib_mute_off(s);
  2923. X
  2924. X                /* Force update of curstat */
  2925. X                get_playstatus(s);
  2926. X            }
  2927. X        }
  2928. X
  2929. X        break;
  2930. X
  2931. X    case M_STOP:
  2932. X        if (s->shuffle || s->program) {
  2933. X            /* Pre-selecting tracks not supported in shuffle
  2934. X             * or program mode.
  2935. X             */
  2936. X            cd_beep();
  2937. X            return;
  2938. X        }
  2939. X
  2940. X        /* Find previous track */
  2941. X        if (s->cur_trk <= 0) {
  2942. X            s->cur_trk = s->trkinfo[0].trkno;
  2943. X            dpy_track(s);
  2944. X        }
  2945. X        else {
  2946. X            i = curtrk_pos(s);
  2947. X
  2948. X            if (i > 0) {
  2949. X                s->cur_trk = s->trkinfo[i-1].trkno;
  2950. X                dpy_track(s);
  2951. X            }
  2952. X        }
  2953. X        break;
  2954. X
  2955. X    default:
  2956. X        cd_beep();
  2957. X        break;
  2958. X    }
  2959. X}
  2960. X
  2961. X
  2962. X/*
  2963. X * cdlib_nexttrk
  2964. X *    Next track function
  2965. X *
  2966. X * Args:
  2967. X *    s - Pointer to the curstat_t structure
  2968. X *
  2969. X * Return:
  2970. X *    Nothing.
  2971. X */
  2972. Xvoid
  2973. Xcdlib_nexttrk(curstat_t *s)
  2974. X{
  2975. X    sword32_t    i;
  2976. X    word32_t    start_addr;
  2977. X    msf_t        start_msf,
  2978. X            end_msf;
  2979. X    bool_t        paused;
  2980. X
  2981. X    if (!disc_ready(s)) {
  2982. X        cd_beep();
  2983. X        return;
  2984. X    }
  2985. X
  2986. X    switch (s->mode) {
  2987. X    case M_A:
  2988. X    case M_AB:
  2989. X    case M_SAMPLE:
  2990. X        s->mode = M_PLAY;
  2991. X        dpy_playmode(s, FALSE);
  2992. X        /*FALLTHROUGH*/
  2993. X    case M_PLAY:
  2994. X    case M_PAUSE:
  2995. X        paused = (s->mode == M_PAUSE);
  2996. X
  2997. X        if (s->shuffle || s->program) {
  2998. X            /* Program/Shuffle mode: just stop the playback
  2999. X             * and let run_prog go to the next track.
  3000. X             */
  3001. X            do_start_stop(FALSE, FALSE);
  3002. X            return;
  3003. X        }
  3004. X
  3005. X        /* Find next track */
  3006. X        if ((i = curtrk_pos(s)) < 0)
  3007. X            return;
  3008. X
  3009. X        if (i < (MAXTRACK - 1) &&
  3010. X            s->trkinfo[i+1].trkno >= 0 &&
  3011. X            s->trkinfo[i+1].trkno != LEAD_OUT_TRACK) {
  3012. X
  3013. X            start_addr = s->trkinfo[i+1].addr;
  3014. X            start_msf.min = s->trkinfo[i+1].min;
  3015. X            start_msf.sec = s->trkinfo[i+1].sec;
  3016. X            start_msf.frame = s->trkinfo[i+1].frame;
  3017. X            s->cur_trk = s->trkinfo[i+1].trkno;
  3018. X            s->cur_idx = 1;
  3019. X
  3020. X            dpy_track(s);
  3021. X            dpy_index(s);
  3022. X
  3023. X            if (paused)
  3024. X                /* Mute: so we don't get a transient */
  3025. X                cdlib_mute_on(s);
  3026. X
  3027. X            end_msf.min = s->tot_min;
  3028. X            end_msf.sec = s->tot_sec;
  3029. X            end_msf.frame = s->tot_frame;
  3030. X
  3031. X            if (!do_playaudio(ADDR_BLK | ADDR_MSF,
  3032. X                      start_addr, s->tot_addr,
  3033. X                      &start_msf, &end_msf, 0, 0)) {
  3034. X                cd_beep();
  3035. X                return;
  3036. X            }
  3037. X
  3038. X            if (paused) {
  3039. X                do_pause_resume(FALSE);
  3040. X
  3041. X                /* Restore volume */
  3042. X                cdlib_mute_off(s);
  3043. X
  3044. X                /* Force update of curstat */
  3045. X                get_playstatus(s);
  3046. X            }
  3047. X        }
  3048. X
  3049. X        break;
  3050. X
  3051. X    case M_STOP:
  3052. X        if (s->shuffle || s->program) {
  3053. X            /* Pre-selecting tracks not supported in shuffle
  3054. X             * or program mode.
  3055. X             */
  3056. X            cd_beep();
  3057. X            return;
  3058. X        }
  3059. X
  3060. X        /* Find next track */
  3061. X        if (s->cur_trk <= 0) {
  3062. X            s->cur_trk = s->trkinfo[0].trkno;
  3063. X            dpy_track(s);
  3064. X        }
  3065. X        else {
  3066. X            i = curtrk_pos(s);
  3067. X
  3068. X            if (i >= 0 &&
  3069. X                s->trkinfo[i+1].trkno != LEAD_OUT_TRACK) {
  3070. X                s->cur_trk = s->trkinfo[i+1].trkno;
  3071. X                dpy_track(s);
  3072. X            }
  3073. X        }
  3074. X        break;
  3075. X
  3076. X    default:
  3077. X        cd_beep();
  3078. X        break;
  3079. X    }
  3080. X}
  3081. X
  3082. X
  3083. X/*
  3084. X * cdlib_previdx
  3085. X *    Previous index function
  3086. X *
  3087. X * Args:
  3088. X *    s - Pointer to the curstat_t structure
  3089. X *
  3090. X * Return:
  3091. X *    Nothing.
  3092. X */
  3093. Xvoid
  3094. Xcdlib_previdx(curstat_t *s)
  3095. X{
  3096. X    byte_t        idx;
  3097. X    msf_t        start_msf,
  3098. X            end_msf;
  3099. X    bool_t        paused;
  3100. X
  3101. X    if (s->shuffle || s->program) {
  3102. X        /* Index search is not supported in program/shuffle mode */
  3103. X        cd_beep();
  3104. X        return;
  3105. X    }
  3106. X
  3107. X    switch (s->mode) {
  3108. X    case M_A:
  3109. X    case M_AB:
  3110. X    case M_SAMPLE:
  3111. X        s->mode = M_PLAY;
  3112. X        dpy_playmode(s, FALSE);
  3113. X        /*FALLTHROUGH*/
  3114. X    case M_PLAY:
  3115. X    case M_PAUSE:
  3116. X        paused = (s->mode == M_PAUSE);
  3117. X
  3118. X        /* Find appropriate index to start */
  3119. X        if (s->cur_idx > 1 &&
  3120. X            (s->cur_tot_addr - s->sav_iaddr) < app_data.prev_threshold)
  3121. X            idx = s->cur_idx - 1;
  3122. X        else
  3123. X            idx = s->cur_idx;
  3124. X        
  3125. X        /* This is a hack...
  3126. X         * Since there is no standard SCSI-2 command to start
  3127. X         * playback on an index boundary and then go on playing
  3128. X         * until the end of the disc, we will use the PLAY AUDIO
  3129. X         * TRACK/INDEX command to go to where we want to start,
  3130. X         * immediately followed by a PAUSE.  We then find the
  3131. X         * current block position and issue a PLAY AUDIO MSF
  3132. X         * or PLAY AUDIO(12) command to start play there.
  3133. X         * We mute the audio in between these operations to
  3134. X         * prevent unpleasant transients.
  3135. X         */
  3136. X
  3137. X        /* Mute */
  3138. X        cdlib_mute_on(s);
  3139. X
  3140. X        if (!do_playaudio(ADDR_TRKIDX, 0, 0, NULL, NULL,
  3141. X                  (byte_t) s->cur_trk, idx)) {
  3142. X            /* Restore volume */
  3143. X            cdlib_mute_off(s);
  3144. X            cd_beep();
  3145. X            return;
  3146. X        }
  3147. X
  3148. X        if (!do_pause_resume(FALSE)) {
  3149. X            /* Restore volume */
  3150. X            cdlib_mute_off(s);
  3151. X            return;
  3152. X        }
  3153. X
  3154. X        /* Use get_playstatus to update the current status */
  3155. X        if (!get_playstatus(s)) {
  3156. X            /* Restore volume */
  3157. X            cdlib_mute_off(s);
  3158. X            return;
  3159. X        }
  3160. X
  3161. X        /* Save starting block addr of this index */
  3162. X        s->sav_iaddr = s->cur_tot_addr;
  3163. X
  3164. X        if (!paused)
  3165. X            /* Restore volume */
  3166. X            cdlib_mute_off(s);
  3167. X
  3168. X        start_msf.min = s->cur_tot_min;
  3169. X        start_msf.sec = s->cur_tot_sec;
  3170. X        start_msf.frame = s->cur_tot_frame;
  3171. X        end_msf.min = s->tot_min;
  3172. X        end_msf.sec = s->tot_sec;
  3173. X        end_msf.frame = s->tot_frame;
  3174. X
  3175. X        if (!do_playaudio(ADDR_BLK | ADDR_MSF,
  3176. X                  s->cur_tot_addr, s->tot_addr,
  3177. X                  &start_msf, &end_msf, 0, 0)) {
  3178. X            cd_beep();
  3179. X            return;
  3180. X        }
  3181. X
  3182. X        if (paused) {
  3183. X            do_pause_resume(FALSE);
  3184. X
  3185. X            /* Restore volume */
  3186. X            cdlib_mute_off(s);
  3187. X
  3188. X            /* Force update of curstat */
  3189. X            get_playstatus(s);
  3190. X        }
  3191. X
  3192. X        break;
  3193. X
  3194. X    default:
  3195. X        cd_beep();
  3196. X        break;
  3197. X    }
  3198. X}
  3199. X
  3200. X
  3201. X/*
  3202. X * cdlib_nextidx
  3203. X *    Next index function
  3204. X *
  3205. X * Args:
  3206. X *    s - Pointer to the curstat_t structure
  3207. X *
  3208. X * Return:
  3209. X *    Nothing.
  3210. X */
  3211. Xvoid
  3212. Xcdlib_nextidx(curstat_t *s)
  3213. X{
  3214. X    msf_t        start_msf,
  3215. X            end_msf;
  3216. X    bool_t        paused;
  3217. X
  3218. X    if (s->shuffle || s->program) {
  3219. X        /* Index search is not supported in program/shuffle mode */
  3220. X        cd_beep();
  3221. X        return;
  3222. X    }
  3223. X
  3224. X    switch (s->mode) {
  3225. X    case M_A:
  3226. X    case M_AB:
  3227. X    case M_SAMPLE:
  3228. X        s->mode = M_PLAY;
  3229. X        dpy_playmode(s, FALSE);
  3230. X        /*FALLTHROUGH*/
  3231. X    case M_PLAY:
  3232. X    case M_PAUSE:
  3233. X        paused = (s->mode == M_PAUSE);
  3234. X
  3235. X        /* Find appropriate index to start */
  3236. X        
  3237. X        /* This is a hack...
  3238. X         * Since there is no standard SCSI-2 command to start
  3239. X         * playback on an index boundary and then go on playing
  3240. X         * until the end of the disc, we will use the PLAY AUDIO
  3241. X         * TRACK/INDEX command to go to where we want to start,
  3242. X         * immediately followed by a PAUSE.  We then find the
  3243. X         * current block position and issue a PLAY AUDIO MSF
  3244. X         * or PLAY AUDIO(12) command to start play there.
  3245. X         * We mute the audio in between these operations to
  3246. X         * prevent unpleasant transients.
  3247. X         */
  3248. X
  3249. X        /* Mute */
  3250. X        cdlib_mute_on(s);
  3251. X
  3252. X        if (!do_playaudio(ADDR_TRKIDX, 0, 0, NULL, NULL,
  3253. X                  (byte_t) s->cur_trk,
  3254. X                  (byte_t) (s->cur_idx + 1))) {
  3255. X            /* Restore volume */
  3256. X            cdlib_mute_off(s);
  3257. X            cd_beep();
  3258. X            return;
  3259. X        }
  3260. X
  3261. X        if (!do_pause_resume(FALSE)) {
  3262. X            /* Restore volume */
  3263. X            cdlib_mute_off(s);
  3264. X            return;
  3265. X        }
  3266. X
  3267. X        /* Use get_playstatus to update the current status */
  3268. X        if (!get_playstatus(s)) {
  3269. X            /* Restore volume */
  3270. X            cdlib_mute_off(s);
  3271. X            return;
  3272. X        }
  3273. X
  3274. X        /* Save starting block addr of this index */
  3275. X        s->sav_iaddr = s->cur_tot_addr;
  3276. X
  3277. X        if (!paused)
  3278. X            /* Restore volume */
  3279. X            cdlib_mute_off(s);
  3280. X
  3281. X        start_msf.min = s->cur_tot_min;
  3282. X        start_msf.sec = s->cur_tot_sec;
  3283. X        start_msf.frame = s->cur_tot_frame;
  3284. X        end_msf.min = s->tot_min;
  3285. X        end_msf.sec = s->tot_sec;
  3286. X        end_msf.frame = s->tot_frame;
  3287. X
  3288. X        if (!do_playaudio(ADDR_BLK | ADDR_MSF,
  3289. X                  s->cur_tot_addr, s->tot_addr,
  3290. X                  &start_msf, &end_msf, 0, 0)) {
  3291. X            cd_beep();
  3292. X            return;
  3293. X        }
  3294. X
  3295. X        if (paused) {
  3296. X            do_pause_resume(FALSE);
  3297. X
  3298. X            /* Restore volume */
  3299. X            cdlib_mute_off(s);
  3300. X
  3301. X            /* Force update of curstat */
  3302. X            get_playstatus(s);
  3303. X        }
  3304. X
  3305. X        break;
  3306. X
  3307. X    default:
  3308. X        cd_beep();
  3309. X        break;
  3310. X    }
  3311. X}
  3312. X
  3313. X
  3314. X/*
  3315. X * cdlib_rew
  3316. X *    Search-rewind function
  3317. X *
  3318. X * Args:
  3319. X *    s - Pointer to the curstat_t structure
  3320. X *
  3321. X * Return:
  3322. X *    Nothing.
  3323. X */
  3324. Xvoid
  3325. Xcdlib_rew(curstat_t *s, bool_t start)
  3326. X{
  3327. X    sword32_t    i;
  3328. X    byte_t        vol;
  3329. X    msf_t        start_msf,
  3330. X            end_msf;
  3331. X    static bool_t    paused = FALSE;
  3332. X
  3333. X    switch (s->mode) {
  3334. X    case M_A:
  3335. X    case M_AB:
  3336. X    case M_SAMPLE:
  3337. X        /* Go to normal play mode first */
  3338. X        cdlib_play_pause(s);
  3339. X
  3340. X        /*FALLTHROUGH*/
  3341. X    case M_PLAY:
  3342. X    case M_PAUSE:
  3343. X        if (start) {
  3344. X            /* Button press */
  3345. X
  3346. X            if (s->mode == M_PLAY)
  3347. X                stop_stat_poll();
  3348. X
  3349. X            paused = (s->mode == M_PAUSE);
  3350. X
  3351. X            if (app_data.mselvol_supp) {
  3352. X                /* Reduce volume */
  3353. X                vol = (byte_t) ((int) s->level *
  3354. X                    app_data.skip_vol / 100);
  3355. X
  3356. X                config_vol((int)
  3357. X                    ((vol < (byte_t)app_data.skip_minvol) ?
  3358. X                     (byte_t) app_data.skip_minvol : vol),
  3359. X                    s,
  3360. X                    FALSE,
  3361. X                    FALSE
  3362. X                );
  3363. X            }
  3364. X
  3365. X            /* Start search rewind */
  3366. X            start_search = TRUE;
  3367. X            run_rew(s);
  3368. X        }
  3369. X        else {
  3370. X            /* Button release */
  3371. X
  3372. X            stop_rew(s);
  3373. X
  3374. X            /* Update display */
  3375. X            get_playstatus(s);
  3376. X
  3377. X            if (s->shuffle || s->program) {
  3378. X                if (app_data.mselvol_supp)
  3379. X                    /* Restore volume */
  3380. X                    cdlib_mute_off(s);
  3381. X
  3382. X                if ((i = curtrk_pos(s)) < 0 ||
  3383. X                    s->trkinfo[i].trkno == LEAD_OUT_TRACK)
  3384. X                    return;
  3385. X
  3386. X                start_msf.min = s->cur_tot_min;
  3387. X                start_msf.sec = s->cur_tot_sec;
  3388. X                start_msf.frame = s->cur_tot_frame;
  3389. X                end_msf.min = s->trkinfo[i+1].min;
  3390. X                end_msf.sec = s->trkinfo[i+1].sec;
  3391. X                end_msf.frame = s->trkinfo[i+1].frame;
  3392. X
  3393. X                if (!do_playaudio(ADDR_BLK | ADDR_MSF,
  3394. X                          s->cur_tot_addr,
  3395. X                          s->trkinfo[i+1].addr,
  3396. X                          &start_msf, &end_msf,
  3397. X                          0, 0)) {
  3398. X                    cd_beep();
  3399. X                    return;
  3400. X                }
  3401. X
  3402. X                start_stat_poll(s);
  3403. X            }
  3404. X            else {
  3405. X                if (paused)
  3406. X                    /* Mute: so we don't get a transient */
  3407. X                    cdlib_mute_on(s);
  3408. X                else if (app_data.mselvol_supp)
  3409. X                    /* Restore volume */
  3410. X                    cdlib_mute_off(s);
  3411. X
  3412. X                start_msf.min = s->cur_tot_min;
  3413. X                start_msf.sec = s->cur_tot_sec;
  3414. X                start_msf.frame = s->cur_tot_frame;
  3415. X                end_msf.min = s->tot_min;
  3416. X                end_msf.sec = s->tot_sec;
  3417. X                end_msf.frame = s->tot_frame;
  3418. X
  3419. X                if (!do_playaudio(ADDR_BLK | ADDR_MSF,
  3420. X                          s->cur_tot_addr,
  3421. X                          s->tot_addr,
  3422. X                          &start_msf, &end_msf,
  3423. X                          0, 0)) {
  3424. X                    cd_beep();
  3425. X                    return;
  3426. X                }
  3427. X
  3428. X                if (paused) {
  3429. X                    do_pause_resume(FALSE);
  3430. X
  3431. X                    /* Restore volume */
  3432. X                    cdlib_mute_off(s);
  3433. X                }
  3434. X                else
  3435. X                    start_stat_poll(s);
  3436. X            }
  3437. X        }
  3438. X        break;
  3439. X
  3440. X    default:
  3441. X        if (start)
  3442. X            cd_beep();
  3443. X        break;
  3444. X    }
  3445. X}
  3446. X
  3447. X
  3448. X/*
  3449. X * cdlib_ff
  3450. X *    Search-fast-forward function
  3451. X *
  3452. X * Args:
  3453. X *    s - Pointer to the curstat_t structure
  3454. X *
  3455. X * Return:
  3456. X *    Nothing.
  3457. X */
  3458. Xvoid
  3459. Xcdlib_ff(curstat_t *s, bool_t start)
  3460. X{
  3461. X    sword32_t    i;
  3462. X    byte_t        vol;
  3463. X    msf_t        start_msf,
  3464. X            end_msf;
  3465. X    static bool_t    paused = FALSE;
  3466. X
  3467. X    switch (s->mode) {
  3468. X    case M_A:
  3469. X    case M_AB:
  3470. X    case M_SAMPLE:
  3471. X        /* Go to normal play mode first */
  3472. X        cdlib_play_pause(s);
  3473. X
  3474. X        /*FALLTHROUGH*/
  3475. X    case M_PLAY:
  3476. X    case M_PAUSE:
  3477. X        if (start) {
  3478. X            /* Button press */
  3479. X
  3480. X            if (s->mode == M_PLAY)
  3481. X                stop_stat_poll();
  3482. X
  3483. X            paused = (s->mode == M_PAUSE);
  3484. X
  3485. X            if (app_data.mselvol_supp) {
  3486. X                /* Reduce volume */
  3487. X                vol = (byte_t) ((int) s->level *
  3488. X                    app_data.skip_vol / 100);
  3489. X
  3490. X                config_vol((int)
  3491. X                    ((vol < (byte_t)app_data.skip_minvol) ?
  3492. X                     (byte_t) app_data.skip_minvol : vol),
  3493. X                    s,
  3494. X                    FALSE,
  3495. X                    FALSE
  3496. X                );
  3497. X            }
  3498. X
  3499. X            /* Start search forward */
  3500. X            start_search = TRUE;
  3501. X            run_ff(s);
  3502. X        }
  3503. X        else {
  3504. X            /* Button release */
  3505. X
  3506. X            stop_ff(s);
  3507. X
  3508. X            /* Update display */
  3509. X            get_playstatus(s);
  3510. X
  3511. X            if (s->shuffle || s->program) {
  3512. X                if (app_data.mselvol_supp)
  3513. X                    /* Restore volume */
  3514. X                    cdlib_mute_off(s);
  3515. X
  3516. X                if ((i = curtrk_pos(s)) < 0 ||
  3517. X                    s->trkinfo[i].trkno == LEAD_OUT_TRACK)
  3518. X                    return;
  3519. X
  3520. X                start_msf.min = s->cur_tot_min;
  3521. X                start_msf.sec = s->cur_tot_sec;
  3522. X                start_msf.frame = s->cur_tot_frame;
  3523. X                end_msf.min = s->trkinfo[i+1].min;
  3524. X                end_msf.sec = s->trkinfo[i+1].sec;
  3525. X                end_msf.frame = s->trkinfo[i+1].frame;
  3526. X
  3527. X                if (!do_playaudio(ADDR_BLK | ADDR_MSF,
  3528. X                          s->cur_tot_addr,
  3529. X                          s->trkinfo[i+1].addr,
  3530. X                          &start_msf, &end_msf,
  3531. X                          0, 0)) {
  3532. X                    cd_beep();
  3533. X                    return;
  3534. X                }
  3535. X
  3536. X                start_stat_poll(s);
  3537. X            }
  3538. X            else {
  3539. X                if (paused)
  3540. X                    /* Mute: so we don't get a transient */
  3541. X                    cdlib_mute_on(s);
  3542. X                else if (app_data.mselvol_supp)
  3543. X                    /* Restore volume */
  3544. X                    cdlib_mute_off(s);
  3545. X
  3546. X                start_msf.min = s->cur_tot_min;
  3547. X                start_msf.sec = s->cur_tot_sec;
  3548. X                start_msf.frame = s->cur_tot_frame;
  3549. X                end_msf.min = s->tot_min;
  3550. X                end_msf.sec = s->tot_sec;
  3551. X                end_msf.frame = s->tot_frame;
  3552. X
  3553. X                if (!do_playaudio(ADDR_BLK | ADDR_MSF,
  3554. X                          s->cur_tot_addr,
  3555. X                          s->tot_addr,
  3556. X                          &start_msf, &end_msf,
  3557. X                          0, 0)) {
  3558. X                    cd_beep();
  3559. X                    return;
  3560. X                }
  3561. X
  3562. X                if (paused) {
  3563. X                    do_pause_resume(FALSE);
  3564. X
  3565. X                    /* Restore volume */
  3566. X                    cdlib_mute_off(s);
  3567. X                }
  3568. X                else
  3569. X                    start_stat_poll(s);
  3570. X            }
  3571. X        }
  3572. X        break;
  3573. X
  3574. X    default:
  3575. X        if (start)
  3576. X            cd_beep();
  3577. X        break;
  3578. X    }
  3579. X}
  3580. X
  3581. X
  3582. X/*
  3583. X * cdlib_mute_on
  3584. X *    Mute audio function
  3585. X *
  3586. X * Args:
  3587. X *    s - Pointer to the curstat_t structure
  3588. X *
  3589. X * Return:
  3590. X *    Nothing.
  3591. X */
  3592. Xvoid
  3593. Xcdlib_mute_on(curstat_t *s)
  3594. X{
  3595. X    config_vol(0, s, FALSE, FALSE);
  3596. X}
  3597. X
  3598. X
  3599. X/*
  3600. X * cdlib_mute_off
  3601. X *    Un-mute audio function
  3602. X *
  3603. X * Args:
  3604. X *    s - Pointer to the curstat_t structure
  3605. X *
  3606. X * Return:
  3607. X *    Nothing.
  3608. X */
  3609. Xvoid
  3610. Xcdlib_mute_off(curstat_t *s)
  3611. X{
  3612. X    config_vol((int) s->level, s, FALSE, FALSE);
  3613. X}
  3614. X
  3615. X
  3616. X/*
  3617. X * cdlib_playprog
  3618. X *    Program/shuffle play function
  3619. X *
  3620. X * Args:
  3621. X *    s - Pointer to the curstat_t structure
  3622. X *
  3623. X * Return:
  3624. X *    Nothing.
  3625. X */
  3626. Xvoid
  3627. Xcdlib_playprog(curstat_t *s)
  3628. X{
  3629. X    switch (s->mode) {
  3630. X    case M_PLAY:
  3631. X    case M_A:
  3632. X    case M_AB:
  3633. X    case M_SAMPLE:
  3634. X        stop_stat_poll();
  3635. X
  3636. X        /*FALLTHROUGH*/
  3637. X    case M_STOP:
  3638. X    case M_PAUSE:
  3639. X        break;
  3640. X
  3641. X    case M_NODISC:
  3642. X        /* No disc: just return */
  3643. X        return;
  3644. X
  3645. X    default:
  3646. X        /* Unknown mode */
  3647. X        return;
  3648. X    }
  3649. X
  3650. X    new_progshuf = TRUE;
  3651. X
  3652. X    if (run_prog(s))
  3653. X        start_stat_poll(s);
  3654. X    else {
  3655. X        cd_beep();
  3656. X        cdlib_stop(s, FALSE);
  3657. X    }
  3658. X}
  3659. X
  3660. X
  3661. X/*
  3662. X * cdlib_init
  3663. X *    Top-level function to initialize the SCSI-passthrough and
  3664. X *    vendor-unique modules.
  3665. X *
  3666. X * Args:
  3667. X *    s - Pointer to the curstat_t structure
  3668. X *
  3669. X * Return:
  3670. X *    Nothing.
  3671. X */
  3672. Xvoid
  3673. Xcdlib_init(curstat_t *s)
  3674. X{
  3675. X    /* Initialize */
  3676. X    stat_polling = FALSE;
  3677. X    stat_interval = app_data.stat_interval;
  3678. X    insert_polling = FALSE;
  3679. X    next_sam = FALSE;
  3680. X    new_progshuf = FALSE;
  3681. X    sav_end_addr = 0;
  3682. X    sav_end_msf.min = sav_end_msf.sec = sav_end_msf.frame = 0;
  3683. X    sav_end_fmt = 0;
  3684. X
  3685. X#ifndef SIMULATED_CDROM
  3686. X    if (setuid(0) < 0 || getuid() != 0)
  3687. X        cd_fatal_popup(app_data.str_fatal, app_data.str_moderr);
  3688. X#endif
  3689. X
  3690. X    /* Initialize curstat structure */
  3691. X    reset_curstat(s, TRUE);
  3692. X
  3693. X    /* Initialize the vendor unique modules */
  3694. X
  3695. X#ifdef HITACHI
  3696. X    if (app_data.vendor_code == VENDOR_HITACHI)
  3697. X        hita_init();
  3698. X#endif
  3699. X
  3700. X#ifdef NEC
  3701. X    if (app_data.vendor_code == VENDOR_NEC)
  3702. X        nec_init();
  3703. X#endif
  3704. X
  3705. X#ifdef PIONEER
  3706. X    if (app_data.vendor_code == VENDOR_PIONEER)
  3707. X        pion_init();
  3708. X#endif
  3709. X
  3710. X#ifdef TOSHIBA
  3711. X    if (app_data.vendor_code == VENDOR_TOSHIBA)
  3712. X        tosh_init();
  3713. X#endif
  3714. X}
  3715. X
  3716. X
  3717. X/*
  3718. X * cdlib_start
  3719. X *    Start the SCSI-passthrough module.
  3720. X *
  3721. X * Args:
  3722. X *    s - Pointer to the curstat_t structure
  3723. X *
  3724. X * Return:
  3725. X *    Nothing.
  3726. X */
  3727. Xvoid
  3728. Xcdlib_start(curstat_t *s)
  3729. X{
  3730. X    /* Check to see if disc is ready */
  3731. X    if (!disc_ready(s))
  3732. X        start_insert_poll(s);
  3733. X
  3734. X    /* Update display */
  3735. X    dpy_all(s);
  3736. X}
  3737. X
  3738. X
  3739. X/*
  3740. X * cdlib_icon
  3741. X *    Handler for main window iconification/de-iconification
  3742. X *
  3743. X * Args:
  3744. X *    s - Pointer to the curstat_t structure
  3745. X *    iconified - Whether the main window is iconified
  3746. X *
  3747. X * Return:
  3748. X *    Nothing.
  3749. X */
  3750. Xvoid
  3751. Xcdlib_icon(curstat_t *s, bool_t iconified)
  3752. X{
  3753. X    /* This function attempts to reduce the status polling frequency
  3754. X     * when possible to cut down on CPU and SCSI bus usage.  This is
  3755. X     * done when xmcd is iconified.
  3756. X     */
  3757. X
  3758. X    /* Increase status polling interval by 4 seconds when iconified */
  3759. X    if (iconified)
  3760. X        stat_interval = app_data.stat_interval + 4000;
  3761. X    else
  3762. X        stat_interval = app_data.stat_interval;
  3763. X
  3764. X    /* Check disc status */
  3765. X    if (!disc_ready(s))
  3766. X        return;
  3767. X
  3768. X    switch (s->mode) {
  3769. X    case M_STOP:
  3770. X    case M_NODISC:
  3771. X    case M_PAUSE:
  3772. X        break;
  3773. X
  3774. X    case M_A:
  3775. X    case M_AB:
  3776. X    case M_SAMPLE:
  3777. X        /* No optimization in these modes */
  3778. X        stat_interval = app_data.stat_interval;
  3779. X        break;
  3780. X
  3781. X    case M_PLAY:
  3782. X        if (!iconified) {
  3783. X            /* Force an immediate update */
  3784. X            stop_stat_poll();
  3785. X            start_stat_poll(s);
  3786. X        }
  3787. X        break;
  3788. X    }
  3789. X}
  3790. X
  3791. X
  3792. X/*
  3793. X * cdlib_halt
  3794. X *    Shut down the SCSI-passthrough and vendor-unique modules.
  3795. X *
  3796. X * Args:
  3797. X *    s - Pointer to the curstat_t structure
  3798. X *
  3799. X * Return:
  3800. X *    Nothing.
  3801. X */
  3802. Xvoid
  3803. Xcdlib_halt(curstat_t *s)
  3804. X{
  3805. X    /* Re-enable front-panel eject button */
  3806. X    if (s->caddy_lock)
  3807. X        cdlib_lock(s, FALSE);
  3808. X
  3809. X    if (s->mode != M_NODISC) {
  3810. X        if (app_data.exit_eject && app_data.eject_supp) {
  3811. X            /* User closing application: Eject disc */
  3812. X            do_start_stop(FALSE, TRUE);
  3813. X        }
  3814. X        else {
  3815. X            if (app_data.exit_stop)
  3816. X                /* User closing application: Stop disc */
  3817. X                do_start_stop(FALSE, FALSE);
  3818. X
  3819. X            switch (s->mode) {
  3820. X            case M_PLAY:
  3821. X            case M_PAUSE:
  3822. X            case M_A:
  3823. X            case M_AB:
  3824. X            case M_SAMPLE:
  3825. X                stop_stat_poll();
  3826. X                break;
  3827. X            }
  3828. X        }
  3829. X    }
  3830. X
  3831. X    /* Shut down the vendor unique modules */
  3832. X
  3833. X#ifdef HITACHI
  3834. X    if (app_data.vendor_code == VENDOR_HITACHI)
  3835. X        hita_halt();
  3836. X#endif
  3837. X
  3838. X#ifdef NEC
  3839. X    if (app_data.vendor_code == VENDOR_NEC)
  3840. X        nec_halt();
  3841. X#endif
  3842. X
  3843. X#ifdef PIONEER
  3844. X    if (app_data.vendor_code == VENDOR_PIONEER)
  3845. X        pion_halt();
  3846. X#endif
  3847. X
  3848. X#ifdef TOSHIBA
  3849. X    if (app_data.vendor_code == VENDOR_TOSHIBA)
  3850. X        tosh_halt();
  3851. X#endif
  3852. X
  3853. X    /* Close device */
  3854. X    pthru_close();
  3855. X}
  3856. X
  3857. X
  3858. X/*
  3859. X * cdlib_mode
  3860. X *    Return a text string indicating the current SCSI mode
  3861. X *    ("SCSI-2" or a particular vendor-unique string).
  3862. X *
  3863. X * Args:
  3864. X *    Nothing.
  3865. X *
  3866. X * Return:
  3867. X *    SCSI mode text string.
  3868. X */
  3869. Xchar *
  3870. Xcdlib_mode(void)
  3871. X{
  3872. X    static char    mode[STR_BUF_SZ];
  3873. X
  3874. X    switch (app_data.vendor_code) {
  3875. X
  3876. X    case VENDOR_SCSI2:
  3877. X        strcpy(mode, "SCSI-2");
  3878. X        break;
  3879. X
  3880. X#ifdef HITACHI
  3881. X    case VENDOR_HITACHI:
  3882. X        strcpy(mode, "Hitachi vendor-unique");
  3883. X        break;
  3884. X#endif
  3885. X
  3886. X#ifdef NEC
  3887. X    case VENDOR_NEC:
  3888. X        strcpy(mode, "NEC vendor-unique");
  3889. X        break;
  3890. X#endif
  3891. X
  3892. X#ifdef PIONEER
  3893. X    case VENDOR_PIONEER:
  3894. X        strcpy(mode, "Pioneer vendor-unique");
  3895. X        break;
  3896. X#endif
  3897. X
  3898. X#ifdef TOSHIBA
  3899. X    case VENDOR_TOSHIBA:
  3900. X        strcpy(mode, "Toshiba vendor-unique");
  3901. X        break;
  3902. X#endif
  3903. X
  3904. X    default:
  3905. X        strcpy(mode, "??");
  3906. X        break;
  3907. X    }
  3908. X
  3909. X    return(mode);
  3910. X}
  3911. X
  3912. X
  3913. X/*
  3914. X * cdlib_vers
  3915. X *    Return a text string indicating the SCSI-passthrough module's
  3916. X *    version number and which SCSI-1 vendor-unique modes are
  3917. X *    supported in this binary.
  3918. X *
  3919. X * Args:
  3920. X *    Nothing.
  3921. X *
  3922. X * Return:
  3923. X *    Version text string.
  3924. X */
  3925. Xchar *
  3926. Xcdlib_vers(void)
  3927. X{
  3928. X    static char    vers[256];
  3929. X
  3930. X    sprintf(vers, "%s v%s\n%s\n",
  3931. X        "SCSI-2 Pass-through module",
  3932. X        CDLIB_VERS,
  3933. X        "SCSI-1 Vendor-unique support:");
  3934. X
  3935. X#ifdef HITACHI
  3936. X    sprintf(vers, "%s    Hitachi\n", vers);
  3937. X#endif
  3938. X
  3939. X#ifdef NEC
  3940. X    sprintf(vers, "%s    NEC\n", vers);
  3941. X#endif
  3942. X
  3943. X#ifdef PIONEER
  3944. X    sprintf(vers, "%s    Pioneer\n", vers);
  3945. X#endif
  3946. X
  3947. X#ifdef TOSHIBA
  3948. X    sprintf(vers, "%s    Toshiba\n", vers);
  3949. X#endif
  3950. X
  3951. X#ifndef VUSUPPORT
  3952. X    sprintf(vers, "%s    (none)\n", vers);
  3953. X#endif
  3954. X
  3955. X    strcat(vers, pthru_vers());
  3956. X
  3957. X    return(vers);
  3958. X}
  3959. X
  3960. X
  3961. END_OF_FILE
  3962. if test 71104 -ne `wc -c <'lib_scsipt.c'`; then
  3963.     echo shar: \"'lib_scsipt.c'\" unpacked with wrong size!
  3964. fi
  3965. # end of 'lib_scsipt.c'
  3966. fi
  3967. if test -f 'lib_sun.c' -a "${1}" != "-c" ; then 
  3968.   echo shar: Will not clobber existing file \"'lib_sun.c'\"
  3969. else
  3970. echo shar: Extracting \"'lib_sun.c'\" \(7347 characters\)
  3971. sed "s/^X//" >'lib_sun.c' <<'END_OF_FILE'
  3972. X/*
  3973. X *   xmcd - Motif(tm) CD Audio Player
  3974. X *
  3975. X *   Copyright (C) 1993  Ti Kan
  3976. X *   E-mail: ti@amb.org
  3977. X *
  3978. X *   This program is free software; you can redistribute it and/or modify
  3979. X *   it under the terms of the GNU General Public License as published by
  3980. X *   the Free Software Foundation; either version 2 of the License, or
  3981. X *   (at your option) any later version.
  3982. X *
  3983. X *   This program is distributed in the hope that it will be useful,
  3984. X *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  3985. X *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  3986. X *   GNU General Public License for more details.
  3987. X *
  3988. X *   You should have received a copy of the GNU General Public License
  3989. X *   along with this program; if not, write to the Free Software
  3990. X *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  3991. X *
  3992. X *   This software module contains code that interfaces xmcd to
  3993. X *   the SunOS operating systems.  The name "Sun" and "SunOS"
  3994. X *   are used here for identification purposes.  This software and
  3995. X *   its author are not affiliated with Sun Microsystems.
  3996. X *
  3997. X *   You may want to compile with -DAUTO_RSENSE on Solaris 2.2 or
  3998. X *   later systems to enable the auto-request sense feature.
  3999. X */
  4000. X#ifndef LINT
  4001. Xstatic char *_lib_sun_c_ident_ = "@(#)lib_sun.c    1.16 93/10/06";
  4002. X#endif
  4003. X
  4004. X#include <Xm/Xm.h>
  4005. X#include "xmcd.h"
  4006. X#include "util.h"
  4007. X#include "cdfunc.h"
  4008. X#include "lib_scsipt.h"
  4009. X
  4010. X#if defined(sun) && !defined(SIMULATED_CDROM)
  4011. X
  4012. X#ifndef OSI_VERS
  4013. X#define OSI_VERS    "1.0"        /* Version */
  4014. X#endif
  4015. X
  4016. X
  4017. Xextern AppData        app_data;
  4018. Xextern bool_t        notrom_error;
  4019. X
  4020. X#ifndef LINT
  4021. Xbool_t            lib_sun = TRUE;
  4022. X#endif
  4023. X
  4024. XSTATIC int        fd = -1;    /* Passthrough device file desc */
  4025. XSTATIC req_sense_data_t    sense_data;    /* Request sense data buffer */
  4026. X
  4027. X
  4028. X/*
  4029. X * pthru_send
  4030. X *    Build SCSI CDB and sent command to the device.
  4031. X *
  4032. X * Args:
  4033. X *    opcode - SCSI command opcode
  4034. X *    addr - The "address" portion of the SCSI CDB
  4035. X *    buf - Pointer to data buffer
  4036. X *    size - Number of bytes to transfer
  4037. X *    rsvd - The "reserved" portion of the SCSI CDB
  4038. X *    length - The "length" portion of the SCSI CDB
  4039. X *    param - The "param" portion of the SCSI CDB
  4040. X *    control - The "control" portion of the SCSI CDB
  4041. X *    rw - Data transfer direction flag (READ_OP or WRITE_OP)
  4042. X *
  4043. X * Return:
  4044. X *    TRUE - command completed successfully
  4045. X *    FALSE - command failed
  4046. X */
  4047. Xbool_t
  4048. Xpthru_send(
  4049. X    byte_t        opcode,
  4050. X    word32_t    addr,
  4051. X    byte_t        *buf,
  4052. X    word32_t    size,
  4053. X    byte_t        rsvd,
  4054. X    word32_t    length,
  4055. X    byte_t        param,
  4056. X    byte_t        control,
  4057. X    byte_t        rw
  4058. X)
  4059. X{
  4060. X    struct uscsi_cmd    ucmd;
  4061. X    byte_t            cdb[12];
  4062. X
  4063. X    
  4064. X    if (fd < 0 || notrom_error)
  4065. X        return(FALSE);
  4066. X
  4067. X    memset(&ucmd, (byte_t) 0, sizeof(ucmd));
  4068. X    memset(cdb, (byte_t) 0, sizeof(cdb));
  4069. X
  4070. X    /* set up SCSI CDB */
  4071. X    switch (opcode & 0xf0) {
  4072. X    case 0xa0:
  4073. X    case 0xe0:
  4074. X        /* 12-byte commands */
  4075. X        cdb[0] = opcode;
  4076. X        cdb[1] = param;
  4077. X        cdb[2] = (addr >> 24) & 0xff;
  4078. X        cdb[3] = (addr >> 16) & 0xff;
  4079. X        cdb[4] = (addr >> 8) & 0xff;
  4080. X        cdb[5] = (addr & 0xff);
  4081. X        cdb[6] = (length >> 24) & 0xff;
  4082. X        cdb[7] = (length >> 16) & 0xff;
  4083. X        cdb[8] = (length >> 8) & 0xff;
  4084. X        cdb[9] = length & 0xff;
  4085. X        cdb[10] = rsvd;
  4086. X        cdb[11] = control;
  4087. X
  4088. X        ucmd.uscsi_cdblen = 12;
  4089. X        break;
  4090. X
  4091. X    case 0xc0:
  4092. X    case 0xd0:
  4093. X    case 0x20:
  4094. X    case 0x30:
  4095. X    case 0x40:
  4096. X        /* 10-byte commands */
  4097. X        cdb[0] = opcode;
  4098. X        cdb[1] = param;
  4099. X        cdb[2] = (addr >> 24) & 0xff;
  4100. X        cdb[3] = (addr >> 16) & 0xff;
  4101. X        cdb[4] = (addr >> 8) & 0xff;
  4102. X        cdb[5] = addr & 0xff;
  4103. X        cdb[6] = rsvd;
  4104. X        cdb[7] = (length >> 8) & 0xff;
  4105. X        cdb[8] = length & 0xff;
  4106. X        cdb[9] = control;
  4107. X
  4108. X        ucmd.uscsi_cdblen = 10;
  4109. X        break;
  4110. X
  4111. X    case 0x00:
  4112. X    case 0x10:
  4113. X        /* 6-byte commands */
  4114. X        cdb[0] = opcode;
  4115. X        cdb[1] = param;
  4116. X        cdb[2] = (addr >> 8) & 0xff;
  4117. X        cdb[3] = addr & 0xff;
  4118. X        cdb[4] = length & 0xff;
  4119. X        cdb[5] = control;
  4120. X
  4121. X        ucmd.uscsi_cdblen = 6;
  4122. X        break;
  4123. X
  4124. X    default:
  4125. X        if (app_data.scsierr_msg)
  4126. X            fprintf(stderr, "0x%02x: Unknown SCSI opcode\n",
  4127. X                opcode);
  4128. X        return(FALSE);
  4129. X    }
  4130. X
  4131. X#ifdef DEBUG
  4132. X    {
  4133. X        int    i;
  4134. X
  4135. X        fprintf(stderr, "\nSCSI CDB bytes:");
  4136. X        for (i = 0; i < ucmd.uscsi_cdblen; i++)
  4137. X            fprintf(stderr, " %02x", cdb[i]);
  4138. X        fprintf(stderr, "\n");
  4139. X    }
  4140. X#endif
  4141. X
  4142. X    /* set up uscsi_cmd */
  4143. X    ucmd.uscsi_cdb = (caddr_t) cdb;
  4144. X    ucmd.uscsi_bufaddr = (caddr_t) buf;
  4145. X    ucmd.uscsi_buflen = (int) size;
  4146. X    ucmd.uscsi_flags = USCSI_SILENT | USCSI_ISOLATE;
  4147. X    if (size != 0)
  4148. X        ucmd.uscsi_flags |= (rw == READ_OP) ? USCSI_READ : USCSI_WRITE;
  4149. X
  4150. X#ifdef AUTO_RSENSE
  4151. X    ucmd.uscsi_flags |= USCSI_RQENABLE;
  4152. X    ucmd.uscsi_rqbuf = (caddr_t) AD_RSENSE(&sense_data);
  4153. X    ucmd.uscsi_rqlen = SZ_RSENSE;
  4154. X#endif
  4155. X
  4156. X    /* Send the command down via the "pass-through" interface */
  4157. X    if (ioctl(fd, USCSICMD, &ucmd) < 0) {
  4158. X        if (opcode != OP_S_TEST)
  4159. X            perror("USCSICMD ioctl failed");
  4160. X        return(FALSE);
  4161. X    }
  4162. X
  4163. X    if (ucmd.uscsi_status != USCSI_STATUS_GOOD) {
  4164. X        if (opcode != OP_S_TEST && app_data.scsierr_msg) {
  4165. X            fprintf(stderr, "%s: %s %s:\n%s=0x%x %s=0x%x\n",
  4166. X                PROGNAME,
  4167. X                "SCSI command fault on",
  4168. X                app_data.device,
  4169. X                "Opcode",
  4170. X                opcode,
  4171. X                "Status",
  4172. X                ucmd.uscsi_status);
  4173. X        }
  4174. X
  4175. X#ifdef AUTO_RSENSE
  4176. X        if (ucmd.rqstatus == USCSI_STATUS_GOOD &&
  4177. X            opcode != OP_S_TEST && app_data.scsierr_msg) {
  4178. X            fprintf(stderr, " Key=0x%x Code=0x%x Qual=0x%x\n",
  4179. X                sense_data.key,
  4180. X                sense_data.code,
  4181. X                sense_data.qual);
  4182. X        }
  4183. X#else    /* !AUTO_RSENSE */
  4184. X        /* Send Request Sense command */
  4185. X        cdb[0] = OP_S_RSENSE;
  4186. X        cdb[1] = 0;
  4187. X        cdb[2] = 0;
  4188. X        cdb[3] = 0;
  4189. X        cdb[4] = (byte_t) SZ_RSENSE;
  4190. X        cdb[5] = 0;
  4191. X
  4192. X        ucmd.uscsi_cdblen = 6;
  4193. X        ucmd.uscsi_cdb = (caddr_t) cdb;
  4194. X        ucmd.uscsi_bufaddr = (caddr_t) AD_RSENSE(&sense_data);
  4195. X        ucmd.uscsi_buflen = (int) SZ_RSENSE;
  4196. X        ucmd.uscsi_flags = USCSI_READ;
  4197. X
  4198. X        if (ioctl(fd, USCSICMD, &ucmd) < 0 || sense_data.valid == 0) {
  4199. X            if (opcode != OP_S_TEST && app_data.scsierr_msg)
  4200. X                fprintf(stderr, "\n");
  4201. X#ifdef DEBUG
  4202. X            perror("USCSICMD ioctl (Request Sense) failed");
  4203. X#endif
  4204. X        }
  4205. X        else if (opcode != OP_S_TEST && app_data.scsierr_msg) {
  4206. X            fprintf(stderr, " Key=0x%x Code=0x%x Qual=0x%x\n",
  4207. X                sense_data.key,
  4208. X                sense_data.code,
  4209. X                sense_data.qual);
  4210. X        }
  4211. X#endif    /* AUTO_RSENSE */
  4212. X
  4213. X        return(FALSE);
  4214. X    }
  4215. X
  4216. X    return(TRUE);
  4217. X}
  4218. X
  4219. X
  4220. X/*
  4221. X * pthru_open
  4222. X *    Open SCSI passthrough device
  4223. X *
  4224. X * Args:
  4225. X *    path - device path name string
  4226. X *
  4227. X * Return:
  4228. X *    TRUE - open successful
  4229. X *    FALSE - open failed
  4230. X */
  4231. Xbool_t
  4232. Xpthru_open(char *path)
  4233. X{
  4234. X    struct stat    stbuf;
  4235. X    char        errstr[STR_BUF_SZ];
  4236. X
  4237. X    /* Check for validity of device node */
  4238. X    if (stat(path, &stbuf) < 0) {
  4239. X        sprintf(errstr, app_data.str_staterr, path);
  4240. X        cd_fatal_popup(app_data.str_fatal, errstr);
  4241. X        return(FALSE);
  4242. X    }
  4243. X    if ((stbuf.st_mode & S_IFMT) != S_IFCHR) {
  4244. X        sprintf(errstr, app_data.str_noderr, path);
  4245. X        cd_fatal_popup(app_data.str_fatal, errstr);
  4246. X        return(FALSE);
  4247. X    }
  4248. X
  4249. X    /* Check for another copy of xmcd running on the same
  4250. X     * CD-ROM device.
  4251. X     */
  4252. X    if (!cd_devlock(path))
  4253. X        return(FALSE);
  4254. X
  4255. X    if ((fd = open(path, O_RDONLY)) < 0)
  4256. X        return(FALSE);
  4257. X
  4258. X    return(TRUE);
  4259. X}
  4260. X
  4261. X
  4262. X/*
  4263. X * pthru_close
  4264. X *    Close SCSI passthrough device
  4265. X *
  4266. X * Args:
  4267. X *    Nothing.
  4268. X *
  4269. X * Return:
  4270. X *    Nothing.
  4271. X */
  4272. Xvoid
  4273. Xpthru_close(void)
  4274. X{
  4275. X    if (fd >= 0) {
  4276. X        close(fd);
  4277. X        fd = -1;
  4278. X    }
  4279. X}
  4280. X
  4281. X
  4282. X/*
  4283. X * pthru_vers
  4284. X *    Return OS Interface Module version string
  4285. X *
  4286. X * Args:
  4287. X *    Nothing.
  4288. X *
  4289. X * Return:
  4290. X *    Module version text string.
  4291. X */
  4292. Xchar *
  4293. Xpthru_vers(void)
  4294. X{
  4295. X    static char    vers[STR_BUF_SZ];
  4296. X
  4297. X    sprintf(vers, "OS Interface module v%s (for SunOS %s)\n", OSI_VERS,
  4298. X#ifdef SVR4
  4299. X        "5.x"
  4300. X#else
  4301. X        "4.x"
  4302. X#endif
  4303. X    );
  4304. X
  4305. X    return(vers);
  4306. X}
  4307. X
  4308. X#else    /* !sun || SIMULATED_CDROM */
  4309. X
  4310. X#ifndef LINT
  4311. Xbool_t            lib_sun = FALSE;
  4312. X#endif
  4313. X
  4314. X#endif    /* sun SIMULATED_CDROM */
  4315. X
  4316. END_OF_FILE
  4317. if test 7347 -ne `wc -c <'lib_sun.c'`; then
  4318.     echo shar: \"'lib_sun.c'\" unpacked with wrong size!
  4319. fi
  4320. # end of 'lib_sun.c'
  4321. fi
  4322. echo shar: End of archive 9 \(of 13\).
  4323. cp /dev/null ark9isdone
  4324. MISSING=""
  4325. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 ; do
  4326.     if test ! -f ark${I}isdone ; then
  4327.     MISSING="${MISSING} ${I}"
  4328.     fi
  4329. done
  4330. if test "${MISSING}" = "" ; then
  4331.     echo You have unpacked all 13 archives.
  4332.     echo "Now read the README and INSTALL files for further instructions."
  4333.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  4334. else
  4335.     echo You still need to unpack the following archives:
  4336.     echo "        " ${MISSING}
  4337. fi
  4338. ##  End of shell archive.
  4339. exit 0
  4340. -- 
  4341.     ///  Ti Kan                vorsprung durch technik
  4342.    ///   AMB Research Laboratories, Sunnyvale, CA. USA
  4343.   ///    ti@amb.org
  4344.  //////  ...!{decwrl,synopsys,tandem,tsoft,ultra}!sgiblab!bazooka!ti
  4345. ///      ...!uunet!bazooka!ti
  4346.  
  4347.  
  4348.  
  4349. exit 0 # Just in case...
  4350. -- 
  4351.   // chris@Sterling.COM           | Send comp.sources.x submissions to:
  4352. \X/  Amiga: The only way to fly!  |    sources-x@sterling.com
  4353.        "It's intuitively obvious to the most casual observer..."
  4354.  GCS d++(--) -p+ c++ !l u++ e+ m+(-) s++/++ n h--- f+ g+++ w+ t++ r+ y+
  4355.