Xref: utzoo comp.sys.amiga.tech:167 comp.sys.amiga:17120 Path: utzoo!mnetor!uunet!lll-winken!lll-lcc!ames!oliveb!amdahl!kim From: kim@amdahl.uts.amdahl.com (Kim DeVaughn) Newsgroups: comp.sys.amiga.tech,comp.sys.amiga Subject: A small ARexx example, and other useful tidbits . . . Message-ID: <26223@amdahl.uts.amdahl.com> Date: 1 Apr 88 23:11:35 GMT Organization: Amdahl Corporation, Sunnyvale, CA 94086 Lines: 310 Keywords: Warning: also contains a small assembly language example! [ "A car is just a big purse on wheels." --Johanna Reynolds ] In a recent posting concerning ARexx and IPC, as an example of ARexx's scripting/macro capabilities, I made reference to an amicron initiated, talking alarm clock program that one of my co-workers whipped off. I hadn't really thought about posting it, until Peter da Silva catagorized the REXX language as being "PL/I like". Bunk. So, in the interest of education, and with Bob Rethemeyer's permission (he's the author), here's "cuckoo", along with a crontab file. Also included is a 336-byte, "bare-bones", assembly language substitute for the "say" command. It's valuable in it's own right as an assembly language example of using the translator.library and narrator.device. [ Coincidentally, I just saw a posting requesting assembly language examples for inclusion into a freely redistributable library, similar in concept to the Fish Disks. Feel free to include "mumble". ] Bear in mind that the REXX language has many more features, and power than are used in "cuckoo". It should, however, give you a "feel" for what the language is like. Note too, that this example makes implicit use of IPC to communicate to AmigaDOS (where it invokes the "say" command [line 19], and also where it invokes whatever is equated to "speak" [lines 8, 59, 60, and 62], which in this case is "mumble"). Hope some of you find this example useful! /kim # This is a shell archive. Remove anything before this line, then # unpack it by saving it in a file and typing "sh file". (Files # unpacked will be owned by you and have default permissions.) # # This archive contains: # cuckoo.rexx timeto.rexx sample.crontab mumble.asm mumble.uue echo x - cuckoo.rexx cat > "cuckoo.rexx" << '//E*O*F cuckoo.rexx//' /* CUCKOO: ANNOUNCES THE CURRENT TIME. R. Rethemeyer 03-88 * * Cuckoo is useful with AmiCron to announce times for events. * * The "MUMBLE" program is used for the voice output. * * If that is not available, change 'speak' to "sys:system/say".* * Usage: "RX CUCKOO [ALARM]" * * The ALARM option produces an obnoxious noise and message. */ /*--------------------------------------------------------------------*/ speak="Mumble" /* PROGRAM FOR VOICE OUTPUT */ nice="Excuse me sir, the time iz now" /* NORMAL MESSAGE */ nasty="All right u bum, get up. Nouw. The time iz" /* ALARM MESSAGE */ dingaling="gggggggggggggggggggggggggggg" /* OBNOXIOUS ALARM NOISE */ /*--------------------------------------------------------------------*/ arg opt if opt="ALARM" then intro=nasty ; else intro=nice zhour = time('h') xmin = time('m') xmin = xmin-((xmin%60)*60) xhour = zhour say "Cuckoo at" zhour||":"||xmin mnite = " " if zhour > 12 then xhour = zhour-12 select when xhour=0 then do; xhour="twelve"; if xmin=0 then mnite="midnite"; end when xhour=11 then xhour = "elaven" when xhour=12 then do; xhour="twelve"; if xmin=0 then mnite="noon"; end otherwise nop end smin=" " if xmin=0 then tmin = "o clock" else do tmin=xmin%10 if tmin=1 then do; select when xmin=10 then tmin = "ten" when xmin=11 then tmin = "elaven" when xmin=12 then tmin = "twelve" when xmin=13 then tmin = "thirt teen" when xmin=14 then tmin = "fourt teen" when xmin=15 then tmin = "fif teen" when xmin=16 then tmin = "six teen" when xmin=17 then tmin = "seven teen" when xmin=18 then tmin = "eight teen" when xmin=19 then tmin = "nine teen" end end else do smin=xmin if xmin>9 then smin=xmin-(tmin*10) if smin=0 then smin=" " select when tmin=0 then tmin = "oh" when tmin=2 then tmin = "twenty" when tmin=3 then tmin = "thirty" when tmin=4 then tmin = "forty" when tmin=5 then tmin = "fifty" end end end if opt="ALARM" then address COMMAND speak dingaling address COMMAND speak intro xhour tmin smin mnite "." if tmin="o clock" & opt="ALARM" then , address COMMAND speak "I repeat," xhour tmin "." exit //E*O*F cuckoo.rexx// echo x - timeto.rexx cat > "timeto.rexx" << '//E*O*F timeto.rexx//' /* speak a sentence prefixed by time */ parse arg sentence cuckoo /* announce the time first */ address command "mumble Its time to " sentence "." exit //E*O*F timeto.rexx// echo x - sample.crontab cat > "sample.crontab" << '//E*O*F sample.crontab//' 0,15,30,45 * * * * rx cuckoo 0,10,20,30,40,50 7 * * 1-5 rx cuckoo alarm 30 7,18 * * * rx timeto feed the cat //E*O*F sample.crontab// echo x - mumble.asm cat > "mumble.asm" << '//E*O*F mumble.asm//' PLEN 60 ********************************************************************** * Program: MUMBLE - bare-bones CLI substitute for SAY command * * Author: Robert Rethemeyer, Sunnyvale, CA (@BBS-HT or BBS-JC) * * Revision: 0.1 03/30/88 initial release * * Status: RELEASED TO THE PUBLIC DOMAIN, "AS-IS" * ********************************************************************** * MUMBLE is a very small CLI program which speaks the text on the * * command line using the Amiga's translator/narrator voice output. * * It is convenient for use in CLI or ARexx scripts. * * Command usage: MUMBLE * ********************************************************************** * MUMBLE provides a function similar to the command line usage of * * the SAY command, but takes much less memory and disk space * * (300 bytes vs. 9K+). It is not, however, as versatile as SAY. * * There are no -options; the voice parameters are fixed, and the * * program will not run in window mode or read from a file. * ********************************************************************** * Mumble return codes: * 0= success * 1-9,20-26= narrator IO error * 11= could not allocate memory * 12= could not open translator.library * 13= could not open narrator.device ********************************************************************** NOLIST INCLUDE "exec/types.i" INCLUDE "exec/io.i" INCLUDE "exec/ports.i" INCLUDE "exec/memory.i" INCLUDE "devices/narrator.i" LIST XREF _LVOOpenLibrary XREF _LVOCloseLibrary XREF _LVOAllocMem XREF _LVOFreeMem XREF _LVOOpenDevice XREF _LVOCloseDevice XREF _LVOTranslate XREF _LVOFindTask XREF _LVOAddPort XREF _LVORemPort XREF _LVODoIO ExecBase EQU 4 execptr EQUR A6 ********************************************************************** * Voice parameters can be changed here, to user's liking: VSEX EQU MALE MALE/FEMALE/DEFSEX VMODE EQU NATURALF0 NATURALF0/ROBOTICF0/DEFMODE VRATE EQU 180 40-400/DEFRATE VFREQ EQU DEFFREQ 5000-28000/DEFFREQ VPITCH EQU DEFPITCH 65-320/DEFPITCH VVOL EQU DEFVOL 0-64/DEFVOL ********************************************************************** Mumble: MOVEQ #0,d5 return code if parmlen=0 MOVE.L d0,d4 SAVE EXECUTION PARMS parmlen BEQ endprog do nothing if parmlen=0 MOVE.L a0,d3 save parmaddr MOVE.L ExecBase,execptr a6=exec lib pointer * ALLOCATE SCRATCH MEMOR% MOVEQ #11,d5 return code if this fails ASL.L #2,d0 size of TRarea = parmlen*4 ADD.L #scratchlen,d0 add to size of scratch area MOVE.L d0,d6 remember for deallocate later MOVE.L #MEMF_PUBLIC+MEMF_CLEAR,d1 mem flags JSR _LVOAllocMem(execptr) ask for the storage MOVE.L d0,a3 a3=scratch area ptr BEQ broke1 abort if request failed * OPEN TRANSLATOR LIBRARY MOVEQ #12,d5 return code if this fails LEA tranlib(pc),a1 addr of library name MOVEQ #0,d0 any version will do JSR _LVOOpenLibrary(execptr) get library pointer MOVE.L d0,a5 a5=tran lib pointer BEQ broke2 back out if no lib * TRANSLATE COMMAND LINE PARAMETER MOVE.L d3,a0 retrieve parmaddr MOVE.L d4,d0 and parmlen LEA TRarea(a3),a1 point to xlat out buff ASL.L #2,d4 figure out buff length again MOVE.L d4,d1 for func (and save for later) JSR _LVOTranslate(a5) translate to phonemes MOVE.L a5,a1 : JSR _LVOCloseLibrary(execptr) close trans lib * INIT NARRATOR DEVICE PORT MOVE.L #0,a1 : JSR _LVOFindTask(execptr) identify this task MOVE.L d0,Narport+MP_SIGTASK(a3) let narrator find it LEA Narport(a3),a1 point to the port area JSR _LVOAddPort(execptr) install narrator port * INIT NARRATOR DEVICE MOVEQ #13,d5 return code if this fails LEA Narname(pc),a0 point to device name MOVEQ #0,d0 unit 0 LEA Nardev(a3),a1 point to device structure MOVEQ #0,d1 no flags JSR _LVOOpenDevice(execptr) open narrator device TST.L d0 if device open failed BNE.S broke3 then back out * INIT DEVICE STUFF LEA Nardev(a3),a1 a1=device structure LEA Narport(a3),a0 a0=port address MOVE.L a0,MN_REPLYPORT(a1) give port addr to device LEA audmaps(pc),a0 audio maps MOVE.L a0,NDI_CHMASKS(a1) addr of maps MOVE.W #4,NDI_NUMMASKS(a1) number of masks MOVE.W #VPITCH,NDI_PITCH(a1) init pitch MOVE.W #VRATE,NDI_RATE(a1) init rate MOVE.W #VVOL,NDI_VOLUME(a1) init volume MOVE.W #VFREQ,NDI_SAMPFREQ(a1) init sample freq MOVE.W #VSEX,NDI_SEX(a1) init sex MOVE.W #VMODE,NDI_MODE(a1) init mode MOVE.W #CMD_WRITE,IO_COMMAND(a1) init device command MOVE.L d4,IO_LENGTH(a1) length of buffer LEA TRarea(a3),a0 addr of buffer MOVE.L a0,IO_DATA(a1) : * THE MOMENT OF TRUTH JSR _LVODoIO(execptr) do i/o, wait for reply MOVE.L d0,d5 save return code NEG.L d5 convert rc to positive * CLEAN UP AND RETURN LEA Nardev(a3),a1 point to device structure JSR _LVOCloseDevice(execptr) release device broke3 LEA Narport(a3),a1 point to port JSR _LVORemPort(execptr) delete the port broke2 MOVE.L d6,d0 length of scratch area MOVE.L a3,a1 addr of scratch area JSR _LVOFreeMem(execptr) free scratch mem broke1 MOVE.L d5,d0 set return code endprog RTS ALL DONE! ************************************************************ CNOP 0,2 tranlib DC.B 'translator.library',0 CNOP 0,2 narname DC.B 'narrator.device',0 CNOP 0,2 audmaps DC.B 3,5,10,12 Audio device maps ************************************************************* version DC.B 'MUMBLE V0.1 RAR' Imbedded version info ************************************************************* STRUCTURE Scratch,0 Format of allocated scratch mem STRUCT Narport,MP_SIZE Message reply port for narrator STRUCT Nardev,NDI_SIZE Narrator IO block LABEL scratchlen Length of scratch area less TRarea STRUCT TRarea,0 xlat out buff (size computed dynamically) END and there ain't no more //E*O*F mumble.asm// echo x - mumble.uue cat > "mumble.uue" << '//E*O*F mumble.uue//' begin 755 mumble M```#\P`````````!``````````````!+```#Z0```$MZ`"@`9P``ZB8(+'@`^ M!'H+Y8`&@````&@L`"(\``$``4ZN_SHF0&<``,9Z#$/Z`,1P`$ZN_=@J0&<`) M`*P@0R`$0^L`:.6$(@1.K?_B(DU.KOYB(GP`````3J[^VB=``!!#ZP``3J[^0 MGGH-0?H`FG``0^L`(G(`3J[^1$J`9F!#ZP`B0>L``"-(``Y!^@"*(T@`.#-\& M``0`/#-\`&X`,C-\`+0`,#-\`$``/C-\5K@`0#-\````-C-\````-#-\``,`& M'"-$`"1!ZP!H(T@`*$ZN_C@J`$2%0^L`(DZN_CY#ZP``3J[^F"`&(DM.KO\NW M(`5.=71R86YS;&%T;W(N;&EB0``;F%R $temp <<\!!! 63 331 2294 cuckoo.rexx 5 28 152 timeto.rexx 3 25 109 sample.crontab 147 730 8084 mumble.asm 13 15 506 mumble.uue 231 1129 11145 total !!! wc cuckoo.rexx timeto.rexx sample.crontab mumble.asm mumble.uue | sed 's=[^ ]*/==' | diff -b $temp - exit 0 -- UUCP: kim@amdahl.amdahl.com or: {sun,decwrl,hplabs,pyramid,ihnp4,uunet,oliveb,cbosgd,ames}!amdahl!kim DDD: 408-746-8462 USPS: Amdahl Corp. M/S 249, 1250 E. Arques Av, Sunnyvale, CA 94086 CIS: 76535,25