RexxEdit Module for Music-X - ©1990 MicroIllusions, Inc. Introduction: ------------- "RexxEdit" is a module that allows Music-X to call an ARexx macro program, which can in turn edit the events in a sequence. This module only works in the Editor pages (the Bar and Event Editor). The module will attempt to start-up the ARexx server, "RexxMast," if it is not already activated. When RexxEdit module is selected from the Module Menu, a file requester will open so the user can select an ARexx program to run. The module first looks for the logical assign "MXRexx:" and, if found, shows the contents of that drawer. If "MXRexx:" is not found, the logical assign "Rexx:" (where all standard ARexx programs are kept) will be searched for and, if found, displayed. If "Rexx:" cannot be found, then the contents of Music-X's own drawer will be displayed. After selecting the ARexx program from the file requester and clicking on "OK", the module will run the ARexx program. The ARexx program can access the events in the currently displayed sequence by calling "external functions" that are contained within the RexxEdit module. These functions can be used to scan through the events; insert, delete or change events; or get information about the current Bar Editor enviroment. In addition, the ARexx program can create a module requester with buttons, sliders, etc., and then discover what setting the user chooses. When the ARexx program terminates, whether through normal execution or because of an error, the module will exit and return control to Music-X. Any changes made by the ARexx program will then be displayed. Writing an ARexx Program for Editing: -------------------------------------- First, RexxEdit always returns results from any function call, so the line "options results" must appear near the beginning of the ARexx program. RexxEdit uses the "Rexx Variable Interface" for editing events, which means that RexxEdit communicates information about events by directly reading or changing variables in the ARexx program. The most important of these variables are those with the stem "EVENT". To begin editing a sequence, the function BEGINSCAN must be called with a parameter indicating whether "all" or just "selected" events are being scanned for. When done editing a sequence, the program must call ENDSCAN. (If a program terminates by error during an editing section, a default ENDSCAN will be performed.) To get each event in the sequence, the program must call NEXTEVENT. This will cause a number of variables with the stem "EVENT" to be created or filled-in. For instance, a control change event would have the variables EVENT.TYPE, EVENT.CHANNEL, EVENT.NUM, EVENT.VALUE, EVENT.START.BARS, EVENT.START.CLOCKS, etc., set to the values contained in the event in the sequence. There is a table below which gives all the possible variables for each event type. The program could then change these values and replace the event by calling REPLEVENT. Or it could change the values and ask that this be inserted as a new event with ADDEVENT. Or the event could just be deleted by calling REMEVENT. If the program wanted to quickly copy the event to another stem variable, it could call COPYEVENT with the name of the stem. RexxEdit also allows the program to peek ahead to look at other events by calling PEEKEVENT with stem variable to return the result in and the number of events to peek ahead. Note that the peek-ahead event cannot be editted (although this may change in a future release of RexxEdit). User Interface Functions: ------------------------- Unless the ARexx program only does some simple action (like remove all events after an END event), it is likely that the program will need some input from the user. This is provided by the "algorithmic module requester design functions" -- quite a name, huh? The program first defines the type of controls it desires in the requester and then calls MXREQUEST with the name of the requester and an optional name for the "PROCEED" button. The following types of controls are available in this release: MXBUTTON - A toggle button with a label to the right of it. MXRADIO - A set of mutually exclusive buttons with labels next to them. MXSLIDER - A slider with a label to the left of it. The minimum and maximum values are given as paramters. The minimum value must be positive or zero and cannot be greater than 255. MXMIRROR - Another slider which goes from a negative to positive value. MXNOTESIZE - Puts up one of those note size selection gadgets (like the Grid Requester has), including a slider and a label to the left of the slider. So, to create a requester with a slider asking for a note transposition value, a set of radio buttons set to choose selected or all events, and having an alternate name to PROCEED control of "TRANSPOSE", the macro program would do as follows (/* ... */being comments): MXMIRROR "Note Value:,127,12" /*Slider ranges from -127 to +127, defaults to +12 */ MXRADIO "Selected events,All events" MXREQUEST "TRANSPOSE NOTES,TRANSPOSE" When MXREQUEST returns, the macro program may query the button and slider by calling MXVALUE with the number of the control (Numbered in the order the conrols appear). In the above example the MXMIRROR slider would be control 1, while the MXRADIO set would be control 2. The value is returned in the global ARexx variable "RESULT". The maximum number of control elements that can exist graphically in a requester is 40. Some controls have multiple elements. MXNOTESIZE controls have four elements. MXRADIO controls have one elemt for each button in the set. MXLABEL "controls" have one element. The PROCEED and CANCEL buttons also count for one element each. NOTE: Controls that use mulitple elements are still counted as a single control for the purpose of telling MXVALUE which control to query, numbered in the order they appear. In addition to the requester-layout functions, the macro program may display a separate message at and time by calling MXREPORT. The macro program may also change the pointer (to indicate that it is busy working) by calling MXPOINTER with either the parameter "SLEEPLY" or "NORMAL". Summary of Functions -------------------- The Code given in the examples of this summary, the conventions are observed: Upper case text is used to represent code which must be spelled as shown although you may actually use upper or lower case when writing. Lower-case text, surrounded by single quotes, is used to represent data you must provide in the code although quotes may not be necessary. Actual numbers or text (including commas) must be provided within quotes, numeric or text variables must be provided outside of quotes. Brackets ("(" and ")") surround portions which may be optionally used or left out of the code. The backets themselves are not used in the actual code. Spaces must be used if shown. For Example: MXREQUEST 'Title(,proceed)' This example, explaining the use of the MXREQUEST function shows that "MXREQUEST" must be spelled exactly this way though case doesn't matter-- "mxrequest" or "mXrEqUeSt" woukd work as well. Next follows a space which must be used to separate the function name from the rest of the line. The rest of the example is lower-case text, surrounded by quotes, so it represents data which you must provide in your own code. The word "title", in this particular case (for MXREQUEST), represents the text which will be displayed at the top of a requester. The next portion, "(,proceed)" may be left out. "proceed" represents text that (in this MXREQUEST case) would be displayed in one of the requester's buttons. If used, whatever you supply for "proceed" must be preceeded by a comma (to separate it from "title" text). Here are some posible variations on the above example (text variables are assumed to be difined previously in the actual code): MXREQUEST "QUANTIZER" MXREQUEST 'QUANTIZER MODULE QUANTIZE' MXRequest Title Text Variable "GO AHEAD" MXREQUEST Titletextvariable "," buttontextvariable MXREQUEST titleString commanString buttonString MXREQUEST CompleteTExtVariable Requester and Control-Handling Functions ---------------------------------------- MXBUTTON 'label(,State)' Creates a toggle button with an explanatory label to its right. "label" represents the label text (23 characters maximum). The initial state may be specified, where '0' means off and '1' means on. The default is off. Returns either 1 (success) or 0 (could not create control). MXRADIO 'labell,label2,...' Creates a set of mutually exclussive buttons (maximum of 12 in the set) with 'labell,label2,...' printed to the right of each button (23 characters maximum for each label). The first listed button defaults to on. There can be no more than 4 MXRADIO groups per module. Returns either 1 (success) or 0 (could not create control). MXSLIDER 'label,minval,maxval(,Initval)' Creates a slider with a 'minval' and 'maxval'. 'mival' must be positive or zero and cannot be greater than 255. 'label' is printed to the left of the slider and can't be longer than 14 characters. The optional 'initval' gives the initial value for the slider. The default is (minval + maxval) / 2. Returns either 1 (success) or 0 (could not create control). MXMIRROR 'label,maxval(,Initval)' Creates a slider whose maximum value is 'maxval' and minumum is negative 'maxval'. 'label' is printed to the left of the slider (14 characters maximum). The optional 'initval' gives the initial value for the slider. The default initval is zero. Returns either 1 (success) or 0 (could not create control). MXSTRING 'Text(,label)' Creates a string entry control. Note that label comes second and is optional. Label length is 14 characters or less. If a label is given, the text string's maximum string length is 31. There may be no more than 2 MXSTRING controls in a requester. Returns either 1 (success) or 0 (could not create control). MXNOTESIZE 'label' Creates a set of note-selection controls (including a slider) like the ones in the grid requester. There may be more than 2 MXNOTESIZE controls in a module. The text, 'label' (14 characters maximum) is printed to the left of the slider. Returns either 1 (success) or 0 (could not create control). MXLABEL 'text' Writes a text string into the next control slot. String length should be 23 characters or less. USeful for labelling or explaining things. The text is left-justified, so spaces must be inserted if you wish to centre the string. (This does count as a control when querying controls by number with the MXVALUE function). MXCOLUMN 'which' Informs RexxEdit that you want a two-column (double-width) requester and lets you specify which column the controls should appear in. "MXCOLUMN 1" must be given before any control is declared. All controls then declared will appear in the left column until the statement "MXCOLUMN 2" occurs. After that, they will appear in the right column. You cannot switch back to column one after going to column two. MXREQUEST 'title(,proceed)' Puts up a requester containing all previously defined controls, plus PROCEED and CANCEL controls. The requester will be labeled 'title'. The title string will be centred automatically and should be no more than 33 characters for a one-column requester, or 67 for a two-column requester. Optionally, the PROCEED control may be labeled. Returns 1 if the user wanted to proceed, 0 if the user wanted to cancel. MAXVALUE 'which' Must be preceded by MXREQUEST. Gets the final value of one of the controls ('which') in a requester after the user closes the requester. Controls are numbered in theorder they are declared in code, starting with 1. (If new controls are declared later for a second requester, the count is reset to 1.) The value is placed into the variable RESULT. For MXBUTTON the value is 0 if the control was unselected and 1 if selected. For MXRADIO, the first button is 0, the seconf 1, etc. For MXSLIDER, MXMIRROR and MXNOTESIZE controls, returns the slider setting. MXSTRING controls return the final text entered. Other Functions --------------- MXOPTION ('options') This turns on or off various options. If no options given, returns the current options as a RESULT string. The avialable options are: SELECTED - Add/replace events in selected state UNSELECTED - Add/replace events in unselected/unmarked state ASIS - Add events in unselected/unmarked state, replace events in state found. This is the default option which is reset each time any macro is called. MXFILE 'title' Puts up the Music-X file requester. The 'title' should be 16 characters or less. The complete path name of the chosen file is placed as a text string in the RESULT variable. Puts empty string (") in RESULT if user cancelled. The mosue pointer is always returned to 'normal' by this call. MXREPORT 'message1(message2)' Puts up a message box where the first line is 'message1' and the optional second line is 'message2'. Messages should be no longer than 76 characters each, to fit on the screen. The mouse pointer is always returned to 'normal' by this call. MXPOINTER 'mode' Change the music-X pointer. 'mode' may be either "SLEEPY" or "NORMAL" MXVERSION 'which' Places a string into the RESULT variable showing the version of the Music-X library if 'which' is "MUSIC-X" or the version of RexxEdit if 'which' is 'REXXEDIT'. GETBARDATA Gets various parameters from the Bar or Event Editor and puts them in the stem variable "BARDATA", indictaes the state of the Editor pages at the time that RexxEdit was called. In cases where variables are not applicable, the invidivdual variable will be defined. Each variable is listed and the relevant data found within is explained below: BARDATA.CLOCKTYPE -- a character string, either 'REL' or 'ABS' indictaing the current colck type used. BARDATA.GRID -- current grid size (in clocks or quarter frames) BARDATA.STEP -- current step size (in clocks or quarter frames) BARDATA.MEASURE -- current beat size (in clocks or quarter frames) BARDATA.SELECT -- a character string, either 'NONE', 'SELECT' or 'MARK' Indicating whether any events were selected or if a region of time was marked. BARDATA.START.BARS -- measure (starting with 0) from start of measure for first selected event or start of marked region. BARDATA.START.CLOCKS -- clocks (starting from 0) from start of measure for first selected event or start of marked region. BARDDATA.START.QFRAMES -- quarter frames (starting with 0) from beginning of sequence for first selected event or start of marked region. BARDATA.STOP.BARS -- measure of start of last selected event or end of marked region. BARDATA.STOP.CLOCKS -- clocks from start of measure for start of last selected event or end of marked region. BARDATA.STOP.QFRAMES -- quarter frames (starting from 0) from beginning of sequence for start of last selected event or end of marked region. Event Editing Functions ----------------------- BEGINSCAN 'mode(,which)' This must be called before any of the other event editing functions may be used. Starts an event scan. The 'mode' is either "ALL" or "SELECTED". If the "SELECTED" mode is used, only those events in the squence which previously have been selected or marked by the user will be accessible to the macro for editing. The sequence to scan is selected with the 'which' parameter (range 0- 249). If no 'which' parameter is given, it scans the work buffer (where the current sequence is temporarily stored while in the edit pages) -- this is the normal way to use this function. returns 1 if the scan started properly, return 0 on an error. ENDSCAN End the current scan. Must be called before starting a new scan or when existing from execution. (Will be executed automatically if exit from an error.) NEXTEVENT May only be used during a scan. reads the next event into a stem variable "EVENT (see variables later). Returns 1 if everything went well, returns 0 if something went wrong or there are no more events. PEEKEVENT 'stem(,count)' May only be used during a scan. Peek ahead by 'count' events (zero or positive number), and place the resulting information in the variable 'stem'. If 'count' is not specified, peek ahead 1 event. Returns either 1 (success) or 0 (failure). ADDEVENT may only be used during a scan. Uses the current values in the stem variable "EVENT" to create a new event and add it to the sequence. Returns either 1 (success) or 0 (failure). REMEVENT May only be used during a scan. Removes the event most recently accessed by NEXTEVENT. returns either 1 (success) or 0 (failure). REPLEVENT May only be used during a scan. Uses the (edited) values in the stem variable "EVENT" to replace the values in the sequence event most recently acessed by NEXTEVENT. Returns either 1 (success) or 0 (failure). COPYEVENT 'stem' may be used at any time. Copies the values in variable "EVENT" to the variable 'stem'. Returns either ' (success) or 0 (failure). NOTE: EVENT.START.TICKS and EVENT.STOP.TICKS are actually copied from the last event read (via NEXTEVENT or PEEKEVENT), if the value is not initialized, it will be set to zero. Variable returned by NEXTEVENT ------------------------------ When NEXTEVENT reads an event, it uses the attributes of that event to replace the values in various portions of the working stem variable EVENT. Any portions of EVENT which are replaced with new values by NEXTEVENTS are left with the old values from the previous event type and should be ignored. The various event attributes and their relevant portions of the stem variable EVENTS are explained here: EVENT.TYPE -- All events have an EVENT.TYPE which is a character string holding a mnemonic like 'NOTE', 'PSEQ', etc. (explained later). EVENT.CLOCKTYPE -- All events have an EVENT.CLOCKTYPE which is a string containing the mnemonic 'REL' for relative clock, or 'ABS' for absolute clock. All events in the same sequence have the same clocktype. EVENT.CHANNEL -- Some events have a MIDI channel assignment (range 0-15). All events have a start time. Some events (those with durations) also have a stop time. The variables used to store the start time and stop time of the current event will depend on the clocktype. All Relative-clocktype events have: EVENT.START.BARS -- Measure number in which event starts (0-4095 for measures 1-4096) EVENT.START.CLOCKS -- Clocks away from beginning of measure (0-3071, 3071 =last clock in largest possible measure of 4/1) EVENT.START.TICKS -- Total clocks away from beginning of sequence (0- 12582911.zero to last clock in measure 4095 in 4/1 time signature) ("Read Only" variable) Relative Clocktype events with durations have: EVENT.STAOP.BARS -- (0-4095) measure number in which eveny stop occurs. EVENT.STOP.CLOCKS -- (0-3071) clocks from beginning of measure in which stop occurs. EVENT.STOP.TICKS -- (0-12582911) ("Read Only" variable). NOTE: .TICKS and are ignored when replacing or adding an event, only .BARS and .CLOCKS are used. All Absolute-clocktype events have: EVENT.START.QFRAMES -- total quarter frames from beginning of sequence (0- 10367999, maximum is 4 quarter frames * 30 frames * 60 seconds * 60 minutes * 24 hours -1) Absolute-clocktype events with durations have: EVENT.STOP.QFRAMES -- (0-10367999) Event types and their variables ------------------------------- Additional variables vary by event type, as noted in the following list. 'END - and END event (no extra variables) 'STOP' - a stop sequencer event (no extra variables) 'SPLI' a loop record splice marker (no extra variables) 'REPT' - a repeat count EVENT.NUM - number of times to play sequence (1-99, 100=repeat indefinately) 'TSIG' - a time signature change EVENT.NUM - The indicator of the time signature (indicating beats per measure). (Range: 1-64, with the restriction that the numerator may be no greater than four times the actual denominator.) EVENT.DEM - The denominator of the time signature (indicating duration of one beat). This number represents the exponent of two needed (the power to which two muct be raised) to produce the actual denominator. (range: 0-4 producing 1, 2, 4, 8, and 16). 'KMAP' - keymap changes, control map change EVENT.MAP - keymap or control map on/off (0=keybaord off, 1-4 keymap number, 5=contril map off, 6-9 for control maps 1-4) EVENT.NUM - incoming MIDI channel to route through map (0-15). 'SYSX' - real-time system exclusive EVENT.NUM - number of bytes of data in this event (0-6) EVENT.DATA - a packed string of the data (maximum 6 bytes) EVENT.LAST - 0 if this is not the last event for this SYSX packet (more events are expected to follow). 1 if this is the last event in the poacket (will show in the Event Editor as EOX). 'TEMP' tempo change EVENT.NUM - new tempo value (10-300) 'PSEQ' - play sequence event EVENT.NUM - number of the sequence to play (0-249) EVENT.TRANSPOSE - transposition value in semitones (0-63 for zero and positive values, 64-127 for negative values from -64 to -1) EVENT.CUT - cut value (0=no cut, 1=Seq, 2=all) 'MSEQ' - mute sequence EVENT.NUM - sequence to mute (0-249) 'MTRK' - mute track EVENT.NUM - track to mute (0-19) 'STRK' - solo track EVENT.NUM - track to solo (0-19) 'NOTE' note event EVENT.NUM - MIDI note number (0-127) EVENT.ATTACK - attack velocity (1-127, 0 should not be used as as to comply with MIDI "Running status") EVENT.RELEASE - release velocity (0-127) 'CAT' - channel aftertouch EVENT.PRESSURE - new pressure value (0-127) 'PAT' - polyphonic aftertouch EVENT.NUM - note number (0-127) EVENT.PRESSURE - new pressure (0-127) 'CTL' - control change EVENT.NUM - controller number (0-127) EVENT.VALUE - new value (0-127) 'PGM' - program change EVENT.NUM - program number (0-127) 'PBEN' - pitch bend EVENT.NUM - pitch bend value (Range 0 to 8192 to 16383, representing actual bend values -8192 to 0 to 8191,)