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

  1. Newsgroups: comp.sources.x
  2. From: ti@bazooka.amb.org (Ti Kan)
  3. Subject: v21i067:  xmcd - X11/Motif CD audio player, Part05/13
  4. Message-ID: <1993Dec19.193858.24134@sparky.sterling.com>
  5. X-Md4-Signature: f07164860bf24267ecbffa5fc9896db8
  6. Sender: chris@sparky.sterling.com (Chris Olson)
  7. Organization: Sterling Software
  8. Date: Sun, 19 Dec 1993 19:38:58 GMT
  9. Approved: chris@sterling.com
  10.  
  11. Submitted-by: ti@bazooka.amb.org (Ti Kan)
  12. Posting-number: Volume 21, Issue 67
  13. Archive-name: xmcd/part05
  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 5 (of 13)."
  23. # Contents:  cdfunc.c
  24. # Wrapped by ti@bazooka on Mon Nov  8 10:35:20 1993
  25. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  26. if test -f 'cdfunc.c' -a "${1}" != "-c" ; then 
  27.   echo shar: Will not clobber existing file \"'cdfunc.c'\"
  28. else
  29. echo shar: Extracting \"'cdfunc.c'\" \(55680 characters\)
  30. sed "s/^X//" >'cdfunc.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 *_cdfunc_c_ident_ = "@(#)cdfunc.c    1.150 93/09/28";
  54. X#endif
  55. X
  56. X#include <X11/keysym.h>
  57. X#include <Xm/Xm.h>
  58. X#include <Xm/MessageB.h>
  59. X#include "xmcd.h"
  60. X#include "patchlevel.h"
  61. X#include "widget.h"
  62. X#include "dbprog.h"
  63. X#include "hotkey.h"
  64. X#include "help.h"
  65. X#include "util.h"
  66. X#include "cdlib.h"
  67. X#include "cdfunc.h"
  68. X
  69. X
  70. X/* Callback info structure */
  71. Xtypedef struct {
  72. X    Widget        widget;
  73. X    String        type;
  74. X    XtCallbackProc    func;
  75. X    XtPointer    data;
  76. X} cbinfo_t;
  77. X
  78. X
  79. Xextern widgets_t    widgets;
  80. Xextern pixmaps_t    pixmaps;
  81. Xextern AppData        app_data;
  82. Xextern bool_t        exit_flag;
  83. X
  84. Xuid_t            ouid;            /* Original uid of user */
  85. Xchar            **dbdirs = NULL;    /* Database directories */
  86. XSTATIC char        keystr[3],        /* Keypad number string */
  87. X            lockfile[40];        /* Lock file path */
  88. XSTATIC int        tm_blinkid = -1,    /* Time dpy blink timer ID */
  89. X            ab_blinkid = -1;    /* A->B dpy blink timer ID */
  90. XSTATIC bool_t        devbusy = FALSE,    /* Device busy flag */
  91. X            searching = FALSE,    /* Running REW or FF */
  92. X            btnlbl_state = FALSE,    /* Button label state */
  93. X            lock_state = FALSE,    /* Caddy lock state */
  94. X            repeat_state = FALSE,    /* Repeat mode state */
  95. X            shuffle_state = FALSE;    /* Shuffle mode state */
  96. X
  97. X
  98. X/*
  99. X * curtrk_pos
  100. X *    Return the trkinfo table offset location of the current playing
  101. X *    CD track.
  102. X *
  103. X * Args:
  104. X *    s - Pointer to the curstat_t structure.
  105. X *
  106. X * Return:
  107. X *    Integer offset into the trkinfo table, or -1 if not currently
  108. X *    playing audio.
  109. X */
  110. Xint
  111. Xcurtrk_pos(curstat_t *s)
  112. X{
  113. X    int    i;
  114. X
  115. X    i = (int) s->cur_trk - 1;
  116. X    if (s->trkinfo[i].trkno == s->cur_trk)
  117. X        return(i);
  118. X
  119. X    for (i = 0; i < MAXTRACK; i++) {
  120. X        if (s->trkinfo[i].trkno == s->cur_trk)
  121. X            return(i);
  122. X    }
  123. X    return(-1);
  124. X}
  125. X
  126. X
  127. X/*
  128. X * curprog_pos
  129. X *    Return an integer representing the position of the current
  130. X *    program or shuffle mode playing order (0 = first, 1 = second, ...).
  131. X *    This routine should be used only when in program or shuffle play
  132. X *    mode.
  133. X *
  134. X * Arg:
  135. X *    s - Pointer to the curstat_t structure.
  136. X *
  137. X * Return:
  138. X *    An integer representing the position of the current program
  139. X *    or shuffle mode playing order, or -1 if not in the appropriate mode.
  140. X */
  141. Xint
  142. Xcurprog_pos(curstat_t *s)
  143. X{
  144. X    return((int) s->playorder[s->prog_cnt]);
  145. X}
  146. X
  147. X
  148. X/*
  149. X * curtrk_type
  150. X *    Return the track type of the currently playing track.
  151. X *
  152. X * Args:
  153. X *    s - Pointer to the curstat_t structure.
  154. X *
  155. X * Return:
  156. X *    TYP_AUDIO or TYP_DATA.
  157. X */
  158. Xbyte_t
  159. Xcurtrk_type(curstat_t *s)
  160. X{
  161. X    sword32_t    i;
  162. X
  163. X    if ((i = curtrk_pos(s)) >= 0)
  164. X        return(s->trkinfo[i].type);
  165. X
  166. X    return(TYP_AUDIO);
  167. X}
  168. X
  169. X
  170. X/*
  171. X * track_rtime
  172. X *    Return the remaining time of the current playing track in seconds.
  173. X *
  174. X * Args:
  175. X *    s - Pointer to the curstat_t structure.
  176. X *
  177. X * Return:
  178. X *    The track remaining time in seconds.
  179. X */
  180. XSTATIC sword32_t
  181. Xtrack_rtime(curstat_t *s)
  182. X{
  183. X    sword32_t    i,
  184. X            secs,
  185. X            tot_sec,
  186. X            cur_sec;
  187. X
  188. X    if ((i = curtrk_pos(s)) < 0)
  189. X        return(0);
  190. X
  191. X    tot_sec = (s->trkinfo[i+1].min * 60 + s->trkinfo[i+1].sec) -
  192. X          (s->trkinfo[i].min * 60 + s->trkinfo[i].sec);
  193. X    cur_sec = s->cur_trk_min * 60 + s->cur_trk_sec;
  194. X    secs = tot_sec - cur_sec;
  195. X
  196. X    return((secs >= 0) ? secs : 0);
  197. X}
  198. X
  199. X
  200. X/*
  201. X * disc_rtime_norm
  202. X *    Return the remaining time of the disc in seconds.  This is
  203. X *    used during normal playback.
  204. X *
  205. X * Args:
  206. X *    s - Pointer to the curstat_t structure.
  207. X *
  208. X * Return:
  209. X *    The disc remaining time in seconds.
  210. X */
  211. XSTATIC sword32_t
  212. Xdisc_rtime_norm(curstat_t *s)
  213. X{
  214. X    sword32_t    secs;
  215. X
  216. X    secs = (s->tot_min * 60 + s->tot_sec) -
  217. X        (s->cur_tot_min * 60 + s->cur_tot_sec);
  218. X
  219. X    return((secs >= 0) ? secs : 0);
  220. X}
  221. X
  222. X
  223. X/*
  224. X * disc_rtime_prog
  225. X *    Return the remaining time of the disc in seconds.  This is
  226. X *    used during shuffle or program mode.
  227. X *
  228. X * Args:
  229. X *    s - Pointer to the curstat_t structure.
  230. X *
  231. X * Return:
  232. X *    The disc remaining time in seconds.
  233. X */
  234. XSTATIC sword32_t
  235. Xdisc_rtime_prog(curstat_t *s)
  236. X{
  237. X    sword32_t    i,
  238. X            secs = 0;
  239. X
  240. X    /* Find the time of all unplayed tracks */
  241. X    for (i = s->prog_cnt; i < (int) s->prog_tot; i++) {
  242. X        secs += ((s->trkinfo[s->playorder[i]+1].min * 60 +
  243. X             s->trkinfo[s->playorder[i]+1].sec) -
  244. X                 (s->trkinfo[s->playorder[i]].min * 60 +
  245. X             s->trkinfo[s->playorder[i]].sec));
  246. X    }
  247. X
  248. X    /* FInd the remaining time of the current track */
  249. X    for (i = 0; i < MAXTRACK; i++) {
  250. X        if (s->trkinfo[i].trkno == LEAD_OUT_TRACK)
  251. X            break;
  252. X
  253. X        if (s->trkinfo[i].trkno == s->cur_trk) {
  254. X            secs += ((s->trkinfo[i+1].min * 60 +
  255. X                  s->trkinfo[i+1].sec) -
  256. X                 (s->cur_tot_min * 60 + s->cur_tot_sec));
  257. X
  258. X            break;
  259. X        }
  260. X    }
  261. X
  262. X    return((secs >= 0) ? secs : 0);
  263. X}
  264. X
  265. X
  266. X/*
  267. X * devspec_init
  268. X *    Read the specified device-specific configuration file and
  269. X *    initialize parameters.
  270. X *
  271. X * Args:
  272. X *    path - Path name to the file to read.
  273. X *    priv - Whether the privileged keywords are to be recognized.
  274. X *
  275. X * Return:
  276. X *    Nothing.
  277. X */
  278. XSTATIC void
  279. Xdevspec_init(char *path, bool_t priv)
  280. X{
  281. X    FILE    *fp;
  282. X    char    buf[STR_BUF_SZ],
  283. X        parm[12];
  284. X
  285. X    if ((fp = fopen(path, "r")) != NULL) {
  286. X        /* Read in device-specific parameters */
  287. X        while (fgets(buf, sizeof(buf), fp) != NULL) {
  288. X            /* Skip comments */
  289. X            if (buf[0] == '#' || buf[0] == '!' || buf[0] == '\n')
  290. X                continue;
  291. X
  292. X            /* These are privileged parameters and users
  293. X             * cannot overide them in their .xmcdcfg file.
  294. X             */
  295. X            if (priv) {
  296. X                if (sscanf(buf, "logicalDriveNumber: %s\n",
  297. X                       parm) > 0) {
  298. X                    app_data.devnum = atoi(parm);
  299. X                    continue;
  300. X                }
  301. X                if (sscanf(buf, "driveVendorCode: %s\n",
  302. X                       parm) > 0) {
  303. X                    app_data.vendor_code = atoi(parm);
  304. X                    continue;
  305. X                }
  306. X                if (sscanf(buf, "playAudio12Support: %s\n",
  307. X                       parm) > 0) {
  308. X                    app_data.play12_supp = stob(parm);
  309. X                    continue;
  310. X                }
  311. X                if (sscanf(buf, "playAudioMSFSupport: %s\n",
  312. X                       parm) > 0) {
  313. X                    app_data.playmsf_supp = stob(parm);
  314. X                    continue;
  315. X                }
  316. X                if (sscanf(buf, "playAudio10Support: %s\n",
  317. X                       parm) > 0) {
  318. X                    app_data.play10_supp = stob(parm);
  319. X                    continue;
  320. X                }
  321. X                if (sscanf(buf, "playAudioTISupport: %s\n",
  322. X                       parm) > 0) {
  323. X                    app_data.playti_supp = stob(parm);
  324. X                    continue;
  325. X                }
  326. X                if (sscanf(buf, "loadSupport: %s\n",
  327. X                       parm) > 0) {
  328. X                    app_data.load_supp = stob(parm);
  329. X                    continue;
  330. X                }
  331. X                if (sscanf(buf, "ejectSupport: %s\n",
  332. X                       parm) > 0) {
  333. X                    app_data.eject_supp = stob(parm);
  334. X                    continue;
  335. X                }
  336. X                if (sscanf(buf, "volumeControlSupport: %s\n",
  337. X                       parm) > 0) {
  338. X                    app_data.mselvol_supp = stob(parm);
  339. X                    continue;
  340. X                }
  341. X                if (sscanf(buf, "volumeControlSetDBD: %s\n",
  342. X                       parm) > 0) {
  343. X                    app_data.mselvol_dbd = stob(parm);
  344. X                    continue;
  345. X                }
  346. X                if (sscanf(buf, "scsiAudioVolumeBase: %s\n",
  347. X                       parm) > 0) {
  348. X                    app_data.base_scsivol = atoi(parm);
  349. X                    continue;
  350. X                }
  351. X                if (sscanf(buf, "pauseResumeSupport: %s\n",
  352. X                       parm) > 0) {
  353. X                    app_data.pause_supp = stob(parm);
  354. X                    continue;
  355. X                }
  356. X                if (sscanf(buf, "caddyLockSupport: %s\n",
  357. X                       parm) > 0) {
  358. X                    app_data.caddylock_supp = stob(parm);
  359. X                    continue;
  360. X                }
  361. X                if (sscanf(buf, "minimumPlayBlocks: %s\n",
  362. X                       parm) > 0) {
  363. X                    app_data.min_playblks = atoi(parm);
  364. X                    continue;
  365. X                }
  366. X            }
  367. X
  368. X            /* These are general parameters that can be
  369. X             * changed by the user.
  370. X             */
  371. X            if (sscanf(buf, "volumeControlTaper: %s\n",
  372. X                   parm) > 0) {
  373. X                app_data.vol_taper = atoi(parm);
  374. X                continue;
  375. X            }
  376. X            if (sscanf(buf, "spinDownOnLoad: %s\n",
  377. X                   parm) > 0) {
  378. X                app_data.load_spindown = stob(parm);
  379. X                continue;
  380. X            }
  381. X            if (sscanf(buf, "ejectOnExit: %s\n",
  382. X                   parm) > 0) {
  383. X                app_data.exit_eject = stob(parm);
  384. X                continue;
  385. X            }
  386. X            if (sscanf(buf, "stopOnExit: %s\n",
  387. X                   parm) > 0) {
  388. X                app_data.exit_stop = stob(parm);
  389. X                continue;
  390. X            }
  391. X        }
  392. X
  393. X        fclose(fp);
  394. X    }
  395. X
  396. X    if (priv) {
  397. X        /* If the drive does not support software eject, then we
  398. X         * can't lock the caddy.
  399. X         */
  400. X        if (!app_data.eject_supp)
  401. X            app_data.caddylock_supp = FALSE;
  402. X
  403. X        /* If the drive does not support locking the caddy, don't
  404. X         * attempt to lock it.
  405. X         */
  406. X        if (!app_data.caddylock_supp)
  407. X            app_data.caddy_lock = FALSE;
  408. X    }
  409. X}
  410. X
  411. X
  412. X/*
  413. X * dpy_track
  414. X *    Update the track number display region of the main window.
  415. X *
  416. X * Args:
  417. X *    s - Pointer to the curstat_t structure.
  418. X *
  419. X * Return:
  420. X *    Nothing
  421. X */
  422. Xvoid
  423. Xdpy_track(curstat_t *s)
  424. X{
  425. X    XmString    xs;
  426. X    char        str[4];
  427. X    static char    prev[4] = { '\0' };
  428. X    static int    sav_trk = -1;
  429. X
  430. X
  431. X    if (s->cur_trk != sav_trk)
  432. X        /* Update database/program window current track display */
  433. X        dbprog_curtrkupd(s);
  434. X
  435. X    sav_trk = s->cur_trk;
  436. X
  437. X    if (s->cur_trk <= 0 || s->mode == M_NODISC)
  438. X        strcpy(str, "-");
  439. X    else if (s->time_dpy == T_REMAIN_DISC) {
  440. X        if (s->shuffle || s->program)
  441. X            sprintf(str, "-%d", s->prog_tot - s->prog_cnt);
  442. X        else
  443. X            sprintf(str, "-%d", s->tot_trks - curtrk_pos(s) - 1);
  444. X    }
  445. X    else
  446. X        sprintf(str, "%d", s->cur_trk);
  447. X
  448. X    if (strcmp(str, prev) == 0)
  449. X        /* No change, just return */
  450. X        return;
  451. X
  452. X    xs = XmStringCreateSimple(str);
  453. X
  454. X    XtVaSetValues(
  455. X        widgets.main.track_ind,
  456. X        XmNlabelString,
  457. X        xs,
  458. X        NULL
  459. X    );
  460. X
  461. X    XmStringFree(xs);
  462. X
  463. X    strcpy(prev, str);
  464. X}
  465. X
  466. X
  467. X/*
  468. X * dpy_index
  469. X *    Update the index number display region of the main window.
  470. X *
  471. X * Args:
  472. X *    s - Pointer to the curstat_t structure.
  473. X *
  474. X * Return:
  475. X *    Nothing
  476. X */
  477. Xvoid
  478. Xdpy_index(curstat_t *s)
  479. X{
  480. X    XmString    xs;
  481. X    char        str[4];
  482. X    static char    prev[4] = { '\0' };
  483. X
  484. X    if (s->cur_idx <= 0 || s->mode == M_NODISC || s->mode == M_STOP)
  485. X        strcpy(str, "-");
  486. X    else
  487. X        sprintf(str, "%d", s->cur_idx);
  488. X
  489. X    if (strcmp(str, prev) == 0)
  490. X        /* No change, just return */
  491. X        return;
  492. X
  493. X    xs = XmStringCreateSimple(str);
  494. X
  495. X    XtVaSetValues(
  496. X        widgets.main.index_ind,
  497. X        XmNlabelString,
  498. X        xs,
  499. X        NULL
  500. X    );
  501. X
  502. X    XmStringFree(xs);
  503. X
  504. X    strcpy(prev, str);
  505. X}
  506. X
  507. X
  508. X/*
  509. X * dpy_time
  510. X *    Update the time display region of the main window.
  511. X *
  512. X * Args:
  513. X *    s - Pointer to the curstat_t structure.
  514. X *    blank - Whether the display region should be blanked.
  515. X *
  516. X * Return:
  517. X *    Nothing
  518. X */
  519. Xvoid
  520. Xdpy_time(curstat_t *s, bool_t blank)
  521. X{
  522. X    sword32_t    time_sec;
  523. X    XmString    xs;
  524. X    char        str[12];
  525. X    static char    prev[12];
  526. X
  527. X    if (blank)
  528. X        str[0] = '\0';
  529. X    else if (s->mode == M_NODISC) {
  530. X        if (devbusy)
  531. X            strcpy(str, app_data.str_busy);
  532. X        else
  533. X            strcpy(str, app_data.str_nodisc);
  534. X    }
  535. X    else if (s->mode == M_STOP)
  536. X        strcpy(str, " --:--");
  537. X    else if (curtrk_type(s) == TYP_DATA)
  538. X        strcpy(str, app_data.str_data);
  539. X    else {
  540. X        switch (s->time_dpy) {
  541. X        case T_ELAPSED:
  542. X            sprintf(str, "%s%02u:%02u",
  543. X                (s->cur_idx == 0) ? "-" : "+",
  544. X                s->cur_trk_min,
  545. X                s->cur_trk_sec);
  546. X            break;
  547. X
  548. X        case T_REMAIN_TRACK:
  549. X            time_sec = track_rtime(s);
  550. X
  551. X            sprintf(str, "-%02u:%02u",
  552. X                time_sec / 60, time_sec % 60);
  553. X            break;
  554. X
  555. X        case T_REMAIN_DISC:
  556. X            if (s->shuffle || s->program) {
  557. X                if (s->cur_idx == 0) {
  558. X                    strcpy(str, " --:--");
  559. X                    break;
  560. X                }
  561. X                else
  562. X                    time_sec = disc_rtime_prog(s);
  563. X            }
  564. X            else
  565. X                time_sec = disc_rtime_norm(s);
  566. X
  567. X            sprintf(str, "-%02u:%02u",
  568. X                time_sec / 60, time_sec % 60);
  569. X            break;
  570. X
  571. X        default:
  572. X            strcpy(str, "??:??");
  573. X            break;
  574. X        }
  575. X    }
  576. X
  577. X    if (strcmp(str, prev) == 0)
  578. X        /* No change: just return */
  579. X        return;
  580. X
  581. X    xs = XmStringCreateSimple(str);
  582. X
  583. X    XtVaSetValues(
  584. X        widgets.main.time_ind,
  585. X        XmNlabelString,
  586. X        xs,
  587. X        NULL
  588. X    );
  589. X
  590. X    XmStringFree(xs);
  591. X
  592. X    strcpy(prev, str);
  593. X}
  594. X
  595. X
  596. X/*
  597. X * dpy_dbmode
  598. X *    Update the cddb indicator of the main window.
  599. X *
  600. X * Args:
  601. X *    s - Pointer to the curstat_t structure.
  602. X *
  603. X * Return:
  604. X *    Nothing
  605. X */
  606. Xvoid
  607. Xdpy_dbmode(curstat_t *s)
  608. X{
  609. X    String        str;
  610. X    XmString    xs;
  611. X    static bool_t    first = TRUE,
  612. X            prev = FALSE;
  613. X
  614. X    if (!first && prev == s->cddb)
  615. X        /* No change: just return */
  616. X        return;
  617. X
  618. X    first = FALSE;
  619. X
  620. X    if (s->cddb)
  621. X        str = app_data.str_dbmode;
  622. X    else
  623. X        str = "";
  624. X
  625. X    xs = XmStringCreateSimple(str);
  626. X
  627. X    XtVaSetValues(
  628. X        widgets.main.dbmode_ind,
  629. X        XmNlabelString,
  630. X        xs,
  631. X        NULL
  632. X    );
  633. X
  634. X    XmStringFree(xs);
  635. X
  636. X    prev = s->cddb;
  637. X}
  638. X
  639. X
  640. X/*
  641. X * dpy_progmode
  642. X *    Update the prog indicator of the main window.
  643. X *
  644. X * Args:
  645. X *    s - Pointer to the curstat_t structure.
  646. X *
  647. X * Return:
  648. X *    Nothing
  649. X */
  650. Xvoid
  651. Xdpy_progmode(curstat_t *s)
  652. X{
  653. X    String        str;
  654. X    XmString    xs;
  655. X    static bool_t    first = TRUE,
  656. X            prev = FALSE;
  657. X
  658. X    if (!first && prev == s->program)
  659. X        /* No change: just return */
  660. X        return;
  661. X
  662. X    first = FALSE;
  663. X
  664. X    if (s->program)
  665. X        str = app_data.str_progmode;
  666. X    else
  667. X        str = "";
  668. X
  669. X    xs = XmStringCreateSimple(str);
  670. X
  671. X    XtVaSetValues(
  672. X        widgets.main.progmode_ind,
  673. X        XmNlabelString,
  674. X        xs,
  675. X        NULL
  676. X    );
  677. X
  678. X    XmStringFree(xs);
  679. X
  680. X    prev = s->program;
  681. X}
  682. X
  683. X
  684. X/*
  685. X * dpy_timemode
  686. X *    Update the time mode indicator of the main window.
  687. X *
  688. X * Args:
  689. X *    s - Pointer to the curstat_t structure.
  690. X *
  691. X * Return:
  692. X *    Nothing
  693. X */
  694. Xvoid
  695. Xdpy_timemode(curstat_t *s)
  696. X{
  697. X    String        str;
  698. X    XmString    xs;
  699. X    static byte_t    prev = 0xff;
  700. X
  701. X    if (prev == s->time_dpy)
  702. X        /* No change: just return */
  703. X        return;
  704. X
  705. X    switch (s->time_dpy) {
  706. X    case T_ELAPSED:
  707. X        str = app_data.str_elapse;
  708. X        break;
  709. X
  710. X    case T_REMAIN_TRACK:
  711. X        str = app_data.str_remaintrk;
  712. X        break;
  713. X
  714. X    case T_REMAIN_DISC:
  715. X        str = app_data.str_remaindisc;
  716. X        break;
  717. X    }
  718. X
  719. X    xs = XmStringCreateSimple(str);
  720. X
  721. X    XtVaSetValues(
  722. X        widgets.main.timemode_ind,
  723. X        XmNlabelString,
  724. X        xs,
  725. X        NULL
  726. X    );
  727. X
  728. X    XmStringFree(xs);
  729. X
  730. X    prev = s->time_dpy;
  731. X}
  732. X
  733. X
  734. X/*
  735. X * dpy_playmode
  736. X *    Update the play mode indicator of the main window.
  737. X *
  738. X * Args:
  739. X *    s - Pointer to the curstat_t structure.
  740. X *
  741. X * Return:
  742. X *    Nothing
  743. X */
  744. Xvoid
  745. Xdpy_playmode(curstat_t *s, bool_t blank)
  746. X{
  747. X    char        *str;
  748. X    XmString    xs;
  749. X    static char    prev[10];
  750. X
  751. X    if (blank)
  752. X        str = "";
  753. X    else {
  754. X        switch (s->mode) {
  755. X        case M_PLAY:
  756. X            str = app_data.str_play;
  757. X            break;
  758. X        case M_PAUSE:
  759. X            str = app_data.str_pause;
  760. X            break;
  761. X        case M_STOP:
  762. X            str = app_data.str_ready;
  763. X            break;
  764. X        case M_A:
  765. X            str = "a->?";
  766. X            break;
  767. X        case M_AB:
  768. X            str = "a->b";
  769. X            break;
  770. X        case M_SAMPLE:
  771. X            str = app_data.str_sample;
  772. X            break;
  773. X        default:
  774. X            str = "";
  775. X            break;
  776. X        }
  777. X    }
  778. X
  779. X    if (strcmp(prev, str) == 0)
  780. X        /* No change: just return */
  781. X        return;
  782. X
  783. X    xs = XmStringCreateSimple(str);
  784. X
  785. X    XtVaSetValues(
  786. X        widgets.main.playmode_ind,
  787. X        XmNlabelString,
  788. X        xs,
  789. X        NULL
  790. X    );
  791. X
  792. X    XmStringFree(xs);
  793. X
  794. X    strcpy(prev, str);
  795. X
  796. X    if (s->mode == M_A)
  797. X        cd_ab_blink(s, TRUE);
  798. X    else
  799. X        cd_ab_blink(s, FALSE);
  800. X}
  801. X
  802. X
  803. X/*
  804. X * dpy_all
  805. X *    Update all indicator of the main window.
  806. X *
  807. X * Args:
  808. X *    s - Pointer to the curstat_t structure.
  809. X *
  810. X * Return:
  811. X *    Nothing
  812. X */
  813. Xvoid
  814. Xdpy_all(curstat_t *s)
  815. X{
  816. X    dpy_dbmode(s);
  817. X    dpy_progmode(s);
  818. X    dpy_timemode(s);
  819. X    dpy_playmode(s, FALSE);
  820. X    dpy_track(s);
  821. X    dpy_index(s);
  822. X    dpy_time(s, FALSE);
  823. X}
  824. X
  825. X
  826. X/*
  827. X * dpy_time_blink
  828. X *    Make the time indicator region of the main window blink.
  829. X *    This is used when the disc is paused.
  830. X *
  831. X * Args:
  832. X *    s - Pointer to the curstat_t structure.
  833. X *
  834. X * Return:
  835. X *    Nothing
  836. X */
  837. XSTATIC void
  838. Xdpy_time_blink(curstat_t *s)
  839. X{
  840. X    static bool_t    bstate = TRUE;
  841. X
  842. X    if (bstate) {
  843. X        tm_blinkid = cd_timeout(
  844. X            app_data.blinkoff_interval,
  845. X            dpy_time_blink,
  846. X            (byte_t *) s
  847. X        );
  848. X        dpy_time(s, TRUE);
  849. X    }
  850. X    else {
  851. X        tm_blinkid = cd_timeout(
  852. X            app_data.blinkon_interval,
  853. X            dpy_time_blink,
  854. X            (byte_t *) s
  855. X        );
  856. X        dpy_time(s, FALSE);
  857. X    }
  858. X    bstate = !bstate;
  859. X}
  860. X
  861. X
  862. X/*
  863. X * dpy_ab_blink
  864. X *    Make the a->b indicator of the main window blink.
  865. X *
  866. X * Args:
  867. X *    s - Pointer to the curstat_t structure.
  868. X *
  869. X * Return:
  870. X *    Nothing
  871. X */
  872. XSTATIC void
  873. Xdpy_ab_blink(curstat_t *s)
  874. X{
  875. X    static bool_t    bstate = TRUE;
  876. X
  877. X    if (bstate) {
  878. X        ab_blinkid = cd_timeout(
  879. X            app_data.blinkoff_interval,
  880. X            dpy_ab_blink,
  881. X            (byte_t *) s
  882. X        );
  883. X        dpy_playmode(s, TRUE);
  884. X    }
  885. X    else {
  886. X        ab_blinkid = cd_timeout(
  887. X            app_data.blinkon_interval,
  888. X            dpy_ab_blink,
  889. X            (byte_t *) s
  890. X        );
  891. X        dpy_playmode(s, FALSE);
  892. X    }
  893. X    bstate = !bstate;
  894. X}
  895. X
  896. X
  897. X/*
  898. X * dpy_keypad_ind
  899. X *    Update the digital track number indicator on the keypad window.
  900. X *
  901. X * Args:
  902. X *    Nothing.
  903. X *
  904. X * Return:
  905. X *    Nothing.
  906. X */
  907. XSTATIC void
  908. Xdpy_keypad_ind(void)
  909. X{
  910. X    XmString    xs;
  911. X
  912. X    if (!XtIsManaged(widgets.keypad.form))
  913. X        return;
  914. X
  915. X    xs = XmStringCreateSimple((keystr[0] == '\0') ? "--" : keystr);
  916. X
  917. X    XtVaSetValues(
  918. X        widgets.keypad.keypad_ind,
  919. X        XmNlabelString,
  920. X        xs,
  921. X        NULL
  922. X    );
  923. X
  924. X    XmStringFree(xs);
  925. X}
  926. X
  927. X
  928. X/*
  929. X * reset_curstat
  930. X *    Reset the curstat_t structure to initial defaults.
  931. X *
  932. X * Args:
  933. X *    s - Pointer to the curstat_t structure.
  934. X *    clear_toc - Whether the trkinfo CD table-of-contents 
  935. X *        should be cleared.
  936. X *
  937. X * Return:
  938. X *    Nothing.
  939. X */
  940. Xvoid
  941. Xreset_curstat(curstat_t *s, bool_t clear_toc)
  942. X{
  943. X    sword32_t    i;
  944. X    static bool_t    first_time = TRUE;
  945. X
  946. X    s->cur_trk = s->cur_idx = -1;
  947. X    s->cur_tot_min = s->cur_tot_sec = s->cur_tot_frame = 0;
  948. X    s->cur_trk_min = s->cur_trk_sec = s->cur_trk_frame = 0;
  949. X    s->cur_tot_addr = s->cur_trk_addr = 0;
  950. X    s->sav_iaddr = 0;
  951. X    s->prog_tot = 0;
  952. X    s->prog_cnt = 0;
  953. X    s->program = FALSE;
  954. X
  955. X    if (clear_toc) {
  956. X        s->mode = M_NODISC;
  957. X        s->first_trk = s->last_trk = -1;
  958. X        s->tot_min = s->tot_sec = 0;
  959. X        s->tot_trks = 0;
  960. X        s->tot_addr = 0;
  961. X
  962. X        for (i = 0; i < MAXTRACK; i++) {
  963. X            s->trkinfo[i].trkno = -1;
  964. X            s->trkinfo[i].min = 0;
  965. X            s->trkinfo[i].sec = 0;
  966. X            s->trkinfo[i].frame = 0;
  967. X            s->trkinfo[i].addr = 0;
  968. X            s->playorder[i] = -1;
  969. X        }
  970. X    }
  971. X
  972. X    if (first_time) {
  973. X        /* These are to be initialized only once */
  974. X        first_time = FALSE;
  975. X
  976. X        s->time_dpy = T_ELAPSED;
  977. X        s->repeat = s->shuffle = FALSE;
  978. X        s->cddb = FALSE;
  979. X        s->level = 0;
  980. X        s->caddy_lock = FALSE;
  981. X        s->vendor[0] = '\0';
  982. X        s->prod[0] = '\0';
  983. X        s->revnum[0] = '\0';
  984. X    }
  985. X}
  986. X
  987. X
  988. X/*
  989. X * reset_shuffle
  990. X *    Recompute a new shuffle play sequence.  Updates the playorder
  991. X *    table in the curstat_t structure.
  992. X *
  993. X * Args:
  994. X *    s - Pointer to the curstat_t structure.
  995. X *
  996. X * Return:
  997. X *    Nothing.
  998. X */
  999. Xvoid
  1000. Xreset_shuffle(curstat_t *s)
  1001. X{
  1002. X    sword32_t    i,
  1003. X            j,
  1004. X            n;
  1005. X
  1006. X    srand((unsigned) time(NULL));
  1007. X    s->prog_cnt = 0;
  1008. X    s->prog_tot = s->tot_trks;
  1009. X
  1010. X    for (i = 0; i < MAXTRACK; i++) {
  1011. X        if (i >= (int) s->prog_tot) {
  1012. X            s->playorder[i] = -1;
  1013. X            continue;
  1014. X        }
  1015. X
  1016. X        do {
  1017. X            n = rand() % (int) s->prog_tot;
  1018. X            for (j = 0; j < i; j++) {
  1019. X                if (n == s->playorder[j])
  1020. X                    break;
  1021. X            }
  1022. X        } while (j < i);
  1023. X
  1024. X        s->playorder[i] = n;
  1025. X    }
  1026. X
  1027. X
  1028. X#ifdef DEBUG
  1029. X    fprintf(stderr, "Shuffle tracks: ");
  1030. X
  1031. X    for (i = 0; i < s->prog_tot; i++)
  1032. X        fprintf(stderr, "%d ", s->trkinfo[s->playorder[i]].trkno);
  1033. X
  1034. X    fprintf(stderr, "\n");
  1035. X#endif
  1036. X}
  1037. X
  1038. X
  1039. X/*
  1040. X * set_lock_btn
  1041. X *    Set the lock button state
  1042. X *
  1043. X * Args:
  1044. X *    state - TRUE=in, FALSE=out
  1045. X *
  1046. X * Return:
  1047. X *    Nothing.
  1048. X */
  1049. Xvoid
  1050. Xset_lock_btn(bool_t state)
  1051. X{
  1052. X    XmToggleButtonSetState(
  1053. X        widgets.main.lock_btn, (int) state, (int) False
  1054. X    );
  1055. X    lock_state = state;
  1056. X}
  1057. X
  1058. X
  1059. X/*
  1060. X * set_repeat_btn
  1061. X *    Set the repeat button state
  1062. X *
  1063. X * Args:
  1064. X *    state - TRUE=in, FALSE=out
  1065. X *
  1066. X * Return:
  1067. X *    Nothing.
  1068. X */
  1069. Xvoid
  1070. Xset_repeat_btn(bool_t state)
  1071. X{
  1072. X    XmToggleButtonSetState(
  1073. X        widgets.main.repeat_btn, (int) state, (int) False
  1074. X    );
  1075. X    repeat_state = state;
  1076. X}
  1077. X
  1078. X
  1079. X/*
  1080. X * set_shuffle_btn
  1081. X *    Set the shuffle button state
  1082. X *
  1083. X * Args:
  1084. X *    state - TRUE=in, FALSE=out
  1085. X *
  1086. X * Return:
  1087. X *    Nothing.
  1088. X */
  1089. Xvoid
  1090. Xset_shuffle_btn(bool_t state)
  1091. X{
  1092. X    XmToggleButtonSetState(
  1093. X        widgets.main.shuffle_btn, (int) state, (int) False
  1094. X    );
  1095. X    shuffle_state = state;
  1096. X}
  1097. X
  1098. X
  1099. X/*
  1100. X * set_vol_slider
  1101. X *    Set the volume control slider position
  1102. X *
  1103. X * Args:
  1104. X *    percent - The percentage setting.
  1105. X *
  1106. X * Return:
  1107. X *    Nothing.
  1108. X */
  1109. Xvoid
  1110. Xset_vol_slider(byte_t percent)
  1111. X{
  1112. X    XmScaleSetValue(widgets.main.level_scale, (int) percent);
  1113. X}
  1114. X
  1115. X
  1116. X/*
  1117. X * set_btn_lbltype
  1118. X *    Set the main window pushbuttons label type
  1119. X *
  1120. X * Args:
  1121. X *    type - BTN_PIXMAP or BTN_STRING.
  1122. X *
  1123. X * Return:
  1124. X *    Nothing.
  1125. X */
  1126. Xvoid
  1127. Xset_btn_lbltype(byte_t type)
  1128. X{
  1129. X    type = (type == BTN_STRING) ? XmSTRING : XmPIXMAP;
  1130. X
  1131. X    XtVaSetValues(widgets.main.btnlbl_btn,
  1132. X        XmNlabelType, type,
  1133. X        NULL
  1134. X    );
  1135. X    XtVaSetValues(widgets.main.lock_btn,
  1136. X        XmNlabelType, type,
  1137. X        NULL
  1138. X    );
  1139. X    XtVaSetValues(widgets.main.repeat_btn,
  1140. X        XmNlabelType, type,
  1141. X        NULL
  1142. X    );
  1143. X    XtVaSetValues(widgets.main.shuffle_btn,
  1144. X        XmNlabelType, type,
  1145. X        NULL
  1146. X    );
  1147. X    XtVaSetValues(widgets.main.eject_btn,
  1148. X        XmNlabelType, type,
  1149. X        NULL
  1150. X    );
  1151. X    XtVaSetValues(widgets.main.poweroff_btn,
  1152. X        XmNlabelType, type,
  1153. X        NULL
  1154. X    );
  1155. X    XtVaSetValues(widgets.main.dbprog_btn,
  1156. X        XmNlabelType, type,
  1157. X        NULL
  1158. X    );
  1159. X    XtVaSetValues(widgets.main.help_btn,
  1160. X        XmNlabelType, type,
  1161. X        NULL
  1162. X    );
  1163. X    XtVaSetValues(widgets.main.time_btn,
  1164. X        XmNlabelType, type,
  1165. X        NULL
  1166. X    );
  1167. X    XtVaSetValues(widgets.main.ab_btn,
  1168. X        XmNlabelType, type,
  1169. X        NULL
  1170. X    );
  1171. X    XtVaSetValues(widgets.main.sample_btn,
  1172. X        XmNlabelType, type,
  1173. X        NULL
  1174. X    );
  1175. X    XtVaSetValues(widgets.main.keypad_btn,
  1176. X        XmNlabelType, type,
  1177. X        NULL
  1178. X    );
  1179. X    XtVaSetValues(widgets.main.playpause_btn,
  1180. X        XmNlabelType, type,
  1181. X        NULL
  1182. X    );
  1183. X    XtVaSetValues(widgets.main.stop_btn,
  1184. X        XmNlabelType, type,
  1185. X        NULL
  1186. X    );
  1187. X    XtVaSetValues(widgets.main.prevtrk_btn,
  1188. X        XmNlabelType, type,
  1189. X        NULL
  1190. X    );
  1191. X    XtVaSetValues(widgets.main.nexttrk_btn,
  1192. X        XmNlabelType, type,
  1193. X        NULL
  1194. X    );
  1195. X    XtVaSetValues(widgets.main.previdx_btn,
  1196. X        XmNlabelType, type,
  1197. X        NULL
  1198. X    );
  1199. X    XtVaSetValues(widgets.main.nextidx_btn,
  1200. X        XmNlabelType, type,
  1201. X        NULL
  1202. X    );
  1203. X    XtVaSetValues(widgets.main.rew_btn,
  1204. X        XmNlabelType, type,
  1205. X        NULL
  1206. X    );
  1207. X    XtVaSetValues(widgets.main.ff_btn,
  1208. X        XmNlabelType, type,
  1209. X        NULL
  1210. X    );
  1211. X}
  1212. X
  1213. X
  1214. X/*
  1215. X * set_btn_color
  1216. X *    Set the label color of a pushbutton widget
  1217. X *
  1218. X * Args:
  1219. X *    w - The pushbutton widget.
  1220. X *    px - The label pixmap, if applicable.
  1221. X *    color - The pixel value of the desired color.
  1222. X *
  1223. X * Return:
  1224. X *    Nothing.
  1225. X */
  1226. XSTATIC void
  1227. Xset_btn_color(Widget w, Pixmap px, Pixel color)
  1228. X{
  1229. X    unsigned char    labtype;
  1230. X
  1231. X    XtVaGetValues(w, XmNlabelType, &labtype, NULL);
  1232. X
  1233. X    if (labtype == XmPIXMAP)
  1234. X        XtVaSetValues(w, XmNlabelPixmap, px, NULL);
  1235. X    else
  1236. X        XtVaSetValues(w, XmNforeground, color, NULL);
  1237. X}
  1238. X
  1239. X
  1240. X/*
  1241. X * set_scale_color
  1242. X *    Set the indicator color of a scale widget
  1243. X *
  1244. X * Args:
  1245. X *    w - The scale widget.
  1246. X *    color - The pixel value of the desired color.
  1247. X *
  1248. X * Return:
  1249. X *    Nothing.
  1250. X */
  1251. XSTATIC void
  1252. Xset_scale_color(Widget w, Pixel color)
  1253. X{
  1254. X    XtVaSetValues(w, XmNforeground, color, NULL);
  1255. X}
  1256. X
  1257. X
  1258. X/*
  1259. X * taper_vol
  1260. X *    Translate the volume level based on the configured taper
  1261. X *    characteristics.
  1262. X *
  1263. X * Args:
  1264. X *    v - The linear volume value.
  1265. X *
  1266. X * Return:
  1267. X *    The curved volume value.
  1268. X */
  1269. Xint
  1270. Xtaper_vol(int v)
  1271. X{
  1272. X    switch (app_data.vol_taper) {
  1273. X    case 1:
  1274. X        /* inverse-squared taper */
  1275. X        return(MAX_VOL - (sqr(MAX_VOL - v) / MAX_VOL));
  1276. X    case 2:
  1277. X        /* squared taper */
  1278. X        return(sqr(v) / MAX_VOL);
  1279. X    case 0:
  1280. X    default:
  1281. X        /* linear taper */
  1282. X        return(v);
  1283. X    }
  1284. X    /*NOTREACHED*/
  1285. X}
  1286. X
  1287. X
  1288. X/*
  1289. X * untaper_vol
  1290. X *    Translate the volume level based on the configured taper
  1291. X *    characteristics.
  1292. X *
  1293. X * Args:
  1294. X *    v - The curved volume value.
  1295. X *
  1296. X * Return:
  1297. X *    The linear volume value.
  1298. X */
  1299. Xint
  1300. Xuntaper_vol(int v)
  1301. X{
  1302. X    switch (app_data.vol_taper) {
  1303. X    case 1:
  1304. X        /* inverse-squared taper */
  1305. X        return(MAX_VOL - isqrt(sqr(MAX_VOL) - (MAX_VOL * v)));
  1306. X    case 2:
  1307. X        /* squared taper */
  1308. X        return(isqrt(v) * 10);
  1309. X    case 0:
  1310. X    default:
  1311. X        /* linear taper */
  1312. X        return(v);
  1313. X    }
  1314. X    /*NOTREACHED*/
  1315. X}
  1316. X
  1317. X
  1318. X/*
  1319. X * cd_timeout
  1320. X *    Alarm clock callback facility
  1321. X *
  1322. X * Args:
  1323. X *    msec - When msec milliseconds has elapsed, the callback
  1324. X *        occurs.
  1325. X *    handler - Pointer to the callback function.
  1326. X *    arg - An argument passed to the callback function.
  1327. X *
  1328. X * Return:
  1329. X *    An integer timeout ID.
  1330. X */
  1331. Xint
  1332. Xcd_timeout(word32_t msec, void (*handler)(), byte_t *arg)
  1333. X{
  1334. X    return((int)
  1335. X        XtAppAddTimeOut(
  1336. X            XtWidgetToApplicationContext(widgets.toplevel),
  1337. X            (unsigned long) msec,
  1338. X            (XtTimerCallbackProc) handler,
  1339. X            (XtPointer) arg
  1340. X        )
  1341. X    );
  1342. X}
  1343. X
  1344. X
  1345. X/*
  1346. X * cd_untimeout
  1347. X *    Cancel a pending alarm configured with cd_timeout.
  1348. X *
  1349. X * Args:
  1350. X *    id - The timeout ID
  1351. X *
  1352. X * Return:
  1353. X *    Nothing.
  1354. X */
  1355. Xvoid
  1356. Xcd_untimeout(int id)
  1357. X{
  1358. X    XtRemoveTimeOut((XtIntervalId) id);
  1359. X}
  1360. X
  1361. X
  1362. X/*
  1363. X * cd_beep
  1364. X *    Beep the workstation speaker.
  1365. X *
  1366. X * Args:
  1367. X *    Nothing.
  1368. X *
  1369. X * Return:
  1370. X *    Nothing.
  1371. X */
  1372. Xvoid
  1373. Xcd_beep(void)
  1374. X{
  1375. X    XBell(XtDisplay(widgets.toplevel), 50);
  1376. X}
  1377. X
  1378. X
  1379. X/*
  1380. X * cd_pause_blink
  1381. X *    Disable or enable the time indicator blinking.
  1382. X *
  1383. X * Args:
  1384. X *    s - Pointer to the curstat_t structure.
  1385. X *    enable - TRUE: start blink, FALSE: stop blink
  1386. X *
  1387. X * Return:
  1388. X *    Nothing.
  1389. X */
  1390. Xvoid
  1391. Xcd_pause_blink(curstat_t *s, bool_t enable)
  1392. X{
  1393. X    static bool_t    blinking = FALSE;
  1394. X
  1395. X    if (enable) {
  1396. X        if (!blinking) {
  1397. X            /* Start time display blink */
  1398. X            blinking = TRUE;
  1399. X            dpy_time_blink(s);
  1400. X        }
  1401. X    }
  1402. X    else if (blinking) {
  1403. X        /* Stop time display blink */
  1404. X        cd_untimeout(tm_blinkid);
  1405. X
  1406. X        tm_blinkid = -1;
  1407. X        blinking = FALSE;
  1408. X    }
  1409. X}
  1410. X
  1411. X
  1412. X/*
  1413. X * cd_ab_blink
  1414. X *    Disable or enable the a->b indicator blinking.
  1415. X *
  1416. X * Args:
  1417. X *    s - Pointer to the curstat_t structure.
  1418. X *    enable - TRUE: start blink, FALSE: stop blink
  1419. X *
  1420. X * Return:
  1421. X *    Nothing.
  1422. X */
  1423. Xvoid
  1424. Xcd_ab_blink(curstat_t *s, bool_t enable)
  1425. X{
  1426. X    static bool_t    blinking = FALSE;
  1427. X
  1428. X    if (enable) {
  1429. X        if (!blinking) {
  1430. X            /* Start A->B display blink */
  1431. X            blinking = TRUE;
  1432. X            dpy_ab_blink(s);
  1433. X        }
  1434. X    }
  1435. X    else if (blinking) {
  1436. X        /* Stop A->B display blink */
  1437. X        cd_untimeout(ab_blinkid);
  1438. X
  1439. X        ab_blinkid = -1;
  1440. X        blinking = FALSE;
  1441. X    }
  1442. X}
  1443. X
  1444. X
  1445. X/*
  1446. X * cd_info_popup
  1447. X *    Pop up the information message dialog box.
  1448. X *
  1449. X * Args:
  1450. X *    title - The title bar text string.
  1451. X *    msg - The information message text string.
  1452. X *
  1453. X * Return:
  1454. X *    Nothing.
  1455. X */
  1456. Xvoid
  1457. Xcd_info_popup(char *title, char *msg)
  1458. X{
  1459. X    XmString    xs;
  1460. X
  1461. X    /* Set the dialog box title */
  1462. X    xs = XmStringCreateSimple(title);
  1463. X    XtVaSetValues(widgets.dialog.info, XmNdialogTitle, xs, NULL);
  1464. X    XmStringFree(xs);
  1465. X
  1466. X    /* Set the dialog box message */
  1467. X    xs = XmStringCreateLtoR(msg, XmSTRING_DEFAULT_CHARSET);
  1468. X    XtVaSetValues(widgets.dialog.info, XmNmessageString, xs, NULL);
  1469. X    XmStringFree(xs);
  1470. X
  1471. X    /* Pop up the info dialog */
  1472. X    if (!XtIsManaged(widgets.dialog.info))
  1473. X        XtManageChild(widgets.dialog.info);
  1474. X}
  1475. X
  1476. X
  1477. X/*
  1478. X * cd_warning_popup
  1479. X *    Pop up the warning message dialog box.
  1480. X *
  1481. X * Args:
  1482. X *    title - The title bar text string.
  1483. X *    msg - The warning message text string.
  1484. X *
  1485. X * Return:
  1486. X *    Nothing.
  1487. X */
  1488. Xvoid
  1489. Xcd_warning_popup(char *title, char *msg)
  1490. X{
  1491. X    XmString    xs;
  1492. X
  1493. X    /* Set the dialog box title */
  1494. X    xs = XmStringCreateSimple(title);
  1495. X    XtVaSetValues(widgets.dialog.warning, XmNdialogTitle, xs, NULL);
  1496. X    XmStringFree(xs);
  1497. X
  1498. X    /* Set the dialog box message */
  1499. X    xs = XmStringCreateLtoR(msg, XmSTRING_DEFAULT_CHARSET);
  1500. X    XtVaSetValues(widgets.dialog.warning, XmNmessageString, xs, NULL);
  1501. X    XmStringFree(xs);
  1502. X
  1503. X    /* Pop up the warning dialog */
  1504. X    if (!XtIsManaged(widgets.dialog.warning))
  1505. X        XtManageChild(widgets.dialog.warning);
  1506. X}
  1507. X
  1508. X
  1509. X/*
  1510. X * cd_fatal_popup
  1511. X *    Pop up the fatal error message dialog box.
  1512. X *
  1513. X * Args:
  1514. X *    title - The title bar text string.
  1515. X *    msg - The fatal error message text string.
  1516. X *
  1517. X * Return:
  1518. X *    Nothing.
  1519. X */
  1520. Xvoid
  1521. Xcd_fatal_popup(char *title, char *msg)
  1522. X{
  1523. X    XmString    xs;
  1524. X
  1525. X    if (!XtIsManaged(widgets.dialog.fatal)) {
  1526. X        /* Set the dialog box title */
  1527. X        xs = XmStringCreateSimple(title);
  1528. X        XtVaSetValues(widgets.dialog.fatal, XmNdialogTitle, xs, NULL);
  1529. X        XmStringFree(xs);
  1530. X
  1531. X        /* Set the dialog box message */
  1532. X        xs = XmStringCreateLtoR(msg, XmSTRING_DEFAULT_CHARSET);
  1533. X        XtVaSetValues(widgets.dialog.fatal, XmNmessageString, xs, NULL);
  1534. X        XmStringFree(xs);
  1535. X
  1536. X        /* Pop up the error dialog */
  1537. X        XtManageChild(widgets.dialog.fatal);
  1538. X    }
  1539. X}
  1540. X
  1541. X
  1542. X/*
  1543. X * cd_confirm_popup
  1544. X *    Pop up the user-confirmation message dialog box.
  1545. X *
  1546. X * Args:
  1547. X *    title - The title bar text string.
  1548. X *    msg - The fatal error message text string.
  1549. X *    f_ok - Pointer to the callback function if user selects OK
  1550. X *    a_ok - Argument passed to f_ok
  1551. X *    f_cancel - Pointer to the callback function if user selects Cancel
  1552. X *    a_cancel - Argument passed to f_cancel
  1553. X *
  1554. X * Return:
  1555. X *    Nothing.
  1556. X */
  1557. Xvoid
  1558. Xcd_confirm_popup(
  1559. X    char *title,
  1560. X    char *msg,
  1561. X    XtCallbackProc f_ok,
  1562. X    XtPointer a_ok,
  1563. X    XtCallbackProc f_cancel,
  1564. X    XtPointer a_cancel
  1565. X)
  1566. X{
  1567. X    XmString    xs;
  1568. X    Widget        ok_btn,
  1569. X            cancel_btn;
  1570. X    static cbinfo_t    ok_cbinfo,
  1571. X            cancel_cbinfo;
  1572. X
  1573. X    /* Set the dialog box title */
  1574. X    xs = XmStringCreateSimple(title);
  1575. X    XtVaSetValues(widgets.dialog.confirm, XmNdialogTitle, xs, NULL);
  1576. X    XmStringFree(xs);
  1577. X
  1578. X    /* Set the dialog box message */
  1579. X    xs = XmStringCreateLtoR(msg, XmSTRING_DEFAULT_CHARSET);
  1580. X    XtVaSetValues(widgets.dialog.confirm, XmNmessageString, xs, NULL);
  1581. X    XmStringFree(xs);
  1582. X
  1583. X    /* Add callbacks */
  1584. X    ok_btn = XmMessageBoxGetChild(
  1585. X        widgets.dialog.confirm,
  1586. X        XmDIALOG_OK_BUTTON
  1587. X    );
  1588. X    cancel_btn = XmMessageBoxGetChild(
  1589. X        widgets.dialog.confirm,
  1590. X        XmDIALOG_CANCEL_BUTTON
  1591. X    );
  1592. X
  1593. X    ok_cbinfo.widget = ok_btn;
  1594. X    ok_cbinfo.type = XmNactivateCallback;
  1595. X    ok_cbinfo.func = f_ok;
  1596. X    ok_cbinfo.data = a_ok;
  1597. X    cancel_cbinfo.widget = cancel_btn;
  1598. X    cancel_cbinfo.type = XmNactivateCallback;
  1599. X    cancel_cbinfo.func = f_cancel;
  1600. X    cancel_cbinfo.data = a_cancel;
  1601. X    
  1602. X    if (f_ok != NULL) {
  1603. X        XtAddCallback(
  1604. X            ok_btn,
  1605. X            XmNactivateCallback,
  1606. X            f_ok,
  1607. X            a_ok
  1608. X        );
  1609. X
  1610. X        XtAddCallback(
  1611. X            ok_btn,
  1612. X            XmNactivateCallback,
  1613. X            (XtCallbackProc) cd_rmcallback,
  1614. X            (XtPointer) &ok_cbinfo
  1615. X        );
  1616. X
  1617. X        XtAddCallback(
  1618. X            cancel_btn,
  1619. X            XmNactivateCallback,
  1620. X            (XtCallbackProc) cd_rmcallback,
  1621. X            (XtPointer) &ok_cbinfo
  1622. X        );
  1623. X    }
  1624. X
  1625. X    if (f_cancel != NULL) {
  1626. X        XtAddCallback(
  1627. X            cancel_btn,
  1628. X            XmNactivateCallback,
  1629. X            f_cancel,
  1630. X            a_cancel
  1631. X        );
  1632. X
  1633. X        XtAddCallback(
  1634. X            cancel_btn,
  1635. X            XmNactivateCallback,
  1636. X            (XtCallbackProc) cd_rmcallback,
  1637. X            (XtPointer) &cancel_cbinfo
  1638. X        );
  1639. X
  1640. X        XtAddCallback(
  1641. X            ok_btn,
  1642. X            XmNactivateCallback,
  1643. X            (XtCallbackProc) cd_rmcallback,
  1644. X            (XtPointer) &cancel_cbinfo
  1645. X        );
  1646. X    }
  1647. X
  1648. X    /* Pop up the error dialog */
  1649. X    if (!XtIsManaged(widgets.dialog.confirm))
  1650. X        XtManageChild(widgets.dialog.confirm);
  1651. X}
  1652. X
  1653. X
  1654. X/*
  1655. X * cd_playprog
  1656. X *    Play the track program as defined in the playorder table.
  1657. X *
  1658. X * Args:
  1659. X *    s - Pointer to the curstat_t structure.
  1660. X *
  1661. X * Return:
  1662. X *    Nothing.
  1663. X */
  1664. Xvoid
  1665. Xcd_playprog(curstat_t *s)
  1666. X{
  1667. X    if (s->mode == M_PAUSE)
  1668. X        cd_pause_blink(s, FALSE);
  1669. X
  1670. X    cdlib_playprog(s);
  1671. X}
  1672. X
  1673. X
  1674. X/*
  1675. X * cd_init
  1676. X *    Top level function that initializes all subsystems.  Used on
  1677. X *    program startup.
  1678. X *
  1679. X * Args:
  1680. X *    s - Pointer to the curstat_t structure.
  1681. X *
  1682. X * Return:
  1683. X *    Nothing.
  1684. X */
  1685. Xvoid
  1686. Xcd_init(curstat_t *s)
  1687. X{
  1688. X    int        i;
  1689. X    char        *cp,
  1690. X            *path,
  1691. X            titlestr[STR_BUF_SZ],
  1692. X            str[FILE_PATH_SZ + 2];
  1693. X    XmString    xs;
  1694. X
  1695. X
  1696. X    /* Check sanity of some parameters and reset to default if
  1697. X     * found to be out of acceptable range.
  1698. X     */
  1699. X    if (app_data.stat_interval < 100 || app_data.stat_interval > 5000)
  1700. X        app_data.stat_interval = STATUS_INTERVAL;
  1701. X    if (app_data.ins_interval < 500 || app_data.ins_interval > 10000)
  1702. X        app_data.ins_interval = INSERT_INTERVAL;
  1703. X    if (app_data.prev_threshold < 1 || app_data.prev_threshold > 750)
  1704. X        app_data.prev_threshold = PREV_THRESHOLD;
  1705. X    if (app_data.skip_blks < 50 || app_data.skip_blks > 1000)
  1706. X        app_data.skip_blks = SKIP_BLKS;
  1707. X    if (app_data.skip_pause < 5 || app_data.skip_pause > 100)
  1708. X        app_data.skip_pause = SKIP_PAUSE;
  1709. X    if (app_data.skip_vol < 0 || app_data.skip_vol > 100)
  1710. X        app_data.skip_vol = SKIP_VOL;
  1711. X    if (app_data.skip_minvol < 0 || app_data.skip_minvol > 20)
  1712. X        app_data.skip_minvol = SKIP_MINVOL;
  1713. X    if (app_data.sample_blks < 75 || app_data.sample_blks > 2000)
  1714. X        app_data.sample_blks = SAMPLE_BLKS;
  1715. X    if (app_data.blinkon_interval < 0 ||
  1716. X        app_data.blinkon_interval > 10000)
  1717. X        app_data.blinkon_interval = BLINKON_INTERVAL;
  1718. X    if (app_data.blinkoff_interval < 0 ||
  1719. X        app_data.blinkoff_interval > 10000)
  1720. X        app_data.blinkoff_interval = BLINKOFF_INTERVAL;
  1721. X    if (app_data.base_scsivol < 0 || app_data.base_scsivol > 0xff)
  1722. X        app_data.base_scsivol = BASE_SCSIVOL;
  1723. X
  1724. X    if (app_data.max_dbdirs <= 0 || app_data.max_dbdirs > 100) {
  1725. X        fprintf(stderr, "%s: %s\n", PROGNAME, app_data.str_dbdirserr);
  1726. X        exit(1);
  1727. X    }
  1728. X
  1729. X    ouid = getuid();
  1730. X
  1731. X    if ((cp = getenv("XMCD_LIBDIR")) != NULL) {
  1732. X        if (app_data.libdir != NULL)
  1733. X            MEM_FREE(app_data.libdir);
  1734. X        app_data.libdir = (char *) MEM_ALLOC(strlen(cp) + 1);
  1735. X        if (app_data.libdir == NULL) {
  1736. X            fprintf(stderr, "%s: %s\n",
  1737. X                PROGNAME, app_data.str_nomemory);
  1738. X            exit(1);
  1739. X        }
  1740. X
  1741. X        strcpy(app_data.libdir, cp);
  1742. X    }
  1743. X
  1744. X    /* Allocate memory for the database directories string pointers array */
  1745. X    dbdirs = (char **)(void *) MEM_ALLOC(
  1746. X        app_data.max_dbdirs * sizeof(char *)
  1747. X    );
  1748. X    if (dbdirs == NULL) {
  1749. X        fprintf(stderr, "%s: %s\n", PROGNAME, app_data.str_nomemory);
  1750. X        exit(1);
  1751. X    }
  1752. X
  1753. X    if ((cp = getenv("XMCD_DBPATH")) != NULL) {
  1754. X        if (app_data.dbdir != NULL)
  1755. X            MEM_FREE(app_data.dbdir);
  1756. X
  1757. X        app_data.dbdir = (char *) MEM_ALLOC(strlen(cp) + 1);
  1758. X        if (app_data.dbdir == NULL) {
  1759. X            fprintf(stderr, "%s: %s\n",
  1760. X                PROGNAME, app_data.str_nomemory);
  1761. X            exit(1);
  1762. X        }
  1763. X
  1764. X        strcpy(app_data.dbdir, cp);
  1765. X    }
  1766. X
  1767. X    /* Create the global array of strings each of which is a
  1768. X     * path to a CD database directory.
  1769. X     */
  1770. X
  1771. X    i = 0;
  1772. X    if (app_data.dbdir[0] == '\0')
  1773. X        dbdirs[0] = NULL;
  1774. X    else {
  1775. X        for (path = app_data.dbdir;
  1776. X             (cp = strchr(path, DBPATH_SEPCHAR)) != NULL &&
  1777. X             i < app_data.max_dbdirs - 1;
  1778. X             path = cp + 1, i++) {
  1779. X            *cp = '\0';
  1780. X
  1781. X            if (path[0] == '/')
  1782. X                dbdirs[i] = (char *) MEM_ALLOC(
  1783. X                    strlen(path) + 1
  1784. X                );
  1785. X            else
  1786. X                dbdirs[i] = (char *) MEM_ALLOC(
  1787. X                    strlen(path) +
  1788. X                    strlen(app_data.libdir) + 7
  1789. X                );
  1790. X
  1791. X            if (dbdirs[i] == NULL) {
  1792. X                fprintf(stderr, "%s: %s\n",
  1793. X                    PROGNAME, app_data.str_nomemory);
  1794. X                exit(1);
  1795. X            }
  1796. X
  1797. X            if (path[0] == '/')
  1798. X                strcpy(dbdirs[i], path);
  1799. X            else
  1800. X                sprintf(dbdirs[i], "%s/cddb/%s",
  1801. X                    app_data.libdir, path);
  1802. X
  1803. X            *cp = DBPATH_SEPCHAR;
  1804. X
  1805. X            /* Add path to list in directory selector popup */
  1806. X            sprintf(str, "  %s", dbdirs[i]);
  1807. X            xs = XmStringCreateSimple(str);
  1808. X            XmListAddItemUnselected(
  1809. X                widgets.dirsel.dir_list,
  1810. X                xs,
  1811. X                i + 1
  1812. X            );
  1813. X            XmStringFree(xs);
  1814. X        }
  1815. X
  1816. X        if (cp != NULL && *cp == DBPATH_SEPCHAR)
  1817. X            *cp = '\0';
  1818. X
  1819. X        if (path[0] == '/')
  1820. X            dbdirs[i] = (char *) MEM_ALLOC(strlen(path) + 1);
  1821. X        else
  1822. X            dbdirs[i] = (char *) MEM_ALLOC(
  1823. X                strlen(path) + strlen(app_data.libdir) + 7
  1824. X            );
  1825. X
  1826. X        if (dbdirs[i] == NULL) {
  1827. X            fprintf(stderr, "%s: %s\n",
  1828. X                PROGNAME, app_data.str_nomemory);
  1829. X            exit(1);
  1830. X        }
  1831. X        if (path[0] == '/')
  1832. X            strcpy(dbdirs[i], path);
  1833. X        else
  1834. X            sprintf(dbdirs[i], "%s/cddb/%s",
  1835. X                app_data.libdir, path);
  1836. X
  1837. X        /* Add path to list in directory selector popup */
  1838. X        sprintf(str, "  %s", dbdirs[i]);
  1839. X        xs = XmStringCreateSimple(str);
  1840. X        XmListAddItemUnselected(widgets.dirsel.dir_list, xs, i + 1);
  1841. X        XmStringFree(xs);
  1842. X    }
  1843. X
  1844. X    for (i++; i < app_data.max_dbdirs; i++)
  1845. X        dbdirs[i] = NULL;
  1846. X
  1847. X    lockfile[0] = '\0';
  1848. X
  1849. X    /* Initialize the database/program subsystem */
  1850. X    dbprog_init(s);
  1851. X
  1852. X    /* Initialize the CD interface subsystem */
  1853. X    cdlib_init(s);
  1854. X
  1855. X    /* Get system-wide device-specific resource configurations */
  1856. X    sprintf(str, "%s/config/%s",
  1857. X        app_data.libdir, basename(app_data.device));
  1858. X    devspec_init(str, TRUE);
  1859. X
  1860. X    /* Get user device-specific resource configurations */
  1861. X    sprintf(str, "%s/.xmcdcfg/%s",
  1862. X        homedir(ouid), basename(app_data.device));
  1863. X    devspec_init(str, FALSE);
  1864. X
  1865. X    /* Set the main window title */
  1866. X    sprintf(titlestr, "%s %d", app_data.main_title, app_data.devnum);
  1867. X    XStoreName(
  1868. X        XtDisplay(widgets.toplevel),
  1869. X        XtWindow(widgets.toplevel),
  1870. X        titlestr
  1871. X    );
  1872. X}
  1873. X
  1874. X
  1875. X/*
  1876. X * cd_start
  1877. X *    Start up I/O to the CD player.
  1878. X *
  1879. X * Args:
  1880. X *    s - Pointer to the curstat_t structure.
  1881. X *
  1882. X * Return:
  1883. X *    Nothing.
  1884. X */
  1885. Xvoid
  1886. Xcd_start(curstat_t *s)
  1887. X{
  1888. X    cdlib_start(s);
  1889. X}
  1890. X
  1891. X
  1892. X/*
  1893. X * cd_icon
  1894. X *    Main window iconification/deiconification handler.
  1895. X *
  1896. X * Args:
  1897. X *    s - Pointer to the curstat_t structure.
  1898. X *    iconified - Whether the main window is iconified.
  1899. X *
  1900. X * Return:
  1901. X *    Nothing.
  1902. X */
  1903. Xvoid
  1904. Xcd_icon(curstat_t *s, bool_t iconified)
  1905. X{
  1906. X    cdlib_icon(s, iconified);
  1907. X}
  1908. X
  1909. X
  1910. X/*
  1911. X * cd_halt
  1912. X *    Top level function to shut down all subsystems.  Used when
  1913. X *    closing the application.
  1914. X *
  1915. X * Args:
  1916. X *    s - Pointer to the curstat_t structure.
  1917. X *
  1918. X * Return:
  1919. X *    Nothing.
  1920. X */
  1921. Xvoid
  1922. Xcd_halt(curstat_t *s)
  1923. X{
  1924. X    cdlib_halt(s);
  1925. X}
  1926. X
  1927. X
  1928. X/*
  1929. X * cd_devlock
  1930. X *    Create a lock to prevent another xmcd process from accessing
  1931. X *    the same CD-ROM device.
  1932. X *
  1933. X * Args:
  1934. X *    path - The lock file path name.
  1935. X *
  1936. X * Return:
  1937. X *    TRUE if the lock was successful.  If FALSE, then it indicates
  1938. X *    that another xmcd process currently has the lock.
  1939. X */
  1940. Xbool_t
  1941. Xcd_devlock(char *path)
  1942. X{
  1943. X    int        fd;
  1944. X    pid_t        pid,
  1945. X            mypid;
  1946. X    char        buf[12];
  1947. X    struct stat    stbuf;
  1948. X
  1949. X    if (stat(path, &stbuf) < 0)
  1950. X        return(FALSE);
  1951. X
  1952. X    if ((stbuf.st_mode & S_IFMT) != S_IFCHR)
  1953. X        return(FALSE);
  1954. X
  1955. X    sprintf(lockfile, "/tmp/.cdlk.%x", stbuf.st_rdev);
  1956. X
  1957. X    mypid = getpid();
  1958. X
  1959. X    for (;;) {
  1960. X        fd = open(lockfile, O_CREAT | O_EXCL | O_WRONLY | O_SYNC);
  1961. X        if (fd < 0) {
  1962. X            if (errno == EEXIST) {
  1963. X                if ((fd = open(lockfile, O_RDONLY)) < 0)
  1964. X                    return(FALSE);
  1965. X
  1966. X                if (read(fd, buf, 12) > 0)
  1967. X                    pid = (pid_t) atoi(buf);
  1968. X                else {
  1969. X                    close(fd);
  1970. X                    return(FALSE);
  1971. X                }
  1972. X
  1973. X                close(fd);
  1974. X
  1975. X                if (pid == mypid)
  1976. X                    /* Our own lock */
  1977. X                    return(TRUE);
  1978. X
  1979. X                if (pid <= 0 ||
  1980. X                    (kill(pid, 0) < 0 && errno == ESRCH)) {
  1981. X                    /* Pid died, steal its lockfile */
  1982. X                    unlink(lockfile);
  1983. X                }
  1984. X                else {
  1985. X                    /* Pid still running: clash */
  1986. X                    devbusy = TRUE;
  1987. X                    return(FALSE);
  1988. X                }
  1989. X            }
  1990. X            else
  1991. X                return(FALSE);
  1992. X        }
  1993. X        else {
  1994. X            sprintf(buf, "%d\n", mypid);
  1995. X            write(fd, buf, strlen(buf));
  1996. X
  1997. X            close(fd);
  1998. X            chmod(lockfile, 0644);
  1999. X
  2000. X            devbusy = FALSE;
  2001. X            return(TRUE);
  2002. X        }
  2003. X    }
  2004. X}
  2005. X
  2006. X
  2007. X/*
  2008. X * onsig
  2009. X *    Signal handler.  Causes the application to shut down gracefully.
  2010. X *
  2011. X * Args:
  2012. X *    sig - The signal number received.
  2013. X *
  2014. X * Return:
  2015. X *    Nothing.
  2016. X */
  2017. Xvoid
  2018. Xonsig(int sig)
  2019. X{
  2020. X    signal(sig, SIG_IGN);
  2021. X    cd_exit(
  2022. X        widgets.toplevel,
  2023. X        (XtPointer) curstat_addr(),
  2024. X        (XtPointer) NULL
  2025. X    );
  2026. X}
  2027. X
  2028. X
  2029. X/**************** vv Callback routines vv ****************/
  2030. X
  2031. X/*
  2032. X * cd_checkbox
  2033. X *    Main window checkbox callback function
  2034. X */
  2035. X/*ARGSUSED*/
  2036. Xvoid
  2037. Xcd_checkbox(Widget w, XtPointer client_data, XtPointer call_data)
  2038. X{
  2039. X    XmRowColumnCallbackStruct
  2040. X            *p = (XmRowColumnCallbackStruct *)(void *) call_data;
  2041. X    curstat_t    *s = (curstat_t *)(void *) client_data;
  2042. X
  2043. X
  2044. X    if (p->reason != XmCR_ACTIVATE)
  2045. X        return;
  2046. X
  2047. X    if (p->widget == widgets.main.btnlbl_btn) {
  2048. X        btnlbl_state = !btnlbl_state;
  2049. X        set_btn_lbltype((byte_t)
  2050. X            (btnlbl_state ? BTN_STRING : BTN_PIXMAP)
  2051. X        );
  2052. X    }
  2053. X    else if (p->widget == widgets.main.lock_btn) {
  2054. X        lock_state = !lock_state;
  2055. X        cdlib_lock(s, lock_state);
  2056. X    }
  2057. X    else if (p->widget == widgets.main.repeat_btn) {
  2058. X        repeat_state = !repeat_state;
  2059. X        cdlib_repeat(s, repeat_state);
  2060. X    }
  2061. X    else if (p->widget == widgets.main.shuffle_btn) {
  2062. X        shuffle_state = !shuffle_state;
  2063. X        cdlib_shuffle(s, shuffle_state);
  2064. X    }
  2065. X}
  2066. X
  2067. X
  2068. X/*
  2069. X * cd_load_eject
  2070. X *    Main window load/eject button callback function
  2071. X */
  2072. X/*ARGSUSED*/
  2073. Xvoid
  2074. Xcd_load_eject(Widget w, XtPointer client_data, XtPointer call_data)
  2075. X{
  2076. X    curstat_t    *s = (curstat_t *)(void *) client_data;
  2077. X
  2078. X    if (searching) {
  2079. X        cd_beep();
  2080. X        return;
  2081. X    }
  2082. X    if (s->mode == M_PAUSE)
  2083. X        cd_pause_blink(s, FALSE);
  2084. X
  2085. X    cdlib_load_eject(s);
  2086. X}
  2087. X
  2088. X
  2089. X/*
  2090. X * cd_poweroff
  2091. X *    Main window quit button callback function
  2092. X */
  2093. X/*ARGSUSED*/
  2094. Xvoid
  2095. Xcd_poweroff(Widget w, XtPointer client_data, XtPointer call_data)
  2096. X{
  2097. X    cd_confirm_popup(
  2098. X        app_data.str_confirm,
  2099. X        app_data.str_quit,
  2100. X        (XtCallbackProc) cd_exit,
  2101. X        client_data,
  2102. X        (XtCallbackProc) NULL,
  2103. X        NULL
  2104. X    );
  2105. X}
  2106. X
  2107. X
  2108. X/*
  2109. X * cd_dbprog
  2110. X *    Main window dbprog button callback function
  2111. X */
  2112. Xvoid
  2113. Xcd_dbprog(Widget w, XtPointer client_data, XtPointer call_data)
  2114. X{
  2115. X    static bool_t    first = TRUE;
  2116. X
  2117. X    if (XtIsManaged(widgets.dbprog.form)) {
  2118. X        /* Pop down the Database/Program window */
  2119. X        dbprog_cancel(w, client_data, call_data);
  2120. X        return;
  2121. X    }
  2122. X
  2123. X    /* Pop up the Database/Program window */
  2124. X    dbprog_popup(w, client_data, call_data);
  2125. X
  2126. X    if (first) {
  2127. X        first = FALSE;
  2128. X        XmProcessTraversal(
  2129. X            widgets.dbprog.cancel_btn,
  2130. X            XmTRAVERSE_CURRENT
  2131. X        );
  2132. X    }
  2133. X}
  2134. X
  2135. X
  2136. X/*
  2137. X * cd_time
  2138. X *    Main window time mode button callback function
  2139. X */
  2140. X/*ARGSUSED*/
  2141. Xvoid
  2142. Xcd_time(Widget w, XtPointer client_data, XtPointer call_data)
  2143. X{
  2144. X    curstat_t    *s = (curstat_t *)(void *) client_data;
  2145. X
  2146. X    switch (s->time_dpy) {
  2147. X    case T_ELAPSED:
  2148. X        s->time_dpy = T_REMAIN_TRACK;
  2149. X        break;
  2150. X
  2151. X    case T_REMAIN_TRACK:
  2152. X        s->time_dpy = T_REMAIN_DISC;
  2153. X        break;
  2154. X
  2155. X    case T_REMAIN_DISC:
  2156. X        s->time_dpy = T_ELAPSED;
  2157. X        break;
  2158. X    }
  2159. X
  2160. X    dpy_timemode(s);
  2161. X    dpy_track(s);
  2162. X    dpy_time(s, FALSE);
  2163. X}
  2164. X
  2165. X
  2166. X/*
  2167. X * cd_ab
  2168. X *    Main window a->b mode button callback function
  2169. X */
  2170. X/*ARGSUSED*/
  2171. Xvoid
  2172. Xcd_ab(Widget w, XtPointer client_data, XtPointer call_data)
  2173. X{
  2174. X    if (searching) {
  2175. X        cd_beep();
  2176. X        return;
  2177. X    }
  2178. X    cdlib_ab((curstat_t *)(void *) client_data);
  2179. X}
  2180. X
  2181. X
  2182. X/*
  2183. X * cd_sample
  2184. X *    Main window sample mode button callback function
  2185. X */
  2186. X/*ARGSUSED*/
  2187. Xvoid
  2188. Xcd_sample(Widget w, XtPointer client_data, XtPointer call_data)
  2189. X{
  2190. X    if (searching) {
  2191. X        cd_beep();
  2192. X        return;
  2193. X    }
  2194. X    cdlib_sample((curstat_t *)(void *) client_data);
  2195. X}
  2196. X
  2197. X
  2198. X/*
  2199. X * cd_level
  2200. X *    Main window volume control slider callback function
  2201. X */
  2202. X/*ARGSUSED*/
  2203. Xvoid
  2204. Xcd_level(Widget w, XtPointer client_data, XtPointer call_data)
  2205. X{
  2206. X    XmScaleCallbackStruct
  2207. X            *p = (XmScaleCallbackStruct *)(void *) call_data;
  2208. X
  2209. X    cdlib_level(
  2210. X        (curstat_t *)(void *) client_data,
  2211. X        (byte_t) p->value,
  2212. X        (bool_t) (p->reason != XmCR_VALUE_CHANGED)
  2213. X    );
  2214. X}
  2215. X
  2216. X
  2217. X/*
  2218. X * cd_play_pause
  2219. X *    Main window play/pause button callback function
  2220. X */
  2221. X/*ARGSUSED*/
  2222. Xvoid
  2223. Xcd_play_pause(Widget w, XtPointer client_data, XtPointer call_data)
  2224. X{
  2225. X    curstat_t    *s = (curstat_t *)(void *) client_data;
  2226. X
  2227. X    if (searching) {
  2228. X        cd_beep();
  2229. X        return;
  2230. X    }
  2231. X
  2232. X    cdlib_play_pause(s);
  2233. X
  2234. X    switch (s->mode) {
  2235. X    case M_PAUSE:
  2236. X        cd_pause_blink(s, TRUE);
  2237. X        break;
  2238. X    case M_PLAY:
  2239. X    case M_STOP:
  2240. X    case M_A:
  2241. X    case M_AB:
  2242. X    case M_SAMPLE:
  2243. X        cd_pause_blink(s, FALSE);
  2244. X        break;
  2245. X    }
  2246. X}
  2247. X
  2248. X
  2249. X/*
  2250. X * cd_stop
  2251. X *    Main window stop button callback function
  2252. X */
  2253. X/*ARGSUSED*/
  2254. Xvoid
  2255. Xcd_stop(Widget w, XtPointer client_data, XtPointer call_data)
  2256. X{
  2257. X    curstat_t    *s = (curstat_t *)(void *) client_data;
  2258. X
  2259. X    if (searching) {
  2260. X        cd_beep();
  2261. X        return;
  2262. X    }
  2263. X    if (s->mode == M_PAUSE)
  2264. X        cd_pause_blink(s, FALSE);
  2265. X
  2266. X    cdlib_stop(s, TRUE);
  2267. X}
  2268. X
  2269. X
  2270. X/*
  2271. X * cd_prevtrk
  2272. X *    Main window prev track button callback function
  2273. X */
  2274. X/*ARGSUSED*/
  2275. Xvoid
  2276. Xcd_prevtrk(Widget w, XtPointer client_data, XtPointer call_data)
  2277. X{
  2278. X    if (searching) {
  2279. X        cd_beep();
  2280. X        return;
  2281. X    }
  2282. X    cdlib_prevtrk((curstat_t *)(void *) client_data);
  2283. X}
  2284. X
  2285. X
  2286. X/*
  2287. X * cd_nexttrk
  2288. X *    Main window next track button callback function
  2289. X */
  2290. X/*ARGSUSED*/
  2291. Xvoid
  2292. Xcd_nexttrk(Widget w, XtPointer client_data, XtPointer call_data)
  2293. X{
  2294. X    if (searching) {
  2295. X        cd_beep();
  2296. X        return;
  2297. X    }
  2298. X    cdlib_nexttrk((curstat_t *)(void *) client_data);
  2299. X}
  2300. X
  2301. X
  2302. X/*
  2303. X * cd_previdx
  2304. X *    Main window prev index button callback function
  2305. X */
  2306. X/*ARGSUSED*/
  2307. Xvoid
  2308. Xcd_previdx(Widget w, XtPointer client_data, XtPointer call_data)
  2309. X{
  2310. X    if (searching) {
  2311. X        cd_beep();
  2312. X        return;
  2313. X    }
  2314. X    cdlib_previdx((curstat_t *)(void *) client_data);
  2315. X}
  2316. X
  2317. X
  2318. X/*
  2319. X * cd_previdx
  2320. X *    Main window next index button callback function
  2321. X */
  2322. X/*ARGSUSED*/
  2323. Xvoid
  2324. Xcd_nextidx(Widget w, XtPointer client_data, XtPointer call_data)
  2325. X{
  2326. X    if (searching) {
  2327. X        cd_beep();
  2328. X        return;
  2329. X    }
  2330. X    cdlib_nextidx((curstat_t *)(void *) client_data);
  2331. X}
  2332. X
  2333. X
  2334. X/*
  2335. X * cd_rew
  2336. X *    Main window search rewind button callback function
  2337. X */
  2338. X/*ARGSUSED*/
  2339. Xvoid
  2340. Xcd_rew(Widget w, XtPointer client_data, XtPointer call_data)
  2341. X{
  2342. X    XmPushButtonCallbackStruct
  2343. X            *p = (XmPushButtonCallbackStruct *)(void *) call_data;
  2344. X    curstat_t    *s = (curstat_t *)(void *) client_data;
  2345. X    bool_t        start;
  2346. X    static bool_t    rew_running = FALSE;
  2347. X
  2348. X    if (p->reason == XmCR_ARM) {
  2349. X        if (!rew_running) {
  2350. X            if (searching) {
  2351. X                /* Release running FF */
  2352. X                XtCallActionProc(
  2353. X                    widgets.main.ff_btn,
  2354. X                    "Activate",
  2355. X                    p->event,
  2356. X                    NULL,
  2357. X                    0
  2358. X                );
  2359. X                XtCallActionProc(
  2360. X                    widgets.main.ff_btn,
  2361. X                    "Disarm",
  2362. X                    p->event,
  2363. X                    NULL,
  2364. X                    0
  2365. X                );
  2366. X            }
  2367. X
  2368. X            rew_running = TRUE;
  2369. X            searching = TRUE;
  2370. X            start = TRUE;
  2371. X        }
  2372. X        else
  2373. X            /* Already running REW */
  2374. X            return;
  2375. X    }
  2376. X    else {
  2377. X        if (rew_running) {
  2378. X            rew_running = FALSE;
  2379. X            searching = FALSE;
  2380. X            start = FALSE;
  2381. X        }
  2382. X        else
  2383. X            /* Not running REW */
  2384. X            return;
  2385. X    }
  2386. X
  2387. X    cdlib_rew(s, start);
  2388. X
  2389. X    if (s->mode == M_PAUSE)
  2390. X        cd_pause_blink(s, (bool_t) !start);
  2391. X}
  2392. X
  2393. X
  2394. X/*
  2395. X * cd_ff
  2396. X *    Main window search fast-forward button callback function
  2397. X */
  2398. X/*ARGSUSED*/
  2399. Xvoid
  2400. Xcd_ff(Widget w, XtPointer client_data, XtPointer call_data)
  2401. X{
  2402. X    XmPushButtonCallbackStruct
  2403. X            *p = (XmPushButtonCallbackStruct *)(void *) call_data;
  2404. X    curstat_t    *s = (curstat_t *)(void *) client_data;
  2405. X    bool_t        start;
  2406. X    static bool_t    ff_running = FALSE;
  2407. X
  2408. X    if (p->reason == XmCR_ARM) {
  2409. X        if (!ff_running) {
  2410. X            if (searching) {
  2411. X                /* Release running REW */
  2412. X                XtCallActionProc(
  2413. X                    widgets.main.rew_btn,
  2414. X                    "Activate",
  2415. X                    p->event,
  2416. X                    NULL,
  2417. X                    0
  2418. X                );
  2419. X                XtCallActionProc(
  2420. X                    widgets.main.rew_btn,
  2421. X                    "Disarm",
  2422. X                    p->event,
  2423. X                    NULL,
  2424. X                    0
  2425. X                );
  2426. X            }
  2427. X
  2428. X            ff_running = TRUE;
  2429. X            searching = TRUE;
  2430. X            start = TRUE;
  2431. X        }
  2432. X        else
  2433. X            /* Already running FF */
  2434. X            return;
  2435. X    }
  2436. X    else {
  2437. X        if (ff_running) {
  2438. X            ff_running = FALSE;
  2439. X            searching = FALSE;
  2440. X            start = FALSE;
  2441. X        }
  2442. X        else
  2443. X            /* Not running FF */
  2444. X            return;
  2445. X    }
  2446. X
  2447. X    cdlib_ff(s, start);
  2448. X
  2449. X    if (s->mode == M_PAUSE)
  2450. X        cd_pause_blink(s, (bool_t) !start);
  2451. X}
  2452. X
  2453. X
  2454. X/*
  2455. X * cd_keypad_popup
  2456. X *    Main window keypad button callback function
  2457. X */
  2458. Xvoid
  2459. Xcd_keypad_popup(Widget w, XtPointer client_data, XtPointer call_data)
  2460. X{
  2461. X    static bool_t    first = TRUE;
  2462. X
  2463. X    if (XtIsManaged(widgets.keypad.form)) {
  2464. X        /* Pop down keypad window */
  2465. X        cd_keypad_popdown(w, client_data, call_data);
  2466. X        return;
  2467. X    }
  2468. X
  2469. X    /* Pop up keypad window */
  2470. X    XtManageChild(widgets.keypad.form);
  2471. X
  2472. X    /* Reset keypad */
  2473. X    cd_keypad_clear(w, client_data, call_data);
  2474. X
  2475. X    if (first) {
  2476. X        first = FALSE;
  2477. X        XmProcessTraversal(
  2478. X            widgets.keypad.cancel_btn,
  2479. X            XmTRAVERSE_CURRENT
  2480. X        );
  2481. X    }
  2482. X}
  2483. X
  2484. X
  2485. X/*
  2486. X * cd_keypad_clear
  2487. X *    Keypad window clear button callback function
  2488. X */
  2489. X/*ARGSUSED*/
  2490. Xvoid
  2491. Xcd_keypad_clear(Widget w, XtPointer client_data, XtPointer call_data)
  2492. X{
  2493. X    /* Reset keypad */
  2494. X    keystr[0] = '\0';
  2495. X    dpy_keypad_ind();
  2496. X}
  2497. X
  2498. X
  2499. X/*
  2500. X * cd_keypad_popdown
  2501. X *    Keypad window popdown callback function
  2502. X */
  2503. X/*ARGSUSED*/
  2504. Xvoid
  2505. Xcd_keypad_popdown(Widget w, XtPointer client_data, XtPointer call_data)
  2506. X{
  2507. X    /* Pop down keypad window */
  2508. X    if (XtIsManaged(widgets.keypad.form))
  2509. X        XtUnmanageChild(widgets.keypad.form);
  2510. X}
  2511. X
  2512. X
  2513. X/*
  2514. X * cd_keypad_num
  2515. X *    Keypad window number button callback function
  2516. X */
  2517. X/*ARGSUSED*/
  2518. Xvoid
  2519. Xcd_keypad_num(Widget w, XtPointer client_data, XtPointer call_data)
  2520. X{
  2521. X    char    tmpstr[2];
  2522. X
  2523. X    /* The user entered a digit */
  2524. X    if (strlen(keystr) >= sizeof(keystr) - 1) {
  2525. X        cd_beep();
  2526. X        return;
  2527. X    }
  2528. X    sprintf(tmpstr, "%u", (int) client_data);
  2529. X    strcat(keystr, tmpstr);
  2530. X    dpy_keypad_ind();
  2531. X}
  2532. X
  2533. X
  2534. X/*
  2535. X * cd_keypad_enter
  2536. X *    Keypad window enter button callback function
  2537. X */
  2538. Xvoid
  2539. Xcd_keypad_enter(Widget w, XtPointer client_data, XtPointer call_data)
  2540. X{
  2541. X    curstat_t    *s = (curstat_t *)(void *) client_data;
  2542. X    bool_t        paused = FALSE,
  2543. X            sav_shuffle,
  2544. X            sav_program;
  2545. X    sword32_t    sav_cur_trk;
  2546. X
  2547. X    /* The user activated the Enter key */
  2548. X
  2549. X    /* Save some parameters */
  2550. X    sav_shuffle = s->shuffle;
  2551. X    sav_program = s->program;
  2552. X    sav_cur_trk = s->cur_trk;
  2553. X
  2554. X    /* Clear shuffle and program mode */
  2555. X    s->shuffle = FALSE;
  2556. X    s->program = FALSE;
  2557. X
  2558. X    if (!cdlib_check_disc(s)) {
  2559. X        cd_beep();
  2560. X        return;
  2561. X    }
  2562. X
  2563. X    s->cur_trk = (sword32_t) atoi(keystr);
  2564. X
  2565. X    if (curtrk_pos(s) < 0) {
  2566. X        /* Illegal track entered */
  2567. X        cd_keypad_clear(w, client_data, call_data);
  2568. X
  2569. X        s->shuffle = sav_shuffle;
  2570. X        s->program = sav_program;
  2571. X        s->cur_trk = sav_cur_trk;
  2572. X
  2573. X        cd_beep();
  2574. X        return;
  2575. X    }
  2576. X
  2577. X    /* Update shuffle button state */
  2578. X    set_shuffle_btn(FALSE);
  2579. X
  2580. X    switch (s->mode) {
  2581. X    case M_PAUSE:
  2582. X        /* Mute sound */
  2583. X        cdlib_mute_on(s);
  2584. X        paused = TRUE;
  2585. X
  2586. X        /*FALLTHROUGH*/
  2587. X    case M_PLAY:
  2588. X    case M_A:
  2589. X    case M_AB:
  2590. X    case M_SAMPLE:
  2591. X        /* Set play status to stop */
  2592. X        cdlib_stop(s, FALSE);
  2593. X
  2594. X        /* Do this again because cdlib_stop resets cur_trk */
  2595. X        s->cur_trk = atoi(keystr);
  2596. X
  2597. X        break;
  2598. X
  2599. X    default:
  2600. X        break;
  2601. X    }
  2602. X
  2603. X    /* Start playback at new track */
  2604. X    cd_play_pause(w, client_data, call_data);
  2605. X
  2606. X    if (paused) {
  2607. X        /* This will cause the playback to pause */
  2608. X        cd_play_pause(w, client_data, call_data);
  2609. X
  2610. X        /* Restore sound */
  2611. X        cdlib_mute_off(s);
  2612. X    }
  2613. X
  2614. X    cd_keypad_clear(w, client_data, call_data);
  2615. X}
  2616. X
  2617. X
  2618. X/*
  2619. X * cd_about
  2620. X *    Program information popup callback function
  2621. X */
  2622. X/*ARGSUSED*/
  2623. Xvoid
  2624. Xcd_about(Widget w, XtPointer client_data, XtPointer call_data)
  2625. X{
  2626. X    int        i;
  2627. X    char        txt[2048];
  2628. X    XmString    xs_progname,
  2629. X            xs_desc,
  2630. X            xs_info,
  2631. X            xs_tmp,
  2632. X            xs;
  2633. X    curstat_t    *s = (curstat_t *)(void *) client_data;
  2634. X
  2635. X    if (XtIsManaged(widgets.dialog.about)) {
  2636. X        /* Pop down the about dialog box */
  2637. X        XtUnmanageChild(widgets.dialog.about);
  2638. X        return;
  2639. X    }
  2640. X
  2641. X    xs_progname = XmStringCreateLtoR(PROGNAME, CHSET1);
  2642. X
  2643. X    sprintf(txt, "   v%s%s PL%d\n%s\n%s\n%s\n\n",
  2644. X        VERSION,
  2645. X        VERSION_EXT,
  2646. X        PATCHLEVEL,
  2647. X        "Motif(tm) CD Audio Player",
  2648. X        "Copyright (C) 1993  Ti Kan",
  2649. X        "E-mail: ti@amb.org");
  2650. X
  2651. X    xs_desc = XmStringCreateLtoR(txt, CHSET2);
  2652. X
  2653. X    sprintf(txt, "%s\n%s%s %s %s%s%s\n%s%s\n%s%s\n\n%s",
  2654. X        cdlib_vers(),
  2655. X        "CD-ROM: ",
  2656. X        (s->vendor[0] == '\0') ? "??" : s->vendor,
  2657. X        s->prod,
  2658. X        (s->revnum[0] == '\0') ? "" : "(",
  2659. X        s->revnum,
  2660. X        (s->revnum[0] == '\0') ? "" : ")",
  2661. X        "Device: ",
  2662. X        app_data.device,
  2663. X        "Mode:   ",
  2664. X        cdlib_mode(),
  2665. X        "CD Database directories:"
  2666. X    );
  2667. X
  2668. X    for (i = 0; i < app_data.max_dbdirs && dbdirs[i] != NULL; i++)
  2669. X        sprintf(txt, "%s\n    %s", txt, dbdirs[i]);
  2670. X
  2671. X    if (i == 0)
  2672. X        strcat(txt, " None");
  2673. X
  2674. X    sprintf(txt, "%s\n\n%s\n%s", txt,
  2675. X        "This is free software and comes with no warranty.",
  2676. X        "See the GNU General Public License for details.");
  2677. X
  2678. X    xs_info = XmStringCreateLtoR(txt, CHSET3);
  2679. X
  2680. X    /* Set the dialog box title */
  2681. X    xs = XmStringCreateSimple(app_data.str_about);
  2682. X    XtVaSetValues(widgets.dialog.about, XmNdialogTitle, xs, NULL);
  2683. X    XmStringFree(xs);
  2684. X
  2685. X    /* Set the dialog box message */
  2686. X    xs_tmp = XmStringConcat(xs_progname, xs_desc);
  2687. X    xs = XmStringConcat(xs_tmp, xs_info);
  2688. X    XtVaSetValues(widgets.dialog.about, XmNmessageString, xs, NULL);
  2689. X    XmStringFree(xs_progname);
  2690. X    XmStringFree(xs_desc);
  2691. X    XmStringFree(xs_info);
  2692. X    XmStringFree(xs_tmp);
  2693. X    XmStringFree(xs);
  2694. X
  2695. X    /* Pop up the about dialog box */
  2696. X    XtManageChild(widgets.dialog.about);
  2697. X}
  2698. X
  2699. X
  2700. X/*
  2701. X * cd_help
  2702. X *    Program help window popup callback function
  2703. X */
  2704. X/*ARGSUSED*/
  2705. Xvoid
  2706. Xcd_help_popup(Widget w, XtPointer client_data, XtPointer call_data)
  2707. X{
  2708. X    if (w == widgets.main.help_btn && XtIsManaged(widgets.help.form)) {
  2709. X        /* Pop down help window */
  2710. X        XtUnmanageChild(widgets.help.form);
  2711. X
  2712. X        return;
  2713. X    }
  2714. X
  2715. X    /* Pop up help window */
  2716. X    help_popup(w);
  2717. X}
  2718. X
  2719. X
  2720. X/*
  2721. X * cd_help_popdown
  2722. X *    Program help window popdown callback function
  2723. X */
  2724. X/*ARGSUSED*/
  2725. Xvoid
  2726. Xcd_help_popdown(Widget w, XtPointer client_data, XtPointer call_data)
  2727. X{
  2728. X    /* Pop down help window */
  2729. X    if (XtIsManaged(widgets.help.form))
  2730. X        XtUnmanageChild(widgets.help.form);
  2731. X}
  2732. X
  2733. X
  2734. X/*
  2735. X * cd_warning_popdown
  2736. X *    Warning message dialog box popdown callback function
  2737. X */
  2738. X/*ARGSUSED*/
  2739. Xvoid
  2740. Xcd_warning_popdown(Widget w, XtPointer client_data, XtPointer call_data)
  2741. X{
  2742. X    /* Pop down the warning dialog */
  2743. X    if (XtIsManaged(widgets.dialog.warning))
  2744. X        XtUnmanageChild(widgets.dialog.warning);
  2745. X}
  2746. X
  2747. X
  2748. X/*
  2749. X * cd_fatal_popdown
  2750. X *    Fatal error message dialog box popdown callback function.
  2751. X *    This causes the application to terminate.
  2752. X */
  2753. Xvoid
  2754. Xcd_fatal_popdown(Widget w, XtPointer client_data, XtPointer call_data)
  2755. X{
  2756. X    /* Pop down the error dialog */
  2757. X    if (XtIsManaged(widgets.dialog.fatal))
  2758. X        XtUnmanageChild(widgets.dialog.fatal);
  2759. X
  2760. X    /* Quit */
  2761. X    cd_exit(w, client_data, call_data);
  2762. X}
  2763. X
  2764. X
  2765. X/*
  2766. X * cd_rmcallback
  2767. X *    Remove callback function specified in cdinfo_t.
  2768. X */
  2769. X/*ARGSUSED*/
  2770. Xvoid
  2771. Xcd_rmcallback(Widget w, XtPointer client_data, XtPointer call_data)
  2772. X{
  2773. X    cbinfo_t    *cb = (cbinfo_t *)(void *) client_data;
  2774. X
  2775. X    XtRemoveCallback(
  2776. X        cb->widget,
  2777. X        cb->type,
  2778. X        (XtCallbackProc) cb->func,
  2779. X        (XtPointer) cb->data
  2780. X    );
  2781. X}
  2782. X
  2783. X
  2784. X/*
  2785. X * cd_form_focus_chg
  2786. X *    Focus change callback.  Used to implement keyboard grabs for
  2787. X *    hotkey handling.
  2788. X */
  2789. X/*ARGSUSED*/
  2790. Xvoid
  2791. Xcd_form_focus_chg(Widget w, XtPointer client_data, XtPointer call_data)
  2792. X{
  2793. X    XmAnyCallbackStruct    *p = (XmAnyCallbackStruct *)(void *) call_data;
  2794. X    Widget            form = (Widget) client_data;
  2795. X    static Widget        prev_form = (Widget) NULL;
  2796. X
  2797. X    if (p->reason != XmCR_FOCUS || form == (Widget) NULL)
  2798. X        return;
  2799. X
  2800. X    if (prev_form != NULL) {
  2801. X        if (form == prev_form)
  2802. X            return;
  2803. X        else
  2804. X            hotkey_ungrabkeys(prev_form);
  2805. X    }
  2806. X
  2807. X    if (form != widgets.toplevel) {
  2808. X        hotkey_grabkeys(form);
  2809. X        prev_form = form;
  2810. X    }
  2811. X}
  2812. X
  2813. X
  2814. X/*
  2815. X * cd_exit
  2816. X *    Shut down the application gracefully.
  2817. X */
  2818. X/*ARGSUSED*/
  2819. Xvoid
  2820. Xcd_exit(Widget w, XtPointer client_data, XtPointer call_data)
  2821. X{
  2822. X    XmAnyCallbackStruct    p;
  2823. X
  2824. X    if (XtIsRealized(widgets.toplevel))
  2825. X        XtUnmapWidget(widgets.toplevel);
  2826. X
  2827. X    cd_halt((curstat_t *)(void *) client_data);
  2828. X
  2829. X    /* Uninstall current keyboard grabs */
  2830. X    p.reason = XmCR_FOCUS;
  2831. X    cd_form_focus_chg(
  2832. X        widgets.toplevel,
  2833. X        (XtPointer) widgets.toplevel,
  2834. X        (XtPointer) &p
  2835. X    );
  2836. X
  2837. X    if (!devbusy && lockfile[0] != '\0')
  2838. X        unlink(lockfile);
  2839. X
  2840. X    exit_flag = TRUE;
  2841. X}
  2842. X
  2843. X
  2844. X/**************** ^^ Callback routines ^^ ****************/
  2845. X
  2846. X/***************** vv Event Handlers vv ******************/
  2847. X
  2848. X
  2849. X/*
  2850. X * cd_btn_focus_chg
  2851. X *    Pushbutton keyboard focus change event handler.  Used to change
  2852. X *    the main window pushbuttons' label color.
  2853. X */
  2854. X/*ARGSUSED*/
  2855. Xvoid
  2856. Xcd_btn_focus_chg(Widget w, XtPointer client_data, XEvent *ev, Boolean *cont)
  2857. X{
  2858. X    static bool_t    first = TRUE;
  2859. X    static int    count = 0;
  2860. X    static Pixel    fg,
  2861. X            hl;
  2862. X
  2863. X    if (!app_data.main_showfocus)
  2864. X        return;
  2865. X
  2866. X    if (first) {
  2867. X        first = FALSE;
  2868. X
  2869. X        XtVaGetValues(w, XmNforeground, &fg, NULL);
  2870. X        XtVaGetValues(w, XmNhighlightColor, &hl, NULL);
  2871. X    }
  2872. X
  2873. X    if (ev->type == FocusOut) {
  2874. X        if (count <= 0)
  2875. X            return;
  2876. X
  2877. X        /* Restore original forground pixmap */
  2878. X        if (w == widgets.main.eject_btn)
  2879. X            set_btn_color(w, pixmaps.main.eject_pixmap, fg);
  2880. X        else if (w == widgets.main.poweroff_btn)
  2881. X            set_btn_color(w, pixmaps.main.poweroff_pixmap, fg);
  2882. X        else if (w == widgets.main.dbprog_btn)
  2883. X            set_btn_color(w, pixmaps.main.dbprog_pixmap, fg);
  2884. X        else if (w == widgets.main.help_btn)
  2885. X            set_btn_color(w, pixmaps.main.help_pixmap, fg);
  2886. X        else if (w == widgets.main.time_btn)
  2887. X            set_btn_color(w, pixmaps.main.time_pixmap, fg);
  2888. X        else if (w == widgets.main.ab_btn)
  2889. X            set_btn_color(w, pixmaps.main.ab_pixmap, fg);
  2890. X        else if (w == widgets.main.sample_btn)
  2891. X            set_btn_color(w, pixmaps.main.sample_pixmap, fg);
  2892. X        else if (w == widgets.main.keypad_btn)
  2893. X            set_btn_color(w, pixmaps.main.keypad_pixmap, fg);
  2894. X        else if (w == widgets.main.level_scale)
  2895. X            set_scale_color(w, fg);
  2896. X        else if (w == widgets.main.playpause_btn)
  2897. X            set_btn_color(w, pixmaps.main.playpause_pixmap, fg);
  2898. X        else if (w == widgets.main.stop_btn)
  2899. X            set_btn_color(w, pixmaps.main.stop_pixmap, fg);
  2900. X        else if (w == widgets.main.prevtrk_btn)
  2901. X            set_btn_color(w, pixmaps.main.prevtrk_pixmap, fg);
  2902. X        else if (w == widgets.main.nexttrk_btn)
  2903. X            set_btn_color(w, pixmaps.main.nexttrk_pixmap, fg);
  2904. X        else if (w == widgets.main.previdx_btn)
  2905. X            set_btn_color(w, pixmaps.main.previdx_pixmap, fg);
  2906. X        else if (w == widgets.main.nextidx_btn)
  2907. X            set_btn_color(w, pixmaps.main.nextidx_pixmap, fg);
  2908. X        else if (w == widgets.main.rew_btn)
  2909. X            set_btn_color(w, pixmaps.main.rew_pixmap, fg);
  2910. X        else if (w == widgets.main.ff_btn)
  2911. X            set_btn_color(w, pixmaps.main.ff_pixmap, fg);
  2912. X
  2913. X        count--;
  2914. X    }
  2915. X    else if (ev->type == FocusIn) {
  2916. X        if (count >= 1)
  2917. X            return;
  2918. X
  2919. X        /* Set new highlighted forground pixmap */
  2920. X        if (w == widgets.main.eject_btn)
  2921. X            set_btn_color(w, pixmaps.main.eject_hlpixmap, hl);
  2922. X        else if (w == widgets.main.poweroff_btn)
  2923. X            set_btn_color(w, pixmaps.main.poweroff_hlpixmap, hl);
  2924. X        else if (w == widgets.main.dbprog_btn)
  2925. X            set_btn_color(w, pixmaps.main.dbprog_hlpixmap, hl);
  2926. X        else if (w == widgets.main.help_btn)
  2927. X            set_btn_color(w, pixmaps.main.help_hlpixmap, hl);
  2928. X        else if (w == widgets.main.time_btn)
  2929. X            set_btn_color(w, pixmaps.main.time_hlpixmap, hl);
  2930. X        else if (w == widgets.main.ab_btn)
  2931. X            set_btn_color(w, pixmaps.main.ab_hlpixmap, hl);
  2932. X        else if (w == widgets.main.sample_btn)
  2933. X            set_btn_color(w, pixmaps.main.sample_hlpixmap, hl);
  2934. X        else if (w == widgets.main.keypad_btn)
  2935. X            set_btn_color(w, pixmaps.main.keypad_hlpixmap, hl);
  2936. X        else if (w == widgets.main.level_scale)
  2937. X            set_scale_color(w, hl);
  2938. X        else if (w == widgets.main.playpause_btn)
  2939. X            set_btn_color(w, pixmaps.main.playpause_hlpixmap, hl);
  2940. X        else if (w == widgets.main.stop_btn)
  2941. X            set_btn_color(w, pixmaps.main.stop_hlpixmap, hl);
  2942. X        else if (w == widgets.main.prevtrk_btn)
  2943. X            set_btn_color(w, pixmaps.main.prevtrk_hlpixmap, hl);
  2944. X        else if (w == widgets.main.nexttrk_btn)
  2945. X            set_btn_color(w, pixmaps.main.nexttrk_hlpixmap, hl);
  2946. X        else if (w == widgets.main.previdx_btn)
  2947. X            set_btn_color(w, pixmaps.main.previdx_hlpixmap, hl);
  2948. X        else if (w == widgets.main.nextidx_btn)
  2949. X            set_btn_color(w, pixmaps.main.nextidx_hlpixmap, hl);
  2950. X        else if (w == widgets.main.rew_btn)
  2951. X            set_btn_color(w, pixmaps.main.rew_hlpixmap, hl);
  2952. X        else if (w == widgets.main.ff_btn)
  2953. X            set_btn_color(w, pixmaps.main.ff_hlpixmap, hl);
  2954. X
  2955. X        count++;
  2956. X    }
  2957. X}
  2958. X
  2959. X/***************** ^^ Event Handlers ^^ ******************/
  2960. X
  2961. END_OF_FILE
  2962. if test 55680 -ne `wc -c <'cdfunc.c'`; then
  2963.     echo shar: \"'cdfunc.c'\" unpacked with wrong size!
  2964. fi
  2965. # end of 'cdfunc.c'
  2966. fi
  2967. echo shar: End of archive 5 \(of 13\).
  2968. cp /dev/null ark5isdone
  2969. MISSING=""
  2970. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 ; do
  2971.     if test ! -f ark${I}isdone ; then
  2972.     MISSING="${MISSING} ${I}"
  2973.     fi
  2974. done
  2975. if test "${MISSING}" = "" ; then
  2976.     echo You have unpacked all 13 archives.
  2977.     echo "Now read the README and INSTALL files for further instructions."
  2978.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2979. else
  2980.     echo You still need to unpack the following archives:
  2981.     echo "        " ${MISSING}
  2982. fi
  2983. ##  End of shell archive.
  2984. exit 0
  2985. -- 
  2986.     ///  Ti Kan                vorsprung durch technik
  2987.    ///   AMB Research Laboratories, Sunnyvale, CA. USA
  2988.   ///    ti@amb.org
  2989.  //////  ...!{decwrl,synopsys,tandem,tsoft,ultra}!sgiblab!bazooka!ti
  2990. ///      ...!uunet!bazooka!ti
  2991.  
  2992.  
  2993.  
  2994. exit 0 # Just in case...
  2995. -- 
  2996.   // chris@Sterling.COM           | Send comp.sources.x submissions to:
  2997. \X/  Amiga: The only way to fly!  |    sources-x@sterling.com
  2998.        "It's intuitively obvious to the most casual observer..."
  2999.  GCS d++(--) -p+ c++ !l u++ e+ m+(-) s++/++ n h--- f+ g+++ w+ t++ r+ y+
  3000.