home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-03-14 | 56.0 KB | 1,720 lines |
- Newsgroups: comp.sources.misc
- From: pwolfe@blizzard.kai.com (Patrick Wolfe)
- Subject: v28i082: cdreader - Audio CD player for SGI's, Part01/01
- Message-ID: <1992Mar7.183159.22096@sparky.imd.sterling.com>
- X-Md4-Signature: 0e5751a4b4f3c064ea19f7aeb703e90e
- Date: Sat, 7 Mar 1992 18:31:59 GMT
- Approved: kent@sparky.imd.sterling.com
-
- Submitted-by: pwolfe@blizzard.kai.com (Patrick Wolfe)
- Posting-number: Volume 28, Issue 82
- Archive-name: cdreader/part01
- Environment: SGI
-
- Cdreader plays an audio compact disc on Silicon Graphics workstations with an
- Audio Processor (the SGI Indigo, for example). Cdreader compiles only under
- release 4.0.1 (or later) of the Irix operating system.
-
- Version 1.4 sports an X11/Motif interface, and a new "shuffle" function.
-
- This is NOT just like SGI's "cdplayer" program, which simply commands the CD
- drive to play an audio CD, and sits back to watch. In that case, the digital
- CD data is converted to analog inside the CDrom drive, and the analog audio
- output is sent to the headphone jack on the front and the audio out jacks on
- the back of the drive. Without headphones or a stereo, you can't hear anything.
- Even with them, the sound is very quiet, and somewhat distorted.
-
- Cdreader uses SGI's libcdaudio routines to read the digital data directly from
- the CD, and sends it to the Audio Processor for conversion to analog audio
- data. You can listen on the Indigo's monophonic speaker, or even better, buy a
- cable with a stereo mini-plug on one end, and two phono plugs on the other, and
- connect from your Indigo's lineout jack to your stereo amplifier's cd-in (or
- tape-in) jacks. Enjoy!
-
- Patrick Wolfe (pwolfe@kai.com, uunet!kailand!pwolfe)
-
- --- cut here --- cut here --- cut here --- cut here --- cut here ---
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then feed it
- # into a shell via "sh file" or similar. To overwrite existing files,
- # type "sh file -c".
- # The tool that generated this appeared in the comp.sources.unix newsgroup;
- # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
- # Contents: Makefile Readme cdreader.1 cdreader.c cdreader.icon
- # Wrapped by kent@sparky on Sat Mar 7 12:27:41 1992
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- echo If this archive is complete, you will see the following message:
- echo ' "shar: End of archive 1 (of 1)."'
- if test -f 'Makefile' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Makefile'\"
- else
- echo shar: Extracting \"'Makefile'\" \(3078 characters\)
- sed "s/^X//" >'Makefile' <<'END_OF_FILE'
- X# Makefile for cdreader
- X
- X# IRIX401_CDREADDA_BUG - workaround for bug in CDreadda() routine
- X# as distributed in Irix 4.0.1, and supposed to be fixed in
- X# the next Irix release. See cdreader.c for details.
- X# AFTER this bug is fixed, remove this option and recompile!
- XDEFS = -DIRIX401_CDREADDA_BUG
- X
- XCFLAGS = -O -s $(DEFS)
- X#CFLAGS = -g -DTESTING $(DEFS)
- X
- X# SGI CD Audio library routines
- XCDLIBS = -lcdaudio -lds
- X
- X# SGI Audio Processor library routines
- XAUDIOLIBS = -laudio
- X
- X# X11/Motif window libraries
- X# The shared libraries make for a smaller executable, and are PREFERRED,
- X# but then the program will only run on systems that have them installed
- X
- X# shared libraries make an executable that's only 168 Kb!
- XXLIBS = -lXm_s -lXt_s -lX11_s -lPW
- X
- X# non shared libraries make an executable that's over 1 Mb tall!
- X#XLIBS = -lXm -lXt -lX11 -lPW
- X
- XLIBS = $(XLIBS) $(CDLIBS) $(AUDIOLIBS) -lc_s
- XFILES = Readme cdreader.c Makefile cdreader.icon cdreader.1
- XBIN = /usr/local/bin
- XICONDIR = /usr/lib/images
- XMANDIR = /usr/catman/local/man1
- X
- Xall: cdreader
- X
- Xcdreader: cdreader.o
- X rm -f cdreader
- X $(CC) -o cdreader $(CFLAGS) cdreader.o $(LIBS)
- X
- Xcdreader.1nr: cdreader.1
- X nroff -man cdreader.1 > cdreader.1nr
- X
- Xinstall: $(BIN)/cdreader $(MANDIR)/cdreader.1 $(ICONDIR)/cdreader.icon
- X
- X$(BIN)/cdreader: cdreader
- X rm -f $(BIN)/cdreader
- X cp cdreader $(BIN)
- X chmod 755 $(BIN)/cdreader
- X ls -l $(BIN)/cdreader
- X
- X$(MANDIR)/cdreader.1: cdreader.1
- X rm -f $(MANDIR)/cdreader.1
- X cp cdreader.1 $(MANDIR)/cdreader.1
- X chmod 644 $(MANDIR)/cdreader.1
- X ls -l $(MANDIR)/cdreader.1
- X
- X$(ICONDIR)/cdreader.icon: cdreader.icon
- X rm -f $(ICONDIR)/cdreader.icon
- X cp cdreader.icon $(ICONDIR)/cdreader.icon
- X chmod 644 $(ICONDIR)/cdreader.icon
- X ls -l $(ICONDIR)/cdreader.icon
- X
- Xdeinstall:
- X rm -f $(BIN)/cdreader
- X
- Xlint:
- X lint -uvxz cdreader.c
- X
- Xshar: $(FILES)
- X rm -f cdreader.shar
- X shar $(FILES) > cdreader.shar
- X ls -l cdreader.shar
- X
- Xclean:
- X rm -f a.out core mklog cdreader cdreader.shar *.o
- X
- X#
- X# Original Author: Patrick Wolfe (pwolfe@kai.com, uunet!kailand!pwolfe)
- X#
- X# This software is Copyright (c) 1992 by Patrick J. Wolfe.
- X#
- X# Permission is hereby granted to copy, distribute or otherwise
- X# use any part of this package as long as you do not try to make
- X# money from it or pretend that you wrote it. This copyright
- X# notice must be maintained in any copy made.
- X#
- X# Use of this software constitutes acceptance for use in an AS IS
- X# condition. There are NO warranties with regard to this software.
- X# In no event shall the author be liable for any damages whatsoever
- X# arising out of or in connection with the use or performance of this
- X# software. Any use of this software is at the user's own risk.
- X#
- X# If you make modifications to this software that you feel
- X# increases it usefulness for the rest of the community, please
- X# email the changes, enhancements, bug fixes as well as any and
- X# all ideas to me. This software is going to be maintained and
- X# enhanced as deemed necessary by the community.
- X#
- X# Patrick J. Wolfe
- X# uunet!kailand!pwolfe
- X# pwolfe@kai.com
- X#
- END_OF_FILE
- if test 3078 -ne `wc -c <'Makefile'`; then
- echo shar: \"'Makefile'\" unpacked with wrong size!
- fi
- # end of 'Makefile'
- fi
- if test -f 'Readme' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Readme'\"
- else
- echo shar: Extracting \"'Readme'\" \(8070 characters\)
- sed "s/^X//" >'Readme' <<'END_OF_FILE'
- X------------------------------------------------------------------------------
- X WHAT IS CDREADER?
- X
- XCdreader plays an audio compact disc on Silicon Graphics workstations with an
- XAudio Processor (the SGI Indigo, for example). Cdreader compiles only under
- Xrelease 4.0.1 (or later) of the Irix operating system.
- X
- XVersion 1.4 sports an X11/Motif interface, and a new "shuffle" function.
- X
- XThis is NOT just like SGI's "cdplayer" program, which simply commands the CD
- Xdrive to play an audio CD, and sits back to watch. In that case, the digital
- XCD data is converted to analog inside the CDrom drive, and the analog audio
- Xoutput is sent to the headphone jack on the front and the audio out jacks on
- Xthe back of the drive. Without headphones or a stereo, you can't hear anything.
- XEven with them, the sound is very quiet, and somewhat distorted.
- X
- XCdreader uses SGI's libcdaudio routines to read the digital data directly from
- Xthe CD, and sends it to the Audio Processor for conversion to analog audio
- Xdata. You can listen on the Indigo's monophonic speaker, or even better, buy a
- Xcable with a stereo mini-plug on one end, and two phono plugs on the other, and
- Xconnect from your Indigo's lineout jack to your stereo amplifier's cd-in (or
- Xtape-in) jacks. Enjoy!
- X
- XWARNING! If you were just using SGI's "cdplayer" program, turn down the volume
- Xbefore starting "cdreader" or you'll risk damaging your equipment (and ears)!
- X
- XCdreader will probably only work with an SGI's cdrom drive. The program will
- Xtell you if your cdrom drive doesn't support reading audio over the SCSI bus.
- XIt uses about 5-6% of the cpu, and 4% of the SCSI bus bandwidth. Use of other
- Xprograms which change the audio processor's parameters is discouraged (but sure
- Xcan make you laugh).
- X
- XThe schedctl() system call in cdreader will (silently) fail unless the program
- Xis installed setuid root, or your kernel configuration is modified to allow
- Xnon-root users to use non-degrading priorities. See the SCHEDCTL(2) and
- XAUTOCONFIG(1M) manpages, and the Irix Programming Guide Vol 2, section 14.2.3
- Xfor complete details. That's what I did, and it's pretty easy! Basically,
- Xbecome superuser, edit /usr/sysgen/master.d/disp, find the variable
- X"ndpri_hilim", change it's value to "NDPHIMAX", run "autoconfig" and reboot.
- X
- XSome people think the delay is caused by disk I/O, but believe me it's not.
- XThat's what I thought, originally, but Mark Callow of SGI corrected me, and
- Xput me onto the fixes.
- X
- XI wrote cdreader on a 16 Mb SGI Indigo running Irix 4.0.1.
- X
- X Patrick Wolfe (pwolfe@kai.com, uunet!kailand!pwolfe)
- X
- X------------------------------------------------------------------------------
- X RELEASE NOTES:
- X
- XVERSION 1.4:
- X
- XDistributed to comp.sources.misc.
- X
- XAdded shuffle, tracks and info buttons. Shuffle plays the whole disc, but in
- Xrandom order. Tracks displays the list and length of tracks, like "cdinfo"
- Xdid. Info displays some information about the program and programmer. Also,
- Xupdated the online help screen to be more useful.
- X
- XAlso, reorganized code so that the program "should" run on any sgi irix 4.0.1
- Xsystem, whether you have a cd drive and audio processor or not. Of course, it
- Xwon't do you any good, but those folks interested in using this program as an
- Xexample for X11/Motif programming won't mind too much.
- X
- XPut all of the commonly used messages and words in defines, for easy
- Xcustomization and translation to foreign languages.
- X
- XFixed next and prev buttons to work in stopped mode, for selecting which track
- Xto start playing on.
- X
- XDiscovered what happens when you have the highest priority task on your system
- Xgo into a cpu loop. I know, I know, I shouldn't put bugs in my programs. It's
- Xunproductive.
- X
- XVERSION 1.3:
- X
- XSports an X11/Motif user interface. Much nicer. Also displays program status
- Xin a window above the buttons. Not distributed.
- X
- XVERSION 1.2:
- X
- XSports an X11 user interface (using Athena Widgets). Much nicer, but not
- Xperfect. I like being to pause it without killing it. Not distributed.
- X
- XCdreader now has a nice Motif style user interface. I removed all of the debug
- Xcode and command line options, since mostly people just want to play cd's from
- Xstart to end, possibly pausing at random points. At least, that's all I do.
- XSorry, no "scan" buttons. How much did you pay for this program anyway?
- X
- XVERSION 1.1:
- X
- XThis version was posted to comp.sys.sgi.
- X
- XCdreader has been improved in that it buffers up enough audio data to eliminate
- Xpractically all pauses in the music that occurred previously. I was informed
- Xthat these were apparently due to cpu conflicts during large amounts of
- Xgraphics scrolling.
- X
- XVERSION 1.0:
- X
- XThis version was uploaded to uunet's ~ftp/tmp directory via anonymous ftp
- X(don't bother checking, it's not there anymore) and announced in comp.sys.sgi.
- X
- XIt was my first (barely) working version of this program.
- X
- X------------------------------------------------------------------------------
- X MISC NOTES:
- X
- XThere is a minor error in Irix 4.0.1's cdaudio.h include file which causes
- Xwarning messages complaining about an extra comma. Ignore them, or fix the
- Xinclude file. Also, some manpages for CD routines are incorrect, or contain
- Xtypos. These are all supposed to be fixed in the next Irix release.
- X
- XWhile working on cdreader, I discovered a problem in the SGI CD audio library
- Xroutine CDreadda(). See comments in the source code. I've been told that this
- Xis fixed in the next Irix release, so after you upgrade, be sure to remove the
- X-DIRIX401_CDREADDA_BUG from the Makefile and recompile.
- X
- XThere is a 2-4 second delay for anything to happen (play, pause, stop).
- XThat's because of the huge audio buffer being used.
- X
- XA couple advantages of my cdreader over SGI's cdplayer program:
- X
- X- There is a noticible clicking noise coming out of my cdrom drive's audio
- X jacks (where the audio output comes when running SGI's cdplayer). This is
- X not the clicking that some people describe when the audio pauses due to cpu
- X scheduling conflicts, it's some distortion, apparently from the cdrom drive
- X motor. I don't know if this problem is common to all cdrom drives, but it
- X sure is annoying. Cdreader's output is the DAC jacks on the back of the
- X Indigo, and doesn't have this problem.
- X
- X- When using SGI's cdplayer, the volume coming out of the audio jacks on the
- X back of the SGI CDrom drive is very low. You really have to jack up the
- X volume on your amp higher than normal.
- X
- X- The CD doesn't spin while in "stopped" or "paused" modes.
- X
- XTHANK YOU SGI, for making such wonderful libraries available. They make
- Xmy Indigo an extremely fun machine to use.
- X
- X Patrick Wolfe (pwolfe@kai.com, uunet!kailand!pwolfe)
- X System Programmer/Operations Manager, Kuck & Associates
- X
- X
- X------------------------------------------------------------------------------
- X LEGAL JUNK:
- X
- X/*
- X * Original Author: Patrick Wolfe (pwolfe@kai.com, uunet!kailand!pwolfe)
- X *
- X * This software is Copyright (c) 1992 by Patrick J. Wolfe.
- X *
- X * Permission is hereby granted to copy, distribute or otherwise
- X * use any part of this package as long as you do not try to make
- X * money from it or pretend that you wrote it. This copyright
- X * notice must be maintained in any copy made.
- X *
- X * Use of this software constitutes acceptance for use in an AS IS
- X * condition. There are NO warranties with regard to this software.
- X * In no event shall the author be liable for any damages whatsoever
- X * arising out of or in connection with the use or performance of this
- X * software. Any use of this software is at the user's own risk.
- X *
- X * If you make modifications to this software that you feel
- X * increases it usefulness for the rest of the community, please
- X * email the changes, enhancements, bug fixes as well as any and
- X * all ideas to me. This software is going to be maintained and
- X * enhanced as deemed necessary by the community.
- X *
- X * Patrick J. Wolfe
- X * uunet!kailand!pwolfe
- X * pwolfe@kai.com
- X */
- X------------------------------------------------------------------------------
- END_OF_FILE
- if test 8070 -ne `wc -c <'Readme'`; then
- echo shar: \"'Readme'\" unpacked with wrong size!
- fi
- # end of 'Readme'
- fi
- if test -f 'cdreader.1' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'cdreader.1'\"
- else
- echo shar: Extracting \"'cdreader.1'\" \(2203 characters\)
- sed "s/^X//" >'cdreader.1' <<'END_OF_FILE'
- X.TH CDREADER 1 "V1.4" "Usenet Software" "Usenet software"
- X
- X.SH NAME
- Xcdreader \- play an audio compact disc through the audio processor
- X
- X.SH SYNOPSIS
- X.B cdreader
- X
- X.SH DESCRIPTION
- X.B Cdreader
- Xplays an audio compact disc through the audio processor.
- X
- XIt opens a window with several buttons, whose function is similar to those on a
- Xaudio CD player. Above the buttons is a message display, where the state of
- Xthe program is displayed. When playing music, the track number and length
- Xappear here.
- X
- X.B Cdreader
- Xperforms much better when installed setuid root, or if you
- Xreconfigure your Irix operating system to allow non-root
- Xusers to use non-degrading priorities. See the
- X.I schedctl(2)
- Xand
- X.I autoconfig(1M)
- Xmanpages, and the
- X.I Irix Programming Guide Vol 2
- Xsection 14.2.3 for complete details (It's easy).
- X
- XThere is a 2-4 second delay for anything to happen (Play, Pause, Stop). This
- Xis because of the large audio buffer being used. It takes time to fill it up
- Xand empty it out. Other than that, and the weird things the buttons do
- Xoccationally, everything works fine.
- X
- X.SH "BUTTONS"
- XSeveral buttons appear in the main
- X.B Cdreader
- Xwindow. They are:
- X
- X.TP
- X.I Play
- XIf stopped, begins playing the first track of an audio CD.
- XIf paused, continues where you left off.
- X.TP
- X.I Pause
- XSuspends audio playback. Press Play to continue.
- X.TP
- X.I Shuffle
- XBegins playing all the tracks on the CD, but in a random order.
- X.TP
- X.I Stop
- XStops audio playback. Resets the current location to the
- Xfirst track of the CD.
- X.TP
- X.I Prev
- Xswitches to the beginning of the previous track.
- X.TP
- X.I Next
- Xswitches to the beginning of the next track. If you press
- XNext while on the last track, playback stops.
- X.TP
- X.I Tracks
- Xdisplays a list of tracks and their lengths. Sorry, but the
- Xnames of the songs is NOT encoded on the CD. Bummer.
- X.TP
- X.I Eject
- XCauses the CD caddy to be ejected from the CDrom drive.
- X.TP
- X.I Quit
- Xcloses the window and terminates the cdreader program.
- X.TP
- X.I Info
- Xdisplays information about the program and programmer.
- X.TP
- X.I Help
- Xdisplays an online help window
- X
- X.SH "SEE ALSO"
- Xcdplayer(1), apanel(1)
- X
- X.SH "AUTHOR"
- X.B Cdreader
- Xis Copyright (c) 1992 by Patrick J. Wolfe,
- X(pwolfe@kai.com, uunet!kailand!pwolfe).
- END_OF_FILE
- if test 2203 -ne `wc -c <'cdreader.1'`; then
- echo shar: \"'cdreader.1'\" unpacked with wrong size!
- fi
- # end of 'cdreader.1'
- fi
- if test -f 'cdreader.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'cdreader.c'\"
- else
- echo shar: Extracting \"'cdreader.c'\" \(34681 characters\)
- sed "s/^X//" >'cdreader.c' <<'END_OF_FILE'
- X/*
- X * cdreader - Plays an audio CD through the SGI Audio Processor.
- X * You can play CDs through the monophonic speaker on your SGI Indigo,
- X * or you can connect an amp to the line-out jacks for some
- X * REAL quality sound.
- X *
- X * Original Author: Patrick Wolfe (pwolfe@kai.com, uunet!kailand!pwolfe)
- X * This software is Copyright (c) 1992 by Patrick J. Wolfe.
- X * See the end of this file for the complete copyright notice.
- X */
- X
- X#define VERSION "1.4"
- X
- X#include <stdio.h>
- X#include <stdlib.h>
- X#include <sys/types.h>
- X /* for errno */
- X#include <errno.h>
- X /* for signal() */
- X#include <signal.h>
- X /* for getopt() */
- X#include <getopt.h>
- X /* for CD*() routines */
- X#include <cdaudio.h>
- X /* for AL*() routines */
- X#include <audio.h>
- X /* for schedctl() */
- X#include <limits.h>
- X#include <sys/prctl.h>
- X#include <sys/schedctl.h>
- X /* for X11/Motif interface */
- X#include <X11/Intrinsic.h>
- X#include <Xm/Xm.h>
- X#include <Xm/CascadeB.h>
- X#include <Xm/Frame.h>
- X#include <Xm/MainW.h>
- X#include <Xm/PushB.h>
- X#include <Xm/PushBG.h>
- X#include <Xm/RowColumn.h>
- X#include <Xm/MessageB.h>
- X#include <Xm/Form.h>
- X
- X#ifdef WATCH_ABUF
- X /* for setitimer */
- X#include <sys/time.h>
- Xint monitor_interval = 15; /* number of seconds between abufs left reports */
- Xint show_bufsleft = 0; /* flag to indicate that it's time to report */
- Xint total_samps = 0; /* number of samples the audio buffer will hold */
- X#endif /* WATCH_ABUF */
- X
- X/*
- X * Most of the common messages are here, for easy customization and
- X * translation for foreign languages. We're not ALL ignorant bastards.
- X */
- X
- X /* button labels */
- X#define PLAY_NAME "Play"
- X#define PREV_NAME "Prev"
- X#define PAUSE_NAME "Pause"
- X#define NEXT_NAME "Next"
- X#define SHUFFLE_NAME "Shuffle"
- X#define TRACKS_NAME "Tracks"
- X#define STOP_NAME "Stop"
- X#define EJECT_NAME "Eject"
- X#define QUIT_NAME "Quit"
- X#define INFO_NAME "Info"
- X#define HELP_NAME "Help"
- X
- X /* status messages */
- Xchar *Playing_Msg = "Playing Track";
- Xchar *Stopped_Msg = "Stopped";
- Xchar *Paused_Msg = "Paused at Track";
- Xchar *Total_Msg = "Total time on disk";
- Xchar *Track_Word = "Track";
- Xchar *Length_Word = "Length";
- X
- X /* error messages */
- Xchar *DISC_NOT_READY = "Disc Not Ready";
- Xchar *CANNOT_READ_SCSI = "\
- XYour cheapo CDrom drive does NOT support reading audio data\n\
- Xacross the SCSI bus. You should have bought one from SGI!";
- Xchar *TOO_MANY_TRACKS = "Too many audio tracks on this disc!\nrecompile with larger MAX_TRACK_INFO.";
- Xchar *CDOPEN_FAILED = "CDopen failed\nCannot Open CDrom device";
- Xchar *CDGETSTATUS_FAILED = "CDgetstatus failed\nCannot get status of CDrom device";
- Xchar *CDGETTRACKINFO_FAILED = "CDgettrackinfo failed";
- Xchar *CDSEEKTRACK_FAILED = "CDseektrack failed\nCannot find track";
- Xchar *CDEJECT_FAILED = "cannot eject disc - not stopped";
- X
- X
- X
- X#define SAMPLES_PER_FRAME (CDDA_DATASIZE/2)
- X
- X/* valid states for main process loop control */
- X#define STOPPED 0 /* we are stopped */
- X#define PAUSED 1 /* we were playing, and are now paused */
- X#define PLAYING 2 /* we are playing music */
- X#define STARTING 3 /* start playing at beginning of the disk */
- X#define CONTINUE 4 /* start playing where you left off */
- X#define STOPPING 5 /* we were playing, and are about to stop */
- X#define PAUSING 6 /* we were playing, and are about to pause */
- X#define START_TRACK 9 /* start playing at the beginning of the current track */
- X
- X/* maximum number of tracks to store info for */
- X/* I *have* seen up to 28 tracks on a single CD, but none longer */
- X#define MAX_TRACK_INFO 64
- X
- X /* audio stuff */
- XALport audio_port = NULL;
- XCDPLAYER *cd_device = NULL;
- XCDPARSER *cd_parser = NULL;
- XCDFRAME *cd_buffer = NULL;
- X
- X /* cd stuff */
- Xstruct cdinformation {
- X short length_min; /* track length */
- X short length_sec;
- X } track_info[MAX_TRACK_INFO];
- Xint first_track = 0; /* first track on the disk */
- Xint last_track = 0; /* index into track_info for entry AFTER last one we have info for */
- Xint current_track = -1; /* number of track currently playing */
- Xint total_min = 0; /* minutes part of total running time on current disk */
- Xint total_sec = 0; /* second part of total running time on current disk */
- Xint play_index = -1; /* index into playlist for shuffle mode, -1 means that shuffle is not on */
- Xint play_list[MAX_TRACK_INFO]; /* order of tracks to play */
- Xint cd_readsize = 12; /* the normal number of frames to read at one time (CDbestreadsize fills this in) */
- Xint cd_init_readsize = 200; /* initial number of frames to read at the beginning of the disc */
- Xint status = STOPPING; /* main process loop status */
- X
- X /* X11 stuff */
- XXtAppContext appcon;
- XWidget main_window,
- X label,
- X play_button,
- X prev_button,
- X pause_button,
- X next_button,
- X shuffle_button,
- X tracks_button,
- X info_button,
- X stop_button,
- X eject_button;
- Xstatic XmStringCharSet charset = (XmStringCharSet) XmSTRING_DEFAULT_CHARSET;
- X
- X
- XDisplay_Warning (message)
- Xchar *message;
- X{
- XWidget button;
- XWidget warning_box;
- XXmString title_string = NULL;
- XXmString message_string = NULL;
- XArg args[4];
- Xregister int n;
- X
- Xmessage_string = XmStringCreateLtoR (message, charset);
- Xtitle_string = XmStringCreateLtoR ("Cdreader Warning!", charset);
- X
- Xn = 0;
- XXtSetArg (args[n], XmNdialogTitle, title_string); n++;
- XXtSetArg (args[n], XmNmessageString, message_string); n++;
- Xwarning_box = XmCreateWarningDialog (main_window, "warning", args, n);
- Xbutton = XmMessageBoxGetChild (warning_box, XmDIALOG_CANCEL_BUTTON);
- XXtUnmanageChild (button);
- Xbutton = XmMessageBoxGetChild (warning_box, XmDIALOG_HELP_BUTTON);
- XXtUnmanageChild (button);
- Xif (title_string) XtFree (title_string);
- Xif (message_string) XtFree (message_string);
- XXtManageChild (warning_box);
- X}
- X
- X
- Xset_message (message)
- Xchar *message;
- X{
- XXmString label_string;
- XArg args[30];
- Xint ctr;
- X
- Xctr = 0;
- Xlabel_string = XmStringCreate (message, charset);
- XXtSetArg (args[ctr], XmNlabelString, label_string); ctr++;
- XXtSetValues (label, args, ctr);
- XXmStringFree (label_string);
- X}
- X
- X
- Xint
- Xget_track_info ()
- X{
- XCDSTATUS cd_status;
- XCDTRACKINFO cd_info;
- X
- Xif ((cd_device == NULL) && ((cd_device = CDopen(0, "r")) == NULL)) {
- X Display_Warning (CDOPEN_FAILED);
- X return (1);
- X }
- X
- X/* display disk info */
- Xif (CDgetstatus(cd_device, &cd_status) == 0) {
- X status = STOPPING;
- X Display_Warning (CDGETSTATUS_FAILED);
- X return (1);
- X }
- X/* don't start unless it's ready */
- Xif (cd_status.state != CD_READY) {
- X status = STOPPING;
- X Display_Warning (DISC_NOT_READY);
- X return (1);
- X }
- Xif (! cd_status.scsi_audio) {
- X status = STOPPING;
- X Display_Warning (CANNOT_READ_SCSI);
- X return (1);
- X }
- Xtotal_min = cd_status.total_min;
- Xtotal_sec = cd_status.total_sec;
- X
- X/* get track information */
- Xfor (first_track = last_track = cd_status.first;
- X (last_track <= cd_status.last) && (last_track < MAX_TRACK_INFO);
- X last_track++) {
- X if (CDgettrackinfo(cd_device, last_track, &cd_info) == 0) {
- X status = STOPPING;
- X Display_Warning (CDGETTRACKINFO_FAILED);
- X return (1);
- X }
- X track_info[last_track].length_min = cd_info.total_min;
- X track_info[last_track].length_sec = cd_info.total_sec;
- X }
- Xif (last_track >= MAX_TRACK_INFO) {
- X Display_Warning (TOO_MANY_TRACKS);
- X return (1);
- X }
- X
- X/* find the best number of frames to read at a time */
- Xcd_readsize = CDbestreadsize (cd_device);
- X
- Xreturn (0);
- X}
- X
- X
- X/* called as signal handler, and when the quit button is pressed */
- Xvoid
- Xquit_pgm ()
- X{
- XCDdeleteparser(cd_parser); /* free parser memory */
- Xif (cd_device != NULL) {
- X CDclose(cd_device); /* close CD player port */
- X }
- Xif (audio_port != NULL) {
- X ALcloseport(audio_port); /* close audio port */
- X }
- Xexit (0);
- X}
- X
- X
- X/* called by pressing the EJECT button */
- Xvoid
- Xeject_callback (w, client_data, call_data)
- XWidget w;
- Xcaddr_t client_data; /* unused */
- Xcaddr_t call_data; /* unused */
- X{
- Xif (status == STOPPED) {
- X if ((cd_device == NULL) && ((cd_device = CDopen(0, "r")) == NULL)) {
- X Display_Warning (CDOPEN_FAILED);
- X }
- X else {
- X CDeject(cd_device);
- X CDclose(cd_device);
- X cd_device = NULL;
- X }
- X }
- Xelse {
- X Display_Warning (CDEJECT_FAILED);
- X }
- X}
- X
- X
- X/* called by pressing the STOP button */
- Xvoid
- Xstop_callback (w, client_data, call_data)
- XWidget w;
- Xcaddr_t client_data; /* unused */
- Xcaddr_t call_data; /* unused */
- X{
- Xplay_index = -1;
- Xstatus = STOPPING;
- X}
- X
- X
- X/* called by pressing the PAUSE button */
- Xvoid
- Xpause_callback (w, client_data, call_data)
- XWidget w;
- Xcaddr_t client_data; /* unused */
- Xcaddr_t call_data; /* unused */
- X{
- Xif (status == PLAYING) {
- X status = PAUSING;
- X }
- X}
- X
- X
- X/* called by pressing the PLAY button */
- Xvoid
- Xplay_callback (w, client_data, call_data)
- XWidget w;
- Xcaddr_t client_data; /* unused */
- Xcaddr_t call_data; /* unused */
- X{
- Xif (status == STOPPED) {
- X status = STARTING;
- X }
- Xelse if (status == PAUSED) {
- X status = CONTINUE;
- X }
- X}
- X
- X
- X/* called by pressing the PREV button */
- Xvoid
- Xprev_callback (w, client_data, call_data)
- XWidget w;
- Xcaddr_t client_data; /* unused */
- Xcaddr_t call_data; /* unused */
- X{
- Xchar message[64];
- X
- Xif ((cd_device == NULL) && get_track_info()) { /* opens cd_device and gets track_info[] */
- X status = STOPPING;
- X return;
- X }
- X
- Xif ((status == PLAYING) || (status == PAUSED) || (status == STOPPED)) {
- X if (play_index == -1) {
- X current_track--;
- X if (current_track < first_track) {
- X current_track = first_track;
- X }
- X }
- X else { /* shuffling */
- X play_index--;
- X if (play_index < first_track) {
- X play_index = first_track;
- X }
- X current_track = play_list[play_index];
- X }
- X
- X if (CDseektrack(cd_device, current_track) == -1) {
- X (void) sprintf (message, "%s %d", CDSEEKTRACK_FAILED, current_track);
- X Display_Warning (message);
- X status = STOPPING;
- X }
- X else if (status == PLAYING) {
- X status = CONTINUE;
- X }
- X else {
- X status = PAUSING;
- X }
- X }
- X}
- X
- X
- X/* called by pressing the NEXT button */
- Xvoid
- Xnext_callback (w, client_data, call_data)
- XWidget w;
- Xcaddr_t client_data; /* unused */
- Xcaddr_t call_data; /* unused */
- X{
- Xchar message[64];
- X
- Xif ((cd_device == NULL) && get_track_info()) { /* opens cd_device and gets track_info[] */
- X status = STOPPING;
- X return;
- X }
- X
- Xif ((status == PLAYING) || (status == PAUSED) || (status == STOPPED)) {
- X if (play_index < 0) {
- X current_track++;
- X if (current_track >= last_track) {
- X current_track = first_track;
- X status = STOPPING;
- X return;
- X }
- X }
- X else { /* shuffling */
- X play_index++;
- X if (play_index >= last_track) {
- X current_track = first_track;
- X status = STOPPING;
- X return;
- X }
- X current_track = play_list[play_index];
- X }
- X
- X if (CDseektrack(cd_device, current_track) == -1) {
- X (void) sprintf (message, "%s %d", CDSEEKTRACK_FAILED, current_track);
- X Display_Warning (message);
- X status = STOPPING;
- X }
- X else if (status == PLAYING) {
- X status = CONTINUE;
- X }
- X else {
- X status = PAUSING;
- X }
- X }
- X}
- X
- X
- X/* called by pressing the SHUFFLE button
- X * plays all tracks on the disk in a random order
- X */
- Xvoid
- Xshuffle_callback (w, client_data, call_data)
- XWidget w;
- Xcaddr_t client_data; /* unused */
- Xcaddr_t call_data; /* unused */
- X{
- Xdouble jdb;
- Xint i, j, m, d = 1;
- Xint played[MAX_TRACK_INFO];
- X
- Xif (get_track_info()) { /* opens cd_device and gets track_info[] */
- X status = STOPPING;
- X return;
- X }
- X
- Xm = last_track - 1;
- X
- X/* initialize played array to -1's, indicating track hasn't been selected to play yet */
- Xfor (i = first_track; i < last_track; i++) {
- X played[i] = 0;
- X }
- X
- X/* seed is our process id */
- Xsrand ((u_int) getpid());
- X
- Xfor (i = first_track; i < last_track; i++) {
- X j = rand( );
- X jdb = (double)j / (double)(RAND_MAX + 1);
- X j = (int)(jdb * m) + 1;
- X for (; played[j]; j += d) {
- X if (j < first_track) {
- X j = last_track;
- X }
- X else if (j >= last_track) {
- X j = first_track;
- X }
- X }
- X d = d * -1; /* switch direction */
- X play_list[i] = j;
- X played[j] = 1;
- X }
- X
- Xplay_index = first_track;
- Xcurrent_track = play_list[play_index];
- Xstatus = START_TRACK;
- X}
- X
- X
- X/* called by pressing the TRACKS button */
- X/* show info about the entire disk */
- Xvoid
- Xtracks_callback (w, client_data, call_data)
- XWidget w;
- Xcaddr_t client_data; /* unused */
- Xcaddr_t call_data; /* unused */
- X{
- XWidget button;
- XWidget message_box;
- XXmString title_string = NULL;
- XXmString message_string = NULL;
- XXmString button_string = NULL;
- XArg args[4];
- Xregister int n;
- Xint track;
- Xchar message[4096];
- Xchar line[256];
- X
- Xif ((status == STOPPED) && get_track_info() ) {
- X return; /* if stopped, try to re-read the track info - might be a new disc */
- X }
- Xif ((status != PLAYING) && (status != PAUSED) && (status != STOPPED)) {
- X return; /* ignore this button during odd status changes */
- X }
- X(void) sprintf (message, "%s = %02d:%02d\n\n", Total_Msg, total_min, total_sec);
- X
- X/* show info about each track */
- Xfor (track = first_track; track < last_track; track++) {
- X (void) sprintf (line, "\t%s %2d: %s %02d:%02d\n", Track_Word, track, Length_Word,
- X track_info[track].length_min, track_info[track].length_sec);
- X (void) strcat (message, line);
- X }
- X
- Xtitle_string = XmStringCreateLtoR ("Cdreader Track List", charset);
- Xbutton_string = XmStringCreateLtoR ("Close", charset);
- Xmessage_string = XmStringCreateLtoR (message, charset);
- X
- Xn = 0;
- XXtSetArg (args[n], XmNdialogTitle, title_string); n++;
- XXtSetArg (args[n], XmNokLabelString, button_string); n++;
- XXtSetArg (args[n], XmNmessageString, message_string); n++;
- Xmessage_box = XmCreateMessageDialog (main_window, "tracks", args, n);
- Xbutton = XmMessageBoxGetChild (message_box, XmDIALOG_CANCEL_BUTTON);
- XXtUnmanageChild (button);
- Xbutton = XmMessageBoxGetChild (message_box, XmDIALOG_HELP_BUTTON);
- XXtUnmanageChild (button);
- Xif (title_string) XtFree (title_string);
- Xif (button_string) XtFree (button_string);
- Xif (message_string) XtFree (message_string);
- XXtManageChild (message_box);
- X}
- X
- X
- X/* called by pressing the INFO button */
- Xvoid
- Xinfo_callback (w, client_data, call_data)
- XWidget w;
- Xcaddr_t client_data; /* unused */
- Xcaddr_t call_data; /* unused */
- X{
- XWidget button;
- XWidget message_box;
- Xchar message[2048];
- XXmString title_string = NULL;
- XXmString message_string = NULL;
- XXmString button_string = NULL;
- XArg args[4];
- Xregister int n;
- X
- X(void) sprintf (message, "\
- XCdreader V%s plays an audio compact disc loaded in an SGI cdrom drive through\n\
- Xthe Audio Processor.\n\
- X\n\
- XCdreader uses the libcdaudio routines to read the digital data directly from\n\
- Xthe cdrom drive, and plays it through the Audio Processor. You can listen on\n\
- Xthe Indigo's speaker, or even better, buy a cable with a stereo mini-plug on\n\
- Xone end, and two phono plugs on the other, and connect from your Indigo's\n\
- Xline out jack to your stereo amplifier's cd in or tape in jacks.\n\
- X\n\
- XCdreader will probably only work with an SGI's cdrom drive and under release\n\
- X4.0.1 (or later) of the Irix operating system. The program will tell you if\n\
- Xyour cdrom drive doesn't support reading audio over the SCSI bus. It uses\n\
- Xabout 5-6%% of the cpu, and 4%% of the SCSI bus bandwidth. Use of other\n\
- Xprograms which change the audio processor's parameters is discouraged (but\n\
- Xsure can make you chuckle).\n\
- X\n\
- XOriginal Author:\n\
- X\tPatrick Wolfe\n\
- X\tSystem Programmer/Operations Manager\n\
- X\tKuck & Associates\n\
- X\t1906 Fox Drive\n\
- X\tChampaign, IL 61820\n\
- X\tInternet: pwolfe@kai.com\n\
- X\tUUCP: uunet!kailand!pwolfe\n\
- X\tvoice: (217) 356-2288\n\
- X\tFAX: (217) 356-5199\n\
- Xcopyright (c) 1992 Patrick J. Wolfe\n", VERSION);
- X
- Xmessage_string = XmStringCreateLtoR (message, charset);
- Xbutton_string = XmStringCreateLtoR ("Close", charset);
- Xtitle_string = XmStringCreateLtoR ("Cdreader Information", charset);
- X
- Xn = 0;
- XXtSetArg (args[n], XmNdialogTitle, title_string); n++;
- XXtSetArg (args[n], XmNokLabelString, button_string); n++;
- XXtSetArg (args[n], XmNmessageString, message_string); n++;
- Xmessage_box = XmCreateMessageDialog (w, "credit", args, n);
- Xbutton = XmMessageBoxGetChild (message_box, XmDIALOG_CANCEL_BUTTON);
- XXtUnmanageChild (button);
- Xbutton = XmMessageBoxGetChild (message_box, XmDIALOG_HELP_BUTTON);
- XXtUnmanageChild (button);
- Xif (title_string) XtFree (title_string);
- Xif (button_string) XtFree (button_string);
- Xif (message_string) XtFree (message_string);
- XXtManageChild (message_box);
- X}
- X
- X
- X/* called by pressing the HELP button */
- Xvoid
- Xhelp_callback (w, client_data, call_data)
- XWidget w;
- Xcaddr_t client_data; /* unused */
- Xcaddr_t call_data; /* unused */
- X{
- XWidget button;
- XWidget message_box;
- Xchar message[2048];
- XXmString title_string = NULL;
- XXmString message_string = NULL;
- XXmString button_string = NULL;
- XArg args[4];
- Xregister int n;
- X
- X(void) sprintf (message, "\
- XCdreader V%s plays an audio compact disc loaded in an SGI cdrom drive through\n\
- Xthe Audio Processor.\n\n\
- XTo get started, load an audio CD in the caddy, and insert it into your cd drive\n\
- Xwith the clear side of the caddy facing up.\n\n\
- XThe buttons function as follows:\n\
- X\tPlay - plays an audio disk\n\
- X\tShuffle - plays the whole disk in a random order\n\
- X\tStop - stops playback\n\
- X\tPause - suspends playback - press Play to continue\n\
- X\tNext - selects the next track\n\
- X\tPrev - selects the previous track\n\
- X\tTracks - displays a table of tracks and their lengths\n\n\
- X\tEject - ejects the disk from the cdrom drive\n\
- XThe buttons are context sensitive, for example, the eject button won't function\n\
- Xunless the program is in the \"Stopped\" state. Buttons are are not active will\n\
- Xappear dimly shaded.\n\n\
- XNear the top of the window is a menu bar. On the bar are three buttons:\n\
- X\tQuit - terminates the program\n\
- X\tInfo - give the author some credit!\n\
- X\tHelp - uh, you're looking at it\n\
- X", VERSION);
- X
- Xmessage_string = XmStringCreateLtoR (message, charset);
- Xbutton_string = XmStringCreateLtoR ("Close", charset);
- Xtitle_string = XmStringCreateLtoR ("Cdreader Help", charset);
- X
- Xn = 0;
- XXtSetArg (args[n], XmNdialogTitle, title_string); n++;
- XXtSetArg (args[n], XmNokLabelString, button_string); n++;
- XXtSetArg (args[n], XmNmessageString, message_string); n++;
- Xmessage_box = XmCreateMessageDialog (w, "helpbox", args, n);
- Xbutton = XmMessageBoxGetChild (message_box, XmDIALOG_CANCEL_BUTTON);
- XXtUnmanageChild (button);
- Xbutton = XmMessageBoxGetChild (message_box, XmDIALOG_HELP_BUTTON);
- XXtUnmanageChild (button);
- Xif (title_string) XtFree (title_string);
- Xif (button_string) XtFree (button_string);
- Xif (message_string) XtFree (message_string);
- XXtManageChild (message_box);
- X}
- X
- X
- X/* called only when the program (track) number changes */
- Xvoid
- Xcd_pnum_callback (arg, type, data)
- Xint arg;
- XCDDATATYPES type;
- Xstruct cdprognum *data;
- X{
- Xchar message[32];
- X
- Xif (play_index == -1) {
- X current_track = data->value;
- X (void) sprintf (message, "%s %d - %s %2d:%02d", Playing_Msg, current_track, Length_Word,
- X track_info[current_track].length_min,
- X track_info[current_track].length_sec);
- X set_message (message);
- X }
- Xelse if (data->value != current_track) { /* shuffling and the track changed */
- X play_index++;
- X if (play_index >= last_track) {
- X status = STOPPING;
- X }
- X else {
- X current_track = play_list[play_index];
- X status = START_TRACK;
- X }
- X }
- X}
- X
- X
- X/* called for every frame - data is already byte swapped and de-emphasized */
- Xvoid
- Xcd_audio_callback (arg, type, data)
- Xint arg;
- XCDDATATYPES type;
- Xvoid *data;
- X{
- XALwritesamps (audio_port, data, SAMPLES_PER_FRAME);
- X}
- X
- X
- Xint
- Xinit_audio ()
- X{
- XALconfig aconfig;
- Xlong pvbuf[6];
- X
- Xif (audio_port == NULL) {
- X /* initialize the audio port */
- X aconfig = ALnewconfig ();
- X
- X /*
- X * create the maximum size audio buffer we can,
- X * in another attempt to avoid pauses in the music.
- X */
- X ALsetqueuesize (aconfig, SAMPLES_PER_FRAME * cd_init_readsize);
- X
- X#ifdef WATCH_ABUF
- X total_samps = SAMPLES_PER_FRAME * cd_init_readsize;
- X printf ("allocating an audio buffer that can hold %d samples\n", total_samps);
- X#endif /* WATCH_ABUF */
- X
- X /*
- X * set the sample to 16 bit width and stereo. Yes, I know it these are the
- X * defaults ... TODAY, but I've gotten into trouble before by assuming the
- X * defaults would never change change. Besides, it doesn't hurt.
- X */
- X ALsetwidth (aconfig, AL_SAMPLE_16);
- X ALsetchannels (aconfig, AL_STEREO);
- X
- X audio_port = ALopenport ("cdreader", "w", aconfig);
- X
- X /* free audio port config buffer immediately */
- X ALfreeconfig(aconfig);
- X
- X if (audio_port == NULL) {
- X Display_Warning ("Could not open a port to the Audio Processor!");
- X return (1);
- X }
- X
- X /* set audio port output sampling rate to 44.1 kHz */
- X pvbuf[0] = AL_OUTPUT_RATE;
- X pvbuf[1] = AL_RATE_44100;
- X ALsetparams (AL_DEFAULT_DEVICE, pvbuf, 2);
- X }
- Xreturn (0);
- X}
- X
- X
- Xint
- Xinit_cd ()
- X{
- X/* allocate a buffer to read CD data into */
- Xif (cd_buffer == (CDFRAME *) NULL) {
- X cd_buffer = (CDFRAME *) malloc (cd_init_readsize * CDDA_BLOCKSIZE);
- X if (cd_buffer == (CDFRAME *) NULL) {
- X Display_Warning ("cannot allocate enough memory for a cd digital data buffer");
- X return (1);
- X }
- X }
- X
- X/* create parser structure */
- Xif (cd_parser == NULL) {
- X cd_parser = CDcreateparser ();
- X if (cd_parser == NULL) {
- X Display_Warning ("SERIOUS ERROR!\nCDcreateparser failed");
- X return (1);
- X }
- X
- X /* initialize parser structure */
- X CDresetparser(cd_parser);
- X
- X /* define callback routines for CDparseframe() */
- X CDsetcallback (cd_parser, cd_audio, cd_audio_callback, 0);
- X CDsetcallback (cd_parser, cd_pnum, cd_pnum_callback, 0);
- X }
- Xreturn (0);
- X}
- X
- X
- Xvoid
- Xinit_motif (argc, argv)
- Xint argc;
- Xchar **argv;
- X{
- XDisplay *display;
- XWidget app_shell, menu_bar, cascade, frame, form, row_column;
- XXmString label_string;
- XArg args[30];
- Xint ctr;
- X
- XXtToolkitInitialize ();
- Xappcon = XtCreateApplicationContext ();
- Xdisplay = XtOpenDisplay (appcon, NULL, "cdreader", "Cdreader", NULL, 0, &argc, argv);
- Xif (!display) {
- X XtWarning ("cdreader: Can't open your X display, exiting...");
- X exit (0);
- X }
- X
- Xapp_shell = XtAppCreateShell ("cdreader", "Cdreader", applicationShellWidgetClass, display, NULL, 0);
- X
- X/* XtGetApplicationResources (app_shell, &AppData, resources, XtNumber(resources), NULL, 0); */
- X
- Xctr = 0;
- Xmain_window = XmCreateMainWindow (app_shell, "main1", args, ctr);
- XXtManageChild (main_window);
- X
- Xctr = 0;
- Xmenu_bar = XmCreateMenuBar (main_window, "menu_bar", args, ctr);
- XXtManageChild (menu_bar);
- X
- Xctr = 0;
- Xcascade = XmCreateCascadeButton (menu_bar, "Quit", args, ctr);
- XXtManageChild (cascade);
- XXtAddCallback (cascade, XmNactivateCallback, quit_pgm, NULL);
- X
- Xctr = 0;
- Xcascade = XmCreateCascadeButton (menu_bar, "Info", args, ctr);
- XXtManageChild (cascade);
- XXtAddCallback (cascade, XmNactivateCallback, info_callback, NULL);
- X
- Xctr = 0;
- Xcascade = XmCreateCascadeButton (menu_bar, "Help", args, ctr);
- XXtManageChild (cascade);
- XXtAddCallback (cascade, XmNactivateCallback, help_callback, NULL);
- X
- X/* let the menu bar know who's the help button around here */
- Xctr = 0;
- XXtSetArg (args[ctr], XmNmenuHelpWidget, cascade); ctr++;
- XXtSetValues (menu_bar, args, ctr);
- X
- X/* create form to hold everything */
- Xctr = 0;
- Xform = XmCreateForm (main_window, "form", args, ctr);
- XXtManageChild (form);
- X
- X/* create label gadget inside frame */
- Xctr = 0;
- Xlabel_string = XmStringCreate ("Stopped", charset);
- XXtSetArg (args[ctr], XmNlabelString, label_string); ctr++;
- XXtSetArg (args[ctr], XmNwidth, 230); ctr++;
- XXtSetArg (args[ctr], XmNheight, 35); ctr++;
- XXtSetArg (args[ctr], XmNrecomputeSize, False); ctr++;
- XXtSetArg (args[ctr], XmNleftAttachment, XmATTACH_FORM); ctr++;
- XXtSetArg (args[ctr], XmNrightAttachment, XmATTACH_FORM); ctr++;
- XXtSetArg (args[ctr], XmNtopAttachment, XmATTACH_FORM); ctr++;
- Xlabel = XmCreateLabelGadget (form, "label", args, ctr);
- XXtManageChild (label);
- X
- X/* create frame mainwindow */
- Xctr = 0;
- XXtSetArg (args[ctr], XmNmarginWidth, 2); ctr++;
- XXtSetArg (args[ctr], XmNmarginHeight, 2); ctr++;
- XXtSetArg (args[ctr], XmNshadowThickness, 1); ctr++;
- XXtSetArg (args[ctr], XmNshadowType, XmSHADOW_OUT); ctr++;
- XXtSetArg (args[ctr], XmNleftAttachment, XmATTACH_FORM); ctr++;
- XXtSetArg (args[ctr], XmNrightAttachment, XmATTACH_FORM); ctr++;
- XXtSetArg (args[ctr], XmNtopAttachment, XmATTACH_WIDGET); ctr++;
- XXtSetArg (args[ctr], XmNtopWidget, label); ctr++;
- XXtSetArg (args[ctr], XmNbottomAttachment, XmATTACH_FORM); ctr++;
- Xframe = XmCreateFrame (form, "frame", args, ctr);
- XXtManageChild (frame);
- X
- X/* create rowcolumn in frame to manage buttons */
- Xctr = 0;
- XXtSetArg (args[ctr], XmNpacking, XmPACK_COLUMN); ctr++;
- XXtSetArg (args[ctr], XmNnumColumns, 4); ctr++;
- Xrow_column = XmCreateRowColumn (frame, "row_column", args, ctr);
- XXtManageChild (row_column);
- X
- X/* create buttons by column */
- Xctr = 0;
- Xlabel_string = XmStringCreateLtoR (PLAY_NAME, charset);
- XXtSetArg (args[ctr], XmNlabelString, label_string); ctr++;
- Xplay_button = XmCreatePushButtonGadget (row_column, PLAY_NAME, args, ctr);
- XXtManageChild (play_button);
- XXtAddCallback (play_button, XmNarmCallback, play_callback, NULL);
- XXmStringFree (label_string);
- X
- Xctr = 0;
- Xlabel_string = XmStringCreateLtoR (PREV_NAME, charset);
- XXtSetArg (args[ctr], XmNlabelString, label_string); ctr++;
- Xprev_button = XmCreatePushButtonGadget (row_column, PREV_NAME, args, ctr);
- XXtManageChild (prev_button);
- XXtAddCallback (prev_button, XmNarmCallback, prev_callback, NULL);
- XXmStringFree (label_string);
- X
- Xctr = 0;
- Xlabel_string = XmStringCreateLtoR (PAUSE_NAME, charset);
- XXtSetArg (args[ctr], XmNlabelString, label_string); ctr++;
- Xpause_button = XmCreatePushButtonGadget (row_column, PAUSE_NAME, args, ctr);
- XXtManageChild (pause_button);
- XXtAddCallback (pause_button, XmNarmCallback, pause_callback, NULL);
- XXmStringFree (label_string);
- X
- Xctr = 0;
- Xlabel_string = XmStringCreateLtoR (NEXT_NAME, charset);
- XXtSetArg (args[ctr], XmNlabelString, label_string); ctr++;
- Xnext_button = XmCreatePushButtonGadget (row_column, NEXT_NAME, args, ctr);
- XXtManageChild (next_button);
- XXtAddCallback (next_button, XmNarmCallback, next_callback, NULL);
- XXmStringFree (label_string);
- X
- Xctr = 0;
- Xlabel_string = XmStringCreateLtoR (SHUFFLE_NAME, charset);
- XXtSetArg (args[ctr], XmNlabelString, label_string); ctr++;
- Xshuffle_button = XmCreatePushButtonGadget (row_column, SHUFFLE_NAME, args, ctr);
- XXtManageChild (shuffle_button);
- XXtAddCallback (shuffle_button, XmNarmCallback, shuffle_callback, NULL);
- XXmStringFree (label_string);
- X
- Xctr = 0;
- Xlabel_string = XmStringCreateLtoR (TRACKS_NAME, charset);
- XXtSetArg (args[ctr], XmNlabelString, label_string); ctr++;
- Xtracks_button = XmCreatePushButtonGadget (row_column, TRACKS_NAME, args, ctr);
- XXtManageChild (tracks_button);
- XXtAddCallback (tracks_button, XmNarmCallback, tracks_callback, NULL);
- XXmStringFree (label_string);
- X
- Xctr = 0;
- Xlabel_string = XmStringCreateLtoR (STOP_NAME, charset);
- XXtSetArg (args[ctr], XmNlabelString, label_string); ctr++;
- Xstop_button = XmCreatePushButtonGadget (row_column, STOP_NAME, args, ctr);
- XXtManageChild (stop_button);
- XXtAddCallback (stop_button, XmNarmCallback, stop_callback, NULL);
- XXmStringFree (label_string);
- X
- Xctr = 0;
- Xlabel_string = XmStringCreateLtoR (EJECT_NAME, charset);
- XXtSetArg (args[ctr], XmNlabelString, label_string); ctr++;
- Xeject_button = XmCreatePushButtonGadget (row_column, EJECT_NAME, args, ctr);
- XXtManageChild (eject_button);
- XXtAddCallback (eject_button, XmNarmCallback, eject_callback, NULL);
- XXmStringFree (label_string);
- X
- X/* set MainWindow areas */
- XXmMainWindowSetAreas (main_window, menu_bar, NULL, NULL, NULL, form);
- X
- X/* put them all on the screen */
- XXtRealizeWidget (app_shell);
- X}
- X
- X
- X#ifdef WATCH_ABUF
- Xvoid
- Xheartbeat ()
- X{
- Xshow_bufsleft = 1;
- Xsignal (SIGALRM, heartbeat);
- X}
- X#endif /* WATCH_ABUF */
- X
- X
- Xmain (argc, argv)
- Xint argc;
- Xchar *argv[];
- X{
- X#ifdef WATCH_ABUF
- Xstruct itimerval itbuf;
- X#endif /* WATCH_ABUF */
- XXEvent an_event;
- Xint frame_ctr, frames_to_play;
- Xchar message[64];
- X
- X/*
- X * Try to increase the scheduling priority of this process. This should help
- X * reduce pauses in the music, due to cpu scheduling conflicts by making
- X * cdreader one of the highest priority processes in the system.
- X *
- X * The schedctl() system call will fail (silently) unless the program is installed
- X * setuid to root, or the kernel is reconfigured to allow mere mortals to use
- X * non-degrading priorities. See the SCHEDCTL(2) and AUTOCONFIG(1M) manpages,
- X * and the Irix Programming Guide Vol 2, section 14.2.3 for complete details.
- X *
- X * That's what I did, and it's pretty easy! Basically, * become superuser,
- X * edit /usr/sysgen/master.d/disp, find the variable "ndpri_hilim", change it's
- X * value to "NDPHIMAX", run "autoconfig" and reboot.
- X *
- X * We don't care if it fails, probably the user doesn't have permission.
- X *
- X * WARNING! when testing new code, DON'T do this! (this is
- X * the voice of experience talking, so listen up!) If you get
- X * into an infinite loop, your system will LOCK UP tight!
- X * (because cdreader will be the highest priority process,
- X * and you won't be able to kill it)
- X *
- X */
- X#ifndef TESTING
- X(void) schedctl (NDPRI, 0, NDPHIMAX+1);
- X#endif
- X
- X/* lose any setuid priviledges assigned to allow schedctl to succeed */
- X(void) seteuid (getuid());
- X
- X(void) signal (SIGHUP, quit_pgm); /* should really trap everything, right? */
- X(void) signal (SIGINT, quit_pgm);
- X(void) signal (SIGQUIT, quit_pgm);
- X(void) signal (SIGTERM, quit_pgm);
- X
- Xinit_motif (argc, argv); /* initialize the X11/Motif user interface */
- X
- X/* main process loop */
- Xfor (;;) {
- X switch (status) {
- X
- X case PAUSED:
- X case STOPPED:
- X XtAppNextEvent (appcon, &an_event);
- X XtDispatchEvent (&an_event);
- X break;
- X
- X case PAUSING:
- X (void) sprintf (message, "%s %d", Paused_Msg, current_track);
- X set_message (message);
- X
- X XtSetSensitive (play_button, True);
- X XtSetSensitive (stop_button, True);
- X XtSetSensitive (pause_button, False);
- X XtSetSensitive (shuffle_button, False);
- X XtSetSensitive (eject_button, False);
- X
- X#ifdef WATCH_ABUF
- X /* turn off monitor timer */
- X signal (SIGALRM, SIG_IGN);
- X itbuf.it_value.tv_sec = itbuf.it_interval.tv_sec = 0;
- X itbuf.it_value.tv_usec = itbuf.it_interval.tv_usec = 0;
- X if (setitimer (ITIMER_REAL, &itbuf, (struct itimerval *) 0) == -1) {
- X perror ("setitimer");
- X return;
- X }
- X#endif /* WATCH_ABUF */
- X
- X status = PAUSED;
- X break;
- X
- X case STOPPING:
- X set_message (Stopped_Msg);
- X current_track = 1;
- X if (cd_device != NULL) {
- X CDclose (cd_device);
- X cd_device = NULL;
- X }
- X
- X XtSetSensitive (play_button, True);
- X XtSetSensitive (shuffle_button, True);
- X XtSetSensitive (eject_button, True);
- X XtSetSensitive (pause_button, False);
- X XtSetSensitive (stop_button, False);
- X
- X#ifdef WATCH_ABUF
- X /* turn off monitor timer */
- X signal (SIGALRM, SIG_IGN);
- X itbuf.it_value.tv_sec = itbuf.it_interval.tv_sec = 0;
- X itbuf.it_value.tv_usec = itbuf.it_interval.tv_usec = 0;
- X if (setitimer (ITIMER_REAL, &itbuf, (struct itimerval *) 0) == -1) {
- X perror ("setitimer");
- X return;
- X }
- X#endif /* WATCH_ABUF */
- X
- X status = STOPPED;
- X break;
- X
- X case STARTING:
- X if (get_track_info()) { /* opens cd_device and gets track_info[] */
- X status = STOPPING;
- X break;
- X }
- X current_track = first_track; /* play whole disk from the start */
- X play_index = -1;
- X
- X case START_TRACK:
- X if (CDseektrack(cd_device, current_track) == -1) {
- X (void) sprintf (message, "%s %d", CDSEEKTRACK_FAILED, current_track);
- X Display_Warning (message);
- X status = STOPPING;
- X break;
- X }
- X /* FALLTHROUGH */
- X
- X case CONTINUE:
- X if (init_audio() || init_cd()) { /* initialize audio port and cd structures */
- X status = STOPPING;
- X break;
- X }
- X
- X (void) sprintf (message, "%s %d - %s %2d:%02d", Playing_Msg, current_track, Length_Word,
- X track_info[current_track].length_min,
- X track_info[current_track].length_sec);
- X set_message (message);
- X
- X while (XtAppPending (appcon)) { /* process any pending X events */
- X XtAppNextEvent (appcon, &an_event);
- X XtDispatchEvent (&an_event);
- X }
- X
- X XtSetSensitive (pause_button, True);
- X XtSetSensitive (stop_button, True);
- X XtSetSensitive (play_button, False);
- X XtSetSensitive (shuffle_button, False);
- X XtSetSensitive (eject_button, False);
- X
- X#ifdef WATCH_ABUF
- X show_bufsleft = 0;
- X signal (SIGALRM, heartbeat);
- X itbuf.it_value.tv_sec = itbuf.it_interval.tv_sec = monitor_interval;
- X itbuf.it_value.tv_usec = itbuf.it_interval.tv_usec = 0;
- X if (setitimer (ITIMER_REAL, &itbuf, (struct itimerval *) 0) == -1) {
- X perror ("setitimer");
- X return;
- X }
- X#endif /* WATCH_ABUF */
- X
- X /*
- X * read enough cd data to fill the audio buffer, to help
- X * cover any later pauses due to cpu scheduling.
- X * Be aware that we might still have some audio data left over
- X * from a previous pause.
- X */
- X frames_to_play = CDreadda (cd_device, &cd_buffer[0], cd_init_readsize);
- X
- X /* process any pending X events */
- X while (XtAppPending (appcon)) {
- X XtAppNextEvent (appcon, &an_event);
- X XtDispatchEvent (&an_event);
- X }
- X
- X if (frames_to_play < 1) {
- X status = STOPPING;
- X }
- X else {
- X status = PLAYING;
- X }
- X break;
- X
- X case PLAYING:
- X
- X#ifdef IRIX401_CDREADDA_BUG
- X /*
- X * BUG! The manpage for CDreadda() says it returns the number
- X * of frames read. In reality, it returns the number of bytes read
- X * into the buffer. Divide by CDDA_BLOCKSIZE to get the number of frames.
- X *
- X * I'd prefer it to work like the manpage says, return the number of frames.
- X * This is supposed to be fixed in the next release of Irix (after 4.0.1).
- X */
- X frames_to_play = frames_to_play / CDDA_BLOCKSIZE;
- X#endif /* IRIX401_CDREADDA_BUG */
- X
- X /* process CD data */
- X for (frame_ctr = 0; frame_ctr < frames_to_play; frame_ctr++) {
- X CDparseframe (cd_parser, &cd_buffer[frame_ctr]);
- X }
- X
- X /* process any pending X events */
- X while (XtAppPending (appcon)) {
- X XtAppNextEvent (appcon, &an_event);
- X XtDispatchEvent (&an_event);
- X }
- X
- X /* still playing? read more CD data */
- X if (status == PLAYING) {
- X frames_to_play = CDreadda (cd_device, &cd_buffer[0], cd_readsize);
- X if (frames_to_play < 1) { /* end of disc */
- X status = STOPPING;
- X }
- X }
- X
- X#ifdef WATCH_ABUF
- X if (show_bufsleft) {
- X show_bufsleft = 0;
- X printf ("abufs left = %d\n", total_samps - ALgetfilled(audio_port));
- X }
- X#endif /* WATCH_ABUF */
- X
- X /* process any pending X events */
- X while (XtAppPending (appcon)) {
- X XtAppNextEvent (appcon, &an_event);
- X XtDispatchEvent (&an_event);
- X }
- X break;
- X
- X default:
- X Display_Warning ("Cdreader has become horribly confused.\nYou should quit and start the program over");
- X status = STOPPING;
- X }
- X }
- X
- X/* NOTREACHED */
- X}
- X
- X/*
- X * Original Author: Patrick Wolfe (pwolfe@kai.com, uunet!kailand!pwolfe)
- X *
- X * This software is Copyright (c) 1992 by Patrick J. Wolfe.
- X *
- X * Permission is hereby granted to copy, distribute or otherwise
- X * use any part of this package as long as you do not try to make
- X * money from it or pretend that you wrote it. This copyright
- X * notice must be maintained in any copy made.
- X *
- X * Use of this software constitutes acceptance for use in an AS IS
- X * condition. There are NO warranties with regard to this software.
- X * In no event shall the author be liable for any damages whatsoever
- X * arising out of or in connection with the use or performance of this
- X * software. Any use of this software is at the user's own risk.
- X *
- X * If you make modifications to this software that you feel
- X * increases it usefulness for the rest of the community, please
- X * email the changes, enhancements, bug fixes as well as any and
- X * all ideas to me. This software is going to be maintained and
- X * enhanced as deemed necessary by the community.
- X *
- X * Patrick J. Wolfe
- X * uunet!kailand!pwolfe
- X * pwolfe@kai.com
- X */
- END_OF_FILE
- if test 34681 -ne `wc -c <'cdreader.c'`; then
- echo shar: \"'cdreader.c'\" unpacked with wrong size!
- fi
- # end of 'cdreader.c'
- fi
- if test -f 'cdreader.icon' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'cdreader.icon'\"
- else
- echo shar: Extracting \"'cdreader.icon'\" \(3086 characters\)
- sed "s/^X//" >'cdreader.icon' <<'END_OF_FILE'
- X#define cdreader_width 60
- X#define cdreader_height 60
- Xstatic char cdreader_bits[] = {
- X 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- X 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
- X 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00,
- X 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00,
- X 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
- X 0x1e, 0xc0, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xf8, 0x7f, 0x00,
- X 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
- X 0xfe, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x3f, 0x00,
- X 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
- X 0xfe, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x07, 0x00,
- X 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
- X 0xfe, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x00, 0x00,
- X 0x00, 0x00, 0x00, 0x00, 0xee, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- X 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
- X 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- X 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
- X 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- X 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
- X 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- X 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
- X 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- X 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x0e, 0x00, 0x00, 0x00,
- X 0x00, 0x00, 0xf8, 0x0f, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x1f,
- X 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x3f, 0x0e, 0x00, 0x00, 0x00,
- X 0x00, 0x00, 0xff, 0x7f, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff,
- X 0x0e, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00,
- X 0x00, 0xc0, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff,
- X 0x0f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00,
- X 0x00, 0xe0, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff,
- X 0x0f, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00,
- X 0x00, 0x80, 0xff, 0xff, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x7f,
- X 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x3f, 0x0e, 0x00, 0x00, 0x00,
- X 0x00, 0x00, 0xfc, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x0f,
- X 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x00, 0x00, 0x00,
- X 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- X 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- X 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- X 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- X 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- X 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
- END_OF_FILE
- if test 3086 -ne `wc -c <'cdreader.icon'`; then
- echo shar: \"'cdreader.icon'\" unpacked with wrong size!
- fi
- # end of 'cdreader.icon'
- fi
- echo shar: End of archive 1 \(of 1\).
- cp /dev/null ark1isdone
- MISSING=""
- for I in 1 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have the archive.
- rm -f ark[1-9]isdone
- else
- echo You still must unpack the following archives:
- echo " " ${MISSING}
- fi
- exit 0
- exit 0 # Just in case...
-