fweelin-0.6/data/basic.sf20000755000175000017500000000677010547030013014062 0ustar mercmercRIFF sfbkLISTINFOifilisngEMU8000INAMexampleICRDIENGIPRDICOPICMTISFTSWAMI v0.9.1a:SWAMI v0.9.1aLISTh sdtasmpl\ o)p6B7N1t+J&!^4ZcJa"i&*/,5:@aEJdOSW[]_`;a`_][sXTPqLGC]>9B51c-#*r'Z%#6#/##4%.'),C0480DG@KN9PQbR3RQOKGB=O6.&| 7ۻU[ e/,rS v#.9CMZV^d/j`n?qrrqfokg2axZRJ(B+9/& M(zX'm5iGV r%]Od4eD }eZq/#+;)' * > 0Eyc0vXBߓX NA̛^4H9҇9 )<1j8h>.CFHzIHFC3?93+]#=8{؎e“ðȮŭe3 b.KJӅ;{[ؚN҄Y8x&ӮϪ?8ϡ ƞA7rLˇpIX>#ΰ%rtɊ/_ r4>Eʷ;*>L(*7C7OYbkqkw{Q~~A|xQtnhJbB[SL!E=70*%!,h~B"&i+_05;@EKO/T XM[]_`;a`_]D[#XTrP LjGB=O940-)9'3%#.#9##Z%d')-0k4u8<@D?HKFNdPQfR%RPNKGxB|<5.% Sv6FN/bgqM{~2yobTE7y+!7fn&/:jEnOW]`` ^~XPGd>H5h-v'#4#9%)I08S@GNQ=ROG=. ]'%Ƚ.DdVdmnrqk=aS0B0 xkht`7 cWn,8&'+#1B^lܤ~J4+Bǃݬ: B1o>FIF;?3a#?ɋ 'Dz7ܽvڕ~pŪ-y,޵kFkU:ξgޕ d1 =)N*CY kzw`~P|_thM[L=0%k"n+5@ K9TX[_Ga_O[TLBU90)7%2##h'-q4r-#A%T0a@"NOR H. .wVnqSa>Bsgx_h"&/ 2=Ȥ2ώl5ǩ}>II?i#|֯8ض܌ ε:ݨN Ǖہ.&*Ywyta[ >%x+@LT__TB0?%$%- fweelin-0.6/data/bcf2000.xml0000644000175000017500000007117011071511705014141 0ustar mercmerc fweelin-0.6/data/browsers.xml0000644000175000017500000001013011071511705014740 0ustar mercmerc fweelin-0.6/data/config-help.txt0000644000175000017500000010635511060100154015311 0ustar mercmercKeyboard Keys ************* For your reference, here is a table that lists keyboard key #s and the corresponding key name (keysym). When referring to keys in the XML config files, use the name given in the second column. 008 - backspace 009 - tab 012 - clear 013 - return 019 - pause 027 - escape 032 - space 033 - exclamation 034 - dblquote 035 - numbersign 036 - dollarsign 038 - ampersand 039 - backquote 040 - openparen 041 - closeparen 042 - asterisk 043 - plus 044 - comma 045 - minus 046 - period 047 - slash 048 - zero 049 - one 050 - two 051 - three 052 - four 053 - five 054 - six 055 - seven 056 - eight 057 - nine 058 - colon 059 - semicolon 060 - lessthan 061 - equal 062 - greaterthan 063 - questionmark 064 - at 091 - squarebracketopen 092 - backslash 093 - squarebracketclose 094 - caret 095 - underscore 096 - tilde 097 - a 098 - b 099 - c 100 - d 101 - e 102 - f 103 - g 104 - h 105 - i 106 - j 107 - k 108 - l 109 - m 110 - n 111 - o 112 - p 113 - q 114 - r 115 - s 116 - t 117 - u 118 - v 119 - w 120 - x 121 - y 122 - z 127 - delete 160 - world0 161 - world1 162 - world2 163 - world3 164 - world4 165 - world5 166 - world6 167 - world7 168 - world8 169 - world9 170 - world10 171 - world11 172 - world12 173 - world13 174 - world14 175 - world15 176 - world16 177 - world17 178 - world18 179 - world19 180 - world20 181 - world21 182 - world22 183 - world23 184 - world24 185 - world25 186 - world26 187 - world27 188 - world28 189 - world29 190 - world30 191 - world31 192 - world32 193 - world33 194 - world34 195 - world35 196 - world36 197 - world37 198 - world38 199 - world39 200 - world40 201 - world41 202 - world42 203 - world43 204 - world44 205 - world45 206 - world46 207 - world47 208 - world48 209 - world49 210 - world50 211 - world51 212 - world52 213 - world53 214 - world54 215 - world55 216 - world56 217 - world57 218 - world58 219 - world59 220 - world60 221 - world61 222 - world62 223 - world63 224 - world64 225 - world65 226 - world66 227 - world67 228 - world68 229 - world69 230 - world70 231 - world71 232 - world72 233 - world73 234 - world74 235 - world75 236 - world76 237 - world77 238 - world78 239 - world79 240 - world80 241 - world81 242 - world82 243 - world83 244 - world84 245 - world85 246 - world86 247 - world87 248 - world88 249 - world89 250 - world90 251 - world91 252 - world92 253 - world93 254 - world94 255 - world95 256 - KP0 257 - KP1 258 - KP2 259 - KP3 260 - KP4 261 - KP5 262 - KP6 263 - KP7 264 - KP8 265 - KP9 266 - KPperiod 267 - KPslash 268 - KPasterisk 269 - KPminus 270 - KPplus 271 - enter 272 - equals 273 - up 274 - down 275 - right 276 - left 277 - insert 278 - home 279 - end 280 - pageup 281 - pagedown 282 - f1 283 - f2 284 - f3 285 - f4 286 - f5 287 - f6 288 - f7 289 - f8 290 - f9 291 - f10 292 - f11 293 - f12 294 - f13 295 - f14 296 - f15 300 - numlock 301 - capslock 302 - scrolllock 303 - rightshift 304 - leftshift 305 - rightctrl 306 - leftctrl 307 - rightalt 308 - leftalt 309 - rightmeta 310 - leftmeta 311 - leftsuper 312 - rightsuper 313 - altgr 314 - compose 315 - help 316 - printscreen 317 - sysreq 318 - break 319 - menu 320 - power 321 - euro 322 - undo Input Events ************ Here is a table of recognized input events. The input matrix is flexible in that different types of input events can be routed to different output events. There is also a parameter routing that connects input parameters like MIDI note velocity to control parameters within FreeWheeling. For example, you can specify that the number of the note pressed controls which loop is triggered. Event "key" binding input="key" conditions="keydown=1 and key=space" A keyboard key is pressed or released. "keydown": 1 if key was pressed, otherwise 0 "key": Name or number of the key (see above table) Event "midicontroller" binding input="midicontroller" conditions="controlnum=64 and midichannel=0 and controlval=64>127" A MIDI controller is changed. "outport": # of MIDI output to echo event to "midichannel": Channel of event "controlnum": Number of control change "controlval": Value of control change "routethroughpatch": 1 sends this MIDI message through the port/channel(s) given by the current patch. 0 sends this message as described by outport/midichannel. Event "midikey" binding input="midikey" conditions="keydown=1 and midichannel=0 and notenum=VAR_noterange and velocity=1>127" A MIDI note is pressed or released. "outport": # of MIDI output to echo event to "keydown": 1 if note is pressed, 0 if note is released "midichannel": Channel of event "notenum": Number of note "velocity": Velocity of noteon/noteoff "routethroughpatch": 1 sends this MIDI message through the port/channel(s) given by the current patch. 0 sends this message as described by outport/midichannel. Event "midichannelpressure" binding input="midichannelpressure" conditions="midichannel=0 and pressureval=64" A MIDI channel pressure (channel aftertouch) message. "outport": # of MIDI output to echo event to "midichannel": Channel of event "pressureval": Pressure of keys "routethroughpatch": 1 sends this MIDI message through the port/channel(s) given by the current patch. 0 sends this message as described by outport/midichannel. Event "midiprogramchange" binding input="midiprogramchange" conditions="midichannel=0 and programval=64" A MIDI program change message. "outport": # of MIDI output to echo event to "midichannel": Channel of event "programval": Program change # "routethroughpatch": 1 sends this MIDI message through the port/channel(s) given by the current patch. 0 sends this message as described by outport/midichannel. Event "midipitchbend" binding input="midipitchbend" conditions="midichannel=0 and pitchval=6000" A MIDI pitch bend message. "outport": # of MIDI output to echo event to "midichannel": Channel of event "pitchval": Pitch bender value "routethroughpatch": 1 sends this MIDI message through the port/channel(s) given by the current patch. 0 sends this message as described by outport/midichannel. Event "joybutton" binding input="joybutton" conditions="joystick=1 and button=3 and down=1" A joystick button has been moved. "joystick": # of the joystick "button": # of the button "down": 1 if button is down, 0 if button is up Event "start-freewheeling" binding input="start-freewheeling" FreeWheeling has just been started. Event "go-sub" binding input="go-sub" Subroutine is being invoked- see "go-sub" in output events. The above input events can also be used as output events. For example, we can trigger a series of MIDI controller changes when a QWERTY key is pressed. Output Events ************* Here is a table of recognized output events, what they do and what parameters they accept: Event "exit-freewheeling" Quit! Event "slide-loop-amplifier-stop-all" Stops sliding amplitudes for all loops. Event "slide-loop-amplifier" Slides the amplitude of a given loop, like a fade. "loopid": the ID of the loop "slide": the speed at which to slide the amplitude. Successive events accelerate the sliding, until you reverse the speed or call set-loop-amplifier Event "set-loop-amplifier" Sets the amplitude of a given loop, and stops any sliding "loopid": the ID of the loop "amp": the amplitude to set it to (linear) Event "adjust-loop-amplifier" Adjusts the amplitude of a given loop, and stops any sliding "loopid": the ID of the loop "ampfactor": the factor to multiply the amplitude by Event "trigger-loop" Triggers a given loop- if no loop exists at that loopid, begins recording a new loop.. if a new loop is recording, the behavior depends: if overdub="1", switches to overdub.. if overdub="0", switches to play.. if a loop is playing, the behavior depends: if overdub="1", switches to overdub.. if overdub="0", switches off.. if a loop is overdubbing, switches to play. This is similar to an EDP style tapin-tapout-play/overdub. When recording a new loop, the length grows until we trigger-loop again. When overdubbing into an existing loop, the existing loop is blended with new input material. You can modify this behavior with the "engage" option. When "engage" is set to 1, the loop will -always- start. When "engage" is set to 0, the loop will -always- stop. If engage is not set, the behavior depends on the current state of the loop, as described above. You can modify the looping behavior with the "shot" option. When "shot" is set to 1, the loop will play through only once. When "shot" is not set, the loop will repeat indefinitely. "loopid": the ID of the loop "vol": the volume to trigger with- this combined with the loop amplitude determine the overall amplitude of the playing loop "shot": shot mode "engage": force on or off? "overdub": 1 or 0 determine whether to overdub or just play "overdubfeedback": Variable that holds the value of feedback to apply during overdub. Variable must be of type float (from 0.0 to 1.0). Variable can be continuously varied. Event "set-trigger-volume" Sets the volume of a given loop trigger. If you have a loop playing, you can change the volume with this event. It is different than the loop amplifier, because each time you trigger the loop you can have a different trigger volume, whereas the loop amplifier changes the volume of the loop once-and-for-all. "loopid": the ID of the loop "vol": the volume to set it to Event "erase-selected-loops" Erase selected loops that are in the given selection set. "setid": Number of the selection set to use (usually this will be 0) Event "erase-all-loops" Erases all loops and time meters. Event "erase-loop" Erases a given loop- if recording is happening on the given id, stops and erases recording. "loopid": the ID of the loop Event "move-loop" Moves a loop from "oldloopid" to "newloopid", if a loop exists there. This can be done at any time- when recording or playing a loop, or when it is inactive. "oldloopid": old loop ID "newloopid": new loop ID Event "slide-master-in-volume" Slides the master input volume at the speed given. A positive value increases volume. Actually, if you call slide-master-in-volume several times you cumulatively increase the speed of sliding. It is like a fade. This applies for other slide events too. "slide": speed of slide Event "slide-in-volume" Slides one input volume at the speed given. A positive value increases volume. "input": number of input to slide volume for "slide": speed of slide Event "slide-master-out-volume" Slides the master output volume at the speed given. A positive value increases volume. "slide": speed of slide Event "set-master-in-volume" Sets the master input volume. Stops sliding. "vol": new linear volume- 1.0 is 100% volume. or "fadervol": new logarithmic volume- specify fader throw (0.0 to 1.0). Event "set-master-out-volume" Sets the master output volume. Stops sliding. "vol": new linear volume- 1.0 is 100% volume. or "fadervol": new logarithmic volume- specify fader throw (0.0 to 1.0). Event "set-in-volume" Sets one input volume. Stops sliding. "input": number of input to set volume for "vol": new linear volume- 1.0 is 100% volume. or "fadervol": new logarithmic volume- specify fader throw (0.0 to 1.0). Event "toggle-input-record" Toggles recording of one input. Does not change monitoring for this input, only whether loops are recorded from the input. "input": number of input to toggle recording for Event "adjust-midi-transpose" Adjusts the pitch transpose for MIDI out. MIDI events that aren't used in an event are echoed back out the MIDI out and to the internal FluidSynth synthesizer. This parameter adjusts the transpose that is applied to MIDI notes before they are echoed. It does not affect the note numbers coming into FreeWheeling events. "adjust": amount to shift transpose (semitones) Event "fluidsynth-enable" Enables or disables processing for the integrated FluidSynth. When FluidSynth is disabled, the real-time DSP for FluidSynth is not active, so FreeWheeling runs faster. By default, this is done by the patch browser. When you select FluidSynth patches, FluidSynth is enabled. When you select other patches, FluidSynth is automatically disabled. "enable": 1 for enable or 0 for disable Event "set-midi-tuning" Retunes MIDI by the current value of the pitchbender. What this does is offset the zero position of pitchbender to a given value. You can easily tune to outside instruments by sweeping the pitchbender until you are in tune and then calling set-midi-tuning with the current value of the pitchbender (see system variables). "tuning": new zero position for MIDI pitchbender Event "set-midi-echo-port" DEPRECATED- FreeWheeling now sends to ports/channels as specified by the patch browser. Sets the MIDI port where incoming MIDI events are echoed. The only events echoed are those that do not trigger something in FreeWheeling. "echoport": new MIDI out port number to echo MIDI events (0 disables) Event "set-variable" Sets the user variable named "var" to the value "val". The value given must be convertible into the type of variable "var". "var": variable to set "value": what to set it to Event "toggle-variable" Toggles (increments) the user variable named "var" through an integer range of values, with a maximum of "maxvalue". Wraps to "minvalue" when maxvalue is exceeded. "var": variable to toggle "maxvalue": maximum value of variable "minvalue": minimum value of variable Event "video-show-loop" Change the range of loops shown onscreen- In the onscreen layout given by "layoutid", shows loops in the range "loopid". For example, if you specify layoutid 0 and loopid 15>30, then layout 0 will show the loop at id 15 in its first element (element id 0), up to loopid 30 in element 15. You will see these changes only if the layout is set to show onscreen, and when there are loops stored in the loopids given. "interfaceid": interface where layout is defined "layoutid": which layout to change the range of shown loops "loopid": new range of shown loops Event "video-show-layout" Shows or hides the layout given by "layoutid". If hideothers is "1", all other layouts are made hidden. "interfaceid": interface where layout is defined "layoutid": layout to show/hide "show": "1" for show and "0" for hide "hideothers": "1" to hide all other layouts Event "video-switch-interface" Switches to (shows) the interface given by "interfaceid". All displays and layouts defined in that interface are shown. All displays and layouts defined in other interfaces are hidden, EXCEPT those in non-switchable interfaces. "interfaceid": interface to switch to Event "video-show-help" Shows or hides help. FreeWheeling has an online help that can be overlaid on the screen while you are playing. This event shows a given page of that help (or hides it). The help text is user defined. Throughout this config file, you'll see comments which begin in "HELP:". Any comments that begin in this way become a part of the help text. If you have a second ":" in the help comment, it becomes a second column in the help text. "page": Help page number to show or "0" for hide Event "video-full-screen" Put FreeWheeling in a window, or let 'er hog the whole screen "fullscreen": "1" for hog fullscreen and "0" for window Event "select-pulse" Selects time pulse #pulse. If no pulse exists at the given #, creates a new one. The length and downbeat of a new pulse are taken from the last recorded loop. Once a pulse is created, it is automatically selected. The selected pulse determines the timing of all newly recorded loops. If a new pulse is selected, only those loops recorded from that point on are affected. To deselect all pulses and return to free time, set pulse="-1". "pulse": Number of the time pulse to create/select Event "delete-pulse" Delete time pulse #pulse. All loops attached to that pulse are also deleted. "pulse": Number of the time pulse to delete Event "show-debug-info" Shows or hides debugging information. The information is printed to the console. It includes input events like MIDI and keyboard keys, and information from bound events. It can help track down problems in your configuration, if FreeWheeling is not working as you imagined. But it introduces some performance latency, so I recommend leaving it off! "show": "1" for show debug info and "0" for hide Event "toggle-disk-output" Toggles output of the master outs to disk. This includes the input mix. OGG files are created in the library folder with the name 'live1.ogg', 'live2.ogg', etc.. The live mix is exactly what you hear from FreeWheeling's outputs. Accompanying each OGG file is a timing file named live.wav.usx, to be used in the GnuSound editor for doing precise splice edits on loop downbeats. Run oggdec on the OGG files and then load into GnuSound. You can also import timing information into Ardour from this .wav.usx file- see the file scripts/go-import-markers. If FreeWheeling is already writing to disk, this shuts the record off. The next write starts in a new folder. FreeWheeling no longer overwrites old files and folders. Existing save folders are skipped. Event "set-auto-loop-saving" Turns on/off auto loop saving. This saves all new loops to disk. The loops are saved in the current "save" folder (see toggle-disk-output), with the name 'loop???.ogg'. The loopID is given in the filename. Loop files are not overwritten- subsequent writes of 55, for example, will yield filenames 'loop55-0.ogg', 'loop55-1.ogg', etc. "save": "1" to turn on auto loop saving and "0" for off Event "save-loop" Saves the loop with given index. The file is named and saved as described above. "loopid": ID of loop to save Event "save-new-scene" Event "save-current-scene" Saves a new scene/overwrites current scene. A scene is a snapshot of all loaded loops and levels. It is like a save of the complete session. Event "create-snapshot" Create a snapshot. A snapshot is a memory of all playing and idle loops and their levels. This allows you to easily create and switch between song 'sections'. "snapid": ID # of snapshot to save Event "rename-snapshot" "snapid": ID # of snapshot to rename Event "trigger-snapshot" "snapid": ID # of snapshot to trigger Event "switch-metronome" Switches an audible metronome on or off for the given pulse. The metronome sounds on the downbeat of the pulse. "pulse": Number of the pulse "metronome": 1 for metronome on, 0 for off Event "tap-pulse" Taps a pulse- each tap gives a new downbeat. This allows you to tap tempo, instead of creating a pulse around an existing loop. If you tap a tempo and switch-metronome to on, it is like playing along with a click track. If you already have loops playing on a pulse, the effect is to change the timing when they loop to their start. The loops themselves do not change speed (yet). "pulse": Number of the pulse "newlen": 1 for change tempo, 0 for just hit downbeat Event "go-sub" Triggers event "go-sub", which you can bind to. The effect is like creating a subroutine of several event triggers. You can then trigger go-sub from many places, and have the same subroutine of events triggered. This allows you to have FreeWheeling do several predefined things in response to one input, like changing loop volumes and moving loops, or repeating some operation on several loops. You can have many subroutines, and each subroutine can accept parameters. Search for go-sub to find examples in this config. "sub": Number of the subroutine "param1": Integer parameter 1 "param2": Integer parameter 2 "param3": Integer parameter 3 Event "browser-move-to-item" Moves forward or back in a browser "browserid": Browser ID- as you have defined in 'display' section "adjust": Number of individual items to move by (+ is forward - is back) "jumpadjust": number of divisions to jump by divisions are placed depending on the type of browser- for example, for Fluidsynth patches, there are divisions between soundfonts Event "browser-select-item" Choose or select the current item in a browser. Different browser types behave differently when an item is selected For example, the loop browser loads the selected loop "browserid": Browser ID- as you have defined in 'display' section Event "browser-rename-item" Rename the current item in a browser. This is an interactive process where the user can make changes to the item name. Many of the regular keyboard bindings become disabled during renaming. During renaming, you can type a new name with the keyboard. ESC aborts renaming, and ENTER accepts the new name. "browserid": Browser ID- as you have defined in 'display' section Event "patchbrowser-move-to-bank" Switch patch browser banks. "direction": -1 or 1 to move backward or forward Event "patchbrowser-move-to-bank-by-index" Switch patch browser banks, choosing by index. "index": Index of patchbank to select Must be in the range of 0 to SYSTEM_num_patchbanks-1 Event "browser-item-browsed" This event is sent out by Freewheeling's browsers whenever a browser item is changed. This is useful in the patch browser- you can bind to browser-item-browsed and send out control changes or change MIDI echo ports whenever a new item is browsed. "browserid": Browser ID- as you have defined in 'display' section. Identifies which browser has had a change in item. Event "video-show-display" Show or hide a video display with the given ID- you define the displays and IDs in the video section below, and then you can turn them on or off as needed through this event. "interfaceid": interface where layout is defined "displayid": Display ID "show": 1 or 0 is show or hide display Event "set-load-loop-id" Sets the loop ID where to put a loop when it is loaded from disk. Loops are loaded by the loop browser when an item is selected (browser-select-item). Whenever a single loop is loaded from disk, it will appear in this loop ID. "loopid": ID to load loops into Event "set-default-loop-placement" Sets the range of loop IDs to be used by default. For example when loading external loops, FW can place them here if the requested IDs are not available. "looprange": Range of IDs to use as default Event "loop-clicked" This event is generated whenever the user clicks a mouse button on a loop slot on-screen. It allows you to respond to clicks on loops. "down": Mouse button down or up? (1 or 0) "button": Number of mouse button pressed/released "loopid": Number of the corresponding loopid clicked on "in": Zero if the loop was clicked in the loop tray One if the loop was clicked in a layout Event "set-sync-type" Set the type of sync for syncronizing to an external sequencer/app. Freewheeling uses a 'pulse' concept of timing. Instead of dividing time up into bars, beats, and ticks (sequencer style), Freewheeling simply defines time as a rhythmic pulsing. When you create a pulse, Freewheeling can optionally transmit or receive sync information for that pulse. Two syncronization mechanisms are provided- Jack and MIDI. Both represent time as bars, beats, and ticks. The sync type parameter controls whether we are mapping beats to pulses (beat sync) or bars to pulses (bar sync). "type": 1 for beat sync, 0 for bar sync Event "set-sync-speed" Set the number of beats/bars per pulse. This affects the translated speed between Freewheeling's internal clock and the external clock. "speed": Number of beats or bars (depending on sync type) to a single pulse. Event "set-midi-sync" Set whether to transmit MIDI sync. Note that to transmit MIDI sync, you also need to set 'midisyncouts' in the general config section, and you need to have a pulse running. "midisync": 1 to transmit MIDI sync. 0 for no MIDI sync. Event "toggle-select-loop" Freewheeling allows you to select and work with several loops at once. This event toggles one loop as selected/unselected. You can have several selection sets. "setid": Number of the selection set in which to toggle the loop (usually this will be 0) "loopid": ID of the loop to toggle Event "select-only-playing-loops" Make the selection include only those loops that are currently playing/ currently idle. "setid": Number of the selection set to change (usually this will be 0) "playing": 1 to include only playing loops 0 to include only idle loops Event "select-all-loops" Select/unselect all loops. "setid": Number of the selection set to change (usually this will be 0) "select": 1 to select all loops 0 to select no loops Event "invert-selection" Invert the selection- Select all loops not currently selected. "setid": Number of the selection set to change (usually this will be 0) Event "trigger-selected-loops" Trigger the selected loops. You can toggle them for playing/idle, or you can force them to play. "setid": Number of the selection set to use (usually this will be 0) "vol": Volume at which to trigger loops "toggleloops": 1 to toggle loops for playing, 0 to force playing. Event "set-selected-loops-trigger-volume" Set the volume of all selected loops. This only affects playing loops. This allows you to fade many loops together. "setid": Number of the selection set to use (usually this will be 0) "vol": Volume to set loops to ***************************************************************************** Creating Bindings ***************** Each binding has two parts- 1) What input event and conditions trigger the binding? 2) What output event(s) are generated and what parameters are set for those events? For example- binding: input="key" conditions="key=escape and keydown=1" output="exit-freewheeling" Is triggered when the escape key is pressed. The key must match "escape" and keydown must match "1" (the key is pressed, not released). The event generated under these conditions is "exit-freewheeling". No parameters are set. Dynamic Parameters ****************** In the above table of input events, you can see that there are different input types that can trigger events. It's possible to use simple expressions in your bindings to dynamically check conditions and assign parameters. For example- This binding is for a MIDI keyboard with volume faders that transmit on different MIDI channels. Here, the volume faders are being used to fade loop levels: binding input="midicontroller" conditions="controlnum=7 and midichannel=0>15" output="set-loop-amplifier" parameters="loopid=midichannel+36 and amp=controlval/127*2" This binding is triggered when MIDI controller 7 (volume) changes are received on channels 0-15. Event "set-loop-amplifier" is generated (to change the volume of a given loop). The loop given is "midichannel+36". The volume to set the loop to is "controlval/127*2". So, a MIDI controller 7 input on channel 2 with controller value 127 will set loop #38 to volume 2.0 (200%). The example shows how input parameters, such as MIDI channel and controller value, can be referenced in your bindings along with simple algebra (+ - / *). Order of Operations ******************* When entering algebraic expressions, note that FreeWheeling does not evaluate with standard order of operations. The order of evaluation is always left to right. So: amp="3+3/6" will evaluate to 1 and not 3 and not 3.5. Algebra is evaluated conservatively with respect to type (I'm such a conservative!) That means that the expression: amp="1/2" will evaluate to 0 and not 0.5. For explicit floating point, use: amp="1.0/2" which evaluates to 0.5. Algebra on Ranges ***************** value="0>12 + 10" evaluates to "10>22". Both ends of the range are worked on. or value="0>5 + 1>5" evaluates to "1>10". Note that the types of each end of a range are always integers, so: value="0.5>1.5 + 0.5>1.5" evaluates to "0>2" User Variables ************** It is also possible to create your own user variables. These can then be referenced in your bindings, or changed during runtime, for a much more dynamic user interface. For example, the binding below will set trigger volume for loops across a range of notes. The binding checks to see that the MIDI note number matches the user variable "VAR_noterange". Since "VAR_noterange" is a range variable, this means that the binding will only trigger event "set-trigger-volume" if the note number is within the range specified by "VAR_noterange". binding input="midikey" conditions="VAR_cutmode=1 and notenum=VAR_noterange and keydown=1" output="set-trigger-volume" parameters="loopid=notenum and vol=velocity/127" **** Note that as of version 0.5pre3, FreeWheeling automatically indexes your bindings based on a hash key, so there is no need to specify wildcard cases (previously done with midikey="*"). **** Another example... The binding: binding input="midikey" conditions="VAR_xferloop=1 and notenum=VAR_noterange adn keydown=1" output="move-loop" parameters="oldloopid=VAR_xferidx and newloopid=notenum+VAR_loopid_pianostart" Checks these conditions: Input event is a MIDI Key Variable 'VAR_xferloop' equals 1? Input parameter notenum is within range of variable 'VAR_noterange' (When comparing against a range, a condition is true when the value is within the bounds of the range) Input parameter keydown equals 1 This binding is used to move a loop onto a piano key. Presumably, this is a special case where we have a loop in a holding place (such as a loop grabbed by a footswitch), and we want to move from that holding place onto the MIDI keyboard. Using a combination of user variables and careful configuration of bindings, a highly tailored user interface can be created. Order of Bindings ***************** The order in which we declare bindings in this file is important. Bindings are checked from top to bottom, so you will need to put special case bindings first. For example, if you want to modify the behavior of a binding when a certain variable is set or key is held, you will have to put the special case before the general case. The first matching binding is the only binding that is triggered. For an example, look under comment -Erase Loops-, and see that holding space while pressing a loop trigger key erases a loop, whereas if space is not held, it triggers the loop. System Variables **************** The following system variables may also be used in configuration. They are internal to FreeWheeling and are always available. You can not change the value of these variables with events like 'set-variable' and 'toggle-variable'.System variables have special events like 'set-master-in-volume' for control. Variables: SYSTEM_midi_transpose - semitones of current MIDI transpose - affects all outgoing MIDI events to FluidSynth and the external MIDI output port SYSTEM_master_in_volume - master input volume - 1.0 is full scale SYSTEM_master_out_volume master output volume - 1.0 is full scale SYSTEM_cur_pitchbend current value of MIDI pitchbender before offset SYSTEM_bender_tune - current offset of MIDI pitchbender (see set-midi-tuning) SYSTEM_cur_limiter_gain - current autolimiter gain - changes as audio levels change it's actually more of a soft compressor SYSTEM_audio_cpu_load - current audio CPU load SYSTEM_sync_active - nonzero if transport sync is sending or receiving beats/bars/ticks This will happen whenever you have a pulse, or if another audio app is transmitting sync information. SYSTEM_sync_transmit - nonzero if Freewheeling is transmitting sync information By default, Freewheeling tries to become timebase master. When the transport starts rolling, FW will transmit sync information. If another app is master, FW will receive sync information. SYSTEM_midisync_transmit - nonzero if Freewheeling is transmitting MIDI sync information. SYSTEM_fluidsynth_enabled - is FluidSynth enabled? SYSTEM_num_help_pages - number of help pages available SYSTEM_num_loops_in_map - total number of loops in the whole map SYSTEM_num_recording_loops_in_map - total number of loops currently recording or overdubbing in map watch this to see if you have runaway loops recording SYSTEM_num_patchbanks - total number of patch banks defined in configuration SYSTEM_cur_patchbank_tag - tag for currently selected patchbank- You can use this to change Freewheeling's behavior depending on which patchbank is selected. SYSTEM_loopid_lastrecord_0 SYSTEM_loopid_lastrecord_1 SYSTEM_loopid_lastrecord_2 ... - loop ids for those loops last recorded - lastrecord_0 is the most recently recorded loop, and so on.. the number of last record appears under loops, so you can see which loops were recorded more recently SYSTEM_in_1_volume SYSTEM_in_2_volume ... - current volumes for given inputs - up to the number of inputs you have defined SYSTEM_in_1_record SYSTEM_in_2_record ... - flag for each input that tells us whether the input is set to record SYSTEM_num_midi_outs number of MIDI outputs you have defined SYSTEM_snapshot_page_firstidx index of the first snapshot on the currently visible page of snapshots Browser types: BROWSE_patch Patch browser BROWSE_loop Loop browser- loads loops from disk BROWSE_scene Scene browser- loads scenes from disk Triggering Multiple Outputs *************************** You can set up one event input to trigger many output events. To do this, specify your output events and parameters for each in a list. Have a look at the binding for input="start-freewheeling", which triggers a bunch of events when FreeWheeling is first started. ** Note that as of version 0.5pre3, this new syntax replaces the old start="1" and continued="1" syntax for startup and multiple output events. ** MIDI Echo ********* FreeWheeling echos incoming MIDI events to MIDI output. However, events that trigger a binding are not echoed. This allows you to connect a softsynth or other MIDI device to one of FreeWheeling's MIDI outputs. Then MIDI inputs which trigger your event bindings, such as triggering loops, will not go to your synth. fweelin-0.6/data/coreinterface.xml0000644000175000017500000011643311071511705015720 0ustar mercmerc fweelin-0.6/data/dancemat.xml0000644000175000017500000001466411071511705014666 0ustar mercmerc fweelin-0.6/data/fweelin.xml0000644000175000017500000000335011071520617014533 0ustar mercmerc ]> &basics; &graphics; &interfaces; fweelin-0.6/data/graphics.xml0000644000175000017500000001135011071511705014677 0ustar mercmerc fweelin-0.6/data/interfaces.xml0000644000175000017500000000247011071547274015237 0ustar mercmerc fweelin-0.6/data/Makefile.am0000755000175000017500000000013210715214117014411 0ustar mercmercfweelindir = $(datadir)/fweelin fweelin_DATA = *.txt *.xml basic.sf2 vera.ttf verabd.ttf fweelin-0.6/data/Makefile.in0000644000175000017500000002216711071520730014430 0ustar mercmerc# Makefile.in generated by automake 1.10 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : subdir = data DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_CLEAN_FILES = SOURCES = DIST_SOURCES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; am__installdirs = "$(DESTDIR)$(fweelindir)" fweelinDATA_INSTALL = $(INSTALL_DATA) DATA = $(fweelin_DATA) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build_alias = @build_alias@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host_alias = @host_alias@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ fweelindir = $(datadir)/fweelin fweelin_DATA = *.txt *.xml basic.sf2 vera.ttf verabd.ttf all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu data/Makefile'; \ cd $(top_srcdir) && \ $(AUTOMAKE) --gnu data/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh install-fweelinDATA: $(fweelin_DATA) @$(NORMAL_INSTALL) test -z "$(fweelindir)" || $(MKDIR_P) "$(DESTDIR)$(fweelindir)" @list='$(fweelin_DATA)'; for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ f=$(am__strip_dir) \ echo " $(fweelinDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(fweelindir)/$$f'"; \ $(fweelinDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(fweelindir)/$$f"; \ done uninstall-fweelinDATA: @$(NORMAL_UNINSTALL) @list='$(fweelin_DATA)'; for p in $$list; do \ f=$(am__strip_dir) \ echo " rm -f '$(DESTDIR)$(fweelindir)/$$f'"; \ rm -f "$(DESTDIR)$(fweelindir)/$$f"; \ done tags: TAGS TAGS: ctags: CTAGS CTAGS: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(DATA) installdirs: for dir in "$(DESTDIR)$(fweelindir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am info: info-am info-am: install-data-am: install-fweelinDATA install-dvi: install-dvi-am install-exec-am: install-html: install-html-am install-info: install-info-am install-man: install-pdf: install-pdf-am install-ps: install-ps-am installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-fweelinDATA .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic distclean \ distclean-generic distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am \ install-fweelinDATA install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ pdf-am ps ps-am uninstall uninstall-am uninstall-fweelinDATA # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: fweelin-0.6/data/mercury.xml0000644000175000017500000002751111071511705014573 0ustar mercmerc fweelin-0.6/data/midifootswitch.xml0000644000175000017500000000652611071511705016144 0ustar mercmerc fweelin-0.6/data/midikeyboard.xml0000644000175000017500000002414011071511705015543 0ustar mercmerc fweelin-0.6/data/patches1.xml0000644000175000017500000006141411071511705014615 0ustar mercmerc fweelin-0.6/data/patches2.xml0000644000175000017500000006126211071511705014617 0ustar mercmerc fweelin-0.6/data/patches3.xml0000644000175000017500000001101711071511705014611 0ustar mercmerc fweelin-0.6/data/patches-b3.xml0000644000175000017500000000064111071511705015031 0ustar mercmerc fweelin-0.6/data/patches-channels.xml0000644000175000017500000000156611071511705016327 0ustar mercmerc fweelin-0.6/data/patches-receptor-1.xml0000644000175000017500000000127111071511705016506 0ustar mercmerc fweelin-0.6/data/patches-receptor-2.xml0000644000175000017500000000135611071511705016513 0ustar mercmerc fweelin-0.6/data/patches-strings.xml0000644000175000017500000000035111071511705016214 0ustar mercmerc fweelin-0.6/data/patches-test.xml0000644000175000017500000000132311050400362015473 0ustar mercmerc fweelin-0.6/data/pckeyboard.xml0000644000175000017500000001613511071511705015230 0ustar mercmerc fweelin-0.6/data/pcr-m1.xml0000644000175000017500000003615211071511705014205 0ustar mercmerc fweelin-0.6/data/verabd.ttf0000644000175000017500000016253410547030013014345 0ustar mercmercOS/2=@VPCLT,eϘ6cmapXcvt >-Rfpgmp9)gasp glyf4h)&hdmxEHheadO$6hhea. $hmtxy,kernlocaXz[maxp} nameYͿpostx<prep|a!\::N:: R^0p   t t  &   ; 0  0   C , [ `   0 & Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved.Bitstream Vera Sans BoldRelease 1.10BitstreamVeraSans-BoldCopyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is a trademark of Bitstream, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of the fonts accompanying this license ("Fonts") and associated documentation files (the "Font Software"), to reproduce and distribute the Font Software, including without limitation the rights to use, copy, merge, publish, distribute, and/or sell copies of the Font Software, and to permit persons to whom the Font Software is furnished to do so, subject to the following conditions: The above copyright and trademark notices and this permission notice shall be included in all copies of one or more of the Font Software typefaces. The Font Software may be modified, altered, or added to, and in particular the designs of glyphs or characters in the Fonts may be modified and additional glyphs or characters may be added to the Fonts, only if the fonts are renamed to names not containing either the words "Bitstream" or the word "Vera". This License becomes null and void to the extent applicable to Fonts or Font Software that has been modified and is distributed under the "Bitstream Vera" names. The Font Software may be sold as part of a larger software package but no copy of one or more of the Font Software typefaces may be sold by itself. THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. Except as contained in this notice, the names of Gnome, the Gnome Foundation, and Bitstream Inc., shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Font Software without prior written authorization from the Gnome Foundation or Bitstream Inc., respectively. For further information, contact: fonts at gnome dot org.http://www.bitstream.comCopyright (c) 2003 by Bitstream, Inc. All Rights Reserved.Bitstream Vera Sans BoldRelease 1.10BitstreamVeraSans-BoldCopyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is a trademark of Bitstream, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of the fonts accompanying this license ("Fonts") and associated documentation files (the "Font Software"), to reproduce and distribute the Font Software, including without limitation the rights to use, copy, merge, publish, distribute, and/or sell copies of the Font Software, and to permit persons to whom the Font Software is furnished to do so, subject to the following conditions: The above copyright and trademark notices and this permission notice shall be included in all copies of one or more of the Font Software typefaces. The Font Software may be modified, altered, or added to, and in particular the designs of glyphs or characters in the Fonts may be modified and additional glyphs or characters may be added to the Fonts, only if the fonts are renamed to names not containing either the words "Bitstream" or the word "Vera". This License becomes null and void to the extent applicable to Fonts or Font Software that has been modified and is distributed under the "Bitstream Vera" names. The Font Software may be sold as part of a larger software package but no copy of one or more of the Font Software typefaces may be sold by itself. THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. Except as contained in this notice, the names of Gnome, the Gnome Foundation, and Bitstream Inc., shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Font Software without prior written authorization from the Gnome Foundation or Bitstream Inc., respectively. For further information, contact: fonts at gnome dot org.http://www.bitstream.comf3f=ffTbfTfmf3bq%fHZfm99Xm=fuff9{{X3fLfLJ#DDf?;Pw /X#/553X sf+j-j!f#^`3B3\fy```{j\{`bXP1L`%!JJ7{'}3Xy9bsA&%$!:$#"!:"!: d}}      Y    & Y @ &  .A@}>,,G}G  @ 2 d۠d%%%   %ё%Д #&̑ɻ]ɻɀ@%]@%dĐ::2  }& @ ]%]@..@   K%%%2 ~}|{zywvwvututsr}qpo,o,nmlkjihc h2gf2ed ed d@cb c b a`a``_ ^]\\[Z[ZZYXWV@VUTSRQRQQPOPONONMLKLKJKJIJIHGFGFEDCDCBA%BAA%@?@?>?>=< =< ;d:987656%54554 4432 33@2 10100/ .-,:-,%,:+d*d)(''& %$#@+$#" "!!@  %@ K}K%%dd   2     @   @d  d++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++, %Id@QX Y!-,%Id@QX Y!-,  P y PXY%%# P y PXY%-,KPX (EDY!-,%E`D-,KSX%%EDY!!-,ED-ff&&/10!%!!fsr) @ <2991/0!!!!h33h^h@1<20###h++)K@1     91/<2<<22<<220!3!!!!#!#!5!!5!!!`aaE````HFR`PF#*1s@? %$ + ,#,, (/($ +/ 2<<991/99999990#&&''&&546773&&'6654&}osy!dede GUNWWP-.);?7* "*/(BE5;CBBDCB '3c@5  % ."( 41+  1 +%49912<0KSXY""32654&'2#"&546#3!2#"&546"32654&3GNMHHLMGֺ%պպHNNHHMNh{rs{{sr{ؽ۽ ٽڽ٨|rs}}sr|{&06@Y     ,-./+0()'%0' - -! '*$ 0$*$  *  199999991/99990KSX999Y"']@   ' 0   0%/ / %&? ? @K K K/K0ZZUZ Z U(\.\0X2_2dig`i i d&2, ' '* 9 5005@J I'I(WW\ ['ggl ]] >7!!'# 5467.54632.#"3267577oc%Xbi*([k^PMU1ABwCt2>FnkmFDےj5j:0.;6"W/wGs))@ 10#+ @ 29910!&547!י);: @   29910654'!)?C)9F@(      <2<29912290%#'%%73%JLLNLNMXX "@   <<1/<<0!!#!5!    m9@ 10!#hduo10!!ot91/0!!h}B/99103#mb/ #@  10&#"326! ! i||jj|{j@'&@mstm (@  1/20!%!!!T[nT HH5@)% 9991/2990KSX9Y"K TX@878Y@&**"""555BJFF]]!!>54&#">3 N!IFuZzz )~B~DiMLH+-zӱ(L@+  #)& )999190!"&'32654&##532654&#"663 sqlg~]^rl#!%'%%)67jcfi[]V^*) \3 C@ !  ! %    <291/<290KSXY"!!3#!!Z@jRJ=@"  " 190!!663 !"&'32654&#"v,Y00{zaSl 12/FFuv+-# $7@ "% %$%190"32654&&&#"6632! !2eeeefeev_PB[uEgჃ-+11ir E@%91/0KSXY"]@ &5F]!!!e'1} #/G@( '-0 $*& '&!$0991990"32654&%&&54$! ! $54632654&#"lttlkrr|כc\ZbbZ\cvnnuunou)ž)*ސUY``YY_`j$7@  %%" $%19073267#"54! !"&2654&#"\RDZ9$@ieffeeff!++22 "vYN`@<21/0!!!!ii`}}N` %@  <210!#!!idiu}=@29190 5<'@ <210!!!!=@<91905511J!H@'    "<299991/9990!546776654&#"6632!!Bj@95`VQfy]N^@D*i1Rb:4\.FOCB:*(ǿbY9>K-o Ml@: 40LM3 30 07$CN34L **)(I(*)4=N<991299999032654&#"#"&54632536654&'&$#"3267#"$'&5476$32!#?iZYjkZXiYثY|:;_tZked~Yk}٘~~On{KM'{zyZGOPGKɝdIz=;bɵdbg^Pag}}IJ}|b~ ' @@     %    91/<90KSXY"K TX  @878Y@ / V f  t   %* IFGH XYVWhifg` t{zu{t      /]]!!!!!F_}))}+%R P@%    !299991/90@ ""/"P"]2654&+2654&+)! [^^[tutuH|B7fPNMQsbcaay$ռmf\;@    - +21990/_]%# !2.#"3267\j}Lu}jksskR78ef87IDDI9.@  -. 99991/0P]32654&#! )=TMwiffixjq#ateeta 0@   21/0 P p ]!!!!!!rg +@ 21/0 P p ]!!!!!rgfK@%    1 3/-+19990_]%# !2.#"3267#!ʥLy}|@   221/<<0@P ` p ]!!!!!!89+y=71/0KTKT[X@878Y@P]!!+f= L@   991990KTKT[X  @878Y @ P ]!!#3265N3IO@UZfi ]]!!!!mR+ff 2@  -7-+10@ /?]"3254 ! f°±hhgddjk 1@   - 299991/0]! !#!32654&#1pzzp_mddlffb@   - 7-+999190@,  '/V S f ` w w p  Y Y YXj i x ]]# ! !"3254fgk-¾lkh\@2%       29991/<9990KSX9Y"]@66EEVVPee`]2654&+!! !.#yiiyL'O}@f7q^?ZgfX֔-XspR-'@*% %( "(999919990@Tp)9999 JJJ X ]\^^ Z!joooh o n!t t t || |!  !  !(]].#"!"$'32654&/.54$!2{hYuӎ⏏ |~[ {78LP@881/20K TKT[X@878Y@ ]!!!! `N3@   91290@p]!3265!! yy6= '@'%91/290KSXY"K TKT[X@878Y@,  GGHHEJWX]]! !! 5N+= x@J 6  6 6 6   %     91/<2290KSXY"K TK T[K T[K T[X  @878Y@  % :?:?3 0 0 @ @ @ ^^a          '('(%* /66220002 4 6 ?IFHE J ]]ZZUURRRZ U ] ooonhheh k n i o wwx v x   K]]! ! !! !=qsnDD==+o' @E    %     91/<290KSXY"K TKT[KT[X  @878Y@X  /& <3 _P      ++%$%+ :55: P ejo  ]] ! ! ! !omGF@(%:: 91/290KSXY"K TK T[KT[X  @878Y@, %%0@P` %*5:0 O o ]]! !!TTu\q w@% 991/0KSXY"K TK T[X  @878Y@ %)69? FHO V_ o ]!!!5!s8!7@210!!!!mB/99103m@210!5!!5!m`@ 91290##fg--/10!5۾^fN10K TKT[X@878YK TX@878Y] #yfxX{ %@*   # # = ;&229991/9990@L/'= =!?'M M!] ]!n n!~ ~!p' ! ! ! !20C@SPc`]]"326=%!5#"&54$!354&#">3 pq[QeiH"ӆsUst/ LJDMm)f]ˢŸUO..^ 8@ B@ 221/0O`]%2654&#">32#"&'!!syyss{{{Ju uJf稠b]]bX5{7@ B ;210_].#"3267# !25IOT@TWV/X=202177\8@ @B ;221/0O`]!!5#"322654&#"hJu tsyysryyXc\II]ɨX {C@!    D ;9190/?]!3267# ! 4&#" q}K"=w`h3f~~CD015:“f}un'`@    E <<991/22990K TKT[X@878Y@ ]#"!!!#35463L<27DN`N\Fy(K@& #& @ B;)221/990O*`*]%#"54325!!"&'3265"32654&Ju uJhic^[o|xsp||b\CA\c !655@   G 21/<9990`]!54&'.#"!!>32 H.pfQnVon#'b])@ <21/0@ P ` p ]!!!!ff`F =@    <2991990@ P`p]!+53265!!fͱ>fLf`\y @   291/<90@`;IIZ]X_ogvv{:DGJV]g`ewpv|]]!! !!fNNK- 1/0@ P`p]!!f{%t@)   #  H H &<991/<<<29990KTX&&&@878Y@'0'P'p'''']>32!>54&#"!4&#"!!>32DpFNfo@RgphBgthmVH wkHk`_`p{5@   G 21/<9990`]!54&'.#"!!>32 H.pfQnVon#'`b]X'{ -@  BLB;107?G]"32654& ! w}}wu||u!EG{88V^{;@B @ 2210O`]%!!>32#"&"32654&fJu us{{ssyy b]]7\Vy ;@  @B;2210O`]"32654&#"325!!ryyrsyyyJu uJhw+c\IG\c{C@     21/990KTX@878Y.#"!!>32/]/fE}*(/`nejb{'@@  6  6% %( SRP"M(9999190KSX99Y" ]@^ #  ,. . . . . ) 9; ; ; : : K J J J H w w  %  7 ?)_) ]].#"!"&'32654&/.54632s_fcKa?o}ktijIm?c=0035+. ###44:90/ x@    T<<991/<2990KTKT[KT[KT[X@878Y@??PPP`` ]]!!;!"&5#33q>\Ա%N7>`;@  G 291/29990`]!3265!!5#"&hG.pfQmp[.w#&)b]`@'%91/290KSXY"K TKT[X@878Y@| 0@Vf  &$+)64990FFII`x$]]! !!fgGw`H` @J 4  4 4 4   %     91/<2290KSXY"K TK T[K T[X  @878Y@ 550 G @ @ _ l        &$+)*+ $ % /554;::78 ?GIFHGH YVV[ T Y _f`b```d ` upspppt p      []]!!!! !H\+\yy` ` @F    %    91/<290KSXY"K TKT[KT[KT[X  @878Y@  / 3< CL R\ bl sz         2     $++$ 4;;4 0 DKKD o       :]] !! ! !l{{l=#LbF`A@C %    9129990KSX9Y"K TKT[KT[X@878Y@ @Pet $$$5586699EEJJEEge    9]]! !+5326?f-f)Gp[S `6:K\F` @% 2991/0KSXY"K TK T[X  @878Y@DYVifyv &)/ 9? J_ ]]!!!5!uNN`f$^@1 %   ! % $  %<<29999999199999990#"&554&##5326554633#"3l==lEUZnoYUmutWW10#$`@2%   #%# %<2<999999919999999032655467&&554&##53233#"##FUZooZUFl==lmWW͖tuR#@  1990#"'&'&'&#"56632326j`k^Xbk`k^VRPE:=MSPE:=K 'k'$u 'm!{@S!! ! !%! !  UU "9999999991/<9990KSXY"K TX"""@878Y@/!/!:!o! !! # ///  /// "+ #EKUZ` ` ` ooo``ooo`fi `#tuyz{t    D]] !!!.54632%32654&#"!}^_}vtwM66MN56MJH"K+uu/L{6MM66MMRfo\'&sk'(um'15uffk'2Nuk'8'uXf'DXf'DCXf'DX1'DX9'DX'DXo5{'FX f'HX f'HCX f'HX 1'Hf'wf'Cwf'w<1'w9'QX'f'RX'f'RCX'f'RX'1'RX'9'Rf'Xf'XCf'X1'X5; *@  WV W <<1220!!!!!5!VJ#!/dL @  XYX10"32654&'2#"&546HdcIHdeGBz0/11-0|D\dHHbcGHd3/0xDCy-03#W@.    !$   B$<<222991<9990&&##667###$4%3NMMNJAY9S: GZ,lm*902i2/  (.##}@@!   <<1/222990&&#"!!!!3#5356!2FMvqu\'&} F=3?k@8@1:4 %+1@ =!+%74:!=\.!\=[.7[(@9999991999990&&#"#"&'532654'&'&&5467&&546326654&uc9KL ҟquMKUfs9AN$ˠoqKATDC{AF''1/CO Y}u0)qI)+2(FJWh33oKL2CbBO4Cj'` ]104676632#"&'&&'535II245633JI326J235624IJ336633;d &@ ^^9120!###&&54$\fN۲h0j@4.(" !++/"!(%  a%.(a_ . 199991/990@ /2O2p22]4$! #"&'532654&/.5467.#"! 1]EtkAJ8s6HX7bFXT`[efZG NJ%94%@uH9/D7'1Zt2UYnm 4Lb@8-*+'0!5 2+A'*,$0-+$!1g3f$cX;eX3cGM299991/29990"32676654&'&&#32654&'2#'&&###2#"$'&5476$yWWWWWVy{WWWWWXϲ##NOM+i`)Gok&: 1mmllmmmmllmm3WWWzyWVVUWWyzWXV5442wyVpP:NAD7nmmmmnnmmmmn1IH@(  2&>f,X c8e XhDJ21/990&&#"3267#"&54632'"32676654&'&&'2#"$'&5476$+9o9q~r@s.A>EyWWWWWVy{WWWWWXymmllmmmmllmmf%#rs~$#WWWzyWVVUWWyzWXVnmmmmnnmmmmn'R v@>  %    ji i ji91<<2<<9990KSXY"73#######5ww㪉LqKBMmf710K TKT[X@878Y]!#f;;1\@1<20K TK T[KT[KT[X@878YK TX@878Y3#%3#1 =@!      <291<2<2.990!3!!!'7#5!7!^P1}@7%     /<291/<90KSXY"K TK T[X@878Y@&W ] !!!!!!!!!{y}sfb^- +@> +,   )*&& &,+,* # )-#7-+,99999999199999990@p- -*'&!/-976!9)?-GYVT!Y(Y)jege!j%j($'))68)KFE I)Z^SVV T!V"[(j ejlaf c!k(x ]]3254&/.#".5!27!"&''\4SM3RJJgfqMLhfqs>;Du1:9@q.dkKMscdOOq /B@#  $'!-!0 $k*k099991<999032654&#"&&#"326#"&546326632#"&+vIZqgLHw+tKZqfMGzDaƯZcG_ů[1CDeOMeeCCdOMeia~q~n .@   l l <2<21/<<0!!#!5!!!  bb '@    <2291/90%!55PN '@   <<291/907!!55%y@B  %     nm n m<2<2999991/2<<<290KSXY"]@, $+6:FI   0@ ]]!!!5!5'!5!! !!!!N9:1k$! %j1`BV3VBT` :@!  !   !2912<990!3265!3267#"&'#"&'idfgdh!'!5]-Yq#/YJhT utqqtG8 KSOO/0;R)8@'! '!* $$*99919906654&#"#"&54632#"&54324&#"32;'#S0@eID`IFa~q9WzC2EqG Ur|tx)w O@    91990@ &#)  ) ( ) 8 ]]!! !!5 Bl_{Nw@pp120!!!!)JD/@    991/<22990#!#!#"663J'7: Ddd>Dǜ3,B*# @- *(&  qr q-9919026732#"&54&#"#"&54632jciRA@Ae '&>ÄkTF32-ӅhB:Yr 7^YUWO\K=4>3:rWT@LHt8;##uu 9A  @  uu 99102#"&546!!"32654&B7T[[TS[[޾ܾM~tt||tt~7F   @  xwx w 9991/<2990!!654&#"!!&5! #~˲˄~#~zx89xz#VˤUy9yǤX{>@B8>66'&# 6-*>;0*? - 6 & 7 3;?<9999912<<<9990@N>>?@MMO@^^_@nno@@@2=0>B=@>R=P>b=`>=>=>=>=>]]4&#""326=>32>3 !3267#"$'#"&54$!354&#"w`gpq[Qe^waGMz =q}~Heߋ"ӆsUf}unLJDMm)JMOMOf~~CD01kdkdŨŸUO..N) +@> )+ *& &&++, #* #)B#LB;,999999991/9999990@@:5 ;75!8)?-IF KGD!H)[VT!U(ikfe!e(5:)EJ)U^(i em( ]].#"32654&'.5!27!"&''XK/w}HO0u|;CDG"jKmFElMpD)A+CN{8,,eP~--^!M@*   "  "<2999919990!3267#"$54677665%!!iAm@84`VQew\N^@D*ii1Q~d:3\/FPDB*(ǾcX:=L-d @ <2991/0!!!33h=^qd@ 10!#!LZ n@*      %  @  9190KSXY"3##'%`w͑%hN7V7#w@I #"!   %   !$2299990KSX92Y"&&#"!!#"&'53267#5!766327.T*Zd!)AD.U)Ycu!3*Bs_sM#;C@!.9* 1 "9*1<-<<219999990#"'&'&'&#"56632326#"'&'&'&#"56632326j`k^Xbian ^Vgj`k ^Xbk`k^V#PE:=MSNE;=KPE:=LTPE:>K  @ /91/90!!!#-3mV?j' 5  @  y y<2991<299055%$'qsq' 5  @ yy <<991<29905-5%%%!$'^ #@   1/<<220!!!!!!hhh}}} 'k'$u 'm'$uffm'2NufP@"     -+ 299991/220@ !!?!O!_!]# !3!!!!!!"# !2i iZhsf / F& 0ihX^{'3t@2"  .(%4"1 1 +B;499912<9990@/5?5O5O5_5o5o55F"]]4&#"!3267#"&'# !2>3 %"32654&w`hA q}~~HRՂG"QRLJBcw}}wu||f}unwf~~CD01QWTT88RVWQ:/10!!/10!!X +@    1<20!3!3!ddXb`Xo + @  1<20!#!#!TeTe`^X@ 10!3'dX`X9@ 10!#Td`V 0@  z{z <<10!!!!!!33Xˁ#uv@A%91990KSXY"  9%-F1'\k'<uh+@55%10KSXY"#3 J=#/@ ! ! $A !* @&00   '}|~-} |022999999122999990'7&&5467'766327'#"&72654&#"ϙљ0l=6l9ϘϚ.j?:l[\[~ Ϛ1k??l.͚Ϛ7n6?i/ϙ\\\]~'y291905%'q'y<91905%%$'+Bu@&       ET<2<<991/<2<2990KTKT[KT[KT[X@878Y@]!!#"!!!!#35463iJK:k$7DN``N'Bl@!      ET<2991/<22990KTKT[KT[KT[X@878Y@]!!!"!!!#3546{L<)7DN`N3;?@!   W VW <<<<2912<220!!!!!!!5!!5!VJ###!<}910!!h}L@ 10!#Te`F + @  1<20!#!#TeTe`^B V #/3?K|@C3 2211 003%@ *$F4 :02$L3IC1!  C=!'= I7' -L9912<<2220KSXY""32654&'2#"&546"32654&'2#"&546#32#"&546"32654& HNNHGLLGֹHNNHHMNGպֺ׺GNMHHLMh{rs{{sr{ؽ۽8|rs}}sr|ٽڽ ؽ۽٨{rs{{sr{ 'k'$uk'(u 'k'$uk'(uk'(uk',duk',du)k',du=k',duffk'2Nuffk'2Nuffk'2Nuk'8'uk'8'uk'8'u` 1/0@ P`p]!!f`yf6@ 91290K TKT[X@878Y3#'#Dzf\9@  @  999919999990K TKT[X@878Y@T              ( ]]'&'&#"#4632326=3#"&7/$&g]$I)=%$(g]$CT%>;+@9X;E10K TKT[X@878YKTX@878Y!!vPF i@  1<0K TKT[KT[X@878YK TX@878Y@]332673#"& cSSc FFJJFw;1*10K TX@878Y!!w1 C @ : 10K TKT[X@878Y32654&#"4632#"&}M67LM67Lvvvv7LM66MM6vvvo5@   991/0K TX@878Y!#"&/32654&'Z:7{0f42S!:A+->j/_[ .(R<fE@991<20K TKT[X@878Y3#3#-fxVo@   991/0!33267#"&546ō2&;1'M(7^)s{6CI'1 \V5myf6@ 91<90K TKT[X@878Y 373Dzx `@2 %    <<.9991/90KSXY"!7!!'%s۔#` j ~@-   %    T <2.991/90KSXY" ]@ut@ P ` ` tp p  ]]!7!'7ho}o XV-k'6ujbf'Vb\qk'=u\Ff']T@ <210##  !L @   -. <291/<20@X!P!`!////////OOOOOOOO________(]]3#32654&#! )#3PULxhgghyk#ateetamX'(@Y&'('%$%(('"#" ! "! 5((5(%('&%"! ## #)'& !#(%" BB;)999919990KSX92Y"KTKT[X)@))878Y@6f!/*76"?*O*oooooooooo]].#"32654&! 4!2''%'!%7l4uru| uj-.N$%3`ox#y-\8 watr`k'<uFf'\ @  - 2299991/0K TK T[KT[KT[KT[X@878Y@,0000PPPP]]!!3 !32654&#=1pzzp]mcenV^;@B @ 2210O`]%!!>32#"&"32654&fJu us{{ssyyb]]7 10!!) /@   <291<290 '7NNNN3NPPN{ 7  @   129035733!9 41Zm]@%   "@99919990KSX9Y"!!56654&#"56632r_9=4I;>TWKGeD 5P(2>-/oHyVZ(W@ #  ""#@#)& )99919990#"&'532654&##532654&#"56632P\fQDB<_hkrJTbZNP4{FAWZ`nQ$%@;@=/3--piE`d @     % @    229991/222990KSXY"333##5!5#335733!9y+ I 41Zd'@   %!   $$& !&"@ #%# (9991/299990KSX9Y"%!!56654&#"56632#335733!qt];>3J<>UXJIc 5N'2?-0oH|T I 41Zh 6:@ : 9988 77: %.1* #! #!$-*$!#917@$$8'" :!'"4  '4-";229999991/2<299990KSXY"33##5!53#"&'532654&##532654&#"56632#3'y%]fQDB<_hjsJTb[OO5zGAVZ-D7#nQ$%@;@=/3--piE`q fk'* 1u\FF'J=k', duo-'6job{'Vbf\k'&fuXuf'Ff\k'&fuXLf'F\$K%@"      @"B;%<<1/<20O&]!5!5!3#!5#"322654&#"FhJu tsyysryyrr+c\II]ɨo10!!ot910!!h}1r@;.*(1.!2*("%!) 2 +) )% 2229999999999122<2990%# '#73&&5467#736!2&&#"!!!!3267_pKXbXMep_Qc-VY2~cTR78 87NO{v$$ zzOO;@ 1<203#%3#mN810K TX@878Y@ //]!#3\#@  @! $  $999991<29990K TX$$$@878Y@\             ##+]]'&'&#"#465463232653#"&8- (kW%J';'%'kW&F#<2j'<9j810K TX@878Y@ //]#yE@ 91<90K TX@878Y@/// ]!#'#f4߲DzyK@ 91290K TX@878Y@//// ]373f߲DzP S@  120K TX@878Y@///// / ]332673#"&`LL`=<<=w*10K TX@878Y!!w  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~>: ~1BSax~ & 0 : !""""+"H"e%  0AR^x}  0 9 !""""+"H"`%^ChVjq_8 (Bbcdefghjikmlnoqprsutvwxzy{}|~f+B{s/) mRo b\}j331 fwwf3ff)u 1 =+'\^fXX\mX{'\RVX\j7dH)7\1 1 fwffXfXfXfXfXfXXmXmXmXmX<XXXXX5}''m-Z;)L'3u'7bXNVL++1 1 f VfXBB  7VhJLL+'3  B B1 w1 ww)fffwV#j\\!X7{mZHdHdHhf\jfXfX\Ro mw   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~    sfthyphenperiodcenteredEuroc6459c6460c6461c6462c6463c6466c6467c6468%%%%Nq] 6 N{U?u<_O K G E a > *2e:\u#p|$Z<~*Z@!I"dqjw   - : G T a n { !!]!"""##$.$%!%K%%&H''n''((()6){))*<*++p,5,-8-a-}-.B..//\/////00001161U1t112 2292233v344-4L4~5*575D5Q5^5k5x5555555556 67667H7k778'8W889-9:9G9T9a9::::;O;;;<>>>>>>??????@4@T@AA@AuAAB 79k:;Y<$&$&$&$&$7a$8$9u$:$<<$Y$\$h$D$D$$<$r$r$$$$<$%9%:%<%%&/&6&&K&K&&&&'&'=>=<=<; <@; :987876765 65 43 21 21 0/ 0 / .- .- ,2+*%+d*)*%)('%(A'%&% &% $#"!! d d BBBdB-B}d       -d@--d++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++, %Id@QX Y!-,%Id@QX Y!-,  P y PXY%%# P y PXY%-,KPX EDY!-,%E`D-,KSX%%EDY!!-,ED-ff@ /10!%!!fsr)5 @@ <2991/0K TX @ 878Y P ]%3#3#5qeM@1<20KTKT[X@878Y@0 @ P ` p ]#!#o$++`@1      91/<<<<<<<2220@   ]!! !3!!!!#!#!5!!5!T%Dh$ig8R>hggh`TifaabbNm!(/@U" '&( /)/))/B" ) *!#*- ) " & 0<<<1/299990KSX99Y"K TX0@00878YK TKT[KT[X000@878Y#.'5.546753.'>54&dijfod]SS\dtzq{---@A$*.U# jXV`OnZXhq) #'3@6$%&%&'$'B .$ &($4'!%   ! + 1 49912<0KSXY"K TK T[K T[KT[KT[K T[X4@44878Y"32654&'2#"&546"32654&%3#2#"&546WccWUccUVcbWWcd1Zܻۻa ۻۼ 0@      !         B  (('+'$ .  .'.'!!199999991/9990KSX99999999Y"2]@ " ) **&:4D ^YZ UZZY0g{ "-  ' (   2'') #**(/2; 49?2J LKFO2VZ Y UY\_2j i`2uy z 2229]]3267 >73#'#"5467.54632.#"[UԠ_I{;B h]hΆ02޸SUWDi;#QX?@Yr~YW׀c?}<$$/1oX3goB@ 10KTKT[X@878Y@ @P`p]#o+{ O@  29910KTX@878YKTX@878Y#&547{>;o @ <99103#654<:=JN@,       <2<2991<22990%#'%%73%g:r:g:PrPbybcy #@   <<1/<<0!!#!5!-Ө-Ӫ--@ 1073#ӤR@d10!!d1/073#B-@B/9910KSXY"3#m #@  10"32'2#"  P3343ssyzZ K@B  1/20KSXY"KTX  @878Y]7!5%3!!JeJsHHժJ@'B   91/20KSX9Y"KTKT[KT[X@878Y@2UVVzzvtvust]]%!!567>54&#"5>32Ls3aM_xzXE[w:mIwBC12\ps({@.    #)&  )99190KTKT[X)@))878Y@ daa d!]!"&'532654&+532654&#"5>32?^jTmǹSrsY %Đ%%12wps{$& Ѳ|d @   B    <291/<290KSXY"K TK T[X@878Y@* *HYiw+&+6NO O Vfuz ]] !33##!55^%3`du@#    190KTKT[X@878YKTX@878Y!!>32!"&'532654&#",X,$^hZkʭQTժ 10$& $X@$  "% " !%190@]]"32654&.#">32# !2 LL;kPL;y$&W]ybhc@B991/0KSXY"KTX@878Y@X9Hg]]!#!3V+ #/C@% '-'0 $*$ !0991990"32654&%&&54632#"$54632654&#"HŚV г "Əُattt$X@# %!"" %190@]]7532#"543 !"&2654&#"LK:lL>$& V\s[#@<21/073#3### %@  <2103#3#ӤR#٬@^M@*B$#29190KSXY" 5Ѧ`@ #<210!!!!^O@+B$#<9190KSXY"55//m$p@+$     &%99991/9990K TX%@%%878Yy z z ]%3##546?>54&#"5>32ſ8ZZ93lOa^gHZX/'eVY5^1YnFC98ŸLVV/5<4q L@2  L4307$7CM34( (+(I+*(I,=M<9912990K TK T[KT[KT[KT[XMMM@878Y@ NN/N?N]32654&#"#"&5463253>54&'&$#"3267#"$'&5476$32|{zy!orqp ˘s'6@   0210].# !267# !2'ffjzSb_^^_HHghG.@   2 99991/0`]3 !%! )5BhPa/w.,~ .@   21/0 ]!!!!!!9>ժF# )@ 21/0 ]!!!!#ZpPժH7s9@ 43 1990%!5!# !2&&# !26uu^opkSUmnHF_`%; ,@ 8  221/<20P ]3!3#!#"d+991/0KTX@878Y@ 0@P`]3#+f M@  9 991990KTX  @878Y@ 0 @ P ` ]3+53265M?nj @(B  291/<290KSXY"]@ ((764GFCUgvw    (+*66650 A@E@@@ b`hgwp  ,]q]q3! !#3wH1j%@ :1/0@ 0P]3!!_ժ @4  B    >  91/<290KSXY"p]@V   && & 45 i|{y   #,'( 4<VY ej vy ]]! !###-}-+3 y@B6 991/<2990KSXY" ]@068HGif FIWXeiy ]]!3!#j+s #@  310"32' ! ':xyLHH[[bb:@   ? 291/0@ ?_]32654&#%!2+#8/ϒs R@*  B     39991990KSX9Y""32#'# ! '? !#y;:xLHHab[T@5  B    ?  299991/<9990KSX9Y"@]@Bz%%%&'&&& 66FFhuuw]]#.+#! 32654&#A{>ٿJx~hb؍O'~@<    B %( "-"(9999190KSX99Y")])/)O)].#"!"&'532654&/.54$32Hs_wzj{r{i76vce+ٶ0/EF~n|-&J@@@1/20K TX@878Y@  @ p ]!!#!ժ+)K@   8A1299990KTX@878Y]332653! ˮ®u\*$h@'B91/290KSXY"P]@b*GGZ} *&&))% 833<<7HEEIIGYVfiizvvyyu)]]!3 3J+D {@I      B     91/<2290KSXY"]@  ($ >>4 0 LMB @ Yjkg ` {|      !   # $ %  <:5306 9 ? 0FFJ@E@BBB@@ D M @@XVY Pfgab```d d d wv{xwtyywpx   []]3 3 3# #D:9:9+=; ]@F      B    91/<290KSXY"K TK T[KT[X  @878Y@ '' 486 KX[fkww       &()&(' ) 54<;:;4 4 8 ? H O X _ eejjhiil l xyyx}  x   @]]3 3 # #su \Y+3{@(B@@ 91/290KSXY" ]@<5000F@@@QQQe &)78@ ghxp ]]3 3#f9\ @BB 991/0KSXY"K TK T[X @ 878Y@@ )&8HGH    / 59? GJO UYfio wx ]]!!!5!sP=g՚oXS@C210K TX@878YKTKT[X@878Y!#3!XB-@B/9910KSXY"#mo<@C<10KTKT[X@878Y!53#5oXޏ@ 91290##HHu-10!5f1@ D10K TKT[X@878Y #ofv{-{ %@'   #   E&22991/9990@n0000 0!0"?'@@@@ @!@"PPPP P!P"P'p' !"'''000 0!@@@ @!PPP P!``` `!ppp p! !]]"326=7#5#"&5463!54&#"5>32߬o?`TeZ3f{bsٴ)Lfa..'' 8@  G F221/0`]4&#"326>32#"&'#3姒:{{:/Rdaadq{?@  HE210@ ].#"3267#"!2NPƳPNM]-U5++++$$>:#qZ8@G E221/0`]3#5#"3232654&#":||ǧ^daDDaq{p@$   KE9190@)?p?????,// , ooooo ]q]!3267# 32.#" ͷjbck)^Z44*,8 Cė/p@     L<<991/22990K TX@878YKTX@878Y@P]#"!!##535463cM/ѹPhc/яNqVZ{ (J@#  &#' & G E)221/990`***]4&#"326!"&'5326=#"3253aQQR9||9=,*[cb::bcd4@  N  F21/<90`]#4&#"#3>32d||Bu\edy+@F<21/0@  @ P ` p ]3#3#`Vy D@   O  F<2991990@ @P`p]3+532653#F1iL`a( @)B F 291/<90KSXY" ]@_ ')+Vfgsw    ('(++@ h` ]q]33 ##%kǹi#y"F1/0@ @P`p]3#{"Z@&   PPF#291/<<<290@0$P$p$$$$$$$ ]>32#4&#"#4&#"#3>32)Erurw?yz|v\`gb|d{6@  N  F21/<90`]#4&#"#3>32d||Bu\`edqu{ J@  QE10@#?{{   {  {]"32654&'2#"s98V{>@ GF2210@ `]%#3>32#"&4&#"326s:{{8 daaqVZ{ >@   GE2210@ `]32654&#"#"3253#/s:||:/daDDadJ{0@    F21/90P].#"#3>32JI,:.˾`fco{'@<  S  SB %( R"E(9999190KSX99Y"']@m   . , , , ; ; ; ; $( ( *//*(() )!$'      '/)?)_))))))]]q.#"#"&'532654&/.54632NZb?ĥZlfae@f?((TT@I!*##55YQKP%$78@  F<<2991/<2990]!!;#"&5#53w{KsբN`>X`6@    NF21/290`]332653#5#"&||Cua{fc=`@'B91/290KSXY"K TX@878YKTKT[X@878Y@Hj{  &&)) 55::0FFIIFH@VVYYPffiigh`ut{{uz>]]3 3#=^^\`TV5` @IU U U U   B     91/<2290KSXY"K TKT[KT[KT[K T[X  @878YK TK T[KT[X @ 878Y@" 5 IIF @ [[U P nnf yy          %%#'!%""%' $ ! # 9669 0FHF@B@@@D D D @@VVVPQRRPS T U cdejejjjn a g ouuy}x}zzxy  { v } @/   y]]333# #V`jjj;y` Z@F      B   91/<290KSXY"K TKT[KT[KT[X  @878YKTX @ 878Y@   & =1 UWX f vzvt        )&% * :9746 9 0 IFE J @ YVYYWVYVV Y P o x  /]] # # 3 dkr))`HJq=V`@C        B     9129990KSX2Y"K TKT[X@878YKTX@878Y@     # 5 I O N Z Z j        '$$  )( % $ $ ' ** 755008 6 6 8 990A@@@@@@@@B E G II@TQQUPPVUVW W U U YYPffh ii`{xx   e]]+5326?3 3N|lLT3!;^^hzHTNlX` @B 2991/0KSXY"K TK T[X @ 878YKTX  @878Y@B&GI  + 690 @@E@@CWY_ ``f``b ]]!!!5!qjL}e`ۓ%$@4 %   !  % $  C %<<29999999199999990K TX%%%@878Y&]#"&=4&+5326=46;#"3>l==k>DV[noZVtsݓXX10#$@6%   #%#C %<2<9999999199999990K TX%@%%878YKTX%%%@878Y&]326=467.=4&+532;#"+FUZooZUF?l>>l?VWstݔ1#@  1990#"'&'&'&#"56632326ian ^Xbian ^V1OD;>MSOE<>LhN'$uhm !@T   !!  ! !!!B     !  VV!"2299999991/<9990KSXY" #]@  s P#f iu {yyv v!# ]]4&#"326!.54632#!#TY?@WX??Y!X=>sr?<҈_Z?YWA?XXN)sIsrFv)su''&-k'(u3^'1usN'2'u)N'8u{-f'DR{-f'DCR{-f'DR{-'DR{-7'DR{-'DRqu{'Fqf'Hqf'HCqf'Hq'Hof'f'C\f'F'd7'Qquf'Rsquf'RCsquf'Rsqu'Rsqu7'RsXf'X{Xf'XC{Xf'X{X'X{9; '@  YW Y <<1<203!!#!5!oo\]u=  @  Z[Z10"32654&'2#"&546PnnPPnoO@v+..ooPOmmOOp1.-rB#!Q@+     "  "<<<221<9990%&&'667#&73JDFHAMf fIX⸹)**'# 32!b`@!    <<1/2<2990K TX@878Y66].#"!!!!53#535632NL=ty-=))׏/я\= >@54&.#"#"&'532654/.5467.54632{?>?>S8alӃ\]>9̭IXW:fqր][;;ȦI.Z.L-[.K''PGZsweZ54m@''TLf{xf[1,pE3!   \ 104632#"&3~|}}||};9 %@]] 91290!###&&54$yfNݸ/@0-'!  **.  !' $'$-F099991/990@@'(     ! "&  : :!MM I!I"jj  ]]4632#"&'532654&/.5467.#"#:A9`@IPAtx;e\`Wqqs`/Q*%jd_[?T>7;[gp/8L`@6EBC?2H09JC 9 $HE301BKL?gwyVpMI`3D/IC@&=>:A$104G$ 7aD=0^* D^ J21/02#"$'&5476$"32676654&'&&&&#"3267#"&54632mmllmmmmllmm^^``^^⃄^]]^\^BB@zBCFInmmmmnnmmmmng^^^傁^^__^]⃅]^^! "'F >@!    b b cbc91<<2<<903#######5Jq7rqr/B^^sRf1@ D10K TKT[X@878Y3#fF)@dd1<20K TK T[X@878YK TK T[KT[KT[X@878YKTKT[X@878Y@````pppp]3#%3#^y'>@"     <291<2<<990!!!!!'7!5!7!}/H{};fըfӪH@9  B     <291/<0KSXY"]@gww  ]!!!!!!#!59=qժF՞f +@< +,  )&  *&& &,+,* # )#3,99999999199999990@*WZWU!je!{vu! FYVjddj(|svz( ]] 324&'.#"&5!27!"&''3>_'y=_''NOy;WfNPƀ[gX@CHp@CpDfbMKYg[KKX /@- !$'!!0 $*0999919990@     $$$   $$ $ ***///***55500055 5 :::???:::EEE@@@EE E JJJOOOJJJV !"&'()]]32654&#".#"326#"&54632>32#"&1TevYR1UfvYRF^_HDa^/XZie7XXjeߦ~᧯w .@     <2<21/<<0!!#!5!!!-Ө-}} T@.B $# <2291/90KSXY" 5!!@po V@/B$ # <<291/90KSXY"55!5AǪR@F  B     fe f e<2299991/2<2<290KSXY"K TX@878Y@(' ' ')((79  ]]!#!5!5'!5!3 3!!!c`Tþ{yT9{3{JD{3V` M@%  !   NF!2912<990"`""]3326533267#"&'#"&'#% )I#ER2bf*V H<9 NPOONNh-)b@'! '!* $$*9991990K TK T[KT[KT[KT[X*@**878Y>54&#"#"&54632#"&54324&#"32IH7$$0e՘ݢe WOmVPmmWKt,>bFأ[t}t{w; ]@    91990@0QVPZ spvupz  Z pp{ t  ]]!! !!5 7AJI3!wq@gg120!#!# }/#@1 " $ #" #h#$9999991/<229990K TX$$$@878Y@V             ##(]]#3267#"&5467!##"#>3!i/7.%7vy"Pµ)6< yJ\:1fd.xo@E}/%&@  & iji&1026732#"&'&&#"#"&546327j Pd@7*8  kOeD=!0 l9TA6?&#Hn!bSA8?Ss;)_@3(%%  * "(kl"k *22999199990!!#5#"&5463354&#"56632"32655P,]uu>DIE~bRhP{@p?Dq[[""CO@Mr`d.@  klk 9910!!2#"&546"32654&PXγгi~hi}|P{ݿܾsN@@"   mm  9991/<20%!5654#"!5!&5! Dz?1/aL"a*>w؍{o{3>@C'-%= 4%:.-*1 %?47&%7& =&-7"E?<9999912<<29990@0+0,0-0.0/00@+@,@-@.@/@0P+P,P-P.P/P0+0@@@@@@@@@??? ??0,0-0.0/@,@-@.@/P,P-P.P/ooo oo`,`-`.`/p,p-p.p/,-./]q].#">32!3267#"&'#"&5463!54&#"5>32"326=DJԄ ̷hddjMI؏`TeZ߬o0Z^Z55*,ywxx..''`f{bsٴ)H +@<+,&  )&  *&& &,+,* # #Q)E,22999999199999990@p(?-YVUV jf!{    { z{ {!"#$%{&%--&YVUZ(ifej(ztvz($$]] 32654&'.#".5327#"&'')gA\*g>}66]C_56`?`!*(Ou))Hn.Mw834OMx43N $@/  !# #%" " "!& %999919990KTKT[KT[X%%%@878Y@ ttttv]33267#"&546?>7>5#537ZZ:3mN`^gIYX0&DeWX5^1YnFC98ŸLVV/5<65 b@ <2991/0K TX @ 878YKTKT[KT[X  @878Y P ]#53#3+e^@ 10!#!^=} *@    91903##'%\sB}}`s-Pb;V#@@   B   !$  $912299990KSX29Y"K TX$$$@878Y.#"!!#"&'53267#5!>32&P,`r<::d/4a/am"?$Ɨ5dzɏ!!J;?@.9*-" *19" <-<<219999990#"'&'&'&#"56632326#"'&'&'&#"56632326ian ^Xbian ^Vgian ^Xbian ^VoNE;=LTNE;=KڲOE;=LSNE;=K`8@91/90@cmpxyvn]] !3!^DC?%# @I    B   o o n<2991<2990KSXY"55%-+#-+#RRH# @I  B   o op<<991<2990KSXY"5%5+-+-#^R^  ^R^   #@   1/<<220%3#%3#%3#hk'$uh^'$us^'2'us ;@   299991/220!!!!! !# !39OAg@AժF|pm|q{'3@1 . ("%4"1 K1 Q+E499912<2290@%?5_5p55555????? ooooo ]q].#"!3267#"&'#"32>32%"32654& H ̷jbdjQGьBN5Z44*,nmnm98olkp݇y/10!!yy/10!!ym '@   1<20#53#53ӤRӤR??m '@   1<203#%3#ӤRӤRլ@@@ 10#53ӤR?@ q103#ӤR՘?o )@ r <<103#3#!!oA#u"@91990  9%-=V'\^N'<su+@B10KSXY"3#-\^R#/@I -'! - -'!0 *$0* $ $(st*(s099999999919999999907'#"&''7&&5467'766324&#"326{r%$&(r;t=:x=q%%&&s7t@?s9q(&%%s>v:@t8s'%$|pprs#G@%Bon29190KSXY"5s-+#R#I@&Bop<9190KSXY"5+-#^R^  /J@(   L<2<2991/<22990K TX@878YKTX@878Y@0P]]#!##53546;#"3#JcM`/яNPhc/J@!    L<<991/<22990K TX@878YKTX@878Y@0P ]!#!"!!##53546JcM/ѹ{Phc/яN9;>@   Y W Y <<2<<2122220%!#!5!!5!3!!!oooo\\HF103#F@ 10%3#ӤR@m '@    1<20%3#%3#ӤRfӤR@@q L #'3?K@D$%&%&'$'B@ .(F4 :&$L%IC'1+C =  1 =I 7+ ! L9912<<2220KSXY"KTK T[K T[K T[K T[KT[XL@LL878Y"32654&'2#"&5462#"&546!3#"32654&2#"&546"32654&WddWUccUt%ZVcbWWcdWccWUccܻۻۻۼܻۻhm'$um'(uhk'$uN'(uk'(uk',/u`m',/uXN',/u;k',/usk'2'usm'2'usk'2'u)k'8u)m'8u)k'8uy` F1/0@ @P`p]3#`?f7@ u91290K TKT[X@878Y3#'#fJ7c@$   VwVv99991<<99990K TK T[X@878Y'.#"#>3232673#"&9! &$}f[&@%9! &$}f[&@Z7IR!7IRb+/10K TKT[X@878Y!!V)9H W@ VV1<0K TX@878YKTKT[KT[X@878Y332673#"&v aWV` v HKKJLDf,@ d10K TX@878Y3# _@ V xV10K TK T[X@878YK TK T[K T[X@878Y4&#"3267#"&54632X@AWWA@Xzssss?XW@AWX@sss#u@  ' 1/90!#"&'532654&'T76xv.W+"J/;<+->i0Y[ 0.W=fB@991<20K TKT[X@878Y3#3#߉fxLu @   '1/90!33267#"&546w-+76 >&Dzs5=X.. W]0i?f7@ u91<90K TKT[X@878Y373xu ?@   : y<<991/900P]3%!!'79Pw^Mo;jnH ^@  z z <<991/90KTX @ 878Y@ @ P ` sz p ]37#'7Ǹ}Lɸ{JZjXjm'6uof'V\m'=uXf']@ <210##    g@    2  y<291/220@(   ]]! )#53!!3 !iP`P5~.,qu('@^%{&%#${##{#({'(#&'('%$%(('"#" ! B('&%"! ## #)&' ! (%#" QE)999999919990KSXY"?*]@v%+("/#/$)%-&-'*(6%F%X X!` `!f"u u!u"%#%$&&&''(6$6%F$E%Z Z!b b!z{     {zzv v!x"**']].#"32654&#"5432''%'3%F2X)6 ~r4*!M!ü޼z&77kc\̑oabk'<su=Vf'\^ =@   ? 2291/0@ ?_]332+#32654&#'ђV>@ GF2210@ `]%#3>32#"&4&#"326s:{{8daa-10!!ת? @M    B   <291<290KSXY" '77w55v8vL57y5yy5 ,@   |]|| 12035733! c)t'+n^J@$}}B ~9190KSX2Y"!!56754&#"56632 "?XhU4zHM98rn81^BQ##{l0b(H@'    #)~&~ )999190#"&'532654&##532654&#"56632 \e9}F4wCmxolV^^ad_(fQI7Z`mR|yOFJLl?<:=svcE`''5 d?''5db''5 dsm'* uqVZH'JP', /uu'6ou{'Vs'k'&-uqf'Fs'm'&-uqf'Fq$J@$ "    GE%<<1/<20`&&&]!5!533##5#"3232654&#"F:||ǧN}}daDDad10!!dHF103#F1@: "+ /) 2+"!)#&  , & &*!/<29999999999122<20K TK T[K T[KT[KT[KT[X222@878Y@z  1Ti lnooooiko o!o"o#n$l%i'i-  !"#$%&'()*+,-2   USjg ]].#"!!!!3267#"#734&5465#7332[f A78 ʝf[Y`(77(6bbiZȻ{.# .{ZiHH"{/ #/{"G)@ dd1<20KTKT[X@878YKTK T[KT[X@878YKTKT[X@878YKTX@878Y@````pppp]3#%3#^ys@B10KSXY"K TX@878YKTX@878Y@ %%6FVjg //]]3#7Ju@!  VV 99991<2990K TX@878YKTX@878Y ]'.#"#4632326=3#"&9 $(}gV$=09" (}gT";9! 2-ev 3)dw @B10KSXY"K TX@878YKTX@878Y@*$$5CUU//]]#ę1w@ 91<90K TX@878YKTX@878YKTX@878Y@ //- ]3#'#Ӌ1@ 91290K TK T[K T[K T[X@878YKTX@878YKTX@878Y@ "  ]373Ӌ ? @   ] <291<290KTKT[KT[KT[K T[K T[X@878YKTKT[X@878Y@T /9IFYi       "5GK S[ e]] !33##5!55bf]my9 j@ VV120K TX@878YKTX@878YKTKT[X@878Y332673#"&v cSRav 6978w{zf103#  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~>: ~1BSax~ & 0 : !""""+"H"e%  0AR^x}  0 9 !""""+"H"`%^ChVjq_8 (Bbcdefghjikmlnoqprsutvwxzy{}|~f55q=3=dd?y}s)3s\\?uLsLsyD{={\{fqqq/q999qqJ+o#7=V;=3XyysLs{{{{{{fqqqqq9999qqqqq9\3 'sLfR#hd+/s`N{H?55=ZyyLss/q%%=V^33 / /9% qyy\\\\;LsLsLs9#LF+o{\3X3 q=55^5bb3sq\+osfqsfqqds 5?+   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~     sfthyphenperiodcenteredEuroc6459c6460c6461c6462c6463c6466c6467c6468c6469""""XO!nE~Le  R s  X : i  = z /Eu)pP@"m#{CwRw [ r !5!B!!!" ""#"0"="J"W"d"q"~"""""""""## ##'#4#A#N#[#h##$4$%3%S%&&'K''((X()_*%*\**+z+,D,,-P-..R./0A011!1P12H2z23F3p3p3}3334z44445595g55556[667C77888J999)969C9P9]9j9w99999999::{::;;^;;;<"<_<<<<<<=c>;>H>U>>>?a??@:@K@\@m@z@@@@@@@@A@AVAkBEBBC_CCDUDE*E?- x$%&')*K+-r./2934K57D9:;< =IQR&UYZ\bdg9xy&z&{&|&}&9 999 K$$$$$9$&$*$2$4$6$7a$8$9}$:$;$ " else echo Importing markers from $2 into $1... mv $1 $1.orig awk -v USX="$2" '$1 == "" { loc = 1; } loc == 0 { print; } loc == 1 { print; while ($1 != "[Markers") { getline < USX; } while (getline < USX) { split($1,A,"="); print " "; } loc = 0; }' $1.orig > $1 fi fweelin-0.6/scripts/gomv-date0000755000175000017500000000112610547030013014737 0ustar mercmerc# Aid for managing loop/scene libraries # # This script can be used in the FreeWheeling library folder (fw-lib/ by default) # to move all loops & scenes with a specific date- # # For example: gomv-date "Apr 15" test/ moves all files from April 15 to folder 'test'. Don't forget quotes! # gomv-date "Apr 16 21:" old/ moves all files from April 16 from 9pm-10pm to folder 'old'. # # No files are moved before prompting you. # echo Found these files.. ls -lt | grep "$1" echo "Move these files to $2? (Enter=Yes, CTRL-C=Abort)" read mv -i -v `ls -lt | grep "$1" | awk '{ print $9 }'` $2 fweelin-0.6/scripts/killfweel0000755000175000017500000000025610547030013015035 0ustar mercmerc#Stop all of these tasks.. killall jack-dssi-host killall ghostess killall -s KILL fweelin killall -s KILL beatrix killall linuxsampler killall jack-rack killall md ~/gokeys fweelin-0.6/scripts/patch-ghostess-xml-patchlist0000644000175000017500000001265010547030013020600 0ustar mercmercdiff -u ghostess-20050916/src/ghostess.c ghostess-20050916-nw/src/ghostess.c --- ghostess-20050916/src/ghostess.c 2005-09-16 10:03:16.000000000 -0700 +++ ghostess-20050916-nw/src/ghostess.c 2006-03-29 11:46:38.000000000 -0800 @@ -14,6 +14,9 @@ * Chris Cannam, and Richard Bown. * - midisine.c, copyright (C) 2004 Ian Esten. * + * Modifications for outputting XML formatted patch list + * by JP Mercury + * * This is a host for DSSI plugins. It listens for MIDI events on an * ALSA sequencer or CoreMIDI port, delivers them to DSSI synths and * outputs the result via JACK. @@ -848,7 +851,7 @@ } int -write_configuration(FILE *fp) +write_configuration(char *filename) { int rc = 0; int id, instno, i, in, port; @@ -856,6 +859,21 @@ char *arg1 = NULL, *arg2 = NULL; configure_item_t *item; + FILE *fp, *fp2; + char fn2[strlen(filename)+strlen(".xml")+1]; + char tmp[255]; + int j, slen; + + // Save configuration + if ((fp = fopen(filename, "w")) == NULL) + return 0; + + // Save XML patch list + strcpy(fn2,filename); + strcat(fn2,".xml"); + if ((fp2 = fopen(fn2, "w")) == NULL) + return 0; + fprintf(fp2,"\n"); if (fprintf(fp, "#!/bin/sh\n") < 0) goto error; if (dssi_path) { @@ -878,6 +896,7 @@ for (instno = 0; instances[instno].id != id; instno++); instance = &instances[instno]; + // Write config escape_for_shell(&arg1, instance->friendly_name); if (fprintf(fp, "-comment %s \\\n", arg1) < 0) goto error; @@ -910,14 +929,59 @@ escape_for_shell(&arg1, instance->plugin->dll->name); escape_for_shell(&arg2, instance->plugin->label); if (fprintf(fp, " %s:%s \\\n", arg1, arg2) < 0) goto error; + + // Write patch list + +#if 0 + instance->pluginProgramCount = i; + instance->pluginPrograms = (DSSI_Program_Descriptor *) + malloc(i * sizeof(DSSI_Program_Descriptor)); + while (i > 0) { + const DSSI_Program_Descriptor *descriptor; + --i; + descriptor = instance->plugin->descriptor-> + get_program(instanceHandles[instance->number], i); + instance->pluginPrograms[i].Bank = descriptor->Bank; + instance->pluginPrograms[i].Program = descriptor->Program; + instance->pluginPrograms[i].Name = strdup(descriptor->Name); + ghss_debug(GDB_PROGRAM, " %s: program %d is MIDI bank %lu program %lu, named '%s'", + instance->friendly_name, i, + instance->pluginPrograms[i].Bank, + instance->pluginPrograms[i].Program, + instance->pluginPrograms[i].Name); + } +#endif + + for (i = 0; i < instance->pluginProgramCount; i++) { + // Replace < and > characters in name (bad XML) + strncpy(tmp,instance->pluginPrograms[i].Name,254); + tmp[254] = '\0'; + slen = strlen(tmp); + for (j = 0; j < slen; j++) + if (tmp[j] == '<' || + tmp[j] == '>') + tmp[j] = ' '; + + fprintf(fp2,"\n", + instance->channel, + tmp, + (int) instance->pluginPrograms[i].Bank, + (int) instance->pluginPrograms[i].Program); + } } if (fprintf(fp, "\n") < 0) goto error; rc = 1; + fprintf(fp2,"\n"); + error: if (arg1) free(arg1); if (arg2) free(arg2); + fclose(fp); + fclose(fp2); + return rc; } @@ -1670,7 +1734,10 @@ if (itemplate->program_set) { instance->currentBank = itemplate->bank; instance->currentProgram = itemplate->program; - instance->pendingProgramChange = 0; + // JPM-Changed pendingProgramChange from 0 to -1 + // was causing program list to not be dumped when + // -prog specified + instance->pendingProgramChange = -1; } else { instance->currentBank = 0; instance->currentProgram = 0; diff -u ghostess-20050916/src/ghostess.h ghostess-20050916-nw/src/ghostess.h --- ghostess-20050916/src/ghostess.h 2005-09-16 09:12:13.000000000 -0700 +++ ghostess-20050916-nw/src/ghostess.h 2006-03-29 11:05:57.000000000 -0800 @@ -188,7 +188,7 @@ extern int midi_thread_running; extern pthread_mutex_t midiEventBufferMutex; -int write_configuration(FILE *fp); +int write_configuration(char *filename); void ui_osc_free(d3h_instance_t *instance); void start_ui(d3h_instance_t *instance); diff -u ghostess-20050916/src/gui_callbacks.c ghostess-20050916-nw/src/gui_callbacks.c --- ghostess-20050916/src/gui_callbacks.c 2005-09-16 10:09:22.000000000 -0700 +++ ghostess-20050916-nw/src/gui_callbacks.c 2006-03-29 11:08:32.000000000 -0800 @@ -120,8 +120,6 @@ void on_save_file_ok( GtkWidget *widget, gpointer data ) { - FILE *fp; - gtk_widget_hide(save_file_selection); file_selection_last_filename = (gchar *)gtk_file_selection_get_filename( GTK_FILE_SELECTION(save_file_selection)); @@ -129,14 +127,9 @@ ghss_debug(GDB_GUI, " on_save_file_ok: file '%s' selected", file_selection_last_filename); - if ((fp = fopen(file_selection_last_filename, "w")) == NULL) { - display_notice("Save Configuration failed:", strerror(errno)); - return; - } - if (!write_configuration(fp)) { + if (!write_configuration(file_selection_last_filename)) { display_notice("Save Configuration failed:", strerror(errno)); } - fclose(fp); display_notice("Configuration Saved.", ""); } fweelin-0.6/scripts/patch-jack-rack-loadfile0000644000175000017500000000135010547030013017550 0ustar mercmerc--- jack-rack-1.4.3/src/main.c +++ jack-rack-1.4.3/src/main.c 96a97 > printf(" -f, --file %s\n", _("Load .rack at start")); 106,107c107,109 < < const char * options = "hps:ionc:tD:"; --- > char *loadfile = 0; > > const char * options = "hps:ionc:tDf:"; 118a121 > { "file", 1, NULL, 'f' }, 211a215,219 > > case 'f': > loadfile = (char *) malloc(sizeof(char) * (strlen(optarg)+1)); > strcpy(loadfile,optarg); > break; 237c245,256 < --- > > /* Load a file at startup? */ > if (loadfile) { > int err; > > printf("Loading file: '%s'\n",loadfile); > err = ui_open_file (global_ui, loadfile); > > if (!err) > ui_set_filename (global_ui, loadfile); > } > fweelin-0.6/scripts/phat1-basic.rack0000644000175000017500000000052610547030013016067 0ustar mercmercU]O0}߯@~@?bj{4l/{"ԁv@ڲ鋿22QB&M==96%\om 3rux<-Jf^>XvuyaY[RR!Y kjTs# 6Bz:,,ϹPK%ӜzFoHM(E:4IP@4VjYqYsv:J{tFPԅLT\5O)5Mޔű#t*8x> `>vAۦ]l]׿60!n߰yA]yfpb>7oQ&H` | ofweelin-0.6/scripts/phat1-echo.rack0000644000175000017500000000071710547030013015726 0ustar mercmercWKs0+tR<;^<1QRFpj{oop0~f 9ƊxM P6`3>x&kAhIxpF,@oRa@Mh;m, ]Bn1/,ea(<𤄅XNa:Tw1jyxFn"­akxw&bEʻ"vrc抉%3roLWqPg{È4dBdke8  w)ရFYewҢr*W"XBٿhWBuYZwj:dInh^58tq &Fip2"Y zY1؎u+KOn,KQ Wetdh=eբ7Kek(/&٤X!RBw<1q$8+I+G fweelin-0.6/scripts/README0000644000175000017500000000374110547030013014013 0ustar mercmercManaging A Library Of Loops & Scenes ------------------------------------ ** godelete-date, gomv-date, goarchive-date scripts Delete/Move, and Archive loops & scenes by date. See individual files for instructions. ** goarchive-scene script Archive a scene and all the loops it uses. Connecting FreeWheeling with Other Linux Audio apps --------------------------------------------------- -Hexter -Jack-Rack Example Scripts and Presets: --------------------------- Several Jack-Racks that use tube amp sims and reverb, and some scripts to load FreeWheeling and Hexter, a killer DX7 synth emulator. - Running 'gofweel' will load FreeWheeling and hook it up to reverb and tube amp. Your live mix will still be saved to disk dry, so you can tweak the FX later. - Running 'godx7' will load Hexter DX7 emulator and connect to tube amp. If FreeWheeling is running, DX7 becomes an input into FreeWheeling (channel 2). If not, DX7 is loaded standalone. - Running 'gofweel-dx7' will load FreeWheeling and DX7 as above, and connect them. You get the DX7 synth connected through a light phaser, then into FreeWheeling. FreeWheeling is channeled through valve saturation and tube amp plugins, and a wide open reverb. This is the whole enchilada. *** You will have to tweak the scripts to change your MIDI hardware name- see script 'waitalsaports'. *** *** You will also have to patch Jack-Rack (see included patch-) to load a .rack at startup. This is a feature that the author, I think, intends to implement, but I have done it for him. The scripts use this feature to autoload a rack. For more info, type 'jack-rack -?' after patching and recompiling and look at the -f option. *** *** Note these scripts are rather aggressive at killing tasks. If you have running versions of freewheeling, ghostess, jack-dssi-host, or jack-rack, expect them to suddenly stop! ** *** I recommend ghostess for hosting your DSSI synths- it allows you to save patch banks for auto startup. Good Luck! -Mercury fweelin-0.6/scripts/vocalverb.rack0000644000175000017500000000044010547030013015751 0ustar mercmercMn 9cJSMɢͲjdEl!8cEQ"!{@N?줱eF`GxXȇ6O2_uc֒--ۈhfSF#<~=Y!X +F8㘅!™jլKݖ^9gIΑZ̹3DUK+w ˰͑70/;i;5B=msNĬTT$l2dz?X2&{gXfweelin-0.6/scripts/waitalsaports0000755000175000017500000000152110547030013015750 0ustar mercmerc# Script to wait for named ALSA midi ports to appear # # usage: waitalsaports # # where name is the full or partial client name (grep search will be done) # # prints the port numbers for system MIDI input and client MIDI input, # respectively # # typically they are 72:0 128:0 ALSA_NAME=$1 # **** You will have to change the following line to reflect the name of your MIDI hardware # On my system aconnect -li reports client 72: 'MidiSport 2x2', so the name can be any subset of that: ALSA_IN_NAME=MidiSport #ALSA_IN_NAME=PCR while ((`aconnect -lo | grep $ALSA_NAME | awk 'END { print NR }'` == 0)) do sleep 0.1 done ALSA_SYSTEM_MIDI=`aconnect -lo | grep $ALSA_IN_NAME | grep client | awk '{ print $2 }'`0 ALSA_CLIENT_MIDI=`aconnect -lo | grep $ALSA_NAME | grep client | awk '{ print $2 }'`0 echo $ALSA_SYSTEM_MIDI $ALSA_CLIENT_MIDI fweelin-0.6/scripts/waitjackports0000755000175000017500000000052510547030013015743 0ustar mercmerc# Script to wait for named JACK ports to appear # # usage: waitjackports # # where name is the full or partial client name (grep search will be done) # # prints all ports belonging to the named client JACK_NAME=$1 while ((`jack_lsp | grep $JACK_NAME | awk 'END { print NR }'` == 0)) do sleep 0.1 done jack_lsp | grep $JACK_NAME fweelin-0.6/examples/combipatchdemo.xml0000644000175000017500000000267610547030013016770 0ustar mercmerc fweelin-0.6/examples/patches1.xml0000644000175000017500000006170610547030013015521 0ustar mercmerc fweelin-0.6/examples/README0000644000175000017500000000523710547030013014144 0ustar mercmercLoops and Scenes Examples ------------------------- You can find sample loops and scenes in the 'Remix Playground' area of the Freewheeling website. http://freewheeling.sourceforge.net/#scenes NEW in V0.5.3- Combination Zone Patches --------------------------------------- * More flexible MIDI patch routing. - Combination patches allow you to split one MIDI controller into a range of zones. This allows you to control several different sounds or softsynths from one MIDI control source. A patch defines the zones, as well as the output port and channel that each zone sends to. You can also send MIDI program and bank change messages for each zone, allowing you to switch programs on external synths. All of this functionality is integrated into the patch browser, so you can seamlessly control other synth apps and sound modules from within FreeWheeling. See 'examples/combipatchdemo.xml' for an example configuration. Patch Browser Definition Example -------------------------------- The file patches1.xml contains an example for how to define patches for an external soft synth. In this case it's an example for a Ghostess DSSI host running one instance of WhySynth and one instance of Hexter. To use this example, copy 'examples/patches1.xml' to the ~/.fweelin/ folder (this folder is created by version 0.5.2 and forward). The WhySynth instance is on channel 0 (first channel), and the Hexter instance is on channel 1 (second channel). When you specify this patch list in Freewheeling's .fweelin.rc configuration file: you will then be able to play both your WhySynth and your Hexter patches, and switch between them. The WhySynth and Hexter patches will appear in separate sections of the patch browser. ------------------------------------------------------------------------------------------- You can automatically generate a patch list from a set of DSSI plugin patches. This saves the work of manually entering all of your patch information. To do this, apply the included patch to Ghostess (scripts/patch-ghostess-xml-patchlist). The patch modifies Ghostess so that when you select 'Save Configuration...' from the File menu, you get both a script to startup Ghostess with the current config and patchset, -as well as- an .XML file with the same base name, that contains the patch list for Freewheeling. I've submitted this patch to Sean Bolton for inclusion in an upcoming Ghostess release. Please nudge him if it has been useful for you (http://home.jps.net/~musound/). ------------------------------------------------------------------------------------------- fweelin-0.6/Makefile.am0000755000175000017500000000002310547030013013471 0ustar mercmercSUBDIRS = src data fweelin-0.6/Makefile.in0000644000175000017500000004351111071520730013513 0ustar mercmerc# Makefile.in generated by automake 1.10 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : subdir = . DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \ $(srcdir)/Makefile.in $(top_srcdir)/configure AUTHORS COPYING \ ChangeLog INSTALL NEWS THANKS depcomp install-sh ltmain.sh \ missing mkinstalldirs ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno config.status.lineno mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_CLEAN_FILES = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ html-recursive info-recursive install-data-recursive \ install-dvi-recursive install-exec-recursive \ install-html-recursive install-info-recursive \ install-pdf-recursive install-ps-recursive install-recursive \ installcheck-recursive installdirs-recursive pdf-recursive \ ps-recursive uninstall-recursive RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) am__remove_distdir = \ { test ! -d $(distdir) \ || { find $(distdir) -type d ! -perm -200 -exec chmod u+w {} ';' \ && rm -fr $(distdir); }; } DIST_ARCHIVES = $(distdir).tar.gz GZIP_ENV = --best distuninstallcheck_listfiles = find . -type f -print distcleancheck_listfiles = find . -type f -print ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build_alias = @build_alias@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host_alias = @host_alias@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ SUBDIRS = src data all: all-recursive .SUFFIXES: am--refresh: @: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ echo ' cd $(srcdir) && $(AUTOMAKE) --gnu '; \ cd $(srcdir) && $(AUTOMAKE) --gnu \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile'; \ cd $(top_srcdir) && \ $(AUTOMAKE) --gnu Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ echo ' $(SHELL) ./config.status'; \ $(SHELL) ./config.status;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) $(SHELL) ./config.status --recheck $(top_srcdir)/configure: $(am__configure_deps) cd $(srcdir) && $(AUTOCONF) $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) # This directory's subdirectories are mostly independent; you can cd # into them and run `make' without going through this Makefile. # To change the values of `make' variables: instead of editing Makefiles, # (1) if the variable is set in `config.status', edit `config.status' # (which will cause the Makefiles to be regenerated when you run `make'); # (2) otherwise, pass the desired values on the `make' command line. $(RECURSIVE_TARGETS): @failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ *k*) failcom='fail=yes';; \ esac; \ done; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ list='$(SUBDIRS)'; for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" $(RECURSIVE_CLEAN_TARGETS): @failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ *k*) failcom='fail=yes';; \ esac; \ done; \ dot_seen=no; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ rev=''; for subdir in $$list; do \ if test "$$subdir" = "."; then :; else \ rev="$$subdir $$rev"; \ fi; \ done; \ rev="$$rev ."; \ target=`echo $@ | sed s/-recursive//`; \ for subdir in $$rev; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done && test -z "$$fail" tags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ done ctags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ done ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ mkid -fID $$unique tags: TAGS TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$tags $$unique; \ fi ctags: CTAGS CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(CTAGS_ARGS)$$tags$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$tags $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) $(am__remove_distdir) test -d $(distdir) || mkdir $(distdir) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ distdir=`$(am__cd) $(distdir) && pwd`; \ top_distdir=`$(am__cd) $(top_distdir) && pwd`; \ (cd $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$top_distdir" \ distdir="$$distdir/$$subdir" \ am__remove_distdir=: \ am__skip_length_check=: \ distdir) \ || exit 1; \ fi; \ done -find $(distdir) -type d ! -perm -777 -exec chmod a+rwx {} \; -o \ ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ || chmod -R a+r $(distdir) dist-gzip: distdir tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz $(am__remove_distdir) dist-bzip2: distdir tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2 $(am__remove_distdir) dist-tarZ: distdir tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z $(am__remove_distdir) dist-shar: distdir shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz $(am__remove_distdir) dist-zip: distdir -rm -f $(distdir).zip zip -rq $(distdir).zip $(distdir) $(am__remove_distdir) dist dist-all: distdir tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz $(am__remove_distdir) # This target untars the dist file and tries a VPATH configuration. Then # it guarantees that the distribution is self-contained by making another # tarfile. distcheck: dist case '$(DIST_ARCHIVES)' in \ *.tar.gz*) \ GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(am__untar) ;;\ *.tar.bz2*) \ bunzip2 -c $(distdir).tar.bz2 | $(am__untar) ;;\ *.tar.Z*) \ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ *.shar.gz*) \ GZIP=$(GZIP_ENV) gunzip -c $(distdir).shar.gz | unshar ;;\ *.zip*) \ unzip $(distdir).zip ;;\ esac chmod -R a-w $(distdir); chmod a+w $(distdir) mkdir $(distdir)/_build mkdir $(distdir)/_inst chmod a-w $(distdir) dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ && cd $(distdir)/_build \ && ../configure --srcdir=.. --prefix="$$dc_install_base" \ $(DISTCHECK_CONFIGURE_FLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) dvi \ && $(MAKE) $(AM_MAKEFLAGS) check \ && $(MAKE) $(AM_MAKEFLAGS) install \ && $(MAKE) $(AM_MAKEFLAGS) installcheck \ && $(MAKE) $(AM_MAKEFLAGS) uninstall \ && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ distuninstallcheck \ && chmod -R a-w "$$dc_install_base" \ && ({ \ (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ } || { rm -rf "$$dc_destdir"; exit 1; }) \ && rm -rf "$$dc_destdir" \ && $(MAKE) $(AM_MAKEFLAGS) dist \ && rm -rf $(DIST_ARCHIVES) \ && $(MAKE) $(AM_MAKEFLAGS) distcleancheck $(am__remove_distdir) @(echo "$(distdir) archives ready for distribution: "; \ list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' distuninstallcheck: @cd $(distuninstallcheck_dir) \ && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \ || { echo "ERROR: files left after uninstall:" ; \ if test -n "$(DESTDIR)"; then \ echo " (check DESTDIR support)"; \ fi ; \ $(distuninstallcheck_listfiles) ; \ exit 1; } >&2 distcleancheck: distclean @if test '$(srcdir)' = . ; then \ echo "ERROR: distcleancheck can only run from a VPATH build" ; \ exit 1 ; \ fi @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left in build directory after distclean:" ; \ $(distcleancheck_listfiles) ; \ exit 1; } >&2 check-am: all-am check: check-recursive all-am: Makefile installdirs: installdirs-recursive installdirs-am: install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic mostlyclean-am distclean: distclean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -f Makefile distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive info: info-recursive info-am: install-data-am: install-dvi: install-dvi-recursive install-exec-am: install-html: install-html-recursive install-info: install-info-recursive install-man: install-pdf: install-pdf-recursive install-ps: install-ps-recursive installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf $(top_srcdir)/autom4te.cache -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: .MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) install-am \ install-strip .PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ all all-am am--refresh check check-am clean clean-generic \ ctags ctags-recursive dist dist-all dist-bzip2 dist-gzip \ dist-shar dist-tarZ dist-zip distcheck distclean \ distclean-generic distclean-tags distcleancheck distdir \ distuninstallcheck dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ installdirs-am maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-generic pdf pdf-am ps ps-am tags \ tags-recursive uninstall uninstall-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: fweelin-0.6/ltmain.sh0000755000175000017500000033042410547030013013270 0ustar mercmerc# ltmain.sh - Provide generalized library-building support services. # NOTE: Changing this file will not affect anything until you rerun ltconfig. # # Copyright (C) 1996-1999 Free Software Foundation, Inc. # Originally by Gordon Matzigkeit , 1996 # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Check that we have a working $echo. if test "X$1" = X--no-reexec; then # Discard the --no-reexec flag, and continue. shift elif test "X$1" = X--fallback-echo; then # Avoid inline document here, it may be left over : elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then # Yippee, $echo works! : else # Restart under the correct shell, and then maybe $echo will work. exec $SHELL "$0" --no-reexec ${1+"$@"} fi if test "X$1" = X--fallback-echo; then # used as fallback echo shift cat <&2 echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 exit 1 fi if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then echo "$modename: not configured to build any kind of library" 1>&2 echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 exit 1 fi # Global variables. mode=$default_mode nonopt= prev= prevopt= run= show="$echo" show_help= execute_dlfiles= lo2o="s/\\.lo\$/.${objext}/" o2lo="s/\\.${objext}\$/.lo/" # Parse our command line options once, thoroughly. while test $# -gt 0 do arg="$1" shift case "$arg" in -*=*) optarg=`$echo "X$arg" | $Xsed -e 's/[-_a-zA-Z0-9]*=//'` ;; *) optarg= ;; esac # If the previous option needs an argument, assign it. if test -n "$prev"; then case "$prev" in execute_dlfiles) eval "$prev=\"\$$prev \$arg\"" ;; *) eval "$prev=\$arg" ;; esac prev= prevopt= continue fi # Have we seen a non-optional argument yet? case "$arg" in --help) show_help=yes ;; --version) echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP" exit 0 ;; --config) sed -e '1,/^### BEGIN LIBTOOL CONFIG/d' -e '/^### END LIBTOOL CONFIG/,$d' $0 exit 0 ;; --debug) echo "$progname: enabling shell trace mode" set -x ;; --dry-run | -n) run=: ;; --features) echo "host: $host" if test "$build_libtool_libs" = yes; then echo "enable shared libraries" else echo "disable shared libraries" fi if test "$build_old_libs" = yes; then echo "enable static libraries" else echo "disable static libraries" fi exit 0 ;; --finish) mode="finish" ;; --mode) prevopt="--mode" prev=mode ;; --mode=*) mode="$optarg" ;; --quiet | --silent) show=: ;; -dlopen) prevopt="-dlopen" prev=execute_dlfiles ;; -*) $echo "$modename: unrecognized option \`$arg'" 1>&2 $echo "$help" 1>&2 exit 1 ;; *) nonopt="$arg" break ;; esac done if test -n "$prevopt"; then $echo "$modename: option \`$prevopt' requires an argument" 1>&2 $echo "$help" 1>&2 exit 1 fi if test -z "$show_help"; then # Infer the operation mode. if test -z "$mode"; then case "$nonopt" in *cc | *++ | gcc* | *-gcc*) mode=link for arg do case "$arg" in -c) mode=compile break ;; esac done ;; *db | *dbx | *strace | *truss) mode=execute ;; *install*|cp|mv) mode=install ;; *rm) mode=uninstall ;; *) # If we have no mode, but dlfiles were specified, then do execute mode. test -n "$execute_dlfiles" && mode=execute # Just use the default operation mode. if test -z "$mode"; then if test -n "$nonopt"; then $echo "$modename: warning: cannot infer operation mode from \`$nonopt'" 1>&2 else $echo "$modename: warning: cannot infer operation mode without MODE-ARGS" 1>&2 fi fi ;; esac fi # Only execute mode is allowed to have -dlopen flags. if test -n "$execute_dlfiles" && test "$mode" != execute; then $echo "$modename: unrecognized option \`-dlopen'" 1>&2 $echo "$help" 1>&2 exit 1 fi # Change the help message to a mode-specific one. generic_help="$help" help="Try \`$modename --help --mode=$mode' for more information." # These modes are in order of execution frequency so that they run quickly. case "$mode" in # libtool compile mode compile) modename="$modename: compile" # Get the compilation command and the source file. base_compile= lastarg= srcfile="$nonopt" suppress_output= user_target=no for arg do # Accept any command-line options. case "$arg" in -o) if test "$user_target" != "no"; then $echo "$modename: you cannot specify \`-o' more than once" 1>&2 exit 1 fi user_target=next ;; -static) build_old_libs=yes continue ;; esac case "$user_target" in next) # The next one is the -o target name user_target=yes continue ;; yes) # We got the output file user_target=set libobj="$arg" continue ;; esac # Accept the current argument as the source file. lastarg="$srcfile" srcfile="$arg" # Aesthetically quote the previous argument. # Backslashify any backslashes, double quotes, and dollar signs. # These are the only characters that are still specially # interpreted inside of double-quoted scrings. lastarg=`$echo "X$lastarg" | $Xsed -e "$sed_quote_subst"` # Double-quote args containing other shell metacharacters. # Many Bourne shells cannot handle close brackets correctly in scan # sets, so we specify it separately. case "$lastarg" in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) lastarg="\"$lastarg\"" ;; esac # Add the previous argument to base_compile. if test -z "$base_compile"; then base_compile="$lastarg" else base_compile="$base_compile $lastarg" fi done case "$user_target" in set) ;; no) # Get the name of the library object. libobj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%'` ;; *) $echo "$modename: you must specify a target with \`-o'" 1>&2 exit 1 ;; esac # Recognize several different file suffixes. # If the user specifies -o file.o, it is replaced with file.lo xform='[cCFSfmso]' case "$libobj" in *.ada) xform=ada ;; *.adb) xform=adb ;; *.ads) xform=ads ;; *.asm) xform=asm ;; *.c++) xform=c++ ;; *.cc) xform=cc ;; *.cpp) xform=cpp ;; *.cxx) xform=cxx ;; *.f90) xform=f90 ;; *.for) xform=for ;; esac libobj=`$echo "X$libobj" | $Xsed -e "s/\.$xform$/.lo/"` case "$libobj" in *.lo) obj=`$echo "X$libobj" | $Xsed -e "$lo2o"` ;; *) $echo "$modename: cannot determine name of library object from \`$libobj'" 1>&2 exit 1 ;; esac if test -z "$base_compile"; then $echo "$modename: you must specify a compilation command" 1>&2 $echo "$help" 1>&2 exit 1 fi # Delete any leftover library objects. if test "$build_old_libs" = yes; then removelist="$obj $libobj" else removelist="$libobj" fi $run $rm $removelist trap "$run $rm $removelist; exit 1" 1 2 15 # Calculate the filename of the output object if compiler does # not support -o with -c if test "$compiler_c_o" = no; then output_obj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\..*$%%'`.${objext} lockfile="$output_obj.lock" removelist="$removelist $output_obj $lockfile" trap "$run $rm $removelist; exit 1" 1 2 15 else need_locks=no lockfile= fi # Lock this critical section if it is needed # We use this script file to make the link, it avoids creating a new file if test "$need_locks" = yes; then until ln "$0" "$lockfile" 2>/dev/null; do $show "Waiting for $lockfile to be removed" sleep 2 done elif test "$need_locks" = warn; then if test -f "$lockfile"; then echo "\ *** ERROR, $lockfile exists and contains: `cat $lockfile 2>/dev/null` This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $run $rm $removelist exit 1 fi echo $srcfile > "$lockfile" fi if test -n "$fix_srcfile_path"; then eval srcfile=\"$fix_srcfile_path\" fi # Only build a PIC object if we are building libtool libraries. if test "$build_libtool_libs" = yes; then # Without this assignment, base_compile gets emptied. fbsd_hideous_sh_bug=$base_compile # All platforms use -DPIC, to notify preprocessed assembler code. command="$base_compile $srcfile $pic_flag -DPIC" if test "$build_old_libs" = yes; then lo_libobj="$libobj" dir=`$echo "X$libobj" | $Xsed -e 's%/[^/]*$%%'` if test "X$dir" = "X$libobj"; then dir="$objdir" else dir="$dir/$objdir" fi libobj="$dir/"`$echo "X$libobj" | $Xsed -e 's%^.*/%%'` if test -d "$dir"; then $show "$rm $libobj" $run $rm $libobj else $show "$mkdir $dir" $run $mkdir $dir status=$? if test $status -ne 0 && test ! -d $dir; then exit $status fi fi fi if test "$compiler_o_lo" = yes; then output_obj="$libobj" command="$command -o $output_obj" elif test "$compiler_c_o" = yes; then output_obj="$obj" command="$command -o $output_obj" fi $run $rm "$output_obj" $show "$command" if $run eval "$command"; then : else test -n "$output_obj" && $run $rm $removelist exit 1 fi if test "$need_locks" = warn && test x"`cat $lockfile 2>/dev/null`" != x"$srcfile"; then echo "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $run $rm $removelist exit 1 fi # Just move the object if needed, then go on to compile the next one if test x"$output_obj" != x"$libobj"; then $show "$mv $output_obj $libobj" if $run $mv $output_obj $libobj; then : else error=$? $run $rm $removelist exit $error fi fi # If we have no pic_flag, then copy the object into place and finish. if test -z "$pic_flag" && test "$build_old_libs" = yes; then # Rename the .lo from within objdir to obj if test -f $obj; then $show $rm $obj $run $rm $obj fi $show "$mv $libobj $obj" if $run $mv $libobj $obj; then : else error=$? $run $rm $removelist exit $error fi xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'` if test "X$xdir" = "X$obj"; then xdir="." else xdir="$xdir" fi baseobj=`$echo "X$obj" | $Xsed -e "s%.*/%%"` libobj=`$echo "X$baseobj" | $Xsed -e "$o2lo"` # Now arrange that obj and lo_libobj become the same file $show "(cd $xdir && $LN_S $baseobj $libobj)" if $run eval '(cd $xdir && $LN_S $baseobj $libobj)'; then exit 0 else error=$? $run $rm $removelist exit $error fi fi # Allow error messages only from the first compilation. suppress_output=' >/dev/null 2>&1' fi # Only build a position-dependent object if we build old libraries. if test "$build_old_libs" = yes; then command="$base_compile $srcfile" if test "$compiler_c_o" = yes; then command="$command -o $obj" output_obj="$obj" fi # Suppress compiler output if we already did a PIC compilation. command="$command$suppress_output" $run $rm "$output_obj" $show "$command" if $run eval "$command"; then : else $run $rm $removelist exit 1 fi if test "$need_locks" = warn && test x"`cat $lockfile 2>/dev/null`" != x"$srcfile"; then echo "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $run $rm $removelist exit 1 fi # Just move the object if needed if test x"$output_obj" != x"$obj"; then $show "$mv $output_obj $obj" if $run $mv $output_obj $obj; then : else error=$? $run $rm $removelist exit $error fi fi # Create an invalid libtool object if no PIC, so that we do not # accidentally link it into a program. if test "$build_libtool_libs" != yes; then $show "echo timestamp > $libobj" $run eval "echo timestamp > \$libobj" || exit $? else # Move the .lo from within objdir $show "$mv $libobj $lo_libobj" if $run $mv $libobj $lo_libobj; then : else error=$? $run $rm $removelist exit $error fi fi fi # Unlock the critical section if it was locked if test "$need_locks" != no; then $rm "$lockfile" fi exit 0 ;; # libtool link mode link) modename="$modename: link" case "$host" in *-*-cygwin* | *-*-mingw* | *-*-os2*) # It is impossible to link a dll without this setting, and # we shouldn't force the makefile maintainer to figure out # which system we are compiling for in order to pass an extra # flag for every libtool invokation. # allow_undefined=no # FIXME: Unfortunately, there are problems with the above when trying # to make a dll which has undefined symbols, in which case not # even a static library is built. For now, we need to specify # -no-undefined on the libtool link line when we can be certain # that all symbols are satisfied, otherwise we get a static library. allow_undefined=yes # This is a source program that is used to create dlls on Windows # Don't remove nor modify the starting and closing comments # /* ltdll.c starts here */ # #define WIN32_LEAN_AND_MEAN # #include # #undef WIN32_LEAN_AND_MEAN # #include # # #ifndef __CYGWIN__ # # ifdef __CYGWIN32__ # # define __CYGWIN__ __CYGWIN32__ # # endif # #endif # # #ifdef __cplusplus # extern "C" { # #endif # BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved); # #ifdef __cplusplus # } # #endif # # #ifdef __CYGWIN__ # #include # DECLARE_CYGWIN_DLL( DllMain ); # #endif # HINSTANCE __hDllInstance_base; # # BOOL APIENTRY # DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved) # { # __hDllInstance_base = hInst; # return TRUE; # } # /* ltdll.c ends here */ # This is a source program that is used to create import libraries # on Windows for dlls which lack them. Don't remove nor modify the # starting and closing comments # /* impgen.c starts here */ # /* Copyright (C) 1999 Free Software Foundation, Inc. # # This file is part of GNU libtool. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # */ # # #include /* for printf() */ # #include /* for open(), lseek(), read() */ # #include /* for O_RDONLY, O_BINARY */ # #include /* for strdup() */ # # static unsigned int # pe_get16 (fd, offset) # int fd; # int offset; # { # unsigned char b[2]; # lseek (fd, offset, SEEK_SET); # read (fd, b, 2); # return b[0] + (b[1]<<8); # } # # static unsigned int # pe_get32 (fd, offset) # int fd; # int offset; # { # unsigned char b[4]; # lseek (fd, offset, SEEK_SET); # read (fd, b, 4); # return b[0] + (b[1]<<8) + (b[2]<<16) + (b[3]<<24); # } # # static unsigned int # pe_as32 (ptr) # void *ptr; # { # unsigned char *b = ptr; # return b[0] + (b[1]<<8) + (b[2]<<16) + (b[3]<<24); # } # # int # main (argc, argv) # int argc; # char *argv[]; # { # int dll; # unsigned long pe_header_offset, opthdr_ofs, num_entries, i; # unsigned long export_rva, export_size, nsections, secptr, expptr; # unsigned long name_rvas, nexp; # unsigned char *expdata, *erva; # char *filename, *dll_name; # # filename = argv[1]; # # dll = open(filename, O_RDONLY|O_BINARY); # if (!dll) # return 1; # # dll_name = filename; # # for (i=0; filename[i]; i++) # if (filename[i] == '/' || filename[i] == '\\' || filename[i] == ':') # dll_name = filename + i +1; # # pe_header_offset = pe_get32 (dll, 0x3c); # opthdr_ofs = pe_header_offset + 4 + 20; # num_entries = pe_get32 (dll, opthdr_ofs + 92); # # if (num_entries < 1) /* no exports */ # return 1; # # export_rva = pe_get32 (dll, opthdr_ofs + 96); # export_size = pe_get32 (dll, opthdr_ofs + 100); # nsections = pe_get16 (dll, pe_header_offset + 4 +2); # secptr = (pe_header_offset + 4 + 20 + # pe_get16 (dll, pe_header_offset + 4 + 16)); # # expptr = 0; # for (i = 0; i < nsections; i++) # { # char sname[8]; # unsigned long secptr1 = secptr + 40 * i; # unsigned long vaddr = pe_get32 (dll, secptr1 + 12); # unsigned long vsize = pe_get32 (dll, secptr1 + 16); # unsigned long fptr = pe_get32 (dll, secptr1 + 20); # lseek(dll, secptr1, SEEK_SET); # read(dll, sname, 8); # if (vaddr <= export_rva && vaddr+vsize > export_rva) # { # expptr = fptr + (export_rva - vaddr); # if (export_rva + export_size > vaddr + vsize) # export_size = vsize - (export_rva - vaddr); # break; # } # } # # expdata = (unsigned char*)malloc(export_size); # lseek (dll, expptr, SEEK_SET); # read (dll, expdata, export_size); # erva = expdata - export_rva; # # nexp = pe_as32 (expdata+24); # name_rvas = pe_as32 (expdata+32); # # printf ("EXPORTS\n"); # for (i = 0; i&2 fi if test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi else if test -z "$pic_flag" && test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi fi build_libtool_libs=no build_old_libs=yes prefer_static_libs=yes break ;; esac done # See if our shared archives depend on static archives. test -n "$old_archive_from_new_cmds" && build_old_libs=yes # Go through the arguments, transforming them on the way. while test $# -gt 0; do arg="$1" shift # If the previous option needs an argument, assign it. if test -n "$prev"; then case "$prev" in output) compile_command="$compile_command @OUTPUT@" finalize_command="$finalize_command @OUTPUT@" ;; esac case "$prev" in dlfiles|dlprefiles) if test "$preload" = no; then # Add the symbol object into the linking commands. compile_command="$compile_command @SYMFILE@" finalize_command="$finalize_command @SYMFILE@" preload=yes fi case "$arg" in *.la | *.lo) ;; # We handle these cases below. force) if test "$dlself" = no; then dlself=needless export_dynamic=yes fi prev= continue ;; self) if test "$prev" = dlprefiles; then dlself=yes elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then dlself=yes else dlself=needless export_dynamic=yes fi prev= continue ;; *) if test "$prev" = dlfiles; then dlfiles="$dlfiles $arg" else dlprefiles="$dlprefiles $arg" fi prev= ;; esac ;; expsyms) export_symbols="$arg" if test ! -f "$arg"; then $echo "$modename: symbol file \`$arg' does not exist" exit 1 fi prev= continue ;; expsyms_regex) export_symbols_regex="$arg" prev= continue ;; release) release="-$arg" prev= continue ;; rpath | xrpath) # We need an absolute path. case "$arg" in [\\/]* | [A-Za-z]:[\\/]*) ;; *) $echo "$modename: only absolute run-paths are allowed" 1>&2 exit 1 ;; esac if test "$prev" = rpath; then case "$rpath " in *" $arg "*) ;; *) rpath="$rpath $arg" ;; esac else case "$xrpath " in *" $arg "*) ;; *) xrpath="$xrpath $arg" ;; esac fi prev= continue ;; *) eval "$prev=\"\$arg\"" prev= continue ;; esac fi prevarg="$arg" case "$arg" in -all-static) if test -n "$link_static_flag"; then compile_command="$compile_command $link_static_flag" finalize_command="$finalize_command $link_static_flag" fi continue ;; -allow-undefined) # FIXME: remove this flag sometime in the future. $echo "$modename: \`-allow-undefined' is deprecated because it is the default" 1>&2 continue ;; -avoid-version) avoid_version=yes continue ;; -dlopen) prev=dlfiles continue ;; -dlpreopen) prev=dlprefiles continue ;; -export-dynamic) export_dynamic=yes continue ;; -export-symbols | -export-symbols-regex) if test -n "$export_symbols" || test -n "$export_symbols_regex"; then $echo "$modename: not more than one -exported-symbols argument allowed" exit 1 fi if test "X$arg" = "X-export-symbols"; then prev=expsyms else prev=expsyms_regex fi continue ;; -L*) dir=`$echo "X$arg" | $Xsed -e 's/^-L//'` # We need an absolute path. case "$dir" in [\\/]* | [A-Za-z]:[\\/]*) ;; *) absdir=`cd "$dir" && pwd` if test -z "$absdir"; then $echo "$modename: warning: cannot determine absolute directory name of \`$dir'" 1>&2 $echo "$modename: passing it literally to the linker, although it might fail" 1>&2 absdir="$dir" fi dir="$absdir" ;; esac case " $deplibs " in *" $arg "*) ;; *) deplibs="$deplibs $arg";; esac case " $lib_search_path " in *" $dir "*) ;; *) lib_search_path="$lib_search_path $dir";; esac case "$host" in *-*-cygwin* | *-*-mingw* | *-*-os2*) dllsearchdir=`cd "$dir" && pwd || echo "$dir"` case ":$dllsearchpath:" in ::) dllsearchpath="$dllsearchdir";; *":$dllsearchdir:"*) ;; *) dllsearchpath="$dllsearchpath:$dllsearchdir";; esac ;; esac ;; -l*) if test "$arg" = "-lc"; then case "$host" in *-*-cygwin* | *-*-mingw* | *-*-os2* | *-*-beos*) # These systems don't actually have c library (as such) continue ;; esac elif test "$arg" = "-lm"; then case "$host" in *-*-cygwin* | *-*-beos*) # These systems don't actually have math library (as such) continue ;; esac fi deplibs="$deplibs $arg" ;; -module) module=yes continue ;; -no-undefined) allow_undefined=no continue ;; -o) prev=output ;; -release) prev=release continue ;; -rpath) prev=rpath continue ;; -R) prev=xrpath continue ;; -R*) dir=`$echo "X$arg" | $Xsed -e 's/^-R//'` # We need an absolute path. case "$dir" in [\\/]* | [A-Za-z]:[\\/]*) ;; *) $echo "$modename: only absolute run-paths are allowed" 1>&2 exit 1 ;; esac case "$xrpath " in *" $dir "*) ;; *) xrpath="$xrpath $dir" ;; esac continue ;; -static) # If we have no pic_flag, then this is the same as -all-static. if test -z "$pic_flag" && test -n "$link_static_flag"; then compile_command="$compile_command $link_static_flag" finalize_command="$finalize_command $link_static_flag" fi continue ;; -thread-safe) thread_safe=yes continue ;; -version-info) prev=vinfo continue ;; # Some other compiler flag. -* | +*) # Unknown arguments in both finalize_command and compile_command need # to be aesthetically quoted because they are evaled later. arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` case "$arg" in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) arg="\"$arg\"" ;; esac ;; *.o | *.obj | *.a | *.lib) # A standard object. objs="$objs $arg" ;; *.lo) # A library object. if test "$prev" = dlfiles; then dlfiles="$dlfiles $arg" if test "$build_libtool_libs" = yes && test "$dlopen" = yes; then prev= continue else # If libtool objects are unsupported, then we need to preload. prev=dlprefiles fi fi if test "$prev" = dlprefiles; then # Preload the old-style object. dlprefiles="$dlprefiles "`$echo "X$arg" | $Xsed -e "$lo2o"` prev= fi libobjs="$libobjs $arg" ;; *.la) # A libtool-controlled library. dlname= libdir= library_names= old_library= # Check to see that this really is a libtool archive. if (sed -e '2q' $arg | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : else $echo "$modename: \`$arg' is not a valid libtool archive" 1>&2 exit 1 fi # If the library was installed with an old release of libtool, # it will not redefine variable installed. installed=yes # Read the .la file # If there is no directory component, then add one. case "$arg" in */* | *\\*) . $arg ;; *) . ./$arg ;; esac # Get the name of the library we link against. linklib= for l in $old_library $library_names; do linklib="$l" done if test -z "$linklib"; then $echo "$modename: cannot find name of link library for \`$arg'" 1>&2 exit 1 fi # Find the relevant object directory and library name. name=`$echo "X$arg" | $Xsed -e 's%^.*/%%' -e 's/\.la$//' -e 's/^lib//'` if test "X$installed" = Xyes; then dir="$libdir" else dir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` if test "X$dir" = "X$arg"; then dir="$objdir" else dir="$dir/$objdir" fi fi if test -n "$dependency_libs"; then # Extract -R and -L from dependency_libs temp_deplibs= for deplib in $dependency_libs; do case "$deplib" in -R*) temp_xrpath=`$echo "X$deplib" | $Xsed -e 's/^-R//'` case " $rpath $xrpath " in *" $temp_xrpath "*) ;; *) xrpath="$xrpath $temp_xrpath";; esac;; -L*) case "$compile_command $temp_deplibs " in *" $deplib "*) ;; *) temp_deplibs="$temp_deplibs $deplib";; esac temp_dir=`$echo "X$deplib" | $Xsed -e 's/^-L//'` case " $lib_search_path " in *" $temp_dir "*) ;; *) lib_search_path="$lib_search_path $temp_dir";; esac ;; *) temp_deplibs="$temp_deplibs $deplib";; esac done dependency_libs="$temp_deplibs" fi if test -z "$libdir"; then # It is a libtool convenience library, so add in its objects. convenience="$convenience $dir/$old_library" old_convenience="$old_convenience $dir/$old_library" deplibs="$deplibs$dependency_libs" compile_command="$compile_command $dir/$old_library$dependency_libs" finalize_command="$finalize_command $dir/$old_library$dependency_libs" continue fi # This library was specified with -dlopen. if test "$prev" = dlfiles; then dlfiles="$dlfiles $arg" if test -z "$dlname" || test "$dlopen" != yes || test "$build_libtool_libs" = no; then # If there is no dlname, no dlopen support or we're linking statically, # we need to preload. prev=dlprefiles else # We should not create a dependency on this library, but we # may need any libraries it requires. compile_command="$compile_command$dependency_libs" finalize_command="$finalize_command$dependency_libs" prev= continue fi fi # The library was specified with -dlpreopen. if test "$prev" = dlprefiles; then # Prefer using a static library (so that no silly _DYNAMIC symbols # are required to link). if test -n "$old_library"; then dlprefiles="$dlprefiles $dir/$old_library" else dlprefiles="$dlprefiles $dir/$linklib" fi prev= fi if test -n "$library_names" && { test "$prefer_static_libs" = no || test -z "$old_library"; }; then link_against_libtool_libs="$link_against_libtool_libs $arg" if test -n "$shlibpath_var"; then # Make sure the rpath contains only unique directories. case "$temp_rpath " in *" $dir "*) ;; *) temp_rpath="$temp_rpath $dir" ;; esac fi # We need an absolute path. case "$dir" in [\\/] | [A-Za-z]:[\\/]*) absdir="$dir" ;; *) absdir=`cd "$dir" && pwd` if test -z "$absdir"; then $echo "$modename: warning: cannot determine absolute directory name of \`$dir'" 1>&2 $echo "$modename: passing it literally to the linker, although it might fail" 1>&2 absdir="$dir" fi ;; esac # This is the magic to use -rpath. # Skip directories that are in the system default run-time # search path, unless they have been requested with -R. case " $sys_lib_dlsearch_path " in *" $absdir "*) ;; *) case "$compile_rpath " in *" $absdir "*) ;; *) compile_rpath="$compile_rpath $absdir" esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) finalize_rpath="$finalize_rpath $libdir" esac ;; esac lib_linked=yes case "$hardcode_action" in immediate | unsupported) if test "$hardcode_direct" = no; then compile_command="$compile_command $dir/$linklib" deplibs="$deplibs $dir/$linklib" case "$host" in *-*-cygwin* | *-*-mingw* | *-*-os2*) dllsearchdir=`cd "$dir" && pwd || echo "$dir"` if test -n "$dllsearchpath"; then dllsearchpath="$dllsearchpath:$dllsearchdir" else dllsearchpath="$dllsearchdir" fi ;; esac elif test "$hardcode_minus_L" = no; then case "$host" in *-*-sunos*) compile_shlibpath="$compile_shlibpath$dir:" ;; esac case "$compile_command " in *" -L$dir "*) ;; *) compile_command="$compile_command -L$dir";; esac compile_command="$compile_command -l$name" deplibs="$deplibs -L$dir -l$name" elif test "$hardcode_shlibpath_var" = no; then case ":$compile_shlibpath:" in *":$dir:"*) ;; *) compile_shlibpath="$compile_shlibpath$dir:";; esac compile_command="$compile_command -l$name" deplibs="$deplibs -l$name" else lib_linked=no fi ;; relink) if test "$hardcode_direct" = yes; then compile_command="$compile_command $absdir/$linklib" deplibs="$deplibs $absdir/$linklib" elif test "$hardcode_minus_L" = yes; then case "$compile_command " in *" -L$absdir "*) ;; *) compile_command="$compile_command -L$absdir";; esac compile_command="$compile_command -l$name" deplibs="$deplibs -L$absdir -l$name" elif test "$hardcode_shlibpath_var" = yes; then case ":$compile_shlibpath:" in *":$absdir:"*) ;; *) compile_shlibpath="$compile_shlibpath$absdir:";; esac compile_command="$compile_command -l$name" deplibs="$deplibs -l$name" else lib_linked=no fi ;; *) lib_linked=no ;; esac if test "$lib_linked" != yes; then $echo "$modename: configuration error: unsupported hardcode properties" exit 1 fi # Finalize command for both is simple: just hardcode it. if test "$hardcode_direct" = yes; then finalize_command="$finalize_command $libdir/$linklib" elif test "$hardcode_minus_L" = yes; then case "$finalize_command " in *" -L$libdir "*) ;; *) finalize_command="$finalize_command -L$libdir";; esac finalize_command="$finalize_command -l$name" elif test "$hardcode_shlibpath_var" = yes; then case ":$finalize_shlibpath:" in *":$libdir:"*) ;; *) finalize_shlibpath="$finalize_shlibpath$libdir:";; esac finalize_command="$finalize_command -l$name" else # We cannot seem to hardcode it, guess we'll fake it. case "$finalize_command " in *" -L$dir "*) ;; *) finalize_command="$finalize_command -L$libdir";; esac finalize_command="$finalize_command -l$name" fi else # Transform directly to old archives if we don't build new libraries. if test -n "$pic_flag" && test -z "$old_library"; then $echo "$modename: cannot find static library for \`$arg'" 1>&2 exit 1 fi # Here we assume that one of hardcode_direct or hardcode_minus_L # is not unsupported. This is valid on all known static and # shared platforms. if test "$hardcode_direct" != unsupported; then test -n "$old_library" && linklib="$old_library" compile_command="$compile_command $dir/$linklib" finalize_command="$finalize_command $dir/$linklib" else case "$compile_command " in *" -L$dir "*) ;; *) compile_command="$compile_command -L$dir";; esac compile_command="$compile_command -l$name" case "$finalize_command " in *" -L$dir "*) ;; *) finalize_command="$finalize_command -L$dir";; esac finalize_command="$finalize_command -l$name" fi fi # Add in any libraries that this one depends upon. compile_command="$compile_command$dependency_libs" finalize_command="$finalize_command$dependency_libs" continue ;; # Some other compiler argument. *) # Unknown arguments in both finalize_command and compile_command need # to be aesthetically quoted because they are evaled later. arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` case "$arg" in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) arg="\"$arg\"" ;; esac ;; esac # Now actually substitute the argument into the commands. if test -n "$arg"; then compile_command="$compile_command $arg" finalize_command="$finalize_command $arg" fi done if test -n "$prev"; then $echo "$modename: the \`$prevarg' option requires an argument" 1>&2 $echo "$help" 1>&2 exit 1 fi if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then eval arg=\"$export_dynamic_flag_spec\" compile_command="$compile_command $arg" finalize_command="$finalize_command $arg" fi oldlibs= # calculate the name of the file, without its directory outputname=`$echo "X$output" | $Xsed -e 's%^.*/%%'` libobjs_save="$libobjs" case "$output" in "") $echo "$modename: you must specify an output file" 1>&2 $echo "$help" 1>&2 exit 1 ;; *.a | *.lib) if test -n "$link_against_libtool_libs"; then $echo "$modename: error: cannot link libtool libraries into archives" 1>&2 exit 1 fi if test -n "$deplibs"; then $echo "$modename: warning: \`-l' and \`-L' are ignored for archives" 1>&2 fi if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then $echo "$modename: warning: \`-dlopen' is ignored for archives" 1>&2 fi if test -n "$rpath"; then $echo "$modename: warning: \`-rpath' is ignored for archives" 1>&2 fi if test -n "$xrpath"; then $echo "$modename: warning: \`-R' is ignored for archives" 1>&2 fi if test -n "$vinfo"; then $echo "$modename: warning: \`-version-info' is ignored for archives" 1>&2 fi if test -n "$release"; then $echo "$modename: warning: \`-release' is ignored for archives" 1>&2 fi if test -n "$export_symbols" || test -n "$export_symbols_regex"; then $echo "$modename: warning: \`-export-symbols' is ignored for archives" 1>&2 fi # Now set the variables for building old libraries. build_libtool_libs=no oldlibs="$output" ;; *.la) # Make sure we only generate libraries of the form `libNAME.la'. case "$outputname" in lib*) name=`$echo "X$outputname" | $Xsed -e 's/\.la$//' -e 's/^lib//'` eval libname=\"$libname_spec\" ;; *) if test "$module" = no; then $echo "$modename: libtool library \`$output' must begin with \`lib'" 1>&2 $echo "$help" 1>&2 exit 1 fi if test "$need_lib_prefix" != no; then # Add the "lib" prefix for modules if required name=`$echo "X$outputname" | $Xsed -e 's/\.la$//'` eval libname=\"$libname_spec\" else libname=`$echo "X$outputname" | $Xsed -e 's/\.la$//'` fi ;; esac output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'` if test "X$output_objdir" = "X$output"; then output_objdir="$objdir" else output_objdir="$output_objdir/$objdir" fi if test -n "$objs"; then $echo "$modename: cannot build libtool library \`$output' from non-libtool objects:$objs" 2>&1 exit 1 fi # How the heck are we supposed to write a wrapper for a shared library? if test -n "$link_against_libtool_libs"; then $echo "$modename: error: cannot link shared libraries into libtool libraries" 1>&2 exit 1 fi if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then $echo "$modename: warning: \`-dlopen' is ignored for libtool libraries" 1>&2 fi set dummy $rpath if test $# -gt 2; then $echo "$modename: warning: ignoring multiple \`-rpath's for a libtool library" 1>&2 fi install_libdir="$2" oldlibs= if test -z "$rpath"; then if test "$build_libtool_libs" = yes; then # Building a libtool convenience library. libext=al oldlibs="$output_objdir/$libname.$libext $oldlibs" build_libtool_libs=convenience build_old_libs=yes fi dependency_libs="$deplibs" if test -n "$vinfo"; then $echo "$modename: warning: \`-version-info' is ignored for convenience libraries" 1>&2 fi if test -n "$release"; then $echo "$modename: warning: \`-release' is ignored for convenience libraries" 1>&2 fi else # Parse the version information argument. IFS="${IFS= }"; save_ifs="$IFS"; IFS=':' set dummy $vinfo 0 0 0 IFS="$save_ifs" if test -n "$8"; then $echo "$modename: too many parameters to \`-version-info'" 1>&2 $echo "$help" 1>&2 exit 1 fi current="$2" revision="$3" age="$4" # Check that each of the things are valid numbers. case "$current" in [0-9]*) ;; *) $echo "$modename: CURRENT \`$current' is not a nonnegative integer" 1>&2 $echo "$modename: \`$vinfo' is not valid version information" 1>&2 exit 1 ;; esac case "$revision" in [0-9]*) ;; *) $echo "$modename: REVISION \`$revision' is not a nonnegative integer" 1>&2 $echo "$modename: \`$vinfo' is not valid version information" 1>&2 exit 1 ;; esac case "$age" in [0-9]*) ;; *) $echo "$modename: AGE \`$age' is not a nonnegative integer" 1>&2 $echo "$modename: \`$vinfo' is not valid version information" 1>&2 exit 1 ;; esac if test $age -gt $current; then $echo "$modename: AGE \`$age' is greater than the current interface number \`$current'" 1>&2 $echo "$modename: \`$vinfo' is not valid version information" 1>&2 exit 1 fi # Calculate the version variables. major= versuffix= verstring= case "$version_type" in none) ;; irix) major=`expr $current - $age + 1` versuffix="$major.$revision" verstring="sgi$major.$revision" # Add in all the interfaces that we are compatible with. loop=$revision while test $loop != 0; do iface=`expr $revision - $loop` loop=`expr $loop - 1` verstring="sgi$major.$iface:$verstring" done ;; linux) major=.`expr $current - $age` versuffix="$major.$age.$revision" ;; osf) major=`expr $current - $age` versuffix=".$current.$age.$revision" verstring="$current.$age.$revision" # Add in all the interfaces that we are compatible with. loop=$age while test $loop != 0; do iface=`expr $current - $loop` loop=`expr $loop - 1` verstring="$verstring:${iface}.0" done # Make executables depend on our current version. verstring="$verstring:${current}.0" ;; sunos) major=".$current" versuffix=".$current.$revision" ;; freebsd-aout) major=".$current" versuffix=".$current.$revision"; ;; freebsd-elf) major=".$current" versuffix=".$current"; ;; windows) # Like Linux, but with '-' rather than '.', since we only # want one extension on Windows 95. major=`expr $current - $age` versuffix="-$major-$age-$revision" ;; *) $echo "$modename: unknown library version type \`$version_type'" 1>&2 echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 exit 1 ;; esac # Clear the version info if we defaulted, and they specified a release. if test -z "$vinfo" && test -n "$release"; then major= verstring="0.0" if test "$need_version" = no; then versuffix= else versuffix=".0.0" fi fi # Remove version info from name if versioning should be avoided if test "$avoid_version" = yes && test "$need_version" = no; then major= versuffix= verstring="" fi # Check to see if the archive will have undefined symbols. if test "$allow_undefined" = yes; then if test "$allow_undefined_flag" = unsupported; then $echo "$modename: warning: undefined symbols not allowed in $host shared libraries" 1>&2 build_libtool_libs=no build_old_libs=yes fi else # Don't allow undefined symbols. allow_undefined_flag="$no_undefined_flag" fi dependency_libs="$deplibs" case "$host" in *-*-cygwin* | *-*-mingw* | *-*-os2* | *-*-beos*) # these systems don't actually have a c library (as such)! ;; *-*-rhapsody*) # rhapsody is a little odd... deplibs="$deplibs -framework System" ;; *) # Add libc to deplibs on all other systems. deplibs="$deplibs -lc" ;; esac fi # Create the output directory, or remove our outputs if we need to. if test -d $output_objdir; then $show "${rm}r $output_objdir/$outputname $output_objdir/$libname.* $output_objdir/${libname}${release}.*" $run ${rm}r $output_objdir/$outputname $output_objdir/$libname.* $output_objdir/${libname}${release}.* else $show "$mkdir $output_objdir" $run $mkdir $output_objdir status=$? if test $status -ne 0 && test ! -d $output_objdir; then exit $status fi fi # Now set the variables for building old libraries. if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then oldlibs="$oldlibs $output_objdir/$libname.$libext" # Transform .lo files to .o files. oldobjs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP` fi if test "$build_libtool_libs" = yes; then # Transform deplibs into only deplibs that can be linked in shared. name_save=$name libname_save=$libname release_save=$release versuffix_save=$versuffix major_save=$major # I'm not sure if I'm treating the release correctly. I think # release should show up in the -l (ie -lgmp5) so we don't want to # add it in twice. Is that correct? release="" versuffix="" major="" newdeplibs= droppeddeps=no case "$deplibs_check_method" in pass_all) # Don't check for shared/static. Everything works. # This might be a little naive. We might want to check # whether the library exists or not. But this is on # osf3 & osf4 and I'm not really sure... Just # implementing what was already the behaviour. newdeplibs=$deplibs ;; test_compile) # This code stresses the "libraries are programs" paradigm to its # limits. Maybe even breaks it. We compile a program, linking it # against the deplibs as a proxy for the library. Then we can check # whether they linked in statically or dynamically with ldd. $rm conftest.c cat > conftest.c </dev/null` for potent_lib in $potential_libs; do # Follow soft links. if ls -lLd "$potent_lib" 2>/dev/null \ | grep " -> " >/dev/null; then continue fi # The statement above tries to avoid entering an # endless loop below, in case of cyclic links. # We might still enter an endless loop, since a link # loop can be closed while we follow links, # but so what? potlib="$potent_lib" while test -h "$potlib" 2>/dev/null; do potliblink=`ls -ld $potlib | sed 's/.* -> //'` case "$potliblink" in [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; *) potlib=`$echo "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";; esac done if eval $file_magic_cmd \"\$potlib\" 2>/dev/null \ | sed 10q \ | egrep "$file_magic_regex" > /dev/null; then newdeplibs="$newdeplibs $a_deplib" a_deplib="" break 2 fi done done if test -n "$a_deplib" ; then droppeddeps=yes echo echo "*** Warning: This library needs some functionality provided by $a_deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have." fi else # Add a -L argument. newdeplibs="$newdeplibs $a_deplib" fi done # Gone through all deplibs. ;; none | unknown | *) newdeplibs="" if $echo "X $deplibs" | $Xsed -e 's/ -lc$//' \ -e 's/ -[LR][^ ]*//g' -e 's/[ ]//g' | grep . >/dev/null; then echo if test "X$deplibs_check_method" = "Xnone"; then echo "*** Warning: inter-library dependencies are not supported in this platform." else echo "*** Warning: inter-library dependencies are not known to be supported." fi echo "*** All declared inter-library dependencies are being dropped." droppeddeps=yes fi ;; esac versuffix=$versuffix_save major=$major_save release=$release_save libname=$libname_save name=$name_save if test "$droppeddeps" = yes; then if test "$module" = yes; then echo echo "*** Warning: libtool could not satisfy all declared inter-library" echo "*** dependencies of module $libname. Therefore, libtool will create" echo "*** a static module, that should work as long as the dlopening" echo "*** application is linked with the -dlopen flag." if test -z "$global_symbol_pipe"; then echo echo "*** However, this would only work if libtool was able to extract symbol" echo "*** lists from a program, using \`nm' or equivalent, but libtool could" echo "*** not find such a program. So, this module is probably useless." echo "*** \`nm' from GNU binutils and a full rebuild may help." fi if test "$build_old_libs" = no; then oldlibs="$output_objdir/$libname.$libext" build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi else echo "*** The inter-library dependencies that have been dropped here will be" echo "*** automatically added whenever a program is linked with this library" echo "*** or is declared to -dlopen it." fi fi # Done checking deplibs! deplibs=$newdeplibs fi # All the library-specific variables (install_libdir is set above). library_names= old_library= dlname= # Test again, we may have decided not to build it any more if test "$build_libtool_libs" = yes; then # Get the real and link names of the library. eval library_names=\"$library_names_spec\" set dummy $library_names realname="$2" shift; shift if test -n "$soname_spec"; then eval soname=\"$soname_spec\" else soname="$realname" fi lib="$output_objdir/$realname" for link do linknames="$linknames $link" done # Ensure that we have .o objects for linkers which dislike .lo # (e.g. aix) in case we are running --disable-static for obj in $libobjs; do xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'` if test "X$xdir" = "X$obj"; then xdir="." else xdir="$xdir" fi baseobj=`$echo "X$obj" | $Xsed -e 's%^.*/%%'` oldobj=`$echo "X$baseobj" | $Xsed -e "$lo2o"` if test ! -f $xdir/$oldobj; then $show "(cd $xdir && ${LN_S} $baseobj $oldobj)" $run eval '(cd $xdir && ${LN_S} $baseobj $oldobj)' || exit $? fi done # Use standard objects if they are pic test -z "$pic_flag" && libobjs=`$echo "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` # Prepare the list of exported symbols if test -z "$export_symbols"; then if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then $show "generating symbol list for \`$libname.la'" export_symbols="$output_objdir/$libname.exp" $run $rm $export_symbols eval cmds=\"$export_symbols_cmds\" IFS="${IFS= }"; save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" if test -n "$export_symbols_regex"; then $show "egrep -e \"$export_symbols_regex\" \"$export_symbols\" > \"${export_symbols}T\"" $run eval 'egrep -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' $show "$mv \"${export_symbols}T\" \"$export_symbols\"" $run eval '$mv "${export_symbols}T" "$export_symbols"' fi fi fi if test -n "$export_symbols" && test -n "$include_expsyms"; then $run eval '$echo "X$include_expsyms" | $SP2NL >> "$export_symbols"' fi if test -n "$convenience"; then if test -n "$whole_archive_flag_spec"; then eval libobjs=\"\$libobjs $whole_archive_flag_spec\" else gentop="$output_objdir/${outputname}x" $show "${rm}r $gentop" $run ${rm}r "$gentop" $show "mkdir $gentop" $run mkdir "$gentop" status=$? if test $status -ne 0 && test ! -d "$gentop"; then exit $status fi generated="$generated $gentop" for xlib in $convenience; do # Extract the objects. case "$xlib" in [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;; *) xabs=`pwd`"/$xlib" ;; esac xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'` xdir="$gentop/$xlib" $show "${rm}r $xdir" $run ${rm}r "$xdir" $show "mkdir $xdir" $run mkdir "$xdir" status=$? if test $status -ne 0 && test ! -d "$xdir"; then exit $status fi $show "(cd $xdir && $AR x $xabs)" $run eval "(cd \$xdir && $AR x \$xabs)" || exit $? libobjs="$libobjs "`find $xdir -name \*.o -print -o -name \*.lo -print | $NL2SP` done fi fi if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then eval flag=\"$thread_safe_flag_spec\" linkopts="$linkopts $flag" fi # Do each of the archive commands. if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then eval cmds=\"$archive_expsym_cmds\" else eval cmds=\"$archive_cmds\" fi IFS="${IFS= }"; save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" # Create links to the real library. for linkname in $linknames; do if test "$realname" != "$linkname"; then $show "(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)" $run eval '(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)' || exit $? fi done # If -module or -export-dynamic was specified, set the dlname. if test "$module" = yes || test "$export_dynamic" = yes; then # On all known operating systems, these are identical. dlname="$soname" fi fi ;; *.lo | *.o | *.obj) if test -n "$link_against_libtool_libs"; then $echo "$modename: error: cannot link libtool libraries into objects" 1>&2 exit 1 fi if test -n "$deplibs"; then $echo "$modename: warning: \`-l' and \`-L' are ignored for objects" 1>&2 fi if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then $echo "$modename: warning: \`-dlopen' is ignored for objects" 1>&2 fi if test -n "$rpath"; then $echo "$modename: warning: \`-rpath' is ignored for objects" 1>&2 fi if test -n "$xrpath"; then $echo "$modename: warning: \`-R' is ignored for objects" 1>&2 fi if test -n "$vinfo"; then $echo "$modename: warning: \`-version-info' is ignored for objects" 1>&2 fi if test -n "$release"; then $echo "$modename: warning: \`-release' is ignored for objects" 1>&2 fi case "$output" in *.lo) if test -n "$objs"; then $echo "$modename: cannot build library object \`$output' from non-libtool objects" 1>&2 exit 1 fi libobj="$output" obj=`$echo "X$output" | $Xsed -e "$lo2o"` ;; *) libobj= obj="$output" ;; esac # Delete the old objects. $run $rm $obj $libobj # Objects from convenience libraries. This assumes # single-version convenience libraries. Whenever we create # different ones for PIC/non-PIC, this we'll have to duplicate # the extraction. reload_conv_objs= gentop= # reload_cmds runs $LD directly, so let us get rid of # -Wl from whole_archive_flag_spec wl= if test -n "$convenience"; then if test -n "$whole_archive_flag_spec"; then eval reload_conv_objs=\"\$reload_objs $whole_archive_flag_spec\" else gentop="$output_objdir/${obj}x" $show "${rm}r $gentop" $run ${rm}r "$gentop" $show "mkdir $gentop" $run mkdir "$gentop" status=$? if test $status -ne 0 && test ! -d "$gentop"; then exit $status fi generated="$generated $gentop" for xlib in $convenience; do # Extract the objects. case "$xlib" in [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;; *) xabs=`pwd`"/$xlib" ;; esac xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'` xdir="$gentop/$xlib" $show "${rm}r $xdir" $run ${rm}r "$xdir" $show "mkdir $xdir" $run mkdir "$xdir" status=$? if test $status -ne 0 && test ! -d "$xdir"; then exit $status fi $show "(cd $xdir && $AR x $xabs)" $run eval "(cd \$xdir && $AR x \$xabs)" || exit $? reload_conv_objs="$reload_objs "`find $xdir -name \*.o -print -o -name \*.lo -print | $NL2SP` done fi fi # Create the old-style object. reload_objs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" output="$obj" eval cmds=\"$reload_cmds\" IFS="${IFS= }"; save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" # Exit if we aren't doing a library object file. if test -z "$libobj"; then if test -n "$gentop"; then $show "${rm}r $gentop" $run ${rm}r $gentop fi exit 0 fi if test "$build_libtool_libs" != yes; then if test -n "$gentop"; then $show "${rm}r $gentop" $run ${rm}r $gentop fi # Create an invalid libtool object if no PIC, so that we don't # accidentally link it into a program. $show "echo timestamp > $libobj" $run eval "echo timestamp > $libobj" || exit $? exit 0 fi if test -n "$pic_flag"; then # Only do commands if we really have different PIC objects. reload_objs="$libobjs $reload_conv_objs" output="$libobj" eval cmds=\"$reload_cmds\" IFS="${IFS= }"; save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" else # Just create a symlink. $show $rm $libobj $run $rm $libobj xdir=`$echo "X$libobj" | $Xsed -e 's%/[^/]*$%%'` if test "X$xdir" = "X$libobj"; then xdir="." else xdir="$xdir" fi baseobj=`$echo "X$libobj" | $Xsed -e 's%^.*/%%'` oldobj=`$echo "X$baseobj" | $Xsed -e "$lo2o"` $show "(cd $xdir && $LN_S $oldobj $baseobj)" $run eval '(cd $xdir && $LN_S $oldobj $baseobj)' || exit $? fi if test -n "$gentop"; then $show "${rm}r $gentop" $run ${rm}r $gentop fi exit 0 ;; # Anything else should be a program. *) if test -n "$vinfo"; then $echo "$modename: warning: \`-version-info' is ignored for programs" 1>&2 fi if test -n "$release"; then $echo "$modename: warning: \`-release' is ignored for programs" 1>&2 fi if test "$preload" = yes; then if test "$dlopen" = unknown && test "$dlopen_self" = unknown && test "$dlopen_self_static" = unknown; then $echo "$modename: warning: \`AC_LIBTOOL_DLOPEN' not used. Assuming no dlopen support." fi fi if test -n "$rpath$xrpath"; then # If the user specified any rpath flags, then add them. for libdir in $rpath $xrpath; do # This is the magic to use -rpath. case "$compile_rpath " in *" $libdir "*) ;; *) compile_rpath="$compile_rpath $libdir" ;; esac case "$finalize_rpath " in *" $libdir "*) ;; *) finalize_rpath="$finalize_rpath $libdir" ;; esac done fi # Now hardcode the library paths rpath= hardcode_libdirs= for libdir in $compile_rpath $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case "$hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator" in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" rpath="$rpath $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) perm_rpath="$perm_rpath $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" eval rpath=\" $hardcode_libdir_flag_spec\" fi compile_rpath="$rpath" rpath= hardcode_libdirs= for libdir in $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case "$hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator" in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" rpath="$rpath $flag" fi elif test -n "$runpath_var"; then case "$finalize_perm_rpath " in *" $libdir "*) ;; *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" eval rpath=\" $hardcode_libdir_flag_spec\" fi finalize_rpath="$rpath" output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'` if test "X$output_objdir" = "X$output"; then output_objdir="$objdir" else output_objdir="$output_objdir/$objdir" fi # Create the binary in the object directory, then wrap it. if test ! -d $output_objdir; then $show "$mkdir $output_objdir" $run $mkdir $output_objdir status=$? if test $status -ne 0 && test ! -d $output_objdir; then exit $status fi fi if test -n "$libobjs" && test "$build_old_libs" = yes; then # Transform all the library objects into standard objects. compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` fi dlsyms= if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then if test -n "$NM" && test -n "$global_symbol_pipe"; then dlsyms="${outputname}S.c" else $echo "$modename: not configured to extract global symbols from dlpreopened files" 1>&2 fi fi if test -n "$dlsyms"; then case "$dlsyms" in "") ;; *.c) # Discover the nlist of each of the dlfiles. nlist="$output_objdir/${outputname}.nm" $show "$rm $nlist ${nlist}S ${nlist}T" $run $rm "$nlist" "${nlist}S" "${nlist}T" # Parse the name list into a source file. $show "creating $output_objdir/$dlsyms" test -z "$run" && $echo > "$output_objdir/$dlsyms" "\ /* $dlsyms - symbol resolution table for \`$outputname' dlsym emulation. */ /* Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP */ #ifdef __cplusplus extern \"C\" { #endif /* Prevent the only kind of declaration conflicts we can make. */ #define lt_preloaded_symbols some_other_symbol /* External symbol declarations for the compiler. */\ " if test "$dlself" = yes; then $show "generating symbol list for \`$output'" test -z "$run" && $echo ': @PROGRAM@ ' > "$nlist" # Add our own program objects to the symbol list. progfiles=`$echo "X$objs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` for arg in $progfiles; do $show "extracting global C symbols from \`$arg'" $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'" done if test -n "$exclude_expsyms"; then $run eval 'egrep -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' $run eval '$mv "$nlist"T "$nlist"' fi if test -n "$export_symbols_regex"; then $run eval 'egrep -e "$export_symbols_regex" "$nlist" > "$nlist"T' $run eval '$mv "$nlist"T "$nlist"' fi # Prepare the list of exported symbols if test -z "$export_symbols"; then export_symbols="$output_objdir/$output.exp" $run $rm $export_symbols $run eval "sed -n -e '/^: @PROGRAM@$/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' else $run eval "sed -e 's/\([][.*^$]\)/\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$output.exp"' $run eval 'grep -f "$output_objdir/$output.exp" < "$nlist" > "$nlist"T' $run eval 'mv "$nlist"T "$nlist"' fi fi for arg in $dlprefiles; do $show "extracting global C symbols from \`$arg'" name=`echo "$arg" | sed -e 's%^.*/%%'` $run eval 'echo ": $name " >> "$nlist"' $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'" done if test -z "$run"; then # Make sure we have at least an empty file. test -f "$nlist" || : > "$nlist" if test -n "$exclude_expsyms"; then egrep -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T $mv "$nlist"T "$nlist" fi # Try sorting and uniquifying the output. if grep -v "^: " < "$nlist" | sort +2 | uniq > "$nlist"S; then : else grep -v "^: " < "$nlist" > "$nlist"S fi if test -f "$nlist"S; then eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$dlsyms"' else echo '/* NONE */' >> "$output_objdir/$dlsyms" fi $echo >> "$output_objdir/$dlsyms" "\ #undef lt_preloaded_symbols #if defined (__STDC__) && __STDC__ # define lt_ptr_t void * #else # define lt_ptr_t char * # define const #endif /* The mapping between symbol names and symbols. */ const struct { const char *name; lt_ptr_t address; } lt_preloaded_symbols[] = {\ " sed -n -e 's/^: \([^ ]*\) $/ {\"\1\", (lt_ptr_t) 0},/p' \ -e 's/^. \([^ ]*\) \([^ ]*\)$/ {"\2", (lt_ptr_t) \&\2},/p' \ < "$nlist" >> "$output_objdir/$dlsyms" $echo >> "$output_objdir/$dlsyms" "\ {0, (lt_ptr_t) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt_preloaded_symbols; } #endif #ifdef __cplusplus } #endif\ " fi pic_flag_for_symtable= case "$host" in # compiling the symbol table file with pic_flag works around # a FreeBSD bug that causes programs to crash when -lm is # linked before any other PIC object. But we must not use # pic_flag when linking with -static. The problem exists in # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) case "$compile_command " in *" -static "*) ;; *) pic_flag_for_symtable=" $pic_flag -DPIC -DFREEBSD_WORKAROUND";; esac;; *-*-hpux*) case "$compile_command " in *" -static "*) ;; *) pic_flag_for_symtable=" $pic_flag -DPIC";; esac esac # Now compile the dynamic symbol file. $show "(cd $output_objdir && $CC -c$no_builtin_flag$pic_flag_for_symtable \"$dlsyms\")" $run eval '(cd $output_objdir && $CC -c$no_builtin_flag$pic_flag_for_symtable "$dlsyms")' || exit $? # Clean up the generated files. $show "$rm $output_objdir/$dlsyms $nlist ${nlist}S ${nlist}T" $run $rm "$output_objdir/$dlsyms" "$nlist" "${nlist}S" "${nlist}T" # Transform the symbol file into the correct name. compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` ;; *) $echo "$modename: unknown suffix for \`$dlsyms'" 1>&2 exit 1 ;; esac else # We keep going just in case the user didn't refer to # lt_preloaded_symbols. The linker will fail if global_symbol_pipe # really was required. # Nullify the symbol file. compile_command=`$echo "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"` finalize_command=`$echo "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"` fi if test -z "$link_against_libtool_libs" || test "$build_libtool_libs" != yes; then # Replace the output file specification. compile_command=`$echo "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` link_command="$compile_command$compile_rpath" # We have no uninstalled library dependencies, so finalize right now. $show "$link_command" $run eval "$link_command" status=$? # Delete the generated files. if test -n "$dlsyms"; then $show "$rm $output_objdir/${outputname}S.${objext}" $run $rm "$output_objdir/${outputname}S.${objext}" fi exit $status fi if test -n "$shlibpath_var"; then # We should set the shlibpath_var rpath= for dir in $temp_rpath; do case "$dir" in [\\/]* | [A-Za-z]:[\\/]*) # Absolute path. rpath="$rpath$dir:" ;; *) # Relative path: add a thisdir entry. rpath="$rpath\$thisdir/$dir:" ;; esac done temp_rpath="$rpath" fi if test -n "$compile_shlibpath$finalize_shlibpath"; then compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" fi if test -n "$finalize_shlibpath"; then finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" fi compile_var= finalize_var= if test -n "$runpath_var"; then if test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do rpath="$rpath$dir:" done compile_var="$runpath_var=\"$rpath\$$runpath_var\" " fi if test -n "$finalize_perm_rpath"; then # We should set the runpath_var. rpath= for dir in $finalize_perm_rpath; do rpath="$rpath$dir:" done finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " fi fi if test "$hardcode_action" = relink; then # Fast installation is not supported link_command="$compile_var$compile_command$compile_rpath" relink_command="$finalize_var$finalize_command$finalize_rpath" $echo "$modename: warning: this platform does not like uninstalled shared libraries" 1>&2 $echo "$modename: \`$output' will be relinked during installation" 1>&2 else if test "$fast_install" != no; then link_command="$finalize_var$compile_command$finalize_rpath" if test "$fast_install" = yes; then relink_command=`$echo "X$compile_var$compile_command$compile_rpath" | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g'` else # fast_install is set to needless relink_command= fi else link_command="$compile_var$compile_command$compile_rpath" relink_command="$finalize_var$finalize_command$finalize_rpath" fi fi # Replace the output file specification. link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` # Delete the old output files. $run $rm $output $output_objdir/$outputname $output_objdir/lt-$outputname $show "$link_command" $run eval "$link_command" || exit $? # Now create the wrapper script. $show "creating $output" # Quote the relink command for shipping. if test -n "$relink_command"; then relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"` fi # Quote $echo for shipping. if test "X$echo" = "X$SHELL $0 --fallback-echo"; then case "$0" in [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $0 --fallback-echo";; *) qecho="$SHELL `pwd`/$0 --fallback-echo";; esac qecho=`$echo "X$qecho" | $Xsed -e "$sed_quote_subst"` else qecho=`$echo "X$echo" | $Xsed -e "$sed_quote_subst"` fi # Only actually do things if our run command is non-null. if test -z "$run"; then # win32 will think the script is a binary if it has # a .exe suffix, so we strip it off here. case $output in *.exe) output=`echo $output|sed 's,.exe$,,'` ;; esac $rm $output trap "$rm $output; exit 1" 1 2 15 $echo > $output "\ #! $SHELL # $output - temporary wrapper script for $objdir/$outputname # Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP # # The $output program cannot be directly executed until all the libtool # libraries that it depends on are installed. # # This wrapper script should never be moved out of the build directory. # If it is, it will not operate correctly. # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. Xsed='sed -e 1s/^X//' sed_quote_subst='$sed_quote_subst' # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. if test \"\${CDPATH+set}\" = set; then CDPATH=:; export CDPATH; fi relink_command=\"$relink_command\" # This environment variable determines our operation mode. if test \"\$libtool_install_magic\" = \"$magic\"; then # install mode needs the following variable: link_against_libtool_libs='$link_against_libtool_libs' else # When we are sourced in execute mode, \$file and \$echo are already set. if test \"\$libtool_execute_magic\" != \"$magic\"; then echo=\"$qecho\" file=\"\$0\" # Make sure echo works. if test \"X\$1\" = X--no-reexec; then # Discard the --no-reexec flag, and continue. shift elif test \"X\`(\$echo '\t') 2>/dev/null\`\" = 'X\t'; then # Yippee, \$echo works! : else # Restart under the correct shell, and then maybe \$echo will work. exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"} fi fi\ " $echo >> $output "\ # Find the directory that this script lives in. thisdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\` test \"x\$thisdir\" = \"x\$file\" && thisdir=. # Follow symbolic links until we get to the real thisdir. file=\`ls -ld \"\$file\" | sed -n 's/.*-> //p'\` while test -n \"\$file\"; do destdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\` # If there was a directory component, then change thisdir. if test \"x\$destdir\" != \"x\$file\"; then case \"\$destdir\" in [\\/]* | [A-Za-z]:[\\/]*) thisdir=\"\$destdir\" ;; *) thisdir=\"\$thisdir/\$destdir\" ;; esac fi file=\`\$echo \"X\$file\" | \$Xsed -e 's%^.*/%%'\` file=\`ls -ld \"\$thisdir/\$file\" | sed -n 's/.*-> //p'\` done # Try to get the absolute directory name. absdir=\`cd \"\$thisdir\" && pwd\` test -n \"\$absdir\" && thisdir=\"\$absdir\" " if test "$fast_install" = yes; then echo >> $output "\ program=lt-'$outputname' progdir=\"\$thisdir/$objdir\" if test ! -f \"\$progdir/\$program\" || \\ { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | sed 1q\`; \\ test \"X\$file\" != \"X\$progdir/\$program\"; }; then file=\"\$\$-\$program\" if test ! -d \"\$progdir\"; then $mkdir \"\$progdir\" else $rm \"\$progdir/\$file\" fi" echo >> $output "\ # relink executable if necessary if test -n \"\$relink_command\"; then if (cd \"\$thisdir\" && eval \$relink_command); then : else $rm \"\$progdir/\$file\" exit 1 fi fi $mv \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || { $rm \"\$progdir/\$program\"; $mv \"\$progdir/\$file\" \"\$progdir/\$program\"; } $rm \"\$progdir/\$file\" fi" else echo >> $output "\ program='$outputname' progdir=\"\$thisdir/$objdir\" " fi echo >> $output "\ if test -f \"\$progdir/\$program\"; then" # Export our shlibpath_var if we have one. if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then $echo >> $output "\ # Add our own library path to $shlibpath_var $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" # Some systems cannot cope with colon-terminated $shlibpath_var # The second colon is a workaround for a bug in BeOS R4 sed $shlibpath_var=\`\$echo \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\` export $shlibpath_var " fi # fixup the dll searchpath if we need to. if test -n "$dllsearchpath"; then $echo >> $output "\ # Add the dll search path components to the executable PATH PATH=$dllsearchpath:\$PATH " fi $echo >> $output "\ if test \"\$libtool_execute_magic\" != \"$magic\"; then # Run the actual program with our arguments. " case $host in # win32 systems need to use the prog path for dll # lookup to work *-*-cygwin*) $echo >> $output "\ exec \$progdir/\$program \${1+\"\$@\"} " ;; # Backslashes separate directories on plain windows *-*-mingw | *-*-os2*) $echo >> $output "\ exec \$progdir\\\\\$program \${1+\"\$@\"} " ;; *) $echo >> $output "\ # Export the path to the program. PATH=\"\$progdir:\$PATH\" export PATH exec \$program \${1+\"\$@\"} " ;; esac $echo >> $output "\ \$echo \"\$0: cannot exec \$program \${1+\"\$@\"}\" exit 1 fi else # The program doesn't exist. \$echo \"\$0: error: \$progdir/\$program does not exist\" 1>&2 \$echo \"This script is just a wrapper for \$program.\" 1>&2 echo \"See the $PACKAGE documentation for more information.\" 1>&2 exit 1 fi fi\ " chmod +x $output fi exit 0 ;; esac # See if we need to build an old-fashioned archive. for oldlib in $oldlibs; do if test "$build_libtool_libs" = convenience; then oldobjs="$libobjs_save" addlibs="$convenience" build_libtool_libs=no else if test "$build_libtool_libs" = module; then oldobjs="$libobjs_save" build_libtool_libs=no else oldobjs="$objs "`$echo "X$libobjs_save" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP` fi addlibs="$old_convenience" fi if test -n "$addlibs"; then gentop="$output_objdir/${outputname}x" $show "${rm}r $gentop" $run ${rm}r "$gentop" $show "mkdir $gentop" $run mkdir "$gentop" status=$? if test $status -ne 0 && test ! -d "$gentop"; then exit $status fi generated="$generated $gentop" # Add in members from convenience archives. for xlib in $addlibs; do # Extract the objects. case "$xlib" in [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;; *) xabs=`pwd`"/$xlib" ;; esac xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'` xdir="$gentop/$xlib" $show "${rm}r $xdir" $run ${rm}r "$xdir" $show "mkdir $xdir" $run mkdir "$xdir" status=$? if test $status -ne 0 && test ! -d "$xdir"; then exit $status fi $show "(cd $xdir && $AR x $xabs)" $run eval "(cd \$xdir && $AR x \$xabs)" || exit $? oldobjs="$oldobjs "`find $xdir -name \*.${objext} -print -o -name \*.lo -print | $NL2SP` done fi # Do each command in the archive commands. if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then eval cmds=\"$old_archive_from_new_cmds\" else # Ensure that we have .o objects in place in case we decided # not to build a shared library, and have fallen back to building # static libs even though --disable-static was passed! for oldobj in $oldobjs; do if test ! -f $oldobj; then xdir=`$echo "X$oldobj" | $Xsed -e 's%/[^/]*$%%'` if test "X$xdir" = "X$oldobj"; then xdir="." else xdir="$xdir" fi baseobj=`$echo "X$oldobj" | $Xsed -e 's%^.*/%%'` obj=`$echo "X$baseobj" | $Xsed -e "$o2lo"` $show "(cd $xdir && ${LN_S} $obj $baseobj)" $run eval '(cd $xdir && ${LN_S} $obj $baseobj)' || exit $? fi done eval cmds=\"$old_archive_cmds\" fi IFS="${IFS= }"; save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" done if test -n "$generated"; then $show "${rm}r$generated" $run ${rm}r$generated fi # Now create the libtool archive. case "$output" in *.la) old_library= test "$build_old_libs" = yes && old_library="$libname.$libext" $show "creating $output" if test -n "$xrpath"; then temp_xrpath= for libdir in $xrpath; do temp_xrpath="$temp_xrpath -R$libdir" done dependency_libs="$temp_xrpath $dependency_libs" fi # Only create the output if not a dry run. if test -z "$run"; then for installed in no yes; do if test "$installed" = yes; then if test -z "$install_libdir"; then break fi output="$output_objdir/$outputname"i fi $rm $output $echo > $output "\ # $outputname - a libtool library file # Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP # # Please DO NOT delete this file! # It is necessary for linking the library. # The name that we can dlopen(3). dlname='$dlname' # Names of this library. library_names='$library_names' # The name of the static archive. old_library='$old_library' # Libraries that this one depends upon. dependency_libs='$dependency_libs' # Version information for $libname. current=$current age=$age revision=$revision # Is this an already installed library? installed=$installed # Directory that this library needs to be installed in: libdir='$install_libdir'\ " done fi # Do a symbolic link so that the libtool archive can be found in # LD_LIBRARY_PATH before the program is installed. $show "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)" $run eval "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)" || exit $? ;; esac exit 0 ;; # libtool install mode install) modename="$modename: install" # There may be an optional sh(1) argument at the beginning of # install_prog (especially on Windows NT). if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh; then # Aesthetically quote it. arg=`$echo "X$nonopt" | $Xsed -e "$sed_quote_subst"` case "$arg" in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) arg="\"$arg\"" ;; esac install_prog="$arg " arg="$1" shift else install_prog= arg="$nonopt" fi # The real first argument should be the name of the installation program. # Aesthetically quote it. arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` case "$arg" in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) arg="\"$arg\"" ;; esac install_prog="$install_prog$arg" # We need to accept at least all the BSD install flags. dest= files= opts= prev= install_type= isdir=no stripme= for arg do if test -n "$dest"; then files="$files $dest" dest="$arg" continue fi case "$arg" in -d) isdir=yes ;; -f) prev="-f" ;; -g) prev="-g" ;; -m) prev="-m" ;; -o) prev="-o" ;; -s) stripme=" -s" continue ;; -*) ;; *) # If the previous option needed an argument, then skip it. if test -n "$prev"; then prev= else dest="$arg" continue fi ;; esac # Aesthetically quote the argument. arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` case "$arg" in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) arg="\"$arg\"" ;; esac install_prog="$install_prog $arg" done if test -z "$install_prog"; then $echo "$modename: you must specify an install program" 1>&2 $echo "$help" 1>&2 exit 1 fi if test -n "$prev"; then $echo "$modename: the \`$prev' option requires an argument" 1>&2 $echo "$help" 1>&2 exit 1 fi if test -z "$files"; then if test -z "$dest"; then $echo "$modename: no file or destination specified" 1>&2 else $echo "$modename: you must specify a destination" 1>&2 fi $echo "$help" 1>&2 exit 1 fi # Strip any trailing slash from the destination. dest=`$echo "X$dest" | $Xsed -e 's%/$%%'` # Check to see that the destination is a directory. test -d "$dest" && isdir=yes if test "$isdir" = yes; then destdir="$dest" destname= else destdir=`$echo "X$dest" | $Xsed -e 's%/[^/]*$%%'` test "X$destdir" = "X$dest" && destdir=. destname=`$echo "X$dest" | $Xsed -e 's%^.*/%%'` # Not a directory, so check to see that there is only one file specified. set dummy $files if test $# -gt 2; then $echo "$modename: \`$dest' is not a directory" 1>&2 $echo "$help" 1>&2 exit 1 fi fi case "$destdir" in [\\/]* | [A-Za-z]:[\\/]*) ;; *) for file in $files; do case "$file" in *.lo) ;; *) $echo "$modename: \`$destdir' must be an absolute directory name" 1>&2 $echo "$help" 1>&2 exit 1 ;; esac done ;; esac # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic="$magic" staticlibs= future_libdirs= current_libdirs= for file in $files; do # Do each installation. case "$file" in *.a | *.lib) # Do the static libraries later. staticlibs="$staticlibs $file" ;; *.la) # Check to see that this really is a libtool archive. if (sed -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : else $echo "$modename: \`$file' is not a valid libtool archive" 1>&2 $echo "$help" 1>&2 exit 1 fi library_names= old_library= # If there is no directory component, then add one. case "$file" in */* | *\\*) . $file ;; *) . ./$file ;; esac # Add the libdir to current_libdirs if it is the destination. if test "X$destdir" = "X$libdir"; then case "$current_libdirs " in *" $libdir "*) ;; *) current_libdirs="$current_libdirs $libdir" ;; esac else # Note the libdir as a future libdir. case "$future_libdirs " in *" $libdir "*) ;; *) future_libdirs="$future_libdirs $libdir" ;; esac fi dir="`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`/" test "X$dir" = "X$file/" && dir= dir="$dir$objdir" # See the names of the shared library. set dummy $library_names if test -n "$2"; then realname="$2" shift shift # Install the shared library and build the symlinks. $show "$install_prog $dir/$realname $destdir/$realname" $run eval "$install_prog $dir/$realname $destdir/$realname" || exit $? if test $# -gt 0; then # Delete the old symlinks, and create new ones. for linkname do if test "$linkname" != "$realname"; then $show "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)" $run eval "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)" fi done fi # Do each command in the postinstall commands. lib="$destdir/$realname" eval cmds=\"$postinstall_cmds\" IFS="${IFS= }"; save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" fi # Install the pseudo-library for information purposes. name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` instname="$dir/$name"i $show "$install_prog $instname $destdir/$name" $run eval "$install_prog $instname $destdir/$name" || exit $? # Maybe install the static library, too. test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library" ;; *.lo) # Install (i.e. copy) a libtool object. # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile="$destdir/$destname" else destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'` destfile="$destdir/$destfile" fi # Deduce the name of the destination old-style object file. case "$destfile" in *.lo) staticdest=`$echo "X$destfile" | $Xsed -e "$lo2o"` ;; *.o | *.obj) staticdest="$destfile" destfile= ;; *) $echo "$modename: cannot copy a libtool object to \`$destfile'" 1>&2 $echo "$help" 1>&2 exit 1 ;; esac # Install the libtool object if requested. if test -n "$destfile"; then $show "$install_prog $file $destfile" $run eval "$install_prog $file $destfile" || exit $? fi # Install the old object if enabled. if test "$build_old_libs" = yes; then # Deduce the name of the old-style object file. staticobj=`$echo "X$file" | $Xsed -e "$lo2o"` $show "$install_prog $staticobj $staticdest" $run eval "$install_prog \$staticobj \$staticdest" || exit $? fi exit 0 ;; *) # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile="$destdir/$destname" else destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'` destfile="$destdir/$destfile" fi # Do a test to see if this is really a libtool program. if (sed -e '4q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then link_against_libtool_libs= relink_command= # If there is no directory component, then add one. case "$file" in */* | *\\*) . $file ;; *) . ./$file ;; esac # Check the variables that should have been set. if test -z "$link_against_libtool_libs"; then $echo "$modename: invalid libtool wrapper script \`$file'" 1>&2 exit 1 fi finalize=yes for lib in $link_against_libtool_libs; do # Check to see that each library is installed. libdir= if test -f "$lib"; then # If there is no directory component, then add one. case "$lib" in */* | *\\*) . $lib ;; *) . ./$lib ;; esac fi libfile="$libdir/`$echo "X$lib" | $Xsed -e 's%^.*/%%g'`" if test -n "$libdir" && test ! -f "$libfile"; then $echo "$modename: warning: \`$lib' has not been installed in \`$libdir'" 1>&2 finalize=no fi done outputname= if test "$fast_install" = no && test -n "$relink_command"; then if test "$finalize" = yes && test -z "$run"; then tmpdir="/tmp" test -n "$TMPDIR" && tmpdir="$TMPDIR" tmpdir=`mktemp -d $tmpdir/libtool-XXXXXX 2> /dev/null` if test $? = 0 ; then : else tmpdir="$tmpdir/libtool-$$" fi if $mkdir -p "$tmpdir" && chmod 700 "$tmpdir"; then : else $echo "$modename: error: cannot create temporary directory \`$tmpdir'" 1>&2 continue fi outputname="$tmpdir/$file" # Replace the output file specification. relink_command=`$echo "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'` $show "$relink_command" if $run eval "$relink_command"; then : else $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2 ${rm}r "$tmpdir" continue fi file="$outputname" else $echo "$modename: warning: cannot relink \`$file'" 1>&2 fi else # Install the binary that we compiled earlier. file=`$echo "X$file" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"` fi fi $show "$install_prog$stripme $file $destfile" $run eval "$install_prog\$stripme \$file \$destfile" || exit $? test -n "$outputname" && ${rm}r "$tmpdir" ;; esac done for file in $staticlibs; do name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` # Set up the ranlib parameters. oldlib="$destdir/$name" $show "$install_prog $file $oldlib" $run eval "$install_prog \$file \$oldlib" || exit $? # Do each command in the postinstall commands. eval cmds=\"$old_postinstall_cmds\" IFS="${IFS= }"; save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" done if test -n "$future_libdirs"; then $echo "$modename: warning: remember to run \`$progname --finish$future_libdirs'" 1>&2 fi if test -n "$current_libdirs"; then # Maybe just do a dry run. test -n "$run" && current_libdirs=" -n$current_libdirs" exec $SHELL $0 --finish$current_libdirs exit 1 fi exit 0 ;; # libtool finish mode finish) modename="$modename: finish" libdirs="$nonopt" admincmds= if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then for dir do libdirs="$libdirs $dir" done for libdir in $libdirs; do if test -n "$finish_cmds"; then # Do each command in the finish commands. eval cmds=\"$finish_cmds\" IFS="${IFS= }"; save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || admincmds="$admincmds $cmd" done IFS="$save_ifs" fi if test -n "$finish_eval"; then # Do the single finish_eval. eval cmds=\"$finish_eval\" $run eval "$cmds" || admincmds="$admincmds $cmds" fi done fi # Exit here if they wanted silent mode. test "$show" = : && exit 0 echo "----------------------------------------------------------------------" echo "Libraries have been installed in:" for libdir in $libdirs; do echo " $libdir" done echo echo "If you ever happen to want to link against installed libraries" echo "in a given directory, LIBDIR, you must either use libtool, and" echo "specify the full pathname of the library, or use \`-LLIBDIR'" echo "flag during linking and do at least one of the following:" if test -n "$shlibpath_var"; then echo " - add LIBDIR to the \`$shlibpath_var' environment variable" echo " during execution" fi if test -n "$runpath_var"; then echo " - add LIBDIR to the \`$runpath_var' environment variable" echo " during linking" fi if test -n "$hardcode_libdir_flag_spec"; then libdir=LIBDIR eval flag=\"$hardcode_libdir_flag_spec\" echo " - use the \`$flag' linker flag" fi if test -n "$admincmds"; then echo " - have your system administrator run these commands:$admincmds" fi if test -f /etc/ld.so.conf; then echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" fi echo echo "See any operating system documentation about shared libraries for" echo "more information, such as the ld(1) and ld.so(8) manual pages." echo "----------------------------------------------------------------------" exit 0 ;; # libtool execute mode execute) modename="$modename: execute" # The first argument is the command name. cmd="$nonopt" if test -z "$cmd"; then $echo "$modename: you must specify a COMMAND" 1>&2 $echo "$help" exit 1 fi # Handle -dlopen flags immediately. for file in $execute_dlfiles; do if test ! -f "$file"; then $echo "$modename: \`$file' is not a file" 1>&2 $echo "$help" 1>&2 exit 1 fi dir= case "$file" in *.la) # Check to see that this really is a libtool archive. if (sed -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : else $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 $echo "$help" 1>&2 exit 1 fi # Read the libtool library. dlname= library_names= # If there is no directory component, then add one. case "$file" in */* | *\\*) . $file ;; *) . ./$file ;; esac # Skip this library if it cannot be dlopened. if test -z "$dlname"; then # Warn if it was a shared library. test -n "$library_names" && $echo "$modename: warning: \`$file' was not linked with \`-export-dynamic'" continue fi dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` test "X$dir" = "X$file" && dir=. if test -f "$dir/$objdir/$dlname"; then dir="$dir/$objdir" else $echo "$modename: cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" 1>&2 exit 1 fi ;; *.lo) # Just add the directory containing the .lo file. dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` test "X$dir" = "X$file" && dir=. ;; *) $echo "$modename: warning \`-dlopen' is ignored for non-libtool libraries and objects" 1>&2 continue ;; esac # Get the absolute pathname. absdir=`cd "$dir" && pwd` test -n "$absdir" && dir="$absdir" # Now add the directory to shlibpath_var. if eval "test -z \"\$$shlibpath_var\""; then eval "$shlibpath_var=\"\$dir\"" else eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" fi done # This variable tells wrapper scripts just to set shlibpath_var # rather than running their programs. libtool_execute_magic="$magic" # Check if any of the arguments is a wrapper script. args= for file do case "$file" in -*) ;; *) # Do a test to see if this is really a libtool program. if (sed -e '4q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then # If there is no directory component, then add one. case "$file" in */* | *\\*) . $file ;; *) . ./$file ;; esac # Transform arg to wrapped name. file="$progdir/$program" fi ;; esac # Quote arguments (to preserve shell metacharacters). file=`$echo "X$file" | $Xsed -e "$sed_quote_subst"` args="$args \"$file\"" done if test -z "$run"; then if test -n "$shlibpath_var"; then # Export the shlibpath_var. eval "export $shlibpath_var" fi # Restore saved enviroment variables if test "${save_LC_ALL+set}" = set; then LC_ALL="$save_LC_ALL"; export LC_ALL fi if test "${save_LANG+set}" = set; then LANG="$save_LANG"; export LANG fi # Now actually exec the command. eval "exec \$cmd$args" $echo "$modename: cannot exec \$cmd$args" exit 1 else # Display what would be done. if test -n "$shlibpath_var"; then eval "\$echo \"\$shlibpath_var=\$$shlibpath_var\"" $echo "export $shlibpath_var" fi $echo "$cmd$args" exit 0 fi ;; # libtool uninstall mode uninstall) modename="$modename: uninstall" rm="$nonopt" files= for arg do case "$arg" in -*) rm="$rm $arg" ;; *) files="$files $arg" ;; esac done if test -z "$rm"; then $echo "$modename: you must specify an RM program" 1>&2 $echo "$help" 1>&2 exit 1 fi for file in $files; do dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` test "X$dir" = "X$file" && dir=. name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` rmfiles="$file" case "$name" in *.la) # Possibly a libtool archive, so verify it. if (sed -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then . $dir/$name # Delete the libtool libraries and symlinks. for n in $library_names; do rmfiles="$rmfiles $dir/$n" done test -n "$old_library" && rmfiles="$rmfiles $dir/$old_library" $show "$rm $rmfiles" $run $rm $rmfiles if test -n "$library_names"; then # Do each command in the postuninstall commands. eval cmds=\"$postuninstall_cmds\" IFS="${IFS= }"; save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" done IFS="$save_ifs" fi if test -n "$old_library"; then # Do each command in the old_postuninstall commands. eval cmds=\"$old_postuninstall_cmds\" IFS="${IFS= }"; save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" done IFS="$save_ifs" fi # FIXME: should reinstall the best remaining shared library. fi ;; *.lo) if test "$build_old_libs" = yes; then oldobj=`$echo "X$name" | $Xsed -e "$lo2o"` rmfiles="$rmfiles $dir/$oldobj" fi $show "$rm $rmfiles" $run $rm $rmfiles ;; *) $show "$rm $rmfiles" $run $rm $rmfiles ;; esac done exit 0 ;; "") $echo "$modename: you must specify a MODE" 1>&2 $echo "$generic_help" 1>&2 exit 1 ;; esac $echo "$modename: invalid operation mode \`$mode'" 1>&2 $echo "$generic_help" 1>&2 exit 1 fi # test -z "$show_help" # We need to display help for each of the modes. case "$mode" in "") $echo \ "Usage: $modename [OPTION]... [MODE-ARG]... Provide generalized library-building support services. --config show all configuration variables --debug enable verbose shell tracing -n, --dry-run display commands without modifying any files --features display basic configuration information and exit --finish same as \`--mode=finish' --help display this help message and exit --mode=MODE use operation mode MODE [default=inferred from MODE-ARGS] --quiet same as \`--silent' --silent don't print informational messages --version print version information MODE must be one of the following: compile compile a source file into a libtool object execute automatically set library path, then run a program finish complete the installation of libtool libraries install install libraries or executables link create a library or an executable uninstall remove libraries from an installed directory MODE-ARGS vary depending on the MODE. Try \`$modename --help --mode=MODE' for a more detailed description of MODE." exit 0 ;; compile) $echo \ "Usage: $modename [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE Compile a source file into a libtool library object. This mode accepts the following additional options: -o OUTPUT-FILE set the output file name to OUTPUT-FILE -static always build a \`.o' file suitable for static linking COMPILE-COMMAND is a command to be used in creating a \`standard' object file from the given SOURCEFILE. The output file name is determined by removing the directory component from SOURCEFILE, then substituting the C source code suffix \`.c' with the library object suffix, \`.lo'." ;; execute) $echo \ "Usage: $modename [OPTION]... --mode=execute COMMAND [ARGS]... Automatically set library path, then run a program. This mode accepts the following additional options: -dlopen FILE add the directory containing FILE to the library path This mode sets the library path environment variable according to \`-dlopen' flags. If any of the ARGS are libtool executable wrappers, then they are translated into their corresponding uninstalled binary, and any of their required library directories are added to the library path. Then, COMMAND is executed, with ARGS as arguments." ;; finish) $echo \ "Usage: $modename [OPTION]... --mode=finish [LIBDIR]... Complete the installation of libtool libraries. Each LIBDIR is a directory that contains libtool libraries. The commands that this mode executes may require superuser privileges. Use the \`--dry-run' option if you just want to see what would be executed." ;; install) $echo \ "Usage: $modename [OPTION]... --mode=install INSTALL-COMMAND... Install executables or libraries. INSTALL-COMMAND is the installation command. The first component should be either the \`install' or \`cp' program. The rest of the components are interpreted as arguments to that command (only BSD-compatible install options are recognized)." ;; link) $echo \ "Usage: $modename [OPTION]... --mode=link LINK-COMMAND... Link object files or libraries together to form another library, or to create an executable program. LINK-COMMAND is a command using the C compiler that you would use to create a program from several object files. The following components of LINK-COMMAND are treated specially: -all-static do not do any dynamic linking at all -avoid-version do not add a version suffix if possible -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) -export-symbols SYMFILE try to export only the symbols listed in SYMFILE -export-symbols-regex REGEX try to export only the symbols matching REGEX -LLIBDIR search LIBDIR for required installed libraries -lNAME OUTPUT-FILE requires the installed library libNAME -module build a library that can dlopened -no-undefined declare that a library does not refer to external symbols -o OUTPUT-FILE create OUTPUT-FILE from the specified objects -release RELEASE specify package release information -rpath LIBDIR the created library will eventually be installed in LIBDIR -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries -static do not do any dynamic linking of libtool libraries -version-info CURRENT[:REVISION[:AGE]] specify library version info [each variable defaults to 0] All other options (arguments beginning with \`-') are ignored. Every other argument is treated as a filename. Files ending in \`.la' are treated as uninstalled libtool libraries, other files are standard or library object files. If the OUTPUT-FILE ends in \`.la', then a libtool library is created, only library objects (\`.lo' files) may be specified, and \`-rpath' is required, except when creating a convenience library. If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created using \`ar' and \`ranlib', or on Windows using \`lib'. If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file is created, otherwise an executable program is created." ;; uninstall) $echo \ "Usage: $modename [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... Remove libraries from an installation directory. RM is the name of the program to use to delete files associated with each FILE (typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed to RM. If FILE is a libtool library, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; *) $echo "$modename: invalid operation mode \`$mode'" 1>&2 $echo "$help" 1>&2 exit 1 ;; esac echo $echo "Try \`$modename --help' for more information about other modes." exit 0 # Local Variables: # mode:shell-script # sh-indentation:2 # End: fweelin-0.6/aclocal.m40000644000175000017500000007615011071520726013320 0ustar mercmerc# generated automatically by aclocal 1.10 -*- Autoconf -*- # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, # 2005, 2006 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. m4_if(m4_PACKAGE_VERSION, [2.61],, [m4_fatal([this file was generated for autoconf 2.61. You have another version of autoconf. If you want to use that, you should regenerate the build system entirely.], [63])]) # Copyright (C) 2002, 2003, 2005, 2006 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_AUTOMAKE_VERSION(VERSION) # ---------------------------- # Automake X.Y traces this macro to ensure aclocal.m4 has been # generated from the m4 files accompanying Automake X.Y. # (This private macro should not be called outside this file.) AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version='1.10' dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl require some minimum version. Point them to the right macro. m4_if([$1], [1.10], [], [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl ]) # _AM_AUTOCONF_VERSION(VERSION) # ----------------------------- # aclocal traces this macro to find the Autoconf version. # This is a private macro too. Using m4_define simplifies # the logic in aclocal, which can simply ignore this definition. m4_define([_AM_AUTOCONF_VERSION], []) # AM_SET_CURRENT_AUTOMAKE_VERSION # ------------------------------- # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # This function is AC_REQUIREd by AC_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], [AM_AUTOMAKE_VERSION([1.10])dnl _AM_AUTOCONF_VERSION(m4_PACKAGE_VERSION)]) # AM_AUX_DIR_EXPAND -*- Autoconf -*- # Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets # $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to # `$srcdir', `$srcdir/..', or `$srcdir/../..'. # # Of course, Automake must honor this variable whenever it calls a # tool from the auxiliary directory. The problem is that $srcdir (and # therefore $ac_aux_dir as well) can be either absolute or relative, # depending on how configure is run. This is pretty annoying, since # it makes $ac_aux_dir quite unusable in subdirectories: in the top # source directory, any form will work fine, but in subdirectories a # relative path needs to be adjusted first. # # $ac_aux_dir/missing # fails when called from a subdirectory if $ac_aux_dir is relative # $top_srcdir/$ac_aux_dir/missing # fails if $ac_aux_dir is absolute, # fails when called from a subdirectory in a VPATH build with # a relative $ac_aux_dir # # The reason of the latter failure is that $top_srcdir and $ac_aux_dir # are both prefixed by $srcdir. In an in-source build this is usually # harmless because $srcdir is `.', but things will broke when you # start a VPATH build or use an absolute $srcdir. # # So we could use something similar to $top_srcdir/$ac_aux_dir/missing, # iff we strip the leading $srcdir from $ac_aux_dir. That would be: # am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` # and then we would define $MISSING as # MISSING="\${SHELL} $am_aux_dir/missing" # This will work as long as MISSING is not called from configure, because # unfortunately $(top_srcdir) has no meaning in configure. # However there are other variables, like CC, which are often used in # configure, and could therefore not use this "fixed" $ac_aux_dir. # # Another solution, used here, is to always expand $ac_aux_dir to an # absolute PATH. The drawback is that using absolute paths prevent a # configured tree to be moved without reconfiguration. AC_DEFUN([AM_AUX_DIR_EXPAND], [dnl Rely on autoconf to set up CDPATH properly. AC_PREREQ([2.50])dnl # expand $ac_aux_dir to an absolute path am_aux_dir=`cd $ac_aux_dir && pwd` ]) # AM_CONDITIONAL -*- Autoconf -*- # Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 8 # AM_CONDITIONAL(NAME, SHELL-CONDITION) # ------------------------------------- # Define a conditional. AC_DEFUN([AM_CONDITIONAL], [AC_PREREQ(2.52)dnl ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl AC_SUBST([$1_TRUE])dnl AC_SUBST([$1_FALSE])dnl _AM_SUBST_NOTMAKE([$1_TRUE])dnl _AM_SUBST_NOTMAKE([$1_FALSE])dnl if $2; then $1_TRUE= $1_FALSE='#' else $1_TRUE='#' $1_FALSE= fi AC_CONFIG_COMMANDS_PRE( [if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then AC_MSG_ERROR([[conditional "$1" was never defined. Usually this means the macro was only invoked conditionally.]]) fi])]) # Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 9 # There are a few dirty hacks below to avoid letting `AC_PROG_CC' be # written in clear, in which case automake, when reading aclocal.m4, # will think it sees a *use*, and therefore will trigger all it's # C support machinery. Also note that it means that autoscan, seeing # CC etc. in the Makefile, will ask for an AC_PROG_CC use... # _AM_DEPENDENCIES(NAME) # ---------------------- # See how the compiler implements dependency checking. # NAME is "CC", "CXX", "GCJ", or "OBJC". # We try a few techniques and use that to set a single cache variable. # # We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was # modified to invoke _AM_DEPENDENCIES(CC); we would have a circular # dependency, and given that the user is not expected to run this macro, # just rely on AC_PROG_CC. AC_DEFUN([_AM_DEPENDENCIES], [AC_REQUIRE([AM_SET_DEPDIR])dnl AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl AC_REQUIRE([AM_MAKE_INCLUDE])dnl AC_REQUIRE([AM_DEP_TRACK])dnl ifelse([$1], CC, [depcc="$CC" am_compiler_list=], [$1], CXX, [depcc="$CXX" am_compiler_list=], [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'], [$1], UPC, [depcc="$UPC" am_compiler_list=], [$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'], [depcc="$$1" am_compiler_list=]) AC_CACHE_CHECK([dependency style of $depcc], [am_cv_$1_dependencies_compiler_type], [if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named `D' -- because `-MD' means `put the output # in D'. mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_$1_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` fi for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with # Solaris 8's {/usr,}/bin/sh. touch sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf case $depmode in nosideeffect) # after this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; none) break ;; esac # We check with `-c' and `-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle `-M -o', and we need to detect this. if depmode=$depmode \ source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_$1_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_$1_dependencies_compiler_type=none fi ]) AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) AM_CONDITIONAL([am__fastdep$1], [ test "x$enable_dependency_tracking" != xno \ && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) ]) # AM_SET_DEPDIR # ------------- # Choose a directory name for dependency files. # This macro is AC_REQUIREd in _AM_DEPENDENCIES AC_DEFUN([AM_SET_DEPDIR], [AC_REQUIRE([AM_SET_LEADING_DOT])dnl AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl ]) # AM_DEP_TRACK # ------------ AC_DEFUN([AM_DEP_TRACK], [AC_ARG_ENABLE(dependency-tracking, [ --disable-dependency-tracking speeds up one-time build --enable-dependency-tracking do not reject slow dependency extractors]) if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' fi AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) AC_SUBST([AMDEPBACKSLASH])dnl _AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl ]) # Generate code to set up dependency tracking. -*- Autoconf -*- # Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. #serial 3 # _AM_OUTPUT_DEPENDENCY_COMMANDS # ------------------------------ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], [for mf in $CONFIG_FILES; do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named `Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # Grep'ing the whole file is not good either: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. if sed 10q "$mf" | grep '^#.*generated by automake' > /dev/null 2>&1; then dirpart=`AS_DIRNAME("$mf")` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running `make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # When using ansi2knr, U may be empty or an underscore; expand it U=`sed -n 's/^U = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`AS_DIRNAME(["$file"])` AS_MKDIR_P([$dirpart/$fdir]) # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done ])# _AM_OUTPUT_DEPENDENCY_COMMANDS # AM_OUTPUT_DEPENDENCY_COMMANDS # ----------------------------- # This macro should only be invoked once -- use via AC_REQUIRE. # # This code is only required when automatic dependency tracking # is enabled. FIXME. This creates each `.P' file that we will # need in order to bootstrap the dependency handling code. AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], [AC_CONFIG_COMMANDS([depfiles], [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) ]) # Do all the work for Automake. -*- Autoconf -*- # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, # 2005, 2006 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 12 # This macro actually does too much. Some checks are only needed if # your package does certain things. But this isn't really a big deal. # AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) # AM_INIT_AUTOMAKE([OPTIONS]) # ----------------------------------------------- # The call with PACKAGE and VERSION arguments is the old style # call (pre autoconf-2.50), which is being phased out. PACKAGE # and VERSION should now be passed to AC_INIT and removed from # the call to AM_INIT_AUTOMAKE. # We support both call styles for the transition. After # the next Automake release, Autoconf can make the AC_INIT # arguments mandatory, and then we can depend on a new Autoconf # release and drop the old call support. AC_DEFUN([AM_INIT_AUTOMAKE], [AC_PREREQ([2.60])dnl dnl Autoconf wants to disallow AM_ names. We explicitly allow dnl the ones we care about. m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl AC_REQUIRE([AC_PROG_INSTALL])dnl if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl # test to see if srcdir already configured if test -f $srcdir/config.status; then AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi AC_SUBST([CYGPATH_W]) # Define the identity of the package. dnl Distinguish between old-style and new-style calls. m4_ifval([$2], [m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl AC_SUBST([PACKAGE], [$1])dnl AC_SUBST([VERSION], [$2])], [_AM_SET_OPTIONS([$1])dnl dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. m4_if(m4_ifdef([AC_PACKAGE_NAME], 1)m4_ifdef([AC_PACKAGE_VERSION], 1), 11,, [m4_fatal([AC_INIT should be called with package and version arguments])])dnl AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl _AM_IF_OPTION([no-define],, [AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl # Some tools Automake needs. AC_REQUIRE([AM_SANITY_CHECK])dnl AC_REQUIRE([AC_ARG_PROGRAM])dnl AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version}) AM_MISSING_PROG(AUTOCONF, autoconf) AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version}) AM_MISSING_PROG(AUTOHEADER, autoheader) AM_MISSING_PROG(MAKEINFO, makeinfo) AM_PROG_INSTALL_SH AM_PROG_INSTALL_STRIP AC_REQUIRE([AM_PROG_MKDIR_P])dnl # We need awk for the "check" target. The system "awk" is bad on # some platforms. AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([AC_PROG_MAKE_SET])dnl AC_REQUIRE([AM_SET_LEADING_DOT])dnl _AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], [_AM_PROG_TAR([v7])])]) _AM_IF_OPTION([no-dependencies],, [AC_PROVIDE_IFELSE([AC_PROG_CC], [_AM_DEPENDENCIES(CC)], [define([AC_PROG_CC], defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl AC_PROVIDE_IFELSE([AC_PROG_CXX], [_AM_DEPENDENCIES(CXX)], [define([AC_PROG_CXX], defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJC], [_AM_DEPENDENCIES(OBJC)], [define([AC_PROG_OBJC], defn([AC_PROG_OBJC])[_AM_DEPENDENCIES(OBJC)])])dnl ]) ]) # When config.status generates a header, we must update the stamp-h file. # This file resides in the same directory as the config header # that is generated. The stamp files are numbered to have different names. # Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the # loop where config.status creates the headers, so we can generate # our stamp files there. AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], [# Compute $1's index in $config_headers. _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $1 | $1:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $1" >`AS_DIRNAME([$1])`/stamp-h[]$_am_stamp_count]) # Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_SH # ------------------ # Define $install_sh. AC_DEFUN([AM_PROG_INSTALL_SH], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl install_sh=${install_sh-"\$(SHELL) $am_aux_dir/install-sh"} AC_SUBST(install_sh)]) # Copyright (C) 2003, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 2 # Check whether the underlying file-system supports filenames # with a leading dot. For instance MS-DOS doesn't. AC_DEFUN([AM_SET_LEADING_DOT], [rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null AC_SUBST([am__leading_dot])]) # Check to see how 'make' treats includes. -*- Autoconf -*- # Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 3 # AM_MAKE_INCLUDE() # ----------------- # Check to see how make treats includes. AC_DEFUN([AM_MAKE_INCLUDE], [am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo done .PHONY: am__doit END # If we don't find an include directive, just comment out the code. AC_MSG_CHECKING([for style of include used by $am_make]) am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # We grep out `Entering directory' and `Leaving directory' # messages which can occur if `w' ends up in MAKEFLAGS. # In particular we don't look at `^make:' because GNU make might # be invoked under some other name (usually "gmake"), in which # case it prints its new name instead of `make'. if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then am__include=include am__quote= _am_result=GNU fi # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then am__include=.include am__quote="\"" _am_result=BSD fi fi AC_SUBST([am__include]) AC_SUBST([am__quote]) AC_MSG_RESULT([$_am_result]) rm -f confinc confmf ]) # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- # Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 5 # AM_MISSING_PROG(NAME, PROGRAM) # ------------------------------ AC_DEFUN([AM_MISSING_PROG], [AC_REQUIRE([AM_MISSING_HAS_RUN]) $1=${$1-"${am_missing_run}$2"} AC_SUBST($1)]) # AM_MISSING_HAS_RUN # ------------------ # Define MISSING if not defined so far and test if it supports --run. # If it does, set am_missing_run to use it, otherwise, to nothing. AC_DEFUN([AM_MISSING_HAS_RUN], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([missing])dnl test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing" # Use eval to expand $SHELL if eval "$MISSING --run true"; then am_missing_run="$MISSING --run " else am_missing_run= AC_MSG_WARN([`missing' script is too old or missing]) fi ]) # Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_MKDIR_P # --------------- # Check for `mkdir -p'. AC_DEFUN([AM_PROG_MKDIR_P], [AC_PREREQ([2.60])dnl AC_REQUIRE([AC_PROG_MKDIR_P])dnl dnl Automake 1.8 to 1.9.6 used to define mkdir_p. We now use MKDIR_P, dnl while keeping a definition of mkdir_p for backward compatibility. dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile. dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of dnl Makefile.ins that do not define MKDIR_P, so we do our own dnl adjustment using top_builddir (which is defined more often than dnl MKDIR_P). AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl case $mkdir_p in [[\\/$]]* | ?:[[\\/]]*) ;; */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; esac ]) # Helper functions for option handling. -*- Autoconf -*- # Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 3 # _AM_MANGLE_OPTION(NAME) # ----------------------- AC_DEFUN([_AM_MANGLE_OPTION], [[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) # _AM_SET_OPTION(NAME) # ------------------------------ # Set option NAME. Presently that only means defining a flag for this option. AC_DEFUN([_AM_SET_OPTION], [m4_define(_AM_MANGLE_OPTION([$1]), 1)]) # _AM_SET_OPTIONS(OPTIONS) # ---------------------------------- # OPTIONS is a space-separated list of Automake options. AC_DEFUN([_AM_SET_OPTIONS], [AC_FOREACH([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) # _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) # ------------------------------------------- # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. AC_DEFUN([_AM_IF_OPTION], [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) # Check to make sure that the build environment is sane. -*- Autoconf -*- # Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 4 # AM_SANITY_CHECK # --------------- AC_DEFUN([AM_SANITY_CHECK], [AC_MSG_CHECKING([whether build environment is sane]) # Just in case sleep 1 echo timestamp > conftest.file # Do `set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null` if test "$[*]" = "X"; then # -L didn't work. set X `ls -t $srcdir/configure conftest.file` fi rm -f conftest.file if test "$[*]" != "X $srcdir/configure conftest.file" \ && test "$[*]" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken alias in your environment]) fi test "$[2]" = conftest.file ) then # Ok. : else AC_MSG_ERROR([newly created file is older than distributed files! Check your system clock]) fi AC_MSG_RESULT(yes)]) # Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_STRIP # --------------------- # One issue with vendor `install' (even GNU) is that you can't # specify the program used to strip binaries. This is especially # annoying in cross-compiling environments, where the build's strip # is unlikely to handle the host's binaries. # Fortunately install-sh will honor a STRIPPROG variable, so we # always use install-sh in `make install-strip', and initialize # STRIPPROG with the value of the STRIP variable (set by the user). AC_DEFUN([AM_PROG_INSTALL_STRIP], [AC_REQUIRE([AM_PROG_INSTALL_SH])dnl # Installed binaries are usually stripped using `strip' when the user # run `make install-strip'. However `strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the `STRIP' environment variable to overrule this program. dnl Don't test for $cross_compiling = yes, because it might be `maybe'. if test "$cross_compiling" != no; then AC_CHECK_TOOL([STRIP], [strip], :) fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) # Copyright (C) 2006 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_SUBST_NOTMAKE(VARIABLE) # --------------------------- # Prevent Automake from outputing VARIABLE = @VARIABLE@ in Makefile.in. # This macro is traced by Automake. AC_DEFUN([_AM_SUBST_NOTMAKE]) # Check how to create a tarball. -*- Autoconf -*- # Copyright (C) 2004, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 2 # _AM_PROG_TAR(FORMAT) # -------------------- # Check how to create a tarball in format FORMAT. # FORMAT should be one of `v7', `ustar', or `pax'. # # Substitute a variable $(am__tar) that is a command # writing to stdout a FORMAT-tarball containing the directory # $tardir. # tardir=directory && $(am__tar) > result.tar # # Substitute a variable $(am__untar) that extract such # a tarball read from stdin. # $(am__untar) < result.tar AC_DEFUN([_AM_PROG_TAR], [# Always define AMTAR for backward compatibility. AM_MISSING_PROG([AMTAR], [tar]) m4_if([$1], [v7], [am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'], [m4_case([$1], [ustar],, [pax],, [m4_fatal([Unknown tar format])]) AC_MSG_CHECKING([how to create a $1 tar archive]) # Loop over all known methods to create a tar archive until one works. _am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' _am_tools=${am_cv_prog_tar_$1-$_am_tools} # Do not fold the above two line into one, because Tru64 sh and # Solaris sh will not grok spaces in the rhs of `-'. for _am_tool in $_am_tools do case $_am_tool in gnutar) for _am_tar in tar gnutar gtar; do AM_RUN_LOG([$_am_tar --version]) && break done am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' am__untar="$_am_tar -xf -" ;; plaintar) # Must skip GNU tar: if it does not support --format= it doesn't create # ustar tarball either. (tar --version) >/dev/null 2>&1 && continue am__tar='tar chf - "$$tardir"' am__tar_='tar chf - "$tardir"' am__untar='tar xf -' ;; pax) am__tar='pax -L -x $1 -w "$$tardir"' am__tar_='pax -L -x $1 -w "$tardir"' am__untar='pax -r' ;; cpio) am__tar='find "$$tardir" -print | cpio -o -H $1 -L' am__tar_='find "$tardir" -print | cpio -o -H $1 -L' am__untar='cpio -i -H $1 -d' ;; none) am__tar=false am__tar_=false am__untar=false ;; esac # If the value was cached, stop now. We just wanted to have am__tar # and am__untar set. test -n "${am_cv_prog_tar_$1}" && break # tar/untar a dummy directory, and stop if the command works rm -rf conftest.dir mkdir conftest.dir echo GrepMe > conftest.dir/file AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) rm -rf conftest.dir if test -s conftest.tar; then AM_RUN_LOG([$am__untar /dev/null 2>&1 && break fi done rm -rf conftest.dir AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) AC_MSG_RESULT([$am_cv_prog_tar_$1])]) AC_SUBST([am__tar]) AC_SUBST([am__untar]) ]) # _AM_PROG_TAR fweelin-0.6/depcomp0000755000175000017500000003305210547030013013017 0ustar mercmerc#! /bin/sh # depcomp - compile a program generating dependencies as side-effects # Copyright 1999, 2000, 2003 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA # 02111-1307, USA. # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Alexandre Oliva . if test -z "$depmode" || test -z "$source" || test -z "$object"; then echo "depcomp: Variables source, object and depmode must be set" 1>&2 exit 1 fi # `libtool' can also be set to `yes' or `no'. if test -z "$depfile"; then base=`echo "$object" | sed -e 's,^.*/,,' -e 's,\.\([^.]*\)$,.P\1,'` dir=`echo "$object" | sed 's,/.*$,/,'` if test "$dir" = "$object"; then dir= fi # FIXME: should be _deps on DOS. depfile="$dir.deps/$base" fi tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} rm -f "$tmpdepfile" # Some modes work just like other modes, but use different flags. We # parameterize here, but still list the modes in the big case below, # to make depend.m4 easier to write. Note that we *cannot* use a case # here, because this file can only contain one case statement. if test "$depmode" = hp; then # HP compiler uses -M and no extra arg. gccflag=-M depmode=gcc fi if test "$depmode" = dashXmstdout; then # This is just like dashmstdout with a different argument. dashmflag=-xM depmode=dashmstdout fi case "$depmode" in gcc3) ## gcc 3 implements dependency tracking that does exactly what ## we want. Yay! Note: for some reason libtool 1.4 doesn't like ## it if -MD -MP comes after the -MF stuff. Hmm. "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi mv "$tmpdepfile" "$depfile" ;; gcc) ## There are various ways to get dependency output from gcc. Here's ## why we pick this rather obscure method: ## - Don't want to use -MD because we'd like the dependencies to end ## up in a subdir. Having to rename by hand is ugly. ## (We might end up doing this anyway to support other compilers.) ## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like ## -MM, not -M (despite what the docs say). ## - Using -M directly means running the compiler twice (even worse ## than renaming). if test -z "$gccflag"; then gccflag=-MD, fi "$@" -Wp,"$gccflag$tmpdepfile" stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ## The second -e expression handles DOS-style file names with drive letters. sed -e 's/^[^:]*: / /' \ -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" ## This next piece of magic avoids the `deleted header file' problem. ## The problem is that when a header file which appears in a .P file ## is deleted, the dependency causes make to die (because there is ## typically no way to rebuild the header). We avoid this by adding ## dummy dependencies for each header file. Too bad gcc doesn't do ## this for us directly. tr ' ' ' ' < "$tmpdepfile" | ## Some versions of gcc put a space before the `:'. On the theory ## that the space means something, we add a space to the output as ## well. ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; sgi) if test "$libtool" = yes; then "$@" "-Wp,-MDupdate,$tmpdepfile" else "$@" -MDupdate "$tmpdepfile" fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files echo "$object : \\" > "$depfile" # Clip off the initial element (the dependent). Don't try to be # clever and replace this with sed code, as IRIX sed won't handle # lines with more than a fixed number of characters (4096 in # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; # the IRIX cc adds comments like `#:fec' to the end of the # dependency line. tr ' ' ' ' < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ tr ' ' ' ' >> $depfile echo >> $depfile # The second pass generates a dummy entry for each header file. tr ' ' ' ' < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ >> $depfile else # The sourcefile does not contain any dependencies, so just # store a dummy comment line, to avoid errors with the Makefile # "include basename.Plo" scheme. echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; aix) # The C for AIX Compiler uses -M and outputs the dependencies # in a .u file. In older versions, this file always lives in the # current directory. Also, the AIX compiler puts `$object:' at the # start of each line; $object doesn't have directory information. # Version 6 uses the directory in both cases. stripped=`echo "$object" | sed 's/\(.*\)\..*$/\1/'` tmpdepfile="$stripped.u" if test "$libtool" = yes; then "$@" -Wc,-M else "$@" -M fi stat=$? if test -f "$tmpdepfile"; then : else stripped=`echo "$stripped" | sed 's,^.*/,,'` tmpdepfile="$stripped.u" fi if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi if test -f "$tmpdepfile"; then outname="$stripped.o" # Each line is of the form `foo.o: dependent.h'. # Do two passes, one to just change these to # `$object: dependent.h' and one to simply `dependent.h:'. sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile" sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile" else # The sourcefile does not contain any dependencies, so just # store a dummy comment line, to avoid errors with the Makefile # "include basename.Plo" scheme. echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; icc) # Intel's C compiler understands `-MD -MF file'. However on # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c # ICC 7.0 will fill foo.d with something like # foo.o: sub/foo.c # foo.o: sub/foo.h # which is wrong. We want: # sub/foo.o: sub/foo.c # sub/foo.o: sub/foo.h # sub/foo.c: # sub/foo.h: # ICC 7.1 will output # foo.o: sub/foo.c sub/foo.h # and will wrap long lines using \ : # foo.o: sub/foo.c ... \ # sub/foo.h ... \ # ... "$@" -MD -MF "$tmpdepfile" stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each line is of the form `foo.o: dependent.h', # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. # Do two passes, one to just change these to # `$object: dependent.h' and one to simply `dependent.h:'. sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this invocation # correctly. Breaking it into two sed invocations is a workaround. sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; tru64) # The Tru64 compiler uses -MD to generate dependencies as a side # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'. # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put # dependencies in `foo.d' instead, so we check for that too. # Subdirectories are respected. dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` test "x$dir" = "x$object" && dir= base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` if test "$libtool" = yes; then tmpdepfile1="$dir.libs/$base.lo.d" tmpdepfile2="$dir.libs/$base.d" "$@" -Wc,-MD else tmpdepfile1="$dir$base.o.d" tmpdepfile2="$dir$base.d" "$@" -MD fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile1" "$tmpdepfile2" exit $stat fi if test -f "$tmpdepfile1"; then tmpdepfile="$tmpdepfile1" else tmpdepfile="$tmpdepfile2" fi if test -f "$tmpdepfile"; then sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" # That's a tab and a space in the []. sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" else echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; #nosideeffect) # This comment above is used by automake to tell side-effect # dependency tracking mechanisms from slower ones. dashmstdout) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout, regardless of -o. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test $1 != '--mode=compile'; do shift done shift fi # Remove `-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done test -z "$dashmflag" && dashmflag=-M # Require at least two characters before searching for `:' # in the target name. This is to cope with DOS-style filenames: # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise. "$@" $dashmflag | sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" tr ' ' ' ' < "$tmpdepfile" | \ ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; dashXmstdout) # This case only exists to satisfy depend.m4. It is never actually # run, as this mode is specially recognized in the preamble. exit 1 ;; makedepend) "$@" || exit $? # Remove any Libtool call if test "$libtool" = yes; then while test $1 != '--mode=compile'; do shift done shift fi # X makedepend shift cleared=no for arg in "$@"; do case $cleared in no) set ""; shift cleared=yes ;; esac case "$arg" in -D*|-I*) set fnord "$@" "$arg"; shift ;; # Strip any option that makedepend may not understand. Remove # the object too, otherwise makedepend will parse it as a source file. -*|$object) ;; *) set fnord "$@" "$arg"; shift ;; esac done obj_suffix="`echo $object | sed 's/^.*\././'`" touch "$tmpdepfile" ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" sed '1,2d' "$tmpdepfile" | tr ' ' ' ' | \ ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" "$tmpdepfile".bak ;; cpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test $1 != '--mode=compile'; do shift done shift fi # Remove `-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done "$@" -E | sed -n '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | sed '$ s: \\$::' > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" cat < "$tmpdepfile" >> "$depfile" sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; msvisualcpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout, regardless of -o, # because we must use -o when running libtool. "$@" || exit $? IFS=" " for arg do case "$arg" in "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") set fnord "$@" shift shift ;; *) set fnord "$@" "$arg" shift shift ;; esac done "$@" -E | sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" echo " " >> "$depfile" . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile" rm -f "$tmpdepfile" ;; none) exec "$@" ;; *) echo "Unknown depmode $depmode" 1>&2 exit 1 ;; esac exit 0 fweelin-0.6/config.log0000644000175000017500000005722511071520755013434 0ustar mercmercThis file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by configure, which was generated by GNU Autoconf 2.61. Invocation command line was $ ./configure --no-create --no-recursion ## --------- ## ## Platform. ## ## --------- ## hostname = laptop uname -m = i686 uname -r = 2.6.22-14-rt uname -s = Linux uname -v = #1 SMP PREEMPT RT Tue Dec 18 10:01:34 UTC 2007 /usr/bin/uname -p = unknown /bin/uname -X = unknown /bin/arch = unknown /usr/bin/arch -k = unknown /usr/convex/getsysinfo = unknown /usr/bin/hostinfo = unknown /bin/machine = unknown /usr/bin/oslevel = unknown /bin/universe = unknown PATH: /usr/local/sbin PATH: /usr/local/bin PATH: /usr/sbin PATH: /usr/bin PATH: /sbin PATH: /bin PATH: /usr/games ## ----------- ## ## Core tests. ## ## ----------- ## configure:1791: checking for a BSD-compatible install configure:1847: result: /usr/bin/install -c configure:1858: checking whether build environment is sane configure:1901: result: yes configure:1929: checking for a thread-safe mkdir -p configure:1968: result: /bin/mkdir -p configure:1981: checking for gawk configure:2011: result: no configure:1981: checking for mawk configure:1997: found /usr/bin/mawk configure:2008: result: mawk configure:2019: checking whether make sets $(MAKE) configure:2040: result: yes configure:2306: checking for g++ configure:2322: found /usr/bin/g++ configure:2333: result: g++ configure:2364: checking for C++ compiler version configure:2371: g++ --version >&5 g++ (GCC) 4.1.3 20070929 (prerelease) (Ubuntu 4.1.2-16ubuntu2) Copyright (C) 2006 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. configure:2374: $? = 0 configure:2381: g++ -v >&5 Using built-in specs. Target: i486-linux-gnu Configured with: ../src/configure -v --enable-languages=c,c++,fortran,objc,obj-c++,treelang --prefix=/usr --enable-shared --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --enable-nls --with-gxx-include-dir=/usr/include/c++/4.1.3 --program-suffix=-4.1 --enable-__cxa_atexit --enable-clocale=gnu --enable-libstdcxx-debug --enable-mpfr --enable-checking=release i486-linux-gnu Thread model: posix gcc version 4.1.3 20070929 (prerelease) (Ubuntu 4.1.2-16ubuntu2) configure:2384: $? = 0 configure:2391: g++ -V >&5 g++: '-V' option must have argument configure:2394: $? = 1 configure:2417: checking for C++ compiler default output file name configure:2444: g++ conftest.cpp >&5 configure:2447: $? = 0 configure:2485: result: a.out configure:2502: checking whether the C++ compiler works configure:2512: ./a.out configure:2515: $? = 0 configure:2532: result: yes configure:2539: checking whether we are cross compiling configure:2541: result: no configure:2544: checking for suffix of executables configure:2551: g++ -o conftest conftest.cpp >&5 configure:2554: $? = 0 configure:2578: result: configure:2584: checking for suffix of object files configure:2610: g++ -c conftest.cpp >&5 configure:2613: $? = 0 configure:2636: result: o configure:2640: checking whether we are using the GNU C++ compiler configure:2669: g++ -c conftest.cpp >&5 configure:2675: $? = 0 configure:2692: result: yes configure:2697: checking whether g++ accepts -g configure:2727: g++ -c -g conftest.cpp >&5 configure:2733: $? = 0 configure:2832: result: yes configure:2866: checking for style of include used by make configure:2894: result: GNU configure:2919: checking dependency style of g++ configure:3010: result: gcc3 configure:3073: checking for gcc configure:3089: found /usr/bin/gcc configure:3100: result: gcc configure:3338: checking for C compiler version configure:3345: gcc --version >&5 gcc (GCC) 4.1.3 20070929 (prerelease) (Ubuntu 4.1.2-16ubuntu2) Copyright (C) 2006 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. configure:3348: $? = 0 configure:3355: gcc -v >&5 Using built-in specs. Target: i486-linux-gnu Configured with: ../src/configure -v --enable-languages=c,c++,fortran,objc,obj-c++,treelang --prefix=/usr --enable-shared --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --enable-nls --with-gxx-include-dir=/usr/include/c++/4.1.3 --program-suffix=-4.1 --enable-__cxa_atexit --enable-clocale=gnu --enable-libstdcxx-debug --enable-mpfr --enable-checking=release i486-linux-gnu Thread model: posix gcc version 4.1.3 20070929 (prerelease) (Ubuntu 4.1.2-16ubuntu2) configure:3358: $? = 0 configure:3365: gcc -V >&5 gcc: '-V' option must have argument configure:3368: $? = 1 configure:3371: checking whether we are using the GNU C compiler configure:3400: gcc -c conftest.c >&5 configure:3406: $? = 0 configure:3423: result: yes configure:3428: checking whether gcc accepts -g configure:3458: gcc -c -g conftest.c >&5 configure:3464: $? = 0 configure:3563: result: yes configure:3580: checking for gcc option to accept ISO C89 configure:3654: gcc -c -g -O2 conftest.c >&5 configure:3660: $? = 0 configure:3683: result: none needed configure:3703: checking dependency style of gcc configure:3794: result: gcc3 configure:3817: checking how to run the C preprocessor configure:3857: gcc -E conftest.c configure:3863: $? = 0 configure:3894: gcc -E conftest.c conftest.c:10:28: error: ac_nonexistent.h: No such file or directory configure:3900: $? = 1 configure: failed program was: | /* confdefs.h. */ | #define PACKAGE_NAME "" | #define PACKAGE_TARNAME "" | #define PACKAGE_VERSION "" | #define PACKAGE_STRING "" | #define PACKAGE_BUGREPORT "" | #define PACKAGE "fweelin" | #define VERSION "0.6" | /* end confdefs.h. */ | #include configure:3933: result: gcc -E configure:3962: gcc -E conftest.c configure:3968: $? = 0 configure:3999: gcc -E conftest.c conftest.c:10:28: error: ac_nonexistent.h: No such file or directory configure:4005: $? = 1 configure: failed program was: | /* confdefs.h. */ | #define PACKAGE_NAME "" | #define PACKAGE_TARNAME "" | #define PACKAGE_VERSION "" | #define PACKAGE_STRING "" | #define PACKAGE_BUGREPORT "" | #define PACKAGE "fweelin" | #define VERSION "0.6" | /* end confdefs.h. */ | #include configure:4043: checking for X configure:4213: gcc -o conftest -g -O2 conftest.c -lX11 >&5 configure:4219: $? = 0 configure:4278: result: libraries , headers configure:4439: gcc -o conftest -g -O2 conftest.c -lX11 >&5 configure:4445: $? = 0 configure:4602: checking for gethostbyname configure:4658: gcc -o conftest -g -O2 conftest.c >&5 configure:4664: $? = 0 configure:4681: result: yes configure:4826: checking for connect configure:4882: gcc -o conftest -g -O2 conftest.c >&5 configure:4888: $? = 0 configure:4905: result: yes configure:4977: checking for remove configure:5033: gcc -o conftest -g -O2 conftest.c >&5 configure:5039: $? = 0 configure:5056: result: yes configure:5128: checking for shmat configure:5184: gcc -o conftest -g -O2 conftest.c >&5 configure:5190: $? = 0 configure:5207: result: yes configure:5288: checking for IceConnectionNumber in -lICE configure:5323: gcc -o conftest -g -O2 conftest.c -lICE >&5 /usr/bin/ld: cannot find -lICE collect2: ld returned 1 exit status configure:5329: $? = 1 configure: failed program was: | /* confdefs.h. */ | #define PACKAGE_NAME "" | #define PACKAGE_TARNAME "" | #define PACKAGE_VERSION "" | #define PACKAGE_STRING "" | #define PACKAGE_BUGREPORT "" | #define PACKAGE "fweelin" | #define VERSION "0.6" | /* end confdefs.h. */ | | /* Override any GCC internal prototype to avoid an error. | Use char because int might match the return type of a GCC | builtin and then its argument prototype would still apply. */ | #ifdef __cplusplus | extern "C" | #endif | char IceConnectionNumber (); | int | main () | { | return IceConnectionNumber (); | ; | return 0; | } configure:5347: result: no configure:5365: checking for main in -lgnutls-openssl configure:5394: gcc -o conftest -g -O2 conftest.c -lgnutls-openssl >&5 configure:5400: $? = 0 configure:5418: result: yes configure:5434: checking for main in -ldl configure:5463: gcc -o conftest -g -O2 conftest.c -ldl -lgnutls-openssl >&5 configure:5469: $? = 0 configure:5487: result: yes configure:5503: checking for FT_Init_FreeType in -lfreetype configure:5538: gcc -o conftest -g -O2 conftest.c -lfreetype -ldl -lgnutls-openssl >&5 configure:5544: $? = 0 configure:5562: result: yes configure:5582: checking for main in -lSDL_gfx configure:5611: gcc -o conftest -g -O2 conftest.c -lSDL_gfx -lfreetype -ldl -lgnutls-openssl >&5 configure:5617: $? = 0 configure:5635: result: yes configure:5652: checking for filledPieRGBA configure:5708: gcc -o conftest -g -O2 conftest.c -lSDL_gfx -lfreetype -ldl -lgnutls-openssl >&5 configure:5714: $? = 0 configure:5731: result: yes configure:5742: checking for main in -lSDL_ttf configure:5771: gcc -o conftest -g -O2 conftest.c -lSDL_ttf -lSDL_gfx -lfreetype -ldl -lgnutls-openssl >&5 configure:5777: $? = 0 configure:5795: result: yes configure:5814: checking for main in -lxml2 configure:5843: gcc -o conftest -g -O2 conftest.c -lxml2 -lSDL_ttf -lSDL_gfx -lfreetype -ldl -lgnutls-openssl >&5 configure:5849: $? = 0 configure:5867: result: yes configure:5886: checking for sqrt in -lm configure:5921: gcc -o conftest -g -O2 conftest.c -lm -lxml2 -lSDL_ttf -lSDL_gfx -lfreetype -ldl -lgnutls-openssl >&5 conftest.c:24: warning: conflicting types for built-in function 'sqrt' configure:5927: $? = 0 configure:5945: result: yes configure:5961: checking for pthread_self in -lpthread configure:5996: gcc -o conftest -g -O2 conftest.c -lpthread -lm -lxml2 -lSDL_ttf -lSDL_gfx -lfreetype -ldl -lgnutls-openssl >&5 configure:6002: $? = 0 configure:6020: result: yes configure:6037: checking for main in -lasound configure:6066: gcc -o conftest -g -O2 conftest.c -lasound -lpthread -lm -lxml2 -lSDL_ttf -lSDL_gfx -lfreetype -ldl -lgnutls-openssl >&5 configure:6072: $? = 0 configure:6090: result: yes configure:6109: checking for jack_client_new in -ljack configure:6144: gcc -o conftest -g -O2 conftest.c -ljack -lasound -lpthread -lm -lxml2 -lSDL_ttf -lSDL_gfx -lfreetype -ldl -lgnutls-openssl >&5 configure:6150: $? = 0 configure:6168: result: yes configure:6187: checking for main in -lfluidsynth configure:6216: gcc -o conftest -g -O2 conftest.c -lfluidsynth -ljack -lasound -lpthread -lm -lxml2 -lSDL_ttf -lSDL_gfx -lfreetype -ldl -lgnutls-openssl >&5 configure:6222: $? = 0 configure:6240: result: yes configure:6289: checking for main in -lvorbis configure:6318: gcc -o conftest -g -O2 conftest.c -lvorbis -ljack -lasound -lpthread -lm -lxml2 -lSDL_ttf -lSDL_gfx -lfreetype -ldl -lgnutls-openssl -lfluidsynth >&5 configure:6324: $? = 0 configure:6342: result: yes configure:6360: checking for main in -lvorbisfile configure:6389: gcc -o conftest -g -O2 conftest.c -lvorbisfile -lvorbis -ljack -lasound -lpthread -lm -lxml2 -lSDL_ttf -lSDL_gfx -lfreetype -ldl -lgnutls-openssl -lfluidsynth >&5 configure:6395: $? = 0 configure:6413: result: yes configure:6431: checking for main in -lvorbisenc configure:6460: gcc -o conftest -g -O2 conftest.c -lvorbisenc -lvorbisfile -lvorbis -ljack -lasound -lpthread -lm -lxml2 -lSDL_ttf -lSDL_gfx -lfreetype -ldl -lgnutls-openssl -lfluidsynth >&5 configure:6466: $? = 0 configure:6484: result: yes configure:6503: checking for main in -lsndfile configure:6532: gcc -o conftest -g -O2 conftest.c -lsndfile -lvorbisenc -lvorbisfile -lvorbis -ljack -lasound -lpthread -lm -lxml2 -lSDL_ttf -lSDL_gfx -lfreetype -ldl -lgnutls-openssl -lfluidsynth >&5 configure:6538: $? = 0 configure:6556: result: yes configure:6579: checking for X configure:6814: result: libraries , headers configure:6818: checking for grep that handles long lines and -e configure:6892: result: /bin/grep configure:6897: checking for egrep configure:6975: result: /bin/grep -E configure:6980: checking for ANSI C header files configure:7010: gcc -c -g -O2 conftest.c >&5 configure:7016: $? = 0 configure:7115: gcc -o conftest -g -O2 conftest.c -L/usr/X11R6/lib -lX11 -lsndfile -lvorbisenc -lvorbisfile -lvorbis -ljack -lasound -lpthread -lm -lxml2 -lSDL_ttf -lSDL_gfx -lfreetype -ldl -lgnutls-openssl -lfluidsynth >&5 configure:7118: $? = 0 configure:7124: ./conftest configure:7127: $? = 0 configure:7144: result: yes configure:7168: checking for sys/types.h configure:7189: gcc -c -g -O2 conftest.c >&5 configure:7195: $? = 0 configure:7211: result: yes configure:7168: checking for sys/stat.h configure:7189: gcc -c -g -O2 conftest.c >&5 configure:7195: $? = 0 configure:7211: result: yes configure:7168: checking for stdlib.h configure:7189: gcc -c -g -O2 conftest.c >&5 configure:7195: $? = 0 configure:7211: result: yes configure:7168: checking for string.h configure:7189: gcc -c -g -O2 conftest.c >&5 configure:7195: $? = 0 configure:7211: result: yes configure:7168: checking for memory.h configure:7189: gcc -c -g -O2 conftest.c >&5 configure:7195: $? = 0 configure:7211: result: yes configure:7168: checking for strings.h configure:7189: gcc -c -g -O2 conftest.c >&5 configure:7195: $? = 0 configure:7211: result: yes configure:7168: checking for inttypes.h configure:7189: gcc -c -g -O2 conftest.c >&5 configure:7195: $? = 0 configure:7211: result: yes configure:7168: checking for stdint.h configure:7189: gcc -c -g -O2 conftest.c >&5 configure:7195: $? = 0 configure:7211: result: yes configure:7168: checking for unistd.h configure:7189: gcc -c -g -O2 conftest.c >&5 configure:7195: $? = 0 configure:7211: result: yes configure:7242: checking errno.h usability configure:7259: gcc -c -g -O2 conftest.c >&5 configure:7265: $? = 0 configure:7279: result: yes configure:7283: checking errno.h presence configure:7298: gcc -E conftest.c configure:7304: $? = 0 configure:7318: result: yes configure:7346: checking for errno.h configure:7354: result: yes configure:7232: checking for stdlib.h configure:7238: result: yes configure:7232: checking for string.h configure:7238: result: yes configure:7242: checking sys/time.h usability configure:7259: gcc -c -g -O2 conftest.c >&5 configure:7265: $? = 0 configure:7279: result: yes configure:7283: checking sys/time.h presence configure:7298: gcc -E conftest.c configure:7304: $? = 0 configure:7318: result: yes configure:7346: checking for sys/time.h configure:7354: result: yes configure:7232: checking for unistd.h configure:7238: result: yes configure:7369: checking for an ANSI C-conforming const configure:7444: gcc -c -g -O2 conftest.c >&5 configure:7450: $? = 0 configure:7465: result: yes configure:7475: checking whether time.h and sys/time.h may both be included configure:7505: gcc -c -g -O2 conftest.c >&5 configure:7511: $? = 0 configure:7526: result: yes configure:7546: checking for floor configure:7602: gcc -o conftest -g -O2 conftest.c -L/usr/X11R6/lib -lX11 -lsndfile -lvorbisenc -lvorbisfile -lvorbis -ljack -lasound -lpthread -lm -lxml2 -lSDL_ttf -lSDL_gfx -lfreetype -ldl -lgnutls-openssl -lfluidsynth >&5 conftest.c:65: warning: conflicting types for built-in function 'floor' configure:7608: $? = 0 configure:7626: result: yes configure:7546: checking for gettimeofday configure:7602: gcc -o conftest -g -O2 conftest.c -L/usr/X11R6/lib -lX11 -lsndfile -lvorbisenc -lvorbisfile -lvorbis -ljack -lasound -lpthread -lm -lxml2 -lSDL_ttf -lSDL_gfx -lfreetype -ldl -lgnutls-openssl -lfluidsynth >&5 configure:7608: $? = 0 configure:7626: result: yes configure:7546: checking for memset configure:7602: gcc -o conftest -g -O2 conftest.c -L/usr/X11R6/lib -lX11 -lsndfile -lvorbisenc -lvorbisfile -lvorbis -ljack -lasound -lpthread -lm -lxml2 -lSDL_ttf -lSDL_gfx -lfreetype -ldl -lgnutls-openssl -lfluidsynth >&5 conftest.c:67: warning: conflicting types for built-in function 'memset' configure:7608: $? = 0 configure:7626: result: yes configure:7546: checking for pow configure:7602: gcc -o conftest -g -O2 conftest.c -L/usr/X11R6/lib -lX11 -lsndfile -lvorbisenc -lvorbisfile -lvorbis -ljack -lasound -lpthread -lm -lxml2 -lSDL_ttf -lSDL_gfx -lfreetype -ldl -lgnutls-openssl -lfluidsynth >&5 conftest.c:68: warning: conflicting types for built-in function 'pow' configure:7608: $? = 0 configure:7626: result: yes configure:7546: checking for sqrt configure:7602: gcc -o conftest -g -O2 conftest.c -L/usr/X11R6/lib -lX11 -lsndfile -lvorbisenc -lvorbisfile -lvorbis -ljack -lasound -lpthread -lm -lxml2 -lSDL_ttf -lSDL_gfx -lfreetype -ldl -lgnutls-openssl -lfluidsynth >&5 conftest.c:69: warning: conflicting types for built-in function 'sqrt' configure:7608: $? = 0 configure:7626: result: yes configure:7790: creating ./config.status ## ---------------- ## ## Cache variables. ## ## ---------------- ## ac_cv_c_compiler_gnu=yes ac_cv_c_const=yes ac_cv_cxx_compiler_gnu=yes ac_cv_env_CCC_set= ac_cv_env_CCC_value= ac_cv_env_CC_set= ac_cv_env_CC_value= ac_cv_env_CFLAGS_set= ac_cv_env_CFLAGS_value= ac_cv_env_CPPFLAGS_set= ac_cv_env_CPPFLAGS_value= ac_cv_env_CPP_set= ac_cv_env_CPP_value= ac_cv_env_CXXFLAGS_set= ac_cv_env_CXXFLAGS_value= ac_cv_env_CXX_set= ac_cv_env_CXX_value= ac_cv_env_LDFLAGS_set= ac_cv_env_LDFLAGS_value= ac_cv_env_LIBS_set= ac_cv_env_LIBS_value= ac_cv_env_XMKMF_set= ac_cv_env_XMKMF_value= ac_cv_env_build_alias_set= ac_cv_env_build_alias_value= ac_cv_env_host_alias_set= ac_cv_env_host_alias_value= ac_cv_env_target_alias_set= ac_cv_env_target_alias_value= ac_cv_func_connect=yes ac_cv_func_filledPieRGBA=yes ac_cv_func_floor=yes ac_cv_func_gethostbyname=yes ac_cv_func_gettimeofday=yes ac_cv_func_memset=yes ac_cv_func_pow=yes ac_cv_func_remove=yes ac_cv_func_shmat=yes ac_cv_func_sqrt=yes ac_cv_have_x='have_x=yes ac_x_includes='\'''\'' ac_x_libraries='\'''\''' ac_cv_header_errno_h=yes ac_cv_header_inttypes_h=yes ac_cv_header_memory_h=yes ac_cv_header_stdc=yes ac_cv_header_stdint_h=yes ac_cv_header_stdlib_h=yes ac_cv_header_string_h=yes ac_cv_header_strings_h=yes ac_cv_header_sys_stat_h=yes ac_cv_header_sys_time_h=yes ac_cv_header_sys_types_h=yes ac_cv_header_time=yes ac_cv_header_unistd_h=yes ac_cv_lib_ICE_IceConnectionNumber=no ac_cv_lib_SDL_gfx_main=yes ac_cv_lib_SDL_ttf_main=yes ac_cv_lib_asound_main=yes ac_cv_lib_dl_main=yes ac_cv_lib_fluidsynth_main=yes ac_cv_lib_freetype_FT_Init_FreeType=yes ac_cv_lib_gnutls_openssl_main=yes ac_cv_lib_jack_jack_client_new=yes ac_cv_lib_m_sqrt=yes ac_cv_lib_pthread_pthread_self=yes ac_cv_lib_sndfile_main=yes ac_cv_lib_vorbis_main=yes ac_cv_lib_vorbisenc_main=yes ac_cv_lib_vorbisfile_main=yes ac_cv_lib_xml2_main=yes ac_cv_objext=o ac_cv_path_EGREP='/bin/grep -E' ac_cv_path_GREP=/bin/grep ac_cv_path_install='/usr/bin/install -c' ac_cv_path_mkdir=/bin/mkdir ac_cv_prog_AWK=mawk ac_cv_prog_CPP='gcc -E' ac_cv_prog_ac_ct_CC=gcc ac_cv_prog_ac_ct_CXX=g++ ac_cv_prog_cc_c89= ac_cv_prog_cc_g=yes ac_cv_prog_cxx_g=yes ac_cv_prog_make_make_set=yes am_cv_CC_dependencies_compiler_type=gcc3 am_cv_CXX_dependencies_compiler_type=gcc3 ## ----------------- ## ## Output variables. ## ## ----------------- ## ACLOCAL='${SHELL} /home/merc/audio/freewheeling/missing --run aclocal-1.10' AMDEPBACKSLASH='\' AMDEP_FALSE='#' AMDEP_TRUE='' AMTAR='${SHELL} /home/merc/audio/freewheeling/missing --run tar' AUTOCONF='${SHELL} /home/merc/audio/freewheeling/missing --run autoconf' AUTOHEADER='${SHELL} /home/merc/audio/freewheeling/missing --run autoheader' AUTOMAKE='${SHELL} /home/merc/audio/freewheeling/missing --run automake-1.10' AWK='mawk' CC='gcc' CCDEPMODE='depmode=gcc3' CFLAGS='-g -O2 ' CPP='gcc -E' CPPFLAGS='' CXX='g++' CXXDEPMODE='depmode=gcc3' CXXFLAGS='-g -O2' CYGPATH_W='echo' DEFS='-DPACKAGE_NAME=\"\" -DPACKAGE_TARNAME=\"\" -DPACKAGE_VERSION=\"\" -DPACKAGE_STRING=\"\" -DPACKAGE_BUGREPORT=\"\" -DPACKAGE=\"fweelin\" -DVERSION=\"0.6\" -DHAVE_LIBGNUTLS_OPENSSL=1 -DHAVE_LIBDL=1 -DHAVE_LIBFREETYPE=1 -DHAVE_LIBSDL_GFX=1 -DCAPITAL_FILLED_PIE=1 -DHAVE_LIBSDL_TTF=1 -DHAVE_LIBXML2=1 -DHAVE_LIBM=1 -DHAVE_LIBPTHREAD=1 -DHAVE_LIBASOUND=1 -DHAVE_LIBJACK=1 -DUSE_FLUIDSYNTH=1 -DHAVE_LIBVORBIS=1 -DHAVE_LIBVORBISFILE=1 -DHAVE_LIBVORBISENC=1 -DHAVE_LIBSNDFILE=1 -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DHAVE_ERRNO_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_SYS_TIME_H=1 -DHAVE_UNISTD_H=1 -DTIME_WITH_SYS_TIME=1 -DHAVE_FLOOR=1 -DHAVE_GETTIMEOFDAY=1 -DHAVE_MEMSET=1 -DHAVE_POW=1 -DHAVE_SQRT=1' DEPDIR='.deps' ECHO_C='' ECHO_N='-n' ECHO_T='' EGREP='/bin/grep -E' EXEEXT='' GREP='/bin/grep' INSTALL_DATA='${INSTALL} -m 644' INSTALL_PROGRAM='${INSTALL}' INSTALL_SCRIPT='${INSTALL}' INSTALL_STRIP_PROGRAM='$(install_sh) -c -s' LDFLAGS='' LIBOBJS='' LIBS=' -L/usr/X11R6/lib -lX11 -lsndfile -lvorbisenc -lvorbisfile -lvorbis -ljack -lasound -lpthread -lm -lxml2 -lSDL_ttf -lSDL_gfx -lfreetype -ldl -lgnutls-openssl -lfluidsynth ' LTLIBOBJS='' MAKEINFO='${SHELL} /home/merc/audio/freewheeling/missing --run makeinfo' OBJEXT='o' PACKAGE='fweelin' PACKAGE_BUGREPORT='' PACKAGE_NAME='' PACKAGE_STRING='' PACKAGE_TARNAME='' PACKAGE_VERSION='' PATH_SEPARATOR=':' SET_MAKE='' SHELL='/bin/bash' STRIP='' VERSION='0.6' XMKMF='' X_CFLAGS='' X_EXTRA_LIBS='' X_LIBS='' X_PRE_LIBS='' ac_ct_CC='gcc' ac_ct_CXX='g++' am__fastdepCC_FALSE='#' am__fastdepCC_TRUE='' am__fastdepCXX_FALSE='#' am__fastdepCXX_TRUE='' am__include='include' am__isrc='' am__leading_dot='.' am__quote='' am__tar='${AMTAR} chof - "$$tardir"' am__untar='${AMTAR} xf -' bindir='${exec_prefix}/bin' build_alias='' datadir='${datarootdir}' datarootdir='${prefix}/share' docdir='${datarootdir}/doc/${PACKAGE}' dvidir='${docdir}' exec_prefix='${prefix}' host_alias='' htmldir='${docdir}' includedir='${prefix}/include' infodir='${datarootdir}/info' install_sh='$(SHELL) /home/merc/audio/freewheeling/install-sh' libdir='${exec_prefix}/lib' libexecdir='${exec_prefix}/libexec' localedir='${datarootdir}/locale' localstatedir='${prefix}/var' mandir='${datarootdir}/man' mkdir_p='/bin/mkdir -p' oldincludedir='/usr/include' pdfdir='${docdir}' prefix='/usr/local' program_transform_name='s,x,x,' psdir='${docdir}' sbindir='${exec_prefix}/sbin' sharedstatedir='${prefix}/com' sysconfdir='${prefix}/etc' target_alias='' ## ----------- ## ## confdefs.h. ## ## ----------- ## #define PACKAGE_NAME "" #define PACKAGE_TARNAME "" #define PACKAGE_VERSION "" #define PACKAGE_STRING "" #define PACKAGE_BUGREPORT "" #define PACKAGE "fweelin" #define VERSION "0.6" #define HAVE_LIBGNUTLS_OPENSSL 1 #define HAVE_LIBDL 1 #define HAVE_LIBFREETYPE 1 #define HAVE_LIBSDL_GFX 1 #define CAPITAL_FILLED_PIE 1 #define HAVE_LIBSDL_TTF 1 #define HAVE_LIBXML2 1 #define HAVE_LIBM 1 #define HAVE_LIBPTHREAD 1 #define HAVE_LIBASOUND 1 #define HAVE_LIBJACK 1 #define USE_FLUIDSYNTH 1 #define HAVE_LIBVORBIS 1 #define HAVE_LIBVORBISFILE 1 #define HAVE_LIBVORBISENC 1 #define HAVE_LIBSNDFILE 1 #define STDC_HEADERS 1 #define HAVE_SYS_TYPES_H 1 #define HAVE_SYS_STAT_H 1 #define HAVE_STDLIB_H 1 #define HAVE_STRING_H 1 #define HAVE_MEMORY_H 1 #define HAVE_STRINGS_H 1 #define HAVE_INTTYPES_H 1 #define HAVE_STDINT_H 1 #define HAVE_UNISTD_H 1 #define HAVE_ERRNO_H 1 #define HAVE_STDLIB_H 1 #define HAVE_STRING_H 1 #define HAVE_SYS_TIME_H 1 #define HAVE_UNISTD_H 1 #define TIME_WITH_SYS_TIME 1 #define HAVE_FLOOR 1 #define HAVE_GETTIMEOFDAY 1 #define HAVE_MEMSET 1 #define HAVE_POW 1 #define HAVE_SQRT 1 configure: exit 0 ## ---------------------- ## ## Running config.status. ## ## ---------------------- ## This file was extended by config.status, which was generated by GNU Autoconf 2.61. Invocation command line was CONFIG_FILES = CONFIG_HEADERS = CONFIG_LINKS = CONFIG_COMMANDS = $ ./config.status on laptop config.status:631: creating Makefile config.status:631: creating src/Makefile config.status:631: creating data/Makefile config.status:822: executing depfiles commands fweelin-0.6/config.status0000755000175000017500000006562511071520754014203 0ustar mercmerc#! /bin/bash # Generated by configure. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=${CONFIG_SHELL-/bin/bash} ## --------------------- ## ## M4sh Initialization. ## ## --------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac fi # PATH needs CR # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then echo "#! /bin/sh" >conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi # Support unset when possible. if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then as_unset=unset else as_unset=false fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) as_nl=' ' IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. case $0 in *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 { (exit 1); exit 1; } fi # Work around bugs in pre-3.0 UWIN ksh. for as_var in ENV MAIL MAILPATH do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. for as_var in \ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ LC_TELEPHONE LC_TIME do if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then eval $as_var=C; export $as_var else ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var fi done # Required to use basename. if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi # Name of the executable. as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # CDPATH. $as_unset CDPATH as_lineno_1=$LINENO as_lineno_2=$LINENO test "x$as_lineno_1" != "x$as_lineno_2" && test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || { # Create $as_me.lineno as a copy of $as_myself, but with $LINENO # uniformly replaced by the line number. The first 'sed' inserts a # line-number line after each line using $LINENO; the second 'sed' # does the real work. The second script uses 'N' to pair each # line-number line with the line containing $LINENO, and appends # trailing '-' during substitution so that $LINENO is not a special # case at line end. # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the # scripts with optimization help from Paolo Bonzini. Blame Lee # E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 { (exit 1); exit 1; }; } # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in -n*) case `echo 'x\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. *) ECHO_C='\c';; esac;; *) ECHO_N='-n';; esac if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir fi echo >conf$$.file if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -p'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -p' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p=: else test -d ./-p && rmdir ./-p as_mkdir_p=false fi if test -x / >/dev/null 2>&1; then as_test_x='test -x' else if ls -dL / >/dev/null 2>&1; then as_ls_L_option=L else as_ls_L_option= fi as_test_x=' eval sh -c '\'' if test -d "$1"; then test -d "$1/."; else case $1 in -*)set "./$1";; esac; case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in ???[sx]*):;;*)false;;esac;fi '\'' sh ' fi as_executable_p=$as_test_x # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 # Save the log message, to keep $[0] and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by $as_me, which was generated by GNU Autoconf 2.61. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " # Files that config.status was made for. config_files=" Makefile src/Makefile data/Makefile" config_commands=" depfiles" ac_cs_usage="\ \`$as_me' instantiates files from templates according to the current configuration. Usage: $0 [OPTIONS] [FILE]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit -q, --quiet do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE Configuration files: $config_files Configuration commands: $config_commands Report bugs to ." ac_cs_version="\ config.status configured by ./configure, generated by GNU Autoconf 2.61, with options \"\" Copyright (C) 2006 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='/home/merc/audio/freewheeling' srcdir='.' INSTALL='/usr/bin/install -c' MKDIR_P='/bin/mkdir -p' # If no file are specified by the user, then we need to provide default # value. By we need to know if files were specified by the user. ac_need_defaults=: while test $# != 0 do case $1 in --*=*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) echo "$ac_cs_version"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift CONFIG_FILES="$CONFIG_FILES $ac_optarg" ac_need_defaults=false;; --he | --h | --help | --hel | -h ) echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) { echo "$as_me: error: unrecognized option: $1 Try \`$0 --help' for more information." >&2 { (exit 1); exit 1; }; } ;; *) ac_config_targets="$ac_config_targets $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi if $ac_cs_recheck; then echo "running CONFIG_SHELL=/bin/bash /bin/bash ./configure " $ac_configure_extra_args " --no-create --no-recursion" >&6 CONFIG_SHELL=/bin/bash export CONFIG_SHELL exec /bin/bash "./configure" $ac_configure_extra_args --no-create --no-recursion fi exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX echo "$ac_log" } >&5 # # INIT-COMMANDS # AMDEP_TRUE="" ac_aux_dir="." # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;; "data/Makefile") CONFIG_FILES="$CONFIG_FILES data/Makefile" ;; *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 echo "$as_me: error: invalid argument: $ac_config_target" >&2;} { (exit 1); exit 1; }; };; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= trap 'exit_status=$? { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status ' 0 trap '{ (exit 1); exit 1; }' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || { echo "$me: cannot create a temporary directory in ." >&2 { (exit 1); exit 1; } } # # Set up the sed scripts for CONFIG_FILES section. # # No need to generate the scripts if there are no CONFIG_FILES. # This happens for instance when ./config.status config.h if test -n "$CONFIG_FILES"; then cat >"$tmp/subs-1.sed" <<\CEOF /@[a-zA-Z_][a-zA-Z_0-9]*@/!b end s,@SHELL@,|#_!!_#|/bin/bash,g s,@PATH_SEPARATOR@,|#_!!_#|:,g s,@PACKAGE_NAME@,|#_!!_#|,g s,@PACKAGE_TARNAME@,|#_!!_#|,g s,@PACKAGE_VERSION@,|#_!!_#|,g s,@PACKAGE_STRING@,|#_!!_#|,g s,@PACKAGE_BUGREPORT@,|#_!!_#|,g s,@exec_prefix@,|#_!!_#|${prefix},g s,@prefix@,|#_!!_#|/usr/local,g s,@program_transform_name@,|#_!!_#|s\,x\,x\,,g s,@bindir@,|#_!!_#|${exec_prefix}/bin,g s,@sbindir@,|#_!!_#|${exec_prefix}/sbin,g s,@libexecdir@,|#_!!_#|${exec_prefix}/libexec,g s,@datarootdir@,|#_!!_#|${prefix}/share,g s,@datadir@,|#_!!_#|${datarootdir},g s,@sysconfdir@,|#_!!_#|${prefix}/etc,g s,@sharedstatedir@,|#_!!_#|${prefix}/com,g s,@localstatedir@,|#_!!_#|${prefix}/var,g s,@includedir@,|#_!!_#|${prefix}/include,g s,@oldincludedir@,|#_!!_#|/usr/include,g s,@docdir@,|#_!!_#|${datarootdir}/doc/${PACKAGE},g s,@infodir@,|#_!!_#|${datarootdir}/info,g s,@htmldir@,|#_!!_#|${docdir},g s,@dvidir@,|#_!!_#|${docdir},g s,@pdfdir@,|#_!!_#|${docdir},g s,@psdir@,|#_!!_#|${docdir},g s,@libdir@,|#_!!_#|${exec_prefix}/lib,g s,@localedir@,|#_!!_#|${datarootdir}/locale,g s,@mandir@,|#_!!_#|${datarootdir}/man,g s,@DEFS@,|#_!!_#|-DPACKAGE_NAME=\\"\\" -DPACKAGE_TARNAME=\\"\\" -DPACKAGE_VERSION=\\"\\" -DPACKAGE_STRING=\\"\\" -DPACKAGE_BUGREPORT=\\"\\" -DPACKAGE=\\"fweelin\\" -DVERSION=\\"0.6\\" -DHAVE_LIBGNUTLS_OPENSSL=1 -DHAVE_LIBDL=1 -DHAVE_LIBFREETYPE=1 -DHAVE_LIBSDL_GFX=1 -DCAPITAL_FILLED_PIE=1 -DHAVE_LIBSDL_TTF=1 -DHAVE_LIBXML2=1 -DHAVE_LIBM=1 -DHAVE_LIBPTHREAD=1 -DHAVE_LIBASOUND=1 -DHAVE_LIBJACK=1 -DUSE_FLUIDSYNTH=1 -DHAVE_LIBVORBIS=1 -DHAVE_LIBVORBISFILE=1 -DHAVE_LIBVORBISENC=1 -DHAVE_LIBSNDFILE=1 -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DHAVE_ERRNO_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_SYS_TIME_H=1 -DHAVE_UNISTD_H=1 -DTIME_WITH_SYS_TIME=1 -DHAVE_FLOOR=1 -DHAVE_GETTIMEOFDAY=1 -DHAVE_MEMSET=1 -DHAVE_POW=1 -DHAVE_SQRT=1,g s,@ECHO_C@,|#_!!_#|,g s,@ECHO_N@,|#_!!_#|-n,g s,@ECHO_T@,|#_!!_#|,g s,@LIBS@,|#_!!_#| -L/usr/X11R6/lib -lX11 -lsndfile -lvorbisenc -lvorbisfile -lvorbis -ljack -lasound -lpthread -lm -lxml2 -lSDL_ttf -lSDL_gfx -lfreetype -ldl -lgnutls-openssl -lfluidsynth ,g s,@build_alias@,|#_!!_#|,g s,@host_alias@,|#_!!_#|,g s,@target_alias@,|#_!!_#|,g s,@INSTALL_PROGRAM@,|#_!!_#|${INSTALL},g s,@INSTALL_SCRIPT@,|#_!!_#|${INSTALL},g s,@INSTALL_DATA@,|#_!!_#|${INSTALL} -m 644,g s,@am__isrc@,|#_!!_#|,g s,@CYGPATH_W@,|#_!!_#|echo,g s,@PACKAGE@,|#_!!_#|fweelin,g s,@VERSION@,|#_!!_#|0.6,g s,@ACLOCAL@,|#_!!_#|${SHELL} /home/merc/audio/freewheeling/missing --run aclocal-1.10,g s,@AUTOCONF@,|#_!!_#|${SHELL} /home/merc/audio/freewheeling/missing --run autoconf,g s,@AUTOMAKE@,|#_!!_#|${SHELL} /home/merc/audio/freewheeling/missing --run automake-1.10,g s,@AUTOHEADER@,|#_!!_#|${SHELL} /home/merc/audio/freewheeling/missing --run autoheader,g s,@MAKEINFO@,|#_!!_#|${SHELL} /home/merc/audio/freewheeling/missing --run makeinfo,g s,@install_sh@,|#_!!_#|$(SHELL) /home/merc/audio/freewheeling/install-sh,g s,@STRIP@,|#_!!_#|,g s,@INSTALL_STRIP_PROGRAM@,|#_!!_#|$(install_sh) -c -s,g s,@mkdir_p@,|#_!!_#|/bin/mkdir -p,g s,@AWK@,|#_!!_#|mawk,g s,@SET_MAKE@,|#_!!_#|,g s,@am__leading_dot@,|#_!!_#|.,g s,@AMTAR@,|#_!!_#|${SHELL} /home/merc/audio/freewheeling/missing --run tar,g s,@am__tar@,|#_!!_#|${AMTAR} chof - "$$tardir",g s,@am__untar@,|#_!!_#|${AMTAR} xf -,g s,@CXX@,|#_!!_#|g++,g s,@CXXFLAGS@,|#_!!_#|-g -O2,g s,@LDFLAGS@,|#_!!_#|,g s,@CPPFLAGS@,|#_!!_#|,g s,@ac_ct_CXX@,|#_!!_#|g++,g s,@EXEEXT@,|#_!!_#|,g s,@OBJEXT@,|#_!!_#|o,g s,@DEPDIR@,|#_!!_#|.deps,g s,@am__include@,|#_!!_#|include,g s,@am__quote@,|#_!!_#|,g s,@AMDEP_TRUE@,|#_!!_#|,g s,@AMDEP_FALSE@,|#_!!_#|#,g s,@AMDEPBACKSLASH@,|#_!!_#|\\,g s,@CXXDEPMODE@,|#_!!_#|depmode=gcc3,g s,@am__fastdepCXX_TRUE@,|#_!!_#|,g s,@am__fastdepCXX_FALSE@,|#_!!_#|#,g s,@CC@,|#_!!_#|gcc,g s,@CFLAGS@,|#_!!_#|-g -O2 ,g s,@ac_ct_CC@,|#_!!_#|gcc,g s,@CCDEPMODE@,|#_!!_#|depmode=gcc3,g s,@am__fastdepCC_TRUE@,|#_!!_#|,g s,@am__fastdepCC_FALSE@,|#_!!_#|#,g s,@XMKMF@,|#_!!_#|,g s,@CPP@,|#_!!_#|gcc -E,g s,@X_CFLAGS@,|#_!!_#|,g s,@X_PRE_LIBS@,|#_!!_#|,g s,@X_LIBS@,|#_!!_#|,g s,@X_EXTRA_LIBS@,|#_!!_#|,g s,@GREP@,|#_!!_#|/bin/grep,g s,@EGREP@,|#_!!_#|/bin/grep -E,g s,@LIBOBJS@,|#_!!_#|,g s,@LTLIBOBJS@,|#_!!_#|,g :end s/|#_!!_#|//g CEOF fi # test -n "$CONFIG_FILES" for ac_tag in :F $CONFIG_FILES :C $CONFIG_COMMANDS do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) { { echo "$as_me:$LINENO: error: Invalid tag $ac_tag." >&5 echo "$as_me: error: Invalid tag $ac_tag." >&2;} { (exit 1); exit 1; }; };; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || { { echo "$as_me:$LINENO: error: cannot find input file: $ac_f" >&5 echo "$as_me: error: cannot find input file: $ac_f" >&2;} { (exit 1); exit 1; }; };; esac ac_file_inputs="$ac_file_inputs $ac_f" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input="Generated from "`IFS=: echo $* | sed 's|^[^:]*/||;s|:[^:]*/|, |g'`" by configure." if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { echo "$as_me:$LINENO: creating $ac_file" >&5 echo "$as_me: creating $ac_file" >&6;} fi case $ac_tag in *:-:* | *:-) cat >"$tmp/stdin";; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` { as_dir="$ac_dir" case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5 echo "$as_me: error: cannot create directory $as_dir" >&2;} { (exit 1); exit 1; }; }; } ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # case $INSTALL in [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; esac ac_MKDIR_P=$MKDIR_P case $MKDIR_P in [\\/$]* | ?:[\\/]* ) ;; */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; esac # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= case `sed -n '/datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p ' $ac_file_inputs` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { echo "$as_me:$LINENO: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} ac_datarootdir_hack=' s&@datadir@&${datarootdir}&g s&@docdir@&${datarootdir}/doc/${PACKAGE}&g s&@infodir@&${datarootdir}/info&g s&@localedir@&${datarootdir}/locale&g s&@mandir@&${datarootdir}/man&g s&\${datarootdir}&${prefix}/share&g' ;; esac sed "/^[ ]*VPATH[ ]*=/{ s/:*\$(srcdir):*/:/ s/:*\${srcdir}:*/:/ s/:*@srcdir@:*/:/ s/^\([^=]*=[ ]*\):*/\1/ s/:*$// s/^[^=]*=[ ]*$// } :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s&@configure_input@&$configure_input&;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t s&@INSTALL@&$ac_INSTALL&;t t s&@MKDIR_P@&$ac_MKDIR_P&;t t $ac_datarootdir_hack " $ac_file_inputs | sed -f "$tmp/subs-1.sed" >$tmp/out test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } && { echo "$as_me:$LINENO: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined." >&5 echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined." >&2;} rm -f "$tmp/stdin" case $ac_file in -) cat "$tmp/out"; rm -f "$tmp/out";; *) rm -f "$ac_file"; mv "$tmp/out" $ac_file;; esac ;; :C) { echo "$as_me:$LINENO: executing $ac_file commands" >&5 echo "$as_me: executing $ac_file commands" >&6;} ;; esac case $ac_file$ac_mode in "depfiles":C) test x"$AMDEP_TRUE" != x"" || for mf in $CONFIG_FILES; do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named `Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # Grep'ing the whole file is not good either: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. if sed 10q "$mf" | grep '^#.*generated by automake' > /dev/null 2>&1; then dirpart=`$as_dirname -- "$mf" || $as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$mf" : 'X\(//\)[^/]' \| \ X"$mf" : 'X\(//\)$' \| \ X"$mf" : 'X\(/\)' \| . 2>/dev/null || echo X"$mf" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running `make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # When using ansi2knr, U may be empty or an underscore; expand it U=`sed -n 's/^U = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`$as_dirname -- "$file" || $as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$file" : 'X\(//\)[^/]' \| \ X"$file" : 'X\(//\)$' \| \ X"$file" : 'X\(/\)' \| . 2>/dev/null || echo X"$file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` { as_dir=$dirpart/$fdir case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5 echo "$as_me: error: cannot create directory $as_dir" >&2;} { (exit 1); exit 1; }; }; } # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done ;; esac done # for ac_tag { (exit 0); exit 0; } fweelin-0.6/configure0000755000175000017500000074674511071520731013401 0ustar mercmerc#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.61. # # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, # 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## --------------------- ## ## M4sh Initialization. ## ## --------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac fi # PATH needs CR # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then echo "#! /bin/sh" >conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi # Support unset when possible. if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then as_unset=unset else as_unset=false fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) as_nl=' ' IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. case $0 in *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 { (exit 1); exit 1; } fi # Work around bugs in pre-3.0 UWIN ksh. for as_var in ENV MAIL MAILPATH do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. for as_var in \ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ LC_TELEPHONE LC_TIME do if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then eval $as_var=C; export $as_var else ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var fi done # Required to use basename. if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi # Name of the executable. as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # CDPATH. $as_unset CDPATH if test "x$CONFIG_SHELL" = x; then if (eval ":") 2>/dev/null; then as_have_required=yes else as_have_required=no fi if test $as_have_required = yes && (eval ": (as_func_return () { (exit \$1) } as_func_success () { as_func_return 0 } as_func_failure () { as_func_return 1 } as_func_ret_success () { return 0 } as_func_ret_failure () { return 1 } exitcode=0 if as_func_success; then : else exitcode=1 echo as_func_success failed. fi if as_func_failure; then exitcode=1 echo as_func_failure succeeded. fi if as_func_ret_success; then : else exitcode=1 echo as_func_ret_success failed. fi if as_func_ret_failure; then exitcode=1 echo as_func_ret_failure succeeded. fi if ( set x; as_func_ret_success y && test x = \"\$1\" ); then : else exitcode=1 echo positional parameters were not saved. fi test \$exitcode = 0) || { (exit 1); exit 1; } ( as_lineno_1=\$LINENO as_lineno_2=\$LINENO test \"x\$as_lineno_1\" != \"x\$as_lineno_2\" && test \"x\`expr \$as_lineno_1 + 1\`\" = \"x\$as_lineno_2\") || { (exit 1); exit 1; } ") 2> /dev/null; then : else as_candidate_shells= as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. case $as_dir in /*) for as_base in sh bash ksh sh5; do as_candidate_shells="$as_candidate_shells $as_dir/$as_base" done;; esac done IFS=$as_save_IFS for as_shell in $as_candidate_shells $SHELL; do # Try only shells that exist, to save several forks. if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { ("$as_shell") 2> /dev/null <<\_ASEOF if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac fi : _ASEOF }; then CONFIG_SHELL=$as_shell as_have_required=yes if { "$as_shell" 2> /dev/null <<\_ASEOF if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac fi : (as_func_return () { (exit $1) } as_func_success () { as_func_return 0 } as_func_failure () { as_func_return 1 } as_func_ret_success () { return 0 } as_func_ret_failure () { return 1 } exitcode=0 if as_func_success; then : else exitcode=1 echo as_func_success failed. fi if as_func_failure; then exitcode=1 echo as_func_failure succeeded. fi if as_func_ret_success; then : else exitcode=1 echo as_func_ret_success failed. fi if as_func_ret_failure; then exitcode=1 echo as_func_ret_failure succeeded. fi if ( set x; as_func_ret_success y && test x = "$1" ); then : else exitcode=1 echo positional parameters were not saved. fi test $exitcode = 0) || { (exit 1); exit 1; } ( as_lineno_1=$LINENO as_lineno_2=$LINENO test "x$as_lineno_1" != "x$as_lineno_2" && test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2") || { (exit 1); exit 1; } _ASEOF }; then break fi fi done if test "x$CONFIG_SHELL" != x; then for as_var in BASH_ENV ENV do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var done export CONFIG_SHELL exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"} fi if test $as_have_required = no; then echo This script requires a shell more modern than all the echo shells that I found on your system. Please install a echo modern shell, or manually run the script under such a echo shell if you do have one. { (exit 1); exit 1; } fi fi fi (eval "as_func_return () { (exit \$1) } as_func_success () { as_func_return 0 } as_func_failure () { as_func_return 1 } as_func_ret_success () { return 0 } as_func_ret_failure () { return 1 } exitcode=0 if as_func_success; then : else exitcode=1 echo as_func_success failed. fi if as_func_failure; then exitcode=1 echo as_func_failure succeeded. fi if as_func_ret_success; then : else exitcode=1 echo as_func_ret_success failed. fi if as_func_ret_failure; then exitcode=1 echo as_func_ret_failure succeeded. fi if ( set x; as_func_ret_success y && test x = \"\$1\" ); then : else exitcode=1 echo positional parameters were not saved. fi test \$exitcode = 0") || { echo No shell found that supports shell functions. echo Please tell autoconf@gnu.org about your system, echo including any error possibly output before this echo message } as_lineno_1=$LINENO as_lineno_2=$LINENO test "x$as_lineno_1" != "x$as_lineno_2" && test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || { # Create $as_me.lineno as a copy of $as_myself, but with $LINENO # uniformly replaced by the line number. The first 'sed' inserts a # line-number line after each line using $LINENO; the second 'sed' # does the real work. The second script uses 'N' to pair each # line-number line with the line containing $LINENO, and appends # trailing '-' during substitution so that $LINENO is not a special # case at line end. # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the # scripts with optimization help from Paolo Bonzini. Blame Lee # E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 { (exit 1); exit 1; }; } # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in -n*) case `echo 'x\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. *) ECHO_C='\c';; esac;; *) ECHO_N='-n';; esac if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir fi echo >conf$$.file if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -p'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -p' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p=: else test -d ./-p && rmdir ./-p as_mkdir_p=false fi if test -x / >/dev/null 2>&1; then as_test_x='test -x' else if ls -dL / >/dev/null 2>&1; then as_ls_L_option=L else as_ls_L_option= fi as_test_x=' eval sh -c '\'' if test -d "$1"; then test -d "$1/."; else case $1 in -*)set "./$1";; esac; case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in ???[sx]*):;;*)false;;esac;fi '\'' sh ' fi as_executable_p=$as_test_x # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= SHELL=${CONFIG_SHELL-/bin/sh} # Identity of this package. PACKAGE_NAME= PACKAGE_TARNAME= PACKAGE_VERSION= PACKAGE_STRING= PACKAGE_BUGREPORT= ac_unique_file="src/fweelin.cc" ac_unique_file="src/fweelin.cc" # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datarootdir datadir sysconfdir sharedstatedir localstatedir includedir oldincludedir docdir infodir htmldir dvidir pdfdir psdir libdir localedir mandir DEFS ECHO_C ECHO_N ECHO_T LIBS build_alias host_alias target_alias INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA am__isrc CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar CXX CXXFLAGS LDFLAGS CPPFLAGS ac_ct_CXX EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CXXDEPMODE am__fastdepCXX_TRUE am__fastdepCXX_FALSE CC CFLAGS ac_ct_CC CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE XMKMF CPP X_CFLAGS X_PRE_LIBS X_LIBS X_EXTRA_LIBS GREP EGREP LIBOBJS LTLIBOBJS' ac_subst_files='' ac_precious_vars='build_alias host_alias target_alias CXX CXXFLAGS LDFLAGS LIBS CPPFLAGS CCC CC CFLAGS XMKMF CPP' # Initialize some variables set by options. ac_init_help= ac_init_version=false # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid feature name: $ac_feature" >&2 { (exit 1); exit 1; }; } ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'` eval enable_$ac_feature=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid feature name: $ac_feature" >&2 { (exit 1); exit 1; }; } ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'` eval enable_$ac_feature=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid package name: $ac_package" >&2 { (exit 1); exit 1; }; } ac_package=`echo $ac_package | sed 's/[-.]/_/g'` eval with_$ac_package=\$ac_optarg ;; -without-* | --without-*) ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid package name: $ac_package" >&2 { (exit 1); exit 1; }; } ac_package=`echo $ac_package | sed 's/[-.]/_/g'` eval with_$ac_package=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) { echo "$as_me: error: unrecognized option: $ac_option Try \`$0 --help' for more information." >&2 { (exit 1); exit 1; }; } ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 { (exit 1); exit 1; }; } eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` { echo "$as_me: error: missing argument to $ac_option" >&2 { (exit 1); exit 1; }; } fi # Be sure to have absolute directory names. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir do eval ac_val=\$$ac_var case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 { (exit 1); exit 1; }; } done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. If a cross compiler is detected then cross compile mode will be used." >&2 elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || { echo "$as_me: error: Working directory cannot be determined" >&2 { (exit 1); exit 1; }; } test "X$ac_ls_di" = "X$ac_pwd_ls_di" || { echo "$as_me: error: pwd does not report name of working directory" >&2 { (exit 1); exit 1; }; } # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$0" || $as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$0" : 'X\(//\)[^/]' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || echo X"$0" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 { (exit 1); exit 1; }; } fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || { echo "$as_me: error: $ac_msg" >&2 { (exit 1); exit 1; }; } pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures this package to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF Program names: --program-prefix=PREFIX prepend PREFIX to installed program names --program-suffix=SUFFIX append SUFFIX to installed program names --program-transform-name=PROGRAM run sed PROGRAM on installed program names X features: --x-includes=DIR X include files are in DIR --x-libraries=DIR X library files are in DIR _ACEOF fi if test -n "$ac_init_help"; then cat <<\_ACEOF Optional Features: --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-fluidsynth use integrated FluidSynth softsynth (libfluidsynth) (default=auto) --disable-video disable video output --enable-lcd enable USB LCD display output --disable-dependency-tracking speeds up one-time build --enable-dependency-tracking do not reject slow dependency extractors Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-x use the X Window System Some influential environment variables: CXX C++ compiler command CXXFLAGS C++ compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS C/C++/Objective C preprocessor flags, e.g. -I if you have headers in a nonstandard directory CC C compiler command CFLAGS C compiler flags XMKMF Path to xmkmf, Makefile generator for X Window System CPP C preprocessor Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF configure generated by GNU Autoconf 2.61 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by $as_me, which was generated by GNU Autoconf 2.61. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; 2) ac_configure_args1="$ac_configure_args1 '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi ac_configure_args="$ac_configure_args '$ac_arg'" ;; esac done done $as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } $as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; } # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo cat <<\_ASBOX ## ---------------- ## ## Cache variables. ## ## ---------------- ## _ASBOX echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( *) $as_unset $ac_var ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo cat <<\_ASBOX ## ----------------- ## ## Output variables. ## ## ----------------- ## _ASBOX echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then cat <<\_ASBOX ## ------------------- ## ## File substitutions. ## ## ------------------- ## _ASBOX echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then cat <<\_ASBOX ## ----------- ## ## confdefs.h. ## ## ----------- ## _ASBOX echo cat confdefs.h echo fi test "$ac_signal" != 0 && echo "$as_me: caught signal $ac_signal" echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer explicitly selected file to automatically selected ones. if test -n "$CONFIG_SITE"; then set x "$CONFIG_SITE" elif test "x$prefix" != xNONE; then set x "$prefix/share/config.site" "$prefix/etc/config.site" else set x "$ac_default_prefix/share/config.site" \ "$ac_default_prefix/etc/config.site" fi shift for ac_site_file do if test -r "$ac_site_file"; then { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special # files actually), so we avoid doing that. if test -f "$cache_file"; then { echo "$as_me:$LINENO: loading cache $cache_file" >&5 echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { echo "$as_me:$LINENO: creating cache $cache_file" >&5 echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 echo "$as_me: former value: $ac_old_val" >&2;} { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 echo "$as_me: current value: $ac_new_val" >&2;} ac_cache_corrupted=: fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 echo "$as_me: error: changes in the environment can compromise the build" >&2;} { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} { (exit 1); exit 1; }; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu am__api_version='1.10' ac_aux_dir= for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do if test -f "$ac_dir/install-sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" break elif test -f "$ac_dir/install.sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break elif test -f "$ac_dir/shtool"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/shtool install -c" break fi done if test -z "$ac_aux_dir"; then { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" >&5 echo "$as_me: error: cannot find install-sh or install.sh in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" >&2;} { (exit 1); exit 1; }; } fi # These three variables are undocumented and unsupported, # and are intended to be withdrawn in a future Autoconf release. # They can cause serious problems if a builder's source tree is in a directory # whose full name contains unusual characters. ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install # AmigaOS /C/install, which installs bootblocks on floppy discs # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # OS/2's system install, which has a completely different semantic # ./install, which can be erroneously created by make from ./install.sh. { echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5 echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6; } if test -z "$INSTALL"; then if test "${ac_cv_path_install+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. # Account for people who put trailing slashes in PATH elements. case $as_dir/ in ./ | .// | /cC/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \ /usr/ucb/* ) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. # Don't use installbsd from OSF since it installs stuff as root # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then if test $ac_prog = install && grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : elif test $ac_prog = install && grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # program-specific install script used by HP pwplus--don't use. : else ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" break 3 fi fi done done ;; esac done IFS=$as_save_IFS fi if test "${ac_cv_path_install+set}" = set; then INSTALL=$ac_cv_path_install else # As a last resort, use the slow shell script. Don't cache a # value for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. INSTALL=$ac_install_sh fi fi { echo "$as_me:$LINENO: result: $INSTALL" >&5 echo "${ECHO_T}$INSTALL" >&6; } # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' { echo "$as_me:$LINENO: checking whether build environment is sane" >&5 echo $ECHO_N "checking whether build environment is sane... $ECHO_C" >&6; } # Just in case sleep 1 echo timestamp > conftest.file # Do `set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null` if test "$*" = "X"; then # -L didn't work. set X `ls -t $srcdir/configure conftest.file` fi rm -f conftest.file if test "$*" != "X $srcdir/configure conftest.file" \ && test "$*" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". { { echo "$as_me:$LINENO: error: ls -t appears to fail. Make sure there is not a broken alias in your environment" >&5 echo "$as_me: error: ls -t appears to fail. Make sure there is not a broken alias in your environment" >&2;} { (exit 1); exit 1; }; } fi test "$2" = conftest.file ) then # Ok. : else { { echo "$as_me:$LINENO: error: newly created file is older than distributed files! Check your system clock" >&5 echo "$as_me: error: newly created file is older than distributed files! Check your system clock" >&2;} { (exit 1); exit 1; }; } fi { echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6; } test "$program_prefix" != NONE && program_transform_name="s&^&$program_prefix&;$program_transform_name" # Use a double $ so make ignores it. test "$program_suffix" != NONE && program_transform_name="s&\$&$program_suffix&;$program_transform_name" # Double any \ or $. echo might interpret backslashes. # By default was `s,x,x', remove it if useless. cat <<\_ACEOF >conftest.sed s/[\\$]/&&/g;s/;s,x,x,$// _ACEOF program_transform_name=`echo $program_transform_name | sed -f conftest.sed` rm -f conftest.sed # expand $ac_aux_dir to an absolute path am_aux_dir=`cd $ac_aux_dir && pwd` test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing" # Use eval to expand $SHELL if eval "$MISSING --run true"; then am_missing_run="$MISSING --run " else am_missing_run= { echo "$as_me:$LINENO: WARNING: \`missing' script is too old or missing" >&5 echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;} fi { echo "$as_me:$LINENO: checking for a thread-safe mkdir -p" >&5 echo $ECHO_N "checking for a thread-safe mkdir -p... $ECHO_C" >&6; } if test -z "$MKDIR_P"; then if test "${ac_cv_path_mkdir+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in mkdir gmkdir; do for ac_exec_ext in '' $ac_executable_extensions; do { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; } || continue case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( 'mkdir (GNU coreutils) '* | \ 'mkdir (coreutils) '* | \ 'mkdir (fileutils) '4.1*) ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext break 3;; esac done done done IFS=$as_save_IFS fi if test "${ac_cv_path_mkdir+set}" = set; then MKDIR_P="$ac_cv_path_mkdir -p" else # As a last resort, use the slow shell script. Don't cache a # value for MKDIR_P within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. test -d ./--version && rmdir ./--version MKDIR_P="$ac_install_sh -d" fi fi { echo "$as_me:$LINENO: result: $MKDIR_P" >&5 echo "${ECHO_T}$MKDIR_P" >&6; } mkdir_p="$MKDIR_P" case $mkdir_p in [\\/$]* | ?:[\\/]*) ;; */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; esac for ac_prog in gawk mawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_AWK+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_AWK="$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AWK=$ac_cv_prog_AWK if test -n "$AWK"; then { echo "$as_me:$LINENO: result: $AWK" >&5 echo "${ECHO_T}$AWK" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi test -n "$AWK" && break done { echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5 echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6; } set x ${MAKE-make}; ac_make=`echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` if { as_var=ac_cv_prog_make_${ac_make}_set; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.make <<\_ACEOF SHELL = /bin/sh all: @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF # GNU make sometimes prints "make[1]: Entering...", which would confuse us. case `${MAKE-make} -f conftest.make 2>/dev/null` in *@@@%%%=?*=@@@%%%*) eval ac_cv_prog_make_${ac_make}_set=yes;; *) eval ac_cv_prog_make_${ac_make}_set=no;; esac rm -f conftest.make fi if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then { echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6; } SET_MAKE= else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." am__isrc=' -I$(srcdir)' # test to see if srcdir already configured if test -f $srcdir/config.status; then { { echo "$as_me:$LINENO: error: source directory already configured; run \"make distclean\" there first" >&5 echo "$as_me: error: source directory already configured; run \"make distclean\" there first" >&2;} { (exit 1); exit 1; }; } fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi # Define the identity of the package. PACKAGE=fweelin VERSION=0.6 cat >>confdefs.h <<_ACEOF #define PACKAGE "$PACKAGE" _ACEOF cat >>confdefs.h <<_ACEOF #define VERSION "$VERSION" _ACEOF # Some tools Automake needs. ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} install_sh=${install_sh-"\$(SHELL) $am_aux_dir/install-sh"} # Installed binaries are usually stripped using `strip' when the user # run `make install-strip'. However `strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the `STRIP' environment variable to overrule this program. if test "$cross_compiling" != no; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_STRIP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { echo "$as_me:$LINENO: result: $STRIP" >&5 echo "${ECHO_T}$STRIP" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_STRIP="strip" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5 echo "${ECHO_T}$ac_ct_STRIP" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&5 echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" # We need awk for the "check" target. The system "awk" is bad on # some platforms. # Always define AMTAR for backward compatibility. AMTAR=${AMTAR-"${am_missing_run}tar"} am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -' #AM_CONFIG_HEADER(config.h) # Check whether --enable-fluidsynth was given. if test "${enable_fluidsynth+set}" = set; then enableval=$enable_fluidsynth; fi # Check whether --enable-video was given. if test "${enable_video+set}" = set; then enableval=$enable_video; fi # Check whether --enable-lcd was given. if test "${enable_lcd+set}" = set; then enableval=$enable_lcd; fi # Checks for programs. ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu if test -z "$CXX"; then if test -n "$CCC"; then CXX=$CCC else if test -n "$ac_tool_prefix"; then for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_CXX+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CXX"; then ac_cv_prog_CXX="$CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CXX=$ac_cv_prog_CXX if test -n "$CXX"; then { echo "$as_me:$LINENO: result: $CXX" >&5 echo "${ECHO_T}$CXX" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi test -n "$CXX" && break done fi if test -z "$CXX"; then ac_ct_CXX=$CXX for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_CXX"; then ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CXX="$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CXX=$ac_cv_prog_ac_ct_CXX if test -n "$ac_ct_CXX"; then { echo "$as_me:$LINENO: result: $ac_ct_CXX" >&5 echo "${ECHO_T}$ac_ct_CXX" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi test -n "$ac_ct_CXX" && break done if test "x$ac_ct_CXX" = x; then CXX="g++" else case $cross_compiling:$ac_tool_warned in yes:) { echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&5 echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&2;} ac_tool_warned=yes ;; esac CXX=$ac_ct_CXX fi fi fi fi # Provide some information about the compiler. echo "$as_me:$LINENO: checking for C++ compiler version" >&5 ac_compiler=`set X $ac_compile; echo $2` { (ac_try="$ac_compiler --version >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compiler --version >&5") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (ac_try="$ac_compiler -v >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compiler -v >&5") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (ac_try="$ac_compiler -V >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compiler -V >&5") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { echo "$as_me:$LINENO: checking for C++ compiler default output file name" >&5 echo $ECHO_N "checking for C++ compiler default output file name... $ECHO_C" >&6; } ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # # List of possible output files, starting from the most likely. # The algorithm is not robust to junk in `.', hence go to wildcards (a.*) # only as a last resort. b.out is created by i960 compilers. ac_files='a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out' # # The IRIX 6 linker writes into existing files which may not be # executable, retaining their permissions. Remove them first so a # subsequent execution test works. ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { (ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link_default") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi { echo "$as_me:$LINENO: result: $ac_file" >&5 echo "${ECHO_T}$ac_file" >&6; } if test -z "$ac_file"; then echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { echo "$as_me:$LINENO: error: C++ compiler cannot create executables See \`config.log' for more details." >&5 echo "$as_me: error: C++ compiler cannot create executables See \`config.log' for more details." >&2;} { (exit 77); exit 77; }; } fi ac_exeext=$ac_cv_exeext # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { echo "$as_me:$LINENO: checking whether the C++ compiler works" >&5 echo $ECHO_N "checking whether the C++ compiler works... $ECHO_C" >&6; } # FIXME: These cross compiler hacks should be removed for Autoconf 3.0 # If not cross compiling, check that we can run a simple program. if test "$cross_compiling" != yes; then if { ac_try='./$ac_file' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_try") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { echo "$as_me:$LINENO: error: cannot run C++ compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details." >&5 echo "$as_me: error: cannot run C++ compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi fi fi { echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6; } rm -f a.out a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6; } { echo "$as_me:$LINENO: result: $cross_compiling" >&5 echo "${ECHO_T}$cross_compiling" >&6; } { echo "$as_me:$LINENO: checking for suffix of executables" >&5 echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6; } if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute suffix of executables: cannot compile and link See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi rm -f conftest$ac_cv_exeext { echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 echo "${ECHO_T}$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT { echo "$as_me:$LINENO: checking for suffix of object files" >&5 echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6; } if test "${ac_cv_objext+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute suffix of object files: cannot compile See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 echo "${ECHO_T}$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { echo "$as_me:$LINENO: checking whether we are using the GNU C++ compiler" >&5 echo $ECHO_N "checking whether we are using the GNU C++ compiler... $ECHO_C" >&6; } if test "${ac_cv_cxx_compiler_gnu+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_compiler_gnu=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_cxx_compiler_gnu=$ac_compiler_gnu fi { echo "$as_me:$LINENO: result: $ac_cv_cxx_compiler_gnu" >&5 echo "${ECHO_T}$ac_cv_cxx_compiler_gnu" >&6; } GXX=`test $ac_compiler_gnu = yes && echo yes` ac_test_CXXFLAGS=${CXXFLAGS+set} ac_save_CXXFLAGS=$CXXFLAGS { echo "$as_me:$LINENO: checking whether $CXX accepts -g" >&5 echo $ECHO_N "checking whether $CXX accepts -g... $ECHO_C" >&6; } if test "${ac_cv_prog_cxx_g+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_save_cxx_werror_flag=$ac_cxx_werror_flag ac_cxx_werror_flag=yes ac_cv_prog_cxx_g=no CXXFLAGS="-g" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_prog_cxx_g=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 CXXFLAGS="" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cxx_werror_flag=$ac_save_cxx_werror_flag CXXFLAGS="-g" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_prog_cxx_g=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cxx_werror_flag=$ac_save_cxx_werror_flag fi { echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_g" >&5 echo "${ECHO_T}$ac_cv_prog_cxx_g" >&6; } if test "$ac_test_CXXFLAGS" = set; then CXXFLAGS=$ac_save_CXXFLAGS elif test $ac_cv_prog_cxx_g = yes; then if test "$GXX" = yes; then CXXFLAGS="-g -O2" else CXXFLAGS="-g" fi else if test "$GXX" = yes; then CXXFLAGS="-O2" else CXXFLAGS= fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu DEPDIR="${am__leading_dot}deps" ac_config_commands="$ac_config_commands depfiles" am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo done .PHONY: am__doit END # If we don't find an include directive, just comment out the code. { echo "$as_me:$LINENO: checking for style of include used by $am_make" >&5 echo $ECHO_N "checking for style of include used by $am_make... $ECHO_C" >&6; } am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # We grep out `Entering directory' and `Leaving directory' # messages which can occur if `w' ends up in MAKEFLAGS. # In particular we don't look at `^make:' because GNU make might # be invoked under some other name (usually "gmake"), in which # case it prints its new name instead of `make'. if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then am__include=include am__quote= _am_result=GNU fi # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then am__include=.include am__quote="\"" _am_result=BSD fi fi { echo "$as_me:$LINENO: result: $_am_result" >&5 echo "${ECHO_T}$_am_result" >&6; } rm -f confinc confmf # Check whether --enable-dependency-tracking was given. if test "${enable_dependency_tracking+set}" = set; then enableval=$enable_dependency_tracking; fi if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' fi if test "x$enable_dependency_tracking" != xno; then AMDEP_TRUE= AMDEP_FALSE='#' else AMDEP_TRUE='#' AMDEP_FALSE= fi depcc="$CXX" am_compiler_list= { echo "$as_me:$LINENO: checking dependency style of $depcc" >&5 echo $ECHO_N "checking dependency style of $depcc... $ECHO_C" >&6; } if test "${am_cv_CXX_dependencies_compiler_type+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named `D' -- because `-MD' means `put the output # in D'. mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CXX_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with # Solaris 8's {/usr,}/bin/sh. touch sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf case $depmode in nosideeffect) # after this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; none) break ;; esac # We check with `-c' and `-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle `-M -o', and we need to detect this. if depmode=$depmode \ source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CXX_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CXX_dependencies_compiler_type=none fi fi { echo "$as_me:$LINENO: result: $am_cv_CXX_dependencies_compiler_type" >&5 echo "${ECHO_T}$am_cv_CXX_dependencies_compiler_type" >&6; } CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then am__fastdepCXX_TRUE= am__fastdepCXX_FALSE='#' else am__fastdepCXX_TRUE='#' am__fastdepCXX_FALSE= fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="${ac_tool_prefix}gcc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_ac_ct_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CC="gcc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 echo "${ECHO_T}$ac_ct_CC" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&5 echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="${ac_tool_prefix}cc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_ac_ct_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CC="$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 echo "${ECHO_T}$ac_ct_CC" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&5 echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH See \`config.log' for more details." >&5 echo "$as_me: error: no acceptable C compiler found in \$PATH See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } # Provide some information about the compiler. echo "$as_me:$LINENO: checking for C compiler version" >&5 ac_compiler=`set X $ac_compile; echo $2` { (ac_try="$ac_compiler --version >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compiler --version >&5") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (ac_try="$ac_compiler -v >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compiler -v >&5") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (ac_try="$ac_compiler -V >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compiler -V >&5") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6; } if test "${ac_cv_c_compiler_gnu+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_compiler_gnu=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6; } GCC=`test $ac_compiler_gnu = yes && echo yes` ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6; } if test "${ac_cv_prog_cc_g+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_prog_cc_g=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 CFLAGS="" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_prog_cc_g=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 echo "${ECHO_T}$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { echo "$as_me:$LINENO: checking for $CC option to accept ISO C89" >&5 echo $ECHO_N "checking for $CC option to accept ISO C89... $ECHO_C" >&6; } if test "${ac_cv_prog_cc_c89+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #include #include /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_prog_cc_c89=$ac_arg else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { echo "$as_me:$LINENO: result: none needed" >&5 echo "${ECHO_T}none needed" >&6; } ;; xno) { echo "$as_me:$LINENO: result: unsupported" >&5 echo "${ECHO_T}unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5 echo "${ECHO_T}$ac_cv_prog_cc_c89" >&6; } ;; esac ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu depcc="$CC" am_compiler_list= { echo "$as_me:$LINENO: checking dependency style of $depcc" >&5 echo $ECHO_N "checking dependency style of $depcc... $ECHO_C" >&6; } if test "${am_cv_CC_dependencies_compiler_type+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named `D' -- because `-MD' means `put the output # in D'. mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CC_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with # Solaris 8's {/usr,}/bin/sh. touch sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf case $depmode in nosideeffect) # after this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; none) break ;; esac # We check with `-c' and `-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle `-M -o', and we need to detect this. if depmode=$depmode \ source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CC_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CC_dependencies_compiler_type=none fi fi { echo "$as_me:$LINENO: result: $am_cv_CC_dependencies_compiler_type" >&5 echo "${ECHO_T}$am_cv_CC_dependencies_compiler_type" >&6; } CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then am__fastdepCC_TRUE= am__fastdepCC_FALSE='#' else am__fastdepCC_TRUE='#' am__fastdepCC_FALSE= fi # Add Xtra Paths for Checking ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5 echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if test "${ac_cv_prog_CPP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Broken: fails on valid input. continue fi rm -f conftest.err conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then # Broken: success on invalid input. continue else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.err conftest.$ac_ext if $ac_preproc_ok; then break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { echo "$as_me:$LINENO: result: $CPP" >&5 echo "${ECHO_T}$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Broken: fails on valid input. continue fi rm -f conftest.err conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then # Broken: success on invalid input. continue else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details." >&5 echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { echo "$as_me:$LINENO: checking for X" >&5 echo $ECHO_N "checking for X... $ECHO_C" >&6; } # Check whether --with-x was given. if test "${with_x+set}" = set; then withval=$with_x; fi # $have_x is `yes', `no', `disabled', or empty when we do not yet know. if test "x$with_x" = xno; then # The user explicitly disabled X. have_x=disabled else case $x_includes,$x_libraries in #( *\'*) { { echo "$as_me:$LINENO: error: Cannot use X directory names containing '" >&5 echo "$as_me: error: Cannot use X directory names containing '" >&2;} { (exit 1); exit 1; }; };; #( *,NONE | NONE,*) if test "${ac_cv_have_x+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else # One or both of the vars are not set, and there is no cached value. ac_x_includes=no ac_x_libraries=no rm -f -r conftest.dir if mkdir conftest.dir; then cd conftest.dir cat >Imakefile <<'_ACEOF' incroot: @echo incroot='${INCROOT}' usrlibdir: @echo usrlibdir='${USRLIBDIR}' libdir: @echo libdir='${LIBDIR}' _ACEOF if (export CC; ${XMKMF-xmkmf}) >/dev/null 2>/dev/null && test -f Makefile; then # GNU make sometimes prints "make[1]: Entering...", which would confuse us. for ac_var in incroot usrlibdir libdir; do eval "ac_im_$ac_var=\`\${MAKE-make} $ac_var 2>/dev/null | sed -n 's/^$ac_var=//p'\`" done # Open Windows xmkmf reportedly sets LIBDIR instead of USRLIBDIR. for ac_extension in a so sl; do if test ! -f "$ac_im_usrlibdir/libX11.$ac_extension" && test -f "$ac_im_libdir/libX11.$ac_extension"; then ac_im_usrlibdir=$ac_im_libdir; break fi done # Screen out bogus values from the imake configuration. They are # bogus both because they are the default anyway, and because # using them would break gcc on systems where it needs fixed includes. case $ac_im_incroot in /usr/include) ac_x_includes= ;; *) test -f "$ac_im_incroot/X11/Xos.h" && ac_x_includes=$ac_im_incroot;; esac case $ac_im_usrlibdir in /usr/lib | /lib) ;; *) test -d "$ac_im_usrlibdir" && ac_x_libraries=$ac_im_usrlibdir ;; esac fi cd .. rm -f -r conftest.dir fi # Standard set of common directories for X headers. # Check X11 before X11Rn because it is often a symlink to the current release. ac_x_header_dirs=' /usr/X11/include /usr/X11R6/include /usr/X11R5/include /usr/X11R4/include /usr/include/X11 /usr/include/X11R6 /usr/include/X11R5 /usr/include/X11R4 /usr/local/X11/include /usr/local/X11R6/include /usr/local/X11R5/include /usr/local/X11R4/include /usr/local/include/X11 /usr/local/include/X11R6 /usr/local/include/X11R5 /usr/local/include/X11R4 /usr/X386/include /usr/x386/include /usr/XFree86/include/X11 /usr/include /usr/local/include /usr/unsupported/include /usr/athena/include /usr/local/x11r5/include /usr/lpp/Xamples/include /usr/openwin/include /usr/openwin/share/include' if test "$ac_x_includes" = no; then # Guess where to find include files, by looking for Xlib.h. # First, try using that file with no special directory specified. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then # We can compile using X headers with no special include directory. ac_x_includes= else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 for ac_dir in $ac_x_header_dirs; do if test -r "$ac_dir/X11/Xlib.h"; then ac_x_includes=$ac_dir break fi done fi rm -f conftest.err conftest.$ac_ext fi # $ac_x_includes = no if test "$ac_x_libraries" = no; then # Check for the libraries. # See if we find them without any special options. # Don't add to $LIBS permanently. ac_save_LIBS=$LIBS LIBS="-lX11 $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { XrmInitialize () ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then LIBS=$ac_save_LIBS # We can link X programs with no special library path. ac_x_libraries= else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 LIBS=$ac_save_LIBS for ac_dir in `echo "$ac_x_includes $ac_x_header_dirs" | sed s/include/lib/g` do # Don't even attempt the hair of trying to link an X program! for ac_extension in a so sl; do if test -r "$ac_dir/libX11.$ac_extension"; then ac_x_libraries=$ac_dir break 2 fi done done fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi # $ac_x_libraries = no case $ac_x_includes,$ac_x_libraries in #( no,* | *,no | *\'*) # Didn't find X, or a directory has "'" in its name. ac_cv_have_x="have_x=no";; #( *) # Record where we found X for the cache. ac_cv_have_x="have_x=yes\ ac_x_includes='$ac_x_includes'\ ac_x_libraries='$ac_x_libraries'" esac fi ;; #( *) have_x=yes;; esac eval "$ac_cv_have_x" fi # $with_x != no if test "$have_x" != yes; then { echo "$as_me:$LINENO: result: $have_x" >&5 echo "${ECHO_T}$have_x" >&6; } no_x=yes else # If each of the values was on the command line, it overrides each guess. test "x$x_includes" = xNONE && x_includes=$ac_x_includes test "x$x_libraries" = xNONE && x_libraries=$ac_x_libraries # Update the cache value to reflect the command line values. ac_cv_have_x="have_x=yes\ ac_x_includes='$x_includes'\ ac_x_libraries='$x_libraries'" { echo "$as_me:$LINENO: result: libraries $x_libraries, headers $x_includes" >&5 echo "${ECHO_T}libraries $x_libraries, headers $x_includes" >&6; } fi if test "$no_x" = yes; then # Not all programs may use this symbol, but it does not hurt to define it. cat >>confdefs.h <<\_ACEOF #define X_DISPLAY_MISSING 1 _ACEOF X_CFLAGS= X_PRE_LIBS= X_LIBS= X_EXTRA_LIBS= else if test -n "$x_includes"; then X_CFLAGS="$X_CFLAGS -I$x_includes" fi # It would also be nice to do this for all -L options, not just this one. if test -n "$x_libraries"; then X_LIBS="$X_LIBS -L$x_libraries" # For Solaris; some versions of Sun CC require a space after -R and # others require no space. Words are not sufficient . . . . { echo "$as_me:$LINENO: checking whether -R must be followed by a space" >&5 echo $ECHO_N "checking whether -R must be followed by a space... $ECHO_C" >&6; } ac_xsave_LIBS=$LIBS; LIBS="$LIBS -R$x_libraries" ac_xsave_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } X_LIBS="$X_LIBS -R$x_libraries" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 LIBS="$ac_xsave_LIBS -R $x_libraries" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then { echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6; } X_LIBS="$X_LIBS -R $x_libraries" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { echo "$as_me:$LINENO: result: neither works" >&5 echo "${ECHO_T}neither works" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext ac_c_werror_flag=$ac_xsave_c_werror_flag LIBS=$ac_xsave_LIBS fi # Check for system-dependent libraries X programs must link with. # Do this before checking for the system-independent R6 libraries # (-lICE), since we may need -lsocket or whatever for X linking. if test "$ISC" = yes; then X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl_s -linet" else # Martyn Johnson says this is needed for Ultrix, if the X # libraries were built with DECnet support. And Karl Berry says # the Alpha needs dnet_stub (dnet does not exist). ac_xsave_LIBS="$LIBS"; LIBS="$LIBS $X_LIBS -lX11" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char XOpenDisplay (); int main () { return XOpenDisplay (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { echo "$as_me:$LINENO: checking for dnet_ntoa in -ldnet" >&5 echo $ECHO_N "checking for dnet_ntoa in -ldnet... $ECHO_C" >&6; } if test "${ac_cv_lib_dnet_dnet_ntoa+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldnet $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dnet_ntoa (); int main () { return dnet_ntoa (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_dnet_dnet_ntoa=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_dnet_dnet_ntoa=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_dnet_dnet_ntoa" >&5 echo "${ECHO_T}$ac_cv_lib_dnet_dnet_ntoa" >&6; } if test $ac_cv_lib_dnet_dnet_ntoa = yes; then X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet" fi if test $ac_cv_lib_dnet_dnet_ntoa = no; then { echo "$as_me:$LINENO: checking for dnet_ntoa in -ldnet_stub" >&5 echo $ECHO_N "checking for dnet_ntoa in -ldnet_stub... $ECHO_C" >&6; } if test "${ac_cv_lib_dnet_stub_dnet_ntoa+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldnet_stub $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dnet_ntoa (); int main () { return dnet_ntoa (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_dnet_stub_dnet_ntoa=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_dnet_stub_dnet_ntoa=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_dnet_stub_dnet_ntoa" >&5 echo "${ECHO_T}$ac_cv_lib_dnet_stub_dnet_ntoa" >&6; } if test $ac_cv_lib_dnet_stub_dnet_ntoa = yes; then X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet_stub" fi fi fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS="$ac_xsave_LIBS" # msh@cis.ufl.edu says -lnsl (and -lsocket) are needed for his 386/AT, # to get the SysV transport functions. # Chad R. Larson says the Pyramis MIS-ES running DC/OSx (SVR4) # needs -lnsl. # The nsl library prevents programs from opening the X display # on Irix 5.2, according to T.E. Dickey. # The functions gethostbyname, getservbyname, and inet_addr are # in -lbsd on LynxOS 3.0.1/i386, according to Lars Hecking. { echo "$as_me:$LINENO: checking for gethostbyname" >&5 echo $ECHO_N "checking for gethostbyname... $ECHO_C" >&6; } if test "${ac_cv_func_gethostbyname+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define gethostbyname to an innocuous variant, in case declares gethostbyname. For example, HP-UX 11i declares gettimeofday. */ #define gethostbyname innocuous_gethostbyname /* System header to define __stub macros and hopefully few prototypes, which can conflict with char gethostbyname (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef gethostbyname /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char gethostbyname (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_gethostbyname || defined __stub___gethostbyname choke me #endif int main () { return gethostbyname (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_func_gethostbyname=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_gethostbyname=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_func_gethostbyname" >&5 echo "${ECHO_T}$ac_cv_func_gethostbyname" >&6; } if test $ac_cv_func_gethostbyname = no; then { echo "$as_me:$LINENO: checking for gethostbyname in -lnsl" >&5 echo $ECHO_N "checking for gethostbyname in -lnsl... $ECHO_C" >&6; } if test "${ac_cv_lib_nsl_gethostbyname+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lnsl $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char gethostbyname (); int main () { return gethostbyname (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_nsl_gethostbyname=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_nsl_gethostbyname=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_nsl_gethostbyname" >&5 echo "${ECHO_T}$ac_cv_lib_nsl_gethostbyname" >&6; } if test $ac_cv_lib_nsl_gethostbyname = yes; then X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl" fi if test $ac_cv_lib_nsl_gethostbyname = no; then { echo "$as_me:$LINENO: checking for gethostbyname in -lbsd" >&5 echo $ECHO_N "checking for gethostbyname in -lbsd... $ECHO_C" >&6; } if test "${ac_cv_lib_bsd_gethostbyname+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lbsd $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char gethostbyname (); int main () { return gethostbyname (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_bsd_gethostbyname=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_bsd_gethostbyname=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_bsd_gethostbyname" >&5 echo "${ECHO_T}$ac_cv_lib_bsd_gethostbyname" >&6; } if test $ac_cv_lib_bsd_gethostbyname = yes; then X_EXTRA_LIBS="$X_EXTRA_LIBS -lbsd" fi fi fi # lieder@skyler.mavd.honeywell.com says without -lsocket, # socket/setsockopt and other routines are undefined under SCO ODT # 2.0. But -lsocket is broken on IRIX 5.2 (and is not necessary # on later versions), says Simon Leinen: it contains gethostby* # variants that don't use the name server (or something). -lsocket # must be given before -lnsl if both are needed. We assume that # if connect needs -lnsl, so does gethostbyname. { echo "$as_me:$LINENO: checking for connect" >&5 echo $ECHO_N "checking for connect... $ECHO_C" >&6; } if test "${ac_cv_func_connect+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define connect to an innocuous variant, in case declares connect. For example, HP-UX 11i declares gettimeofday. */ #define connect innocuous_connect /* System header to define __stub macros and hopefully few prototypes, which can conflict with char connect (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef connect /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char connect (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_connect || defined __stub___connect choke me #endif int main () { return connect (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_func_connect=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_connect=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_func_connect" >&5 echo "${ECHO_T}$ac_cv_func_connect" >&6; } if test $ac_cv_func_connect = no; then { echo "$as_me:$LINENO: checking for connect in -lsocket" >&5 echo $ECHO_N "checking for connect in -lsocket... $ECHO_C" >&6; } if test "${ac_cv_lib_socket_connect+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsocket $X_EXTRA_LIBS $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char connect (); int main () { return connect (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_socket_connect=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_socket_connect=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_socket_connect" >&5 echo "${ECHO_T}$ac_cv_lib_socket_connect" >&6; } if test $ac_cv_lib_socket_connect = yes; then X_EXTRA_LIBS="-lsocket $X_EXTRA_LIBS" fi fi # Guillermo Gomez says -lposix is necessary on A/UX. { echo "$as_me:$LINENO: checking for remove" >&5 echo $ECHO_N "checking for remove... $ECHO_C" >&6; } if test "${ac_cv_func_remove+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define remove to an innocuous variant, in case declares remove. For example, HP-UX 11i declares gettimeofday. */ #define remove innocuous_remove /* System header to define __stub macros and hopefully few prototypes, which can conflict with char remove (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef remove /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char remove (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_remove || defined __stub___remove choke me #endif int main () { return remove (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_func_remove=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_remove=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_func_remove" >&5 echo "${ECHO_T}$ac_cv_func_remove" >&6; } if test $ac_cv_func_remove = no; then { echo "$as_me:$LINENO: checking for remove in -lposix" >&5 echo $ECHO_N "checking for remove in -lposix... $ECHO_C" >&6; } if test "${ac_cv_lib_posix_remove+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lposix $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char remove (); int main () { return remove (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_posix_remove=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_posix_remove=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_posix_remove" >&5 echo "${ECHO_T}$ac_cv_lib_posix_remove" >&6; } if test $ac_cv_lib_posix_remove = yes; then X_EXTRA_LIBS="$X_EXTRA_LIBS -lposix" fi fi # BSDI BSD/OS 2.1 needs -lipc for XOpenDisplay. { echo "$as_me:$LINENO: checking for shmat" >&5 echo $ECHO_N "checking for shmat... $ECHO_C" >&6; } if test "${ac_cv_func_shmat+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define shmat to an innocuous variant, in case declares shmat. For example, HP-UX 11i declares gettimeofday. */ #define shmat innocuous_shmat /* System header to define __stub macros and hopefully few prototypes, which can conflict with char shmat (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef shmat /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char shmat (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_shmat || defined __stub___shmat choke me #endif int main () { return shmat (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_func_shmat=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_shmat=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_func_shmat" >&5 echo "${ECHO_T}$ac_cv_func_shmat" >&6; } if test $ac_cv_func_shmat = no; then { echo "$as_me:$LINENO: checking for shmat in -lipc" >&5 echo $ECHO_N "checking for shmat in -lipc... $ECHO_C" >&6; } if test "${ac_cv_lib_ipc_shmat+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lipc $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char shmat (); int main () { return shmat (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_ipc_shmat=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_ipc_shmat=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_ipc_shmat" >&5 echo "${ECHO_T}$ac_cv_lib_ipc_shmat" >&6; } if test $ac_cv_lib_ipc_shmat = yes; then X_EXTRA_LIBS="$X_EXTRA_LIBS -lipc" fi fi fi # Check for libraries that X11R6 Xt/Xaw programs need. ac_save_LDFLAGS=$LDFLAGS test -n "$x_libraries" && LDFLAGS="$LDFLAGS -L$x_libraries" # SM needs ICE to (dynamically) link under SunOS 4.x (so we have to # check for ICE first), but we must link in the order -lSM -lICE or # we get undefined symbols. So assume we have SM if we have ICE. # These have to be linked with before -lX11, unlike the other # libraries we check for below, so use a different variable. # John Interrante, Karl Berry { echo "$as_me:$LINENO: checking for IceConnectionNumber in -lICE" >&5 echo $ECHO_N "checking for IceConnectionNumber in -lICE... $ECHO_C" >&6; } if test "${ac_cv_lib_ICE_IceConnectionNumber+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lICE $X_EXTRA_LIBS $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char IceConnectionNumber (); int main () { return IceConnectionNumber (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_ICE_IceConnectionNumber=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_ICE_IceConnectionNumber=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_ICE_IceConnectionNumber" >&5 echo "${ECHO_T}$ac_cv_lib_ICE_IceConnectionNumber" >&6; } if test $ac_cv_lib_ICE_IceConnectionNumber = yes; then X_PRE_LIBS="$X_PRE_LIBS -lSM -lICE" fi LDFLAGS=$ac_save_LDFLAGS fi #if test x"$no_x" = xyes; then # AC_ERROR([Can not find X11 development headers or libraries.]) #fi # Checks for libraries. #AC_CHECK_LIB([X11], [XOpenDisplay], , [AC_MSG_ERROR(VIDEO: You need libx11-dev installed)]) { echo "$as_me:$LINENO: checking for main in -lgnutls-openssl" >&5 echo $ECHO_N "checking for main in -lgnutls-openssl... $ECHO_C" >&6; } if test "${ac_cv_lib_gnutls_openssl_main+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lgnutls-openssl $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_gnutls_openssl_main=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_gnutls_openssl_main=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_gnutls_openssl_main" >&5 echo "${ECHO_T}$ac_cv_lib_gnutls_openssl_main" >&6; } if test $ac_cv_lib_gnutls_openssl_main = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_LIBGNUTLS_OPENSSL 1 _ACEOF LIBS="-lgnutls-openssl $LIBS" else { { echo "$as_me:$LINENO: error: You need libgnutls11-dev installed" >&5 echo "$as_me: error: You need libgnutls11-dev installed" >&2;} { (exit 1); exit 1; }; } fi { echo "$as_me:$LINENO: checking for main in -ldl" >&5 echo $ECHO_N "checking for main in -ldl... $ECHO_C" >&6; } if test "${ac_cv_lib_dl_main+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_dl_main=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_dl_main=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_dl_main" >&5 echo "${ECHO_T}$ac_cv_lib_dl_main" >&6; } if test $ac_cv_lib_dl_main = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_LIBDL 1 _ACEOF LIBS="-ldl $LIBS" else { { echo "$as_me:$LINENO: error: You need libc6-dev installed" >&5 echo "$as_me: error: You need libc6-dev installed" >&2;} { (exit 1); exit 1; }; } fi { echo "$as_me:$LINENO: checking for FT_Init_FreeType in -lfreetype" >&5 echo $ECHO_N "checking for FT_Init_FreeType in -lfreetype... $ECHO_C" >&6; } if test "${ac_cv_lib_freetype_FT_Init_FreeType+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lfreetype $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char FT_Init_FreeType (); int main () { return FT_Init_FreeType (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_freetype_FT_Init_FreeType=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_freetype_FT_Init_FreeType=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_freetype_FT_Init_FreeType" >&5 echo "${ECHO_T}$ac_cv_lib_freetype_FT_Init_FreeType" >&6; } if test $ac_cv_lib_freetype_FT_Init_FreeType = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_LIBFREETYPE 1 _ACEOF LIBS="-lfreetype $LIBS" else { { echo "$as_me:$LINENO: error: VIDEO: You need libfreetype6-dev installed. http://freetype.sourceforge.net/index2.html" >&5 echo "$as_me: error: VIDEO: You need libfreetype6-dev installed. http://freetype.sourceforge.net/index2.html" >&2;} { (exit 1); exit 1; }; } fi # Check for SDL_gfx with different function names.. { echo "$as_me:$LINENO: checking for main in -lSDL_gfx" >&5 echo $ECHO_N "checking for main in -lSDL_gfx... $ECHO_C" >&6; } if test "${ac_cv_lib_SDL_gfx_main+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lSDL_gfx $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_SDL_gfx_main=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_SDL_gfx_main=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_SDL_gfx_main" >&5 echo "${ECHO_T}$ac_cv_lib_SDL_gfx_main" >&6; } if test $ac_cv_lib_SDL_gfx_main = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_LIBSDL_GFX 1 _ACEOF LIBS="-lSDL_gfx $LIBS" else { { echo "$as_me:$LINENO: error: VIDEO: You need libsdl-gfx1.2-dev installed. http://www.ferzkopp.net/~aschiffler/Software/SDL_gfx-2.0/" >&5 echo "$as_me: error: VIDEO: You need libsdl-gfx1.2-dev installed. http://www.ferzkopp.net/~aschiffler/Software/SDL_gfx-2.0/" >&2;} { (exit 1); exit 1; }; } fi { echo "$as_me:$LINENO: checking for filledPieRGBA" >&5 echo $ECHO_N "checking for filledPieRGBA... $ECHO_C" >&6; } if test "${ac_cv_func_filledPieRGBA+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define filledPieRGBA to an innocuous variant, in case declares filledPieRGBA. For example, HP-UX 11i declares gettimeofday. */ #define filledPieRGBA innocuous_filledPieRGBA /* System header to define __stub macros and hopefully few prototypes, which can conflict with char filledPieRGBA (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef filledPieRGBA /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char filledPieRGBA (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_filledPieRGBA || defined __stub___filledPieRGBA choke me #endif int main () { return filledPieRGBA (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_func_filledPieRGBA=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_filledPieRGBA=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_func_filledPieRGBA" >&5 echo "${ECHO_T}$ac_cv_func_filledPieRGBA" >&6; } if test $ac_cv_func_filledPieRGBA = yes; then cat >>confdefs.h <<\_ACEOF #define CAPITAL_FILLED_PIE 1 _ACEOF fi { echo "$as_me:$LINENO: checking for main in -lSDL_ttf" >&5 echo $ECHO_N "checking for main in -lSDL_ttf... $ECHO_C" >&6; } if test "${ac_cv_lib_SDL_ttf_main+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lSDL_ttf $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_SDL_ttf_main=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_SDL_ttf_main=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_SDL_ttf_main" >&5 echo "${ECHO_T}$ac_cv_lib_SDL_ttf_main" >&6; } if test $ac_cv_lib_SDL_ttf_main = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_LIBSDL_TTF 1 _ACEOF LIBS="-lSDL_ttf $LIBS" else { { echo "$as_me:$LINENO: error: VIDEO: You need libsdl-ttf2.0-dev installed. http://www.libsdl.org/projects/SDL_ttf/" >&5 echo "$as_me: error: VIDEO: You need libsdl-ttf2.0-dev installed. http://www.libsdl.org/projects/SDL_ttf/" >&2;} { (exit 1); exit 1; }; } fi { echo "$as_me:$LINENO: checking for main in -lxml2" >&5 echo $ECHO_N "checking for main in -lxml2... $ECHO_C" >&6; } if test "${ac_cv_lib_xml2_main+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lxml2 $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_xml2_main=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_xml2_main=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_xml2_main" >&5 echo "${ECHO_T}$ac_cv_lib_xml2_main" >&6; } if test $ac_cv_lib_xml2_main = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_LIBXML2 1 _ACEOF LIBS="-lxml2 $LIBS" else { { echo "$as_me:$LINENO: error: CONFIG: You need libxml2-dev installed. http://www.xmlsoft.org/" >&5 echo "$as_me: error: CONFIG: You need libxml2-dev installed. http://www.xmlsoft.org/" >&2;} { (exit 1); exit 1; }; } fi { echo "$as_me:$LINENO: checking for sqrt in -lm" >&5 echo $ECHO_N "checking for sqrt in -lm... $ECHO_C" >&6; } if test "${ac_cv_lib_m_sqrt+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lm $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char sqrt (); int main () { return sqrt (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_m_sqrt=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_m_sqrt=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_m_sqrt" >&5 echo "${ECHO_T}$ac_cv_lib_m_sqrt" >&6; } if test $ac_cv_lib_m_sqrt = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_LIBM 1 _ACEOF LIBS="-lm $LIBS" else { { echo "$as_me:$LINENO: error: CORE: You need libm installed" >&5 echo "$as_me: error: CORE: You need libm installed" >&2;} { (exit 1); exit 1; }; } fi { echo "$as_me:$LINENO: checking for pthread_self in -lpthread" >&5 echo $ECHO_N "checking for pthread_self in -lpthread... $ECHO_C" >&6; } if test "${ac_cv_lib_pthread_pthread_self+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lpthread $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char pthread_self (); int main () { return pthread_self (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_pthread_pthread_self=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_pthread_pthread_self=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_pthread_pthread_self" >&5 echo "${ECHO_T}$ac_cv_lib_pthread_pthread_self" >&6; } if test $ac_cv_lib_pthread_pthread_self = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_LIBPTHREAD 1 _ACEOF LIBS="-lpthread $LIBS" else { { echo "$as_me:$LINENO: error: CORE: You need libpthread installed" >&5 echo "$as_me: error: CORE: You need libpthread installed" >&2;} { (exit 1); exit 1; }; } fi { echo "$as_me:$LINENO: checking for main in -lasound" >&5 echo $ECHO_N "checking for main in -lasound... $ECHO_C" >&6; } if test "${ac_cv_lib_asound_main+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lasound $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_asound_main=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_asound_main=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_asound_main" >&5 echo "${ECHO_T}$ac_cv_lib_asound_main" >&6; } if test $ac_cv_lib_asound_main = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_LIBASOUND 1 _ACEOF LIBS="-lasound $LIBS" else { { echo "$as_me:$LINENO: error: AUDIO: You need ALSA installed (libasound2-dev). http://www.alsa-project.org/" >&5 echo "$as_me: error: AUDIO: You need ALSA installed (libasound2-dev). http://www.alsa-project.org/" >&2;} { (exit 1); exit 1; }; } fi { echo "$as_me:$LINENO: checking for jack_client_new in -ljack" >&5 echo $ECHO_N "checking for jack_client_new in -ljack... $ECHO_C" >&6; } if test "${ac_cv_lib_jack_jack_client_new+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ljack $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char jack_client_new (); int main () { return jack_client_new (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_jack_jack_client_new=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_jack_jack_client_new=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_jack_jack_client_new" >&5 echo "${ECHO_T}$ac_cv_lib_jack_jack_client_new" >&6; } if test $ac_cv_lib_jack_jack_client_new = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_LIBJACK 1 _ACEOF LIBS="-ljack $LIBS" else { { echo "$as_me:$LINENO: error: AUDIO: You need JACK audio library (libjack-dev) installed. http://jackit.sourceforge.net/" >&5 echo "$as_me: error: AUDIO: You need JACK audio library (libjack-dev) installed. http://jackit.sourceforge.net/" >&2;} { (exit 1); exit 1; }; } fi if test "$enable_fluidsynth" != "no"; then { echo "$as_me:$LINENO: checking for main in -lfluidsynth" >&5 echo $ECHO_N "checking for main in -lfluidsynth... $ECHO_C" >&6; } if test "${ac_cv_lib_fluidsynth_main+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lfluidsynth $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_fluidsynth_main=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_fluidsynth_main=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_fluidsynth_main" >&5 echo "${ECHO_T}$ac_cv_lib_fluidsynth_main" >&6; } if test $ac_cv_lib_fluidsynth_main = yes; then fluidsynth=yes else fluidsynth=no fi if test "$fluidsynth" = "yes"; then LIBS="$LIBS -lfluidsynth" cat >>confdefs.h <<\_ACEOF #define USE_FLUIDSYNTH 1 _ACEOF echo "--- Enabling integrated FluidSynth synth ---"; else echo "--- No libfluidsynth -- FluidSynth support will not be built! ---"; fi else echo "--- Disabling integrated FluidSynth synth ---"; fi if test "$enable_video" == "no"; then cat >>confdefs.h <<\_ACEOF #define NO_VIDEO 1 _ACEOF echo "--- Disabling video output --"; fi if test "$enable_lcd" == "yes"; then cat >>confdefs.h <<\_ACEOF #define LCD_DISPLAY 1 _ACEOF echo "--- Enabling USB LCD display --"; fi #SDL_VERSION=1.2.4 #AM_PATH_SDL($SDL_VERSION, # :, # AC_MSG_ERROR([VIDEO: *** SDL version $SDL_VERSION not found! # http://www.libsdl.org/]) #) { echo "$as_me:$LINENO: checking for main in -lvorbis" >&5 echo $ECHO_N "checking for main in -lvorbis... $ECHO_C" >&6; } if test "${ac_cv_lib_vorbis_main+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lvorbis $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_vorbis_main=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_vorbis_main=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_vorbis_main" >&5 echo "${ECHO_T}$ac_cv_lib_vorbis_main" >&6; } if test $ac_cv_lib_vorbis_main = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_LIBVORBIS 1 _ACEOF LIBS="-lvorbis $LIBS" else { { echo "$as_me:$LINENO: error: AUDIO: You need libvorbis-dev installed. http://www.xiph.org/ogg/vorbis/" >&5 echo "$as_me: error: AUDIO: You need libvorbis-dev installed. http://www.xiph.org/ogg/vorbis/" >&2;} { (exit 1); exit 1; }; } fi { echo "$as_me:$LINENO: checking for main in -lvorbisfile" >&5 echo $ECHO_N "checking for main in -lvorbisfile... $ECHO_C" >&6; } if test "${ac_cv_lib_vorbisfile_main+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lvorbisfile $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_vorbisfile_main=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_vorbisfile_main=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_vorbisfile_main" >&5 echo "${ECHO_T}$ac_cv_lib_vorbisfile_main" >&6; } if test $ac_cv_lib_vorbisfile_main = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_LIBVORBISFILE 1 _ACEOF LIBS="-lvorbisfile $LIBS" else { { echo "$as_me:$LINENO: error: AUDIO: You need libvorbisfile installed. http://www.xiph.org/ogg/vorbis/" >&5 echo "$as_me: error: AUDIO: You need libvorbisfile installed. http://www.xiph.org/ogg/vorbis/" >&2;} { (exit 1); exit 1; }; } fi { echo "$as_me:$LINENO: checking for main in -lvorbisenc" >&5 echo $ECHO_N "checking for main in -lvorbisenc... $ECHO_C" >&6; } if test "${ac_cv_lib_vorbisenc_main+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lvorbisenc $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_vorbisenc_main=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_vorbisenc_main=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_vorbisenc_main" >&5 echo "${ECHO_T}$ac_cv_lib_vorbisenc_main" >&6; } if test $ac_cv_lib_vorbisenc_main = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_LIBVORBISENC 1 _ACEOF LIBS="-lvorbisenc $LIBS" else { { echo "$as_me:$LINENO: error: AUDIO: You need libvorbis-dev installed. http://www.xiph.org/ogg/vorbis/" >&5 echo "$as_me: error: AUDIO: You need libvorbis-dev installed. http://www.xiph.org/ogg/vorbis/" >&2;} { (exit 1); exit 1; }; } fi { echo "$as_me:$LINENO: checking for main in -lsndfile" >&5 echo $ECHO_N "checking for main in -lsndfile... $ECHO_C" >&6; } if test "${ac_cv_lib_sndfile_main+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsndfile $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_sndfile_main=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_sndfile_main=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_sndfile_main" >&5 echo "${ECHO_T}$ac_cv_lib_sndfile_main" >&6; } if test $ac_cv_lib_sndfile_main = yes; then cat >>confdefs.h <<_ACEOF #define HAVE_LIBSNDFILE 1 _ACEOF LIBS="-lsndfile $LIBS" else { { echo "$as_me:$LINENO: error: AUDIO: you need libsndfile installed. http://www.http://www.mega-nerd.com/libsndfile/" >&5 echo "$as_me: error: AUDIO: you need libsndfile installed. http://www.http://www.mega-nerd.com/libsndfile/" >&2;} { (exit 1); exit 1; }; } fi CFLAGS="$CFLAGS $SDL_CFLAGS" LIBS="$X_LIBS $X_PRE_LIBS -L/usr/X11R6/lib -lX11 $X_EXTRA_LIBS $LIBS" LIBS="$LIBS $SDL_LIBS" # Checks for header files. { echo "$as_me:$LINENO: checking for X" >&5 echo $ECHO_N "checking for X... $ECHO_C" >&6; } # Check whether --with-x was given. if test "${with_x+set}" = set; then withval=$with_x; fi # $have_x is `yes', `no', `disabled', or empty when we do not yet know. if test "x$with_x" = xno; then # The user explicitly disabled X. have_x=disabled else case $x_includes,$x_libraries in #( *\'*) { { echo "$as_me:$LINENO: error: Cannot use X directory names containing '" >&5 echo "$as_me: error: Cannot use X directory names containing '" >&2;} { (exit 1); exit 1; }; };; #( *,NONE | NONE,*) if test "${ac_cv_have_x+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else # One or both of the vars are not set, and there is no cached value. ac_x_includes=no ac_x_libraries=no rm -f -r conftest.dir if mkdir conftest.dir; then cd conftest.dir cat >Imakefile <<'_ACEOF' incroot: @echo incroot='${INCROOT}' usrlibdir: @echo usrlibdir='${USRLIBDIR}' libdir: @echo libdir='${LIBDIR}' _ACEOF if (export CC; ${XMKMF-xmkmf}) >/dev/null 2>/dev/null && test -f Makefile; then # GNU make sometimes prints "make[1]: Entering...", which would confuse us. for ac_var in incroot usrlibdir libdir; do eval "ac_im_$ac_var=\`\${MAKE-make} $ac_var 2>/dev/null | sed -n 's/^$ac_var=//p'\`" done # Open Windows xmkmf reportedly sets LIBDIR instead of USRLIBDIR. for ac_extension in a so sl; do if test ! -f "$ac_im_usrlibdir/libX11.$ac_extension" && test -f "$ac_im_libdir/libX11.$ac_extension"; then ac_im_usrlibdir=$ac_im_libdir; break fi done # Screen out bogus values from the imake configuration. They are # bogus both because they are the default anyway, and because # using them would break gcc on systems where it needs fixed includes. case $ac_im_incroot in /usr/include) ac_x_includes= ;; *) test -f "$ac_im_incroot/X11/Xos.h" && ac_x_includes=$ac_im_incroot;; esac case $ac_im_usrlibdir in /usr/lib | /lib) ;; *) test -d "$ac_im_usrlibdir" && ac_x_libraries=$ac_im_usrlibdir ;; esac fi cd .. rm -f -r conftest.dir fi # Standard set of common directories for X headers. # Check X11 before X11Rn because it is often a symlink to the current release. ac_x_header_dirs=' /usr/X11/include /usr/X11R6/include /usr/X11R5/include /usr/X11R4/include /usr/include/X11 /usr/include/X11R6 /usr/include/X11R5 /usr/include/X11R4 /usr/local/X11/include /usr/local/X11R6/include /usr/local/X11R5/include /usr/local/X11R4/include /usr/local/include/X11 /usr/local/include/X11R6 /usr/local/include/X11R5 /usr/local/include/X11R4 /usr/X386/include /usr/x386/include /usr/XFree86/include/X11 /usr/include /usr/local/include /usr/unsupported/include /usr/athena/include /usr/local/x11r5/include /usr/lpp/Xamples/include /usr/openwin/include /usr/openwin/share/include' if test "$ac_x_includes" = no; then # Guess where to find include files, by looking for Xlib.h. # First, try using that file with no special directory specified. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then # We can compile using X headers with no special include directory. ac_x_includes= else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 for ac_dir in $ac_x_header_dirs; do if test -r "$ac_dir/X11/Xlib.h"; then ac_x_includes=$ac_dir break fi done fi rm -f conftest.err conftest.$ac_ext fi # $ac_x_includes = no if test "$ac_x_libraries" = no; then # Check for the libraries. # See if we find them without any special options. # Don't add to $LIBS permanently. ac_save_LIBS=$LIBS LIBS="-lX11 $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { XrmInitialize () ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then LIBS=$ac_save_LIBS # We can link X programs with no special library path. ac_x_libraries= else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 LIBS=$ac_save_LIBS for ac_dir in `echo "$ac_x_includes $ac_x_header_dirs" | sed s/include/lib/g` do # Don't even attempt the hair of trying to link an X program! for ac_extension in a so sl; do if test -r "$ac_dir/libX11.$ac_extension"; then ac_x_libraries=$ac_dir break 2 fi done done fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi # $ac_x_libraries = no case $ac_x_includes,$ac_x_libraries in #( no,* | *,no | *\'*) # Didn't find X, or a directory has "'" in its name. ac_cv_have_x="have_x=no";; #( *) # Record where we found X for the cache. ac_cv_have_x="have_x=yes\ ac_x_includes='$ac_x_includes'\ ac_x_libraries='$ac_x_libraries'" esac fi ;; #( *) have_x=yes;; esac eval "$ac_cv_have_x" fi # $with_x != no if test "$have_x" != yes; then { echo "$as_me:$LINENO: result: $have_x" >&5 echo "${ECHO_T}$have_x" >&6; } no_x=yes else # If each of the values was on the command line, it overrides each guess. test "x$x_includes" = xNONE && x_includes=$ac_x_includes test "x$x_libraries" = xNONE && x_libraries=$ac_x_libraries # Update the cache value to reflect the command line values. ac_cv_have_x="have_x=yes\ ac_x_includes='$x_includes'\ ac_x_libraries='$x_libraries'" { echo "$as_me:$LINENO: result: libraries $x_libraries, headers $x_includes" >&5 echo "${ECHO_T}libraries $x_libraries, headers $x_includes" >&6; } fi { echo "$as_me:$LINENO: checking for grep that handles long lines and -e" >&5 echo $ECHO_N "checking for grep that handles long lines and -e... $ECHO_C" >&6; } if test "${ac_cv_path_GREP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else # Extract the first word of "grep ggrep" to use in msg output if test -z "$GREP"; then set dummy grep ggrep; ac_prog_name=$2 if test "${ac_cv_path_GREP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_path_GREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in grep ggrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in *GNU*) ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; *) ac_count=0 echo $ECHO_N "0123456789$ECHO_C" >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" echo 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break ac_count=`expr $ac_count + 1` if test $ac_count -gt ${ac_path_GREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_GREP_found && break 3 done done done IFS=$as_save_IFS fi GREP="$ac_cv_path_GREP" if test -z "$GREP"; then { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5 echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;} { (exit 1); exit 1; }; } fi else ac_cv_path_GREP=$GREP fi fi { echo "$as_me:$LINENO: result: $ac_cv_path_GREP" >&5 echo "${ECHO_T}$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { echo "$as_me:$LINENO: checking for egrep" >&5 echo $ECHO_N "checking for egrep... $ECHO_C" >&6; } if test "${ac_cv_path_EGREP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else # Extract the first word of "egrep" to use in msg output if test -z "$EGREP"; then set dummy egrep; ac_prog_name=$2 if test "${ac_cv_path_EGREP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_path_EGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in egrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in *GNU*) ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; *) ac_count=0 echo $ECHO_N "0123456789$ECHO_C" >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" echo 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break ac_count=`expr $ac_count + 1` if test $ac_count -gt ${ac_path_EGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_found && break 3 done done done IFS=$as_save_IFS fi EGREP="$ac_cv_path_EGREP" if test -z "$EGREP"; then { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5 echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;} { (exit 1); exit 1; }; } fi else ac_cv_path_EGREP=$EGREP fi fi fi { echo "$as_me:$LINENO: result: $ac_cv_path_EGREP" >&5 echo "${ECHO_T}$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" { echo "$as_me:$LINENO: checking for ANSI C header files" >&5 echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6; } if test "${ac_cv_header_stdc+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_header_stdc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF rm -f conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_try") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then : else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi fi { echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 echo "${ECHO_T}$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then cat >>confdefs.h <<\_ACEOF #define STDC_HEADERS 1 _ACEOF fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then eval "$as_ac_Header=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_Header=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&6; } if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in errno.h stdlib.h string.h sys/time.h unistd.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&6; } else # Is the header compilable? { echo "$as_me:$LINENO: checking $ac_header usability" >&5 echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6; } # Is the header present? { echo "$as_me:$LINENO: checking $ac_header presence" >&5 echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ;; esac { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&6; } fi if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done # Checks for typedefs, structures, and compiler characteristics. { echo "$as_me:$LINENO: checking for an ANSI C-conforming const" >&5 echo $ECHO_N "checking for an ANSI C-conforming const... $ECHO_C" >&6; } if test "${ac_cv_c_const+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { /* FIXME: Include the comments suggested by Paul. */ #ifndef __cplusplus /* Ultrix mips cc rejects this. */ typedef int charset[2]; const charset cs; /* SunOS 4.1.1 cc rejects this. */ char const *const *pcpcc; char **ppc; /* NEC SVR4.0.2 mips cc rejects this. */ struct point {int x, y;}; static struct point const zero = {0,0}; /* AIX XL C 1.02.0.0 rejects this. It does not let you subtract one const X* pointer from another in an arm of an if-expression whose if-part is not a constant expression */ const char *g = "string"; pcpcc = &g + (g ? g-g : 0); /* HPUX 7.0 cc rejects these. */ ++pcpcc; ppc = (char**) pcpcc; pcpcc = (char const *const *) ppc; { /* SCO 3.2v4 cc rejects this. */ char *t; char const *s = 0 ? (char *) 0 : (char const *) 0; *t++ = 0; if (s) return 0; } { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ int x[] = {25, 17}; const int *foo = &x[0]; ++foo; } { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ typedef const int *iptr; iptr p = 0; ++p; } { /* AIX XL C 1.02.0.0 rejects this saying "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ struct s { int j; const int *ap[3]; }; struct s *b; b->j = 5; } { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ const int foo = 10; if (!foo) return 0; } return !cs[0] && !zero.x; #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_c_const=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_c_const=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_c_const" >&5 echo "${ECHO_T}$ac_cv_c_const" >&6; } if test $ac_cv_c_const = no; then cat >>confdefs.h <<\_ACEOF #define const _ACEOF fi { echo "$as_me:$LINENO: checking whether time.h and sys/time.h may both be included" >&5 echo $ECHO_N "checking whether time.h and sys/time.h may both be included... $ECHO_C" >&6; } if test "${ac_cv_header_time+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #include int main () { if ((struct tm *) 0) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_header_time=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_header_time=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_header_time" >&5 echo "${ECHO_T}$ac_cv_header_time" >&6; } if test $ac_cv_header_time = yes; then cat >>confdefs.h <<\_ACEOF #define TIME_WITH_SYS_TIME 1 _ACEOF fi # Checks for library functions. for ac_func in floor gettimeofday memset pow sqrt do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` { echo "$as_me:$LINENO: checking for $ac_func" >&5 echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define $ac_func to an innocuous variant, in case declares $ac_func. For example, HP-UX 11i declares gettimeofday. */ #define $ac_func innocuous_$ac_func /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $ac_func /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $ac_func (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$ac_func || defined __stub___$ac_func choke me #endif int main () { return $ac_func (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then eval "$as_ac_var=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_var=no" fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi ac_res=`eval echo '${'$as_ac_var'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&6; } if test `eval echo '${'$as_ac_var'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done ac_config_files="$ac_config_files Makefile src/Makefile data/Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( *) $as_unset $ac_var ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes (double-quote # substitution turns \\\\ into \\, and sed turns \\ into \). sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then test "x$cache_file" != "x/dev/null" && { echo "$as_me:$LINENO: updating cache $cache_file" >&5 echo "$as_me: updating cache $cache_file" >&6;} cat confcache >$cache_file else { echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5 echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' # Transform confdefs.h into DEFS. # Protect against shell expansion while executing Makefile rules. # Protect against Makefile macro expansion. # # If the first sed substitution is executed (which looks for macros that # take arguments), then branch to the quote section. Otherwise, # look for a macro that doesn't take arguments. ac_script=' t clear :clear s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g t quote s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g t quote b any :quote s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g s/\[/\\&/g s/\]/\\&/g s/\$/$$/g H :any ${ g s/^\n// s/\n/ /g p } ' DEFS=`sed -n "$ac_script" confdefs.h` ac_libobjs= ac_ltlibobjs= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. ac_libobjs="$ac_libobjs \${LIBOBJDIR}$ac_i\$U.$ac_objext" ac_ltlibobjs="$ac_ltlibobjs \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"AMDEP\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"AMDEP\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"am__fastdepCXX\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"am__fastdepCXX\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi : ${CONFIG_STATUS=./config.status} ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 echo "$as_me: creating $CONFIG_STATUS" >&6;} cat >$CONFIG_STATUS <<_ACEOF #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF ## --------------------- ## ## M4sh Initialization. ## ## --------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac fi # PATH needs CR # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then echo "#! /bin/sh" >conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi # Support unset when possible. if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then as_unset=unset else as_unset=false fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) as_nl=' ' IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. case $0 in *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 { (exit 1); exit 1; } fi # Work around bugs in pre-3.0 UWIN ksh. for as_var in ENV MAIL MAILPATH do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. for as_var in \ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ LC_TELEPHONE LC_TIME do if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then eval $as_var=C; export $as_var else ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var fi done # Required to use basename. if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi # Name of the executable. as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # CDPATH. $as_unset CDPATH as_lineno_1=$LINENO as_lineno_2=$LINENO test "x$as_lineno_1" != "x$as_lineno_2" && test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || { # Create $as_me.lineno as a copy of $as_myself, but with $LINENO # uniformly replaced by the line number. The first 'sed' inserts a # line-number line after each line using $LINENO; the second 'sed' # does the real work. The second script uses 'N' to pair each # line-number line with the line containing $LINENO, and appends # trailing '-' during substitution so that $LINENO is not a special # case at line end. # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the # scripts with optimization help from Paolo Bonzini. Blame Lee # E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 { (exit 1); exit 1; }; } # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in -n*) case `echo 'x\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. *) ECHO_C='\c';; esac;; *) ECHO_N='-n';; esac if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir fi echo >conf$$.file if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -p'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -p' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p=: else test -d ./-p && rmdir ./-p as_mkdir_p=false fi if test -x / >/dev/null 2>&1; then as_test_x='test -x' else if ls -dL / >/dev/null 2>&1; then as_ls_L_option=L else as_ls_L_option= fi as_test_x=' eval sh -c '\'' if test -d "$1"; then test -d "$1/."; else case $1 in -*)set "./$1";; esac; case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in ???[sx]*):;;*)false;;esac;fi '\'' sh ' fi as_executable_p=$as_test_x # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 # Save the log message, to keep $[0] and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by $as_me, which was generated by GNU Autoconf 2.61. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF cat >>$CONFIG_STATUS <<_ACEOF # Files that config.status was made for. config_files="$ac_config_files" config_commands="$ac_config_commands" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF ac_cs_usage="\ \`$as_me' instantiates files from templates according to the current configuration. Usage: $0 [OPTIONS] [FILE]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit -q, --quiet do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE Configuration files: $config_files Configuration commands: $config_commands Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF ac_cs_version="\\ config.status configured by $0, generated by GNU Autoconf 2.61, with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" Copyright (C) 2006 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' INSTALL='$INSTALL' MKDIR_P='$MKDIR_P' _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF # If no file are specified by the user, then we need to provide default # value. By we need to know if files were specified by the user. ac_need_defaults=: while test $# != 0 do case $1 in --*=*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) echo "$ac_cs_version"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift CONFIG_FILES="$CONFIG_FILES $ac_optarg" ac_need_defaults=false;; --he | --h | --help | --hel | -h ) echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) { echo "$as_me: error: unrecognized option: $1 Try \`$0 --help' for more information." >&2 { (exit 1); exit 1; }; } ;; *) ac_config_targets="$ac_config_targets $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF if \$ac_cs_recheck; then echo "running CONFIG_SHELL=$SHELL $SHELL $0 "$ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 CONFIG_SHELL=$SHELL export CONFIG_SHELL exec $SHELL "$0"$ac_configure_args \$ac_configure_extra_args --no-create --no-recursion fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF # # INIT-COMMANDS # AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;; "data/Makefile") CONFIG_FILES="$CONFIG_FILES data/Makefile" ;; *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 echo "$as_me: error: invalid argument: $ac_config_target" >&2;} { (exit 1); exit 1; }; };; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= trap 'exit_status=$? { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status ' 0 trap '{ (exit 1); exit 1; }' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || { echo "$me: cannot create a temporary directory in ." >&2 { (exit 1); exit 1; } } # # Set up the sed scripts for CONFIG_FILES section. # # No need to generate the scripts if there are no CONFIG_FILES. # This happens for instance when ./config.status config.h if test -n "$CONFIG_FILES"; then _ACEOF ac_delim='%!_!# ' for ac_last_try in false false false false false :; do cat >conf$$subs.sed <<_ACEOF SHELL!$SHELL$ac_delim PATH_SEPARATOR!$PATH_SEPARATOR$ac_delim PACKAGE_NAME!$PACKAGE_NAME$ac_delim PACKAGE_TARNAME!$PACKAGE_TARNAME$ac_delim PACKAGE_VERSION!$PACKAGE_VERSION$ac_delim PACKAGE_STRING!$PACKAGE_STRING$ac_delim PACKAGE_BUGREPORT!$PACKAGE_BUGREPORT$ac_delim exec_prefix!$exec_prefix$ac_delim prefix!$prefix$ac_delim program_transform_name!$program_transform_name$ac_delim bindir!$bindir$ac_delim sbindir!$sbindir$ac_delim libexecdir!$libexecdir$ac_delim datarootdir!$datarootdir$ac_delim datadir!$datadir$ac_delim sysconfdir!$sysconfdir$ac_delim sharedstatedir!$sharedstatedir$ac_delim localstatedir!$localstatedir$ac_delim includedir!$includedir$ac_delim oldincludedir!$oldincludedir$ac_delim docdir!$docdir$ac_delim infodir!$infodir$ac_delim htmldir!$htmldir$ac_delim dvidir!$dvidir$ac_delim pdfdir!$pdfdir$ac_delim psdir!$psdir$ac_delim libdir!$libdir$ac_delim localedir!$localedir$ac_delim mandir!$mandir$ac_delim DEFS!$DEFS$ac_delim ECHO_C!$ECHO_C$ac_delim ECHO_N!$ECHO_N$ac_delim ECHO_T!$ECHO_T$ac_delim LIBS!$LIBS$ac_delim build_alias!$build_alias$ac_delim host_alias!$host_alias$ac_delim target_alias!$target_alias$ac_delim INSTALL_PROGRAM!$INSTALL_PROGRAM$ac_delim INSTALL_SCRIPT!$INSTALL_SCRIPT$ac_delim INSTALL_DATA!$INSTALL_DATA$ac_delim am__isrc!$am__isrc$ac_delim CYGPATH_W!$CYGPATH_W$ac_delim PACKAGE!$PACKAGE$ac_delim VERSION!$VERSION$ac_delim ACLOCAL!$ACLOCAL$ac_delim AUTOCONF!$AUTOCONF$ac_delim AUTOMAKE!$AUTOMAKE$ac_delim AUTOHEADER!$AUTOHEADER$ac_delim MAKEINFO!$MAKEINFO$ac_delim install_sh!$install_sh$ac_delim STRIP!$STRIP$ac_delim INSTALL_STRIP_PROGRAM!$INSTALL_STRIP_PROGRAM$ac_delim mkdir_p!$mkdir_p$ac_delim AWK!$AWK$ac_delim SET_MAKE!$SET_MAKE$ac_delim am__leading_dot!$am__leading_dot$ac_delim AMTAR!$AMTAR$ac_delim am__tar!$am__tar$ac_delim am__untar!$am__untar$ac_delim CXX!$CXX$ac_delim CXXFLAGS!$CXXFLAGS$ac_delim LDFLAGS!$LDFLAGS$ac_delim CPPFLAGS!$CPPFLAGS$ac_delim ac_ct_CXX!$ac_ct_CXX$ac_delim EXEEXT!$EXEEXT$ac_delim OBJEXT!$OBJEXT$ac_delim DEPDIR!$DEPDIR$ac_delim am__include!$am__include$ac_delim am__quote!$am__quote$ac_delim AMDEP_TRUE!$AMDEP_TRUE$ac_delim AMDEP_FALSE!$AMDEP_FALSE$ac_delim AMDEPBACKSLASH!$AMDEPBACKSLASH$ac_delim CXXDEPMODE!$CXXDEPMODE$ac_delim am__fastdepCXX_TRUE!$am__fastdepCXX_TRUE$ac_delim am__fastdepCXX_FALSE!$am__fastdepCXX_FALSE$ac_delim CC!$CC$ac_delim CFLAGS!$CFLAGS$ac_delim ac_ct_CC!$ac_ct_CC$ac_delim CCDEPMODE!$CCDEPMODE$ac_delim am__fastdepCC_TRUE!$am__fastdepCC_TRUE$ac_delim am__fastdepCC_FALSE!$am__fastdepCC_FALSE$ac_delim XMKMF!$XMKMF$ac_delim CPP!$CPP$ac_delim X_CFLAGS!$X_CFLAGS$ac_delim X_PRE_LIBS!$X_PRE_LIBS$ac_delim X_LIBS!$X_LIBS$ac_delim X_EXTRA_LIBS!$X_EXTRA_LIBS$ac_delim GREP!$GREP$ac_delim EGREP!$EGREP$ac_delim LIBOBJS!$LIBOBJS$ac_delim LTLIBOBJS!$LTLIBOBJS$ac_delim _ACEOF if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 91; then break elif $ac_last_try; then { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 echo "$as_me: error: could not make $CONFIG_STATUS" >&2;} { (exit 1); exit 1; }; } else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed` if test -n "$ac_eof"; then ac_eof=`echo "$ac_eof" | sort -nru | sed 1q` ac_eof=`expr $ac_eof + 1` fi cat >>$CONFIG_STATUS <<_ACEOF cat >"\$tmp/subs-1.sed" <<\CEOF$ac_eof /@[a-zA-Z_][a-zA-Z_0-9]*@/!b end _ACEOF sed ' s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g s/^/s,@/; s/!/@,|#_!!_#|/ :n t n s/'"$ac_delim"'$/,g/; t s/$/\\/; p N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n ' >>$CONFIG_STATUS >$CONFIG_STATUS <<_ACEOF :end s/|#_!!_#|//g CEOF$ac_eof _ACEOF # VPATH may cause trouble with some makes, so we remove $(srcdir), # ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=/{ s/:*\$(srcdir):*/:/ s/:*\${srcdir}:*/:/ s/:*@srcdir@:*/:/ s/^\([^=]*=[ ]*\):*/\1/ s/:*$// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF fi # test -n "$CONFIG_FILES" for ac_tag in :F $CONFIG_FILES :C $CONFIG_COMMANDS do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) { { echo "$as_me:$LINENO: error: Invalid tag $ac_tag." >&5 echo "$as_me: error: Invalid tag $ac_tag." >&2;} { (exit 1); exit 1; }; };; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || { { echo "$as_me:$LINENO: error: cannot find input file: $ac_f" >&5 echo "$as_me: error: cannot find input file: $ac_f" >&2;} { (exit 1); exit 1; }; };; esac ac_file_inputs="$ac_file_inputs $ac_f" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input="Generated from "`IFS=: echo $* | sed 's|^[^:]*/||;s|:[^:]*/|, |g'`" by configure." if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { echo "$as_me:$LINENO: creating $ac_file" >&5 echo "$as_me: creating $ac_file" >&6;} fi case $ac_tag in *:-:* | *:-) cat >"$tmp/stdin";; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` { as_dir="$ac_dir" case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5 echo "$as_me: error: cannot create directory $as_dir" >&2;} { (exit 1); exit 1; }; }; } ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # case $INSTALL in [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; esac ac_MKDIR_P=$MKDIR_P case $MKDIR_P in [\\/$]* | ?:[\\/]* ) ;; */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; esac _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= case `sed -n '/datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p ' $ac_file_inputs` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { echo "$as_me:$LINENO: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF sed "$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s&@configure_input@&$configure_input&;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t s&@INSTALL@&$ac_INSTALL&;t t s&@MKDIR_P@&$ac_MKDIR_P&;t t $ac_datarootdir_hack " $ac_file_inputs | sed -f "$tmp/subs-1.sed" >$tmp/out test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } && { echo "$as_me:$LINENO: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined." >&5 echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined." >&2;} rm -f "$tmp/stdin" case $ac_file in -) cat "$tmp/out"; rm -f "$tmp/out";; *) rm -f "$ac_file"; mv "$tmp/out" $ac_file;; esac ;; :C) { echo "$as_me:$LINENO: executing $ac_file commands" >&5 echo "$as_me: executing $ac_file commands" >&6;} ;; esac case $ac_file$ac_mode in "depfiles":C) test x"$AMDEP_TRUE" != x"" || for mf in $CONFIG_FILES; do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named `Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # Grep'ing the whole file is not good either: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. if sed 10q "$mf" | grep '^#.*generated by automake' > /dev/null 2>&1; then dirpart=`$as_dirname -- "$mf" || $as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$mf" : 'X\(//\)[^/]' \| \ X"$mf" : 'X\(//\)$' \| \ X"$mf" : 'X\(/\)' \| . 2>/dev/null || echo X"$mf" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running `make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # When using ansi2knr, U may be empty or an underscore; expand it U=`sed -n 's/^U = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`$as_dirname -- "$file" || $as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$file" : 'X\(//\)[^/]' \| \ X"$file" : 'X\(//\)$' \| \ X"$file" : 'X\(/\)' \| . 2>/dev/null || echo X"$file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` { as_dir=$dirpart/$fdir case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5 echo "$as_me: error: cannot create directory $as_dir" >&2;} { (exit 1); exit 1; }; }; } # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done ;; esac done # for ac_tag { (exit 0); exit 0; } _ACEOF chmod +x $CONFIG_STATUS ac_clean_files=$ac_clean_files_save # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || { (exit 1); exit 1; } fi fweelin-0.6/configure.ac0000755000175000017500000000775511071520634013754 0ustar mercmerc# Process this file with autoconf to produce a configure script. AC_INIT(src/fweelin.cc) AM_INIT_AUTOMAKE(fweelin,0.6) AC_CONFIG_SRCDIR([src/fweelin.cc]) #AM_CONFIG_HEADER(config.h) AC_ARG_ENABLE(fluidsynth,[ --enable-fluidsynth use integrated FluidSynth softsynth (libfluidsynth) (default=auto) ]) AC_ARG_ENABLE(video,[ --disable-video disable video output ]) AC_ARG_ENABLE(lcd,[ --enable-lcd enable USB LCD display output ]) # Checks for programs. AC_PROG_CXX AC_PROG_CC # Add Xtra Paths for Checking AC_PATH_XTRA #if test x"$no_x" = xyes; then # AC_ERROR([Can not find X11 development headers or libraries.]) #fi # Checks for libraries. #AC_CHECK_LIB([X11], [XOpenDisplay], , [AC_MSG_ERROR(VIDEO: You need libx11-dev installed)]) AC_CHECK_LIB([gnutls-openssl], [main], , [AC_MSG_ERROR(You need libgnutls11-dev installed)]) AC_CHECK_LIB([dl], [main], , [AC_MSG_ERROR(You need libc6-dev installed)]) AC_CHECK_LIB([freetype], [FT_Init_FreeType], , [AC_MSG_ERROR(VIDEO: You need libfreetype6-dev installed. http://freetype.sourceforge.net/index2.html)]) # Check for SDL_gfx with different function names.. AC_CHECK_LIB([SDL_gfx], [main], , [AC_MSG_ERROR(VIDEO: You need libsdl-gfx1.2-dev installed. http://www.ferzkopp.net/~aschiffler/Software/SDL_gfx-2.0/)]) AC_CHECK_FUNC(filledPieRGBA, [AC_DEFINE(CAPITAL_FILLED_PIE)]) AC_CHECK_LIB([SDL_ttf], [main], , [AC_MSG_ERROR(VIDEO: You need libsdl-ttf2.0-dev installed. http://www.libsdl.org/projects/SDL_ttf/)]) AC_CHECK_LIB([xml2], [main], , [AC_MSG_ERROR(CONFIG: You need libxml2-dev installed. http://www.xmlsoft.org/)]) AC_CHECK_LIB([m], [sqrt], , [AC_MSG_ERROR(CORE: You need libm installed)]) AC_CHECK_LIB([pthread], [pthread_self], , [AC_MSG_ERROR(CORE: You need libpthread installed)]) AC_CHECK_LIB([asound], [main], , [AC_MSG_ERROR(AUDIO: You need ALSA installed (libasound2-dev). http://www.alsa-project.org/)]) AC_CHECK_LIB([jack], [jack_client_new], , [AC_MSG_ERROR(AUDIO: You need JACK audio library (libjack-dev) installed. http://jackit.sourceforge.net/)]) if test "$enable_fluidsynth" != "no"; then AC_CHECK_LIB([fluidsynth], [main], fluidsynth=yes, fluidsynth=no) if test "$fluidsynth" = "yes"; then LIBS="$LIBS -lfluidsynth" AC_DEFINE(USE_FLUIDSYNTH, 1, [Define if FluidSynth support should be enabled]) echo "--- Enabling integrated FluidSynth synth ---"; else echo "--- No libfluidsynth -- FluidSynth support will not be built! ---"; fi else echo "--- Disabling integrated FluidSynth synth ---"; fi if test "$enable_video" == "no"; then AC_DEFINE(NO_VIDEO, 1, [Define if video output is disabled]) echo "--- Disabling video output --"; fi if test "$enable_lcd" == "yes"; then AC_DEFINE(LCD_DISPLAY, 1, [Define if USB LCD display is enabled]) echo "--- Enabling USB LCD display --"; fi #SDL_VERSION=1.2.4 #AM_PATH_SDL($SDL_VERSION, # :, # AC_MSG_ERROR([VIDEO: *** SDL version $SDL_VERSION not found! # http://www.libsdl.org/]) #) AC_CHECK_LIB([vorbis], [main], , [AC_MSG_ERROR(AUDIO: You need libvorbis-dev installed. http://www.xiph.org/ogg/vorbis/)]) AC_CHECK_LIB([vorbisfile], [main], , [AC_MSG_ERROR(AUDIO: You need libvorbisfile installed. http://www.xiph.org/ogg/vorbis/)]) AC_CHECK_LIB([vorbisenc], [main], , [AC_MSG_ERROR(AUDIO: You need libvorbis-dev installed. http://www.xiph.org/ogg/vorbis/)]) AC_CHECK_LIB([sndfile], [main], , [AC_MSG_ERROR(AUDIO: you need libsndfile installed. http://www.http://www.mega-nerd.com/libsndfile/)]) CFLAGS="$CFLAGS $SDL_CFLAGS" LIBS="$X_LIBS $X_PRE_LIBS -L/usr/X11R6/lib -lX11 $X_EXTRA_LIBS $LIBS" LIBS="$LIBS $SDL_LIBS" # Checks for header files. AC_PATH_X AC_HEADER_STDC AC_CHECK_HEADERS([errno.h stdlib.h string.h sys/time.h unistd.h]) # Checks for typedefs, structures, and compiler characteristics. AC_C_CONST AC_HEADER_TIME # Checks for library functions. AC_CHECK_FUNCS([floor gettimeofday memset pow sqrt]) AC_OUTPUT(Makefile src/Makefile data/Makefile) fweelin-0.6/src/elastin/0000755000175000017500000000000010746275475013715 5ustar mercmercfweelin-0.6/src/elastin/elastin.cc0000644000175000017500000011153110724066726015656 0ustar mercmerc// 500 2500 500 500 2.0 2.0 // 1000 2500 1500 128 5.0 2.0 (better freq stability) (*best*) // 1000 2500 1500 1000 5.0 2.0 (smoother?) // These numbers break it: seems to happen for many ratescales below 1.0, // with -odd- numbers: // 1000 2500 1500 128 1000 5.0 1.0 0.64 0.0 0.0 // *** For FW: // // *** Add functions to RT modify parameters // *** Compensate for shift in loopstartpt/loopendpt (adjust timedelta) // OK Implement counter that tells us how far into the original sample we've // synthesized at any point (ie generated samples / stretch factor for period) // // OK Implement continuous looping of sample (calc loop points and synthesize // in loop mode) (*accomodate 'tail' when calculating loop points*) // // OK Implement RATE shift and "pitch" shift (using combined stretch/rate) // // *** Analyze with 'shorts' // *** Variable crossfade length (longer crossfades seem to produce more // consistent harmonics, but add 'subtle echos' on transients-- balance) // *** Optimize analysis (most melodic passages have consistent chunk lengths) // *** Bug on 1.0 stretch-- extra samples written (crossfadelen samples) // *** Interpolate chunks // Split harmonic / inharmonic portion // .. use IFFT phasevoc for harmonic (or large fragmentsize) // .. use timedomain for noise p // .. or use separate timedomain SOLA methods on each portion // TEST RESULTS using women2/women2b. // show that it's OK to encode/decode sample and keep markers // (as would happen in saving/loading loops) // hard to detect quality loss // OLD NOTES // Idea: Within each chunk we have subchunks // We also subdivide by frequency bands. // // OK* Move beginning of chunk instead of j2 pos (alternate) // (on seven.wav, sounds better with alternate movepoints) // *** Anticipatory repeat-- if we know some poorly scored areas are coming up // **** Recursive analysis-- we go into poorly scored areas with subresolution // to extract smaller repeating segments // *** Problems seem to occur around transients... subresolution around // areas with sharp peaks? // Use peak profile to pick spots to reduce chunksize... zoom in on those // areas // -or- // use really small chunks and do correlation between chunks // then string together many successive chunks that are very similar // (correlate well to each other) and repeat the whole set, instead of // just one at a time (better frequency resolution) #include #include #include "elastin.h" // Favor next chunk threshhold- // A higher FAVOR_THRESH means the next chunk has to be -significantly- // better than this chunk for crossfading to be chosen. #define FAVOR_THRESH 0.5 // How much better (reduced ratio) does a static chunk insertion have to be // before we go ahead and do it #define MOVETHRESH 0.9 Elastin_Data::~Elastin_Data() { // *** Free analysis data! Elastin_Jump *cur = firstj; while (cur != 0) { Elastin_Jump *tmp = cur->next; delete cur; cur = tmp; } if (loopj != 0) delete loopj; }; Elastin::~Elastin() { if (sbufs != 0) Takedown_SampleBufs(); }; void Elastin::Takedown_SampleBufs() { // *** Free sample buffers for (int i = 0; i < d->numch; i++) delete[] sbufs[i]; delete[] sbufs; }; void Elastin::Setup_SampleBufs() { // *** Allocate sample buffers sbufs = new el_sample_t *[d->numch]; for (int i = 0; i < d->numch; i++) sbufs[i] = new el_sample_t[(d->maxchunk+d->cmpchunk)*2]; }; Elastin_Data *Elastin::Analyze_Start (Elastin_SampleFeed *feed, el_nframes_t maxcrossfadelen, el_nframes_t minchunk, el_nframes_t maxchunk, el_nframes_t cmpchunk) { if (cmpchunk > maxchunk) return 0; if (d != 0 && d->firstj != 0) return 0; if (d != 0) fprintf(stderr,"ELASTIN: WARNING: Starting analyze when already attached " "to an Elastin_Data\n"); d = new Elastin_Data(); d->feed = feed; d->minchunk = minchunk; d->maxchunk = maxchunk; d->cmpchunk = cmpchunk; d->slen = feed->GetLength(); d->numch = feed->GetNumChannels(); if (d->numch <= 0) return 0; if (sbufs != 0) Takedown_SampleBufs(); Setup_SampleBufs(); if (maxcrossfadelen != 0) // Add static chunk for beginning d->AddJump(new Elastin_Jump(0,maxcrossfadelen, maxcrossfadelen,-1,JUMPFLAG_STATIC)); #if 0 // DEPRECATED- mono // Now scan the whole sample and extract amplitude envelope #define AMPENV_CHUNK 512 el_sample_t *ampbuf = new el_sample_t[AMPENV_CHUNK]; el_nframes_t apos = 0; el_nframes_t ampenvlen = slen/AMPENV_CHUNK; el_sample_t *ampenv = 0; if (ampenvlen > 0) ampenv = new el_sample_t[ampenvlen]; int ampenvidx = 0; while (ampenvidx < ampenvlen) { el_nframes_t aremaining = slen-apos; if (aremaining > AMPENV_CHUNK) aremaining = AMPENV_CHUNK; // Get samples feed->GetSamples(apos,aremaining,ampbuf); // Compute amplitude for this chunk if (aremaining > 0) { register el_sample_t amp = 0.0; for (register el_nframes_t n = 0; n < aremaining; n++) amp += fabs(ampbuf[n]); ampenv[ampenvidx] = amp/aremaining; } else ampenv[ampenvidx] = 0; if (ampenvidx > 0 && ampenvidx+1 < ampenvlen) DEBUGPRINT("d: %f\n",ampenv[ampenvidx]-ampenv[ampenvidx-1]); // Advance ampenvidx++; apos += aremaining; } delete[] ampbuf; #endif spos = maxcrossfadelen; return d; }; int Elastin::Analyze_Stop (el_nframes_t loopstartpt, el_nframes_t loopendpt) { if (d == 0) return -1; if (d->analysisdone) { // Add last chunks (static) if (d->lastj != 0) { if (d->slen - d->lastj->j2 > d->maxchunk*2) fprintf(stderr,"ELASTIN: ERROR: End static chunk too large!\n"); d->AddJump(new Elastin_Jump(d->lastj->j2, d->slen, d->slen - d->lastj->j2, -1, JUMPFLAG_STATIC)); } #ifdef COMPUTE_LOOP_POINTS // Compute loop points from end<>begin // Use begin/end points specified DEBUGPRINT("LOOP: %d>%d rough endpoints given\n",loopstartpt,loopendpt); // Read in samples // We will use sbufs split evenly in two. The first half of the buffer // will store samples around the loop start point. The second half // of the buffer will contain samples around the loop end point. // We need to grab an extra 'cmpchunk' samples at the end to give the // correlation something to chew on. el_nframes_t halfpt = d->maxchunk + d->cmpchunk; // Check range start1->start2 against end1->end2 el_nframes_t start1 = loopstartpt - d->maxchunk/2, // Feed indices for // start range start2 = loopstartpt + d->maxchunk/2 + d->cmpchunk, s_orig = d->maxchunk/2, // Index in sbufs of loopstartpt sample end1 = loopendpt - d->maxchunk/2, // Feed indices for end range end2 = loopendpt + d->maxchunk/2 + d->cmpchunk, e_orig = halfpt + d->maxchunk/2; // Index in sbufs of loopendpt sample // Ensure comparison ranges are within sample bounds if (start1 < 0) { start2 -= start1; // Extend end of range (to accomodate clipped begin) s_orig += start1; // Therefore, center moves forward start1 = 0; } if (end2 >= d->slen) { end1 -= (end2 - d->slen + 1); // Bring forward beginning of range // (accomodate clipped end) e_orig += (end2 - d->slen + 1); // Therefore, center moves towards end end2 = d->slen-1; } // Ensure default start and end points give enough space for correlate if (s_orig < 0) { DEBUGPRINT("LOOP: Default loop begin too early- " "not enough space for correlate- fixed!\n"); loopstartpt -= s_orig; s_orig = 0; } if (e_orig + d->cmpchunk >= 2*halfpt) { DEBUGPRINT("LOOP: Default loop end too late- " "not enough space for correlate- fixed!\n"); loopendpt += (2*halfpt - d->cmpchunk - 1 - e_orig); e_orig = 2*halfpt - d->cmpchunk - 1; } DEBUGPRINT("LOOP: StartChunkLen: %d EndChunkLen: %d S_orig: %d E_orig: %d\n", start2-start1, end2-end1, s_orig, e_orig); if (start2 >= d->slen || end1 < 0) { // Really short sample- no loop points possible fprintf(stderr,"ELASTIN: *** Short sample! No loop points possible!\n"); } else { // Get start and end parts to compare // Get start d->feed->GetSamples(start1,start2-start1,sbufs); // Get end el_sample_t *sbufs_tmp[d->numch]; for (int ch = 0; ch < d->numch; ch++) sbufs_tmp[ch] = &(sbufs[ch][halfpt]); d->feed->GetSamples(end1,end2-end1,sbufs_tmp); // Now, find best correlate position char first = 1; float bestcor = 0.0; el_nframes_t bestcoridx = 0; // Moving loopstartpt with loopendpt pinned el_nframes_t boundary = halfpt-d->cmpchunk; // Can't correlate past halfpt for (el_nframes_t i = 0; i < boundary; i++) { float cor = Correlate(i,e_orig,d->cmpchunk); // DEBUGPRINT("BEGIN: %d cor: %f\n",i,cor); if (cor < bestcor) { bestcor = cor; bestcoridx = i; } else if (first) { first = 0; bestcor = cor; bestcoridx = i; } } // Moving loopendpt with loopstartpt pinned boundary = 2*halfpt-d->cmpchunk; // Can't correlate past end of buffer for (el_nframes_t i = halfpt; i < boundary; i++) { float cor = Correlate(s_orig,i,d->cmpchunk); // DEBUGPRINT("END: %d cor: %f\n",i-halfpt,cor); if (cor < bestcor) { bestcor = cor; bestcoridx = i; } else if (first) { first = 0; bestcor = cor; bestcoridx = i; } } // Best? if (bestcoridx < halfpt) { // Moving loopstartpt with loopendpt pinned d->loopj = new Elastin_Jump(start1+bestcoridx,loopendpt,0,bestcor, JUMPFLAG_LOOPPT); DEBUGPRINT("LOOP: Move start: %d>%d\n",d->loopj->j1,d->loopj->j2); } else { // Moving loopendpt with loopstartpt pinned d->loopj = new Elastin_Jump(loopstartpt,end1+bestcoridx-halfpt,0,bestcor, JUMPFLAG_LOOPPT); DEBUGPRINT("LOOP: Move end: %d>%d\n",d->loopj->j1,d->loopj->j2); } // Determine which chunk the loop start point is in // Store that in loopj->next Elastin_Jump *cur = d->firstj; d->loopj->next = 0; while (cur != 0 && d->loopj->next == 0) { if (d->loopj->j1 >= cur->j1 && d->loopj->j1 < cur->j2) d->loopj->next = cur; cur = cur->next; } if (d->loopj->next == 0) fprintf(stderr,"ELASTIN: ERROR: Loop start point not within any chunk!\n"); DEBUGPRINT("DONE!\n"); } #endif #ifdef USE_SYNTHMAX_SCORE // Recalibrate scores // Get mean score float meanscore = 0.0; int scorecnt = 0; Elastin_Jump *cur = firstj; while (cur != 0) { if (!cur->IsStatic()) { meanscore += cur->score; scorecnt++; } cur = cur->next; } if (scorecnt > 1) { meanscore /= (float) scorecnt; DEBUGPRINT("Mean score: %f\n",meanscore); // Now compute standard deviation float stddev = 0; cur = firstj; while (cur != 0) { if (!cur->IsStatic()) { float dev = cur->score - meanscore; stddev += dev*dev; } cur = cur->next; } stddev = sqrt(stddev/(scorecnt-1)); DEBUGPRINT("Std dev: %f\n",stddev); // Now recalibrate scores in terms of deviation from mean cur = firstj; while (cur != 0) { if (!cur->IsStatic()) { cur->score = (cur->score - meanscore)/stddev; DEBUGPRINT("jump: len(%d) %d>%d score: %f\n",cur->jlen,cur->j1,cur->j2, cur->score); } cur = cur->next; } } #endif } return 0; }; // Get amplitude envelope from spos[idx1]->spos[idx2] el_sample_t Elastin::Analyze_GetAmpEnv (el_nframes_t idx1, el_nframes_t idx2) { el_sample_t alen = (idx2-idx1)*d->numch; if (alen == 0) return 0.0; register el_sample_t amp = 0.0; for (int i = 0; i < d->numch; i++) { register el_sample_t *sbuf = sbufs[i]; for (register el_nframes_t n = idx1; n < idx2; n++) amp += fabs(sbuf[n]); } return amp/alen; }; #define DO_COR(i1,i2) \ (Correlate(i1,i2,cmpchunk) * pow((i2)-(i1),0.5)) int Elastin::Analyze (int numchunks) { // static el_sample_t prevamp = 0.0; if (d == 0 || d->feed == 0) return -1; char go = 1; for (int i = 0; go && i < numchunks; i++) { el_nframes_t runlen = d->maxchunk*2, remaining = d->slen-spos, passmaxchunk = d->maxchunk, passminchunk = d->minchunk; char gopass = 1; if (remaining < runlen) { // Approaching end of sample-- shorten pass go = 0; runlen = remaining; passmaxchunk = runlen/2; if (passminchunk > passmaxchunk) gopass = 0; } if (gopass) { // Read in samples d->feed->GetSamples(spos,runlen,sbufs); // Now, find best correlate position char first = 1; float bestcor = 0.0; el_nframes_t bestcoridx = 0, minchunk = d->minchunk, cmpchunk = d->cmpchunk; for (el_nframes_t i = minchunk; i < passmaxchunk; i++) { float cor = DO_COR(0,i); if (cor < bestcor) { bestcor = cor; bestcoridx = i; } else if (first) { first = 0; bestcor = cor; bestcoridx = i; } } float bestcor1 = bestcor; // Try move begin el_nframes_t moverange = bestcoridx - d->minchunk, bestcoridx_b = 0; for (el_nframes_t i = 1; i < moverange; i++) { float cor = DO_COR(i,bestcoridx); if (cor < bestcor) { bestcor = cor; bestcoridx_b = i; } } if (bestcoridx_b != 0 && bestcor/bestcor1 < MOVETHRESH) { DEBUGPRINT("bestcor_b: %f->%f (%d>%d)\n",bestcor1,bestcor, bestcoridx_b,bestcoridx); // Add static portion from 0>bestcoridx_b #if 0 el_sample_t amp = Analyze_GetAmpEnv(0,bestcoridx_b); DEBUGPRINT("d: %f [%f]\n",amp-prevamp,-1.0); prevamp = amp; #endif d->AddJump(new Elastin_Jump(spos,spos+bestcoridx_b,bestcoridx_b,-1, JUMPFLAG_STATIC)); } else { // Try move begin 2 moverange = passmaxchunk - d->minchunk; // if too many large static chunks causing excessive reps--- // if (moverange > MAX_STATIC_LEN) moverange = MAX_STATIC_LEN bestcoridx_b = 0; el_nframes_t cmpchunk = d->cmpchunk; for (el_nframes_t i = 1; i < moverange; i++) { float cor = DO_COR(i,passmaxchunk); if (cor < bestcor) { bestcor = cor; bestcoridx_b = i; } } if (bestcoridx_b != 0 && bestcor/bestcor1 < MOVETHRESH) { DEBUGPRINT("bestcor_b2: %f->%f (%d>%d)\n",bestcor1,bestcor, bestcoridx_b,passmaxchunk); // Add static portion from 0>bestcoridx_b #if 0 el_sample_t amp = Analyze_GetAmpEnv(0,bestcoridx_b); DEBUGPRINT("d: %f [%f]\n",amp-prevamp,-1.0); prevamp = amp; #endif d->AddJump(new Elastin_Jump(spos,spos+bestcoridx_b,bestcoridx_b,-1, JUMPFLAG_STATIC)); // Use bestcoridx_b > passmaxchunk jump bestcoridx = passmaxchunk; } else { // Use original jump bestcoridx_b = 0; bestcor = bestcor1; } } // Store bestcoridx/bestcor as a jump, and continue there #if 0 el_sample_t amp = Analyze_GetAmpEnv(bestcoridx_b,bestcoridx); DEBUGPRINT("d: %f [%f]\n",amp-prevamp,bestcor); prevamp = amp; #endif Elastin_Jump *newj; d->AddJump(newj = new Elastin_Jump(spos+bestcoridx_b,spos+bestcoridx, bestcoridx-bestcoridx_b,bestcor)); DEBUGPRINT("jump: len(%d) %d>%d score: %f\n",newj->jlen,newj->j1,newj->j2, newj->score); spos += bestcoridx; } } if (!go) d->analysisdone = 1; return (go ? 0 : -1); }; int Elastin::Synthesize_Start (el_nframes_t startpos, el_nframes_t crossfadelen, char loopmode, el_nframes_t loop_crossfadelen, float synthmaxscore, el_sample_t **tempbufs, el_nframes_t tempbufslen, float timestretch, float rateshift, float ts_pitchshift, float rt_pitchshift) { // Check if we've analyzed audio if (d == 0 || d->feed == 0 || !d->analysisdone || d->firstj == 0 || sbufs == 0) return -1; // Check crossfade length // *** Loop cross fade length can not exceed 'cmpchunk' because // it's possible that loopj->j2 is as close as cmpchunk samples // to the end of the sample! if ((loopmode && loop_crossfadelen > d->cmpchunk) || crossfadelen > d->maxchunk || crossfadelen > d->firstj->j2) return -2; this->tempbufs = tempbufs; this->tempbufslen = tempbufslen; this->tempbuf_pos = 0.0; this->tempbuf_filled = 0; this->crossfadelen = crossfadelen; this->loopmode = loopmode; this->loop_crossfadelen = loop_crossfadelen; this->timestretch = timestretch; this->rateshift = rateshift; this->ts_pitchshift = ts_pitchshift; this->rt_pitchshift = rt_pitchshift; Synth_ComputeParams(); this->synthmaxscore = synthmaxscore; cfcnt = 0; forcedstatic = 0; timedelta = 0; synthcount = 0.0; // *** Startpos not yet implemented curj = d->firstj; Synth_SetupChunk(0); return 0; }; int Elastin::Synthesize_Stop () { return 0; }; el_nframes_t Elastin::Synthesize (el_sample_t **bufs, el_nframes_t len) { if (bufs == 0) return 0; // Zero buffer! if (combirateshift != 1.0) { // Timestretch + Rateshift (TS+RT) // DEBUGPRINT("tempbuf_pos: %.5lf\n",tempbuf_pos); // Check if intermediate buffers are big enough // Endpos is the end position // (ie the new starting position in tempbuf after this pass, unwrapped) double endpos = tempbuf_pos + combirateshift * len; // Ensure there's always an extra sample for interpolation el_nframes_t endpos_withpad = (el_nframes_t) endpos + 1; if (tempbufs == 0 || endpos_withpad >= tempbufslen) { fprintf(stderr,"ELASTIN: ERROR: Tempbufs not allocated or not big enough" " for synthesize: combirateshift: %.2f tempbufslen: %d " "tempbufs: %p!\n", combirateshift,tempbufslen,tempbufs); // Shunt rate shift return Synthesize_TS(bufs,len); } // First, pull and timestretch audio (accounting for filled spot in // tempbufs from previous pass) el_sample_t *tempbufs_tmp[d->numch]; for (int ch = 0; ch < d->numch; ch++) tempbufs_tmp[ch] = &(tempbufs[ch][tempbuf_filled]); el_nframes_t tofill = endpos_withpad - tempbuf_filled + 1; // DEBUGPRINT("Filled: %d Tofill: %d\n",tempbuf_filled,tofill); if (tofill < 0) tofill = 0; el_nframes_t ts_outlen = Synthesize_TS(tempbufs_tmp,tofill); // Check if TS actually synthesized 'tofill' samples char end = 0; el_nframes_t ret; if (ts_outlen != tofill) { // No, must be end of sample-- adjust length we produce // Use bounds checking Synthesize_RT pass to produce -just enough- // output given the reduced size in tempbufs (ts_outlen + tempbuf_filled) end = 1; ret = Synthesize_RT(tempbufs,bufs,len,1,ts_outlen + tempbuf_filled); } else // Second, rate shift audio in tempbufs ret = Synthesize_RT(tempbufs,bufs,len); if (end) { tempbuf_pos = 0.0; tempbuf_filled = 0; } else { // Third, advance tempbuf_pos, and wrap based on fractional part of // endpos- this gives us the new starting position relative to // the start of tempbufs el_nframes_t endpos_d1 = (el_nframes_t) endpos; tempbuf_pos = endpos - endpos_d1; // Move sample(s) at end of buffer to beginning for next pass tempbuf_filled = endpos_withpad - endpos_d1 + 1; for (el_nframes_t n = 0; n < tempbuf_filled; n++) for (int ch = 0; ch < d->numch; ch++) tempbufs[ch][n] = tempbufs[ch][endpos_d1 + n]; // DEBUGPRINT("endpos: %.5lf\n",endpos); // DEBUGPRINT("copied %d positions @ %d > head ",tempbuf_filled,endpos_d1); // DEBUGPRINT("(sample: %f)\n",tempbufs[0][0]); } return ret; } else { if (tempbufs != 0 && tempbuf_filled != 0) { // *** TEST THIS // We have some data already generated from a TS+RT pass (above) // Use it first el_sample_t *bufs_tmp[d->numch]; for (int ch = 0; ch < d->numch; ch++) { memcpy(&(bufs[ch][0]),&(tempbufs[ch][0]), tempbuf_filled*sizeof(el_sample_t)); bufs_tmp[ch] = &(bufs[ch][tempbuf_filled]); } // Now synthesize remaining samples el_nframes_t ret = Synthesize_TS(bufs_tmp,len - tempbuf_filled) + tempbuf_filled; // Reset tempbuf_filled = 0; return ret; } else // Timestretch only! return Synthesize_TS(bufs,len); } }; el_nframes_t Elastin::Synthesize_RT (el_sample_t **tempbufs, el_sample_t **bufs, el_nframes_t outlen, char checkinbounds, el_nframes_t inlen_max) { register double tb_pos = tempbuf_pos; // *** Can use float? // Compute fractional and integer part of position, and linear interpolate // using this sample and adjacent across all channels #define DO_RT_SCALE \ el_nframes_t intpos = (el_nframes_t) tb_pos; \ float fracpos = tb_pos - intpos, \ oneminus_fracpos = 1.0 - fracpos; \ \ for (int ch = 0; ch < d->numch; ch++) \ bufs[ch][n] = \ oneminus_fracpos * tempbufs[ch][intpos] + \ fracpos * tempbufs[ch][intpos+1]; if (checkinbounds) { // Slow (in bounds checking) DEBUGPRINT("Slow RT scale w/ bounds check!\n"); if ((el_nframes_t) tb_pos + 1 >= inlen_max) { // No samples can be produced- need at least 2 samples in tempbufs return 0; } for (el_nframes_t n = 0; n < outlen; n++) { DO_RT_SCALE; tb_pos += combirateshift; if ((el_nframes_t) tb_pos + 1 >= inlen_max) { // Reached boundary! Return # produced so far return n+1; } } } else { // Fast (no in bounds checking) // // We assume there are enough samples in // tempbufs for rate scale) for (el_nframes_t n = 0; n < outlen; n++, tb_pos += combirateshift) { DO_RT_SCALE; } } // DEBUGPRINT("RTshift: float pos AT,AFTER end of pass: %.5lf, %.5lf (combirateshift: %.5f)\n",tb_pos - combirateshift,tb_pos,combirateshift); // DEBUGPRINT("RTshift: int pos AT end of pass (+1 interpolate): %d ",(el_nframes_t) (tb_pos - combirateshift) + 1); // DEBUGPRINT("(sample: %f)\n",tempbufs[0][(el_nframes_t) (tb_pos - combirateshift) + 1]); return outlen; }; el_nframes_t Elastin::Synthesize_TS (el_sample_t **bufs, el_nframes_t len) { el_nframes_t len_remaining = len, bufidx = 0; char run_again; do { run_again = 0; // Compute run length el_nframes_t run_len = runremaining; if (run_len > len_remaining) run_len = len_remaining; // Run if (run_len > 0) { switch (ss) { case EL_StaticRun : case EL_StaticRun_EarlyFade : case EL_StaticRun_LoopPt : case EL_Run : case EL_Run_LoopPt : { // Copy for (int ch = 0; ch < d->numch; ch++) memcpy(&(bufs[ch][bufidx]),&(sbufs[ch][chunkidx]), run_len*sizeof(el_sample_t)); } break; case EL_Fade : { // Fade float fv1 = 0.0, fv2 = 0.0; for (int ch = 0; ch < d->numch; ch++) { register el_sample_t *bb = &(bufs[ch][bufidx]), *sb1 = &(sbufs[ch][fadepos1]), *sb2 = &(sbufs[ch][fadepos2]); fv1 = fadevol1; fv2 = fadevol2; for (el_nframes_t i = 0; i < run_len; i++, bb++, sb1++, sb2++) { *bb = fv1 * *sb1 + fv2 * *sb2; fv1 -= fadeinc; fv2 += fadeinc; // Bounds check on fadevols? } } fadepos1 += run_len; fadepos2 += run_len; fadevol1 = fv1; fadevol2 = fv2; } break; default: break; } // Advance runremaining -= run_len; bufidx += run_len; chunkidx += run_len; } // Next pass if (runremaining <= 0) { // Prepare for next pass len_remaining -= run_len; if (len_remaining > 0) run_again = 1; // Chunk boundary switch (ss) { case EL_StaticRun_LoopPt : case EL_Run_LoopPt : { // Crossfade at loop point cft = CF_LoopPt; DEBUGPRINT("Setup fade (length %d)\n",loop_crossfadelen); // Get first part of crossfade (around loopj->j2) spos = d->loopj->j2; chunkidx = 0; d->feed->GetSamples(spos,loop_crossfadelen,sbufs); // Get second part of crossfade, store immediately after first in // sbufs spos = d->loopj->j1; el_sample_t *sbufs_tmp[d->numch]; for (int ch = 0; ch < d->numch; ch++) sbufs_tmp[ch] = &(sbufs[ch][loop_crossfadelen]); d->feed->GetSamples(spos,loop_crossfadelen,sbufs_tmp); // Relocate jump curj = d->loopj->next; // Setup crossfade fadepos1 = 0; fadepos2 = loop_crossfadelen; fadevol1 = 1.0; fadevol2 = 0.0; fadeinc = 1.0/loop_crossfadelen; runremaining = loop_crossfadelen; // *** What to do about timedelta? // I think this is right. Compensate for crossfade time. timedelta += (combitimestretch-1.0)*runremaining; ss = EL_Fade; } break; case EL_StaticRun : case EL_StaticRun_EarlyFade : case EL_Run : { // Check-- should we crossfade back to repeat, crossfade forward // to skip, or continue straight thru? if (Synth_CheckCFBack()) { // Crossfade back cft = CF_Back; cfcnt++; DEBUGPRINT("TD: %lf [cfback (cfcnt %d)]\n",timedelta,cfcnt); fadepos1 = chunkidx; fadepos2 = 0; fadevol1 = 1.0; fadevol2 = 0.0; fadeinc = 1.0/crossfadelen; runremaining = crossfadelen; // Compensate for samples added // DEBUGPRINT("compensate timedelta: %lf -> ",timedelta); timedelta -= curj->jlen; // DEBUGPRINT("%lf\n",timedelta); ss = EL_Fade; } else if (ss == EL_StaticRun_EarlyFade || (ss == EL_Run && (cfcnt = Synth_CheckCFForward()) != 0)) { // Crossfade forward 'cfcnt' chunks cft = CF_Forward; // Get first part of crossfade spos = curj->j2 - crossfadelen; // Current spot chunkidx = 0; d->feed->GetSamples(spos,crossfadelen,sbufs); // Skip chunks int cnt = 0; el_nframes_t skiplen = 0; for (; cnt < cfcnt && curj->next != 0; cnt++) { curj = curj->next; skiplen += curj->jlen; } if (cnt < cfcnt) { // Skipping stopped early- no more chunks!- stop! synthcount += bufidx / combitimestretch; return bufidx; } DEBUGPRINT("TD: %lf [cffwd %d chunks (%d len)]\n", timedelta,cfcnt,skiplen); // Get second part of crossfade, store immediately after first in // sbufs spos = curj->j2 - crossfadelen; // Current spot el_sample_t *sbufs_tmp[d->numch]; for (int ch = 0; ch < d->numch; ch++) sbufs_tmp[ch] = &(sbufs[ch][crossfadelen]); d->feed->GetSamples(spos,crossfadelen,sbufs_tmp); // Setup crossfade fadepos1 = 0; fadepos2 = crossfadelen; fadevol1 = 1.0; fadevol2 = 0.0; fadeinc = 1.0/crossfadelen; runremaining = crossfadelen; // Compensate for samples removed-- include crossfade as // part of last chunk timedelta += (combitimestretch-1.0)*runremaining + combitimestretch*skiplen; ss = EL_Fade; } else { // No crossfade-- // Continue to next chunk cfcnt = 0; DEBUGPRINT("TD: %lf [NO CF]\n",timedelta); if (curj->next != 0) { Elastin_Jump *prevj = curj; curj = curj->next; Synth_SetupChunk(prevj); } else { // No more chunks-- stop! synthcount += bufidx / combitimestretch; return bufidx; } } } break; case EL_Fade : { // Switch from fade to run! // DEBUGPRINT("fadedone\n"); if (cft == CF_Forward) { // Finished crossfade forward- load samples for next chunk if (curj->next != 0) { curj = curj->next; Synth_SetupChunk(0); } else { // No more chunks-- stop! synthcount += bufidx / combitimestretch; return bufidx; } } else if (cft == CF_Back) { // Finished crossfade backward- run remaining samples chunkidx = fadepos2; // Start at end-of-fade position runremaining = curj->jlen - crossfadelen; ss = EL_Run; } else if (cft == CF_LoopPt) { // Finished crossfade at loop point- run starting at new curj- // tell SetupChunk we've looped by passing loopj, which is flagged // for IsLoopPt() DEBUGPRINT("Done looppt fade. Setup start point.\n"); Synth_SetupChunk(d->loopj); } } break; default: break; } } } while (run_again); synthcount += bufidx / combitimestretch; return bufidx; }; // Returns nonzero if, given current conditions, we should crossfade back char Elastin::Synth_CheckCFBack () { // Don't crossfade back static chunks or if we are speeding up audio if (curj->IsStatic(synthmaxscore) || forcedstatic || combitimestretch <= 1.0) { forcedstatic = 0; return 0; } DEBUGPRINT("timedelta: %lf\n",timedelta); int average_repeats = (int) combitimestretch; if (timedelta > 0.0) { // Next chunk is static? Must repeat then, to avoid getting // way out of time if (curj->next == 0 || curj->next->IsStatic(synthmaxscore)) return 1; // Spread to next chunk? if (cfcnt >= average_repeats) { DEBUGPRINT("spread to next [%d]\n",cfcnt); return 0; } // Favor next chunk? if (curj->score - curj->next->score >= FAVOR_THRESH) { DEBUGPRINT("favor next [%d] [%f/%f]\n",cfcnt, curj->next->score,curj->score); return 0; } // Otherwise, repeat now return 1; } else if (cfcnt < average_repeats-1 && curj->next != 0 && curj->next->IsStatic(synthmaxscore) && timedelta + (combitimestretch-1.0)*curj->next->jlen > 0.0) { // Anticipate that we will need to repeat a chunk-- // if the next chunk is static and that chunk will cause us // to be behind, repeat this earlier chunk instead of many // repeats after the static chunk DEBUGPRINT("anticipate cfback [%d]\n",cfcnt); return 1; } else // No crossfade back return 0; }; // Check whether we should crossfade forward from current position- // Returns the number of jumps to skip, or zero if no crossfade forward // should be done int Elastin::Synth_CheckCFForward () { Elastin_Jump *cjn = curj->next; int cnt = 0; double td = timedelta; while (1) { // DEBUGPRINT("timedelta: %lf skipfwdcnt: %d\n",td,cnt); // Don't crossfade forward across static chunks // or if we are slowing down audio if (cjn == 0 || cjn->IsStatic(synthmaxscore) || combitimestretch >= 1.0) return cnt; int average_skips = (int) (combitimestretch <= 0.0 ? -1 : (1.0/combitimestretch)); if (td < 0.0) { // Next next chunk is static? Must skip then, to avoid getting // way out of time if (cjn->next == 0 || cjn->next->IsStatic(synthmaxscore)) return cnt+1; // Spread to next chunk? if (average_skips > 0 && cnt >= average_skips) { DEBUGPRINT("spread to next [%d]\n",cnt); return cnt; } // Favor next chunk? if (cjn->score - cjn->next->score >= FAVOR_THRESH) { DEBUGPRINT("favor next [%d] [%f/%f]\n",cnt, cjn->next->score,cjn->score); return cnt; } // Otherwise, skip cnt++; } else if (average_skips > 0 && cnt < average_skips-1 && cjn->next != 0 && cjn->next->IsStatic(synthmaxscore) && td + (combitimestretch-1.0)*cjn->jlen < 0.0) { // Anticipate that we will need to skip a chunk-- // if the next next chunk is static and that chunk will cause us // to be ahead, skip this earlier coming chunk instead of many // skips after the static chunk DEBUGPRINT("anticipate cffwd [%d]\n",cnt); cnt++; } else // No more crossfade forward return cnt; // Advance to next skip td += (combitimestretch-1.0)*cjn->jlen; cjn = cjn->next; } }; void Elastin::Synth_SetupChunk (Elastin_Jump *prevj) { if (prevj != 0 && prevj->IsLoopPt()) { DEBUGPRINT("After loop fade: Reposition!\n"); // We just looped. Loop fade may have moved us to a new chunk. // Reposition spos += loop_crossfadelen; // If necessary, jump to next chunk while (spos >= curj->j2 && curj != 0) { DEBUGPRINT("next chunk!\n"); curj = curj->next; } } if (curj->IsStatic()) { // Static run if (prevj != 0 && prevj->IsLoopPt()) { // Following loop fade, new position... // We will load the sample from spos to j2 DEBUGPRINT("After loop fade: New startpt- STATIC run!\n"); chunkidx = 0; runremaining = curj->j2 - spos; } else if (prevj == 0 || prevj->IsStatic() || forcedstatic) { forcedstatic = 0; DEBUGPRINT("static-- j1\n"); // Previous chunk was static/crossfade forward-- // so we are at j1 position. spos = curj->j1; chunkidx = 0; runremaining = curj->jlen; } else { DEBUGPRINT("static-- j1 crossfp\n"); // Previous regular chunk, so we are crossfadelen samples // before j1 spos = curj->j1 - crossfadelen; chunkidx = 0; runremaining = curj->jlen + crossfadelen; } char islooppt = 0; if (loopmode && d->loopj != 0 && curj->j2 >= d->loopj->j2) { if (d->loopj->j2 < curj->j1) { // Loop point actually happened already- how did we miss it? fprintf(stderr,"ELASTIN: ERROR: Loop point missed!\n"); } else { // Loop point happens during this chunk. Make note and reduce length. runremaining -= (curj->j2 - d->loopj->j2); islooppt = 1; } } // Bring timedelta up-to-date with the end of the new chunk double otimedelta = timedelta; timedelta += (combitimestretch-1.0)*runremaining; // Advance check for crossfade forward- we need to prepare before // the end of the static chunk in this case // Technically, there is a small (crossfadelen) discrepancy, where // we will tend to favor a crossfadeforward- because normally we check // crossfade using timedelta @ the position before j1, here we are checking // fully at the j1 position of the next chunk. However, this is not // cumulative. if (!islooppt && runremaining >= crossfadelen && (cfcnt = Synth_CheckCFForward()) != 0) { // Crossfade forward, so shorten run to provide space for crossfade DEBUGPRINT("Static Run Early Fade!\n"); runremaining -= crossfadelen; timedelta = otimedelta + (combitimestretch-1.0)*runremaining; ss = EL_StaticRun_EarlyFade; } else if (islooppt) { DEBUGPRINT("StaticRun @ LoopPt\n"); ss = EL_StaticRun_LoopPt; } else ss = EL_StaticRun; // Get new samples if (runremaining > 0) d->feed->GetSamples(spos,runremaining,sbufs); } else { // Regular run el_nframes_t chunklen = curj->jlen + crossfadelen; if (prevj != 0 && prevj->IsLoopPt()) { // Following loop fade, new position... DEBUGPRINT("After loop fade: New startpt- REGULAR run!\n"); chunkidx = spos - curj->j1 + crossfadelen; runremaining = curj->j2 - crossfadelen - spos; if (runremaining < 0) { // If runremaining < 0, we are beyond the cross fade position // (crossfadelen samples before j2). There is no way to start // a crossfade now, so we will have to play out this block in a static // way // Play to j2, load chunk from spos to j2 chunkidx = 0; runremaining = curj->j2 - spos; chunklen = runremaining; // Force static run DEBUGPRINT("Forced static after looppt fade!\n"); forcedstatic = 1; } else // Load samples starting from before j1, in case we need to // crossfade back right away spos = curj->j1 - crossfadelen; } else { spos = curj->j1 - crossfadelen; if (prevj == 0 || prevj->IsStatic() || forcedstatic) { forcedstatic = 0; DEBUGPRINT("reg-- j1\n"); // Previous chunk was static/crossfade forward-- // so we are at j1 position. runremaining = curj->jlen - crossfadelen; chunkidx = crossfadelen; if (spos < 0) { fprintf(stderr,"ELASTIN: ERROR: Crossfade- not enough space!\n"); // Not enough space for crossfade, disable chunklen = curj->jlen; spos = 0; chunkidx = 0; runremaining += crossfadelen; } } else { DEBUGPRINT("reg-- j1 crossfp\n"); // Previous regular chunk, so we are crossfadelen samples // before j1 runremaining = curj->jlen; chunkidx = 0; if (spos < 0) { fprintf(stderr, "ELASTIN: ERROR: Not first chunk but no data for crossfade?\n"); spos = 0; } } } if (forcedstatic) { // Finished with loop point crossfade, but finished late in chunk- // force static play ss = EL_StaticRun; } else if (loopmode && d->loopj != 0 && curj->j2 >= d->loopj->j2) { if (d->loopj->j2 < curj->j1) { // Loop point actually happened already- how did we miss it? fprintf(stderr,"ELASTIN: ERROR: Loop point missed!\n"); } else { // Loop point happens during this chunk. Recalculate runremaining- // Runremaining now takes us crossfadelen samples before j2. // Runremaining should take us right to the loop point DEBUGPRINT("Regular Run @ LoopPt\n"); runremaining += crossfadelen + d->loopj->j2 - curj->j2; } // Regular run cut off by loop point ss = EL_Run_LoopPt; } else // Regular run ss = EL_Run; // Get new samples if (runremaining > 0) d->feed->GetSamples(spos,chunklen,sbufs); // Bring timedelta up-to-date with the end of the new chunk // DEBUGPRINT("advance td: %lf -> ",timedelta); timedelta += (combitimestretch-1.0)*runremaining; // DEBUGPRINT("%lf\n",timedelta); } }; fweelin-0.6/src/elastin/elastin.h0000644000175000017500000003553410724066726015530 0ustar mercmerc#ifndef __ELASTIN_H #define __ELASTIN_H #include #include #include typedef float el_sample_t; typedef int32_t el_nframes_t; // Uncomment this to enable verbose debug messages #define PRINT_DEBUG_MESSAGES #ifdef PRINT_DEBUG_MESSAGES #define DEBUGPRINT printf #else #define DEBUGPRINT donothing #endif inline void donothing(...) { return; }; // Convert cents to frequency ratio #define CENTS_TO_FREQ_RATIO(n) (powf(2.0,((float) (n)/1200))) // SynthMaxScore causes certain chunks with bad scores to be disregarded // for crossfading during stretching. But it requires an extra 'calibration' // step to calibrate the chunk scores after computation. // #define USE_SYNTHMAX_SCORE // Loop points can be computed for smooth, continuous looping of the sample #define COMPUTE_LOOP_POINTS class Elastin_Jump { #define JUMPFLAG_STATIC 1 // Jump is static (not to be repeated/skipped) #define JUMPFLAG_LOOPPT 2 // Jump is a loop point jump public: Elastin_Jump(el_nframes_t j1, el_nframes_t j2, el_nframes_t jlen, float score, char jumpflags = 0) : j1(j1), j2(j2), jlen(jlen), score(score), jumpflags(jumpflags), next(0) { if (jumpflags & JUMPFLAG_STATIC) DEBUGPRINT("static len: %d\n",jlen); }; // Returns nonzero if j1>j2 specifies a -static- chunk inline char IsStatic() { return (jumpflags & JUMPFLAG_STATIC); }; // Returns nonzero if j2>j1 specifies a -loop point- jump inline char IsLoopPt() { return (jumpflags & JUMPFLAG_LOOPPT); }; // Returns nonzero if j1>j2 specifies a -static- chunk, // or if this chunk's score in relation to 'maxscore' effectively makes // this chunk static inline char IsStatic(float maxscore) { #ifdef USE_SYNTHMAX_SCORE return ((jumpflags & JUMPFLAG_STATIC) || score > maxscore); #else return (jumpflags & JUMPFLAG_STATIC); #endif }; // Jump point from j1 -> j2, corresponding length and score el_nframes_t j1, j2, jlen; float score; unsigned char jumpflags; // Special flags for this jump Elastin_Jump *next; }; class Elastin_SampleFeed { public: virtual ~Elastin_SampleFeed() {}; // A SampleFeed has one duty- to return samples when requested-- // Notice that we require random access to samples-- return sample at // position 'pos', with 'cnt' length // // GetSamples should store the sample data in the provided 'bufs' // and return zero if successful. // // Bufs is an array of buffers, one per channel. The bufs array and sample // buffers are provided. You need only fill them. virtual int GetSamples (el_nframes_t pos, el_nframes_t cnt, el_sample_t **bufs) = 0; // Return total length of sample virtual el_nframes_t GetLength () = 0; // Return total number of audio channels virtual int GetNumChannels () = 0; }; typedef enum { EL_StaticRun, EL_StaticRun_EarlyFade, EL_StaticRun_LoopPt, EL_Run, EL_Run_LoopPt, EL_Fade, } Elastin_SynthStatus; typedef enum { CF_Back, CF_Forward, CF_LoopPt, } Elastin_CrossfadeType; // Elastin data associated with a sample // This data is generated by class Elastin in an analysis pass, // and used by class Elastin in a synthesis pass class Elastin_Data { friend class Elastin; public: Elastin_Data() : analysisdone(0), feed(0), slen(0), firstj(0), lastj(0), loopj(0) {}; ~Elastin_Data(); private: inline void AddJump (Elastin_Jump *nw) { // Singly linked list with first & last pointers-- // Quick adding at end of list, // Forward-only scanning if (firstj == 0) { firstj = nw; lastj = nw; } else { lastj->next = nw; lastj = nw; } }; // Analysis parameters char analysisdone; // Nonzero if analysis is complete el_nframes_t minchunk, // Minimum length of chunk maxchunk, // Maximum length of chunk cmpchunk; // Compare (correlate) length for chunk // General Elastin_SampleFeed *feed; // Sample feed which provides sample data int numch; // Number of sample channels el_nframes_t slen; // Length of sample 'feed' Elastin_Jump *firstj, // (First pointer) in list of jumps in sample *lastj, // (Last pointer) in list of jumps in sample *loopj; // Loop point for sample }; // Main elastin engine- instantiate for analysis or synthesis of a sample class Elastin { public: // Instantiate Elastin analysis/synthesis engine- optionally provide // a pre-existing Elastin_Data to attach to. If given, this allows // a new Elastin instance to synthesize from an existing pre-analyzed sample Elastin(Elastin_Data *d = 0) : timestretch(1.0), rateshift(1.0), ts_pitchshift(0.0), rt_pitchshift(0.0), d(d), sbufs(0), curj(0) {}; ~Elastin(); // Attach this Elastin instance to a given Elastin_Data, // allowing you to synthesize using a pre-analyzed sample // // (not RT safe- performs allocation and initialization related to 'd') inline void Attach (Elastin_Data *d) { this->d = d; Synthesize_Prep(); }; // ** Analysis // Start analysis, getting sample data from 'feed' // // Specify range of size for chunks (minchunk, maxchunk), and // correlate length 'cmpchunk' (between minchunk and maxchunk) // // Pass the maximum crossfade length you intend to use during synthesis. // Once set, synthesis will not start with a crossfade length higher than // this. // // Analyze_Start returns an Elastin_Data instance that is linked to // the given sample feed and parameters you have set. You can use this // Elastin_Data later to synthesize stretched audio. You must delete // the Elastin_Data when you are finished with it. // // Returns null on error. Elastin_Data *Analyze_Start (Elastin_SampleFeed *feed, el_nframes_t maxcrossfadelen, el_nframes_t minchunk, el_nframes_t maxchunk, el_nframes_t cmpchunk); // Do 'numchunks' of analysis // Returns 0 on success // Returns -1 if no more chunks can be analyzed int Analyze (int numchunks); // Stop analysis-- once Analyze returns -1, you may call Analyze_Stop int Analyze_Stop (el_nframes_t loopstartpt, el_nframes_t loopendpt); // ** Resynthesis // Start synthesis, getting sample data from feed // // Start at position startpos (in sample) // Specify length of chunk cross fade // Specify whether sample should be continuously looped (loopmode = 1) // If loop mode is active, specify a length for loop crossfade // Lowering synthmaxscore causes poor chunks to be skipped during synthesis // // Tempbufs is a set of buffers you provide for intermediate data when // rate shifting. Tempbufslen is the length of the buffers you provide. // Tempbufslen must be sufficient to store all the intermediate samples // needed in a single Synthesize pass. You may not write to tempbufs at // any time, even between calls Synthesize. // // Tempbufslen must be rateshift * len in length. Rateshift is the maximum // effective rateshift during synthesis (including pitch shifting). Len // is the maximum length to be processed during a single Synthesize() pass. // Generally, a safe temp buffer size is 2*len or 3*len, or up to 20*len // if you are doing DJ scratching or scrubby type effects. // // If no rate shifting or pitch shifting will be done (timestretch only), // then tempbufs may be null. // // timestretch is the amount to stretch the sample length (2.0 is twice the // length) // rateshift is your user specified rateshift. // ts_pitchshift is the amount of pitch shift in cents, // using the timestretch + rateshift method (sample length doesn't change) // rt_pitchshift is the amount of pitch shift in cents, // using the pure rateshift method (sample length does change) // // You can combine the above parameters in any way you like. The net // effect is calculated in Synth_ComputeParams(). // // (RT safe) int Synthesize_Start (el_nframes_t startpos, el_nframes_t crossfadelen, char loopmode, el_nframes_t loop_crossfadelen, float synthmaxscore, el_sample_t **tempbufs = 0, el_nframes_t tempbufslen = 0, float timestretch = 1.0, float rateshift = 1.0, float ts_pitchshift = 0.0, float rt_pitchshift = 0.0); // Do synthesis, returning len frames of audio into the supplied buffers // (one per channel). // // Returns the number of frames actually stored // When the return value is less than 'len', the synthesis is complete. // // (RT safe) el_nframes_t Synthesize (el_sample_t **bufs, el_nframes_t len); // Stop synthesis // // (RT safe) int Synthesize_Stop (); // Returns how far along in the original sample we've synthesized inline double GetSynthCount () { return synthcount; }; // These functions modify synthesis parameters // You can call them at any time during synthesis // (but not actually during a call to Synthesize()) inline void Set_TimeStretch (float timestretch) { this->timestretch = timestretch; Synth_ComputeParams(); }; inline void Set_RateShift (float rateshift) { this->rateshift = rateshift; Synth_ComputeParams(); }; inline void Set_TS_PitchShift (float ts_pitchshift) { this->ts_pitchshift = ts_pitchshift; Synth_ComputeParams(); }; inline void Set_RT_Pitchshift (float rt_pitchshift) { this->rt_pitchshift = rt_pitchshift; Synth_ComputeParams(); }; private: // Rate shift part of synthesis // Rate shift from tempbufs, storing outlen samples into bufs el_nframes_t Synthesize_RT (el_sample_t **tempbufs, el_sample_t **bufs, el_nframes_t outlen, char checkinbounds = 0, el_nframes_t inlen_max = 0); // Timestretch part of synthesis el_nframes_t Synthesize_TS (el_sample_t **bufs, el_nframes_t len); // Correlate cnt samples between idx1 and idx2 // Accounting for all channels inline float Correlate (el_nframes_t idx1, el_nframes_t idx2, el_nframes_t cnt) { register float cor = 0.0; register int numch = d->numch; for (register int i = 0; i < numch; i++) { register el_sample_t *t1 = &(sbufs[i][idx1]), *t2 = &(sbufs[i][idx2]); for (register el_nframes_t j = 0; j < cnt; j++, t1++, t2++) cor += fabs(*t1 - *t2); } return cor; }; // Get amplitude envelope between idx1 and idx2 el_sample_t Analyze_GetAmpEnv (el_nframes_t idx1, el_nframes_t idx2); // Check whether we should crossfade forward from current position- // Returns the number of jumps to skip, or zero if no crossfade forward // should be done int Synth_CheckCFForward (); // Returns nonzero if, given current conditions, we should crossfade // back char Synth_CheckCFBack (); // Setup buffers and counts for this chunk, given the previous jump void Synth_SetupChunk (Elastin_Jump *prevj); // Recompute net rate and timestretch from given parameters // (timestretch, rate shift, and two pitch shifts) inline void Synth_ComputeParams () { combitimestretch = timestretch * CENTS_TO_FREQ_RATIO(ts_pitchshift); combirateshift = rateshift * CENTS_TO_FREQ_RATIO(ts_pitchshift) * CENTS_TO_FREQ_RATIO(rt_pitchshift); }; // Prepare for synthesis // This function performs memory allocation and general initialization // related to synthesis. It is called -after- analyzing or attaching // to a pre-analyzed sample, but before calling Synthesize_Start() // // This allows us to move non-RT code out of real-time threads. // Synthesize_Start, Synthesize, and Synthesize_Stop are all RT safe! // // Returns nonzero on error int Synthesize_Prep () { if (d == 0 || d->feed == 0) return -1; if (sbufs != 0) Takedown_SampleBufs(); Setup_SampleBufs(); return 0; }; // Called to allocate/free sample buffers void Setup_SampleBufs(); void Takedown_SampleBufs(); // Temporary (user provided) buffers // Elastin stores timestretched audio in tempbufs. // Elastin then performs rate shifting on tempbufs. // The net effect encompasses time, pitch, and rate shifting. el_sample_t **tempbufs; el_nframes_t tempbufslen; double tempbuf_pos; // Floating position in tempbufs // (used in rateshift) el_nframes_t tempbuf_filled; // Number of samples already filled in tempbufs // Synthesis parameters float timestretch, // Time stretch factor rateshift, // Rate shift factor ts_pitchshift, // Pitch shift (via timestretch+rate) in cents rt_pitchshift, // Pitch shift (via rate) in cents // Calculated net parameters combirateshift, // Combined (net) rate shift to use combitimestretch, // Combined (net) time stretch to use synthmaxscore; // Synth max score-- factor for rejecting // poorly correlated chunks char loopmode; // In loop mode, Elastin synthesizes continuously // through the end of the sample, returning to // the beginning. Analysis determines the most // smooth loop points double synthcount; // How far along in original sample have we // synthesized? If looping, this may be greater // than the original sample length. // This is different than 'spos', in that spos // is an internal count which varies with jumps // and crossfades, whereas 'synthcount' is a // count designed to provide information to the // caller about the overall position of synthesis el_nframes_t crossfadelen, // Crossfade length loop_crossfadelen, // Crossfade length for loop point chunkpos, // Position of nearest chunk boundary chunkidx, // Sample index into current chunk chunklen, // Length of current chunk runremaining; // Length remaining to synthesize in current run double timedelta; // How many samples off target are we for length? Elastin_SynthStatus ss; // Current status Elastin_CrossfadeType cft; // Current crossfade type int cfcnt; // Count of how many consecutive crossfades // we've done char forcedstatic; // Nonzero if we force this chunk to play in a // static way. // Crossfade parameters el_nframes_t fadepos1, fadepos2; el_sample_t fadevol1, fadevol2, fadeinc; // General Elastin_Data *d; // Data for the sample we are using el_sample_t **sbufs; // Sample buffers (one per channel) // (these buffers contain a fragment of sample data) el_nframes_t spos; // Current analysis/synthesis position in sample 'feed' Elastin_Jump *curj; // (Current pointer) in list of jumps in sample }; #endif fweelin-0.6/src/fweelin_audioio.cc0000755000175000017500000002452311050104732015710 0ustar mercmerc/* Does power come from fancy toys or does power come from the integrity of our walk? */ /* Copyright 2004-2008 Jan Pekau (JP Mercury) This file is part of Freewheeling. Freewheeling is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. Freewheeling is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Freewheeling. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include "fweelin_config.h" #include "fweelin_audioio.h" #include "fweelin_core_dsp.h" #if USE_FLUIDSYNTH #include "fweelin_fluidsynth.h" #endif // **************** SYSTEM LEVEL AUDIO int AudioIO::process (nframes_t nframes, void *arg) { AudioIO *inst = static_cast(arg); // Get CPU load inst->cpuload = jack_cpu_load(inst->client); // Get JACK transport timing and status int tmp_roll = (jack_transport_query(inst->client,&(inst->jpos)) == JackTransportRolling); if (inst->jpos.valid & JackPositionBBT) inst->sync_active = 1; else inst->sync_active = 0; // Get buffers from jack AudioBuffers *ab = inst->app->getABUFS(); for (int i = 0; i < ab->numins_ext; i++) { // Left/mono channel ab->ins[0][i] = (sample_t *) jack_port_get_buffer (inst->iport[0][i], nframes); // Right channel ab->ins[1][i] = (inst->iport[1][i] != 0 ? (sample_t *) jack_port_get_buffer (inst->iport[1][i], nframes) : 0); } for (int i = 0; i < ab->numouts; i++) { // Left/mono channel ab->outs[0][i] = (sample_t *) jack_port_get_buffer (inst->oport[0][i], nframes); // Right channel ab->outs[1][i] = (inst->oport[1][i] != 0 ? (sample_t *) jack_port_get_buffer (inst->oport[1][i], nframes) : 0); } if (inst->rp != 0) { if (nframes != inst->app->getBUFSZ()) { printf("AUDIO: We've got a problem, honey!--\n"); printf("Audio buffer size has changed: %d->%d\n", inst->app->getBUFSZ(),nframes); exit(1); } // Run through audio processors inst->rp->process(0, nframes, ab); } inst->timebase_master = 0; // Reset timebase master flag- // callback will set to 1 if we are the master inst->transport_roll = tmp_roll; // Set transport rolling status return 0; } // Reposition JACK transport to the given position // Used for syncing external apps void AudioIO::RelocateTransport(nframes_t pos) { if (timebase_master) { jack_transport_locate(client,pos); repos = 1; } }; void AudioIO::timebase_callback(jack_transport_state_t state, jack_nframes_t nframes, jack_position_t *pos, int new_pos, void *arg) { AudioIO *inst = static_cast(arg); // Set timebase master flag inst->timebase_master = 1; /* printf("timebase called back (frame: %d, framerate: %d)!\n", pos->frame,pos->frame_rate); */ // Use our pulse information plus JACK's frame information // to calculate bars and beats and ticks Pulse *p = inst->app->getLOOPMGR()->GetCurPulse(); if (p != 0) { if (new_pos) { if (inst->repos) inst->repos = 0; // JACK telling us we have moved- but we initiated // the move, so ignore else { // Somebody has started the transport at a new position- // signal back that we want to start at a new position-- // based on the current pulse position. // printf("relocate: posframe: %d to %d\n",pos->frame,p->GetPos()); jack_transport_locate(inst->client,p->GetPos()); inst->repos = 1; #if 0 inst->sync_start_frame = pos->frame + (p->GetLength()-p->GetPos()); printf("posframe: %d syncstartframe set: %d\n",pos->frame, inst->sync_start_frame); #endif inst->sync_start_frame = 0; //pos->frame; } } #define TICKS_PER_BEAT 1920 int32_t rel_frame = (int) pos->frame - inst->sync_start_frame; float rel_bar = (float) rel_frame*inst->app->GetSyncSpeed()/p->GetLength(); if (inst->app->GetSyncType() != 0) // Beat sync, adjust bar by SYNC_BEATS_PER_BAR rel_bar /= SYNC_BEATS_PER_BAR; pos->valid = JackPositionBBT; pos->bar = (int32_t) rel_bar; float bar_frac = rel_bar - pos->bar; pos->beat = (int) (bar_frac * SYNC_BEATS_PER_BAR); pos->beats_per_bar = SYNC_BEATS_PER_BAR; if (inst->app->GetSyncType() == 0) pos->beats_per_minute = SYNC_BEATS_PER_BAR* 60.0*(double) pos->frame_rate/p->GetLength(); else pos->beats_per_minute = 60.0*(double) pos->frame_rate/p->GetLength(); pos->beat_type = SYNC_BEATS_PER_BAR; pos->ticks_per_beat = TICKS_PER_BEAT; float beat_frac = bar_frac*SYNC_BEATS_PER_BAR - (float)pos->beat; pos->tick = (int) (beat_frac * TICKS_PER_BEAT); pos->bar++; pos->beat++; //pos->tick++; pos->bar_start_tick = pos->bar * SYNC_BEATS_PER_BAR * TICKS_PER_BEAT; //printf("ticks per beat: %f\n",pos->ticks_per_beat); //printf("rel bar: %f, bar: %d, beat: %d, tick: %d\n",rel_bar, pos->bar, // pos->beat, pos->tick); } } int AudioIO::srate_callback (nframes_t nframes, void *arg) { AudioIO *inst = static_cast(arg); printf ("AUDIO: Sample rate is now %d/sec\n", nframes); inst->srate = nframes; return 0; } void AudioIO::audio_shutdown (void *arg) { printf("AUDIO: shutdown! exiting..\n"); exit(1); } int AudioIO::activate (Processor *rp) { const char **ports; // Store the rootprocessor passed as beginning of signal chain this->rp = rp; // Start rolling audio through JACK server if (jack_activate (client)) { printf("AUDIO: ERROR: Cannot activate client!\n"); return 1; } // Connect ports //AudioBuffers *ab = app->getABUFS(); // INPUT // No longer connect audio ports because the mapping isn't clear with // multi stereoins/outs if ((ports = jack_get_ports (client, NULL, NULL, JackPortIsPhysical|JackPortIsOutput)) == NULL) printf("AUDIO: WARNING: Cannot find any physical capture ports!\n"); #if 0 for (int i = 0; i < ab->numins_ext && ports[i] != 0; i++) if (jack_connect (client, ports[i], jack_port_name (iport[i]))) { printf("AUDIO: Cannot connect input port %d->%s!\n",i, jack_port_name(iport[i])); } #endif free(ports); // OUTPUT if ((ports = jack_get_ports (client, NULL, NULL, JackPortIsPhysical|JackPortIsInput)) == NULL) printf("AUDIO: WARNING: Cannot find any physical playback ports!"); #if 0 for (int i = 0; i < ab->numouts && ports[i] != 0; i++) if (jack_connect (client, jack_port_name (oport[i]), ports[i])) { printf("AUDIO: Cannot connect output port %d->%s!\n",i, jack_port_name(oport[i])); } #endif free(ports); return 0; } nframes_t AudioIO::getbufsz() { return jack_get_buffer_size (client); } void AudioIO::close () { jack_release_timebase (client); jack_client_close (client); delete[] iport[0]; delete[] iport[1]; delete[] oport[0]; delete[] oport[1]; printf("AUDIO: end\n"); } int AudioIO::open () { // **** AUDIO startup // Try to become a client of the JACK server if ((client = jack_client_new ("FreeWheeling")) == 0) { fprintf (stderr, "AUDIO: ERROR: Jack server not running!\n"); return 1; } /* tell the JACK server to call `process()' whenever there is work to be done. */ jack_set_process_callback (client, process, this); jack_nframes_t bufsz = jack_get_buffer_size (client); printf ("AUDIO: Audio buffer size is: %d\n", bufsz); /* tell the JACK server to call `srate_callback()' whenever the sample rate of the system changes. */ jack_set_sample_rate_callback (client, srate_callback, this); /* tell the JACK server to call `jack_shutdown()' if it ever shuts down, either entirely, or if it just decides to stop calling us. */ jack_on_shutdown (client, audio_shutdown, this); // Set timebase callback jack_set_timebase_callback (client, 1, timebase_callback, this); /* display the current sample rate. once the client is activated (see below), you should rely on your own sample rate callback (see above) for this value. */ srate = jack_get_sample_rate (client); printf ("AUDIO: Engine sample rate is %d\n", srate); // Set time scale timescale = (float) bufsz/srate; repos = 0; // Create buffers AudioBuffers *ab = app->getABUFS(); printf("AUDIO: Using %d external inputs, %d total inputs\n", ab->numins_ext,ab->numins); iport[0] = new jack_port_t *[ab->numins_ext]; iport[1] = new jack_port_t *[ab->numins_ext]; oport[0] = new jack_port_t *[ab->numouts]; oport[1] = new jack_port_t *[ab->numouts]; // Create ports char tmp[255]; for (int i = 0; i < ab->numins_ext; i++) { char stereo = ab->IsStereoInput(i); snprintf(tmp,255,"in_%d%s",i+1,(stereo ? "L" : "")); iport[0][i] = jack_port_register(client, tmp, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); if (stereo) { snprintf(tmp,255,"in_%d%s",i+1,"R"); iport[1][i] = jack_port_register(client, tmp, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); } else iport[1][i] = 0; } for (int i = 0; i < ab->numouts; i++) { char stereo = ab->IsStereoOutput(i); snprintf(tmp,255,"out_%d%s",i+1,(stereo ? "L" : "")); oport[0][i] = jack_port_register(client, tmp, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); if (stereo) { snprintf(tmp,255,"out_%d%s",i+1,"R"); oport[1][i] = jack_port_register(client, tmp, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); } else oport[1][i] = 0; } return 0; } fweelin-0.6/src/fweelin_audioio.h0000755000175000017500000000746111050104732015554 0ustar mercmerc#ifndef __FWEELIN_AUDIOIO_H #define __FWEELIN_AUDIOIO_H /* Copyright 2004-2008 Jan Pekau (JP Mercury) This file is part of Freewheeling. Freewheeling is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. Freewheeling is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Freewheeling. If not, see . */ extern "C" { #include } typedef jack_default_audio_sample_t sample_t; typedef jack_nframes_t nframes_t; class Fweelin; class Processor; // **************** SYSTEM LEVEL AUDIO class AudioIO { public: AudioIO(Fweelin *app) : sync_start_frame(0), timebase_master(0), sync_active(0), app(app) {}; // Open up system level audio int open (); // Activate system level audio int activate (Processor *rp); // Close system level audio void close (); // Get realtime buffer size nframes_t getbufsz(); // **Callbacks** // Realtime process function.. the beginning of the DSP chain static int process (nframes_t nframes, void *arg); // Timebase (jack transport sync) callback static void timebase_callback(jack_transport_state_t state, jack_nframes_t nframes, jack_position_t *pos, int new_pos, void *arg); // Sampling rate change callback static int srate_callback (nframes_t nframes, void *arg); // Callback for audio shutdown static void audio_shutdown (void *arg); // Get current sampling rate inline nframes_t get_srate() { return srate; }; // Get approximate audio CPU load inline float GetAudioCPULoad() { return cpuload; }; inline float GetTimeScale() { return timescale; }; // Transport sync methods // Reposition transport to the given position // Used for syncing external apps void RelocateTransport(nframes_t pos); // Get current bar in transport mechanism inline int GetTransport_Bar() { return jpos.bar; }; // Get current beat in transport mechaniasm inline int GetTransport_Beat() { return jpos.beat; }; // Get current BPM in transport mechanism inline double GetTransport_BPM() { return jpos.beats_per_minute; }; // Get current # of beats per bar in transport mechanism inline float GetTransport_BPB() { return jpos.beats_per_bar; }; // Are we sending or receiving sync? inline char IsSync() { return sync_active; }; // Are we the timebase master? inline char IsTimebaseMaster() { return timebase_master; }; // Is the transport rolling? inline char IsTransportRolling() { return transport_roll; }; // Audio system client jack_client_t *client; // Inputs and outputs- stereo pairs jack_port_t **iport[2], **oport[2]; float cpuload; // Current approximate audio CPU load float timescale; // fragment length/sample rate = length (s) of one fragment nframes_t srate; // Sampling rate // Variables for audio (Jack transport) sync // Jack frame where the first bar began in transport int32_t sync_start_frame; char repos; // Nonzero if we have repositioned JACK internally jack_position_t jpos; // Current JACK position char timebase_master; // Nonzero if we are the JACK timebase master char sync_active; // Nonzero if sync is active char transport_roll; // Nonzero if the transport is rolling // Pointer to the main app Fweelin *app; // Processor which is basically the root of the signal flow Processor *rp; }; #endif fweelin-0.6/src/fweelin_block.cc0000755000175000017500000017716211065526167015401 0ustar mercmerc/* Things, in their Essence, are not of this world. */ /* Copyright 2004-2008 Jan Pekau (JP Mercury) This file is part of Freewheeling. Freewheeling is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. Freewheeling is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Freewheeling. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include "fweelin_block.h" #include "fweelin_core.h" iFileDecoder::iFileDecoder(Fweelin *app) : app(app), infd(0) {}; SndFileDecoder::SndFileDecoder(Fweelin *app, codec type) : iFileDecoder(app), filetype(type) { memset (&sfinfo, 0, sizeof (sfinfo)) ; samplesize = sizeof(float); sfinfd = NULL; // rbsize = 0; }; SndFileDecoder::~SndFileDecoder() {}; int SndFileDecoder::ReadFromFile(FILE *in, nframes_t rbuf_len) { if (!(sfinfd = sf_open_fd(fileno(in), SFM_READ, &sfinfo, SF_FALSE) )) { printf("DISK: unable to open file for reading \n"); return 1; } if (sfinfo.channels == 2) { printf("DISK: (SndFile) Stereo loop\n"); stereo = 1; } else if (sfinfo.channels == 1) { printf("DISK: (SndFile) Mono loop\n"); stereo = 0; } else { printf("DISK: (SndFile) Unknown # of audio channels %d\n",sfinfo.channels); return 1; } rbuf = new float[sfinfo.channels*rbuf_len]; obuf[0] = new float[rbuf_len]; if (stereo) obuf[1] = new float[rbuf_len]; if (sfinfo.samplerate != (signed int) app->getAUDIO()->get_srate()) { printf("DISK: (SndFile) Audio encoded at %dHz but we are running at " "%dHz.\n" "Samplerate conversion not yet supported.\n", (int) sfinfo.samplerate, app->getAUDIO()->get_srate()); return 1; } infd = in; return 0; }; int SndFileDecoder::ReadSamples(AudioBlockIterator *it, nframes_t max_len) { int len = 0; if (stereo) { if (filetype == FLAC){ // need to convert from int24 len = sf_read_float(sfinfd,rbuf,sfinfo.channels*max_len); len /= sfinfo.channels; } else { // everything else is currently native float len = sf_read_raw(sfinfd,rbuf,sfinfo.channels*max_len*samplesize); len /= (sfinfo.channels *samplesize); } for (nframes_t i = 0; i < max_len; i++) { // deinterleave channels using brute strength obuf[0][i] = rbuf[2*i]; obuf[1][i] = rbuf[2*i+1]; } if (len > 0) { it->PutFragment(obuf[0],obuf[1],len,1); it->NextFragment(); } } else { if (filetype == FLAC) { // need to convert from int24 len = sf_read_float(sfinfd,obuf[0],sfinfo.channels*max_len); } else { // everything else is currently native float len = sf_read_raw(sfinfd,obuf[0],sfinfo.channels*max_len*samplesize); } if (len > 0) { it->PutFragment(obuf[0],0,len,1); it->NextFragment(); } } return len; }; void SndFileDecoder::Stop(){ if(rbuf != NULL) delete[] rbuf; if(obuf[0] != NULL) delete[] obuf[0]; if(obuf[1] != NULL) delete[] obuf[1]; sf_close(sfinfd); } VorbisDecoder::VorbisDecoder(Fweelin *app) : iFileDecoder(app) {}; VorbisDecoder::~VorbisDecoder() {}; // Returns nonzero on error int VorbisDecoder::ReadFromFile(FILE *in, nframes_t rbuf_len) { if (ov_open(in, &vf, NULL, 0) < 0) { printf("DISK: (VorbisFile) Input does not appear to be an Ogg " "bitstream.\n"); return 1; } vorbis_info *vi = ov_info(&vf,-1); if (vi->channels == 2) { printf("DISK: (VorbisFile) Stereo loop\n"); stereo = 1; } else if (vi->channels == 1) { printf("DISK: (VorbisFile) Mono loop\n"); stereo = 0; } else { printf("DISK: (VorbisFile) Unknown # of audio channels %d\n",vi->channels); return 1; } if (vi->rate != (signed int) app->getAUDIO()->get_srate()) { printf("DISK: (VorbisFile) Audio encoded at %dHz but we are running at " "%dHz.\n" "Samplerate conversion not yet supported.\n", (int) vi->rate,app->getAUDIO()->get_srate()); return 1; } infd = in; return 0; }; int VorbisDecoder::ReadSamples(AudioBlockIterator *i, nframes_t max_len) { int len; float **outb; len = ov_read_float(&vf,&outb,max_len,¤t_section); if (len > 0) { if (stereo) i->PutFragment(outb[0],outb[1],len,1); else i->PutFragment(outb[0],0,len,1); i->NextFragment(); } return len; }; // int VorbisDecoder::Decode(float **pcm_channels, nframes_t max_len) { // return ov_read_float(&vf,&pcm_channels,max_len,¤t_section); // }; iFileEncoder::iFileEncoder(Fweelin *app, char stereo) : app(app), stereo(stereo), outfd(0) { }; SndFileEncoder::SndFileEncoder (Fweelin *app, nframes_t maxframes, char stereo, codec format) : iFileEncoder(app,stereo), tbuf(0) { filetype = format; memset(&sfinfo, 0, sizeof (sfinfo)) ; // set params sfinfo.samplerate = app->getAUDIO()->get_srate(); sfinfo.frames = 0x7FFFFFFF; if (stereo) { sfinfo.channels = 2; tbuf = new float[maxframes*sfinfo.channels]; } else sfinfo.channels = 1; if (filetype == FLAC) sfinfo.format = (SF_FORMAT_FLAC | SF_FORMAT_PCM_24); else sfinfo.format = (SF_FORMAT_WAV | SF_FORMAT_FLOAT); samplesize = sizeof(float); // buffer = NULL; // printf("SndFileEncoder init\n"); }; int SndFileEncoder::SetupFileForWriting (FILE *file) { if (!(sndoutfd = sf_open_fd(fileno(file), SFM_WRITE, &sfinfo, SF_FALSE))) { printf("DISK: Couldn't open output sound file!\n"); return 1; } return 0; }; long int SndFileEncoder::WriteSamplesToDisk (sample_t **ibuf, nframes_t startframe, nframes_t numframes) { if (stereo) { for (nframes_t i = 0; i < numframes; i++) { tbuf[2*i] = ibuf[0][startframe+i]; tbuf[2*i+1] = ibuf[1][startframe+i]; } if (filetype == FLAC) // FIXME: perhaps some error checking sf_write_float(sndoutfd, tbuf, numframes*sfinfo.channels); else sf_write_raw(sndoutfd, static_cast(tbuf), numframes*samplesize*sfinfo.channels); } else { if (filetype == FLAC) // FIXME: perhaps some error checking sf_write_float(sndoutfd, ibuf[0], numframes); else sf_write_raw(sndoutfd, ibuf[0], numframes*samplesize); } return (long int) numframes; } void SndFileEncoder::PrepareFileForClosing(){ sf_close(sndoutfd); } VorbisEncoder::VorbisEncoder(Fweelin *app, char stereo) : iFileEncoder(app,stereo) { // Setup vorbis vorbis_info_init(&vi); if (vorbis_encode_init_vbr(&vi,(stereo ? 2 : 1),app->getAUDIO()->get_srate(), app->getCFG()->GetVorbisEncodeQuality())) return; // Comment vorbis_comment_init(&vc); vorbis_comment_add_tag(&vc,"ENCODER","FreeWheeling"); // Analysis state/Aux encoding storage vorbis_analysis_init(&vd,&vi); vorbis_block_init(&vd,&vb); /* set up our packet->stream encoder */ /* pick a random serial number; that way we can more likely build chained streams just by concatenation */ srand(time(NULL)); ogg_stream_init(&os,rand()); }; VorbisEncoder::~VorbisEncoder() { /* Vorbis clean up and exit. vorbis_info_clear() must be called last */ ogg_stream_clear(&os); vorbis_block_clear(&vb); vorbis_dsp_clear(&vd); vorbis_comment_clear(&vc); vorbis_info_clear(&vi); }; int VorbisEncoder::SetupFileForWriting(FILE *out) { outfd = out; // Write vorbis header ogg_packet header; ogg_packet header_comm; ogg_packet header_code; vorbis_analysis_headerout(&vd,&vc,&header,&header_comm,&header_code); ogg_stream_packetin(&os,&header); /* automatically placed in its own page */ ogg_stream_packetin(&os,&header_comm); ogg_stream_packetin(&os,&header_code); while(1) { int result = ogg_stream_flush(&os,&og); if (result == 0) break; fwrite(og.header,1,og.header_len,outfd); fwrite(og.body,1,og.body_len,outfd); } return 0; }; long int VorbisEncoder::WriteSamplesToDisk (sample_t **ibuf, nframes_t startframe, nframes_t numframes) { // Here we make assumption that sample_t is equivalent to float // And that there is only 1 vorbis channel of data float **obuf = GetAnalysisBuffer(numframes); if (stereo) { memcpy(obuf[0], &ibuf[0][startframe], sizeof(float) * numframes); memcpy(obuf[1], &ibuf[1][startframe], sizeof(float) * numframes); } else { memcpy(obuf[0], &ibuf[0][startframe], sizeof(float) * numframes); } WroteToBuffer(numframes); Encode(); return (long int) numframes; }; // This analyzes and dumps any remaining frames out to file long int VorbisEncoder::Encode() { if (outfd != 0) { long int outputsize = 0; // Now do the real analysis!! Meat n potatoes! while(vorbis_analysis_blockout(&vd,&vb) == 1) { /* analysis, assume we want to use bitrate management */ vorbis_analysis(&vb,NULL); vorbis_bitrate_addblock(&vb); while(vorbis_bitrate_flushpacket(&vd,&op)) { /* weld the packet into the bitstream */ ogg_stream_packetin(&os,&op); /* write out pages (if any) */ char eos = 0; while (!eos) { int result = ogg_stream_pageout(&os,&og); if (result == 0) break; fwrite(og.header,1,og.header_len,outfd); fwrite(og.body,1,og.body_len,outfd); // Add to the output size outputsize += og.header_len; outputsize += og.body_len; if (ogg_page_eos(&og)) eos = 1; } } } return outputsize; } else { printf("BLOCK: ERROR: OGG encoder finished but Encode() called!\n"); return 0; } } void VorbisEncoder::Preprocess(sample_t *l, sample_t *r, nframes_t len) { if (r == 0) //mono for (nframes_t i = 0; i < len; i++) l[i] *= 0.9; else { for (nframes_t i = 0; i < len; i++) { l[i] *= 0.9; r[i] *= 0.9; } } }; BlockReadManager::BlockReadManager(FILE *in, AutoReadControl *arc, BlockManager *bmg, nframes_t peaksavgs_chunksize) : ManagedChain(0,0), in(in), smooth_end(0), arc(arc), dec(0), bmg(bmg), pa_mgr(0), peaksavgs_chunksize(peaksavgs_chunksize) { pthread_mutex_init(&decode_lock,0); }; BlockReadManager::~BlockReadManager() { if (in != 0) { End(0); } pthread_mutex_destroy (&decode_lock); }; void BlockReadManager::SetLoopType (codec looptype){ printf("DISK: Looptype: %s\n", bmg->GetApp()->getCFG()->GetCodecName(looptype)); filetype = looptype; }; // Start decoding from the given file void BlockReadManager::Start(FILE *new_in) { if (dec != 0) return; // Already running if (in == 0 && new_in != 0) { // New input specified in = new_in; } if (in != 0) { // Start vorbis decoder switch (filetype) { case VORBIS: dec = new VorbisDecoder(bmg->GetApp()); break; case WAV: dec = new SndFileDecoder(bmg->GetApp(),WAV); break; case FLAC: dec = new SndFileDecoder(bmg->GetApp(),FLAC); break; case AU: dec = new SndFileDecoder(bmg->GetApp(),AU); break; default: dec = new VorbisDecoder(bmg->GetApp()); break; } b = (AudioBlock *) bmg->GetApp()->getPRE_AUDIOBLOCK()->RTNewWithWait(); i = new AudioBlockIterator(b,DECODE_CHUNKSIZE, bmg->GetApp()->getPRE_EXTRACHANNEL()); // Compute audio peaks & averages for display if (peaksavgs_chunksize != 0) { AudioBlock *peaks = (AudioBlock *) b->RTNew(), *avgs = (AudioBlock *) b->RTNew(); if (peaks == 0 || avgs == 0) { printf("BlockReadManager: ERROR: No free blocks for peaks/avgs\n"); if (peaks != 0) peaks->RTDelete(); if (avgs != 0) avgs->RTDelete(); pa_mgr = 0; } else { b->AddExtendedData(new BED_PeaksAvgs(peaks,avgs,peaksavgs_chunksize)); pa_mgr = bmg->PeakAvgOn(b,i,1); } } // Tell decoder to read from file if (dec->ReadFromFile(in,DECODE_CHUNKSIZE)) // End in error, freeing vorbis End(1); } }; void BlockReadManager::End(char error) { // Can't end while decoding- lock mutex pthread_mutex_lock (&decode_lock); // Stop decoder if (dec != 0) { dec->Stop(); delete dec; // Chop block to current position i->EndChain(); // End peaks avgs compute now if (pa_mgr != 0) { // Catchup then end pa_mgr->Manage(); pa_mgr->End(); bmg->PeakAvgOff(b); pa_mgr = 0; } delete i; i = 0; dec = 0; } if (in != 0) { printf("DISK: Close input.\n"); // Vorbis decoder closes file through ov_clear! in = 0; } if (b != 0) { if (error) { // If error, delete chain and send zero to ReadComplete b->DeleteChain(); b = 0; } else { // Finished read, handle looppoint smoothing if (smooth_end) // New way printf("blen: %d\n",b->GetTotalLen()); // b->Smooth(0,BlockWriteManager::ENCODE_CROSSOVER_LEN); else { // Old way b->Smooth(1,BlockReadManager::SMOOTH_FIX_LEN); // We will have to adjust the pulselength because we are changing the // length of the loop here } } // Callback if (arc != 0) arc->ReadComplete(b); b = 0; } pthread_mutex_unlock(&decode_lock); }; int BlockReadManager::Manage() { if (in == 0) { // Not currently decoding if (arc != 0) { // We have a callback, get a chain to load arc->GetReadBlock(&in,&smooth_end); if (in != 0) // We got a chain to load, so begin Start(); } else { // No callback, so we are done! return 1; } } if (in != 0) { // Make sure we have started on this blockchain if (dec == 0) Start(); // Continue decoding pthread_mutex_lock (&decode_lock); // Now that we have the lock, make sure we are still active if (in != 0) { for (int pass = 0; in != 0 && pass < NUM_DECODE_PASSES; pass++) { // Make sure we have an extra block in our chain if (i->GetCurBlock()->next == 0) { AudioBlock *nw = (AudioBlock *) i->GetCurBlock()->RTNew(); if (nw == 0) { // Pause decode until block is here printf("BlockReadManager: Waiting for block.\n"); pthread_mutex_unlock (&decode_lock); return 0; } i->GetCurBlock()->Link(nw); } // Decode samples int len = dec->ReadSamples(i,DECODE_CHUNKSIZE); if (len == 0) { // EOF pthread_mutex_unlock (&decode_lock); End(0); } else if (len < 0) { // Stream error- just continue printf("BlockReadManager: Stream read error!\n"); } } } pthread_mutex_unlock (&decode_lock); } return 0; }; BlockWriteManager::BlockWriteManager(FILE *out, AutoWriteControl *awc, BlockManager *bmg, AudioBlock *b, AudioBlockIterator *i) : ManagedChain(b,i), out(out), len(0), awc(awc), enc(0), bmg(bmg) { pthread_mutex_init(&encode_lock,0); }; BlockWriteManager::~BlockWriteManager() { if (b != 0) { End(); } pthread_mutex_destroy (&encode_lock); }; // Start encoding the given block chain to the given file void BlockWriteManager::Start(FILE *new_out, AudioBlock *new_b, AudioBlockIterator *new_i, nframes_t new_len) { if (enc != 0) return; // Already running if (b == 0 && new_b != 0) { // New chain specified // printf("start: new chain b: %p new_b: %p\n",b,new_b); b = new_b; i = new_i; out = new_out; len = new_len; } if (b != 0) { //printf("start: out: %p new_out: %p, b: %p new_b: %p\n",out,new_out, // b,new_b); // Encode an extra ENCODE_CROSSOVER_LEN frames at the end // because OGG loops are not sample aligned from end-to-begin // len += ENCODE_CROSSOVER_LEN; // printf("slen: %d\n", len); pos = 0; // Start File encoder Fweelin *app = bmg->GetApp(); switch (app->getCFG()->GetLoopOutFormat()) { case VORBIS: enc = new VorbisEncoder(app,b->IsStereo()); break; case WAV: enc = new SndFileEncoder(app,ENCODE_CHUNKSIZE,b->IsStereo(),WAV); break; case FLAC: enc = new SndFileEncoder(app,ENCODE_CHUNKSIZE,b->IsStereo(),FLAC); break; case AU: enc = new SndFileEncoder(app,ENCODE_CHUNKSIZE,b->IsStereo(),AU); break; default: enc = new VorbisEncoder(app,b->IsStereo()); break; }; ei = new AudioBlockIterator(b,ENCODE_CHUNKSIZE); // Set encoder to dump to file enc->SetupFileForWriting(out); } }; void BlockWriteManager::End() { // Can't end while encoding- lock mutex pthread_mutex_lock (&encode_lock); // Stop encoder if (enc != 0) { enc->PrepareFileForClosing(); delete enc; delete ei; enc = 0; } if (out != 0) { printf("DISK: Close output.\n"); fclose(out); out = 0; } b = 0; i = 0; len = 0; pthread_mutex_unlock(&encode_lock); }; int BlockWriteManager::Manage() { if (b == 0) { // Not currently encoding if (awc != 0) { // We have a callback, get a chain to save awc->GetWriteBlock(&out,&b,&i,&len); if (b != 0) // We got a chain to save, so begin Start(); } else { // No callback, so we are done! return 1; } } if (b != 0) { // Make sure we have started on this blockchain if (enc == 0) Start(); // Continue encoding pthread_mutex_lock (&encode_lock); // Now that we have the lock, make sure we are still active if (b != 0) { nframes_t remaining = len-pos, num = MIN(ENCODE_CHUNKSIZE,remaining); sample_t *ibuf[2]; if (enc->IsStereo()) { // Stereo ei->GetFragment(&ibuf[0],&ibuf[1]); pos += enc->WriteSamplesToDisk(ibuf,0,num); } else { // Mono ei->GetFragment(&ibuf[0],0); pos += enc->WriteSamplesToDisk(ibuf,0,num); } if (remaining <= ENCODE_CHUNKSIZE) { // Finished encoding pthread_mutex_unlock (&encode_lock); End(); } else ei->NextFragment(); } pthread_mutex_unlock (&encode_lock); } return 0; }; BED_PeaksAvgs::~BED_PeaksAvgs() { peaks->DeleteChain(); avgs->DeleteChain(); }; int BED_MarkerPoints::CountMarkers() { TimeMarker *cur = markers; int markcnt = 0; while (cur != 0) { markcnt++; cur = cur->next; }; return markcnt; }; BED_MarkerPoints::~BED_MarkerPoints() { TimeMarker *cur = markers; while (cur != 0) { TimeMarker *tmp = cur->next; cur->RTDelete(); cur = tmp; } }; // Returns the nth marker before (in time) the current offset passed // This method correctly handles a reverse wrap case when the // marker NBeforeCur is farther ahead in the attached block than the // current offset TimeMarker *BED_MarkerPoints::GetMarkerNBeforeCur(int n, nframes_t curofs) { TimeMarker *cur = markers; signed int markcnt = 0; int totalmarks = CountMarkers(); if (totalmarks == 0) return 0; // No solution because there are no markers! else { while (cur != 0 && cur->markofs < curofs) { markcnt++; cur = cur->next; } // Markcnt now indexes the next marker after curofs // Go N before! markcnt -= n; while (markcnt < 0) { // Reverse wrap case markcnt += totalmarks; } // Now get marker indexed by markcnt cur = markers; int markcnt2 = 0; while (cur != 0 && markcnt2 != markcnt) { markcnt2++; cur = cur->next; } // & return it return cur; } }; // Create a new extra channel BED_ExtraChannel::BED_ExtraChannel(nframes_t len) { if (len > 0) { //printf("allocating origbuf..\n"); origbuf = buf = new sample_t[len]; //printf("done: origbuf %p: buf %p!..\n",origbuf,buf); } else origbuf = buf = 0; }; BED_ExtraChannel::~BED_ExtraChannel() { if (origbuf != 0) { //printf("deleting origbuf %p: buf %p!..\n",origbuf,buf); delete[] origbuf; //printf("done!\n"); } }; // Create a new audioblock as the beginning of a block list AudioBlock::AudioBlock(nframes_t len) : len(len), next(0), first(this), xt(0) { if (len > 0) origbuf = buf = new sample_t[len]; } // Create a new audioblock and link up the specified block to it AudioBlock::AudioBlock(AudioBlock *prev, nframes_t len) : len(len), next(0), first(prev->first), xt(0) { prev->next = this; if (len > 0) origbuf = buf = new sample_t[len]; } AudioBlock::~AudioBlock() { //printf("~AudioBlock len: %d dsz: %d\n",len,sizeof(*buf)); if (origbuf != 0) delete[] origbuf; } // Clears this block chain- not changing length void AudioBlock::Zero() { AudioBlock *cur = first; while (cur != 0) { memset(cur->buf,0,sizeof(sample_t)*cur->len); cur = cur->next; } }; // Link us up to the specified block void AudioBlock::Link(AudioBlock *to) { to->first = first; to->next = 0; next = to; } // RT safe void AudioBlock::ChopChain() { // Chop off the chain at this block // Freeing unused blocks AudioBlock *cur = next; next = 0; while (cur != 0) { AudioBlock *tmp = cur->next; if (cur->xt != 0) printf("BLOCK: WARNING: XT data not freed in ChopChain! " "Possible leak.\n"); cur->RTDelete(); cur = tmp; } } // Smooth an audio block- // either smooth the beginning into the end (smoothtype == 1) // or smooth the end into the beginning (smoothtype == 0) void AudioBlock::Smooth(char smoothtype, nframes_t smoothlen) { // Smooth the end of this chain into the beginning for looping AudioBlock *smoothblk; nframes_t smoothofs, smoothcnt, totallen = GetTotalLen(); if (totallen >= smoothlen) smoothcnt = totallen - smoothlen; else return; // Very short chain, can't smooth it // Get block & offset for start of smooth SetPtrsFromAbsOffset(&smoothblk, &smoothofs, smoothcnt); if (smoothblk == 0) { // Shouldn't happen printf("AudioBlock: ERROR: Block position mismatch in Smooth.\n"); exit(1); } AudioBlock *startblk = first; nframes_t startofs = 0; // Second channel? BED_ExtraChannel *rightstartblk = (BED_ExtraChannel *) startblk->GetExtendedData(T_BED_ExtraChannel), *rightsmoothblk = (BED_ExtraChannel *) smoothblk->GetExtendedData(T_BED_ExtraChannel); char stereo = 0; if (rightstartblk != 0 && rightsmoothblk != 0) stereo = 1; float mix = 0.0, dmix = 1./(float)smoothlen; for (nframes_t i = 0; i < smoothlen; i++, mix += dmix) { if (smoothtype) { // Write beginning into end smoothblk->buf[smoothofs] = mix*startblk->buf[startofs] + (1.0-mix)*smoothblk->buf[smoothofs]; if (stereo) rightsmoothblk->buf[smoothofs] = mix*rightstartblk->buf[startofs] + (1.0-mix)*rightsmoothblk->buf[smoothofs]; } else { // Write end into beginning startblk->buf[startofs] = mix*startblk->buf[startofs] + (1.0-mix)*smoothblk->buf[smoothofs]; if (stereo) rightstartblk->buf[startofs] = mix*rightstartblk->buf[startofs] + (1.0-mix)*rightsmoothblk->buf[smoothofs]; } smoothofs++; startofs++; if (smoothofs >= smoothblk->len) { smoothblk = smoothblk->next; smoothofs = 0; if (smoothblk == 0) { if (i+1 < smoothlen) { // Shouldn't happen printf("AudioBlock: ERROR: (smoothblk) Block size mismatch in " "Smooth: i: %d\n", i); exit(1); } rightsmoothblk = 0; } else { rightsmoothblk = (BED_ExtraChannel *) smoothblk->GetExtendedData(T_BED_ExtraChannel); if (stereo && rightsmoothblk == 0) { // Shouldn't happen printf("AudioBlock: ERROR: (smoothblk) Right channel " "disappeared!\n"); exit(1); } } } if (startofs >= startblk->len) { startblk = startblk->next; startofs = 0; if (startblk == 0) { if (i+1 < smoothlen) { // Shouldn't happen printf("AudioBlock: ERROR: (startblk) Block size mismatch in " "Smooth.\n"); exit(1); } rightstartblk = 0; } else { rightstartblk = (BED_ExtraChannel *) startblk->GetExtendedData(T_BED_ExtraChannel); if (stereo && rightstartblk == 0) { // Shouldn't happen printf("AudioBlock: ERROR: (startblk) Right channel disappeared!\n"); exit(1); } } } } if (smoothtype) { // Adjust first buf to skip samples that were smoothed into end if (first->len < smoothlen) { printf("AudioBlock: WARNING: First block is very short, " "no adjust in Smooth.\n"); } else { first->buf += smoothlen; first->len -= smoothlen; BED_ExtraChannel *rightfirst = (BED_ExtraChannel *) first->GetExtendedData(T_BED_ExtraChannel); if (rightfirst != 0) rightfirst->buf += smoothlen; } } else { // Shorten the chain to skip end which is now smoothed into beginning HackTotalLengthBy(smoothlen); } //printf("endsmooth: startofs: %d smoothofs: %d len: %d\n", // startofs, smoothofs, totallen); } // not RT safe void AudioBlock::DeleteChain() { AudioBlock *cur = first; while (cur != 0) { // First erase any extended data BlockExtendedData *curxt = cur->xt; while (curxt != 0) { BlockExtendedData *tmpxt = curxt->next; delete curxt; curxt = tmpxt; } // Then the block itself! AudioBlock *tmp = cur->next; cur->RTDelete(); cur = tmp; } } // Returns the total length of this audio chain nframes_t AudioBlock::GetTotalLen() { nframes_t tally = 0; AudioBlock *cur = first; while (cur != 0) { tally += cur->len; cur = cur->next; } return tally; }; // Gets extended data for this block BlockExtendedData *AudioBlock::GetExtendedData(BlockExtendedDataType x) { BlockExtendedData *cur = xt; while (cur!=0 && cur->GetType()!=x) cur = cur->next; return cur; }; // Add this extended data to the list of extended data for this block void AudioBlock::AddExtendedData(BlockExtendedData *nw) { nw->next = xt; xt = nw; }; // Finds the audioblock and offset into that block that correspond // to the provided absolute offset into this chain void AudioBlock::SetPtrsFromAbsOffset(AudioBlock **ptr, nframes_t *blkofs, nframes_t absofs) { AudioBlock *cur = first, *prev = 0; nframes_t curofs = 0, prevofs = 0; while (cur != 0 && curofs <= absofs) { prevofs = curofs; curofs += cur->len; prev = cur; cur = cur->next; } if (curofs < absofs || prev == 0) { // We're at the end and we still haven't traversed far enough! // Return err *ptr = 0; return; } *ptr = prev; *blkofs = absofs-prevofs; }; // Generates a subchain of AudioBlocks by copying the samples between offsets // from & to.. offsets expressed absolutely with reference to // beginning of this chain! // Samples are copied up to but not including toofs // If toofs < fromofs, generates a subblock that includes the end of // the block and the beginning up to toofs (wrap case) // Returns the last block in the new subchain // Flag sets whether to copy stereo channel if there is one // Realtime safe? AudioBlock *AudioBlock::GenerateSubChain(nframes_t fromofs, nframes_t toofs, char copystereo) { if (toofs == fromofs) return 0; // Handle wrap case if (toofs < fromofs) toofs += GetTotalLen(); // Stereo? BED_ExtraChannel *rightfirst = (BED_ExtraChannel *) first->GetExtendedData(T_BED_ExtraChannel); char stereo = (copystereo && rightfirst != 0); // Get enough new blocks to fit the subblock size nframes_t sublen = toofs - fromofs, suballoc = 0; AudioBlock *subfirst = 0, *subcur = 0; while (suballoc < sublen) { if (subfirst == 0) { subcur = subfirst = (AudioBlock *)RTNew(); if (subfirst == 0) { printf("Err: GenerateSubChain- No new blocks available\n"); return 0; } } else { AudioBlock *tmp = (AudioBlock *)RTNew(); if (tmp == 0) { printf("Err: GenerateSubChain- No new blocks available\n"); return 0; } subcur->Link(tmp); subcur = subcur->next; } if (stereo) { BED_ExtraChannel *rightsub = (BED_ExtraChannel*)rightfirst->RTNew(); if (rightsub == 0) { printf("Err: GenerateSubChain- No new right blocks available\n"); return 0; } subcur->AddExtendedData(rightsub); } suballoc += subcur->len; } // Find starting pos in chain AudioBlock *cur; nframes_t curofs = 0; SetPtrsFromAbsOffset(&cur,&curofs,fromofs); subcur = subfirst; nframes_t subofs = 0, remaining = sublen; // Extra channel BED_ExtraChannel *subright = (stereo ? (BED_ExtraChannel *) subcur->GetExtendedData(T_BED_ExtraChannel) : 0), *right = (stereo ? (BED_ExtraChannel *) cur->GetExtendedData(T_BED_ExtraChannel) : 0); do { nframes_t n = MIN(cur->len-curofs,remaining); n = MIN(n,subcur->len-subofs); memcpy(&subcur->buf[subofs],&cur->buf[curofs],n*sizeof(sample_t)); if (stereo) memcpy(&subright->buf[subofs],&right->buf[curofs],n*sizeof(sample_t)); subofs += n; curofs += n; remaining -= n; if (curofs >= cur->len) { cur = cur->next; curofs = 0; if (cur == 0) // Past the end of the block chain-- wrap around to first cur = first; if (stereo) right = (BED_ExtraChannel *) cur->GetExtendedData(T_BED_ExtraChannel); } if (subofs >= subcur->len) { subcur = subcur->next; subofs = 0; if (subcur == 0 && remaining) { // This should never happen, because we make the destination // chain long enough to hold the subblock printf("Err: GenerateSubChain destination block size mismatch\n"); exit(1); } if (stereo) subright = (BED_ExtraChannel *) subcur->GetExtendedData(T_BED_ExtraChannel); } } while (remaining); // Truncate the last presized subblock to the right length subcur->len = subofs; // And return the last block in the chain return subcur; }; // *** To be tested! *** // // Removes the last 'hacklen' samples from this block chain // Returns nonzero on error! // Realtime safe? int AudioBlock::HackTotalLengthBy(nframes_t hacklen) { // Compute the position of hack nframes_t chainlen = GetTotalLen(); //printf("Hack (b): %ld\n",chainlen); AudioBlock *hackblk; nframes_t hackofs = 0; if (chainlen <= hacklen) return 1; SetPtrsFromAbsOffset(&hackblk,&hackofs,chainlen-hacklen); // Now hackblk[hackofs] should be the first sample to erase at the // end of the chain hackblk->len = hackofs; // Truncate length of block // Note: Block memory isnt resized, so some extra memory lingers until // the block is erased AudioBlock *tmp = hackblk->next; hackblk->next = 0; // End of chain at hack position // Erase remaining blocks in chain hackblk = tmp; while (hackblk != 0) { tmp = hackblk->next; // First erase any extended data BlockExtendedData *hackxt = hackblk->xt; while (hackxt != 0) { BlockExtendedData *tmpxt = hackxt->next; delete hackxt; hackxt = tmpxt; } // Then the block itself hackblk->RTDelete(); hackblk = tmp; } //printf("Hack (e): %ld\n",GetTotalLen()); return 0; }; // Inserts the new blockchain at the beginning of this block chain // Returns a pointer to the new first block AudioBlock *AudioBlock::InsertFirst(AudioBlock *nw) { // Move to the end of the passed chain while (nw->next != 0) nw = nw->next; // Link new block to the beginning of our chain nw->next = first; // Link all first pointers to first block in new chain AudioBlock *cur = first; while (cur != 0) { cur->first = nw->first; cur = cur->next; } return nw->first; }; AudioBlockIterator::AudioBlockIterator(AudioBlock *firstblock, nframes_t fragmentsize, PreallocatedType *pre_extrachannel) : pre_extrachannel(pre_extrachannel), currightblock(0), nextrightblock(0), curblock(firstblock), nextblock(0), curblkofs(0), nextblkofs(0), curcnt(0), nextcnt(0), currightblock_w(0), nextrightblock_w(0), curblock_w(0 /*???*/), nextblock_w(0), curblkofs_w(0), nextblkofs_w(0), curcnt_w(0), nextcnt_w(0), fragmentsize(fragmentsize), stopped(0) { fragment[0] = new sample_t[fragmentsize]; fragment[1] = new sample_t[fragmentsize]; } AudioBlockIterator::~AudioBlockIterator() { delete[] fragment[0]; delete[] fragment[1]; }; // Stores in cnt the absolute count corresponding to the given // block and offset void AudioBlockIterator::GenCnt(AudioBlock *blk, nframes_t blkofs, nframes_t *cnt) { AudioBlock *cur = curblock->first; nframes_t curofs = 0; while (cur != 0 && cur != blk) { // Add the length of this whole block curofs += cur->len; cur = cur->next; } if (cur == 0) { // Given block not found! *cnt = 0; } else { // We are now on the given block- add only current block offset curofs += blkofs; *cnt = curofs; } } void AudioBlockIterator::Jump(nframes_t ofs) { // Quantize the specified offset to within the limits of the blockchain ofs = ofs % curblock->GetTotalLen(); nframes_t cb_ofs = 0; curblock->SetPtrsFromAbsOffset(&curblock,&cb_ofs,ofs); curblkofs = cb_ofs; if (curblock == 0) { printf("Err: AudioBlockIterator::Jump- Pointer/size mismatch\n"); exit(1); } currightblock = 0; nextrightblock = 0; nextblock = 0; nextblkofs = 0; curcnt = ofs; nextcnt = 0; } void AudioBlockIterator::GenConstants() { // Need to recompute curcnt to account for extra blocks? nframes_t tmp; GenCnt(curblock,(nframes_t) curblkofs,&tmp); curcnt = tmp; GenCnt(nextblock,(nframes_t) nextblkofs,&tmp); nextcnt = tmp; } // Moves iterator to start position void AudioBlockIterator::Zero() { currightblock = 0; nextrightblock = 0; curblock = curblock->first; curblkofs = 0; curcnt = 0; nextblock = 0; } // Advances to the next fragment void AudioBlockIterator::NextFragment() { // Only advance if not stopped if (!stopped) { // We must first get a fragment before advancing if (nextblock == 0) GetFragment(0,0); currightblock = nextrightblock; nextrightblock = 0; curblock = nextblock; curblkofs = nextblkofs; curcnt = nextcnt; nextblock = 0; // Also advance write block (if rate scaling) char ratescale = 0; if (ratescale) { currightblock_w = nextrightblock_w; nextrightblock_w = 0; curblock_w = nextblock_w; curblkofs_w = nextblkofs_w; curcnt_w = nextcnt_w; nextblock_w = 0; } } } // PutFragment stores the specified fragment into this AudioBlock // returns nonzero if the end of the block is reached, and we wrap to next int AudioBlockIterator::PutFragment (sample_t *frag_l, sample_t *frag_r, nframes_t size_override, char wait_alloc) { nframes_t fragofs = 0; nframes_t n = (size_override == 0 ? fragmentsize : size_override); int wrap = 0; char ratescale = 0; // Keep local track of pointers // Since we have to be threadsafe BED_ExtraChannel *lclrightblock; AudioBlock *lclblock; double lclblkofs, lclcnt; if (ratescale) { // Use write block lclrightblock = currightblock_w; lclblock = curblock_w; lclblkofs = curblkofs_w; lclcnt = curcnt_w; } else { // Write to read block (no scaling on read, // so same buffers can be used) lclrightblock = currightblock; lclblock = curblock; lclblkofs = curblkofs; lclcnt = curcnt; } nframes_t nextbit; do { nframes_t lclblkofs_d = (nframes_t) lclblkofs; nextbit = MIN((nframes_t) n, lclblock->len - lclblkofs_d); // Copy into block // Left memcpy(&lclblock->buf[lclblkofs_d], &frag_l[fragofs], sizeof(sample_t)*nextbit); // If right channel is given and we don't know the right block, find it if (frag_r != 0) { if (lclrightblock == 0) { lclrightblock = (BED_ExtraChannel *) lclblock->GetExtendedData(T_BED_ExtraChannel); if (lclrightblock == 0) { // No right channel exists but we are being told to put data there-- // so create a right channel! if (pre_extrachannel == 0) { printf("BLOCK: ERROR: Need to make right channel buffer but no " "preallocator was passed!\n"); return 0; } else { do { lclrightblock = (BED_ExtraChannel *) pre_extrachannel->RTNew(); if (lclrightblock == 0 && wait_alloc) { printf("BLOCK: Waiting for BED_ExtraChannel.\n"); usleep(10000); // Wait then try again } } while (lclrightblock == 0 && wait_alloc); if (lclrightblock != 0) lclblock->AddExtendedData(lclrightblock); else { printf("BLOCK: ERROR: RTNew() failed for BED_ExtraChannel.\n"); return 0; } } } } // Right memcpy(&lclrightblock->buf[lclblkofs_d], &frag_r[fragofs], sizeof(sample_t)*nextbit); } fragofs += nextbit; lclblkofs += nextbit; lclcnt += nextbit; n -= nextbit; if (lclblkofs >= lclblock->len) { // If we get here, it means this block has been fully dumped // so we need the next block wrap = 1; if (lclblock->next == 0) { // END OF AUDIOBLOCK LIST, LOOP TO BEGINNING lclblock = lclblock->first; lclblkofs = 0; lclcnt = lclblkofs; lclrightblock = 0; } else { lclblock = lclblock->next; lclblkofs = 0; lclrightblock = 0; } } } while (n); if (ratescale) { nextblock_w = lclblock; nextrightblock_w = lclrightblock; nextblkofs_w = lclblkofs; nextcnt_w = lclcnt; } else { nextblock = lclblock; nextrightblock = lclrightblock; nextblkofs = lclblkofs; nextcnt = lclcnt; } return wrap; } // Returns the current fragment of audio // nextblock and nextblkofs become the new block pointer and offset // for the next fragment void AudioBlockIterator::GetFragment(sample_t **frag_l, sample_t **frag_r) { // Keep local track of pointers // Since we have to be threadsafe BED_ExtraChannel *lclrightblock = currightblock; AudioBlock *lclblock = curblock; double lclblkofs = curblkofs, lclcnt = curcnt; char ratescale = 0; float rate = 2.0; if (ratescale) { double n = fragmentsize*rate; if (lclblkofs + n + 1 >= lclblock->len) { // Wrap happens here- check bounds in loop for (nframes_t cnt = 0; cnt < fragmentsize; cnt++) { // Linear interpolation rate scale nframes_t decofs = (nframes_t) lclblkofs; float fracofs = lclblkofs - decofs; if (frag_r != 0) { if (lclrightblock == 0) { lclrightblock = (BED_ExtraChannel *) lclblock->GetExtendedData(T_BED_ExtraChannel); if (lclrightblock == 0) { // No right channel exists but we are being told to get data-- printf("BLOCK: ERROR: Iterator asked for right channel but none " "exists!\n"); return; } } } sample_t s1 = lclblock->buf[decofs], s2, s1r, s2r; if (frag_r != 0) s1r = lclrightblock->buf[decofs]; nframes_t decofs_p1 = decofs+1; if (decofs_p1 < lclblock->len) { s2 = lclblock->buf[decofs_p1]; if (frag_r != 0) s2r = lclrightblock->buf[decofs_p1]; } else { AudioBlock *next_b; if (lclblock->next != 0) next_b = lclblock->next; else next_b = lclblock->first; s2 = next_b->buf[0]; if (frag_r != 0) { BED_ExtraChannel *tmp_r = (BED_ExtraChannel *) next_b->GetExtendedData(T_BED_ExtraChannel); if (tmp_r != 0) s2r = tmp_r->buf[0]; else s2r = s1r; } } float fracofs_om = 1.0-fracofs; fragment[0][cnt] = fracofs*s2 + fracofs_om*s1; if (frag_r != 0) fragment[1][cnt] = fracofs*s2r + fracofs_om*s1r; lclblkofs += rate; lclcnt += rate; if (lclblkofs >= lclblock->len) { // If we get here, it means this block is at an end // so we need the next block lclblkofs -= lclblock->len; if (lclblock->next == 0) { // END OF AUDIOBLOCK LIST, LOOP TO BEGINNING lclcnt = lclblkofs; lclblock = lclblock->first; lclrightblock = 0; } else { lclblock = lclblock->next; lclrightblock = 0; } } } } else { // No wrap- don't check bounds for (nframes_t cnt = 0; cnt < fragmentsize; cnt++, lclblkofs += rate, lclcnt += rate) { // Linear interpolation rate scale nframes_t decofs = (nframes_t) lclblkofs; float fracofs = lclblkofs - decofs; if (frag_r != 0) { if (lclrightblock == 0) { lclrightblock = (BED_ExtraChannel *) lclblock->GetExtendedData(T_BED_ExtraChannel); if (lclrightblock == 0) { // No right channel exists but we are being told to get data-- printf("BLOCK: ERROR: Iterator asked for right channel but none " "exists!\n"); return; } } } nframes_t decofs_p1 = decofs+1; sample_t s1 = lclblock->buf[decofs], s2 = lclblock->buf[decofs_p1]; float fracofs_om = 1.0-fracofs; fragment[0][cnt] = fracofs*s2 + fracofs_om*s1; if (frag_r != 0) { sample_t s1r = lclrightblock->buf[decofs], s2r = lclrightblock->buf[decofs_p1]; fragment[1][cnt] = fracofs*s2r + fracofs_om*s1r; } } } } else { // No rate scale nframes_t fragofs = 0; nframes_t n = fragmentsize; nframes_t nextbit; do { nframes_t lclblkofs_d = (nframes_t) lclblkofs; nextbit = MIN((nframes_t) n, lclblock->len - lclblkofs_d); if (nextbit) { // Left memcpy(&fragment[0][fragofs], &lclblock->buf[lclblkofs_d], sizeof(sample_t)*nextbit); // If right channel is given and we don't know the right block, find it if (frag_r != 0) { if (lclrightblock == 0) { lclrightblock = (BED_ExtraChannel *) lclblock->GetExtendedData(T_BED_ExtraChannel); if (lclrightblock == 0) { // No right channel exists but we are being told to get data-- printf("BLOCK: ERROR: Iterator asked for right channel but none " "exists!\n"); return; } } // Right memcpy(&fragment[1][fragofs], &lclrightblock->buf[lclblkofs_d], sizeof(sample_t)*nextbit); } else // Make -sure- we don't jump blocks and keep old rightblock lclrightblock = 0; fragofs += nextbit; lclblkofs += nextbit; lclcnt += nextbit; n -= nextbit; } if (lclblkofs >= lclblock->len) { // If we get here, it means this block is at an end // so we need the next block if (lclblock->next == 0) { // END OF AUDIOBLOCK LIST, LOOP TO BEGINNING lclblock = lclblock->first; lclblkofs = 0; lclcnt = lclblkofs; lclrightblock = 0; } else { lclblock = lclblock->next; lclblkofs = 0; // Beginning of next block lclrightblock = 0; } } } while (n); } nextblock = lclblock; nextrightblock = lclrightblock; nextblkofs = lclblkofs; nextcnt = lclcnt; // Return fragment buffers if (frag_l != 0) *frag_l = fragment[0]; if (frag_r != 0) *frag_r = fragment[1]; }; // RT safe void AudioBlockIterator::EndChain() { // Mark iterator stopped stopped = 1; //printf("Crop: %ld to %ld\n", curblock->len, curblkofs); if (curblkofs < (nframes_t) fragmentsize) { //printf("WARNING: REALLY SHORT BLOCK: %d\n",curblkofs); curblock->len = fragmentsize; } else curblock->len = (nframes_t) curblkofs; // Stop the chain at this place curblock->ChopChain(); } int GrowChainManager::Manage() { // Manage chain growth if (!i->IsStopped()) if (i->GetCurBlock()->next == 0) { // Iterator is running and no more blocks at the end // of this chain! Get another and link it up. AudioBlock *nw = (AudioBlock *) i->GetCurBlock()->RTNew(); if (nw == 0) { printf("GrowChainManager: ERROR: No free blocks to grow chain\n"); return 0; } i->GetCurBlock()->Link(nw); // Second channel allocating is done as needed by PutFragment // in the iterator } return 0; }; void PeaksAvgsManager::Setup() { // Setup iterators pa = (BED_PeaksAvgs *)(b->GetExtendedData(T_BED_PeaksAvgs)); // To do: Optimize this to bypass iterator- // it would be faster since we are moving one sample at a time! peaksi = new AudioBlockIterator(pa->peaks,1); avgsi = new AudioBlockIterator(pa->avgs,1); mi = new AudioBlockIterator(b,1); stereo = b->IsStereo(); if (grow) { // Grow peaks & avgs blocks bmg->GrowChainOn(pa->peaks,peaksi); bmg->GrowChainOn(pa->avgs,avgsi); } }; PeaksAvgsManager::~PeaksAvgsManager() { if (bmg != 0) { End(); delete peaksi; delete avgsi; delete mi; } }; void PeaksAvgsManager::End() { if (!ended) { ended = 1; if (grow) { // End chain at current pos! peaksi->EndChain(); avgsi->EndChain(); bmg->GrowChainOff(pa->peaks); bmg->GrowChainOff(pa->avgs); } } } int PeaksAvgsManager::Manage() { // Stop if ended.. if (ended) return 1; // Compute running peaks and averages char wrap; do { wrap = 0; // Get current position in iterator nframes_t curcnt = i->GetTotalLength2Cur(); if (curcnt < lastcnt) { // We have a wrap condition!- loop // printf("Wrap! Now at: %ld\n",curcnt); curcnt = b->GetTotalLen(); wrap = 1; } // Update peaks & averages to current position while (lastcnt < curcnt) { sample_t *sptr[2]; sample_t s_l, s_r; if (stereo) { mi->GetFragment(&sptr[0],&sptr[1]); s_l = *sptr[0]; s_r = *sptr[1]; } else { mi->GetFragment(&sptr[0],0); s_l = *sptr[0]; s_r = 0; } // If chunkcnt is -1, we have temporarily stopped until a wrap if (go) { if (s_l > runmax) runmax = s_l; if (s_l < runmin) runmin = s_l; if (stereo) { if (s_r > runmax) runmax = s_r; if (s_r < runmin) runmin = s_r; runtally += (fabs(s_l)+fabs(s_r))/2; } else runtally += fabs(s_l); chunkcnt++; if (chunkcnt >= pa->chunksize) { // One chunk done sample_t peak = runmax-runmin, avg = (sample_t) (runtally/pa->chunksize); if (peaksi->PutFragment(&peak,0) || avgsi->PutFragment(&avg,0)) { // Peaks should not be wrapping before main buf, stop! // // Note that this does happen!! go = 0; } else { peaksi->NextFragment(); avgsi->NextFragment(); chunkcnt = 0; } runtally = 0; runmax = 0; runmin = 0; } } mi->NextFragment(); lastcnt++; } if (wrap) { /* printf("Main wrap!: MI: %ld PI: %ld AI: %ld\n", mi->GetTotalLength2Cur(), peaksi->GetTotalLength2Cur(), avgsi->GetTotalLength2Cur()); */ mi->Zero(); peaksi->Zero(); avgsi->Zero(); lastcnt = 0; // Wrap to beginning, and do the samples there go = 1; chunkcnt = 0; runtally = 0; runmax = 0; runmin = 0; } } while (wrap); return 0; }; void StripeBlockManager::Setup() { // Does this block have BED_MarkerPoints? mp = (BED_MarkerPoints *)(b->GetExtendedData(T_BED_MarkerPoints)); if (mp == 0) { // No marker block b->AddExtendedData(mp = new BED_MarkerPoints()); } }; int StripeBlockManager::Manage() { // This is called whenever a time marker should be striped // to the block char wrap = 0; do { if (wrap) wrap = 2; // Special case if we just wrapped and are on a 2nd pass else wrap = 0; // Get current iterated offset into block nframes_t curcnt = i->GetTotalLength2Cur(); if (curcnt < lastcnt) { // We have a wrap condition!- loop // printf("Wrap! Now at: %ld\n",curcnt); curcnt = b->GetTotalLen(); wrap = 1; } // Scan through time markers for a good place to insert a new one TimeMarker *cur = mp->markers, *prev = 0; if (wrap == 2) { // On 2nd pass, delete markers at 0. wrap = 0; while (cur != 0 && cur->markofs < lastcnt) { prev = cur; cur = cur->next; } } else { while (cur != 0 && cur->markofs <= lastcnt) { prev = cur; cur = cur->next; } } // Delete any markers between last position & current while (cur != 0 && cur->markofs <= curcnt) { TimeMarker *tmp = cur->next; cur->RTDelete(); cur = tmp; if (prev != 0) prev->next = cur; else mp->markers = cur; } if (!wrap) { // Now insert a new marker in this position // Use realtime new method- no problem TimeMarker *nw = (TimeMarker *) pre_tm->RTNew(); if (nw == 0) { printf("StripeBlockManager: ERROR: No free TimeMarkers\n"); return 0; } nw->markofs = curcnt; nw->next = cur; if (prev != 0) prev->next = nw; else mp->markers = nw; // Update counters lastcnt = curcnt; } else lastcnt = 0; // Start again from beginning to curcnt } while (wrap); return 0; }; BlockManager::BlockManager (Fweelin *app) : manageblocks(0), himanageblocks(0), threadgo(1), app(app) { pre_growchain = new PreallocatedType(app->getMMG(), ::new GrowChainManager(), sizeof(GrowChainManager)); pre_peaksavgs = new PreallocatedType(app->getMMG(), ::new PeaksAvgsManager(), sizeof(PeaksAvgsManager)); pre_hipri = new PreallocatedType(app->getMMG(), ::new HiPriManagedChain(), sizeof(HiPriManagedChain)); pre_stripeblock = new PreallocatedType(app->getMMG(), ::new StripeBlockManager(), sizeof(StripeBlockManager)); pthread_mutex_init(&manage_thread_lock,0); const static size_t STACKSIZE = 1024*128; pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setstacksize(&attr,STACKSIZE); printf("BLOCK: Stacksize: %d.\n",STACKSIZE); // Start a block managing thread int ret = pthread_create(&manage_thread, &attr, run_manage_thread, static_cast(this)); if (ret != 0) { printf("(blockmanager) pthread_create failed, exiting"); exit(1); } SRMWRingBuffer_Writers::RegisterWriter(manage_thread); struct sched_param schp; memset(&schp, 0, sizeof(schp)); // Manage thread calls delete- can't be SCHED_FIFO schp.sched_priority = sched_get_priority_max(SCHED_OTHER); // schp.sched_priority = sched_get_priority_min(SCHED_FIFO); if (pthread_setschedparam(manage_thread, SCHED_OTHER, &schp) != 0) { printf("BLOCK: Can't set realtime thread, will use nonRT!\n"); } } BlockManager::~BlockManager () { // Terminate the management thread threadgo = 0; pthread_join(manage_thread,0); pthread_mutex_destroy (&manage_thread_lock); delete pre_growchain; delete pre_peaksavgs; delete pre_hipri; delete pre_stripeblock; } // Turns on automatic allocation of new blocks at the end of the // specified chain. We work in conjunction with the specified iterator, // so that when the iterator approaches the end of the block chain, // the chain grows automatically void BlockManager::GrowChainOn (AudioBlock *b, AudioBlockIterator *i) { // Check if the block is already being watched DelManager(&manageblocks,b,T_MC_GrowChain); // Tell the manage thread to grow this chain GrowChainManager *nw = (GrowChainManager *) pre_growchain->RTNewWithWait(); nw->b = b; nw->i = i; AddManager(&manageblocks,nw); } void BlockManager::GrowChainOff (AudioBlock *b) { DelManager(&manageblocks,b,T_MC_GrowChain); } // Turns on computation of running sample peaks and averages // for the specified Block & Iterator // We compute as the currenty iterated position advances PeaksAvgsManager *BlockManager::PeakAvgOn (AudioBlock *b, AudioBlockIterator *i, char grow) { // Check if the block is already being watched DelManager(&manageblocks,b,T_MC_PeaksAvgs); // Tell the manage thread to compute peaks & averages PeaksAvgsManager *nw = (PeaksAvgsManager *) pre_peaksavgs->RTNewWithWait(); nw->bmg = this; nw->b = b; nw->i = i; nw->grow = grow; nw->Setup(); AddManager(&manageblocks,nw); return nw; } void BlockManager::PeakAvgOff (AudioBlock *b) { DelManager(&manageblocks,b,T_MC_PeaksAvgs); } void BlockManager::StripeBlockOn (void *trigger, AudioBlock *b, AudioBlockIterator *i) { // Check if the block is already being watched DelHiManager(&himanageblocks,b,T_MC_StripeBlock,trigger); // Tell the manage thread to stripe beats on blocks StripeBlockManager *nw = (StripeBlockManager *) pre_stripeblock-> RTNewWithWait(); nw->pre_tm = app->getPRE_TIMEMARKER(); nw->b = b; nw->i = i; nw->trigger = trigger; nw->Setup(); AddHiManager(&himanageblocks,nw); } void BlockManager::StripeBlockOff (void *trigger, AudioBlock *b) { DelHiManager(&himanageblocks,b,T_MC_StripeBlock,trigger); } // Generic delete/add functions for managers (not hipri) void BlockManager::DelManager (ManagedChain *m) { DelManager(&manageblocks,m); }; void BlockManager::AddManager (ManagedChain *nw) { AddManager(&manageblocks,nw); }; void BlockManager::DelManager (ManagedChain **first, ManagedChain *m) { ManagedChain *cur = *first; // Search for manager 'm' in our list while (cur != 0 && (cur != m || cur->status == T_MC_PendingDelete)) cur = cur->next; if (cur != 0) // Flag for deletion cur->status = T_MC_PendingDelete; }; void BlockManager::RefDeleted (ManagedChain **first, void *ref) { ManagedChain *cur = *first; while (cur != 0) { if (cur->status == T_MC_Running && cur->RefDeleted(ref)) // Flag for deletion cur->status = T_MC_PendingDelete; // Next chain cur = cur->next; } } void BlockManager::HiRefDeleted (HiPriManagedChain **first, void *ref) { HiPriManagedChain *cur = *first; while (cur != 0) { if (cur->status == T_MC_Running && cur->RefDeleted(ref)) // Flag for deletion cur->status = T_MC_PendingDelete; // Next chain cur = (HiPriManagedChain *) cur->next; } } // Notify all Managers that the object pointed to has been deleted- // To avoid broken dependencies void BlockManager::RefDeleted (void *ref) { RefDeleted(&manageblocks,ref); HiRefDeleted(&himanageblocks,ref); } // Activate a hipriority trigger- all hiprimanagedchains with // specified trigger pointer will have manage() method called // Safe to call in realtime! void BlockManager::HiPriTrigger (void *trigger) { HiPriManagedChain *cur = himanageblocks; //printf("HIPRITRIG: %ld\n", mgrcnt); cur = himanageblocks; while (cur != 0) { if (cur->status == T_MC_Running && (cur->trigger == trigger || cur->trigger == 0)) // Ok, right trigger or no trigger specified, call 'em! if (cur->Manage()) // Flag for delete cur->status = T_MC_PendingDelete; // Next chain cur = (HiPriManagedChain *) cur->next; } } // Returns the 1st chain manager associated with block b // that has type t ManagedChain *BlockManager::GetBlockManager(AudioBlock *o, ManagedChainType t) { ManagedChain *cur = manageblocks; // Search for block 'o' && type t in our list while (cur != 0 && (cur->status == T_MC_PendingDelete || cur->b != o || cur->GetType() != t)) cur = cur->next; return cur; }; void BlockManager::AddManager (ManagedChain **first, ManagedChain *nw) { nw->status = T_MC_Running; // Possibility of priority inversion if AddManager is run in RT, // because non-RT manage thread also locks here. So far, AddManager shouldn't // be run in RT if (pthread_mutex_trylock (&manage_thread_lock) == 0) { ManagedChain *cur = *first; if (cur == 0) *first = nw; // That was easy, now we have 1 item else { while (cur->next != 0) cur = cur->next; cur->next = nw; // Link up the last item to new1 } pthread_mutex_unlock (&manage_thread_lock); } else // Priority inversion printf("BLOCK: WARNING: Priority inversion during AddManager\n"); } void BlockManager::AddHiManager (HiPriManagedChain **first, HiPriManagedChain *nw) { nw->status = T_MC_Running; // Possibility of priority inversion if AddHiManager is run in RT, // because non-RT manage thread also locks here. // So far, AddHiManager shouldn't be run in RT if (pthread_mutex_trylock (&manage_thread_lock) == 0) { HiPriManagedChain *cur = *first; if (cur == 0) *first = nw; // That was easy, now we have 1 item else { while (cur->next != 0) cur = (HiPriManagedChain *) cur->next; cur->next = nw; // Link up the last item to new1 } pthread_mutex_unlock (&manage_thread_lock); } else // Priority inversion printf("BLOCK: WARNING: Priority inversion during AddHiManager\n"); } // Delete a managed chain for block o and manager type t // If t is T_MC_None, removes the first managed chain for 'o' // of any type void BlockManager::DelManager (ManagedChain **first, AudioBlock *o, ManagedChainType t) { ManagedChain *cur = *first; // Search for block 'o' in our list of type 't' while (cur != 0 && (cur->status == T_MC_PendingDelete || cur->b != o || (cur->GetType() != t && t != T_MC_None))) cur = cur->next; if (cur != 0) // Flag for deletion cur->status = T_MC_PendingDelete; } // Delete a hiprimanaged chain for block o and manager type t // with specified trigger. // If t is T_MC_None, removes the first managed chain for 'o' // with specified trigger, of any type void BlockManager::DelHiManager (HiPriManagedChain **first, AudioBlock *o, ManagedChainType t, void *trigger) { HiPriManagedChain *cur = *first; // Search for block 'o' in our list of type 't' while (cur != 0 && (cur->status == T_MC_PendingDelete || cur->b != o || cur->trigger != trigger || (cur->GetType() != t && t != T_MC_None))) cur = (HiPriManagedChain *) cur->next; if (cur != 0) // Flag for deletion cur->status = T_MC_PendingDelete; } void *BlockManager::run_manage_thread (void *ptr) { BlockManager *inst = static_cast(ptr); while (inst->threadgo) { // Manage the blocks we have ManagedChain *cur = inst->manageblocks; while (cur != 0) { if (cur->status == T_MC_Running) if (cur->Manage()) // Flag for deletion cur->status = T_MC_PendingDelete; // Next chain cur = cur->next; } // Delete managers cur = inst->manageblocks; ManagedChain *prev = 0; while (cur != 0) { if (cur->status == T_MC_PendingDelete) { // printf("MGR %p DELETE\n",cur); // Remove chain pthread_mutex_lock (&inst->manage_thread_lock); ManagedChain *tmp = cur->next; if (prev != 0) prev->next = tmp; else inst->manageblocks = tmp; pthread_mutex_unlock (&inst->manage_thread_lock); //printf("end mgr\n"); cur->RTDelete(); cur = tmp; } else { // Next chain prev = cur; cur = cur->next; } } HiPriManagedChain *hcur = inst->himanageblocks, *hprev = 0; while (hcur != 0) { if (hcur->status == T_MC_PendingDelete) { // printf("HI-MGR %p DELETE\n",hcur); // Remove chain pthread_mutex_lock (&inst->manage_thread_lock); HiPriManagedChain *tmp = (HiPriManagedChain *) hcur->next; if (hprev != 0) hprev->next = tmp; else inst->himanageblocks = tmp; pthread_mutex_unlock (&inst->manage_thread_lock); //printf("end mgr\n"); hcur->RTDelete(); hcur = tmp; } else { // Next chain hprev = hcur; hcur = (HiPriManagedChain *) hcur->next; } } // Produce status report? FloConfig *fs = inst->app->getCFG(); if (fs->status_report == FS_REPORT_BLOCKMANAGER) { fs->status_report++; printf("BLOCKMANAGER REPORT:\n"); ManagedChain *cur = inst->manageblocks; while (cur != 0) { printf(" bmg mgr: type(%d) status(%d)\n",cur->GetType(),cur->status); cur = cur->next; } cur = inst->himanageblocks; while (cur != 0) { printf(" bmg HiPrimgr: type(%d) status(%d)\n",cur->GetType(), cur->status); cur = cur->next; } } // 10 ms delay between management tasks usleep(10000); } // Delete all blockmanagers now ManagedChain *cur = inst->manageblocks; while (cur != 0) { ManagedChain *tmp = cur->next; cur->RTDelete(); cur = tmp; } cur = inst->himanageblocks; while (cur != 0) { ManagedChain *tmp = cur->next; cur->RTDelete(); cur = tmp; } return 0; } fweelin-0.6/src/fweelin_block.h0000755000175000017500000010016611050104732015211 0ustar mercmerc#ifndef __FWEELIN_BLOCK_H #define __FWEELIN_BLOCK_H /* Copyright 2004-2008 Jan Pekau (JP Mercury) This file is part of Freewheeling. Freewheeling is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. Freewheeling is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Freewheeling. If not, see . */ #include #include #include #ifdef __MACOSX__ #include #else #include #endif #include "fweelin_audioio.h" #include "fweelin_mem.h" #include "fweelin_event.h" #include "elastin/elastin.h" // Types of audio codecs supported typedef enum { UNKNOWN = -1, FIRST_FORMAT = 0, VORBIS = 0, WAV = 1, FLAC = 2, AU = 3, END_OF_FORMATS = 4 } codec; #ifndef MIN #define MIN(a,b) ((a) < (b) ? (a) : (b)) #endif #ifndef MAX #define MAX(a,b) ((a) > (b) ? (a) : (b)) #endif class Fweelin; class Loop; class AudioBlock; class BlockManager; class PeaksAvgsManager; // A list of all block extended data types // Used as a kind of RTTI for getting BED of a certain type at runtime enum BlockExtendedDataType { T_BED_None, T_BED_ExtraChannel, T_BED_PeaksAvgs, T_BED_MarkerPoints }; class BlockExtendedData { public: BlockExtendedData() : next(0) {}; BlockExtendedData(BlockExtendedData *prev) : next(0) { prev->next = this; }; virtual ~BlockExtendedData() {}; virtual BlockExtendedDataType GetType() { return T_BED_None; }; // Pointer to next bit of extended data in list BlockExtendedData *next; }; // A type of block extended data that allows // peaks & averages across audioblocks to be stored inside them. // Used for things like scope computations which are autocalculated // and stored inside blocks as BED_PeaksAvgs class BED_PeaksAvgs : public BlockExtendedData { public: BED_PeaksAvgs(AudioBlock *peaks, AudioBlock *avgs, nframes_t chunksize) : peaks(peaks), avgs(avgs), chunksize(chunksize) {}; ~BED_PeaksAvgs(); virtual BlockExtendedDataType GetType() { return T_BED_PeaksAvgs; }; // Peaks & averages AudioBlock *peaks, *avgs; // Chunk size across which peaks & averages are computed // Length of peaks & avgs blocks = length of parent block / chunksize nframes_t chunksize; }; class TimeMarker : public Preallocated { public: TimeMarker(nframes_t markofs = 0, long data = 0) : markofs(markofs), data(data), next(0) {}; // FWMEM_DEFINE_DELBLOCK; virtual void Recycle() { markofs = 0; data = 0; next = 0; }; // Block mode allocate /* virtual Preallocated *NewInstance() { return ::new TimeMarker[GetMgr()->GetBlockSize()]; }; */ virtual Preallocated *NewInstance() { return ::new TimeMarker(); }; nframes_t markofs; // Marker position measured in samples long data; // Unspecified extra data (use as req'd) TimeMarker *next; // Next time marker }; // A type of block extended data that stores time markers into a block class BED_MarkerPoints : public BlockExtendedData { public: BED_MarkerPoints() : markers(0) {}; ~BED_MarkerPoints(); virtual BlockExtendedDataType GetType() { return T_BED_MarkerPoints; }; int CountMarkers(); // Returns the nth marker before (in time) the current offset passed // This method correctly handles a reverse wrap case when the // marker NBeforeCur is farther ahead in the attached block than the // current offset TimeMarker *GetMarkerNBeforeCur(int n, nframes_t curofs); TimeMarker *markers; }; class AudioBlock : public Preallocated { public: // Default length of new audio blocks (samples) static const nframes_t AUDIOBLOCK_DEFAULT_LEN = 20000, AUDIOBLOCK_SMOOTH_ENDPOINTS_LEN = 64; // Create a new audioblock as the beginning of a block list AudioBlock(nframes_t len = AUDIOBLOCK_DEFAULT_LEN); // Create a new audioblock and link up the specified block to it AudioBlock(AudioBlock *prev, nframes_t len); virtual ~AudioBlock(); virtual Preallocated *NewInstance() { return ::new AudioBlock(); }; // Is this block stereo? (does it have a BED_ExtraChannel attached?) inline char IsStereo() { return (GetExtendedData(T_BED_ExtraChannel) != 0); }; // Link us up to the specified block void Link(AudioBlock *to); // Clears this block chain- not changing length void Zero(); // Erases any blocks in the chain after this block- this one // becomes the last void ChopChain(); // Smooth an audio chain- // either smooth the beginning into the end (smoothtype == 1) // or smooth the end into the beginning (smoothtype == 0) void Smooth(char smoothtype = 1, nframes_t smoothlen = AUDIOBLOCK_SMOOTH_ENDPOINTS_LEN); // Erases this whole audioblock chain from first to last // Also erases any extended data! // RT safe void DeleteChain(); // Returns the total length of this audio chain nframes_t GetTotalLen(); // Gets extended data for this block BlockExtendedData *GetExtendedData(BlockExtendedDataType x); // Add this extended data to the list of extended data for this block void AddExtendedData(BlockExtendedData *nw); // Finds the audioblock and offset into that block that correspond // to the provided absolute offset into this chain void SetPtrsFromAbsOffset(AudioBlock **ptr, nframes_t *blkofs, nframes_t absofs); // Generates a subchain of AudioBlocks by copying the samples between offsets // from & to.. offsets expressed absolutely with reference to // beginning of this chain! // Samples are copied up to but not including toofs // If toofs < fromofs, generates a subblock that includes the end of // the block and the beginning up to toofs (wrap case) // Realtime safe? AudioBlock *GenerateSubChain(nframes_t fromofs, nframes_t toofs, char copystereo); // Removes the last 'hacklen' samples from this block chain // Returns nonzero on error! // Not realtime safe! int HackTotalLengthBy(nframes_t hacklen); // Inserts the new block at the beginning of this block chain // Returns a pointer to the new first block AudioBlock *InsertFirst(AudioBlock *nw); sample_t *buf, // Samples for block- this pointer can be adjusted if the // block is shortened as in Smooth() *origbuf; // Original unmodified sample pointer nframes_t len; // Length of block AudioBlock *next, // Next block *first; // First block in chain // Extended data list for this block BlockExtendedData *xt; }; // A type of block extended data that allows // an extra channel of audio to be attached to an audioblock // Used for stereo loops class BED_ExtraChannel : public Preallocated, public BlockExtendedData { public: BED_ExtraChannel(nframes_t len = AudioBlock::AUDIOBLOCK_DEFAULT_LEN); virtual ~BED_ExtraChannel(); virtual Preallocated *NewInstance() { return ::new BED_ExtraChannel(); }; virtual BlockExtendedDataType GetType() { return T_BED_ExtraChannel; }; // Sample data for extra channel- each stereo block must have an instance // of BED_ExtraChannel with a sample buffer that matches length with // the parent AudioBlock sample_t *buf, // This pointer can be adjusted in Smooth() *origbuf; // Original unmodified sample pointer }; // Iterator for storing/extracting data in audio blocks. // Freewheeling stores audio in small blocks, which are linked together // in a chain. // // The main functions for iteration are GetFragment (retrieves an audio // fragment from block(s)), PutFragment (stores an audio fragment into // block(s)), and NextFragment (advances the iterator). // // The iterator can also perform rate scaling. // // When rate scaling, the iterator writes to a different block chain than // it reads from. The chain can then grow/shrink as the rate scaling // changes. class AudioBlockIterator /*: public Elastin_SampleFeed*/ { public: // Optionally pass preallocatedtype for extrachannel if you want // extra channels to be added as needed when putting fragments AudioBlockIterator(AudioBlock *firstblock, nframes_t fragmentsize, PreallocatedType *pre_extrachannel = 0); ~AudioBlockIterator(); inline float round(float num) { if (num-(long)num < 0.5) return floor(num); else return ceil(num); } // Stores in cnt the absolute count corresponding to the given // block and offset void GenCnt(AudioBlock *blk, nframes_t blkofs, nframes_t *cnt); void GenConstants(); // Moves iterator to start position void Zero(); // Advances to the next fragment void NextFragment(); // Jumps to an absolute offset within the blockchain void Jump(nframes_t ofs); // PutFragment stores the specified fragment back into this AudioBlock // (optional right channel) // Returns nonzero if the end of the block is reached, and we wrap to next // Optional size_override puts a different size fragment into the block- // any size can be put so long as the chain is long enough // Optional wait_alloc waits for allocation of new extra channels if needed // (don't use this flag in RT!) // If rate scaling is active, the iterator always writes to a new // block, because the length of the newly stored sample may be // different than the length of the original (see 'write block' // variables). No scaling is done in PutFragment, just a choice of // which block chain to write to int PutFragment (sample_t *frag_l, sample_t *frag_r, nframes_t size_override = 0, char wait_alloc = 0); // Returns the current fragment of audio // Points frag_l and frag_r buffers to the current fragment // frag_r is optional // nextblock and nextblkofs become the new block pointer and offset // for the next fragment void GetFragment(sample_t **frag_l, sample_t **frag_r); // Adjusts the block chain so that the current iterator position // becomes the new end of the chain void EndChain(); inline nframes_t GetTotalLength2Cur() { return (nframes_t) curcnt; } inline char IsStopped() { return stopped; }; inline void Stop() { stopped = 1; }; // Returns the block currently being iterated through inline AudioBlock *GetCurBlock() { return curblock; }; private: // Optional right audio channel for the block we are iterating PreallocatedType *pre_extrachannel; // Preallocator for 2nd channel blocks BED_ExtraChannel *currightblock, *nextrightblock, // Values for write block *currightblock_w, *nextrightblock_w; AudioBlock *curblock, *nextblock, // Values for write block *curblock_w, *nextblock_w; double curblkofs, // Use doubles for position (rate scale needs them) nextblkofs, curcnt, nextcnt, // Values for write block curblkofs_w, nextblkofs_w, curcnt_w, nextcnt_w; // Buffers for storing smaller fragments from within AudioBlocks nframes_t fragmentsize; sample_t *fragment[2]; char stopped; // Nonzero if this iterator is stopped }; // List of all types of chain managers enum ManagedChainType { T_MC_None, T_MC_GrowChain, T_MC_PeaksAvgs, T_MC_BlockRead, T_MC_BlockWrite, T_MC_HiPri, T_MC_StripeBlock }; // Status of managed chain enum ManagedChainStatus { T_MC_Running, T_MC_PendingDelete }; // Generic class specifying a chain of blocks & iterator to manage // Management happens when blockmanager periodically calls // the Manage() method for all managed chains. // Different types of manager classes do different management tasks // with blocks. class ManagedChain : public Preallocated { public: ManagedChain(AudioBlock *b = 0, AudioBlockIterator *i = 0) : b(b), i(i), next(0) {}; virtual ~ManagedChain() {}; virtual Preallocated *NewInstance() { return ::new ManagedChain(); }; // Called periodically to manage a block // Return zero to proceed normally // Return nonzero to delete this manager virtual int Manage() { return 0; }; // This method is called whenever an object (ref) is deleted // that Managed Chains might want to know about. For example, // RootProcessor notifies BlockManager whenever child processors // are deleted. This allows ManagedChains to react, if they depend // on the deleted object. If we return nonzero, this manager is // deleted. virtual int RefDeleted(void *ref) { if (ref == b || ref == i) // Block or iterator gone!! End this manager! return 1; else return 0; }; virtual ManagedChainType GetType() { return T_MC_None; }; AudioBlock *b; AudioBlockIterator *i; ManagedChainStatus status; ManagedChain *next; }; // GrowChainManager periodically grows a block chain so that the // iterator i never reaches its end-- good for unlimited length records class GrowChainManager : public ManagedChain { public: GrowChainManager(AudioBlock *b = 0, AudioBlockIterator *i = 0) : ManagedChain(b,i) {}; virtual Preallocated *NewInstance() { return ::new GrowChainManager(); }; virtual ManagedChainType GetType() { return T_MC_GrowChain; }; virtual int Manage(); }; // Base class for different types of file encoders class iFileEncoder { public: iFileEncoder (Fweelin *app, char stereo); virtual ~iFileEncoder() {}; // Tell the encoder to dump to this file we have just opened // This writes the files header information // Returns nonzero on error. virtual int SetupFileForWriting (FILE *file) = 0; // Get the samples from the relevant buffer (ibuf) and write them to file, // (startframe) tells us what index to start copying from the input buffer, // (numframes) tells us how many frames to encode. // Returns the number of frames written. virtual long int WriteSamplesToDisk (sample_t **ibuf, nframes_t startframe, nframes_t numframes) = 0; // Stop encoding and finish up- but don't close output file! virtual void PrepareFileForClosing () = 0; // Vorbis in particular needs to a bit of scaling down to avoid clipping... // any simular processing should be put here virtual void Preprocess (sample_t *l, sample_t *r, nframes_t len) = 0; inline char IsStereo() { return stereo; }; protected: Fweelin *app; char stereo; FILE *outfd; }; class SndFileEncoder : public iFileEncoder { public: // Encoder for libSndfile formats- at the moment, WAV, AU and FLAC. // Maxframes is maximum number of frames to write in one call to // WriteSamplesToDisk // Codec type is one of those values. // We also specify wether we are using Mono or Stereo Encoding SndFileEncoder (Fweelin *app, nframes_t maxframes, char stereo, codec type); ~SndFileEncoder() { if (tbuf != 0) delete[] tbuf; }; int SetupFileForWriting (FILE *file); long int WriteSamplesToDisk (sample_t **ibuf, nframes_t startframe, nframes_t numframes); void PrepareFileForClosing (void); void Preprocess (sample_t *l, sample_t *r, nframes_t len) {}; private: codec filetype; int samplesize; SF_INFO sfinfo; SNDFILE *sndoutfd; float *tbuf; // Temporary audio buffer for saving }; class VorbisEncoder : public iFileEncoder { public: // Vorbis encoder library init/end are done in constructor/destructor // We specify stereo or mono encoding VorbisEncoder (Fweelin *app, char stereo); virtual ~VorbisEncoder(); int SetupFileForWriting (FILE *file); long int WriteSamplesToDisk (sample_t **ibuf, nframes_t startframe, nframes_t numframes); void PrepareFileForClosing (void) { // Tell vorbis we are done with the stream vorbis_analysis_wrote(&vd,0); // Encode any remaining stuff Encode(); }; void Preprocess (sample_t *l, sample_t *r, nframes_t len); private: // Returns vorbis encoder's analysis buffers for len frames // Depending on mono/stereo it is an array of 1/2 by len samples float **GetAnalysisBuffer(nframes_t len) { return vorbis_analysis_buffer(&vd,len); }; // Tell vorbis we wrote some samples to its analysis buffer void WroteToBuffer(nframes_t len) { vorbis_analysis_wrote(&vd,len); }; // Runs the encoder, returns number of bytes written long int Encode(); // Vorbis encoder stuff ogg_stream_state os; /* take physical pages, weld into a logical stream of packets */ ogg_page og; /* one Ogg bitstream page. Vorbis packets are inside */ ogg_packet op; /* one raw packet of data for decode */ vorbis_info vi; /* struct that stores all the static vorbis bitstream settings */ vorbis_comment vc; /* struct that stores all the user comments */ vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */ vorbis_block vb; /* local working space for packet->PCM decode */ }; class iFileDecoder { public: iFileDecoder (Fweelin *app); virtual ~iFileDecoder () {}; // Tell the decoder to decode from a given file // This reads the files header virtual int ReadFromFile(FILE *in, nframes_t rbuf_len) = 0; // Decode a maximum of max_len samples and return buffers in pcm_channels // (format as per VorbisFile ov_read_float) // Returns # of samples read, 0 if EOF, <0 if error virtual int ReadSamples(AudioBlockIterator *i, nframes_t max_len) = 0; // Stop decoding and finish up-- and close the input file! // ??? -- old note? FIXME workaround for memory managment issue virtual void Stop() = 0; // Are we decoding in stereo? inline char IsStereo() { return stereo; }; protected: // Fweelin Fweelin *app; // Stereo decoding? char stereo; // Input from this file FILE *infd; }; class SndFileDecoder : public iFileDecoder { public: SndFileDecoder(Fweelin *app, codec type); ~SndFileDecoder(); int ReadFromFile (FILE *in, nframes_t rbuf_len); // int Decode (float **pcm_channels, nframes_t max_len); int ReadSamples(AudioBlockIterator *it, nframes_t max_len); void Stop(); private: codec filetype; int samplesize; SF_INFO sfinfo; SNDFILE *sfinfd; float *obuf[2]; float *rbuf; }; class VorbisDecoder : public iFileDecoder { public: // Vorbis library init/end are done in constructor/destructor VorbisDecoder(Fweelin *app); ~VorbisDecoder(); // Decode a maximum of max_len samples and return buffers in pcm_channels // (format as per VorbisFile ov_read_float) // Returns # of samples read, 0 if EOF, <0 if error int ReadSamples(AudioBlockIterator *i, nframes_t max_len); // int Decode(float **pcm_channels, nframes_t max_len); // Stop decoding and finish up-- and close the input file! void Stop() { // Tell vorbis we are done with the stream ov_clear(&vf); }; // Tell the decoder to decode from a given file // This reads the vorbis header int ReadFromFile(FILE *in, nframes_t rbuf_len); private: // Vorbis decoder stuff OggVorbis_File vf; int current_section; char pcmout[]; }; class AutoWriteControl { public: // This callback method is called periodically by BlockWriteManager // to get the next block chain to write. This allows the main app to // decide which loops to save, while the BlockManager thread does the work // in the background virtual void GetWriteBlock(FILE **out, AudioBlock **b, AudioBlockIterator **i, nframes_t *len) = 0; }; class AutoReadControl { public: // This callback method is called periodically by BlockReadManager // to get the next block chain to read. This allows the main app to // decide which loops to load, while the BlockManager thread does the work // in the background // // GetReadBlock sets 'smooth_end' to nonzero to request for // BlockReadManager to smooth the end of the block into the beginning. // This is the new way to deal with begin-end inconsistencies when loading // OGG loops. To accomodate loops saved without the extra data at the end, // we can set 'smooth_end' to zero. virtual void GetReadBlock(FILE **in, char *smooth_end) = 0; // When the audio data read is complete, BlockReadManager calls ReadComplete // which tells you that you have a new loop in memory virtual void ReadComplete(AudioBlock *b) = 0; }; // BlockReadManager reads & uncompresses an audio block chain // this implementation is used for loading loops. class BlockReadManager : public ManagedChain { public: // Crossfade length when loading old loops (not the new format ones) const static nframes_t SMOOTH_FIX_LEN = 64, DECODE_CHUNKSIZE = 2048; // Increase this number will result in faster decoding but slower response // during decoding (less CPU given up for other Manage tasks) const static int NUM_DECODE_PASSES = 100; BlockReadManager(FILE *in = 0, AutoReadControl *arc = 0, BlockManager *bmg = 0, nframes_t peaksavgs_chunksize = 0); virtual ~BlockReadManager(); virtual Preallocated *NewInstance() { return ::new BlockReadManager(); }; void SetLoopType (codec looptype); // BlockReadManager's RefDeleted may block to avoid block data being // deleted while we are still encoding- we finish up our current decode pass // and then return virtual int RefDeleted(void *ref) { if (ref == arc) { // AutoReadControl is ending, so we should end too arc = 0; return 1; } else return 0; }; // Start decoding into memory from the given file void Start(FILE *new_in = 0); // Ends reading- with error (nonzero) or without error (zero) void End(char error); virtual ManagedChainType GetType() { return T_MC_BlockRead; }; virtual int Manage(); FILE *in; // File to read from char smooth_end; // Smooth end of loop into beginning? AutoReadControl *arc; // A way to ask app what blocks to read iFileDecoder *dec; // Decoder BlockManager *bmg; codec filetype; PeaksAvgsManager *pa_mgr; // Computer for peaks/avgs during load nframes_t peaksavgs_chunksize; pthread_mutex_t decode_lock; }; // BlockWriteManager compresses and writes a block chain (OGG vorbis format) // this implementation is used for saving loops, // unlike the BlockStreamer implementation in core_dsp, which streams // real-time // // Two modes are provided- // 1) follow iterator i-- compresses behind iterator i // 2) compress the whole chain // // We can also choose to invoke BlockWriteManager with AutoWriteControl, // providing a callback which we invoke after writing a block chain. // The callback tells us whether to write another chain, and if so, // gives us the new block and iterator pointers as well as a file out class BlockWriteManager : public ManagedChain { public: const static nframes_t ENCODE_CHUNKSIZE = 10000, ENCODE_CROSSOVER_LEN = 1000; BlockWriteManager(FILE *out = 0, AutoWriteControl *awc = 0, BlockManager *bmg = 0, AudioBlock *b = 0, AudioBlockIterator *i = 0); virtual ~BlockWriteManager(); virtual Preallocated *NewInstance() { return ::new BlockWriteManager(); }; // BlockWriteManager's RefDeleted may block to avoid block data being // deleted while we are still encoding- we finish up our current encode pass // and then return virtual int RefDeleted(void *ref) { if (ref == awc) { // AutoWriteControl is ending, so we should end too awc = 0; return 1; } else if (ref == b || ref == i) { // Block or iterator gone!! The chain we are encoding has been erased- // so stop encoding printf("DISK: Blocks deleted while saving- abort!\n"); End(); if (awc != 0) // Auto save, so keep running return 0; else // Single save, so stop return 1; } else return 0; }; // Start encoding the given block chain to the given file void Start(FILE *new_out = 0, AudioBlock *new_b = 0, AudioBlockIterator *new_i = 0, nframes_t new_len = 0); // Ends writing void End(); virtual ManagedChainType GetType() { return T_MC_BlockWrite; }; virtual int Manage(); FILE *out; // File to write this loop to AudioBlockIterator *ei; // Encode iterator nframes_t len, // Length of block to save pos; // Current save position AutoWriteControl *awc; // A way to ask app what blocks to write iFileEncoder *enc; BlockManager *bmg; pthread_mutex_t encode_lock; }; // PeaksAvgsManager periodically calculates peaks and averages for // blockchain b, keeping up with iterator i // using BlockExtendedData to store peaks & averages class PeaksAvgsManager : public ManagedChain { public: PeaksAvgsManager(BlockManager *bmg = 0, AudioBlock *b = 0, AudioBlockIterator *i = 0, char grow = 0) : ManagedChain(b,i), bmg(bmg), runmax(0), runmin(0), runtally(0), lastcnt(0), chunkcnt(0), stereo(0), grow(grow), go(1), ended(0) {}; virtual ~PeaksAvgsManager(); virtual Preallocated *NewInstance() { return ::new PeaksAvgsManager(); }; virtual int RefDeleted(void *ref) { if (ref == b || ref == i) { // Block or iterator gone!! End this manager! b = 0; return 1; } else return 0; }; // Call before starting! void Setup(); // Ends computation of peaks & averages, chopping the // peaks & averages blocks at this length.. void End(); AudioBlockIterator *GetPeaksI() { return peaksi; }; AudioBlockIterator *GetAvgsI() { return avgsi; }; AudioBlock *GetPeaks() { return pa->peaks; }; AudioBlock *GetAvgs() { return pa->avgs; }; virtual ManagedChainType GetType() { return T_MC_PeaksAvgs; }; virtual int Manage(); BlockManager *bmg; // Target place to store peaks & averages BED_PeaksAvgs *pa; // Iterators for blocks storing peaks & averages AudioBlockIterator *peaksi, *avgsi, *mi; // Iterator for block b for this manager // Used to keep syncronized up to latest changes to block b sample_t runmax, // Running sample maximum runmin, // Running sample minimum runtally; // Running sample tally nframes_t lastcnt, // Last count (curcnt) in iterator i chunkcnt; // Count in current chunk // (where peaks & avgs are calculated) char stereo; // Computing peaks from stereo block? char grow, // Nonzero if peaks & avgs data should be grown // (if input block b is also growing) go, // Nonzero if we are computing peaks & averages ended; // Nonzero if we have ended for good }; // Base class for hipriority managed blocks-- // When a block becomes HiPriManaged it specifies a trigger pointer // A realtime process can then call BlockManager with a trigger pointer // and invoke the Manage() method for all blocks managed with matching // trigger. This allows blocks to interact with other realtime // components, such as time pulses, without knowing what they are. // Manage() is not called periodically, like it is with other // manager types-- so Manage methods must work in realtime class HiPriManagedChain : public ManagedChain { public: HiPriManagedChain(void *trigger = 0, AudioBlock *b = 0, AudioBlockIterator *i = 0) : ManagedChain(b,i), trigger(trigger), lastcnt(0) {}; virtual Preallocated *NewInstance() { return ::new HiPriManagedChain(); }; virtual int RefDeleted(void *ref) { if (ref == b || ref == i || ref == trigger) // Block, iterator, or trigger gone! End this manager! return 1; else return 0; }; virtual ManagedChainType GetType() { return T_MC_HiPri; }; void *trigger; nframes_t lastcnt; // Last iterated pos in block }; // StripeBlockManager is a special hipriority block manager // that stripes blocks with time markers whenever it is invoked // through BlockManager with the specified trigger pointer. // This allows a block to register that some other realtime process // (for example, a time pulse), can trigger time points to be // striped! // We use BED_MarkerPoints to store time markers in the block class StripeBlockManager : public HiPriManagedChain { public: StripeBlockManager(PreallocatedType *pre_tm = 0, void *trigger = 0, AudioBlock *b = 0, AudioBlockIterator *i = 0) : HiPriManagedChain(trigger,b,i), pre_tm(pre_tm) {}; // Call before starting! void Setup(); virtual Preallocated *NewInstance() { return ::new StripeBlockManager(); }; // Do we need a destructor that erases all striped marks?? // Depends on desired functionality-- // do marks persist after the managers that created them are gone? virtual ManagedChainType GetType() { return T_MC_StripeBlock; }; virtual int Manage(); // Target place to store markers BED_MarkerPoints *mp; // Preallocated manager for time markers PreallocatedType *pre_tm; }; // BlockManager handles different maintenance tasks related to // audio blocks. // // It handles -periodic maintenance-, such as resizing a block chain, // performing peak calculations, saving to disk, and analysis on a chain. // // It also handles -time-critical events-, such as firing off pulse sync // messages. This second function may soon be moved to the EventManager. class BlockManager { public: BlockManager (Fweelin *app); ~BlockManager (); Fweelin *GetApp() { return app; }; // Turns on automatic allocation of new blocks at the end of the // specified chain. We work in conjunction with the specified iterator, // so that when the iterator approaches the end of the block chain, // the chain grows automatically void GrowChainOn (AudioBlock *b, AudioBlockIterator *i); void GrowChainOff (AudioBlock *b); // Turns on computation of running sample peaks and averages // for the specified Block & Iterator // We compute as the currenty iterated position advances PeaksAvgsManager *PeakAvgOn (AudioBlock *b, AudioBlockIterator *i, char grow = 0); void PeakAvgOff (AudioBlock *b); // Stripes the specified chain with TimeMarkers according to the specified // trigger. Works in conjunction with RT threads that call HiPriTrigger. void StripeBlockOn (void *trigger, AudioBlock *b, AudioBlockIterator *i); // Removes striping from the specified trigger on blockchain b void StripeBlockOff (void *trigger, AudioBlock *b); // Notify all Managers that the object pointed to has been deleted- // To avoid broken dependencies void RefDeleted (void *ref); // Activate a hipriority trigger- all hiprimanagedchains with // specified trigger pointer will have manage() method called // RT safe! void HiPriTrigger (void *trigger); // Returns the 1st chain manager associated with block o // that has type t ManagedChain *GetBlockManager(AudioBlock *o, ManagedChainType t); // Generic delete/add functions for managers (not hipri) void DelManager (ManagedChain *m); void AddManager (ManagedChain *nw); protected: void DelManager (ManagedChain **first, ManagedChain *m); void AddManager (ManagedChain **first, ManagedChain *nw); void AddHiManager (HiPriManagedChain **first, HiPriManagedChain *nw); void RefDeleted (ManagedChain **first, void *ref); void HiRefDeleted (HiPriManagedChain **first, void *ref); // Delete a managed chain for block o and manager type t // If t is T_MC_None, removes the first managed chain for 'o' // of any type void DelManager (ManagedChain **first, AudioBlock *o, ManagedChainType t = T_MC_None); // Delete a hiprimanaged chain for block o and manager type t // with specified trigger. // If t is T_MC_None, removes the first managed chain for 'o' // with specified trigger, of any type void DelHiManager (HiPriManagedChain **first, AudioBlock *o, ManagedChainType t, void *trigger); // NEED TO MAKE/USE GENERALIZED LIST CLASS // ^^ speed issues? static void *run_manage_thread (void *ptr); ManagedChain *manageblocks; HiPriManagedChain *himanageblocks; pthread_t manage_thread; pthread_mutex_t manage_thread_lock; int threadgo; // ****************** PREALLOCATED TYPE MANAGERS PreallocatedType *pre_growchain, *pre_peaksavgs, *pre_hipri, *pre_stripeblock; // Parent app Fweelin *app; }; #endif fweelin-0.6/src/fweelin_browser.cc0000644000175000017500000007273611050377022015754 0ustar mercmerc/* Copyright 2004-2008 Jan Pekau (JP Mercury) This file is part of Freewheeling. Freewheeling is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. Freewheeling is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Freewheeling. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include "fweelin_core.h" #include "fweelin_fluidsynth.h" #include "fweelin_browser.h" const double ItemRenamer::BLINK_DELAY = 0.5; ItemRenamer::ItemRenamer (Fweelin *app, RenameCallback *cb, char *oldname) : app(app), cb(cb) { if (oldname == 0) strcpy(rename_tmpbuf,""); else if (strlen(oldname)+1 >= (unsigned int) RENAME_BUF_SIZE) { strncpy(rename_tmpbuf,oldname,RENAME_BUF_SIZE-1); rename_tmpbuf[RENAME_BUF_SIZE-1] = '\0'; } else strcpy(rename_tmpbuf,oldname); if (app->getCFG()->AddEventHook(this)) { printf("RENAME: You can only rename one item at a time.\n"); renaming = 0; } else { app->getSDLIO()->EnableUNICODE(1); app->getSDLIO()->EnableKeyRepeat(1); renaming = 1; } }; char ItemRenamer::HookEvent(Event *ev, EventProducer *from) { switch (ev->GetType()) { case T_EV_Input_Key : { KeyInputEvent *kev = (KeyInputEvent *) ev; // Intercept alphanumeric keys (use UNICODE translation) if ((kev->unicode > 32 && kev->unicode < 127) || (kev->unicode > 160 && kev->unicode < 256)) { if (kev->down) Rename_Append((char) (kev->unicode & 0xFF)); return 1; } else if (kev->keysym == SDLK_BACKSPACE) { if (kev->down) Rename_Backspace(); return 1; } else if (kev->keysym == SDLK_SPACE) { if (kev->down) Rename_Append(' '); } else if (kev->keysym == SDLK_RETURN || kev->keysym == SDLK_KP_ENTER) { if (kev->down) { app->getCFG()->RemoveEventHook(this); app->getSDLIO()->EnableUNICODE(0); app->getSDLIO()->EnableKeyRepeat(0); // Notify callback that item has been renamed cb->ItemRenamed(rename_tmpbuf); // Callback may delete -this- } return 1; } else if (kev->keysym == SDLK_ESCAPE) { if (kev->down) { app->getCFG()->RemoveEventHook(this); app->getSDLIO()->EnableUNICODE(0); app->getSDLIO()->EnableKeyRepeat(0); // Stop cb->ItemRenamed(0); // Callback may delete -this- } return 1; } return 0; } break; default: break; } return 0; }; // Add an item to this browser // (Doubley linked list add with sort) // Nonzero if we should sort (according to the BrowserItem::Compare() method) void Browser::AddItem(BrowserItem *nw, char sort) { LockBrowser(); if (first == 0) { first = nw; cur = first; // printf("BROWSER: (id: %d) First item now: %s\n",id,first->name); } else { BrowserItem *cur = first; if (sort && nw->Compare(cur) < 0) { // Insert before first if that's where she goes nw->next = first; nw->prev = 0; first->prev = nw; first = nw; } else { // Insert at end or in the right place if sorting if (sort) { while (cur->next != 0 && nw->Compare(cur->next) >= 0) cur = cur->next; } else { while (cur->next != 0) cur = cur->next; } // Insert after cur nw->next = cur->next; if (cur->next != 0) cur->next->prev = nw; nw->prev = cur; cur->next = nw; } } UnlockBrowser(); }; // Remove an item from this browser // For each item we call the MatchItem(itemmatch) method in BrowserItem // until MatchItem returns zero. Then we remove that item. void Browser::RemoveItem(int itemmatch) { LockBrowser(); BrowserItem *curi = first; while (curi != 0 && curi->MatchItem(itemmatch)) curi = curi->next; if (curi != 0) { // Found, remove if (curi->prev != 0) curi->prev->next = curi->next; else first = curi->next; if (curi->next != 0) curi->next->prev = curi->prev; // Move currently selected item if we just removed it if (cur == curi) cur = (curi->prev != 0 ? curi->prev : curi->next); delete curi; } UnlockBrowser(); }; void Browser::ItemRenamed(char *nw) { if (nw != 0) { // Assign new name and stop RenameItem(cur,nw); delete renamer; renamer = 0; // Notify callback of new name if (callback != 0) callback->ItemRenamed(cur); // If edit is blank, assign default name for onscreen display if (strlen(cur->name) == 0) { char tmp[FWEELIN_OUTNAME_LEN]; if (GetType() == B_Loop) GetDisplayName(((LoopBrowserItem *) cur)->filename, &((LoopBrowserItem *) cur)->time, tmp,FWEELIN_OUTNAME_LEN); else if (GetType() == B_Scene) GetDisplayName(((SceneBrowserItem *) cur)->filename, &((SceneBrowserItem *) cur)->time, tmp,FWEELIN_OUTNAME_LEN); RenameItem(cur,tmp); cur->default_name = 1; } else cur->default_name = 0; } else { // Rename was aborted delete renamer; renamer = 0; } }; // Via this method, a browser is notified of a change to the on-disk name // of an item. For example, when a Loop in memory is renamed, we also // rename it on disk, and the loop browser must be notified of this new name. void Browser::ItemRenamedOnDisk(char *old_filename, char *new_filename, char *new_name) { if (old_filename == 0 || new_filename == 0) return; BrowserItem *cur = first; char found = 0; while (cur != 0 && !found) { char *filename = 0; if (cur->GetType() == B_Loop) filename = ((LoopBrowserItem *) cur)->filename; else if (cur->GetType() == B_Scene) filename = ((SceneBrowserItem *) cur)->filename; // printf("looking for oldfilename: %s .. cur: %s\n", // old_filename, filename); if (filename != 0 && !strcmp(filename,old_filename)) found = 1; else cur = cur->next; } if (found) { // Found this item in our browser-- rename in our browser // Assign new filename char *filename = 0; if (cur->GetType() == B_Loop) filename = ((LoopBrowserItem *) cur)->filename; else if (cur->GetType() == B_Scene) filename = ((SceneBrowserItem *) cur)->filename; delete[] filename; filename = new char[strlen(new_filename)+1]; strcpy(filename,new_filename); if (cur->GetType() == B_Loop) ((LoopBrowserItem *) cur)->filename = filename; else if (cur->GetType() == B_Scene) ((SceneBrowserItem *) cur)->filename = filename; // Assign new name and stop RenameItem(cur,new_name); // If new name is blank, assign default name for onscreen display if (cur->name == 0 || strlen(cur->name) == 0) { char tmp[FWEELIN_OUTNAME_LEN]; if (GetType() == B_Loop) GetDisplayName(((LoopBrowserItem *) cur)->filename, &((LoopBrowserItem *) cur)->time, tmp,FWEELIN_OUTNAME_LEN); else if (GetType() == B_Scene) GetDisplayName(((SceneBrowserItem *) cur)->filename, &((SceneBrowserItem *) cur)->time, tmp,FWEELIN_OUTNAME_LEN); RenameItem(cur,tmp); cur->default_name = 1; } else cur->default_name = 0; } }; // Get the onscreen display name for a file with given name. // (filename must refer to a file of the type this browser handles) // Write the name to outbuf, with max maxlen characters. // Returns nonzero if we used a 'default' name. char Browser::GetDisplayName(char *filename, time_t *filetime, char *outbuf, int maxlen) { // Loop exists, use combination of time and hash as name int baselen = strlen(app->getCFG()->GetLibraryPath()) + 1; if (btype == B_Loop) baselen += strlen(FWEELIN_OUTPUT_LOOP_NAME); else if (btype == B_Scene) baselen += strlen(FWEELIN_OUTPUT_SCENE_NAME); else { printf("BROWSER: We don't support getting a display name for type %d\n", btype); return 1; } char sf_basename[FWEELIN_OUTNAME_LEN], sf_hash[FWEELIN_OUTNAME_LEN], sf_objname[FWEELIN_OUTNAME_LEN]; if (Saveable::SplitFilename(filename, baselen, sf_basename, sf_hash, sf_objname,FWEELIN_OUTNAME_LEN) || strlen(sf_objname) == 0) { // No object name given in filename // Compute default name char hashshort_1 = 'X', hashshort_2 = 'X'; Saveable::GetHashFirst(filename,baselen,&hashshort_1,&hashshort_2); // Compose name for item snprintf(outbuf,maxlen,"%c%c %s",hashshort_1,hashshort_2,ctime(filetime)); outbuf[maxlen-1] = '\0'; outbuf[strlen(outbuf)-1] = '\0'; // Cut off return character return 1; } else { // Use name given in filename strncpy(outbuf,sf_objname,maxlen); outbuf[maxlen-1] = '\0'; return 0; } } Browser::~Browser() { if (app != 0) { app->getEMG()->UnlistenEvent(this,0,T_EV_BrowserMoveToItem); app->getEMG()->UnlistenEvent(this,0,T_EV_BrowserSelectItem); } ClearAllItems(); pthread_mutex_destroy (&browser_lock); }; void Browser::ClearAllItems() { LockBrowser(); BrowserItem *cur = first; first = 0; while (cur != 0) { BrowserItem *tmp = cur->next; delete cur; cur = tmp; }; UnlockBrowser(); }; void Browser::Setup(Fweelin *a, BrowserCallback *c) { app = a; callback = c; app->getEMG()->ListenEvent(this,0,T_EV_BrowserMoveToItem); app->getEMG()->ListenEvent(this,0,T_EV_BrowserMoveToItemAbsolute); app->getEMG()->ListenEvent(this,0,T_EV_BrowserSelectItem); app->getEMG()->ListenEvent(this,0,T_EV_BrowserRenameItem); }; // Add divisions between browser items using the Compare function- // whenever two neighbouring items have difference greater than maxdelta, // a division is inserted. In browsing files, for example, this allows us // to group files that where created close to one another in time // // We also put divisions around any items that have been given a unique // name void Browser::AddDivisions(int maxdelta) { if (first != 0) { BrowserItem *cur = first; char go = 1; do { while (cur->next != 0 && cur->next->Compare(cur) < maxdelta && ((cur->default_name && cur->next->default_name) || cur->GetType() == B_Division || cur->next->GetType() == B_Division)) cur = cur->next; if (cur->next != 0) { // Add a division between cur and cur->next BrowserItem *div = new BrowserDivision(); div->prev = cur; div->next = cur->next; cur->next->prev = div; cur->next = div; cur = div->next; } else // Done go = 0; } while (go); } }; void Browser::MoveTo(int adjust, int jumpadjust) { LockBrowser(); if (xpand) { xpand_lastactivity = mygettime(); xpanded = 1; } if (cur == 0) cur = first; if (cur != 0) { // Jump by jumpadjust int adjdir = (jumpadjust >= 0 ? 1 : -1), adjmag = (adjdir == 1 ? abs(jumpadjust) : abs(jumpadjust)+1); BrowserItem *prev = cur; for (int i = 0; cur != 0 && i < adjmag; i++) { prev = cur; while (cur != 0 && cur->GetType() != B_Division) cur = (adjdir == 1 ? cur->next : cur->prev); if (cur != 0) // We are on the division, skip over it which way? cur = (adjdir == 1 || i+1 >= adjmag ? cur->next : cur->prev); if (cur == 0) { if (adjdir == -1 && i+1 >= adjmag) { // Going back to beginning of list cur = first; } else // Went too far, go back cur = prev; } } // Move by adjust adjdir = (adjust >= 0 ? 1 : -1); adjmag = abs(adjust); for (int i = 0; cur != 0 && i < adjmag; i++) { prev = cur; cur = (adjdir == 1 ? cur->next : cur->prev); if (cur != 0 && cur->GetType() == B_Division) i--; // Don't count divisions } if (cur == 0) cur = prev; } else { printf("BROWSER: No elements to move to for browser '%s'\n", GetTypeName(GetType())); } // Call browser virtual method for item browsed- // derived types of browsers may need to do internal updates ItemBrowsed(); // Send out 'item-browsed' event-- which can be bound to // in the config file. BrowserItemBrowsedEvent *bievt = (BrowserItemBrowsedEvent *) Event::GetEventByType(T_EV_BrowserItemBrowsed); bievt->browserid = id; // printf("BROWSER: itembrowsed send %p id: %d\n",bievt,id); app->getEMG()->BroadcastEventNow(bievt, this); if (cur != 0 && callback != 0) callback->ItemBrowsed(cur); UnlockBrowser(); }; void Browser::Select() { if (cur != 0 && callback != 0) callback->ItemSelected(cur); }; void Browser::Rename() { if (cur != 0 && renamer == 0 && (GetType() == B_Loop || GetType() == B_Scene)) { renamer = new ItemRenamer(app,this,(cur->default_name ? 0 : cur->name)); if (!renamer->IsRenaming()) { delete renamer; renamer = 0; } } }; void Browser::ReceiveEvent(Event *ev, EventProducer *from) { switch (ev->GetType()) { case T_EV_BrowserMoveToItem : { BrowserMoveToItemEvent *bev = (BrowserMoveToItemEvent *) ev; // Meant for this browser? if (bev->browserid == id) { if (CRITTERS) printf("BROWSER: Received BrowserMoveToItem " "(browser id: %d, adjust: %d, jumpadjust: %d)\n", bev->browserid, bev->adjust, bev->jumpadjust); MoveTo(bev->adjust, bev->jumpadjust); } } break; case T_EV_BrowserMoveToItemAbsolute : { BrowserMoveToItemAbsoluteEvent *bev = (BrowserMoveToItemAbsoluteEvent *) ev; // Meant for this browser? if (bev->browserid == id) { if (CRITTERS) printf("BROWSER: Received BrowserMoveToItemAbsolute " "(browser id: %d, idx: %d)\n", bev->browserid, bev->idx); MoveToBeginning(); MoveTo(bev->idx, 0); } } break; case T_EV_BrowserSelectItem : { BrowserSelectItemEvent *bev = (BrowserSelectItemEvent *) ev; // Meant for this browser? if (bev->browserid == id) { if (CRITTERS) printf("BROWSER: Received BrowserSelectItem\n"); Select(); } } break; case T_EV_BrowserRenameItem : { BrowserRenameItemEvent *bev = (BrowserRenameItemEvent *) ev; // Meant for this browser? if (bev->browserid == id) { if (CRITTERS) printf("BROWSER: Received BrowserRenameItem\n"); Rename(); } } break; default: break; } } LoopTray::~LoopTray() { if (app != 0) { app->getEMG()->UnlistenEvent(this,0,T_EV_TriggerSet); app->getEMG()->UnlistenEvent(this,0,T_EV_RenameLoop); } }; void LoopTray::Setup(Fweelin *a, BrowserCallback *c) { Browser::Setup(a,c); basepos = app->getCFG()->XCvt(0.016); iconsize = app->getCFG()->XCvt(0.03); xpanded = xpand; app->getEMG()->ListenEvent(this,0,T_EV_TriggerSet); app->getEMG()->ListenEvent(this,0,T_EV_RenameLoop); }; void LoopTray::ReceiveEvent(Event *ev, EventProducer *from) { switch (ev->GetType()) { case T_EV_TriggerSet : { TriggerSetEvent *tev = (TriggerSetEvent *) ev; // printf("tmap set: %d->%p\n",tev->idx,tev->nw); if (tev->nw == 0) { // Delete, // Scan for a LoopTrayItem corresponding to this index RemoveItem(tev->idx); touchtray = 1; } else { // Get the placename- where the loop is mapped char *pname = 0; FloLayout *curl = app->getCFG()->GetLayouts(); while (curl != 0) { if (tev->idx >= curl->loopids.lo && tev->idx <= curl->loopids.hi) { // Loop is mapped to an element in this layout- get the name int firstid = curl->loopids.lo; FloLayoutElement *curel = curl->elems; while (curel != 0 && firstid + curel->id != tev->idx) curel = curel->next; if (curel != 0) pname = curel->name; } curl = curl->next; } // Add, LoopTrayItem *nw = new LoopTrayItem(tev->nw,tev->idx, tev->nw->name, (tev->nw->name == 0 ? 1 : 0), pname); AddItem(nw,1); touchtray = 1; } } break; case T_EV_RenameLoop : { RenameLoopEvent *rev = (RenameLoopEvent *) ev; if (rev->in == 0) { Rename(rev->loopid); if (CRITTERS) printf("LOOPTRAY: Received RenameLoop(loopid: %d)\n",rev->loopid); } } break; default: // Let base class handle it Browser::ReceiveEvent(ev,from); break; } }; // A loop was renamed from outside the loop tray // (loops can be renamed in layouts) // (or on disk) void LoopTray::ItemRenamedFromOutside(Loop *l, char *nw) { if (l != 0 && nw != 0) { // Find the item that has been renamed { LoopTrayItem *curl = (LoopTrayItem *) first; while (curl != 0 && curl->l != l) curl = (LoopTrayItem *) curl->next; cur = curl; } if (cur != 0) { // Assign new name RenameItem(cur,nw); cur->default_name = 0; touchtray = 1; } } }; void LoopTray::ItemRenamed(char *nw) { if (nw != 0) { // Assign new name and stop RenameItem(cur,nw); delete renamer; renamer = 0; // Notify callback of new name if (callback != 0) callback->ItemRenamed(cur); cur->default_name = 0; touchtray = 1; } else { // Rename was aborted delete renamer; renamer = 0; } }; void LoopTray::Rename(int loopid) { if (renamer == 0) { // Find the LoopTrayItem with the given 'loopid' { LoopTrayItem *curl = (LoopTrayItem *) first; while (curl != 0 && curl->loopid != loopid) curl = (LoopTrayItem *) curl->next; cur = curl; } if (cur != 0) { if (CRITTERS) printf("RENAME: Item: %p\n",cur); renamer = new ItemRenamer(app,this,(cur->default_name ? 0 : cur->name)); if (!renamer->IsRenaming()) { delete renamer; renamer = 0; } } } }; char LoopTray::MouseMotion(MouseMotionInputEvent *mev) { if (resize_win != RS_Off) { int xdelta = mev->x - resize_xhand, ydelta = mev->y - resize_yhand; if (resize_win == RS_Move) { xpand_x1 = old_xpand_x1 + xdelta; xpand_y1 = old_xpand_y1 + ydelta; xpand_x2 = old_xpand_x2 + xdelta; xpand_y2 = old_xpand_y2 + ydelta; } else { if ((resize_win == RS_Right || resize_win == RS_TopRight || resize_win == RS_BottomRight) && xpand_x1+basepos*2 <= old_xpand_x2+xdelta) { xpand_x2 = old_xpand_x2 + xdelta; } else if ((resize_win == RS_Left || resize_win == RS_TopLeft || resize_win == RS_BottomLeft) && old_xpand_x1+xdelta+basepos*2 <= xpand_x2) { xpand_x1 = old_xpand_x1 + xdelta; } if ((resize_win == RS_Bottom || resize_win == RS_BottomLeft || resize_win == RS_BottomRight) && xpand_y1+basepos*2 <= old_xpand_y2+ydelta) { xpand_y2 = old_xpand_y2 + ydelta; } else if ((resize_win == RS_Top || resize_win == RS_TopLeft || resize_win == RS_TopRight) && old_xpand_y1+ydelta+basepos*2 <= xpand_y2) { xpand_y1 = old_xpand_y1 + ydelta; } touchtray = 1; } return 1; } return 0; } char LoopTray::MouseButton(MouseButtonInputEvent *mev) { if (resize_win != RS_Off && mev->button == resize_button && !mev->down) { // Mouse release on resize resize_win = RS_Off; return 1; } int mx = mev->x, my = mev->y; // Check if mouse event inside tray if (mx >= xpand_x1 && mx <= xpand_x2 && my >= xpand_y1 && my <= xpand_y2) { // Mouse inside tray if (mx > xpand_x1+basepos && my > xpand_y1+basepos && mx < xpand_x2-basepos && my < xpand_y2-basepos) { // Mouse in inner region if (mev->down) { // Check if the mouse is clicking in any loop LoopTrayItem *curl = (LoopTrayItem *) first; char go = 1, found = 0; while (curl != 0 && go) { if (curl->xpos != -1) { int relx = mx-xpand_x1-(curl->xpos+loopmap->map_xs/2), rely = my-xpand_y1-(curl->ypos+loopmap->map_ys/2); if (relx*relx+rely*rely <= loopsize*loopsize/4) { // Mouse is clicking within this loop found = 1; // Issue 'loop clicked' event LoopClickedEvent *lcevt = (LoopClickedEvent *) Event::GetEventByType(T_EV_LoopClicked); lcevt->button = mev->button; lcevt->down = mev->down; lcevt->loopid = curl->loopid; lcevt->in = 0; // In=0 means clicked in looptray app->getEMG()->BroadcastEvent(lcevt, this); } } else go = 0; curl = (LoopTrayItem *) curl->next; } if (!found) { // Not clicking inside any loop-- // Start moving resize_win = RS_Move; resize_button = mev->button; resize_xhand = mx; resize_yhand = my; old_xpand_x1 = xpand_x1; old_xpand_y1 = xpand_y1; old_xpand_x2 = xpand_x2; old_xpand_y2 = xpand_y2; } } } else { // Mouse in border region if (mev->down) { // Start resizing char bord_l = 0, bord_lm = 0, bord_r = 0, bord_rm = 0, bord_t = 0, bord_tm = 0, bord_b = 0, bord_bm = 0; int bord_mid_thresh = basepos*3; if (mx >= xpand_x1 && mx <= xpand_x1+basepos) { bord_l = 1; bord_lm = 1; } else if (mx >= xpand_x2-basepos && mx <= xpand_x2) { bord_r = 1; bord_rm = 1; } else if (mx >= xpand_x1 && mx <= xpand_x1+bord_mid_thresh) { bord_lm = 1; } else if (mx >= xpand_x2-bord_mid_thresh && mx <= xpand_x2) { bord_rm = 1; } if (my >= xpand_y1 && my <= xpand_y1+basepos) { bord_t = 1; bord_tm = 1; } else if (my >= xpand_y2-basepos && my <= xpand_y2) { bord_b = 1; bord_bm = 1; } else if (my >= xpand_y1 && my <= xpand_y1+bord_mid_thresh) { bord_tm = 1; } else if (my >= xpand_y2-bord_mid_thresh && my <= xpand_y2) { bord_bm = 1; } if (bord_l) { if (bord_tm) resize_win = RS_TopLeft; else if (bord_bm) resize_win = RS_BottomLeft; else resize_win = RS_Left; } else if (bord_r) { if (bord_tm) resize_win = RS_TopRight; else if (bord_bm) resize_win = RS_BottomRight; else resize_win = RS_Right; } else if (bord_t) { if (bord_lm) resize_win = RS_TopLeft; else if (bord_rm) resize_win = RS_TopRight; else resize_win = RS_Top; } else if (bord_b) { if (bord_lm) resize_win = RS_BottomLeft; else if (bord_rm) resize_win = RS_BottomRight; else resize_win = RS_Bottom; } else { printf("BROWSER: Error in mouse border algorithm!\n"); resize_win = RS_Off; } resize_button = mev->button; resize_xhand = mev->x; resize_yhand = mev->y; old_xpand_x1 = xpand_x1; old_xpand_y1 = xpand_y1; old_xpand_x2 = xpand_x2; old_xpand_y2 = xpand_y2; } } // Eat event return 1; } else if (mx >= xpos && mx <= xpos+iconsize && my >= ypos && my <= ypos+iconsize) { if (mev->down) { // Mouse clicked on icon xpanded = (xpanded ? 0 : 1); touchtray = 1; } return 1; } else { // Mouse outside tray, ignore return 0; } }; PatchBrowser::~PatchBrowser() { // Invoke our special ClearAllItems method ClearAllItems(); if (app != 0) { app->getEMG()->UnlistenEvent(this,0,T_EV_PatchBrowserMoveToBank); app->getEMG()->UnlistenEvent(this,0,T_EV_PatchBrowserMoveToBankByIndex); } }; void PatchBrowser::ClearAllItems() { LockBrowser(); cur = 0; first = 0; // Delete all items in all patch banks PatchBank *curpb = pb_first; pb_first = 0; while (curpb != 0) { BrowserItem *cur = curpb->first; curpb->first = 0; curpb->cur = 0; while (cur != 0) { BrowserItem *tmp = cur->next; delete cur; cur = tmp; } curpb = curpb->next; }; // *** Do we need to clear all patchbanks too? UnlockBrowser(); }; void PatchBrowser::PB_MoveTo (int direction) { LockBrowser(); if (xpand) { xpand_lastactivity = mygettime(); xpanded = 1; } // Update pb_cur if (pb_cur != 0) { pb_cur->cur = cur; pb_cur->first = first; } else pb_cur = pb_first; if (pb_cur != 0) { if (direction > 0) { // Forward if (pb_cur->next != 0) pb_cur = pb_cur->next; } else { // Slow way to move backwards in a singly linked list PatchBank *tmp = pb_first; while (tmp != 0 && tmp->next != pb_cur) tmp = tmp->next; if (tmp != 0) pb_cur = tmp; } // Assign patch 'cur' and 'first' pointers based on this patch bank first = pb_cur->first; cur = pb_cur->cur; pb_cur_tag = pb_cur->tag; SetMIDIEcho(); } else pb_cur_tag = -1; UnlockBrowser(); }; void PatchBrowser::PB_MoveToIndex (int index) { LockBrowser(); if (xpand) { xpand_lastactivity = mygettime(); xpanded = 1; } // Update pb_cur if (pb_cur != 0) { pb_cur->cur = cur; pb_cur->first = first; } else pb_cur = pb_first; // Count to right patchbank pb_cur = pb_first; for (int i = 0; i < index && pb_cur != 0; i++, pb_cur = pb_cur->next); if (pb_cur == 0) pb_cur = pb_first; else { // Assign patch 'cur' and 'first' pointers based on this patch bank first = pb_cur->first; cur = pb_cur->cur; SetMIDIEcho(); } if (pb_cur != 0) pb_cur_tag = pb_cur->tag; else pb_cur_tag = -1; UnlockBrowser(); }; void PatchBrowser::Setup(Fweelin *a, BrowserCallback *c) { Browser::Setup(a,c); app->getEMG()->ListenEvent(this,0,T_EV_PatchBrowserMoveToBank); app->getEMG()->ListenEvent(this,0,T_EV_PatchBrowserMoveToBankByIndex); }; void PatchBrowser::ReceiveEvent(Event *ev, EventProducer *from) { switch (ev->GetType()) { case T_EV_PatchBrowserMoveToBank : { PatchBrowserMoveToBankEvent *pbev = (PatchBrowserMoveToBankEvent *) ev; PB_MoveTo(pbev->direction); if (CRITTERS) printf("PATCH BROWSER: Received PatchBrowserMoveToBank " "(direction: %d)\n", pbev->direction); } break; case T_EV_PatchBrowserMoveToBankByIndex : { PatchBrowserMoveToBankByIndexEvent *pbev = (PatchBrowserMoveToBankByIndexEvent *) ev; PB_MoveToIndex(pbev->index); if (CRITTERS) printf("PATCH BROWSER: Received PatchBrowserMoveToBankByIndex " "(index: %d)\n", pbev->index); } break; default: // Let base class handle it Browser::ReceiveEvent(ev,from); break; } }; // Sets the right MIDI port(s) and channel(s) for echo based on this // patches' settings void PatchBrowser::SetMIDIEcho() { /* printf("pb cur: %p port: %d\n",pb_cur,pb_cur->port); printf("cur: %p\n",cur); printf("app: %p\n",app); printf("getmidi: %p\n",app->getMIDI()); */ if (app != 0 && app->getMIDI() != 0) app->getMIDI()->SetMIDIEcho((pb_cur == 0 ? 0 : pb_cur->port), (cur != 0 && cur->GetType() == B_Patch ? (PatchItem *) cur : 0)); }; void FloDisplaySnapshots::Rename (int idx) { Snapshot *s = app->getSNAP(idx); if (renamer == 0 && s != 0 && s->exists) { renamer = new ItemRenamer(app,this,s->name); rename_idx = idx; if (!renamer->IsRenaming()) { delete renamer; renamer = 0; } // Keep display showing while we interactively rename forceshow = 1; } }; void FloDisplaySnapshots::ItemRenamed(char *nw) { forceshow = 0; if (nw != 0) { // printf("NEW SNAPSHOT NAME: %s\n",nw); Snapshot *s = app->getSNAP(rename_idx); if (s != 0) { LockSnaps(); if (s->name != 0) delete[] s->name; if (nw != 0) { s->name = new char[strlen(nw)+1]; strcpy(s->name,nw); } else s->name = 0; UnlockSnaps(); } delete renamer; renamer = 0; } else { // Rename was aborted delete renamer; renamer = 0; } }; fweelin-0.6/src/fweelin_browser.h0000644000175000017500000004271111050163057015605 0ustar mercmerc#ifndef __FWEELIN_BROWSER_H #define __FWEELIN_BROWSER_H /* Copyright 2004-2008 Jan Pekau (JP Mercury) This file is part of Freewheeling. Freewheeling is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. Freewheeling is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Freewheeling. If not, see . */ #include "fweelin_event.h" #include "fweelin_config.h" class CircularMap; class MouseButtonInputEvent; class MouseMotionInputEvent; enum ResizeType { RS_Off, RS_Move, // Move only RS_Top, RS_Bottom, RS_Left, RS_Right, RS_TopLeft, RS_TopRight, RS_BottomLeft, RS_BottomRight }; enum BrowserItemType { B_Undefined = 0, B_Loop_Tray, // Loop tray (loaded loops) B_Scene_Tray, // Scene tray (loaded scenes) B_Loop, // Loop (all loops in library) B_Scene, // Scene (all scenes in library) B_Patch, B_Division, B_Last }; class BrowserItem { public: // Initialize a browser item with name n BrowserItem(char *n = 0, char default_name = 1) : default_name(default_name), next(0), prev(0) { if (n == 0) name = 0; else { name = new char[strlen(n)+1]; strcpy(name,n); } }; virtual ~BrowserItem() { if (name != 0) delete[] name; }; virtual BrowserItemType GetType() = 0; // Compare this item to a second item and return whether this item is // greater than (>0), less than (<0), or equal to (==0) second // Used for sorting browser items virtual int Compare(BrowserItem *second) { return 0; }; // Return zero if the item described by 'itemmatch' matches this item // This is a type-neutral compare function to be overridden to provide // meaningful matches for different browsers virtual int MatchItem(int itemmatch) { return 1; }; char default_name; // Nonzero if the name for this item is a default name char *name; BrowserItem *next, *prev; }; class BrowserDivision : public BrowserItem { public: virtual BrowserItemType GetType() { return B_Division; }; }; class BrowserCallback { public: virtual void ItemBrowsed(BrowserItem *i) = 0; virtual void ItemSelected(BrowserItem *i) = 0; virtual void ItemRenamed(BrowserItem *i) = 0; }; class RenameCallback { public: virtual void ItemRenamed(char *nw) = 0; }; class RenameUIVars { public: RenameUIVars() : rename_cursor_blinktime(0), rename_cursor_toggle(0) {}; double rename_cursor_blinktime; char rename_cursor_toggle; }; // This class encapsulates the UI for renaming an item class ItemRenamer : public EventHook { public: const static int RENAME_BUF_SIZE = 512; // Maximum length of item name const static double BLINK_DELAY; ItemRenamer(Fweelin *app, RenameCallback *cb, char *oldname); // Hook events for typing new names virtual char HookEvent(Event *ev, EventProducer *from); inline char *GetCurName() { return rename_tmpbuf; }; inline RenameUIVars *UpdateUIVars() { double t = mygettime(); if (t-rui.rename_cursor_blinktime >= BLINK_DELAY) { rui.rename_cursor_blinktime = t; rui.rename_cursor_toggle = (rui.rename_cursor_toggle ? 0 : 1); } return &rui; }; inline char IsRenaming() { return renaming; }; private: inline void Rename_Append(char c) { int rblen = strlen(rename_tmpbuf); if (rblen+1 < RENAME_BUF_SIZE) { rename_tmpbuf[rblen] = c; // printf("KEY: %c\n",rename_tmpbuf[rblen]); rename_tmpbuf[++rblen] = '\0'; } }; inline void Rename_Backspace() { int rblen = strlen(rename_tmpbuf); if (rblen > 0) rename_tmpbuf[rblen-1] = '\0'; }; Fweelin *app; RenameCallback *cb; // Way to notify the caller when we are done renaming char rename_tmpbuf[RENAME_BUF_SIZE]; // Buffer for new name RenameUIVars rui; char renaming; // Nonzero if we are renaming }; class Browser : public FloDisplay, public EventListener, public EventProducer, public RenameCallback { public: Browser (int iid, BrowserItemType btype, char xpand, int xpand_x1, int xpand_y1, int xpand_x2, int xpand_y2, float xpand_delay) : FloDisplay(iid), renamer(0), app(0), btype(btype), callback(0), first(0), cur(0), xpand_x1(xpand_x1), xpand_y1(xpand_y1), xpand_x2(xpand_x2), xpand_y2(xpand_y2), xpand_centery(-1), xpand_liney(-1), xpand_spread(-1), xpand_lastactivity(0.0), xpand_delay(xpand_delay), xpand(xpand), xpanded(0) { pthread_mutex_init (&browser_lock,0); if (btype >= B_Last || (int) btype < 0) { printf("BROWSER: Invalid browsetype %d!\n",btype); btype = (BrowserItemType) 0; } }; virtual ~Browser(); // Call after construction when we have app & callback ready virtual void Setup(Fweelin *a, BrowserCallback *c); // Move to the beginning of the browser list // Does not fully update, so MoveTo must be called after inline void MoveToBeginning() { LockBrowser(); cur = first; UnlockBrowser(); }; // Move to a new item, relative to the current void MoveTo(int adjust, int jumpadjust); // Select the current item void Select(); // Rename the current item void Rename(); // Mouse button pressed (return nonzero to eat event, zero to ignore) virtual char MouseButton(MouseButtonInputEvent *mev) { return 0; }; // Mouse moved (return nonzero to eat event, zero to ignore) virtual char MouseMotion(MouseMotionInputEvent *mev) { return 0; }; // Get the onscreen display name for a file with given name. // (filename must refer to a file of the type this browser handles) // Write the name to outbuf, with max maxlen characters. // Returns nonzero if we used a 'default' name. char GetDisplayName(char *filename, time_t *filetime, char *outbuf, int maxlen); ItemRenamer *renamer; // Renamer instance, or null if we are not renaming virtual void ItemRenamed(char *nw); // Callback for renamer // Via this method, a browser is notified of a change to the on-disk name // of an item. For example, when a Loop in memory is renamed, we also // rename it on disk, and the loop browser must be notified of this new name. void ItemRenamedOnDisk(char *old_filename, char *new_filename, char *new_name); inline BrowserItemType GetType() { return btype; }; virtual FloDisplayType GetFloDisplayType() { return FD_Browser; }; inline static char *GetTypeName(BrowserItemType b) { switch (b) { case B_Scene_Tray : return "Scene Tray"; case B_Loop_Tray : return "Loop Tray"; case B_Loop : return "Loop"; case B_Scene : return "Scene"; case B_Division : return "Division"; case B_Patch : return "Patch"; default : return "**UNKNOWN**"; } }; // Receive events virtual void ReceiveEvent(Event *ev, EventProducer *from); // Draw to screen virtual void Draw(SDL_Surface *screen); virtual void Draw_Item(SDL_Surface *screen, BrowserItem *i, int x, int y); virtual void ClearAllItems(); // Add divisions between browser items using the Compare function- // whenever two neighbouring items have difference greater than maxdelta, // a division is inserted. In browsing files, for example, this allows us // to group files that where created close to one another in time void AddDivisions(int maxdelta); // Add an item to this browser // (Doubley linked list add with sort) // Nonzero if we should sort (according to the BrowserItem::Compare() method) virtual void AddItem(BrowserItem *nw, char sort = 0); // Remove an item from this browser // For each item we call the MatchItem(itemmatch) method in BrowserItem // until MatchItem returns zero. Then we remove that item. virtual void RemoveItem(int itemmatch); // Return current browser item inline BrowserItem *GetCurItem() { return cur; }; // Threadsafe item rename inline void RenameItem(BrowserItem *i, char *nw) { LockBrowser(); if (i->name != 0) delete[] i->name; if (nw != 0) { i->name = new char[strlen(nw)+1]; strcpy(i->name,nw); } else i->name = 0; UnlockBrowser(); }; inline void LockBrowser() { pthread_mutex_lock (&browser_lock); }; inline void UnlockBrowser() { pthread_mutex_unlock (&browser_lock); }; protected: // Internal update function called when a new item is browsed- // derived classes may override virtual void ItemBrowsed() {}; Fweelin *app; BrowserItemType btype; // Browser type BrowserCallback *callback; // Callback to notify of browser events BrowserItem *first, // First item *cur; // Current item // Dimensions of expanded browser view when moving between items: int xpand_x1, xpand_y1, xpand_x2, xpand_y2, xpand_centery, xpand_liney, xpand_spread; double xpand_lastactivity, // Time of last activity in browser- // controls when to expand xpand_delay; // Time to hold up expanded browser char xpand, // Nonzero if we should expand when moving xpanded; // Nonzero if we are expanded pthread_mutex_t browser_lock; // A way to lock up a browser so two threads // don't race on it }; class LoopTray : public Browser { public: LoopTray (int iid, BrowserItemType btype, char xpand, int xpand_x1, int xpand_y1, int xpand_x2, int xpand_y2, int loopsize) : Browser(iid,btype,xpand,xpand_x1,xpand_y1,xpand_x2,xpand_y2,0.0), loopsize(loopsize), basepos(0), iconsize(0), resize_win(RS_Off), touchtray(0), loopmap(0) {}; virtual ~LoopTray(); // Call after construction when we have app & callback ready virtual void Setup(Fweelin *a, BrowserCallback *c); // Draw to screen virtual void Draw(SDL_Surface *screen); virtual void Draw_Item(SDL_Surface *screen, BrowserItem *i, int x, int y); // Receive events virtual void ReceiveEvent(Event *ev, EventProducer *from); // Mouse updates virtual char MouseButton(MouseButtonInputEvent *mev); virtual char MouseMotion(MouseMotionInputEvent *mev); // Renaming void Rename(int loopid); virtual void ItemRenamed(char *nw); void ItemRenamedFromOutside(Loop *l, char *nw); int loopsize, // Size of loops in tray basepos, // Base (border) size in tray iconsize; // Size of iconified tray // Window move/resize variables ResizeType resize_win; int resize_button, resize_xhand, resize_yhand, old_xpand_x1, old_xpand_x2, old_xpand_y1, old_xpand_y2; // Has the tray been changed and coordinates need recalculating? char touchtray; CircularMap *loopmap; // Mapping to draw circular loops }; class CombiZone { public: void SetupZone (int kr_lo = 0, int kr_hi = 0, char port_r = 0, int port = 0, int bank = -1, int prog = -1, int channel = 0) { this->kr_lo = kr_lo; this->kr_hi = kr_hi; this->port_r = port_r; this->port = port; this->bank = bank; this->prog = prog; this->channel = channel; }; int kr_lo, // Bottom key for this zone kr_hi; // Top key for this zone char port_r; // Nonzero if we should transmit to the MIDI port given below int port, // By default, a zone transmits to the MIDI port given by // a given patchbank. But it is also possible to redirect // a zone to output to any MIDI port. 0 is the internal // FluidSynth port. bank, // Bank select for zone (-1 for none) prog, // Program change for zone (-1 for none) channel; // Transmit channel # for zone }; // Small class to encapsulate patches class PatchItem : public BrowserItem { public: PatchItem (int id = 0, int bank = 0, int prog = 0, int channel = 0, char *name = 0) : BrowserItem(name), id(id), bank(bank), prog(prog), channel(channel), zones(0), numzones(0) {}; virtual ~PatchItem() { if (zones != 0) delete[] zones; }; inline void SetupZones (int numzones) { this->numzones = numzones; zones = new CombiZone[numzones]; } inline CombiZone *GetZone (int idx) { if (idx >= 0 && idx < numzones) return &zones[idx]; else return 0; }; // Is this a combi patch (multizone) (returns nonzero) // or just a regular patch? (returns zero) inline char IsCombi() { return numzones > 0; }; virtual BrowserItemType GetType() { return B_Patch; }; int id, // Unique patch ID bank, // Bank select for patch prog, // Program change for patch channel; // Channel # for patch // For a combination patch, we have an array of all zones CombiZone *zones; int numzones; }; // Patch browser is unique in that it manages -several- lists of // BrowserItems-- one for each MIDI port and, optionally, each channel // to which patch names are assigned. // // Each list of patches is called a PatchBank: #define MIDI_BANKCHANGE_MSB 0 #define MIDI_BANKCHANGE_LSB 32 class PatchBank { public: PatchBank (int port, int tag, char suppresschg) : port(port), tag(tag), suppresschg(suppresschg), first(0), cur(0), next(0) {}; int port, // MIDI output port for this patch bank // (or -1 for internal FluidSynth patch bank) tag; // Tag for identifying patchbank- can be // used by the user config to change FW behavior when // a given patchbank is active char suppresschg; // Suppress program/bank change messages being sent // for this patch bank? BrowserItem *first, // First item *cur; // Current item PatchBank *next; }; class PatchBrowser : public Browser { friend class Fweelin; public: // Every DIV_SPACING patches, we insert a divider in the browser const static int DIV_SPACING = 10; PatchBrowser (int iid, BrowserItemType btype, char xpand, int xpand_x1, int xpand_y1, int xpand_x2, int xpand_y2, float xpand_delay) : Browser(iid,btype,xpand,xpand_x1,xpand_y1,xpand_x2,xpand_y2,xpand_delay), pb_first(0), pb_cur(0), pb_cur_tag(-1), num_pb(0) {}; virtual ~PatchBrowser(); virtual void ClearAllItems(); virtual void Setup(Fweelin *a, BrowserCallback *c); virtual void ReceiveEvent(Event *ev, EventProducer *from); // Add patch bank void PB_Add (PatchBank *pb) { LockBrowser(); num_pb++; // Update pb_cur if (pb_cur != 0) { pb_cur->cur = cur; pb_cur->first = first; } // Insert at end of list if (pb_first == 0) pb_first = pb_cur = pb; else { PatchBank *pb_i = pb_first; while (pb_i->next != 0) pb_i = pb_i->next; pb_i->next = pb_cur = pb; } // And set cur & first pointers cur = pb->cur; first = pb->first; pb_cur_tag = pb->tag; SetMIDIEcho(); UnlockBrowser(); }; // Add patch bank at beginning of patchbanks void PB_AddBegin (PatchBank *pb) { LockBrowser(); num_pb++; // Update pb_cur if (pb_cur != 0) { pb_cur->cur = cur; pb_cur->first = first; } // Insert at beginning of list pb->next = pb_first; pb_first = pb_cur = pb; // And set cur & first pointers cur = pb->cur; first = pb->first; pb_cur_tag = pb->tag; SetMIDIEcho(); UnlockBrowser(); }; // Move to the next (+ve direction) or previous (-ve direction) patch bank void PB_MoveTo (int direction); // Move to a patchbank given by index void PB_MoveToIndex (int index); inline PatchBank *GetCurPatchBank() const { return pb_cur; }; // Sets the right MIDI port(s) and channel(s) for echo based on this // patches' settings void SetMIDIEcho(); protected: virtual void ItemBrowsed() { SetMIDIEcho(); }; private: PatchBank *pb_first, // List of patchbanks *pb_cur; // Current patchbank int pb_cur_tag, // Tag from current patchbank num_pb; // Number of patchbanks defined }; class FloDisplaySnapshots : public FloDisplay, public RenameCallback { public: FloDisplaySnapshots (Fweelin *app, int iid) : FloDisplay(iid), renamer(0), app(app), firstidx(0), numdisp(-1) { pthread_mutex_init (&snaps_lock,0); }; ~FloDisplaySnapshots() { pthread_mutex_destroy (&snaps_lock); }; virtual FloDisplayType GetFloDisplayType() { return FD_Snapshots; }; virtual void Draw(SDL_Surface *screen); ItemRenamer *renamer; // Renamer instance, or null if we are not renaming int rename_idx; // Index of snapshot we are renaming virtual void ItemRenamed(char *nw); // Callback for renamer // Rename the snapshot with given index void Rename (int idx); inline void LockSnaps() { pthread_mutex_lock (&snaps_lock); }; inline void UnlockSnaps() { pthread_mutex_unlock (&snaps_lock); }; Fweelin *app; int firstidx, // Index of first snapshot to display numdisp; // Number of snapshots to display int sx, sy, // Size of snapshots list margin; // Margin for text protected: pthread_mutex_t snaps_lock; // A way to lock up snapshot display so two threads // don't race on it }; #endif fweelin-0.6/src/fweelin.cc0000755000175000017500000000313011065526722014203 0ustar mercmerc/* ************ FreeWheeling ************ What is music, if it is not shared in community, held in friendship, alive and breathing, soil and soul? THANKS & PRAISE */ /* Copyright 2004-2008 Jan Pekau (JP Mercury) This file is part of Freewheeling. Freewheeling is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. Freewheeling is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Freewheeling. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include "fweelin_midiio.h" #include "fweelin_videoio.h" #include "fweelin_sdlio.h" #include "fweelin_audioio.h" #include "fweelin_core.h" #include "fweelin_core_dsp.h" #if 1 int main (int argc, char *argv[]) { Fweelin flo; printf("FreeWheeling %s\n",VERSION); printf("May we return to the circle.\n\n"); if (!flo.setup()) flo.go(); else printf("Error starting FreeWheeling!"); return 0; } #endif // Improvisation is loving what is. fweelin-0.6/src/fweelin_config.cc0000755000175000017500000031041011060102655015520 0ustar mercmerc// A deer crossed my path today // // It said // // Why all this pressure // to change the world?? // // Accept the world as it is. // That is peace. // That is healing. // // It is not idleness. // It is precise action, // Energy conservation. /* Copyright 2004-2008 Jan Pekau (JP Mercury) This file is part of Freewheeling. Freewheeling is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. Freewheeling is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Freewheeling. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include #include #include "fweelin_config.h" #include "fweelin_midiio.h" #include "fweelin_sdlio.h" #include "fweelin_core.h" // *********** CONFIG #ifdef __MACOSX__ #import /* for MAXPATHLEN */ char FWEELIN_datadir[MAXPATHLEN]; char *FWEELIN_DATADIR = FWEELIN_datadir; #endif const char CfgMathOperation::operators[] = {'/', '*', '+', '-'}; const int CfgMathOperation::numops = 4; const int FloConfig::NUM_PREALLOCATED_AUDIO_BLOCKS = 40; const int FloConfig::NUM_PREALLOCATED_TIME_MARKERS = 40; const float FloConfig::AUDIO_MEMORY_LEN = 10.0; // Maximum path length for config files #define CFG_PATH_MAX 2048 // Copies configuration file 'cfgname' from shared to ~/.fweelin // If copyall is set, copies *all* .XML files from shared to ~/.fweelin // Backups are made if needed void FloConfig::CopyConfigFile (char *cfgname, char copyall) { char buf[CFG_PATH_MAX]; char *homedir = getenv("HOME"); if (copyall) { // Copy all .xml files in shared: glob_t globbuf; snprintf(buf,CFG_PATH_MAX,"%s/*%s", FWEELIN_DATADIR,FWEELIN_CONFIG_EXT); printf("INIT: Copying all config files from shared folder...\n"); if (glob(buf, 0, NULL, &globbuf) == 0) { for (size_t i = 0; i < globbuf.gl_pathc; i++) { // Strip path and send filename char *lastslash = strrchr(globbuf.gl_pathv[i],'/'); if (lastslash == 0) CopyConfigFile(globbuf.gl_pathv[i],0); else CopyConfigFile(lastslash+1,0); } globfree(&globbuf); } } else { // Config file exists? (need to backup?) snprintf(buf,CFG_PATH_MAX,"%s/%s/%s",homedir, FWEELIN_CONFIG_DIR,cfgname); struct stat st; if (stat(buf,&st) == 0) { // Find backup name char tmp2[CFG_PATH_MAX]; int bCnt = 1; char go = 1; while (go) { snprintf(tmp2,CFG_PATH_MAX,"%s.backup.%d",buf,bCnt); if (stat(tmp2,&st) != 0) go = 0; // Free backup filename else bCnt++; } // Backup printf("Backing up your old configuration to: %s\n",tmp2); char tmp3[CFG_PATH_MAX]; snprintf(tmp3,CFG_PATH_MAX,"cp \"%s\" \"%s\"",buf,tmp2); printf("INIT: Copying: %s\n",tmp3); system(tmp3); } // Copy over from shared char buf2[CFG_PATH_MAX]; snprintf(buf2,CFG_PATH_MAX,"cp \"%s/%s\" \"%s/%s\"", FWEELIN_DATADIR,cfgname, homedir,FWEELIN_CONFIG_DIR); printf("INIT: Copying: %s\n",buf2); system(buf2); } }; char *FloConfig::PrepareLoadConfigFile (char *cfgname, char basecfg) { static char buf[CFG_PATH_MAX]; char *homedir = getenv("HOME"); // Look for config file char go = 1; do { snprintf(buf,CFG_PATH_MAX,"%s/%s/%s",homedir, FWEELIN_CONFIG_DIR,cfgname); struct stat st; if (stat(buf,&st) != 0) { if (go == 2) { // Already tried to copy config file from shared. // Config file not found printf("INIT: Can't find configuration file '%s'.\n",buf); return 0; } else { // 1st try- // Can't find config file in config dir- printf("INIT: Configuration file '%s' not in usual place. " "Checking.\n",buf); // Check if config dir exists? snprintf(buf,CFG_PATH_MAX,"%s/%s",homedir,FWEELIN_CONFIG_DIR); if (mkdir(buf,S_IRWXU)) { if (errno != EEXIST) { printf("INIT: Error %d creating config folder '%s'- " "do you have write permission there?\n", errno,buf); } } else printf("INIT: *** Created new config folder '%s'.\n",buf); // Copy configuration file(s) from shared folder CopyConfigFile(cfgname,basecfg); go = 2; } } else go = 0; // Found, end search } while (go); return buf; }; void UserVariable::Print(char *str, int maxlen) { if (name != 0 && str == 0) printf("'%s'[",name); switch (type) { case T_char : if (str != 0) snprintf(str,maxlen,"%d",(int) *this); else printf("%d",(int) *this); break; case T_int : if (str != 0) snprintf(str,maxlen,"%d",(int) *this); else printf("%d",(int) *this); break; case T_long : if (str != 0) snprintf(str,maxlen,"%ld",(long) *this); else printf("%ld",(long) *this); break; case T_float : if (str != 0) snprintf(str,maxlen,"%.2f",(float) *this); else printf("%.2f",(float) *this); break; case T_range : { Range r = *this; if (str != 0) snprintf(str,maxlen,"%d>%d",r.lo,r.hi); else printf("%d>%d",r.lo,r.hi); } break; case T_variable : if (str != 0) snprintf(str,maxlen,"variable"); else printf("variable"); break; case T_variableref : if (str != 0) snprintf(str,maxlen,"variable reference"); else printf("variable reference"); break; case T_invalid : if (str != 0) snprintf(str,maxlen,"invalid"); else printf("invalid"); break; } if (name != 0 && str == 0) printf("]"); }; void CfgToken::Print() { switch (cvt) { case T_CFG_None : printf("[none]\n"); break; case T_CFG_Static : val.Print(); break; case T_CFG_EventParameter : printf("'%s'",evparam.name); break; case T_CFG_UserVariable : var->Print(); break; } }; // Evaluate the current value of this token to dst // Using event ev as a reference for event parameter // If overwritetype is nonzero, sets dst to be of the appropriate data type // Otherwise, converts to existing type of dst void CfgToken::Evaluate(UserVariable *dst, Event *ev, char overwritetype) { switch (cvt) { case T_CFG_None : break; case T_CFG_Static : if (overwritetype) dst->type = val.type; dst->SetFrom(val); break; case T_CFG_EventParameter : if (ev != 0) { UserVariable tmp; tmp.type = evparam.dtype; char *evofs = (char *)ev + evparam.ofs; switch (evparam.dtype) { case T_char : memcpy(tmp.value,evofs,sizeof(char)); break; case T_int : memcpy(tmp.value,evofs,sizeof(int)); break; case T_long : memcpy(tmp.value,evofs,sizeof(long)); break; case T_float : memcpy(tmp.value,evofs,sizeof(float)); break; default : printf(" CfgToken: Can't evaluate invalid data type\n"); } if (overwritetype) dst->type = tmp.type; dst->SetFrom(tmp); } break; case T_CFG_UserVariable : if (overwritetype) dst->type = var->type; dst->SetFrom(*var); break; } }; char ParsedExpression::IsStatic() { if (start.cvt != T_CFG_Static) return 0; // Check math ops for nonstatics CfgMathOperation *cur = ops; while (cur != 0) { if (cur->operand.cvt != T_CFG_Static) return 0; cur = cur->next; } return 1; }; void ParsedExpression::Print() { // Print starting token start.Print(); CfgMathOperation *cop = ops; while (cop != 0) { printf("%c",cop->otype); cop->operand.Print(); cop = cop->next; } }; // Evaluate this expression UserVariable ParsedExpression::Evaluate(Event *input) { // Starting token.. UserVariable cur; start.Evaluate(&cur,input,1); // Setup cur with evaluation of start token // Move through the math.. CfgMathOperation *cop = ops; while (cop != 0) { // Evaluate the operand UserVariable tmp; cop->operand.Evaluate(&tmp,input,1); switch (cop->otype) { case '/' : cur /= tmp; break; case '*' : cur *= tmp; break; case '+' : cur += tmp; break; case '-' : cur -= tmp; break; default : printf("Evaluate Expression: Invalid math operand\n"); } cop = cop->next; } return cur; }; EventBinding::~EventBinding() { // Erase prototype event if (boundproto != 0) boundproto->RTDelete(); { // Erase dynamic token conditions DynamicToken *cur = tokenconds; while (cur != 0) { DynamicToken *tmp = cur->next; delete cur; cur = tmp; } } { // Erase dynamic parameter sets DynamicToken *cur = paramsets; while (cur != 0) { DynamicToken *tmp = cur->next; delete cur; cur = tmp; } } }; InputMatrix::InputMatrix(Fweelin *app) : vars(0), app(app) { // Setup input bindings array input_bind = new EventBinding **[T_EV_Last_Bindable]; for (int i = 0; i < T_EV_Last_Bindable; i++) input_bind[i] = 0; }; void InputMatrix::Start() { // Setup IM to listen!- this can not be done earlier because, during // configuration, EMG is not active // Listen for input events if (app->getEMG() == 0) { printf("INIT: Error: Event Manager not yet active!\n"); exit(1); } app->getEMG()->ListenEvent(this,0,T_EV_SetVariable); app->getEMG()->ListenEvent(this,0,T_EV_ToggleVariable); app->getEMG()->ListenEvent(this,0,T_EV_ShowDebugInfo); app->getEMG()->ListenEvent(this,0,T_EV_AdjustMidiTranspose); // Input events int evnum = (int) EventType(T_EV_Last_Bindable); for (int i = 0; i < evnum; i++) if (i == (int) EventType(T_EV_GoSub) || i == (int) EventType(T_EV_StartInterface)) // Listen for GoSub/StartInterface, // but allow us to call ourselves because // that is what gosub does! app->getEMG()->ListenEvent(this,0,(EventType) i); else // Listen for input events, blocking receive of calls from ourself to // prevent infinite loops on event echo app->getEMG()->ListenEvent(this,0,(EventType) i,1); }; InputMatrix::~InputMatrix() { EventBinding *cur, *tmp; app->getEMG()->UnlistenEvent(this,0,T_EV_SetVariable); app->getEMG()->UnlistenEvent(this,0,T_EV_ToggleVariable); app->getEMG()->UnlistenEvent(this,0,T_EV_ShowDebugInfo); app->getEMG()->UnlistenEvent(this,0,T_EV_AdjustMidiTranspose); // Input events int evnum = (int) EventType(T_EV_Last_Bindable); for (int i = 0; i < evnum; i++) { // Stop listening app->getEMG()->UnlistenEvent(this,0,(EventType) i); EventBinding **cur_hash = input_bind[i]; if (cur_hash != 0) { // & Free data structures int pidx = Event::GetParamIdxByType((EventType) i); if (pidx == -1) delete cur_hash; // No hash array, just one else { Event *tmpev = Event::GetEventByType((EventType) i,1); int hashsz = tmpev->GetParam(pidx).max_index+1; tmpev->RTDelete(); for (int j = 0; j < hashsz; j++) { cur = cur_hash[j]; while (cur != 0) { tmp = cur->next; delete cur; cur = tmp; } }; delete[] cur_hash; } } } delete[] input_bind; { UserVariable *cur = vars; while (cur != 0) { UserVariable *tmp = cur->next; delete cur; cur = tmp; } } }; // Removes leading and trailing spaces from string str // Modifies the end of string str and returns a pointer to the new // beginning after spaces char *InputMatrix::RemoveSpaces (char *str) { char *curptr = str; while (*curptr == ' ') curptr++; int n = strlen(str)-1; while (n > 0 && str[n] == ' ') { str[n] = '\0'; n--; } return curptr; }; // Adds one key to the given list based on the keysym name // Returns the new first pointer SDLKeyList *InputMatrix::AddOneKey (SDLKeyList *first, char *str) { // Remove leading and trailing spaces str = RemoveSpaces(str); SDLKey kh_sym = SDLIO::GetSDLKey(str); if (kh_sym != SDLK_UNKNOWN) { printf("'%s' + ",str); // Link it in! if (first == 0) first = new SDLKeyList(kh_sym); else { SDLKeyList *cur = first; while (cur->next != 0) cur = cur->next; cur->next = new SDLKeyList(kh_sym); } } else printf("** UNKNOWN KEY '%s' ** + ",str); return first; }; // Extracts named keys from the given string and returns a list // of the keysyms (named keys are separated by ,) SDLKeyList *InputMatrix::ExtractKeys (char *str) { char buf[255]; // Copy buf char *delim = ","; // Go through list of keys specified: char *cur = strpbrk(str,delim); int firstopidx; if (cur != 0) firstopidx = (long)cur-(long)str; else firstopidx = -1; // First key if (firstopidx == -1) { strncpy(buf,str,255); buf[254] = '\0'; } else { long len = MIN(firstopidx,254); memcpy(buf,str,len); buf[len] = '\0'; } // Parse it SDLKeyList *first = 0; first = AddOneKey(first,buf); while (cur != 0) { cur++; char *next = strpbrk(cur,delim); // Copy the key name long len; if (next != 0) len = (long)next-(long)cur; else len = strlen(cur); if (len >= 255) len = 254; memcpy(buf,cur,len); buf[len] = '\0'; // And parse it first = AddOneKey(first,buf); cur = next; } return first; }; void InputMatrix::SetVariable (UserVariable *var, char *value) { // First, parse the value based on the variable type switch (var->type) { case T_char : *var = (char) atoi(value); break; case T_int : *var = (int) atoi(value); break; case T_long : *var = (long) atol(value); break; case T_float : *var = (float) atof(value); break; case T_range : { char tmp[255]; strncpy(tmp,value,255); tmp[254] = '\0'; char *delim = strchr(tmp,'>'); if (delim != 0) { *delim = '\0'; delim++; } int lo = atoi(tmp), hi = (delim != 0 ? atoi(delim) : 0); Range r(lo,hi); *var = r; } break; case T_variable : case T_variableref : case T_invalid : printf("SetVariable: Invalid variable type!\n"); break; } }; void InputMatrix::CreateVariable (xmlNode *declare) { UserVariable *nw = new UserVariable(); // Name xmlChar *name = xmlGetProp(declare, (const xmlChar *)"var"); if (name == 0) { printf(FWEELIN_ERROR_COLOR_ON "*** INIT: WARNING: Variable name not specified when declaring.\n" FWEELIN_ERROR_COLOR_OFF); delete nw; return; } nw->name = new char[xmlStrlen(name)+1]; strcpy(nw->name,(char *)name); xmlFree(name); // Type xmlChar *type = xmlGetProp(declare, (const xmlChar *)"type"); if (type == 0) { printf(FWEELIN_ERROR_COLOR_ON "*** INIT: WARNING: Variable type not specified when declaring.\n" FWEELIN_ERROR_COLOR_OFF); delete nw; return; } nw->type = GetCoreDataType((char *) type); if (nw->type == T_invalid) { printf(FWEELIN_ERROR_COLOR_ON "*** INIT: WARNING: Invalid variable type.\n" FWEELIN_ERROR_COLOR_OFF); delete nw; return; } // Value xmlChar *value = xmlGetProp(declare, (const xmlChar *)"init"); if (value == 0) memset(nw->value,0,CFG_VAR_SIZE); else SetVariable(nw,(char *) value); // Insert into variable list nw->next = vars; vars = nw; printf(" declare: variable '%s' type '%s' value '%s'\n", nw->name, type, value); xmlFree(type); if (value != 0) xmlFree(value); }; // Scans in the given binding for settings for output event parameters // and sets us up to handle those void InputMatrix::CreateParameterSets (int interfaceid, EventBinding *bind, xmlNode *binding, Event *input, int contnum) { const static char *delim = " and "; const static char *str_base = "parameters"; int str_len = strlen(str_base)+4; char basebuf[str_len]; if (contnum == 0) sprintf(basebuf,str_base); else snprintf(basebuf,str_len,"%s%d",str_base,contnum); // Interface ID set explicitly? char interfaceset = 0; xmlChar *paramstr = xmlGetProp(binding, (const xmlChar *)basebuf); if (paramstr != 0) { // Config specifies param sets // Separate into each param set char *buf = new char[xmlStrlen(paramstr)+1], *curp = (char *)paramstr, *nextp; do { nextp = strstr(curp,delim); int len = (nextp == 0 ? strlen(curp) : (int) (nextp-curp)); strncpy(buf,curp,len); buf[len] = '\0'; // Now buf contains one parameter- parse it // Get LValue char *sep = strchr(buf,'='); if (sep != 0) { *sep = '\0'; // Remove leading and trailing spaces char *lv = RemoveSpaces(buf); // Find extra tokens not properly formatted if (strchr(sep+1,'=') != 0) { char *rv = RemoveSpaces(sep+1); printf(FWEELIN_ERROR_COLOR_ON "*** INIT: WARNING: Missing 'and' in parameters token: " "'%s=%s'\n" FWEELIN_ERROR_COLOR_OFF, lv,rv); } // Get RValue char *rv = RemoveSpaces(sep+1); // Check LValue against output parameters char found = 0; for (int i = 0; !found && i < bind->boundproto->GetNumParams(); i++) { EventParameter param = bind->boundproto->GetParam(i); if (!strcmp(lv,param.name)) { // Config specifies a param set for this parameter found = 1; if (!strcmp(param.name,INTERFACEID)) // Parameter is interface ID interfaceset = 1; // Parse RValue expression that specifies set. char enable_keynames = (bind->boundproto->GetType() == T_EV_Input_Key && !strcmp(param.name,"key")); ParsedExpression *exp = ParseExpression(rv, input, enable_keynames); // OK, check if expression is static if (exp->IsStatic()) { // Yup, so evaluate now UserVariable val = exp->Evaluate(input); // Store directly in output prototype event char *nwofs = (char *)bind->boundproto + param.ofs; // Data location StoreParameter(nwofs,param.dtype,&val); printf(" -set '%s' = ",param.name); val.Print(); printf("\n"); delete exp; } else { // Dynamic expression DynamicToken *nwset = new DynamicToken(); CfgToken token; token.cvt = T_CFG_EventParameter; token.evparam = param; nwset->token = token; nwset->exp = exp; nwset->next = bind->paramsets; bind->paramsets = nwset; printf(" -set '%s' = ",param.name); exp->Print(); printf("\n"); } } } // Debugging for invalid paramset if (!found) { printf(FWEELIN_ERROR_COLOR_ON "*** INIT: WARNING: Invalid parameters token: '%s=%s'\n" FWEELIN_ERROR_COLOR_OFF, lv,rv); } } // Next condition curp = (nextp == 0 ? 0 : nextp+strlen(delim)); } while (curp != 0); delete[] buf; xmlFree(paramstr); } if (!interfaceset) { // Interface ID not set explicitly as parameter- check if // the event we're binding for output has 'interfaceid'- // if so, set implicitly based on what interface this binding is // defined in char found = 0; for (int i = 0; !found && i < bind->boundproto->GetNumParams(); i++) { EventParameter param = bind->boundproto->GetParam(i); if (!strcmp(param.name,INTERFACEID)) { // Yup, set implicitly found = 1; char tmp[20]; snprintf(tmp,20,"%d",interfaceid); // Set from interface ID ParsedExpression *exp = ParseExpression(tmp, input); // OK, check if expression is static if (exp->IsStatic()) { // Yup, so evaluate now UserVariable val = exp->Evaluate(input); // Store directly in output prototype event char *nwofs = (char *)bind->boundproto + param.ofs; // Data location StoreParameter(nwofs,param.dtype,&val); printf(" -implicitly set '%s' = ",param.name); val.Print(); printf("\n"); delete exp; } else { // Dynamic expression DynamicToken *nwset = new DynamicToken(); CfgToken token; token.cvt = T_CFG_EventParameter; token.evparam = param; nwset->token = token; nwset->exp = exp; nwset->next = bind->paramsets; bind->paramsets = nwset; printf(" -implicitly set '%s' = ",param.name); exp->Print(); printf("\n"); } } } } }; // Scans in the given binding for conditions on input event parameters // or user variables, and sets us up to handle those // Returns the hash index for this binding, based on an indexed parameter, // or 0 if this binding is not indexed int InputMatrix::CreateConditions (int interfaceid, EventBinding *bind, xmlNode *binding, Event *input, int paramidx) { const static char *delim = " and "; // Return index int ret_index = 0; // Interface ID set explicitly? char interfaceset = 0; xmlChar *cond = xmlGetProp(binding, (const xmlChar *)"conditions"); if (cond != 0) { // Config specifies conditions // Separate into each condition char *buf = new char[xmlStrlen(cond)+1], *curc = (char *)cond, *nextc; do { nextc = strstr(curc,delim); int len = (nextc == 0 ? strlen(curc) : (int) (nextc-curc)); strncpy(buf,curc,len); buf[len] = '\0'; // Now buf contains one condition- parse it // Get LValue char *sep = strchr(buf,'='); if (sep != 0) { *sep = '\0'; // Remove leading and trailing spaces char *lv = RemoveSpaces(buf); // Find extra tokens not properly formatted if (strchr(sep+1,'=') != 0) { char *rv = RemoveSpaces(sep+1); printf(FWEELIN_ERROR_COLOR_ON "*** INIT: WARNING: Missing 'and' in conditions token: " "'%s=%s'\n" FWEELIN_ERROR_COLOR_OFF, lv,rv); } // Get RValue char *rv = RemoveSpaces(sep+1); // Check LValue against input parameters char found = 0; if (input != 0) { for (int i = 0; !found && i < input->GetNumParams(); i++) { EventParameter param = input->GetParam(i); if (!strcmp(lv,param.name)) { // Config specifies a condition for this parameter found = 1; if (!strcmp(param.name,INTERFACEID)) // Condition is interface ID interfaceset = 1; // Parse RValue expression that specifies condition. char enable_keynames = (input->GetType() == T_EV_Input_Key && !strcmp(param.name,"key")); ParsedExpression *exp = ParseExpression(rv, input, enable_keynames); // Is this parameter indexed? if (i == paramidx) { // OK, is the RValue static (ie can we store the binding // in a hash or do we need to compute during runtime)? if (exp->IsStatic()) { // Yup, so evaluate now UserVariable val = exp->Evaluate(input); // Return hash value ret_index = (int) val % param.max_index; } else { // Indexed parameter, but value is not static- // Use wildcard slot in hash ret_index = param.max_index; } } // Create DynamicToken to hold condition DynamicToken *nwcond = new DynamicToken(); CfgToken token; token.cvt = T_CFG_EventParameter; token.evparam = param; nwcond->token = token; nwcond->exp = exp; nwcond->next = bind->tokenconds; bind->tokenconds = nwcond; printf(" -condition '%s' == ",param.name); exp->Print(); if (enable_keynames) printf(" [%s]",rv); printf("\n"); } } } // Check LValue against user variables UserVariable *cur = vars; while (!found && cur != 0) { if (cur->name != 0) { if (!strcmp(lv,cur->name)) { // Config specifies a condition for this variable found = 1; // Parse RValue expression that specifies condition. ParsedExpression *exp = ParseExpression(rv, input); // Create DynamicToken to hold condition DynamicToken *nwcond = new DynamicToken(); CfgToken token; token.cvt = T_CFG_UserVariable; token.var = cur; nwcond->token = token; nwcond->exp = exp; nwcond->next = bind->tokenconds; bind->tokenconds = nwcond; printf(" -condition '%s' == ",cur->name); exp->Print(); printf("\n"); } } cur = cur->next; } // Debugging for invalid condition if (!found) { printf(FWEELIN_ERROR_COLOR_ON "*** INIT: WARNING: Invalid conditions token: '%s=%s'\n" FWEELIN_ERROR_COLOR_OFF, lv,rv); } } // Next condition curc = (nextc == 0 ? 0 : nextc+strlen(delim)); } while (curc != 0); delete[] buf; xmlFree(cond); } if (!interfaceset) { // Interface ID not set explicitly as condition- check if // the event we're binding for input has 'interfaceid'- // if so, set implicitly based on what interface this binding is // defined in char found = 0; for (int i = 0; !found && i < input->GetNumParams(); i++) { EventParameter param = input->GetParam(i); if (!strcmp(param.name,INTERFACEID)) { // Yup, set implicitly found = 1; char tmp[20]; snprintf(tmp,20,"%d",interfaceid); // Set from interface ID ParsedExpression *exp = ParseExpression(tmp, input); // Is this parameter indexed? if (i == paramidx) { // OK, is the RValue static (ie can we store the binding // in a hash or do we need to compute during runtime)? if (exp->IsStatic()) { // Yup, so evaluate now UserVariable val = exp->Evaluate(input); // Return hash value ret_index = (int) val % param.max_index; } else { // Indexed parameter, but value is not static- // Use wildcard slot in hash ret_index = param.max_index; } } // Create DynamicToken to hold condition DynamicToken *nwcond = new DynamicToken(); CfgToken token; token.cvt = T_CFG_EventParameter; token.evparam = param; nwcond->token = token; nwcond->exp = exp; nwcond->next = bind->tokenconds; bind->tokenconds = nwcond; printf(" -implicit condition '%s' == ",param.name); exp->Print(); printf("\n"); } } } // printf(" (hash %d)\n",ret_index); return ret_index; } void InputMatrix::CreateBinding (int interfaceid, xmlNode *binding) { EventBinding *nw = 0, *prev = 0; // Input event xmlChar *instr = xmlGetProp(binding, (const xmlChar *)"input"); if (instr == 0) { printf(FWEELIN_ERROR_COLOR_ON " [Invalid binding: No input event!]\n" FWEELIN_ERROR_COLOR_OFF); } else { printf(" binding: input '%s'", (char *) instr); // Go from the named event to an Event* prototype // Wait for an instance if none available Event *inproto = Event::GetEventByName((char *)instr,1); if (inproto == 0) printf(FWEELIN_ERROR_COLOR_ON " [Invalid event!]\n" FWEELIN_ERROR_COLOR_OFF); else { int typ = inproto->GetType(); if (typ >= T_EV_Last_Bindable) printf(FWEELIN_ERROR_COLOR_ON " [This event type can't be an input!]\n" FWEELIN_ERROR_COLOR_OFF); else { int pidx = Event::GetParamIdxByType((EventType) typ); if (input_bind[typ] == 0) { // No bindings yet for this type- set it up if (pidx == -1) { // No index for this type input_bind[typ] = new EventBinding *; input_bind[typ][0] = 0; } else { // Create hashtable for this type // Store one extra element for wildcard case int hashsz = inproto->GetParam(pidx).max_index+1; printf("\nCONFIG: Create '%s' parameter hashtable[%d] for input " "event '%s'\n",inproto->GetParam(pidx).name, hashsz,Event::GetEventName((EventType) typ)); input_bind[typ] = new EventBinding *[hashsz]; for (int i = 0; i < hashsz; i++) input_bind[typ][i] = 0; } } // OK, create a binding nw = new EventBinding(); // Echo? xmlChar *echo = xmlGetProp(binding, (const xmlChar *)"echo"); if (echo != 0) { nw->echo = atoi((char *)echo); if (nw->echo) printf(" (echo)"); xmlFree(echo); } // Conditions printf("\n"); int store_idx = CreateConditions(interfaceid, nw,binding,inproto,pidx); // Output event(s) int contnum = 0; char go = 1, first = 1; do { const static char *str_base = "output"; int str_len = strlen(str_base)+4; char buf[str_len]; if (contnum == 0) sprintf(buf,str_base); else snprintf(buf,str_len,"%s%d",str_base,contnum); xmlChar *outstr = xmlGetProp(binding, (const xmlChar *)buf); if (outstr == 0) { // Try at least "output" and "output1" if (contnum > 0) go = 0; } else { printf(" -> output '%s'", (char *) outstr); if (nw == 0) { // OK, we need another binding (continued) nw = new EventBinding(); } // Go from the named event to an Event* prototype // Wait for an instance if none available nw->boundproto = Event::GetEventByName((char *)outstr,1); if (nw->boundproto == 0) printf(FWEELIN_ERROR_COLOR_ON " [*** Invalid event! ***]\n" FWEELIN_ERROR_COLOR_OFF); else { printf("\n"); // Create parameter settings CreateParameterSets(interfaceid,nw,binding,inproto,contnum); if (prev != 0) { // So flag previous binding as 'continued' prev->continued = 1; // And link it up to this new binding //prev->next = nw; } // Store binding //printf("typ: %d store_idx: %d\n",typ,store_idx); //printf("ib_one: %p\n",input_bind[typ]); if (input_bind[typ][store_idx] == 0) input_bind[typ][store_idx] = nw; else { EventBinding *cur = input_bind[typ][store_idx]; while (cur->next != 0) cur = cur->next; cur->next = nw; } prev = nw; nw = 0; first = 0; } xmlFree(outstr); } contnum++; } while (go); if (first) printf(FWEELIN_ERROR_COLOR_ON " [*** No output event specified! ***]\n" FWEELIN_ERROR_COLOR_OFF); if (nw != 0) { // Erase unstored binding delete nw; nw = 0; } } // Erase input prototype used for querying inproto->RTDelete(); } xmlFree(instr); } }; // Parses the given token (no math ops!) into dst // Correctly identifies when variables or event parameters are referenced // enable_keynames means that the token is first interpreted as a keyboard // key name void InputMatrix::ParseToken(char *str, CfgToken *dst, Event *ref, char enable_keynames) { //printf("parse token: %s\n",str); // First, remove leading or trailing spaces // Careful, we **overwrite 'str'** while (*str == ' ') str++; char *tmp = strchr(str,' '); if (tmp != 0) *tmp = '\0'; // Parse key name? if (enable_keynames) { int keysym = SDLIO::GetSDLKey((char *) str); if (keysym != SDLK_UNKNOWN && keysym >= SDLK_FIRST && keysym < SDLK_LAST) { // Token references a keyboard key! dst->cvt = T_CFG_Static; // Interpret as static dst->val.type = T_int; dst->val = keysym; return; } } // Check if token references an event parameter if (ref != 0) for (int j = 0; j < ref->GetNumParams(); j++) { EventParameter evparam = ref->GetParam(j); if (!strcmp(str,evparam.name)) { // Matching parameter dst->cvt = T_CFG_EventParameter; dst->evparam = evparam; return; } } // Check if token references a user variable UserVariable *cur = vars; while (cur != 0) { if (!strcmp(str,cur->name)) { // Matching user variable dst->cvt = T_CFG_UserVariable; dst->var = cur; return; } cur = cur->next; } // No matches to variables or parameters, interpret as static token char *ascii_scalar = " 0123456789.>,"; if (strlen(str) > 0 && strpbrk(str,ascii_scalar) != str) { // Wait a second, this isn't a scalar, it probably has letters! printf(FWEELIN_ERROR_COLOR_ON "\n*** INIT: WARNING: Invalid token: %s\n" FWEELIN_ERROR_COLOR_OFF, str); dst->cvt = T_CFG_None; dst->var = 0; return; } // Figure out what type of static the token is dst->cvt = T_CFG_Static; char *rng_delim = strchr(str,'>'); if (rng_delim != 0) { // Range character found dst->val.type = T_range; } else { char *float_delim = strchr(str,'.'); if (float_delim != 0) { // Float character found dst->val.type = T_float; } else { // Assume scalar is 'int'-- // This affects runtime performance in that all dynamic evaluations // of the parent expression are computed using this type! dst->val.type = T_int; } } // Given the type, set the variable! SetVariable(&(dst->val),str); }; // Parses a given expression string, extracting tokens // for example: 'VAR_curnote+12' references variable VAR_curnote and // creates 1 math operation +12 // The expression may also reference parameters in event 'ref' // and these references will be extracted ParsedExpression *InputMatrix::ParseExpression(char *str, Event *ref, char enable_keynames) { char opstr[CfgMathOperation::numops+1]; char buf[255]; // Copy buf CfgMathOperation *first = 0, *last = 0; signed int firstopidx = -1; //printf("parse expression: %s\n",str); // Create list of operators int i; for (i = 0; i < CfgMathOperation::numops; i++) opstr[i] = CfgMathOperation::operators[i]; opstr[i] = '\0'; // Find the first occurance of an operator in string str char *cur = strpbrk(str,opstr); if (cur != 0) firstopidx = (long)cur-(long)str; else firstopidx = -1; // Now, begin creating parsed expression ParsedExpression *exp = new ParsedExpression(); // Parse beginning token if (firstopidx == -1) { strncpy(buf,str,255); buf[254] = '\0'; } else { long len = MIN(firstopidx,254); memcpy(buf,str,len); buf[len] = '\0'; } ParseToken(buf,&(exp->start),ref,enable_keynames); while (cur != 0) { char op = *cur; // Store operand cur++; char *next = strpbrk(cur,opstr); // Copy the operand long len; if (next != 0) len = (long)next-(long)cur; else len = strlen(cur); if (len >= 255) len = 254; memcpy(buf,cur,len); buf[len] = '\0'; // Now we have operator 'op' and operand in 'buf' CfgMathOperation *nw = new CfgMathOperation(); nw->otype = op; ParseToken(buf,&(nw->operand),ref,enable_keynames); if (first == 0) first = last = nw; else { last->next = nw; last = nw; } cur = next; } exp->ops = first; return exp; }; // Stores in ptr the value val given that ptr is of type dtype void InputMatrix::StoreParameter(char *ptr, CoreDataType dtype, UserVariable *val) { switch (dtype) { case T_char : *ptr = (char) *val; break; case T_int : *((int *) ptr) = (int) *val; break; case T_long : *((long *) ptr) = (long) *val; break; case T_float : *((float *) ptr) = (float) *val; break; case T_range : *((Range *) ptr) = (Range) *val; break; case T_variable : *((UserVariable *) ptr) = *val; break; case T_variableref : *((UserVariable **) ptr) = val; break; default : printf("Unrecognized event parameter type!\n"); break; } }; // Using the eventbinding's parametersets as a template, dynamically // sets parameters in the output event void InputMatrix::SetDynamicParameters(Event *input, Event *output, EventBinding *bind) { // Go through the settings DynamicToken *cur = bind->paramsets; while (cur != 0) { if (cur->token.cvt == T_CFG_EventParameter) { // Get ptr to output parameter char *outofs = (char *)output + cur->token.evparam.ofs; if (cur->token.evparam.dtype == T_variableref) { // Output event wants a reference to a variable-- not an evaluation! // See if the starting token is a UserVariable if (cur->exp->start.cvt == T_CFG_UserVariable) StoreParameter(outofs,T_variableref,cur->exp->start.var); else { printf("CONFIG: SetDynamicParameters: Event expects UserVariable but" " another type is given by config!\n"); StoreParameter(outofs,T_variableref,0); } } else { // Evaluate expression with dynamic input & variable parameters UserVariable val = cur->exp->Evaluate(input); // Store the output data correctly StoreParameter(outofs,cur->token.evparam.dtype,&val); } } else printf("CONFIG: SetDynamicParameters: Unknown destination in token!\n"); cur = cur->next; } }; // Are the conditions in the EventBinding bind matched by the // given input event and user variables? char InputMatrix::CheckConditions(Event *input, EventBinding *bind) { char match = 1; // Check dynamic token conditions DynamicToken *cur = bind->tokenconds; while (cur != 0 && match) { // Compare evaluations of token and expression UserVariable cmp1; cur->token.Evaluate(&cmp1,input,1); UserVariable cmp2 = cur->exp->Evaluate(input); if (cmp1 != cmp2) match = 0; else cur = cur->next; } return match; }; // Traverses through the list of event bindings beginning at 'start' // looking for a binding that matches current user variables and input // event 'ev' EventBinding *InputMatrix::MatchBinding(Event *ev, EventBinding *start) { #if 0 { EventBinding *cur = start; int count = 0; while (cur != 0) { count++; cur = cur->next; } printf(" [SCAN] Hash size: %d",count); } #endif EventBinding *cur = start; char go = 1, prevcont = 0; while (cur != 0 && go) { if (!prevcont && CheckConditions(ev,cur)) go = 0; else { prevcont = cur->continued; cur = cur->next; } } #if 0 if (cur != 0) printf(" HIT!\n"); else printf("\n"); #endif return cur; }; void InputMatrix::ReceiveEvent(Event *ev, EventProducer *from) { char echo = 1; EventBinding *match = 0; // Input events int i = ev->GetType(); if (ev->GetType() < T_EV_Last_Bindable) { EventHook *ev_hook = app->getCFG()->ev_hook; if (ev_hook == 0 || !ev_hook->HookEvent(ev,from)) { if (CRITTERS && ev->GetType() == T_EV_GoSub) printf("CONFIG: GoSub(%d)\n",((GoSubEvent *) ev)->sub); if (input_bind[i] != 0) { EventBinding **cur_hash = input_bind[i]; // Find indexed parameter EventBinding *search = 0; EventParameter param; int pidx = Event::GetParamIdxByType((EventType) i); if (pidx == -1) { //printf("noidx "); search = *cur_hash; } else { param = ev->GetParam(pidx); if (param.dtype != T_int) { // Error! printf("CONFIG: Error: Indexed event parameters must be " "integers!\n"); } else { // Get value of indexed parameter in input event char *evofs = (char *)ev + param.ofs; int hashval = *((int *) evofs) % param.max_index; //printf("hashidx: %d ",hashval); // Search in the right list of bindings- based on the hash index search = cur_hash[hashval]; } } // Now, check for matching binding in the search list if (search != 0) match = MatchBinding(ev,search); if (match == 0 && pidx != -1 && cur_hash[param.max_index] != 0) // OK, no match on the exact hash! -- check wildcards stored at the // end of the hashtable match = MatchBinding(ev,cur_hash[param.max_index]); } // First matching binding, check if she says to echo if (match != 0) echo = match->echo; else if (ev->GetType() == T_EV_GoSub || ev->GetType() == T_EV_StartInterface) echo = 0; // Never echo back unmatched GoSub/StartInterface- // we'll get into a loop // printf("CONFIG: Binding match %p (echo %d)\n",match,echo); while (match != 0) { // So we have a binding.. trigger the bound event! Event *shot = (Event *) match->boundproto->RTNew(); if (shot == 0) printf("CONFIG: WARNING: Can't send event- RTNew() failed\n"); else { *shot = *match->boundproto; // Copy from prototype SetDynamicParameters(ev,shot,match); app->getEMG()->BroadcastEventNow(shot, this); } // Trigger any continued bindings.. if (match->continued) match = match->next; else match = 0; } // Echo the incoming event back? if (echo) { Event *echo = (Event *) ev->RTNew(); if (echo == 0) printf("CONFIG: WARNING: Can't send event- RTNew() failed\n"); else { *echo = *ev; // Copy from incoming input echo->echo = 1; // Set echo flag app->getEMG()->BroadcastEventNow(echo, this); } } } else if (ev_hook != 0) { // Hook swallowed event if (CRITTERS) printf("CONFIG: Hook swallowed event (type %d).\n",ev->GetType()); } } else { switch (ev->GetType()) { // *** Internal events case T_EV_SetVariable : { SetVariableEvent *sv = (SetVariableEvent *) ev; // Set the variable to the given value if (sv->var == 0 || sv->var->IsSystemVariable()) printf(" SetVariableEvent: Invalid variable!\n"); else { // Check if variable change is within maxjump char goset = 1; if (sv->maxjumpcheck) { // Maxjump check enabled // Compute change in variable UserVariable jump = sv->var->GetDelta(sv->value); if (jump > sv->maxjump) goset = 0; // Don't set variable } if (goset) { if (CRITTERS) { printf("CONFIG: SetVariable: "); sv->var->Print(); printf(" -> "); sv->var->SetFrom(sv->value); sv->var->Print(); printf("\n"); } else sv->var->SetFrom(sv->value); } else { // Don't set variable if (CRITTERS) { printf("CONFIG: SetVariable: "); sv->var->Print(); printf(" -> [NOT SET- Max jump exceeded!]\n"); } } } } break; case T_EV_ToggleVariable : { ToggleVariableEvent *tv = (ToggleVariableEvent *) ev; // Set the variable to the given value if (tv->var == 0 || tv->var->IsSystemVariable()) printf(" ToggleVariableEvent: Invalid variable!\n"); else { int tmp = (int) (*(tv->var)); tmp++; if (tmp > tv->maxvalue) tmp = tv->minvalue; UserVariable v; v.type = T_int; v = tmp; if (CRITTERS) { printf("CONFIG: ToggleVariable: "); tv->var->Print(); printf(" -> "); tv->var->SetFrom(v); tv->var->Print(); printf("\n"); } else tv->var->SetFrom(v); } } break; case T_EV_ShowDebugInfo : { ShowDebugInfoEvent *dev = (ShowDebugInfoEvent *) ev; app->getCFG()->showdebug = dev->show; if (CRITTERS) printf("CONFIG: show debugging info = %s\n", (dev->show ? "on" : "off")); } break; case T_EV_AdjustMidiTranspose : { AdjustMidiTransposeEvent *tev = (AdjustMidiTransposeEvent *) ev; app->getCFG()->transpose += tev->adjust; if (CRITTERS) printf("CONFIG: adjust transpose midi by %d: transpose = %d.\n", tev->adjust,app->getCFG()->transpose); } break; default: break; } } }; void FloConfig::ConfigureEventBindings(xmlDocPtr doc, xmlNode *events, int interfaceid, char firstpass) { xmlNode *cur_node; for (cur_node = events->children; cur_node != NULL; cur_node = cur_node->next) { // Check for a help node if (firstpass) CheckForHelp(cur_node); // First pass, only configure declarations if (firstpass && !xmlStrcmp(cur_node->name, (const xmlChar *)"declare")) { // Variable declaration im.CreateVariable(cur_node); } else if (!firstpass && !xmlStrcmp(cur_node->name, (const xmlChar *)"binding")) { // Binding im.CreateBinding(interfaceid,cur_node); } } }; void FloConfig::ConfigureBasics(xmlDocPtr doc, xmlNode *gen) { xmlNode *cur_node; for (cur_node = gen->children; cur_node != NULL; cur_node = cur_node->next) { // Check for a help node CheckForHelp(cur_node); if ((!xmlStrcmp(cur_node->name, (const xmlChar *)"var"))) { // System variable setting // Check xmlChar *n = 0; if ((n = xmlGetProp(cur_node, (const xmlChar *)"numloopids")) != 0) { num_triggers = atoi((char *) n); if (num_triggers < 1) num_triggers = 1; printf("CONFIG: Starting with %d triggers.\n",num_triggers); } else if ((n = xmlGetProp(cur_node, (const xmlChar *)"maxsnapshots")) != 0) { max_snapshots = atoi((char *) n); if (max_snapshots < 1) max_snapshots = 1; printf("CONFIG: Starting with %d max snapshots.\n",max_snapshots); } else if ((n = xmlGetProp(cur_node, (const xmlChar *)"librarypath")) != 0) { if (xmlStrchr(n,'~') == n) { // Reference to home dir char *homedir = getenv("HOME"); librarypath = new char[strlen(homedir)+xmlStrlen(n)+1]; strcpy(librarypath,homedir); strcat(librarypath,(char *) &n[1]); } else { librarypath = new char[xmlStrlen(n)+1]; strcpy(librarypath,(char *) n); } char *ptr = strrchr(librarypath,'/'); if (ptr != 0 && strlen(ptr) == 1) // Trailing backslash? // Remove *ptr = '\0'; printf("CONFIG: Library path: '%s'\n",librarypath); // Ensure library path exists if (mkdir(librarypath,S_IRWXU)) { if (errno != EEXIST) { printf("DISK: Error %d creating library folder '%s'- " "do you have write permission there?\n", errno,librarypath); } } else printf("DISK: Created new library @ '%s'\n",librarypath); } else if ((n = xmlGetProp(cur_node, (const xmlChar *)"maxplayvol")) != 0) { maxplayvol = atof((char *) n); if (maxplayvol < 0.0) maxplayvol = 1.0; printf("CONFIG: Maximum play volume set to %.2f%%.\n", maxplayvol*100); } else if ((n = xmlGetProp(cur_node, (const xmlChar *)"maxlimitergain")) != 0) { maxlimitergain = atof((char *) n); if (maxlimitergain < 0.0) maxlimitergain = 1.0; printf("CONFIG: Maximum limiter gain set to %.2f%%.\n", maxlimitergain*100); } else if ((n = xmlGetProp(cur_node, (const xmlChar *)"limiterthreshhold")) != 0) { limiterthreshhold = atof((char *) n); if (limiterthreshhold < 0.0) limiterthreshhold = 0.9; printf("CONFIG: Limiter threshhold set to %.2f%%.\n", limiterthreshhold*100); } else if ((n = xmlGetProp(cur_node, (const xmlChar *)"limiterreleaserate")) != 0) { limiterreleaserate = atof((char *) n); if (limiterreleaserate < 0.0) limiterreleaserate = 0.000020; printf("CONFIG: Limiter release rate set to %.2f%%.\n", limiterreleaserate*100); } else if ((n = xmlGetProp(cur_node, (const xmlChar *)"fadermaxdb")) != 0) { fadermaxdb = atof((char *) n); printf("CONFIG: Fader max dB set to %.2f.\n", fadermaxdb); } else if ((n = xmlGetProp(cur_node, (const xmlChar *)"loopoutformat")) != 0) { loopoutformat = GetCodecFromName((const char *) n); if (loopoutformat == UNKNOWN) printf(FWEELIN_ERROR_COLOR_ON "CONFIG: Invalid loop output format: %s\n" FWEELIN_ERROR_COLOR_OFF,n); else printf("CONFIG: Loop out format is: %s\n", GetCodecName(loopoutformat)); } else if ((n = xmlGetProp(cur_node, (const xmlChar *)"streamoutformat")) != 0) { streamoutformat = GetCodecFromName((const char *) n); if (streamoutformat == UNKNOWN) printf(FWEELIN_ERROR_COLOR_ON "CONFIG: Invalid stream output format: %s\n" FWEELIN_ERROR_COLOR_OFF,n); else printf("CONFIG: Stream out format is: %s\n", GetCodecName(streamoutformat)); } else if ((n = xmlGetProp(cur_node, (const xmlChar *)"oggquality")) != 0) { float q = atof((char *) n); if (q <= 0.0) printf(FWEELIN_ERROR_COLOR_ON "CONFIG: Invalid OGG quality: %f\n" FWEELIN_ERROR_COLOR_OFF,q); else { vorbis_encode_quality = q; printf("CONFIG: OGG Quality: %f\n",vorbis_encode_quality); } } else if ((n = xmlGetProp(cur_node, (const xmlChar *)"midiouts")) != 0) { midiouts = atoi((char *) n); if (midiouts < 1) midiouts = 1; printf("CONFIG: Config sets %d MIDI outputs.\n",midiouts); } else if ((n = xmlGetProp(cur_node, (const xmlChar *)"midisyncouts")) != 0) { msouts = ExtractArrayInt((char *)n, &msnumouts); printf("CONFIG: Set %d MIDI sync outputs: ",msnumouts); for (int i = 0; i < msnumouts; i++) { printf("%d ",msouts[i]); msouts[i]--; // Adjust so that 0 is the first output } printf("\n"); } else if ((n = xmlGetProp(cur_node, (const xmlChar *)"externalaudioinputs")) != 0) { // # of inputs extaudioins = xmlStrlen(n); if (extaudioins < 1) extaudioins = 1; int intaudioins = AudioBuffers::GetIntAudioIns(); printf("CONFIG: Starting with %d external audio input(s)\n" " and %d internal audio input(s)--\n", extaudioins,intaudioins); ms_inputs = new char[extaudioins + intaudioins]; // Assign stereo/mono and create input variables char tmp[255]; for (int i = 0; i < extaudioins + intaudioins; i++) { if (i < extaudioins) { switch (n[i]) { case 'S' : case 's' : ms_inputs[i] = 1; printf("CONFIG: Input #%d is stereo\n",i+1); break; case 'M' : case 'm' : ms_inputs[i] = 0; printf("CONFIG: Input #%d is mono\n",i+1); break; default: printf(FWEELIN_ERROR_COLOR_ON "*** INIT: WARNING: I don't understand input #%d = %c\n" "Assuming input is mono.\n" FWEELIN_ERROR_COLOR_OFF, i+1,n[i]); ms_inputs[i] = 0; break; } } else ms_inputs[i] = 0; snprintf(tmp,255,"SYSTEM_in_%d_volume",i+1); AddEmptyVariable(tmp); snprintf(tmp,255,"SYSTEM_in_%d_record",i+1); AddEmptyVariable(tmp); snprintf(tmp,255,"SYSTEM_in_%d_peak",i+1); AddEmptyVariable(tmp); } } if (n != 0) xmlFree(n); } #if USE_FLUIDSYNTH else if ((!xmlStrcmp(cur_node->name, (const xmlChar *)"fluidsynth"))) { // FluidSynth setting // Check xmlChar *n = 0; if ((n = xmlGetProp(cur_node, (const xmlChar *)"param")) != 0) { xmlChar *val = 0; if ((val = xmlGetProp(cur_node, (const xmlChar *)"setint")) != 0) { AddFluidParam(new FluidSynthParam_Int((char *)n, atoi((char *)val))); } else if ((val = xmlGetProp(cur_node, (const xmlChar *)"setnum")) != 0) { AddFluidParam(new FluidSynthParam_Num((char *)n, atof((char *)val))); } else if ((val = xmlGetProp(cur_node, (const xmlChar *)"setstr")) != 0) { AddFluidParam(new FluidSynthParam_Str((char *)n,(char *)val)); } if (val != 0) xmlFree(val); } else if ((n = xmlGetProp(cur_node, (const xmlChar *)"soundfont")) != 0) { AddFluidFont(new FluidSynthSoundFont((char *)n)); } else if ((n = xmlGetProp(cur_node, (const xmlChar *)"interpolation")) != 0) { fsinterp = atoi((char *)n); } else if ((n = xmlGetProp(cur_node, (const xmlChar *)"tuning")) != 0) { fstuning = atof((char *)n); } else if ((n = xmlGetProp(cur_node, (const xmlChar *)"channel")) != 0) { fschannel = atoi((char *)n); } else if ((n = xmlGetProp(cur_node, (const xmlChar *)"stereo")) != 0) { fsstereo = atoi((char *)n); if (ms_inputs != 0) { ms_inputs[extaudioins] = fsstereo; printf("CONFIG: FluidSynth running in %s\n", (fsstereo ? "stereo" : "mono")); } else printf(FWEELIN_ERROR_COLOR_ON "*** INIT: WARNING: FluidSynth stereo can't be set before " "externalaudioinputs is set- check config!\n" FWEELIN_ERROR_COLOR_OFF); } if (n != 0) xmlFree(n); } #endif } // Print whether master is stereo printf("CONFIG: FreeWheeling is running in %s", (IsStereoMaster() ? "stereo.\n * Please be aware, this " "significantly increases memory usage. *\n" : "mono.\n")); }; char FloConfig::IsStereoMaster() { // Check inputs int numins = extaudioins + AudioBuffers::GetIntAudioIns(); for (int i = 0; i < numins; i++) if (ms_inputs[i]) return 1; // Yep, one input is stereo, so we have to run in stereo // No stereo inputs, run in mono! return 0; }; // Extracts an array of floats (delimited by character delim_char) // from the given string- returns size of array in 'size' float *FloConfig::ExtractArray(char *n, int *size, char delim_char) { char buf[255]; strncpy(buf,n,254); buf[254] = '\0'; char *delim = buf; *size = 0; while (delim != 0) { (*size)++; delim = strchr(delim+1,delim_char); } if (*size == 0) return 0; float *array = new float[*size]; delim = buf; int i = 0; while (i < *size) { char *nd = strchr(delim,delim_char); if (nd != 0) { *nd = '\0'; nd++; } //printf("%d: %s\n",i,delim); array[i++] = atof(delim); delim = nd; } return array; }; int *FloConfig::ExtractArrayInt(char *n, int *size, char delim_char) { char buf[255]; strncpy(buf,n,254); buf[254] = '\0'; char *delim = buf; *size = 0; while (delim != 0) { (*size)++; delim = strchr(delim+1,delim_char); } if (*size == 0) return 0; int *array = new int[*size]; delim = buf; int i = 0; while (i < *size) { char *nd = strchr(delim,delim_char); if (nd != 0) { *nd = '\0'; nd++; } //printf("%d: %s\n",i,delim); array[i++] = atoi(delim); delim = nd; } return array; }; void FloConfig::ConfigureElement(xmlDocPtr doc, xmlNode *elemn, FloLayoutElement *elem, float xscale, float yscale) { xmlNode *cur_node; for (cur_node = elemn->children; cur_node != NULL; cur_node = cur_node->next) { // Check for a help node CheckForHelp(cur_node); if ((!xmlStrcmp(cur_node->name, (const xmlChar *)"box"))) { // Box declaration FloLayoutBox *nw = new FloLayoutBox(); printf(" Box: "); xmlChar *n = xmlGetProp(cur_node, (const xmlChar *)"outline"); if (n != 0) { nw->lineleft = (strchr((char *)n,'L') ? 1 : 0); nw->linetop = (strchr((char *)n,'T') ? 1 : 0); nw->lineright = (strchr((char *)n,'R') ? 1 : 0); nw->linebottom = (strchr((char *)n,'B') ? 1 : 0); printf("outline (L%d,T%d,R%d,B%d) ",nw->lineleft,nw->linetop, nw->lineright,nw->linebottom); xmlFree(n); } // Position n = xmlGetProp(cur_node, (const xmlChar *)"pos"); if (n != 0) { int cs; float *coord = ExtractArray((char *)n, &cs); if (cs >= 4) { nw->left = (int) round(elem->bx + XCvtf(xscale*coord[0])); nw->top = (int) round(elem->by + YCvtf(yscale*coord[1])); nw->right = (int) round(elem->bx + XCvtf(xscale*coord[2])); nw->bottom = (int) round(elem->by + YCvtf(yscale*coord[3])); printf("dim (%d,%d)-(%d,%d) ",nw->left,nw->top, nw->right,nw->bottom); delete[] coord; } xmlFree(n); } // Link in the new geometry if (elem->geo == 0) elem->geo = nw; else { FloLayoutElementGeometry *cur = elem->geo; while (cur->next != 0) cur = cur->next; cur->next = nw; } printf("\n"); } } }; void FloConfig::ConfigureLayout(xmlDocPtr doc, xmlNode *layn, FloLayout *lay, float xscale, float yscale) { xmlNode *cur_node; for (cur_node = layn->children; cur_node != NULL; cur_node = cur_node->next) { // Check for a help node CheckForHelp(cur_node); if ((!xmlStrcmp(cur_node->name, (const xmlChar *)"element"))) { // Element declaration FloLayoutElement *nw = new FloLayoutElement(); printf(" Element: "); xmlChar *n = xmlGetProp(cur_node, (const xmlChar *)"id"); if (n != 0) { nw->id = atoi((char *)n); printf("#%d ",nw->id); xmlFree(n); } n = xmlGetProp(cur_node, (const xmlChar *)"name"); if (n != 0) { nw->name = new char[xmlStrlen(n)+1]; strcpy(nw->name,(char*)n); printf("'%s' ",nw->name); xmlFree(n); } // Base n = xmlGetProp(cur_node, (const xmlChar *)"base"); if (n != 0) { int cs; float *coord = ExtractArray((char *)n, &cs); if (cs) { nw->bx = lay->xpos + XCvtf(xscale*coord[0]); nw->by = lay->ypos + YCvtf(yscale*coord[1]); printf("@ (%d,%d) ",(int) nw->bx,(int) nw->by); delete[] coord; } xmlFree(n); } // Name position n = xmlGetProp(cur_node, (const xmlChar *)"namepos"); if (n != 0) { int cs; float *coord = ExtractArray((char *)n, &cs); if (cs) { nw->nxpos = (int) round(nw->bx + XCvtf(xscale*coord[0])); nw->nypos = (int) round(nw->by + YCvtf(yscale*coord[1])); printf("Name@ (%d,%d) ",nw->nxpos,nw->nypos); delete[] coord; } xmlFree(n); } // Loop position n = xmlGetProp(cur_node, (const xmlChar *)"looppos"); if (n != 0) { int cs; float *coord = ExtractArray((char *)n, &cs); if (cs) { nw->loopx = (int) round(nw->bx + XCvtf(xscale*coord[0])); nw->loopy = (int) round(nw->by + YCvtf(yscale*coord[1])); printf("looppos (%d,%d) ",nw->loopx,nw->loopy); delete[] coord; } xmlFree(n); } n = xmlGetProp(cur_node, (const xmlChar *)"loopsize"); if (n != 0) { nw->loopsize = MIN(XCvt(MIN(xscale,yscale)*atof((char *)n)), YCvt(MIN(xscale,yscale)*atof((char *)n))); printf("loopsize %d ",nw->loopsize); xmlFree(n); } // Link in the new element if (lay->elems == 0) lay->elems = nw; else { FloLayoutElement *cur = lay->elems; while (cur->next != 0) cur = cur->next; cur->next = nw; } printf("\n"); // Now populate the element with geometries.. ConfigureElement(doc,cur_node,nw,xscale,yscale); } } }; void FloConfig::ConfigurePatchBanks(xmlNode *pb, PatchBrowser *br) { // The patch browser can contain a number of patchbanks. // Configure them. for (xmlNode *cur_node = pb->children; cur_node != NULL; cur_node = cur_node->next) { if ((!xmlStrcmp(cur_node->name, (const xmlChar *)"patchbank"))) { // Get MIDI port int pb_mport = 0; xmlChar *n = 0; if ((n = xmlGetProp(cur_node, (const xmlChar *)"midiport")) != 0) { pb_mport = atoi((char *) n); xmlFree(n); } // Patchbank tag // Get MIDI port int pb_tag = -1; if ((n = xmlGetProp(cur_node, (const xmlChar *)"tag")) != 0) { pb_tag = atoi((char *) n); xmlFree(n); } // Separate channels into distinct patchbanks? char sepchan = 0; if ((n = xmlGetProp(cur_node, (const xmlChar *)"separatechannels")) != 0) { sepchan = atoi((char *) n); xmlFree(n); } // Suppress bank/program changes when changing patches? // (ie only change channel) char suppresschg = 0; if ((n = xmlGetProp(cur_node, (const xmlChar *)"suppressprogramchanges")) != 0) { suppresschg = atoi((char *) n); xmlFree(n); } xmlChar *pb_patches = xmlGetProp(cur_node, (const xmlChar *)"patches"); if (pb_patches != 0) { // PatchBank file defined xmlDocPtr pb_doc; // Try both ~/.fweelin and fweelin data dir char *buf = PrepareLoadConfigFile((char *) pb_patches,0); // Load and parse pb_doc = (buf == 0 ? 0 : xmlParseFile(buf)); if (pb_doc == 0) printf(FWEELIN_ERROR_COLOR_ON "\n*** INIT: ERROR: Problem parsing patches file '%s'.\n" FWEELIN_ERROR_COLOR_OFF, pb_patches); else { xmlNode *pb_root = xmlDocGetRootElement(pb_doc); if (!pb_root || !pb_root->name || xmlStrcmp(pb_root->name,(const xmlChar *) "patchlist")) printf(FWEELIN_ERROR_COLOR_ON "\n*** INIT: ERROR: Patches file '%s' invalid format.\n" FWEELIN_ERROR_COLOR_OFF, pb_patches); else { int p_curchan = -1, pcnt = 0; for (xmlNode *pb_curpatch = pb_root->children; pb_curpatch != NULL; pb_curpatch = pb_curpatch->next) { if ((!xmlStrcmp(pb_curpatch->name, (const xmlChar *)"combi"))) { // Combi (multi-zone multi-channel) // First, count zones int numzones = 0; for (xmlNode *curzone = pb_curpatch->children; curzone != NULL; curzone = curzone->next) if ((!xmlStrcmp(curzone->name, (const xmlChar *)"zone"))) numzones++; printf("\nCOMBI: Numzones: %d\n",numzones); // Setup combi xmlChar *cname = 0; cname = xmlGetProp(pb_curpatch,(const xmlChar *)"name"); if (pcnt == 0) { // First patch // Create new PatchBank br->PB_Add(new PatchBank(pb_mport,pb_tag,suppresschg)); } PatchItem *pi = new PatchItem(pcnt++,-1,-1,-1,(char *) cname); pi->SetupZones(numzones); br->AddItem(pi); if (pcnt % PatchBrowser::DIV_SPACING == 0) br->AddItem(new BrowserDivision()); if (cname != 0) xmlFree(cname); // For each zone int curzone_idx = 0; for (xmlNode *curzone = pb_curpatch->children; curzone != NULL; curzone = curzone->next) { if ((!xmlStrcmp(curzone->name, (const xmlChar *)"zone"))) { int kr_lo = 0, kr_hi = 0; if ((n = xmlGetProp(curzone, (const xmlChar *)"keyrange")) != 0) { int krs; float *kr = ExtractArray((char *)n, &krs, '>'); if (krs == 2) { kr_lo = (int) kr[0]; kr_hi = (int) kr[1]; } delete[] kr; xmlFree(n); } char mport_r = 0; int mport = pb_mport; xmlChar *n = 0; if ((n = xmlGetProp(curzone, (const xmlChar *)"midiport")) != 0) { mport_r = 1; mport = atoi((char *) n); xmlFree(n); } int bank = -1; if ((n = xmlGetProp(curzone, (const xmlChar *)"bank")) != 0) { bank = atoi((char *) n); xmlFree(n); } int prog = -1; if ((n = xmlGetProp(curzone, (const xmlChar *)"program")) != 0) { prog = atoi((char *) n); xmlFree(n); } int chan = 0; if ((n = xmlGetProp(curzone, (const xmlChar *)"channel")) != 0) { chan = atoi((char *) n); xmlFree(n); } printf(" ZONE [%d>%d]: midiport[%s]:%d " "bank: %d prog: %d chan: %d\n", kr_lo,kr_hi, (mport_r ? "REDIRECT" : "DEFAULT"),mport, bank,prog,chan); pi->GetZone(curzone_idx)->SetupZone(kr_lo,kr_hi, mport_r,mport, bank,prog,chan); curzone_idx++; } } } else if ((!xmlStrcmp(pb_curpatch->name, (const xmlChar *)"patch"))) { // Single channel patch int chan = 0; if ((n = xmlGetProp(pb_curpatch, (const xmlChar *)"channel")) != 0) { chan = atoi((char *) n); xmlFree(n); } int bank = 0; if ((n = xmlGetProp(pb_curpatch, (const xmlChar *)"bank")) != 0) { bank = atoi((char *) n); xmlFree(n); } int prog = 0; if ((n = xmlGetProp(pb_curpatch, (const xmlChar *)"program")) != 0) { prog = atoi((char *) n); xmlFree(n); } xmlChar *pname = 0; if ((pname = xmlGetProp(pb_curpatch, (const xmlChar *)"name")) != 0) { if ((sepchan && chan != p_curchan) || (!sepchan && pcnt == 0)) { // Separate channels (patchbank for each channel)-- // or first patch // Create new PatchBank br->PB_Add(new PatchBank(pb_mport,pb_tag,suppresschg)); p_curchan = chan; pcnt = 0; //printf("new patchbank: mport: %d chan: %d\n", // pb_mport,chan); } br->AddItem(new PatchItem(pcnt++,bank,prog,chan, (char *) pname)); //printf("bank: %d prog: %d patch: '%s'\n",bank,prog, // (char *) pname); if (pcnt % PatchBrowser::DIV_SPACING == 0) br->AddItem(new BrowserDivision()); xmlFree(pname); } } } } xmlFreeDoc(pb_doc); } xmlFree(pb_patches); } } } }; void FloConfig::ConfigureGraphics(xmlDocPtr doc, xmlNode *vid, int interfaceid) { xmlNode *cur_node; for (cur_node = vid->children; cur_node != NULL; cur_node = cur_node->next) { // Check for a help node CheckForHelp(cur_node); if ((!xmlStrcmp(cur_node->name, (const xmlChar *)"var"))) { // System variable setting // Check xmlChar *n = 0; if ((n = xmlGetProp(cur_node, (const xmlChar *)"resolution")) != 0) { // Video resolution int cs; float *coord = ExtractArray((char *)n, &cs); if (cs) { vsize[0] = (int)coord[0]; vsize[1] = (int)coord[1]; scope_sample_len = vsize[0]; // Scope goes across screen delete[] coord; } printf("CONFIG: Starting with (%d,%d) resolution.\n",vsize[0], vsize[1]); xmlFree(n); } n = xmlGetProp(cur_node, (const xmlChar *)"videodelay"); if (n != 0) { vdelay = atoi((char *)n); printf("CONFIG: Video delay: %d ms\n",vdelay); vdelay *= 1000; // usecs xmlFree(n); } } else if ((!xmlStrcmp(cur_node->name, (const xmlChar *)"font"))) { // Font loading FloFont *nw = new FloFont(); printf("CONFIG: New onscreen font: "); xmlChar *n = xmlGetProp(cur_node, (const xmlChar *)"name"); if (n != 0) { nw->name = new char[xmlStrlen(n)+1]; strcpy(nw->name,(char*)n); printf("%s: ",nw->name); xmlFree(n); } n = xmlGetProp(cur_node, (const xmlChar *)"file"); if (n != 0) { nw->filename = new char[xmlStrlen(n)+1]; strcpy(nw->filename,(char*)n); printf(nw->filename); xmlFree(n); } n = xmlGetProp(cur_node, (const xmlChar *)"size"); if (n != 0) { nw->size = atoi((char *)n); printf(" (%d pt)",nw->size); xmlFree(n); } // Link in the new font if (fonts == 0) fonts = nw; else { FloFont *cur = fonts; while (cur->next != 0) cur = cur->next; cur->next = nw; } printf("\n"); } else if ((!xmlStrcmp(cur_node->name, (const xmlChar *)"display"))) { // Onscreen display declaration FloDisplay *nw = 0; printf("CONFIG: New onscreen display: "); int iid = interfaceid; xmlChar *n = xmlGetProp(cur_node, (const xmlChar *)"interfaceid"); if (n != 0) { iid = atoi((char *) n); printf("(interface ID: %d) ",iid); xmlFree(n); } // Type of display? n = xmlGetProp(cur_node, (const xmlChar *)"type"); if (n != 0) { if (!xmlStrcmp(n, (const xmlChar *)"text")) { printf("(text) "); nw = new FloDisplayText(iid); } else if (!xmlStrcmp(n, (const xmlChar *)"browser")) { printf("(browser) "); // Browser type BrowserItemType btype = (BrowserItemType) 0; xmlChar *nn = xmlGetProp(cur_node, (const xmlChar *)"browsetype"); if (nn != 0) { ParsedExpression *tmp = im.ParseExpression((char *) nn, 0); btype = (BrowserItemType) (int) tmp->Evaluate(0); printf("type: %s ",Browser::GetTypeName(btype)); delete tmp; xmlFree(nn); } // Expanded browser view char xpand = 0; int xpand_x1 = 0, xpand_x2 = 0, xpand_y1 = 0, xpand_y2 = 0; float xpand_delay = 1.0; nn = xmlGetProp(cur_node, (const xmlChar *)"xpand"); if (nn != 0) { xpand = atoi((char *) nn); printf("xpand: %d ",xpand); xmlFree(nn); } nn = xmlGetProp(cur_node, (const xmlChar *)"xdelay"); if (nn != 0) { xpand_delay = atof((char *) nn); printf("xdelay: %f ",xpand_delay); xmlFree(nn); } nn = xmlGetProp(cur_node, (const xmlChar *)"xbox"); if (nn != 0) { int cs; float *coord = ExtractArray((char *)nn, &cs); if (cs >= 4) { xpand_x1 = (int) round(XCvtf(coord[0])); xpand_y1 = (int) round(YCvtf(coord[1])); xpand_x2 = (int) round(XCvtf(coord[2])); xpand_y2 = (int) round(YCvtf(coord[3])); printf("xpand_box: (%d,%d)-(%d,%d) ",xpand_x1,xpand_y1, xpand_x2,xpand_y2); delete[] coord; } xmlFree(nn); } // Check for another browser with the same type-- not allowed FloDisplay *checkd = displays; char dupe = 0; while (!dupe && checkd != 0) { if (checkd->GetFloDisplayType() == FD_Browser && ((Browser *) checkd)->GetType() == btype) dupe = 1; checkd = checkd->next; } if (!dupe) { switch (btype) { case B_Loop_Tray : { int loopsize = 0; nn = xmlGetProp(cur_node, (const xmlChar *)"loopsize"); if (nn != 0) { loopsize = (int) round(XCvtf(atof((char *) nn))); xmlFree(nn); } nw = new LoopTray(iid, btype,xpand,xpand_x1,xpand_y1, xpand_x2,xpand_y2,loopsize); } break; case B_Scene_Tray : { } break; case B_Patch : { nw = new PatchBrowser(iid, btype,xpand,xpand_x1,xpand_y1, xpand_x2,xpand_y2,xpand_delay); ConfigurePatchBanks(cur_node,(PatchBrowser *) nw); } break; default : { // All other kinds of browsers nw = new Browser(iid, btype,xpand,xpand_x1,xpand_y1, xpand_x2,xpand_y2,xpand_delay); } break; } } else { printf(FWEELIN_ERROR_COLOR_ON "\n*** INIT: WARNING: Duplicate browser of type: '%s'\n" FWEELIN_ERROR_COLOR_OFF, Browser::GetTypeName(btype)); nw = 0; } } else if (!xmlStrcmp(n, (const xmlChar *)"switch")) { printf("(switch) "); nw = new FloDisplaySwitch(iid); } else if (!xmlStrcmp(n, (const xmlChar *)"circle-switch")) { printf("(circle-switch) "); nw = new FloDisplayCircleSwitch(iid); // Circle radii xmlChar *nn = xmlGetProp(cur_node, (const xmlChar *)"size1"); if (nn != 0) { float sz = atof((char *)nn); ((FloDisplayCircleSwitch *) nw)->rad1 = XCvt(sz); printf("size1 %d ",((FloDisplayCircleSwitch *) nw)->rad1); xmlFree(nn); } nn = xmlGetProp(cur_node, (const xmlChar *)"size0"); if (nn != 0) { float sz = atof((char *)nn); ((FloDisplayCircleSwitch *) nw)->rad0 = XCvt(sz); printf("size0 %d ",((FloDisplayCircleSwitch *) nw)->rad0); xmlFree(nn); } // Flashing? nn = xmlGetProp(cur_node, (const xmlChar *)"flash"); if (nn != 0) { ((FloDisplayCircleSwitch *) nw)->flash = atoi((char *)nn); if (((FloDisplayCircleSwitch *) nw)->flash) printf("(flashing) "); xmlFree(nn); } } else if (!xmlStrcmp(n, (const xmlChar *)"text-switch")) { printf("(text-switch) "); nw = new FloDisplayTextSwitch(iid); // Text lines xmlChar *nn = xmlGetProp(cur_node, (const xmlChar *)"text1"); if (nn != 0) { char *text1 = new char[xmlStrlen(nn)+1]; strcpy(text1,(char*)nn); ((FloDisplayTextSwitch *) nw)->text1 = text1; printf("'%s' ",text1); xmlFree(nn); } nn = xmlGetProp(cur_node, (const xmlChar *)"text0"); if (nn != 0) { char *text0 = new char[xmlStrlen(nn)+1]; strcpy(text0,(char*)nn); ((FloDisplayTextSwitch *) nw)->text0 = text0; printf("'%s' ",text0); xmlFree(nn); } } else if (!xmlStrcmp(n, (const xmlChar *)"snapshots")) { printf("(snapshots) "); nw = new FloDisplaySnapshots(GetInputMatrix()->app,iid); FloDisplaySnapshots *nws = (FloDisplaySnapshots *) nw; nws->margin = XCvt(0.005); // Snapshots display size xmlChar *nn = xmlGetProp(cur_node, (const xmlChar *)"size"); if (nn != 0) { int cs; float *coord = ExtractArray((char *)nn, &cs); if (cs) { nws->sx = XCvt(coord[0]); nws->sy = XCvt(coord[1]); printf("size (%d,%d) ",nws->sx,nws->sy); } delete[] coord; xmlFree(nn); } } else if (!xmlStrcmp(n, (const xmlChar *)"bar") || !xmlStrcmp(n, (const xmlChar *)"bar-switch")) { // Bar or bar-switch? char sw = 0; FloDisplayBar *nwb; if (!xmlStrcmp(n, (const xmlChar *)"bar-switch")) { sw = 1; printf("(bar-switch) "); nwb = new FloDisplayBarSwitch(iid); } else { printf("(bar) "); nwb = new FloDisplayBar(iid); } nw = nwb; // Bar orientation xmlChar *nn = xmlGetProp(cur_node, (const xmlChar *)"orientation"); if (nn != 0) { if (!xmlStrcmp(nn,(const xmlChar *)"horizontal")) { nwb->orient = O_Horizontal; printf("(horizontal) "); } else if (!xmlStrcmp(nn,(const xmlChar *)"vertical")) { nwb->orient = O_Vertical; printf("(vertical) "); } else printf("(invalid bar orient: '%s') ",nn); xmlFree(nn); } // Bar scale nn = xmlGetProp(cur_node, (const xmlChar *)"barscale"); if (nn != 0) { nwb->barscale = atof((char *)nn); xmlFree(nn); } nwb->barscale = (nwb->orient == O_Horizontal ? XCvtf(nwb->barscale) : YCvtf(nwb->barscale)); printf("barscale %.2f ",nwb->barscale); // Bar thickness nn = xmlGetProp(cur_node, (const xmlChar *)"thickness"); if (nn != 0) { float bt = atof((char *)nn); nwb->thickness = (nwb->orient == O_Horizontal ? YCvt(bt) : XCvt(bt)); printf("thickness %d ",nwb->thickness); xmlFree(nn); } // dB scale? nn = xmlGetProp(cur_node, (const xmlChar *)"dbscale"); if (nn != 0) { nwb->dbscale = atoi((char *)nn); printf("(%s) ",(nwb->dbscale ? "dB scale" : "linear scale")); xmlFree(nn); } // calibration marks? nn = xmlGetProp(cur_node, (const xmlChar *)"marks"); if (nn != 0) { nwb->marks = atoi((char *)nn); printf("%s",(nwb->marks ? "(marks) " : "")); xmlFree(nn); } if (nwb->dbscale) nwb->maxdb = fadermaxdb; if (sw) { // Color nn = xmlGetProp(cur_node, (const xmlChar *)"color"); if (nn != 0) { ((FloDisplayBarSwitch *) nwb)->color = atoi((char *) nn); printf(" color %d ",((FloDisplayBarSwitch *) nwb)->color); xmlFree(nn); } // Calibration mark nn = xmlGetProp(cur_node, (const xmlChar *)"calibrate"); if (nn != 0) { ((FloDisplayBarSwitch *) nwb)->calibrate = 1; ((FloDisplayBarSwitch *) nwb)->cval = atof((char *) nn); printf(" calibrate %.2f ",((FloDisplayBarSwitch *) nwb)->cval); xmlFree(nn); } // Expression to display nn = xmlGetProp(cur_node, (const xmlChar *)"switchvar"); if (nn != 0) { printf(" switch-expression: "); ((FloDisplayBarSwitch *) nwb)->switchexp = im.ParseExpression((char *) nn, 0); ((FloDisplayBarSwitch *) nwb)->switchexp->Print(); printf(" "); xmlFree(nn); } } } else { printf(FWEELIN_ERROR_COLOR_ON "(invalid display type: '%s')\n" FWEELIN_ERROR_COLOR_OFF,n); } xmlFree(n); } if (nw != 0) { // Title n = xmlGetProp(cur_node, (const xmlChar *)"title"); if (n != 0) { nw->title = new char[xmlStrlen(n)+1]; strcpy(nw->title,(char*)n); printf("'%s' ",nw->title); xmlFree(n); } // Position n = xmlGetProp(cur_node, (const xmlChar *)"pos"); if (n != 0) { int cs; float *coord = ExtractArray((char *)n, &cs); if (cs) { nw->xpos = XCvt(coord[0]); nw->ypos = YCvt(coord[1]); printf("@ (%d,%d) ",nw->xpos,nw->ypos); delete[] coord; } xmlFree(n); } // Show? n = xmlGetProp(cur_node, (const xmlChar *)"show"); if (n != 0) { nw->show = atoi((char *)n); if (nw->show) printf("(show) "); xmlFree(n); } // Font for display n = xmlGetProp(cur_node, (const xmlChar *)"font"); if (n != 0) { nw->font = GetFont((char *) n); if (nw->font != 0) printf("(font: %s) ",nw->font->name); else printf("(ERR: no font named '%s'!) ",n); xmlFree(n); } // ID n = xmlGetProp(cur_node, (const xmlChar *)"id"); if (n != 0) { ParsedExpression *tmp = im.ParseExpression((char *) n, 0); nw->id = (int) tmp->Evaluate(0); printf("(id: %d) ",nw->id); delete tmp; xmlFree(n); } // Expression to display n = xmlGetProp(cur_node, (const xmlChar *)"var"); if (n != 0) { printf("\n expression: "); nw->exp = im.ParseExpression((char *) n, 0); nw->exp->Print(); xmlFree(n); } // Link in the new display if (displays == 0) displays = nw; else { FloDisplay *cur = displays; while (cur->next != 0) cur = cur->next; cur->next = nw; } printf("\n"); } } else if ((!xmlStrcmp(cur_node->name, (const xmlChar *)"layout"))) { // Layout declaration FloLayout *nw = new FloLayout(); printf("CONFIG: New onscreen loop layout: "); // Set interface ID based on // what interface the layout is declared in nw->iid = interfaceid; xmlChar *n = xmlGetProp(cur_node, (const xmlChar *)"id"); if (n != 0) { nw->id = atoi((char *)n); printf("#%d ",nw->id); xmlFree(n); } n = xmlGetProp(cur_node, (const xmlChar *)"show"); if (n != 0) { nw->show = atoi((char *)n); if (nw->show) printf("(show) "); xmlFree(n); } n = xmlGetProp(cur_node, (const xmlChar *)"label"); if (n != 0) { nw->showlabel = atoi((char *)n); if (nw->showlabel) printf("(label) "); xmlFree(n); } n = xmlGetProp(cur_node, (const xmlChar *)"elabel"); if (n != 0) { nw->showelabel = atoi((char *)n); if (nw->showelabel) printf("(label elements) "); xmlFree(n); } n = xmlGetProp(cur_node, (const xmlChar *)"name"); if (n != 0) { nw->name = new char[xmlStrlen(n)+1]; strcpy(nw->name,(char*)n);; printf("'%s' ",nw->name); xmlFree(n); } float xscale = 1.0, yscale = 1.0; n = xmlGetProp(cur_node, (const xmlChar *)"scale"); if (n != 0) { int cs; float *coord = ExtractArray((char *)n, &cs); if (cs) { xscale = coord[0]; yscale = coord[1]; printf("scale (%.2f,%.2f) ",xscale,yscale); delete[] coord; } xmlFree(n); } // Position n = xmlGetProp(cur_node, (const xmlChar *)"pos"); if (n != 0) { int cs; float *coord = ExtractArray((char *)n, &cs); if (cs) { nw->xpos = XCvt(coord[0]); nw->ypos = YCvt(coord[1]); printf("@ (%d,%d) ",nw->xpos,nw->ypos); delete[] coord; } xmlFree(n); } // Name position n = xmlGetProp(cur_node, (const xmlChar *)"namepos"); if (n != 0) { int cs; float *coord = ExtractArray((char *)n, &cs); if (cs) { nw->nxpos = nw->xpos + XCvt(coord[0]); nw->nypos = nw->ypos + YCvt(coord[1]); printf("Name@ (%d,%d) ",nw->nxpos,nw->nypos); delete[] coord; } xmlFree(n); } // Link in the new layout if (layouts == 0) layouts = nw; else { FloLayout *cur = layouts; while (cur->next != 0) cur = cur->next; cur->next = nw; } printf("\n"); // Now populate the layout with elements.. ConfigureLayout(doc,cur_node,nw,xscale,yscale); } } }; // Is node 'n' a comment with help information? If so, add to our // internal help list void FloConfig::CheckForHelp(xmlNode *n) { if (n->type == XML_COMMENT_NODE) { char *str = (char *) n->content; while (*str == ' ') str++; // Advance past beginning whitespace if (!strncmp(str,FWEELIN_CONFIG_HELP_TOKEN, strlen(FWEELIN_CONFIG_HELP_TOKEN))) { // This token is a comment with help prefix-- store str += strlen(FWEELIN_CONFIG_HELP_TOKEN); char *s = new char[strlen(str)+1]; strcpy(s,str); // Replace divider with null to split string into two parts (columns) // This allows keys to be listed in separate help columns from their // functions char *div = strchr(s,':'); if (div != 0) { *div = '\0'; div++; } FloStringList *nw = new FloStringList(s,div); printf(" add user help: %s:%s\n",s,div); // Link in the new string if (help == 0) help = nw; else { FloStringList *cur = help; while (cur->next != 0) cur = cur->next; cur->next = nw; } } } }; // Creates an empty variable based on the given name. The config file // can then refer to the variable UserVariable *FloConfig::AddEmptyVariable(char *name) { UserVariable *nw = new UserVariable(); if (name != 0) { nw->name = new char[strlen(name)+1]; strcpy(nw->name,name); } // Insert into variable list nw->next = im.vars; im.vars = nw; return nw; }; // Makes the given variable into a system variable by linking it to // the pointer void FloConfig::LinkSystemVariable(char *name, CoreDataType type, char *ptr) { UserVariable *cur = im.vars; while (cur != 0) { if (cur->name != 0) { if (!strcmp(cur->name,name)) { // Variable found!- Link it with a system variable printf("CONFIG: Link system variable: %s -> %p\n",name,ptr); cur->type = type; cur->value = ptr; } } cur = cur->next; } }; FloConfig::~FloConfig() { // Erase displays { FloDisplay *cur = displays; while (cur != 0) { FloDisplay *tmp = cur->next; delete cur; cur = tmp; } } // Erase fonts { FloFont *cur = fonts; while (cur != 0) { FloFont *tmp = cur->next; delete cur; cur = tmp; } } // Erase layouts { FloLayout *cur = layouts; while (cur != 0) { FloLayout *tmp = cur->next; delete cur; cur = tmp; } } // Erase help { FloStringList *cur = help; while (cur != 0) { FloStringList *tmp = cur->next; delete cur; cur = tmp; } } #if USE_FLUIDSYNTH // Erase FluidSynth config { FluidSynthParam *cur = fsparam; while (cur != 0) { FluidSynthParam *tmp = cur->next; delete cur; cur = tmp; } } { FluidSynthSoundFont *cur = fsfont; while (cur != 0) { FluidSynthSoundFont *tmp = cur->next; delete cur; cur = tmp; } } #endif if (ms_inputs != 0) delete[] ms_inputs; if (librarypath != 0) delete librarypath; }; FloConfig::FloConfig(Fweelin *app) : im(app), ev_hook(0), librarypath(0), midiouts(1), msnumouts(0), msouts(0), ms_inputs(0), extaudioins(0), maxplayvol(5.0), maxlimitergain(1.0), limiterthreshhold(0.9), limiterreleaserate(0.000020), loopoutformat(VORBIS), streamoutformat(VORBIS), vorbis_encode_quality(0.5), num_triggers(1024), vdelay(50000), showdebug(0), layouts(0), fonts(0), displays(0), help(0), #if USE_FLUIDSYNTH fsinterp(4), fschannel(0), fsstereo(1), fstuning(0.0), fsparam(0), fsfont(0), #endif transpose(0), loop_peaksavgs_chunksize(500), status_report(0), numinterfaces(0), numnsinterfaces(0), max_snapshots(20) { vsize[0] = 640; vsize[1] = 480; scope_sample_len = vsize[0]; // Scope goes across screen }; void FloConfig::ConfigureInterfaces (xmlDocPtr doc, xmlNode *ifs, char firstpass) { int cur_iid = 1, // First interface has ID 1 (0 is main config) // First non-switchable interface has this ID cur_nsiid = NS_INTERFACE_START_ID; for (xmlNode *cur_node = ifs->children; cur_node != NULL; cur_node = cur_node->next) { if (!xmlStrcmp(cur_node->name, (const xmlChar *)"interface")) { char switchable = 1; xmlChar *n = xmlGetProp(cur_node, (const xmlChar *)"switchable"); if (n != 0) { switchable = atoi((char *) n); xmlFree(n); } n = xmlGetProp(cur_node, (const xmlChar *)"setup"); if (n != 0) { printf("INIT: Load interface '%s' [%s]\n",(char *) n, (firstpass ? "first pass" : "second pass")); char *buf = PrepareLoadConfigFile((char *) n,0); xmlSubstituteEntitiesDefault(1); xmlDocPtr doc = (buf == 0 ? 0 : xmlParseFile(buf)); if (doc == 0) printf(FWEELIN_ERROR_COLOR_ON "INIT: Error parsing config file '%s'.\n" FWEELIN_ERROR_COLOR_OFF,(char *) n); else { xmlNode *root = xmlDocGetRootElement(doc); if (!root || !root->name || xmlStrcmp(root->name,(const xmlChar *) "interface") ) printf(FWEELIN_ERROR_COLOR_ON "INIT: Interface config file '%s' format invalid-- " "should start with 'interface' tag\n" FWEELIN_ERROR_COLOR_OFF,(char *) n); else { if (switchable) ConfigureRoot(doc,root,cur_iid++,firstpass); else ConfigureRoot(doc,root,cur_nsiid++,firstpass); } xmlFreeDoc(doc); } xmlFree(n); } } } numinterfaces = cur_iid-1; numnsinterfaces = cur_nsiid-NS_INTERFACE_START_ID; printf("CONFIG: # of interfaces: %d switchable / %d non-switchable\n", numinterfaces,numnsinterfaces); }; void FloConfig::ConfigureRoot (xmlDocPtr doc, xmlNode *root, int interfaceid, char firstpass) { for (xmlNode *cur_node = root->children; cur_node != NULL; cur_node = cur_node->next) { if (!firstpass && interfaceid == 0 && !xmlStrcmp(cur_node->name, (const xmlChar *)"basics")) { // Basics cfg ConfigureBasics(doc,cur_node); } else if (!firstpass && !xmlStrcmp(cur_node->name, (const xmlChar *)"graphics")) { // Video cfg ConfigureGraphics(doc,cur_node,interfaceid); } else if (/* interfaceid != 0 && */ !xmlStrcmp(cur_node->name, (const xmlChar *)"bindings")) { // Events if (interfaceid == 0) { // All at once in main config ConfigureEventBindings(doc,cur_node,interfaceid,1); ConfigureEventBindings(doc,cur_node,interfaceid,0); } else ConfigureEventBindings(doc,cur_node,interfaceid,firstpass); } else if (!firstpass && interfaceid == 0 && !xmlStrcmp(cur_node->name, (const xmlChar *)"interfaces")) { // Interfaces- 2 passes- first load variables, then rest ConfigureInterfaces(doc,cur_node,1); ConfigureInterfaces(doc,cur_node,0); } } }; // Parse configuration file, setup config void FloConfig::Parse() { #ifdef __MACOSX__ // On Mac OS X, Set FWEELIN_DATADIR to bundle resource folder CFURLRef url = CFBundleCopyResourcesDirectoryURL(CFBundleGetMainBundle()); CFURLGetFileSystemRepresentation(url, true, (UInt8 *)FWEELIN_DATADIR, MAXPATHLEN); CFRelease(url); #endif // Setup event type table Event::SetupEventTypeTable(im.app->getMMG()); // Look for config file char *buf = PrepareLoadConfigFile(FWEELIN_CONFIG_FILE,1); xmlSubstituteEntitiesDefault(1); xmlDocPtr doc = (buf == 0 ? 0 : xmlParseFile(buf)); if (doc == 0) { printf("INIT: Error parsing config file '%s'.\n",FWEELIN_CONFIG_FILE); exit(1); } else { xmlNode *root = NULL; /*Get the root element node */ root = xmlDocGetRootElement(doc); if (!root || !root->name || xmlStrcmp(root->name,(const xmlChar *) "freewheeling") ) printf("INIT: Config file format invalid-- should start with 'freewheeling' tag\n"); else { // Get config file version and make sure it matches our version xmlChar *ver = xmlGetProp(root, (const xmlChar *)"version"); if (ver == 0 || strcmp((char *) ver,VERSION)) { printf("INIT: ERROR: Config file version \"%s\" does not match " "FreeWheeling version \"%s\"!\n\n",ver,VERSION); // Copy over new config files from shared CopyConfigFile(FWEELIN_CONFIG_FILE,1); // Free and restart printf("CONFIG: Reading new config...\n"); xmlFreeDoc(doc); buf = PrepareLoadConfigFile(FWEELIN_CONFIG_FILE,1); doc = xmlParseFile(buf); /*Get the root element node */ root = xmlDocGetRootElement(doc); xmlChar *ver = xmlGetProp(root, (const xmlChar *)"version"); if (ver == 0 || strcmp((char *) ver,VERSION)) { printf("INIT: ERROR: Config in install dir is not up to date!\n" "Did you run 'make install'?\n"); exit(1); } } else xmlFree(ver); ConfigureRoot(doc,root); } /*free the document */ xmlFreeDoc(doc); /* *Free the global variables that may *have been allocated by the parser. */ xmlCleanupParser(); } }; void FloConfig::StartInterfaces () { for (int iid = NS_INTERFACE_START_ID; iid < NS_INTERFACE_START_ID+numnsinterfaces; iid++) { Event *proto = Event::GetEventByType(T_EV_StartInterface,1); if (proto == 0) { printf("GO: Can't get start interface event prototype!\n"); } else { StartInterfaceEvent *cpy = (StartInterfaceEvent *) proto->RTNewWithWait(); if (cpy == 0) printf("CONFIG: WARNING: Can't send event- RTNew() failed\n"); else { printf("CONFIG: Start non-switchable interface %d\n",iid); cpy->interfaceid = iid; im.app->getEMG()->BroadcastEventNow(cpy, &im); } } } for (int iid = 1; iid <= numinterfaces; iid++) { Event *proto = Event::GetEventByType(T_EV_StartInterface,1); if (proto == 0) { printf("GO: Can't get start interface event prototype!\n"); } else { StartInterfaceEvent *cpy = (StartInterfaceEvent *) proto->RTNewWithWait(); if (cpy == 0) printf("CONFIG: WARNING: Can't send event- RTNew() failed\n"); else { printf("CONFIG: Start switchable interface %d\n",iid); cpy->interfaceid = iid; im.app->getEMG()->BroadcastEventNow(cpy, &im); } } } }; fweelin-0.6/src/fweelin_config.h0000755000175000017500000007405511071520617015402 0ustar mercmerc#ifndef __FWEELIN_CONFIG_H #define __FWEELIN_CONFIG_H /* Copyright 2004-2008 Jan Pekau (JP Mercury) This file is part of Freewheeling. Freewheeling is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. Freewheeling is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Freewheeling. If not, see . */ #include #include #include #include #include "fweelin_block.h" // Number of beats per bar // (used only to compute sync, since FW does not use the concept of bars/beats internally) #define SYNC_BEATS_PER_BAR 4 // Maximum number of time pulses #define MAX_PULSES 10 // How many different sets of loop selections to remember? #define NUM_LOOP_SELECTION_SETS 10 // Keep track of the last n indexes we recorded to #define LAST_REC_COUNT 8 // Divisions are added in browsers wherever files are greater than // FWEELIN_FILE_BROWSER_DIVISION_TIME seconds apart #define FWEELIN_FILE_BROWSER_DIVISION_TIME 3600 #define FWEELIN_CONFIG_DIR ".fweelin" #define FWEELIN_CONFIG_FILE "fweelin.xml" #define FWEELIN_CONFIG_EXT ".xml" #define FWEELIN_CONFIG_HELP_TOKEN "HELP:" #define FWEELIN_OUTPUT_STREAM_NAME "live" #define FWEELIN_OUTPUT_TIMING_EXT ".wav.usx" #define FWEELIN_OUTPUT_LOOP_NAME "loop" #define FWEELIN_OUTPUT_SCENE_NAME "scene" #define FWEELIN_OUTPUT_SNAPSHOT_NAME "snapshot" #define FWEELIN_OUTPUT_LOOPSNAPSHOT_NAME "loopsnap" #define FWEELIN_OUTPUT_DATA_EXT ".xml" // Console sequence for error color #define FWEELIN_ERROR_COLOR_ON "\033[31;1m" #define FWEELIN_ERROR_COLOR_OFF "\033[0m" // Interface ID assigned to first non-switchable interface #define NS_INTERFACE_START_ID 1000 #ifdef __MACOSX__ // On Linux, FWEELIN_DATADIR refers to /usr/local/share/fweelin as set by autoconf // On Mac, we store our data in the Resource directory of the fweelin.app bundle. // This string stores the location of the Resource directory, and is set in the Obj-C stub // for the code. extern char *FWEELIN_DATADIR; // On Linux, VERSION is defined within configure.ac // For Mac OS, we set it here: #define VERSION "0.6" #endif #include "fweelin_datatypes.h" #include "fweelin_audioio.h" #include "fweelin_event.h" #include "fweelin_videoio.h" // TTF_Font decl class Event; class SDLIO; class MidiIO; class CircularMap; class PatchBrowser; // ****************** CONFIG CLASSES enum CfgTokenType { T_CFG_None, T_CFG_UserVariable, T_CFG_EventParameter, T_CFG_Static }; // Config tokens can reference user variables (UserVariable) // or input EventParameters (EventParameter) // or static values class CfgToken { public: CfgToken() : cvt(T_CFG_None), var(0) {}; CfgTokenType cvt; // Dump CfgToken to stdout void Print(); // Evaluate the current value of this token to dst // Using event ev as a reference for event parameter // If overwritetype is nonzero, sets dst to be of the appropriate data type // Otherwise, converts to existing type of dst void Evaluate(UserVariable *dst, Event *ev, char overwritetype); // Reference a user defined variable UserVariable *var; // Reference an event parameter EventParameter evparam; // Or reference a static value UserVariable val; }; // Simple algebra is possible in config file // it allows, for example, a midi fader level to be divided into an appropriate // amplitude. // This is one math operation as part of an expression class CfgMathOperation { public: CfgMathOperation() : next(0) {}; // Symbols for different math operators (div, mul, add, sub, etc..) const static char operators[]; // Number of different math operators const static int numops; char otype; // One of the above operator types CfgToken operand; CfgMathOperation *next; }; // A complete expression of config tokens modified by math operations class ParsedExpression { public: ParsedExpression() : ops(0) {}; ~ParsedExpression() { // Erase math ops CfgMathOperation *cur = ops; while (cur != 0) { CfgMathOperation *tmp = cur->next; delete cur; cur = tmp; } }; // Evaluate this expression UserVariable Evaluate(Event *input); // Returns nonzero if this expression contains only static tokens // and no user variables and no input parameters char IsStatic(); // Dump expression to stdout void Print(); CfgToken start; // Starting token of expression CfgMathOperation *ops; // Optional sequence of math ops to perform on 'val' }; // DynamicToken is an expression and a config token, // used in a few places: // // 1) To evaluate an expression and assign the result to an output event // parameter (wrapped in CfgToken) // 2) To evaluate an expression and compare the result to an input event // parameter (wrapped in CfgToken) // 2) To evaluate an expression and compare the result to a user variable // (wrapped in CfgToken) class DynamicToken { public: DynamicToken() : exp(0), next(0) {}; ~DynamicToken() { if (exp != 0) delete exp; }; CfgToken token; // Variable/parameter to compare or assign to ParsedExpression *exp; // Expression to evaluate DynamicToken *next; }; // Binding between a freewheeling event and some input action // controls basic user interface class EventBinding { public: EventBinding() : boundproto(0), echo(0), tokenconds(0), paramsets(0), continued(0), next(0) {}; virtual ~EventBinding(); Event *boundproto; // Prototype instance of the output event // Nonzero if input events should be rebroadcast even // if they are consumed in this binding char echo; // ** Conditions // List of dynamic token conditions // (for example, MIDI channel on input must match given expression) DynamicToken *tokenconds; // ** Parameter mappings // List of dynamic parameter assignments for output events // (for example, when triggering from MIDI keyboard: loop # = notenum + 12) DynamicToken *paramsets; // Continued is nonzero if the next binding should always be triggered // when this binding is triggered- so the next binding is a // continuation of this binding char continued; EventBinding *next; }; class InputMatrix : public EventProducer, public EventListener { public: InputMatrix(Fweelin *app); virtual ~InputMatrix(); // Sets the given variable to the given value- string is interpreted // based on variable type void SetVariable (UserVariable *var, char *value); // Called during configuration to create user defined variables void CreateVariable (xmlNode *declare); // Called during configuration to bind input controllers to events void CreateBinding (int interfaceid, xmlNode *binding); // Are the conditions in the EventBinding bind matched by the // given input event and user variables? char CheckConditions(Event *input, EventBinding *bind); // Receive input events void ReceiveEvent(Event *ev, EventProducer *from); // Start function, called shortly before Fweelin begins running void Start(); // *********** User defined variables UserVariable *vars; Fweelin *app; // Parses a given expression string, extracting tokens // for example: 'VAR_curnote+12' references variable VAR_curnote and // creates 1 math operation +12 // The expression may also reference parameters in event 'ref' // and these references will be extracted ParsedExpression *ParseExpression(char *str, Event *ref, char enable_keynames = 0); private: // Removes leading and trailing spaces from string str // Modifies the end of string str and returns a pointer to the new // beginning after spaces char *RemoveSpaces (char *str); // Adds one key to the given list based on the keysym name // Returns the new first pointer SDLKeyList *AddOneKey (SDLKeyList *first, char *str); // Extracts named keys from the given string and returns a list // of the keysyms (named keys are separated by ,) SDLKeyList *ExtractKeys (char *str); // Parses the given token (no math ops!) into dst // Correctly identifies when variables or event parameters are referenced void ParseToken(char *str, CfgToken *dst, Event *ref, char enable_keynames = 0); // Stores in ptr the value val given that ptr is of type dtype void StoreParameter(char *ptr, CoreDataType dtype, UserVariable *val); // Using the eventbinding's parametersets as a template, dynamically // sets parameters in the output event void SetDynamicParameters(Event *input, Event *output, EventBinding *bind); // Scans in the given binding for settings for output event parameters // and sets us up to handle those void CreateParameterSets (int interfaceid, EventBinding *bind, xmlNode *binding, Event *input, int contnum); // Scans in the given binding for conditions on input event parameters // or user variables, and sets us up to handle those // Returns the hash index for this binding, based on an indexed parameter, // or 0 if this binding is not indexed int CreateConditions (int interfaceid, EventBinding *bind, xmlNode *binding, Event *input, int paramidx); // Traverses through the list of event bindings beginning at 'start' // looking for a binding that matches current user variables and input // event 'ev' EventBinding *MatchBinding(Event *ev, EventBinding *start); // *********** Event Bindings // Bindings that trigger on input events- for each input event type, // a hashtable of bindings along an indexed parameter EventBinding ***input_bind; }; class FloLayoutElementGeometry { public: FloLayoutElementGeometry() : next(0) {}; // Draw this element to the given screen- // implementation given in videoio.cc virtual void Draw(SDL_Surface *screen, SDL_Color clr) = 0; // Inside returns nonzero if the given coordinates fall inside this // element geometry virtual char Inside(int x, int y) = 0; // Next geo FloLayoutElementGeometry *next; }; class FloLayoutBox : public FloLayoutElementGeometry { public: // Draw this element to the given screen- // implementation given in videoio.cc virtual void Draw(SDL_Surface *screen, SDL_Color clr); // Inside returns nonzero if the given coordinates fall inside this // element geometry virtual char Inside(int x, int y) { if (x >= left && x <= right && y >= top && y <= bottom) return 1; else return 0; }; // Outlines along borders? char lineleft, linetop, lineright, linebottom; // Coordinates of box int left, top, right, bottom; }; class FloLayoutElement { public: FloLayoutElement() : id(0), name(0), nxpos(0), nypos(0), bx(0.0), by(0.0), loopmap(0), loopx(0), loopy(0), loopsize(0), geo(0), next(0) {}; ~FloLayoutElement() { if (name != 0) delete[] name; // Erase geometries FloLayoutElementGeometry *cur = geo; while (cur != 0) { FloLayoutElementGeometry *tmp = cur->next; delete cur; cur = tmp; } }; // Inside returns nonzero if the given coordinates fall inside this // element- we check all geometries char Inside(int x, int y) { FloLayoutElementGeometry *cur = geo; while (cur != 0) { if (cur->Inside(x,y)) return 1; // Inside this geo, so inside this element cur = cur->next; } return 0; // Not inside any geo, so not inside this element }; int id; // Id of element char *name; // Name of element int nxpos, nypos; // Location to print name label float bx, by; // Base position for element // Generated map that will take a flat scope and project it onto the right // size circle-- see videoio CircularMap *loopmap; int loopx, loopy, // Position of loop graphic for the element loopsize; // Size of loop graphic (diameter) // Geo describes how to draw this element FloLayoutElementGeometry *geo; // Next element FloLayoutElement *next; }; // The user can define the onscreen layout for loops-- see config file! class FloLayout { public: FloLayout() : id(0), iid(0), xpos(0), ypos(0), loopids(0,0), name(0), nxpos(0), nypos(0), elems(0), show(1), showlabel(1), showelabel(1), next(0) {}; ~FloLayout() { if (name != 0) delete[] name; // Erase elements FloLayoutElement *cur = elems; while (cur != 0) { FloLayoutElement *tmp = cur->next; delete cur; cur = tmp; } }; int id, // User refers to a layout by layout ID iid, // Interface id. Interface id + layout id uniquely identify // a layout xpos, ypos; // Base location on screen for this layout Range loopids; // Range of loopids that map to interface elements char *name; // ex PC Keyboard, MIDI Footpedal int nxpos, nypos; // Location to print name label FloLayoutElement *elems; // Elements that make up this layout char show, // Layout shown onscreen? showlabel, // Name of layout shown onscreen? showelabel; // Element names in layout shown onscreen? // Next layout FloLayout *next; }; // List of strings- optional two strings per listitem // Second string is assumed to be substring of first string // Only first string is deleted at destructor class FloStringList { public: FloStringList(char *str, char *str2 = 0) : str(str), str2(str2), next(0) {}; ~FloStringList() { if (str != 0) delete[] str; }; char *str, *str2; FloStringList *next; }; // List of fonts used in video- video handles the loading and unloading, // but config sets up these structures to know which fonts and sizes to load class FloFont { public: FloFont() : name(0), filename(0), font(0), size(0), next(0) {}; ~FloFont() { if (filename != 0) delete[] filename; if (name != 0) delete[] name; }; char *name, *filename; TTF_Font *font; int size; FloFont *next; }; enum FloDisplayType { FD_Unknown, FD_Browser, FD_Snapshots }; // List of variable displays used in video // There are different types of displays, this is a base class class FloDisplay { public: FloDisplay (int iid) : iid(iid), id(-1), exp(0), font(0), title(0), xpos(0), ypos(0), show(1), forceshow(0), next(0) {}; virtual ~FloDisplay() { if (title != 0) delete[] title; if (exp != 0) delete exp; }; // Draw this display to the given screen- // implementation given in videoio.cc virtual void Draw(SDL_Surface *screen) = 0; virtual FloDisplayType GetFloDisplayType() { return FD_Unknown; }; int iid, // Interface id. Interface id + display id uniquely identify // a display id; // Display ID ParsedExpression *exp; // Expression which evaluates to a value to display FloFont *font; // Font for text char *title; // Title to be displayed int xpos, ypos; // Onscreen location for display char show, // Show (nonzero) or hide (zero) display forceshow; // Force display to show? FloDisplay *next; }; // Text display shows the value of expression 'exp' as onscreen text class FloDisplayText : public FloDisplay { public: FloDisplayText (int iid) : FloDisplay(iid) {}; virtual void Draw(SDL_Surface *screen); }; // Switch display shows the title in different color depending on the value of // expression 'exp' class FloDisplaySwitch : public FloDisplay { public: FloDisplaySwitch (int iid) : FloDisplay(iid) {}; virtual void Draw(SDL_Surface *screen); }; // Circle switch display shows a circle which changes color and optionally // flashes depending on the value of expression 'exp' class FloDisplayCircleSwitch : public FloDisplay { public: FloDisplayCircleSwitch (int iid) : FloDisplay(iid), rad1(0), rad0(0), flash(0), prevnonz(0), nonztime(0.) {}; virtual void Draw(SDL_Surface *screen); int rad1, rad0; // Radii of circle when switch is on or off // For flashing char flash, // Flash or solid colors? prevnonz; // Previous character value of expression (for nonzero test) double nonztime; // System time at which the expression last became nonzero }; // Text switch display shows one string of text when a value is nonzero, // and another string of text when a value is zero. class FloDisplayTextSwitch : public FloDisplay { public: FloDisplayTextSwitch (int iid) : FloDisplay(iid), text1(0), text0(0) {}; virtual void Draw(SDL_Surface *screen); char *text1, // Text for nonzero value *text0; // Text for zero value }; enum CfgOrientation { O_Horizontal, O_Vertical }; // Bar display shows the value of expression 'exp' as a bar class FloDisplayBar : public FloDisplay { public: FloDisplayBar (int iid) : FloDisplay(iid), orient(O_Vertical), barscale(1.0), thickness(10), dbscale(0), marks(0), maxdb(0) {}; virtual void Draw(SDL_Surface *screen); CfgOrientation orient; // Orientation of bar float barscale; // Scaling factor for size of bar int thickness; // Thickness of bar char dbscale, // If nonzero, this bar maps a linear amplitude variable to a logarithmic scale bar // If zero, there is a linear mapping to the bar marks; // If nonzero, calibration marks are shown (dB scale only) float maxdb; // (dbscale) Maximum dB level shown }; // Bar-switch display shows the value of expression 'exp' as a bar and changes the color of the bar // depending on the value of expression 'switchexp' class FloDisplayBarSwitch : public FloDisplayBar { public: FloDisplayBarSwitch (int iid) : FloDisplayBar(iid), switchexp(0), color(1), calibrate(0), cval(0.0) {}; virtual ~FloDisplayBarSwitch() { if (switchexp != 0) delete switchexp; }; virtual void Draw(SDL_Surface *screen); ParsedExpression *switchexp; // Expression which evaluates to a value. Nonzero values cause the bar // to appear bright, zero values cause a dim, faded bar int color; // Color of bar-switch (index of hardcoded color) char calibrate; // Nonzero shows calibration value on barswitch & changes color when level exceeds calibration value float cval; // Calibration value (linear) }; class FloDisplaySquares : public FloDisplay { public: FloDisplaySquares (int iid) : FloDisplay(iid), orient(O_Horizontal) {}; virtual void Draw(SDL_Surface *screen); CfgOrientation orient; // Orientation of bar float v1, v2, // Value corresponding to first and last square sinterval; // 1 square for every 'sinterval' change in value int sx, sy; // Square size }; // FluidSynth config #include "fweelin_fluidsynth.h" #if USE_FLUIDSYNTH class FluidSynthParam { public: FluidSynthParam(char *name) : next(0) { this->name = new char[strlen(name)+1]; strcpy(this->name,name); }; virtual ~FluidSynthParam() { delete[] name; }; // Send this parameter into the given settings virtual void Send(fluid_settings_t *settings) = 0; char *name; FluidSynthParam *next; }; class FluidSynthParam_Num : public FluidSynthParam { public: FluidSynthParam_Num(char *name, double val) : FluidSynthParam(name), val(val) {}; virtual void Send(fluid_settings_t *settings); double val; }; class FluidSynthParam_Int : public FluidSynthParam { public: FluidSynthParam_Int(char *name, int val) : FluidSynthParam(name), val(val) {}; virtual void Send(fluid_settings_t *settings); int val; }; class FluidSynthParam_Str : public FluidSynthParam { public: FluidSynthParam_Str(char *name, char *val) : FluidSynthParam(name) { this->val = new char[strlen(val)+1]; strcpy(this->val,val); }; virtual ~FluidSynthParam_Str() { delete[] val; }; virtual void Send(fluid_settings_t *settings); char *val; }; class FluidSynthSoundFont { public: FluidSynthSoundFont(char *name) : next(0) { if (strchr(name,'/') != 0) { // Path specified this->name = new char[strlen(name)+1]; strcpy(this->name,name); } else { // Path not specified, use default this->name = new char[strlen(FWEELIN_DATADIR)+1+strlen(name)+1]; sprintf(this->name,"%s/%s",FWEELIN_DATADIR,name); } }; ~FluidSynthSoundFont() { delete[] name; }; char *name; FluidSynthSoundFont *next; }; #endif // Fweelin configuration class FloConfig { public: FloConfig(Fweelin *app); ~FloConfig(); // Parse configuration file, setup config void Parse(); // Start function, called shortly before Fweelin begins running void Start() { im.Start(); }; // Send start-interface event to all interfaces void StartInterfaces (); // Copy config file from shared folder // Optionally copy all config files void CopyConfigFile (char *cfgname, char copyall); // Prepare to load configuration file 'cfgname' // Finds the file in one of several places, and copies it to // the config folder. Returns the path name if found, or null if not found char *PrepareLoadConfigFile (char *cfgname, char basecfg); // Configure bindings between events and their triggers void ConfigureEventBindings(xmlDocPtr doc, xmlNode *events, int interfaceid = 0, char firstpass = 0); void ConfigureElement(xmlDocPtr doc, xmlNode *elemn, FloLayoutElement *elem, float xscale, float yscale); void ConfigureLayout(xmlDocPtr doc, xmlNode *layn, FloLayout *lay, float xscale, float yscale); void ConfigurePatchBanks(xmlNode *pb, PatchBrowser *br); void ConfigureGraphics(xmlDocPtr doc, xmlNode *vid, int interfaceid = 0); void ConfigureBasics(xmlDocPtr doc, xmlNode *gen); void ConfigureInterfaces (xmlDocPtr doc, xmlNode *ifs, char firstpass); void ConfigureRoot (xmlDocPtr doc, xmlNode *root, int interfaceid = 0, char firstpass = 0); // Is node 'n' a comment with help information? If so, add to our // internal help list void CheckForHelp(xmlNode *n); // Creates an empty variable based on the given name. The config file // can then refer to the variable UserVariable *AddEmptyVariable(char *name); // Makes the given variable into a system variable by linking it to // the pointer void LinkSystemVariable(char *name, CoreDataType type, char *ptr); // Input matrix- stores and handles all bindings between inputs and events inline InputMatrix *GetInputMatrix() { return &im; }; InputMatrix im; // Add an event hook, if none already exists // An event hook gets first dibs on incoming events // We use this to override the usual functions of, say, the keyboard, // and redirect them elsewhere, like typing text. // // Returns zero on success and nonzero if another hook exists already inline char AddEventHook (EventHook *hook) { if (ev_hook == 0) { ev_hook = hook; return 0; } else return 1; }; // Remove an event hook // Returns zero on success inline char RemoveEventHook (EventHook *hook) { if (ev_hook == hook) { ev_hook = 0; return 0; } else return 1; }; // Event hook- right now, we only support one at a time EventHook *ev_hook; // Extracts an array of floats (delimited by character delim_char) // from the given string- returns size of array in 'size' float *ExtractArray(char *n, int *size, char delim_char = ','); // Same, with ints int *ExtractArrayInt(char *n, int *size, char delim_char = ','); // Library path inline char *GetLibraryPath() { if (librarypath != 0) return librarypath; else { printf("CORE: ERROR: Library path not set in configuration!\n"); exit(1); } }; char *librarypath; // Number of MIDI out ports inline int GetNumMIDIOuts() { return midiouts; }; int midiouts; // List of MIDI ports to transmit sync info to inline int GetNumMIDISyncOuts() { return msnumouts; }; inline int *GetMIDISyncOuts() { return msouts; }; int msnumouts, *msouts; // Is input/output #n stereo? inline char IsStereoInput(int n) { return ms_inputs[n]; }; inline char IsStereoOutput(int n) { return IsStereoMaster(); }; char *ms_inputs; // Zero or nonzero for each input- is this input stereo? // Is FreeWheeling running in stereo or completely in mono? char IsStereoMaster(); // Number of external audio inputs into FreeWheeling (specified in config file) // AudioIO may add its own inputs internal to FreeWheeling // (for example, softsynth) inline int GetExtAudioIns() { return extaudioins; }; int extaudioins; // Maximum play volume inline float GetMaxPlayVol() { return maxplayvol; }; float maxplayvol; // Maximum limiter gain inline float GetMaxLimiterGain() { return maxlimitergain; }; float maxlimitergain; // Limiter threshhold inline float GetLimiterThreshhold() { return limiterthreshhold; }; float limiterthreshhold; // Limiter release rate inline float GetLimiterReleaseRate() { return limiterreleaserate; }; float limiterreleaserate; // Logarithmic fader settings inline float GetFaderMaxDB() { return fadermaxdb; }; float fadermaxdb; // File format to save loops to inline codec GetLoopOutFormat() { return loopoutformat; }; codec loopoutformat; // File format to save streams to inline codec GetStreamOutFormat() { return streamoutformat; }; codec streamoutformat; inline char *GetCodecName (codec i) { switch (i) { case VORBIS: return "ogg"; case WAV: return "wav"; case FLAC: return "flac"; case AU: return "au"; default: return "UNKNOWN"; } }; inline codec GetCodecFromName (const char *n) { for (codec i = FIRST_FORMAT; i < END_OF_FORMATS; i = (codec) (i+1)) if (!strcasecmp(n,GetCodecName(i))) return i; return UNKNOWN; }; inline char *GetAudioFileExt (codec i) { switch (i) { case VORBIS: return ".ogg"; case WAV: return ".wav"; case FLAC: return ".flac"; case AU: return ".au"; default: return ".ogg"; }; }; // Quality for encoding OGG files inline float GetVorbisEncodeQuality() { return vorbis_encode_quality; }; float vorbis_encode_quality; // Number of triggers (loop ids) inline int GetNumTriggers() { return num_triggers; }; int num_triggers; // Video config inline int *GetVSize() { return vsize; }; inline float XCvtf(float x) { return (x*vsize[0]); }; inline float YCvtf(float y) { return (y*vsize[1]); }; inline int XCvt(float x) { return (int) (x*vsize[0]); }; inline int YCvt(float y) { return (int) (y*vsize[1]); }; int vsize[2]; inline int GetVDelay() { return vdelay; }; int vdelay; // # of samples in visual oscilloscope buffer nframes_t scope_sample_len; inline nframes_t GetScopeSampleLen() { return scope_sample_len; }; // Macro to check whether debug info is on #define CRITTERS (app->getCFG()->IsDebugInfo()) // Return nonzero if debug info to be shown char IsDebugInfo() { return showdebug; }; // Show debugging info? char showdebug; // Graphical layouts FloLayout *GetLayouts() { return layouts; }; FloLayout *layouts; // Graphical fonts // Returns the named font from our list of fonts FloFont *GetFont (char *name) { FloFont *cur = fonts; while (cur != 0 && strcmp(cur->name,name)) cur = cur->next; return cur; }; FloFont *GetFonts() { return fonts; }; FloFont *fonts; // Graphical displays inline FloDisplay *GetDisplays() { return displays; }; inline FloDisplay *GetDisplayById (int iid, int id) { FloDisplay *cur = displays; while (cur != 0) { if (cur->iid == iid && cur->id == id) return cur; cur = cur->next; } return 0; }; inline FloDisplay *GetDisplayByType (FloDisplayType typ) { FloDisplay *cur = displays; while (cur != 0) { if (cur->GetFloDisplayType() == typ) return cur; cur = cur->next; } return 0; }; FloDisplay *displays; // Help text int GetNumHelpLines() { FloStringList *cur = help; int cnt = 0; while (cur != 0) { cnt++; cur = cur->next; } return cnt; }; char *GetHelpLine(int idx, int col) { FloStringList *cur = help; int cnt = 0; while (cur != 0 && cnt != idx) { cnt++; cur = cur->next; } if (cur == 0) return 0; else return (col == 0 ? cur->str : cur->str2); }; FloStringList *help; #if USE_FLUIDSYNTH // FluidSynth config int fsinterp; int GetFluidInterpolation() { return fsinterp; }; int fschannel; int GetFluidChannel() { return fschannel; }; char fsstereo; char GetFluidStereo() { return fsstereo; }; float fstuning; float GetFluidTuning() { return fstuning; }; FluidSynthParam *fsparam; FluidSynthParam *GetFluidParam() { return fsparam; }; void AddFluidParam(FluidSynthParam *nw) { if (fsparam == 0) fsparam = nw; else { FluidSynthParam *cur = fsparam; while (cur->next != 0) cur = cur->next; cur->next = nw; } }; FluidSynthSoundFont *fsfont; void AddFluidFont(FluidSynthSoundFont *nw) { if (fsfont == 0) fsfont = nw; else { FluidSynthSoundFont *cur = fsfont; while (cur->next != 0) cur = cur->next; cur->next = nw; } }; FluidSynthSoundFont *GetFluidFont() { return fsfont; }; #endif // Pitch transpose on outgoing MIDI events signed int transpose; // Chunksize for peaks & avgs display of loops // (bigger # means shorter displays) nframes_t loop_peaksavgs_chunksize; int status_report; #define FS_REPORT_BLOCKMANAGER 1 // Total number of interfaces defined in config int numinterfaces, // Switchable interfaces // (range 1<=i<=numinterfaces) numnsinterfaces; // Nonswitchable interfaces // Maximum number of snapshots user can create inline int GetMaxSnapshots() { return max_snapshots; }; int max_snapshots; // Seconds of fixed audio history const static float AUDIO_MEMORY_LEN; // # of audio blocks to preallocate const static int NUM_PREALLOCATED_AUDIO_BLOCKS; // # of time markers to preallocate const static int NUM_PREALLOCATED_TIME_MARKERS; }; #endif fweelin-0.6/src/fweelin_core.cc0000755000175000017500000034177011065527467015241 0ustar mercmerc/* Truth has a power like electricity When we dance in Truth, it is infectious, unmistakable. */ /* Copyright 2004-2008 Jan Pekau (JP Mercury) This file is part of Freewheeling. Freewheeling is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. Freewheeling is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Freewheeling. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "fweelin_core.h" #include "fweelin_fluidsynth.h" const float Loop::MIN_VOL = 0.01; // *********** CORE Snapshot *Fweelin::getSNAP (int idx) { if (idx >= 0 && idx < cfg->GetMaxSnapshots()) return &snaps[idx]; else return 0; } void Snapshot::CreateSnapshot (char *name, LoopManager *lm, TriggerMap *tmap) { if (exists && this->name != 0 && name == 0) { // Preserve name of snapshot DeleteSnapshot(0); } else DeleteSnapshot(); exists = 1; if (this->name == 0 && name != 0) { this->name = new char[strlen(name)+1]; strcpy(this->name,name); } if (lm != 0) { // Count all loops numls = tmap->CountLoops(); if (numls > 0) { ls = new LoopSnapshot[numls]; int idx = 0; for (int i = 0; i < tmap->GetMapSize(); i++) { if (tmap->GetMap(i) != 0) { Loop *l = tmap->GetMap(i); if (idx >= numls) { printf("CORE: ERROR: Loop count mismatch creating snapshot!\n"); return; } ls[idx++] = LoopSnapshot(i,lm->GetStatus(i), l->vol,lm->GetTriggerVol(i)); } } } } }; // Trigger snapshot #idx - return nonzero on failure char Fweelin::TriggerSnapshot (int idx) { Snapshot *s = getSNAP(idx); if (s != 0 && s->exists) { for (int i = 0; i < s->numls; i++) { LoopSnapshot *ls = &(s->ls[i]); loopmgr->SetLoopVolume(ls->l_idx,ls->l_vol); if (ls->status == T_LS_Off && loopmgr->IsActive(ls->l_idx)) { loopmgr->Deactivate(ls->l_idx); } else if (ls->status == T_LS_Playing || ls->status == T_LS_Overdubbing) { if (loopmgr->GetStatus(ls->l_idx) != T_LS_Playing) { // Loop not yet playing if (loopmgr->IsActive(ls->l_idx)) loopmgr->Deactivate(ls->l_idx); loopmgr->Activate(ls->l_idx, 0, ls->t_vol); } else { // Loop already playing- adjust volume loopmgr->SetTriggerVol(ls->l_idx, ls->t_vol); } } } return 0; } else return 1; }; // Splits a saveable filename in the format 'basename-hash-objectname' // into its base name, hash and object name components // // Returns zero on success char Saveable::SplitFilename(char *filename, int baselen, char *basename, char *hash, char *objname, int maxlen) { // Loop exists, use combination of time and hash as name char *slashptr = filename + baselen; if (slashptr < filename+strlen(filename)) { char *slashptr2 = strchr(slashptr+1,'-'), *extptr = strrchr(filename,'.'); if (extptr == 0) extptr = filename+strlen(filename); // No extension // Extract base name int len = 0; if (basename != 0) { len = MIN(baselen,maxlen-1); memcpy(basename,filename,sizeof(char)*len); basename[len] = '\0'; } // Extract hash char *breaker = (slashptr2 != 0 ? slashptr2 : extptr); if (strlen(slashptr+1) - strlen(breaker) == SAVEABLE_HASH_LENGTH*2) { if (hash != 0) { len = MIN(SAVEABLE_HASH_LENGTH*2,maxlen-1); memcpy(hash,slashptr+1,sizeof(char)*len); hash[len] = '\0'; } } else { printf("SAVEABLE: Invalid hash within filename: '%s'\n", filename); return 1; } // Now check if the filename also contains an object name- // this would be placed after the hash if (objname != 0) { if (slashptr2 != 0) { // Name len = strlen(slashptr2+1) - strlen(extptr); len = MIN(len,maxlen-1); memcpy(objname,slashptr2+1,sizeof(char)*len); objname[len] = '\0'; } else strcpy(objname,""); } } else { printf("SAVEABLE: Invalid filename for extracting hash/name: '%s'\n", filename); return 1; } return 0; }; void Saveable::RenameSaveable(char **filename_ptr, int baselen, char *newname, const char **exts, int num_exts) { // Parse filename to extract hash part char fn_base[FWEELIN_OUTNAME_LEN], fn_hash[FWEELIN_OUTNAME_LEN], fn_name[FWEELIN_OUTNAME_LEN]; if (Saveable::SplitFilename(*filename_ptr,baselen,fn_base,fn_hash,fn_name, FWEELIN_OUTNAME_LEN)) printf("SAVEABLE: Can't rename '%s'- poorly formatted filename.\n", *filename_ptr); else { char tmp[FWEELIN_OUTNAME_LEN]; strncpy(tmp,*filename_ptr,FWEELIN_OUTNAME_LEN); tmp[FWEELIN_OUTNAME_LEN-1] = '\0'; delete[] *filename_ptr; *filename_ptr = new char[strlen(fn_base)+1+ strlen(fn_hash)+1+ strlen(newname)+1]; if (strlen(newname) > 0) sprintf(*filename_ptr,"%s-%s-%s", fn_base,fn_hash,newname); else sprintf(*filename_ptr,"%s-%s", fn_base,fn_hash); char tmp_a[FWEELIN_OUTNAME_LEN], tmp_b[FWEELIN_OUTNAME_LEN]; for (int i = 0; i < num_exts; i++) { // Add each type of extension provided and rename the file snprintf(tmp_a,FWEELIN_OUTNAME_LEN,"%s%s",tmp,exts[i]); snprintf(tmp_b,FWEELIN_OUTNAME_LEN,"%s%s",*filename_ptr,exts[i]); if (!rename(tmp_a,tmp_b)) printf("SAVEABLE: Rename file '%s' -> '%s'\n",tmp_a,tmp_b); //else //printf("SAVEABLE: File '%s' not found for rename\n",tmp_a); } } }; // This is for renaming an item in memory, so that the disk corresponds // with the new name void Saveable::RenameSaveable(char *librarypath, char *basename, char *old_objname, char *nw_objname, const char **exts, int num_exts, char **old_filename, char **new_filename) { if (savestatus == SAVE_DONE) { // OK, we have to rename on disk // Get filename to rename GET_SAVEABLE_HASH_TEXT(GetSaveHash()); *old_filename = new char[FWEELIN_OUTNAME_LEN]; *new_filename = new char[FWEELIN_OUTNAME_LEN]; for (int i = 0; i < num_exts; i++) { // Add each type of extension provided and rename the file if (old_objname == 0 || strlen(old_objname) == 0) snprintf(*old_filename,FWEELIN_OUTNAME_LEN,"%s/%s-%s%s", librarypath,basename,hashtext,exts[i]); else snprintf(*old_filename,FWEELIN_OUTNAME_LEN,"%s/%s-%s-%s%s", librarypath,basename,hashtext,old_objname,exts[i]); if (nw_objname == 0 || strlen(nw_objname) == 0) snprintf(*new_filename,FWEELIN_OUTNAME_LEN,"%s/%s-%s%s", librarypath,basename,hashtext,exts[i]); else snprintf(*new_filename,FWEELIN_OUTNAME_LEN,"%s/%s-%s-%s%s", librarypath,basename,hashtext,nw_objname,exts[i]); printf("SAVEABLE: Rename file '%s' -> '%s'\n", *old_filename,*new_filename); rename(*old_filename,*new_filename); } // Get names without extensions if (old_objname == 0) snprintf(*old_filename,FWEELIN_OUTNAME_LEN,"%s/%s-%s", librarypath,basename,hashtext); else snprintf(*old_filename,FWEELIN_OUTNAME_LEN,"%s/%s-%s-%s", librarypath,basename,hashtext,old_objname); if (nw_objname == 0) snprintf(*new_filename,FWEELIN_OUTNAME_LEN,"%s/%s-%s", librarypath,basename,hashtext); else snprintf(*new_filename,FWEELIN_OUTNAME_LEN,"%s/%s-%s-%s", librarypath,basename,hashtext,nw_objname); } }; // Save loop void Loop::Save(Fweelin *app) { // Queue save app->getLOOPMGR()->AddLoopToSaveQueue(this); }; void LoopManager::AddToSaveQueue(Event *ev) { numsave++; EventManager::QueueEvent(&savequeue,ev); }; void LoopManager::AddLoopToSaveQueue(Loop *l) { if (!autosave && l->GetSaveStatus() == NO_SAVE) { numsave++; LoopListEvent *ll = (LoopListEvent *) Event::GetEventByType(T_EV_LoopList,1); ll->l = l; EventManager::QueueEvent(&savequeue,ll); } }; void LoopManager::AddLoopToLoadQueue(char *filename, int index, float vol) { numload++; LoopListEvent *ll = (LoopListEvent *) Event::GetEventByType(T_EV_LoopList,1); strcpy(ll->l_filename,filename); ll->l_idx = index; ll->l_vol = vol; EventManager::QueueEvent(&loadqueue,ll); }; // Adds the loop with given filename to the loop browser br void LoopManager::AddLoopToBrowser(Browser *br, char *filename) { char tmp[FWEELIN_OUTNAME_LEN]; struct stat st; if (stat(filename,&st) == 0) { char default_name = br->GetDisplayName(filename,&st.st_mtime,tmp,FWEELIN_OUTNAME_LEN); br->AddItem(new LoopBrowserItem(st.st_mtime,tmp,default_name,filename),1); } }; // Populate the loop browser with any loops on disk void LoopManager::SetupLoopBrowser() { Browser *br = app->getBROWSER(B_Loop); if (br != 0) { // Clear br->ClearAllItems(); // Look for loops on disk glob_t globbuf; char tmp[FWEELIN_OUTNAME_LEN]; for (codec lformat = FIRST_FORMAT; lformat < END_OF_FORMATS; lformat = (codec) (lformat+1)) { snprintf(tmp,FWEELIN_OUTNAME_LEN,"%s/%s*%s", app->getCFG()->GetLibraryPath(),FWEELIN_OUTPUT_LOOP_NAME, app->getCFG()->GetAudioFileExt(lformat)); printf("BROWSER: (Loop) Scanning for loops in library: %s\n",tmp); if (glob(tmp, 0, NULL, &globbuf) == 0) { for (size_t i = 0; i < globbuf.gl_pathc; i++) { //printf("BROWSER: (Loop) Loop: %s\n",globbuf.gl_pathv[i]); AddLoopToBrowser(br,globbuf.gl_pathv[i]); } br->AddDivisions(FWEELIN_FILE_BROWSER_DIVISION_TIME); br->MoveToBeginning(); globfree(&globbuf); } } } }; // Adds the scene with given filename to the scene browser br SceneBrowserItem *LoopManager::AddSceneToBrowser(Browser *br, char *filename) { char tmp[FWEELIN_OUTNAME_LEN]; SceneBrowserItem *ret = 0; struct stat st; if (stat(filename,&st) == 0) { char default_name = br->GetDisplayName(filename,&st.st_mtime,tmp,FWEELIN_OUTNAME_LEN); br->AddItem(ret = new SceneBrowserItem(st.st_mtime,tmp,default_name,filename),1); } return ret; }; // Populate the scene browser with any scenes on disk void LoopManager::SetupSceneBrowser() { Browser *br = app->getBROWSER(B_Scene); if (br != 0) { // Clear br->ClearAllItems(); // Look for scenes on disk glob_t globbuf; char tmp[FWEELIN_OUTNAME_LEN]; snprintf(tmp,FWEELIN_OUTNAME_LEN,"%s/%s*%s", app->getCFG()->GetLibraryPath(),FWEELIN_OUTPUT_SCENE_NAME, FWEELIN_OUTPUT_DATA_EXT); printf("BROWSER: (Scene) Scanning for scenes in library: %s\n",tmp); if (glob(tmp, 0, NULL, &globbuf) == 0) { for (size_t i = 0; i < globbuf.gl_pathc; i++) { // printf("BROWSER: (Scene) Scene: %s\n",globbuf.gl_pathv[i]); AddSceneToBrowser(br,globbuf.gl_pathv[i]); } br->AddDivisions(FWEELIN_FILE_BROWSER_DIVISION_TIME); br->MoveToBeginning(); globfree(&globbuf); } } }; void LoopManager::ItemBrowsed(BrowserItem *i) {}; void LoopManager::ItemSelected(BrowserItem *i) { switch (i->GetType()) { case B_Loop: printf("DISK: Load '%s'\n",((LoopBrowserItem *) i)->filename); LoadLoop(((LoopBrowserItem *) i)->filename,loadloopid, newloopvol / GetOutputVolume()); break; case B_Scene: printf("DISK: Load '%s'\n",((SceneBrowserItem *) i)->filename); LoadScene((SceneBrowserItem *) i); break; default: break; } }; void LoopManager::ItemRenamed(BrowserItem *i) { switch (i->GetType()) { case B_Loop_Tray: // Change name inside the loop { LoopTrayItem *curl = (LoopTrayItem *) i; char *old_filename = 0, *new_filename = 0; // Rename on disk const static char *exts[] = {app->getCFG()->GetAudioFileExt(curl->l->format), FWEELIN_OUTPUT_DATA_EXT}; curl->l->RenameSaveable(app->getCFG()->GetLibraryPath(), FWEELIN_OUTPUT_LOOP_NAME, curl->l->name, curl->name, exts, 2, &old_filename, &new_filename); // We also need to rename in the loop browser if (app->getBROWSER(B_Loop) != 0) app->getBROWSER(B_Loop)-> ItemRenamedOnDisk(old_filename,new_filename,curl->name); if (old_filename != 0) delete[] old_filename; if (new_filename != 0) delete[] new_filename; // And in memory.. RenameLoop(curl->l,curl->name); } break; case B_Loop: { // Name change on disk int baselen = strlen(app->getCFG()->GetLibraryPath()) + 1 + strlen(FWEELIN_OUTPUT_LOOP_NAME); // Add all audio format names + XML to extension list int numexts = END_OF_FORMATS + 1; char *exts[numexts]; for (codec c = FIRST_FORMAT; c < END_OF_FORMATS; c = (codec) (c+1)) exts[c] = app->getCFG()->GetAudioFileExt(c); exts[END_OF_FORMATS] = FWEELIN_OUTPUT_DATA_EXT; // Rename all possible audio files + XML metadata to new name printf("DISK: Rename '%s'\n",((LoopBrowserItem *) i)->filename); Saveable::RenameSaveable(&((LoopBrowserItem *) i)->filename,baselen, i->name,(const char **) exts,numexts); // Is this loop loaded? If so, rename it // Find loop in memory (by hash, extracted from filename) char fn_hash[FWEELIN_OUTNAME_LEN]; if (!Saveable::SplitFilename(((LoopBrowserItem *) i)->filename, baselen,0,fn_hash,0,FWEELIN_OUTNAME_LEN)) { // Convert text 'fn_hash' to binary hash and scan for it Saveable tmp; if (!(tmp.SetSaveableHashFromText(fn_hash))) { int foundidx; if ((foundidx = app->getTMAP()->ScanForHash(tmp.GetSaveHash())) != -1) { // This loop -is- loaded, rename in map and in loop tray // printf("loop renamed is also in memory: %d\n",foundidx); Loop *foundloop = GetSlot(foundidx); // Rename in memory RenameLoop(foundloop,i->name); // We have to notify the LoopTray of the new name given LoopTray *tray = (LoopTray *) app->getBROWSER(B_Loop_Tray); if (tray != 0) tray->ItemRenamedFromOutside(foundloop,i->name); } } } } break; case B_Scene: { int baselen = strlen(app->getCFG()->GetLibraryPath()) + 1 + strlen(FWEELIN_OUTPUT_SCENE_NAME); const static char *exts[] = {FWEELIN_OUTPUT_DATA_EXT}; printf("DISK: Rename '%s'\n",((SceneBrowserItem *) i)->filename); Saveable::RenameSaveable(&((SceneBrowserItem *) i)->filename,baselen, i->name,exts,1); } break; default: break; } }; LoopManager::LoopManager (Fweelin *app) : renamer(0), rename_loop(0), savequeue(0), loadqueue(0), cursave(0), curload(0), numsave(0), numload(0), loadloopid(0), needs_saving_stamp(0), default_looprange(Range(0,app->getCFG()->GetNumTriggers())), autosave(0), app(app), newloopvol(1.0), subdivide(1), curpulseindex(-1) { pthread_mutex_init (&loops_lock,0); int mapsz = app->getTMAP()->GetMapSize(); plist = new Processor *[mapsz]; status = new LoopStatus[mapsz]; waitactivate = new int[mapsz]; waitactivate_shot = new char[mapsz]; waitactivate_vol = new float[mapsz]; waitactivate_od = new char[mapsz]; waitactivate_od_fb = new float *[mapsz]; numloops = 0; numrecordingloops = 0; lastrecidx = new int[LAST_REC_COUNT]; memset(lastrecidx, 0, sizeof(int) * LAST_REC_COUNT); memset(plist, 0, sizeof(Processor *) * mapsz); int lst = T_LS_Off; memset(status, lst, sizeof(LoopStatus) * mapsz); memset(waitactivate, 0, sizeof(int) * mapsz); memset(waitactivate_shot, 0, sizeof(char) * mapsz); memset(waitactivate_vol, 0, sizeof(float) * mapsz); memset(waitactivate_od, 0, sizeof(char) * mapsz); memset(waitactivate_od_fb, 0, sizeof(float) * mapsz); memset(pulses, 0, sizeof(Pulse *) * MAX_PULSES); // Turn on block read/write managers for loading & saving loops bread = ::new BlockReadManager(0,this,app->getBMG(), app->getCFG()->loop_peaksavgs_chunksize); bwrite = ::new BlockWriteManager(0,this,app->getBMG()); app->getBMG()->AddManager(bread); app->getBMG()->AddManager(bwrite); // Listen for important events app->getEMG()->ListenEvent(this,0,T_EV_EndRecord); app->getEMG()->ListenEvent(this,0,T_EV_ToggleDiskOutput); app->getEMG()->ListenEvent(this,0,T_EV_ToggleSelectLoop); app->getEMG()->ListenEvent(this,0,T_EV_SelectOnlyPlayingLoops); app->getEMG()->ListenEvent(this,0,T_EV_SelectAllLoops); app->getEMG()->ListenEvent(this,0,T_EV_InvertSelection); app->getEMG()->ListenEvent(this,0,T_EV_CreateSnapshot); app->getEMG()->ListenEvent(this,0,T_EV_RenameSnapshot); app->getEMG()->ListenEvent(this,0,T_EV_TriggerSnapshot); app->getEMG()->ListenEvent(this,0,T_EV_SetAutoLoopSaving); app->getEMG()->ListenEvent(this,0,T_EV_SaveLoop); app->getEMG()->ListenEvent(this,0,T_EV_SaveNewScene); app->getEMG()->ListenEvent(this,0,T_EV_SaveCurrentScene); app->getEMG()->ListenEvent(this,0,T_EV_SetLoadLoopId); app->getEMG()->ListenEvent(this,0,T_EV_SetDefaultLoopPlacement); app->getEMG()->ListenEvent(this,0,T_EV_SlideMasterInVolume); app->getEMG()->ListenEvent(this,0,T_EV_SlideMasterOutVolume); app->getEMG()->ListenEvent(this,0,T_EV_SlideInVolume); app->getEMG()->ListenEvent(this,0,T_EV_SetMasterInVolume); app->getEMG()->ListenEvent(this,0,T_EV_SetMasterOutVolume); app->getEMG()->ListenEvent(this,0,T_EV_SetInVolume); app->getEMG()->ListenEvent(this,0,T_EV_ToggleInputRecord); app->getEMG()->ListenEvent(this,0,T_EV_DeletePulse); app->getEMG()->ListenEvent(this,0,T_EV_SelectPulse); app->getEMG()->ListenEvent(this,0,T_EV_TapPulse); app->getEMG()->ListenEvent(this,0,T_EV_SwitchMetronome); app->getEMG()->ListenEvent(this,0,T_EV_SetSyncType); app->getEMG()->ListenEvent(this,0,T_EV_SetSyncSpeed); app->getEMG()->ListenEvent(this,0,T_EV_SetMidiSync); app->getEMG()->ListenEvent(this,0,T_EV_SetTriggerVolume); app->getEMG()->ListenEvent(this,0,T_EV_SlideLoopAmp); app->getEMG()->ListenEvent(this,0,T_EV_SetLoopAmp); app->getEMG()->ListenEvent(this,0,T_EV_AdjustLoopAmp); app->getEMG()->ListenEvent(this,0,T_EV_TriggerLoop); app->getEMG()->ListenEvent(this,0,T_EV_TriggerSelectedLoops); app->getEMG()->ListenEvent(this,0,T_EV_SetSelectedLoopsTriggerVolume); app->getEMG()->ListenEvent(this,0,T_EV_AdjustSelectedLoopsAmp); app->getEMG()->ListenEvent(this,0,T_EV_MoveLoop); app->getEMG()->ListenEvent(this,0,T_EV_RenameLoop); app->getEMG()->ListenEvent(this,0,T_EV_EraseLoop); app->getEMG()->ListenEvent(this,0,T_EV_EraseAllLoops); app->getEMG()->ListenEvent(this,0,T_EV_EraseSelectedLoops); app->getEMG()->ListenEvent(this,0,T_EV_SlideLoopAmpStopAll); }; LoopManager::~LoopManager() { // Stop block read/write managers bread->End(0); bwrite->End(); app->getBMG()->DelManager(bread); app->getBMG()->DelManager(bwrite); // Stop listening app->getEMG()->UnlistenEvent(this,0,T_EV_EndRecord); app->getEMG()->UnlistenEvent(this,0,T_EV_ToggleDiskOutput); app->getEMG()->UnlistenEvent(this,0,T_EV_ToggleSelectLoop); app->getEMG()->UnlistenEvent(this,0,T_EV_SelectOnlyPlayingLoops); app->getEMG()->UnlistenEvent(this,0,T_EV_SelectAllLoops); app->getEMG()->UnlistenEvent(this,0,T_EV_InvertSelection); app->getEMG()->UnlistenEvent(this,0,T_EV_CreateSnapshot); app->getEMG()->UnlistenEvent(this,0,T_EV_RenameSnapshot); app->getEMG()->UnlistenEvent(this,0,T_EV_TriggerSnapshot); app->getEMG()->UnlistenEvent(this,0,T_EV_SetAutoLoopSaving); app->getEMG()->UnlistenEvent(this,0,T_EV_SaveLoop); app->getEMG()->UnlistenEvent(this,0,T_EV_SaveNewScene); app->getEMG()->UnlistenEvent(this,0,T_EV_SaveCurrentScene); app->getEMG()->UnlistenEvent(this,0,T_EV_SetLoadLoopId); app->getEMG()->UnlistenEvent(this,0,T_EV_SetDefaultLoopPlacement); app->getEMG()->UnlistenEvent(this,0,T_EV_SlideMasterInVolume); app->getEMG()->UnlistenEvent(this,0,T_EV_SlideMasterOutVolume); app->getEMG()->UnlistenEvent(this,0,T_EV_SlideInVolume); app->getEMG()->UnlistenEvent(this,0,T_EV_SetMasterInVolume); app->getEMG()->UnlistenEvent(this,0,T_EV_SetMasterOutVolume); app->getEMG()->UnlistenEvent(this,0,T_EV_SetInVolume); app->getEMG()->UnlistenEvent(this,0,T_EV_ToggleInputRecord); app->getEMG()->UnlistenEvent(this,0,T_EV_DeletePulse); app->getEMG()->UnlistenEvent(this,0,T_EV_SelectPulse); app->getEMG()->UnlistenEvent(this,0,T_EV_TapPulse); app->getEMG()->UnlistenEvent(this,0,T_EV_SwitchMetronome); app->getEMG()->UnlistenEvent(this,0,T_EV_SetSyncType); app->getEMG()->UnlistenEvent(this,0,T_EV_SetSyncSpeed); app->getEMG()->UnlistenEvent(this,0,T_EV_SetMidiSync); app->getEMG()->UnlistenEvent(this,0,T_EV_SetTriggerVolume); app->getEMG()->UnlistenEvent(this,0,T_EV_SlideLoopAmp); app->getEMG()->UnlistenEvent(this,0,T_EV_SetLoopAmp); app->getEMG()->UnlistenEvent(this,0,T_EV_AdjustLoopAmp); app->getEMG()->UnlistenEvent(this,0,T_EV_TriggerLoop); app->getEMG()->UnlistenEvent(this,0,T_EV_TriggerSelectedLoops); app->getEMG()->UnlistenEvent(this,0,T_EV_SetSelectedLoopsTriggerVolume); app->getEMG()->UnlistenEvent(this,0,T_EV_AdjustSelectedLoopsAmp); app->getEMG()->UnlistenEvent(this,0,T_EV_MoveLoop); app->getEMG()->UnlistenEvent(this,0,T_EV_RenameLoop); app->getEMG()->UnlistenEvent(this,0,T_EV_EraseLoop); app->getEMG()->UnlistenEvent(this,0,T_EV_EraseAllLoops); app->getEMG()->UnlistenEvent(this,0,T_EV_EraseSelectedLoops); app->getEMG()->UnlistenEvent(this,0,T_EV_SlideLoopAmpStopAll); EventManager::DeleteQueue(savequeue); EventManager::DeleteQueue(loadqueue); // Let BMG know that we are ending app->getBMG()->RefDeleted((AutoWriteControl *) this); delete[] lastrecidx; delete[] plist; delete[] status; delete[] waitactivate; delete[] waitactivate_shot; delete[] waitactivate_vol; delete[] waitactivate_od; delete[] waitactivate_od_fb; pthread_mutex_destroy (&loops_lock); }; // Get length returns the length of any loop on the specified index nframes_t LoopManager::GetLength(int index) { if (status[index] == T_LS_Recording) { // Ooh, we are recording on this index. Get the current length return ((RecordProcessor *) plist[index])->GetRecordedLength(); } else { Loop *cur = app->getTMAP()->GetMap(index); if (cur != 0) return cur->blocks->GetTotalLen(); } return 0; } // Get length returns the length of any loop on the specified index // Rounded to its currently quantized length // Or 0 if the loop has no pulse nframes_t LoopManager::GetRoundedLength(int index) { if (status[index] == T_LS_Recording) { // Return 0 when recording return 0; // Ooh, we are recording on this index. Get the current length // return ((RecordProcessor *) plist[index])->GetRecordedLength(); } else { Loop *cur = app->getTMAP()->GetMap(index); if (cur != 0) if (cur->pulse != 0) return cur->pulse->QuantizeLength(cur->blocks->GetTotalLen()); else return 0; // cur->blocks->GetTotalLen(); } return 0; } float LoopManager::GetPos(int index) { if (status[index] == T_LS_Recording) return 0.0; else { Loop *cur = app->getTMAP()->GetMap(index); if (cur != 0 && plist[index] != 0) { nframes_t playedlen = 0; if (status[index] == T_LS_Playing) playedlen = ((PlayProcessor *) plist[index])->GetPlayedLength(); else if (status[index] == T_LS_Overdubbing) playedlen = ((RecordProcessor *) plist[index])->GetRecordedLength(); if (cur->pulse == 0) return (float) playedlen / cur->blocks->GetTotalLen(); else { if (cur->pulse->QuantizeLength(cur->blocks->GetTotalLen()) == 0) { printf("LoopManager: ERROR: Problem with quantize GetPos\n"); exit(1); } return (float) playedlen / cur->pulse->QuantizeLength(cur->blocks->GetTotalLen()); } } } return 0.0; } // Get current # of samples into block chain with given index nframes_t LoopManager::GetCurCnt(int index) { if (status[index] == T_LS_Recording) return 0; else { Loop *cur = app->getTMAP()->GetMap(index); if (cur != 0 && plist[index] != 0) { if (status[index] == T_LS_Playing) return ((PlayProcessor *) plist[index])->GetPlayedLength(); else if (status[index] == T_LS_Overdubbing) return ((RecordProcessor *) plist[index])->GetRecordedLength(); } } return 0; } // Sets triggered volume on specified index // If index is not playing, activates the index void LoopManager::SetTriggerVol(int index, float vol) { if (status[index] == T_LS_Playing) ((PlayProcessor *) plist[index])->SetPlayVol(vol); else if (status[index] == T_LS_Overdubbing) ((RecordProcessor *) plist[index])->SetODPlayVol(vol); } // Gets trigger volume on specified index // If index is not playing, returns 0 float LoopManager::GetTriggerVol(int index) { if (status[index] == T_LS_Playing) return ((PlayProcessor *) plist[index])->GetPlayVol(); else if (status[index] == T_LS_Overdubbing) return ((RecordProcessor *) plist[index])->GetODPlayVol(); else return 0.0; } // Returns a loop with the specified index, if one exists Loop *LoopManager::GetSlot(int index) { return app->getTMAP()->GetMap(index); } void LoopManager::AdjustOutputVolume(float adjust) { app->getRP()->AdjustOutputVolume(adjust); } void LoopManager::SetOutputVolume(float set, float logset) { if (set >= 0.) app->getRP()->SetOutputVolume(set); else if (logset >= 0.) app->getRP()->SetOutputVolume(DB2LIN(AudioLevel::fader_to_dB(logset, app->getCFG()->GetFaderMaxDB()))); } float LoopManager::GetOutputVolume() { return app->getRP()->GetOutputVolume(); } void LoopManager::AdjustInputVolume(float adjust) { app->getRP()->AdjustInputVolume(adjust); } void LoopManager::SetInputVolume(float set, float logset) { if (set >= 0.) app->getRP()->SetInputVolume(set); else if (logset >= 0.) app->getRP()->SetInputVolume(DB2LIN(AudioLevel::fader_to_dB(logset, app->getCFG()->GetFaderMaxDB()))); } float LoopManager::GetInputVolume() { return app->getRP()->GetInputVolume(); } void LoopManager::SetLoopVolume(int index, float val) { Loop *lp = app->getTMAP()->GetMap(index); if (lp != 0) { // First, preprocess for smoothing Processor *p = GetProcessor(index); if (p != 0) p->dopreprocess(); if (val >= 0.0) lp->vol = val; else lp->vol = 0.0; } } float LoopManager::GetLoopVolume(int index) { Loop *lp = app->getTMAP()->GetMap(index); if (lp != 0) return lp->vol; else return 1.0; } void LoopManager::AdjustLoopVolume(int index, float adjust) { Loop *lp = app->getTMAP()->GetMap(index); if (lp != 0) { lp->dvol += adjust*app->getAUDIO()->GetTimeScale(); if (lp->dvol < 0.0) lp->dvol = 0.0; } } void LoopManager::SetLoopdVolume(int index, float val) { Loop *lp = app->getTMAP()->GetMap(index); if (lp != 0) lp->dvol = val; } float LoopManager::GetLoopdVolume(int index) { Loop *lp = app->getTMAP()->GetMap(index); if (lp != 0) return lp->dvol; else return 1.0; } void LoopManager::SelectPulse (int pulseindex) { if (pulseindex == -1) { if (GetCurPulse() != 0) GetCurPulse()->SetMIDIClock(0); // Stop MIDI clock //printf("**Select: No pulse\n"); curpulseindex = -1; } else if (pulseindex < 0 || pulseindex >= MAX_PULSES) { printf("CORE: Invalid pulse #%d, ignoring.\n",pulseindex); return; } else if (pulses[pulseindex] == 0) { //printf("New pulse[%d]: %d SUB: %d\n", pulseindex, lastindex, subdivide); CreatePulse(lastindex, pulseindex, subdivide); } else { //printf("Select pulse[%d]\n", pulseindex); curpulseindex = pulseindex; StripePulseOn(pulses[pulseindex]); // Select pulse, send MIDI start GetCurPulse()->SetMIDIClock(1); } } // Save a whole scene, with an optional filename- // if none is given, saves a new scene void TriggerMap::Save(Fweelin *app, char *filename) { if (GetSaveStatus() == NO_SAVE) { // Scene hash is generated from hash of all loops in the triggermap-- // so start by saving all loops app->getLOOPMGR()->SetAutoLoopSaving(0); for (int i = 0; i < app->getCFG()->GetNumTriggers(); i++) app->getLOOPMGR()->SaveLoop(i); // Now, we have to wait until all that saving is done. // Queue a scene marker event in the save queue SceneMarkerEvent *sEvt = (SceneMarkerEvent *) Event::GetEventByType(T_EV_SceneMarker,1); if (filename != 0) strncpy(sEvt->s_filename,filename,FWEELIN_OUTNAME_LEN); app->getLOOPMGR()->AddToSaveQueue(sEvt); } }; void TriggerMap::SetMap (int index, Loop *smp) { if (index < 0 || index >= mapsize) { printf("SetMap: Invalid loop index!\n"); } else { map[index] = smp; TouchMap(); // Fire off a TriggerSet event TriggerSetEvent *tevt = (TriggerSetEvent *) Event::GetEventByType(T_EV_TriggerSet); tevt->idx = index; tevt->nw = smp; app->getEMG()->BroadcastEventNow(tevt, this); } }; void TriggerMap::GoSave(char *filename) { // All loops in the scene are now hashed and saved char newScene = (filename[0] == '\0'); // New scene or overwrite existing? if (newScene) { // Begin our save by generating a scene hash from the loop hashes // This will give us an appropriate scene filename MD5_CTX md5gen; MD5_Init(&md5gen); for (int i = 0; i < mapsize; i++) if (map[i] != 0) { if (map[i]->GetSaveStatus() == SAVE_DONE) // Update scene hash with hash from this loop MD5_Update(&md5gen,map[i]->GetSaveHash(),SAVEABLE_HASH_LENGTH); else printf("DISK: WARNING: Loop %d not saved yet but scene about to be " "saved!\n",i); } // Done- compute our final hash MD5_Final(GetSaveHash(),&md5gen); } SetSaveStatus(SAVE_DONE); // Compose filenames & start writing char tmp[FWEELIN_OUTNAME_LEN]; if (newScene) { GET_SAVEABLE_HASH_TEXT(GetSaveHash()); snprintf(tmp,FWEELIN_OUTNAME_LEN,"%s/%s-%s%s", app->getCFG()->GetLibraryPath(),FWEELIN_OUTPUT_SCENE_NAME, hashtext,FWEELIN_OUTPUT_DATA_EXT); } else snprintf(tmp,FWEELIN_OUTNAME_LEN,"%s%s", filename,FWEELIN_OUTPUT_DATA_EXT); if (!newScene) { // Back up existing scene data struct stat st; if (stat(tmp,&st) == 0) { // First available backup filename char tmp2[FWEELIN_OUTNAME_LEN]; int bCnt = 1; char go = 1; while (go) { snprintf(tmp2,FWEELIN_OUTNAME_LEN,"%s.backup.%d",tmp,bCnt); if (stat(tmp2,&st) != 0) go = 0; // Free backup filename else bCnt++; } char buf[FWEELIN_OUTNAME_LEN * 2 + 20]; printf("INIT: Backup existing scene.\n"); sprintf(buf,"mv \"%s\" \"%s\"",tmp,tmp2); printf("INIT: Executing: %s\n",buf); system(buf); } } struct stat st; printf("DISK: Opening %s '%s' for saving.\n", (newScene ? "new scene" : "existing scene"), tmp); if (newScene && stat(tmp,&st) == 0) { printf("DISK: ERROR: MD5 collision while saving scene- file exists!\n"); } else { // Save scene XML data xmlDocPtr ldat = xmlNewDoc((xmlChar *) "1.0"); if (ldat != 0) { const static int XT_LEN = 10; char xmltmp[XT_LEN]; // Scene ldat->children = xmlNewDocNode(ldat,0, (xmlChar *) FWEELIN_OUTPUT_SCENE_NAME,0); // Loops for (int i = 0; i < mapsize; i++) if (map[i] != 0 && map[i]->GetSaveStatus() == SAVE_DONE) { xmlNodePtr lp = xmlNewChild(ldat->children, 0, (xmlChar *) FWEELIN_OUTPUT_LOOP_NAME, 0); // Loop index snprintf(xmltmp,XT_LEN,"%d",i); xmlSetProp(lp,(xmlChar *) "loopid",(xmlChar *) xmltmp); // Loop hash (used to find the loop on disk) unsigned char *sh = map[i]->GetSaveHash(); GET_SAVEABLE_HASH_TEXT(sh); xmlSetProp(lp,(xmlChar *) "hash",(xmlChar *) hashtext); // Loop volume snprintf(xmltmp,XT_LEN,"%.5f",map[i]->vol); xmlSetProp(lp,(xmlChar *) "volume",(xmlChar *) xmltmp); } // Snapshots Snapshot *snaps = app->getSNAPS(); for (int i = 0; i < app->getCFG()->GetMaxSnapshots(); i++) { if (snaps[i].exists) { Snapshot *s = &snaps[i]; xmlNodePtr sp = xmlNewChild(ldat->children, 0, (xmlChar *) FWEELIN_OUTPUT_SNAPSHOT_NAME, 0); // Snapshot index snprintf(xmltmp,XT_LEN,"%d",i); xmlSetProp(sp,(xmlChar *) "snapid",(xmlChar *) xmltmp); // Name if (s->name != 0) xmlSetProp(sp,(xmlChar *) "name",(xmlChar *) s->name); for (int j = 0; j < s->numls; j++) { LoopSnapshot *ls = &(s->ls[j]); xmlNodePtr slp = xmlNewChild(sp, 0, (xmlChar *) FWEELIN_OUTPUT_LOOPSNAPSHOT_NAME, 0); // Loop index snprintf(xmltmp,XT_LEN,"%d",ls->l_idx); xmlSetProp(slp,(xmlChar *) "loopid",(xmlChar *) xmltmp); // Loop status snprintf(xmltmp,XT_LEN,"%d",ls->status); xmlSetProp(slp,(xmlChar *) "status",(xmlChar *) xmltmp); // Loop volume snprintf(xmltmp,XT_LEN,"%.5f",ls->l_vol); xmlSetProp(slp,(xmlChar *) "loopvol",(xmlChar *) xmltmp); // Trigger volume snprintf(xmltmp,XT_LEN,"%.5f",ls->t_vol); xmlSetProp(slp,(xmlChar *) "triggervol",(xmlChar *) xmltmp); } } } xmlSaveFormatFile(tmp,ldat,1); xmlFreeDoc(ldat); if (newScene) { // Add scene to browser so we can load it Browser *br = app->getBROWSER(B_Scene); if (br != 0) { app->setCURSCENE(app->getLOOPMGR()->AddSceneToBrowser(br,tmp)); br->AddDivisions(FWEELIN_FILE_BROWSER_DIVISION_TIME); } } printf("DISK: Close output.\n"); } } }; // If we are autosaving, we have to maintain a list of new loops to be saved void LoopManager::CheckSaveMap() { if (needs_saving_stamp != app->getTMAP()->GetLastUpdate()) { //printf("Rebuild save map.\n"); // No, rebuild! numsave = 0; savequeue = EventManager::DeleteQueue(savequeue); // Scan for loops that haven't yet been saved, add them to our list TriggerMap *tmap = app->getTMAP(); int mapsz = tmap->GetMapSize(); for (int i = 0; i < mapsz; i++) { Loop *l = tmap->GetMap(i); if (l != 0 && l->GetSaveStatus() == NO_SAVE) { // Loop exists but not saved-- add to our map LoopListEvent *ll = (LoopListEvent *) Event::GetEventByType(T_EV_LoopList,1); ll->l = l; numsave++; EventManager::QueueEvent(&savequeue,ll); } } // Now we've updated map needs_saving_stamp = tmap->GetLastUpdate(); } else { //printf("Stamp match: %lf\n",needs_saving_stamp); } } // Saves loop XML data & prepares to save loop audio void LoopManager::SetupSaveLoop(Loop *l, int l_idx, FILE **out, AudioBlock **b, AudioBlockIterator **i, nframes_t *len) { const static nframes_t LOOP_HASH_CHUNKSIZE = 10000; if (l->GetSaveStatus() == NO_SAVE) { // Now return blocks from this loop to save *b = l->blocks; #if 0 if (l->pulse != 0) // Loop is syncronized to a pulse- quantize length *len = l->pulse->QuantizeLength(l->blocks->GetTotalLen()); else #endif // Take length from blocks *len = l->blocks->GetTotalLen(); *i = 0; // Generate hash from audio data double hashtime = mygettime(); // *** Hopefully this won't take so long- or we may have to split it up // as we split up the write phase AudioBlockIterator *hashi = new AudioBlockIterator(l->blocks, LOOP_HASH_CHUNKSIZE); MD5_CTX md5gen; MD5_Init(&md5gen); char go = 1; char stereo = l->blocks->IsStereo(); do { nframes_t pos = hashi->GetTotalLength2Cur(), remaining = *len-pos; nframes_t num = MIN(LOOP_HASH_CHUNKSIZE,remaining); sample_t *ibuf[2]; if (stereo) { // Stereo hashi->GetFragment(&ibuf[0],&ibuf[1]); MD5_Update(&md5gen,ibuf[0],sizeof(sample_t) * num); MD5_Update(&md5gen,ibuf[1],sizeof(sample_t) * num); } else { // Mono hashi->GetFragment(&ibuf[0],0); MD5_Update(&md5gen,ibuf[0],sizeof(sample_t) * num); } if (remaining <= LOOP_HASH_CHUNKSIZE) { // Finished encoding go = 0; } else hashi->NextFragment(); } while (go); // Done- compute final hash MD5_Final(l->GetSaveHash(),&md5gen); l->SetSaveStatus(SAVE_DONE); delete hashi; double dhashtime = mygettime()-hashtime; printf("HASH TIME: %f ms\n",dhashtime * 1000); // Compose filenames & start writing char tmp[FWEELIN_OUTNAME_LEN]; GET_SAVEABLE_HASH_TEXT(l->GetSaveHash()); if (l->name == 0 || strlen(l->name) == 0) snprintf(tmp,FWEELIN_OUTNAME_LEN,"%s/%s-%s%s", app->getCFG()->GetLibraryPath(),FWEELIN_OUTPUT_LOOP_NAME, hashtext, app->getCFG()->GetAudioFileExt(app->getCFG()->GetLoopOutFormat())); else snprintf(tmp,FWEELIN_OUTNAME_LEN,"%s/%s-%s-%s%s", app->getCFG()->GetLibraryPath(),FWEELIN_OUTPUT_LOOP_NAME, hashtext,l->name, app->getCFG()->GetAudioFileExt(app->getCFG()->GetLoopOutFormat())); struct stat st; printf("DISK: Opening '%s' for saving.\n",tmp); if (stat(tmp,&st) == 0) { printf("DISK: ERROR: MD5 collision while saving loop- file exists!\n"); *b = 0; *len = 0; *i = 0; if (*out != 0) { fclose(*out); *out = 0; } } else { // Go save! *out = fopen(tmp,"wb"); if (*out == 0) { printf("DISK: ERROR: Couldn't open file! Does the folder exist and " "do you have write permission?\n"); *b = 0; *len = 0; *i = 0; if (*out != 0) { fclose(*out); *out = 0; } } else { // Add loop to browser so we can load it Browser *br = app->getBROWSER(B_Loop); if (br != 0) { AddLoopToBrowser(br,tmp); br->AddDivisions(FWEELIN_FILE_BROWSER_DIVISION_TIME); } // Main file open, now save loop XML data if (l->name == 0 || strlen(l->name) == 0) snprintf(tmp,FWEELIN_OUTNAME_LEN,"%s/%s-%s%s", app->getCFG()->GetLibraryPath(),FWEELIN_OUTPUT_LOOP_NAME, hashtext,FWEELIN_OUTPUT_DATA_EXT); else snprintf(tmp,FWEELIN_OUTNAME_LEN,"%s/%s-%s-%s%s", app->getCFG()->GetLibraryPath(),FWEELIN_OUTPUT_LOOP_NAME, hashtext,l->name,FWEELIN_OUTPUT_DATA_EXT); xmlDocPtr ldat = xmlNewDoc((xmlChar *) "1.0"); if (ldat != 0) { const static int XT_LEN = 10; char xmltmp[XT_LEN]; ldat->children = xmlNewDocNode(ldat,0, (xmlChar *) FWEELIN_OUTPUT_LOOP_NAME,0); // version snprintf(xmltmp,XT_LEN,"%d",LOOP_SAVE_FORMAT_VERSION); xmlSetProp(ldat->children,(xmlChar *) "version",(xmlChar *) xmltmp); // # beats snprintf(xmltmp,XT_LEN,"%ld",l->nbeats); xmlSetProp(ldat->children,(xmlChar *) "nbeats",(xmlChar *) xmltmp); // pulse length if (l->pulse == 0) xmlSetProp(ldat->children,(xmlChar *) "pulselen",(xmlChar *) "0"); else { snprintf(xmltmp,XT_LEN,"%d",l->pulse->GetLength()); xmlSetProp(ldat->children,(xmlChar *) "pulselen", (xmlChar *) xmltmp); } xmlSaveFormatFile(tmp,ldat,1); xmlFreeDoc(ldat); } } } } else { printf("DISK: WARNING: Loop marked already saved.\n"); *b = 0; *len = 0; *i = 0; if (*out != 0) { fclose(*out); *out = 0; } } }; // Loads loop XML data & prepares to load loop audio int LoopManager::SetupLoadLoop(FILE **in, char *smooth_end, Loop **new_loop, int l_idx, float l_vol, char *l_filename) { // Open up right file and begin loading char tmp[FWEELIN_OUTNAME_LEN]; codec format = UNKNOWN; // Try exact filename with all format types for (codec i = FIRST_FORMAT; i < END_OF_FORMATS; i = (codec) (i+1)) { snprintf(tmp,FWEELIN_OUTNAME_LEN,"%s%s",l_filename, app->getCFG()->GetAudioFileExt(i)); *in = fopen(tmp,"rb"); if (*in != 0) { printf("DISK: Open loop '%s'\n",tmp); bread->SetLoopType(i); format = i; break; } } if (*in == 0) { // No go, try wildcard search with all format types for (codec i = FIRST_FORMAT; i < END_OF_FORMATS; i = (codec) (i+1)) { snprintf(tmp,FWEELIN_OUTNAME_LEN,"%s*%s",l_filename, app->getCFG()->GetAudioFileExt(i)); glob_t globbuf; if (glob(tmp, 0, NULL, &globbuf) == 0) { for (size_t j = 0; *in == 0 && j < globbuf.gl_pathc; j++) { printf("DISK: Open loop '%s'\n",globbuf.gl_pathv[j]); *in = fopen(globbuf.gl_pathv[j],"rb"); } globfree(&globbuf); } if (*in != 0) { bread->SetLoopType(i); format = i; break; } } if (*in == 0) { printf("DISK: ERROR: Couldn't open loop '%s'!\n",tmp); return 1; } } // Main file open, now load loop XML data snprintf(tmp,FWEELIN_OUTNAME_LEN,"%s%s", l_filename,FWEELIN_OUTPUT_DATA_EXT); // Create loop data *new_loop = new Loop(0,0,1.0,l_vol,0,format); struct stat st; int result = 1; if (stat(tmp,&st) != 0) { // Try loading with wildcard snprintf(tmp,FWEELIN_OUTNAME_LEN,"%s*%s", l_filename,FWEELIN_OUTPUT_DATA_EXT); glob_t globbuf; if (glob(tmp, 0, NULL, &globbuf) == 0) { for (size_t i = 0; result != 0 && i < globbuf.gl_pathc; i++) { result = stat(globbuf.gl_pathv[i],&st); if (result == 0) strncpy(tmp,globbuf.gl_pathv[i], FWEELIN_OUTNAME_LEN); // Save the name for later } globfree(&globbuf); } if (result != 0) printf("DISK: WARNING: Loop data '%s' missing!\n" "I will load just the raw audio.\n",tmp); } else result = 0; xmlDocPtr ldat = 0; if (result == 0) ldat = xmlParseFile(tmp); if (ldat == 0) printf("DISK: WARNING: Loop data '%s' invalid!\n" "I will load just the raw audio.\n",tmp); else { xmlNode *root = xmlDocGetRootElement(ldat); // Extract hash from filename char fn_hash[FWEELIN_OUTNAME_LEN], loopname[FWEELIN_OUTNAME_LEN]; int baselen = strlen(app->getCFG()->GetLibraryPath()) + 1 + strlen(FWEELIN_OUTPUT_LOOP_NAME); if (!Saveable::SplitFilename(tmp,baselen,0,fn_hash,loopname, FWEELIN_OUTNAME_LEN)) { // Set hash from filename (*new_loop)->SetSaveableHashFromText(fn_hash); // GET_SAVEABLE_HASH_TEXT((*new_loop)->GetSaveHash()); // printf("md5: %s\n",hashtext); // First, check if this loop has already been loaded // by scanning for another loop with the same hash int dupidx; if ((dupidx = app->getTMAP()->ScanForHash((*new_loop)->GetSaveHash())) != -1) { printf("DISK: (DUPLICATE) Loop to load is already loaded at " "ID #%d.\n",dupidx); delete (*new_loop); *new_loop = 0; fclose(*in); *in = 0; return 1; } // Set loop name from filename (*new_loop)->name = new char[strlen(loopname)+1]; strcpy((*new_loop)->name,loopname); } else printf("DISK: Loop filename '%s' missing hash!\n",l_filename); // version xmlChar *n = xmlGetProp(root, (const xmlChar *) "version"); if (n != 0) { if (atoi((char *) n) >= 1) // New format of loop save, so smooth end *smooth_end = 1; else *smooth_end = 0; xmlFree(n); } else { *smooth_end = 0; printf("DISK: Old format loop '%s'- loading with length fix.\n", l_filename); } // # beats n = xmlGetProp(root, (const xmlChar *) "nbeats"); if (n != 0) { (*new_loop)->nbeats = atoi((char *) n); xmlFree(n); } // pulse length if ((n = xmlGetProp(root, (const xmlChar *) "pulselen")) != 0) { int plen = atoi((char *) n); if (plen != 0) { // Loop should be syncronized to a pulse of given length- (*new_loop)->pulse = CreatePulse(plen); } xmlFree(n); } xmlFreeDoc(ldat); // Don't call cleanup because another thread may have xml open // xmlCleanupParser(); } return 0; }; // Starts an interactive rename for a loop in memory void LoopManager::RenameLoop(int loopid) { if (renamer == 0) { Loop *l = GetSlot(loopid); if (l != 0) { if (CRITTERS) printf("RENAME: Loop: %p\n",l); rename_loop = l; renamer = new ItemRenamer(app,this,l->name); if (!renamer->IsRenaming()) { delete renamer; renamer = 0; rename_loop = 0; } } } }; void LoopManager::ItemRenamed(char *nw) { if (nw != 0) { // Rename on disk const static char *exts[] = {app->getCFG()->GetAudioFileExt(rename_loop->format), FWEELIN_OUTPUT_DATA_EXT}; char *old_filename = 0, *new_filename = 0; rename_loop->RenameSaveable(app->getCFG()->GetLibraryPath(), FWEELIN_OUTPUT_LOOP_NAME, rename_loop->name, nw, exts, 2, &old_filename, &new_filename); // We also need to rename in the loop browser if (app->getBROWSER(B_Loop) != 0) app->getBROWSER(B_Loop)-> ItemRenamedOnDisk(old_filename,new_filename,nw); if (old_filename != 0) delete[] old_filename; if (new_filename != 0) delete[] new_filename; // Rename in memory RenameLoop(rename_loop,nw); // We have to notify the LoopTray of the new name given LoopTray *tray = (LoopTray *) app->getBROWSER(B_Loop_Tray); if (tray != 0) tray->ItemRenamedFromOutside(rename_loop,nw); delete renamer; renamer = 0; rename_loop = 0; } else { // Rename was aborted delete renamer; renamer = 0; rename_loop = 0; } }; void LoopManager::GetWriteBlock(FILE **out, AudioBlock **b, AudioBlockIterator **i, nframes_t *len) { // If we are autosaving, check that our list is up to date if (autosave) CheckSaveMap(); // Do we have a loop to save? Event *cur = savequeue, *prev = 0; if (cursave >= numsave) { numsave = 0; cursave = 0; } int l_idx = 0; char go = 1, advance = 1; while (cur != 0 && go) { if (cur->GetType() == T_EV_LoopList) { // Loop in save queue- does it exist and is it ready to save? if ((l_idx = app->getTMAP()->SearchMap(((LoopListEvent *) cur)->l)) == -1 || GetStatus(l_idx) == T_LS_Overdubbing || GetStatus(l_idx) == T_LS_Recording) { if (l_idx == -1) { printf("DEBUG: Loop no longer exists- abort save!\n"); EventManager::RemoveEvent(&savequeue,prev,&cur); advance = 0; } // If we are overdubbing or recording, just ignore this loop // we will come back to it } else { go = 0; // Found a suitable loop to save- stop! advance = 0; } } else { if (cur->GetType() == T_EV_SceneMarker) { // Scene marker in queue indicates we need to save a scene- if (cur == savequeue) { // No loops are waiting to be saved.. go app->getTMAP()->GoSave(((SceneMarkerEvent *) cur)->s_filename); EventManager::RemoveEvent(&savequeue,prev,&cur); cursave++; advance = 0; } } } // Move to next item if (advance) { prev = cur; cur = cur->next; } else advance = 1; } if (cur != 0) { if (cur->GetType() != T_EV_LoopList) { printf("DISK: ERROR: LoopList event type mismatch!\n"); EventManager::RemoveEvent(&savequeue,prev,&cur); } else { // Remove from list Loop *curl = ((LoopListEvent *) cur)->l; EventManager::RemoveEvent(&savequeue,prev,&cur); // Open up right files, save data & setup for audio save SetupSaveLoop(curl,l_idx,out,b,i,len); cursave++; } } else { // No loops to save right now *b = 0; *len = 0; *i = 0; if (*out != 0) { fclose(*out); *out = 0; } } } // We receive calls periodically for loading of loops- void LoopManager::GetReadBlock(FILE **in, char *smooth_end) { if (curload >= numload) { numload = 0; curload = 0; } // Do we have a loop to load? Event *cur = loadqueue; if (cur != 0) { if (cur->GetType() == T_EV_LoopList) { // Open up right files, load data & setup for audio load LoopListEvent *ll = (LoopListEvent *) cur; if (SetupLoadLoop(in,smooth_end, &ll->l,ll->l_idx,ll->l_vol,ll->l_filename)) { // Not a loop or there was an error in loading EventManager::RemoveEvent(&loadqueue,0,&cur); curload++; } } else { // Not a loop- remove EventManager::RemoveEvent(&loadqueue,0,&cur); curload++; } } else { // Nothing to load right now if (*in != 0) { printf("DISK: (Load) Nothing to load- close input!\n"); fclose(*in); *in = 0; } } } void LoopManager::ReadComplete(AudioBlock *b) { curload++; // Add loop to triggermap and remove from load queue Event *cur = loadqueue; if (cur == 0 || cur->GetType() != T_EV_LoopList) printf("DISK: ERROR: Load list mismatch!\n"); else { if (b == 0) printf("DISK: ERROR: .. during load!\n"); else { LoopListEvent *ll = (LoopListEvent *) cur; // Put blocks into loop ll->l->blocks = b; if (app->getTMAP()->GetMap(ll->l_idx) != 0) { // Loop ID is full. Choose another int newidx = app->getTMAP()->GetFirstFree(default_looprange.lo, default_looprange.hi); if (newidx != -1) { printf("LOOP MANAGER: LoopID #%d full, got new ID: #%d!\n", ll->l_idx,newidx); ll->l_idx = newidx; } else { printf("LOOP MANAGER: No free loopids in default placement range.\n" "I will erase the loop at id #%d.\n",ll->l_idx); DeleteLoop(ll->l_idx); } } // Add loop to our map app->getTMAP()->SetMap(ll->l_idx,ll->l); lastindex = ll->l_idx; // Set this so we can make a pulse from this loop } // And remove from load list EventManager::RemoveEvent(&loadqueue,0,&cur); } } void LoopManager::StripePulseOn(Pulse *pulse) { app->getBMG()->StripeBlockOn(pulse,app->getAMPEAKS(), app->getAMPEAKSI()); app->getBMG()->StripeBlockOn(pulse,app->getAUDIOMEM(), app->getAUDIOMEMI()); } void LoopManager::StripePulseOff(Pulse *pulse) { app->getBMG()->StripeBlockOff(pulse,app->getAMPEAKS()); app->getBMG()->StripeBlockOff(pulse,app->getAUDIOMEM()); } // Creates a pulse of the given length in the first available slot, // if none already exists of the right length Pulse *LoopManager::CreatePulse(nframes_t len) { // First, check to see if we have a pulse of the right length- int i; for (i = 0; i < MAX_PULSES && (pulses[i] == 0 || pulses[i]->GetLength() != len); i++); if (i < MAX_PULSES) // Found it, use this pulse return pulses[i]; else { // No pulse found of right length-- create a new one for (i = 0; i < MAX_PULSES && pulses[i] != 0; i++); if (i < MAX_PULSES) { app->getRP()->AddChild(pulses[i] = new Pulse(app,len,0), ProcessorItem::TYPE_HIPRIORITY); StripePulseOn(pulses[i]); curpulseindex = i; // Send MIDI start for pulse GetCurPulse()->SetMIDIClock(1); return pulses[i]; } else // No space for a new pulse! return 0; } }; // Create a time pulse around the specified index // The length of the loop on the specified index becomes // a time constant around which other loops center themselves // subdivide the length of the loop by subdivide to get the core pulse void LoopManager::CreatePulse(int index, int pulseindex, int sub) { Loop *cur = app->getTMAP()->GetMap(index); if (cur != 0 && (status[index] == T_LS_Off || status[index] == T_LS_Playing || status[index] == T_LS_Overdubbing)) { // Set pulse length based on loop length nframes_t len = GetLength(index); if (len != 0) { // Create iterator len /= sub; // Length subdivide nframes_t startpos = 0; // So set the starting pulse position based on where loop is playing if (status[index] == T_LS_Playing) startpos = ((PlayProcessor *) plist[index])->GetPlayedLength() % len; else if (status[index] == T_LS_Overdubbing) startpos = ((RecordProcessor *) plist[index])-> GetRecordedLength() % len; app->getRP()->AddChild(cur->pulse = pulses[pulseindex] = new Pulse(app,len,startpos), ProcessorItem::TYPE_HIPRIORITY); StripePulseOn(cur->pulse); curpulseindex = pulseindex; cur->nbeats = sub; // Set # of beats in the loop // Send MIDI start for pulse GetCurPulse()->SetMIDIClock(1); // Now reconfigure processor on this index to be synced to the new pulse if (status[index] == T_LS_Playing) ((PlayProcessor *) plist[index])->SyncUp(); else if (status[index] == T_LS_Overdubbing) ((RecordProcessor *) plist[index])->SyncUp(); } } } // Taps a pulse- starting at the downbeat- if newlen is nonzero, the pulse's // length is adjusted to reflect the length between taps- and a new pulse // is created if none exists void LoopManager::TapPulse(int pulseindex, char newlen) { // If more than TIMEOUT_RATIO * the current pulse length // frames have passed since the last tap, a new length is not defined const static float TAP_NEWLEN_TIMEOUT_RATIO = 5.0, //2.0, // Higher graduation makes tempo more stable against changes TAP_NEWLEN_GRADUATION = 0.0, //0.5, // Tolerance for rejecting tap tempo changes- as fraction of current length TAP_NEWLEN_REJECT_TOLERANCE = 1.0; //0.3; if (pulseindex >= 0 || pulseindex < MAX_PULSES) { Pulse *cur = pulses[pulseindex]; if (cur == 0) { if (newlen) { // New pulse- tap now!- set zero length for now cur = pulses[pulseindex] = new Pulse(app,0,0); cur->stopped = 1; cur->prevtap = app->getRP()->GetSampleCnt(); //cur->SwitchMetronome(1); app->getRP()->AddChild(cur,ProcessorItem::TYPE_HIPRIORITY); StripePulseOn(cur); curpulseindex = pulseindex; } } else { // Test position of axis char nextdownbeat = 0; if (cur->GetPct() >= 0.5) nextdownbeat = 1; // Old pulse- tap now! if (newlen) { // Redefine length from tap nframes_t oldlen = cur->GetLength(), newtap = app->getRP()->GetSampleCnt(), newlen = newtap - cur->prevtap; // .. only if the new length isn't outrageous if (oldlen < 64) cur->SetLength(newlen); else if (newlen < oldlen * TAP_NEWLEN_TIMEOUT_RATIO) { // 2nd outrageous length check float ratio = (float) MIN(newlen,oldlen)/MAX(newlen,oldlen); if (ratio > 1.0-TAP_NEWLEN_REJECT_TOLERANCE) cur->SetLength((nframes_t) (oldlen*TAP_NEWLEN_GRADUATION + newlen*(1-TAP_NEWLEN_GRADUATION))); } cur->prevtap = newtap; //cur->SwitchMetronome(1); cur->stopped = 0; } if (nextdownbeat) // Tap to beginning- with wrap cur->Wrap(); else // Tap to beginning- no wrap cur->SetPos(0); // Notify external transport that we have moved app->getAUDIO()->RelocateTransport(0); } } else printf("CORE: Invalid pulse #%d, ignoring.\n",pulseindex); } void LoopManager::SwitchMetronome(int pulseindex, char active) { if (pulseindex >= 0 || pulseindex < MAX_PULSES) { Pulse *cur = pulses[pulseindex]; if (cur != 0) cur->SwitchMetronome(active); else printf("CORE: No pulse at #%d, ignoring.\n",pulseindex); } else printf("CORE: Invalid pulse #%d, ignoring.\n",pulseindex); } void LoopManager::DeletePulse(int pulseindex) { if (pulseindex < 0 || pulseindex >= MAX_PULSES) { printf("CORE: Invalid pulse #%d, ignoring.\n",pulseindex); return; } if (pulses[pulseindex] != 0) { // Stop striping beats from this pulse StripePulseOff(pulses[pulseindex]); // Erase all loops which are attached to this pulse-- or we'll have // references pointing to the deleted pulse int nt = app->getCFG()->GetNumTriggers(); for (int i = 0; i < nt; i++) if (GetPulse(i) == pulses[pulseindex]) DeleteLoop(i); // Erase this pulse app->getRP()->DelChild(pulses[pulseindex]); pulses[pulseindex] = 0; } } Pulse *LoopManager::GetPulse(int index) { Loop *lp = GetSlot(index); if (lp != 0) return lp->pulse; else return 0; } // Move the loop at specified index to another index // only works if target index is empty // returns 1 if success int LoopManager::MoveLoop (int src, int tgt) { Loop *srloop = app->getTMAP()->GetMap(src); if (srloop != 0) { Loop *tgtloop = app->getTMAP()->GetMap(tgt); if (tgtloop == 0) { app->getTMAP()->SetMap(tgt,srloop); app->getTMAP()->SetMap(src,0); plist[tgt] = plist[src]; plist[src] = 0; status[tgt] = status[src]; status[src] = T_LS_Off; waitactivate[tgt] = waitactivate[src]; waitactivate[src] = 0; waitactivate_shot[tgt] = waitactivate_shot[src]; waitactivate_shot[src] = 0; waitactivate_vol[tgt] = waitactivate_vol[src]; waitactivate_vol[src] = 0.; waitactivate_od[tgt] = waitactivate_od[src]; waitactivate_od[src] = 0; waitactivate_od_fb[tgt] = waitactivate_od_fb[src]; waitactivate_od_fb[src] = 0; for (int i = 0; i < LAST_REC_COUNT; i++) if (lastrecidx[i] == src) lastrecidx[i] = tgt; if (lastindex == src) lastindex = tgt; UpdateLoopLists_ItemMoved(src,tgt); } else return 0; } else return 0; return 1; } // Delete the loop at the specified index.. // Not RT safe! // Threadsafe void LoopManager::DeleteLoop (int index) { LockLoops(); Loop *lp = app->getTMAP()->GetMap(index); if (lp != 0) { // First, zero the map at the given index // To prevent anybody from attaching to the loop as we delete it app->getTMAP()->SetMap(index, 0); } if (plist[index] != 0) { // We have a processor on this loop! Stop it! if (status[index] == T_LS_Recording) { RecordProcessor *recp = (RecordProcessor *) plist[index]; recp->AbortRecording(); AudioBlock *recblk = recp->GetFirstRecordedBlock(); if (recblk != 0) { app->getBMG()->RefDeleted(recblk); recblk->DeleteChain(); // *** Not RT Safe if (lp != 0) lp->blocks = 0; } numrecordingloops--; } else if (status[index] == T_LS_Overdubbing) numrecordingloops--; // Remove the record/play processor app->getRP()->DelChild(plist[index]); plist[index] = 0; status[index] = T_LS_Off; waitactivate[index] = 0; waitactivate_shot[index] = 0; waitactivate_vol[index] = 0.; waitactivate_od[index] = 0; waitactivate_od_fb[index] = 0; } if (lp != 0) { if (lp->blocks != 0) { // Notify any blockmanagers working on this loop's audio to end! app->getBMG()->RefDeleted(lp->blocks); lp->blocks->DeleteChain(); // *** Not RT Safe } delete lp; // *** Not RT Safe numloops--; // Update looplists/scenes to ensure that loop is removed from them UpdateLoopLists_ItemRemoved(index); } UnlockLoops(); } void LoopManager::UpdateLoopLists_ItemAdded (int l_idx) { // Update... // Snapshots Snapshot *snaps = app->getSNAPS(); for (int i = 0; i < app->getCFG()->GetMaxSnapshots(); i++) { if (snaps[i].exists) { Snapshot *s = &snaps[i]; char go = 1; for (int j = 0; go && j < s->numls; j++) if (s->ls[j].l_idx == l_idx) go = 0; if (go) { // Loop index not present in snapshot- add, defaulting to loop off LoopSnapshot *newls = 0; newls = new LoopSnapshot[s->numls+1]; memcpy(newls,s->ls,sizeof(LoopSnapshot) * s->numls); LoopSnapshot *n = &newls[s->numls]; n->l_idx = l_idx; n->status = T_LS_Off; n->l_vol = GetLoopVolume(l_idx); n->t_vol = 0.; delete[] s->ls; s->ls = newls; s->numls = s->numls+1; } } } }; void LoopManager::UpdateLoopLists_ItemRemoved (int l_idx) { // Update... // Selection sets for (int i = 0; i < NUM_LOOP_SELECTION_SETS; i++) { LoopList **ll = app->getLOOPSEL(i); *ll = LoopList::Remove(*ll,l_idx); } // Snapshots Snapshot *snaps = app->getSNAPS(); for (int i = 0; i < app->getCFG()->GetMaxSnapshots(); i++) { if (snaps[i].exists) { Snapshot *s = &snaps[i]; char go = 1; for (int j = 0; go && j < s->numls; j++) if (s->ls[j].l_idx == l_idx) { // Remove loop from list LoopSnapshot *newls = 0; if (s->numls > 1) { newls = new LoopSnapshot[s->numls-1]; // All elements preceding j memcpy(newls,s->ls,sizeof(LoopSnapshot) * j); // & following memcpy(&newls[j],&(s->ls[j+1]), sizeof(LoopSnapshot) * (s->numls-j-1)); } delete[] s->ls; s->ls = newls; s->numls = s->numls-1; go = 0; // No more checking in this snapshot } } } }; void LoopManager::UpdateLoopLists_ItemMoved (int l_idx_old, int l_idx_new) { // Update... // Selection sets for (int i = 0; i < NUM_LOOP_SELECTION_SETS; i++) { LoopList **ll = app->getLOOPSEL(i), *prev, *found = LoopList::Scan(*ll,l_idx_old,&prev); // Update index if (found != 0) found->l_idx = l_idx_new; } // Snapshots Snapshot *snaps = app->getSNAPS(); for (int i = 0; i < app->getCFG()->GetMaxSnapshots(); i++) { if (snaps[i].exists) { Snapshot *s = &snaps[i]; for (int j = 0; j < s->numls; j++) if (s->ls[j].l_idx == l_idx_old) s->ls[j].l_idx = l_idx_new; } } }; // Trigger the loop at index within the map // The exact behavior varies depending on what is already happening with // this loop and the settings passed- see .fweelin.rc // *** Not RT Safe void LoopManager::Activate (int index, char shot, float vol, nframes_t ofs, char overdub, float *od_feedback) { // printf("ACTIVATE plist %p status %d\n",plist[index],status[index]); if (plist[index] != 0) { // We have a problem, we already have a processor on this index. // Queue the requested activate waitactivate[index] = 1; waitactivate_shot[index] = shot; waitactivate_vol[index] = vol; waitactivate_od[index] = overdub; waitactivate_od_fb[index] = od_feedback; return; } Loop *lp = app->getTMAP()->GetMap(index); if (lp == 0) { // Record a new loop float *inputvol = &(app->getRP()->inputvol); // Where to get input vol from app->getRP()->AddChild(plist[index] = new RecordProcessor(app,app->getISET(),inputvol, GetCurPulse(), app->getAUDIOMEM(), app->getAUDIOMEMI(), app->getCFG()-> loop_peaksavgs_chunksize)); numrecordingloops++; status[index] = T_LS_Recording; // Keep track of this index in our record of last recorded indexes for (int i = LAST_REC_COUNT-1; i > 0; i--) lastrecidx[i] = lastrecidx[i-1]; lastrecidx[0] = index; } else { // A loop exists at that index if (overdub) { // Overdub float *inputvol = &(app->getRP()->inputvol); // Get input vol from main app->getRP()->AddChild(plist[index] = new RecordProcessor(app, app->getISET(),inputvol, lp,vol,ofs,od_feedback)); numrecordingloops++; status[index] = T_LS_Overdubbing; } else { // Play app->getRP()->AddChild(plist[index] = new PlayProcessor(app,lp,vol,ofs)); status[index] = T_LS_Playing; } } } // *** Not RT Safe void LoopManager::Deactivate (int index) { if (plist[index] == 0) { // We have a problem, there is supposed to be a processor here! printf("Nothing happening on index %d to deactivate\n",index); return; } // If we recorded something new to this index, store it in the map if (status[index] == T_LS_Recording && app->getTMAP()->GetMap(index) == 0) { // *** Perhaps make a function in RecordProcessor called // ** 'createloop'.. which does the encapsulation from the blocks Pulse *curpulse = 0; if (curpulseindex != -1) curpulse = pulses[curpulseindex]; // Adjust newloop volume so that it will match the volume // it was heard as-- since output volume does not scale // the initial monitor but does scale loops, we need to adjust float adjustednewloopvol = newloopvol / GetOutputVolume(); //printf("newlp from plist: %p\n",plist[index]); Loop *newlp = new Loop(((RecordProcessor *) plist[index])->GetFirstRecordedBlock(), curpulse,1.0,adjustednewloopvol, ((RecordProcessor *) plist[index])->GetNBeats(), app->getCFG()->GetLoopOutFormat()); app->getTMAP()->SetMap(index, newlp); UpdateLoopLists_ItemAdded(index); numloops++; lastindex = index; // Record processor will broadcast when it is ready to end! ((RecordProcessor *) plist[index])->End(); } else if (status[index] == T_LS_Overdubbing) { // Overdubbing record processor will end immediately and broadcast // EndRecord event ((RecordProcessor *) plist[index])->End(); } else if (status[index] == T_LS_Playing) { // Stop playing/overdubbing app->getRP()->DelChild(plist[index]); plist[index] = 0; status[index] = T_LS_Off; } } void LoopManager::SaveLoop(int index) { Loop *l = app->getTMAP()->GetMap(index); if (l != 0) l->Save(app); }; // Saves a new scene void LoopManager::SaveNewScene() { TriggerMap *tm = app->getTMAP(); if (tm != 0) tm->Save(app); }; // Saves over current scene void LoopManager::SaveCurScene() { if (app->getCURSCENE() == 0) SaveNewScene(); else { TriggerMap *tm = app->getTMAP(); if (tm != 0) tm->Save(app,app->getCURSCENE()->filename); } }; // Load loop from disk into the given index void LoopManager::LoadLoop(char *filename, int index, float vol) { AddLoopToLoadQueue(filename,index,vol); }; // Load scene from disk void LoopManager::LoadScene(SceneBrowserItem *i) { char *filename = i->filename; // Load XML data for scene char tmp[FWEELIN_OUTNAME_LEN], tmp2[FWEELIN_OUTNAME_LEN]; snprintf(tmp,FWEELIN_OUTNAME_LEN,"%s%s", filename,FWEELIN_OUTPUT_DATA_EXT); xmlDocPtr dat = xmlParseFile(tmp); if (dat == 0) printf("DISK: ERROR: Scene data '%s' invalid or missing!\n",tmp); else { xmlNode *root = xmlDocGetRootElement(dat); if (!root || !root->name || xmlStrcmp(root->name,(const xmlChar *) FWEELIN_OUTPUT_SCENE_NAME)) printf("DISK: ERROR: Scene data '%s' bad format!\n",tmp); else { for (xmlNode *cur_node = root->children; cur_node != NULL; cur_node = cur_node->next) { if ((!xmlStrcmp(cur_node->name, (const xmlChar *) FWEELIN_OUTPUT_LOOP_NAME))) { // Loop within scene-- read int l_idx = loadloopid; float vol = 1.0; // Loopid xmlChar *n = xmlGetProp(cur_node, (const xmlChar *) "loopid"); if (n != 0) { l_idx = atoi((char *) n); xmlFree(n); } // Volume if ((n = xmlGetProp(cur_node, (const xmlChar *) "volume")) != 0) { vol = atof((char *) n); xmlFree(n); } // Hash if ((n = xmlGetProp(cur_node, (const xmlChar *) "hash")) != 0) { // Compose loop filename from hash snprintf(tmp2,FWEELIN_OUTNAME_LEN,"%s/%s-%s", app->getCFG()->GetLibraryPath(), FWEELIN_OUTPUT_LOOP_NAME,n); xmlFree(n); // Load the loop into the specified index printf(" (loopid %d vol %.5f filename %s)\n", l_idx,vol,tmp2); LoadLoop(tmp2,l_idx,vol); // sleep(2); } else printf("DISK: Scene definition for loop (id %d) has missing " "hash!\n",l_idx); } else if ((!xmlStrcmp(cur_node->name, (const xmlChar *) FWEELIN_OUTPUT_SNAPSHOT_NAME))) { // Snapshot within scene-- read int snapid = 0; char sgo = 1; // Snapshot index xmlChar *n = xmlGetProp(cur_node, (const xmlChar *) "snapid"); if (n != 0) { snapid = atoi((char *) n); xmlFree(n); } // Check if snapshot exists- if so, find another slot if (app->getSNAP(snapid) == 0 || app->getSNAP(snapid)->exists) { Snapshot *snaps = app->getSNAPS(); char go = 1; int i = 0; while (go && i < app->getCFG()->GetMaxSnapshots()) { if (!snaps[i].exists) go = 0; else i++; } if (go) { printf("DISK: No space to load snapshot in scene-\n" "please raise maximum # of snapshots in configuration!\n"); sgo = 0; } else snapid = i; } if (sgo) { // Name n = xmlGetProp(cur_node, (const xmlChar *) "name"); printf(" (snapshot: %s)\n",n); Snapshot *s = app->LoadSnapshot(snapid,(char *) n); if (n != 0) xmlFree(n); // Now, count loop snapshots given in snapshot if (s != 0) { int numls = 0; for (xmlNode *ls_node = cur_node->children; ls_node != NULL; ls_node = ls_node->next) { if ((!xmlStrcmp(ls_node->name, (const xmlChar *) FWEELIN_OUTPUT_LOOPSNAPSHOT_NAME))) { numls++; } } printf(" (%d loops in snapshot)\n",numls); // Setup & load loop snapshots s->numls = numls; if (numls > 0) s->ls = new LoopSnapshot[numls]; else s->ls = 0; int i = 0; for (xmlNode *ls_node = cur_node->children; ls_node != NULL; ls_node = ls_node->next) { if ((!xmlStrcmp(ls_node->name, (const xmlChar *) FWEELIN_OUTPUT_LOOPSNAPSHOT_NAME))) { LoopSnapshot *ls = &(s->ls[i]); // Loop index xmlChar *nn = xmlGetProp(ls_node, (const xmlChar *) "loopid"); if (nn != 0) { ls->l_idx = atoi((char *) nn); xmlFree(nn); } // Loop status nn = xmlGetProp(ls_node, (const xmlChar *) "status"); if (nn != 0) { ls->status = (LoopStatus) atoi((char *) nn); xmlFree(nn); } // Loop volume nn = xmlGetProp(ls_node, (const xmlChar *) "loopvol"); if (nn != 0) { ls->l_vol = atof((char *) nn); xmlFree(nn); } // Trigger volume nn = xmlGetProp(ls_node, (const xmlChar *) "triggervol"); if (nn != 0) { ls->t_vol = atof((char *) nn); xmlFree(nn); } i++; } } } } } } // Now, remember this scene is loaded app->setCURSCENE(i); } } xmlFreeDoc(dat); // Don't call cleanup because another thread may have xml open // xmlCleanupParser(); }; void LoopManager::ReceiveEvent(Event *ev, EventProducer *from) { switch (ev->GetType()) { case T_EV_EndRecord : // Recording has ended on one of the RecordProcessors- find it! for (int i = 0; i < app->getTMAP()->GetMapSize(); i++) if (plist[i] == from) { // Should we keep this recording if (!((EndRecordEvent *) ev)->keeprecord) { DeleteLoop(i); // No } else { nframes_t playofs = 0; if (status[i] == T_LS_Recording) { // Adjust number of beats in loop based on the recording app->getTMAP()->GetMap(i)->nbeats = ((RecordProcessor *) plist[i])->GetNBeats(); Pulse *recsync = ((RecordProcessor *) plist[i])->GetPulse(); // Sync recording may have ended late, so start play where we // left off if (recsync != 0) playofs = recsync->GetPos(); } else if (status[i] == T_LS_Overdubbing) { // Start play at position where overdub left off playofs = ((RecordProcessor *) plist[i])->GetRecordedLength(); } // Remove recordprocessor from chain app->getRP()->DelChild(plist[i]); numrecordingloops--; status[i] = T_LS_Off; plist[i] = 0; // Check if we need to activate a playprocessor if (waitactivate[i]) { waitactivate[i] = 0; // Activate is not RT safe (new processor alloc) // So this event thread had better be nonRT! Activate(i,waitactivate_shot[i],waitactivate_vol[i], playofs, waitactivate_od[i],waitactivate_od_fb[i]); } } } break; case T_EV_ToggleDiskOutput : { // OK! if (CRITTERS) printf("CORE: Received ToggleDiskOutputEvent\n"); app->ToggleDiskOutput(); } break; case T_EV_ToggleSelectLoop : { ToggleSelectLoopEvent *sev = (ToggleSelectLoopEvent *) ev; // OK! if (CRITTERS) printf("CORE: Received ToggleSelectLoopEvent: Set %d Loop ID %d\n", sev->setid,sev->loopid); LoopList **ll = app->getLOOPSEL(sev->setid); if (ll != 0) { // Get loop with id Loop *l = app->getTMAP()->GetMap(sev->loopid); if (l != 0) { LoopList *prev; LoopList *exists = LoopList::Scan(*ll,sev->loopid,&prev); if (exists != 0) { // printf("REMOVE!\n"); *ll = LoopList::Remove(*ll,exists,prev); l->ChangeSelectedCount(-1); } else { // printf("ADD!\n"); *ll = LoopList::AddBegin(*ll,sev->loopid); l->ChangeSelectedCount(1); } } } else printf("CORE: Invalid set id #%d when selecting loop\n",sev->setid); } break; case T_EV_SelectOnlyPlayingLoops : { SelectOnlyPlayingLoopsEvent *sev = (SelectOnlyPlayingLoopsEvent *) ev; // OK! if (CRITTERS) printf("CORE: Received SelectOnlyPlayingLoopsEvent: Set %d [%s]\n", sev->setid,(sev->playing ? "PLAYING" : "IDLE")); LoopList **ll = app->getLOOPSEL(sev->setid); if (ll != 0) { // Scan all loops for playing loops for (int i = 0; i < app->getCFG()->GetNumTriggers(); i++) { Loop *l = app->getTMAP()->GetMap(i); if (GetStatus(i) == T_LS_Overdubbing || GetStatus(i) == T_LS_Playing) { if (l != 0) { // Loop exists, and it's playing! LoopList *prev; LoopList *exists = LoopList::Scan(*ll,i,&prev); if (!sev->playing && exists != 0) { // printf("REMOVE!\n"); *ll = LoopList::Remove(*ll,exists,prev); l->ChangeSelectedCount(-1); } else if (sev->playing && exists == 0) { // printf("ADD!\n"); *ll = LoopList::AddBegin(*ll,i); l->ChangeSelectedCount(1); } } } else if (app->getTMAP()->GetMap(i) != 0) { // Loop exists, but not playing/overdubbing LoopList *prev; LoopList *exists = LoopList::Scan(*ll,i,&prev); if (sev->playing && exists != 0) { // printf("REMOVE!\n"); *ll = LoopList::Remove(*ll,exists,prev); l->ChangeSelectedCount(-1); } else if (!sev->playing && exists == 0) { // printf("ADD!\n"); *ll = LoopList::AddBegin(*ll,i); l->ChangeSelectedCount(1); } } } } else printf("CORE: Invalid set id #%d when selecting loop\n",sev->setid); } break; case T_EV_SelectAllLoops : { SelectAllLoopsEvent *sev = (SelectAllLoopsEvent *) ev; // OK! if (CRITTERS) printf("CORE: Received SelectAllLoopsEvent: Set %d [%s]\n", sev->setid,(sev->select ? "SELECT" : "UNSELECT")); LoopList **ll = app->getLOOPSEL(sev->setid); if (ll != 0) { // Scan all loops for (int i = 0; i < app->getCFG()->GetNumTriggers(); i++) { Loop *l = app->getTMAP()->GetMap(i); if (l != 0) { // Loop exists in map LoopList *prev; LoopList *exists = LoopList::Scan(*ll,i,&prev); if (!sev->select && exists != 0) { // Unselect loops- remove loop from list // printf("REMOVE!\n"); *ll = LoopList::Remove(*ll,exists,prev); l->ChangeSelectedCount(-1); } else if (sev->select && exists == 0) { // Select loops- add loop to list // printf("ADD!\n"); *ll = LoopList::AddBegin(*ll,i); l->ChangeSelectedCount(1); } } } } else printf("CORE: Invalid set id #%d when selecting loop\n",sev->setid); } break; case T_EV_InvertSelection : { InvertSelectionEvent *sev = (InvertSelectionEvent *) ev; // OK! if (CRITTERS) printf("CORE: Received InvertSelectionEvent: Set %d\n",sev->setid); LoopList **ll = app->getLOOPSEL(sev->setid); if (ll != 0) { // Scan all loops for (int i = 0; i < app->getCFG()->GetNumTriggers(); i++) { Loop *l = app->getTMAP()->GetMap(i); if (l != 0) { // Loop exists in map LoopList *prev; LoopList *exists = LoopList::Scan(*ll,i,&prev); if (exists != 0) { // Loop exists in list- remove // printf("REMOVE!\n"); *ll = LoopList::Remove(*ll,exists,prev); l->ChangeSelectedCount(-1); } else if (exists == 0) { // Loop not in list- add // printf("ADD!\n"); *ll = LoopList::AddBegin(*ll,i); l->ChangeSelectedCount(1); } } } } else printf("CORE: Invalid set id #%d when selecting loop\n",sev->setid); } break; case T_EV_TriggerSnapshot : { TriggerSnapshotEvent *sev = (TriggerSnapshotEvent *) ev; // OK! if (CRITTERS) printf("CORE: Received TriggerSnapshotEvent: Snapshot #%d\n", sev->snapid); if (app->TriggerSnapshot(sev->snapid)) printf("CORE: Invalid snapshot #%d- can't trigger\n",sev->snapid); } break; case T_EV_CreateSnapshot : { CreateSnapshotEvent *sev = (CreateSnapshotEvent *) ev; // OK! if (CRITTERS) printf("CORE: Received CreateSnapshotEvent: Snapshot #%d\n", sev->snapid); if (app->CreateSnapshot(sev->snapid) == 0) printf("CORE: Invalid snapshot #%d- can't create\n",sev->snapid); } break; case T_EV_RenameSnapshot : { RenameSnapshotEvent *sev = (RenameSnapshotEvent *) ev; // OK! if (CRITTERS) printf("CORE: Received RenameSnapshotEvent: Snapshot #%d\n", sev->snapid); FloDisplaySnapshots *sdisp = (FloDisplaySnapshots *) app->getCFG()->GetDisplayByType(FD_Snapshots); if (sdisp != 0) sdisp->Rename(sev->snapid); } break; case T_EV_SetSelectedLoopsTriggerVolume : { SetSelectedLoopsTriggerVolumeEvent *sev = (SetSelectedLoopsTriggerVolumeEvent *) ev; // OK! if (CRITTERS) printf("CORE: Received SetSelectedLoopsTriggerVolumeEvent: Set %d: Volume %f\n", sev->setid,sev->vol); LoopList **ll = app->getLOOPSEL(sev->setid); if (ll != 0) { LoopList *cur = *ll; while (cur != 0) { SetTriggerVol(cur->l_idx,sev->vol); cur = cur->next; } } else printf("CORE: Invalid set id #%d when selecting loop\n",sev->setid); } break; case T_EV_AdjustSelectedLoopsAmp : { AdjustSelectedLoopsAmpEvent *sev = (AdjustSelectedLoopsAmpEvent *) ev; // OK! if (CRITTERS) printf("CORE: Received AdjustSelectedLoopsAmpEvent: Set %d: " "Amp factor %f\n", sev->setid,sev->ampfactor); LoopList **ll = app->getLOOPSEL(sev->setid); if (ll != 0) { LoopList *cur = *ll; while (cur != 0) { SetLoopVolume(cur->l_idx, sev->ampfactor * GetLoopVolume(cur->l_idx)); cur = cur->next; } } else printf("CORE: Invalid set id #%d when selecting loop\n",sev->setid); } break; case T_EV_EraseSelectedLoops : { EraseSelectedLoopsEvent *sev = (EraseSelectedLoopsEvent *) ev; // OK! if (CRITTERS) printf("CORE: Received EraseSelectedLoopsEvent: Set: %d\n",sev->setid); LoopList **ll = app->getLOOPSEL(sev->setid); if (ll != 0) { LoopList *cur = *ll; while (cur != 0) { DeleteLoop(cur->l_idx); cur = cur->next; } } else printf("CORE: Invalid set id #%d when erasing selected loops\n", sev->setid); } break; case T_EV_SetAutoLoopSaving : { SetAutoLoopSavingEvent *sev = (SetAutoLoopSavingEvent *) ev; // OK! if (CRITTERS) printf("CORE: Received SetAutoLoopSavingEvent (%s)\n", (sev->save ? "on" : "off")); SetAutoLoopSaving(sev->save); } break; case T_EV_SaveLoop : { SaveLoopEvent *sev = (SaveLoopEvent *) ev; // OK! if (CRITTERS) printf("CORE: Received SaveLoopEvent (%d)\n",sev->index); SaveLoop(sev->index); } break; case T_EV_SaveNewScene : { // OK! if (CRITTERS) printf("CORE: Received SaveNewSceneEvent\n"); SaveNewScene(); } break; case T_EV_SaveCurrentScene : { // OK! if (CRITTERS) printf("CORE: Received SaveCurrentSceneEvent\n"); SaveCurScene(); } break; case T_EV_SetLoadLoopId : { SetLoadLoopIdEvent *sev = (SetLoadLoopIdEvent *) ev; // OK! if (CRITTERS) printf("CORE: Received SetLoadLoopIdEvent (%d)\n",sev->index); loadloopid = sev->index; } break; case T_EV_SetDefaultLoopPlacement : { SetDefaultLoopPlacementEvent *sev = (SetDefaultLoopPlacementEvent *) ev; // OK! if (CRITTERS) printf("CORE: Received SetDefaultLoopPlacementEvent (%d>%d)\n", sev->looprange.lo,sev->looprange.hi); default_looprange = sev->looprange; } break; case T_EV_SlideMasterInVolume : { SlideMasterInVolumeEvent *vev = (SlideMasterInVolumeEvent *) ev; // OK! if (CRITTERS) printf("CORE: Received SlideMasterInVolumeEvent(%f)\n", vev->slide); AdjustInputVolume(vev->slide); } break; case T_EV_SlideMasterOutVolume : { SlideMasterOutVolumeEvent *vev = (SlideMasterOutVolumeEvent *) ev; // OK! if (CRITTERS) printf("CORE: Received SlideMasterOutVolumeEvent(%f)\n", vev->slide); AdjustOutputVolume(vev->slide); } break; case T_EV_SlideInVolume : { SlideInVolumeEvent *vev = (SlideInVolumeEvent *) ev; // OK! if (CRITTERS) printf("CORE: Received SlideInVolumeEvent(%d: %f)\n", vev->input, vev->slide); app->getISET()->AdjustInputVol(vev->input-1, vev->slide); } break; case T_EV_SetMasterInVolume : { SetMasterInVolumeEvent *vev = (SetMasterInVolumeEvent *) ev; // OK! if (CRITTERS) printf("CORE: Received SetMasterInVolumeEvent(%f, %f)\n", vev->vol, vev->fadervol); SetInputVolume(vev->vol,vev->fadervol); } break; case T_EV_SetMasterOutVolume : { SetMasterOutVolumeEvent *vev = (SetMasterOutVolumeEvent *) ev; // OK! if (CRITTERS) printf("CORE: Received SetMasterOutVolumeEvent(%f, %f)\n", vev->vol, vev->fadervol); SetOutputVolume(vev->vol,vev->fadervol); } break; case T_EV_SetInVolume : { SetInVolumeEvent *vev = (SetInVolumeEvent *) ev; // OK! if (CRITTERS) printf("CORE: Received SetInVolumeEvent(%d: %f, %f)\n", vev->input, vev->vol, vev->fadervol); app->getISET()->SetInputVol(vev->input-1, vev->vol, vev->fadervol); } break; case T_EV_ToggleInputRecord : { ToggleInputRecordEvent *vev = (ToggleInputRecordEvent *) ev; // OK! if (CRITTERS) printf("CORE: Received ToggleInputRecordEvent(%d)\n", vev->input); app->getISET()->SelectInput(vev->input-1,(app->getISET()->InputSelected(vev->input-1) == 0 ? 1 : 0)); } break; case T_EV_DeletePulse : { DeletePulseEvent *dev = (DeletePulseEvent *) ev; // OK! if (CRITTERS) printf("CORE: Received DeletePulse(%d)\n", dev->pulse); DeletePulse(dev->pulse); } break; case T_EV_SelectPulse : { SelectPulseEvent *sev = (SelectPulseEvent *) ev; // OK! if (CRITTERS) printf("CORE: Received SelectPulse(%d)\n", sev->pulse); SelectPulse(sev->pulse); } break; case T_EV_TapPulse : { TapPulseEvent *tev = (TapPulseEvent *) ev; // OK! if (CRITTERS) printf("CORE: Received TapPulse(%d) %s\n", tev->pulse, (tev->newlen ? "[new length]" : "")); TapPulse(tev->pulse,tev->newlen); } break; case T_EV_SwitchMetronome : { SwitchMetronomeEvent *swev = (SwitchMetronomeEvent *) ev; // OK! if (CRITTERS) printf("CORE: Received SwitchMetronome(%d) %s\n", swev->pulse, (swev->metronome ? "[on]" : "[off]")); SwitchMetronome(swev->pulse,swev->metronome); } break; case T_EV_SetSyncType : { SetSyncTypeEvent *sev = (SetSyncTypeEvent *) ev; // OK! if (CRITTERS) printf("CORE: Received SetSyncType(%d)\n", sev->stype); app->SetSyncType(sev->stype); } break; case T_EV_SetSyncSpeed : { SetSyncSpeedEvent *sev = (SetSyncSpeedEvent *) ev; // OK! if (CRITTERS) printf("CORE: Received SetSyncSpeed(%d)\n", sev->sspd); app->SetSyncSpeed(sev->sspd); } break; case T_EV_SetMidiSync : { SetMidiSyncEvent *sev = (SetMidiSyncEvent *) ev; // OK! if (CRITTERS) printf("CORE: Received SetMidiSync(%d)\n", sev->midisync); app->getMIDI()->SetMIDISyncTransmit(sev->midisync); } break; case T_EV_SetTriggerVolume : { SetTriggerVolumeEvent *laev = (SetTriggerVolumeEvent *) ev; // OK! if (CRITTERS) printf("CORE: Received SetTriggerVolume(%d,%f)\n", laev->index, laev->vol); SetTriggerVol(laev->index,laev->vol); } break; case T_EV_SlideLoopAmp : { SlideLoopAmpEvent *laev = (SlideLoopAmpEvent *) ev; // OK! if (CRITTERS) printf("CORE: Received SlideLoopAmp(%d,%f)\n", laev->index, laev->slide); AdjustLoopVolume(laev->index,laev->slide); } break; case T_EV_SetLoopAmp : { SetLoopAmpEvent *laev = (SetLoopAmpEvent *) ev; // OK! if (CRITTERS) printf("CORE: Received SetLoopAmp(%d,%f)\n", laev->index, laev->amp); SetLoopVolume(laev->index,laev->amp); } break; case T_EV_AdjustLoopAmp : { AdjustLoopAmpEvent *laev = (AdjustLoopAmpEvent *) ev; // OK! if (CRITTERS) printf("CORE: Received AdjustLoopAmp(%d,%f)\n", laev->index, laev->ampfactor); SetLoopVolume(laev->index, laev->ampfactor * GetLoopVolume(laev->index)); } break; case T_EV_TriggerLoop : { TriggerLoopEvent *tev = (TriggerLoopEvent *) ev; int index = tev->index, engage = tev->engage; float vol = tev->vol; char od = tev->od, shot = tev->shot; UserVariable *od_fb = tev->od_fb; float *od_fb_ptr = 0; if (od_fb != 0) { if (od_fb->GetType() == T_float) od_fb_ptr = (float *) od_fb->GetValue(); else printf("CORE: ERROR: Overdub feedback assigned to variable '%s'- but that variable is not a 'float'!\n",od_fb->GetName()); } // OK! if (CRITTERS) { printf("CORE: Received TriggerLoop(%d,%.2f)", index, vol); if (od) { printf(" [overdub]"); if (od_fb != 0) { printf(" (feedback "); od_fb->Print(); printf(")\n"); } else printf("\n"); } if (shot) printf(" (shot)"); if (engage != -1) printf(" (%s)\n",(engage ? "force on" : "force off")); else printf("\n"); } if ((engage == -1 || engage == 1) && (GetStatus(index) == T_LS_Recording || GetStatus(index) == T_LS_Overdubbing || (GetStatus(index) == T_LS_Playing && od == 1))) { // Stop-start case nframes_t ofs = 0; if (GetStatus(index) == T_LS_Overdubbing && od == 1) { // Don't allow retrigger from overdub to overdub-- override to play od = 0; } else if (GetStatus(index) == T_LS_Playing) { // Play->overdub case- start overdub where play left off ofs = ((PlayProcessor *) plist[index])->GetPlayedLength(); } Deactivate(index); // Stop Activate(index,shot,vol,ofs,od,od_fb_ptr); // Start } else if ((engage == -1 || engage == 0) && IsActive(index)) { // Stop case (play and no overdub) Deactivate(index); } else if (engage == -1 || engage == 1) { // Start case (record) Activate(index,shot,vol,0,od,od_fb_ptr); } } break; case T_EV_TriggerSelectedLoops : { TriggerSelectedLoopsEvent *tev = (TriggerSelectedLoopsEvent *) ev; if (CRITTERS) printf("CORE: Received TriggerSelectedLoops(set #%d,%.2f)\n", tev->setid,tev->vol); LoopList **ll = app->getLOOPSEL(tev->setid); if (ll != 0) { // Get all loops from this set LoopList *cur = *ll; while (cur != 0) { if (IsActive(cur->l_idx)) { // Overdub/play on this loop if (tev->toggleloops) Deactivate(cur->l_idx); } else { // Loop idle-- start play // No overdub/shot/etc, just straight play Activate(cur->l_idx,0,tev->vol,0,0,0); } cur = cur->next; } } else printf("CORE: Invalid set id #%d when triggering selected loops\n", tev->setid); } break; case T_EV_MoveLoop : { MoveLoopEvent *mev = (MoveLoopEvent *) ev; // OK! if (CRITTERS) printf("CORE: Received MoveLoop(%d->%d)\n", mev->oldloopid, mev->newloopid); MoveLoop(mev->oldloopid,mev->newloopid); } break; case T_EV_RenameLoop : { RenameLoopEvent *rev = (RenameLoopEvent *) ev; if (rev->in == 1) { RenameLoop(rev->loopid); if (CRITTERS) printf("LOOPMGR: Received RenameLoop(loopid: %d)\n",rev->loopid); } } break; case T_EV_EraseLoop : { EraseLoopEvent *eev = (EraseLoopEvent *) ev; // OK! if (CRITTERS) printf("CORE: Received EraseLoop(%d)\n", eev->index); DeleteLoop(eev->index); } break; case T_EV_EraseAllLoops : { // OK! if (CRITTERS) printf("CORE: Received EraseAllLoops\n"); // Erase scene settings app->setCURSCENE(0); // Erase all loops! // printf("DEBUG: ERASE LOOPS!\n"); for (int i = 0; i < app->getCFG()->GetNumTriggers(); i++) DeleteLoop(i); // And all pulses! // printf("DEBUG: ERASE PULSES!\n"); for (int i = 0; i < MAX_PULSES; i++) DeletePulse(i); // printf("DEBUG: DONE!\n\n"); // And all snapshots! Snapshot *s = app->getSNAPS(); for (int i = 0; i < app->getCFG()->GetMaxSnapshots(); i++) s[i].DeleteSnapshot(); } break; case T_EV_SlideLoopAmpStopAll : { // OK! if (CRITTERS) printf("CORE: Received SlideLoopAmpStopAll\n"); for (int i = 0; i < app->getCFG()->GetNumTriggers(); i++) SetLoopdVolume(i,1.0); } break; default: break; } } int Fweelin::go() { running = 1; // Broadcast start session event! Event *proto = Event::GetEventByType(T_EV_StartSession); if (proto == 0) { printf("GO: Can't get start event prototype!\n"); } else { Event *cpy = (Event *) proto->RTNew(); if (cpy == 0) printf("CORE: WARNING: Can't send event- RTNew() failed\n"); else emg->BroadcastEventNow(cpy, this); } // Broadcast events for starting all interfaces! cfg->StartInterfaces(); // Encourage the user! printf("\n-- ** OKIE DOKIE, KIDDO! ** --\n"); // *** SDL IO is now done in main thread- Mac OS X SDL requires it, and on Linux it's one less thread SDLIO::run_sdl_thread(sdlio); // Old method #if 0 // Now just wait.. the threads will take care of everything while (sdlio->IsActive()) { usleep(100000); }; #endif // Cleanup if (vid != 0) vid->close(); sdlio->close(); midi->close(); audio->close(); if (vid != 0) delete vid; delete sdlio; delete midi; delete audio; delete iset; delete abufs; delete[] snaps; #if USE_FLUIDSYNTH delete fluidp; #endif delete[] browsers; printf("MAIN: end stage 1\n"); //sleep(1); // Manually reset audio memory to its original state- // not preallocated! getAMPEAKS()->SetupPreallocated(0,Preallocated::PREALLOC_BASE_INSTANCE); getAMAVGS()->SetupPreallocated(0,Preallocated::PREALLOC_BASE_INSTANCE); audiomem->SetupPreallocated(0,Preallocated::PREALLOC_BASE_INSTANCE); // And main classes.. delete tmap; printf(" 1\n"); delete loopmgr; printf(" 2\n"); delete rp; printf(" 3\n"); delete bmg; printf(" 4\n"); printf("MAIN: end stage 2\n"); //::delete audiomem; delete[] scope; printf("MAIN: end stage 3\n"); // Delete preallocated type managers delete pre_audioblock; delete pre_extrachannel; delete pre_timemarker; printf("MAIN: end stage 4\n"); //sleep(2); delete cfg; printf(" 1\n"); //sleep(2); delete emg; //sleep(2); printf(" 2\n"); delete mmg; SDL_Quit(); SRMWRingBuffer_Writers::CloseAll(); printf("MAIN: end\n"); return 0; } BED_MarkerPoints *Fweelin::getAMPEAKSPULSE() { AudioBlock *peaks = getAMPEAKS(); if (peaks != 0) return dynamic_cast (getAMPEAKS()->GetExtendedData(T_BED_MarkerPoints)); else return 0; }; AudioBlock *Fweelin::getAMPEAKS() { return dynamic_cast(bmg->GetBlockManager(audiomem, T_MC_PeaksAvgs))-> GetPeaks(); }; AudioBlock *Fweelin::getAMAVGS() { return dynamic_cast(bmg->GetBlockManager(audiomem, T_MC_PeaksAvgs))-> GetAvgs(); }; AudioBlockIterator *Fweelin::getAMPEAKSI() { return dynamic_cast(bmg->GetBlockManager(audiomem, T_MC_PeaksAvgs))-> GetPeaksI(); }; AudioBlockIterator *Fweelin::getAMAVGSI() { return dynamic_cast(bmg->GetBlockManager(audiomem, T_MC_PeaksAvgs))-> GetAvgsI(); }; AudioBlockIterator *Fweelin::getAUDIOMEMI() { return amrec->GetIterator(); }; Browser *Fweelin::GetBrowserFromConfig(BrowserItemType b) { FloDisplay *cur = cfg->displays; while (cur != 0) { if (cur->GetFloDisplayType() == FD_Browser && ((Browser *) cur)->GetType() == b) return (Browser *) cur; cur = cur->next; } return 0; }; void Fweelin::ToggleDiskOutput() { if (fs->GetStatus() == FileStreamer::STATUS_STOPPED) { // Create appropriate filename for output char tmp[FWEELIN_OUTNAME_LEN]; char go = 1; do { snprintf(tmp,FWEELIN_OUTNAME_LEN,"%s/%s%d%s", cfg->GetLibraryPath(),FWEELIN_OUTPUT_STREAM_NAME,writenum, getCFG()->GetAudioFileExt(getCFG()->GetStreamOutFormat())); struct stat st; printf("DISK: Opening '%s' for streaming.\n",tmp); if (stat(tmp,&st) == 0) { printf("DISK: File exists, trying another.\n"); writenum++; } else { // Also check for timing data file- don't overwrite that snprintf(timingname,FWEELIN_OUTNAME_LEN,"%s/%s%d%s", cfg->GetLibraryPath(),FWEELIN_OUTPUT_STREAM_NAME, writenum,FWEELIN_OUTPUT_TIMING_EXT); if (stat(timingname,&st) == 0) { printf("DISK: Timing file exists, trying another.\n"); writenum++; } else go = 0; } } while (go); // Compose filename & start writing strcpy(streamoutname,tmp); snprintf(timingname,FWEELIN_OUTNAME_LEN,"%s/%s%d%s", cfg->GetLibraryPath(),FWEELIN_OUTPUT_STREAM_NAME, writenum,FWEELIN_OUTPUT_TIMING_EXT); fs->StartWriting(streamoutname,timingname,getCFG()->GetStreamOutFormat()); } else { // Stop disk output fs->StopWriting(); strcpy(streamoutname,""); strcpy(timingname,""); // Advance to next logical filename writenum++; } }; int Fweelin::setup() { char tmp[255]; // Keep all memory inline mlockall(MCL_CURRENT | MCL_FUTURE); SRMWRingBuffer_Writers::InitAll(); // Initialize vars for (int i = 0; i < NUM_LOOP_SELECTION_SETS; i++) loopsel[i] = 0; #ifndef __MACOSX__ if (!XInitThreads()) { printf("MAIN: ERROR: FreeWheeling requires threaded Xlib support\n"); return 0; } #else FweelinMac::LinkFweelin(this); #endif /* Initialize SDL- this happens here because it is common to video, keys & config */ // SDL_INIT_NOPARACHUTE /* (SDL_INIT_JOYSTICK | SDL_INIT_EVENTTHREAD) < 0) { */ if ( SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0 ) { printf("MAIN: ERROR: Can't initialize SDL: %s\n",SDL_GetError()); return 0; } atexit(SDL_Quit); // Memory manager mmg = new MemoryManager(); // Load configuration from .rc file cfg = new FloConfig(this); // Create system variables so that config will have them first! UserVariable *tmpv; tmpv = cfg->AddEmptyVariable("BROWSE_loop"); tmpv->type = T_int; *tmpv = (int) B_Loop; tmpv = cfg->AddEmptyVariable("BROWSE_scene"); tmpv->type = T_int; *tmpv = (int) B_Scene; tmpv = cfg->AddEmptyVariable("BROWSE_loop_tray"); tmpv->type = T_int; *tmpv = (int) B_Loop_Tray; tmpv = cfg->AddEmptyVariable("BROWSE_scene_tray"); tmpv->type = T_int; *tmpv = (int) B_Scene_Tray; tmpv = cfg->AddEmptyVariable("BROWSE_patch"); tmpv->type = T_int; *tmpv = (int) B_Patch; cfg->AddEmptyVariable("SYSTEM_num_midi_outs"); cfg->AddEmptyVariable("SYSTEM_midi_transpose"); cfg->AddEmptyVariable("SYSTEM_master_in_volume"); cfg->AddEmptyVariable("SYSTEM_master_out_volume"); cfg->AddEmptyVariable("SYSTEM_cur_pitchbend"); cfg->AddEmptyVariable("SYSTEM_bender_tune"); cfg->AddEmptyVariable("SYSTEM_cur_limiter_gain"); cfg->AddEmptyVariable("SYSTEM_audio_cpu_load"); cfg->AddEmptyVariable("SYSTEM_sync_active"); cfg->AddEmptyVariable("SYSTEM_sync_transmit"); cfg->AddEmptyVariable("SYSTEM_midisync_transmit"); #if USE_FLUIDSYNTH cfg->AddEmptyVariable("SYSTEM_fluidsynth_enabled"); #endif cfg->AddEmptyVariable("SYSTEM_num_help_pages"); cfg->AddEmptyVariable("SYSTEM_num_loops_in_map"); cfg->AddEmptyVariable("SYSTEM_num_recording_loops_in_map"); cfg->AddEmptyVariable("SYSTEM_num_patchbanks"); cfg->AddEmptyVariable("SYSTEM_cur_patchbank_tag"); cfg->AddEmptyVariable("SYSTEM_num_switchable_interfaces"); cfg->AddEmptyVariable("SYSTEM_snapshot_page_firstidx"); for (int i = 0; i < LAST_REC_COUNT; i++) { sprintf(tmp,"SYSTEM_loopid_lastrecord_%d",i); cfg->AddEmptyVariable(tmp); } // Now parse and setup config cfg->Parse(); // Event manager emg = new EventManager(); vid = new VideoIO(this); if (vid->activate()) { printf("MAIN: ERROR: Can't start video handler!\n"); return 1; } while (!vid->IsActive()) usleep(100000); abufs = new AudioBuffers(this); iset = new InputSettings(this,abufs->numins); audio = new AudioIO(this); if (audio->open()) { printf("MAIN: ERROR: Can't start system level audio!\n"); return 1; } fragmentsize = audio->getbufsz(); printf("MAIN: Core block size: %d\n",fragmentsize); // Linkup to browsers browsers = new Browser *[(int) B_Last]; memset(browsers,0,sizeof(Browser *) * (int) B_Last); // Setup patch browser, if defined in config { Browser *br = GetBrowserFromConfig(B_Patch); if (br != 0) { browsers[B_Patch] = br; br->Setup(this,this); // We handle callbacks ourselves for patch browser } } // FluidSynth #if USE_FLUIDSYNTH // Create synth printf("MAIN: Creating integrated FluidSynth.\n"); fluidp = new FluidSynthProcessor(this,cfg->GetFluidStereo()); // Setup patch names fluidp->SetupPatches(); #endif // Setup sample buffer for visual scope scope = new sample_t[fragmentsize]; scope_len = fragmentsize; // Block manager bmg = new BlockManager(this); // Preallocated type managers pre_audioblock = new PreallocatedType(mmg, ::new AudioBlock(), sizeof(AudioBlock), FloConfig:: NUM_PREALLOCATED_AUDIO_BLOCKS); if (cfg->IsStereoMaster()) // Only preallocate for stereo blocks if we are running in stereo pre_extrachannel = new PreallocatedType(mmg, ::new BED_ExtraChannel(), sizeof(BED_ExtraChannel), FloConfig:: NUM_PREALLOCATED_AUDIO_BLOCKS); else pre_extrachannel = 0; pre_timemarker = new PreallocatedType(mmg,::new TimeMarker(), sizeof(TimeMarker), FloConfig:: NUM_PREALLOCATED_TIME_MARKERS); rp = new RootProcessor(this,iset); // Add monitor mix float *inputvol = &(rp->inputvol); // Where to get input vol from rp->AddChild(new PassthroughProcessor(this,iset,inputvol), ProcessorItem::TYPE_GLOBAL); // Add disk writer rp->AddChild(fs = new FileStreamer(this), ProcessorItem::TYPE_FINAL); writenum = 1; strcpy(streamoutname,""); curscene = 0; #if 0 strcpy(scenedispname,""); strcpy(scenefilename,""); #endif strcpy(timingname,""); // Fixed audio memory nframes_t memlen = (nframes_t) (audio->get_srate() * cfg->AUDIO_MEMORY_LEN), scopelen = cfg->GetScopeSampleLen(), chunksize = memlen/scopelen; // Note here we bypass using Preallocated RTNew because we want // a single block of our own size, not many preallocated blocks // chained together.. audiomem = ::new AudioBlock(memlen); if (audiomem == 0) { printf("CORE: ERROR: Can't create audio memory!\n"); exit(1); } audiomem->Zero(); // If we are running in stereo, create a custom right channel to match // our left channel audio memory if (cfg->IsStereoMaster()) { BED_ExtraChannel *audiomem_r = ::new BED_ExtraChannel(memlen); if (audiomem_r == 0) { printf("CORE: ERROR: Can't create audio memory (right channel)!\n"); exit(1); } audiomem->AddExtendedData(audiomem_r); } // So we have to set a pointer manually to the manager.. // Because some functions depend on using audiomem as a basis // to access RTNew audiomem->SetupPreallocated(pre_audioblock, Preallocated::PREALLOC_BASE_INSTANCE); // Begin recording into audio memory (use mono/stereo memory as appropriate) amrec = new RecordProcessor(this,iset,inputvol,audiomem, cfg->IsStereoMaster()); if (amrec == 0) { printf("CORE: ERROR: Can't create core RecordProcessor!\n"); exit(1); } rp->AddChild(amrec,ProcessorItem::TYPE_HIPRIORITY); // Compute running peaks and averages from audio mem (for scope) AudioBlock *peaks = ::new AudioBlock(scopelen), *avgs = ::new AudioBlock(scopelen); if (peaks == 0 || avgs == 0) { printf("CORE: ERROR: Can't create peaks/averages memory!\n"); exit(1); } peaks->Zero(); avgs->Zero(); // **BUG-- small leak-- the above two are never deleted peaks->SetupPreallocated(pre_audioblock, Preallocated::PREALLOC_BASE_INSTANCE); avgs->SetupPreallocated(pre_audioblock, Preallocated::PREALLOC_BASE_INSTANCE); audiomem->AddExtendedData(new BED_PeaksAvgs(peaks,avgs,chunksize)); bmg->PeakAvgOn(audiomem,amrec->GetIterator()); int nt = cfg->GetNumTriggers(); tmap = new TriggerMap(this,nt); loopmgr = new LoopManager(this); // Setup loop & scene browsers & trays, if defined in config { Browser *br = GetBrowserFromConfig(B_Loop); if (br != 0) { browsers[B_Loop] = br; br->Setup(this,loopmgr); } loopmgr->SetupLoopBrowser(); br = GetBrowserFromConfig(B_Scene); if (br != 0) { browsers[B_Scene] = br; br->Setup(this,loopmgr); } loopmgr->SetupSceneBrowser(); br = GetBrowserFromConfig(B_Loop_Tray); if (br != 0) { browsers[B_Loop_Tray] = br; br->Setup(this,loopmgr); } } // Create snapshots snaps = new Snapshot[cfg->GetMaxSnapshots()]; // Input methods sdlio = new SDLIO(this); midi = new MidiIO(this); if (sdlio->activate()) { printf("(start) cant start keyboard handler\n"); return 1; } if (midi->activate()) { printf("(start) cant start midi\n"); return 1; } // Linkup system variables cfg->LinkSystemVariable("SYSTEM_num_midi_outs",T_int, (char *) &(cfg->midiouts)); cfg->LinkSystemVariable("SYSTEM_midi_transpose",T_int, (char *) &(cfg->transpose)); cfg->LinkSystemVariable("SYSTEM_master_in_volume",T_float, (char *) &(rp->inputvol)); cfg->LinkSystemVariable("SYSTEM_master_out_volume",T_float, (char *) &(rp->outputvol)); cfg->LinkSystemVariable("SYSTEM_cur_pitchbend",T_int, (char *) &(midi->curbender)); cfg->LinkSystemVariable("SYSTEM_bender_tune",T_int, (char *) &(midi->bendertune)); cfg->LinkSystemVariable("SYSTEM_cur_limiter_gain",T_float, (char *) &(rp->curlimitvol)); cfg->LinkSystemVariable("SYSTEM_audio_cpu_load",T_float, (char *) &(audio->cpuload)); cfg->LinkSystemVariable("SYSTEM_sync_active",T_char, (char *) &(audio->sync_active)); cfg->LinkSystemVariable("SYSTEM_sync_transmit",T_char, (char *) &(audio->timebase_master)); cfg->LinkSystemVariable("SYSTEM_midisync_transmit",T_char, (char *) &(midi->midisyncxmit)); #if USE_FLUIDSYNTH cfg->LinkSystemVariable("SYSTEM_fluidsynth_enabled",T_char, (char *) &(fluidp->enable)); #endif cfg->LinkSystemVariable("SYSTEM_num_help_pages",T_int, (char *) &(vid->numhelppages)); cfg->LinkSystemVariable("SYSTEM_num_loops_in_map",T_int, (char *) &(loopmgr->numloops)); cfg->LinkSystemVariable("SYSTEM_num_recording_loops_in_map",T_int, (char *) &(loopmgr->numrecordingloops)); cfg->LinkSystemVariable("SYSTEM_num_recording_loops_in_map",T_int, (char *) &(loopmgr->numrecordingloops)); if (browsers[B_Patch] != 0) { cfg->LinkSystemVariable("SYSTEM_num_patchbanks",T_int, (char *) &(((PatchBrowser *) browsers[B_Patch])-> num_pb)); cfg->LinkSystemVariable("SYSTEM_cur_patchbank_tag",T_int, (char *) &(((PatchBrowser *) browsers[B_Patch])-> pb_cur_tag)); } cfg->LinkSystemVariable("SYSTEM_num_switchable_interfaces",T_int, (char *) &(cfg->numinterfaces)); for (int i = 0; i < LAST_REC_COUNT; i++) { sprintf(tmp,"SYSTEM_loopid_lastrecord_%d",i); cfg->LinkSystemVariable(tmp,T_int, (char *) &(loopmgr->lastrecidx[i])); } for (int i = 0; i < iset->numins; i++) { snprintf(tmp,255,"SYSTEM_in_%d_volume",i+1); cfg->LinkSystemVariable(tmp,T_float, (char *) &(iset->invols[i])); snprintf(tmp,255,"SYSTEM_in_%d_peak",i+1); cfg->LinkSystemVariable(tmp,T_float, (char *) &(iset->inpeak[i])); snprintf(tmp,255,"SYSTEM_in_%d_record",i+1); cfg->LinkSystemVariable(tmp,T_char, (char *) &(iset->selins[i])); } { FloDisplaySnapshots *sn = (FloDisplaySnapshots *) cfg->GetDisplayByType(FD_Snapshots); if (sn != 0) cfg->LinkSystemVariable("SYSTEM_snapshot_page_firstidx",T_int, (char *) &(sn->firstidx)); } // Finally, final Config start cfg->Start(); // Now start signal processing if (audio->activate(rp)) { printf("MAIN: Error with signal processing start!\n"); return 1; } return 0; } void Fweelin::ItemSelected(BrowserItem *i) { if (i->GetType() != B_Patch) printf("CORE: ERROR- Patch Browser contains items of invalid type!\n"); else { PatchBrowser *br = (PatchBrowser *) getBROWSER(B_Patch); if (br != 0) { PatchBank *pb = br->GetCurPatchBank(); if (pb->port == 0) { // We are selecting in a Fluidsynth bank-- send patch change #if USE_FLUIDSYNTH getFLUIDP()->SendPatchChange((PatchItem *) i); #else printf("CORE: ERROR: Can't change FluidSynth patches- no FluidSynth " "support!\n"); #endif } else { // Check if change messages to be sent? if (!pb->suppresschg) { // Tell MIDI to send out bank/program change(s) for new patch getMIDI()->SendBankProgramChange((PatchItem *) i); } } } } }; fweelin-0.6/src/fweelin_core_dsp.cc0000755000175000017500000021726611065526553016104 0ustar mercmerc/* Music holds us together "it becomes a movement" "every cell is forward, achieving" */ /* Copyright 2004-2008 Jan Pekau (JP Mercury) This file is part of Freewheeling. Freewheeling is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. Freewheeling is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Freewheeling. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include "fweelin_config.h" #include "fweelin_core_dsp.h" const float Processor::MIN_VOL = 0.01; const nframes_t Processor:: DEFAULT_SMOOTH_LENGTH = 64; // Length of metronome strike sound in samples const nframes_t Pulse::METRONOME_HIT_LEN = 800; // Initial metronome volume const float Pulse::METRONOME_INIT_VOL = 0.1; // Autolimiter const float RootProcessor::LIMITER_ATTACK_LENGTH = 1024, RootProcessor::LIMITER_START_AMP = 1.0; const nframes_t RootProcessor::LIMITER_ADJUST_PERIOD = 64; const float RecordProcessor::OVERDUB_DEFAULT_FEEDBACK = 0.5; const static float MAX_VOL = 5.0; const static float MAX_DVOL = 1.5; // DB FADER CODE #define DB_FLOOR -1000.f #define FADER_MIN_DB -70.f // IEC 60-268-18 fader levels. Thanks to Steve Harris. // Thanks to Chris Cannam & Sonic Visualiser code float iec_dB_to_fader (float db) { float def = 0.0f; // Meter deflection %age if (db < -70.0f) { def = 0.0f; } else if (db < -60.0f) { def = (db + 70.0f) * 0.25f; } else if (db < -50.0f) { def = (db + 60.0f) * 0.5f + 2.5f; // used to be +5.0f, but this caused a discontinuity in low dB deflections } else if (db < -40.0f) { def = (db + 50.0f) * 0.75f + 7.5f; } else if (db < -30.0f) { def = (db + 40.0f) * 1.5f + 15.0f; } else if (db < -20.0f) { def = (db + 30.0f) * 2.0f + 30.0f; } else { def = (db + 20.0f) * 2.5f + 50.0f; } return def; } static float iec_fader_to_dB(float def) // Meter deflection %age { float db = 0.0f; if (def >= 50.0f) { db = (def - 50.0f) / 2.5f - 20.0f; } else if (def >= 30.0f) { db = (def - 30.0f) / 2.0f - 30.0f; } else if (def >= 15.0f) { db = (def - 15.0f) / 1.5f - 40.0f; } else if (def >= 7.5f) { db = (def - 7.5f) / 0.75f - 50.0f; } else if (def >= 2.5f) { // used to be 0.5, ... db = (def - 2.5f) / 0.5f - 60.0f; // used to be (def - 5.0f), but this caused a discontinuity in low dB deflections } else { db = (def / 0.25f) - 70.0f; } return db; } float AudioLevel::fader_to_dB (float level, float maxDb) { if (level == 0.) return DB_FLOOR; float maxPercent = iec_dB_to_fader(maxDb); float percent = level * maxPercent; float dB = iec_fader_to_dB(percent); return dB; } float AudioLevel::dB_to_fader (float dB, float maxDb) { if (dB == DB_FLOOR) return 0.; // The IEC scale gives a "percentage travel" for a given dB // level, but it reaches 100% at 0dB. So we want to treat the // result not as a percentage, but as a scale between 0 and // whatever the "percentage" for our (possibly >0dB) max dB is. float maxPercent = iec_dB_to_fader(maxDb); float percent = iec_dB_to_fader(dB); float faderLevel = percent / maxPercent; if (faderLevel < 0.) faderLevel = 0.; if (faderLevel > 1.0) faderLevel = 1.0; return faderLevel; } // // *********** CORE SIGNAL PROCESSING AudioBuffers::AudioBuffers(Fweelin *app) : app(app) { numins_ext = app->getCFG()->GetExtAudioIns(); numins = numins_ext + GetIntAudioIns(); numouts = GetAudioOuts(); ins[0] = new sample_t *[numins]; ins[1] = new sample_t *[numins]; outs[0] = new sample_t *[numouts]; outs[1] = new sample_t *[numouts]; memset(ins[0],0,sizeof(sample_t *) * numins); memset(ins[1],0,sizeof(sample_t *) * numins); memset(outs[0],0,sizeof(sample_t *) * numouts); memset(outs[1],0,sizeof(sample_t *) * numouts); }; AudioBuffers::~AudioBuffers() { delete[] ins[0]; delete[] ins[1]; delete[] outs[0]; delete[] outs[1]; }; char AudioBuffers::IsStereoInput(int n) { return app->getCFG()->IsStereoInput(n); }; char AudioBuffers::IsStereoOutput(int n) { return app->getCFG()->IsStereoOutput(n); }; char AudioBuffers::IsStereoMaster() { return app->getCFG()->IsStereoMaster(); }; // Mixes the selected inputs (nonzero) to dest // Dest is an array of 2 pointers to left & right buffers // If dest[1] is null, mix is done in mono // Also, we do compensation for DC offset of inputs // // *** Glitch/inefficiency: MixInputs is called for each RecordProcessor // And for PassthroughProcessor- DC offsets are recomputed, etc void AudioBuffers::MixInputs (nframes_t len, sample_t **dest, InputSettings *iset, float inputvol, char compute_stats) { const static int DCOFS_MINIMUM_SAMPLE_COUNT = 10000; const static float DCOFS_LOWPASS_COEFF = 0.99, DCOFS_ONEMINUS_LOWPASS_COEFF = 1.0-DCOFS_LOWPASS_COEFF; const static nframes_t PEAK_HOLD_LENGTH = 1; // Mix together selected inputs.. int stereomix = (dest[1] != 0 ? 1 : 0); memset(dest[0],0,sizeof(sample_t) * len); if (stereomix) memset(dest[1],0,sizeof(sample_t) * len); nframes_t phold = 0; if (compute_stats) phold = app->getAUDIO()->get_srate() * PEAK_HOLD_LENGTH; for (int i = 0; i < numins; i++) { if (iset->selins[i]) { // If input is selected! for (int j = 0; j <= stereomix; j++) { // Left & right channels sample_t *in = ins[j][i]; float vol = iset->invols[i] * inputvol; // DC offset compute sample_t sum = 0, peak = 0, dcofs = iset->insavg[j][i]; nframes_t peaktime = 0; int cnt = 0; if (compute_stats) { cnt = iset->inscnt[i]; sum = iset->insums[j][i]; peaktime = iset->inpeaktime[i]; if (cnt-peaktime > phold) // Old peak- fall to zero peak = 0; else // Retain peak peak = iset->inpeak[i]; } if (j == 0) { // Left if (compute_stats) { // Stats for (nframes_t idx = 0; idx < len; idx++) { sample_t s = in[idx], sabs = fabs(s); sum += s; if (sabs > peak) { peak = sabs; peaktime = cnt; } cnt++; dest[0][idx] += (s-dcofs) * vol; } iset->inscnt[i] = cnt; } else { // No stats for (nframes_t idx = 0; idx < len; idx++) dest[0][idx] += (in[idx]-dcofs) * vol; } } else { // If input is mono, take signal from left channel and // use it for the right output if (in == 0) in = ins[0][i]; if (compute_stats) { // Stats for (nframes_t idx = 0; idx < len; idx++) { sample_t s = in[idx], sabs = fabs(s); sum += s; if (sabs > peak) { peak = sabs; peaktime = cnt; } dest[j][idx] += (s-dcofs) * vol; } } else { // No stats for (nframes_t idx = 0; idx < len; idx++) dest[j][idx] += (in[idx]-dcofs) * vol; } } // DC offset adjust if (compute_stats) { iset->insums[j][i] = sum; iset->inpeak[i] = peak; iset->inpeaktime[i] = peaktime; if (cnt > DCOFS_MINIMUM_SAMPLE_COUNT) iset->insavg[j][i] = (DCOFS_LOWPASS_COEFF*iset->insavg[j][i]) + (DCOFS_ONEMINUS_LOWPASS_COEFF*sum/cnt); } } } } } char InputSettings::IsSelectedStereo() { for (int i = 0; i < numins; i++) if (selins[i] && app->getCFG()->IsStereoInput(i)) return 1; // Nope! return 0; }; void InputSettings::AdjustInputVol(int n, float adjust) { if (n >= 0 || n < numins) { if (dinvols[n] < MAX_DVOL) dinvols[n] += adjust*app->getAUDIO()->GetTimeScale(); if (dinvols[n] < 0.0) dinvols[n] = 0.0; } else { printf("CORE: InputSettings- input number %d not in range.\n",n); } } Processor::Processor(Fweelin *app) : app(app), prelen(DEFAULT_SMOOTH_LENGTH), prewritten(0), prewriting(0) { // Create preprocess audio buffers (for smoothing) preab = new AudioBuffers(app); for (int i = 0; i < preab->numouts; i++) { preab->outs[0][i] = new sample_t[prelen]; preab->outs[1][i] = (preab->IsStereoMaster() ? new sample_t[prelen] : 0); } }; Processor::~Processor() { // Delete preprocess audio buffers for (int i = 0; i < preab->numouts; i++) { delete[] preab->outs[0][i]; if (preab->outs[1][i] != 0) delete[] preab->outs[1][i]; } delete preab; }; void Processor::dopreprocess() { if (prewriting) { printf("Caught ourselves writing PREPROCESS!\n"); return; } if (!prewritten && !prewriting) { // Do a preprocess to smooth abrupt changes in flow prewriting = 1; process(1,prelen,preab); // Process but write to preprocess buffers prewriting = 0; prewritten = 1; } } // Fade together current with preprocessed to create a smoothed output during // control changes void Processor::fadepreandcurrent(AudioBuffers *ab) { if (prewriting) { // This does happen } if (prewritten) { float dr = 1.0/prelen; // For each output for (int i = 0; i < ab->numouts; i++) { int stereo = (ab->outs[1][i] != 0 ? 1 : 0); for (int j = 0; j <= stereo; j++) { // Fade between preprocessed and current output sample_t *out = ab->outs[j][i]; if (out != 0) { // Do the pre-buffers match the outputs in channels? sample_t *pre = preab->outs[j][i]; if (pre == 0) { printf("DSP: ERROR: Pre buffers are null for active output.\n"); } else { float ramp = 0.0; for (nframes_t l = 0; l < prelen; l++, ramp += dr) out[l] = (out[l]*ramp) + (pre[l]*(1.0-ramp)); } } } } prewritten = 0; } } Pulse::Pulse(Fweelin *app, nframes_t len, nframes_t startpos) : Processor(app), len(len), curpos(startpos), wrapped(0), stopped(0), prev_sync_bb(0), sync_cnt(0), prev_sync_speed(-1), prev_sync_type(0), prevbpm(0.0), prevtap(0), metroofs(metrolen), metrolen(METRONOME_HIT_LEN), metroactive(0), metrovol(METRONOME_INIT_VOL), numsyncpos(0), clockrun(SS_NONE) { // Generate metronome data metro = new sample_t[metrolen]; for (nframes_t i = 0; i < metrolen; i++ ) metro[i] = ((sample_t)rand()/RAND_MAX - 0.5) * (1.0 - (float)i/metrolen); }; Pulse::~Pulse() { // Notify BlockManager we are dying in case any mgrs depend on us app->getBMG()->RefDeleted(this); delete [] metro; }; // Quantizes src length to fit to this pulse length nframes_t Pulse::QuantizeLength(nframes_t src) { float frac = (float) src/len; if (frac < 0.5) frac = 1.0; // Don't allow 0 length loops return (nframes_t) (round(frac) * len); } void Pulse::SetMIDIClock (char start) { if (app->getMIDI()->GetMIDISyncTransmit()) { if (start) clockrun = SS_START; else { clockrun = SS_NONE; // Send MIDI stop for pulse MIDIStartStopInputEvent *ssevt = (MIDIStartStopInputEvent *) Event::GetEventByType(T_EV_Input_MIDIStartStop); ssevt->start = 0; app->getEMG()->BroadcastEventNow(ssevt, this); } } }; // Please note that all sync is done with a granularity of the audio period // size. A potential bug exists when loops recorded with one period size // are played on a system with another period size... the syncronization // may not line up, causing a click in the audio. // // Not sure how this might be resolved // For loops whose syncronized length is not a multiple of the period size, // those loops may need to be resized so that the loop point falls on a // period boundary // void Pulse::process(char pre, nframes_t l, AudioBuffers *ab) { // If we're using Jack transport (audio) sync, and we're slave to another app, // adjust pulse to stay in-sync if (app->getAUDIO()->IsTransportRolling() && !app->getAUDIO()->IsTimebaseMaster()) { char sync_type = app->GetSyncType(); int sync_speed = app->GetSyncSpeed(); if (sync_type != prev_sync_type || sync_speed != prev_sync_speed) { // Make sure we recalculate length / wrap if sync params changed prevbpm = 0; prev_sync_bb = -1; prev_sync_type = sync_type; prev_sync_speed = sync_speed; } double bpm = app->getAUDIO()->GetTransport_BPM(); if (bpm != prevbpm) { // Adjust pulse length from BPM float mult = (sync_type ? sync_speed : app->getAUDIO()->GetTransport_BPB()* sync_speed); len = (nframes_t) ((double) 60.*app->getAUDIO()->get_srate()*mult/bpm); // printf("slave to bpm: %lf, len: %d\n",bpm,len); prevbpm = bpm; } int sync_bb = (sync_type ? app->getAUDIO()->GetTransport_Beat() : app->getAUDIO()->GetTransport_Bar()); if (sync_bb != prev_sync_bb) { sync_cnt++; if (sync_cnt >= sync_speed) { // Wrap pulse- enough bars or beats has passed sync_cnt = 0; Wrap(); } // printf("slave to sync: %d\n",sync_bb); prev_sync_bb = sync_bb; } } nframes_t fragmentsize = app->getBUFSZ(); if (l > fragmentsize) l = fragmentsize; // Process on left channel of first output sample_t *out = ab->outs[0][0]; nframes_t ofs = 0; if (!pre && !stopped) { nframes_t remaining = len-curpos; // Move forward pulse position wrapped = 0; nframes_t oldpos = curpos; curpos += MIN(l,remaining); // If we are transmitting MIDI sync, do so now if (clockrun != SS_NONE && app->getMIDI()->GetMIDISyncTransmit()) { char sync_type = app->GetSyncType(); int sync_speed = app->GetSyncSpeed(); // 1 pulse = how many MIDI clock messages to send? // In sync-beat mode, each pulse is SyncSpeed beats, so MIDI_CLOCK_FREQUENCY*SyncSpeed clocks to send // In sync-bar mode, each pulse is one bar, so MIDI_CLOCK_FREQUENCY*BeatsPerBar*SyncSpeed clocks to send int clocksperpulse = MIDI_CLOCK_FREQUENCY*sync_speed; if (!sync_type) clocksperpulse *= SYNC_BEATS_PER_BAR; // Check timing of pulse float framesperclock = (float) len/clocksperpulse; int oldclock = (int) ((float) oldpos/framesperclock), newclock = (int) ((float) curpos/framesperclock); if ((clockrun == SS_BEAT && newclock != oldclock) || curpos >= len) { // printf("CLOCKY-OO %d!\n",newclock); if (clockrun == SS_START) { // Send MIDI start for pulse MIDIStartStopInputEvent *ssevt = (MIDIStartStopInputEvent *) Event::GetEventByType(T_EV_Input_MIDIStartStop); ssevt->start = 1; app->getEMG()->BroadcastEventNow(ssevt, this); } // Time for another clock message MIDIClockInputEvent *clkevt = (MIDIClockInputEvent *) Event::GetEventByType(T_EV_Input_MIDIClock); // *** Broadcast immediately-- this will yield lowest MIDI sync latency, // but may cause problems if MIDI transmit code blocks/conflicts with RT audio thread // (which it very well might) // _experimental_ app->getEMG()->BroadcastEventNow(clkevt, this); // If this is the first downbeat, start the clock proper clockrun = SS_BEAT; } } // Check pulse wrap if (curpos >= len) { // Downbeat!! wrapped = 1; curpos = 0; // Send out a pulse sync event PulseSyncEvent *pevt = (PulseSyncEvent *) Event::GetEventByType(T_EV_PulseSync); pevt->syncidx = -1; // Builtin sync (on the downbeat) app->getEMG()->BroadcastEventNow(pevt, this); // Trigger management of any RT work on blocks // (currently PulseSync event handles loop points, but // BMG handles striping through StripeBlockManager) // *** To be consolidated into EMG? app->getBMG()->HiPriTrigger(this); // Metronome sound on metroofs = 0; l -= remaining; memset(out,0,sizeof(sample_t) * remaining); ofs += remaining; } // Send out user-define pulse syncs for (int i = 0; i < numsyncpos; i++) { if (syncpos[i] != 0 && oldpos < syncpos[i] && (curpos >= syncpos[i] || wrapped)) { // Send out a pulse sync event PulseSyncEvent *pevt = (PulseSyncEvent *) Event::GetEventByType(T_EV_PulseSync); pevt->syncidx = i; // User-define sync app->getEMG()->BroadcastEventNow(pevt, this); } } } // Producing metronome signal if (metroofs < metrolen) { if (metroactive && metrovol > 0.0) { nframes_t i = 0; for (; i < l && metroofs+iouts[1][0] != 0) memcpy(ab->outs[1][0],ab->outs[0][0],sizeof(sample_t) * l); } RootProcessor::RootProcessor(Fweelin *app, InputSettings *iset) : Processor(app), threadgo(1), iset(iset), outputvol(1.0), doutputvol(1.0), inputvol(1.0), dinputvol(1.0), firstchild(0), samplecnt(0) { // Reset limiter ResetLimiter(); const static size_t STACKSIZE = 1024*64; pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setstacksize(&attr,STACKSIZE); printf("CLEANUP: Stacksize: %d.\n",STACKSIZE); // Start a new thread for cleanup int ret = pthread_create(&cleanup_thread, &attr, run_cleanup_thread, static_cast(this)); if (ret != 0) { printf("(rootprocessor) pthread_create failed, exiting\n"); exit(1); } SRMWRingBuffer_Writers::RegisterWriter(cleanup_thread); // Temporary buffers and routing abtmp = new AudioBuffers(app); // Pre needs a separate set because preprocess runs in a different thread preabtmp = new AudioBuffers(app); buf[0] = new sample_t[app->getBUFSZ()]; prebuf[0] = new sample_t[prelen]; if (abtmp->IsStereoMaster()) { buf[1] = new sample_t[app->getBUFSZ()]; prebuf[1] = new sample_t[prelen]; } else { buf[1] = 0; prebuf[1] = 0; } //printf (" :: Processor: RootProcessor begin (block size: %d)\n", // app->getBUFSZ()); }; RootProcessor::~RootProcessor() { // printf(" :: Processor: RootProcessor cleanup...\n"); // The cleanup thread will erase all child processors threadgo = 0; pthread_join(cleanup_thread,0); delete[] buf[0]; delete[] prebuf[0]; if (buf[1] != 0) delete[] buf[1]; if (prebuf[1] != 0) delete[] prebuf[1]; delete abtmp; delete preabtmp; // printf(" :: Processor: RootProcessor end\n"); } void RootProcessor::ResetLimiter() { dlimitvol = app->getCFG()->GetLimiterReleaseRate(); limitvol = LIMITER_START_AMP; curlimitvol = LIMITER_START_AMP; maxvol = app->getCFG()->GetLimiterThreshhold(); limiterfreeze = 0; } void RootProcessor::AdjustOutputVolume(float adjust) { if (doutputvol < MAX_DVOL) doutputvol += adjust*app->getAUDIO()->GetTimeScale(); if (doutputvol < 0.0) doutputvol = 0.0; } void RootProcessor::AdjustInputVolume(float adjust) { if (dinputvol < MAX_DVOL) dinputvol += adjust*app->getAUDIO()->GetTimeScale(); if (dinputvol < 0.0) dinputvol = 0.0; } // Adds a child processor.. the processor begins processing immediately // Not realtime safe void RootProcessor::AddChild (Processor *o, int type) { // Do a preprocess for fadein dopreprocess(); ProcessorItem *cur = firstchild; if (cur == 0) firstchild = new ProcessorItem(o,type); // That was easy, now we have 1 child else { while (cur->next != 0) cur = cur->next; cur->next = new ProcessorItem(o,type); // Link up the last item to the new one } } // Removes a child processor from receiving processing time.. // also, deletes the child processor // Realtime safe! void RootProcessor::DelChild (Processor *o) { ProcessorItem *cur = firstchild, *prev = 0; // Search for processor 'o' in our list while (cur != 0 && cur->p != o) { prev = cur; cur = cur->next; } if (cur != 0) { // Found it! // Do a preprocess for fadeout dopreprocess(); // Tell processor, Halt! o->Halt(); // Then set it to be deleted cur->status = ProcessorItem::STATUS_PENDING_DELETE; } } void RootProcessor::processchain(char pre, nframes_t len, AudioBuffers *ab, AudioBuffers *abchild, const int ptype, const char mixintoout) { int stereo = (ab->outs[1][0] != 0 && abchild->outs[1][0] != 0 ? 1 : 0); // Go through all children of type 'ptype' and mix ProcessorItem *cur = firstchild; while (cur != 0) { if (cur->status == ProcessorItem::STATUS_GO && cur->type == ptype) { cur->p -> process(pre, len, abchild); // Sum from temporary output into actual output if (mixintoout) { for (int chan = 0; chan <= stereo; chan++) { sample_t *sumout = ab->outs[chan][0], *out = abchild->outs[chan][0]; for (nframes_t j = 0; j < len; j++) sumout[j] += out[j]; } } } cur = cur->next; } } void RootProcessor::process(char pre, nframes_t len, AudioBuffers *ab) { nframes_t fragmentsize = app->getBUFSZ(); if (len > fragmentsize) len = fragmentsize; // First, apply changes to volumes if (!pre) { // Run FluidSynth first, because its out feeds an input // Later support may come for true multiple signal chains #if USE_FLUIDSYNTH FluidSynthProcessor *fluidp = app->getFLUIDP(); fluidp->process(0, len, ab); #endif // Adjust global in/out volumes if (doutputvol != 1.0 || dinputvol != 1.0) { // Smoothing isn't necessary if the deltas are small! // dopreprocess(); // Apply delta if (doutputvol > 1.0 && outputvol < MIN_VOL) outputvol = MIN_VOL; if (outputvol < MAX_VOL) outputvol *= doutputvol; if (dinputvol > 1.0 && inputvol < MIN_VOL) inputvol = MIN_VOL; if (inputvol < MAX_VOL) inputvol *= dinputvol; } // Adjust individual input volumes for (int i = 0; i < iset->numins; i++) { if (iset->dinvols[i] > 1.0 && iset->invols[i] < MIN_VOL) iset->invols[i] = MIN_VOL; iset->invols[i] *= iset->dinvols[i]; } } // Zero the output buffers- we'll be summing into them sample_t *out[2] = {ab->outs[0][0], ab->outs[1][0]}; int stereo = (out[1] != 0 ? 1 : 0); memset(out[0],0,sizeof(sample_t)*len); if (stereo) memset(out[1],0,sizeof(sample_t)*len); if (!pre) { // Setup our own audio route, routing output to our internal buffer // Then, child processors will use this buffer memcpy(abtmp->ins[0],ab->ins[0],sizeof(sample_t *) * ab->numins); memcpy(abtmp->ins[1],ab->ins[1],sizeof(sample_t *) * ab->numins); memset(abtmp->outs[0],0,sizeof(sample_t *) * ab->numouts); memset(abtmp->outs[1],0,sizeof(sample_t *) * ab->numouts); abtmp->outs[0][0] = buf[0]; abtmp->outs[1][0] = buf[1]; // Go through 1st all hipri, then all default children and mix processchain(pre,len,ab,abtmp,ProcessorItem::TYPE_HIPRIORITY,1); processchain(pre,len,ab,abtmp,ProcessorItem::TYPE_DEFAULT,1); } else { // Preprocess-- // Notice I use a different set of structs for AudioBuffer ptrs // This is so that a concurrently running preprocess and RT process // do not collide memset(preabtmp->ins[0],0,sizeof(sample_t *) * ab->numins); memset(preabtmp->ins[1],0,sizeof(sample_t *) * ab->numins); memset(preabtmp->outs[0],0,sizeof(sample_t *) * ab->numouts); memset(preabtmp->outs[1],0,sizeof(sample_t *) * ab->numouts); preabtmp->outs[0][0] = prebuf[0]; preabtmp->outs[1][0] = prebuf[1]; // Go through 1st all hipri, then all default children and mix processchain(pre,len,ab,preabtmp,ProcessorItem::TYPE_HIPRIORITY,1); processchain(pre,len,ab,preabtmp,ProcessorItem::TYPE_DEFAULT,1); } // Output volume for (int chan = 0; chan <= stereo; chan++) { sample_t *o = out[chan]; for (nframes_t l = 0; l < len; l++) o[l] *= outputvol; } if (!pre) { // Fade together current with preprocessed to create smoothed fadepreandcurrent(ab); // Now go through all global children after volume xform and mix processchain(pre,len,ab,abtmp,ProcessorItem::TYPE_GLOBAL,1); // ** autolimit ** to be moved to its own processor ** // Autolimit treats stereo channels as linked float localmaxvol = 0.0, maxamp = app->getCFG()->GetMaxLimiterGain(), limitthresh = app->getCFG()->GetLimiterThreshhold(), limitrr = app->getCFG()->GetLimiterReleaseRate(); int clipcnt = 0; sample_t *s_left = out[0], *s_right = out[1]; if (stereo) { // Stereo limit for (nframes_t l = 0; l < len; l++, s_left++, s_right++) { float abssamp_l = fabs(*s_left), abssamp_r = fabs(*s_right); // Volume scale *s_left *= curlimitvol; *s_right *= curlimitvol; float abssamp2_l = fabs(*s_left), abssamp2_r = fabs(*s_right); if (!limiterfreeze) { // Find local maxima if (abssamp_l > localmaxvol) localmaxvol = abssamp_l; if (abssamp_r > localmaxvol) localmaxvol = abssamp_r; // Find clipping after limit if (abssamp2_l > limitthresh) clipcnt++; // Force limit if (abssamp2_r > limitthresh) clipcnt++; // Force limit // Adjust volume scale curlimitvol += dlimitvol; } // Clipping kludge-- // Some output formats clip near 1.0.. brickwall limit to 1.0 if (abssamp2_l > 0.99) { // Absolute clip! Truncate if (*s_left > 0.0) *s_left = 0.99; else *s_left = -0.99; } if (abssamp2_r > 0.99) { // Absolute clip! Truncate if (*s_right > 0.0) *s_right = 0.99; else *s_right = -0.99; } if (l+1 == len || l % LIMITER_ADJUST_PERIOD == 0) { // Time to check & adjust limit parameters if (clipcnt > 0 || localmaxvol > maxvol) { // We got more clipping! clipcnt = 0; float newlimitvol = limitthresh/localmaxvol; // Compute volume reduction necessary to bring in peak limitvol = newlimitvol; // Compute delta (speed) to get to that reduction (attack time) dlimitvol = (limitvol-curlimitvol)/LIMITER_ATTACK_LENGTH; // Store new max maxvol = localmaxvol; } if (dlimitvol < 0.0 && curlimitvol <= limitvol) { // We are done the attack phase- switch to release! dlimitvol = limitrr; } if (dlimitvol > 0.0 && curlimitvol > maxamp) { // Too much amp! dlimitvol = 0.0; } } } } else { // Mono limit for (nframes_t l = 0; l < len; l++, s_left++) { float abssamp_l = fabs(*s_left); // Volume scale *s_left *= curlimitvol; float abssamp2_l = fabs(*s_left); if (!limiterfreeze) { // Find local maxima if (abssamp_l > localmaxvol) localmaxvol = abssamp_l; // Find clipping after limit if (abssamp2_l > limitthresh) clipcnt++; // Force limit // Adjust volume scale curlimitvol += dlimitvol; } // Vorbis clipping kludge-- // Vorbis clips near 1.0.. 1st step is brickwall at 1.0 // then scale down.. (scaling happens in FileStreamer) if (abssamp2_l > 0.99) { // Absolute clip! Truncate if (*s_left > 0.0) *s_left = 0.99; else *s_left = -0.99; } if (l+1 == len || l % LIMITER_ADJUST_PERIOD == 0) { // Time to check & adjust limit parameters if (clipcnt > 0 || localmaxvol > maxvol) { // We got more clipping! clipcnt = 0; float newlimitvol = limitthresh/localmaxvol; // Compute volume reduction necessary to bring in peak limitvol = newlimitvol; // Compute delta (speed) to get to that reduction (attack time) dlimitvol = (limitvol-curlimitvol)/LIMITER_ATTACK_LENGTH; // Store new max maxvol = localmaxvol; } if (dlimitvol < 0.0 && curlimitvol <= limitvol) { // We are done the attack phase- switch to release! dlimitvol = limitrr; } if (dlimitvol > 0.0 && curlimitvol > maxamp) { // Too much amp! dlimitvol = 0.0; } } } } // Make a copy for the visual scope // Output scope is disabled // memcpy(app->getSCOPE(), out, sizeof(sample_t) * len); // Now go through all FINAL children-- // They work on the end resulting signal, so we need to change the routing // so that our output becomes their input abtmp->ins[0][0] = out[0]; abtmp->ins[1][0] = out[1]; abtmp->outs[0][0] = out[0]; abtmp->outs[1][0] = out[1]; processchain(pre,len,ab,abtmp,ProcessorItem::TYPE_FINAL,0); // No mixing // Advance global sample count samplecnt += len; } // Now copy single hardcoded output to all other outputs // This is a hack until more developed multioutput support is implemented for (int i = 1; i < ab->numouts; i++) { for (int chan = 0; chan <= stereo; chan++) { if (ab->outs[chan][i] != 0) memcpy(ab->outs[chan][i],ab->outs[chan][0],sizeof(sample_t) * len); } } } void *RootProcessor::run_cleanup_thread (void *ptr) { RootProcessor *inst = static_cast(ptr); while (inst->threadgo) { // Traverse the list of children and look for a processor pending delete ProcessorItem *cur = inst->firstchild, *prev = 0; while (cur != 0) { // Search for any processor pending delete in our list while (cur != 0 && cur->status != ProcessorItem::STATUS_PENDING_DELETE) { prev = cur; cur = cur->next; } if (cur != 0) { // Got one to delete, unlink! if (prev != 0) prev->next = cur->next; else inst->firstchild = cur->next; ProcessorItem *tmp = cur->next; delete cur->p; delete cur; cur = tmp; } } // Consider changing this from fixed sleep to mutex- // or letting memmgr do the processor deletion usleep(10000); } // RootProcessor closing.. // Cleanup thread ending-- that means all child processors must end! ProcessorItem *cur = inst->firstchild; while (cur != 0) { ProcessorItem *tmp = cur->next; // Stop child! delete cur->p; delete cur; cur = tmp; } // printf(" :: Processor: RootProcessor- all children finished.\n"); return 0; } // Overdubbing version of record into existing loop RecordProcessor::RecordProcessor(Fweelin *app, InputSettings *iset, float *inputvol, Loop *od_loop, float od_playvol, nframes_t od_startofs, float *od_feedback) : Processor(app), sync_state(SS_NONE), iset(iset), inputvol(inputvol), nbeats(0), endsyncidx(-2), endsyncwait(0), stopped(0), pa_mgr(0), od_loop(od_loop), od_playvol(od_playvol), od_feedback(od_feedback), od_curbeat(0), od_fadein(1), od_fadeout(0), od_stop(0), od_prefadeout(0), od_lastofs(0) { // Store initial value for overdub feedback if (od_feedback != 0) od_feedback_lastval = *od_feedback; // Use the block supplied-- fixed length growchain = 0; compute_stats = 0; recblk = od_loop->blocks; // Clear the hash for the loop, since overdubbing will change it od_loop->SetSaveStatus(NO_SAVE); mbuf[0] = new sample_t[app->getBUFSZ()]; od_last_mbuf[0] = new sample_t[app->getBUFSZ()]; od_last_lpbuf[0] = new sample_t[app->getBUFSZ()]; // Is the loop we are overdubbing into a stereo loop? If so, run in stereo if (recblk->IsStereo()) { stereo = 1; mbuf[1] = new sample_t[app->getBUFSZ()]; od_last_mbuf[1] = new sample_t[app->getBUFSZ()]; od_last_lpbuf[1] = new sample_t[app->getBUFSZ()]; } else { stereo = 0; mbuf[1] = 0; od_last_mbuf[1] = 0; od_last_lpbuf[1] = 0; } // Create an audioblock iterator to move through that memory i = new AudioBlockIterator(recblk,app->getBUFSZ(), app->getPRE_EXTRACHANNEL()); // And a temporary iterator for overdub jumps tmpi = new AudioBlockIterator(recblk,app->getBUFSZ(), app->getPRE_EXTRACHANNEL()); // Check for quantize to pulse sync = od_loop->pulse; if (sync != 0) { // Behavior is that in overdub we always start immediately // .. at the right place in the loop if (od_startofs == 0) i->Jump(sync->GetPos()); else { // Calculate correct current beat based on startofs od_curbeat = od_startofs/sync->GetLength(); } // Notify Pulse to call us every beat sync_state = SS_BEAT; app->getEMG()->ListenEvent(this,sync,T_EV_PulseSync); } if (od_startofs != 0) { // Start at specified position i->Jump(od_startofs); } // And update peaks&avgs for displays (no grow!) pa_mgr = app->getBMG()->PeakAvgOn(recblk,i); }; // Recording into preexisting fixed size block // We can optionally specify whether we want the block to be stereo // Don't try to switch from stereo->mono->stereo for a block, though // If we don't specify stereo/mono, RecordProcessor decides automatically // based on the existing 'dest' RecordProcessor::RecordProcessor(Fweelin *app, InputSettings *iset, float *inputvol, AudioBlock *dest, int suggest_stereo) : Processor(app), sync_state(SS_NONE), iset(iset), inputvol(inputvol), sync(0), tmpi(0), nbeats(0), stopped(0), pa_mgr(0), od_loop(0), od_feedback(0), od_fadeout(0), od_stop(0), od_prefadeout(0) { // Use the block supplied-- fixed length growchain = 0; compute_stats = 1; recblk = dest; // Stereo or mono? mbuf[0] = new sample_t[app->getBUFSZ()]; stereo = (suggest_stereo == -1 ? recblk->IsStereo() : suggest_stereo); if (stereo) mbuf[1] = new sample_t[app->getBUFSZ()]; else mbuf[1] = 0; // Create an audioblock iterator to move through that memory i = new AudioBlockIterator(recblk,app->getBUFSZ(), app->getPRE_EXTRACHANNEL()); }; // ISSUES- // // Loop is straddled right now // between RecordProcessor & LoopManager-- icky // make separation more clear // // Tricky stuff with those block managers // // Recording new blocks, growing size as necessary RecordProcessor::RecordProcessor(Fweelin *app, InputSettings *iset, float *inputvol, Pulse *sync, AudioBlock *audiomem, AudioBlockIterator *audiomemi, nframes_t peaksavgs_chunksize) : Processor(app), sync_state(SS_NONE), iset(iset), inputvol(inputvol), sync(sync), tmpi(0), nbeats(0), endsyncidx(-2), endsyncwait(0), stopped(0), pa_mgr(0), od_loop(0), od_feedback(0), od_fadeout(0), od_stop(0), od_prefadeout(0) { // Grow the length of record as necessary growchain = 1; compute_stats = 0; // Get the next available block so we can begin recording now! recblk = (AudioBlock *) app->getPRE_AUDIOBLOCK()->RTNew(); if (recblk == 0) { printf("RecordProcessor: ERROR: No free blocks for record\n"); stopped = 1; i = 0; return; } // Stereo or mono? mbuf[0] = new sample_t[app->getBUFSZ()]; if (iset->IsSelectedStereo()) { stereo = 1; mbuf[1] = new sample_t[app->getBUFSZ()]; } else { stereo = 0; mbuf[1] = 0; } // printf("REC: New loop: %s\n",(stereo ? "stereo" : "mono")); // Create an audioblock iterator to move through that memory i = new AudioBlockIterator(recblk,app->getBUFSZ(), app->getPRE_EXTRACHANNEL()); // Check for sync to an pulse if (sync != 0) { if (sync->GetPct() >= 0.5) { // Close to next downbeat- so delay record start til then stopped = 1; sync_state = SS_START; app->getEMG()->ListenEvent(this,sync,T_EV_PulseSync); } else { // Close to previous downbeat- start record now & grab missed // chunk from previous downbeat til now // Use BED_MarkerPoints in audiomem to get chunk BED_MarkerPoints *mp = (BED_MarkerPoints *) (audiomem->GetExtendedData(T_BED_MarkerPoints)); if (mp == 0) { // No marker block printf("Err (SYNCREC): No markers striped in Audio Mem!\n"); exit(1); } else { // Get a sub block from the previous downbeat nframes_t curofs = audiomemi->GetTotalLength2Cur(), prevofs; TimeMarker *prevm = mp->GetMarkerNBeforeCur(1,curofs); if (prevm != 0) { prevofs = prevm->markofs; AudioBlock *beginblk = audiomem->GenerateSubChain(prevofs,curofs,stereo); if (beginblk == 0) { printf("Err: Problem generating subchain from audiomemory.\n"); exit(1); } // Now reorganize the block chain to put beginblk first recblk = recblk->InsertFirst(beginblk); // Recalculate iterator constants-- iterator should // start recording at end of block ripped from audiomemory i->GenConstants(); } else { // Bad markers (not fatal!)- just don't copy from audiomem printf("SYNCREC: Previous markers in Audio Mem unknown!\n"); } } // Notify Pulse to call us every beat sync_state = SS_BEAT; app->getEMG()->ListenEvent(this,sync,T_EV_PulseSync); } } // Concurrently compute peaks & averages during recording if (peaksavgs_chunksize != 0) { AudioBlock *peaks = (AudioBlock *) recblk->RTNew(), *avgs = (AudioBlock *) recblk->RTNew(); if (peaks == 0 || avgs == 0) { printf("RecordProcessor: ERROR: No free blocks for peaks/avgs\n"); stopped = 1; return; } recblk->AddExtendedData(new BED_PeaksAvgs(peaks,avgs, peaksavgs_chunksize)); pa_mgr = app->getBMG()->PeakAvgOn(recblk,i,1); } // Tell the block manager to auto-grow this block chain for recording app->getBMG()->GrowChainOn(recblk,i); }; RecordProcessor::~RecordProcessor() { if (!stopped) { // This shouldn't be a problem, it happens in overdub and direct record AbortRecording(); } // Notify BlockManager we are dying in case any mgrs depend on us app->getBMG()->RefDeleted(this); app->getBMG()->RefDeleted(i); // Stop listening for pulse sync events if (sync != 0) app->getEMG()->UnlistenEvent(this,sync,T_EV_PulseSync); if (i != 0) delete i; if (tmpi != 0) delete tmpi; delete[] mbuf[0]; if (mbuf[1] != 0) delete[] mbuf[1]; if (od_loop != 0) { delete[] od_last_mbuf[0]; if (od_last_mbuf[1] != 0) delete[] od_last_mbuf[1]; delete[] od_last_lpbuf[0]; if (od_last_lpbuf[1] != 0) delete[] od_last_lpbuf[1]; } }; void RecordProcessor::SyncUp() { // Sync loop to pulse if (od_loop != 0) { sync_state = SS_START; sync = od_loop->pulse; app->getEMG()->ListenEvent(this,sync,T_EV_PulseSync); } } nframes_t RecordProcessor::GetRecordedLength() { return i->GetTotalLength2Cur(); } void RecordProcessor::EndNow() { // End record now if (od_loop == 0) stopped = 1; // For straight record, stop all processing else od_stop = 1; // For overdub, keep playing going EndRecordEvent *endrec = (EndRecordEvent *) Event::GetEventByType(T_EV_EndRecord); if (endrec == 0) { printf("RecordProcessor: ERROR: No free event memory\n"); exit(1); } if (od_loop == 0 && i->GetTotalLength2Cur() == 0) { // Zero length record! Forget it! endrec->keeprecord = 0; AbortRecording(); } else { endrec->keeprecord = 1; // Not overdubbing.. if (od_loop == 0) { // Chop recorded block to current position (end record) i->EndChain(); if (growchain) { // Stop expanding this recording app->getBMG()->GrowChainOff(recblk); } // For new non syncronized loops-- // Bend our strip of audio into a loop // Smooth beginning into end, shorten loop- if (sync == 0) recblk->Smooth(); /* else printf("reclen: %d, synclen: %d\n",recblk->GetTotalLen(), sync->GetLength()); */ } // End peaks avgs compute now if (pa_mgr != 0) { pa_mgr->End(); app->getBMG()->PeakAvgOff(recblk); pa_mgr = 0; } } // Broadcast a message that recording has finished // Broadcast nonRT, because EndRecord does non-RT safe operations app->getEMG()->BroadcastEvent(endrec, this); } // May be called during EndNow() (RT) // RT safe void RecordProcessor::AbortRecording() { // Stop iterator- this stops GrowChain as well as other // managers attached to iterator i->Stop(); // Stop pulse sync if (sync != 0) { // AbortRecording is RT safe, so reset sync_state to stop further // sync processing sync_state = SS_ENDED; } // No more process(), just in case race condition // causes process() while we are still cleaning up stopped = 1; // End peaks avgs compute now if (pa_mgr != 0) { pa_mgr->End(); app->getBMG()->PeakAvgOff(recblk); pa_mgr = 0; } // Blocks are deleted nonRT in DeleteLoop if (growchain) // Stop expanding this recording app->getBMG()->GrowChainOff(recblk); } void RecordProcessor::ReceiveEvent(Event *ev, EventProducer *from) { switch (ev->GetType()) { case T_EV_PulseSync : { PulseSyncEvent *pev = (PulseSyncEvent *) ev; if (pev->syncidx == -1) { switch (sync_state) { case SS_START: if (od_loop != 0) { // Overdub record, fade to start since we are syncing with pulse Jump(od_loop->pulse->GetPos()); } else { // Start record now stopped = 0; } sync_state = SS_BEAT; break; case SS_END: nbeats++; endsyncwait = 1; break; case SS_BEAT: if (od_loop != 0) { // Overdub record od_curbeat++; if (od_curbeat >= od_loop->nbeats) { // Quantize loop by restarting Jump(od_loop->pulse->GetPos()); od_curbeat = 0; } } else { // Regular grow record nbeats++; } // Call us on further beats sync_state = SS_BEAT; break; case SS_ENDED: break; default: break; } } else if (pev->syncidx == endsyncidx && endsyncwait) { // End record now EndNow(); // Remove user-defined sync point sync->DelSyncPos(endsyncidx); // Stop calling us! sync_state = SS_ENDED; } } break; default: break; } }; #if 0 int RecordProcessor::ProcessorCall(void *trigger, int data) { if (trigger == sync) { // Called because of downbeat switch (data) { case PC_START: if (od_loop != 0) { // Overdub record, fade to start since we are syncing with pulse Jump(od_loop->pulse->GetPos()); } else { // Start record now stopped = 0; } // Notify Pulse to call us every beat return PC_BEAT; case PC_END: // End record now nbeats++; EndNow(); // Stop calling us! return PC_NONE; case PC_BEAT: if (od_loop != 0) { // Overdub record od_curbeat++; if (od_curbeat >= od_loop->nbeats) { // Quantize loop by restarting Jump(od_loop->pulse->GetPos()); od_curbeat = 0; } } else { // Regular grow record nbeats++; } // Call us on further beats return PC_BEAT; } } return PC_NONE; }; #endif void RecordProcessor::End() { if (od_loop != 0) { // Overdub ends after short smooth fadeout (see process()) od_fadeout = 1; } else { if (sync != 0) { // Sync, so check timing if (sync->GetPct() >= 0.5 || sync->GetPos() < REC_TAIL_LEN) { // Delay record til slightly after downbeat-- we // want to capture an extra 'tail' for crossfading. if (sync->GetPos() < REC_TAIL_LEN) endsyncwait = 1; // Past the downbeat endsyncidx = sync->AddSyncPos(REC_TAIL_LEN); sync_state = SS_END; } else { // Close to previous downbeat- end record now & crop extra chunk EndNow(); // Now hack off end of recording to downbeat // *** To be tested *** /*if (recblk->HackTotalLengthBy(sync->GetPos())) printf("Err (SYNCREC): Problem cutting length of record\n");*/ } } else { // No sync, stop recording now! EndNow(); } } } // Fades input samples out of mix- writing to 'dest' void RecordProcessor::FadeOut_Input(nframes_t len, sample_t *input_l, sample_t *input_r, sample_t *loop_l, sample_t *loop_r, float old_fb, float new_fb, float fb_delta, sample_t *dest_l, sample_t *dest_r) { // Fade out input samples // (feedback to 1.0) // Left float ramp = 0.0, negramp = 1.0, dr = 1.0/prelen; nframes_t l = 0; float cur_fb = old_fb; if (fb_delta == 0.0) { for (; l < prelen; l++, ramp += dr, negramp -= dr) { dest_l[l] = (input_l[l]*negramp) + (loop_l[l]*(ramp+negramp*cur_fb)); } } else { for (; l < prelen; l++, ramp += dr, negramp -= dr, cur_fb += fb_delta) { dest_l[l] = (input_l[l]*negramp) + (loop_l[l]*(ramp+negramp*cur_fb)); } } // Copy remainder of fragment directly from loop if (len-l > 0) memcpy(&(dest_l[l]),&(loop_l[l]),sizeof(sample_t) * (len-l)); if (dest_r != 0) { // Right ramp = 0.0; negramp = 1.0; cur_fb = old_fb; if (fb_delta == 0.0) { for (l = 0; l < prelen; l++, ramp += dr, negramp -= dr) { dest_r[l] = (input_r[l]*negramp) + (loop_r[l]*(ramp+negramp*cur_fb)); } } else { for (l = 0; l < prelen; l++, ramp += dr, negramp -= dr, cur_fb += fb_delta) { dest_r[l] = (input_r[l]*negramp) + (loop_r[l]*(ramp+negramp*cur_fb)); } } // Copy remainder of fragment directly from loop if (len-l > 0) memcpy(&(dest_r[l]),&(loop_r[l]),sizeof(sample_t) * (len-l)); } }; // Fades input samples into mix- writing to 'dest' void RecordProcessor::FadeIn_Input(nframes_t len, sample_t *input_l, sample_t *input_r, sample_t *loop_l, sample_t *loop_r, float old_fb, float new_fb, float fb_delta, sample_t *dest_l, sample_t *dest_r) { // Left // Fade in input samples float ramp = 0.0, negramp = 1.0, dr = 1.0/prelen; nframes_t l = 0; float cur_fb = old_fb; if (fb_delta == 0.0) { for (; l < prelen; l++, ramp += dr, negramp -= dr) { dest_l[l] = (input_l[l]*ramp) + (loop_l[l]*(negramp+ramp*cur_fb)); } // Proceed as regular mix for (; l < len; l++) dest_l[l] = input_l[l] + loop_l[l] * cur_fb; } else { for (; l < prelen; l++, ramp += dr, negramp -= dr, cur_fb += fb_delta) { dest_l[l] = (input_l[l]*ramp) + (loop_l[l]*(negramp+ramp*cur_fb)); } // Proceed as regular mix for (; l < len; l++, cur_fb += fb_delta) dest_l[l] = input_l[l] + loop_l[l] * cur_fb; } if (dest_r != 0) { // Right // Fade in input samples ramp = 0.0; negramp = 1.0; cur_fb = old_fb; if (fb_delta == 0.0) { for (l = 0; l < prelen; l++, ramp += dr, negramp -= dr) { dest_r[l] = (input_r[l]*ramp) + (loop_r[l]*(negramp+ramp*cur_fb)); } // Proceed as regular mix for (; l < len; l++) dest_r[l] = input_r[l] + loop_r[l] * cur_fb; } else { for (l = 0; l < prelen; l++, ramp += dr, negramp -= dr, cur_fb += fb_delta) { dest_r[l] = (input_r[l]*ramp) + (loop_r[l]*(negramp+ramp*cur_fb)); } // Proceed as regular mix for (; l < len; l++, cur_fb += fb_delta) dest_r[l] = input_r[l] + loop_r[l] * cur_fb; } } }; // Jumps to a position within an overdubbing loop- fade of input & output void RecordProcessor::Jump(nframes_t ofs) { //dopreprocess(); //i->Jump(ofs); nframes_t curofs = i->GetTotalLength2Cur(); if (curofs != ofs) { if (od_loop != 0) { #if 0 printf("Overdub jump: %d -> %d\n",curofs,ofs); printf("looplen: %d pulselen: %d\n",od_loop->blocks->GetTotalLen(), od_loop->pulse->GetLength()); // Since we are jumping in overdub, we need to fade out/in input // We need to fadeout input on preprocess // and fadein input on new position // So go back to the last processed fragment and fade out input samples FadeOut_Input(app->getBUFSZ(), od_last_mbuf[0], od_last_mbuf[1], od_last_lpbuf[0], od_last_lpbuf[1], od_feedback, od_last_mbuf[0], od_last_mbuf[1]); // Store in last processed fragment tmpi->Jump(od_lastofs); tmpi->PutFragment(od_last_mbuf[0],od_last_mbuf[1]); od_fadein = 1; #endif od_lastofs = curofs; od_prefadeout = 1; od_fadein = 1; } dopreprocess(); i->Jump(ofs); } }; void RecordProcessor::process(char pre, nframes_t len, AudioBuffers *ab) { nframes_t fragmentsize = app->getBUFSZ(); if (len > fragmentsize) len = fragmentsize; // Some key behavior: // stopped means no processing occurs // od_fadein means fade in input samples // od_fadeout means fade out input samples (it is the end of overdub) // od_stop means overdub has ended but playing from loop is retained sample_t *out[2] = {ab->outs[0][0], ab->outs[1][0]}; if (!stopped) { sample_t *lpbuf[2] = {0,0}; // Loop buffer // Compute feedback delta float new_fb, old_fb, fb_delta = 0.0; if (od_feedback != 0) { new_fb = *od_feedback; old_fb = od_feedback_lastval; fb_delta = (new_fb-old_fb)/len; } else new_fb = old_fb = OVERDUB_DEFAULT_FEEDBACK; if (!pre) od_feedback_lastval = new_fb; /* if (od_feedback != 0) printf("OLD FB: %f NEW FB: %f DELTA: %f\n",old_fb,new_fb,fb_delta); */ // ** Play part if (od_loop != 0) { // Overdub- playing & recording // Adjust volume if (!pre) od_loop->UpdateVolume(); // Check if we need to fade-out at a previous position if (!pre && od_prefadeout) { // We jumped to a new position in overdub.. fadeout at // old position tmpi->Jump(od_lastofs); // Get audio from the block if (stereo) tmpi->GetFragment(&lpbuf[0],&lpbuf[1]); else tmpi->GetFragment(&lpbuf[0],0); // Mix selected inputs ab->MixInputs(len,mbuf,iset,*inputvol,compute_stats); FadeOut_Input(len, mbuf[0], mbuf[1], lpbuf[0], lpbuf[1], old_fb, new_fb, fb_delta, mbuf[0], mbuf[1]); if (stereo) tmpi->PutFragment(mbuf[0],mbuf[1]); else tmpi->PutFragment(mbuf[0],0); od_prefadeout = 0; } // Get audio from the block if (stereo) i->GetFragment(&lpbuf[0],&lpbuf[1]); else i->GetFragment(&lpbuf[0],0); // Scale volume float vol = od_loop->vol * od_playvol; // Protect our ears! float maxvol = app->getCFG()->GetMaxPlayVol(); if (vol > maxvol) vol = maxvol; if (vol < 0) vol = 0; // Play to output if (stereo) { sample_t *o_l = out[0], *o_r = out[1], *lpb_l = lpbuf[0], *lpb_r = lpbuf[1]; for (nframes_t l = 0; l < len; l++, o_l++, o_r++, lpb_l++, lpb_r++) { *o_l = *lpb_l * vol; *o_r = *lpb_r * vol; } } else { sample_t *o_l = out[0], *lpb_l = lpbuf[0]; for (nframes_t l = 0; l < len; l++, o_l++, lpb_l++) *o_l = *lpb_l * vol; if (out[1] != 0) // Mono loop into stereo outs- duplicate memcpy(out[1],out[0],sizeof(sample_t) * len); } if (!pre) { // Fade together current with preprocessed to create smoothed fadepreandcurrent(ab); } } else { // No overdub- not playing- zero outputs memset(out[0],0,sizeof(sample_t) * len); if (out[1] != 0) memset(out[1],0,sizeof(sample_t) * len); } // ** Record part if (!pre && !od_stop) { // Mix selected inputs to record loop ab->MixInputs(len,mbuf,iset,*inputvol,compute_stats); if (od_loop != 0) { // Overdub- mix new input with loop // First, make copies of buffers incase we have an overdub jump memcpy(od_last_lpbuf[0],lpbuf[0],sizeof(sample_t) * len); memcpy(od_last_mbuf[0],mbuf[0],sizeof(sample_t) * len); if (stereo) { memcpy(od_last_lpbuf[1],lpbuf[1],sizeof(sample_t) * len); memcpy(od_last_mbuf[1],mbuf[1],sizeof(sample_t) * len); } // od_lastofs = i->GetTotalLength2Cur(); if (!od_fadeout && !od_fadein) { // Regular case mix if (stereo) { sample_t *m_l = mbuf[0], *m_r = mbuf[1], *lpb_l = lpbuf[0], *lpb_r = lpbuf[1]; if (fb_delta == 0.0) { for (nframes_t l = 0; l < len; l++, m_l++, m_r++, lpb_l++, lpb_r++) { *m_l += *lpb_l * old_fb; *m_r += *lpb_r * old_fb; } } else { for (nframes_t l = 0; l < len; l++, m_l++, m_r++, lpb_l++, lpb_r++, old_fb += fb_delta) { *m_l += *lpb_l * old_fb; *m_r += *lpb_r * old_fb; } } } else { sample_t *m_l = mbuf[0], *lpb_l = lpbuf[0]; if (fb_delta == 0.0) { for (nframes_t l = 0; l < len; l++, m_l++, lpb_l++) *m_l += *lpb_l * old_fb; } else { for (nframes_t l = 0; l < len; l++, m_l++, lpb_l++, old_fb += fb_delta) *m_l += *lpb_l * old_fb; } } } else if (od_fadein) { // Fade in input samples FadeIn_Input(len, mbuf[0], mbuf[1], lpbuf[0], lpbuf[1], old_fb, new_fb, fb_delta, mbuf[0], mbuf[1]); // Proceed as regular overdub od_fadein = 0; } else if (od_fadeout) { // Fade out input samples FadeOut_Input(len, mbuf[0], mbuf[1], lpbuf[0], lpbuf[1], old_fb, new_fb, fb_delta, mbuf[0], mbuf[1]); } } // Record if (stereo) i->PutFragment(mbuf[0],mbuf[1]); else i->PutFragment(mbuf[0],0); if (!pre) { if (od_fadeout) { // Now end! EndNow(); } // Move along i->NextFragment(); } } else if (!pre && od_stop) { // Ended, no record but just advance i->NextFragment(); } } else { memset(out[0],0,sizeof(sample_t) * len); if (out[1] != 0) memset(out[1],0,sizeof(sample_t) * len); } } PlayProcessor::PlayProcessor(Fweelin *app, Loop *playloop, float playvol, nframes_t startofs) : Processor(app), sync_state(SS_NONE), stopped(0), playloop(playloop), playvol(playvol), curbeat(0) { // Stereo? stereo = playloop->blocks->IsStereo(); // Setup iterator to move through loop i = new AudioBlockIterator(playloop->blocks,app->getBUFSZ()); // Check for quantize to pulse sync = playloop->pulse; if (sync != 0) { // OK, we are synced to an pulse, so notify on every beat of that pulse if (startofs == 0 && sync->GetPct() >= 0.5) { // Close to next downbeat- so delay play start til then stopped = 1; sync_state = SS_START; app->getEMG()->ListenEvent(this,sync,T_EV_PulseSync); } else { // Either we are close to a previous downbeat, // or we've been set to start at a specific place. // Start play now at the right place if (startofs == 0) i->Jump(sync->GetPos()); else { // Calculate correct current beat based on startofs curbeat = startofs/sync->GetLength(); } // Notify Pulse to call us every beat sync_state = SS_BEAT; app->getEMG()->ListenEvent(this,sync,T_EV_PulseSync); } } if (startofs != 0) { // Start at specified position i->Jump(startofs); } }; PlayProcessor::~PlayProcessor() { // Notify BlockManager we are dying in case any mgrs depend on us app->getBMG()->RefDeleted(this); app->getBMG()->RefDeleted(i); // Stop listening for pulse sync events if (sync != 0) app->getEMG()->UnlistenEvent(this,sync,T_EV_PulseSync); delete i; } void PlayProcessor::SyncUp() { // Sync loop to pulse sync_state = SS_START; sync = playloop->pulse; app->getEMG()->ListenEvent(this,sync,T_EV_PulseSync); } nframes_t PlayProcessor::GetPlayedLength() { return i->GetTotalLength2Cur(); } void PlayProcessor::ReceiveEvent(Event *ev, EventProducer *from) { switch (ev->GetType()) { case T_EV_PulseSync : { PulseSyncEvent *pev = (PulseSyncEvent *) ev; if (pev->syncidx == -1) { switch (sync_state) { case SS_START: // Start play now dopreprocess(); // Fade to start i->Jump(sync->GetPos()); stopped = 0; // Call us every beat sync_state = SS_BEAT; break; case SS_BEAT: curbeat++; if (curbeat >= playloop->nbeats) { // Quantize loop by restarting dopreprocess(); // Fade to loop point i->Jump(sync->GetPos()); curbeat = 0; } // Call us on further beats sync_state = SS_BEAT; break; case SS_ENDED: break; default: break; } } } break; default: break; } }; void PlayProcessor::process(char pre, nframes_t len, AudioBuffers *ab) { nframes_t fragmentsize = app->getBUFSZ(); if (len > fragmentsize) len = fragmentsize; sample_t *out[2] = {ab->outs[0][0], ab->outs[1][0]}; if (!stopped) { if (!pre) playloop->UpdateVolume(); // Get audio from the block and put it in out sample_t *buf[2]; if (stereo) i->GetFragment(&buf[0],&buf[1]); else i->GetFragment(&buf[0],0); // Scale volume float vol = playloop->vol * playvol; // Protect our ears! float maxvol = app->getCFG()->GetMaxPlayVol(); if (vol > maxvol) vol = maxvol; if (vol < 0) vol = 0; // Play if (stereo) { sample_t *o_l = out[0], *o_r = out[1], *b_l = buf[0], *b_r = buf[1]; for (nframes_t l = 0; l < len; l++, o_l++, o_r++, b_l++, b_r++) { *o_l = *b_l * vol; *o_r = *b_r * vol; } } else { sample_t *o_l = out[0], *b_l = buf[0]; for (nframes_t l = 0; l < len; l++, o_l++, b_l++) *o_l = *b_l * vol; if (out[1] != 0) // Mono loop into stereo outs- duplicate memcpy(out[1],out[0],sizeof(sample_t) * len); } if (!pre) { // Fade together current with preprocessed to create smoothed fadepreandcurrent(ab); // Advance to next fragment! i->NextFragment(); } } else { memset(out[0],0,sizeof(sample_t) * len); if (out[1] != 0) memset(out[1],0,sizeof(sample_t) * len); } } FileStreamer::FileStreamer(Fweelin *app, nframes_t outbuflen) : Processor(app), writerstatus(STATUS_STOPPED), outname(0), timingname(0), nbeats(0), outbuflen(outbuflen), threadgo(1) { // Encode in stereo if master FW is running in stereo stereo = preab->IsStereoMaster(); const static size_t STACKSIZE = 1024*128; pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setstacksize(&attr,STACKSIZE); printf("FILESTREAMER: Stacksize: %d.\n",STACKSIZE); // Start encoding thread int ret = pthread_create(&encode_thread, &attr, run_encode_thread, static_cast(this)); if (ret != 0) { printf("(FILESTREAMER) pthread_create failed, exiting\n"); exit(1); } SRMWRingBuffer_Writers::RegisterWriter(encode_thread); // Allocate space for time markers marks = ::new TimeMarker[MARKERBUFLEN]; } FileStreamer::~FileStreamer() { // Stop any writing if (writerstatus != STATUS_STOPPED) writerstatus = STATUS_STOP_PENDING; // Terminate the management thread threadgo = 0; pthread_join(encode_thread,0); // Erase space for time markers ::delete[] marks; // printf(" :: Processor: VorbisStreamer end\n"); }; void FileStreamer::InitStreamer() { // Allocate output buffer outbuf[0] = new sample_t[outbuflen]; if (stereo) outbuf[1] = new sample_t[outbuflen]; else outbuf[1] = 0; // Setup encoder switch (filetype) { case VORBIS: // OGG VORBIS enc = new VorbisEncoder(app,stereo); break; case WAV: //WAV enc = new SndFileEncoder(app, outbuflen, stereo, WAV); break; case FLAC: //FLAC enc = new SndFileEncoder(app, outbuflen, stereo, FLAC); break; case AU: //AU enc = new SndFileEncoder(app, outbuflen, stereo, AU); break; default: enc = new VorbisEncoder(app,stereo); break; } }; void FileStreamer::EndStreamer() { // Free output buffer delete[] outbuf[0]; if (outbuf[1] != 0) delete[] outbuf[1]; // Cleanup encoder delete enc; }; void FileStreamer::process(char pre, nframes_t len, AudioBuffers *ab) { // Hack- take first input and stream to disk sample_t *in[2] = {ab->ins[0][0], ab->ins[1][0]}; // sample_t *out = ab->outs[0]; if (!pre && writerstatus == STATUS_RUNNING) { // Streamer is active-- dump the realtime data into our buffer // for later encoding // Vorbis clips near 1.0 sample_t *b_l = in[0], *b_r = in[1]; if (stereo && b_r != 0) { // Stereo enc->Preprocess(b_l,b_r,len); if (outpos + len < outbuflen) { memcpy(&outbuf[0][outpos],in[0],sizeof(sample_t) * len); memcpy(&outbuf[1][outpos],in[1],sizeof(sample_t) * len); outpos += len; } else { // Wrap case- byte-by-byte nframes_t n; sample_t *o_l = outbuf[0], *o_r = outbuf[1]; for (n = 0; outpos < outbuflen; outpos++, n++) { o_l[outpos] = b_l[n]; o_r[outpos] = b_r[n]; } outpos = 0; wrap = 1; for (; n < len; outpos++, n++) { o_l[outpos] = b_l[n]; o_r[outpos] = b_r[n]; } } } else { // Mono enc->Preprocess(b_l,0,len); if (outpos + len < outbuflen) { memcpy(&outbuf[0][outpos],in[0],sizeof(sample_t) * len); outpos += len; } else { // Wrap case- byte-by-byte nframes_t n; sample_t *o_l = outbuf[0]; for (n = 0; outpos < outbuflen; outpos++, n++) o_l[outpos] = b_l[n]; outpos = 0; wrap = 1; for (; n < len; outpos++, n++) o_l[outpos] = b_l[n]; } } } // Don't touch output as we are processing in serial //memset(out,0,sizeof(sample_t) * len); }; void FileStreamer::ReceiveEvent(Event *ev, EventProducer *from) { switch (ev->GetType()) { case T_EV_PulseSync : // Called because of downbeat // Record the beat if (timingfd != 0) { nbeats++; marks[mkwriteidx].markofs = app->getRP()->GetSampleCnt()-startcnt; marks[mkwriteidx].data = nbeats; mkwriteidx++; if (mkwriteidx >= MARKERBUFLEN) mkwriteidx = 0; } break; default: break; } }; void *FileStreamer::run_encode_thread (void *ptr) { FileStreamer *inst = static_cast(ptr); nframes_t curpos; // *** Could FileStreamer be rewritten as a BlockManager, using the // BMG manage thread? It could still be a core DSP processor, no? while (inst->threadgo || inst->writerstatus != STATUS_STOPPED) { switch (inst->writerstatus) { case STATUS_RUNNING: // We're running, so feed data to the chosen audio encoder. // Make a local copy of outpos-- because it is liable to change // during this loop!-- RT thread curpos = inst->outpos; if (curpos != inst->encodepos) { nframes_t num; if (inst->wrap) { // Wrap case- so take from the end & beginning of circular buffer nframes_t numend = inst->outbuflen - inst->encodepos; num = curpos + numend; if (numend > 0) { inst->outputsize += inst->enc->WriteSamplesToDisk (inst->outbuf, inst->encodepos, numend); } if (curpos > 0) { inst->outputsize += inst->enc->WriteSamplesToDisk (inst->outbuf, 0, curpos); } inst->wrap = 0; } else { if (curpos > inst->encodepos) { num = curpos - inst->encodepos; inst->outputsize += inst->enc->WriteSamplesToDisk (inst->outbuf, inst->encodepos, num); } else { // Wrap not set but buffer seems wrapped- this could be caused // by extreme processor load and this thread not keeping up with // RT- print warning printf("STREAMER: WARNING: Buffer wrap possible?\n"); } } inst->encodepos = curpos; } // Now dump markers to gnusound USX for later edit points while (inst->mkreadidx != inst->mkwriteidx) { fprintf(inst->timingfd,"%ld=4 0 0.000000 lb%d\n", (long int) inst->marks[inst->mkreadidx].markofs, (int) inst->marks[inst->mkreadidx].data); inst->mkreadidx++; if (inst->mkreadidx >= MARKERBUFLEN) inst->mkreadidx = 0; } break; case STATUS_START_PENDING: // Open output file // printf("DISK: Open output file.\n"); inst->outfd = fopen(inst->outname,"wb"); inst->timingfd = fopen(inst->timingname,"wb"); if (inst->outfd != 0 && inst->timingfd != 0) { // Setup vorbis lib printf("DISK: Initialize streamer.\n"); inst->InitStreamer(); // Write header block for GNUSound fprintf(inst->timingfd, "[Mixer]\n" "0=1.000000\n" "1=1.000000\n" "Source Is Mute=0\n" "Source Is Solo=0\n\n" "[Markers for track 0]\n"); // Setup beat counting inst->nbeats = 0; inst->mkwriteidx = 0; inst->mkreadidx = 0; // Notify us on ALL pulse beats... we will stripe them all! inst->app->getEMG()->ListenEvent(inst,0,T_EV_PulseSync); // Set encoder to dump to file we have opened inst->enc->SetupFileForWriting(inst->outfd); inst->outputsize = 0; inst->outpos = 0; inst->encodepos = 0; inst->wrap = 0; inst->startcnt = inst->app->getRP()->GetSampleCnt(); inst->writerstatus = STATUS_RUNNING; // printf("DISK: Streamer encoding.\n"); } else { printf("DISK: Error writing output file.\n"); if (inst->outfd != 0) fclose(inst->outfd); if (inst->timingfd != 0) fclose(inst->timingfd); inst->writerstatus = STATUS_STOPPED; inst->timingfd = 0; inst->outname = 0; inst->timingname = 0; inst->app->FlushStreamOutName(); } break; case STATUS_STOP_PENDING: printf("DISK: Closing streamer.\n"); // Tell encoder we are stopping inst->enc->PrepareFileForClosing(); // Now end inst->EndStreamer(); // Stop notify on ALL pulse beats. inst->app->getEMG()->UnlistenEvent(inst,0,T_EV_PulseSync); fclose(inst->outfd); fclose(inst->timingfd); inst->timingfd = 0; printf("DISK: ..done\n"); inst->writerstatus = STATUS_STOPPED; inst->outname = 0; // OK to start a new file inst->timingname = 0; break; } // 100 ms delay between encoding cycles- give other processes a go! usleep(100000); } return 0; }; PassthroughProcessor::PassthroughProcessor(Fweelin *app, InputSettings *iset, float *inputvol) : Processor(app), iset(iset), inputvol(inputvol) { // Create input settings for all inputs set alliset = new InputSettings(app,app->getABUFS()->numins); }; PassthroughProcessor::~PassthroughProcessor() { delete alliset; // printf(" :: Processor: PassthroughProcessor end\n"); }; void PassthroughProcessor::process(char pre, nframes_t len, AudioBuffers *ab) { nframes_t fragmentsize = app->getBUFSZ(); if (len > fragmentsize) len = fragmentsize; // Single output hack sample_t *out[2] = {ab->outs[0][0], ab->outs[1][0]}; if (!pre) { // *** // This part could be optimized out of RT // Copy current input settings *alliset = *iset; // And set all inputs to selected for our mix for (int i = 0; i < alliset->numins; i++) alliset->selins[i] = 1; // *** // Mix all inputs together into single output- this is a monitor mix ab->MixInputs(len,out,alliset,*inputvol,0); } else { memset(out[0],0,sizeof(sample_t) * len); if (out[1] != 0) memset(out[1],0,sizeof(sample_t) * len); } } void InputSettings::SetInputVol(int n, float vol, float logvol) { if (n >= 0 || n < numins) { if (vol >= 0.) invols[n] = vol; else if (logvol >= 0.) invols[n] = DB2LIN(AudioLevel::fader_to_dB(logvol, app->getCFG()->GetFaderMaxDB())); dinvols[n] = 1.0; } else { printf("CORE: InputSettings- input number %d not in range.\n",n); } } fweelin-0.6/src/fweelin_core_dsp.h0000755000175000017500000006135711060041254015725 0ustar mercmerc#ifndef __FWEELIN_CORE_DSP_H #define __FWEELIN_CORE_DSP_H /* Copyright 2004-2008 Jan Pekau (JP Mercury) This file is part of Freewheeling. Freewheeling is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. Freewheeling is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Freewheeling. If not, see . */ #include "fweelin_core.h" #include "fweelin_event.h" #include "fweelin_block.h" #ifndef MIN #define MIN(a,b) ((a) < (b) ? (a) : (b)) #endif #ifndef MAX #define MAX(a,b) ((a) > (b) ? (a) : (b)) #endif // Macros for converting between linear amplitude and dB #define DB2LIN(db) (powf(10.0f, (db) * 0.05f)) #define LIN2DB(amp) (20.0f * log10f(amp)) class Fweelin; class Loop; class AudioBlock; class AudioBlockIterator; class PeaksAvgsManager; class TimeMarker; class InputSettings; class AudioLevel; // Class for converting between dB and vertical fader levels class AudioLevel { public: static float fader_to_dB (float level, float maxDb); static float dB_to_fader (float dB, float maxDb); }; // Audio buffers encapsulates all buffers going into & out of // a processor-- allowing for multiple ins and outs to be passed class AudioBuffers { public: AudioBuffers(Fweelin *app); ~AudioBuffers(); // Get input #n, left/mono (0) or right (1) channel inline sample_t *GetInput(int n, short channel) { return ins[channel][n]; }; // Get output #n, left/mono (0) or right (1) channel inline sample_t *GetOutput(int n, short channel) { return outs[channel][n]; }; // Get # of inputs/ouputs inline int GetNumInputs() { return numins; }; inline int GetNumOutputs() { return numouts; }; // Is input/output #n stereo? char IsStereoInput(int n); char IsStereoOutput(int n); // Is FreeWheeling running in stereo or completely in mono? char IsStereoMaster(); // Mixes the selected inputs to dest (array of 2 channels) void MixInputs (nframes_t len, sample_t **dest, InputSettings *iset, float inputvol, char compute_stats); // Get number of internal audio inputs into FreeWheeling static inline int GetIntAudioIns() { #if USE_FLUIDSYNTH return 1; #else return 0; #endif } // Number of audio outs static inline int GetAudioOuts() { return 1; }; Fweelin *app; // Main app int numins, // Total number of ins numins_ext, // Number of external inputs numouts; // & outs sample_t **ins[2], // 2 list of input sample buffers (mono/left and right) **outs[2]; // & 2 lists of output sample buffers (mono/left and right) }; // Settings for each input coming into FreeWheeling // Now we can have multiple sets of settings & pass settings to recordprocessor. // This allows differen recordprocessors to record from different inputs. class InputSettings { public: InputSettings(Fweelin *app, int numins) : app(app), numins(numins) { selins = new char[numins]; invols = new float[numins]; dinvols = new float[numins]; insums[0] = new sample_t[numins]; insums[1] = new sample_t[numins]; insavg[0] = new sample_t[numins]; insavg[1] = new sample_t[numins]; inpeak = new sample_t[numins]; inpeaktime = new nframes_t[numins]; inscnt = new int[numins]; // Start with all inputs selected, and default volumes! for (int i = 0; i < numins; i++) { selins[i] = 1; invols[i] = 1.0; dinvols[i] = 1.0; insums[0][i] = 0.0; insums[1][i] = 0.0; insavg[0][i] = 0.0; insavg[1][i] = 0.0; inpeak[i] = 0.0; inpeaktime[i] = 0; inscnt[i] = 0; } }; ~InputSettings() { delete[] selins; delete[] invols; delete[] dinvols; delete[] insums[0]; delete[] insums[1]; delete[] insavg[0]; delete[] insavg[1]; delete[] inpeak; delete[] inpeaktime; delete[] inscnt; }; // (de)Select input void SelectInput(int n, char selected) { if (n >= 0 || n < numins) { selins[n] = selected; } else { printf("CORE: InputSettings- input number %d not in range.\n",n); } }; // Is input n selected? char InputSelected(int n) { if (n >= 0 || n < numins) { return selins[n]; } else { printf("CORE: InputSettings- input number %d not in range.\n",n); return 0; } }; // Are any of the selected inputs stereo? char IsSelectedStereo(); // Set input volume for input n void AdjustInputVol(int n, float adjust); void SetInputVol(int n, float vol, float logvol); float GetInputVol(int n) { if (n >= 0 || n < numins) { return invols[n]; } else { printf("CORE: InputSettings- input number %d not in range.\n",n); return 0; } }; float *GetInputVols() { return invols; }; // Copy contents of settings from source object- don't fuss with pointers inline void operator = (InputSettings &src) { if (numins != src.numins) printf("CORE: InputSettings- number of inputs mismatch!\n"); else { memcpy(selins,src.selins,sizeof(char)*numins); memcpy(invols,src.invols,sizeof(float)*numins); memcpy(dinvols,src.dinvols,sizeof(float)*numins); memcpy(insums[0],src.insums[0],sizeof(sample_t)*numins); memcpy(insums[1],src.insums[1],sizeof(sample_t)*numins); memcpy(insavg[0],src.insavg[0],sizeof(sample_t)*numins); memcpy(insavg[1],src.insavg[1],sizeof(sample_t)*numins); memcpy(inpeak,src.inpeak,sizeof(sample_t)*numins); memcpy(inpeaktime,src.inpeaktime,sizeof(sample_t)*numins); memcpy(inscnt,src.inscnt,sizeof(int)*numins); } }; Fweelin *app; // Main app- we get a few variables from it int numins; // Number of inputs char *selins; // For each input, is it selected? float *invols, // For each input, what's the volume? *dinvols; // And the rate of volume change sample_t *insums[2], *insavg[2], *inpeak; nframes_t *inpeaktime; int *inscnt; }; enum SyncStateType { SS_NONE, SS_START, SS_BEAT, SS_END, SS_ENDED }; // Handles realtime DSP from a signal chain // *** Consider making this an RT allocated type-- // because right now, triggering loops actually allocates memory class Processor : public EventProducer { public: const static float MIN_VOL; const static nframes_t DEFAULT_SMOOTH_LENGTH; Processor(Fweelin *app); virtual ~Processor(); // Realtime process one fragment of audio-- process len samples- // { if pre is nonzero, preprocess len bytes ahead- // used for smoothing sudden changes-- don't actually // advance pointers } virtual void process(char pre, nframes_t len, AudioBuffers *ab) = 0; Fweelin *getAPP() { return app; }; // This is called by RootProcessor when a processor is flagged- // pending delete and should no longer perform any processing virtual void Halt() {}; void dopreprocess(); protected: // Fade together current with preprocessed to create a smoothed buffer void fadepreandcurrent(AudioBuffers *ab); // Parent Flo-Monkey app Fweelin *app; // Preprocessing audio buffers- store preprocessed output for // smoothing on control changes AudioBuffers *preab; nframes_t prelen; char prewritten, // Nonzero if a // preprocess has been written to buffers prewriting; // Nonzero if a // preprocess is being written to buffers }; // One processor in a linked list of processors class ProcessorItem { public: // Processor is running, or ready to be deleted const static int STATUS_GO = 0, STATUS_PENDING_DELETE = 1; // Processor type- // Global: processor will process // after output volume transformation, and so, is not affected by it // Hipriority: these processors will process // before all other processors // Final: processor will process after all other processors-- // after TYPE_GLOBAL, after autolimit-- // it will be fed the end signal chain of all other processors *as input* const static int TYPE_DEFAULT = 0, TYPE_GLOBAL = 1, TYPE_HIPRIORITY = 2, TYPE_FINAL = 3; ProcessorItem(Processor *p, int type = TYPE_DEFAULT) : p(p), next(0), status(STATUS_GO), type(type) {}; Processor *p; ProcessorItem *next; int status, type; }; // Pulse defines a heartbeat for a piece // It keeps track of a constant period for tempo, as well as // the timing of the downbeat (current position in pulse) class Pulse : public Processor { public: // Length of metronome strike sound in samples const static nframes_t METRONOME_HIT_LEN; // Initial metronome volume const static float METRONOME_INIT_VOL; // Maximum number of sync positions const static int MAX_SYNC_POS = 100; Pulse(Fweelin *app, nframes_t len, nframes_t startpos); ~Pulse(); inline float round(float num) { if (num-(long)num < 0.5) return floor(num); else return ceil(num); } virtual void process(char pre, nframes_t l, AudioBuffers *ab); inline char IsMetronomeActive() { return metroactive; }; inline void SwitchMetronome(char active) { metroactive = active; }; // Start/stop sending MIDI clock for this pulse void SetMIDIClock (char start); // Quantizes src length to fit to this pulse length nframes_t QuantizeLength(nframes_t src); // These methods add and remove sync positions. // A pulse sends out an RT PulseSync event whenever any of these // positions is reached. inline int AddSyncPos(nframes_t pos) { // Returns sync index of new position // Check position if (pos >= len) { printf("PULSE: Sync position adjusted for really short loop " "(pos %d, len %d)\n",pos,len); pos = len-1; } // First, search for unfilled positions in our array int i = 0; while (i < numsyncpos && syncpos[i] != 0) i++; if (i < numsyncpos) { // Position found, use this index syncpos[i] = pos; return i; } else { // No holes found, add to end of array if (numsyncpos >= MAX_SYNC_POS) { printf("PULSE: Too many sync positions.\n"); return -1; } else { int ret = numsyncpos; syncpos[numsyncpos++] = pos; return ret; } } }; // Removes sync position at index syncidx inline void DelSyncPos(int syncidx) { if (syncidx < 0 || syncidx >= numsyncpos) printf("PULSE: Invalid sync position %d (0->%d).\n",syncidx,numsyncpos); else { if (syncidx+1 == numsyncpos) { // Position exists on the end of array- shrink syncpos[syncidx] = 0; numsyncpos--; } else // Position exists in the middle of the array- create a hole syncpos[syncidx] = 0; } }; // Returns nonzero if the wrapped bit is set-- which indicates // that the Meter has wrapped around to the beginning (downbeat) // in the last process frame inline char Wrapped() { if (wrapped) { wrapped = 0; return 1; } else return 0; } // Get current position in pulse in frames inline nframes_t GetPos() { return curpos; }; // Set current position of pulse in frames inline void SetPos(nframes_t pos) { curpos = pos; }; // Cause this pulse to wrap to its beginning, firing off any triggers // and producing a metronome pulse-- SetPos(0) does not do this inline void Wrap() { curpos = len; }; // Set length of pulse in frames inline void SetLength(nframes_t newlen) { len = newlen; }; // Get current position in % inline float GetPct() { return (float)curpos/len; }; // Returns length of pulse in frames inline nframes_t GetLength() { return len; }; nframes_t len, // Length of one revolution of this pulse in samples curpos; // Current position in samples into this pulse char wrapped, // Wrapped? stopped; // Stopped? int prev_sync_bb, // Previous beat/bar from transport (used for slave sync) sync_cnt, // Number of external beats/bars that have elapsed since // this pulse has wrapped around prev_sync_speed; char prev_sync_type; double prevbpm; // Previous BPM from transport // Tap nframes_t prevtap; // samplecnt @ previous tap // Metronome sample_t *metro; // Sample data for metronome strike nframes_t metroofs, // Current position into metronome sample metrolen; // Length of metronome sample char metroactive; // Nonzero if metronome sound is active float metrovol; // Volume of metronome nframes_t syncpos[MAX_SYNC_POS]; // Sync positions int numsyncpos; // Current number of sync positions SyncStateType clockrun; // Status of MIDI clock }; // This is the base of signal processing tree- it connects to system level audio // and calls child processors which do signal processing // Child processes execute in parallel and their signals are summed class RootProcessor : public Processor { public: RootProcessor(Fweelin *app, InputSettings *iset); virtual ~RootProcessor(); // Adds a child processor.. the processor begins processing immediately // Possibly realtime safe? void AddChild (Processor *o, int type = ProcessorItem::TYPE_DEFAULT); // Removes a child processor from receiving processing time.. // also, deletes the child processor // Realtime safe! void DelChild (Processor *o); void AdjustOutputVolume(float adjust); void SetOutputVolume(float set) { // Preprocess audio for smoothing dopreprocess(); outputvol = set; doutputvol = 1.0; }; inline float GetOutputVolume() { return outputvol; } void AdjustInputVolume(float adjust); void SetInputVolume(float set) { // Preprocess audio for smoothing dopreprocess(); inputvol = set; dinputvol = 1.0; }; inline float GetInputVolume() { return inputvol; } float GetLimiterVolume() { return curlimitvol; }; char GetLimiterFreeze() { return limiterfreeze; }; void SetLimiterFreeze(char set) { limiterfreeze = set; }; void ResetLimiter(); // Sample accurate timing is provided through samplecnt inline nframes_t GetSampleCnt() { return samplecnt; }; // Process len frames through all child processors of type 'ptype', // passing abchild audio buffers to the processors and optionally mixing // into the main output buffers ab void processchain(char pre, nframes_t len, AudioBuffers *ab, AudioBuffers *abchild, const int ptype, const char mixintoout); virtual void process(char pre, nframes_t len, AudioBuffers *ab); static void *run_cleanup_thread (void *ptr); pthread_t cleanup_thread; int threadgo; // Volumes- we are responsible for adjusting volumes in RT InputSettings *iset; float outputvol, doutputvol, // Delta output volume-- rate of change inputvol, dinputvol; // Delta input volume-- rate of change ProcessorItem *firstchild; // Temporary buffers for summing signals AudioBuffers *abtmp, *preabtmp; sample_t *buf[2], *prebuf[2]; // Count samples processed from start of execution nframes_t samplecnt; // Autolimiter const static float LIMITER_ATTACK_LENGTH, LIMITER_START_AMP; const static nframes_t LIMITER_ADJUST_PERIOD; float dlimitvol, // Limiter volume delta- how fast vol is being changed limitvol, // Target volume- amplitude needed to stop clipping curlimitvol, // Current volume- volume is moving towards limitvol maxvol; // Maximum volume found in audio coming into limiter char limiterfreeze; // Nonzero if limiter is frozen- no changes in amp }; class RecordProcessor : public Processor, public EventListener { public: // Extra tail on record end facilitates smooth crossfade for // sync-recorded loops const static nframes_t REC_TAIL_LEN = 1024; const static float OVERDUB_DEFAULT_FEEDBACK; // Notes: // One caveat, since hipri mgrs have granularity of only one fragment // loop points are not sample accurate but to nearest fragment // but there will be no drift since meter is sample accurate // and it is syncronizing time // .. // Should RecordProcessor create loops instead of LoopManager? // .. // Recording into preexisting fixed size block RecordProcessor(Fweelin *app, InputSettings *iset, float *inputvol, AudioBlock *dest, int suggest_stereo = -1); // Overdubbing version of record into existing loop RecordProcessor(Fweelin *app, InputSettings *iset, float *inputvol, Loop *od_loop, float od_playvol, nframes_t od_startofs, float *od_feedback); // Pointer to value for feedback (can be continuously varied) // Recording new blocks, growing size as necessary RecordProcessor(Fweelin *app, InputSettings *iset, float *inputvol, Pulse *sync = 0, AudioBlock *audiomem = 0, AudioBlockIterator *audiomemi = 0, nframes_t peaksavgs_chunksize = 0); // Destructor- executed nonRT ~RecordProcessor(); virtual void process(char pre, nframes_t len, AudioBuffers *ab); // In Halt() method we ensure that no stray Pulse_Syncs will be responded to virtual void Halt() { sync_state = SS_ENDED; }; virtual void ReceiveEvent(Event *ev, EventProducer *from); // Sync up overdubbing of the loop to a newly created pulse void SyncUp(); nframes_t GetRecordedLength(); AudioBlock *GetFirstRecordedBlock() { return recblk; } PeaksAvgsManager *GetPAMgr() { return pa_mgr; } // Is this an overdub record (1) or a fresh record (0)? char IsOverdub() { return (od_loop != 0); }; long GetNBeats() { return nbeats; }; // End this recording- if we are syncronized to an external pulse, // then we adjust recording end time as necessary void End(); // Stops recording now-- RT safe! void EndNow(); // Abort recording-- free memory associated with all audio blocks void AbortRecording(); // Fades input samples out of mix- writing to 'dest' void FadeOut_Input(nframes_t len, sample_t *input_l, sample_t *input_r, sample_t *loop_l, sample_t *loop_r, float old_fb, float new_fb, float fb_delta, sample_t *dest_l, sample_t *dest_r); // Fades input samples into mix- writing to 'dest' void FadeIn_Input(nframes_t len, sample_t *input_l, sample_t *input_r, sample_t *loop_l, sample_t *loop_r, float old_fb, float new_fb, float fb_delta, sample_t *dest_l, sample_t *dest_r); // Jumps to a position within an overdubbing loop- fade of input & output void Jump(nframes_t ofs); void SetODPlayVol(float newvol) { // Preprocess audio for smoothing dopreprocess(); od_playvol = newvol; } float GetODPlayVol() { return od_playvol; } AudioBlockIterator *GetIterator() { return i; }; Pulse *GetPulse() { return sync; }; SyncStateType sync_state; // Are we waiting for a downbeat, running, ended? // Recording in stereo? char stereo; // Which inputs to record from and at what volumes? InputSettings *iset; float *inputvol; // Pointer to overall input volume- can change during record sample_t *mbuf[2]; // Mixed input buffers // Pulse to syncronize (quantize) record to Pulse *sync; // Iterator with current record position, and temporary iterator AudioBlockIterator *i, *tmpi; // Block to record into AudioBlock *recblk; // (Syncrec) Number of beat triggers passed in this recording long nbeats; int endsyncidx; // Pulse sync index for delayed end-of-record char endsyncwait; // Are we waiting for a delayed end-of-record? char stopped, growchain, // Nonzero if we should grow the chain of blocks-- // Zero if record is fixed length compute_stats; // Nonzero if we should compute stats like DC offset, // sums & peaks for InputSettings // Manager for peaks & averages computation alongside this record PeaksAvgsManager *pa_mgr; // Overdub settings Loop *od_loop; float od_playvol, *od_feedback, od_feedback_lastval; // Last value for feedback- used to determine delta, to remove // zipper noise long od_curbeat; // Current beat in od_loop char od_fadein, od_fadeout, od_stop, // Fade in overdub, fade out overdub, // and stop overdub flags od_prefadeout; // Overdub, preprocess fadeout nframes_t od_lastofs; // Last position of record sample_t *od_last_mbuf[2], // Copy of last mixed input buffers *od_last_lpbuf[2]; // Copy of last loop buffers }; class PlayProcessor : public Processor, public EventListener { public: PlayProcessor(Fweelin *app, Loop *playloop, float playvol, nframes_t startofs = 0); virtual ~PlayProcessor(); // Sync up playing of the loop to a newly created pulse void SyncUp(); virtual void process(char pre, nframes_t len, AudioBuffers *ab); nframes_t GetPlayedLength(); void SetPlayVol(float newvol) { // Preprocess audio for smoothing dopreprocess(); playvol = newvol; } float GetPlayVol() { return playvol; } // In Halt() method we ensure that no stray Pulse_Syncs will be responded to virtual void Halt() { sync_state = SS_ENDED; }; virtual void ReceiveEvent(Event *ev, EventProducer *from); SyncStateType sync_state; // Are we waiting for a downbeat, running, ended? // Pulse to syncronize (quantize) play to Pulse *sync; // Playing in stereo? char stereo; // Stop- pause for right place to start char stopped; AudioBlockIterator *i; Loop *playloop; float playvol; long curbeat; }; class FileStreamer : public Processor, public EventListener { public: const static nframes_t OUTPUTBUFLEN = 100000; const static int MARKERBUFLEN = 50; FileStreamer(Fweelin *app, nframes_t outbuflen = OUTPUTBUFLEN); virtual ~FileStreamer(); virtual void process(char pre, nframes_t len, AudioBuffers *ab); virtual void ReceiveEvent(Event *ev, EventProducer *from); // Starts writing to a new audio stream // Note all the heavy work is done in the encode thread! int StartWriting(char *filename, char *timingname, codec type) { if (outname != 0) return -1; // Already writing! outname = filename; outputsize = 0; filetype = type; this->timingname = timingname; writerstatus = STATUS_START_PENDING; return 0; }; // Stop writing to a stream // Note all the heavy work is done in the encode thread! void StopWriting() { writerstatus = STATUS_STOP_PENDING; }; char GetStatus() { return writerstatus; }; // Returns the number of *frames* written so far-- not bytes // The actual file size will vary depending on the codec used long int GetOutputSize() { return outputsize; }; static void *run_encode_thread (void *ptr); const static char STATUS_STOPPED = 0, STATUS_RUNNING = 1, STATUS_STOP_PENDING = 2, STATUS_START_PENDING = 3; private: void InitStreamer(); void EndStreamer(); char writerstatus; // Encoding in stereo? char stereo; codec filetype; // File FILE *outfd, // Current output filedescriptor (audio) *timingfd; // Current timing output filedescriptor (data- USX) char *outname, // Current output filename *timingname; // Current timing output filename // Time markers for storing downbeat points along with audio TimeMarker *marks; int mkwriteidx, mkreadidx; // Number of beat triggers passed in this recording long nbeats; // Global sample count at start of stream file nframes_t startcnt; // Output buffers sample_t *outbuf[2]; nframes_t outbuflen, outpos, // Current position of realtime data coming into output buffer encodepos; // Current position of encoder in buffer (lags behind outpos) char wrap; // Nonzero if outpos has wrapped but encodepos hasn't yet // Number of bytes written to output file long int outputsize; // Disk encode/disk write thread pthread_t encode_thread; int threadgo; // Encoder iFileEncoder *enc; }; // PassthroughProcessor creates a monitor mix of all inputs into the given output class PassthroughProcessor : public Processor { public: PassthroughProcessor(Fweelin *app, InputSettings *iset, float *inputvol); virtual ~PassthroughProcessor(); virtual void process(char pre, nframes_t len, AudioBuffers *ab); // Input settings with all inputs selected- to create monitor mix InputSettings *alliset, *iset; // Pointer to outside input settings from which levels will be taken float *inputvol; // Pointer to overall input volume- can change }; #endif fweelin-0.6/src/fweelin_core.h0000755000175000017500000007411411060035503015052 0ustar mercmerc#ifndef __FWEELIN_CORE_H #define __FWEELIN_CORE_H /* ******** Art is what's going on right under our noses. An artist is one who listens to it. ******** */ /* Copyright 2004-2008 Jan Pekau (JP Mercury) This file is part of Freewheeling. Freewheeling is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. Freewheeling is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Freewheeling. If not, see . */ #ifdef __MACOSX__ #include #else #include #endif #include "fweelin_midiio.h" #include "fweelin_videoio.h" #include "fweelin_sdlio.h" #include "fweelin_audioio.h" #include "fweelin_core_dsp.h" #include "fweelin_block.h" #include "fweelin_event.h" #include "fweelin_config.h" #include "fweelin_browser.h" class SDLIO; class EventManager; class BlockManager; class RootProcessor; class RecordProcessor; class TriggerMap; class AudioBlock; class AudioBlockIterator; class Loop; class Pulse; class BED_MarkerPoints; class FileStreamer; class PreallocatedType; class AudioBuffers; class InputSettings; class Browser; #if USE_FLUIDSYNTH class FluidSynthProcessor; #endif // ****************** CORE CLASSES // Status types for loops enum LoopStatus { T_LS_Off = 0, T_LS_Recording = 1, T_LS_Overdubbing = 2, T_LS_Playing = 3 }; // Base class for all saveable types of objects #define SAVEABLE_HASH_LENGTH 16 //MD5_DIGEST_LENGTH #define GET_SAVEABLE_HASH_TEXT(s) \ char hashtext[SAVEABLE_HASH_LENGTH*2+1]; \ { \ char *ptr = hashtext; \ for (int i = 0; i < SAVEABLE_HASH_LENGTH; i++, ptr += 2) \ sprintf(ptr,"%02X",s[i]); \ *ptr = '\0'; \ } enum SaveStatus { NO_SAVE, SAVE_DONE }; class Saveable { public: Saveable() : savestatus(NO_SAVE) {}; virtual void Save(Fweelin *app) {}; // Save the object inline unsigned char *GetSaveHash() { return savehash; }; inline int CompareHash(unsigned char *hash2) { return memcmp(savehash,hash2,sizeof(unsigned char) * SAVEABLE_HASH_LENGTH); }; inline SaveStatus GetSaveStatus() { return savestatus; }; inline void SetSaveStatus(SaveStatus s) { savestatus = s; }; inline int SetSaveableHashFromText(char *stext) { int slen = strlen(stext); if (slen != SAVEABLE_HASH_LENGTH*2) { printf("DISK: Invalid MD5 hash '%s'\n",stext); return 1; } else { char htmp[3]; htmp[2] = '\0'; for (int i = 0, j = 0; i < slen; i += 2, j++) { htmp[0] = stext[i]; htmp[1] = stext[i+1]; int sh_tmp; sscanf(htmp,"%X",&sh_tmp); savehash[j] = (unsigned char) sh_tmp; } SetSaveStatus(SAVE_DONE); return 0; } }; // Splits a saveable filename in the format 'basename-hash-objectname' // into its base name, hash and object name components // // Returns zero on success static char SplitFilename(char *filename, int baselen, char *basename, char *hash, char *objname, int maxlen); // Rename the file with name *filename_ptr to a new name // use the format 'basename-hash-objectname' // Here, we specify a new objectname 'newname', but the basename and hash // are retained in the filename // Exts is a list of filename extensions to try for renaming // num_exts is the size of the list // // This is for renaming an item on disk static void RenameSaveable(char **filename_ptr, int baselen, char *newname, const char **exts, int num_exts); // Renames -this- saveable object on disk to correspond with the new name // given. Any files having an MD5 corresponding to this saveable are // renamed. // // This is for renaming an item in memory, so that the disk corresponds // with the new name // // *Old_filename and *new_filename are set to point to the old and new // filename-- you must delete[] the memory that is allocated for these void RenameSaveable(char *librarypath, char *basename, char *old_objname, char *nw_objname, const char **exts, int num_exts, char **old_filename, char **new_filename); // Gets the first two characters of the hash in the given filename, // given the base length-- store in *c1 and *c2-- only if the // filename contains a valid hash inline static void GetHashFirst(char *filename, int baselen, char *c1, char *c2) { char *c = filename + baselen + 1; if (c < filename+strlen(filename)) { *c1 = *c++; *c2 = *c; #if 0 char *slashptr = strchr(c,'-'); if (slashptr == 0) // If name is not in filename slashptr = strrchr(filename,'.'); // Use extension to get hash printf("c1 - %d vs %d\n",slashptr-c,SAVEABLE_HASH_LENGTH*2); if (slashptr != 0 && slashptr-c == SAVEABLE_HASH_LENGTH*2) { printf("set\n"); *c1 = *c++; *c2 = *c; } #endif } } protected: // When we save an object, we first compute the MD5 hash for that object // and put that in the filename for the object. Other objects can refer to // the object by hash. SaveStatus savestatus; unsigned char savehash[SAVEABLE_HASH_LENGTH+1]; }; // Loop // -Wraps around a list of audio blocks // -Stores basic parameters for a loop, such as volumes class Loop : public Saveable { friend class LoopManager; public: const static float MIN_VOL; Loop (AudioBlock *blocks, Pulse *pulse, float quant, float vol, long nbeats, codec format) : name(0), format(format), blocks(blocks), pulse(pulse), quant(quant), vol(vol), dvol(1.0), nbeats(nbeats), selcnt(0) {}; virtual ~Loop () { if (name != 0) delete[] name; }; // Save loop virtual void Save(Fweelin *app); // RT update volume inline void UpdateVolume() { if (dvol != 1.0) { // Apply delta if (dvol > 1.0 && vol < MIN_VOL) vol = MIN_VOL; vol *= dvol; } }; inline void ChangeSelectedCount (int delta) { selcnt += delta; if (selcnt < 0) selcnt = 0; }; // Perhaps store the length of the loop... // Because right now GetTotalLength is a calculation // in AudioBlock char *name; // Name of loop, or null codec format; // File format on disk AudioBlock *blocks; // Chain of blocks that form this loop Pulse *pulse; // Time pulse to which this loop is quantized float quant; // Quantization factor float vol, // Volume multiplier dvol; // Rate of volume change long nbeats; // Number of beats in this loop int selcnt; // Number of times this loop is currently selected // (see toggle-select-loop). A loop can be selected // in several sets }; // Snapshot of information for a loop class LoopSnapshot { public: LoopSnapshot (int l_idx = -1, LoopStatus status = T_LS_Off, float l_vol = 0.0, float t_vol = 0.0) : l_idx(l_idx), status(status), l_vol(l_vol), t_vol(t_vol) {}; int l_idx; // Loop index LoopStatus status; // Is it playing? float l_vol, // Loop volume (persistent) t_vol; // Trigger volume (not persistent) }; // A snapshot remembers all settings related to which loops are playing & // at what levels class Snapshot { public: Snapshot() : name(0), exists(0), ls(0) {}; ~Snapshot () { DeleteSnapshot(); }; void DeleteSnapshot (char erasename = 1) { if (erasename && name != 0) { delete[] name; name = 0; } if (ls != 0) { delete[] ls; ls = 0; } exists = 0; }; // Create a snapshot from loops right now void CreateSnapshot (char *name, LoopManager *lm, TriggerMap *tmap); char *name; // Name of snapshot char exists; // This snapshot exists (nonzero), or empty slot (zero)? // Array of info for each loop within the snapshot LoopSnapshot *ls; int numls; }; // A set of loops class LoopList { public: LoopList (int l_idx = -1) : l_idx(l_idx), next(0) {}; // Scans through the list beginning with 'first' for the loop 'l_idx'- // returns the LoopList containing 'item', and sets 'prev' to the previous // LoopList. If not found, returns 0. static LoopList *Scan (LoopList *first, int l_idx, LoopList **prev) { LoopList *cur = first, *tprev = 0; while (cur != 0 && cur->l_idx != l_idx) { tprev = cur; cur = cur->next; } *prev = tprev; return cur; }; // Add to the beginning of a list of loops- return the new first pointer static LoopList *AddBegin (LoopList *first, int l_idx) { if (first == 0) return new LoopList(l_idx); else { LoopList *nwl = new LoopList(l_idx); nwl->next = first; return nwl; } }; // Remove the given looplist 'll' from the list of loops- // you must also pass the element previous to ll // We return the new first pointer static LoopList *Remove (LoopList *first, LoopList *ll, LoopList *prev) { if (ll != 0) { if (ll == first) { LoopList *nwfirst = ll->next; delete ll; return nwfirst; } else { if (prev != 0) prev->next = ll->next; delete ll; return first; } } return first; }; // Remove the given loop from the list of loops- return the new first pointer static LoopList *Remove (LoopList *first, int l_idx) { LoopList *prev, *ll = Scan(first,l_idx,&prev); return Remove(first,ll,prev); }; // Erase a list of loops, given the first static void Delete (LoopList *first) { LoopList *cur = first; while (cur != 0) { LoopList *tmp = cur->next; delete cur; cur = tmp; } }; int l_idx; LoopList *next; }; // This class manages sets of loops, allowing them to be triggered.. // like a keymap class TriggerMap : public Saveable, public EventProducer { public: TriggerMap (Fweelin *app, int mapsize) : app(app), mapsize(mapsize), lastupdate(0) { // Map is an array of pointers to different loops map = new Loop *[mapsize]; memset(map,0,mapsize * sizeof(Loop *)); }; virtual ~TriggerMap () { delete[] map; } // Save a whole scene, with an optional filename- // if none is given, saves a new scene virtual void Save(Fweelin *app, char *filename = 0); // Go save- when all loops are saved, this part saves the XML data // for the scene void GoSave(char *filename); inline void SetMap (int index, Loop *smp); inline Loop *GetMap (int index) { if (index < 0 || index >= mapsize) { printf("GetMap: Invalid loop index!\n"); return 0; } else return map[index]; } inline int SearchMap (Loop *l) { for (int i = 0; i < mapsize; i++) if (map[i] == l) return i; return -1; }; // Return the first free loopid within the range of indexes 'lo -> hi' // or -1 if no free IDs found inline int GetFirstFree (int lo, int hi) { int i_start = lo, i_end = hi; if (i_start < 0) i_start = 0; if (i_start >= mapsize) i_start = mapsize-1; if (i_end < 0) i_end = 0; if (i_end >= mapsize) i_start = mapsize-1; for (int i = i_start; i <= i_end; i++) if (map[i] == 0) return i; return -1; }; // Returns the loop ID for the first loop whose 'savehash' matches the given // hash, or -1 if none found inline int ScanForHash (unsigned char *hash) { for (int i = 0; i < mapsize; i++) if (map[i] != 0 && map[i]->GetSaveStatus() == SAVE_DONE && !map[i]->CompareHash(hash)) return i; return -1; }; inline int GetMapSize() { return mapsize; } inline double GetLastUpdate() { return lastupdate; } inline void TouchMap() { lastupdate = mygettime(); SetSaveStatus(NO_SAVE); }; // Return the number of loops in the map inline int CountLoops() { int cnt = 0; for (int i = 0; i < mapsize; i++) if (map[i] != 0) cnt++; return cnt; }; private: Fweelin *app; int mapsize; Loop **map; // Time of last update of the map- used for rebuilding tables & such double lastupdate; }; // LoopTrayItem is for loaded loops class LoopTrayItem : public BrowserItem { public: LoopTrayItem(Loop *l, int loopid, char *name, char default_name, char *placename) : BrowserItem(name,default_name), l(l), loopid(loopid), xpos(-1), ypos(-1), placename(placename) {}; virtual int Compare(BrowserItem *second) { if (second->GetType() == B_Loop_Tray) return ((LoopTrayItem *) second)->loopid-loopid; else return 0; }; virtual int MatchItem(int itemmatch) { if (loopid == itemmatch) return 0; else return 1; }; virtual BrowserItemType GetType() { return B_Loop_Tray; }; Loop *l; // Loop that this item refers to int loopid, // Loop ID for it xpos, // Position in tray window ypos; char *placename; // Place name for where the loop is mapped }; // LoopBrowserItem is for loops in the library on disk class LoopBrowserItem : public BrowserItem { public: LoopBrowserItem(time_t time, char *name, char default_name, char *fn) : BrowserItem(name,default_name), time(time) { if (fn == 0) filename = 0; else { // Copy filename filename = new char[strlen(fn)+1]; strcpy(filename,fn); // Remove extension char *ext_ptr = strrchr(filename,'.'); if (ext_ptr != 0) *ext_ptr = '\0'; } }; virtual ~LoopBrowserItem() { if (filename != 0) delete[] filename; }; virtual int Compare(BrowserItem *second) { if (second->GetType() == B_Loop) return ((LoopBrowserItem *) second)->time-(signed int) time; else return 0; }; virtual BrowserItemType GetType() { return B_Loop; }; time_t time; char *filename; }; class SceneBrowserItem : public BrowserItem { public: SceneBrowserItem(time_t time, char *name, char default_name, char *fn) : BrowserItem(name, default_name), time(time) { if (fn == 0) filename = 0; else { // Copy filename filename = new char[strlen(fn)+1]; strcpy(filename,fn); // Remove extension char *ext_ptr = strrchr(filename,'.'); if (ext_ptr != 0) *ext_ptr = '\0'; } }; virtual ~SceneBrowserItem() { if (filename != 0) delete[] filename; }; virtual int Compare(BrowserItem *second) { if (second->GetType() == B_Scene) return ((SceneBrowserItem *) second)->time - (signed int) time; else return 0; }; virtual BrowserItemType GetType() { return B_Scene; }; time_t time; char *filename; }; // LoopManager contains all loops, and wraps up recording, playing, and // other RT & non-RT processing on loops class LoopManager : public EventListener, public AutoWriteControl, public AutoReadControl, public BrowserCallback, public RenameCallback { friend class Loop; public: // Version tracking for saving of loop data const static int LOOP_SAVE_FORMAT_VERSION = 1; LoopManager (Fweelin *app); virtual ~LoopManager(); virtual void ReceiveEvent(Event *ev, EventProducer *from); virtual void ItemBrowsed(BrowserItem *i); virtual void ItemSelected(BrowserItem *i); virtual void ItemRenamed(BrowserItem *i); // Populate the loop/scene browser with any loops/scenes on disk void SetupLoopBrowser(); void SetupSceneBrowser(); // Get length returns the length of any loop on the specified index nframes_t GetLength(int index); // Get length returns the length of any loop on the specified index // Rounded to its currently quantized length // Or 0 if the loop has no pulse nframes_t GetRoundedLength(int index); // Returns from 0.0-1.0 how far through a block chain with specified index // we are float GetPos(int index); // Get current # of samples into block chain with given index nframes_t GetCurCnt(int index); // Returns nonzero if there is a processor at the specified mapindex int IsActive(int index) { return (plist[index] != 0); } // Sets trigger volume on specified index // If index is not playing, activates the index void SetTriggerVol(int index, float vol); // Gets triggered volume on specified index // If index is not playing, returns 0 float GetTriggerVol(int index); // Returns the status at the specified index inline LoopStatus GetStatus(int index) { return status[index]; }; inline Processor *GetProcessor(int index) { return plist[index]; }; // Returns a loop with the specified index, if one exists Loop *GetSlot(int index); void AdjustNewLoopVolume(float adjust) { newloopvol += adjust; if (newloopvol < 0.0) newloopvol = 0.0; } float GetNewLoopVolume() { return newloopvol; } void AdjustOutputVolume(float adjust); void SetOutputVolume(float set, float logset); float GetOutputVolume(); void AdjustInputVolume(float adjust); void SetInputVolume(float set, float logset); float GetInputVolume(); void SetLoopVolume(int index, float val); float GetLoopVolume(int index); void AdjustLoopVolume(int index, float adjust); void SetLoopdVolume(int index, float val); float GetLoopdVolume(int index); void SelectPulse(int pulseindex); // Create a time pulse around the specified index // The length of the loop on the specified index becomes // a time constant around which other loops center themselves // subdivide the length of the loop by subdivide to get the core pulse void CreatePulse(int index, int pulseindex, int sub); // Creates a pulse of the given length in the first available slot, // if none already exists of the right length Pulse *CreatePulse(nframes_t len); // Taps a pulse- starting at the downbeat- if newlen is nonzero, the pulse's // length is adjusted to reflect the length between taps- and a new pulse // is created if none exists void TapPulse(int pulseindex, char newlen); void SwitchMetronome(int pulseindex, char active); inline Pulse *GetCurPulse() { if (curpulseindex >= 0) return pulses[curpulseindex]; else return 0; }; inline int GetCurPulseIndex() { return curpulseindex; }; inline Pulse *GetPulseByIndex(int pulseindex) { return pulses[pulseindex]; }; // Deletes the specified pulse, stopping striping void DeletePulse(int pulseindex); // Gets the pulse to which the loop on index is attached Pulse *GetPulse(int index); inline void SetSubdivide(int sub) { //printf("Set subdivide: %d\n", sub); subdivide = sub; } inline int GetSubdivide() { return subdivide; }; // Move the loop at specified index to another index // only works if target index is empty // returns 1 if success int MoveLoop (int src, int tgt); // Prompts the user for a new name for the given loop // We can only rename one loop at a time void RenameLoop(int loopid); virtual void ItemRenamed(char *nw); ItemRenamer *renamer; // Renamer instance, or null if we are not renaming Loop *rename_loop; // Loop being renamed inline ItemRenamer *GetRenamer() { return renamer; }; inline Loop *GetRenameLoop() { return rename_loop; }; // Delete the loop at the specified index.. void DeleteLoop (int index); // Add the given loop index to all snapshots (off) void UpdateLoopLists_ItemAdded (int l_idx); // Remove the given loop index from all loop lists void UpdateLoopLists_ItemRemoved (int l_idx); // Update all loop lists to reflect that a loop has moved in the TriggerMap void UpdateLoopLists_ItemMoved (int l_idx_old, int l_idx_new); // Trigger the loop at index within the map // The exact behavior varies depending on what is already happening with // this loop and the settings passed- see ~/.fweelin/.fweelin.rc void Activate (int index, char shot = 0, float vol = 1.0, nframes_t ofs = 0, char overdub = 0, float *od_feedback = 0); void Deactivate (int index); // Saves the loop with given index void SaveLoop (int index); // Load loop from disk into the given index void LoadLoop(char *filename, int index, float vol = 1.0); // Saves a new scene of all loops void SaveNewScene(); // Saves over the current scene void SaveCurScene(); // Load scene from disk void LoadScene(SceneBrowserItem *i); // We receive calls periodically for saving of loops- // here, we return blocks to save from loops which need saving virtual void GetWriteBlock(FILE **out, AudioBlock **b, AudioBlockIterator **i, nframes_t *len); // We receive calls periodically for loading of loops- virtual void GetReadBlock(FILE **in, char *smooth_end); virtual void ReadComplete(AudioBlock *b); // Check if the needs_saving map is up to date, rebuild if needed. void CheckSaveMap(); // Adds the loop/scene with given filename to the browser br void AddLoopToBrowser(Browser *br, char *filename); SceneBrowserItem *AddSceneToBrowser(Browser *br, char *filename); inline void SetAutoLoopSaving(char save) { autosave = save; }; void AddToSaveQueue(Event *ev); inline int GetNumSave() { return numsave; }; inline int GetCurSave() { return cursave; }; inline int GetNumLoad() { return numload; }; inline int GetCurLoad() { return curload; }; Event *savequeue, // Loop/scene save queue *loadqueue; // Loop/scene load queue int cursave, curload, // # of loops/scenes saved/loaded numsave, numload; // Total # of loops/scenes to save/load int loadloopid; // Index where to load new loops from disk double needs_saving_stamp; // Timestamp from trigger map from which // needs_saving was built Range default_looprange; // Default placement for loops int *lastrecidx; // List of last indexes recorded to int numloops, // Total number of loops in map numrecordingloops; // Number of loops currently recording in map inline void LockLoops() { pthread_mutex_lock (&loops_lock); }; inline void UnlockLoops() { pthread_mutex_unlock (&loops_lock); }; protected: // Rename a loop in memory (threadsafe) inline void RenameLoop(Loop *l, char *nw) { LockLoops(); if (l->name != 0) // Erase loop stored name delete[] l->name; if (nw != 0) { l->name = new char[strlen(nw)+1]; strcpy(l->name,nw); } else l->name = 0; UnlockLoops(); }; // Adds the given loop to the list of loops to save void AddLoopToSaveQueue(Loop *l); // Adds the given loop to the list of loops to load void AddLoopToLoadQueue(char *filename, int index, float vol); // Saves loop XML data & prepares to save loop audio void SetupSaveLoop(Loop *l, int l_idx, FILE **out, AudioBlock **b, AudioBlockIterator **i, nframes_t *len); // Loads loop XML data & prepares to load loop audio- // returns nonzero on error int SetupLoadLoop(FILE **in, char *smooth_end, Loop **new_loop, int l_idx, float l_vol, char *l_filename); // Setup time marker striping on audio memory when a new // pulse is selected void StripePulseOn(Pulse *pulse); // Deactivate time marker striping on audio memory for the // given pulse void StripePulseOff(Pulse *pulse); // Turn on/off auto loop saving char autosave; // Autosave loops? // Core Fweelin app on which this player is working on Fweelin *app; // We also need to keep track of record/playprocessors attached to each // index Processor **plist; // Pointer to a processor for each index // *** Replace this with well designed event queue system int *waitactivate; // For each index, are we waiting to activate? float *waitactivate_vol; char *waitactivate_od, *waitactivate_shot; float **waitactivate_od_fb; LoopStatus *status; // For each index, what's the status? // Block managers that load/save loops BlockReadManager *bread; BlockWriteManager *bwrite; // Initial volume of new loops float newloopvol; // Subdivision for creating new pulses int subdivide; // Index of last deactivated trigger index.. used when creating new pulses int lastindex; // Current pulse (index) for new loops.. will be quantized to this pulse int curpulseindex; // List of possible pulses Pulse *pulses[MAX_PULSES]; pthread_mutex_t loops_lock; // A way to lock up loops so two threads // don't race on one loop }; // This is Fweelin class Fweelin : public EventProducer, public BrowserCallback { public: Fweelin() : #if USE_FLUIDSYNTH fluidp(0), #endif mmg(0), bmg(0), emg(0), rp(0), tmap(0), loopmgr(0), browsers(0), abufs(0), iset(0), audio(0), midi(0), sdlio(0), vid(0), scope(0), scope_len(0), audiomem(0), amrec(0), sync_type(0), sync_speed(1), running(0) {}; ~Fweelin() {}; char IsRunning() { return running; }; // Setup int setup(); // Start int go(); void ToggleDiskOutput(); void FlushStreamOutName() { strcpy(streamoutname,""); }; inline nframes_t getBUFSZ() { return fragmentsize; }; inline sample_t *getSCOPE() { return scope; }; inline nframes_t getSCOPELEN() { return scope_len; }; #if USE_FLUIDSYNTH inline FluidSynthProcessor *getFLUIDP() { return fluidp; }; FluidSynthProcessor *fluidp; #endif inline AudioBlock *getAUDIOMEM() { return audiomem; }; AudioBlockIterator *getAUDIOMEMI(); inline RecordProcessor *getAMREC() { return amrec; }; AudioBlock *getAMPEAKS(); AudioBlock *getAMAVGS(); AudioBlockIterator *getAMPEAKSI(); AudioBlockIterator *getAMAVGSI(); BED_MarkerPoints *getAMPEAKSPULSE(); inline MemoryManager *getMMG() { return mmg; }; inline BlockManager *getBMG() { return bmg; }; inline EventManager *getEMG() { return emg; }; inline RootProcessor *getRP() { return rp; }; inline FileStreamer *getSTREAMER() { return fs; }; inline TriggerMap *getTMAP() { return tmap; }; inline LoopManager *getLOOPMGR() { return loopmgr; }; inline AudioIO *getAUDIO() { return audio; }; inline MidiIO *getMIDI() { return midi; }; inline VideoIO *getVIDEO() { return vid; }; inline SDLIO *getSDLIO() { return sdlio; }; inline FloConfig *getCFG() { return cfg; }; inline char *getSTREAMOUTNAME() { return streamoutname; }; inline SceneBrowserItem *getCURSCENE() { return curscene; }; inline void setCURSCENE(SceneBrowserItem *nw) { curscene = nw; }; inline PreallocatedType *getPRE_EXTRACHANNEL() { return pre_extrachannel; }; inline PreallocatedType *getPRE_AUDIOBLOCK() { return pre_audioblock; }; inline PreallocatedType *getPRE_TIMEMARKER() { return pre_timemarker; }; inline AudioBuffers *getABUFS() { return abufs; }; inline InputSettings *getISET() { return iset; }; inline Browser *getBROWSER(BrowserItemType b) { if (b >= 0 && b < B_Last) return browsers[b]; else return 0; } // Selections inline LoopList **getLOOPSEL(int idx) { if (idx >= 0 && idx < NUM_LOOP_SELECTION_SETS) return &loopsel[idx]; else return 0; }; // Snapshots Snapshot *getSNAP(int idx); inline Snapshot *getSNAPS() { return snaps; }; // Create snapshot from current state of all loops Snapshot *CreateSnapshot (int idx) { Snapshot *s = getSNAP(idx); if (s != 0) { tmap->TouchMap(); s->CreateSnapshot(0,loopmgr,tmap); } return s; }; // Load snapshot from disk- just create space & name Snapshot *LoadSnapshot (int idx, char *name) { Snapshot *s = getSNAP(idx); if (s != 0) { tmap->TouchMap(); s->CreateSnapshot(name,0,0); s->numls = 0; } return s; }; // Trigger snapshot #idx - return nonzero on failure char TriggerSnapshot (int idx); // Create a snapshot from loops right now void CreateSnapshot (char *name, LoopManager *lm, TriggerMap *tmap); // Sync parameters inline int GetSyncSpeed() { return sync_speed; }; inline char GetSyncType() { return sync_type; }; inline void SetSyncSpeed(int sspd) { if (sspd < 1) sync_speed = 1; else sync_speed = sspd; }; inline void SetSyncType(char stype) { sync_type = stype; }; // Patch browser callbacks virtual void ItemBrowsed(BrowserItem *i) { ItemSelected(i); }; virtual void ItemSelected(BrowserItem *i); // Patches can not yet be renamed virtual void ItemRenamed(BrowserItem *i) { return; }; private: MemoryManager *mmg; BlockManager *bmg; EventManager *emg; RootProcessor *rp; TriggerMap *tmap; LoopManager *loopmgr; Browser **browsers; Browser *GetBrowserFromConfig(BrowserItemType b); // ****************** PREALLOCATED TYPE MANAGERS PreallocatedType *pre_audioblock, *pre_extrachannel, *pre_timemarker; // ****************** DISK STREAMER FileStreamer *fs; int writenum; // Number of audio output file currently being written char streamoutname[FWEELIN_OUTNAME_LEN], // Name of output file timingname[FWEELIN_OUTNAME_LEN]; // Name of timing stripe file // ****************** LOOP SELECTIONS LoopList *loopsel[NUM_LOOP_SELECTION_SETS]; // ****************** ARRAY OF SNAPSHOTS Snapshot *snaps; // ****************** SCENE INFO SceneBrowserItem *curscene; // ****************** SYSTEM LEVEL AUDIO // Audio buffers AudioBuffers *abufs; // Input settings InputSettings *iset; // Audio interface AudioIO *audio; // ****************** MIDI MidiIO *midi; // ****************** SDL INPUT (KEYBOARD / MOUSE / JOYSTICK) SDLIO *sdlio; // ****************** VIDEO VideoIO *vid; // Audio buffer size nframes_t fragmentsize; // Buffers for visual sample scope sample_t *scope; nframes_t scope_len; // Audio memory & the processor which records to it AudioBlock *audiomem; RecordProcessor *amrec; // Control settings FloConfig *cfg; // Variables for sync char sync_type; // Nonzero for beat-sync and zero for bar-sync int sync_speed; // Number of beats or bars (external) per pulse (FW) char running; // Nonzero if FW is fully started }; #endif fweelin-0.6/src/fweelin_datatypes.cc0000755000175000017500000000304511065527501016262 0ustar mercmerc/* To change the world, I aspire to perceive it differently. */ /* Copyright 2004-2008 Jan Pekau (JP Mercury) This file is part of Freewheeling. Freewheeling is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. Freewheeling is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Freewheeling. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include "fweelin_datatypes.h" int SRMWRingBuffer_Writers::num_writers = 0; pthread_t SRMWRingBuffer_Writers::ids[MAX_WRITER_THREADS]; pthread_mutex_t SRMWRingBuffer_Writers::register_lock; CoreDataType GetCoreDataType(char *name) { if (!strcmp(name, "char")) return T_char; else if (!strcmp(name, "int")) return T_int; else if (!strcmp(name, "long")) return T_long; else if (!strcmp(name, "float")) return T_float; else if (!strcmp(name, "range")) return T_range; else return T_invalid; }; fweelin-0.6/src/fweelin_datatypes.h0000755000175000017500000004325011065527466016140 0ustar mercmerc#ifndef __FWEELIN_DATATYPES_H #define __FWEELIN_DATATYPES_H #include /* Copyright 2004-2008 Jan Pekau (JP Mercury) This file is part of Freewheeling. Freewheeling is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. Freewheeling is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Freewheeling. If not, see . */ enum CoreDataType { T_char, T_int, T_long, T_float, T_range, T_variable, T_variableref, T_invalid }; CoreDataType GetCoreDataType(char *name); class Range { public: Range(int lo, int hi) : lo(lo), hi(hi) {}; int lo, hi; }; // Flexible data type configuration variable- // Used in parsing and evaluating expressions from config file #define CFG_VAR_SIZE 16 // Number of data bytes in one variable class UserVariable { public: UserVariable() : name(0), value(data), next(0) {}; ~UserVariable() { if (name != 0) delete[] name; }; // Ensures that the precision of this variable is at least that of src // If not, reconfigures this variable to match src.. // For ex, if this is T_char and src is T_float, this becomes T_float void RaisePrecision (UserVariable &src) { switch (src.type) { case T_char : break; case T_int : if (type == T_char) { int tmp = (int) *this; type = T_int; *this = tmp; } break; case T_long : if (type == T_char || type == T_int) { long tmp = (long) *this; type = T_long; *this = tmp; } break; case T_float : if (type == T_char || type == T_int || type == T_long) { float tmp = (float) *this; type = T_float; *this = tmp; } break; default : break; } }; char operator > (UserVariable &cmp) { RaisePrecision(cmp); // Comparing ranges yields undefined results if (type == T_range || cmp.type == T_range) return 0; switch (type) { case T_char : return (*((char *) value) > (char) cmp); case T_int : return (*((int *) value) > (int) cmp); case T_long : return (*((long *) value) > (long) cmp); case T_float : return (*((float *) value) > (float) cmp); case T_variable : case T_variableref : printf(" UserVariable: WARNING: Compare T_variable or T_variableref " " not implemented!\n"); return 0; case T_range : printf(" UserVariable: WARNING: Can't compare range variable!\n"); return 0; case T_invalid : printf(" UserVariable: WARNING: Can't compare invalid variable!\n"); return 0; } return 0; }; char operator == (UserVariable &cmp) { RaisePrecision(cmp); // Special case if one variable is range and one is scalar-- then // we check if the scalar is within the range if (type == T_range && cmp.type != T_range) { int v = (int) cmp; Range r(*((int *) value),*(((int *) value)+1)); return (v >= r.lo && v <= r.hi); } if (cmp.type == T_range && type != T_range) { int v = (int) *this; Range r(*((int *) cmp.value),*(((int *) cmp.value)+1)); return (v >= r.lo && v <= r.hi); } switch (type) { case T_char : return (*((char *) value) == (char) cmp); case T_int : return (*((int *) value) == (int) cmp); case T_long : return (*((long *) value) == (long) cmp); case T_float : return (*((float *) value) == (float) cmp); case T_range : { Range r = (Range) cmp; return (*((int *) value) == r.lo && *(((int *) value)+1) == r.hi); } case T_variable : case T_variableref : printf(" UserVariable: WARNING: Compare T_variable or T_variableref " " not implemented!\n"); return 0; case T_invalid : printf(" UserVariable: WARNING: Can't compare invalid variable!\n"); return 0; } return 0; }; char operator != (UserVariable &cmp) { return !(operator == (cmp)); }; void operator += (UserVariable &src) { RaisePrecision(src); switch (type) { case T_char : *((char *) value) += (char) src; break; case T_int : *((int *) value) += (int) src; break; case T_long : *((long *) value) += (long) src; break; case T_float : *((float *) value) += (float) src; break; case T_range : { Range r = (Range) src; *((int *) value) += r.lo; *(((int *) value)+1) += r.hi; } break; case T_variable : case T_variableref : printf(" UserVariable: WARNING: Algebra on T_variable or T_variableref " " not possible!\n"); break; case T_invalid : printf(" UserVariable: WARNING: Can't operate on invalid variable!\n"); break; } }; // Return the absolute value of the difference (delta) between this variable and arg UserVariable GetDelta (UserVariable &arg) { UserVariable ret; ret.type = T_char; ret.RaisePrecision(*this); ret.RaisePrecision(arg); switch (ret.type) { case T_char : ret = (char) abs((char) arg - (char) *this); break; case T_int : ret = (int) abs((int) arg - (int) *this); break; case T_long : ret = (long) labs((long) arg - (long) *this); break; case T_float : ret = (float) fabsf((float) arg - (float) *this); break; default : printf(" UserVariable: WARNING: GetDelta() doesn't work on this type of variable!\n"); break; } return ret; }; void operator -= (UserVariable &src) { RaisePrecision(src); switch (type) { case T_char : *((char *) value) -= (char) src; break; case T_int : *((int *) value) -= (int) src; break; case T_long : *((long *) value) -= (long) src; break; case T_float : *((float *) value) -= (float) src; break; case T_range : { Range r = (Range) src; *((int *) value) -= r.lo; *(((int *) value)+1) -= r.hi; } break; case T_variable : case T_variableref : printf(" UserVariable: WARNING: Algebra on T_variable or T_variableref " " not possible!\n"); break; case T_invalid : printf(" UserVariable: WARNING: Can't operate on invalid variable!\n"); break; } }; void operator *= (UserVariable &src) { RaisePrecision(src); switch (type) { case T_char : *((char *) value) *= (char) src; break; case T_int : *((int *) value) *= (int) src; break; case T_long : *((long *) value) *= (long) src; break; case T_float : *((float *) value) *= (float) src; break; case T_range : { Range r = (Range) src; *((int *) value) *= r.lo; *(((int *) value)+1) *= r.hi; } break; case T_variable : case T_variableref : printf(" UserVariable: WARNING: Algebra on T_variable or T_variableref " " not possible!\n"); break; case T_invalid : printf(" UserVariable: WARNING: Can't operate on invalid variable!\n"); break; } }; void operator /= (UserVariable &src) { switch (type) { case T_char : case T_int : case T_long : case T_float : { // Special case- when dividing a scalar by another scalar, the // result is always evaluated to a float!! float t = (float) src; // Convert this variable to a float if (t != 0) { *((float *) value) = (float) *this / t; type = T_float; } } break; case T_range : { Range r = (Range) src; if (r.lo != 0) *((int *) value) /= r.lo; if (r.hi != 0) *(((int *) value)+1) /= r.hi; } break; case T_variable : case T_variableref : printf(" UserVariable: WARNING: Algebra on T_variable or T_variableref " " not possible!\n"); break; case T_invalid : printf(" UserVariable: WARNING: Can't operate on invalid variable!\n"); break; } }; UserVariable & operator = (char src) { *((char *) value) = src; return *this; }; UserVariable & operator = (int src) { *((int *) value) = src; return *this; }; UserVariable & operator = (long src) { *((long *) value) = src; return *this; }; UserVariable & operator = (float src) { *((float *) value) = src; return *this; }; UserVariable & operator = (Range src) { *((int *) value) = src.lo; *(((int *) value)+1) = src.hi; return *this; }; operator char () { switch (type) { case T_char : return *((char *) value); case T_int : return (char) *((int *) value); case T_long : return (char) *((long *) value); case T_float : return (char) *((float *) value); case T_range : printf(" UserVariable: WARNING: Can't convert range to scalar!\n"); return 0; case T_variable : case T_variableref : printf(" UserVariable: WARNING: Can't convert T_variable or " "T_variableref!\n"); return 0; case T_invalid : printf(" UserVariable: WARNING: Can't convert invalid variable!\n"); return 0; } return 0; }; operator int () { switch (type) { case T_char : return (int) *((char *) value); case T_int : return *((int *) value); case T_long : return (int) *((long *) value); case T_float : return (int) *((float *) value); case T_range : printf(" UserVariable: WARNING: Can't convert range to scalar!\n"); return 0; case T_variable : case T_variableref : printf(" UserVariable: WARNING: Can't convert T_variable or " "T_variableref!\n"); return 0; case T_invalid : printf(" UserVariable: WARNING: Can't convert invalid variable!\n"); return 0; } return 0; }; operator long () { switch (type) { case T_char : return (long) *((char *) value); case T_int : return (long) *((int *) value); case T_long : return *((long *) value); case T_float : return (long) *((float *) value); case T_range : printf(" UserVariable: WARNING: Can't convert range to scalar!\n"); return 0; case T_variable : case T_variableref : printf(" UserVariable: WARNING: Can't convert T_variable or " "T_variableref!\n"); return 0; case T_invalid : printf(" UserVariable: WARNING: Can't convert invalid variable!\n"); return 0; } return 0; }; operator float () { switch (type) { case T_char : return (float) *((char *) value); case T_int : return (float) *((int *) value); case T_long : return (float) *((long *) value); case T_float : return *((float *) value); case T_range : printf(" UserVariable: WARNING: Can't convert range to scalar!\n"); return 0; case T_variable : case T_variableref : printf(" UserVariable: WARNING: Can't convert T_variable or " "T_variableref!\n"); return 0; case T_invalid : printf(" UserVariable: WARNING: Can't convert invalid variable!\n"); return 0; } return 0; }; operator Range () { switch (type) { case T_char : return Range(*((char *) value), *((char *) value)); case T_int : return Range(*((int *) value), *((int *) value)); case T_long : return Range(*((long *) value), *((long *) value)); case T_float : return Range((int) *((float *) value), (int) *((float *) value)); case T_range : return Range(*((int *) value),*(((int *) value)+1)); case T_variable : case T_variableref : printf(" UserVariable: WARNING: Can't convert T_variable or " "T_variableref!\n"); return Range(0,0); case T_invalid : printf(" UserVariable: WARNING: Can't convert invalid variable!\n"); return Range(0,0); } return Range(0,0); }; void operator = (UserVariable &src) { // Assignment operator does not copy name to avoid memory alloc // problems type = src.type; memcpy(data,src.data,CFG_VAR_SIZE); if (src.value == src.data) value = data; else value = src.value; // System variable, copy data ptr directly }; // Sets this UserVariable from src, converting from src type to this void SetFrom(UserVariable &src) { switch (type) { case T_char : *this = (char) src; break; case T_int : *this = (int) src; break; case T_long : *this = (long) src; break; case T_float : *this = (float) src; break; case T_range : *this = (Range) src; break; case T_variable : case T_variableref : case T_invalid : printf(" UserVariable: WARNING: Can't set from invalid variable!\n"); break; } } // Dump UserVariable to string str (maxlen is maximum length) // or stdout if str = 0 void Print(char *str = 0, int maxlen = 0); inline char IsSystemVariable() { return (value != data); }; inline char *GetValue() { return value; }; // Returns the raw data bytes for the value of this variable inline CoreDataType GetType() { return type; }; inline char *GetName() { return name; }; char *name; CoreDataType type; char data[CFG_VAR_SIZE]; // System variables are a special type of variable that is created by the // core FreeWheeling system and not the user. // // A system variable is essentially a pointer to an internal data value // inside FreeWheeling. It can be read by the configuration system like // any other user variable, but it accesses directly into FreeWheeling's // internal memory and so it has a mind of its own // // If value points to the data array, this is a user variable // If value does not point to data, this is a system variable char *value; UserVariable *next; }; // Data for writer threads (common to all instances of SRMWRingBuffer) class SRMWRingBuffer_Writers { public: #define MAX_WRITER_THREADS 50 // Hard-wired maximum number of writer threads // Global prep methods static void InitAll() { pthread_mutex_init(®ister_lock,0); num_writers = 0; }; static void CloseAll() { pthread_mutex_destroy(®ister_lock); num_writers = 0; }; static void RegisterWriter (pthread_t id) { pthread_mutex_lock (®ister_lock); if (num_writers >= MAX_WRITER_THREADS) { printf("CORE: ERROR: Too many writer threads for Ring Buffer!\n"); exit(1); } ids[num_writers] = id; num_writers++; pthread_mutex_unlock (®ister_lock); }; static void RegisterWriter () { pthread_mutex_lock (®ister_lock); if (num_writers >= MAX_WRITER_THREADS) { printf("CORE: ERROR: Too many writer threads for Ring Buffer!\n"); exit(1); } ids[num_writers] = pthread_self(); num_writers++; pthread_mutex_unlock (®ister_lock); }; static int num_writers; // Number of writer threads registered static pthread_t ids[MAX_WRITER_THREADS]; // Thread ID for each writer static pthread_mutex_t register_lock; }; // Ringbuffer implementation for a Single Reader Thread & Multiple Writer Threads // // This expands to a set of ringbuffers- one for each writer thread. The order of elements between threads is not preserved. // Elements are written and read using COPY operations. template class SRMWRingBuffer { // Create a ringbuffer with numel elements of class T SRMWRingBuffer (int numel) : numel(numel) { wbufs = new jack_ringbuffer_t *[SRMWRingBuffer_Writers::num_writers]; for (int i = 0; i < SRMWRingBuffer_Writers::num_writers; i++) wbufs[i] = jack_ringbuffer_create(sizeof(T) * numel); }; ~SRMWRingBuffer() { for (int i = 0; i < SRMWRingBuffer_Writers::num_writers; i++) jack_ringbuffer_free(wbufs[i]); delete[] wbufs; }; // Instance methods int WriteElement (T *el) { // Determine which write thread we are pthread_t id = pthread_self(); for (int i = 0; i < SRMWRingBuffer_Writers::num_writers; i++) if (pthread_equal(id,SRMWRingBuffer_Writers::ids[i])) { // Write to the appropriate ringbuf if (jack_ringbuffer_write(wbufs[i],el,sizeof(T)) < sizeof(T)) { printf("CORE: No space in RingBuffer for element\n"); return -1; } else return 0; } printf("CORE: RingBuffer write from unregistered write thread!\n"); return -1; }; T *ReadElement () { // Check each ring buffer for (int i = 0; i < SRMWRingBuffer_Writers::num_writers; i++) { size_t avail = jack_ringbuffer_read_space(wbufs[i]); if (avail >= sizeof(T)) { // Read element here if (jack_ringbuffer_read(wbufs[i],tmpread,sizeof(T)) != sizeof(T)) { printf("CORE: Size mismatch during RingBuffer read\n"); return 0; } else return tmpread; } } // No data available return 0; }; protected: // Array of single-read single-write ring buffers: one for each writer thread jack_ringbuffer_t **wbufs; int numel; // Number of elements of class T in the buffer char tmpread[sizeof(T)]; // Holding spot for read }; #endif fweelin-0.6/src/fweelin_event.cc0000755000175000017500000003650011050157515015405 0ustar mercmerc/* They said we don't do kirtan during seva. Because singing is not mouna. but I differ-- Rhythm is stillness in motion. And in the silence, there is music. */ /* Copyright 2004-2008 Jan Pekau (JP Mercury) This file is part of Freewheeling. Freewheeling is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. Freewheeling is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Freewheeling. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include "fweelin_event.h" EventTypeTable *Event::ett = 0; // Events are allocated in blocks using the Memory Manager // These macros help populate the event type table with names and managers // They also determine which, if any, event parameters are indexed for speed #define SET_ETYPE(etyp,nm,typ) \ case etyp : \ { \ Event *proto = \ ::new typ[PreallocatedType:: \ PREALLOC_DEFAULT_NUM_INSTANCES]; \ ett[i].name = nm; \ ett[i].mgr = \ new PreallocatedType(mmgr,proto,sizeof(typ), \ PreallocatedType:: \ PREALLOC_DEFAULT_NUM_INSTANCES, \ 1); \ ett[i].slowdelivery = 0; \ int paramidx = -1, j = 0; \ for (; j < proto->GetNumParams() && \ proto->GetParam(j).max_index == -1; j++); \ if (j < proto->GetNumParams()) \ paramidx = j; \ ett[i].paramidx = paramidx; \ } \ break; #define SET_ETYPE_SLOW(etyp,nm,typ) \ case etyp : \ { \ Event *proto = \ ::new typ[PreallocatedType:: \ PREALLOC_DEFAULT_NUM_INSTANCES]; \ ett[i].name = nm; \ ett[i].mgr = \ new PreallocatedType(mmgr,proto,sizeof(typ), \ PreallocatedType:: \ PREALLOC_DEFAULT_NUM_INSTANCES, \ 1); \ ett[i].slowdelivery = 1; \ int paramidx = -1, j = 0; \ for (; j < proto->GetNumParams() && \ proto->GetParam(j).max_index == -1; j++); \ if (j < proto->GetNumParams()) \ paramidx = j; \ ett[i].paramidx = paramidx; \ } \ break; #define SET_ETYPE_NO_BLOCK(etyp,nm,typ) \ case etyp : \ { \ Event *proto = \ ::new typ[PreallocatedType:: \ PREALLOC_DEFAULT_NUM_INSTANCES]; \ ett[i].name = nm; \ ett[i].mgr = \ new PreallocatedType(mmgr,proto,sizeof(typ), \ PreallocatedType:: \ PREALLOC_DEFAULT_NUM_INSTANCES, \ 0); \ int paramidx = -1, j = 0; \ for (; j < proto->GetNumParams() && \ proto->GetParam(j).max_index == -1; j++); \ if (j < proto->GetNumParams()) \ paramidx = j; \ ett[i].paramidx = paramidx; \ } \ break; #define SET_ETYPE_NUMPREALLOC(etyp,nm,typ,numpre) \ case etyp : \ { \ Event *proto = ::new typ[numpre]; \ ett[i].name = nm; \ ett[i].mgr = new PreallocatedType(mmgr,proto,sizeof(typ),numpre,1); \ int paramidx = -1, j = 0; \ for (; j < proto->GetNumParams() && \ proto->GetParam(j).max_index == -1; j++); \ if (j < proto->GetNumParams()) \ paramidx = j; \ ett[i].paramidx = paramidx; \ } \ break; void Event::SetupEventTypeTable(MemoryManager *mmgr) { int evnum = (int) EventType(T_EV_Last); ett = new EventTypeTable[evnum]; for (int i = 0; i < evnum; i++) { switch (EventType(i)) { // *** Notice some events are marked SET_ETYPE_SLOW // This is critical because some code sections are not able to run in RT // Any event marked SET_ETYPE should be able to be run in RT, // because if it is bound to a MIDI trigger, that will happen. // // Events marked SET_ETYPE_SLOW will always run from the nonRT event // thread. This means they will be delivered after SET_ETYPE events if // a sequence of events is sent. SET_ETYPE(T_EV_Input_Key,"key",KeyInputEvent); SET_ETYPE(T_EV_Input_JoystickButton,"joybutton", JoystickButtonInputEvent); SET_ETYPE(T_EV_Input_MIDIKey,"midikey",MIDIKeyInputEvent); SET_ETYPE(T_EV_Input_MIDIController,"midicontroller", MIDIControllerInputEvent); SET_ETYPE(T_EV_Input_MIDIProgramChange, "midiprogramchange", MIDIProgramChangeInputEvent); SET_ETYPE(T_EV_Input_MIDIChannelPressure, "midichannelpressure", MIDIChannelPressureInputEvent); SET_ETYPE(T_EV_Input_MIDIPitchBend,"midipitchbend", MIDIPitchBendInputEvent); SET_ETYPE_NUMPREALLOC(T_EV_Input_MIDIClock,"midiclock",MIDIClockInputEvent,20); SET_ETYPE(T_EV_Input_MIDIStartStop,"midistartstop",MIDIStartStopInputEvent); SET_ETYPE(T_EV_LoopClicked,"loop-clicked",LoopClickedEvent); SET_ETYPE(T_EV_GoSub,"go-sub",GoSubEvent); SET_ETYPE(T_EV_StartSession,"start-freewheeling",StartSessionEvent); SET_ETYPE(T_EV_StartInterface,"start-interface",StartInterfaceEvent); SET_ETYPE_SLOW(T_EV_ExitSession,"exit-freewheeling",ExitSessionEvent); SET_ETYPE(T_EV_SlideMasterInVolume,"slide-master-in-volume", SlideMasterInVolumeEvent); SET_ETYPE(T_EV_SlideMasterOutVolume,"slide-master-out-volume", SlideMasterOutVolumeEvent); SET_ETYPE(T_EV_SlideInVolume,"slide-in-volume", SlideInVolumeEvent); SET_ETYPE(T_EV_SetMasterInVolume,"set-master-in-volume", SetMasterInVolumeEvent); SET_ETYPE(T_EV_SetMasterOutVolume,"set-master-out-volume", SetMasterOutVolumeEvent); SET_ETYPE(T_EV_SetInVolume,"set-in-volume", SetInVolumeEvent); SET_ETYPE(T_EV_ToggleInputRecord,"toggle-input-record", ToggleInputRecordEvent); SET_ETYPE(T_EV_SetMidiEchoPort,"set-midi-echo-port", SetMidiEchoPortEvent); SET_ETYPE(T_EV_SetMidiEchoChannel,"set-midi-echo-channel", SetMidiEchoChannelEvent); SET_ETYPE(T_EV_AdjustMidiTranspose,"adjust-midi-transpose", AdjustMidiTransposeEvent); SET_ETYPE(T_EV_FluidSynthEnable,"fluidsynth-enable", FluidSynthEnableEvent); SET_ETYPE(T_EV_SetMidiTuning,"set-midi-tuning", SetMidiTuningEvent); SET_ETYPE(T_EV_SetTriggerVolume,"set-trigger-volume", SetTriggerVolumeEvent); SET_ETYPE(T_EV_SlideLoopAmp,"slide-loop-amplifier",SlideLoopAmpEvent); SET_ETYPE(T_EV_SetLoopAmp,"set-loop-amplifier",SetLoopAmpEvent); SET_ETYPE(T_EV_AdjustLoopAmp,"adjust-loop-amplifier",AdjustLoopAmpEvent); SET_ETYPE(T_EV_TriggerLoop,"trigger-loop",TriggerLoopEvent); SET_ETYPE_SLOW(T_EV_MoveLoop,"move-loop",MoveLoopEvent); SET_ETYPE_SLOW(T_EV_RenameLoop,"rename-loop",RenameLoopEvent); SET_ETYPE_SLOW(T_EV_EraseLoop,"erase-loop",EraseLoopEvent); SET_ETYPE_SLOW(T_EV_EraseAllLoops,"erase-all-loops",EraseAllLoopsEvent); SET_ETYPE_SLOW(T_EV_EraseSelectedLoops,"erase-selected-loops", EraseSelectedLoopsEvent); SET_ETYPE(T_EV_SlideLoopAmpStopAll,"slide-loop-amplifier-stop-all", SlideLoopAmpStopAllEvent); SET_ETYPE_SLOW(T_EV_DeletePulse,"delete-pulse",DeletePulseEvent); SET_ETYPE_SLOW(T_EV_SelectPulse,"select-pulse",SelectPulseEvent); SET_ETYPE(T_EV_TapPulse,"tap-pulse",TapPulseEvent); SET_ETYPE(T_EV_SwitchMetronome,"switch-metronome",SwitchMetronomeEvent); SET_ETYPE(T_EV_SetSyncType,"set-sync-type",SetSyncTypeEvent); SET_ETYPE(T_EV_SetSyncSpeed,"set-sync-speed",SetSyncSpeedEvent); SET_ETYPE(T_EV_SetMidiSync,"set-midi-sync",SetMidiSyncEvent); SET_ETYPE(T_EV_SetVariable,"set-variable",SetVariableEvent); SET_ETYPE(T_EV_ToggleVariable,"toggle-variable",ToggleVariableEvent); SET_ETYPE_SLOW(T_EV_VideoShowSnapshotPage,"video-show-snapshot-page", VideoShowSnapshotPageEvent); SET_ETYPE_SLOW(T_EV_VideoShowLoop,"video-show-loop",VideoShowLoopEvent); SET_ETYPE_SLOW(T_EV_VideoShowLayout,"video-show-layout", VideoShowLayoutEvent); SET_ETYPE_SLOW(T_EV_VideoSwitchInterface,"video-switch-interface", VideoSwitchInterfaceEvent); SET_ETYPE_SLOW(T_EV_VideoShowDisplay,"video-show-display", VideoShowDisplayEvent); SET_ETYPE_SLOW(T_EV_VideoShowHelp,"video-show-help", VideoShowHelpEvent); SET_ETYPE_SLOW(T_EV_VideoFullScreen,"video-full-screen", VideoFullScreenEvent); SET_ETYPE_SLOW(T_EV_ShowDebugInfo,"show-debug-info", ShowDebugInfoEvent); SET_ETYPE_SLOW(T_EV_ToggleDiskOutput,"toggle-disk-output", ToggleDiskOutputEvent); SET_ETYPE(T_EV_SetAutoLoopSaving,"set-auto-loop-saving", SetAutoLoopSavingEvent); SET_ETYPE_SLOW(T_EV_SaveLoop,"save-loop",SaveLoopEvent); SET_ETYPE_SLOW(T_EV_SaveNewScene,"save-new-scene",SaveNewSceneEvent); SET_ETYPE_SLOW(T_EV_SaveCurrentScene,"save-current-scene", SaveCurrentSceneEvent); SET_ETYPE(T_EV_SetLoadLoopId,"set-load-loop-id",SetLoadLoopIdEvent); SET_ETYPE(T_EV_SetDefaultLoopPlacement,"set-default-loop-placement", SetDefaultLoopPlacementEvent); SET_ETYPE_SLOW(T_EV_ToggleSelectLoop,"toggle-select-loop", ToggleSelectLoopEvent); SET_ETYPE_SLOW(T_EV_SelectOnlyPlayingLoops,"select-only-playing-loops", SelectOnlyPlayingLoopsEvent); SET_ETYPE_SLOW(T_EV_SelectAllLoops,"select-all-loops", SelectAllLoopsEvent); SET_ETYPE_SLOW(T_EV_TriggerSelectedLoops,"trigger-selected-loops", TriggerSelectedLoopsEvent); SET_ETYPE(T_EV_SetSelectedLoopsTriggerVolume, "set-selected-loops-trigger-volume", SetSelectedLoopsTriggerVolumeEvent); SET_ETYPE(T_EV_AdjustSelectedLoopsAmp, "adjust-selected-loops-amp", AdjustSelectedLoopsAmpEvent); SET_ETYPE_SLOW(T_EV_InvertSelection,"invert-selection", InvertSelectionEvent); SET_ETYPE_SLOW(T_EV_CreateSnapshot,"create-snapshot", CreateSnapshotEvent); SET_ETYPE_SLOW(T_EV_RenameSnapshot,"rename-snapshot", RenameSnapshotEvent); SET_ETYPE_SLOW(T_EV_TriggerSnapshot,"trigger-snapshot", TriggerSnapshotEvent); SET_ETYPE_SLOW(T_EV_BrowserMoveToItem,"browser-move-to-item", BrowserMoveToItemEvent); SET_ETYPE_SLOW(T_EV_BrowserMoveToItemAbsolute, "browser-move-to-item-absolute", BrowserMoveToItemAbsoluteEvent); SET_ETYPE_SLOW(T_EV_BrowserSelectItem,"browser-select-item", BrowserSelectItemEvent); SET_ETYPE_SLOW(T_EV_BrowserRenameItem,"browser-rename-item", BrowserRenameItemEvent); SET_ETYPE(T_EV_BrowserItemBrowsed,"browser-item-browsed", BrowserItemBrowsedEvent); SET_ETYPE_SLOW(T_EV_PatchBrowserMoveToBank,"patchbrowser-move-to-bank", PatchBrowserMoveToBankEvent); SET_ETYPE_SLOW(T_EV_PatchBrowserMoveToBankByIndex, "patchbrowser-move-to-bank-by-index", PatchBrowserMoveToBankByIndexEvent); // Internal events-- don't try to bind to these SET_ETYPE(T_EV_EndRecord,"__internal__",EndRecordEvent); SET_ETYPE(T_EV_LoopList,"__internal__",LoopListEvent); SET_ETYPE(T_EV_SceneMarker,"__internal__",SceneMarkerEvent); SET_ETYPE(T_EV_PulseSync,"__internal__",PulseSyncEvent); SET_ETYPE(T_EV_TriggerSet,"__internal__",TriggerSetEvent); SET_ETYPE(T_EV_Input_MouseButton,"__internal__",MouseButtonInputEvent); SET_ETYPE(T_EV_Input_MouseMotion,"__internal__",MouseMotionInputEvent); default: break; } } }; void Event::TakedownEventTypeTable() { int evnum = (int) EventType(T_EV_Last); for (int i = 0; i < evnum; i++) { // Deleting the manager will delete all instances // allocated thru it-- if (ett[i].mgr != 0) delete ett[i].mgr; // so the prototype base instance is already deleted ett[i].proto = 0; } delete[] ett; }; Event *Event::GetEventByType(EventType typ, char wait) { if (ett == 0) { printf("EVENT: ERROR- no event type table!\n"); exit(1); } int i = (int) typ; if (ett[i].mgr != 0) { Event *ret = (Event *) ett[i].mgr->RTNew(); if (ret != 0) return ret; else { // No instance available if (wait) { // Wait printf("EVENT: Waiting for memory to be allocated.\n"); do { usleep(10000); ret = (Event *) ett[i].mgr->RTNew(); } while (ret == 0); return ret; } else { return 0; // Don't wait } } } else if (ett[i].proto != 0) { Event *ret = (Event *) ett[i].proto->RTNew(); if (ret != 0) return ret; else { // No instance available if (wait) { // Wait printf("EVENT: Waiting for mem alloc...\n"); do { usleep(10000); ret = (Event *) ett[i].proto->RTNew(); } while (ret == 0); return ret; } else { return 0; // Don't wait } } } else { printf("ERROR: no prototype or mgr for event type: '%s'\n", ett[i].name); return 0; } }; Event *Event::GetEventByName(char *evtname, char wait) { if (ett == 0) { printf("EVENT: Error- no event type table!\n"); exit(1); } int evnum = (int) EventType(T_EV_Last); for (int i = 0; i < evnum; i++) { if (ett[i].name != 0) if (!strcmp(evtname, ett[i].name)) return GetEventByType((EventType) i,wait); } return 0; }; EventManager::~EventManager() { //printf("Event Manager: cleanup... this: %p\n",this); // Terminate the dispatch thread threadgo = 0; pthread_mutex_lock (&dispatch_thread_lock); pthread_cond_signal (&dispatch_ready); pthread_mutex_unlock (&dispatch_thread_lock); pthread_join(dispatch_thread,0); pthread_cond_destroy (&dispatch_ready); pthread_mutex_destroy (&dispatch_thread_lock); pthread_mutex_destroy (&listener_list_lock); int evnum = (int) EventType(T_EV_Last); for (int i = 0; i < evnum; i++) { // Erase listeners EventListenerItem *cur = listeners[i]; while (cur != 0) { EventListenerItem *tmp = cur->next; delete cur; cur = tmp; } } delete[] listeners; // Takedown event type table // printf(" .. ETT takedown (this: %p)\n",this); Event::TakedownEventTypeTable(); // printf(" .. ETT takedown done (this: %p)\n",this); printf("EVENT: manager end.\n"); }; fweelin-0.6/src/fweelin_event.h0000755000175000017500000022472611065526545015271 0ustar mercmerc#ifndef __FWEELIN_EVENT_H #define __FWEELIN_EVENT_H /* Copyright 2004-2008 Jan Pekau (JP Mercury) This file is part of Freewheeling. Freewheeling is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. Freewheeling is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Freewheeling. If not, see . */ #include #include extern "C" { #include } // Event parameter name for interface ID #define INTERFACEID "interfaceid" class Loop; class Event; class EventProducer { }; class EventListener { public: virtual void ReceiveEvent(Event *ev, EventProducer *from) = 0; }; // An event hook gets first dibs on incoming events // We use this to override the usual functions of, say, the keyboard, // and redirect them elsewhere, like typing text. class EventHook { public: // HookEvent works just like EventListener::ReceiveEvent, // except it returns nonzero if it has swallowed the event // and zero if it has disregarded the event. // // If HookEvent disregards the event, it is processed as defined // through the configuration system virtual char HookEvent(Event *ev, EventProducer *from) = 0; }; double mygettime(void); // Max filename length #define FWEELIN_OUTNAME_LEN 512 #define MAX_MIDI_CHANNELS 16 #define MAX_MIDI_CONTROLLERS 127 #define MAX_MIDI_NOTES 127 #define MAX_MIDI_PORTS 4 // Get a new block of events of the given type #define EVT_NEW_BLOCK(typ,etyp) ::new typ[Event::GetMemMgrByType(etyp)-> \ GetBlockSize()] // Basic defines for within an Event #define EVT_DEFINE(typ,etyp) \ typ() { Recycle(); }; \ \ virtual Preallocated *NewInstance() { \ return EVT_NEW_BLOCK(typ,etyp); \ }; \ virtual EventType GetType() { return etyp; }; \ FWMEM_DEFINE_DELBLOCK #define EVT_DEFINE_NO_CONSTR(typ,etyp) \ virtual Preallocated *NewInstance() { \ return EVT_NEW_BLOCK(typ,etyp); \ }; \ virtual EventType GetType() { return etyp; }; \ FWMEM_DEFINE_DELBLOCK #define EVT_DEFINE_NO_BLOCK(typ,etyp) \ typ() { Recycle(); }; \ \ virtual Preallocated *NewInstance() { \ return ::new typ(); \ }; \ virtual EventType GetType() { return etyp; }; // List of all types of events enum EventType { T_EV_None, T_EV_Input_Key, T_EV_Input_JoystickButton, T_EV_Input_MIDIKey, T_EV_Input_MIDIController, T_EV_Input_MIDIProgramChange, T_EV_Input_MIDIChannelPressure, T_EV_Input_MIDIPitchBend, T_EV_Input_MIDIClock, T_EV_Input_MIDIStartStop, T_EV_StartSession, T_EV_StartInterface, T_EV_GoSub, T_EV_LoopClicked, T_EV_BrowserItemBrowsed, // End of bindable events- // Events after this can not trigger config bindings T_EV_Last_Bindable, T_EV_Input_MouseButton, T_EV_Input_MouseMotion, T_EV_EndRecord, T_EV_LoopList, T_EV_SceneMarker, T_EV_PulseSync, T_EV_TriggerSet, T_EV_SetVariable, T_EV_ToggleVariable, T_EV_VideoShowSnapshotPage, T_EV_VideoShowLoop, T_EV_VideoShowLayout, T_EV_VideoSwitchInterface, T_EV_VideoShowDisplay, T_EV_VideoShowHelp, T_EV_VideoFullScreen, T_EV_ShowDebugInfo, T_EV_ExitSession, T_EV_SlideMasterInVolume, T_EV_SlideMasterOutVolume, T_EV_SlideInVolume, T_EV_SetMasterInVolume, T_EV_SetMasterOutVolume, T_EV_SetInVolume, T_EV_ToggleInputRecord, T_EV_SetMidiEchoPort, T_EV_SetMidiEchoChannel, T_EV_AdjustMidiTranspose, T_EV_FluidSynthEnable, T_EV_SetMidiTuning, T_EV_DeletePulse, T_EV_SelectPulse, T_EV_TapPulse, T_EV_SwitchMetronome, T_EV_SetSyncType, T_EV_SetSyncSpeed, T_EV_SetMidiSync, T_EV_ToggleSelectLoop, T_EV_SelectOnlyPlayingLoops, T_EV_SelectAllLoops, T_EV_TriggerSelectedLoops, T_EV_SetSelectedLoopsTriggerVolume, T_EV_AdjustSelectedLoopsAmp, T_EV_InvertSelection, T_EV_CreateSnapshot, T_EV_RenameSnapshot, T_EV_TriggerSnapshot, T_EV_SetTriggerVolume, T_EV_SlideLoopAmp, T_EV_SetLoopAmp, T_EV_AdjustLoopAmp, T_EV_TriggerLoop, T_EV_MoveLoop, T_EV_RenameLoop, T_EV_EraseLoop, T_EV_EraseAllLoops, T_EV_EraseSelectedLoops, T_EV_SlideLoopAmpStopAll, T_EV_ToggleDiskOutput, T_EV_SetAutoLoopSaving, T_EV_SaveLoop, T_EV_SaveNewScene, T_EV_SaveCurrentScene, T_EV_SetLoadLoopId, T_EV_SetDefaultLoopPlacement, T_EV_BrowserMoveToItem, T_EV_BrowserMoveToItemAbsolute, T_EV_BrowserSelectItem, T_EV_BrowserRenameItem, T_EV_PatchBrowserMoveToBank, T_EV_PatchBrowserMoveToBankByIndex, T_EV_Last }; #include "fweelin_datatypes.h" #include "fweelin_block.h" // Gets the offset of given variable into the current class #define FWEELIN_GETOFS(a) ((long)&a - (long)this) class SDLKeyList; class PreallocatedType; class Event; // EventParameters are parameters in events that can be controlled // from inputs such as MIDI and Keyboard (see InputMatrix) class EventParameter { public: // Specify an event parameter with given name, offset into event, // size of data type, and max index (-1 by default if parameter // is not indexed) EventParameter (char *name = 0, long ofs = 0, CoreDataType dtype = T_char, int max_index = -1) : name(name), ofs(ofs), dtype(dtype), max_index(max_index) {}; char *name; // Name of event parameter long ofs; // Offset into event class of data CoreDataType dtype; // Type of data int max_index; // Config stores a hashtable for input events for // quick triggering-- this is the # of hash indexes // for an indexed parameter, or -1 for an unindexed param }; // Table of all event types and memory managers for them class EventTypeTable { public: EventTypeTable (char *name = 0, PreallocatedType *mgr = 0, Event *proto = 0, int paramidx = -1, char slowdelivery = 0) : name(name), mgr(mgr), proto(proto), paramidx(paramidx), slowdelivery(slowdelivery) {}; char *name; PreallocatedType *mgr; Event *proto; int paramidx; // Index of event parameter that is used for hash index // For example, in the keyboard input event, the keysym // is indexed for quick triggering of keyboard events by key char slowdelivery; // Nonzero if this event should be delivered slow, in // a nonRT thread. This is useful for events that cause // nonRT-safe operations to be executed. }; // Events can be allocated in realtime using class Preallocated class Event : public Preallocated { public: Event() { Recycle(); }; virtual ~Event() {}; virtual void Recycle() { from = 0; to = 0; next = 0; time.tv_sec = 0; time.tv_nsec = 0; echo = 0; }; virtual void operator = (const Event &src) {}; virtual EventType GetType() { return T_EV_None; }; // Returns the number of parameters this event has virtual int GetNumParams() { return 0; }; // Returns the nth parameter virtual EventParameter GetParam(int n) { return EventParameter(); }; // Get the memory manager for the given type static inline PreallocatedType *GetMemMgrByType(EventType typ) { return ett[(int) typ].mgr; }; // Returns an instance of the event named 'evtname' // If wait is nonzero and there are no free instances through RTNew, // we wait until one becomes available static Event *GetEventByName(char *evtname, char wait = 0); // Returns an instance of the event with given type static Event *GetEventByType(EventType typ, char wait = 0); // Returns the index of the indexed parameter for the event with given // type static int GetParamIdxByType(EventType typ) { return ett[typ].paramidx; }; // Returns the string name of the given event type static char *GetEventName(EventType typ) { return ett[typ].name; }; static EventTypeTable *ett; static void SetupEventTypeTable(MemoryManager *mmgr); static void TakedownEventTypeTable(); // In an event queue, stores who this event is from EventProducer *from; // In an event queue, stores who this event is to EventListener *to; // In an event queue, this stores pointer to next event Event *next; // Time to send event struct timespec time; // Event is being echoed to MIDI outputs? // If echo is nonzero, the event is sent through the patch routing // for the currently selected patch- affecting the port(s) and channel(s) // where the event is sent. If echo is 0, the event is sent out as described // in the event (ie via outport and midichannel parameters). char echo; }; // GoSub is really an event that encapsulates other events // It allows us to fire off a subroutine of events by triggering one GoSubEvent // The events that are fired off are defined by creating a binding to // input event "go-sub" class GoSubEvent : public Event { // Size of hashtable for indexing based on subs parameter const static int SUBS_HASH = 127; public: EVT_DEFINE(GoSubEvent,T_EV_GoSub); virtual void operator = (const Event &src) { GoSubEvent &s = (GoSubEvent &) src; sub = s.sub; param1 = s.param1; param2 = s.param2; param3 = s.param3; }; virtual int GetNumParams() { return 4; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter("sub",FWEELIN_GETOFS(sub),T_int,SUBS_HASH); case 1: return EventParameter("param1",FWEELIN_GETOFS(param1),T_float); case 2: return EventParameter("param2",FWEELIN_GETOFS(param2),T_float); case 3: return EventParameter("param3",FWEELIN_GETOFS(param3),T_float); } return EventParameter(); }; int sub; // Subroutine # float param1, // Parameter 1 param2, // Parameter 2 param3; // Parameter 3 }; class KeyInputEvent : public Event { public: EVT_DEFINE(KeyInputEvent,T_EV_Input_Key); virtual void operator = (const Event &src) { KeyInputEvent &s = (KeyInputEvent &) src; down = s.down; keysym = s.keysym; unicode = s.unicode; }; virtual int GetNumParams() { return 3; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter("keydown",FWEELIN_GETOFS(down),T_char); case 1: return EventParameter("key",FWEELIN_GETOFS(keysym),T_int,SDLK_LAST); case 2: return EventParameter("unicode",FWEELIN_GETOFS(unicode),T_int); } return EventParameter(); }; char down; // Nonzero if key is pressed, zero if key is released int keysym, // Keysym of key pressed unicode; // Unicode translation (if enabled) int presslen; }; class LoopClickedEvent : public Event { public: EVT_DEFINE(LoopClickedEvent,T_EV_LoopClicked); virtual void operator = (const Event &src) { LoopClickedEvent &s = (LoopClickedEvent &) src; down = s.down; button = s.button; loopid = s.loopid; in = s.in; }; virtual int GetNumParams() { return 4; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter("down",FWEELIN_GETOFS(down),T_char); case 1: return EventParameter("button",FWEELIN_GETOFS(button),T_int); case 2: return EventParameter("loopid",FWEELIN_GETOFS(loopid),T_int); case 3: return EventParameter("in",FWEELIN_GETOFS(in),T_char); } return EventParameter(); }; char down, // Nonzero if button is pressed, zero if button is released in; // Zero if clicked in looptray, one if clicked in layout int button; // Button # pressed/released int loopid; // LoopID of loop that was clicked int presslen; }; class JoystickButtonInputEvent : public Event { public: EVT_DEFINE(JoystickButtonInputEvent,T_EV_Input_JoystickButton); virtual void operator = (const Event &src) { JoystickButtonInputEvent &s = (JoystickButtonInputEvent &) src; down = s.down; joystick = s.joystick; button = s.button; }; virtual int GetNumParams() { return 3; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter("down",FWEELIN_GETOFS(down),T_char); case 1: return EventParameter("button",FWEELIN_GETOFS(button),T_int); case 2: return EventParameter("joystick",FWEELIN_GETOFS(joystick),T_int); } return EventParameter(); }; char down; // Nonzero if button is pressed, zero if button is released int button; // Button # pressed/released int joystick; // Index of joystick int presslen; }; class MouseButtonInputEvent : public Event { public: EVT_DEFINE(MouseButtonInputEvent,T_EV_Input_MouseButton); virtual void operator = (const Event &src) { MouseButtonInputEvent &s = (MouseButtonInputEvent &) src; down = s.down; button = s.button; x = s.x; y = s.y; }; virtual int GetNumParams() { return 4; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter("down",FWEELIN_GETOFS(down),T_char); case 1: return EventParameter("button",FWEELIN_GETOFS(button),T_int); case 2: return EventParameter("x",FWEELIN_GETOFS(x),T_int); case 3: return EventParameter("y",FWEELIN_GETOFS(y),T_int); } return EventParameter(); }; char down; // Nonzero if button is pressed, zero if button is released int button; // Button # pressed/released int x, y; // Coordinates of press (on screen) int presslen; }; class MouseMotionInputEvent : public Event { public: EVT_DEFINE(MouseMotionInputEvent,T_EV_Input_MouseMotion); virtual void operator = (const Event &src) { MouseMotionInputEvent &s = (MouseMotionInputEvent &) src; x = s.x; y = s.y; }; virtual int GetNumParams() { return 2; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter("x",FWEELIN_GETOFS(x),T_int); case 1: return EventParameter("y",FWEELIN_GETOFS(y),T_int); } return EventParameter(); }; int x, y; // Coordinates of mouse motion (on screen) }; class MIDIControllerInputEvent : public Event { public: EVT_DEFINE(MIDIControllerInputEvent,T_EV_Input_MIDIController); virtual void Recycle() { outport = 1; Event::Recycle(); }; virtual void operator = (const Event &src) { MIDIControllerInputEvent &s = (MIDIControllerInputEvent &) src; outport = s.outport; channel = s.channel; ctrl = s.ctrl; val = s.val; echo = s.echo; }; virtual int GetNumParams() { return 5; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter("outport",FWEELIN_GETOFS(outport),T_int); case 1: return EventParameter("midichannel",FWEELIN_GETOFS(channel),T_int); case 2: return EventParameter("controlnum",FWEELIN_GETOFS(ctrl),T_int, MAX_MIDI_CONTROLLERS); case 3: return EventParameter("controlval",FWEELIN_GETOFS(val),T_int); case 4: return EventParameter("routethroughpatch",FWEELIN_GETOFS(echo),T_char); } return EventParameter(); }; int outport, // # of MIDI output to send event to channel, // MIDI channel ctrl, // controller # val; // value }; class MIDIChannelPressureInputEvent : public Event { public: EVT_DEFINE(MIDIChannelPressureInputEvent, T_EV_Input_MIDIChannelPressure); virtual void Recycle() { outport = 1; Event::Recycle(); }; virtual void operator = (const Event &src) { MIDIChannelPressureInputEvent &s = (MIDIChannelPressureInputEvent &) src; outport = s.outport; channel = s.channel; val = s.val; echo = s.echo; }; virtual int GetNumParams() { return 4; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter("outport",FWEELIN_GETOFS(outport),T_int); case 1: return EventParameter("midichannel",FWEELIN_GETOFS(channel),T_int, MAX_MIDI_CHANNELS); case 2: return EventParameter("pressureval",FWEELIN_GETOFS(val),T_int); case 3: return EventParameter("routethroughpatch",FWEELIN_GETOFS(echo),T_char); } return EventParameter(); }; int outport, // # of MIDI output to send event to channel, // MIDI channel val; // Channel pressure value }; class MIDIProgramChangeInputEvent : public Event { public: EVT_DEFINE(MIDIProgramChangeInputEvent, T_EV_Input_MIDIProgramChange); virtual void Recycle() { outport = 1; Event::Recycle(); }; virtual void operator = (const Event &src) { MIDIProgramChangeInputEvent &s = (MIDIProgramChangeInputEvent &) src; outport = s.outport; channel = s.channel; val = s.val; echo = s.echo; }; virtual int GetNumParams() { return 4; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter("outport",FWEELIN_GETOFS(outport),T_int); case 1: return EventParameter("midichannel",FWEELIN_GETOFS(channel),T_int, MAX_MIDI_CHANNELS); case 2: return EventParameter("programval",FWEELIN_GETOFS(val),T_int); case 3: return EventParameter("routethroughpatch",FWEELIN_GETOFS(echo),T_char); } return EventParameter(); }; int outport, // # of MIDI output to send event to channel, // MIDI channel val; // program change value }; class MIDIPitchBendInputEvent : public Event { public: EVT_DEFINE(MIDIPitchBendInputEvent,T_EV_Input_MIDIPitchBend); virtual void Recycle() { outport = 1; Event::Recycle(); }; virtual void operator = (const Event &src) { MIDIPitchBendInputEvent &s = (MIDIPitchBendInputEvent &) src; outport = s.outport; channel = s.channel; val = s.val; echo = s.echo; }; virtual int GetNumParams() { return 4; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter("outport",FWEELIN_GETOFS(outport),T_int); case 1: return EventParameter("midichannel",FWEELIN_GETOFS(channel),T_int, MAX_MIDI_CHANNELS); case 2: return EventParameter("pitchval",FWEELIN_GETOFS(val),T_int); case 3: return EventParameter("routethroughpatch",FWEELIN_GETOFS(echo),T_char); } return EventParameter(); }; int outport, // # of MIDI output to send event to channel, // MIDI channel val; // pitch bend value }; class MIDIKeyInputEvent : public Event { public: EVT_DEFINE(MIDIKeyInputEvent,T_EV_Input_MIDIKey); virtual void Recycle() { outport = 1; Event::Recycle(); }; virtual void operator = (const Event &src) { MIDIKeyInputEvent &s = (MIDIKeyInputEvent &) src; outport = s.outport; down = s.down; channel = s.channel; notenum = s.notenum; vel = s.vel; echo = s.echo; }; virtual int GetNumParams() { return 6; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter("outport",FWEELIN_GETOFS(outport),T_int); case 1: return EventParameter("keydown",FWEELIN_GETOFS(down),T_char); case 2: return EventParameter("midichannel",FWEELIN_GETOFS(channel),T_int, MAX_MIDI_CHANNELS); case 3: return EventParameter("notenum",FWEELIN_GETOFS(notenum),T_int); case 4: return EventParameter("velocity",FWEELIN_GETOFS(vel),T_int); case 5: return EventParameter("routethroughpatch",FWEELIN_GETOFS(echo),T_char); } return EventParameter(); }; char down; // Nonzero if key is pressed, zero if key is released int outport, // # of MIDI output to send event to channel, // MIDI channel notenum, // note number vel; // velocity }; class MIDIClockInputEvent : public Event { public: EVT_DEFINE(MIDIClockInputEvent,T_EV_Input_MIDIClock); virtual void Recycle() { outport = 1; Event::Recycle(); }; virtual void operator = (const Event &src) { MIDIClockInputEvent &s = (MIDIClockInputEvent &) src; outport = s.outport; }; virtual int GetNumParams() { return 1; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter("outport",FWEELIN_GETOFS(outport),T_int); } return EventParameter(); }; int outport; // # of MIDI output to send event to }; class MIDIStartStopInputEvent : public Event { public: EVT_DEFINE(MIDIStartStopInputEvent,T_EV_Input_MIDIStartStop); virtual void Recycle() { outport = 1; start = 0; Event::Recycle(); }; virtual void operator = (const Event &src) { MIDIStartStopInputEvent &s = (MIDIStartStopInputEvent &) src; outport = s.outport; start = s.start; }; virtual int GetNumParams() { return 2; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter("outport",FWEELIN_GETOFS(outport),T_int); case 1: return EventParameter("start",FWEELIN_GETOFS(start),T_char); } return EventParameter(); }; int outport; // # of MIDI output to send event to char start; // 1- MIDI Start, 0- MIDI Stop }; class SetVariableEvent : public Event { public: EVT_DEFINE(SetVariableEvent,T_EV_SetVariable); virtual void Recycle() { maxjumpcheck = 0; Event::Recycle(); }; virtual void operator = (const Event &src) { SetVariableEvent &s = (SetVariableEvent &) src; var = s.var; value.type = s.value.type; value = s.value; maxjumpcheck = s.maxjumpcheck; maxjump.type = s.maxjump.type; maxjump = s.maxjump; }; virtual int GetNumParams() { return 4; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter("var",FWEELIN_GETOFS(var),T_variableref); case 1: return EventParameter("value",FWEELIN_GETOFS(value),T_variable); case 2: return EventParameter("maxjumpcheck",FWEELIN_GETOFS(maxjumpcheck),T_char); case 3: return EventParameter("maxjump",FWEELIN_GETOFS(maxjump),T_variable); } return EventParameter(); }; UserVariable *var; // Variable to set UserVariable value, // Value to set it to maxjump; // Maximum jump in variable between current value and new value // Jumps beyond maxjump cause the variable not to be set char maxjumpcheck; // Nonzero if we should check variable change against maxjump- // If maxjumpcheck is zero, the variable is always set }; class ToggleVariableEvent : public Event { public: EVT_DEFINE(ToggleVariableEvent,T_EV_ToggleVariable); virtual void Recycle() { maxvalue = 1; minvalue = 0; Event::Recycle(); }; virtual void operator = (const Event &src) { ToggleVariableEvent &s = (ToggleVariableEvent &) src; var = s.var; maxvalue = s.maxvalue; minvalue = s.minvalue; }; virtual int GetNumParams() { return 3; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter("var",FWEELIN_GETOFS(var),T_variableref); case 1: return EventParameter("maxvalue",FWEELIN_GETOFS(maxvalue),T_int); case 2: return EventParameter("minvalue",FWEELIN_GETOFS(minvalue),T_int); } return EventParameter(); }; UserVariable *var; // Variable to increment (toggle) int maxvalue, // Maximum value of variable before wraparound minvalue; // Value to wrap to }; class VideoShowLoopEvent : public Event { public: EVT_DEFINE_NO_CONSTR(VideoShowLoopEvent,T_EV_VideoShowLoop); VideoShowLoopEvent() : loopid(0,0) { Recycle(); }; virtual void Recycle() { interfaceid = -1; layoutid = 0; loopid = Range(0,0); Event::Recycle(); }; virtual void operator = (const Event &src) { VideoShowLoopEvent &s = (VideoShowLoopEvent &) src; interfaceid = s.interfaceid; layoutid = s.layoutid; loopid = s.loopid; }; virtual int GetNumParams() { return 3; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter(INTERFACEID,FWEELIN_GETOFS(interfaceid),T_int); case 1: return EventParameter("layoutid",FWEELIN_GETOFS(layoutid),T_int); case 2: return EventParameter("loopid",FWEELIN_GETOFS(loopid),T_range); } return EventParameter(); }; int interfaceid, // Interface in which layout is defined layoutid; // Layout in which to show loops Range loopid; // Range of loop IDs that will be set to correspond to // elements in layout }; class VideoShowSnapshotPageEvent : public Event { public: EVT_DEFINE_NO_CONSTR(VideoShowSnapshotPageEvent,T_EV_VideoShowSnapshotPage); VideoShowSnapshotPageEvent() { Recycle(); }; virtual void Recycle() { interfaceid = -1; displayid = 0; page = 0; Event::Recycle(); }; virtual void operator = (const Event &src) { VideoShowSnapshotPageEvent &s = (VideoShowSnapshotPageEvent &) src; interfaceid = s.interfaceid; displayid = s.displayid; page = s.page; }; virtual int GetNumParams() { return 3; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter(INTERFACEID,FWEELIN_GETOFS(interfaceid),T_int); case 1: return EventParameter("displayid",FWEELIN_GETOFS(displayid),T_int); case 2: return EventParameter("page",FWEELIN_GETOFS(page),T_int); } return EventParameter(); }; int interfaceid, // Interface in which snapshot display is defined displayid, // Display ID of snapshot display page; // +1 (next page) or -1 (previous page) }; class VideoShowLayoutEvent : public Event { public: EVT_DEFINE(VideoShowLayoutEvent,T_EV_VideoShowLayout); virtual void Recycle() { interfaceid = -1; layoutid = 0; show = 0; hideothers = 0; Event::Recycle(); }; virtual void operator = (const Event &src) { VideoShowLayoutEvent &s = (VideoShowLayoutEvent &) src; interfaceid = s.interfaceid; layoutid = s.layoutid; show = s.show; hideothers = s.hideothers; }; virtual int GetNumParams() { return 4; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter(INTERFACEID,FWEELIN_GETOFS(interfaceid),T_int); case 1: return EventParameter("layoutid",FWEELIN_GETOFS(layoutid),T_int); case 2: return EventParameter("show",FWEELIN_GETOFS(show),T_char); case 3: return EventParameter("hideothers",FWEELIN_GETOFS(hideothers),T_char); } return EventParameter(); }; int interfaceid, // Interface in which layout is defined layoutid; // Layout to show char show, // Show it or hide it? hideothers; // Hide other layouts? }; class VideoSwitchInterfaceEvent : public Event { public: EVT_DEFINE(VideoSwitchInterfaceEvent,T_EV_VideoSwitchInterface); virtual void Recycle() { interfaceid = -1; Event::Recycle(); }; virtual void operator = (const Event &src) { VideoSwitchInterfaceEvent &s = (VideoSwitchInterfaceEvent &) src; interfaceid = s.interfaceid; }; virtual int GetNumParams() { return 1; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter(INTERFACEID,FWEELIN_GETOFS(interfaceid),T_int); } return EventParameter(); }; int interfaceid; // Interface to switch to }; class VideoShowDisplayEvent : public Event { public: EVT_DEFINE(VideoShowDisplayEvent,T_EV_VideoShowDisplay); virtual void Recycle() { interfaceid = -1; displayid = 0; show = 0; Event::Recycle(); }; virtual void operator = (const Event &src) { VideoShowDisplayEvent &s = (VideoShowDisplayEvent &) src; interfaceid = s.interfaceid; displayid = s.displayid; show = s.show; }; virtual int GetNumParams() { return 3; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter(INTERFACEID,FWEELIN_GETOFS(interfaceid),T_int); case 1: return EventParameter("displayid",FWEELIN_GETOFS(displayid),T_int); case 2: return EventParameter("show",FWEELIN_GETOFS(show),T_char); } return EventParameter(); }; int interfaceid, // Interface in which display is defined displayid; // Display to show char show; // Show it or hide it? }; class ShowDebugInfoEvent : public Event { public: EVT_DEFINE(ShowDebugInfoEvent,T_EV_ShowDebugInfo); virtual void Recycle() { show = 0; Event::Recycle(); }; virtual void operator = (const Event &src) { ShowDebugInfoEvent &s = (ShowDebugInfoEvent &) src; show = s.show; }; virtual int GetNumParams() { return 1; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter("show",FWEELIN_GETOFS(show),T_char); } return EventParameter(); }; char show; // Show debugging info onscreen? }; class VideoShowHelpEvent : public Event { public: EVT_DEFINE(VideoShowHelpEvent,T_EV_VideoShowHelp); virtual void Recycle() { page = 0; Event::Recycle(); }; virtual void operator = (const Event &src) { VideoShowHelpEvent &s = (VideoShowHelpEvent &) src; page = s.page; }; virtual int GetNumParams() { return 1; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter("page",FWEELIN_GETOFS(page),T_int); } return EventParameter(); }; int page; // Help page to show or 0 for no help }; class VideoFullScreenEvent : public Event { public: EVT_DEFINE(VideoFullScreenEvent,T_EV_VideoFullScreen); virtual void Recycle() { fullscreen = 0; Event::Recycle(); }; virtual void operator = (const Event &src) { VideoFullScreenEvent &s = (VideoFullScreenEvent &) src; fullscreen = s.fullscreen; }; virtual int GetNumParams() { return 1; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter("fullscreen",FWEELIN_GETOFS(fullscreen), T_char); } return EventParameter(); }; char fullscreen; // Freewheeling is full screen or in a window? }; class StartSessionEvent : public Event { public: EVT_DEFINE(StartSessionEvent,T_EV_StartSession); }; class StartInterfaceEvent : public Event { public: EVT_DEFINE(StartInterfaceEvent,T_EV_StartInterface); virtual void Recycle() { interfaceid = -1; Event::Recycle(); }; virtual void operator = (const Event &src) { StartInterfaceEvent &s = (StartInterfaceEvent &) src; interfaceid = s.interfaceid; }; virtual int GetNumParams() { return 1; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter(INTERFACEID,FWEELIN_GETOFS(interfaceid),T_int); } return EventParameter(); }; int interfaceid; // Interface to start }; class ExitSessionEvent : public Event { public: EVT_DEFINE(ExitSessionEvent,T_EV_ExitSession); }; class SlideMasterInVolumeEvent : public Event { public: EVT_DEFINE(SlideMasterInVolumeEvent,T_EV_SlideMasterInVolume); virtual void operator = (const Event &src) { SlideMasterInVolumeEvent &s = (SlideMasterInVolumeEvent &) src; slide = s.slide; }; virtual int GetNumParams() { return 1; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter("slide",FWEELIN_GETOFS(slide),T_float); } return EventParameter(); }; float slide; // Change in speed of amplitude slide }; class SlideMasterOutVolumeEvent : public Event { public: EVT_DEFINE(SlideMasterOutVolumeEvent,T_EV_SlideMasterOutVolume); virtual void operator = (const Event &src) { SlideMasterOutVolumeEvent &s = (SlideMasterOutVolumeEvent &) src; slide = s.slide; }; virtual int GetNumParams() { return 1; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter("slide",FWEELIN_GETOFS(slide),T_float); } return EventParameter(); }; float slide; // Change in speed of amplitude slide }; class SlideInVolumeEvent : public Event { public: EVT_DEFINE(SlideInVolumeEvent,T_EV_SlideInVolume); virtual void operator = (const Event &src) { SlideInVolumeEvent &s = (SlideInVolumeEvent &) src; input = s.input; slide = s.slide; }; virtual int GetNumParams() { return 2; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter("input",FWEELIN_GETOFS(input),T_int); case 1: return EventParameter("slide",FWEELIN_GETOFS(slide),T_float); } return EventParameter(); }; int input; // Number of input to change volume for float slide; // Change in speed of amplitude slide }; class SetMasterInVolumeEvent : public Event { public: EVT_DEFINE(SetMasterInVolumeEvent,T_EV_SetMasterInVolume); virtual void Recycle() { vol = -1.; fadervol = -1.; Event::Recycle(); }; virtual void operator = (const Event &src) { SetMasterInVolumeEvent &s = (SetMasterInVolumeEvent &) src; vol = s.vol; fadervol = s.fadervol; }; virtual int GetNumParams() { return 2; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter("vol",FWEELIN_GETOFS(vol),T_float); case 1: return EventParameter("fadervol",FWEELIN_GETOFS(fadervol),T_float); } return EventParameter(); }; float vol, // Linear volume to set fadervol; // Logarithmic volume to set (by fader throw) }; class SetMasterOutVolumeEvent : public Event { public: EVT_DEFINE(SetMasterOutVolumeEvent,T_EV_SetMasterOutVolume); virtual void Recycle() { vol = -1.; fadervol = -1.; Event::Recycle(); }; virtual void operator = (const Event &src) { SetMasterOutVolumeEvent &s = (SetMasterOutVolumeEvent &) src; vol = s.vol; fadervol = s.fadervol; }; virtual int GetNumParams() { return 2; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter("vol",FWEELIN_GETOFS(vol),T_float); case 1: return EventParameter("fadervol",FWEELIN_GETOFS(fadervol),T_float); } return EventParameter(); }; float vol, // Linear volume to set fadervol; // Logarithmic volume to set (by fader throw) }; class SetInVolumeEvent : public Event { public: EVT_DEFINE(SetInVolumeEvent,T_EV_SetInVolume); virtual void Recycle() { input = 1; vol = -1.; fadervol = -1.; Event::Recycle(); }; virtual void operator = (const Event &src) { SetInVolumeEvent &s = (SetInVolumeEvent &) src; input = s.input; vol = s.vol; fadervol = s.fadervol; }; virtual int GetNumParams() { return 3; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter("input",FWEELIN_GETOFS(input),T_int); case 1: return EventParameter("vol",FWEELIN_GETOFS(vol),T_float); case 2: return EventParameter("fadervol",FWEELIN_GETOFS(fadervol),T_float); } return EventParameter(); }; int input; // Number of input to change volume for float vol, // Linear volume to set fadervol; // Logarithmic volume to set (by fader throw) }; class ToggleInputRecordEvent : public Event { public: EVT_DEFINE(ToggleInputRecordEvent,T_EV_ToggleInputRecord); virtual void operator = (const Event &src) { ToggleInputRecordEvent &s = (ToggleInputRecordEvent &) src; input = s.input; }; virtual int GetNumParams() { return 1; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter("input",FWEELIN_GETOFS(input),T_int); } return EventParameter(); }; int input; // Number of input to toggle for recording }; class SetMidiEchoPortEvent : public Event { public: EVT_DEFINE(SetMidiEchoPortEvent,T_EV_SetMidiEchoPort); virtual void operator = (const Event &src) { SetMidiEchoPortEvent &s = (SetMidiEchoPortEvent &) src; echoport = s.echoport; }; virtual int GetNumParams() { return 1; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter("echoport",FWEELIN_GETOFS(echoport),T_int); } return EventParameter(); }; int echoport; // Port # to echo MIDI events to or 0 for disable echo }; class SetMidiEchoChannelEvent : public Event { public: EVT_DEFINE(SetMidiEchoChannelEvent,T_EV_SetMidiEchoChannel); virtual void operator = (const Event &src) { SetMidiEchoChannelEvent &s = (SetMidiEchoChannelEvent &) src; echochannel = s.echochannel; }; virtual int GetNumParams() { return 1; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter("echochannel",FWEELIN_GETOFS(echochannel),T_int); } return EventParameter(); }; int echochannel; // Override MIDI channel for MIDI event echo // (-1 to leave as is) }; class AdjustMidiTransposeEvent : public Event { public: EVT_DEFINE(AdjustMidiTransposeEvent,T_EV_AdjustMidiTranspose); virtual void operator = (const Event &src) { AdjustMidiTransposeEvent &s = (AdjustMidiTransposeEvent &) src; adjust = s.adjust; }; virtual int GetNumParams() { return 1; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter("adjust",FWEELIN_GETOFS(adjust),T_int); } return EventParameter(); }; int adjust; // Number of semitones to add to MIDI transpose }; class FluidSynthEnableEvent : public Event { public: EVT_DEFINE(FluidSynthEnableEvent,T_EV_FluidSynthEnable); virtual void operator = (const Event &src) { FluidSynthEnableEvent &s = (FluidSynthEnableEvent &) src; enable = s.enable; }; virtual int GetNumParams() { return 1; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter("enable",FWEELIN_GETOFS(enable),T_char); } return EventParameter(); }; char enable; // FluidSynth enabled? }; class SetMidiTuningEvent : public Event { public: EVT_DEFINE(SetMidiTuningEvent,T_EV_SetMidiTuning); virtual void Recycle() { tuning = 0; Event::Recycle(); }; virtual void operator = (const Event &src) { SetMidiTuningEvent &s = (SetMidiTuningEvent &) src; tuning = s.tuning; }; virtual int GetNumParams() { return 1; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter("tuning",FWEELIN_GETOFS(tuning),T_int); } return EventParameter(); }; int tuning; // New offset of 0 position for pitch bender- // shifts whole pitch bend by this value }; class SetTriggerVolumeEvent : public Event { public: EVT_DEFINE(SetTriggerVolumeEvent,T_EV_SetTriggerVolume); virtual void operator = (const Event &src) { SetTriggerVolumeEvent &s = (SetTriggerVolumeEvent &) src; index = s.index; vol = s.vol; }; virtual int GetNumParams() { return 2; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter("loopid",FWEELIN_GETOFS(index),T_int); case 1: return EventParameter("vol",FWEELIN_GETOFS(vol),T_float); } return EventParameter(); }; int index; // Index of loop to set trigger volume for float vol; // New trigger volume }; class SlideLoopAmpEvent : public Event { public: EVT_DEFINE(SlideLoopAmpEvent,T_EV_SlideLoopAmp); virtual void operator = (const Event &src) { SlideLoopAmpEvent &s = (SlideLoopAmpEvent &) src; index = s.index; slide = s.slide; }; virtual int GetNumParams() { return 2; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter("loopid",FWEELIN_GETOFS(index),T_int); case 1: return EventParameter("slide",FWEELIN_GETOFS(slide),T_float); } return EventParameter(); }; int index; // Index of loop to slide amplitude for float slide; // Change in speed of slide }; class SetLoopAmpEvent : public Event { public: EVT_DEFINE(SetLoopAmpEvent,T_EV_SetLoopAmp); virtual void operator = (const Event &src) { SetLoopAmpEvent &s = (SetLoopAmpEvent &) src; index = s.index; amp = s.amp; }; virtual int GetNumParams() { return 2; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter("loopid",FWEELIN_GETOFS(index),T_int); case 1: return EventParameter("amp",FWEELIN_GETOFS(amp),T_float); } return EventParameter(); }; int index; // Index of loop to set amplitude for float amp; // Amplitude to set loop at }; class AdjustLoopAmpEvent : public Event { public: EVT_DEFINE(AdjustLoopAmpEvent,T_EV_AdjustLoopAmp); virtual void operator = (const Event &src) { AdjustLoopAmpEvent &s = (AdjustLoopAmpEvent &) src; index = s.index; ampfactor = s.ampfactor; }; virtual int GetNumParams() { return 2; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter("loopid",FWEELIN_GETOFS(index),T_int); case 1: return EventParameter("ampfactor",FWEELIN_GETOFS(ampfactor),T_float); } return EventParameter(); }; int index; // Index of loop to adjust amplitude for float ampfactor; // Factor to multiply loop amplitudesby }; class TriggerLoopEvent : public Event { public: EVT_DEFINE(TriggerLoopEvent,T_EV_TriggerLoop); virtual void Recycle() { index = 0; vol = 1.0; engage = -1; shot = 0; od = 0; od_fb = 0; Event::Recycle(); }; virtual void operator = (const Event &src) { TriggerLoopEvent &s = (TriggerLoopEvent &) src; index = s.index; vol = s.vol; engage = s.engage; shot = s.shot; od = s.od; od_fb = s.od_fb; }; virtual int GetNumParams() { return 6; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter("loopid",FWEELIN_GETOFS(index),T_int); case 1: return EventParameter("engage",FWEELIN_GETOFS(engage),T_int); case 2: return EventParameter("shot",FWEELIN_GETOFS(shot),T_char); case 3: return EventParameter("vol",FWEELIN_GETOFS(vol),T_float); case 4: return EventParameter("overdub",FWEELIN_GETOFS(od),T_char); case 5: return EventParameter("overdubfeedback",FWEELIN_GETOFS(od_fb),T_variableref); } return EventParameter(); }; int index; // Index of loop int engage; // -1 is the default behavior, where each trigger-loop // event toggles between rec/play and off // 0 forces the loop to off // 1 forces the loop to on char shot; // Nonzero if we should only play thru once- no loop float vol; // Volume of trigger char od; // Nonzero if we should trigger an overdub UserVariable *od_fb; // Variable which holds overdub feedback- can be continuously varied }; class MoveLoopEvent : public Event { public: EVT_DEFINE(MoveLoopEvent,T_EV_MoveLoop); virtual void operator = (const Event &src) { MoveLoopEvent &s = (MoveLoopEvent &) src; oldloopid = s.oldloopid; newloopid = s.newloopid; }; virtual int GetNumParams() { return 2; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter("oldloopid",FWEELIN_GETOFS(oldloopid),T_int); case 1: return EventParameter("newloopid",FWEELIN_GETOFS(newloopid),T_int); } return EventParameter(); }; int oldloopid, // Old index of loop newloopid; // New index of loop }; class EraseLoopEvent : public Event { public: EVT_DEFINE(EraseLoopEvent,T_EV_EraseLoop); virtual void operator = (const Event &src) { EraseLoopEvent &s = (EraseLoopEvent &) src; index = s.index; }; virtual int GetNumParams() { return 1; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter("loopid",FWEELIN_GETOFS(index),T_int); } return EventParameter(); }; int index; // Index of loop }; class EraseAllLoopsEvent : public Event { public: EVT_DEFINE(EraseAllLoopsEvent,T_EV_EraseAllLoops); }; class EraseSelectedLoopsEvent : public Event { public: EVT_DEFINE(EraseSelectedLoopsEvent,T_EV_EraseSelectedLoops); virtual void Recycle() { setid = 0; Event::Recycle(); }; virtual void operator = (const Event &src) { EraseSelectedLoopsEvent &s = (EraseSelectedLoopsEvent &) src; setid = s.setid; }; virtual int GetNumParams() { return 1; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter("setid",FWEELIN_GETOFS(setid),T_int); } return EventParameter(); }; int setid; // ID # of the selection set to work on }; class SlideLoopAmpStopAllEvent : public Event { public: EVT_DEFINE(SlideLoopAmpStopAllEvent,T_EV_SlideLoopAmpStopAll); }; class ToggleDiskOutputEvent : public Event { public: EVT_DEFINE(ToggleDiskOutputEvent,T_EV_ToggleDiskOutput); }; class SetAutoLoopSavingEvent : public Event { public: EVT_DEFINE(SetAutoLoopSavingEvent,T_EV_SetAutoLoopSaving); virtual void operator = (const Event &src) { SetAutoLoopSavingEvent &s = (SetAutoLoopSavingEvent &) src; save = s.save; }; virtual int GetNumParams() { return 1; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter("save",FWEELIN_GETOFS(save),T_char); } return EventParameter(); }; char save; // Are we autosaving loops? }; class SaveLoopEvent : public Event { public: EVT_DEFINE(SaveLoopEvent,T_EV_SaveLoop); virtual void operator = (const Event &src) { SaveLoopEvent &s = (SaveLoopEvent &) src; index = s.index; }; virtual int GetNumParams() { return 1; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter("loopid",FWEELIN_GETOFS(index),T_int); } return EventParameter(); }; int index; // Index of loop to save }; class SaveNewSceneEvent : public Event { public: EVT_DEFINE(SaveNewSceneEvent,T_EV_SaveNewScene); }; class SaveCurrentSceneEvent : public Event { public: EVT_DEFINE(SaveCurrentSceneEvent,T_EV_SaveCurrentScene); }; class SetLoadLoopIdEvent : public Event { public: EVT_DEFINE(SetLoadLoopIdEvent,T_EV_SetLoadLoopId); virtual void operator = (const Event &src) { SetLoadLoopIdEvent &s = (SetLoadLoopIdEvent &) src; index = s.index; }; virtual int GetNumParams() { return 1; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter("loopid",FWEELIN_GETOFS(index),T_int); } return EventParameter(); }; int index; // Index to load loops into }; class SetDefaultLoopPlacementEvent : public Event { public: EVT_DEFINE_NO_CONSTR(SetDefaultLoopPlacementEvent, T_EV_SetDefaultLoopPlacement); SetDefaultLoopPlacementEvent() : looprange(0,0) { Recycle(); }; virtual void Recycle() { looprange = Range(0,0); Event::Recycle(); }; virtual void operator = (const Event &src) { SetDefaultLoopPlacementEvent &s = (SetDefaultLoopPlacementEvent &) src; looprange = s.looprange; }; virtual int GetNumParams() { return 1; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter("looprange",FWEELIN_GETOFS(looprange),T_range); } return EventParameter(); }; Range looprange; // Range of loop IDs to be used when others are full }; class BrowserMoveToItemEvent : public Event { public: EVT_DEFINE(BrowserMoveToItemEvent,T_EV_BrowserMoveToItem); virtual void Recycle() { browserid = -1; adjust = 0; jumpadjust = 0; Event::Recycle(); }; virtual void operator = (const Event &src) { BrowserMoveToItemEvent &s = (BrowserMoveToItemEvent &) src; browserid = s.browserid; adjust = s.adjust; jumpadjust = s.jumpadjust; }; virtual int GetNumParams() { return 3; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter("browserid",FWEELIN_GETOFS(browserid),T_int); case 1: return EventParameter("adjust",FWEELIN_GETOFS(adjust),T_int); case 2: return EventParameter("jumpadjust",FWEELIN_GETOFS(jumpadjust),T_int); } return EventParameter(); }; int browserid; // Display ID of browser int adjust; // Move fwd/back by adjust items int jumpadjust; // Jump fwd/back by jumpadjust divisions }; class BrowserMoveToItemAbsoluteEvent : public Event { public: EVT_DEFINE(BrowserMoveToItemAbsoluteEvent,T_EV_BrowserMoveToItemAbsolute); virtual void Recycle() { browserid = -1; idx = 0; Event::Recycle(); }; virtual void operator = (const Event &src) { BrowserMoveToItemAbsoluteEvent &s = (BrowserMoveToItemAbsoluteEvent &) src; browserid = s.browserid; idx = s.idx; }; virtual int GetNumParams() { return 2; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter("browserid",FWEELIN_GETOFS(browserid),T_int); case 1: return EventParameter("idx",FWEELIN_GETOFS(idx),T_int); } return EventParameter(); }; int browserid; // Display ID of browser int idx; // Index to move to (absolute from beginning of list) }; class BrowserSelectItemEvent : public Event { public: EVT_DEFINE(BrowserSelectItemEvent,T_EV_BrowserSelectItem); virtual void Recycle() { browserid = -1; Event::Recycle(); }; virtual void operator = (const Event &src) { BrowserSelectItemEvent &s = (BrowserSelectItemEvent &) src; browserid = s.browserid; }; virtual int GetNumParams() { return 1; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter("browserid",FWEELIN_GETOFS(browserid),T_int); } return EventParameter(); }; int browserid; // Display ID of browser }; class BrowserRenameItemEvent : public Event { public: EVT_DEFINE(BrowserRenameItemEvent,T_EV_BrowserRenameItem); virtual void Recycle() { browserid = -1; Event::Recycle(); }; virtual void operator = (const Event &src) { BrowserRenameItemEvent &s = (BrowserRenameItemEvent &) src; browserid = s.browserid; }; virtual int GetNumParams() { return 1; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter("browserid",FWEELIN_GETOFS(browserid),T_int); } return EventParameter(); }; int browserid; // Display ID of browser }; class BrowserItemBrowsedEvent : public Event { public: EVT_DEFINE(BrowserItemBrowsedEvent,T_EV_BrowserItemBrowsed); virtual void Recycle() { browserid = -1; Event::Recycle(); }; virtual void operator = (const Event &src) { BrowserItemBrowsedEvent &s = (BrowserItemBrowsedEvent &) src; browserid = s.browserid; }; virtual int GetNumParams() { return 1; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter("browserid",FWEELIN_GETOFS(browserid),T_int); } return EventParameter(); }; int browserid; // Display ID of browser }; class PatchBrowserMoveToBankEvent : public Event { public: EVT_DEFINE(PatchBrowserMoveToBankEvent,T_EV_PatchBrowserMoveToBank); virtual void Recycle() { direction = 1; Event::Recycle(); }; virtual void operator = (const Event &src) { PatchBrowserMoveToBankEvent &s = (PatchBrowserMoveToBankEvent &) src; direction = s.direction; }; virtual int GetNumParams() { return 1; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter("direction",FWEELIN_GETOFS(direction),T_int); } return EventParameter(); }; int direction; // Direction to move (+1/-1 next/previous) }; class PatchBrowserMoveToBankByIndexEvent : public Event { public: EVT_DEFINE(PatchBrowserMoveToBankByIndexEvent, T_EV_PatchBrowserMoveToBankByIndex); virtual void Recycle() { index = 0; Event::Recycle(); }; virtual void operator = (const Event &src) { PatchBrowserMoveToBankByIndexEvent &s = (PatchBrowserMoveToBankByIndexEvent &) src; index = s.index; }; virtual int GetNumParams() { return 1; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter("index",FWEELIN_GETOFS(index),T_int); } return EventParameter(); }; int index; // Index of patchbank to choose }; class RenameLoopEvent : public Event { public: EVT_DEFINE(RenameLoopEvent,T_EV_RenameLoop); virtual void Recycle() { loopid = 0; in = 0; Event::Recycle(); }; virtual void operator = (const Event &src) { RenameLoopEvent &s = (RenameLoopEvent &) src; loopid = s.loopid; in = s.in; }; virtual int GetNumParams() { return 2; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter("loopid",FWEELIN_GETOFS(loopid),T_int); case 1: return EventParameter("in",FWEELIN_GETOFS(in),T_char); } return EventParameter(); }; int loopid; // Loop ID to rename char in; // Rename in loop tray (0) or layout (1) }; class SelectPulseEvent : public Event { public: EVT_DEFINE(SelectPulseEvent,T_EV_SelectPulse); virtual void operator = (const Event &src) { SelectPulseEvent &s = (SelectPulseEvent &) src; pulse = s.pulse; }; virtual int GetNumParams() { return 1; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter("pulse",FWEELIN_GETOFS(pulse),T_int); } return EventParameter(); }; int pulse; // Index of pulse }; class DeletePulseEvent : public Event { public: EVT_DEFINE(DeletePulseEvent,T_EV_DeletePulse); virtual void operator = (const Event &src) { DeletePulseEvent &s = (DeletePulseEvent &) src; pulse = s.pulse; }; virtual int GetNumParams() { return 1; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter("pulse",FWEELIN_GETOFS(pulse),T_int); } return EventParameter(); }; int pulse; // Index of pulse }; class TapPulseEvent : public Event { public: EVT_DEFINE(TapPulseEvent,T_EV_TapPulse); virtual void operator = (const Event &src) { TapPulseEvent &s = (TapPulseEvent &) src; pulse = s.pulse; newlen = s.newlen; }; virtual int GetNumParams() { return 2; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter("pulse",FWEELIN_GETOFS(pulse),T_int); case 1: return EventParameter("newlen",FWEELIN_GETOFS(newlen),T_char); } return EventParameter(); }; int pulse; // Index of pulse char newlen; // Nonzero to redefine pulse length or create new pulse }; class SwitchMetronomeEvent : public Event { public: EVT_DEFINE(SwitchMetronomeEvent,T_EV_SwitchMetronome); virtual void operator = (const Event &src) { SwitchMetronomeEvent &s = (SwitchMetronomeEvent &) src; pulse = s.pulse; metronome = s.metronome; }; virtual int GetNumParams() { return 2; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter("pulse",FWEELIN_GETOFS(pulse),T_int); case 1: return EventParameter("metronome",FWEELIN_GETOFS(metronome),T_char); } return EventParameter(); }; int pulse; // Index of pulse char metronome; // Metronome active? }; class SetSyncTypeEvent : public Event { public: EVT_DEFINE(SetSyncTypeEvent,T_EV_SetSyncType); virtual void operator = (const Event &src) { SetSyncTypeEvent &s = (SetSyncTypeEvent &) src; stype = s.stype; }; virtual int GetNumParams() { return 1; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter("type",FWEELIN_GETOFS(stype),T_char); } return EventParameter(); }; char stype; // Nonzero for beat sync, zero for bar sync }; class SetSyncSpeedEvent : public Event { public: EVT_DEFINE(SetSyncSpeedEvent,T_EV_SetSyncSpeed); virtual void operator = (const Event &src) { SetSyncSpeedEvent &s = (SetSyncSpeedEvent &) src; sspd = s.sspd; }; virtual int GetNumParams() { return 1; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter("speed",FWEELIN_GETOFS(sspd),T_int); } return EventParameter(); }; int sspd; // Number of external transport beats/bars per internal pulse }; class SetMidiSyncEvent : public Event { public: EVT_DEFINE(SetMidiSyncEvent,T_EV_SetMidiSync); virtual void operator = (const Event &src) { SetMidiSyncEvent &s = (SetMidiSyncEvent &) src; midisync = s.midisync; }; virtual int GetNumParams() { return 1; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter("midisync",FWEELIN_GETOFS(midisync),T_int); } return EventParameter(); }; int midisync; // Nonzero to transmit MIDI sync, zero for no MIDI sync }; class ToggleSelectLoopEvent : public Event { public: EVT_DEFINE(ToggleSelectLoopEvent,T_EV_ToggleSelectLoop); virtual void operator = (const Event &src) { ToggleSelectLoopEvent &s = (ToggleSelectLoopEvent &) src; setid = s.setid; loopid = s.loopid; }; virtual int GetNumParams() { return 2; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter("setid",FWEELIN_GETOFS(setid),T_int); case 1: return EventParameter("loopid",FWEELIN_GETOFS(loopid),T_int); } return EventParameter(); }; int setid, // ID # of the selection set in which to toggle the loop loopid; // ID # of loop to toggle }; class SelectOnlyPlayingLoopsEvent : public Event { public: EVT_DEFINE(SelectOnlyPlayingLoopsEvent,T_EV_SelectOnlyPlayingLoops); virtual void operator = (const Event &src) { SelectOnlyPlayingLoopsEvent &s = (SelectOnlyPlayingLoopsEvent &) src; setid = s.setid; playing = s.playing; }; virtual int GetNumParams() { return 2; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter("setid",FWEELIN_GETOFS(setid),T_int); case 1: return EventParameter("playing",FWEELIN_GETOFS(playing),T_char); } return EventParameter(); }; int setid; // ID # of the selection set to work on char playing; // Nonzero if we should select only those loops currently // playing-- zero if we should select only those loops // currently idle }; class SelectAllLoopsEvent : public Event { public: EVT_DEFINE(SelectAllLoopsEvent,T_EV_SelectAllLoops); virtual void operator = (const Event &src) { SelectAllLoopsEvent &s = (SelectAllLoopsEvent &) src; setid = s.setid; select = s.select; }; virtual int GetNumParams() { return 2; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter("setid",FWEELIN_GETOFS(setid),T_int); case 1: return EventParameter("select",FWEELIN_GETOFS(select),T_char); } return EventParameter(); }; int setid; // ID # of the selection set to work on char select; // Nonzero to select/zero to unselect all loops }; class InvertSelectionEvent : public Event { public: EVT_DEFINE(InvertSelectionEvent,T_EV_InvertSelection); virtual void operator = (const Event &src) { InvertSelectionEvent &s = (InvertSelectionEvent &) src; setid = s.setid; }; virtual int GetNumParams() { return 1; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter("setid",FWEELIN_GETOFS(setid),T_int); } return EventParameter(); }; int setid; // ID # of the selection set to invert (select all other loops) }; class CreateSnapshotEvent : public Event { public: EVT_DEFINE(CreateSnapshotEvent,T_EV_CreateSnapshot); virtual void Recycle() { snapid = 0; Event::Recycle(); }; virtual void operator = (const Event &src) { CreateSnapshotEvent &s = (CreateSnapshotEvent &) src; snapid = s.snapid; }; virtual int GetNumParams() { return 1; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter("snapid",FWEELIN_GETOFS(snapid),T_int); } return EventParameter(); }; int snapid; // Create and store snapshot #snapid }; class RenameSnapshotEvent : public Event { public: EVT_DEFINE(RenameSnapshotEvent,T_EV_RenameSnapshot); virtual void Recycle() { snapid = 0; Event::Recycle(); }; virtual void operator = (const Event &src) { RenameSnapshotEvent &s = (RenameSnapshotEvent &) src; snapid = s.snapid; }; virtual int GetNumParams() { return 1; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter("snapid",FWEELIN_GETOFS(snapid),T_int); } return EventParameter(); }; int snapid; // Rename snapshot #snapid }; class TriggerSnapshotEvent : public Event { public: EVT_DEFINE(TriggerSnapshotEvent,T_EV_TriggerSnapshot); virtual void Recycle() { snapid = 0; Event::Recycle(); }; virtual void operator = (const Event &src) { TriggerSnapshotEvent &s = (TriggerSnapshotEvent &) src; snapid = s.snapid; }; virtual int GetNumParams() { return 1; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter("snapid",FWEELIN_GETOFS(snapid),T_int); } return EventParameter(); }; int snapid; // Trigger snapshot #snapid }; class TriggerSelectedLoopsEvent : public Event { public: EVT_DEFINE(TriggerSelectedLoopsEvent,T_EV_TriggerSelectedLoops); virtual void Recycle() { setid = 0; vol = 1.0; toggleloops = 0; Event::Recycle(); }; virtual void operator = (const Event &src) { TriggerSelectedLoopsEvent &s = (TriggerSelectedLoopsEvent &) src; setid = s.setid; vol = s.vol; toggleloops = s.toggleloops; }; virtual int GetNumParams() { return 3; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter("setid",FWEELIN_GETOFS(setid),T_int); case 1: return EventParameter("vol",FWEELIN_GETOFS(vol),T_float); case 2: return EventParameter("toggleloops",FWEELIN_GETOFS(toggleloops),T_char); } return EventParameter(); }; int setid; // ID # of the selection set to work on float vol; // Volume at which to trigger selected loops char toggleloops; // Nonzero to toggle loops, zero to force active }; class SetSelectedLoopsTriggerVolumeEvent : public Event { public: EVT_DEFINE(SetSelectedLoopsTriggerVolumeEvent, T_EV_SetSelectedLoopsTriggerVolume); virtual void Recycle() { setid = 0; vol = 1.0; Event::Recycle(); }; virtual void operator = (const Event &src) { SetSelectedLoopsTriggerVolumeEvent &s = (SetSelectedLoopsTriggerVolumeEvent &) src; setid = s.setid; vol = s.vol; }; virtual int GetNumParams() { return 2; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter("setid",FWEELIN_GETOFS(setid),T_int); case 1: return EventParameter("vol",FWEELIN_GETOFS(vol),T_float); } return EventParameter(); }; int setid; // ID # of the selection set to work on float vol; // Trigger volume to set for loops }; class AdjustSelectedLoopsAmpEvent : public Event { public: EVT_DEFINE(AdjustSelectedLoopsAmpEvent, T_EV_AdjustSelectedLoopsAmp); virtual void Recycle() { setid = 0; ampfactor = 1.0; Event::Recycle(); }; virtual void operator = (const Event &src) { AdjustSelectedLoopsAmpEvent &s = (AdjustSelectedLoopsAmpEvent &) src; setid = s.setid; ampfactor = s.ampfactor; }; virtual int GetNumParams() { return 2; }; virtual EventParameter GetParam(int n) { switch (n) { case 0: return EventParameter("setid",FWEELIN_GETOFS(setid),T_int); case 1: return EventParameter("ampfactor",FWEELIN_GETOFS(ampfactor),T_float); } return EventParameter(); }; int setid; // ID # of the selection set to work on float ampfactor; // Factor to multiply all loop amplitudes by }; class EndRecordEvent : public Event { public: EVT_DEFINE(EndRecordEvent,T_EV_EndRecord); // Nonzero if recording should be kept char keeprecord; }; // List refers to loops in memory or on disk- used by background save/load class LoopListEvent : public Event { public: EVT_DEFINE(LoopListEvent,T_EV_LoopList); virtual void Recycle() { l = 0; strcpy(l_filename,""); l_idx = 0; l_vol = 1.0; Event::Recycle(); }; Loop *l; // Loop // Filename of loop on disk // (note we have to copy the string) char l_filename[FWEELIN_OUTNAME_LEN]; int l_idx; // Index of loop in map float l_vol; // Volume to set loop to when loading }; class SceneMarkerEvent : public Event { public: EVT_DEFINE(SceneMarkerEvent,T_EV_SceneMarker); virtual void Recycle() { strcpy(s_filename,""); Event::Recycle(); }; char s_filename[FWEELIN_OUTNAME_LEN]; // Filename of scene on disk }; class PulseSyncEvent : public Event { public: EVT_DEFINE(PulseSyncEvent,T_EV_PulseSync); int syncidx; // If this sync is used-defined, this is the sync index // returned from AddSyncPos. If this sync is for the // downbeat, this parameter is -1. }; // TriggerSet is fired by TriggerMap whenever a change is made to the map // The LoopTray and potentially others listen for changes to the TriggerMap class TriggerSetEvent : public Event { public: EVT_DEFINE(TriggerSetEvent,T_EV_TriggerSet); int idx; // On index 'idx' Loop *nw; // ..we now have 'nw' }; // Consider making EventListenerItem a Preallocated type to improve performance // when adding/removing listeners-- this will happen more often now that // PulseSyncEvent and other BMG type tasks are being merged into EMG class EventListenerItem { public: EventListenerItem(EventListener *callwhom, EventProducer *eventsfrom, EventType oftype, char block_self_calls) : callwhom(callwhom), eventsfrom(eventsfrom), oftype(oftype), block_self_calls(block_self_calls), next(0) {}; // Call this listener.. EventListener *callwhom; // When events from this event producer.. EventProducer *eventsfrom; // And this type.. are produced EventType oftype; // If nonzero, this flag stops a producer's events from calling itself // if that producer is also a listener char block_self_calls; // Pointer to next list item EventListenerItem *next; }; // EventManager manages generic event types // Allows for sending & receiving of events between different // parts of the application-- which is useful because those // parts can then be loosely coupled through extensible modular event // types // // Events can be sent immediately in the same thread they are broadcast // Or they can be sent through a dispatch thread // // Events can be sent through RT safe methods.. the dispatch is // optimized by event type, to eliminate lengthy searches for // eventlisteners class EventManager { public: EventManager () : events(0), threadgo(1) { printf("Start event manager.\n"); // Create listener structure.. int evnum = (int) EventType(T_EV_Last); listeners = new EventListenerItem *[evnum]; for (int i = 0; i < evnum; i++) listeners[i] = 0; pthread_mutex_init(&dispatch_thread_lock,0); pthread_mutex_init(&listener_list_lock,0); pthread_cond_init(&dispatch_ready,0); const static size_t STACKSIZE = 1024*128; pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setstacksize(&attr,STACKSIZE); printf("EVENT: Stacksize: %d.\n",STACKSIZE); // Start an event dispatch thread int ret = pthread_create(&dispatch_thread, &attr, run_dispatch_thread, static_cast(this)); if (ret != 0) { printf("(eventmanager) pthread_create failed, exiting"); exit(1); } SRMWRingBuffer_Writers::RegisterWriter(dispatch_thread); struct sched_param schp; memset(&schp, 0, sizeof(schp)); // Should event manager be SCHED_FIFO? good question! // not an easy question.. non RT event manager means we may // introduce a perceptible delay in events handled through // broadcast (not broadcastnow, as those go direct) // // but!.. currently EndRecordEvent does things that are not RT safe // so we can't have RT manager!! schp.sched_priority = sched_get_priority_max(SCHED_OTHER); //schp.sched_priority = sched_get_priority_min(SCHED_FIFO); if (pthread_setschedparam(dispatch_thread, SCHED_OTHER, &schp) != 0) { printf("EVENT: Can't set hi priority thread, will use regular!\n"); } }; ~EventManager(); // Event queue functions ** inline static Event *DeleteQueue(Event *first) { Event *cur = first; while (cur != 0) { Event *tmp = cur->next; cur->RTDelete(); cur = tmp; } return 0; } inline static void QueueEvent(Event **first, Event *nw) { Event *cur = *first; if (cur == 0) *first = nw; else { while (cur->next != 0) cur = cur->next; cur->next = nw; } }; inline static void RemoveEvent(Event **first, Event *prev, Event **cur) { Event *tmp = (*cur)->next; if (prev != 0) prev->next = tmp; else *first = tmp; (*cur)->RTDelete(); *cur = tmp; }; // Broadcast immediately! inline void BroadcastEventNow(Event *ev, EventProducer *source, char allowslowdelivery = 1, char deleteonsend = 1) { int evnum = (int) ev->GetType(); // Check if this event is slow-delivery only if (allowslowdelivery && Event::ett[evnum].slowdelivery) BroadcastEvent(ev,source); else { // Scan through the listeners to see who to call EventListenerItem *cur = listeners[evnum]; while (cur != 0) { if ((cur->eventsfrom == 0 && (!cur->block_self_calls || source != (void *) cur->callwhom)) || source == 0 || cur->eventsfrom == source) cur->callwhom->ReceiveEvent(ev,source); cur = cur->next; } // This event has been broadcast.. erase it!.. use RTDelete() if (deleteonsend) ev->RTDelete(); } }; // Broadcast through dispatch thread! // RT safe! -- so long as you allocate your event with RTNew() // *** Rewrite with one lockless ringbuffer for each broadcasting thread // EMG reads all ringbuffers void BroadcastEvent(Event *ev, EventProducer *source) { // printf("*** THREAD (BROADCAST): %li\n",pthread_self()); ev->from = source; //ev->time = mygettime(); QueueEvent(&events,ev); // Wake up the dispatch thread if (pthread_mutex_trylock (&dispatch_thread_lock) == 0) { pthread_cond_signal (&dispatch_ready); pthread_mutex_unlock (&dispatch_thread_lock); } else // Priority inversion printf("EVENT: WARNING: Priority inversion during event broadcast! Event '%s' may be lost!\n",Event::ett[(int) ev->GetType()].name); // printf("EVENT: SENT: %s!\n",Event::ett[(int) ev->GetType()].name); }; // Not RT safe, but threadsafe! // Listen for the given event (optionally from the given producer) and callme // when it occurs-- optionally, block calls from myself void ListenEvent(EventListener *callme, EventProducer *from, EventType type, char block_self_calls = 0) { EventListenerItem *nw = new EventListenerItem(callme,from,type, block_self_calls); pthread_mutex_lock(&listener_list_lock); // Add to the listeners list int evnum = (int) type; EventListenerItem *cur = listeners[evnum]; if (cur == 0) listeners[evnum] = nw; // That was easy, now we have 1 item else { while (cur->next != 0) cur = cur->next; cur->next = nw; // Link up the last item to new1 } pthread_mutex_unlock(&listener_list_lock); }; // Not RT safe! void UnlistenEvent(EventListener *callme, EventProducer *from, EventType type) { pthread_mutex_lock(&listener_list_lock); // Remove from the listeners list int evnum = (int) type; EventListenerItem *cur = listeners[evnum], *prev = 0; // Search for those listening to 'from' & 'type' while (cur != 0 && (cur->callwhom != callme || cur->eventsfrom != from)) { prev = cur; cur = cur->next; } if (cur != 0) { // Got it, unlink! if (prev != 0) prev->next = cur->next; else listeners[evnum] = cur->next; delete cur; } pthread_mutex_unlock(&listener_list_lock); }; static void *run_dispatch_thread (void *ptr) { EventManager *inst = static_cast(ptr); pthread_mutex_lock(&inst->dispatch_thread_lock); while (inst->threadgo) { // Scan through all events Event *cur = inst->events; while (cur != 0) { //printf("broadcast thread\n"); // Print time elapsed since broadcast //double dt = (mygettime()-cur->time) * 1000; //printf("Evt dispatch- dt: %2.2f ms\n",dt); if (cur->GetMgr() == 0) printf("EVENT: WARNING: Broadcast from RT nonRT event!!\n"); // printf("EVENT: DISPATCH: %s!\n",Event::ett[(int) cur->GetType()].name); inst->BroadcastEventNow(cur,cur->from,0,0); // Force delivery now, // don't erase til we // advance Event *tmp = cur->next; cur->RTDelete(); cur = tmp; } // Potentially a problem right here-- // If we get interrupted by RT which adds an event, // It will be lost right here when we empty queue // ** So, perhaps modify event queue so that we block in the case that // someone is accessing the queue (for ex, BroadcastEvent) // So the dispatch thread holds for other threads. Not a big deal. // ** Or, implement lockless ring buffer design here // Empty queue! inst->events = 0; // printf("EVENT: empty queue\n"); // Wait for wakeup pthread_cond_wait (&inst->dispatch_ready, &inst->dispatch_thread_lock); // printf("EVENT: WAKEUP!\n"); } printf("Event Manager: end dispatch thread\n"); pthread_mutex_unlock(&inst->dispatch_thread_lock); return 0; }; // For each event type, we store a list of listeners.. EventListenerItem **listeners; // Event queue- for calling listeners in lowpriority Event *events; SRMWRingBuffer *eq; pthread_t dispatch_thread; pthread_mutex_t dispatch_thread_lock, listener_list_lock; pthread_cond_t dispatch_ready; int threadgo; jack_ringbuffer_data_t asd; }; #endif fweelin-0.6/src/fweelin_fluidsynth.cc0000755000175000017500000001705111050104732016446 0ustar mercmerc#if USE_FLUIDSYNTH /* Copyright 2004-2008 Jan Pekau (JP Mercury) This file is part of Freewheeling. Freewheeling is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. Freewheeling is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Freewheeling. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include "fweelin_fluidsynth.h" #define fluid_sfont_iteration_start(_sf) (*(_sf)->iteration_start)(_sf) #define fluid_sfont_iteration_next(_sf,_pr) (*(_sf)->iteration_next)(_sf,_pr) #define fluid_preset_get_name(_preset) (*(_preset)->get_name)(_preset) #define fluid_preset_get_banknum(_preset) (*(_preset)->get_banknum)(_preset) #define fluid_preset_get_num(_preset) (*(_preset)->get_num)(_preset) void FluidSynthParam_Int::Send(fluid_settings_t *settings) { printf("FLUID: Setting parameter '%s' = '%d'\n",name,val); fluid_settings_setint(settings, name, val); }; void FluidSynthParam_Num::Send(fluid_settings_t *settings) { printf("FLUID: Setting parameter '%s' = '%f'\n",name,val); fluid_settings_setnum(settings, name, val); }; void FluidSynthParam_Str::Send(fluid_settings_t *settings) { printf("FLUID: Setting parameter '%s' = '%s'\n",name,val); fluid_settings_setstr(settings, name, val); }; FluidSynthProcessor::FluidSynthProcessor(Fweelin *app, char stereo) : Processor(app), stereo(stereo), enable(1) { nframes_t bufsz = app->getBUFSZ(); leftbuf = new sample_t[bufsz]; rightbuf = new sample_t[bufsz]; // Setup FluidSynth settings = new_fluid_settings(); { FluidSynthParam *cur = app->getCFG()->GetFluidParam(); while (cur != 0) { cur->Send(settings); cur = cur->next; } } // Set sampling rate fluid_settings_setnum(settings, "synth.sample-rate", app->getAUDIO()->get_srate()); // Create synth synth = new_fluid_synth(settings); // Set interpolation quality printf("FLUID: Setting interpolation quality: %d\n", app->getCFG()->GetFluidInterpolation()); fluid_synth_set_interp_method(synth,-1, app->getCFG()->GetFluidInterpolation()); // User-specified global fluidsynth tuning float tuning = app->getCFG()->GetFluidTuning(); if (tuning != 0.0) { printf("FLUID: Setting pitch tuning: %.2f cents\n", tuning); // Create tuning for each key in octave double pitches[12]; for (int i = 0; i < 12; i++) pitches[i] = tuning; fluid_synth_create_octave_tuning(synth, 0, 0, "DETUNE", pitches); // Select tuning for (int i = 0; i < MAX_MIDI_CHANNELS; i++) fluid_synth_select_tuning(synth, i, 0, 0); } else printf("FLUID: Using default tuning\n"); // Load soundfonts { FluidSynthSoundFont *cur = app->getCFG()->GetFluidFont(); while (cur != 0) { printf("FLUID: Loading SoundFont '%s'\n",cur->name); fluid_synth_sfload(synth,cur->name,1); cur = cur->next; } } app->getEMG()->ListenEvent(this,0,T_EV_FluidSynthEnable); }; FluidSynthProcessor::~FluidSynthProcessor() { app->getEMG()->UnlistenEvent(this,0,T_EV_FluidSynthEnable); delete_fluid_synth(synth); delete_fluid_settings(settings); delete[] leftbuf; delete[] rightbuf; }; void FluidSynthProcessor::process(char pre, nframes_t len, AudioBuffers *ab) { if (!pre) { // Map our output to the end of the external inputs ab->ins[0][ab->numins_ext] = leftbuf; if (stereo) ab->ins[1][ab->numins_ext] = rightbuf; else ab->ins[1][ab->numins_ext] = 0; if (enable) { // Run synth DSP fluid_synth_write_float(synth, len, leftbuf, 0, 1, rightbuf, 0, 1); if (!stereo) { // Mono, so fold the right channel into the left like pudding for (nframes_t l = 0; l < len; l++) leftbuf[l] = (leftbuf[l] + rightbuf[l]) / 2; } } else { // Silence, not enabled memset(leftbuf,0,sizeof(sample_t) * len); if (stereo) memset(rightbuf,0,sizeof(sample_t) * len); } } }; // Read new current patch from 'patches' and send patch change to synth void FluidSynthProcessor::SendPatchChange(PatchItem *p) { fluid_synth_program_select(synth, p->channel, p->id, p->bank, p->prog); }; // Sets up our internal patch list based on loaded soundfonts void FluidSynthProcessor::SetupPatches() { fluid_preset_t preset; PatchBrowser *br = (PatchBrowser *) app->getBROWSER(B_Patch); if (br != 0) { // Add FluidSynth patch bank int fluidchan = app->getCFG()->GetFluidChannel(); br->PB_AddBegin(new PatchBank(0,-1,0)); // Use port 0 for FluidSynth // Store patches int sfcnt = fluid_synth_sfcount(synth); for (int i = 0; i < sfcnt; i++) { fluid_sfont_t *curfont = fluid_synth_get_sfont(synth,i); fluid_sfont_iteration_start(curfont); while (fluid_sfont_iteration_next(curfont, &preset)) br->AddItem(new PatchItem(fluid_sfont_get_id(curfont), fluid_preset_get_banknum(&preset), fluid_preset_get_num(&preset), fluidchan, fluid_preset_get_name(&preset))); if (i+1 < sfcnt) { // End of soundfont- put in a divider br->AddItem(new BrowserDivision()); } } } }; void FluidSynthProcessor::ReceiveMIDIEvent(Event *ev) { FloConfig *fs = app->getCFG(); switch (ev->GetType()) { case T_EV_Input_MIDIController : if (enable) { MIDIControllerInputEvent *mcev = (MIDIControllerInputEvent *) ev; fluid_synth_cc(synth,app->getCFG()->GetFluidChannel(), mcev->ctrl,mcev->val); } break; case T_EV_Input_MIDIPitchBend : if (enable) { MIDIPitchBendInputEvent *mpev = (MIDIPitchBendInputEvent *) ev; fluid_synth_pitch_bend(synth,app->getCFG()->GetFluidChannel(), mpev->val + FLUIDSYNTH_PITCHBEND_CENTER); } break; case T_EV_Input_MIDIKey : if (enable) { MIDIKeyInputEvent *mkev = (MIDIKeyInputEvent *) ev; if (mkev->down) fluid_synth_noteon(synth, app->getCFG()->GetFluidChannel(), mkev->notenum+fs->transpose, mkev->vel); else fluid_synth_noteoff(synth, app->getCFG()->GetFluidChannel(), mkev->notenum+fs->transpose); } break; default: break; } }; void FluidSynthProcessor::ReceiveEvent(Event *ev, EventProducer *from) { switch (ev->GetType()) { case T_EV_FluidSynthEnable : { FluidSynthEnableEvent *fev = (FluidSynthEnableEvent *) ev; // OK! if (CRITTERS) printf("FLUID: Received FluidSynthEnable (%s)\n", (fev->enable ? "on" : "off")); SetEnable(fev->enable); } break; default: break; } } #endif fweelin-0.6/src/fweelin_fluidsynth.h0000644000175000017500000000421311050104733016302 0ustar mercmerc#ifndef __FWEELIN_FLUIDSYNTH_H #define __FWEELIN_FLUIDSYNTH_H /* Copyright 2004-2008 Jan Pekau (JP Mercury) This file is part of Freewheeling. Freewheeling is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. Freewheeling is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Freewheeling. If not, see . */ #if USE_FLUIDSYNTH #include #include "fweelin_core_dsp.h" #include "fweelin_browser.h" // Whacky FluidSynth center of pitchbend is 0x2000 not 0 #define FLUIDSYNTH_PITCHBEND_CENTER 0x2000 // Integrated soft-synth based on libfluidsynth class FluidSynthProcessor : public Processor, public EventListener { friend class Fweelin; public: FluidSynthProcessor(Fweelin *app, char stereo); virtual ~FluidSynthProcessor(); virtual void process(char pre, nframes_t len, AudioBuffers *ab); virtual void ReceiveEvent(Event *ev, EventProducer *from); // Send a new patch to synth void SendPatchChange(PatchItem *p); // Receive MIDI events for synth void ReceiveMIDIEvent(Event *ev); // Enable/disable FluidSynth- if disabled, bypasses // processor stage to reduce CPU usage, but leaves memory allocated inline void SetEnable(char en) { // Preprocess audio for smoothing //dopreprocess(); this->enable = en; }; char GetEnable() { return enable; }; // Sets up browser patches based on loaded soundfonts void SetupPatches(); private: // Run FluidSynth in stereo? char stereo; // Left and right output buffers sample_t *leftbuf, *rightbuf; // And fluidsynth variables.. fluid_settings_t *settings; fluid_synth_t *synth; // Currently processing? char enable; }; #endif #endif fweelin-0.6/src/fweelin_logo.h0000755000175000017500000027505411050104733015071 0ustar mercmerc/* GIMP RGBA C-Source image dump (fweelin-logo.c) */ /* Copyright 2004-2008 Jan Pekau (JP Mercury) This file is part of Freewheeling. Freewheeling is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. Freewheeling is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Freewheeling. If not, see . */ static const struct { unsigned int width; unsigned int height; unsigned int bytes_per_pixel; /* 3:RGB, 4:RGBA */ unsigned char pixel_data[223 * 42 * 4 + 1]; } fweelin_logo = { 223, 42, 4, "\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1" "\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1" "\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1" "\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1" "\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1" "\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1" "\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1" "\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\2\0\0\0\2" "\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1" "\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" "\0\0\0\0\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1" "\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\1\0\0\0\1" "\0\0\0\1\0\0\0\1\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2" "\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1" "\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0\1" "\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\2\0\0\0\2" "\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\1" "\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1" "\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1" "\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1" "\0\0\0\1\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\1\0\0\0\1\0\0\0\1" "\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1" "\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\2\0\0\0\2\0\0\0\2" "\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\3\0\0\0\3\0\0\0\3\0\0\0\3" "\0\0\0\3\0\0\0\3\0\0\0\3\0\0\0\2\0\0\0\2\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1" "\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1" "\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\2\0\0\0\2" "\0\0\0\3\0\0\0\3\0\0\0\3\0\0\0\3\0\0\0\3\0\0\0\3\0\0\0\3\0\0\0\2\0\0\0\3" "\0\0\0\3\0\0\0\3\0\0\0\3\0\0\0\4\0\0\0\4\0\0\0\4\0\0\0\3\0\0\0\3\0\0\0\2" "\0\0\0\2\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\0" "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1" "\0\0\0\1\0\0\0\1\0\0\0\2\0\0\0\3\0\0\0\3\0\0\0\3\0\0\0\4\0\0\0\4\0\0\0\4" "\0\0\0\4\0\0\0\4\0\0\0\4\0\0\0\4\0\0\0\4\0\0\0\4\0\0\0\4\0\0\0\4\0\0\0\4" "\0\0\0\3\0\0\0\3\0\0\0\2\0\0\0\2\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1" "\0\0\0\1\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0\1\0\0\0\1" "\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\2\0\0\0\2\0\0\0\3\0\0\0\3" "\0\0\0\4\0\0\0\4\0\0\0\3\0\0\0\3\0\0\0\3\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2" "\0\0\0\3\0\0\0\3\0\0\0\3\0\0\0\3\0\0\0\3\0\0\0\3\0\0\0\3\0\0\0\3\0\0\0\3" "\0\0\0\2\0\0\0\3\0\0\0\3\0\0\0\3\0\0\0\3\0\0\0\4\0\0\0\4\0\0\0\4\0\0\0\4" "\0\0\0\5\0\0\0\5\0\0\0\5\0\0\0\6\0\0\0\7\0\0\0\7\0\0\0\7\0\0\0\7\0\0\0\6" "\0\0\0\5\0\0\0\4\0\0\0\3\0\0\0\2\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1" "\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1" "\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\2\0\0\0\3\0\0\0\4\0\0\0\5\0\0\0\6\0\0\0\6" "\0\0\0\7\0\0\0\7\0\0\0\7\0\0\0\6\0\0\0\6\0\0\0\5\0\0\0\6\0\0\0\6\0\0\0\7" "\0\0\0\10\0\0\0\10\0\0\0\10\0\0\0\10\0\0\0\7\0\0\0\6\0\0\0\5\0\0\0\4\0\0" "\0\2\0\0\0\2\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\0\0\0\0\0\0\0" "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\2\0\0" "\0\3\0\0\0\4\0\0\0\5\0\0\0\6\0\0\0\7\0\0\0\10\0\0\0\10\0\0\0\11\0\0\0\11" "\0\0\0\11\0\0\0\10\0\0\0\10\0\0\0\10\0\0\0\10\0\0\0\7\0\0\0\7\0\0\0\7\0\0" "\0\6\0\0\0\5\0\0\0\4\0\0\0\3\0\0\0\2\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0" "\0\1\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0\1\0\0\0\1\0\0" "\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\2\0\0\0\3\0\0\0\4\0\0\0\5\0\0\0\6\0\0" "\0\7\0\0\0\7\0\0\0\7\0\0\0\6\0\0\0\5\0\0\0\4\0\0\0\4\0\0\0\4\0\0\0\4\0\0" "\0\5\0\0\0\6\0\0\0\6\0\0\0\6\0\0\0\6\0\0\0\6\0\0\0\6\0\0\0\5\0\0\0\5\0\0" "\0\4\0\0\0\5\0\0\0\5\0\0\0\6\0\0\0\7\0\0\0\7\0\0\0\10\0\0\0\10\0\0\0\10\0" "\0\0\11\0\0\0\12\0\0\0\13\0\0\0\14\0\0\0\16\0\0\0\16\0\0\0\17\0\0\0\16\0" "\0\0\15\0\0\0\12\0\0\0\10\0\0\0\6\0\0\0\4\0\0\0\2\0\0\0\2\0\0\0\1\0\0\0\1" "\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0\1\0\0\0\1" "\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\2\0\0\0\3\0\0\0\5\0\0\0\7\0\0\0\12\0\0\0\14" "\0\0\0\15\0\0\0\16\0\0\0\16\0\0\0\15\0\0\0\14\0\0\0\13\0\0\0\13\0\0\0\14" "\0\0\0\15\0\0\0\16\0\0\0\17\0\0\0\20\0\0\0\20\0\0\0\17\0\0\0\16\0\0\0\14" "\0\0\0\12\0\0\0\7\0\0\0\4\0\0\0\3\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1" "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0\1\0\0\0\2" "\0\0\0\2\0\0\0\4\0\0\0\6\0\0\0\10\0\0\0\12\0\0\0\14\0\0\0\16\0\0\0\20\0\0" "\0\21\0\0\0\22\0\0\0\23\0\0\0\22\0\0\0\22\0\0\0\21\0\0\0\20\0\0\0\20\0\0" "\0\20\0\0\0\17\0\0\0\16\0\0\0\15\0\0\0\13\0\0\0\10\0\0\0\6\0\0\0\4\0\0\0" "\2\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\0\0\0\0\1\0\0\0" "\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0" "\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\0\0\0\0" "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0" "\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\2\0\0\0\3\0\0\0\4\0\0\0" "\7\0\0\0\11\0\0\0\13\0\0\0\15\0\0\0\16\0\0\0\16\0\0\0\16\0\0\0\14\0\0\0\13" "\0\0\0\11\0\0\0\11\0\0\0\11\0\0\0\12\0\0\0\13\0\0\0\14\0\0\0\15\0\0\0\16" "\0\0\0\16\0\0\0\15\0\0\0\14\0\0\0\13\0\0\0\12\0\0\0\11\0\0\0\12\0\0\0\13" "\0\0\0\14\0\0\0\16\0\0\0\17\0\0\0\20\0\0\0\21\0\0\0\21\0\0\0\23\0\0\0\24" "\0\0\0\27\0\0\0\31\0\0\0\33\0\0\0\35\0\0\0\35\0\0\0\34\0\0\0\31\0\0\0\25" "\0\0\0\20\0\0\0\14\0\0\0\10\0\0\0\5\0\0\0\3\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0" "\1\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0" "\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0" "\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0" "\1\0\0\0\2\0\0\0\4\0\0\0\6\0\0\0\12\0\0\0\16\0\0\0\23\0\0\0\27\0\0\0\32\0" "\0\0\34\0\0\0\34\0\0\0\32\0\0\0\31\0\0\0\27\0\0\0\27\0\0\0\30\0\0\0\31\0" "\0\0\34\0\0\0\36\0\0\0\37\0\0\0\40\0\0\0\36\0\0\0\33\0\0\0\27\0\0\0\22\0" "\0\0\15\0\0\0\10\0\0\0\5\0\0\0\3\0\0\0\2\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1" "\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1" "\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1" "\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1" "\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\3\0\0\0\4" "\0\0\0\7\0\0\0\13\0\0\0\17\0\0\0\23\0\0\0\27\0\0\0\33\0\0\0\36\0\0\0\40\0" "\0\0\"\0\0\0\"\0\0\0\"\0\0\0!\0\0\0\40\0\0\0\37\0\0\0\37\0\0\0\36\0\0\0\35" "\0\0\0\34\0\0\0\30\0\0\0\24\0\0\0\20\0\0\0\13\0\0\0\7\0\0\0\5\0\0\0\3\0\0" "\0\2\0\0\0\2\0\0\0\2\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0" "\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0" "\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0" "\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0" "\0\1\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\4\0\0\0\6\0\0\0\11\0\0\0\15\0\0\0\21\0" "\0\0\26\0\0\0\31\0\0\0\33\0\0\0\33\0\0\0\32\0\0\0\30\0\0\0\25\0\0\0\23\0" "\0\0\21\0\0\0\21\0\0\0\23\0\0\0\25\0\0\0\30\0\0\0\31\0\0\0\32\0\0\0\32\0" "\0\0\31\0\0\0\27\0\0\0\25\0\0\0\23\0\0\0\22\0\0\0\22\0\0\0\25\0\0\0\27\0" "\0\0\32\0\0\0\35\0\0\0\37\0\0\0\40\0\0\0!\0\0\0#\0\0\0%\0\0\0(\0\0\0,\0\0" "\0/\0\0\0""2\0\0\0""2\0\0\0""0\0\0\0+\0\0\0%\0\0\0\35\0\0\0\25\0\0\0\16\0" "\0\0\10\0\0\0\5\0\0\0\3\0\0\0\2\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0" "\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0" "\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0" "\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0" "\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\2\0\0\0\2\0\0\0\4\0\0\0\7\0\0\0\14\0" "\0\0\22\0\0\0\32\0\0\0\"\0\0\0(\0\0\0-\0\0\0""0\0\0\0""0\0\0\0.\0\0\0,\0" "\0\0*\0\0\0)\0\0\0*\0\0\0-\0\0\0""0\0\0\0""3\0\0\0""5\0\0\0""5\0\0\0""3\0" "\0\0.\0\0\0'\0\0\0\36\0\0\0\26\0\0\0\16\0\0\0\11\0\0\0\5\0\0\0\3\0\0\0\2" "\0\0\0\2\0\0\0\2\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1" "\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1" "\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1" "\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1" "\0\0\0\2\0\0\0\4\0\0\0\10\0\0\0\15\0\0\0\23\0\0\0\33\0\0\0#\0\0\0*\0\0\0" """0\0\0\0""5\0\0\0""8\0\0\0:\0\0\0;\0\0\0;\0\0\0""9\0\0\0""8\0\0\0""7\0\0" "\0""6\0\0\0""6\0\0\0""4\0\0\0""0\0\0\0+\0\0\0$\0\0\0\33\0\0\0\24\0\0\0\15" "\0\0\0\10\0\0\0\5\0\0\0\3\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\1\0\0\0\1\0\0\0\1" "\0\0\0\1\0\0\0\1\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2" "\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1" "\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\2\0\0\0\2\0\0\0\2" "\0\0\0\2\0\0\0\2\0\0\0\3\0\0\0\3\0\0\0\3\0\0\0\4\0\0\0\7\0\0\0\13\0\0\0\20" "\0\0\0\27\0\0\0\37\0\0\0&\0\0\0,\0\0\0""0\0\0\0""0\0\0\0.\0\0\0+\0\0\0&\0" "\0\0\"\0\0\0\40\0\0\0\40\0\0\0#\0\0\0'\0\0\0+\0\0\0.\0\0\0/\0\0\0/\0\0\0" "-\0\0\0*\0\0\0&\0\0\0\"\0\0\0!\0\0\0!\0\0\0%\0\0\0)\0\0\0/\0\0\0""3\0\0\0" """5\0\0\0""8\0\0\0""9\0\0\0<\0\0\0?\0\0\0D\0\0\0H\0\0\0M\0\0\0P\0\0\0P\0" "\0\0L\0\0\0E\0\0\0:\0\0\0.\0\0\0\"\0\0\0\26\0\0\0\16\0\0\0\10\0\0\0\5\0\0" "\0\3\0\0\0\2\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0" "\0\1\0\0\0\1\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0" "\0\2\0\0\0\2\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0" "\0\1\0\0\0\1\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0" "\0\2\0\0\0\2\0\0\0\4\0\0\0\7\0\0\0\14\0\0\0\24\0\0\0\36\0\0\0*\0\0\0""7\0" "\0\0A\0\0\0I\0\0\0M\0\0\0M\0\0\0K\0\0\0G\0\0\0D\0\0\0C\0\0\0E\0\0\0H\0\0" "\0M\0\0\0Q\0\0\0T\0\0\0S\0\0\0O\0\0\0G\0\0\0<\0\0\0.\0\0\0!\0\0\0\26\0\0" "\0\15\0\0\0\7\0\0\0\4\0\0\0\3\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0" "\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0" "\0\1\0\0\0\1\0\0\0\1\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0" "\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\1\0\0" "\0\1\0\0\0\1\0\0\0\1\0\0\0\2\0\0\0\4\0\0\0\7\0\0\0\15\0\0\0\25\0\0\0\37\0" "\0\0,\0\0\0""7\0\0\0B\0\0\0K\0\0\0R\0\0\0W\0\0\0Z\0\0\0[\0\0\0Z\0\0\0Y\0" "\0\0W\0\0\0V\0\0\0U\0\0\0T\0\0\0Q\0\0\0L\0\0\0C\0\0\0""9\0\0\0,\0\0\0\40" "\0\0\0\25\0\0\0\16\0\0\0\11\0\0\0\6\0\0\0\4\0\0\0\4\0\0\0\3\0\0\0\3\0\0\0" "\3\0\0\0\3\0\0\0\3\0\0\0\3\0\0\0\3\0\0\0\3\0\0\0\4\0\0\0\4\0\0\0\4\0\0\0" "\4\0\0\0\4\0\0\0\4\0\0\0\4\0\0\0\4\0\0\0\3\0\0\0\3\0\0\0\2\0\0\0\2\0\0\0" "\2\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\3\0\0\0\3\0\0\0" "\4\0\0\0\4\0\0\0\4\0\0\0\4\0\0\0\5\0\0\0\5\0\0\0\6\0\0\0\10\0\0\0\14\0\0" "\0\22\0\0\0\33\0\0\0&\0\0\0""1\0\0\0=\0\0\0F\0\0\0K\0\0\0L\0\0\0J\0\0\0D" "\0\0\0=\0\0\0""8\0\0\0""4\0\0\0""5\0\0\0""9\0\0\0?\0\0\0E\0\0\0I\0\0\0K\0" "\0\0K\0\0\0H\0\0\0C\0\0\0<\0\0\0""7\0\0\0""4\0\0\0""6\0\0\0;\0\0\0B\0\0\0" "I\0\0\0O\0\0\0S\0\0\0V\0\0\0Y\0\0\0\\\0\0\0`\0\0\0e\27\27\27j\\\\\\ossss" "\300\300\300rtttm]]]c<<\0\0\0" "P;;;^\301\301\301ivvvnRRRoXXXm\4\4\4i\0\0\0e\0\0\0c\0\0\0e\14\14\14iyyyo" "\250\250\250t\241\241\241w\203\203\203uYYYo\213\213\213c\303\303\303TTTT" "A\0\0\0/\0\0\0\37\0\0\0\23\0\0\0\13\0\0\0\7\0\0\0\5\0\0\0\4\0\0\0\4\0\0\0" "\4\0\0\0\4\0\0\0\4\0\0\0\4\0\0\0\4\0\0\0\4\0\0\0\3\0\0\0\3\0\0\0\2\0\0\0" "\2\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\2\0\0\0\2\0\0\0\3\0\0\0\4\0\0\0\4\0\0\0" "\4\0\0\0\4\0\0\0\4\0\0\0\4\0\0\0\4\0\0\0\4\0\0\0\4\0\0\0\4\0\0\0\4\0\0\0" "\4\0\0\0\3\0\0\0\3\0\0\0\2\0\0\0\2\0\0\0\1\0\0\0\3\0\0\0\5\0\0\0\12\0\0\0" "\23\0\0\0\37\0\0\0.\0\0\0@\33\33\33Q###`\"\"\"l###v\223\223\223|\316\316" "\316\177\320\320\320\200\255\255\255\200ZZZ~###|###{666z\213\213\213x\213" "\213\213t\\\\\\m\211\211\211a[[[S\0\0\0A\0\0\0""0\0\0\0!\0\0\0\26\0\0\0\17" "\0\0\0\13\0\0\0\11\0\0\0\10\0\0\0\7\0\0\0\7\0\0\0\7\0\0\0\6\0\0\0\6\0\0\0" "\6\0\0\0\6\0\0\0\6\0\0\0\7\0\0\0\10\0\0\0\11\0\0\0\12\0\0\0\12\0\0\0\11\0" "\0\0\11\0\0\0\10\0\0\0\7\0\0\0\6\0\0\0\4\0\0\0\4\0\0\0\3\0\0\0\3\0\0\0\2" "\0\0\0\3\0\0\0\3\0\0\0\4\0\0\0\5\0\0\0\6\0\0\0\7\0\0\0\10\0\0\0\11\0\0\0" "\11\0\0\0\11\0\0\0\12\0\0\0\12\0\0\0\14\0\0\0\16\0\0\0\24\0\0\0\34\0\0\0" ")\0\0\0""8\0\0\0I\25\25\25Y###e\243\243\243l\331\331\331n!!!k\"\"\"d\11\11" "\11[\0\0\0T\0\0\0P\0\0\0Q\0\0\0V\11\11\11^\200\200\200fOOOk\"\"\"n!!!m\37" "\37\37iyyyaaaaY\0\0\0R\0\0\0N\0\0\0P\0\0\0W\16\16\16`\252\252\252j\324\324" "\324q!!!w\31\31\31{\210\210\210~\177\177\177\201\211\211\211\205LLL\212\314" "\314\314\220\266\266\266\225\316\316\316\230\235\235\235\226\262\262\262" "\220\324\324\324\203\341\341\341q\203\203\203[\0\0\0E\0\0\0""0\0\0\0\37\0" "\0\0\24\0\0\0\15\0\0\0\10\0\0\0\6\0\0\0\4\0\0\0\3\0\0\0\3\0\0\0\2\0\0\0\2" "\0\0\0\3\0\0\0\3\0\0\0\4\0\0\0\5\0\0\0\6\0\0\0\7\0\0\0\10\0\0\0\11\0\0\0" "\11\0\0\0\11\0\0\0\10\0\0\0\7\0\0\0\6\0\0\0\5\0\0\0\4\0\0\0\3\0\0\0\3\0\0" "\0\3\0\0\0\3\0\0\0\4\0\0\0\4\0\0\0\5\0\0\0\7\0\0\0\7\0\0\0\10\0\0\0\10\0" "\0\0\10\0\0\0\7\0\0\0\7\0\0\0\7\0\0\0\10\0\0\0\13\0\0\0\21\0\0\0\34\0\0\0" "+\0\0\0?:::U\232\232\232l\341\341\341~\323\323\323\213\355\355\355\223\354" "\354\354\224\357\357\357\222\346\346\346\215\330\330\330\211\12\12\12\207" "888\211\236\236\236\216\343\343\343\223\240\240\240\231\223\223\223\233\257" "\257\257\230\312\312\312\220\305\305\305\201\275\275\275mvvvU\0\0\0>\0\0" "\0*\0\0\0\33\0\0\0\21\0\0\0\14\0\0\0\11\0\0\0\11\0\0\0\10\0\0\0\11\0\0\0" "\11\0\0\0\11\0\0\0\11\0\0\0\11\0\0\0\10\0\0\0\7\0\0\0\6\0\0\0\4\0\0\0\3\0" "\0\0\3\0\0\0\3\0\0\0\3\0\0\0\4\0\0\0\5\0\0\0\6\0\0\0\7\0\0\0\10\0\0\0\11" "\0\0\0\11\0\0\0\11\0\0\0\10\0\0\0\10\0\0\0\10\0\0\0\10\0\0\0\10\0\0\0\10" "\0\0\0\7\0\0\0\7\0\0\0\6\0\0\0\5\0\0\0\3\0\0\0\2\0\0\0\3\0\0\0\6\0\0\0\16" "\0\0\0\31\0\0\0*\1\1\1>\260\260\260V\352\352\352l\271\271\271\200\361\361" "\361\216\316\316\316\231\311\311\311\240XXX\244AAA\245UUU\245\340\340\340" "\243\317\317\317\241\331\331\331\240\273\273\273\237\253\253\253\235\254" "\254\254\230\272\272\272\217\275\275\275\200\354\354\354n\0\0\0X\0\0\0C\0" "\0\0""0\0\0\0#\0\0\0\31\0\0\0\24\0\0\0\21\0\0\0\20\0\0\0\17\0\0\0\16\0\0" "\0\16\0\0\0\15\0\0\0\14\0\0\0\14\0\0\0\15\0\0\0\16\0\0\0\17\0\0\0\21\0\0" "\0\23\0\0\0\24\0\0\0\24\0\0\0\23\0\0\0\22\0\0\0\20\0\0\0\16\0\0\0\14\0\0" "\0\11\0\0\0\7\0\0\0\6\0\0\0\5\0\0\0\5\0\0\0\5\0\0\0\6\0\0\0\10\0\0\0\12\0" "\0\0\14\0\0\0\16\0\0\0\20\0\0\0\22\0\0\0\23\0\0\0\23\0\0\0\24\0\0\0\25\0" "\0\0\26\0\0\0\31\0\0\0\37\0\0\0*\0\0\0""9111M\273\273\273b\340\340\340v\323" "\323\323\205\367\367\367\217\367\367\367\221\354\354\354\215\352\352\352" "\205\311\311\311{VVVs\0\0\0o\0\0\0pzzzv\303\303\303\177\346\346\346\211\361" "\361\361\217\357\357\357\222\360\360\360\221\360\360\360\213\311\311\311" "\202\345\345\345wZZZn\0\0\0j\0\0\0ltttu\320\320\320\200\317\317\317\214\352" "\352\352\225\361\361\361\233\334\334\334\237\277\277\277\242\304\304\304" "\246\335\335\335\251\332\332\332\256uuu\263\24\24\24\267\0\0\0\271\0\0\0" "\267\0\0\0\257\"\"\"\241666\214\331\331\331s\0\0\0Y\0\0\0A\0\0\0-\0\0\0\37" "\0\0\0\25\0\0\0\17\0\0\0\14\0\0\0\11\0\0\0\7\0\0\0\5\0\0\0\4\0\0\0\4\0\0" "\0\5\0\0\0\6\0\0\0\10\0\0\0\12\0\0\0\14\0\0\0\16\0\0\0\20\0\0\0\21\0\0\0" "\22\0\0\0\22\0\0\0\21\0\0\0\17\0\0\0\15\0\0\0\13\0\0\0\10\0\0\0\6\0\0\0\5" "\0\0\0\5\0\0\0\6\0\0\0\7\0\0\0\11\0\0\0\13\0\0\0\15\0\0\0\17\0\0\0\20\0\0" "\0\20\0\0\0\20\0\0\0\17\0\0\0\16\0\0\0\16\0\0\0\17\0\0\0\22\0\0\0\31\0\0" "\0%\0\0\0""8\0\0\0Q\301\301\301k\210\210\210\206'''\233\6\6\6\252ggg\263" "\250\250\250\265\177\177\177\264\265\265\265\260\357\357\357\254&&&\252\341" "\341\341\254mmm\260555\265\36\36\36\271\0\0\0\272\0\0\0\267\0\0\0\255,,," "\233\333\333\333\204\"\"\"i\0\0\0N\0\0\0""7\0\0\0&\0\0\0\32\0\0\0\24\0\0" "\0\22\0\0\0\21\0\0\0\21\0\0\0\22\0\0\0\23\0\0\0\23\0\0\0\23\0\0\0\22\0\0" "\0\20\0\0\0\16\0\0\0\13\0\0\0\11\0\0\0\7\0\0\0\6\0\0\0\6\0\0\0\7\0\0\0\10" "\0\0\0\12\0\0\0\15\0\0\0\17\0\0\0\21\0\0\0\21\0\0\0\22\0\0\0\21\0\0\0\21" "\0\0\0\20\0\0\0\20\0\0\0\20\0\0\0\20\0\0\0\20\0\0\0\17\0\0\0\16\0\0\0\13" "\0\0\0\11\0\0\0\6\0\0\0\4\0\0\0\4\0\0\0\10\0\0\0\21\0\0\0\37\0\0\0""5\2\2" "\2N\362\362\362k\332\332\332\205\20\20\20\234JJJ\255\36\36\36\271\12\12\12" "\300\0\0\0\304\0\0\0\306\0\0\0\305\20\20\20\304\12\12\12\303999\301;;;\300" "kkk\275GGG\270FFF\256UUU\236\343\343\343\212\236\236\236r\0\0\0Z\0\0\0E\0" "\0\0""5\0\0\0*\0\0\0$\0\0\0\40\0\0\0\36\0\0\0\35\0\0\0\34\0\0\0\33\0\0\0" "\32\0\0\0\30\0\0\0\30\0\0\0\31\0\0\0\33\0\0\0\35\0\0\0\40\0\0\0#\0\0\0%\0" "\0\0%\0\0\0%\0\0\0\"\0\0\0\37\0\0\0\33\0\0\0\27\0\0\0\23\0\0\0\17\0\0\0\14" "\0\0\0\12\0\0\0\11\0\0\0\12\0\0\0\15\0\0\0\20\0\0\0\24\0\0\0\30\0\0\0\34" "\0\0\0\37\0\0\0\"\0\0\0$\0\0\0%\0\0\0&\0\0\0&\0\0\0'\0\0\0)\0\0\0""0\0\0" "\0;\0\0\0Lwwwc\324\324\324{KKK\222```\243$$$\256iii\261bbb\256\220\220\220" "\246\357\357\357\233\350\350\350\223\6\6\6\216GGG\220\330\330\330\227yyy" "\241\213\213\213\252[[[\261VVV\264GGG\262;;;\253\207\207\207\241\365\365" "\365\225QQQ\213\0\0\0\207'''\212\347\347\347\223\245\245\245\237AAA\2538" "88\265???\274(((\300eee\303>>>\306\367\367\367\310\236\236\236\314\6\6\6" "\320\0\0\0\323\0\0\0\324\0\0\0\321\0\0\0\311\0\0\0\272\0\0\0\245\314\314" "\314\213\0\0\0o\0\0\0U\0\0\0?\0\0\0/\0\0\0$\0\0\0\34\0\0\0\26\0\0\0\21\0" "\0\0\16\0\0\0\13\0\0\0\11\0\0\0\11\0\0\0\12\0\0\0\14\0\0\0\20\0\0\0\24\0" "\0\0\30\0\0\0\34\0\0\0\37\0\0\0!\0\0\0\"\0\0\0\"\0\0\0\40\0\0\0\35\0\0\0" "\31\0\0\0\24\0\0\0\20\0\0\0\14\0\0\0\12\0\0\0\12\0\0\0\13\0\0\0\16\0\0\0" "\22\0\0\0\26\0\0\0\32\0\0\0\35\0\0\0\37\0\0\0\37\0\0\0\37\0\0\0\36\0\0\0" "\34\0\0\0\33\0\0\0\33\0\0\0\35\0\0\0$\0\0\0""2\0\0\0F\200\200\200a\370\370" "\370~XXX\233\0\0\0\262\0\0\0\304\0\0\0\315\0\0\0\320\4\4\4\320\16\16\16\315" "\276\276\276\311\262\262\262\310\251\251\251\311\1\1\1\314\0\0\0\320\0\0" "\0\324\0\0\0\324\0\0\0\317\0\0\0\304xxx\261\270\270\270\231ggg|\0\0\0`\0" "\0\0G\0\0\0""6\0\0\0*\0\0\0$\0\0\0!\0\0\0!\0\0\0!\0\0\0#\0\0\0$\0\0\0$\0" "\0\0$\0\0\0\"\0\0\0\37\0\0\0\33\0\0\0\26\0\0\0\22\0\0\0\16\0\0\0\14\0\0\0" "\14\0\0\0\15\0\0\0\20\0\0\0\24\0\0\0\31\0\0\0\34\0\0\0\40\0\0\0!\0\0\0\"" "\0\0\0\"\0\0\0!\0\0\0\40\0\0\0\37\0\0\0\37\0\0\0\37\0\0\0\37\0\0\0\35\0\0" "\0\32\0\0\0\26\0\0\0\21\0\0\0\14\0\0\0\10\0\0\0\4\0\0\0\12\0\0\0\24\0\0\0" "%\0\0\0=\2\2\2Z\361\361\361|***\231\0\0\0\263\0\0\0\305\0\0\0\322\0\0\0\331" "\0\0\0\335\0\0\0\336\0\0\0\336\0\0\0\335\0\0\0\334\0\0\0\333\0\0\0\332\0" "\0\0\327\0\0\0\322\0\0\0\310\0\0\0\270\311\311\311\244\221\221\221\213\0" "\0\0t\0\0\0]\0\0\0M\0\0\0B\0\0\0;\0\0\0""7\0\0\0""5\0\0\0""3\0\0\0""2\0\0" "\0""0\0\0\0.\0\0\0,\0\0\0+\0\0\0,\0\0\0/\0\0\0""3\0\0\0""8\0\0\0<\0\0\0>" "\0\0\0?\0\0\0>\0\0\0:\0\0\0""6\0\0\0/\0\0\0)\0\0\0\"\0\0\0\34\0\0\0\27\0" "\0\0\23\0\0\0\22\0\0\0\24\0\0\0\27\0\0\0\35\0\0\0$\0\0\0*\0\0\0""1\0\0\0" """6\0\0\0:\0\0\0<\0\0\0>\0\0\0?\0\0\0?\0\0\0?\0\0\0A\0\0\0F\0\0\0P\0\0\0" "a\260\260\260xPPP\221\0\0\0\252\0\0\0\274\0\0\0\307\0\0\0\313\0\0\0\310\35" "\35\35\301\303\303\303\270WWW\257===\253\363\363\363\255bbb\264\7\7\7\275" "\0\0\0\307\0\0\0\315\13\13\13\317&&&\314\0\0\0\306OOO\273\364\364\364\257" "\200\200\200\246\0\0\0\241\331\331\331\244\213\213\213\256\0\0\0\272\0\0" "\0\306\0\0\0\320\14\14\14\326\25\25\25\332\0\0\0\334'''\336\371\371\371\340" "\231\231\231\343\0\0\0\345\0\0\0\347\0\0\0\347\0\0\0\344\0\0\0\334\0\0\0" "\316ooo\272\337\337\337\241\25\25\25\206\0\0\0m\0\0\0W\0\0\0F\0\0\0""9\0" "\0\0/\0\0\0'\0\0\0\40\0\0\0\31\0\0\0\24\0\0\0\22\0\0\0\21\0\0\0\23\0\0\0" "\27\0\0\0\35\0\0\0$\0\0\0+\0\0\0""1\0\0\0""6\0\0\0""9\0\0\0;\0\0\0:\0\0\0" """7\0\0\0""2\0\0\0,\0\0\0$\0\0\0\35\0\0\0\27\0\0\0\24\0\0\0\23\0\0\0\26\0" "\0\0\32\0\0\0\40\0\0\0'\0\0\0-\0\0\0""2\0\0\0""5\0\0\0""7\0\0\0""6\0\0\0" """4\0\0\0""2\0\0\0""0\0\0\0.\0\0\0/\0\0\0""4\0\0\0@\0\0\0T\217\217\217p\356" "\356\356\216\13\13\13\253\0\0\0\304\0\0\0\326\0\0\0\337\0\0\0\344\0\0\0\344" "\0\0\0\342\230\230\230\340\375\375\375\337\245\245\245\340\3\3\3\342\0\0" "\0\345\0\0\0\347\0\0\0\346\0\0\0\340\0\0\0\325{{{\303\366\366\366\253qqq" "\217\0\0\0t\0\0\0\\\0\0\0K\0\0\0@\0\0\0;\0\0\0""8\0\0\0""8\0\0\0:\0\0\0;" "\0\0\0=\0\0\0=\0\0\0<\0\0\0:\0\0\0""5\0\0\0/\0\0\0'\0\0\0\40\0\0\0\32\0\0" "\0\26\0\0\0\26\0\0\0\31\0\0\0\36\0\0\0$\0\0\0+\0\0\0""1\0\0\0""6\0\0\0""9" "\0\0\0:\0\0\0:\0\0\0""8\0\0\0""7\0\0\0""7\0\0\0""7\0\0\0""6\0\0\0""5\0\0" "\0""2\0\0\0-\0\0\0&\0\0\0\36\0\0\0\25\0\0\0\16\0\0\0\5\0\0\0\13\0\0\0\27" "\0\0\0)\0\0\0D\2\2\2c\362\362\362\210)))\247\0\0\0\304\0\0\0\326\0\0\0\343" "\0\0\0\351\0\0\0\355\0\0\0\357\0\0\0\357\0\0\0\356\0\0\0\355\0\0\0\355\0" "\0\0\354\0\0\0\351\0\0\0\344\0\0\0\333\0\0\0\315\264\264\264\273\334\334" "\334\244&&&\216\0\0\0z\0\0\0k\0\0\0`\0\0\0Z\0\0\0V\0\0\0S\0\0\0R\0\0\0P\0" "\0\0M\0\0\0K\0\0\0H\0\0\0G\0\0\0H\0\0\0K\0\0\0Q\0\0\0V\0\0\0\\\22\22\22_" "\20\20\20`\0\0\0^\0\0\0Z\0\0\0S\0\0\0K\0\0\0B\0\0\0""9\0\0\0""0\0\0\0(\0" "\0\0#\0\0\0!\0\0\0#\0\0\0)\0\0\0""1\0\0\0;\0\0\0D\0\0\0M\0\0\0T\0\0\0Y\0" "\0\0]\0\0\0_\1\1\1`\24\24\24`\3\3\3_\0\0\0^\0\0\0a\0\0\0i\0\0\0xuuu\215\201" "\201\201\245\0\0\0\274\0\0\0\316\0\0\0\332\0\0\0\336\0\0\0\334\0\0\0\326" "\242\242\242\316\320\320\320\307\6\6\6\304\316\316\316\306nnn\314\0\0\0\324" "\0\0\0\334\0\0\0\341\0\0\0\343\0\0\0\340\0\0\0\332\20\20\20\320\340\340\340" "\305\201\201\201\274\0\0\0\270\247\247\247\273MMM\304\0\0\0\317\0\0\0\332" "\0\0\0\343\0\0\0\350\0\0\0\353\0\0\0\355hhh\356\374\374\374\360\333\333\333" "\361\5\5\5\363\0\0\0\363\0\0\0\363\0\0\0\360\0\0\0\351\0\0\0\335PPP\314\303" "\303\303\266OOO\237\0\0\0\210\0\0\0t\0\0\0c\0\0\0V\0\0\0J\0\0\0?\0\0\0""5" "\0\0\0+\0\0\0$\0\0\0\40\0\0\0\37\0\0\0\"\0\0\0)\0\0\0""1\0\0\0;\0\0\0D\0" "\0\0M\0\0\0S\0\0\0X\0\0\0Z\12\12\12Z\15\15\15V\0\0\0O\0\0\0F\0\0\0<\0\0\0" """1\0\0\0)\0\0\0#\0\0\0\"\0\0\0&\0\0\0,\0\0\0""6\0\0\0?\0\0\0H\0\0\0O\0\0" "\0T\0\0\0U\0\0\0U\0\0\0S\0\0\0P\0\0\0L\0\0\0H\0\0\0F\0\0\0I\0\0\0R\0\0\0" "d\177\177\177~\360\360\360\232]]]\267\0\0\0\317\0\0\0\341\0\0\0\353\0\0\0" "\360\0\0\0\361\21\21\21\360\247\247\247\357\261\261\261\356\335\335\335\357" "<<<\360\0\0\0\362\0\0\0\363\0\0\0\361\0\0\0\353\0\0\0\341\210\210\210\321" "\313\313\313\274\275\275\275\243\0\0\0\213\0\0\0v\0\0\0g\0\0\0]\0\0\0Y\0" "\0\0W\0\0\0X\0\0\0Z\0\0\0\\\0\0\0]\0\0\0^\0\0\0]\16\16\16Y\20\20\20R\0\0" "\0I\0\0\0>\0\0\0""4\0\0\0,\0\0\0'\0\0\0'\0\0\0+\0\0\0""2\0\0\0;\0\0\0E\0" "\0\0M\15\15\15T\27\27\27X\0\0\0Z\0\0\0Y\0\0\0X\0\0\0W\0\0\0U\0\0\0U\0\0\0" "U\0\0\0S\25\25\25N\4\4\4G\0\0\0<\0\0\0""0\0\0\0\"\0\0\0\27\0\0\0\5\0\0\0" "\14\0\0\0\31\0\0\0,\0\0\0I\2\2\2j\324\324\324\221\14\14\14\261\0\0\0\316" "\0\0\0\340\0\0\0\355\0\0\0\363\0\0\0\367\0\0\0\370\0\0\0\370\0\0\0\370\0" "\0\0\370\0\0\0\367\0\0\0\366\0\0\0\364\0\0\0\360\0\0\0\351\0\0\0\335\313" "\313\313\316\241\241\241\274%%%\252\\\\\\\231\240\240\240\214MMM\203GGG~" "NNN{NNNxNNNwKKKtNNNqNNNn\27\27\27j\0\0\0i\0\0\0j\0\0\0nAAAt\262\262\262{" "\246\246\246\201\347\347\347\204\341\341\341\205\265\265\265\203\265\265" "\265~\252\252\252w\30\30\30n\0\0\0c\0\0\0W\0\0\0K\0\0\0A\0\0\0:\0\0\0""7" "\0\0\0:\0\0\0A\0\0\0K\0\0\0X\11\11\11d\255\255\255o\247\247\247x<<<~\261" "\261\261\202\265\265\265\205\270\270\270\206\355\355\355\205\252\252\252" "\203\263\263\263\200xxx\200\23\23\23\205\0\0\0\220GGG\241\204\204\204\266" "\0\0\0\312\0\0\0\333\0\0\0\346\0\0\0\353\0\0\0\352\0\0\0\345\245\245\245" "\337\355\355\355\332CCC\330\272\272\272\331\263\263\263\336\0\0\0\345\0\0" "\0\353\0\0\0\357\0\0\0\360\0\0\0\356\0\0\0\350\0\0\0\337GGG\326\234\234\234" "\317\0\0\0\314\224\224\224\317OOO\326\0\0\0\337\0\0\0\350\0\0\0\357\0\0\0" "\363\0\0\0\366\0\0\0\367\313\313\313\370\340\340\340\371\326\326\326\371" "DDD\372\0\0\0\372\0\0\0\371\0\0\0\367\0\0\0\362\0\0\0\350,,,\333\353\353" "\353\312\300\300\300\267}}}\245\247\247\247\223\241\241\241\205MMMw\40\40" "\40k\0\0\0]\0\0\0P\0\0\0D\0\0\0:\0\0\0""5\0\0\0""4\0\0\0""9\0\0\0B\0\0\0" "M\0\0\0Y///e\253\253\253o\207\207\207wXXX}\257\257\257\177\322\322\322~\325" "\325\325zRRRqGGGf\5\5\5Y\0\0\0L\0\0\0A\0\0\0:\0\0\0""9\0\0\0=\0\0\0F\0\0" "\0R&&&^OOOj\237\237\237s\254\254\254x\240\240\240zNNNzNNNxNNNsGGGn\20\20" "\20i\0\0\0d\0\0\0d\0\0\0i\0\0\0v\0\0\0\214]]]\246ooo\300\0\0\0\327\0\0\0" "\347\0\0\0\361\0\0\0\366\0\0\0\370%%%\370\374\374\374\370\252\252\252\370" "\177\177\177\370\330\330\330\370\13\13\13\371\6\6\6\371...\367%%%\362\34" "\34\34\352QQQ\334\363\363\363\314hhh\267III\245HHH\224LLL\210MMM\201JJJ}" "NNN|NNN}QQQ\177\253\253\253\201\265\265\265\203\265\265\265\203\233\233\233" "\201\275\275\275}\326\326\326u$$$j\0\0\0\\\0\0\0P\0\0\0D\0\0\0?\0\0\0>\0" "\0\0C\0\0\0M\0\0\0Y(((fNNNp\261\261\261x\363\363\363}\262\262\262\177___" "~NNN}AAA|))){NNNzCCCynnnv\363\363\363pqqqe\34\34\34U\0\0\0D\0\0\0""1\0\0" "\0!\0\0\0\6\0\0\0\15\0\0\0\32\0\0\0/\0\0\0M\2\2\2o\332\332\332\226\21\21" "\21\267\0\0\0\324\0\0\0\346\0\0\0\362\0\0\0\370\0\0\0\373\0\0\0\374&&&\374" "!!!\374\15\15\15\374\2\2\2\374\0\0\0\373\0\0\0\372\0\0\0\367\0\0\0\362\6" "\6\6\351ooo\336\352\352\352\320\337\337\337\303\341\341\341\266\326\326\326" "\255\314\314\314\246\345\345\345\242\317\317\317\237\256\256\256\235\303" "\303\303\233\324\324\324\231\302\302\302\226\247\247\247\222\342\342\342" "\217NNN\215\31\31\31\216\305\305\305\222\351\351\351\230\206\206\206\237" "\246\246\246\245\275\275\275\250\273\273\273\251kkk\250EEE\243\221\221\221" "\233\331\331\331\221\327\327\327\206XXXx\11\11\11k\0\0\0_\0\0\0W\0\0\0S\0" "\0\0V\0\0\0^\6\6\6k\263\263\263y\332\332\332\207\351\351\351\223\273\273" "\273\234\340\340\340\242\345\345\345\246\240\240\240\251\234\234\234\251" "\254\254\254\250\214\214\214\245\266\266\266\242\346\346\346\237XXX\241\0" "\0\0\247===\264\324\324\324\304\0\0\0\325\0\0\0\344\0\0\0\355\0\0\0\362\0" "\0\0\362\0\0\0\360TTT\353\300\300\300\350\340\340\340\346\344\344\344\347" "PPP\353\0\0\0\357\0\0\0\364\0\0\0\366\0\0\0\367\0\0\0\365\0\0\0\361\0\0\0" "\352!!!\343\340\340\340\336\207\207\207\333\351\351\351\336555\343\0\0\0" "\352\0\0\0\361\0\0\0\366\0\0\0\371\0\0\0\373\0\0\0\374\232\232\232\374\356" "\356\356\374\202\202\202\375\11\11\11\375\0\0\0\375\0\0\0\375\0\0\0\373\0" "\0\0\370\0\0\0\361\"\"\"\347\317\317\317\333\303\303\303\315\273\273\273" "\300\352\352\352\262\304\304\304\246\334\334\334\232\346\346\346\215\323" "\323\323~ttto\13\13\13a\0\0\0U\0\0\0O\0\0\0O\0\0\0U\0\0\0`$$$m~~~{\237\237" "\237\210\362\362\362\223\273\273\273\234\241\241\241\241nnn\243%%%\242\216" "\216\216\235\342\342\342\225\361\361\361\210rrrz\12\12\12k\0\0\0^\0\0\0V" "\0\0\0U\0\0\0Z\0\0\0e\14\14\14r\327\327\327\200\324\324\324\215\251\251\251" "\226\240\240\240\234\236\236\236\237\312\312\312\237\307\307\307\234\321" "\321\321\230\272\272\272\222\335\335\335\214\331\331\331\205ddd\201\1\1\1" "\203\0\0\0\214\20\20\20\235\306\306\306\262hhh\311\0\0\0\335\0\0\0\354\0" "\0\0\365\0\0\0\372\0\0\0\374\4\4\4\374!!!\374\353\353\353\374\336\336\336" "\374\333\333\333\375???\375&&&\375///\373\7\7\7\367xxx\361\277\277\277\347" "\372\372\372\332\221\221\221\313^^^\276\342\342\342\261\236\236\236\251\226" "\226\226\244\347\347\347\241\271\271\271\241\237\237\237\242\364\364\364" "\244\276\276\276\246BBB\247bbb\250\302\302\302\245\324\324\324\241\327\327" "\327\230\346\346\346\214\241\241\241}FFFo\0\0\0b\0\0\0[\0\0\0[\0\0\0awww" "m\200\200\200z\310\310\310\210\333\333\333\223\213\213\213\234[[[\241zzz" "\243\323\323\323\243\350\350\350\242\330\330\330\241\342\342\342\240\267" "\267\267\237\346\346\346\235\224\224\224\231vvv\220\245\245\245\203\322\322" "\322owwwY\0\0\0@\0\0\0+\0\0\0\7\0\0\0\16\0\0\0\35\0\0\0""2\0\0\0Q\2\2\2t" "\350\350\350\233\36\36\36\273\0\0\0\330\0\0\0\352\0\0\0\365\0\0\0\373\0\0" "\0\376\0\0\0\377222\377\223\223\223\377\364\364\364\377\232\232\232\377\243" "\243\243\376PPP\375666\373$$$\370zzz\362]]]\353222\341\34\34\34\331\0\0\0" "\320\24\24\24\312\21\21\21\305\3\3\3\302\202\202\202\300\210\210\210\277" "FFF\275111\273SSS\271DDD\266ccc\262\322\322\322\261\254\254\254\262\330\330" "\330\265LLL\272\30\30\30\300\13\13\13\305\14\14\14\310ttt\311\23\23\23\310" "\26\26\26\304\0\0\0\275\0\0\0\264jjj\251\365\365\365\234\324\324\324\216" "\247\247\247\202ZZZy\0\0\0u\0\0\0xbbb\201\252\252\252\215\364\364\364\234" ">>>\251444\265\201\201\201\275\227\227\227\303YYY\307\21\21\21\311\0\0\0" "\311\0\0\0\310\0\0\0\305\14\14\14\300nnn\275\337\337\337\274\251\251\251" "\277222\307\324\324\324\323///\337\0\0\0\353\0\0\0\363\0\0\0\367\0\0\0\370" "\0\0\0\366\0\0\0\364mmm\361\332\332\332\360\206\206\206\361\0\0\0\364\0\0" "\0\367\0\0\0\372\0\0\0\373\0\0\0\373\0\0\0\372\0\0\0\367\0\0\0\363\0\0\0" "\356\217\217\217\352\355\355\355\350\307\307\307\352\0\0\0\355\0\0\0\362" "\0\0\0\366\0\0\0\372\0\0\0\374\0\0\0\375\0\0\0\375\326\326\326\376\342\342" "\342\376\213\213\213\376\13\13\13\377\0\0\0\377\0\0\0\376\0\0\0\375\0\0\0" "\373\0\0\0\367\0\0\0\361eee\351jjj\340KKK\327@@@\316fff\305999\272===\256" "kkk\240\277\277\277\220\255\255\255\201\0\0\0u\0\0\0o\0\0\0o333v\246\246" "\246\202\311\311\311\220\236\236\236\236RRR\253NNN\265$$$\275\0\0\0\302\0" "\0\0\304\0\0\0\303\0\0\0\276\36\36\36\266\210\210\210\252\313\313\313\234" "\325\325\325\215\14\14\14\200\0\0\0x\10\10\10w@@@|xxx\207\336\336\336\224" "\273\273\273\243999\257\3\3\3\270\0\0\0\276\27\27\27\301---\301(((\277bb" "b\273www\265RRR\256\215\215\215\247\347\347\347\241\220\220\220\237\0\0\0" "\244&&&\260\364\364\364\300jjj\323\0\0\0\343\0\0\0\360\0\0\0\370\0\0\0\374" "\0\0\0\376\0\0\0\376JJJ\377\367\367\367\377\377\377\377\377\262\262\262\377" "\35\35\35\377\24\24\24\376\0\0\0\375\0\0\0\372***\366\240\240\240\357\360" "\360\360\347\364\364\364\335\322\322\322\324KKK\315HHH\307\32\32\32\304Z" "ZZ\302\26\26\26\303\0\0\0\303rrr\305\20\20\20\307\0\0\0\310\0\0\0\310%%%" "\306AAA\301uuu\271\231\231\231\255\311\311\311\236\327\327\327\220888\204" "\0\0\0}\0\0\0}\27\27\27\203\362\362\362\217\262\262\262\235\227\227\227\252" "BBB\265\1\1\1\276<<<\302AAA\304\202\202\202\304\247\247\247\303\346\346\346" "\302bbb\301\0\0\0\300\0\0\0\275\0\0\0\270\0\0\0\255\0\0\0\235\234\234\234" "\205\344\344\344jEEEM\0\0\0""4\0\0\0\7\0\0\0\20\0\0\0\37\0\0\0""5\0\0\0V" "UUUy\334\334\334\240)))\300\0\0\0\332\0\0\0\354\0\0\0\367\0\0\0\374\0\0\0" "\376\0\0\0\377999\377\311\311\311\377\371\371\371\377\314\314\314\377\363" "\363\363\377\270\270\270\377\262\262\262\375|||\373\325\325\325\370HHH\363" "\0\0\0\356\0\0\0\351\0\0\0\343\0\0\0\337\0\0\0\334\0\0\0\332\15\15\15\330" "\13\13\13\327\0\0\0\326\0\0\0\325\4\4\4\323\3\3\3\321\7\7\7\317\313\313\313" "\316\356\356\356\316\301\301\301\321;;;\325\14\14\14\331\0\0\0\335\0\0\0" "\337\0\0\0\340\0\0\0\337\0\0\0\334\0\0\0\327\0\0\0\317\15\15\15\306+++\272" "ddd\257\237\237\237\243\222\222\222\233\0\0\0\227\22\22\22\231\321\321\321" "\241\301\301\301\255bbb\272\4\4\4\306$$$\320\21\21\21\326\26\26\26\334\14" "\14\14\337\0\0\0\340\0\0\0\340\0\0\0\337\0\0\0\334\0\0\0\330\2\2\2\324TT" "T\322\301\301\301\323\244\244\244\330\323\323\323\337(((\350\0\0\0\360\0" "\0\0\366\0\0\0\372\0\0\0\373\0\0\0\373\0\0\0\371ggg\370\362\362\362\367P" "PP\370\0\0\0\371\0\0\0\373\0\0\0\375\0\0\0\376\0\0\0\376\0\0\0\375\0\0\0" "\372\0\0\0\370\0\0\0\365FFF\363\342\342\342\362nnn\362\0\0\0\365\0\0\0\367" "\0\0\0\371\0\0\0\373\0\0\0\374\0\0\0\374\2\2\2\375\335\335\335\375\345\345" "\345\376sss\376\30\30\30\377\0\0\0\377\0\0\0\377\0\0\0\376\0\0\0\375\0\0" "\0\373\0\0\0\367\16\16\16\363333\356\2\2\2\350\0\0\0\342\0\0\0\333\0\0\0" "\323\0\0\0\311\0\0\0\274\30\30\30\255\346\346\346\237\264\264\264\224\3\3" "\3\216fff\220\244\244\244\227\350\350\350\242bbb\257\16\16\16\274\0\0\0\307" "\0\0\0\320\0\0\0\327\0\0\0\333\0\0\0\334\0\0\0\334\0\0\0\327\0\0\0\320\0" "\0\0\306CCC\271\321\321\321\254\333\333\333\241666\231\34\34\34\230\232\232" "\232\235\327\327\327\247\240\240\240\263\16\16\16\300\0\0\0\313\0\0\0\323" "\0\0\0\330\0\0\0\332\0\0\0\332\0\0\0\331\0\0\0\325\0\0\0\321\6\6\6\313''" "'\303}}}\275\341\341\341\271\204\204\204\273)))\302\364\364\364\316===\334" "\0\0\0\351\0\0\0\363\0\0\0\371\0\0\0\375\0\0\0\376\0\0\0\377\262\262\262" "\377\366\366\366\377\277\277\277\377333\377\0\0\0\377\0\0\0\377\0\0\0\376" "\0\0\0\374\0\0\0\372KKK\365\337\337\337\361\353\353\353\353HHH\345\1\1\1" "\341\0\0\0\336\0\0\0\334\0\0\0\333\0\0\0\333\0\0\0\334\0\0\0\335\0\0\0\337" "\0\0\0\337\0\0\0\337\0\0\0\336\0\0\0\332\0\0\0\322\0\0\0\310TTT\274xxx\257" "\315\315\315\243\0\0\0\235---\236\341\341\341\244\304\304\304\257???\273" "\1\1\1\307\0\0\0\320\0\0\0\327\0\0\0\333\0\0\0\335\0\0\0\335666\334CCC\333" "\0\0\0\332\0\0\0\331\0\0\0\325\0\0\0\317\0\0\0\301\0\0\0\256\0\0\0\223ii" "iusssT\0\0\0""9\0\0\0\11\0\0\0\22\0\0\0#\0\0\0;\0\0\0\\###\177\355\355\355" "\245III\304\0\0\0\336\0\0\0\356\0\0\0\367\0\0\0\374\0\0\0\376\0\0\0\377\12" "\12\12\377***\377JJJ\377```\377\232\232\232\377KKK\377\0\0\0\376EEE\375\300" "\300\300\373\40\40\40\371\0\0\0\366\0\0\0\363\0\0\0\360\0\0\0\356\0\0\0\353" "\0\0\0\351\0\0\0\347\0\0\0\346\0\0\0\346\0\0\0\346\0\0\0\345\0\0\0\345\10" "\10\10\344\205\205\205\344sss\344\32\32\32\346\0\0\0\351\0\0\0\353\0\0\0" "\356\0\0\0\360\0\0\0\360\0\0\0\357\0\0\0\355\0\0\0\352\0\0\0\344\0\0\0\335" "\0\0\0\324\0\0\0\313***\302\343\343\343\273JJJ\270\345\345\345\271\361\361" "\361\300\254\254\254\311\21\21\21\324\0\0\0\335\0\0\0\344\0\0\0\352\0\0\0" "\355\0\0\0\357\0\0\0\360\0\0\0\360\0\0\0\357\0\0\0\355\0\0\0\352\0\0\0\347" "\24\24\24\344ZZZ\344\343\343\343\345\340\340\340\352\20\20\20\360\0\0\0\365" "\0\0\0\371\0\0\0\374\0\0\0\375\0\0\0\375\0\0\0\375\15\15\15\374\264\264\264" "\374:::\374\0\0\0\374\0\0\0\375\0\0\0\376\0\0\0\377\0\0\0\377\0\0\0\376\0" "\0\0\375\0\0\0\373\0\0\0\372uuu\371\242\242\242\370AAA\370\0\0\0\371\0\0" "\0\372\0\0\0\372\0\0\0\372\0\0\0\371\10\10\10\371uuu\371\366\366\366\372" "\361\361\361\373\200\200\200\375\0\0\0\376\0\0\0\377\0\0\0\377\0\0\0\377" "\0\0\0\376\0\0\0\375\0\0\0\374\0\0\0\371\0\0\0\367\0\0\0\364\0\0\0\360\0" "\0\0\354\0\0\0\346\0\0\0\336\0\0\0\324\0\0\0\310\263\263\263\273XXX\262K" "KK\256\340\340\340\260vvv\267\203\203\203\300&&&\313\0\0\0\326\0\0\0\337" "\0\0\0\345\0\0\0\352\0\0\0\355\0\0\0\356\0\0\0\355\0\0\0\352\0\0\0\345\0" "\0\0\335\0\0\0\323888\311\307\307\307\277\261\261\261\271ttt\271\273\273" "\273\275\333\333\333\305===\317\0\0\0\331\0\0\0\341\0\0\0\347\0\0\0\353\0" "\0\0\354\0\0\0\355\0\0\0\353\0\0\0\351\0\0\0\346\0\0\0\341\0\0\0\333\0\0" "\0\325///\321\335\335\335\321ooo\325\274\274\274\335\4\4\4\346\0\0\0\357" "\0\0\0\366\0\0\0\373\0\0\0\376\0\0\0\377\26\26\26\377\331\331\331\377\361" "\361\361\377\202\202\202\377...\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\376" "\0\0\0\374\242\242\242\372\265\265\265\367\362\362\362\365___\362\21\21\21" "\360\0\0\0\357\0\0\0\356\0\0\0\355\0\0\0\356\0\0\0\356\0\0\0\357\0\0\0\357" "\0\0\0\360\0\0\0\360\0\0\0\356\0\0\0\353\0\0\0\346\0\0\0\336\0\0\0\324\0" "\0\0\312\345\345\345\301```\275\356\356\356\275\274\274\274\302\25\25\25" "\313\0\0\0\324\0\0\0\336\0\0\0\345\0\0\0\352\0\0\0\355\0\0\0\356\0\0\0\356" "\0\0\0\356\0\0\0\355\0\0\0\354\0\0\0\352\0\0\0\345\0\0\0\335\0\0\0\315\0" "\0\0\270EEE\231\277\277\277ynnnV\0\0\0:\0\0\0\13\0\0\0\26\0\0\0)\0\0\0B\0" "\0\0dXXX\207\274\274\274\254\0\0\0\312\0\0\0\341\0\0\0\357\0\0\0\370\0\0" "\0\374\0\0\0\375\0\0\0\376\0\0\0\375\0\0\0\375\0\0\0\375\0\0\0\376;;;\376" "000\376***\376\0\0\0\376\0\0\0\375\0\0\0\374\0\0\0\373\0\0\0\371\0\0\0\366" "\0\0\0\364\0\0\0\360\0\0\0\356\0\0\0\353\0\0\0\352\0\0\0\353\0\0\0\354\0" "\0\0\356\0\0\0\357KKK\360fff\361%%%\361\0\0\0\362\0\0\0\364\0\0\0\366\0\0" "\0\367\0\0\0\370\0\0\0\371\0\0\0\370\0\0\0\367\0\0\0\365\0\0\0\361\0\0\0" "\355\0\0\0\347\0\0\0\340\0\0\0\331\244\244\244\324\365\365\365\321\305\305" "\305\323'''\327\24\24\24\336\0\0\0\346\0\0\0\354\0\0\0\361\0\0\0\365\0\0" "\0\367\0\0\0\370\1\1\1\371\0\0\0\371\0\0\0\370\0\0\0\366\0\0\0\364\0\0\0" "\362\0\0\0\360\17\17\17\357\330\330\330\360\341\341\341\362LLL\365\0\0\0" "\371\0\0\0\373\0\0\0\375\0\0\0\376\0\0\0\376\0\0\0\376\0\0\0\376\20\20\20" "\376\14\14\14\376\0\0\0\376\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0" "\377\0\0\0\376\0\0\0\376\0\0\0\375666\374,,,\373\3\3\3\373\0\0\0\373\0\0" "\0\372\0\0\0\370\0\0\0\366\0\0\0\364\16\16\16\363\334\334\334\364\276\276" "\276\366\334\334\334\370RRR\373\0\0\0\375\0\0\0\376\0\0\0\377\0\0\0\377\0" "\0\0\377\0\0\0\377\0\0\0\376\0\0\0\375\0\0\0\374\0\0\0\372\0\0\0\370\0\0" "\0\366\0\0\0\362\0\0\0\354\0\0\0\344\2\2\2\332\265\265\265\321HHH\312\276" "\276\276\307\321\321\321\311\7\7\7\317\17\17\17\327\7\7\7\340\0\0\0\347\0" "\0\0\355\0\0\0\362\1\1\1\365\3\3\3\367\1\1\1\367\0\0\0\367\0\0\0\365\0\0" "\0\361\0\0\0\354\0\0\0\345\0\0\0\336uuu\327\346\346\346\322\331\331\331\322" "\323\323\323\325MMM\333\0\0\0\342\0\0\0\351\0\0\0\357\0\0\0\363\27\27\27" "\365666\367+++\367\5\5\5\366\0\0\0\365\0\0\0\362\0\0\0\357\0\0\0\353\0\0" "\0\346\23\23\23\343\337\337\337\342\344\344\344\344JJJ\351\0\0\0\357\0\0" "\0\365\0\0\0\371\0\0\0\374\0\0\0\376\0\0\0\377'''\377\322\322\322\377\343" "\343\343\377\40\40\40\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377" "\0\0\0\376\340\340\340\375\323\323\323\374\202\202\202\372RRR\371!!!\370" "\0\0\0\367\0\0\0\367\0\0\0\367\0\0\0\367\0\0\0\370\0\0\0\370\2\2\2\370\0" "\0\0\370\0\0\0\370\0\0\0\367\0\0\0\365\0\0\0\362\0\0\0\355\0\0\0\345\0\0" "\0\336sss\330\350\350\350\325\326\326\326\325>>>\331\0\0\0\337\0\0\0\346" "\0\0\0\355\0\0\0\361\0\0\0\365\0\0\0\367\0\0\0\367\0\0\0\367\0\0\0\367\0" "\0\0\367\0\0\0\366\0\0\0\363\0\0\0\355\0\0\0\343\0\0\0\321\2\2\2\271\350" "\350\350\230hhhw\21\21\21S\0\0\0""7\0\0\0\15\0\0\0\32\0\0\0/\0\0\0J\0\0\0" "n\307\307\307\221ZZZ\265\0\0\0\320\0\0\0\345\0\0\0\362\0\0\0\370\0\0\0\373" "\0\0\0\373\0\0\0\372\0\0\0\371\0\0\0\371\0\0\0\371\0\0\0\372\0\0\0\373\0" "\0\0\374\0\0\0\375\0\0\0\376\0\0\0\376\0\0\0\375\0\0\0\374\0\0\0\373\0\0" "\0\370\0\0\0\364\0\0\0\357\0\0\0\352\0\0\0\346\0\0\0\345\0\0\0\346\0\0\0" "\352\0\0\0\357\0\0\0\362\15\15\15\365\36\36\36\367\0\0\0\371\0\0\0\372\0" "\0\0\373\0\0\0\374\0\0\0\374\1\1\1\375UUU\375QQQ\375\0\0\0\374\0\0\0\373" "\0\0\0\371\0\0\0\367\0\0\0\363\0\0\0\357\10\10\10\352\230\230\230\347\207" "\207\207\345,,,\346\0\0\0\351\0\0\0\355\0\0\0\362\0\0\0\366\0\0\0\371\0\0" "\0\373\0\0\0\374\22\22\22\375qqq\375,,,\375\0\0\0\374\0\0\0\374\0\0\0\372" "\0\0\0\371\0\0\0\367\0\0\0\367|||\367\351\351\351\370UUU\372\0\0\0\373\0" "\0\0\375\0\0\0\376\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0" "\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0" "\377\0\0\0\377\0\0\0\376\0\0\0\376\0\0\0\375\0\0\0\374\0\0\0\373\0\0\0\370" "\0\0\0\364\0\0\0\360\0\0\0\354FFF\353\321\321\321\354CCC\357\365\365\365" "\363\31\31\31\370\0\0\0\373\0\0\0\375\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0" "\377\0\0\0\377\0\0\0\377\0\0\0\376\0\0\0\376\0\0\0\375\0\0\0\373\0\0\0\371" "\0\0\0\365\0\0\0\357sss\351\372\372\372\343\256\256\256\336\210\210\210\335" "\7\7\7\336\0\0\0\343\0\0\0\351\0\0\0\356\0\0\0\363\0\0\0\367\17\17\17\371" "OOO\373\214\214\214\374555\374\4\4\4\374\0\0\0\373\0\0\0\371\0\0\0\366\0" "\0\0\362\0\0\0\355\33\33\33\351\272\272\272\346\333\333\333\346\255\255\255" "\350\11\11\11\353\0\0\0\360\0\0\0\364\0\0\0\367\13\13\13\372rrr\373hhh\374" "\223\223\223\374LLL\374\0\0\0\373\0\0\0\372\0\0\0\370\0\0\0\365\0\0\0\362" "\6\6\6\360\274\274\274\357\340\340\340\360\\\\\\\362\0\0\0\366\0\0\0\371" "\0\0\0\374\0\0\0\376\0\0\0\377\0\0\0\377qqq\377\344\344\344\377\314\314\314" "\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377nnn\377\334" "\334\334\376\326\326\326\376\12\12\12\376\0\0\0\375\0\0\0\375\0\0\0\375\0" "\0\0\375\0\0\0\375\0\0\0\375***\375|||\375\244\244\244\375@@@\375\0\0\0\375" "\0\0\0\374\0\0\0\373\0\0\0\371\0\0\0\366\0\0\0\362\21\21\21\355\330\330\330" "\351\360\360\360\347ggg\350\0\0\0\352\0\0\0\356\0\0\0\362\0\0\0\366\0\0\0" "\371\0\0\0\373\0\0\0\374\0\0\0\375\0\0\0\375\0\0\0\375\0\0\0\374\0\0\0\372" "\0\0\0\367\0\0\0\360\0\0\0\344\0\0\0\320\221\221\221\265\263\263\263\222" "\0\0\0p\0\0\0L\0\0\0""1\0\0\0\20\0\0\0\36\0\0\0""5\0\0\0R\177\177\177w\355" "\355\355\233000\275\0\0\0\326\0\0\0\351\0\0\0\363\0\0\0\370\0\0\0\371\0\0" "\0\367\0\0\0\365\0\0\0\363\0\0\0\362\0\0\0\362\0\0\0\363\0\0\0\365\0\0\0" "\367\0\0\0\372\0\0\0\373\0\0\0\375\0\0\0\375\0\0\0\374\0\0\0\372\0\0\0\366" "\0\0\0\360\0\0\0\350\30\30\30\340yyy\333\205\205\205\331YYY\333\16\16\16" "\341\0\0\0\351\0\0\0\360\0\0\0\366\0\0\0\371\0\0\0\374\0\0\0\375\0\0\0\376" "\0\0\0\376\0\0\0\377\33\33\33\377\307\307\307\377\337\337\337\377\0\0\0\377" "\0\0\0\376\0\0\0\375\0\0\0\374\0\0\0\371\0\0\0\367\200\200\200\365\222\222" "\222\362---\362\0\0\0\362\0\0\0\364\0\0\0\366\0\0\0\371\0\0\0\373\0\0\0\375" "\0\0\0\376QQQ\377iii\377\204\204\204\377\17\17\17\377\0\0\0\377\0\0\0\376" "\0\0\0\375\0\0\0\374\0\0\0\373\0\0\0\372\252\252\252\372\344\344\344\372" "---\373\0\0\0\375\0\0\0\376\0\0\0\376\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0" "\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\20\20\20\377777\377\0\0\0\377" "\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\376\0\0\0\374\0" "\0\0\371\0\0\0\365\0\0\0\356\0\0\0\350444\343\347\347\347\341\224\224\224" "\342\322\322\322\350\327\327\327\356\25\25\25\364\0\0\0\371\0\0\0\375\0\0" "\0\376\0\0\0\377\0\0\0\377OOO\377\252\252\252\377\257\257\257\377aaa\377" "fff\377\0\0\0\377\0\0\0\376\0\0\0\374\0\0\0\371\0\0\0\366NNN\362\365\365" "\365\356\302\302\302\353&&&\353\0\0\0\354\0\0\0\357\0\0\0\363\0\0\0\367\0" "\0\0\372\0\0\0\374NNN\375ttt\376UUU\377\"\"\"\377\0\0\0\376\0\0\0\376\0\0" "\0\375\0\0\0\373\0\0\0\371\0\0\0\366\5\5\5\364)))\362\36\36\36\362\36\36" "\36\363\2\2\2\365\0\0\0\370\0\0\0\372\0\0\0\374\3\3\3\375FFF\376}}}\376z" "zz\377\23\23\23\376\0\0\0\376\0\0\0\375\0\0\0\374\0\0\0\373\0\0\0\371###" "\367\365\365\365\367\240\240\240\367\21\21\21\370\0\0\0\372\0\0\0\374\0\0" "\0\376\0\0\0\376\0\0\0\377DDD\377\305\305\305\377\340\340\340\377QQQ\377" "\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377222\377\322\322\322\377" "\237\237\237\377\350\350\350\377\11\11\11\377\0\0\0\377\0\0\0\377\0\0\0\377" "\0\0\0\377\0\0\0\377\14\14\14\377\241\241\241\377\361\361\361\377\364\364" "\364\377```\377\0\0\0\377\0\0\0\377\0\0\0\376\0\0\0\375\0\0\0\373\0\0\0\371" "]]]\366\316\316\316\364\307\307\307\363\22\22\22\363\0\0\0\364\0\0\0\366" "\0\0\0\371\0\0\0\373\0\0\0\375\37\37\37\376ooo\377\313\313\313\377LLL\377" "\0\0\0\377\0\0\0\376\0\0\0\374\0\0\0\371\0\0\0\361\0\0\0\343\37\37\37\315" "\312\312\312\260ddd\214\0\0\0i\0\0\0F\0\0\0,\0\0\0\23\0\0\0#\0\0\0<\1\1\1" "[\323\323\323\201+++\244\0\0\0\305\0\0\0\334\0\0\0\354\0\0\0\364\0\0\0\366" "\0\0\0\364\0\0\0\360\13\13\13\353\31\31\31\346\20\20\20\344\0\0\0\344\0\0" "\0\346\0\0\0\352\0\0\0\356\0\0\0\363\0\0\0\367\0\0\0\372\0\0\0\373\0\0\0" "\373\0\0\0\370\0\0\0\362\2\2\2\350}}}\335\336\336\336\321\357\357\357\311" "\327\327\327\306\344\344\344\312\345\345\345\323000\337\0\0\0\352\0\0\0\363" "\0\0\0\371\0\0\0\374\0\0\0\376\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0" "\0\0\377\26\26\26\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\376\0\0\0\375\0" "\0\0\374yyy\373hhh\372\0\0\0\372\0\0\0\372\0\0\0\373\0\0\0\374\0\0\0\375" "\0\0\0\376\0\0\0\377\0\0\0\377999\377***\377\0\0\0\377\0\0\0\377\0\0\0\377" "\0\0\0\377\0\0\0\376\0\0\0\375\0\0\0\374qqq\373\342\342\342\372\336\336\336" "\373\0\0\0\373\0\0\0\374\0\0\0\376\0\0\0\376\0\0\0\377\0\0\0\377\0\0\0\377" "\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377444\377\242\242\242\377" "\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\376\0" "\0\0\373\0\0\0\366\0\0\0\360\0\0\0\347\204\204\204\335\360\360\360\327\343" "\343\343\324&&&\327\334\334\334\337999\350\5\5\5\361\0\0\0\367\0\0\0\373" "\0\0\0\376\0\0\0\377\37\37\37\377\334\334\334\377\265\265\265\377\357\357" "\357\377\265\265\265\377555\377\0\0\0\377\0\0\0\377\0\0\0\376\0\0\0\375\0" "\0\0\373]]]\370\345\345\345\366\216\216\216\365\0\0\0\364\0\0\0\365\0\0\0" "\370\0\0\0\372\0\0\0\374\0\0\0\375QQQ\376999\377)))\377\0\0\0\377\0\0\0\377" "\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\376\0\0\0\375\0\0\0\373aaa\372QQQ\372" "\0\0\0\372\0\0\0\372\0\0\0\373\0\0\0\374\0\0\0\375\0\0\0\376\0\0\0\377\0" "\0\0\377\36\36\36\377\17\17\17\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\376" "\0\0\0\376\0\0\0\375000\374\353\353\353\374DDD\374\0\0\0\374\0\0\0\375\0" "\0\0\376\0\0\0\376\0\0\0\377\0\0\0\377\276\276\276\377\366\366\366\377\330" "\330\330\377\10\10\10\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377" "\230\230\230\377\300\300\300\377\302\302\302\377\237\237\237\377\0\0\0\377" "\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\234\234\234\377\334\334" "\334\377xxx\377\342\342\342\377MMM\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0" "\0\377\0\0\0\376\0\0\0\375~~~\373\247\247\247\372\0\0\0\372\0\0\0\372\0\0" "\0\373\0\0\0\374\0\0\0\375\0\0\0\376DDD\377\237\237\237\377\345\345\345\377" "\331\331\331\377\311\311\311\377\1\1\1\377\0\0\0\377\0\0\0\375\0\0\0\370" "\0\0\0\357\0\0\0\341\177\177\177\310\320\320\320\252iii\204\0\0\0a\0\0\0" "?\0\0\0&\0\0\0\26\0\0\0'\0\0\0C\1\1\1c\316\316\316\212\10\10\10\254\0\0\0" "\313\0\0\0\341\0\0\0\356\0\0\0\364\0\0\0\363\27\27\27\357\216\216\216\346" "\222\222\222\336\240\240\240\326\307\307\307\322\23\23\23\321\23\23\23\324" "\0\0\0\333EEE\342\36\36\36\352\0\0\0\361\0\0\0\366\0\0\0\371\0\0\0\371\0" "\0\0\365\0\0\0\354\4\4\4\340\337\337\337\320\241\241\241\301777\266\10\10" "\10\263\33\33\33\270\255\255\255\304\241\241\241\324\0\0\0\343\0\0\0\357" "\0\0\0\367\0\0\0\374\0\0\0\376\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0" "\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0" "\0\376\0\0\0\375\0\0\0\375\0\0\0\375\0\0\0\375\0\0\0\375\0\0\0\376\0\0\0" "\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377" "\0\0\0\377\0\0\0\376\0\0\0\376\0\0\0\374\0\0\0\372BBB\371\327\327\327\370" "\337\337\337\370\0\0\0\371\0\0\0\373\0\0\0\375\0\0\0\376\0\0\0\377\0\0\0" "\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\376\5\5\5\376FFF\376)" "))\376\0\0\0\376\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0" "\375\0\0\0\371\0\0\0\363\0\0\0\352\0\0\0\337\324\324\324\323RRR\313///\311" "lll\315\275\275\275\327\0\0\0\343\0\0\0\356\0\0\0\366\0\0\0\373\0\0\0\375" "\0\0\0\376\237\237\237\377\332\332\332\377\0\0\0\377\325\325\325\377\177" "\177\177\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\376\0\0\0\374" "\11\11\11\373\214\214\214\372\36\36\36\371\0\0\0\372\0\0\0\372\0\0\0\373" "\0\0\0\375\0\0\0\376\0\0\0\377\26\26\26\377\2\2\2\377\0\0\0\377\0\0\0\377" "\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\376\0\0\0\376\20" "\20\20\375\10\10\10\375\0\0\0\375\0\0\0\375\0\0\0\376\0\0\0\376\0\0\0\377" "\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0" "\0\0\377\0\0\0\377\0\0\0\377\0\0\0\376\207\207\207\376\377\377\377\376tt" "t\376\0\0\0\376\0\0\0\376\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\276\276" "\276\377\240\240\240\377\241\241\241\377\0\0\0\377\0\0\0\377\0\0\0\377\0" "\0\0\377\0\0\0\377'''\377\303\303\303\377\236\236\236\377\353\353\353\377" "III\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377@@@\377\327\327" "\327\377\36\36\36\377***\377\342\342\342\377&&&\377\0\0\0\377\0\0\0\377\0" "\0\0\377\0\0\0\377\0\0\0\377\40\40\40\376\314\314\314\376\\\\\\\375\0\0\0" "\375\0\0\0\375\0\0\0\375\0\0\0\376\0\0\0\377\0\0\0\377\271\271\271\377\356" "\356\356\377AAA\377\264\264\264\377\246\246\246\377\1\1\1\377\0\0\0\377\0" "\0\0\374\0\0\0\370\0\0\0\356\0\0\0\336iii\305\365\365\365\245:::\177\0\0" "\0[\0\0\0:\0\0\0#\0\0\0\30\0\0\0+\0\0\0I\1\1\1j\305\305\305\221\0\0\0\263" "\0\0\0\321\0\0\0\344\0\0\0\360\0\0\0\362\0\0\0\357\27\27\27\347\222\222\222" "\332\304\304\304\314\316\316\316\300\352\352\352\271\356\356\356\267\327" "\327\327\273\213\213\213\305\261\261\261\321\346\346\346\336~~~\351\0\0\0" "\361\0\0\0\366\0\0\0\366\0\0\0\362\0\0\0\347\6\6\6\330\352\352\352\304$$" "$\261\0\0\0\242\0\0\0\235\0\0\0\244\316\316\316\262yyy\307\0\0\0\332\0\0" "\0\352\0\0\0\364\0\0\0\372\0\0\0\376\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0" "\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377" "\0\0\0\376\0\0\0\376\0\0\0\376\0\0\0\376\0\0\0\376\0\0\0\376\0\0\0\377\0" "\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0" "\0\377\0\0\0\377\0\0\0\376\0\0\0\374\0\0\0\372\0\0\0\367mmm\364\331\331\331" "\363\267\267\267\363\31\31\31\365\0\0\0\367\0\0\0\372\0\0\0\374\0\0\0\376" "\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\376\0\0\0\375\0\0\0\375\203\203\203" "\374\330\330\330\374ccc\374\0\0\0\375\0\0\0\376\0\0\0\376\0\0\0\377\0\0\0" "\377\0\0\0\376\0\0\0\374\0\0\0\370\0\0\0\360\0\0\0\345\12\12\12\326\320\320" "\320\311\0\0\0\277\0\0\0\276\252\252\252\304\214\214\214\320\0\0\0\337\0" "\0\0\353\0\0\0\364\0\0\0\372\0\0\0\374\5\5\5\375\201\201\201\375\244\244" "\244\375\0\0\0\375\330\330\330\375\243\243\243\376\0\0\0\376\0\0\0\377\0" "\0\0\377\0\0\0\376\0\0\0\376\0\0\0\375\330\330\330\374\361\361\361\373\27" "\27\27\373\0\0\0\373\0\0\0\374\0\0\0\375\0\0\0\376\0\0\0\377\0\0\0\377\0" "\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0" "\0\377\0\0\0\377\0\0\0\377\0\0\0\376\0\0\0\376\0\0\0\376\0\0\0\376\0\0\0" "\376\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377" "\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\37733" "3\377\235\235\235\377ddd\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0" "\0\377###\377\344\344\344\377000\377\245\245\245\377\0\0\0\377\0\0\0\377" "\0\0\0\377\0\0\0\377\0\0\0\377\1\1\1\377eee\377\260\260\260\377\241\241\241" "\377nnn\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377!!!\377\335" "\335\335\377\227\227\227\377+++\377\362\362\362\377OOO\377\0\0\0\377\0\0" "\0\377\0\0\0\377\0\0\0\377\0\0\0\377777\377\375\375\375\377iii\377\0\0\0" "\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377$$$\377\321\321\321" "\377666\377\357\357\357\377\320\320\320\377XXX\377\0\0\0\377\0\0\0\374\0" "\0\0\367\0\0\0\355\0\0\0\334\22\22\22\302\321\321\321\241gggz\0\0\0W\0\0" "\0""6\0\0\0\40\0\0\0\33\0\0\0/\0\0\0N\1\1\1p\350\350\350\227\40\40\40\271" "\0\0\0\325\0\0\0\347\0\0\0\360\0\0\0\361\0\0\0\352\0\0\0\336xxx\314\223\223" "\223\272\0\0\0\251...\236888\233\323\323\323\241\361\361\361\256\353\353" "\353\276\355\355\355\320\204\204\204\340\0\0\0\354\0\0\0\362\0\0\0\364\0" "\0\0\357\0\0\0\343\6\6\6\321\354\354\354\271kkk\243\0\0\0\222\0\0\0\214\0" "\0\0\222\317\317\317\243mmm\273\0\0\0\321\0\0\0\344\0\0\0\361\0\0\0\371\0" "\0\0\374\0\0\0\377\0\0\0\377\22\22\22\377MMM\377\0\0\0\377\0\0\0\377\0\0" "\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\376\25\25\25\375\211\211\211\375" "ccc\375\0\0\0\375\0\0\0\375\0\0\0\376\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0" "\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\33\33\33\376nnn\374" "888\372---\366222\362uuu\356\366\366\366\353\342\342\342\354$$$\357\0\0\0" "\363\0\0\0\367\0\0\0\373\0\0\0\375\0\0\0\376\0\0\0\376\0\0\0\376\0\0\0\374" "\0\0\0\373\0\0\0\371\322\322\322\370\351\351\351\370\303\303\303\371\0\0" "\0\372\0\0\0\374\0\0\0\375\0\0\0\376\0\0\0\377\0\0\0\376\0\0\0\373\0\0\0" "\365\0\0\0\355\0\0\0\337===\317\341\341\341\301\0\0\0\267\0\0\0\266\254\254" "\254\276\277\277\277\314\0\0\0\334\0\0\0\352\0\0\0\364\0\0\0\371\0\0\0\373" "\0\0\0\373qqq\373\236\236\236\372\0\0\0\372\332\332\332\373<<<\374\0\0\0" "\375\0\0\0\376\0\0\0\376\0\0\0\376\0\0\0\374\0\0\0\373\333\333\333\372\347" "\347\347\371\27\27\27\372\0\0\0\372\0\0\0\374\0\0\0\375\0\0\0\376\0\0\0\377" "\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\15\15\15\377" "nnn\377\35\35\35\377\0\0\0\377\0\0\0\376111\376\40\40\40\376\0\0\0\376\0" "\0\0\376\0\0\0\376\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377+++\377777\377" "\0\0\0\377%%%\377\3\3\3\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0" "\377\0\0\0\377\224\224\224\377\234\234\234\377\0\0\0\377\0\0\0\377\0\0\0" "\377\0\0\0\377\0\0\0\377$$$\377\346\346\346\377uuu\377\245\245\245\377\0" "\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\376DDD\376\367\367" "\367\376\354\354\354\376^^^\376\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0" "\0\0\377\0\0\0\376\321\321\321\376\224\224\224\376\31\31\31\376\342\342\342" "\377\7\7\7\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377bbb\377\371" "\371\371\377___\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0" "\0\377\24\24\24\377\356\356\356\377}}}\377\361\361\361\377\235\235\235\377" "\24\24\24\377\0\0\0\376\0\0\0\374\0\0\0\366\0\0\0\353\0\0\0\332\12\12\12" "\276\316\316\316\236AAAw\0\0\0T\0\0\0""3\0\0\0\36\0\0\0\35\0\0\0""3\0\0\0" "S999u\350\350\350\235###\276\0\0\0\330\0\0\0\350\0\0\0\360\0\0\0\356\0\0" "\0\344\0\0\0\324\216\216\216\275\222\222\222\246\0\0\0\220\0\0\0\202\0\0" "\0~\10\10\10\205\12\12\12\226\11\11\11\253ttt\302\350\350\350\326\0\0\0\346" "\0\0\0\357\0\0\0\361\0\0\0\353\0\0\0\336\5\5\5\311\370\370\370\257\215\215" "\215\226\0\0\0\202\0\0\0{\0\0\0\202hhh\224\274\274\274\256\0\0\0\306\0\0" "\0\335\0\0\0\354\0\0\0\366\0\0\0\373\0\0\0\376\2\2\2\377FFF\377\231\231\231" "\377kkk\377'''\377'''\377\35\35\35\377\30\30\30\376\40\40\40\375\0\0\0\374" "\245\245\245\372\365\365\365\372\335\335\335\371\0\0\0\372\0\0\0\373\0\0" "\0\374\0\0\0\375\0\0\0\376\0\0\0\377\0\0\0\377\17\17\17\377\"\"\"\377NNN" "\377\305\305\305\377\260\260\260\376\206\206\206\375\325\325\325\372KKK\366" "444\360\234\234\234\352\343\343\343\344\245\245\245\341\237\237\237\342T" "TT\347\0\0\0\355\0\0\0\364\0\0\0\371\0\0\0\374\0\0\0\375\0\0\0\374\0\0\0" "\373\0\0\0\371\0\0\0\366\0\0\0\363sss\362\361\361\361\362\342\342\342\363" "\0\0\0\366\0\0\0\371\0\0\0\373\0\0\0\375\0\0\0\375\0\0\0\374\0\0\0\371\0" "\0\0\362\0\0\0\350\0\0\0\331$$$\310\331\331\331\270\0\0\0\257\0\0\0\260x" "xx\271\334\334\334\311\35\35\35\333\0\0\0\351\0\0\0\363\0\0\0\367\0\0\0\370" "\0\0\0\367@@@\366\344\344\344\366...\366\347\347\347\367VVV\371\0\0\0\374" "\0\0\0\375\0\0\0\374\0\0\0\373\0\0\0\371\0\0\0\367~~~\365\364\364\364\364" "kkk\365\0\0\0\366\0\0\0\370\0\0\0\373\0\0\0\375\0\0\0\376\0\0\0\377\22\22" "\22\377~~~\377\233\233\233\377~~~\377\212\212\212\377aaa\377ddd\376\235\235" "\235\376\0\0\0\375\14\14\14\374\260\260\260\373\256\256\256\373\0\0\0\373" "\0\0\0\374\0\0\0\375\0\0\0\376\0\0\0\376\0\0\0\377\0\0\0\377\232\232\232" "\377\310\310\310\377\257\257\257\377\365\365\365\377\242\242\242\377\201" "\201\201\377\21\21\21\377\22\22\22\377\23\23\23\377\26\26\26\377\234\234" "\234\377\354\354\354\377\270\270\270\377\0\0\0\377\0\0\0\377\0\0\0\377\0" "\0\0\377\0\0\0\377\1\1\1\377\255\255\255\377\237\237\237\377\357\357\357" "\377\13\13\13\377\0\0\0\377\0\0\0\377\0\0\0\376\0\0\0\375\0\0\0\374\213\213" "\213\374\362\362\362\373\362\362\362\374\216\216\216\375\0\0\0\376\0\0\0" "\376\0\0\0\376\0\0\0\376\0\0\0\375\0\0\0\374\260\260\260\373\235\235\235" "\373$$$\374\365\365\365\374888\375\0\0\0\376\0\0\0\377\0\0\0\377\0\0\0\377" "\0\0\0\377\11\11\11\377,,,\377qqq\377\33\33\33\377\0\0\0\377\0\0\0\377\0" "\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377KKK\377\320\320\320\377\322\322\322" "\377\214\214\214\377\0\0\0\377\0\0\0\376\0\0\0\373\0\0\0\365\0\0\0\351\0" "\0\0\327\6\6\6\273\305\305\305\232fffr\0\0\0P\0\0\0""1\0\0\0\34\0\0\0\40" "\0\0\0""6\0\0\0Wnnnz\265\265\265\241\0\0\0\301\0\0\0\333\0\0\0\351\0\0\0" "\357\0\0\0\353\0\0\0\336\0\0\0\312\223\223\223\257rrr\224\0\0\0z\0\0\0k\0" "\0\0f\0\0\0n\0\0\0\202\3\3\3\233\335\335\335\267YYY\316\0\0\0\341\0\0\0\353" "\0\0\0\355\0\0\0\347\0\0\0\327\3\3\3\301\262\262\262\245\321\321\321\212" "\0\0\0u\0\0\0l\0\0\0sqqq\205\260\260\260\240\0\0\0\273\0\0\0\324\0\0\0\345" "\0\0\0\361\0\0\0\370\0\0\0\374\25\25\25\376444\376\355\355\355\377\317\317" "\317\377\311\311\311\377\256\256\256\376\224\224\224\375\254\254\254\374" "\260\260\260\372\0\0\0\370222\365\372\372\372\363\242\242\242\362\0\0\0\363" "\0\0\0\365\0\0\0\370\0\0\0\372\0\0\0\374\0\0\0\376\0\0\0\377bbb\377\332\332" "\332\377\316\316\316\377\370\370\370\376\245\245\245\375\240\240\240\372" "iii\366\14\14\14\361\2\2\2\351~~~\340\336\336\336\331\22\22\22\325rrr\327" "\231\231\231\336\0\0\0\346\0\0\0\357\0\0\0\365\0\0\0\371\0\0\0\372\0\0\0" "\371\0\0\0\366\0\0\0\362\0\0\0\356\0\0\0\352\207\207\207\350\316\316\316" "\350\331\331\331\353\0\0\0\360\0\0\0\365\0\0\0\371\0\0\0\373\0\0\0\373\0" "\0\0\372\0\0\0\366\0\0\0\355\0\0\0\341\13\13\13\321\236\236\236\277\342\342" "\342\260\0\0\0\250%%%\252\276\276\276\266\323\323\323\307;;;\331\0\0\0\350" "\0\0\0\360\0\0\0\364\0\0\0\363\0\0\0\361\202\202\202\357\367\367\367\356" "\252\252\252\357\350\350\350\362\221\221\221\366\0\0\0\371\0\0\0\372\0\0" "\0\372\0\0\0\370\0\0\0\364\0\0\0\360~~~\354\365\365\365\353HHH\353\0\0\0" "\356\0\0\0\363\0\0\0\367\0\0\0\372\0\0\0\375\34\34\34\376www\377\374\374" "\374\377\371\371\371\377\335\335\335\376\361\361\361\376\306\306\306\375" "<<<\374222\372\0\0\0\371KKK\367\226\226\226\366\241\241\241\365666\366\0" "\0\0\367\0\0\0\371\0\0\0\373\0\0\0\375\0\0\0\376\0\0\0\376bbb\377\360\360" "\360\377\367\367\367\377\323\323\323\377\353\353\353\377\351\351\351\377" "\221\221\221\377vvv\377GGG\376\33\33\33\376\302\302\302\376\372\372\372\376" "NNN\376\0\0\0\376\0\0\0\376\0\0\0\375\0\0\0\375\0\0\0\375\0\0\0\375aaa\375" "\357\357\357\375\327\327\327\376\7\7\7\376\0\0\0\375\0\0\0\374\0\0\0\373" "\0\0\0\371\0\0\0\370\200\200\200\367\372\372\372\367\321\321\321\370RRR\372" "\0\0\0\374\0\0\0\375\0\0\0\375\0\0\0\373\0\0\0\372\0\0\0\370\221\221\221" "\367\216\216\216\366)))\367\363\363\363\370ccc\372\0\0\0\374\0\0\0\375\0" "\0\0\376\0\0\0\376\0\0\0\377+++\377\364\364\364\377\260\260\260\377rrr\377" "\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\227\227\227" "\377\320\320\320\377\322\322\322\377999\377\0\0\0\377\0\0\0\376\0\0\0\372" "\0\0\0\364\0\0\0\346\0\0\0\323'''\265\367\367\367\224DDDm\0\0\0K\0\0\0-\0" "\0\0\32\0\0\0\"\0\0\0""9\0\0\0[{{{~\273\273\273\245%%%\303\0\0\0\333\0\0" "\0\350\0\0\0\353\0\0\0\345\0\0\0\325\0\0\0\276\232\232\232\240\217\217\217" "\202\0\0\0g\0\0\0W\0\0\0S\0\0\0\\\0\0\0rddd\216\315\315\315\256000\310\0" "\0\0\334\0\0\0\346\0\0\0\347\0\0\0\340\0\0\0\316\1\1\1\267\230\230\230\231" "\330\330\330}\0\0\0g\0\0\0^\0\0\0c[[[u\353\353\353\220\"\"\"\254\0\0\0\307" "\0\0\0\333\0\0\0\352\0\0\0\363\0\0\0\370\0\0\0\372\3\3\3\374\16\16\16\374" "GGG\374GGG\374nnn\374,,,\372zzz\370111\364\0\0\0\357\12\12\12\353\341\341" "\341\350\310\310\310\346NNN\350\0\0\0\353\0\0\0\360\0\0\0\364\0\0\0\370\0" "\0\0\373\0\0\0\374\6\6\6\375TTT\375\304\304\304\374\231\231\231\373{{{\371" "\32\32\32\365\0\0\0\360\0\0\0\347\0\0\0\335---\322\344\344\344\312JJJ\307" "EEE\312\270\270\270\322\0\0\0\335\0\0\0\350\0\0\0\360\0\0\0\364\0\0\0\365" "\0\0\0\362\0\0\0\356\0\0\0\350\0\0\0\341\7\7\7\334\307\307\307\331YYY\333" "\320\320\320\340\11\11\11\347\0\0\0\356\0\0\0\364\0\0\0\367\0\0\0\367\0\0" "\0\364\0\0\0\357\0\0\0\345\0\0\0\327\25\25\25\305\314\314\314\263\351\351" "\351\245\0\0\0\237YYY\243\317\317\317\262\306\306\306\304333\327\0\0\0\344" "\0\0\0\354\0\0\0\356\0\0\0\354\3\3\3\350\207\207\207\345\271\271\271\344" "\263\263\263\346\340\340\340\352888\357\0\0\0\364\0\0\0\366\0\0\0\365\0\0" "\0\361\0\0\0\353\0\0\0\344\213\213\213\336\352\352\352\334\213\213\213\335" "\10\10\10\341\0\0\0\350\0\0\0\357\0\0\0\365\0\0\0\371***\373>>>\374\37\37" "\37\375\250\250\250\374\254\254\254\373...\372\13\13\13\371\2\2\2\367\0\0" "\0\364\0\0\0\361\5\5\5\356\30\30\30\354\332\332\332\353\217\217\217\354\0" "\0\0\357\0\0\0\363\0\0\0\366\0\0\0\371\0\0\0\372\0\0\0\373\5\5\5\374SSS\374" "\272\272\272\374\274\274\274\374\242\242\242\374www\374uuu\374(((\374\4\4" "\4\373\0\0\0\373\224\224\224\373\334\334\334\373\224\224\224\372\16\16\16" "\372\0\0\0\372\0\0\0\372\0\0\0\371\0\0\0\371\0\0\0\371MMM\371\362\362\362" "\371\356\356\356\372BBB\372\0\0\0\371\0\0\0\367\0\0\0\365\0\0\0\363\0\0\0" "\360\\\\\\\357\363\363\363\360\364\364\364\362777\364\0\0\0\367\0\0\0\371" "\0\0\0\371\0\0\0\367\0\0\0\364***\361\250\250\250\356\370\370\370\355\210" "\210\210\357\330\330\330\361ZZZ\364\0\0\0\367\0\0\0\371\0\0\0\373\0\0\0\374" "\0\0\0\374)))\375\366\366\366\375\356\356\356\376\216\216\216\377\0\0\0\377" "\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\12\12\12\377!!!\377nn" "n\377\16\16\16\377\0\0\0\377\0\0\0\375\0\0\0\371\0\0\0\360\0\0\0\342\0\0" "\0\315\7\7\7\256\316\316\316\214\1\1\1f\0\0\0E\0\0\0)\0\0\0\27\0\0\0#\0\0" "\0;\0\0\0]\303\303\303\201\277\277\277\246\12\12\12\303\0\0\0\331\0\0\0\344" "\0\0\0\345\0\0\0\335\0\0\0\312\2\2\2\261\353\353\353\221fffs\0\0\0W\0\0\0" "G\0\0\0D\0\0\0O\0\0\0g\263\263\263\205\266\266\266\246```\301\0\0\0\325\0" "\0\0\337\0\0\0\336\0\0\0\325\0\0\0\301\217\217\217\250\341\341\341\211\37" "\37\37n\0\0\0X\0\0\0N\0\0\0S\0\0\0d\243\243\243\177\301\301\301\233777\267" "\0\0\0\316\0\0\0\336\0\0\0\351\0\0\0\360\0\0\0\364\0\0\0\366\0\0\0\367\0" "\0\0\370\5\5\5\370]]]\367\37\37\37\364\0\0\0\357\0\0\0\351\0\0\0\342\12\12" "\12\334\363\363\363\327\257\257\257\325\257\257\257\327&&&\334\0\0\0\343" "\0\0\0\353\0\0\0\361\0\0\0\365\0\0\0\370\0\0\0\371\0\0\0\371\27\27\27\370" "\14\14\14\365\0\0\0\362\0\0\0\354\0\0\0\344\0\0\0\332\0\0\0\316\242\242\242" "\301\334\334\334\270QQQ\266NNN\272\341\341\341\305\25\25\25\323\0\0\0\337" "\0\0\0\350\0\0\0\354\0\0\0\353\0\0\0\347\0\0\0\340\0\0\0\330\5\5\5\317xx" "x\311\307\307\307\306\22\22\22\312\323\323\323\321MMM\333\0\0\0\345\0\0\0" "\354\0\0\0\357\0\0\0\357\0\0\0\353\0\0\0\343\0\0\0\330\0\0\0\310OOO\265\344" "\344\344\243\231\231\231\226\0\0\0\223\20\20\20\232\341\341\341\253\30\30" "\30\277\0\0\0\321\0\0\0\336\0\0\0\345\0\0\0\344\0\0\0\340>>>\332\370\370" "\370\326yyy\326eee\331\327\327\327\340...\347\0\0\0\355\0\0\0\357\0\0\0\356" "\0\0\0\350\0\0\0\337\0\0\0\324\330\330\330\314___\310\323\323\323\311\204" "\204\204\320\0\0\0\332\0\0\0\344\0\0\0\355\0\0\0\363\0\0\0\366\0\0\0\370" "\0\0\0\370\0\0\0\367\0\0\0\366\0\0\0\363\0\0\0\361\0\0\0\355\0\0\0\350\0" "\0\0\343\0\0\0\337\245\245\245\334\365\365\365\333\302\302\302\336\14\14" "\14\342\0\0\0\350\0\0\0\355\0\0\0\361\0\0\0\364\0\0\0\365\0\0\0\366\0\0\0" "\367\0\0\0\370\0\0\0\370\0\0\0\370\0\0\0\370\40\40\40\367\0\0\0\366\0\0\0" "\365\0\0\0\364\327\327\327\363\333\333\333\363%%%\363\0\0\0\362\0\0\0\362" "\0\0\0\362\0\0\0\361\0\0\0\360\30\30\30\360\307\307\307\361\365\365\365\362" "\337\337\337\362uuu\362\0\0\0\362\0\0\0\357\0\0\0\354\0\0\0\350\0\0\0\345" "\244\244\244\343\313\313\313\344\367\367\367\350HHH\354\0\0\0\360\0\0\0\362" "\0\0\0\362\0\0\0\357\0\0\0\352OOO\345\325\325\325\341\261\261\261\337\254" "\254\254\341\222\222\222\345???\352\0\0\0\357\0\0\0\363\0\0\0\365\0\0\0\367" "\0\0\0\370\12\12\12\371\312\312\312\373\357\357\357\374\334\334\334\375\3" "\3\3\376\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0" "\0\377\0\0\0\377\0\0\0\377\0\0\0\376\0\0\0\373\0\0\0\366\0\0\0\354\0\0\0" "\333\0\0\0\304EEE\244\331\331\331\202\1\1\1]\0\0\0>\0\0\0$\0\0\0\24\0\0\0" "%\0\0\0<\0\0\0^\313\313\313\200]]]\244\0\0\0\277\0\0\0\323\0\0\0\334\0\0" "\0\332\0\0\0\320\0\0\0\273555\241\316\316\316\200\0\0\0c\0\0\0I\0\0\0:\0" "\0\0""9\0\0\0E\0\0\0^\322\322\322|ccc\235AAA\270\0\0\0\313\0\0\0\322\0\0" "\0\320\0\0\0\304\0\0\0\257\311\311\311\226\20\20\20w\0\0\0\\\0\0\0H\0\0\0" ">\0\0\0B\0\0\0Q\15\15\15j\306\306\306\206\201\201\201\242\0\0\0\272\0\0\0" "\315\0\0\0\331\0\0\0\342\0\0\0\347\0\0\0\353\0\0\0\355\0\0\0\357\0\0\0\357" "\0\0\0\355\0\0\0\351\0\0\0\342\0\0\0\331\0\0\0\317\23\23\23\305\354\354\354" "\276333\274\364\364\364\277\207\207\207\307\0\0\0\321\0\0\0\333\0\0\0\344" "\0\0\0\353\0\0\0\357\0\0\0\361\0\0\0\361\0\0\0\357\0\0\0\353\0\0\0\345\0" "\0\0\335\1\1\1\323\17\17\17\306\11\11\11\270\241\241\241\253\210\210\210" "\242\6\6\6\241>>>\250\324\324\324\265\15\15\15\304\0\0\0\322\0\0\0\333\0" "\0\0\336\0\0\0\333\0\0\0\325\0\0\0\314\35\35\35\301\177\177\177\267\331\331" "\331\260<<<\257BBB\264\343\343\343\277\210\210\210\314\0\0\0\327\0\0\0\337" "\0\0\0\342\0\0\0\341\0\0\0\333\0\0\0\321\0\0\0\304\6\6\6\262\321\321\321" "\237\253\253\253\216\0\0\0\204\0\0\0\204\31\31\31\216\326\326\326\240\15" "\15\15\265\0\0\0\307\0\0\0\323\0\0\0\327\0\0\0\325\0\0\0\316III\307\267\267" "\267\303BBB\303\310\310\310\310\262\262\262\321GGG\332\0\0\0\342\0\0\0\344" "\0\0\0\341\0\0\0\331\0\0\0\315\234\234\234\300\306\306\306\264\0\0\0\256" "mmm\260\313\313\313\271\17\17\17\306\0\0\0\324\0\0\0\337\0\0\0\350\0\0\0" "\355\0\0\0\357\0\0\0\357\0\0\0\356\0\0\0\353\0\0\0\347\0\0\0\342\0\0\0\334" "\0\0\0\326\0\0\0\317\0\0\0\311\206\206\206\305\201\201\201\305\276\276\276" "\310===\317\0\0\0\327\0\0\0\337\0\0\0\344\0\0\0\350\0\0\0\352\0\0\0\354\0" "\0\0\355\0\0\0\356\0\0\0\357\0\0\0\357\0\0\0\356\0\0\0\355\0\0\0\353\0\0" "\0\351III\347\364\364\364\346YYY\345\1\1\1\345\0\0\0\345\0\0\0\344\0\0\0" "\343\0\0\0\342\0\0\0\341NNN\341\327\327\327\342\343\343\343\343XXX\345DD" "D\345\0\0\0\344\0\0\0\340\0\0\0\333\0\0\0\326MMM\322\323\323\323\321uuu\323" "\311\311\311\330)))\337\2\2\2\345\0\0\0\350\0\0\0\347\0\0\0\343\0\0\0\333" "PPP\324\323\323\323\316\\\\\\\313\333\333\333\315GGG\323\2\2\2\332\0\0\0" "\341\0\0\0\346\0\0\0\352\0\0\0\355\0\0\0\357TTT\362\350\350\350\365\335\335" "\335\370\366\366\366\373;;;\375\0\0\0\376\0\0\0\377\0\0\0\377\0\0\0\377\0" "\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\375\0\0\0\371\0\0" "\0\362\0\0\0\346\0\0\0\322\11\11\11\271\233\233\233\227hhhu\0\0\0R\0\0\0" """6\0\0\0\37\0\0\0\20\0\0\0$\0\0\0;\0\0\0[\257\257\257{ZZZ\235\0\0\0\266" "\0\0\0\307\0\0\0\315\0\0\0\312\0\0\0\275\34\34\34\247\320\320\320\215```" "n\0\0\0R\0\0\0;\0\0\0""0\0\0\0""0\0\0\0=\0\0\0U\260\260\260rYYY\221\0\0\0" "\251\0\0\0\272\0\0\0\300\0\0\0\274\32\32\32\256EEE\231\325\325\325\177\0" "\0\0c\0\0\0K\0\0\0""8\0\0\0/\0\0\0""2\0\0\0?\0\0\0U%%%o\342\342\342\212\241" "\241\241\241III\265\0\0\0\303\0\0\0\315\0\0\0\323\0\0\0\331\0\0\0\334\0\0" "\0\337\0\0\0\337\0\0\0\334\0\0\0\327\0\0\0\316\0\0\0\302\16\16\16\265\264" "\264\264\251\230\230\230\241\14\14\14\236\371\371\371\242\325\325\325\253" "\212\212\212\270\30\30\30\305\0\0\0\321\0\0\0\332\0\0\0\340\0\0\0\342\0\0" "\0\342\0\0\0\337\0\0\0\332\0\0\0\322\0\0\0\307:::\272\302\302\302\254\313" "\313\313\235\343\343\343\220111\211\0\0\0\212RRR\222\265\265\265\241\0\0" "\0\262\0\0\0\277\0\0\0\307\0\0\0\311\0\0\0\305\0\0\0\274666\261\243\243\243" "\245\331\331\331\232PPP\223\0\0\0\223ooo\233\332\332\332\250\233\233\233" "\267\0\0\0\304\0\0\0\314\0\0\0\317\0\0\0\314\0\0\0\305\0\0\0\271<<<\252\230" "\230\230\230\307\307\307\205444v\0\0\0o\0\0\0q\27\27\27~\362\362\362\221" "\27\27\27\246\0\0\0\267\0\0\0\301\0\0\0\303\4\4\4\277\14\14\14\267\221\221" "\221\257ggg\252QQQ\254\307\307\307\263ppp\276\0\0\0\311\0\0\0\321\0\0\0\324" "\0\0\0\320\0\0\0\306\20\20\20\267\336\336\336\247\27\27\27\231\0\0\0\222" "\10\10\10\224\312\312\312\236{{{\255\21\21\21\275\0\0\0\314\0\0\0\327\0\0" "\0\335\0\0\0\340\0\0\0\337\0\0\0\335\0\0\0\331\0\0\0\323\6\6\6\314CCC\305" "mmm\274qqq\264\254\254\254\255\344\344\344\250,,,\250kkk\256\265\265\265" "\266\0\0\0\300\0\0\0\311\0\0\0\320\0\0\0\324\0\0\0\327\0\0\0\331\0\0\0\333" "\0\0\0\335\0\0\0\336\0\0\0\336\0\0\0\336\0\0\0\333\0\0\0\330\11\11\11\326" "\205\205\205\323\367\367\367\322\266\266\266\320\3\3\3\317\0\0\0\317\0\0" "\0\316\0\0\0\314\0\0\0\313\0\0\0\312\225\225\225\312\340\340\340\313\362" "\362\362\315aaa\317\4\4\4\320\0\0\0\316\0\0\0\312\0\0\0\305%%%\276\254\254" "\254\272kkk\271[[[\274\316\316\316\304\14\14\14\314\0\0\0\323\0\0\0\327\0" "\0\0\326\0\0\0\320\6\6\6\307\241\241\241\274\253\253\253\264===\261\330\330" "\330\263JJJ\272555\303\12\12\12\313\0\0\0\322\0\0\0\330\0\0\0\334\0\0\0\340" "\224\224\224\346QQQ\353&&&\361\231\231\231\366\343\343\343\372\242\242\242" "\375\201\201\201\376???\377///\377\11\11\11\377\0\0\0\377\0\0\0\377\0\0\0" "\377\0\0\0\376\0\0\0\373\0\0\0\366\0\0\0\354\0\0\0\336\0\0\0\307ooo\253\355" "\355\355\211'''g\0\0\0F\0\0\0-\0\0\0\31\0\0\0\15\0\0\0!\0\0\0""6222S\353" "\353\353qXXX\217\2\2\2\245\5\5\5\263\0\0\0\267\0\0\0\262\37\37\37\244\343" "\343\343\216\263\263\263v\0\0\0Y\0\0\0A\0\0\0.\0\0\0%\0\0\0'\0\0\0""3\0\0" "\0Jtttdggg\200\20\20\20\225\22\22\22\243\14\14\14\247111\241\312\312\312" "\223\336\336\336~\256\256\256g\0\0\0N\0\0\0""9\0\0\0)\0\0\0\"\0\0\0$\0\0" "\0.\0\0\0A\1\1\1V\257\257\257o\352\352\352\204\326\326\326\227\320\320\320" "\245\261\261\261\260!!!\270\6\6\6\276\0\0\0\303\3\3\3\307\15\15\15\307\15" "\15\15\304\15\15\15\275\21\21\21\262\260\260\260\245\331\331\331\226\253" "\253\253\211\10\10\10\200\1\1\1}\33\33\33\201%%%\213\350\350\350\232\205" "\205\205\251\26\26\26\267\0\0\0\302\0\0\0\311\0\0\0\314\3\3\3\314\17\17\17" "\310666\301SSS\267\306\306\306\252\345\345\345\234\256\256\256\214rrr~\\" "\\\\s\0\0\0m\0\0\0p\22\22\22z\267\267\267\211\0\0\0\231\10\10\10\246\10\10" "\10\255AAA\255\246\246\246\247\277\277\277\235\340\340\340\221\302\302\302" "\204BBBy\0\0\0t\0\0\0v555\177\340\340\340\216\242\242\242\236\6\6\6\253\0" "\0\0\263;;;\264\220\220\220\260\204\204\204\247\212\212\212\232\352\352\352" "\212\204\204\204y\30\30\30h\0\0\0\\\0\0\0X\0\0\0\\\32\32\32j\354\354\354" "}444\221\15\15\15\240///\250%%%\250___\242\333\333\333\231\341\341\341\221" "@@@\215\0\0\0\220\265\265\265\231***\245\4\4\4\261\15\15\15\272\4\4\4\274" "\32\32\32\270%%%\254\315\315\315\234\254\254\254\213\2\2\2|\0\0\0t\0\0\0" "vZZZ\200\306\306\306\221\206\206\206\242000\262\0\0\0\276\0\0\0\305\0\0\0" "\311\6\6\6\310\"\"\"\304KKK\276aaa\267\264\264\264\257\353\353\353\246\350" "\350\350\234\330\330\330\222yyy\213\202\202\202\207\11\11\11\210\10\10\10" "\216\333\333\333\230qqq\243\223\223\223\256\262\262\262\265;;;\272nnn\275" "OOO\277%%%\302\10\10\10\304---\306###\306rrr\305\5\5\5\302\4\4\4\276~~~\272" "\374\374\374\267\367\367\367\264\360\360\360\263\331\331\331\262\330\330" "\330\261\226\226\226\260\310\310\310\256\305\305\305\254\335\335\335\253" "\342\342\342\254\212\212\212\255\343\343\343\260(((\262;;;\263KKK\261iii" "\255???\246\216\216\216\240\311\311\311\233\16\16\16\233\\\\\\\240\354\354" "\354\251888\263\7\7\7\273\3\3\3\300\0\0\0\276\5\5\5\267|||\254\352\352\352" "\240\20\20\20\226\0\0\0\222|||\224\344\344\344\233\226\226\226\245hhh\257" "\24\24\24\267888\276\17\17\17\304ZZZ\313\301\301\301\324\340\340\340\335" "\327\327\327\347\342\342\342\360\333\333\333\366\263\263\263\373\227\227" "\227\375\253\253\253\377\274\274\274\377www\377FFF\377555\377\26\26\26\377" "\0\0\0\375\0\0\0\371\0\0\0\362\0\0\0\346\0\0\0\324---\271\345\345\345\233" "gggx\0\0\0X\0\0\0:\0\0\0$\0\0\0\23\0\0\0\12\0\0\0\35\0\0\0/(((H\351\351\351" "b\231\231\231{\244\244\244\215\255\255\255\230|||\232<<<\224\253\253\253" "\207\246\246\246r\0\0\0]\0\0\0E\0\0\0""1\0\0\0\"\0\0\0\34\0\0\0\36\0\0\0" ")\0\0\0=OOOS\363\363\363j\335\335\335{\344\344\344\206\324\324\324\210\350" "\350\350\201\275\275\275t\0\0\0a\0\0\0M\0\0\0""9\0\0\0(\0\0\0\34\0\0\0\27" "\0\0\0\30\0\0\0\40\0\0\0.\0\0\0?555STTTe\275\275\275v\317\317\317\203\276" "\276\276\216\363\363\363\226\302\302\302\235\251\251\251\243\217\217\217" "\247\261\261\261\250[[[\245\303\303\303\235\351\351\351\222\271\271\271\204" "\26\26\26t\0\0\0g\0\0\0^\0\0\0\\\0\0\0`\0\0\0j\204\204\204y\351\351\351\211" "\270\270\270\230\214\214\214\243iii\253&&&\257kkk\256\310\310\310\252\357" "\357\357\241\361\361\361\226\336\336\336\210aaaz\32\32\32k\0\0\0^\0\0\0U" "\0\0\0Q\0\0\0U\22\22\22_\336\336\336nxxx|\304\304\304\207\303\303\303\214" "\351\351\351\213\263\263\263\204sssz)))n\0\0\0b\0\0\0Y\0\0\0V\0\0\0Y\0\0" "\0c[[[r\333\333\333\201\216\216\216\215qqq\224\342\342\342\224\235\235\235" "\216\360\360\360\205tttxJJJi\0\0\0Z\0\0\0L\0\0\0C\0\0\0A\0\0\0G\31\31\31" "U\363\363\363f\324\324\324w\275\275\275\203\357\357\357\210\363\363\363\207" "\327\327\327\201RRRx\0\0\0q\0\0\0n\0\0\0r\261\261\261{\323\323\323\207\220" "\220\220\224\320\320\320\234\223\223\223\236\222\222\222\231\227\227\227" "\216\364\364\364~KKKm\0\0\0_\0\0\0X\0\0\0Y\0\0\0c\203\203\203r\370\370\370" "\203\335\335\335\223\214\214\214\240^^^\247SSS\252\300\300\300\251\271\271" "\271\244\303\303\303\235\277\277\277\225\303\303\303\214555\202vvvxxxxo\0" "\0\0h\0\0\0e\0\0\0g\0\0\0n\226\226\226x\351\351\351\203\276\276\276\215\356" "\356\356\224\342\342\342\230\341\341\341\233\274\274\274\236\344\344\344" "\241\275\275\275\244\241\241\241\246\226\226\226\246\332\332\332\245\245" "\245\245\241\271\271\271\234\340\340\340\230\206\206\206\224\367\367\367" "\221\313\313\313\217\231\231\231\216\271\271\271\215\332\332\332\214\324" "\324\324\212\331\331\331\210JJJ\207!!!\210VVV\211\361\361\361\215\272\272" "\272\217\324\324\324\220\364\364\364\216\322\322\322\212\276\276\276\203" "\273\273\273}GGGz\0\0\0{ZZZ\200\363\363\363\212\322\322\322\224\261\261\261" "\235\211\211\211\242\220\220\220\240\250\250\250\231\347\347\347\215qqq\201" "\0\0\0v\0\0\0q\0\0\0s\237\237\237y\354\354\354\203\350\350\350\215\360\360" "\360\226\317\317\317\236\331\331\331\246\331\331\331\260\266\266\266\275" "\352\352\352\313[[[\332666\346\223\223\223\360\220\220\220\367\264\264\264" "\373\252\252\252\375\273\273\273\376\235\235\235\376MMM\376\0\0\0\376\25" "\25\25\375\0\0\0\373\0\0\0\366\0\0\0\355\0\0\0\335\20\20\20\310\237\237\237" "\252\177\177\177\212\0\0\0g\0\0\0I\0\0\0.\0\0\0\33\0\0\0\16\0\0\0\7\0\0\0" "\27\0\0\0&\0\0\0:nnnN\304\304\304b\372\372\372p\206\206\206y\256\256\256" "y\347\347\347s\227\227\227g\14\14\14V\0\0\0D\0\0\0""1\0\0\0\"\0\0\0\30\0" "\0\0\23\0\0\0\26\0\0\0\37\0\0\0.\2\2\2@wwwR\326\326\326_\272\272\272g\"\"" "\"f\"\"\"`\5\5\5U\0\0\0F\0\0\0""6\0\0\0'\0\0\0\33\0\0\0\22\0\0\0\16\0\0\0" "\17\0\0\0\25\0\0\0\37\0\0\0+\0\0\0:\0\0\0H\24\24\24U\20\20\20`\24\24\24j" "\"\"\"q###xNNN~\340\340\340\202\345\345\345\204\345\345\345\201\274\274\274" "z>>>o\5\5\5b\0\0\0T\0\0\0H\0\0\0A\0\0\0>\0\0\0B\0\0\0L\7\7\7YLLLg|||u\324" "\324\324\200\347\347\347\210\337\337\337\214\373\373\373\213\314\314\314" "\206fff~\36\36\36s\27\27\27e\0\0\0Y\0\0\0L\0\0\0A\0\0\0:\0\0\0""8\0\0\0=" "\2\2\2FeeeR\217\217\217^\201\201\201g\205\205\205jbbbh\0\0\0a\0\0\0X\0\0" "\0M\0\0\0D\0\0\0=\0\0\0;\0\0\0>\0\0\0H\13\13\13U\251\251\251b\347\347\347" "m\317\317\317rMMMq\10\10\10k\34\34\34b\0\0\0V\0\0\0J\0\0\0>\0\0\0""4\0\0" "\0-\0\0\0-\0\0\0""3\3\3\3?!!!M\314\314\314[\246\246\246dNNNg!!!e\17\17\17" "_\0\0\0W\0\0\0Q\0\0\0P\0\0\0T\27\27\27]SSSh\333\333\333s\357\357\357{\211" "\211\211}\266\266\266x\347\347\347nZZZ`\11\11\11Q\0\0\0E\0\0\0>\0\0\0?\0" "\0\0G\20\20\20T\"\"\"cxxxr\334\334\334}\345\345\345\204\343\343\343\206k" "kk\205\336\336\336\200\200\200\200y###q\17\17\17h\0\0\0^\0\0\0U\0\0\0N\0" "\0\0H\0\0\0F\0\0\0H\0\0\0OjjjX\317\317\317b\20\20\20j999p\206\206\206t**" "*v\0\0\0y\27\27\27|\322\322\322\177\334\334\334\201\345\345\345\202\305\305" "\305\200yyy|###w\33\33\33r\12\12\12o\"\"\"l\10\10\10j\0\0\0h\30\30\30h##" "#g\21\21\21e\31\31\31d\0\0\0c\0\0\0c\12\12\12e111h\214\214\214jLLLk###i\16" "\16\16f\0\0\0`\0\0\0[\0\0\0Y\0\0\0Z\13\13\13`BBBi\353\353\353s\334\334\334" "|\301\301\301\200\313\313\313~\365\365\365w|||l\0\0\0`\0\0\0W\0\0\0R\0\0" "\0S\13\13\13X###a\"\"\"i111r\212\212\212{\177\177\177\205$$$\222\0\0\0\243" "\305\305\305\265\\\\\\\311\0\0\0\332\3\3\3\350\20\20\20\360\24\24\24\366" "\4\4\4\371\24\24\24\372\\\\\\\373333\373\0\0\0\373\0\0\0\372\0\0\0\367\0" "\0\0\357\0\0\0\344\0\0\0\321WWW\271\363\363\363\231333y\0\0\0W\0\0\0;\0\0" "\0#\0\0\0\24\0\0\0\12\0\0\0\5\0\0\0\21\0\0\0\34\0\0\0*\0\0\0""9\21\21\21" "HNNNR\0\0\0W\0\0\0W\0\0\0R\0\0\0H\0\0\0;\0\0\0.\0\0\0!\0\0\0\26\0\0\0\17" "\0\0\0\15\0\0\0\17\0\0\0\26\0\0\0!\0\0\0-\0\0\0:\0\0\0B\0\0\0G\0\0\0G\0\0" "\0A\0\0\0""9\0\0\0.\0\0\0#\0\0\0\30\0\0\0\21\0\0\0\13\0\0\0\10\0\0\0\11\0" "\0\0\14\0\0\0\23\0\0\0\33\0\0\0%\0\0\0.\0\0\0""8\0\0\0@\0\0\0H\0\0\0N\0\0" "\0T\0\0\0Y\0\0\0^\36\36\36_OOO]\13\13\13W\0\0\0N\0\0\0C\0\0\0""8\0\0\0.\0" "\0\0(\0\0\0'\0\0\0*\0\0\0""2\0\0\0<\0\0\0H\0\0\0S\0\0\0]\0\0\0d\12\12\12" "g\275\275\275fdddb\0\0\0Z\0\0\0P\0\0\0E\0\0\0;\0\0\0""1\0\0\0)\0\0\0$\0\0" "\0$\0\0\0(\0\0\0/\0\0\0""9\0\0\0A\0\0\0G\0\0\0I\0\0\0F\0\0\0A\0\0\0""9\0" "\0\0""2\0\0\0*\0\0\0&\0\0\0%\0\0\0)\0\0\0""1\0\0\0;\27\27\27E\\\\\\M\30\30" "\30P\0\0\0O\0\0\0I\0\0\0B\0\0\0""9\0\0\0/\0\0\0'\0\0\0\40\0\0\0\34\0\0\0" "\35\0\0\0\"\0\0\0+\0\0\0""6\0\0\0?\0\0\0F\0\0\0G\0\0\0E\0\0\0@\0\0\0:\0\0" "\0""6\0\0\0""5\0\0\0""9\0\0\0@\0\0\0J===RNNNX\0\0\0Z\0\0\0V\0\0\0N\0\0\0" "C\0\0\0""7\0\0\0.\0\0\0)\0\0\0)\0\0\0/\0\0\0""9\0\0\0E\0\0\0Q===ZLLL_\0\0" "\0a\0\0\0_\0\0\0[\0\0\0U\0\0\0N\0\0\0F\0\0\0?\0\0\0""7\0\0\0""2\0\0\0-\0" "\0\0,\0\0\0/\0\0\0""4\0\0\0;\0\0\0C\0\0\0I\0\0\0M\0\0\0P\0\0\0R\0\0\0U\0" "\0\0W\0\0\0Z\0\0\0\\\0\0\0\\\0\0\0[\0\0\0W\0\0\0S\0\0\0O\0\0\0K\0\0\0H\0" "\0\0G\0\0\0F\0\0\0E\0\0\0D\0\0\0C\0\0\0B\0\0\0A\0\0\0B\0\0\0C\0\0\0F\0\0" "\0H\0\0\0H\0\0\0G\0\0\0D\0\0\0@\0\0\0<\0\0\0;\0\0\0=\0\0\0B\0\0\0J\0\0\0" "R\0\0\0Y\0\0\0\\///[___V###L\0\0\0C\0\0\0:\0\0\0""6\0\0\0""6\0\0\0:\0\0\0" "A\0\0\0H\0\0\0P\0\0\0X\0\0\0d\0\0\0s\0\0\0\207\307\307\307\235ZZZ\265\0\0" "\0\312\0\0\0\333\0\0\0\346\0\0\0\355\0\0\0\361\0\0\0\363\0\0\0\365\0\0\0" "\365\0\0\0\365\0\0\0\363\0\0\0\357\0\0\0\346\0\0\0\331\0\0\0\303VVV\251\314" "\314\314\207\0\0\0g\0\0\0G\0\0\0.\0\0\0\33\0\0\0\17\0\0\0\7\0\0\0\4\0\0\0" "\14\0\0\0\23\0\0\0\35\0\0\0&\0\0\0""0\0\0\0""7\0\0\0:\0\0\0:\0\0\0""6\0\0" "\0/\0\0\0&\0\0\0\35\0\0\0\24\0\0\0\16\0\0\0\11\0\0\0\10\0\0\0\11\0\0\0\16" "\0\0\0\25\0\0\0\35\0\0\0%\0\0\0+\0\0\0.\0\0\0-\0\0\0)\0\0\0#\0\0\0\33\0\0" "\0\25\0\0\0\16\0\0\0\12\0\0\0\6\0\0\0\5\0\0\0\5\0\0\0\7\0\0\0\13\0\0\0\20" "\0\0\0\26\0\0\0\34\0\0\0\"\0\0\0'\0\0\0,\0\0\0""1\0\0\0""6\0\0\0:\0\0\0>" "\0\0\0?\0\0\0=\0\0\0""9\0\0\0""2\0\0\0*\0\0\0\"\0\0\0\33\0\0\0\27\0\0\0\26" "\0\0\0\31\0\0\0\36\0\0\0%\0\0\0.\0\0\0""6\0\0\0>\0\0\0C\0\0\0E\0\0\0E\0\0" "\0B\0\0\0<\0\0\0""4\0\0\0,\0\0\0$\0\0\0\35\0\0\0\30\0\0\0\25\0\0\0\25\0\0" "\0\30\0\0\0\35\0\0\0$\0\0\0)\0\0\0-\0\0\0.\0\0\0,\0\0\0(\0\0\0#\0\0\0\35" "\0\0\0\31\0\0\0\26\0\0\0\26\0\0\0\30\0\0\0\37\0\0\0&\0\0\0-\0\0\0""2\0\0" "\0""4\0\0\0""3\0\0\0.\0\0\0)\0\0\0\"\0\0\0\34\0\0\0\26\0\0\0\22\0\0\0\21" "\0\0\0\21\0\0\0\25\0\0\0\33\0\0\0\"\0\0\0)\0\0\0-\0\0\0-\0\0\0+\0\0\0'\0" "\0\0#\0\0\0!\0\0\0!\0\0\0$\0\0\0)\0\0\0""0\0\0\0""6\0\0\0:\0\0\0<\0\0\0""9" "\0\0\0""3\0\0\0,\0\0\0#\0\0\0\35\0\0\0\31\0\0\0\31\0\0\0\35\0\0\0$\0\0\0" "-\0\0\0""5\0\0\0;\0\0\0?\0\0\0A\0\0\0?\0\0\0<\0\0\0""7\0\0\0""1\0\0\0,\0" "\0\0&\0\0\0!\0\0\0\35\0\0\0\32\0\0\0\32\0\0\0\34\0\0\0\40\0\0\0%\0\0\0*\0" "\0\0.\0\0\0""1\0\0\0""3\0\0\0""5\0\0\0""6\0\0\0""8\0\0\0;\0\0\0<\0\0\0=\0" "\0\0;\0\0\0""8\0\0\0""5\0\0\0""2\0\0\0/\0\0\0-\0\0\0+\0\0\0+\0\0\0*\0\0\0" "*\0\0\0)\0\0\0(\0\0\0(\0\0\0(\0\0\0)\0\0\0+\0\0\0,\0\0\0-\0\0\0,\0\0\0*\0" "\0\0'\0\0\0%\0\0\0$\0\0\0&\0\0\0*\0\0\0""0\0\0\0""6\0\0\0;\0\0\0>\0\0\0=" "\0\0\0""9\0\0\0""2\0\0\0+\0\0\0%\0\0\0!\0\0\0!\0\0\0$\0\0\0(\0\0\0.\0\0\0" """4\0\0\0<\0\0\0G\0\0\0W\0\0\0m\300\300\300\205aaa\237\0\0\0\266\0\0\0\311" "\0\0\0\326\0\0\0\336\0\0\0\343\0\0\0\346\0\0\0\350\0\0\0\352\0\0\0\352\0" "\0\0\350\0\0\0\343\0\0\0\330\0\0\0\311FFF\261\335\335\335\226\223\223\223" "u\0\0\0V\0\0\0""9\0\0\0$\0\0\0\24\0\0\0\12\0\0\0\5\0\0\0\2\0\0\0\7\0\0\0" "\14\0\0\0\21\0\0\0\27\0\0\0\35\0\0\0!\0\0\0\"\0\0\0\"\0\0\0\37\0\0\0\33\0" "\0\0\26\0\0\0\20\0\0\0\13\0\0\0\7\0\0\0\5\0\0\0\4\0\0\0\6\0\0\0\10\0\0\0" "\14\0\0\0\21\0\0\0\25\0\0\0\30\0\0\0\32\0\0\0\31\0\0\0\27\0\0\0\23\0\0\0" "\17\0\0\0\13\0\0\0\10\0\0\0\5\0\0\0\3\0\0\0\2\0\0\0\3\0\0\0\4\0\0\0\5\0\0" "\0\10\0\0\0\13\0\0\0\17\0\0\0\22\0\0\0\25\0\0\0\31\0\0\0\34\0\0\0\37\0\0" "\0\"\0\0\0$\0\0\0%\0\0\0$\0\0\0!\0\0\0\35\0\0\0\30\0\0\0\23\0\0\0\17\0\0" "\0\14\0\0\0\14\0\0\0\15\0\0\0\21\0\0\0\25\0\0\0\32\0\0\0\40\0\0\0%\0\0\0" "(\0\0\0*\0\0\0*\0\0\0(\0\0\0#\0\0\0\36\0\0\0\31\0\0\0\24\0\0\0\17\0\0\0\15" "\0\0\0\13\0\0\0\13\0\0\0\15\0\0\0\20\0\0\0\24\0\0\0\27\0\0\0\31\0\0\0\32" "\0\0\0\30\0\0\0\26\0\0\0\22\0\0\0\17\0\0\0\15\0\0\0\13\0\0\0\14\0\0\0\16" "\0\0\0\21\0\0\0\26\0\0\0\32\0\0\0\35\0\0\0\37\0\0\0\35\0\0\0\32\0\0\0\27" "\0\0\0\22\0\0\0\17\0\0\0\14\0\0\0\11\0\0\0\11\0\0\0\11\0\0\0\14\0\0\0\17" "\0\0\0\24\0\0\0\27\0\0\0\31\0\0\0\32\0\0\0\30\0\0\0\25\0\0\0\23\0\0\0\22" "\0\0\0\22\0\0\0\24\0\0\0\30\0\0\0\34\0\0\0\40\0\0\0#\0\0\0#\0\0\0!\0\0\0" "\36\0\0\0\31\0\0\0\24\0\0\0\20\0\0\0\16\0\0\0\16\0\0\0\20\0\0\0\25\0\0\0" "\32\0\0\0\37\0\0\0#\0\0\0&\0\0\0&\0\0\0%\0\0\0#\0\0\0\40\0\0\0\34\0\0\0\30" "\0\0\0\25\0\0\0\21\0\0\0\17\0\0\0\16\0\0\0\16\0\0\0\17\0\0\0\22\0\0\0\25" "\0\0\0\30\0\0\0\32\0\0\0\34\0\0\0\35\0\0\0\36\0\0\0\37\0\0\0!\0\0\0\"\0\0" "\0#\0\0\0#\0\0\0\"\0\0\0\40\0\0\0\36\0\0\0\34\0\0\0\32\0\0\0\30\0\0\0\27" "\0\0\0\27\0\0\0\27\0\0\0\26\0\0\0\26\0\0\0\25\0\0\0\25\0\0\0\26\0\0\0\26" "\0\0\0\30\0\0\0\31\0\0\0\31\0\0\0\30\0\0\0\27\0\0\0\25\0\0\0\24\0\0\0\24" "\0\0\0\25\0\0\0\30\0\0\0\34\0\0\0\40\0\0\0#\0\0\0%\0\0\0$\0\0\0\"\0\0\0\36" "\0\0\0\31\0\0\0\25\0\0\0\23\0\0\0\22\0\0\0\24\0\0\0\26\0\0\0\32\0\0\0\37" "\0\0\0%\0\0\0""0\0\0\0?\0\0\0TIIIk\335\335\335\206\35\35\35\235\0\0\0\261" "\0\0\0\276\27\27\27\307\32\32\32\315\0\0\0\321\0\0\0\324\0\0\0\326\0\0\0" "\326\0\0\0\325\0\0\0\317\0\0\0\304...\263\333\333\333\233\224\224\224\200" "\0\0\0`\0\0\0E\0\0\0,\0\0\0\33\0\0\0\16\0\0\0\7\0\0\0\3\0\0\0\2\0\0\0\4\0" "\0\0\6\0\0\0\12\0\0\0\15\0\0\0\20\0\0\0\22\0\0\0\23\0\0\0\22\0\0\0\21\0\0" "\0\17\0\0\0\13\0\0\0\10\0\0\0\6\0\0\0\4\0\0\0\3\0\0\0\2\0\0\0\3\0\0\0\4\0" "\0\0\6\0\0\0\11\0\0\0\13\0\0\0\15\0\0\0\16\0\0\0\15\0\0\0\14\0\0\0\12\0\0" "\0\10\0\0\0\6\0\0\0\4\0\0\0\3\0\0\0\2\0\0\0\1\0\0\0\2\0\0\0\2\0\0\0\3\0\0" "\0\4\0\0\0\6\0\0\0\7\0\0\0\11\0\0\0\13\0\0\0\15\0\0\0\16\0\0\0\20\0\0\0\22" "\0\0\0\24\0\0\0\24\0\0\0\24\0\0\0\22\0\0\0\20\0\0\0\15\0\0\0\12\0\0\0\10" "\0\0\0\6\0\0\0\6\0\0\0\7\0\0\0\11\0\0\0\13\0\0\0\16\0\0\0\21\0\0\0\24\0\0" "\0\26\0\0\0\30\0\0\0\27\0\0\0\26\0\0\0\23\0\0\0\21\0\0\0\15\0\0\0\12\0\0" "\0\10\0\0\0\6\0\0\0\6\0\0\0\6\0\0\0\7\0\0\0\11\0\0\0\13\0\0\0\14\0\0\0\15" "\0\0\0\15\0\0\0\14\0\0\0\13\0\0\0\11\0\0\0\10\0\0\0\6\0\0\0\6\0\0\0\6\0\0" "\0\7\0\0\0\11\0\0\0\14\0\0\0\16\0\0\0\20\0\0\0\20\0\0\0\20\0\0\0\16\0\0\0" "\14\0\0\0\11\0\0\0\10\0\0\0\6\0\0\0\5\0\0\0\5\0\0\0\5\0\0\0\6\0\0\0\10\0" "\0\0\12\0\0\0\14\0\0\0\15\0\0\0\15\0\0\0\14\0\0\0\13\0\0\0\12\0\0\0\11\0" "\0\0\11\0\0\0\13\0\0\0\15\0\0\0\17\0\0\0\22\0\0\0\23\0\0\0\23\0\0\0\22\0" "\0\0\20\0\0\0\16\0\0\0\13\0\0\0\11\0\0\0\7\0\0\0\7\0\0\0\11\0\0\0\13\0\0" "\0\16\0\0\0\21\0\0\0\23\0\0\0\25\0\0\0\25\0\0\0\24\0\0\0\23\0\0\0\21\0\0" "\0\17\0\0\0\14\0\0\0\12\0\0\0\11\0\0\0\10\0\0\0\7\0\0\0\7\0\0\0\10\0\0\0" "\11\0\0\0\13\0\0\0\15\0\0\0\16\0\0\0\17\0\0\0\17\0\0\0\20\0\0\0\20\0\0\0" "\21\0\0\0\22\0\0\0\23\0\0\0\23\0\0\0\22\0\0\0\21\0\0\0\20\0\0\0\16\0\0\0" "\15\0\0\0\14\0\0\0\14\0\0\0\13\0\0\0\13\0\0\0\13\0\0\0\13\0\0\0\13\0\0\0" "\13\0\0\0\13\0\0\0\13\0\0\0\14\0\0\0\14\0\0\0\15\0\0\0\14\0\0\0\13\0\0\0" "\13\0\0\0\12\0\0\0\12\0\0\0\13\0\0\0\15\0\0\0\17\0\0\0\21\0\0\0\23\0\0\0" "\24\0\0\0\24\0\0\0\23\0\0\0\20\0\0\0\16\0\0\0\13\0\0\0\12\0\0\0\11\0\0\0" "\12\0\0\0\14\0\0\0\16\0\0\0\21\0\0\0\26\0\0\0\37\0\0\0,\0\0\0>\0\0\0T\236" "\236\236l\313\313\313\201nnn\223\255\255\255\240\302\302\302\252\226\226" "\226\260hhh\265III\270\4\4\4\273\10\10\10\274\3\3\3\272\6\6\6\265\27\27\27" "\251\254\254\254\231\351\351\351\202BBBi\0\0\0M\0\0\0""6\0\0\0!\0\0\0\23" "\0\0\0\12\0\0\0\5\0\0\0\2\0\0\0\1\0\0\0\2\0\0\0\3\0\0\0\5\0\0\0\6\0\0\0\10" "\0\0\0\11\0\0\0\11\0\0\0\11\0\0\0\10\0\0\0\7\0\0\0\6\0\0\0\4\0\0\0\3\0\0" "\0\2\0\0\0\2\0\0\0\1\0\0\0\2\0\0\0\2\0\0\0\3\0\0\0\4\0\0\0\5\0\0\0\6\0\0" "\0\6\0\0\0\6\0\0\0\6\0\0\0\5\0\0\0\4\0\0\0\3\0\0\0\2\0\0\0\1\0\0\0\1\0\0" "\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\2\0\0\0\3\0\0\0\3\0\0\0\4\0\0\0\5\0\0" "\0\6\0\0\0\7\0\0\0\10\0\0\0\11\0\0\0\12\0\0\0\12\0\0\0\12\0\0\0\11\0\0\0" "\10\0\0\0\6\0\0\0\5\0\0\0\4\0\0\0\3\0\0\0\3\0\0\0\3\0\0\0\4\0\0\0\5\0\0\0" "\7\0\0\0\10\0\0\0\12\0\0\0\13\0\0\0\14\0\0\0\14\0\0\0\13\0\0\0\12\0\0\0\10" "\0\0\0\6\0\0\0\5\0\0\0\4\0\0\0\3\0\0\0\3\0\0\0\3\0\0\0\3\0\0\0\4\0\0\0\5" "\0\0\0\6\0\0\0\6\0\0\0\6\0\0\0\6\0\0\0\5\0\0\0\4\0\0\0\4\0\0\0\3\0\0\0\3" "\0\0\0\3\0\0\0\4\0\0\0\5\0\0\0\6\0\0\0\7\0\0\0\10\0\0\0\10\0\0\0\7\0\0\0" "\7\0\0\0\6\0\0\0\5\0\0\0\4\0\0\0\3\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\3\0\0\0" "\4\0\0\0\5\0\0\0\6\0\0\0\6\0\0\0\6\0\0\0\6\0\0\0\5\0\0\0\5\0\0\0\4\0\0\0" "\4\0\0\0\5\0\0\0\6\0\0\0\7\0\0\0\11\0\0\0\11\0\0\0\11\0\0\0\11\0\0\0\10\0" "\0\0\7\0\0\0\5\0\0\0\4\0\0\0\3\0\0\0\3\0\0\0\4\0\0\0\5\0\0\0\7\0\0\0\10\0" "\0\0\11\0\0\0\12\0\0\0\12\0\0\0\12\0\0\0\11\0\0\0\10\0\0\0\7\0\0\0\6\0\0" "\0\5\0\0\0\4\0\0\0\4\0\0\0\3\0\0\0\3\0\0\0\4\0\0\0\4\0\0\0\5\0\0\0\6\0\0" "\0\7\0\0\0\7\0\0\0\7\0\0\0\7\0\0\0\10\0\0\0\10\0\0\0\11\0\0\0\11\0\0\0\11" "\0\0\0\11\0\0\0\10\0\0\0\10\0\0\0\7\0\0\0\6\0\0\0\6\0\0\0\5\0\0\0\5\0\0\0" "\5\0\0\0\5\0\0\0\5\0\0\0\5\0\0\0\5\0\0\0\5\0\0\0\5\0\0\0\5\0\0\0\6\0\0\0" "\6\0\0\0\5\0\0\0\5\0\0\0\5\0\0\0\5\0\0\0\5\0\0\0\5\0\0\0\6\0\0\0\7\0\0\0" "\10\0\0\0\11\0\0\0\12\0\0\0\12\0\0\0\11\0\0\0\10\0\0\0\7\0\0\0\5\0\0\0\5" "\0\0\0\4\0\0\0\5\0\0\0\6\0\0\0\7\0\0\0\11\0\0\0\15\0\0\0\23\0\0\0\35\0\0" "\0,\0\0\0=\16\16\16Pzzzb\302\302\302r\302\302\302}\304\304\304\206\235\235" "\235\213\311\311\311\220\347\347\347\224\300\300\300\230\364\364\364\231" "\267\267\267\230\332\332\332\223\245\245\245\211\341\341\341zVVVe\20\20\20" "P\0\0\0""9\0\0\0'\0\0\0\27\0\0\0\15\0\0\0\7\0\0\0\3\0\0\0\2\0\0\0\1\0\0\0" "\1\0\0\0\2\0\0\0\2\0\0\0\3\0\0\0\4\0\0\0\4\0\0\0\5\0\0\0\5\0\0\0\4\0\0\0" "\4\0\0\0\3\0\0\0\2\0\0\0\2\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0" "\2\0\0\0\2\0\0\0\3\0\0\0\3\0\0\0\3\0\0\0\3\0\0\0\3\0\0\0\2\0\0\0\2\0\0\0" "\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0" "\1\0\0\0\2\0\0\0\2\0\0\0\3\0\0\0\3\0\0\0\4\0\0\0\4\0\0\0\4\0\0\0\5\0\0\0" "\5\0\0\0\5\0\0\0\4\0\0\0\4\0\0\0\3\0\0\0\3\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0" "\2\0\0\0\2\0\0\0\3\0\0\0\4\0\0\0\4\0\0\0\5\0\0\0\5\0\0\0\6\0\0\0\6\0\0\0" "\5\0\0\0\5\0\0\0\4\0\0\0\3\0\0\0\3\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0" "\2\0\0\0\2\0\0\0\3\0\0\0\3\0\0\0\3\0\0\0\3\0\0\0\3\0\0\0\3\0\0\0\2\0\0\0" "\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\3\0\0\0\4\0\0\0\4\0\0\0" "\4\0\0\0\4\0\0\0\3\0\0\0\3\0\0\0\2\0\0\0\2\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0" "\1\0\0\0\2\0\0\0\2\0\0\0\3\0\0\0\3\0\0\0\3\0\0\0\3\0\0\0\3\0\0\0\3\0\0\0" "\2\0\0\0\2\0\0\0\2\0\0\0\3\0\0\0\3\0\0\0\4\0\0\0\4\0\0\0\5\0\0\0\5\0\0\0" "\4\0\0\0\4\0\0\0\3\0\0\0\3\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\3\0\0\0" "\4\0\0\0\4\0\0\0\5\0\0\0\5\0\0\0\5\0\0\0\5\0\0\0\5\0\0\0\4\0\0\0\4\0\0\0" "\3\0\0\0\3\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\3\0\0\0" "\3\0\0\0\3\0\0\0\4\0\0\0\4\0\0\0\4\0\0\0\4\0\0\0\4\0\0\0\4\0\0\0\4\0\0\0" "\5\0\0\0\4\0\0\0\4\0\0\0\4\0\0\0\4\0\0\0\3\0\0\0\3\0\0\0\3\0\0\0\3\0\0\0" "\3\0\0\0\3\0\0\0\3\0\0\0\3\0\0\0\3\0\0\0\3\0\0\0\3\0\0\0\3\0\0\0\3\0\0\0" "\3\0\0\0\3\0\0\0\3\0\0\0\3\0\0\0\3\0\0\0\3\0\0\0\3\0\0\0\3\0\0\0\4\0\0\0" "\4\0\0\0\5\0\0\0\5\0\0\0\5\0\0\0\4\0\0\0\4\0\0\0\3\0\0\0\3\0\0\0\3\0\0\0" "\3\0\0\0\3\0\0\0\3\0\0\0\4\0\0\0\5\0\0\0\7\0\0\0\14\0\0\0\23\0\0\0\35\0\0" "\0*\0\0\0""8\0\0\0F\0\0\0R\0\0\0[\0\0\0b\0\0\0g\10\10\10l222p444sRRRu\232" "\232\232tFFFp\220\220\220gYYY[\0\0\0K\0\0\0:\0\0\0)\0\0\0\33\0\0\0\20\0\0" "\0\11\0\0\0\4\0\0\0\2\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\2\0\0" "\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\1\0\0\0\1\0\0\0\1\0\0" "\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0" "\0\2\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0" "\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0" "\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0" "\0\2\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\2\0\0" "\0\2\0\0\0\2\0\0\0\2\0\0\0\3\0\0\0\3\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0" "\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0" "\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0" "\0\1\0\0\0\1\0\0\0\1\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0" "\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0" "\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0" "\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\1\0\0" "\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0" "\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\1\0\0\0\1\0\0\0\1\0\0" "\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0" "\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0" "\0\2\0\0\0\2\0\0\0\2\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0" "\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0" "\0\1\0\0\0\1\0\0\0\1\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0\0\2\0\0" "\0\2\0\0\0\2\0\0\0\2\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\2\0\0" "\0\3\0\0\0\4\0\0\0\7\0\0\0\13\0\0\0\22\0\0\0\32\0\0\0#\0\0\0,\0\0\0""5\0" "\0\0;\0\0\0@\0\0\0D\0\0\0H\0\0\0K\0\0\0N\0\0\0P\0\0\0P\0\0\0M\0\0\0F\0\0" "\0=\0\0\0""2\0\0\0&\0\0\0\32\0\0\0\21\0\0\0\12\0\0\0\5\0\0\0\3\0\0\0\1\0" "\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0" "\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0" "\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0" "\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0" "\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0" "\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0" "\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\2\0" "\0\0\2\0\0\0\2\0\0\0\2\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0" "\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0" "\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0" "\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0" "\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0" "\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0" "\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0" "\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0" "\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0" "\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0" "\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0" "\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0" "\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0" "\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0" "\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\2\0\0\0\3\0\0\0\4\0" "\0\0\6\0\0\0\12\0\0\0\17\0\0\0\25\0\0\0\32\0\0\0\40\0\0\0$\0\0\0'\0\0\0*" "\0\0\0-\0\0\0/\0\0\0""2\0\0\0""3\0\0\0""3\0\0\0""1\0\0\0-\0\0\0'\0\0\0\37" "\0\0\0\30\0\0\0\20\0\0\0\12\0\0\0\6\0\0\0\3\0\0\0\2\0\0\0\1\0\0\0\1\0\0\0" "\1", }; fweelin-0.6/src/fweelin_mem.cc0000755000175000017500000004555711065526741015065 0ustar mercmerc/* I surrender, and God comes singing. */ /* Copyright 2004-2008 Jan Pekau (JP Mercury) This file is part of Freewheeling. Freewheeling is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. Freewheeling is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Freewheeling. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include "fweelin_mem.h" #include "fweelin_datatypes.h" MemoryManager::MemoryManager() : pts(0), apts(0) { // Init mutex/conditions pthread_mutex_init(&mgr_thread_lock,0); pthread_cond_init(&mgr_go,0); const static size_t STACKSIZE = 1024*128; pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setstacksize(&attr,STACKSIZE); printf("MEMMGR: Stacksize: %d.\n",STACKSIZE); // Setup manager thread threadgo = 1; int ret = pthread_create(&mgr_thread, &attr, run_mgr_thread, static_cast(this)); if (ret != 0) { printf("MEM: (memorymanager) pthread_create failed, exiting"); exit(1); } SRMWRingBuffer_Writers::RegisterWriter(mgr_thread); // Setup high priority threads struct sched_param schp; memset(&schp, 0, sizeof(schp)); schp.sched_priority = sched_get_priority_max(SCHED_OTHER); printf("MEM: Memory manager thread (p%d)\n",schp.sched_priority); if (pthread_setschedparam(mgr_thread, SCHED_OTHER, &schp) != 0) { printf("MEM: Can't set thread priority, will use regular!\n"); } }; MemoryManager::~MemoryManager() { // Terminate the manager thread threadgo = 0; pthread_mutex_lock (&mgr_thread_lock); pthread_cond_signal (&mgr_go); pthread_mutex_unlock (&mgr_thread_lock); pthread_join(mgr_thread,0); pthread_cond_destroy (&mgr_go); pthread_mutex_destroy (&mgr_thread_lock); printf("MEM: End manager thread.\n"); }; void MemoryManager::WakeUp(PreallocatedType *t) { // First, add the specified type to the list of active types if (apts == 0) { t->anext = 0; apts = t; } else { // Only add to active type list if it isn't already there! // This should be low overhead since the active types list will usually // be small PreallocatedType *cur = apts; while (cur->anext != 0 && cur != t) cur = cur->anext; if (cur != t) { t->anext = 0; cur->anext = t; } } // Wake up the manager thread if (pthread_mutex_trylock (&mgr_thread_lock) == 0) { pthread_cond_signal (&mgr_go); pthread_mutex_unlock (&mgr_thread_lock); } // *** Redesign active types list to be circular ring buffer-- // this would avoid potential loss of update on race condition to reset/read // apts /* else printf("MEM: Warning: Mgr thread active during mutex trylock.\n"); */ }; void MemoryManager::AddType(PreallocatedType *t) { pthread_mutex_lock (&mgr_thread_lock); if (pts == 0) pts = t; else { t->next = pts; pts = t; } pthread_mutex_unlock (&mgr_thread_lock); }; void MemoryManager::DelType(PreallocatedType *t) { pthread_mutex_lock (&mgr_thread_lock); if (apts != 0) printf("MEM: Warning: Active pre types not zero during DelType\n"); PreallocatedType *cur = pts, *prev = 0; // Search for type 't' in our list while (cur != 0 && cur != t) { prev = cur; cur = cur->next; } if (cur != 0) { // Got one to delete, unlink! if (prev != 0) prev->next = cur->next; else pts = cur->next; // Look in the active list { PreallocatedType *cur = apts; while (cur != 0 && cur != t) cur = cur->anext; if (cur != 0) { printf("MEM: ERROR: Deleted type found in active list!\n"); exit(1); } } // Necessary? cur->Cleanup(); } if (apts != 0) printf("MEM: Warning: Active pre types not zero during DelType\n"); pthread_mutex_unlock (&mgr_thread_lock); }; void *MemoryManager::run_mgr_thread (void *ptr) { MemoryManager *inst = static_cast(ptr); // printf("*** THREAD: %p\n",pthread_self()); pthread_mutex_lock(&inst->mgr_thread_lock); while (inst->threadgo) { // Go through all PreallocatedTypes in our active list PreallocatedType *cur = inst->apts; while (cur != 0) { if (cur->GetUpdateLists()) // Update free/inuse lists for this type cur->UpdateLists(); // Make sure there are enough free instances of this type cur->GoPreallocate(); // Next, look for instances pending delete! cur->GoPostdelete(); cur = cur->anext; } // Clear active type list until we are woken up again inst->apts = 0; // Wait for wakeup pthread_cond_wait (&inst->mgr_go, &inst->mgr_thread_lock); } printf("MEM: Begin cleanup.\n"); PreallocatedType *cur = inst->pts; while (cur != 0) { cur->Cleanup(); cur = cur->next; } printf("MEM: End cleanup.\n"); pthread_mutex_unlock(&inst->mgr_thread_lock); return 0; } PreallocatedType::PreallocatedType(MemoryManager *mmgr, Preallocated *prealloc_base, int instance_size, int prealloc_num_instances, char block_mode) : update_lists(0), instance_size(instance_size), prealloc_num_instances(prealloc_num_instances), block_mode(block_mode), block_last_idx(0), mmgr(mmgr), next(0), anext(0) { if (block_mode) { // Setup base block of instances if (prealloc_num_instances < 3) { printf("MEM: ERROR- Block mode must have at least 3 instances."); exit(1); } // Mark first instance in block as base Preallocated *cur = prealloc_base; cur->SetupPreallocated(this,Preallocated::PREALLOC_BASE_INSTANCE); /* printf("MEM: NEW BLOCK (STARTUP): %p, size: %d\n",cur, instance_size); */ // Rest are free cur = (Preallocated *) (((char *) cur) + instance_size); for (int i = 1; i < prealloc_num_instances; i++, cur = (Preallocated *) (((char *) cur) + instance_size)) { cur->SetupPreallocated(this, Preallocated::PREALLOC_PENDING_USE); if (i == 1) // Second instance contains # of free instances cur->predata.prealloc_num_free = prealloc_num_instances-1; } // Put base block in free (doesn't go in use until all are used) this->prealloc_base = prealloc_base; prealloc_free = prealloc_base; prealloc_inuse = 0; } else { // Setup the base instance prealloc_base-> SetupPreallocated(this,Preallocated::PREALLOC_BASE_INSTANCE); // Put base instance in use this->prealloc_base = prealloc_base; prealloc_free = 0; prealloc_inuse = prealloc_base; } // Make sure there are enough free instances GoPreallocate(); // Add ourselves to list of managed types mmgr->AddType(this); }; PreallocatedType::~PreallocatedType() { // Remove ourselves from list of managed types mmgr->DelType(this); }; // Realtime-safe function to get a new instance of this class Preallocated *PreallocatedType::RTNew() { Preallocated *nw = 0; if (block_mode) { Preallocated *cur = prealloc_free; char gogo = 1; while (gogo && cur != 0) { char go = 1; int idx = block_last_idx; nw = (Preallocated *) (((char *) cur) + idx*instance_size); while (go && nw->prealloc_status != Preallocated::PREALLOC_PENDING_USE) { idx++; nw = (Preallocated *) (((char *) nw) + instance_size); if (idx >= prealloc_num_instances) { idx = 0; nw = cur; } if (idx == block_last_idx) // We've checked the whole block, none free go = 0; } if (go) { // Found a free instance in this block, use it nw->prealloc_status = Preallocated::PREALLOC_IN_USE; block_last_idx = idx+1; if (block_last_idx >= prealloc_num_instances) block_last_idx = 0; Preallocated *second = (Preallocated *) (((char *) cur) + instance_size); second->predata.prealloc_num_free--; /* printf("MEM: RTNew (block %p, instance %p)- Num free: %d\n",cur, nw,second->predata.prealloc_num_free); */ // Less than half the block is free? if (second->predata.prealloc_num_free < prealloc_num_instances/2) { if (cur->predata.prealloc_next == 0) { // No other free blocks, so wakeup to allocate more // printf("MEM: RTNew (block)- Wakeup!\n"); mmgr->WakeUp(this); } if (second->predata.prealloc_num_free <= 0) { // No more free instances in this block-- // Update lists update_lists = 1; } } // Stop searching gogo = 0; } else { // No free instance in this block- // This can happen if memmgr hasn't yet updated its lists nw = 0; // printf("MEM: RTNew (block)- WARNING: Full block in free list.\n"); // Update lists update_lists = 1; // Search through next free block cur = cur->predata.prealloc_next; } } if (cur == 0) { // No free instances! printf("\nMEM: RTNew (block)- No instances available.\n"); mmgr->WakeUp(this); return 0; // Problem! No free instances! } } else { // Get the first free instance nw = prealloc_free; while (nw != 0 && nw->prealloc_status != Preallocated::PREALLOC_PENDING_USE) nw = nw->predata.prealloc_next; if (nw == 0) { printf("\nMEM: RTNew- No instances available:\n"); // DEBUG- Print status for all instances Preallocated *p = prealloc_free; printf("FREE LIST:\n"); while (p != 0) { printf("STATUS: %d\n",p->prealloc_status); p = p->predata.prealloc_next; } p = prealloc_inuse; printf("IN USE LIST:\n"); while (p != 0) { printf("STATUS: %d\n",p->prealloc_status); p = p->predata.prealloc_next; } mmgr->WakeUp(this); return 0; // Problem! No free instances! } nw->prealloc_status = Preallocated::PREALLOC_IN_USE; // Update lists update_lists = 1; // Wake up the memory manager to allocate new mmgr->WakeUp(this); } return nw; }; Preallocated *PreallocatedType::RTNewWithWait() { Preallocated *ret = 0; do { ret = RTNew(); if (ret == 0) { printf("MEM: Waiting for memory to be allocated.\n"); usleep(10000); } } while (ret == 0); return ret; }; // Realtime-safe function to delete this instance of this class // It might get slow if you have many blocks of instances void PreallocatedType::RTDelete(Preallocated *inst) { if (block_mode) { // Recycle the instance inst->Recycle(); // Mark as free inst->prealloc_status = Preallocated::PREALLOC_PENDING_USE; // Check pointer range to see which block this instance is in Preallocated *cur = prealloc_free; int blocksize = instance_size*prealloc_num_instances; while (cur != 0 && (inst < cur || (char *) inst >= ((char *) cur) + blocksize)) cur = cur->predata.prealloc_next; if (cur == 0) { cur = prealloc_inuse; while (cur != 0 && (inst < cur || (char *) inst >= ((char *) cur) + blocksize)) cur = cur->predata.prealloc_next; } if (cur == 0) { printf("MEM: RTDelete (block): WARNING: Instance %p not found " "in any block!\n",inst); return; } //printf("MEM: RTDelete (block %p, instance %p)\n",cur,inst); // Add to free count Preallocated *second = (Preallocated *) (((char *) cur) + instance_size); second->predata.prealloc_num_free++; // If we are going from having no free instances to having 1 free instance // then we probably need to move this block to free list if (second->predata.prealloc_num_free == 1) { // Update lists update_lists = 1; } } else { // Mark the instance pending delete!-- the rest happens in the thread inst->prealloc_status = Preallocated::PREALLOC_PENDING_DELETE; //printf("RTdel\n"); // Wake up the memory manager to delete the instance mmgr->WakeUp(this); } }; void PreallocatedType::UpdateLists() { // Flag that we have updated our lists update_lists = 0; // printf("MEM: UPDATE LISTS!\n"); // First, check for instances/blocks to move from free to in use list Preallocated *cur = prealloc_free, *prev = 0; while (cur != 0) { char movecur = 0; if (block_mode) { Preallocated *second = (Preallocated *) (((char *) cur) + instance_size); if (second->predata.prealloc_num_free <= 0) { // printf("MEM: Move block %p (free->inuse)\n",cur); movecur = 1; } } else if (!block_mode && (cur->prealloc_status == Preallocated::PREALLOC_IN_USE || cur->prealloc_status == Preallocated::PREALLOC_PENDING_DELETE)) { // printf("MEM: Move instance %p (free->inuse)\n",cur); movecur = 1; } if (movecur) { // This block/instance needs to move to the in use list // Insert at beginning of list // // *** Note that this will move the base instance so it is // *** no longer at the beginning of the in use list // *** For this reason, a separate 'prealloc_base' pointer has been // *** created Preallocated *tmp = cur->predata.prealloc_next; cur->predata.prealloc_next = prealloc_inuse; prealloc_inuse = cur; if (prev != 0) prev->predata.prealloc_next = tmp; else prealloc_free = tmp; cur = tmp; } else { prev = cur; cur = cur->predata.prealloc_next; } } // In block mode, we also need to check for blocks to move back // from the in use to the free list if (block_mode) { cur = prealloc_inuse; prev = 0; while (cur != 0) { Preallocated *second = (Preallocated *) (((char *) cur) + instance_size); if (second->predata.prealloc_num_free > 0) { // printf("MEM: Move block %p (inuse->free)\n",cur); // This block needs to move to the free list // Insert at beginning of list Preallocated *tmp = cur->predata.prealloc_next; cur->predata.prealloc_next = prealloc_free; prealloc_free = cur; if (prev != 0) prev->predata.prealloc_next = tmp; else prealloc_inuse = tmp; cur = tmp; } else { prev = cur; cur = cur->predata.prealloc_next; } } } }; void PreallocatedType::GoPostdelete() { // *** NOTE: Currently no support for deleting additional blocks // of instances- so if we are bursting to many instances // the memory overhead will remain *** if (!block_mode) { // *** This could be optimized with a separate list for instances // *** pending delete! Preallocated *cur = prealloc_inuse, *prev = 0; while (cur != 0) { if (cur->prealloc_status == Preallocated::PREALLOC_PENDING_DELETE) { // Remove instance from list Preallocated *tmp = cur->predata.prealloc_next; if (prev != 0) prev->predata.prealloc_next = tmp; else prealloc_inuse = tmp; // printf("del ptr: %p sz: %d!!\n",cur,sizeof(*cur)); ::delete cur; cur = tmp; } else { // Next instance prev = cur; cur = cur->predata.prealloc_next; } } } }; void PreallocatedType::GoPreallocate() { if (block_mode) { Preallocated *second = (Preallocated *) (((char *) prealloc_free) + instance_size); // Less than half the block is free? if (prealloc_free == 0 || second->predata.prealloc_num_free < prealloc_num_instances/2) { // OK, allocate a new block // * NewInstance must create an array of the right size for block // mode to work * Preallocated *nw_b = prealloc_base->NewInstance(); // printf("MEM: NEW BLOCK: %p!\n",nw_b); // Setup new block Preallocated *cur = nw_b; for (int i = 0; i < prealloc_num_instances; i++, cur = (Preallocated *) (((char *) cur) + instance_size)) { cur->SetupPreallocated(this,Preallocated::PREALLOC_PENDING_USE); if (i == 1) // Second instance contains # of free instances cur->predata.prealloc_num_free = prealloc_num_instances; } // Link it in nw_b->predata.prealloc_next = prealloc_free; prealloc_free = nw_b; } } else { // Make sure there are enough free instances int cnt = prealloc_num_instances; Preallocated *cur = prealloc_free, *prev = 0; while (cnt > 0 && cur != 0) { cnt--; prev = cur; cur = cur->predata.prealloc_next; } if (cnt > 0) { // We need more free instances, so let's make em if (prev == 0) { // First new instance prealloc_free = prev = prealloc_base->NewInstance(); prev->SetupPreallocated(this, /*Preallocated::PREALLOC_BASE_INSTANCE*/ Preallocated::PREALLOC_PENDING_USE); // printf("MEM: First new instance in free list!\n"); cnt--; } while (cnt > 0) { // More new instances // printf("MEM: new instance- typ: %p inuse: %p\n",this,prealloc_inuse); prev->predata.prealloc_next = cur = prealloc_base->NewInstance(); cur->SetupPreallocated(this,Preallocated::PREALLOC_PENDING_USE); prev = cur; cnt--; } } } }; void PreallocatedType::Cleanup() { // Ok, we've been told to stop // So we have to delete all preallocated instances/blocks! Preallocated *cur = prealloc_free; prealloc_free = 0; while (cur != 0) { // Remove instance from list Preallocated *tmp = cur->predata.prealloc_next; if (block_mode) { // printf("MEM: block delete from prealloc_free list: %p\n",cur); cur->DelBlock(); } else ::delete cur; cur = tmp; } cur = prealloc_inuse; prealloc_inuse = 0; while (cur != 0) { // Remove instance from list Preallocated *tmp = cur->predata.prealloc_next; if (block_mode) { // printf("MEM: block delete from prealloc_inuse list: %p\n",cur); cur->DelBlock(); } else ::delete cur; cur = tmp; } }; fweelin-0.6/src/fweelin_mem.h0000755000175000017500000002047511050104733014702 0ustar mercmerc#ifndef __FWEELIN_MEM_H #define __FWEELIN_MEM_H /* Copyright 2004-2008 Jan Pekau (JP Mercury) This file is part of Freewheeling. Freewheeling is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. Freewheeling is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Freewheeling. If not, see . */ class MemoryManager; class Preallocated; class PreallocatedType { friend class MemoryManager; public: // Default number of instances to keep preallocated const static int PREALLOC_DEFAULT_NUM_INSTANCES = 10; // Tells memory manager to start preallocating blocks of this type // Note for each type of preallocated data we can specify // a different number of instances to keep ready for RT consumption // // We must provide one instance of the Preallocated class as a reference // This is prealloc_base // // If block_mode is 1, an array of instances is used, and unused instances // are recycled instead of new ones constructed. PreallocatedType(MemoryManager *mmgr, Preallocated *prealloc_base, int instance_size, int prealloc_num_instances = PREALLOC_DEFAULT_NUM_INSTANCES, char block_mode = 0); // Stops preallocating this type ~PreallocatedType(); // Realtime-safe function to get a new instance of this class Preallocated *RTNew(); // RTNewWithWait() returns a new instance-- whereas RTNew returns 0 // if none is available, RTNewWithWait -waits- until one becomes available // -- not realtime safe -- Preallocated *RTNewWithWait(); // Realtime-safe function to delete this instance of this class void RTDelete(Preallocated *inst); // Perform any preallocations and pending deletes that are needed! // Called by memory manager void GoPreallocate(); void GoPostdelete(); // Update free and inuse lists so that free blocks and in use blocks // appear in the right lists- this can't be done in RT as it can break // the lists void UpdateLists(); // Cleanup- delete all preallocated instances of this type- called // on program exit void Cleanup(); inline int GetBlockSize() { return prealloc_num_instances; }; inline char GetUpdateLists() { return update_lists; }; private: char update_lists; // Flag- we need to update our free and inuse lists // b/c one free block is now inuse / vice versa // Actual size of one instance (we can't get it with RTTI, so you have to // pass it!) int instance_size; // Number of instances to keep preallocated int prealloc_num_instances; // Block mode or single instance mode? char block_mode; // Last block index scanned for free instances int block_last_idx; // List of free instances Preallocated *prealloc_free; // List of instances in use Preallocated *prealloc_inuse; // Base instance-- always available to use to create more instances Preallocated *prealloc_base; MemoryManager *mmgr; // MemoryManager maintains 2 lists of PreallocatedTypes PreallocatedType *next, *anext; // Next in active list }; // This class is a base for classes that want to be preallocated // and postdeleted-- classes in which new instances are needed // in realtime-- the memory allocation is done in a nonrealtime thread // // One such allocate&delete thread exists for all preallocated types // MemoryManager handles that thread. // // Using this class as a base adds some bytes of size to each instance // which might be a concern if you are allocating many instances! class Preallocated { friend class PreallocatedType; public: // Default constructor calls recycle to init this instance Preallocated() : prealloc_mgr(0) {}; virtual ~Preallocated() {}; void *operator new(size_t s) { printf("ERROR: Preallocated type can not be allocated directly\n"); exit(1); }; void operator delete(void *d) { //printf("ERROR: Preallocated type can not be deleted directly\n"); //exit(1); // We used to give an error message- // now we pass this delete on to RTDelete ((Preallocated *) d)->RTDelete(); } // Realtime-safe function to get a new instance of this class Preallocated *RTNew() { if (prealloc_mgr == 0) { // No mgr, so allocate nonRT way! //printf("WARNING: nonRT Prealloc in RTNew\n"); return NewInstance(); } else return prealloc_mgr->RTNew(); }; Preallocated *RTNewWithWait() { if (prealloc_mgr == 0) { // No mgr, so allocate nonRT way! //printf("WARNING: nonRT Prealloc in RTNew\n"); return NewInstance(); } else return prealloc_mgr->RTNewWithWait(); }; // Realtime-safe function to delete this instance of this class void RTDelete() { if (prealloc_mgr == 0) { // No mgr, nonRT delete! // printf("WARNING: nonRT delete in RTDelete: %p\n",this); ::delete this; } else prealloc_mgr->RTDelete(this); }; // Returns the PreallocatedType manager associated with this type inline PreallocatedType *GetMgr() { return prealloc_mgr; }; // Status values const static char PREALLOC_BASE_INSTANCE = 0, // Base instance, never deleted PREALLOC_PENDING_USE = 1, PREALLOC_IN_USE = 2, PREALLOC_PENDING_DELETE = 3; // This setup function is called from PreallocatedType // after a new instance of Preallocated is created. // It sets up the internal variables in this instance. void SetupPreallocated(PreallocatedType *mgr, char status) { prealloc_mgr = mgr; prealloc_status = status; predata.prealloc_next = 0; }; private: // Code to destroy a block of instances- only called in block mode // This is a workaround because operator delete[] is not virtual // and can not handle our arrays of derived instances #define FWMEM_DEFINE_DELBLOCK virtual void DelBlock() { ::delete[] this; }; FWMEM_DEFINE_DELBLOCK; // Code to call new operator for the derived class (nonRT) // All allocation and lengthy initialization can be done here // If this type is allocated in block mode, NewInstance must allocate // not one instance, but an array of instances with prealloc_num_instances // size virtual Preallocated *NewInstance() = 0; // Code to recycle an old instance to be used again // This is called *only* in block mode when an instance is RTDeleted. // Instead of deleting and constructing instances, we recycle // instances and pass them as new instances. // // So initialization code can go here, but this function // must be RT safe. virtual void Recycle() {}; // Status of this instance char prealloc_status; // PreallocatedType that manages the allocation of new instances // ** With a table, this could be optimized out of each instance ** PreallocatedType *prealloc_mgr; union { // In block mode, // Each instance is part of an array. And each array is part of a linked // list. So we have a list of blocks of instances. // The 1st instance in a block points to the next block. // The 2nd instance in a block holds the # of free instances in that block: int prealloc_num_free; // Next instance- or in block mode, next block of instances Preallocated *prealloc_next; } predata; }; class MemoryManager { public: MemoryManager(); ~MemoryManager(); // Starts managing the specified type void AddType(PreallocatedType *t); // Stops managing the specified type void DelType(PreallocatedType *t); // Wake up the manager thread- something to be done on the specified type void WakeUp(PreallocatedType *t); private: // Thread function static void *run_mgr_thread (void *ptr); // List of all PreallocatedTypes we are managing PreallocatedType *pts; // List of all PreallocatedTypes with activity pending PreallocatedType *apts; // Thread to preallocate and postdelete instances pthread_t mgr_thread; pthread_mutex_t mgr_thread_lock; pthread_cond_t mgr_go; int threadgo; }; #endif fweelin-0.6/src/fweelin_midiio.cc0000755000175000017500000010531711065526265015551 0ustar mercmerc/* Control is such a trick-- We can guide the ship but are we ever really in control of where we land? */ /* Copyright 2004-2008 Jan Pekau (JP Mercury) This file is part of Freewheeling. Freewheeling is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. Freewheeling is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Freewheeling. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include "fweelin_midiio.h" #include "fweelin_core.h" // ******** MIDI #define MIDI_CLIENT_NAME "FreeWheeling" #ifdef __MACOSX__ // ******** MACOSX MIDI void MidiIO::SetMIDIInput (int idx) { if (inputidx != -1) { // Deselect previous source MIDIEndpointRef src = MIDIGetSource(inputidx); if (src != 0) { //printf("DISCONNECT MIDI: %d\n",inputidx); MIDIPortDisconnectSource(in_ports[0], src); } } inputidx = idx; // Select new source MIDIEndpointRef src = MIDIGetSource(inputidx); if (src != 0) { //printf("CONNECT MIDI: %d\n",inputidx); MIDIPortConnectSource(in_ports[0], src, 0); } }; // Open MIDI engine with num_in writeable ports and num_out readable ports. // Nonzero is returned on error char MidiIO::open_midi (int num_in, int num_out) { if (MIDIClientCreate(CFSTR(MIDI_CLIENT_NAME), 0, 0, &client) != noErr) { fprintf(stderr, "MIDI: Error opening MIDI client.\n"); return -1; } int l1; char portname[64]; numins = num_in; numouts = num_out; in_ports = new MIDIPortRef[num_in]; out_ports = new MIDIPortRef[num_out]; out_sources = new MIDIEndpointRef[num_out]; for (l1 = 0; l1 < num_in; l1++) { sprintf(portname, MIDI_CLIENT_NAME " IN %d", l1+1); if (MIDIInputPortCreate(client, CFStringCreateWithCString(0,portname,kCFStringEncodingUTF8), MidiInputProc, this, &in_ports[l1]) != noErr) { fprintf(stderr, "MIDI: Error creating MIDI port.\n"); return -1; } } for (l1 = 0; l1 < num_out; l1++) { sprintf(portname, MIDI_CLIENT_NAME " OUT %d", l1+1); if (MIDIOutputPortCreate(client, CFStringCreateWithCString(0,portname,kCFStringEncodingUTF8), &out_ports[l1]) != noErr) { fprintf(stderr, "MIDI: Error creating MIDI port.\n"); return -1; } } // Make list of input sources int n = MIDIGetNumberOfSources(); printf("MIDI: Input possible from %d sources.\n", n); CFStringRef endname; char cendname[1024]; FweelinMac::ClearMIDIInputList(); for (int i = 0; i < n; ++i) { MIDIEndpointRef src = MIDIGetSource(i); MIDIObjectGetStringProperty(src, kMIDIPropertyName, &endname); CFStringGetCString(endname, cendname, 1024, kCFStringEncodingUTF8); printf(" MIDI: source name: %s\n",cendname); FweelinMac::AddMIDIInputSource(cendname); } // Connect first input SetMIDIInput(0); #if 0 // We no longer use MIDISend to send to destinations-- // because many apps connect to sources, we instead create virtual sources for each output // and use MIDIReceived to send to them // Discover a place to send MIDI data n = MIDIGetNumberOfDestinations(); printf("MIDI: Output possible to %d destinations.\n",n); if (n > 0) dest = MIDIGetDestination(n-1); if (dest == 0) { printf("MIDI: WARNING: No place to send MIDI.\n"); return 0; // No place to send data } // Get name of destination we are sending to CFStringRef pName; char name[64]; MIDIObjectGetStringProperty(dest, kMIDIPropertyName, &pName); CFStringGetCString(pName, name, sizeof(name), 0); CFRelease(pName); printf("MIDI: Sending MIDI to destination: %s\n", name); // MIDI transmit using destinations #define MIDI_TRANSMIT(idx) MIDISend(out_ports[idx], dest, packetList) #else dest = 0; // Create virtual sources char sourcename[64]; for (int i = 0; i < num_out; i++) { sprintf(sourcename, MIDI_CLIENT_NAME " OUT %d", i+1); if (MIDISourceCreate(client,CFStringCreateWithCString(0,sourcename,kCFStringEncodingUTF8), &out_sources[i]) != noErr) { fprintf(stderr, "MIDI: Error creating virtual MIDI source.\n"); return -1; } } // MIDI transmit using virtual sources #define MIDI_TRANSMIT(idx) MIDIReceived(out_sources[idx], packetList) #endif return 0; } int MidiIO::activate() { FloConfig *fs = app->getCFG(); // Open up MIDI if (open_midi(1, fs->GetNumMIDIOuts())) { fprintf(stderr, "MIDI: Can't open MIDI client.\n"); exit(1); } listen_events(); // Request initial patch from patch browser PatchBrowser *br = (PatchBrowser *) app->getBROWSER(B_Patch); if (br != 0) br->SetMIDIEcho(); return 0; } void MidiIO::close() { printf("MIDI: begin close...\n"); unlisten_events(); printf("MIDI: end\n"); } void MidiIO::MidiInputProc (const MIDIPacketList *pktlist, void *refCon, void *connRefCon) { MidiIO *inst = static_cast(refCon); MIDIPacket *packet = (MIDIPacket *) pktlist->packet; for (int j = 0; j < pktlist->numPackets; j++) { if ((packet->data[0] >= 0x80 && packet->data[0] <= 0x8F) || (packet->data[0] >= 0x90 && packet->data[0] <= 0x9F && packet->data[2] == 0)) { // Interpret NoteOn velocity 0 as note off // Note Off int base = (packet->data[0] >= 0x90 ? 0x90 : 0x80); inst->ReceiveNoteOffEvent(packet->data[0] - base, packet->data[1], packet->data[2]); } else if (packet->data[0] >= 0x90 && packet->data[0] <= 0x9F) { // Note On inst->ReceiveNoteOnEvent(packet->data[0] - 0x90, packet->data[1], packet->data[2]); } else if (packet->data[0] >= 0xB0 && packet->data[0] <= 0xBF) { // Control Change inst->ReceiveControlChangeEvent(packet->data[0] - 0xB0, packet->data[1], packet->data[2]); } else if (packet->data[0] >= 0xC0 && packet->data[0] <= 0xCF) { // Program Change inst->ReceiveProgramChangeEvent(packet->data[0] - 0xC0, packet->data[1]); } else if (packet->data[0] >= 0xD0 && packet->data[0] <= 0xDF) { // Channel Pressure inst->ReceiveChannelPressureEvent(packet->data[0] - 0xD0, packet->data[1]); } else if (packet->data[0] >= 0xE0 && packet->data[0] <= 0xEF) { // Pitch Bend int lsb = packet->data[1], msb = packet->data[2], benderval = msb << 8 + lsb; inst->ReceivePitchBendEvent(packet->data[0] - 0xE0, benderval); } // Advance packet = MIDIPacketNext(packet); } } void MidiIO::OutputController (int port, int chan, int ctrl, int val) { unsigned char msg[3]; msg[0] = 0xB0 + chan; msg[1] = (unsigned char) ctrl; if (val > 127) val = 127; else if (val < 0) val = 0; msg[2] = (unsigned char) val; curPacket = MIDIPacketListAdd(packetList,sizeof(obuf), curPacket,0 /*Now*/,3,msg); }; void MidiIO::OutputProgramChange (int port, int chan, int val) { unsigned char msg[2]; msg[0] = 0xC0 + chan; if (val > 127) val = 127; else if (val < 0) val = 0; msg[1] = (unsigned char) val; curPacket = MIDIPacketListAdd(packetList,sizeof(obuf), curPacket,0 /*Now*/,2,msg); }; void MidiIO::OutputChannelPressure (int port, int chan, int val) { unsigned char msg[2]; msg[0] = 0xD0 + chan; if (val > 127) val = 127; else if (val < 0) val = 0; msg[1] = (unsigned char) val; curPacket = MIDIPacketListAdd(packetList,sizeof(obuf), curPacket,0 /*Now*/,2,msg); }; void MidiIO::OutputPitchBend (int port, int chan, int val) { unsigned char msg[3]; msg[0] = 0xE0 + chan; msg[1] = (unsigned char) (val & 0x00FF); // LSB msg[2] = (unsigned char) (val >> 8); // MSB curPacket = MIDIPacketListAdd(packetList,sizeof(obuf), curPacket,0 /*Now*/,3,msg); }; void MidiIO::OutputNote (int port, int chan, char down, int notenum, int vel) { unsigned char msg[3]; if (down) msg[0] = 0x90 + chan; // NoteOn else msg[0] = 0x80 + chan; // NoteOff msg[1] = (unsigned char) notenum; msg[2] = (unsigned char) vel; curPacket = MIDIPacketListAdd(packetList,sizeof(obuf), curPacket,0 /*Now*/,3,msg); }; void MidiIO::OutputClock (int port) { unsigned char msg = 0xF8; curPacket = MIDIPacketListAdd(packetList,sizeof(obuf), curPacket,0 /*Now*/,1,&msg); }; void MidiIO::OutputStart (int port) { unsigned char msg = 0xFA; curPacket = MIDIPacketListAdd(packetList,sizeof(obuf), curPacket,0 /*Now*/,1,&msg); }; void MidiIO::OutputStop (int port) { unsigned char msg = 0xFC; curPacket = MIDIPacketListAdd(packetList,sizeof(obuf), curPacket,0 /*Now*/,1,&msg); }; void MidiIO::OutputStartOnPort () { // Init output packet curPacket = MIDIPacketListInit(packetList); }; void MidiIO::OutputEndOnPort (int port) { // Send MIDI packet- all messages for this port MIDI_TRANSMIT(port); }; #else // ******** LINUX MIDI // Open MIDI engine with num_in writeable ports and num_out readable ports. // Nonzero is returned on error char MidiIO::open_midi (int num_in, int num_out) { int l1; char portname[64]; numins = num_in; numouts = num_out; in_ports = new int[num_in]; out_ports = new int[num_out]; if (snd_seq_open(&seq_handle, "default", SND_SEQ_OPEN_DUPLEX, 0) < 0) { fprintf(stderr, "MIDI: Error opening ALSA MIDI.\n"); return -1; } snd_seq_set_client_name(seq_handle, MIDI_CLIENT_NAME); for (l1 = 0; l1 < num_in; l1++) { sprintf(portname, MIDI_CLIENT_NAME " IN %d", l1+1); if ((in_ports[l1] = snd_seq_create_simple_port(seq_handle, portname, SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE, SND_SEQ_PORT_TYPE_APPLICATION)) < 0) { fprintf(stderr, "MIDI: Error creating MIDI port.\n"); return -1; } } for (l1 = 0; l1 < num_out; l1++) { sprintf(portname, MIDI_CLIENT_NAME " OUT %d", l1+1); if ((out_ports[l1] = snd_seq_create_simple_port(seq_handle, portname, SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, SND_SEQ_PORT_TYPE_APPLICATION)) < 0) { fprintf(stderr, "MIDI: Error creating MIDI port.\n"); return -1; } } return 0; } int MidiIO::activate() { // Linux MIDI handling using ALSA seq on its own thread printf("MIDI: Starting MIDI thread..\n"); const static size_t STACKSIZE = 1024*64; pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setstacksize(&attr,STACKSIZE); printf("MIDI: Stacksize: %d.\n",STACKSIZE); midithreadgo = 1; int ret = pthread_create(&midi_thread, &attr, run_midi_thread, this); if (ret != 0) { printf("(start) pthread_create failed, exiting"); return 1; } SRMWRingBuffer_Writers::RegisterWriter(midi_thread); // Setup high priority threads struct sched_param schp; memset(&schp, 0, sizeof(schp)); // MIDI thread at SCHED_FIFO- yes! High priority! //schp.sched_priority = sched_get_priority_max(SCHED_OTHER); //schp.sched_priority = sched_get_priority_min(SCHED_FIFO); schp.sched_priority = sched_get_priority_max(SCHED_FIFO); printf("MIDI: HiPri Thread %d\n",schp.sched_priority); if (pthread_setschedparam(midi_thread, SCHED_FIFO /* OTHER */, &schp) != 0) { printf("MIDI: Can't set realtime thread, will use nonRT!\n"); } // Request initial patch from patch browser PatchBrowser *br = (PatchBrowser *) app->getBROWSER(B_Patch); if (br != 0) br->SetMIDIEcho(); return 0; } void MidiIO::close() { printf("MIDI: begin close...\n"); midithreadgo = 0; pthread_join(midi_thread,0); printf("MIDI: end\n"); } void *MidiIO::run_midi_thread(void *ptr) { MidiIO *inst = static_cast(ptr); int npfd; struct pollfd *pfd; FloConfig *fs = inst->app->getCFG(); printf("MIDIthread start..\n"); // printf("*** MIDI THREAD: %li\n",pthread_self()); // Open up ALSA MIDI client if (inst->open_midi(1, fs->GetNumMIDIOuts())) { fprintf(stderr, "MIDI: Can't open ALSA MIDI.\n"); exit(1); } npfd = snd_seq_poll_descriptors_count(inst->seq_handle, POLLIN); pfd = (struct pollfd *)alloca(npfd * sizeof(struct pollfd)); snd_seq_poll_descriptors(inst->seq_handle, pfd, npfd, POLLIN); inst->listen_events(); // Main MIDI loop while (inst->midithreadgo) { // Every second, come out of poll-- so we don't get locked up // if no MIDI events come in if (poll(pfd, npfd, 1000) > 0) { // There's an event here! Read! snd_seq_event_t *ev; // static int cnt = 0; do { snd_seq_event_input(inst->seq_handle, &ev); switch (ev->type) { #if 0 case SND_SEQ_EVENT_QFRAME: printf("MTC quarterframe\n"); break; case SND_SEQ_EVENT_CLOCK: if (cnt % 24 == 0) printf("clock: %d\n",cnt); cnt++; //printf("clock: %d\n",ev->data.time.tick); //printf("clock: %d\n",ev->data.time.time.tv_sec); //printf("clock: %d\n",ev->data.queue.param.time.time.tv_sec); break; case SND_SEQ_EVENT_TICK: printf("MIDI: 'tick' not yet implemented\n"); break; case SND_SEQ_EVENT_TEMPO: printf("MIDI: 'tempo' not yet implemented\n"); break; #endif case SND_SEQ_EVENT_CONTROLLER: // Control Change inst->ReceiveControlChangeEvent(ev->data.control.channel, ev->data.control.param, ev->data.control.value); break; case SND_SEQ_EVENT_CHANPRESS: // Channel aftertouch inst->ReceiveChannelPressureEvent(ev->data.control.channel, ev->data.control.value); break; case SND_SEQ_EVENT_PGMCHANGE: // Program Change inst->ReceiveProgramChangeEvent(ev->data.control.channel, ev->data.control.value); break; case SND_SEQ_EVENT_PITCHBEND: // Pitch Bend inst->ReceivePitchBendEvent(ev->data.control.channel, ev->data.control.value); break; case SND_SEQ_EVENT_NOTEON: // Note On inst->ReceiveNoteOnEvent(ev->data.control.channel, ev->data.note.note, ev->data.note.velocity); break; case SND_SEQ_EVENT_NOTEOFF: // Note Off inst->ReceiveNoteOffEvent(ev->data.control.channel, ev->data.note.note, ev->data.note.velocity); break; } snd_seq_free_event(ev); } while (snd_seq_event_input_pending(inst->seq_handle, 0) > 0); } } inst->unlisten_events(); printf("MIDI: thread done\n"); return 0; } void MidiIO::OutputController (int port, int chan, int ctrl, int val) { if (val > 127) val = 127; else if (val < 0) val = 0; snd_seq_event_t outev; snd_seq_ev_set_subs(&outev); snd_seq_ev_set_direct(&outev); snd_seq_ev_set_source(&outev,out_ports[port]); snd_seq_ev_set_controller(&outev,chan,ctrl,val); snd_seq_event_output_direct(seq_handle, &outev); }; void MidiIO::OutputProgramChange (int port, int chan, int val) { if (val > 127) val = 127; else if (val < 0) val = 0; snd_seq_event_t outev; snd_seq_ev_set_subs(&outev); snd_seq_ev_set_direct(&outev); snd_seq_ev_set_source(&outev,out_ports[port]); snd_seq_ev_set_pgmchange(&outev,chan,val); snd_seq_event_output_direct(seq_handle, &outev); }; void MidiIO::OutputChannelPressure (int port, int chan, int val) { if (val > 127) val = 127; else if (val < 0) val = 0; snd_seq_event_t outev; snd_seq_ev_set_subs(&outev); snd_seq_ev_set_direct(&outev); snd_seq_ev_set_source(&outev,out_ports[port]); snd_seq_ev_set_chanpress(&outev,chan,val); snd_seq_event_output_direct(seq_handle, &outev); }; void MidiIO::OutputPitchBend (int port, int chan, int val) { snd_seq_event_t outev; snd_seq_ev_set_subs(&outev); snd_seq_ev_set_direct(&outev); snd_seq_ev_set_source(&outev,out_ports[port]); snd_seq_ev_set_pitchbend(&outev,chan,val); snd_seq_event_output_direct(seq_handle, &outev); }; void MidiIO::OutputNote (int port, int chan, char down, int notenum, int vel) { snd_seq_event_t outev; snd_seq_ev_set_subs(&outev); snd_seq_ev_set_direct(&outev); snd_seq_ev_set_source(&outev,out_ports[port]); if (down) snd_seq_ev_set_noteon(&outev,chan,notenum,vel); else snd_seq_ev_set_noteoff(&outev,chan,notenum,vel); snd_seq_event_output_direct(seq_handle, &outev); }; void MidiIO::OutputClock (int port) { snd_seq_event_t outev; snd_seq_ev_set_subs(&outev); snd_seq_ev_set_direct(&outev); snd_seq_ev_set_source(&outev,out_ports[port]); outev.type = SND_SEQ_EVENT_CLOCK; snd_seq_ev_set_fixed(&outev); snd_seq_event_output_direct(seq_handle, &outev); }; void MidiIO::OutputStart (int port) { snd_seq_event_t outev; snd_seq_ev_set_subs(&outev); snd_seq_ev_set_direct(&outev); snd_seq_ev_set_source(&outev,out_ports[port]); outev.type = SND_SEQ_EVENT_START; snd_seq_ev_set_fixed(&outev); snd_seq_event_output_direct(seq_handle, &outev); }; void MidiIO::OutputStop (int port) { snd_seq_event_t outev; snd_seq_ev_set_subs(&outev); snd_seq_ev_set_direct(&outev); snd_seq_ev_set_source(&outev,out_ports[port]); outev.type = SND_SEQ_EVENT_STOP; snd_seq_ev_set_fixed(&outev); snd_seq_event_output_direct(seq_handle, &outev); }; // Events are sent directly- no buffer emptying necessary void MidiIO::OutputStartOnPort () {}; void MidiIO::OutputEndOnPort (int port) {}; #endif // ******** CROSS-PLATFORM MIDI CODE MidiIO::MidiIO (Fweelin *app) : bendertune(0), curbender(0), echoport(1), echochan(-1), curpatch(0), numins(0), numouts(0), app(app), #ifdef __MACOSX__ client(0), in_ports(0), out_ports(0), out_sources(0), dest(0), inputidx(-1), curPacket(0), packetList((MIDIPacketList *) obuf), #else seq_handle(0), in_ports(0), out_ports(0), midithreadgo(0), #endif midisyncxmit(0) { note_def_port = new int[MAX_MIDI_NOTES]; note_patch = new PatchItem *[MAX_MIDI_NOTES]; memset(note_def_port,0,sizeof(int) * MAX_MIDI_NOTES); memset(note_patch,0,sizeof(PatchItem *) * MAX_MIDI_NOTES); }; void MidiIO::listen_events () { FloConfig *fs = app->getCFG(); app->getEMG()->ListenEvent(this,0,T_EV_SetMidiTuning); app->getEMG()->ListenEvent(this,0,T_EV_SetMidiEchoPort); app->getEMG()->ListenEvent(this,0,T_EV_SetMidiEchoChannel); app->getEMG()->ListenEvent(this,fs->GetInputMatrix(), T_EV_Input_MIDIKey); app->getEMG()->ListenEvent(this,fs->GetInputMatrix(), T_EV_Input_MIDIController); app->getEMG()->ListenEvent(this,fs->GetInputMatrix(), T_EV_Input_MIDIProgramChange); app->getEMG()->ListenEvent(this,fs->GetInputMatrix(), T_EV_Input_MIDIPitchBend); app->getEMG()->ListenEvent(this,0,T_EV_Input_MIDIClock); app->getEMG()->ListenEvent(this,0,T_EV_Input_MIDIStartStop); } void MidiIO::unlisten_events () { FloConfig *fs = app->getCFG(); app->getEMG()->UnlistenEvent(this,0,T_EV_SetMidiTuning); app->getEMG()->UnlistenEvent(this,0,T_EV_SetMidiEchoPort); app->getEMG()->UnlistenEvent(this,0,T_EV_SetMidiEchoChannel); app->getEMG()->UnlistenEvent(this,fs->GetInputMatrix(), T_EV_Input_MIDIKey); app->getEMG()->UnlistenEvent(this,fs->GetInputMatrix(), T_EV_Input_MIDIController); app->getEMG()->UnlistenEvent(this,fs->GetInputMatrix(), T_EV_Input_MIDIProgramChange); app->getEMG()->UnlistenEvent(this,fs->GetInputMatrix(), T_EV_Input_MIDIPitchBend); app->getEMG()->UnlistenEvent(this,0,T_EV_Input_MIDIClock); app->getEMG()->UnlistenEvent(this,0,T_EV_Input_MIDIStartStop); } void MidiIO::ReceiveNoteOffEvent (int channel, int notenum, int vel) { // Note Off MIDIKeyInputEvent *mevt = (MIDIKeyInputEvent *) Event::GetEventByType(T_EV_Input_MIDIKey); mevt->down = 0; mevt->channel = channel; mevt->notenum = notenum; if (mevt->notenum < 0 || mevt->notenum >= MAX_MIDI_NOTES) { printf("MIDI: Bad MIDI note #%d!\n",mevt->notenum); mevt->notenum = 0; } mevt->vel = vel; mevt->outport = note_def_port[mevt->notenum]; if (app->getCFG()->IsDebugInfo()) printf("MIDI: Note %d off, channel %d velocity %d\n", mevt->notenum, mevt->channel, mevt->vel); app->getEMG()->BroadcastEventNow(mevt, this); }; void MidiIO::ReceiveNoteOnEvent (int channel, int notenum, int vel) { MIDIKeyInputEvent *mevt = (MIDIKeyInputEvent *) Event::GetEventByType(T_EV_Input_MIDIKey); mevt->channel = channel; mevt->notenum = notenum; if (mevt->notenum < 0 || mevt->notenum >= MAX_MIDI_NOTES) { printf("MIDI: Bad MIDI note #%d!\n",mevt->notenum); mevt->notenum = 0; } mevt->vel = vel; if (vel > 0) { mevt->down = 1; note_def_port[mevt->notenum] = mevt->outport = echoport; note_patch[mevt->notenum] = curpatch; } else { mevt->down = 0; mevt->outport = note_def_port[mevt->notenum]; } if (app->getCFG()->IsDebugInfo()) printf("MIDI: Note %d %s, channel %d velocity %d\n", mevt->notenum, (mevt->down ? "on" : "off"), mevt->channel, mevt->vel); app->getEMG()->BroadcastEventNow(mevt, this); } void MidiIO::ReceivePitchBendEvent (int channel, int value) { // Store incoming bender value curbender = value; // Perform tune value += bendertune; MIDIPitchBendInputEvent *mevt = (MIDIPitchBendInputEvent *) Event::GetEventByType(T_EV_Input_MIDIPitchBend); mevt->outport = echoport; mevt->channel = channel; mevt->val = value; if (app->getCFG()->IsDebugInfo()) printf("MIDI: Pitchbend channel %d value %d\n", mevt->channel,mevt->val); app->getEMG()->BroadcastEventNow(mevt, this); } void MidiIO::ReceiveChannelPressureEvent (int channel, int value) { MIDIChannelPressureInputEvent *mevt = (MIDIChannelPressureInputEvent *) Event::GetEventByType(T_EV_Input_MIDIChannelPressure); mevt->outport = echoport; mevt->channel = channel; mevt->val = value; if (app->getCFG()->IsDebugInfo()) printf("MIDI: Channel pressure channel %d value %d\n", mevt->channel,mevt->val); app->getEMG()->BroadcastEventNow(mevt, this); } void MidiIO::ReceiveProgramChangeEvent (int channel, int value) { MIDIProgramChangeInputEvent *mevt = (MIDIProgramChangeInputEvent *) Event::GetEventByType(T_EV_Input_MIDIProgramChange); mevt->outport = echoport; mevt->channel = channel; mevt->val = value; if (app->getCFG()->IsDebugInfo()) printf("MIDI: Program change channel %d value %d\n", mevt->channel,mevt->val); app->getEMG()->BroadcastEventNow(mevt, this); } void MidiIO::ReceiveControlChangeEvent (int channel, int ctrl, int value) { MIDIControllerInputEvent *mevt = (MIDIControllerInputEvent *) Event::GetEventByType(T_EV_Input_MIDIController); mevt->outport = echoport; mevt->channel = channel; mevt->ctrl = ctrl; mevt->val = value; if (app->getCFG()->IsDebugInfo()) printf("MIDI: Controller %d channel %d value %d\n",mevt->ctrl, mevt->channel,mevt->val); app->getEMG()->BroadcastEventNow(mevt, this); } MidiIO::~MidiIO() { delete[] note_def_port; delete[] note_patch; if (in_ports != 0) delete[] in_ports; if (out_ports != 0) delete[] out_ports; #ifdef __MACOSX__ if (out_sources != 0) delete[] out_sources; #endif } void MidiIO::SetMIDIEcho (int def_port, PatchItem *patch) { if (CRITTERS) printf("MIDI: Set Echo Port: %d Patch: %s\n",def_port, (patch != 0 ? patch->name : "(none)")); // Save default port char outportschanged = 0, usefluid = 0; // Enable FluidSynth? if (def_port >= 0 && def_port <= numouts) { if (def_port != echoport) { echoport = def_port; outportschanged = 1; if (echoport == 0) usefluid = 1; } } else printf("MIDI: Invalid port #%d (valid range 0-%d)\n", def_port,numouts); if (patch != 0) { if (patch->IsCombi()) { // Store reference to patch, to get zones later if (patch != curpatch) { curpatch = patch; // Check if FluidSynth port is referenced- outportschanged = 1; usefluid = 0; for (int i = 0; i < patch->numzones && !usefluid; i++) { CombiZone *z = patch->GetZone(i); if ((!z->port_r && echoport == 0) || // Port 0 is FluidSynth (z->port_r && z->port == 0)) usefluid = 1; } if (CRITTERS) printf("MIDI: COMBI PATCH!\n"); } } else { // Easy, single channel patch curpatch = patch; echochan = patch->channel; } } if (outportschanged) { // If ports changed // Enable/Disable FluidSynth engine FluidSynthEnableEvent *fsevt = (FluidSynthEnableEvent *) Event::GetEventByType(T_EV_FluidSynthEnable); fsevt->enable = usefluid; app->getEMG()->BroadcastEventNow(fsevt, this); } } void MidiIO::ReceiveEvent(Event *ev, EventProducer *from) { // Handle special events for MIDI switch (ev->GetType()) { case T_EV_SetMidiTuning : { SetMidiTuningEvent *tev = (SetMidiTuningEvent *) ev; // OK! if (CRITTERS) printf("MIDI: Received SetMidiTuning " "(new tuning: %d)\n", tev->tuning); SetBenderTune(tev->tuning); } return; #if 0 case T_EV_SetMidiEchoPort : { SetMidiEchoPortEvent *pev = (SetMidiEchoPortEvent *) ev; // OK! if (CRITTERS) printf("MIDI: Received SetMidiEchoPort " "(port #: %d)\n", pev->echoport); if (pev->echoport >= 0 && pev->echoport <= numouts) echoport = pev->echoport; else printf("MIDI: Invalid port #%d (valid range 0-%d)\n", pev->echoport,numouts); } return; case T_EV_SetMidiEchoChannel : { SetMidiEchoChannelEvent *cev = (SetMidiEchoChannelEvent *) ev; // OK! if (CRITTERS) printf("MIDI: Received SetMidiEchoChannel " "(channel #: %d)\n", cev->echochannel); echochan = cev->echochannel; } return; #endif default: break; } // Unhandled event?-- echo back to MIDI outs EchoEvent(ev); } int MidiIO::EchoEventToPortChannel (Event *ev, int port, int channel) { FloConfig *fs = app->getCFG(); // DEBUG // printf("ECHO EVENT -> Port: %d Channel: %d\n",port,channel); int ret = -1; switch (ev->GetType()) { case T_EV_Input_MIDIClock : { // MIDIClockInputEvent *clkevt = (MIDIClockInputEvent *) ev; OutputClock(ret = port); } break; case T_EV_Input_MIDIStartStop : { MIDIStartStopInputEvent *ssevt = (MIDIStartStopInputEvent *) ev; if (ssevt->start) OutputStart(ret = port); else OutputStop(ret = port); } break; case T_EV_Input_MIDIController : { MIDIControllerInputEvent *mcev = (MIDIControllerInputEvent *) ev; OutputController(ret = (port == -1 ? mcev->outport-1 : port), (channel == -1 ? mcev->channel : channel), mcev->ctrl, mcev->val); } break; case T_EV_Input_MIDIProgramChange : { MIDIProgramChangeInputEvent *mpev = (MIDIProgramChangeInputEvent *) ev; OutputProgramChange(ret = (port == -1 ? mpev->outport-1 : port), (channel == -1 ? mpev->channel : channel), mpev->val); } break; case T_EV_Input_MIDIChannelPressure : { MIDIChannelPressureInputEvent *mpev = (MIDIChannelPressureInputEvent *) ev; OutputChannelPressure(ret = (port == -1 ? mpev->outport-1 : port), (channel == -1 ? mpev->channel : channel), mpev->val); } break; case T_EV_Input_MIDIPitchBend : { MIDIPitchBendInputEvent *mpev = (MIDIPitchBendInputEvent *) ev; OutputPitchBend(ret = (port == -1 ? mpev->outport-1 : port), (channel == -1 ? mpev->channel : channel), mpev->val); } break; case T_EV_Input_MIDIKey : { MIDIKeyInputEvent *mkev = (MIDIKeyInputEvent *) ev; OutputNote(ret = (port == -1 ? mkev->outport-1 : port), (channel == -1 ? mkev->channel : channel), mkev->down, mkev->notenum + fs->transpose, mkev->vel); if (!mkev->down) // Double up on Note Offs OutputNote(ret = (port == -1 ? mkev->outport-1 : port), (channel == -1 ? mkev->channel : channel), mkev->down, mkev->notenum + fs->transpose, mkev->vel); } break; default: break; } return ret; }; void MidiIO::EchoEvent (Event *ev) { // Handle MIDI event echos.. if (ev->GetType() == T_EV_Input_MIDIClock || ev->GetType() == T_EV_Input_MIDIStartStop) { // MIDI sync message- send out to all ports set to transmit MIDI sync int *xmitports = app->getCFG()->GetMIDISyncOuts(), numxmitports = app->getCFG()->GetNumMIDISyncOuts(); for (int i = 0; i < numxmitports; i++) { OutputStartOnPort(); int port = EchoEventToPortChannel(ev,xmitports[i],-1); OutputEndOnPort(port); } } else if (!ev->echo) { // This event is generated from the configuration explicitly- not // an automatic echo of an unhandled MIDI event-- // So don't send it through our current patch settings. // Send to the exact port and channel specified OutputStartOnPort(); int port = EchoEventToPortChannel(ev,-1,-1); OutputEndOnPort(port); } else { // Echo of unused MIDI event- use patch logic // Handle special note off case- ensure note off sent to right place(s) PatchItem *ev_patch = 0; int ev_port = 0; if (ev->GetType() == T_EV_Input_MIDIKey && !((MIDIKeyInputEvent *) ev)->down && note_patch[((MIDIKeyInputEvent *) ev)->notenum] != 0) { // Use patch which was used when note was pressed ev_patch = note_patch[((MIDIKeyInputEvent *) ev)->notenum]; ev_port = note_def_port[((MIDIKeyInputEvent *) ev)->notenum]; } else { // Use current patch for all other events ev_patch = curpatch; ev_port = echoport; } // DEBUG // printf("MIDI: Echo port: %d Patch: %p\n",ev_port,ev_patch); if (ev_patch != 0 && ev_patch->IsCombi()) { // Combi patch- keyboard split into zones, possible multichannel output int curport = -1; for (int i = 0; i < ev_patch->numzones; i++) { CombiZone *z = ev_patch->GetZone(i); int notenum = -1; MIDIKeyInputEvent *note = 0; if (ev->GetType() == T_EV_Input_MIDIKey) { note = (MIDIKeyInputEvent *) ev; notenum = note->notenum; } if (notenum == -1 || (notenum >= z->kr_lo && notenum <= z->kr_hi)) { int z_port = (z->port_r ? z->port : echoport); if (curport == -1 || z_port != curport) { // Starting with a new port if (curport > 0 && curport <= numouts) OutputEndOnPort(curport-1); if (z_port > 0 && z_port <= numouts) OutputStartOnPort(); curport = z_port; } if (curport > 0 && curport <= numouts) EchoEventToPortChannel(ev,curport-1,z->channel); else if (curport == 0) { #if USE_FLUIDSYNTH app->getFLUIDP()->ReceiveMIDIEvent(ev); #endif } } } } else { if (ev_port > 0 && ev_port <= numouts) { // Single channel output- easy case OutputStartOnPort(); EchoEventToPortChannel(ev,ev_port-1, (echochan != -1 && ev_patch != 0 ? ev_patch->channel : echochan)); OutputEndOnPort(ev_port-1); } else if (ev_port == 0) { #if USE_FLUIDSYNTH app->getFLUIDP()->ReceiveMIDIEvent(ev); #endif } } } }; void MidiIO::SendBankProgramChangeToPortChannel (int bank, int program, int port, int channel) { if (bank != -1) { OutputController(port,channel,MIDI_BANKCHANGE_MSB,bank / 128); OutputController(port,channel,MIDI_BANKCHANGE_MSB,bank % 128); } if (program != -1) OutputProgramChange(port,channel,program); }; void MidiIO::SendBankProgramChange (PatchItem *patch) { printf("MIDI: Program Change\n"); if (patch != 0) { if (patch->IsCombi()) { // Combi, send individual zone bank/patch changes for (int i = 0; i < patch->numzones; i++) { CombiZone *z = patch->GetZone(i); int z_port = (z->port_r ? z->port : echoport); if (z_port > 0 && z_port <= numouts) SendBankProgramChangeToPortChannel(z->bank, z->prog, z_port-1, z->channel); } } else { // Single patch, send bank/patch change if (echoport > 0 && echoport <= numouts) SendBankProgramChangeToPortChannel(patch->bank, patch->prog, echoport-1, patch->channel); } } }; fweelin-0.6/src/fweelin_midiio.h0000755000175000017500000001415211050104733015371 0ustar mercmerc#ifndef __FWEELIN_MIDIIO_H #define __FWEELIN_MIDIIO_H /* Copyright 2004-2008 Jan Pekau (JP Mercury) This file is part of Freewheeling. Freewheeling is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. Freewheeling is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Freewheeling. If not, see . */ #ifdef __MACOSX__ #include // Small MIDI output buffer- must be large enough to hold any one MIDI message #define OBUF_LEN 128 #else #include #endif #include "fweelin_event.h" #define MIDI_CLOCK_FREQUENCY 24 // 24 MIDI clock messages per quarter note (beat) MIDI standard class Fweelin; class PatchItem; class MidiIO : public EventProducer, public EventListener { friend class Fweelin; public: MidiIO (Fweelin *app); virtual ~MidiIO (); void ReceiveEvent(Event *ev, EventProducer *from); int activate (); void close (); void SetBenderTune(int tuning) { bendertune = tuning; }; int GetBenderTune() { return bendertune; }; void ResetBenderTune() { bendertune = 0; }; // Sets MIDI echo to one or more ports and channels based on: // a default MIDI output port (def_port) // and the given patch. // // Regular patches use the default MIDI output port and one channel, given // within the patch. // // Combi patches split the keyboard into multiple zones. // Each zone can output to any channel, and can optionally override and send // to a different MIDI output port altogether. This allows one MIDI // controller to control many instruments, even on different softsynths, // at the same time. // Zones can overlap, so that one key sends to multiple channels/ports void SetMIDIEcho (int def_port, PatchItem *patch); // Send bank and program change messages where appropriate for the given // patch void SendBankProgramChange (PatchItem *patch); #ifndef __MACOSX__ char IsActive () { return midithreadgo; }; #else // Switch MIDI inputs (which system MIDI input source feeds Fweelin?) void SetMIDIInput (int idx); #endif // MIDI Sync inline int GetMIDISyncTransmit() { return midisyncxmit; }; inline void SetMIDISyncTransmit(int midisyncxmit) { this->midisyncxmit = midisyncxmit; }; // Value to offset bender amounts by-- used to do tuning from // bender int bendertune; // Current bender value (before tuning adjustment) int curbender; // MIDI ECHO // Single channel echo- // Echo MIDI events out which MIDI port? // (0 is off, port #s ascending from 1 reference out_ports) int echoport; // Echo out which MIDI channel? // (-1 echoes without changing channel information) int echochan; PatchItem *curpatch; // Current patch- gives which channel(s) // to map to // Number of MIDI in/out ports int numins, numouts; protected: // Core app Fweelin *app; // Open MIDI engine with num_in writeable ports and num_out readable ports. // Nonzero is returned on error char open_midi (int num_in, int num_out); // Listen/unlisten to events (used in startup & shutdown) void listen_events (); void unlisten_events (); // Methods that send one MIDI message to one system MIDI out void OutputController (int port, int chan, int ctrl, int val); void OutputProgramChange (int port, int chan, int val); void OutputChannelPressure (int port, int chan, int val); void OutputPitchBend (int port, int chan, int val); void OutputNote (int port, int chan, char down, int notenum, int vel); // MIDI Sync messages void OutputClock (int port); void OutputStart (int port); void OutputStop (int port); // Start/End pass messages void OutputStartOnPort (); // First message for this port in this pass void OutputEndOnPort (int port); // Last message for this port in this pass // Echo MIDI event to a single port and channel // Return the port echoed to int EchoEventToPortChannel (Event *ev, int port, int channel); // Echo MIDI event back to MIDI outs, according to current patch settings void EchoEvent (Event *ev); // Receive incoming MIDI events from the system and broadcast FreeWheeling // MIDI events internally void ReceiveNoteOffEvent (int channel, int notenum, int vel); void ReceiveNoteOnEvent (int channel, int notenum, int vel); void ReceivePitchBendEvent (int channel, int value); void ReceiveChannelPressureEvent (int channel, int value); void ReceiveProgramChangeEvent (int channel, int value); void ReceiveControlChangeEvent (int channel, int ctrl, int value); // Send bank and program change message to port/channel void SendBankProgramChangeToPortChannel (int bank, int program, int port, int channel); #ifdef __MACOSX__ MIDIClientRef client; MIDIPortRef *in_ports, *out_ports; MIDIEndpointRef *out_sources; MIDIEndpointRef dest; // Deprecated int inputidx; // Index of last selected MIDI input source MIDIPacket *curPacket; MIDIPacketList *packetList; Byte obuf[OBUF_LEN]; // Small MIDI event output buffer void static MidiInputProc (const MIDIPacketList *pktlist, void *refCon, void *connRefCon); #else // Midi event handler thread static void *run_midi_thread (void *ptr); snd_seq_t *seq_handle; int *in_ports, *out_ports; pthread_t midi_thread; char midithreadgo; #endif // For each MIDI note on the scale, what default port and patch was the note // played with? This allows us to send note off(s) to the right place(s), // even when the patch is changed while notes are held int *note_def_port; PatchItem **note_patch; // MIDI Sync int midisyncxmit; // Nonzero if we should transmit MIDI sync messages }; #endif fweelin-0.6/src/fweelin_sdlio.cc0000755000175000017500000003653311065526247015414 0ustar mercmerc/* With my hands, I weave the bridge's design feeling as the sides combine, reality remade and realigned, I fell thru death, now it's my time. */ /* Copyright 2004-2008 Jan Pekau (JP Mercury) This file is part of Freewheeling. Freewheeling is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. Freewheeling is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Freewheeling. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include #include #ifdef __MACOSX__ #include #include #else #include #include #endif #include "fweelin_sdlio.h" #include "fweelin_core.h" // ******** KEYBOARD / MOUSE / JOYSTICK HANDLER static const char *SDL_names[] = { "", "", "", "", "", "", "", "", "backspace", "tab", "", "", "clear", "return", "", "", "", "", "", "pause", "", "", "", "", "", "", "", "escape", "", "", "", "", "space", "exclamation", "dblquote", "numbersign", "dollarsign", "", "ampersand", "backquote", "openparen", "closeparen", "asterisk", "plus", "comma", "minus", "period", "slash", "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "colon", "semicolon", "lessthan", "equal", "greaterthan", "questionmark", "at", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "squarebracketopen", "backslash", "squarebracketclose", "caret", "underscore", "tilde", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "", "", "", "", "delete", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "world0", "world1", "world2", "world3", "world4", "world5", "world6", "world7", "world8", "world9", "world10", "world11", "world12", "world13", "world14", "world15", "world16", "world17", "world18", "world19", "world20", "world21", "world22", "world23", "world24", "world25", "world26", "world27", "world28", "world29", "world30", "world31", "world32", "world33", "world34", "world35", "world36", "world37", "world38", "world39", "world40", "world41", "world42", "world43", "world44", "world45", "world46", "world47", "world48", "world49", "world50", "world51", "world52", "world53", "world54", "world55", "world56", "world57", "world58", "world59", "world60", "world61", "world62", "world63", "world64", "world65", "world66", "world67", "world68", "world69", "world70", "world71", "world72", "world73", "world74", "world75", "world76", "world77", "world78", "world79", "world80", "world81", "world82", "world83", "world84", "world85", "world86", "world87", "world88", "world89", "world90", "world91", "world92", "world93", "world94", "world95", "KP0", "KP1", "KP2", "KP3", "KP4", "KP5", "KP6", "KP7", "KP8", "KP9", "KPperiod", "KPslash", "KPasterisk", "KPminus", "KPplus", "enter", "equals", "up", "down", "right", "left", "insert", "home", "end", "pageup", "pagedown", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", "", "", "", "numlock", "capslock", "scrolllock", "rightshift", "leftshift", "rightctrl", "leftctrl", "rightalt", "leftalt", "rightmeta", "leftmeta", "leftsuper", "rightsuper", "altgr", "compose", "help", "printscreen", "sysreq", "break", "menu", "power", "euro", "undo"}; SDLKey SDLIO::GetSDLKey(char *keyname) { SDLKey ky; for (ky = SDLK_FIRST; ky < SDLK_LAST; ky = (SDLKey)(ky+1)) { /*char *nm = SDL_GetKeyName(ky); printf("\"%s\", \n",(!strcmp(nm,"unknown key") ? "" : nm));*/ /*if (SDL_names[ky][0] != '\0') printf("%03d - %s\n",ky,SDL_names[ky]);*/ if (!strcmp(SDL_names[ky],keyname)) return ky; } return SDLK_UNKNOWN; }; const char *SDLIO::GetSDLName(SDLKey sym) { return SDL_names[sym]; }; int SDLIO::activate() { sdlthreadgo = 1; #if 0 printf("SDLIO: Starting SDL input thread.\n"); const static size_t STACKSIZE = 1024*64; pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setstacksize(&attr,STACKSIZE); printf("SDL: Stacksize: %d.\n",STACKSIZE); sdlthreadgo = 1; int ret = pthread_create(&sdl_thread, &attr, run_sdl_thread, this); if (ret != 0) { printf("SDLIO: (SDL input) pthread_create failed, exiting"); return 1; } SRMWRingBuffer_Writers::RegisterWriter(sdl_thread); // Setup high priority threads struct sched_param schp; memset(&schp, 0, sizeof(schp)); schp.sched_priority = sched_get_priority_max(SCHED_OTHER); printf("SDLIO: thread priority %d\n",schp.sched_priority); if (pthread_setschedparam(sdl_thread, SCHED_OTHER, &schp) != 0) { printf("SDLIO: Can't set hi priority thread, will use regular!\n"); } #endif return 0; } void SDLIO::close() { sdlthreadgo = 0; // *** SDL IO now running on main thread // pthread_join(sdl_thread,0); printf("SDLIO: end\n"); } void SDLIO::ReceiveEvent(Event *ev, EventProducer *from) { switch (ev->GetType()) { case T_EV_ExitSession : sdlthreadgo = 0; printf("\n** Event: Exit session\n"); break; default: break; } } // *********** Old hardcoded key handler // *********** Still handles a few things directly void SDLIO::handle_key(int keycode, char press) { //printf("SDLIO: %d\n",keycode); static int prevkeycode = 0, prevcnt = 0; if (press) { if (keycode == prevkeycode) prevcnt++; else prevcnt = 0; prevkeycode = keycode; if (keycode == 51) { // Backslash freezes & resets limiter if (sets.leftshift || sets.rightshift) { // Reset limiter app->getRP()->ResetLimiter(); } else { // Toggle limiter freeze char limiterfreeze = app->getRP()->GetLimiterFreeze(); limiterfreeze = (limiterfreeze == 0 ? 1 : 0); app->getRP()->SetLimiterFreeze(limiterfreeze); } } else if (keycode == 108) { // greyENTER // Produce stdout status report app->getCFG()->status_report = 1; } else if (keycode == 65) { // spacebar sets.spacekey = 1; } else if (keycode == 64) { // left alt sets.leftalt = 1; } else if (keycode == 113) { // right alt sets.rightalt = 1; } else if (keycode == 50) { // left shift sets.leftshift = 1; } else if (keycode == 62) { // right shift sets.rightshift = 1; } else if (keycode == 37) { // left ctrl sets.leftctrl = 1; } else if (keycode == 109) { // right ctrl sets.rightctrl = 1; } else if (keycode == 98) { // up arrow, hold for adjusting individual loop volumes sets.upkey = 1; } else if (keycode == 104) { // down arrow, hold for adjusting individual loop volumes sets.downkey = 1; } else if (keycode == 9) { // escape key- exit! //app->getEMG()->BroadcastEvent(::new ExitSessionEvent(), this); //sdlthreadgo = 0; //printf("end\n"); } else { // This keyrange (F1-F10) is set to select pulses if ((keycode >= 67 && keycode <= 76)) { if (sets.leftshift || sets.rightshift) { // Set subdivide // Old method (F1=1, F2=2, F3=4, F4=8, F5=16..) // app->getLOOPMGR()->SetSubdivide((int) pow(2,keycode-67)); // New method- Fn is translated to subdivide directly // And amplified by repeat presses of Fn int newsub = (prevcnt+1) * (keycode-67+1); app->getLOOPMGR()->SetSubdivide(newsub); } } #if 0 if (keycode == 95) { // Toggle metronome on current pulse (F11) Pulse *a = app->getLOOPMGR()->GetCurPulse(); if (a != 0) a->SwitchMetronome((a->IsMetronomeActive() ? 0 : 1)); } #endif } } else { // Release if (keycode == 64) { // left alt sets.leftalt = 0; } else if (keycode == 113) { // right alt sets.rightalt = 0; } else if (keycode == 65) { // spacebar sets.spacekey = 0; } else if (keycode == 50) { // left shift sets.leftshift = 0; } else if (keycode == 62) { // right shift sets.rightshift = 0; } else if (keycode == 37) { // left ctrl sets.leftctrl = 0; } else if (keycode == 109) { // right ctrl sets.rightctrl = 0; } else if (keycode == 98) { // up arrow sets.upkey = 0; } else if (keycode == 104) { // down arrow sets.downkey = 0; } } } // This is the SDL input event loop void *SDLIO::run_sdl_thread(void *ptr) { SDLIO *inst = static_cast(ptr); SDL_Event event; printf("SDLIO: SDL Input thread start.\n"); #ifdef __MACOSX__ // inst->cocoa.SetupCocoaThread(); #endif // Setup joysticks inst->numjoy = SDL_NumJoysticks(); if (inst->numjoy > 0) inst->joys = new SDL_Joystick *[inst->numjoy]; printf("SDLIO: Detected %d joysticks..\n", inst->numjoy); for (int i = 0; i < inst->numjoy; i++) { printf(" Joystick #%d: %s\n",i+1,SDL_JoystickName(i)); inst->joys[i] = SDL_JoystickOpen(i); } // Listen for pertinent events if (inst->app->getEMG() == 0) { printf("INIT: Error: Event Manager not yet active!\n"); exit(1); } inst->app->getEMG()->ListenEvent(inst,0,T_EV_ExitSession); while (inst->sdlthreadgo) { if (SDL_WaitEvent(&event)) { switch (event.type) { case SDL_JOYBUTTONDOWN : case SDL_JOYBUTTONUP : { JoystickButtonInputEvent *jevt = (JoystickButtonInputEvent *) Event::GetEventByType(T_EV_Input_JoystickButton); jevt->joystick = event.jbutton.which; jevt->button = event.jbutton.button; jevt->down = (event.type == SDL_JOYBUTTONUP ? 0 : 1); inst->app->getEMG()->BroadcastEventNow(jevt, inst); if (inst->app->getCFG()->IsDebugInfo()) printf("JOYSTICK: Joystick #%d, button #%d %s\n", jevt->joystick,jevt->button, (jevt->down ? "pressed" : "released")); } break; case SDL_MOUSEMOTION : { MouseMotionInputEvent *mevt = (MouseMotionInputEvent *) Event::GetEventByType(T_EV_Input_MouseMotion); mevt->x = event.motion.x; mevt->y = event.motion.y; inst->app->getEMG()->BroadcastEventNow(mevt, inst); // No debug info for mouse motion #if 0 if (inst->app->getCFG()->IsDebugInfo()) printf("MOUSE: Motion: (%d,%d)\n", mevt->x, mevt->y); #endif } // printf("x: %d y: %d\n", // event.motion.x,event.motion.y); break; case SDL_MOUSEBUTTONDOWN : case SDL_MOUSEBUTTONUP : { MouseButtonInputEvent *mevt = (MouseButtonInputEvent *) Event::GetEventByType(T_EV_Input_MouseButton); mevt->button = event.button.button; mevt->down = (event.type == SDL_MOUSEBUTTONUP ? 0 : 1); mevt->x = event.button.x; mevt->y = event.button.y; inst->app->getEMG()->BroadcastEventNow(mevt, inst); if (inst->app->getCFG()->IsDebugInfo()) printf("MOUSE: Button #%d %s @ (%d,%d)\n", mevt->button, (mevt->down ? "pressed" : "released"), mevt->x, mevt->y); } //printf("button: %d x: %d y: %d\n", // event.button.button, // event.button.x,event.button.y); break; case SDL_KEYDOWN : { SDLKey sym = event.key.keysym.sym; if (sym >= SDLK_FIRST && sym < SDLK_LAST) { // Mark the key as held down inst->keyheld[sym] = 1; // Now generate an input event.. KeyInputEvent *kevt = (KeyInputEvent *) Event::GetEventByType(T_EV_Input_Key); kevt->down = 1; kevt->keysym = sym; kevt->unicode = event.key.keysym.unicode; inst->app->getEMG()->BroadcastEventNow(kevt, inst); if (inst->app->getCFG()->IsDebugInfo()) printf("KEYBOARD: Key pressed: %d (%s)\n", kevt->keysym, GetSDLName(sym)); inst->handle_key(event.key.keysym.scancode,1); } else { printf("KEYBOARD: Invalid key\n"); } } break; case SDL_KEYUP : { SDLKey sym = event.key.keysym.sym; if (sym >= SDLK_FIRST && sym < SDLK_LAST) { // Mark the key as unheld inst->keyheld[sym] = 0; // Now generate an input event.. KeyInputEvent *kevt = (KeyInputEvent *) Event::GetEventByType(T_EV_Input_Key); kevt->down = 0; kevt->keysym = sym; kevt->unicode = event.key.keysym.unicode; inst->app->getEMG()->BroadcastEventNow(kevt, inst); if (inst->app->getCFG()->IsDebugInfo()) printf("KEYBOARD: Key released: %d (%s)\n", kevt->keysym, GetSDLName(sym)); inst->handle_key(event.key.keysym.scancode,0); break; } else printf("KEYBOARD: Invalid key\n"); } break; } } /*else { printf("SDL Error Waiting for Event!\n"); sdlthreadgo = 0; }*/ // usleep(100); // Give up the processor briefly! } inst->app->getEMG()->UnlistenEvent(inst,0,T_EV_ExitSession); printf("Closing joysticks.\n"); for (int i = 0; i < inst->numjoy; i++) SDL_JoystickClose(inst->joys[i]); #ifdef __MACOSX__ // inst->cocoa.TakedownCocoaThread(); #endif printf("SDLIO: SDL Input thread done.\n"); return 0; } fweelin-0.6/src/fweelin_sdlio.h0000755000175000017500000000566611050104733015243 0ustar mercmerc#ifndef __FWEELIN_SDLIO_H #define __FWEELIN_SDLIO_H /* Copyright 2004-2008 Jan Pekau (JP Mercury) This file is part of Freewheeling. Freewheeling is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. Freewheeling is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Freewheeling. If not, see . */ #include #include "fweelin_event.h" #ifdef __MACOSX__ #include "FweelinMac.h" #endif class Fweelin; // Deprecated! class KeySettings { public: KeySettings() : leftshift(0), rightshift(0), leftctrl(0), rightctrl(0), leftalt(0), rightalt(0), upkey(0), downkey(0), spacekey(0) {}; // Function modifier keys char leftshift, rightshift, leftctrl, rightctrl, leftalt, rightalt, upkey, downkey, spacekey; }; class SDLKeyList { public: SDLKeyList (SDLKey k) : k(k), next(0) {}; SDLKey k; SDLKeyList *next; }; // SDL Input Handler class SDLIO : public EventProducer, public EventListener { public: SDLIO (Fweelin *app) : app(app), sdlthreadgo(0) { keyheld = new char[SDLK_LAST]; for (int i = 0; i < SDLK_LAST; i++) keyheld[i] = 0; }; virtual ~SDLIO() { delete[] keyheld; }; int activate (); void close (); char IsActive () { return sdlthreadgo; }; char *GetKeysHeld () { return keyheld; }; KeySettings *getSETS() { return &sets; }; void ReceiveEvent(Event *ev, EventProducer *from); // We use slightly modified keynames for the config system: // Gets the SDL keysym that corresponds to key with a given name static SDLKey GetSDLKey(char *keyname); // And the name corresponding to the keysym.. static const char *GetSDLName(SDLKey sym); inline void EnableUNICODE(int enable) { SDL_EnableUNICODE(enable); }; inline void EnableKeyRepeat(int enable) { if (enable) SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL); else SDL_EnableKeyRepeat(0,0); }; // SDL event handler thread static void *run_sdl_thread (void *ptr); protected: #ifdef __MACOSX__ FweelinMac cocoa; // Cocoa thread setup #endif // Core app Fweelin *app; // Joysticks int numjoy; // Number of joysticks SDL_Joystick **joys; // Control structure for each joystick // Keys currently held down- array for all SDLKeys, nonzero if held char *keyheld; // Deprecated KeySettings sets; void handle_key(int keycode, char press); pthread_t sdl_thread; char sdlthreadgo; }; #endif fweelin-0.6/src/fweelin_videoio.cc0000755000175000017500000025676511065526225015747 0ustar mercmerc/* Art is the beginning. */ /* Copyright 2004-2008 Jan Pekau (JP Mercury) This file is part of Freewheeling. Freewheeling is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. Freewheeling is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Freewheeling. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include #ifdef LCD_DISPLAY #include #include #endif #include "fweelin_videoio.h" #include "fweelin_core.h" #include "fweelin_logo.h" #ifdef __MACOSX__ #define CAPITAL_FILLED_PIE #endif // Different versions of sdl-gfx have different naming #ifdef CAPITAL_FILLED_PIE #define FILLED_PIE filledPieRGBA #else #define FILLED_PIE filledpieRGBA #endif char *strup (char *str) { const static int STRBUFLEN = 512; static char buf[STRBUFLEN]; strncpy(buf,str,STRBUFLEN-1); buf[STRBUFLEN-1] = '\0'; int len = strlen(buf); for (int i = 0; i < len; i++) buf[i] = toupper(buf[i]); return buf; }; char *strlwr (char *str) { const static int STRBUFLEN = 512; static char buf[STRBUFLEN]; strncpy(buf,str,STRBUFLEN-1); buf[STRBUFLEN-1] = '\0'; int len = strlen(buf); for (int i = 0; i < len; i++) buf[i] = tolower(buf[i]); return buf; }; double mygettime(void) { static struct timeval mytv; gettimeofday(&mytv,NULL); return(mytv.tv_sec+mytv.tv_usec/1000000.0); } int round(float num) { if (num-(long)num < 0.5) return (int) floor(num); else return (int) ceil(num); } void LoopTray::Draw(SDL_Surface *screen) { const static SDL_Color borderclr = {100, 100, 90, 0}; LockBrowser(); // **** Add event to change placenames when 'video-show-loop' is called VideoIO *vid = app->getVIDEO(); // Generate circular map for loop tray if (loopmap == 0) loopmap = vid->CreateMap(vid->getLSCOPEPIC(),loopsize); // Draw iconified version boxRGBA(screen,xpos,ypos,xpos+iconsize,ypos+iconsize, borderclr.r,borderclr.g,borderclr.b,255); hlineRGBA(screen,xpos,xpos+iconsize,ypos,40,40,40,255); hlineRGBA(screen,xpos,xpos+iconsize,ypos+iconsize,40,40,40,255); vlineRGBA(screen,xpos,ypos,ypos+iconsize,40,40,40,255); vlineRGBA(screen,xpos+iconsize,ypos,ypos+iconsize,40,40,40,255); FILLED_PIE(screen,xpos+iconsize/2,ypos+iconsize/2, iconsize*3/8, 30,359, 0xF9,0xE6,0x13,255); circleRGBA(screen,xpos+iconsize/2,ypos+iconsize/2, iconsize*3/8, 40,40,40, 255); // Outline if (xpanded) { // Draw background { int xpand_yb1 = xpand_y1+basepos, xpand_yb2 = xpand_y2-basepos, xpand_xb1 = xpand_x1+basepos, xpand_xb2 = xpand_x2-basepos; boxRGBA(screen,xpand_x1,xpand_y1,xpand_xb1,xpand_y2, borderclr.r,borderclr.g,borderclr.b,255); boxRGBA(screen,xpand_xb1,xpand_y1,xpand_x2,xpand_y2, borderclr.r,borderclr.g,borderclr.b,255); boxRGBA(screen,xpand_x1,xpand_y1,xpand_x2,xpand_yb1, borderclr.r,borderclr.g,borderclr.b,255); boxRGBA(screen,xpand_x1,xpand_yb2,xpand_x2,xpand_y2, borderclr.r,borderclr.g,borderclr.b,255); boxRGBA(screen,xpand_xb1,xpand_yb1,xpand_xb2,xpand_yb2,0,0,0,255); } hlineRGBA(screen,xpand_x1,xpand_x2,xpand_y1,40,40,40,255); hlineRGBA(screen,xpand_x1,xpand_x2,xpand_y2,40,40,40,255); vlineRGBA(screen,xpand_x1,xpand_y1,xpand_y2,40,40,40,255); vlineRGBA(screen,xpand_x2,xpand_y1,xpand_y2,40,40,40,255); LoopTrayItem *curl = (LoopTrayItem *) first; // If necessary, recalc positions for loops if (touchtray) { char go = 1; int curx = basepos, cury = basepos; int loopjump = loopsize+basepos; // Space for loops? if (curx >= xpand_x2-xpand_x1-loopjump || cury >= xpand_y2-xpand_y1-loopjump) go = 0; while (curl != 0) { if (go) { curl->xpos = curx; curl->ypos = cury; // Move to next spot curx += loopjump; if (curx >= xpand_x2-xpand_x1-loopjump) { curx = basepos; cury += loopjump; if (cury >= xpand_y2-xpand_y1-loopjump) go = 0; } } else { curl->xpos = -1; curl->ypos = -1; } curl = (LoopTrayItem *) curl->next; } touchtray = 0; } // Draw items curl = (LoopTrayItem *) first; char go = 1; while (curl != 0 && go) { if (curl->xpos != -1) Draw_Item(screen,curl,xpand_x1+curl->xpos,xpand_y1+curl->ypos); else go = 0; curl = (LoopTrayItem *) curl->next; } } UnlockBrowser(); }; void LoopTray::Draw_Item(SDL_Surface *screen, BrowserItem *i, int x, int y) { const static float loop_colorbase = 0.5; const static SDL_Color white = { 0xEF, 0xAF, 0xFF, 0 }; const static SDL_Color cursorclr = { 0xEF, 0x11, 0x11, 0 }; static SDL_Color loop_color[4] = { { 0x62, 0x62, 0x62, 0 }, { 0xF9, 0xE6, 0x13, 0 }, { 0xFF, 0xFF, 0xFF, 0 }, { 0xE0, 0xDA, 0xD5, 0 } }; LoopManager *loopmgr = app->getLOOPMGR(); LoopTrayItem *li = (LoopTrayItem *) i; float colormag; char loopexists; if (loopmgr->GetSlot(li->loopid) || loopmgr->IsActive(li->loopid)) { loopexists = 1; colormag = loop_colorbase + loopmgr->GetTriggerVol(li->loopid); if (colormag > 1.0) colormag = 1.0; } else { loopexists = 0; colormag = loop_colorbase; } // Draw loop if (loopexists) { if (!app->getVIDEO()-> DrawLoop(loopmgr,li->loopid,screen,app->getVIDEO()->getLSCOPEPIC(), loop_color,colormag,app->getCFG(),0,loopmap,x,y, app->getRP()->GetLimiterVolume(),0)) { // Place name if (li->placename != 0) VideoIO::draw_text(screen,font->font,li->placename,x,y,white); // Loop name if (xpand_liney == -1) TTF_SizeText(font->font,VERSION,0,&xpand_liney); // printf("cur: %p\n",cur); if (i == cur && renamer != 0) { RenameUIVars *rui = renamer->UpdateUIVars(); // Draw text with cursor int sx, sy; int txty = y+loopsize-xpand_liney; char *curn = renamer->GetCurName(); if (*curn != '\0') VideoIO::draw_text(screen,font->font,curn, x,txty,white,0,0,&sx,&sy); else { sx = 0; sy = xpand_liney; } if (rui->rename_cursor_toggle) boxRGBA(screen, x+sx,txty, x+sx+sy/2,txty+sy, cursorclr.r,cursorclr.g,cursorclr.b,255); } else if (li->name != 0) VideoIO::draw_text(screen,font->font,li->name, x,y+loopsize-xpand_liney, white); } } // Browser::Draw_Item(screen,i,x,y); }; // Draw browser display void Browser::Draw_Item(SDL_Surface *screen, BrowserItem *i, int x, int y) { const static SDL_Color white = { 0xEF, 0xAF, 0xFF, 0 }; const static SDL_Color cursorclr = { 0x77, 0x77, 0x77, 0 }; static char tmp[255]; if (font != 0 && font->font != 0 && i != 0) { switch (i->GetType()) { case B_Patch : { PatchItem *p = (PatchItem *) i; // Current patch snprintf(tmp,255,"%02d: %s", p->id, p->name); tmp[254] = '\0'; VideoIO::draw_text(screen,font->font,tmp,x,y,white); } break; case B_Division : break; default : { if (i->GetType() == B_Loop) snprintf(tmp,255,"%s-",FWEELIN_OUTPUT_LOOP_NAME); else if (i->GetType() == B_Scene) snprintf(tmp,255,"%s-",FWEELIN_OUTPUT_SCENE_NAME); else tmp[0] = '\0'; if (i == cur && renamer != 0) { RenameUIVars *rui = renamer->UpdateUIVars(); strncat(tmp,renamer->GetCurName(),255); tmp[254] = '\0'; // Draw text with cursor int sx, sy; VideoIO::draw_text(screen,font->font,tmp,x,y,white,0,0, &sx,&sy); if (rui->rename_cursor_toggle) boxRGBA(screen, x+sx,y, x+sx+sy/2,y+sy, cursorclr.r,cursorclr.g,cursorclr.b,255); } else if (i->name != 0) { strncat(tmp,i->name,255); tmp[254] = '\0'; VideoIO::draw_text(screen,font->font,tmp,x,y,white); } } break; } } }; // Draw browser display void Browser::Draw(SDL_Surface *screen) { LockBrowser(); if (xpanded) { // Draw expanded view // Dim the background for (int i = xpand_y1; i <= xpand_y2; i++) hlineRGBA(screen,xpand_x1,xpand_x2,i,0,0,0,200); hlineRGBA(screen,xpand_x1,xpand_x2,xpand_y1,127,127,127,255); hlineRGBA(screen,xpand_x1,xpand_x2,xpand_y2,127,127,127,255); vlineRGBA(screen,xpand_x1,xpand_y1,xpand_y2,127,127,127,255); vlineRGBA(screen,xpand_x2,xpand_y1,xpand_y2,127,127,127,255); if (cur != 0) { BrowserItem *sp_1 = cur, *sp_2 = cur; // Compute text height and center of expanded window-- once! if (xpand_liney == -1) { TTF_SizeText(font->font,VERSION,0,&xpand_liney); xpand_centery = (xpand_y1+xpand_y2)/2; xpand_spread = MIN(xpand_centery-xpand_y1, xpand_y2-xpand_centery); xpand_spread /= xpand_liney; // printf("compute xpand_liney: %d xpand_centery: %d\n", // xpand_liney, xpand_centery); } int ofs_1 = 0; boxRGBA(screen, xpand_x1,xpand_centery, xpand_x2,xpand_centery+xpand_liney, 127,0,0,255); Draw_Item(screen,sp_1,xpand_x1, xpand_centery-xpand_liney*ofs_1); while (ofs_1 < xpand_spread && sp_1->prev != 0) { sp_1 = sp_1->prev; ofs_1++; Draw_Item(screen,sp_1,xpand_x1, xpand_centery-xpand_liney*ofs_1); } int ofs_2 = 0; while (ofs_2 < xpand_spread-1 && sp_2->next != 0) { sp_2 = sp_2->next; ofs_2++; Draw_Item(screen,sp_2,xpand_x1, xpand_centery+xpand_liney*ofs_2); } } if (mygettime()-xpand_lastactivity >= xpand_delay) { // No activity, close expanded window xpanded = 0; } } // Draw single-line view Draw_Item(screen,cur,xpos,ypos); UnlockBrowser(); } // Draw text display void FloDisplayText::Draw(SDL_Surface *screen) { static char tmp[255]; const static SDL_Color titleclr = { 0x77, 0x88, 0x99, 0 }; const static SDL_Color valclr = { 0xDF, 0xEF, 0x20, 0 }; if (font != 0 && font->font != 0) { int xofs = 0, yofs = 0; // Draw title if (title != 0) VideoIO::draw_text(screen,font->font, title,xpos,ypos,titleclr,0,1, &xofs,&yofs); // Draw value UserVariable val = exp->Evaluate(0); val.Print(tmp,255); VideoIO::draw_text(screen,font->font, tmp,xpos+xofs,ypos,valclr,0,1); } }; // Draw switch display void FloDisplaySwitch::Draw(SDL_Surface *screen) { const static SDL_Color title1clr = { 0xDF, 0xEF, 0x20, 0 }; const static SDL_Color title0clr = { 0x11, 0x22, 0x33, 0 }; if (font != 0 && font->font != 0 && title != 0) { // Evaluate exp UserVariable val = exp->Evaluate(0); char nonz = (char) val; // Draw title VideoIO::draw_text(screen,font->font, title,xpos,ypos,(nonz ? title1clr : title0clr),0,1); } }; // Draw circular switch display void FloDisplayCircleSwitch::Draw(SDL_Surface *screen) { const static SDL_Color titleclr = { 0x77, 0x88, 0x99, 0 }; SDL_Color c1clr = { 0xDF, 0x20, 0x20, 0 }; SDL_Color c0clr = { 0x11, 0x22, 0x33, 0 }; const static float flashspd = 4.0; double dt = mygettime()-nonztime; char flashon = 1; if (flash) flashon = !((char) (((long int) (dt*flashspd)) % 2)); // Evaluate exp UserVariable val = exp->Evaluate(0); char nonz = (char) val; if (nonz && !prevnonz) // Value is switching on-- store time nonztime = mygettime(); prevnonz = nonz; // Draw circle SDL_Color *c = (nonz && flashon ? &c1clr : &c0clr); filledCircleRGBA(screen,xpos,ypos,(nonz && flashon ? rad1 : rad0), c->r, c->g, c->b, 255); if (font != 0 && font->font != 0 && title != 0) { // Draw title VideoIO::draw_text(screen,font->font, title,xpos+2*rad0,ypos,titleclr,0,1); } }; // Draw text switch display void FloDisplayTextSwitch::Draw(SDL_Surface *screen) { // No title displayed SDL_Color c1clr = { 0x77, 0x88, 0x99, 0 }; SDL_Color c0clr = { 0x99, 0x88, 0x77, 0 }; // Evaluate exp UserVariable val = exp->Evaluate(0); char nonz = (char) val; // Draw appropriate text char *dtxt = (nonz ? text1 : text0); if (dtxt != 0) VideoIO::draw_text(screen,font->font,dtxt, xpos,ypos, (nonz ? c1clr : c0clr),0,1); }; // Draw text display void FloDisplayBar::Draw(SDL_Surface *screen) { const static SDL_Color titleclr = { 0x77, 0x88, 0x99, 0 }; const static SDL_Color barclr = { 0xFF, 0x50, 0x20, 0 }; const static float calwidth = 1.1; if (font != 0 && font->font != 0) { // Draw title if (title != 0) VideoIO::draw_text(screen,font->font, title,xpos,ypos,titleclr, (orient == O_Vertical ? 1 : 2), (orient == O_Horizontal ? 1 : 0)); } // Get value of expression UserVariable val = exp->Evaluate(0); float fval = (float) val; if (dbscale) { // dB // Convert linear value to dB and then to fader level: int lvl = (int) (AudioLevel::dB_to_fader(LIN2DB(fval), maxdb) * barscale); // Draw bar if (orient == O_Vertical) { // Vertical if (marks) { // Show calibration const static float mindb = -60., dbstep = 6.0; int clrstep = (int) (255/((maxdb-mindb)/dbstep)), clr = 0; for (float i = mindb; i <= maxdb; i += dbstep, clr += clrstep) { // printf("%f > %f def\n",i,AudioLevel::dB_to_fader(i, maxdb)); int clvl = (int) (AudioLevel::dB_to_fader(i, maxdb) * barscale); hlineRGBA(screen, xpos-(int) (calwidth*thickness), xpos-thickness, ypos-clvl, clr,clr,clr,255); hlineRGBA(screen, xpos+thickness, xpos+(int) (calwidth*thickness), ypos-clvl, clr,clr,clr,255); } } // Bar boxRGBA(screen, xpos-thickness,ypos, xpos+thickness,ypos-lvl, barclr.r/2,barclr.g/2,barclr.b/2,255); boxRGBA(screen, xpos-thickness/2,ypos, xpos+thickness/2,ypos-lvl, barclr.r,barclr.g,barclr.b,255); } else { // Horizontal if (marks) { // Show calibration const static float mindb = -60., dbstep = 6.0; int clrstep = (int) (255/((maxdb-mindb)/dbstep)), clr = 0; for (float i = mindb; i <= maxdb; i += dbstep, clr += clrstep) { int clvl = (int) (AudioLevel::dB_to_fader(i, maxdb) * barscale); vlineRGBA(screen, xpos+clvl, ypos-(int) (calwidth*thickness), ypos-thickness, clr,clr,clr,255); vlineRGBA(screen, xpos+clvl, ypos+thickness, ypos+(int) (calwidth*thickness), clr,clr,clr,255); } } // Bar boxRGBA(screen, xpos,ypos-thickness, xpos+lvl,ypos+thickness, barclr.r/2,barclr.g/2,barclr.b/2,255); boxRGBA(screen, xpos,ypos-thickness/2, xpos+lvl,ypos+thickness/2, barclr.r,barclr.g,barclr.b,255); } } else { // Linear // Draw bar if (orient == O_Vertical) { // Vertical // Show calibration boxRGBA(screen, xpos-thickness/2,ypos, xpos+thickness/2,(int) (ypos-barscale), barclr.r/2,barclr.g/2,barclr.b/2,255); // Bar boxRGBA(screen, xpos-thickness,ypos, xpos+thickness,(int) (ypos-fval*barscale), barclr.r/2,barclr.g/2,barclr.b/2,255); boxRGBA(screen, xpos-thickness/2,ypos, xpos+thickness/2,(int) (ypos-fval*barscale), barclr.r,barclr.g,barclr.b,255); } else { // Horizontal // Show calibration boxRGBA(screen, xpos,ypos-thickness/2, (int) (xpos+barscale),ypos+thickness/2, barclr.r/2,barclr.g/2,barclr.b/2,255); // Bar boxRGBA(screen, xpos,ypos-thickness, (int) (xpos+fval*barscale),ypos+thickness, barclr.r/2,barclr.g/2,barclr.b/2,255); boxRGBA(screen, xpos,ypos-thickness/2, (int) (xpos+fval*barscale),ypos+thickness/2, barclr.r,barclr.g,barclr.b,255); } } }; // Draw text display void FloDisplayBarSwitch::Draw(SDL_Surface *screen) { const static SDL_Color titleclr = { 0x77, 0x88, 0x99, 0 }, warnclr = { 0xFF, 0, 0, 0 }; const static SDL_Color barclr[2] = { { 0xEF, 0xAF, 0xFF, 0 }, { 0xCF, 0x4F, 0xFC, 0 } }; const static float calwidth = 1.1; const SDL_Color *bc = (color == 2 ? &barclr[1] : &barclr[0]); if (font != 0 && font->font != 0) { // Draw title if (title != 0) VideoIO::draw_text(screen,font->font, title,xpos,ypos,titleclr, (orient == O_Vertical ? 1 : 2), (orient == O_Horizontal ? 1 : 0)); } // Get value of expression UserVariable val = exp->Evaluate(0); float fval = (float) val; UserVariable sval = switchexp->Evaluate(0); char sw = (char) sval; if (calibrate && fval >= cval) bc = &warnclr; if (dbscale) { // dB // Convert linear value to dB and then to fader level: int lvl = (int) (AudioLevel::dB_to_fader(LIN2DB(fval), maxdb) * barscale); // Draw bar if (orient == O_Vertical) { // Vertical if (marks) { // Show calibration const static float mindb = -60., dbstep = 6.0; int clrstep = (int) (255/((maxdb-mindb)/dbstep)), clr = 0; for (float i = mindb; i <= maxdb; i += dbstep, clr += clrstep) { int clvl = (int) (AudioLevel::dB_to_fader(i, maxdb) * barscale); hlineRGBA(screen, xpos-(int) (calwidth*thickness/2), xpos-thickness/2, ypos-clvl, clr,clr,clr,(sw ? 255 : 127)); hlineRGBA(screen, xpos+thickness/2, xpos+(int) (calwidth*thickness/2), ypos-clvl, clr,clr,clr,(sw ? 255 : 127)); } } // Bar boxRGBA(screen, xpos-thickness/2,ypos, xpos+thickness/2,ypos-lvl, bc->r,bc->g,bc->b,(sw ? 255 : 127)); } else { // Horizontal if (marks) { // Show calibration const static float mindb = -60., dbstep = 6.0; int clrstep = (int) (255/((maxdb-mindb)/dbstep)), clr = 0; for (float i = mindb; i <= maxdb; i += dbstep, clr += clrstep) { int clvl = (int) (AudioLevel::dB_to_fader(i, maxdb) * barscale); vlineRGBA(screen, xpos+clvl, ypos-(int) (calwidth*thickness/2), ypos-thickness/2, clr,clr,clr,(sw ? 255 : 127)); vlineRGBA(screen, xpos+clvl, ypos+thickness/2, ypos+(int) (calwidth*thickness/2), clr,clr,clr,(sw ? 255 : 127)); } } // Bar boxRGBA(screen, xpos,ypos-thickness/2, xpos+lvl,ypos+thickness/2, bc->r,bc->g,bc->b,(sw ? 255 : 127)); } } else { // Linear // Draw bar if (orient == O_Vertical) { // Vertical // Bar boxRGBA(screen, xpos-thickness/2,ypos, xpos+thickness/2,(int) (ypos-fval*barscale), bc->r,bc->g,bc->b,(sw ? 255 : 127)); // Calibrate if (calibrate) hlineRGBA(screen, xpos-thickness/2, xpos+thickness/2, (int) (ypos-cval*barscale), 255,255,255,(sw ? 255 : 127)); } else { // Horizontal // Bar boxRGBA(screen, xpos,ypos-thickness/2, (int) (xpos+fval*barscale),ypos+thickness/2, bc->r,bc->g,bc->b,(sw ? 255 : 127)); // Calibrate if (calibrate) vlineRGBA(screen, (int) (xpos+cval*barscale), ypos-thickness/2, ypos+thickness/2, 255,255,255,(sw ? 255 : 127)); } } }; // Draw this element to the given screen- // implementation given in videoio.cc void FloLayoutBox::Draw(SDL_Surface *screen, SDL_Color clr) { // Solid box boxRGBA(screen, left,top,right,bottom, clr.r,clr.g,clr.b,255); // Outline if (lineleft) vlineRGBA(screen,left,top,bottom,0,0,0,255); if (lineright) vlineRGBA(screen,right,top,bottom,0,0,0,255); if (linetop) hlineRGBA(screen,left,right,top,0,0,0,255); if (linebottom) hlineRGBA(screen,left,right,bottom,0,0,0,255); }; // Draw snapshots display void FloDisplaySnapshots::Draw(SDL_Surface *screen) { const static SDL_Color titleclr = { 0x77, 0x88, 0x99, 0 }; const static SDL_Color borderclr = { 0xFF, 0x50, 0x20, 0 }; const static SDL_Color cursorclr = { 0xEF, 0x11, 0x11, 0 }; LockSnaps(); if (numdisp == -1) { int height = TTF_FontHeight(font->font); numdisp = sy/height; } boxRGBA(screen, xpos,ypos,xpos+sx,ypos+sy, 0,0,0,190); vlineRGBA(screen,xpos,ypos,ypos+sy, borderclr.r,borderclr.g,borderclr.b,255); vlineRGBA(screen,xpos+sx,ypos,ypos+sy, borderclr.r,borderclr.g,borderclr.b,255); hlineRGBA(screen,xpos,xpos+sx,ypos, borderclr.r,borderclr.g,borderclr.b,255); hlineRGBA(screen,xpos,xpos+sx,ypos+sy, borderclr.r,borderclr.g,borderclr.b,255); if (font != 0 && font->font != 0) { // Draw title if (title != 0) VideoIO::draw_text(screen,font->font, title,xpos+sx/2,ypos,titleclr,1,2); } // Draw items int cury = ypos+margin; int height = TTF_FontHeight(font->font); for (int i = firstidx; i < firstidx + numdisp; i++, cury += height) { const static int SNAP_NAME_LEN = 512; char buf[SNAP_NAME_LEN]; Snapshot *sn = app->getSNAP(i); if (sn != 0) { RenameUIVars *rui = 0; char *nm = sn->name; if (renamer != 0 && i == rename_idx) { // Use current name from renamer rui = renamer->UpdateUIVars(); nm = renamer->GetCurName(); } if (nm != 0) snprintf(buf,SNAP_NAME_LEN,"%2d %s",i+1,nm); else if (sn->exists != 0) snprintf(buf,SNAP_NAME_LEN,"%2d **",i+1); else snprintf(buf,SNAP_NAME_LEN,"%2d",i+1); int sx, sy; VideoIO::draw_text(screen,font->font, buf,xpos+margin,cury,titleclr,0,0,&sx,&sy); if (rui != 0 && rui->rename_cursor_toggle) boxRGBA(screen, xpos+margin+sx,cury, xpos+margin+sx+sy/2,cury+sy, cursorclr.r,cursorclr.g,cursorclr.b,255); } } UnlockSnaps(); }; CircularMap::CircularMap(SDL_Surface *in, int map_xs, int map_ys, int in_xs, int in_ys, int rinner, int rsize) : in(in), map_xs(map_xs), map_ys(map_ys), in_xs(in_xs), in_ys(in_ys), rinner(rinner), rsize(rsize), next(0) { // Allocate memory for maps map = new Uint8 *[map_xs * map_ys]; // 4 scan run lengths per scanline scanmap = new int[4 * map_ys]; // Compute constants int map_xc = map_xs/2; int map_yc = map_ys/2; int pitch = in->pitch; int bpp = in->format->BytesPerPixel; Uint8 *in_base = (Uint8 *) in->pixels; // Now generate, interating across output range for (int y = 0; y < map_ys; y++) { int runnum = 0, // Count of consecutive written/notwritten pixels // Positive is written, negative is notwritten pixelscount = 0; for (int x = 0; x < map_xs; x++) { //printf("%d %d\n", x, y); int yofs = y-map_yc, xofs = map_xc-x; float theta = atan2(yofs,xofs), in_x = in_xs*(theta+M_PI)/(2*M_PI); // Now that we know x mapping, based on calculated theta (see theta) // Let's get y mapping float in_y; if (sin(theta) == 0) { // This fixes an annoying horizontal crack in the map in_y = (xofs-rinner)*in_ys/rsize; //printf("xofs: %d yofs: %d inx: %f iny: %f\n",xofs,yofs,in_x,in_y); } else in_y = (yofs/sin(theta)-rinner)*in_ys/rsize; // Are we in range, honey? int idx = y*map_xs + x; if (in_x >= 0 & in_y >= 0 && in_x < in_xs && in_y < in_ys) { /*printf("%d %d\n", x, y); printf(" in[%d,%d]\n",(int)in_x,(int)in_y);*/ // Yup-- write the map map[idx] = in_base + round(in_y)*pitch + round(in_x)*bpp; // Generate scan map if (pixelscount <= 0) { // OK start of run // Write number of empty pixels from last run to here scanmap[y*4 + runnum] = -pixelscount; //printf("Y:%d r:%d cnt: %d\n",y,runnum,-pixelscount); runnum++; pixelscount = 0; } pixelscount++; } else { //printf(" none\n"); // Mapping is empty for this location map[idx] = 0; // Generate scan map if (pixelscount > 0) { // OK end of run // Write number of pixels written from beginning of run to here scanmap[y*4 + runnum] = pixelscount; //printf("Y:%d r:%d cnt: %d\n",y,runnum,pixelscount); runnum++; pixelscount = 0; } pixelscount--; } } // Now write the rest of scan map if (pixelscount > 0) { // OK end of run // Write number of pixels written from beginning of run to here scanmap[y*4 + runnum] = pixelscount; //printf("Y:%d r:%d cnt: %d\n",y,runnum,pixelscount); runnum++; } //printf("EOL- r:%d\n",runnum); //usleep(100000); for (; runnum < 4; runnum++) scanmap[y*4 + runnum] = -1; } } CircularMap::~CircularMap() { delete[] scanmap; delete[] map; }; // Map flat scope onto circle // Return nonzero on error char CircularMap::Map(SDL_Surface *out, int dstx, int dsty) { int bpp; int *tmpscan = scanmap; // Get surface format bpp = out->format->BytesPerPixel; if (bpp != in->format->BytesPerPixel) { printf("VIDEO: ERROR: Temporary buffer & video screen not " "matching depth (in: %d out: %d).\n", in->format->BytesPerPixel,bpp); return 1; } // Check for clipping if (dstx < 0 || dsty < 0 || dstx+map_xs >= out->w || dsty+map_ys >= out->h) return 1; // Don't handle clip case-- just don't draw! /* * Lock the surface */ if (SDL_MUSTLOCK(out)) { if (SDL_LockSurface(out) < 0) { return 1; } } int out_pitch = out->pitch; Uint8 **ptr = map, **ptr2, *optr = (Uint8 *) out->pixels + dsty*out_pitch + dstx*bpp, *optr2; Uint8 *op, *ip; int ofs, scanleft; for (int y = 0; y < map_ys; y++, ptr += map_xs, optr += out_pitch, tmpscan += scanleft) { scanleft = 4; ptr2 = ptr; optr2 = optr; // What's the first x location on this scanline we should look at? while ((ofs = *tmpscan) != -1 && scanleft) { tmpscan++; // Starting position on this scanline ptr2 += ofs; optr2 += ofs*bpp; //printf("wy:%d sofs:%d ",y,ofs); // And the number of bytes in the run on this scanline ofs = *(tmpscan++); //printf("len:%d\n",ofs); // Depending on the number of bytes per pixel, handle this scanline // differently-- optimized subroutines follow.. switch (bpp) { case 1: { for (int i = 0; i < ofs; i++, ptr2++, optr2 += bpp) // Copy 1 byte pixels *optr2 = **ptr2; } break; case 2: { for (int i = 0; i < ofs; i++, ptr2++, optr2 += bpp) // Copy 2 byte pixels *((Uint16 *) optr2) = *((Uint16 *) (*ptr2)); } break; case 3: { // 3 byte pixels for (int i = 0; i < ofs; i++, ptr2++, optr2 += bpp) { // Access the map to find offset into input ip = *ptr2; // And output pointer is right there op = optr2; if (SDL_BYTEORDER == SDL_BIG_ENDIAN) { ip += 2; // Copy, reversing bit order for this pixel for (int n = 0; n < bpp; n++) *(op++) = *(ip--); } else { // Copy, regular bit order for this pixel for (int n = 0; n < bpp; n++) *(op++) = *(ip++); } } } break; case 4: { for (int i = 0; i < ofs; i++, ptr2++, optr2 += bpp) // Copy 4 byte pixels *((Uint32 *) optr2) = *((Uint32 *) (*ptr2)); } break; } // Ok, 1 scan run complete, so 2 endpoints less on scanline scanleft -= 2; } } /* * Unlock surface */ if (SDL_MUSTLOCK(out)) { SDL_UnlockSurface(out); } return 0; }; // ******** VIDEO HANDLER int VideoIO::activate() { #ifdef __MACOSX__ // On Mac OS X, prime video in main thread SetVideoMode(0); #endif #if 1 printf("VIDEO: Starting handler..\n"); pthread_mutex_init (&video_thread_lock,0); const static size_t STACKSIZE = 1024*128; pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setstacksize(&attr,STACKSIZE); printf("VIDEO: Stacksize: %d.\n",STACKSIZE); int ret = pthread_create(&video_thread, &attr, run_video_thread, this); if (ret != 0) { printf("VIDEO: (start) pthread_create failed, exiting"); return 1; } SRMWRingBuffer_Writers::RegisterWriter(video_thread); // Setup low priority thread #if 0 struct sched_param schp; memset(&schp, 0, sizeof(schp)); schp.sched_priority = sched_get_priority_min(SCHED_OTHER); printf("VIDEO: Low priority thread %d\n",schp.sched_priority); if (pthread_setschedparam(video_thread, SCHED_OTHER, &schp) != 0) printf("VIDEO: Can't set thread priority, will use regular!\n"); #endif // Listen for events if (app->getEMG() == 0) { printf("VIDEO: Error: Event Manager not yet active!\n"); exit(1); } app->getEMG()->ListenEvent(this,0,T_EV_VideoShowSnapshotPage); app->getEMG()->ListenEvent(this,0,T_EV_VideoShowLoop); app->getEMG()->ListenEvent(this,0,T_EV_VideoShowDisplay); app->getEMG()->ListenEvent(this,0,T_EV_VideoShowLayout); app->getEMG()->ListenEvent(this,0,T_EV_VideoSwitchInterface); app->getEMG()->ListenEvent(this,0,T_EV_VideoShowHelp); app->getEMG()->ListenEvent(this,0,T_EV_VideoFullScreen); app->getEMG()->ListenEvent(this,0,T_EV_Input_MouseButton); app->getEMG()->ListenEvent(this,0,T_EV_Input_MouseMotion); #endif return 0; } void VideoIO::close() { app->getEMG()->UnlistenEvent(this,0,T_EV_VideoShowSnapshotPage); app->getEMG()->UnlistenEvent(this,0,T_EV_VideoShowLoop); app->getEMG()->UnlistenEvent(this,0,T_EV_VideoShowDisplay); app->getEMG()->UnlistenEvent(this,0,T_EV_VideoShowLayout); app->getEMG()->UnlistenEvent(this,0,T_EV_VideoSwitchInterface); app->getEMG()->UnlistenEvent(this,0,T_EV_VideoShowHelp); app->getEMG()->UnlistenEvent(this,0,T_EV_VideoFullScreen); app->getEMG()->UnlistenEvent(this,0,T_EV_Input_MouseButton); app->getEMG()->UnlistenEvent(this,0,T_EV_Input_MouseMotion); videothreadgo = 0; pthread_join(video_thread,0); pthread_mutex_destroy (&video_thread_lock); printf("VIDEO: end\n"); } void VideoIO::ReceiveEvent(Event *ev, EventProducer *from) { switch (ev->GetType()) { case T_EV_Input_MouseMotion : { MouseMotionInputEvent *mev = (MouseMotionInputEvent *) ev; // Notify all visible browsers of mouse move FloDisplay *curdisplay = app->getCFG()->GetDisplays(); char skip = 0; while (curdisplay != 0 && !skip) { if ((curdisplay->show || curdisplay->forceshow) && curdisplay->GetFloDisplayType() == FD_Browser) skip = ((Browser *) curdisplay)->MouseMotion(mev); curdisplay = curdisplay->next; } } break; case T_EV_Input_MouseButton : { MouseButtonInputEvent *mev = (MouseButtonInputEvent *) ev; // Notify all visible browsers of button press FloDisplay *curdisplay = app->getCFG()->GetDisplays(); char skip = 0; while (curdisplay != 0 && !skip) { if ((curdisplay->show || curdisplay->forceshow) && curdisplay->GetFloDisplayType() == FD_Browser) skip = ((Browser *) curdisplay)->MouseButton(mev); curdisplay = curdisplay->next; } if (!skip) { // Only continue if a browser hasn't eaten the event // Has the mouse button been pressed inside any of the // on-screen layout elements? FloLayout *cur = app->getCFG()->GetLayouts(); while (cur != 0) { if (cur->show) { int firstid = cur->loopids.lo, curid = firstid, maxid = cur->loopids.hi; // Check each element in this layout FloLayoutElement *curel = cur->elems; while (curel != 0 && curid <= maxid) { if (curel->Inside(mev->x,mev->y)) { // Mouse button inside element- // Issue 'loop clicked' event LoopClickedEvent *lcevt = (LoopClickedEvent *) Event::GetEventByType(T_EV_LoopClicked); lcevt->button = mev->button; lcevt->down = mev->down; lcevt->loopid = firstid + curel->id; lcevt->in = 1; // In=1 means clicked in on-screen layout app->getEMG()->BroadcastEventNow(lcevt, this); if (CRITTERS) printf("MOUSE: Button #%d %s in element: %s\n", mev->button, (mev->down ? "pressed" : "released"), curel->name); } curid++; curel = curel->next; } } cur = cur->next; } } } break; case T_EV_VideoShowSnapshotPage : { VideoShowSnapshotPageEvent *vev = (VideoShowSnapshotPageEvent *) ev; if (CRITTERS) printf("VIDEO: %s snapshot page (interface id %d, display id %d)\n", (vev->page < 0 ? "Previous" : "Next"), vev->interfaceid,vev->displayid); // Find the right display FloDisplay *cur = app->getCFG()->GetDisplayById(vev->interfaceid, vev->displayid); if (cur != 0 && cur->GetFloDisplayType() == FD_Snapshots) { FloDisplaySnapshots *sn = (FloDisplaySnapshots *) cur; if (vev->page < 0) { int newidx = sn->firstidx - sn->numdisp; if (newidx < 0) newidx = 0; sn->firstidx = newidx; } else { int newidx = sn->firstidx + sn->numdisp; if (newidx < app->getCFG()->GetMaxSnapshots()) sn->firstidx = newidx; } } else printf("VIDEO: Specified display is not a snapshot display " "(interface id %d, display id %d)\n", vev->interfaceid,vev->displayid); } break; case T_EV_VideoShowLoop : { VideoShowLoopEvent *vev = (VideoShowLoopEvent *) ev; if (CRITTERS) printf("VIDEO: Show loop (interface %d layout %d): %d>%d\n", vev->interfaceid, vev->layoutid,vev->loopid.lo,vev->loopid.hi); // Error check range if (vev->loopid.lo < 0 || vev->loopid.hi < 0 || vev->loopid.lo >= app->getCFG()->GetNumTriggers() || vev->loopid.hi >= app->getCFG()->GetNumTriggers() || vev->loopid.hi < vev->loopid.lo) { printf("VIDEO: Invalid loopid range for interface %d " "layout %d: %d>%d\n", vev->interfaceid, vev->layoutid,vev->loopid.lo,vev->loopid.hi); } else { // Find the right layout int id = vev->layoutid, iid = vev->interfaceid; FloLayout *cur = app->getCFG()->GetLayouts(); char found = 0; while (cur != 0) { if (iid == cur->iid && id == cur->id) { // Match-- change the range of displayed loops for // this layout cur->loopids = vev->loopid; found = 1; } cur = cur->next; } if (!found) printf("VIDEO: Invalid layoutid %d in interface %d.\n", vev->layoutid,vev->interfaceid); } } break; case T_EV_VideoShowDisplay : { VideoShowDisplayEvent *vev = (VideoShowDisplayEvent *) ev; if (CRITTERS) printf("VIDEO: %s display (interface id %d, display id %d)\n", (vev->show ? "show" : "hide"), vev->interfaceid,vev->displayid); // Find the right display FloDisplay *cur = app->getCFG()->GetDisplayById(vev->interfaceid, vev->displayid); if (cur != 0) cur->show = vev->show; else printf("VIDEO: Invalid display (interface id %d, display id %d)\n", vev->interfaceid,vev->displayid); } break; case T_EV_VideoShowLayout : { VideoShowLayoutEvent *vev = (VideoShowLayoutEvent *) ev; if (CRITTERS) printf("VIDEO: %s layout (interface id %d, layout id %d) %s\n", (vev->show ? "show" : "hide"), vev->interfaceid,vev->layoutid, (vev->hideothers ? "(hide others)" : "")); // Find the right layout int iid = vev->interfaceid, id = vev->layoutid; FloLayout *cur = app->getCFG()->GetLayouts(); char found = 0; while (cur != 0) { if (iid == cur->iid && id == cur->id) { // Match! // Set show or hide cur->show = vev->show; found = 1; } else if (vev->hideothers) { // Hide other layouts cur->show = 0; } cur = cur->next; } if (!found) printf("VIDEO: Invalid layoutid %d in interface %d.\n", vev->layoutid,vev->interfaceid); } break; case T_EV_VideoSwitchInterface : { // Here, we show all layouts & displays that belong to the given // interface // All other layouts & displays are hidden, unless they belong to a // non-switchable interface VideoSwitchInterfaceEvent *vev = (VideoSwitchInterfaceEvent *) ev; if (CRITTERS) printf("VIDEO: Switch to interface %d\n",vev->interfaceid); // Show/hide layouts int iid = vev->interfaceid; { FloLayout *cur = app->getCFG()->GetLayouts(); while (cur != 0) { if (cur->iid != 0 && cur->iid < NS_INTERFACE_START_ID) { // Switchable interface? if (cur->iid == iid) // Layout in matching interface- show cur->show = 1; else // Layout in unmatching interface- hide cur->show = 0; } cur = cur->next; } } { FloDisplay *cur = app->getCFG()->GetDisplays(); while (cur != 0) { if (cur->iid != 0 && cur->iid < NS_INTERFACE_START_ID) { // Switchable interface? if (cur->iid == iid) // Display in matching interface- show cur->show = 1; else // Display in unmatching interface- hide cur->show = 0; } cur = cur->next; } } } break; case T_EV_VideoShowHelp : { VideoShowHelpEvent *vev = (VideoShowHelpEvent *) ev; if (CRITTERS) printf("VIDEO: show help page - %d%s\n", vev->page,(vev->page ? "" : " - off")); if (vev->page >= 0 && vev->page <= numhelppages) showhelppage = vev->page; else printf("VIDEO: invalid help page - %d (valid range: 0-%d)\n", vev->page,numhelppages); } break; case T_EV_VideoFullScreen : { VideoFullScreenEvent *vev = (VideoFullScreenEvent *) ev; if (CRITTERS) printf("VIDEO: set full screen = %s\n", (vev->fullscreen ? "on" : "off")); SetVideoMode(vev->fullscreen); } break; default: break; } }; // This is a custom surface blitter that doesn't use large block // memory writes and thus avoids the strange video glitch of introducing // audio pops on some machines-- some loss in performance! void VideoIO::Custom_BlitSurface(SDL_Surface *in, SDL_Surface *out, SDL_Rect *dstrect) { int opitch = out->pitch, ipitch = in->pitch, bpp = out->format->BytesPerPixel; if (bpp != in->format->BytesPerPixel) { printf("VIDEO: ERROR: Buffer and screen different format!\n"); return; } /* * Lock the surface */ if (SDL_MUSTLOCK(out)) { if (SDL_LockSurface(out) < 0) { return; } } Uint8 *opixels = (Uint8 *)out->pixels + dstrect->y*opitch + dstrect->x*bpp, *ipixels = (Uint8 *)in->pixels; int xrun = (dstrect->x+dstrect->w <= out->w ? dstrect->w : out->w-dstrect->x), yrun = (dstrect->y+dstrect->h <= out->h ? dstrect->h : out->h-dstrect->y), ojump = opitch-xrun*bpp, ijump = ipitch-xrun*bpp; switch (bpp) { case 1 : { for (int i = 0; i < yrun; i++, opixels += ojump, ipixels += ijump) for (int j = 0; j < xrun; j++, opixels += bpp, ipixels += bpp) *opixels = *ipixels; } break; case 2 : { for (int i = 0; i < yrun; i++, opixels += ojump, ipixels += ijump) for (int j = 0; j < xrun; j++, opixels += bpp, ipixels += bpp) *((Uint16 *) opixels) = *((Uint16 *) ipixels); } break; case 3 : { for (int i = 0; i < yrun; i++, opixels += ojump, ipixels += ijump) for (int j = 0; j < xrun; j++, opixels += bpp, ipixels += bpp) { *(opixels++) = *(ipixels++); *(opixels++) = *(ipixels++); *(opixels++) = *(ipixels++); } } break; case 4 : { for (int i = 0; i < yrun; i++, opixels += ojump, ipixels += ijump) for (int j = 0; j < xrun; j++, opixels += bpp, ipixels += bpp) *((Uint32 *) opixels) = *((Uint32 *) ipixels); } break; } /* * Unlock surface */ if (SDL_MUSTLOCK(out)) { SDL_UnlockSurface(out); } }; void VideoIO::Squeeze_BlitSurface(SDL_Surface *in, SDL_Surface *out, SDL_Rect *dstrect) { int opitch = out->pitch, ipitch = in->pitch, bpp = out->format->BytesPerPixel; if (bpp != in->format->BytesPerPixel) { printf("VIDEO: ERROR: Buffer and screen different format!\n"); return; } if (dstrect->w == 0 || dstrect->h == 0) return; if (dstrect->h > in->h) dstrect->h = in->h; /* * Lock the surface */ if (SDL_MUSTLOCK(out)) { if (SDL_LockSurface(out) < 0) { return; } } Uint8 *opixels = (Uint8 *)out->pixels + dstrect->y*opitch + dstrect->x*bpp, *ipixels = (Uint8 *)in->pixels; float yscale = (float) in->h/dstrect->h; int xrun = (dstrect->x+dstrect->w <= out->w ? dstrect->w : out->w-dstrect->x), yh = (dstrect->y+dstrect->h <= out->h ? dstrect->h : out->h-dstrect->y), yrun = (int) (yh*yscale), ojump = opitch-xrun*bpp, ijump = ipitch-xrun*bpp, ilinejump = ipitch; /* printf("xrun: %d yrun: %d w: %d h: %d yscale: %.2f ijump: %d\n", xrun,yrun, in->w,in->h, yscale,ijump); */ switch (bpp) { case 1 : { for (float i = 0; i < yrun; opixels += ojump) { for (int j = 0; j < xrun; j++, opixels += bpp, ipixels += bpp) *opixels = *ipixels; int oldi = (int)i; i += yscale; ipixels += ijump+ilinejump*((int)i-(int)oldi-1); } } break; case 2 : { for (float i = 0; i < yrun; opixels += ojump) { for (int j = 0; j < xrun; j++, opixels += bpp, ipixels += bpp) *((Uint16 *) opixels) = *((Uint16 *) ipixels); int oldi = (int)i; i += yscale; ipixels += ijump+ilinejump*((int)i-(int)oldi-1); } } break; case 3 : { for (float i = 0; i < yrun; opixels += ojump) { for (int j = 0; j < xrun; j++, opixels += bpp, ipixels += bpp) { *(opixels++) = *(ipixels++); *(opixels++) = *(ipixels++); *(opixels++) = *(ipixels++); } int oldi = (int)i; i += yscale; ipixels += ijump+ilinejump*((int)i-(int)oldi-1); } } break; case 4 : { for (float i = 0; i < yrun; opixels += ojump) { for (int j = 0; j < xrun; j++, opixels += bpp, ipixels += bpp) *((Uint32 *) opixels) = *((Uint32 *) ipixels); int oldi = (int)i; i += yscale; ipixels += ijump+ilinejump*((int)i-(int)oldi-1); } } break; } /* * Unlock surface */ if (SDL_MUSTLOCK(out)) { SDL_UnlockSurface(out); } }; // Draws text on the given surface // Justify is 0 for default justify, 1 for center, and 2 for opposite side // Returns size of text drawn in sx and sy (optionally) int VideoIO::draw_text(SDL_Surface *out, TTF_Font *font, char *str, int x, int y, SDL_Color clr, char justifyx, char justifyy, int *sx, int *sy) { SDL_Surface *text; SDL_Rect dstrect; SDL_Color black = { 0, 0, 0, 0 }; text = TTF_RenderText_Shaded(font, str, clr, black); if ( text != NULL ) { dstrect.x = x; dstrect.y = y; dstrect.w = text->w; dstrect.h = text->h; if (sx != 0) *sx = dstrect.w; if (sy != 0) *sy = dstrect.h; if (justifyx) dstrect.x -= (justifyx == 1 ? dstrect.w/2 : dstrect.w); if (justifyy) dstrect.y -= (justifyy == 1 ? dstrect.h/2 : dstrect.h); SDL_SetColorKey(text, SDL_SRCCOLORKEY|SDL_RLEACCEL, 0); SDL_BlitSurface(text, NULL, out, &dstrect); SDL_FreeSurface(text); } else { if (sx != 0) *sx = 0; if (sy != 0) *sy = 0; return 1; } return 0; } char VideoIO::DrawLoop(LoopManager *loopmgr, int i, SDL_Surface *screen, SDL_Surface *lscopepic, SDL_Color *loopcolors, float colormag, FloConfig *fs, FloLayoutElement *curel, CircularMap *direct_map, int direct_xpos, int direct_ypos, float lvol, char drawtext) { const static SDL_Color txtclr = { 0xFF, 0x50, 0x20, 0 }, cursorclr = { 0xEF, 0x11, 0x11, 0 }, txtclr2 = { 0xEF, 0xAF, 0xFF, 0 }; // Color for selected loops static SDL_Color selcolor[4] = { { 0xF9, 0xE6, 0x13, 0 }, { 0x62, 0x62, 0x62, 0 }, { 0xFF, 0xFF, 0xFF, 0 }, { 0xE0, 0xDA, 0xD5, 0 } }; const float cpeak_mul = 2.0, // For pulsing loops - magnitude of pulse cpeak_base = 0.5; // For pulsing loops - base size of loop const int lscope_maxmag = OCY(15), lscopemag = OCY(20), looppiemag = OCX(20); BED_PeaksAvgs *pa; nframes_t plen = 0; float curpeak = 1.0, ispd; sample_t *peakbuf, *avgbuf; static int liney = -1; // How high is a line of text? // Lockup loops so that loop manager doesn't go and delete one while we // are drawing it loopmgr->LockLoops(); Loop *l = 0; if (loopmgr->GetStatus(i) == T_LS_Recording) { // Use current record length for visual size pa = (BED_PeaksAvgs *) ((RecordProcessor *) loopmgr-> GetProcessor(i))-> GetFirstRecordedBlock()->GetExtendedData(T_BED_PeaksAvgs); if (pa != 0) { PeaksAvgsManager *pa_mgr = ((RecordProcessor *) loopmgr-> GetProcessor(i))->GetPAMgr(); if (pa_mgr != 0) plen = pa_mgr->GetPeaksI()->GetTotalLength2Cur(); } } else { l = loopmgr->GetSlot(i); if (l != 0) { // Double check the loop is still there // Use loop length for visual size pa = (BED_PeaksAvgs *) l->blocks->GetExtendedData(T_BED_PeaksAvgs); } else pa = 0; if (pa != 0) plen = pa->peaks->GetTotalLen(); } char selected = 0; if (l != 0 && l->selcnt > 0) { selected = 1; loopcolors = selcolor; // Color loop selected } // Draw peaks & avgs float loopvol = 1.0, // Loop volume loopdvol = 1.0; // Loop volume delta if (pa != 0) { // Background SDL_FillRect(lscopepic,NULL, SDL_MapRGB(lscopepic->format, (int) (loopcolors[0].r*colormag), (int) (loopcolors[0].g*colormag), (int) (loopcolors[0].b*colormag))); if (plen > 0) { // Access buffers peakbuf = pa->peaks->buf; avgbuf = pa->avgs->buf; loopvol = loopmgr->GetLoopVolume(i); loopdvol = loopmgr->GetLoopdVolume(i); nframes_t idx = loopmgr->GetCurCnt(i)/ fs->loop_peaksavgs_chunksize; // Compute current peak curpeakidx[i] = idx; if (curpeakidx[i] == lastpeakidx[i]) curpeak = oldpeak[i]; // No new peak data since last update! else { nframes_t j = lastpeakidx[i]; if (curpeakidx[i] < lastpeakidx[i]) j = 0; curpeak = 0; for (; j < curpeakidx[i]; j++) curpeak = MAX(curpeak,peakbuf[j]*loopvol); curpeak *= cpeak_mul; curpeak += cpeak_base; oldpeak[i] = curpeak; lastpeakidx[i] = curpeakidx[i]; } float cmag = lvol*loopvol*lscopemag*curpeak; float rv1 = loopcolors[1].r*colormag, gv1 = loopcolors[1].g*colormag, bv1 = loopcolors[1].b*colormag, rv2 = loopcolors[2].r*colormag, gv2 = loopcolors[2].g*colormag, bv2 = loopcolors[2].b*colormag; int midpt = lscopepic->h/2; // Ratio of visual size to audio scope buffer length ispd = (float) lscopepic->w / plen; // Write into the buffer on sliding position to give animated // scope effect float pos = -(float)idx*ispd; if (pos < 0.) pos += (float)lscopepic->w; for (nframes_t j = 0; j < plen; j++, pos += ispd) { float pbj = peakbuf[j]; int peakd = (int) (cmag*pbj); if (peakd > lscope_maxmag) peakd = lscope_maxmag; if (pos >= (float)lscopepic->w) pos = 0.; float peaky = avgbuf[j]/(pbj*pbj + 0.00000001)*2; if (peaky > 1.0) peaky = 1.0; float rv = rv1 * peaky + rv2 * (1.-peaky), gv = gv1 * peaky + gv2 * (1.-peaky), bv = bv1 * peaky + bv2 * (1.-peaky); //if (rv > 255) rv = 255; //if (gv > 255) gv = 255; //if (bv > 255) bv = 255; if (ispd >= 1.) { int pos1 = (int) pos, pos2 = (int) (pos+ispd); boxRGBA(lscopepic, (int) pos1, midpt-peakd, (int) pos2, midpt+peakd, (int) rv, (int) gv, (int) bv, 255); } else vlineRGBA(lscopepic, (int) pos, midpt-peakd, midpt+peakd, (int) rv, (int) gv, (int) bv, 255); } } } // loopmgr->UnlockLoops(); // Map flat scope onto circle CircularMap *loopmap; int dispx, dispy; if (curel != 0) { // Show in layout loopmap = curel->loopmap; dispx = curel->loopx; dispy = curel->loopy; } else { // Show direct on screen loopmap = direct_map; dispx = direct_xpos; dispy = direct_ypos; } int fullx = loopmap->map_xs, fully = loopmap->map_ys, halfx = fullx/2, halfy = fully/2; if (curel != 0) { // Layout specifies center of loop position.. compensate dispx -= halfx; dispy -= halfy; } // Show scope if (!loopmap->Map(screen,dispx,dispy)) { circleRGBA(screen,dispx+halfx,dispy+halfy,halfx, 0,0,0, 255); // Outline // Show portion played in semitranslucent int pieradius = MIN((int) (lvol*looppiemag*curpeak),70); FILLED_PIE(screen,dispx+halfx,dispy+halfy, pieradius,0, (int) (360*loopmgr->GetPos(i)), (int) (loopcolors[3].r*colormag), (int) (loopcolors[3].g*colormag), (int) (loopcolors[3].b*colormag),127); // Show volume float loop_volmag = fullx*0.9/2, // For loop volume bar loop_dvolmag = fullx*250; // For loop volume delta bar int magbar = (int) (loop_volmag*loopmgr->GetTriggerVol(i)); boxRGBA(screen,dispx+halfx-magbar, dispy+halfy-halfy/5, dispx+halfx+magbar, dispy+halfy+halfy/5, (int) (loopcolors[3].r*colormag),0,0, 127); // Show volume delta magbar = (int) ((loopdvol-1.0)*loop_dvolmag); boxRGBA(screen,dispx+halfx, dispy+halfy+halfy/4, dispx+halfx+magbar, dispy+halfy+halfy/2, (int) (loopcolors[3].r*colormag),0,0, 127); // Show if overdub if (loopmgr->GetStatus(i) == T_LS_Overdubbing) draw_text(screen,mainfont,"O",dispx+halfx,dispy+halfy,txtclr,1,1); if (drawtext) { // Show loop name ItemRenamer *renamer = loopmgr->GetRenamer(); if (renamer != 0 && l == loopmgr->GetRenameLoop()) { // This loop is being renamed- show current name RenameUIVars *rui = renamer->UpdateUIVars(); if (liney == -1) TTF_SizeText(smallfont,VERSION,0,&liney); // Draw text with cursor int sx, sy; int txty = dispy+fully; char *curn = renamer->GetCurName(); if (*curn != '\0') VideoIO::draw_text(screen,smallfont,curn, dispx,txty,txtclr2,0,2,&sx,&sy); else { sx = 0; sy = liney; } if (rui->rename_cursor_toggle) boxRGBA(screen, dispx+sx,txty, dispx+sx+sy/2,txty-sy, cursorclr.r,cursorclr.g,cursorclr.b,255); } else if (l != 0 && l->name != 0) // Show name draw_text(screen,smallfont,l->name, dispx,dispy+fully,txtclr2,0,2); // Show last recorded loop # int cnt = 0; for (cnt = 0; cnt < LAST_REC_COUNT && loopmgr->lastrecidx[cnt] != i; cnt++); if (cnt < LAST_REC_COUNT) { char tmp[50]; snprintf(tmp,50,"L%d",cnt+1); draw_text(screen,smallfont,tmp, dispx+fullx,dispy,txtclr2,2,0); } #if 0 // Old way to label loop in 'show-all-loops' mode if (curel == 0) { char tmp[50]; // Show direct-- so label the loop Pulse *a = loopmgr->GetPulse(i); long len; if (a != 0) len = loopmgr->GetRoundedLength(i)/a->len; else len = loopmgr->GetRoundedLength(i); if (len != 0) snprintf(tmp,50,"%03d %ld",i,len); else snprintf(tmp,50,"%03d",i); SDL_Color tmpclr = { (int) (loopcolors[3].r*colormag), (int) (loopcolors[3].g*colormag), (int) (loopcolors[3].b*colormag), 0 }; draw_text(screen,mainfont,tmp,dispx,dispy+textyofs,tmpclr); } #endif } loopmgr->UnlockLoops(); return 0; } else { loopmgr->UnlockLoops(); return 1; } }; // If no suitable map exists in list 'cmaps', creates a planar>circular map // of diameter 'sz', mapping from the given surface. CircularMap *VideoIO::CreateMap(SDL_Surface *lscopepic, int sz) { // OK, scan to see if a fitting map already exists CircularMap *nw; if (cmaps != 0) nw = cmaps->Scan(sz); else nw = 0; if (nw == 0) { // No fitting map found, generate one at the right size int lscope_crinner = (int) (sz*0.13), lscope_crsize = sz/2 - lscope_crinner; printf("VIDEO: Generating planar->circular map @ size %d\n",sz); nw = new CircularMap(lscopepic, sz,sz, lscopewidth,lscopeheight, lscope_crinner, lscope_crsize); // Store a copy in our list if (cmaps == 0) cmaps = nw; else cmaps->Link(nw); } return nw; }; #ifdef LCD_DISPLAY int VideoIO::InitLCD (char *devname, int baud) { struct termios term; // Open lcd_handle = open(devname, O_RDWR | O_NOCTTY /*| O_NONBLOCK*/); if (lcd_handle <= 0) { printf("InitLCD: Failed to connect to USB LCD\n"); return 1; } if (tcgetattr(lcd_handle, &term) != 0) { printf("InitLCD: tcgetattr() failed\n"); return 1; } // Input modes term.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|INPCK|ISTRIP|INLCR|IGNCR|ICRNL |IXON|IXOFF); term.c_iflag |= IGNPAR; // Output modes term.c_oflag &= ~(OPOST|ONLCR|OCRNL|ONOCR|ONLRET|OFILL |OFDEL|NLDLY|CRDLY|TABDLY|BSDLY|VTDLY|FFDLY); term.c_oflag |= NL0|CR0|TAB0|BS0|VT0|FF0; // Control modes term.c_cflag &= ~(CSIZE|PARENB|PARODD|HUPCL|CRTSCTS); term.c_cflag |= CREAD|CS8|CSTOPB|CLOCAL; // Local modes term.c_lflag &= ~(ISIG|ICANON|IEXTEN|ECHO); term.c_lflag |= NOFLSH; // Set baud rate cfsetospeed(&term, baud); cfsetispeed(&term, baud); // Set if (tcsetattr(lcd_handle, TCSANOW, &term) != 0) { printf("InitLCD: tcsetattr() failed\n"); return 1; } // Backlight off LCD_Send(14); LCD_Send(0); // Hide cursor LCD_Send(4); // Turn off "scroll" and "wrap" LCD_Send(20); LCD_Send(24); // Clear display LCD_Send(12); memset(lcd_dat,sizeof(lcd_dat),' '); lcd_curb = 0; printf("InitLCD: success\n"); return 0; } void VideoIO::LCDB_Dump () { int oldb = (lcd_curb == 0 ? 1 : 0); // Compare old and current buffers if (memcmp(&lcd_dat[lcd_curb][0][0],&lcd_dat[oldb][0][0], sizeof(char) * LCD_ROWS * LCD_COLS) != 0) { // Buffers differ, dump difference int lu_r = -2, lu_c = -2; // Last update row/col for (int r = 0; r < LCD_ROWS; r++) for (int c = 0; c < LCD_COLS; c++) if (lcd_dat[lcd_curb][r][c] != lcd_dat[oldb][r][c]) { // This cell differs- send if (r != lu_r || c != lu_c+1) { // Need to reposition- not the next character // printf("pos: %d %d\n",c,r); LCD_Send(17); LCD_Send(c); LCD_Send(r); } // Send new character // printf("%c\n",lcd_dat[lcd_curb][r][c]); LCD_Send(lcd_dat[lcd_curb][r][c]); /* printf("BUF#%d Sending: %c @ (%d,%d)\n",lcd_curb, lcd_dat[lcd_curb][r][c],c,r); */ lu_r = r; lu_c = c; } } // Switch write buffers lcd_curb = oldb; }; #endif // This is the video event loop void VideoIO::video_event_loop () { FloConfig *fs = app->getCFG(); LoopManager *loopmgr = app->getLOOPMGR(); #ifndef NO_VIDEO int XSIZE = fs->GetVSize()[0]; const static SDL_Color red = { 0xFF, 0x50, 0x20, 0 }, //blue = { 0x30, 0x20, 0xEF, 0 }, white = { 0xEF, 0xAF, 0xFF, 0 }, truewhite = { 0xFF, 0xFF, 0xFF, 0 }, gray = { 0x77, 0x88, 0x99, 0 }, yellow = { 0xDF, 0xEF, 0x20, 0 }, infobarclr = red; int nt = app->getCFG()->GetNumTriggers(); const static int num_loopcolors = 4; SDL_Color loopcolors[num_loopcolors][4] = { { { 0x5F, 0x7C, 0x2B, 0 }, { 0xD3, 0xFF, 0x82, 0 }, { 0xFF, 0xFF, 0xFF, 0 }, { 0xDE, 0xE2, 0xD5, 0 } }, { { 0x8E, 0x75, 0x62, 0 }, { 0xFF, 0x9C, 0x4C, 0 }, { 0xFF, 0xFF, 0xFF, 0 }, { 0xE0, 0xDA, 0xD5, 0 } }, { { 0x62, 0x8C, 0x85, 0 }, { 0x43, 0xF2, 0xD5, 0 }, { 0xFF, 0xFF, 0xFF, 0 }, { 0xA9, 0xC6, 0xC1, 0 } }, { { 0x69, 0x4B, 0x89, 0 }, { 0xA8, 0x56, 0xFF, 0 }, { 0xFF, 0xFF, 0xFF, 0 }, { 0xDF, 0xCB, 0xF4, 0 } } }; char tmp[255]; curpeakidx = new nframes_t[nt]; lastpeakidx = new nframes_t[nt]; oldpeak = new float[nt]; memset(curpeakidx,0,sizeof(nframes_t) * nt); memset(lastpeakidx,0,sizeof(nframes_t) * nt); for (int i = 0; i < nt; i++) oldpeak[i] = 1.0; // Video coordinates & settings const int scopemag = OCY(40), metermag = OCY(25), iscopey = OCY(350), //oscopex = 260, //oscopey = iscopey, //oscopemag = 100, patchx = OCX(35), patchy = OCY(460), pulsex = OCX(600), pulsey = OCY(20), pulsespc = OCY(40), pulsepiemag = OCX(10), // Input scope width scopewidth = XSIZE, // Y position of time marker ticks tmarky = iscopey + OCY(100), progressbar_x = OCX(20), progressbar_y = OCY(400), progressbar_xs = OCX(640)-progressbar_x*2, progressbar_ys = OCY(20); // Flat loop scope dimensions-- lscopewidth = OCX(320); lscopeheight = OCY(30); const static float loop_colorbase = 0.5; nframes_t scopelen = app->getCFG()->GetScopeSampleLen(); // Loop scope bitmap Uint8 video_bpp = screen->format->BitsPerPixel; Uint32 Rmask = screen->format->Rmask, Gmask = screen->format->Gmask, Bmask = screen->format->Bmask, Amask = screen->format->Amask; printf("VIDEO: Creating temporary buffers at %d bits\n",video_bpp); lscopepic = SDL_CreateRGBSurface(SDL_HWSURFACE, lscopewidth, lscopeheight, video_bpp, Rmask, Gmask, Bmask, Amask); // Flat // Generate circular maps for all the different sized layout elements // as defined in config // Mappings from flat to circular for loops shown at different sizes cmaps = 0; FloLayout *curlayout = fs->GetLayouts(); while (curlayout != 0) { FloLayoutElement *curel = curlayout->elems; while (curel != 0) { int sz = curel->loopsize; if (sz > 0) curel->loopmap = CreateMap(lscopepic,sz); curel = curel->next; } curlayout = curlayout->next; } #if 0 // Load title image printf("VIDEO: Loading title bitmap.\n"); SDL_Surface *titlepic = SDL_LoadBMP(FWEELIN_TITLE_IMAGE); if (titlepic == 0) { printf("Couldn't load title image from: %s\n" "Did you run 'make install'?\n", FWEELIN_TITLE_IMAGE); return; } SDL_Surface *titletemppic = SDL_CreateRGBSurface(SDL_HWSURFACE, titlepic->w, titlepic->h, video_bpp, Rmask, Gmask, Bmask, Amask); // Flat // Draw final title image with fweelin version SDL_BlitSurface(titlepic, 0, titletemppic, 0); int ver_x, ver_y; TTF_SizeText(mainfont,VERSION,&ver_x,&ver_y); draw_text(titletemppic,mainfont,VERSION, titletemppic->w-ver_x-15,titletemppic->h-ver_y-15,truewhite); SDL_FreeSurface(titlepic); #endif // Logo image SDL_Surface *logopic = 0; if (fweelin_logo.bytes_per_pixel != 4) printf("VIDEO: Warning: Logo image must be 32-bit.\n"); else { logopic = SDL_CreateRGBSurface(SDL_HWSURFACE, fweelin_logo.width, fweelin_logo.height, 32, 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000); memcpy(logopic->pixels,fweelin_logo.pixel_data, fweelin_logo.width * fweelin_logo.height * fweelin_logo.bytes_per_pixel); } // Help setup const static int helpx = OCX(0), helpy = OCY(10), helpmaxy2 = OCY(460), maxhelppages = 255; // Maximum # of help pages int helpstartidx[maxhelppages], helpendidx[maxhelppages], curstartidx; int helpx2 = helpx, curhelpy2 = helpy, helpy2 = helpy, helpmaxcol1 = 0, helpmaxcol2 = 0; int x, y1, y2; // Size up and paginate help numhelppages = 0; curstartidx = 0; for (int i = 0; i < fs->GetNumHelpLines(); i++) { char *s1 = fs->GetHelpLine(i,0), *s2 = fs->GetHelpLine(i,1); if (s1 != 0) { TTF_SizeText(helpfont,s1,&x,&y1); if (s2 != 0) { helpmaxcol1 = MAX(helpmaxcol1,x); TTF_SizeText(helpfont,s2,&x,&y2); helpmaxcol2 = MAX(helpmaxcol2,x); } else { y2 = 0; } if (curhelpy2 + MAX(y1,y2) >= helpmaxy2) { // New page helpstartidx[numhelppages] = curstartidx; helpendidx[numhelppages] = i-1; curstartidx = i; numhelppages++; if (numhelppages >= maxhelppages) { printf("VIDEO: ERROR: Too many help pages!\n"); exit(1); } helpy2 = MAX(helpy2,curhelpy2); curhelpy2 = helpy + MAX(y1,y2); } else { // Same page curhelpy2 += MAX(y1,y2); } } } helpstartidx[numhelppages] = curstartidx; helpendidx[numhelppages] = fs->GetNumHelpLines()-1; numhelppages++; // 1 is considered first help page helpx2 = helpx + helpmaxcol1 + helpmaxcol2; const static int CHECK_SIZE_FRAMES = 20; int checksizecnt = CHECK_SIZE_FRAMES; nframes_t streamoutsize = 0; char streamoutstatfailed = 0; double streamoutfloatsize = 0.0; video_time = 0; double video_start = mygettime(); #endif // NO_VIDEO #ifdef LCD_DISPLAY #define LCD_FLASHLEN 5 #define LOOPROW 1 float prev_pct = 0.0; int flashcnt = LCD_FLASHLEN; InitLCD("/dev/ttyUSB0",B19200); #endif while (videothreadgo) { // This video thread eats CPU // So for slower machines I advise using a higher delay time usleep(app->getCFG()->GetVDelay()); // Lock video space from changes pthread_mutex_lock (&video_thread_lock); #ifdef LCD_DISPLAY { LCDB_Clear(); // Draw pulse Pulse *a = loopmgr->GetPulseByIndex(0); if (a != 0) { float pct = a->GetPct(); if (pct < prev_pct) flashcnt = 0; // LCDB_SetChar(0,LCD_COLS-1,'*'); if (flashcnt++ < LCD_FLASHLEN) LCDB_SetStr(0,0,"********************"); else LCDB_SetChar(0,(int) (a->GetPct()*LCD_COLS),'*'); prev_pct = pct; } // Draw loops loopmgr->LockLoops(); FloLayout *curlayout = fs->GetLayouts(); int lc = 0, lr = LOOPROW; while (curlayout != 0) { if (curlayout->show && curlayout->elems != 0) { // Draw each element in this layout FloLayoutElement *curel = curlayout->elems; int firstid = curlayout->loopids.lo, curid = firstid, maxid = curlayout->loopids.hi; while (curel != 0 && curid <= maxid) { // Calculate the actual loop ID that corresponds to this element int i = firstid + curel->id; char loopexists; if (loopmgr->GetSlot(i) || loopmgr->IsActive(i)) loopexists = 1; else loopexists = 0; // Draw loop for this element if (loopexists && curlayout->showelabel) { // printf("el: %s\n",curel->name); if (loopmgr->IsActive(i)) { /* LCDB_SetChar(lr,lc-1,'-'); char *buf; */ LCDB_SetStr(lr,lc,strup(curel->name)); // LCDB_SetChar(lr,lc+strlen(buf),'-'); } else LCDB_SetStr(lr,lc,strlwr(curel->name)); lc += strlen(curel->name) + 1; if (lc >= LCD_COLS - 3) { lc = 0; lr++; } } /*if (loopexists) DrawLoop(loopmgr,i,screen,lscopepic, loopcolors[clrnum],colormag, fs,curel,0,0,0, lvol);*/ curel = curel->next; curid++; } } curlayout = curlayout->next; } loopmgr->UnlockLoops(); // LCDB_Debug(); LCDB_Dump(); } #endif // LCD_DISPLAY #ifndef NO_VIDEO //double t1 = mygettime(); float lvol = app->getRP()->GetLimiterVolume(); sample_t *peakbuf, *avgbuf; // Clear screen SDL_FillRect(screen,NULL,0); // Draw layouts #if 1 FloLayout *curlayout = fs->GetLayouts(); while (curlayout != 0) { // Draw this layout, if active if (curlayout->show && curlayout->elems != 0) { // Draw each element in this layout FloLayoutElement *curel = curlayout->elems; int firstid = curlayout->loopids.lo, curid = firstid, maxid = curlayout->loopids.hi; while (curel != 0 && curid <= maxid) { // Calculate the actual loop ID that corresponds to this element int i = firstid + curel->id; // What color should this element be? int clrnum = i % num_loopcolors; float colormag; char loopexists; if (loopmgr->GetSlot(i) || loopmgr->IsActive(i)) { loopexists = 1; colormag = loop_colorbase + loopmgr->GetTriggerVol(i); if (colormag > 1.0) colormag = 1.0; } else { loopexists = 0; colormag = loop_colorbase; } SDL_Color elclr; Loop *l = loopmgr->GetSlot(i); if (l != 0 && l->selcnt > 0) { // Selected loop static SDL_Color selcolor[4] = { { 0xF9, 0xE6, 0x13, 0 }, { 0x62, 0x62, 0x62, 0 }, { 0xFF, 0xFF, 0xFF, 0 }, { 0xE0, 0xDA, 0xD5, 0 } }; elclr.r = selcolor[0].r; elclr.g = selcolor[0].g; elclr.b = selcolor[0].b; elclr.unused = 0; } else { elclr.r = (int) (loopcolors[clrnum][0].r*colormag); elclr.g = (int) (loopcolors[clrnum][0].g*colormag); elclr.b = (int) (loopcolors[clrnum][0].b*colormag); elclr.unused = 0; } // Draw each geometry of this element FloLayoutElementGeometry *curgeo = curel->geo; while (curgeo != 0) { curgeo->Draw(screen,elclr); curgeo = curgeo->next; } // Draw loop for this element if (loopexists) DrawLoop(loopmgr,i,screen,lscopepic, loopcolors[clrnum],colormag, fs,curel,0,0,0, lvol); // Label this element if (curlayout->showelabel) draw_text(screen,mainfont,curel->name,curel->nxpos,curel->nypos, white); curel = curel->next; curid++; } // Label the layout if (curlayout->showlabel) draw_text(screen,mainfont,curlayout->name, curlayout->nxpos,curlayout->nypos,white); } curlayout = curlayout->next; } #endif // Show pies for pulses int curpulsey = pulsey; for (int i = 0; i < MAX_PULSES; i++) { Pulse *a = loopmgr->GetPulseByIndex(i); if (a != 0) { if (loopmgr->GetCurPulseIndex() == i) // Selected pulse twice as big! FILLED_PIE(screen,pulsex,curpulsey,pulsepiemag * 2,0, (int) (360*a->GetPct()),127,127,127,255); else FILLED_PIE(screen,pulsex,curpulsey,pulsepiemag,0, (int) (360*a->GetPct()),127,127,127,255); sprintf(tmp,"%d",i+1); draw_text(screen,mainfont,tmp,pulsex-pulsepiemag,curpulsey- pulsepiemag,red); curpulsey += pulsespc; } } // Draw input scope #if 0 peakbuf = app->getAMPEAKS()->buf, avgbuf = app->getAMAVGS()->buf; int midpt = iscopey; float mul = scopemag*lvol, // Ratio of visual size to audio scope buffer length ispd = scopewidth / scopelen; // Write into the buffer on sliding position to give animated scope effect float pos = -(float)app->getAMPEAKSI()->GetTotalLength2Cur()*ispd; if (pos < 0.) pos += (float)scopewidth; for (nframes_t i = 0; i < scopelen; i++, pos += ispd) { float pbi = peakbuf[i]; int peakd = (int) (mul*pbi); //avgd = (int) (mul*1.5*avgbuf[i]); if (pos >= (float)scopewidth) pos = 0.; float peaky = avgbuf[i]/(pbi*pbi + 0.00000001)*2; if (peaky > 1.0) peaky = 1.0; float rv = 0xC2 * peaky + 0xF9 * (1.-peaky), gv = 0x7E * peaky + 0xBB * (1.-peaky), bv = 0xDD * peaky + 0x2A * (1.-peaky); //if (rv > 255) rv = 255; //if (gv > 255) gv = 255; //if (bv > 255) bv = 255; vlineRGBA(screen, (int) pos, midpt-peakd, midpt+peakd, (int) rv, (int) gv, (int) bv, 255); } // Scope meter marks BED_MarkerPoints *mp = app->getAMPEAKSPULSE(); TimeMarker *cur = 0; if (mp != 0) cur = mp->markers; while (cur != 0) { pos = (float) ((signed int) cur->markofs - (signed int) app->getAMPEAKSI()->GetTotalLength2Cur()) *ispd; if (pos < 0.) pos += (float)scopewidth; vlineRGBA(screen, (int) pos, tmarky-metermag, tmarky, 255,255,255,255); cur = cur->next; } #endif // Output scope #if 0 int ox = -1, oy = -1; for (nframes_t i = 0; i < app->getSCOPELEN(); i++) { int x = oscopex+i*2, y = oscopey+(int) (oscopemag*app->getSCOPE()[i]); if (ox != -1) lineRGBA(screen,ox,oy,x,y,127,127,255,255); ox = x; oy = y; } #endif // ** These two hardcoded displays could be made configurable // Stream output status char *writename = app->getSTREAMOUTNAME(); if (strlen(writename) == 0) { strcpy(tmp,"stream off"); // No output checksizecnt = CHECK_SIZE_FRAMES; } else { if (++checksizecnt >= CHECK_SIZE_FRAMES) { // Stat for size of file checksizecnt = 0; struct stat st; if (stat(app->getSTREAMOUTNAME(),&st) == 0) { streamoutstatfailed = 0; streamoutsize = st.st_size; streamoutfloatsize = streamoutsize / (1024.*1024); } else { streamoutstatfailed = 1; streamoutsize = app->getSTREAMER()->GetOutputSize(); } } if (streamoutstatfailed) sprintf(tmp,"%s %d frames", writename,streamoutsize); else sprintf(tmp,"%s %.1f mb", writename,streamoutfloatsize); } draw_text(screen,mainfont,tmp,patchx,patchy-OCY(22),gray); // Scene name SceneBrowserItem *curscene = app->getCURSCENE(); if (curscene != 0) draw_text(screen,mainfont,curscene->name,0,0,gray); // ** // Draw displays #if 1 FloDisplay *curdisplay = fs->GetDisplays(); while (curdisplay != 0) { if (curdisplay->show || curdisplay->forceshow) curdisplay->Draw(screen); curdisplay = curdisplay->next; } #endif // Show save/load progress bar char draw_progress = 0; int progress_size = 0; if (loopmgr->GetNumSave() != 0) { draw_progress = 1; progress_size = (int) ((float)loopmgr->GetCurSave()/ loopmgr->GetNumSave()* progressbar_xs); } if (loopmgr->GetNumLoad() != 0) { draw_progress = 1; progress_size = (int) ((float)loopmgr->GetCurLoad()/ loopmgr->GetNumLoad()* progressbar_xs); } if (draw_progress) { boxRGBA(screen,progressbar_x+progress_size,progressbar_y, progressbar_x+progressbar_xs, progressbar_y+progressbar_ys, 50,50,10,255); boxRGBA(screen,progressbar_x,progressbar_y, progressbar_x+progress_size, progressbar_y+progressbar_ys, 255,255,30,255); hlineRGBA(screen,progressbar_x,progressbar_x+progress_size, progressbar_y,40,40,40,255); hlineRGBA(screen,progressbar_x,progressbar_x+progress_size, progressbar_y+progressbar_ys,40,40,40,255); vlineRGBA(screen,progressbar_x,progressbar_y, progressbar_y+progressbar_ys,40,40,40,255); vlineRGBA(screen,progressbar_x+progress_size,progressbar_y, progressbar_y+progressbar_ys,40,40,40,255); } // Show help on top if (showhelppage) { int spacey1, spacey2, curhelpy = helpy; // Dim the background // This doesn't work for large regions- bug in SDL_gfx? // boxRGBA(screen,helpx,helpy,helpx2,helpy2,255,255,255,0); for (int i = helpy; i <= helpy2; i++) hlineRGBA(screen,helpx,helpx2,i,0,0,0,127); hlineRGBA(screen,helpx,helpx2,helpy,255,255,255,127); hlineRGBA(screen,helpx,helpx2,helpy2,255,255,255,127); vlineRGBA(screen,helpx,helpy,helpy2,255,255,255,127); vlineRGBA(screen,helpx2,helpy,helpy2,255,255,255,127); // Now, draw help for (int i = helpstartidx[showhelppage-1]; i <= helpendidx[showhelppage-1]; i++) { char *s1 = fs->GetHelpLine(i,0), *s2 = fs->GetHelpLine(i,1); if (s1 != 0) draw_text(screen,helpfont,s1,helpx,curhelpy,yellow,0,0,0,&spacey1); else spacey1 = 0; if (s2 != 0) draw_text(screen,helpfont,s2,helpx+helpmaxcol1,curhelpy, truewhite,0,0,0,&spacey2); else spacey2 = 0; curhelpy += MAX(spacey1,spacey2); } } #if 0 // Old title image drawing-- // Draw title image double video_elapsed = mygettime() - video_start; float titlepct = video_elapsed/0.5; /* if (titletemppic->format->BytesPerPixel == 4) { int sz = titletemppic->w*titletemppic->h; char *pix = (char *) titletemppic->pixels; char vid = (char) (video_elapsed*255); for (int i = 0; i < sz; i++, pix += 4) if (*(pix+1) != 0 || *(pix+2) != 0 || *(pix+3) != 0) { // int val = (int) ((float)rand()/RAND_MAX*vid); //if (val > 255) // val = 255; *pix = vid; } else *pix = 0; } */ if (titlepct < 1.0) { int titlepos = (int) (titlepct*titletemppic->h); SDL_Rect dst; dst.x = screen->w/2-titletemppic->w/2; dst.y = screen->h/2-titlepos/2; dst.w = titletemppic->w; dst.h = titlepos; Squeeze_BlitSurface(titletemppic,screen,&dst); } else if (titlepct >= 1.0 && titlepct <= 4.0) { int titlepos = (int) (1.0*titletemppic->h); SDL_Rect dst; dst.x = screen->w/2-titletemppic->w/2; dst.y = screen->h/2-titlepos/2; dst.w = titletemppic->w; dst.h = titlepos; Squeeze_BlitSurface(titletemppic,screen,&dst); } else if (titlepct > 4.0 && titlepct < 5.0) { int titlepos = (int) ((5.0-titlepct)*titletemppic->h); SDL_Rect dst; dst.x = screen->w/2-titletemppic->w/2; dst.y = screen->h/2-titlepos/2; dst.w = titletemppic->w; dst.h = titlepos; Squeeze_BlitSurface(titletemppic,screen,&dst); } else if (titletemppic != 0) { SDL_FreeSurface(titletemppic); titletemppic = 0; } #endif // Draw logo #if 1 if (logopic != 0) { double video_elapsed = mygettime() - video_start; float titlepct = video_elapsed; float t_floatin = 2.0, t_floatout = 4.0; if (titlepct < 1.0) { SDL_Rect dst; dst.x = screen->w-logopic->w; dst.y = (int) (-logopic->h + screen->h*titlepct); dst.w = logopic->w; dst.h = logopic->h; SDL_BlitSurface(logopic, NULL, screen, &dst); } else if (titlepct > t_floatin && titlepct < t_floatin+1.0) { SDL_Rect dst; dst.x = screen->w-logopic->w; dst.y = screen->h-logopic->h; dst.w = logopic->w; dst.h = logopic->h; SDL_BlitSurface(logopic, NULL, screen, &dst); int ver_x, ver_y; TTF_SizeText(mainfont,VERSION,&ver_x,&ver_y); draw_text(screen,mainfont,VERSION, (int) (screen->w-(titlepct-t_floatin)*(ver_x+5)), screen->h-ver_y-5,truewhite); } else if (titlepct >= t_floatin && titlepct <= t_floatout) { SDL_Rect dst; dst.x = screen->w-logopic->w; dst.y = screen->h-logopic->h; dst.w = logopic->w; dst.h = logopic->h; SDL_BlitSurface(logopic, NULL, screen, &dst); int ver_x, ver_y; TTF_SizeText(mainfont,VERSION,&ver_x,&ver_y); draw_text(screen,mainfont,VERSION, screen->w-(ver_x+5), screen->h-ver_y-5,truewhite); } else if (titlepct > t_floatout && titlepct < t_floatout+1.0) { SDL_Rect dst; dst.x = screen->w-logopic->w; dst.y = screen->h-logopic->h; dst.w = logopic->w; dst.h = logopic->h; SDL_BlitSurface(logopic, NULL, screen, &dst); int ver_x, ver_y; TTF_SizeText(mainfont,VERSION,&ver_x,&ver_y); draw_text(screen,mainfont,VERSION, (int) (screen->w-(1.0-(titlepct-t_floatout))*(ver_x+5)), screen->h-ver_y-5,truewhite); } else { SDL_Rect dst; dst.x = screen->w-logopic->w; dst.y = screen->h-logopic->h; dst.w = logopic->w; dst.h = logopic->h; SDL_BlitSurface(logopic, NULL, screen, &dst); } } #endif // Now update screen! SDL_UpdateRect(screen, 0, 0, 0, 0); //video_time = mygettime() - t1; #endif // NO_VIDEO // Unlock video space from changes pthread_mutex_unlock (&video_thread_lock); } #ifndef NO_VIDEO delete[] curpeakidx; delete[] lastpeakidx; delete[] oldpeak; // Erase circular maps CircularMap *cur = cmaps; while (cur != 0) { CircularMap *tmp = cur->next; delete cur; cur = tmp; } // Close things up if (logopic != 0) SDL_FreeSurface(logopic); SDL_FreeSurface(lscopepic); #endif // NO_VIDEO } void VideoIO::SetVideoMode(char fullscreen) { const SDL_VideoInfo *info; Uint8 video_bpp; Uint32 videoflags; pthread_mutex_lock (&video_thread_lock); if (screen != 0) // Free existing screen SDL_FreeSurface(screen); screen = 0; /* Alpha blending doesn't work well at 8-bit color */ info = SDL_GetVideoInfo(); if ( info->vfmt->BitsPerPixel > 8 ) { video_bpp = info->vfmt->BitsPerPixel; } else { video_bpp = 16; } printf("VIDEO: SetVideoMode: Using %d-bit color\n", video_bpp); // Disabled (slower) options: /*| SDL_SRCALPHA | SDL_RESIZABLE |*/ videoflags = SDL_HWSURFACE | SDL_DOUBLEBUF; this->fullscreen = fullscreen; if (fullscreen) videoflags |= SDL_FULLSCREEN | SDL_NOFRAME; /* Set right video mode */ int XSIZE = app->getCFG()->GetVSize()[0], YSIZE = app->getCFG()->GetVSize()[1]; if ( (screen=SDL_SetVideoMode(XSIZE,YSIZE,video_bpp,videoflags)) == NULL ) { printf("VIDEO: Couldn't set %ix%i video mode: %s\n",XSIZE,YSIZE, SDL_GetError()); exit(1); } /* Use alpha blending */ //SDL_SetAlpha(inst->screen, SDL_SRCALPHA, 0); /* Set title for window */ SDL_WM_SetCaption("FreeWheeling","FreeWheeling"); pthread_mutex_unlock (&video_thread_lock); } void *VideoIO::run_video_thread(void *ptr) { VideoIO *inst = static_cast(ptr); printf("VIDEO: Thread start..\n"); // printf("*** VIDEO THREAD: %li\n",pthread_self()); #ifdef __MACOSX__ inst->cocoa.SetupCocoaThread(); #endif #ifndef NO_VIDEO // Initialize the font library if ( TTF_Init() < 0 ) { fprintf(stderr, "Couldn't initialize TTF: %s\n",SDL_GetError()); return 0; } atexit(TTF_Quit); // Load all fonts inst->mainfont = 0; inst->helpfont = 0; inst->smallfont = 0; { FloFont *cur = inst->app->getCFG()->GetFonts(); char tmp[255]; while (cur != 0) { if (cur->name != 0 && cur->filename != 0 && cur->size != 0) { snprintf(tmp,255,"%s/%s",FWEELIN_DATADIR,cur->filename); printf("VIDEO: Loading font %s: %s (%d pt)\n",cur->name,tmp,cur->size); struct stat st; if (stat(tmp,&st) != 0) { printf("VIDEO: Couldn't find font file: %s\n" "Did you run 'make install'?\n",tmp); exit(1); } cur->font = TTF_OpenFont(tmp, cur->size); if (cur->font == 0) { printf("VIDEO: Couldn't load %d pt font from: %s\n" "Did you run 'make install'?\n", cur->size, tmp); exit(1); } TTF_SetFontStyle(cur->font, TTF_STYLE_NORMAL); // Check if this is a font we use if (!strcmp(cur->name,"main")) inst->mainfont = cur->font; else if (!strcmp(cur->name,"help")) inst->helpfont = cur->font; else if (!strcmp(cur->name,"small")) inst->smallfont = cur->font; } cur = cur->next; } } if (inst->mainfont == 0) { printf("VIDEO: Error, no 'main' font loaded!\n"); exit(1); } if (inst->helpfont == 0) { printf("VIDEO: Error, no 'help' font loaded!\n"); exit(1); } if (inst->smallfont == 0) { printf("VIDEO: Error, no 'small' font loaded!\n"); exit(1); } #endif // NO_VIDEO inst->videothreadgo = 1; printf("VIDEO: SDL Ready!\n"); // Wait until we are actually running! while (!inst->app->IsRunning()) usleep(10000); #ifndef __MACOSX__ // On Mac OS X, this is done in the main thread // Set video mode / window size inst->SetVideoMode(0); #endif // Start main loop inst->video_event_loop(); #ifndef NO_VIDEO // Close all fonts { FloFont *cur = inst->app->getCFG()->GetFonts(); while (cur != 0) { if (cur->font != 0) TTF_CloseFont(cur->font); cur = cur->next; } } #endif // NO_VIDEO // Close things up SDL_QuitSubSystem(SDL_INIT_VIDEO); #ifdef __MACOSX__ inst->cocoa.TakedownCocoaThread(); #endif printf("VIDEO: thread done\n"); return 0; } fweelin-0.6/src/fweelin_videoio.h0000755000175000017500000001546011050104733015560 0ustar mercmerc#ifndef __FWEELIN_VIDEOIO_H #define __FWEELIN_VIDEOIO_H /* Copyright 2004-2008 Jan Pekau (JP Mercury) This file is part of Freewheeling. Freewheeling is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. Freewheeling is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Freewheeling. If not, see . */ #include "fweelin_event.h" #include #ifdef __MACOSX__ #include #include #include "FweelinMac.h" #else #include #include #endif // Convert from 640,480 screen size to the user's coordinate system #define OCX(x) (app->getCFG()->XCvt((float)(x)/640)) #define OCY(y) (app->getCFG()->YCvt((float)(y)/480)) #define FWEELIN_TITLE_IMAGE FWEELIN_DATADIR "/fweelin.bmp" class Fweelin; class LoopManager; class FloConfig; class FloLayoutElement; // This crazy class computes a mapping // to bend a flat strip bitmap into a circle-- good for makin wheels! class CircularMap { public: // Create a mapping from the flat surface 'in' to a circular region // of the given dimensions-- the output surface location is specified when // actually mapping CircularMap(SDL_Surface *in, int map_xs, int map_ys, int in_xs, int in_ys, int rinner, int rsize); // Frees this map ~CircularMap(); // Map flat scope onto circle char Map(SDL_Surface *out, int dstx, int dsty); // Scans for a map with map_xs == sz CircularMap *Scan(int sz) { CircularMap *cur = this; while (cur != 0 && cur->map_xs != sz) cur = cur->next; return cur; }; // Links the given map to the end of this map list void Link(CircularMap *nw) { CircularMap *cur = this; while (cur->next != 0) cur = cur->next; cur->next = nw; }; SDL_Surface *in; Uint8 **map; int *scanmap; int map_xs, map_ys, in_xs, in_ys, rinner, rsize; CircularMap *next; }; // Video Handler class VideoIO : public EventProducer, public EventListener { friend class Fweelin; public: VideoIO (Fweelin *app) : app(app), screen(0), cmaps(0), showlooprange(0,0), showhelppage(0), videothreadgo(0) {}; int activate (); void close (); char IsActive () { return videothreadgo; }; double GetVideoTime() { return video_time; }; void SetVideoMode(char fullscreen); char GetVideoMode() { return fullscreen; }; void ReceiveEvent(Event *ev, EventProducer *from); // Draw text, and optionally return size of text drawn in sx and sy static int draw_text(SDL_Surface *out, TTF_Font *font, char *str, int x, int y, SDL_Color clr, char centerx = 0, char centery = 0, int *sx = 0, int *sy = 0); // If no suitable map exists in list 'cmaps', creates a planar>circular map // of diameter 'sz', mapping from the given surface. CircularMap *CreateMap(SDL_Surface *lscopepic, int sz); inline SDL_Surface *getLSCOPEPIC() { return lscopepic; }; // Draw the circular scope and status information for one loop-- // given by loopid 'i' and optional layout element 'curel'.. // if curel is null, we draw direct with the given circular map // and position. // Returns nonzero if loop not drawn char DrawLoop(LoopManager *loopmgr, int i, SDL_Surface *screen, SDL_Surface *lscopepic, SDL_Color *loopcolors, float colormag, FloConfig *fs, FloLayoutElement *curel, CircularMap *direct_map, int direct_xpos, int direct_ypos, float lvol, char drawtext = 1); protected: // Core app Fweelin *app; // Video event handler thread static void *run_video_thread (void *ptr); void video_event_loop (); // This is a custom surface blitter that doesn't use large block // memory writes and thus avoids the strange video glitch of introducing // audio pops on some machines-- some loss in performance! void Custom_BlitSurface(SDL_Surface *in, SDL_Surface *out, SDL_Rect *dstrect); void Squeeze_BlitSurface(SDL_Surface *in, SDL_Surface *out, SDL_Rect *dstrect); #ifdef __MACOSX__ FweelinMac cocoa; // Cocoa thread setup #endif char fullscreen; // Fullscreen video? SDL_Surface *screen; // Pointers to fonts that video uses-- links into FloFont structures TTF_Font *mainfont, *helpfont, *smallfont; // Planar->Circular mapping variables CircularMap *cmaps; int lscopewidth, lscopeheight; SDL_Surface *lscopepic; nframes_t *curpeakidx, *lastpeakidx; float *oldpeak; Range showlooprange; // Which loops to show onscreen int showhelppage, // Which help page to show (0=off) numhelppages; // Number of help pages that are defined // Length of time taken (s) for one iteration of video loop double video_time; pthread_t video_thread; char videothreadgo; pthread_mutex_t video_thread_lock; #ifdef LCD_DISPLAY #define LCD_ROWS 4 #define LCD_COLS 20 // Initialize LCD connection int InitLCD (char *devname, int baud); // Writing directly to LCD inline void LCD_Send (unsigned char dat) { if (lcd_handle) while (write(lcd_handle, &dat, 1) != 1) { printf("LCD_Send failed\n"); usleep(1000); } }; inline void LCD_SendStr (char *data) { while (*data) LCD_Send(*data++); } // Writing to LCD via double buffer (more efficient) inline void LCDB_SetChar (int row, int col, char dat) { if (row >= 0 && row < LCD_ROWS && col >= 0 && col < LCD_COLS) lcd_dat[lcd_curb][row][col] = dat; }; inline void LCDB_SetStr (int row, int col, char *data) { while (*data) LCDB_SetChar(row,col++,*data++); } inline void LCDB_Clear () { memset(lcd_dat[lcd_curb],' ',sizeof(char) * LCD_ROWS * LCD_COLS); }; inline void LCDB_Debug () { char buf[LCD_COLS+1]; buf[LCD_COLS] = '\0'; for (int r = 0; r < LCD_ROWS; r++) { strncpy(buf,lcd_dat[lcd_curb][r],LCD_COLS); printf("%s\n",buf); } }; // Dump buffer to LCD, writing any changes, then switch buffer void LCDB_Dump (); // Handle for LCD output int lcd_handle; char lcd_dat[2][LCD_ROWS][LCD_COLS]; // Double buffer for LCD screen int lcd_curb; // Which of two double buffers is // being written to #endif }; #endif fweelin-0.6/src/Makefile.am0000755000175000017500000000317110666600535014305 0ustar mercmerc#LIBTOOL = libtool # #COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ # $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) #LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) \ # $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) #CCLD = $(CC) #LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ # $(AM_LDFLAGS) $(LDFLAGS) -o $@ ## CFLAGS = @CFLAGS@ #CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ # $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) #LTCXXCOMPILE = $(LIBTOOL) --mode=compile $(CXX) $(DEFS) \ # $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ # $(AM_CXXFLAGS) $(CXXFLAGS) #CXXLD = $(CXX) #CXXLINK = $(LIBTOOL) --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ # $(AM_LDFLAGS) $(LDFLAGS) -o $@ ## CXXFLAGS = @CXXFLAGS@ bin_PROGRAMS = fweelin fweelin_SOURCES = elastin/elastin.cc fweelin.cc fweelin_datatypes.cc fweelin_event.cc fweelin_config.cc fweelin_browser.cc fweelin_audioio.cc fweelin_sdlio.cc fweelin_midiio.cc fweelin_videoio.cc fweelin_core.cc fweelin_mem.cc fweelin_block.cc fweelin_core_dsp.cc fweelin_fluidsynth.cc fweelindir = $(datadir)/fweelin FWEELIN_CFLAGS = -I. -g -Wall -Wno-non-virtual-dtor -D_REENTRANT -DPTHREADS -DNDEBUG -DVERSION=\"$(VERSION)\" -DFWEELIN_DATADIR=\"$(fweelindir)\" -DADDON_DIR=\"/usr/local/lib/jack\" -I/usr/include/freetype2 -I/usr/include/libxml2 -funroll-loops -finline-functions -fomit-frame-pointer -ffast-math -fexpensive-optimizations -fstrict-aliasing -falign-loops=2 -falign-jumps=2 -falign-functions=2 -O9 AM_CFLAGS = $(CFLAGS) $(FWEELIN_CFLAGS) AM_CXXFLAGS = $(CFLAGS) $(CXXFLAGS) $(FWEELIN_CFLAGS) fweelin-0.6/src/Makefile.in0000644000175000017500000004165111071520730014305 0ustar mercmerc# Makefile.in generated by automake 1.10 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ #LIBTOOL = libtool # #COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ # $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) #LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) \ # $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) #CCLD = $(CC) #LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ # $(AM_LDFLAGS) $(LDFLAGS) -o $@ #CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ # $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) #LTCXXCOMPILE = $(LIBTOOL) --mode=compile $(CXX) $(DEFS) \ # $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ # $(AM_CXXFLAGS) $(CXXFLAGS) #CXXLD = $(CXX) #CXXLINK = $(LIBTOOL) --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ # $(AM_LDFLAGS) $(LDFLAGS) -o $@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : bin_PROGRAMS = fweelin$(EXEEXT) subdir = src DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_CLEAN_FILES = am__installdirs = "$(DESTDIR)$(bindir)" binPROGRAMS_INSTALL = $(INSTALL_PROGRAM) PROGRAMS = $(bin_PROGRAMS) am_fweelin_OBJECTS = elastin.$(OBJEXT) fweelin.$(OBJEXT) \ fweelin_datatypes.$(OBJEXT) fweelin_event.$(OBJEXT) \ fweelin_config.$(OBJEXT) fweelin_browser.$(OBJEXT) \ fweelin_audioio.$(OBJEXT) fweelin_sdlio.$(OBJEXT) \ fweelin_midiio.$(OBJEXT) fweelin_videoio.$(OBJEXT) \ fweelin_core.$(OBJEXT) fweelin_mem.$(OBJEXT) \ fweelin_block.$(OBJEXT) fweelin_core_dsp.$(OBJEXT) \ fweelin_fluidsynth.$(OBJEXT) fweelin_OBJECTS = $(am_fweelin_OBJECTS) fweelin_LDADD = $(LDADD) DEFAULT_INCLUDES = -I.@am__isrc@ depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) CXXLD = $(CXX) CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ -o $@ SOURCES = $(fweelin_SOURCES) DIST_SOURCES = $(fweelin_SOURCES) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build_alias = @build_alias@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host_alias = @host_alias@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ fweelin_SOURCES = elastin/elastin.cc fweelin.cc fweelin_datatypes.cc fweelin_event.cc fweelin_config.cc fweelin_browser.cc fweelin_audioio.cc fweelin_sdlio.cc fweelin_midiio.cc fweelin_videoio.cc fweelin_core.cc fweelin_mem.cc fweelin_block.cc fweelin_core_dsp.cc fweelin_fluidsynth.cc fweelindir = $(datadir)/fweelin FWEELIN_CFLAGS = -I. -g -Wall -Wno-non-virtual-dtor -D_REENTRANT -DPTHREADS -DNDEBUG -DVERSION=\"$(VERSION)\" -DFWEELIN_DATADIR=\"$(fweelindir)\" -DADDON_DIR=\"/usr/local/lib/jack\" -I/usr/include/freetype2 -I/usr/include/libxml2 -funroll-loops -finline-functions -fomit-frame-pointer -ffast-math -fexpensive-optimizations -fstrict-aliasing -falign-loops=2 -falign-jumps=2 -falign-functions=2 -O9 AM_CFLAGS = $(CFLAGS) $(FWEELIN_CFLAGS) AM_CXXFLAGS = $(CFLAGS) $(CXXFLAGS) $(FWEELIN_CFLAGS) all: all-am .SUFFIXES: .SUFFIXES: .cc .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \ cd $(top_srcdir) && \ $(AUTOMAKE) --gnu src/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)" @list='$(bin_PROGRAMS)'; for p in $$list; do \ p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ if test -f $$p \ ; then \ f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ echo " $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \ $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \ else :; fi; \ done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; for p in $$list; do \ f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \ rm -f "$(DESTDIR)$(bindir)/$$f"; \ done clean-binPROGRAMS: -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) fweelin$(EXEEXT): $(fweelin_OBJECTS) $(fweelin_DEPENDENCIES) @rm -f fweelin$(EXEEXT) $(CXXLINK) $(fweelin_OBJECTS) $(fweelin_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elastin.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fweelin.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fweelin_audioio.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fweelin_block.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fweelin_browser.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fweelin_config.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fweelin_core.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fweelin_core_dsp.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fweelin_datatypes.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fweelin_event.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fweelin_fluidsynth.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fweelin_mem.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fweelin_midiio.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fweelin_sdlio.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fweelin_videoio.Po@am__quote@ .cc.o: @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $< .cc.obj: @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` elastin.o: elastin/elastin.cc @am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT elastin.o -MD -MP -MF $(DEPDIR)/elastin.Tpo -c -o elastin.o `test -f 'elastin/elastin.cc' || echo '$(srcdir)/'`elastin/elastin.cc @am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/elastin.Tpo $(DEPDIR)/elastin.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='elastin/elastin.cc' object='elastin.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o elastin.o `test -f 'elastin/elastin.cc' || echo '$(srcdir)/'`elastin/elastin.cc elastin.obj: elastin/elastin.cc @am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT elastin.obj -MD -MP -MF $(DEPDIR)/elastin.Tpo -c -o elastin.obj `if test -f 'elastin/elastin.cc'; then $(CYGPATH_W) 'elastin/elastin.cc'; else $(CYGPATH_W) '$(srcdir)/elastin/elastin.cc'; fi` @am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/elastin.Tpo $(DEPDIR)/elastin.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='elastin/elastin.cc' object='elastin.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o elastin.obj `if test -f 'elastin/elastin.cc'; then $(CYGPATH_W) 'elastin/elastin.cc'; else $(CYGPATH_W) '$(srcdir)/elastin/elastin.cc'; fi` ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ mkid -fID $$unique tags: TAGS TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$tags $$unique; \ fi ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(CTAGS_ARGS)$$tags$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$tags $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) installdirs: for dir in "$(DESTDIR)$(bindir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-binPROGRAMS clean-generic mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-exec-am: install-binPROGRAMS install-html: install-html-am install-info: install-info-am install-man: install-pdf: install-pdf-am install-ps: install-ps-am installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS .MAKE: install-am install-strip .PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ clean-generic ctags distclean distclean-compile \ distclean-generic distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-binPROGRAMS \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \ uninstall-am uninstall-binPROGRAMS # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: fweelin-0.6/MacOSX/build/0000755000175000017500000000000010746301442013640 5ustar mercmercfweelin-0.6/MacOSX/English.lproj/0000755000175000017500000000000010746301442015257 5ustar mercmercfweelin-0.6/MacOSX/English.lproj/InfoPlist.strings0000755000175000017500000000054210556277142020615 0ustar mercmerc/* Localized versions of Info.plist keys */ CFBundleName = "FreeWheeling"; CFBundleShortVersionString = "FreeWheeling"; NSHumanReadableCopyright = "Copyright 2007 Jan Pekau"; fweelin-0.6/MacOSX/freewheeling.icns0000644000175000017500000015643710556277142016113 0ustar mercmercicnsics#H????ics8++3,,+2+W 3]2] + 2,,32,WW,22]2,,,2,W32,,W,33,2,+V2is32{dV ҥàȀbtŠ۳ᛘ琶S? ơ̄H¤AaΑS ­ͿƾϽ ΅Ԉ{€*bʲѽʊv¶ʝ۶ҀOtƳıȿS™? ªǽ̼ ‹ȳƄH@asS k}U_}`zSsRW}UƳojnk_~zQ~q> vj|G{?s8mk 5555 ')551C432g{ICN#????????????icl8+++++++WW,,,++V+,,32,+2,++22++W2 W]+W33  33]]+2  33VW3  ]]+,2  23V++  322,23+,333W3W,W2,++2,2W]]]22+V2,2]]V22,222222232+]3W]2++V2 3]W22,,,V2 22+3W2V33 2+,3^W32,22 ,32+2332+]33V+W22,+3,2+++W33323,++2233]]3]V,++]]2322]+VVV++++++il32 uҧc ߥ|-B'?ě鮘(0ᬷʯ0ř6iǵƼզ̨–һ籐bƲƓħ׽˱ŵܚƦŗVسxȻ긶^ȐƤ ŭ'ɼ ə͉(ǿλǖ̷vx̏ͪ rÙƷ^ԯ pϣ^ ʋƾy-ǻŷ٪?įūº%ȱɭ͟<˺ʳ˾~(0ؔʴ˿̦|ij˹Ϸ֜-~†ƶ¤ևoz÷̩ӺѿǾǩbͷ߭ţɾŰˮzr|cǼ~s~³sĞp¿›4ýöoāúöS¹·ůuĦŵ[rǾ· Ⱦſÿ'ͿƼȾ² ÿŲʉ(­q~uɮy_autxǦ rǿô]Ӯ lˣ] }˹viu-°hЦ?uѼ%u<Dzjyin$-~idy}sVTc½yjwYRZm˚+~vkt_W`{̈́YOfoulXhö ϶oWa|{{fr^гö}oldةƳ»uksh{liŠue^fhcpnh^p‹|pTp’{odr|~} xHmeR}yu|zwcYWXu Ʒu%̳|̹gw~u|pƉ&Ǽ}ZP\{\ƧjLO_x\lĥ oŽ~v\Ҭl8mk & # TtP{ItPxT|;K1 6 6 6 6 6 6 5)'[ /"V t(z8t4x4|7=U'>MaE- 255555) it32'3qӾ}xt^!%]z|ɴtpjJ%Qu{~DztogA5VĶ9&X«΀̀öK DҀ4$1+Uư݀ԀҀF%C9z{xĽrtn,CGз4FЀŨ5 n`VbӀ ɱS=>Fp ʬHa ľBY Ƽ@HX8lƿU5%> "Ȱ Ƭʽ@5 ǭǹ~0Iöؿ"\ҹû=:ҹ#!l\UlŻ λX<>F5lŰ)ӮH`Ū!ºĿBWƫ"ǿ? AJGcɷ,ǷĭQ-(1x %ĵnjxY* мѣ_y ¹ҧ_  »NHM>̻ ΣvljQһ %ث|rnNSV>Lȯ ٲ{Réd ʳi ̷h) нl»  x˾ | ՖEJ]ݮtt~߳||)#ߴ~~݀ ݀ɸɦ/̯:γ-̷̾ 6ǿӾ̇+¿ѺЇ8ʷӇ&Շ,÷ ɀׇ (÷π؇,¶؇ +ľڇż7؀ՃۇŽ1ÿրՁԆ ܇ Ž7وۀ߇Žָ Ł  Ž.ֶŽض ȿ, ¾,ȿ ¿/¿/Ľ¾'³܇¾ɿ҇Ƚŷ͇ƽ:˿Ƕȇ'ʩ¾ ʦþ ˦´ĺϬò|Į!¶Ğooxzƫ !ƺŝlltĬ  ƻ˜cdmŲ ̼49HƷ"ȵlǶ$ȶi% ²iĿĴcɹIJfɸֿh¼#̺ұ^5G1AϾԽ˃.)Կ  ؿpϿ վrÿӽex̿)ϽY!{Ͽy)κä\ r• ϿɻtQ!/9:TʿžB" !@̼ļ.Bξ /4Gοˤ.LC>YľɻI,)-!ȷɸ9¾Ⱥ(ĵ'Ā$Ɯqmn ëԀ ݵʸtQĤް˺nŦܭpQ%?&[þɚūL 'B<ûϿÕ߀(KBĽȹʿ»)L>ÿħ-IMD@S~Ы­D,,0C3¿}|ussuwx{ɡ~{"0w,yx|âĭxC hqitztvi]`T >û2 )ςɷ5=¿(0'x}xsxzxvrmtnhortvrjaǀ ɾ ȃ у '/l~кysoY%XuvzưokfF%Mouw®nib;LµĂ9 X«ľG%B¨{} ˻3(1+N} ȼ@9xyvȀijù~oql%Dǿƽ¿Ͳ0&Dÿƿ4k[T_ʽ¿«P=>F l;¿ĨF)_ʾø€¼@KW̾ø¹=QHX8jƻĹR5%>ǻ̀źрŰȼȺ̀ƺŭǻ~@5· ̀ ƻŀ‚«Ķ{IǾ;Ƽ~ƻ}"VɸƀȿĿк|sxŻ;46ʸ{z¿ȾĀҀиxot~ɼ `iZPg»~ȿĿʱ~x{}~ʾW<>FlӺDȿĿɽ~{|˪FR^ٸȿĿȻ}z п@aU׷ȿĿź~zy{}{¼<AJGcϸTȿľ¾~}}ſM+& &vǺ7þсɶ{rUh*|ǮþŰɚYvîƁ3ÿπ!İȟW*ƾɂ"ûżκ{KCI:%ȲûĀ7ɾʞofdLϱʀXƽſɽӥvkgH7ST;J£ƿĀ÷ҫztN7usw€Á õƀ Һa7wkjm~ļÀ ɀ ҿcvifkˀ2ƽ Ȁ e)xkin||ž Àν´g4ƿ~ussvtx·ʀǀÀǀƧɂ Ͼt;ɹvtsomqǻĀƀɀʀ x4Ⱥ|}xvzźʀƀĀƾǀȀˀyùĀǺɀ̈́ ΐ>EW4ǽÀ«ƀ̀զjmxTþſˀ˃πתst}>)€ƿЁр׬ww:ǽ!ր݀&þ$׀ـ ƫ%؀ف؀ـ ǰ߂Gـځ؀Ųف@ǿ܃ۀɇ4Ŀ{р݀ހ½̇2}Ҁۀ܀·ÿՁ݀އ7ĸ}{{Ӏ΀û·ڀۇ5ſ{{yvssz~πʀǀχـڂ݀6Ʋyxvtqquwv{ˀĀ¿χրׁցۀ&ðxxwvutx{zӀ҂ʃȀχǾ̀΀Ѓ"|vwy}À ч úDžȀƼ{|wstyՇûDžȀƼ{{xssxՇûńǀƁ }yyxuv{ڇ ºĀƁǀ,¶wuwy}́р҃ӂ º{ÀŀĀ,|usuy~׀ڀۀـ º{€À*ztrtyق݀ƽ€%~spqxɀ́ր׀ց Ǿ'rnqxā ҁс ȿ…ÿpkov~ Ŀ€рȿvru|À߇ĀÀāŸׇˀ· ȿ(Ѐʇż&́ŀ&Ň !Ȁɀƀ|pu@»¿úˀȀ¿vhoVºļ˂ʀvio¼ €ļсʂĿ}ou)z}uxþπ+÷ɾllu'xzqu|}ÿÿŀπ+ùʿiiq~w{π̀!¸ɽ`ai(ľƀ¿π ƀŀāƀǷ~27F îĀ ƿĂÿπűj(ů žłÿπ  ųgƿ ľĀ Ѐ gЁрȺ`Ёрπˀÿ˻c  тπĿ͸e~΃πʫ]!5G1AɱÄɀ҂π~-(еÀ̀ Ձπ¿o˶̀Ձ¾ѿq~x{̀ ԀdFvƷpimsvt¾ƿӀüWG!zɷj`flqo¾žӀȾZG p˽}}zw½рö|qNB/9:TƷ¿!¿¼@! @̀Jī ļ+aBȰɽ,GdzŁȿ!Ţ-&LC>Y½ľ5ŷH,)-!!˽ü1Ʒ $6˾ºɀ̀%;$XõĿpkmU ùwrźƼǴqʽxmg=Ļ{ǻɸmR˿vp¿ù{ĽսoQ%?&ZǾ|xy¾uotH%K<Ƽ~tpqx¾qmq{Ǿ'KBȾ}ropw~~½rlrz(KG|zxomnu||qlq|ɽ+IMB@RͿxssdbbcddgnvw|~{zmjo~ҼB+*.C0ſkgf]Z[\__bluuzuqrhgl}ؽ 0ȿrmmcb,dcgotv{{xvqouªuC fohr~y{uvz}}sug[^R5>ſ25(ǵ5=(5'w{vrwywuqlrmgnqrurhhi_ Ƽ DŽ ̿ τ ſ'/iy{͹vplXUprvˁ ïlhcEGkosŁ ľlf_: L%{~~55Uĺ~vwrloyE5=ƺulmicdoǷ/;1+Nxpqkdfoµ?,9vxu}tfgp{jnh%CAź{hhpȮ-(Dμ}ihoػ1*k[P^²}jiqӼL< Wij:uuz<HX6i/utz P5% >ȿ 2tty~Ĺ3suzuĸ|@3 uu{}ux5Iøvw|qixz|6Vðtqvwx}ze]gvz~¿96Ȁ/ů|kgnxy} waYanqvƺ`iZPfƼykhl{yz}|n`\bjmq|ƺS;Iy vnqx~~ 0{xpSGR~xɻgZ[YXX]}8||}pjqøkktw˻dXYVSTZ zz|Grluĺghp˼j^_][[_|# uqyĹ]`h&˿{qrrpos9 ³{07F~}}{~Ih ¨}~{yy}! °fŽ}||1eo}|}~uiehvy~_}|W{|}n_[`rv{a|{|{||F~|n^Z_sw|ųd ||{yz}~H~p`]ay}æ[ 5G1@Ĥuopoos v "yjfl})%ͫibdegfhopptC|miomǮjdfhhfirttv.{njpνpd\]^^Yax}~?~spwcuÿ[QSSRMZ} yv~VxİUJNOMHY xu~ºYpƶtlldZUbPzoLT/97Tİwnu> <ƾuz5+a@ä{ù, GªQ-#JA=Wƽ|~8G*)-Yų|x{Ĵ 6ij: ƺ$+ȼ}}vqmwuqy ƻmjlUoodXPc~}}{vtuy}}]XbınQŵji]PG^~}}{usuy||YT_~ƵlRŷssgZTf|zyysrswzz}[V`~ϹnQ%=#Vķ{yw`\[[TSS[baf{SNUfwzƽF%K;yyv]XWVPNPW]]a{xSOTcpqxļ'K@øyxu]XWWPOOW^\az~xTPVcoqxɽ(KGtsq\XWVQPPX^]azyxsWSYgtw~ĺ+IJ@?Qȸv`[ZLJJKMMOV^]aw||ia_`WV\pι@+*.C0sYSTGEFHJKMU^\av~yycZWYVV]q׻} ,Ƽ|d^_RQTSV[`aey~xxja_agyuCfnhr}y}zokjmnmq|vurtf[^R5;¼}xxyzttý/5({z|xrqƴ5;{{(5'uzupwywupkqkflqrurfgh^ ¿źƁ˾ľt8mk@   !$%&&&&&&&&&&&&&&&&&&&&&&&&&&%$!  $.6=ACDDDDDDDDDDDDDDDDDDDDDDDDDDCA=6.$  ;T.    )NmG7)    +2:BNoɐn\NB:0!  5v¸L'  Yv=-  &2pWD3&  .;CKUa겅rbUK>(  :yɾQ2  -]zL1!  /K{pQ=&  #LdmA$  Kؼm6$  "cڋL6#  -?}mS:"  <_uǟ_9"  9]3"  !JvI3"  7IrҜu]8!  ;Ҿ_:"  .^S3#  #?ukJ4$ #Kc~ƤmA&  Kټm?$  /dڊW6$  -K~vS:"  :\|Ƥ_8!  .yӜY2! lE'$AlE'%ClE'&DlE'&DlE'&DlE'&DlE'&DlE'&DlE'&DlE'&DlE'&DlE'&DlE'&DlE'&DlE'&DlE'&DlE'&DlE'&DlE'&DlE'&DlE'%ClE'$AlE'">lE'9lD' 1jD& 'YsgA%2Lsa=" $:`}X7 -RmK/ $IåY=% CૅeG. @ۜsS7" ?ՏdD*  =ςW9! 8uL/  0ޯf@'  Luּ}P4 'rE+ (QxƪW8# 1LpɤbB+  0Q鲅bH1  !Lݢs^L>3*!  &2Zİ}VC2&  /FXht}Ȱ}tfP<,  &4@JQTW[`j몋xj`[WTQJ@3&  &,1469?IkkXI?9641,&  $-;N`ss_L:-$  $1@O[cikllllllllllllllllllkic[O@1$  '1:?CEEEEEEEEEEEEEEEEEEEEC?:1'  "%%&&&&&&&&&&&&&&&&&&%%"   fweelin-0.6/MacOSX/FweelinMac.h0000644000175000017500000000151510547030013014716 0ustar mercmerc// // FweelinMac.h // fweelin // #ifndef __FWEELIN_MAC_H__ #define __FWEELIN_MAC_H__ // Interface class between Objective-C Mac OS X code and C++ Fweelin code class FweelinMac { public: // Performs setup/takedown on a new pthread to make it behave well with Cocoa void SetupCocoaThread(); void TakedownCocoaThread(); void *autoreleasepool; // MIDI input list static void ClearMIDIInputList(); static void AddMIDIInputSource(char *name); static void SetMIDIInput(int idx); // Menu shortcuts to commands static void SetDebugMode(int active); static void Quit(); static void ShowHelp(); static void LinkSDLMain (void *m) { sdlmain = m; }; static void *sdlmain; // Pointer to instance of SDLMain static void LinkFweelin (void *fw) { fweelin = fw; }; static void *fweelin; // Pointer to instance of Fweelin }; #endiffweelin-0.6/MacOSX/FweelinMac.mm0000644000175000017500000000320210547030013015073 0ustar mercmerc// // FweelinMac.mm // fweelin // #import #include "FweelinMac.h" #include "SDLMain.h" #include "fweelin_core.h" void *FweelinMac::sdlmain = 0; void *FweelinMac::fweelin = 0; void FweelinMac::ClearMIDIInputList() { // printf("***SDLMAIN: %p\n",sdlmain); SDLMain *s = (SDLMain *)sdlmain; [s clearMIDIInputList]; }; void FweelinMac::AddMIDIInputSource(char *name) { SDLMain *s = (SDLMain *)sdlmain; [s addMIDIInputSource:[NSString stringWithUTF8String:name]]; }; void FweelinMac::SetMIDIInput(int idx) { // Connect MIDI Fweelin *fw = (Fweelin *)fweelin; fw->getMIDI()->SetMIDIInput(idx); }; void FweelinMac::SetDebugMode(int active) { Fweelin *fw = (Fweelin *)fweelin; ShowDebugInfoEvent *devt = (ShowDebugInfoEvent *) Event::GetEventByType(T_EV_ShowDebugInfo); devt->show = active; fw->getEMG()->BroadcastEventNow(devt, fw); }; void FweelinMac::Quit() { Fweelin *fw = (Fweelin *)fweelin; ExitSessionEvent *evt = (ExitSessionEvent *) Event::GetEventByType(T_EV_ExitSession); fw->getEMG()->BroadcastEventNow(evt, fw); }; void FweelinMac::ShowHelp() { Fweelin *fw = (Fweelin *)fweelin; VideoShowHelpEvent *evt = (VideoShowHelpEvent *) Event::GetEventByType(T_EV_VideoShowHelp); evt->page = 1; fw->getEMG()->BroadcastEventNow(evt, fw); }; // Performs initialization on a new pthread to make it behave well with Cocoa void FweelinMac::SetupCocoaThread() { // printf("MULTITHREADED: %d\n",[NSThread isMultiThreaded]); autoreleasepool = [[NSAutoreleasePool alloc] init]; }; void FweelinMac::TakedownCocoaThread() { NSAutoreleasePool *tmp = (NSAutoreleasePool *) autoreleasepool; [tmp release]; }; fweelin-0.6/MacOSX/fweelin_Prefix.pch0000644000175000017500000000024310547030013016172 0ustar mercmerc// // Prefix header for all source files of the 'fweelin' target in the 'fweelin' project // #include "SDL.h" #ifdef __OBJC__ #import #endif fweelin-0.6/MacOSX/fweelin.xcodeproj/0000755000175000017500000000000010746301451016166 5ustar mercmercfweelin-0.6/MacOSX/fweelin.xcodeproj/mercury.mode10000644000175000017500000012545210562716653020626 0ustar mercmerc ActivePerspectiveName Project AllowedModules BundleLoadPath MaxInstances n Module PBXSmartGroupTreeModule Name Groups and Files Outline View BundleLoadPath MaxInstances n Module PBXNavigatorGroup Name Editor BundleLoadPath MaxInstances n Module XCTaskListModule Name Task List BundleLoadPath MaxInstances n Module XCDetailModule Name File and Smart Group Detail Viewer BundleLoadPath MaxInstances 1 Module PBXBuildResultsModule Name Detailed Build Results Viewer BundleLoadPath MaxInstances 1 Module PBXProjectFindModule Name Project Batch Find Tool BundleLoadPath MaxInstances n Module PBXRunSessionModule Name Run Log BundleLoadPath MaxInstances n Module PBXBookmarksModule Name Bookmarks Tool BundleLoadPath MaxInstances n Module PBXClassBrowserModule Name Class Browser BundleLoadPath MaxInstances n Module PBXCVSModule Name Source Code Control Tool BundleLoadPath MaxInstances n Module PBXDebugBreakpointsModule Name Debug Breakpoints Tool BundleLoadPath MaxInstances n Module XCDockableInspector Name Inspector BundleLoadPath MaxInstances n Module PBXOpenQuicklyModule Name Open Quickly Tool BundleLoadPath MaxInstances 1 Module PBXDebugSessionModule Name Debugger BundleLoadPath MaxInstances 1 Module PBXDebugCLIModule Name Debug Console Description DefaultDescriptionKey DockingSystemVisible Extension mode1 FavBarConfig PBXProjectModuleGUID AC5A53140AC098E400622F72 XCBarModuleItemNames XCBarModuleItems FirstTimeWindowDisplayed Identifier com.apple.perspectives.project.mode1 MajorVersion 31 MinorVersion 1 Name Default Notifications OpenEditors PerspectiveWidths -1 -1 Perspectives ChosenToolbarItems active-target-popup action NSToolbarFlexibleSpaceItem buildOrClean build-and-runOrDebug com.apple.ide.PBXToolbarStopButton get-info toggle-editor NSToolbarFlexibleSpaceItem com.apple.pbx.toolbar.searchfield ControllerClassBaseName IconName WindowOfProjectWithEditor Identifier perspective.project IsVertical Layout ContentConfiguration PBXBottomSmartGroupGIDs 1C37FBAC04509CD000000102 1C37FAAC04509CD000000102 1C08E77C0454961000C914BD 1C37FABC05509CD000000102 1C37FABC05539CD112110102 E2644B35053B69B200211256 1C37FABC04509CD000100104 1CC0EA4004350EF90044410B 1CC0EA4004350EF90041110B PBXProjectModuleGUID 1CE0B1FE06471DED0097A5F4 PBXProjectModuleLabel Files PBXProjectStructureProvided yes PBXSmartGroupTreeModuleColumnData PBXSmartGroupTreeModuleColumnWidthsKey 285 PBXSmartGroupTreeModuleColumnsKey_v4 MainColumn PBXSmartGroupTreeModuleOutlineStateKey_v7 PBXSmartGroupTreeModuleOutlineStateExpansionKey 29B97314FDCFA39411CA2CEA 080E96DDFE201D6D7F000001 29B97315FDCFA39411CA2CEA 29B97317FDCFA39411CA2CEA 29B97323FDCFA39411CA2CEA 1058C7A0FEA54F0111CA2CBB AC5A53270AC099C900622F72 19C28FACFE9D520D11CA2CBB 8D1107320486CEB800E47090 1C37FBAC04509CD000000102 1C37FABC05509CD000000102 PBXSmartGroupTreeModuleOutlineStateSelectionKey 17 1 0 PBXSmartGroupTreeModuleOutlineStateVisibleRectKey {{0, 0}, {285, 629}} PBXTopSmartGroupGIDs XCIncludePerspectivesSwitch XCSharingToken com.apple.Xcode.GFSharingToken GeometryConfiguration Frame {{0, 0}, {302, 647}} GroupTreeTableConfiguration MainColumn 285 RubberWindowFrame 140 149 979 688 0 0 1440 878 Module PBXSmartGroupTreeModule Proportion 302pt Dock BecomeActive ContentConfiguration PBXProjectModuleGUID 1CE0B20306471E060097A5F4 PBXProjectModuleLabel fweelin_event.h PBXSplitModuleInNavigatorKey Split0 PBXProjectModuleGUID 1CE0B20406471E060097A5F4 PBXProjectModuleLabel fweelin_event.h _historyCapacity 0 bookmark AC19AECE0B77E57400AEC16F history AC5A56880AC2419A00622F72 AC12676A0AC8E0C600FE916E AC126C790AC8F26100FE916E ACE0E9A30ACA1CC1007E3ED2 AC6427D80AD883FA00752A08 AC6427E70AD884EE00752A08 AC642A1E0ADB317200752A08 ACA2C5D60B06E0F700E02DC6 ACA2C6CD0B06EC6700E02DC6 ACA2C7CF0B07C82F00E02DC6 ACA2C81F0B0830F900E02DC6 ACA2CB8A0B0AC86600E02DC6 ACA2CB8C0B0AC86600E02DC6 ACA2CB8D0B0AC86600E02DC6 ACA2CB9E0B0AC89600E02DC6 ACA2CE0D0B10369800E02DC6 ACF2F7A10B4C70B2005197BB ACABFD0E0B6178C500CA3C21 ACABFDBC0B61895200CA3C21 ACABFDF70B61D7DB00CA3C21 ACABFE190B61E19100CA3C21 ACABFE3E0B61E39100CA3C21 ACF227730B6826DC005CFC14 ACF227B50B682D68005CFC14 ACF227B70B682D68005CFC14 ACF227F10B689BAA005CFC14 ACF227F20B689BAA005CFC14 AC776D5F0B69B290005E3D84 AC776D600B69B290005E3D84 AC2AECD60B6AD6CE00AFA3A9 AC2AECD90B6AD6CE00AFA3A9 AC2080220B6EDC4A002A78E8 AC2080240B6EDC4A002A78E8 AC20802E0B6F09C5002A78E8 ACBF6FEF0B7326D6004A69E7 AC19AEB60B77E01400AEC16F AC19AEC20B77E09D00AEC16F AC19AEC30B77E09D00AEC16F AC19AECB0B77E57400AEC16F AC19AECC0B77E57400AEC16F prevStack AC5A54D30AC0EA0200622F72 AC5A54E90AC0EA8500622F72 AC5A54EA0AC0EA8500622F72 AC5A54EB0AC0EA8500622F72 AC5A54EC0AC0EA8500622F72 AC5A55D80AC2198F00622F72 AC5A55D90AC2198F00622F72 AC5A568E0AC2419A00622F72 AC5A56900AC2419A00622F72 AC5A56980AC2419A00622F72 AC5A569A0AC2419A00622F72 AC5A569C0AC2419A00622F72 AC5A569D0AC2419A00622F72 AC5A569E0AC2419A00622F72 AC5A56FE0AC2448600622F72 AC5A57660AC250C200622F72 AC1267750AC8E0C600FE916E AC1267760AC8E0C600FE916E AC12677A0AC8E0C600FE916E AC12677B0AC8E0C600FE916E AC126BEC0AC8E94900FE916E AC126C5A0AC8F08000FE916E AC126C5B0AC8F08000FE916E AC126C5C0AC8F08000FE916E AC126C930AC8F36000FE916E ACFC0AB00AC99E2E00DAC478 ACFC0AB10AC99E2E00DAC478 ACFC0B910AC9A70300DAC478 ACE0E72E0AC9CF47007E3ED2 ACE0E94B0ACA196D007E3ED2 AC642A270ADB317200752A08 AC642A280ADB317200752A08 ACA2C5D90B06E0F700E02DC6 ACA2CE0E0B10369800E02DC6 AC776D620B69B290005E3D84 AC776D640B69B290005E3D84 AC776D650B69B290005E3D84 AC2080280B6EDC4A002A78E8 AC20802A0B6EDC4A002A78E8 AC19AEB80B77E01400AEC16F AC19AEB90B77E01400AEC16F AC19AEC50B77E09D00AEC16F AC19AEC60B77E09D00AEC16F AC19AEC70B77E09D00AEC16F AC19AECD0B77E57400AEC16F SplitCount 1 StatusBarVisibility GeometryConfiguration Frame {{0, 0}, {672, 449}} RubberWindowFrame 140 149 979 688 0 0 1440 878 Module PBXNavigatorGroup Proportion 449pt ContentConfiguration PBXProjectModuleGUID 1CE0B20506471E060097A5F4 PBXProjectModuleLabel Detail GeometryConfiguration Frame {{0, 454}, {672, 193}} RubberWindowFrame 140 149 979 688 0 0 1440 878 Module XCDetailModule Proportion 193pt Proportion 672pt Name Project ServiceClasses XCModuleDock PBXSmartGroupTreeModule XCModuleDock PBXNavigatorGroup XCDetailModule TableOfContents AC19AEBB0B77E01400AEC16F 1CE0B1FE06471DED0097A5F4 AC19AEBC0B77E01400AEC16F 1CE0B20306471E060097A5F4 1CE0B20506471E060097A5F4 ToolbarConfiguration xcode.toolbar.config.default ControllerClassBaseName IconName WindowOfProject Identifier perspective.morph IsVertical 0 Layout BecomeActive 1 ContentConfiguration PBXBottomSmartGroupGIDs 1C37FBAC04509CD000000102 1C37FAAC04509CD000000102 1C08E77C0454961000C914BD 1C37FABC05509CD000000102 1C37FABC05539CD112110102 E2644B35053B69B200211256 1C37FABC04509CD000100104 1CC0EA4004350EF90044410B 1CC0EA4004350EF90041110B PBXProjectModuleGUID 11E0B1FE06471DED0097A5F4 PBXProjectModuleLabel Files PBXProjectStructureProvided yes PBXSmartGroupTreeModuleColumnData PBXSmartGroupTreeModuleColumnWidthsKey 186 PBXSmartGroupTreeModuleColumnsKey_v4 MainColumn PBXSmartGroupTreeModuleOutlineStateKey_v7 PBXSmartGroupTreeModuleOutlineStateExpansionKey 29B97314FDCFA39411CA2CEA 1C37FABC05509CD000000102 PBXSmartGroupTreeModuleOutlineStateSelectionKey 0 PBXSmartGroupTreeModuleOutlineStateVisibleRectKey {{0, 0}, {186, 337}} PBXTopSmartGroupGIDs XCIncludePerspectivesSwitch 1 XCSharingToken com.apple.Xcode.GFSharingToken GeometryConfiguration Frame {{0, 0}, {203, 355}} GroupTreeTableConfiguration MainColumn 186 RubberWindowFrame 373 269 690 397 0 0 1440 878 Module PBXSmartGroupTreeModule Proportion 100% Name Morph PreferredWidth 300 ServiceClasses XCModuleDock PBXSmartGroupTreeModule TableOfContents 11E0B1FE06471DED0097A5F4 ToolbarConfiguration xcode.toolbar.config.default.short PerspectivesBarVisible ShelfIsVisible SourceDescription file at '/System/Library/PrivateFrameworks/DevToolsInterface.framework/Versions/A/Resources/XCPerspectivesSpecificationMode1.xcperspec' StatusbarIsVisible TimeStamp 0.0 ToolbarDisplayMode 1 ToolbarIsVisible ToolbarSizeMode 1 Type Perspectives UpdateMessage The Default Workspace in this version of Xcode now includes support to hide and show the detail view (what has been referred to as the "Metro-Morph" feature). You must discard your current Default Workspace settings and update to the latest Default Workspace in order to gain this feature. Do you wish to update to the latest Workspace defaults for project '%@'? WindowJustification 5 WindowOrderList AC5A53180AC098FB00622F72 1C0AD2B3069F1EA900FABCE6 /Users/mercury/Desktop/port/freewheeling/MacOSX/fweelin.xcodeproj WindowString 140 149 979 688 0 0 1440 878 WindowTools FirstTimeWindowDisplayed Identifier windowTool.build IsVertical Layout Dock ContentConfiguration PBXProjectModuleGUID 1CD0528F0623707200166675 PBXProjectModuleLabel StatusBarVisibility GeometryConfiguration Frame {{0, 0}, {1207, 311}} RubberWindowFrame 286 118 1207 575 0 0 1440 878 Module PBXNavigatorGroup Proportion 311pt ContentConfiguration PBXProjectModuleGUID XCMainBuildResultsModuleGUID PBXProjectModuleLabel Build XCBuildResultsTrigger_Collapse 1021 XCBuildResultsTrigger_Open 1011 GeometryConfiguration Frame {{0, 316}, {1207, 218}} RubberWindowFrame 286 118 1207 575 0 0 1440 878 Module PBXBuildResultsModule Proportion 218pt Proportion 534pt Name Build Results ServiceClasses PBXBuildResultsModule StatusbarIsVisible TableOfContents AC5A53180AC098FB00622F72 AC19AEBD0B77E01400AEC16F 1CD0528F0623707200166675 XCMainBuildResultsModuleGUID ToolbarConfiguration xcode.toolbar.config.build WindowString 286 118 1207 575 0 0 1440 878 WindowToolGUID AC5A53180AC098FB00622F72 WindowToolIsVisible FirstTimeWindowDisplayed Identifier windowTool.debugger IsVertical Layout Dock ContentConfiguration Debugger HorizontalSplitView _collapsingFrameDimension 0.0 _indexOfCollapsedView 0 _percentageOfCollapsedView 0.0 isCollapsed yes sizes {{0, 0}, {247, 190}} {{247, 0}, {447, 190}} VerticalSplitView _collapsingFrameDimension 0.0 _indexOfCollapsedView 0 _percentageOfCollapsedView 0.0 isCollapsed yes sizes {{0, 0}, {694, 190}} {{0, 190}, {694, 191}} LauncherConfigVersion 8 PBXProjectModuleGUID 1C162984064C10D400B95A72 PBXProjectModuleLabel Debug - GLUTExamples (Underwater) GeometryConfiguration DebugConsoleDrawerSize {100, 120} DebugConsoleVisible None DebugConsoleWindowFrame {{200, 200}, {500, 300}} DebugSTDIOWindowFrame {{200, 200}, {500, 300}} Frame {{0, 0}, {694, 381}} RubberWindowFrame 589 261 694 422 0 0 1440 878 Module PBXDebugSessionModule Proportion 381pt Proportion 381pt Name Debugger ServiceClasses PBXDebugSessionModule StatusbarIsVisible TableOfContents 1CD10A99069EF8BA00B06720 ACA2C84D0B08335700E02DC6 1C162984064C10D400B95A72 ACA2C84E0B08335700E02DC6 ACA2C84F0B08335700E02DC6 ACA2C8500B08335700E02DC6 ACA2C8510B08335700E02DC6 ACA2C8520B08335700E02DC6 ACA2C8530B08335700E02DC6 ToolbarConfiguration xcode.toolbar.config.debug WindowString 589 261 694 422 0 0 1440 878 WindowToolGUID 1CD10A99069EF8BA00B06720 WindowToolIsVisible FirstTimeWindowDisplayed Identifier windowTool.find IsVertical Layout Dock Dock ContentConfiguration PBXProjectModuleGUID 1CDD528C0622207200134675 PBXProjectModuleLabel fweelin_core.cc StatusBarVisibility GeometryConfiguration Frame {{0, 0}, {862, 353}} RubberWindowFrame 237 136 862 611 0 0 1440 878 Module PBXNavigatorGroup Proportion 862pt Proportion 353pt BecomeActive ContentConfiguration PBXProjectModuleGUID 1CD0528E0623707200166675 PBXProjectModuleLabel Project Find GeometryConfiguration Frame {{0, 358}, {862, 212}} RubberWindowFrame 237 136 862 611 0 0 1440 878 Module PBXProjectFindModule Proportion 212pt Proportion 570pt Name Project Find ServiceClasses PBXProjectFindModule StatusbarIsVisible TableOfContents 1C530D57069F1CE1000CFCEE ACBF6FDA0B72BFDF004A69E7 ACBF6FDB0B72BFDF004A69E7 1CDD528C0622207200134675 1CD0528E0623707200166675 WindowString 237 136 862 611 0 0 1440 878 WindowToolGUID 1C530D57069F1CE1000CFCEE WindowToolIsVisible Identifier MENUSEPARATOR FirstTimeWindowDisplayed Identifier windowTool.debuggerConsole IsVertical Layout Dock ContentConfiguration PBXProjectModuleGUID 1C78EAAC065D492600B07095 PBXProjectModuleLabel Debugger Console GeometryConfiguration Frame {{0, 0}, {440, 358}} RubberWindowFrame 196 389 440 400 0 0 1440 878 Module PBXDebugCLIModule Proportion 358pt Proportion 359pt Name Debugger Console ServiceClasses PBXDebugCLIModule StatusbarIsVisible TableOfContents AC126BC70AC8E7D700FE916E ACA2C6770B06E8E600E02DC6 1C78EAAC065D492600B07095 WindowString 196 389 440 400 0 0 1440 878 WindowToolGUID AC126BC70AC8E7D700FE916E WindowToolIsVisible FirstTimeWindowDisplayed Identifier windowTool.run IsVertical Layout Dock ContentConfiguration LauncherConfigVersion 3 PBXProjectModuleGUID 1CD0528B0623707200166675 PBXProjectModuleLabel Run Runner HorizontalSplitView _collapsingFrameDimension 0.0 _indexOfCollapsedView 0 _percentageOfCollapsedView 0.0 isCollapsed yes sizes {{0, 0}, {366, 168}} {{0, 173}, {366, 270}} VerticalSplitView _collapsingFrameDimension 0.0 _indexOfCollapsedView 0 _percentageOfCollapsedView 0.0 isCollapsed yes sizes {{0, 0}, {406, 443}} {{411, 0}, {517, 443}} GeometryConfiguration Frame {{0, 0}, {527, 170}} RubberWindowFrame 889 183 527 211 0 0 1440 878 Module PBXRunSessionModule Proportion 170pt Proportion 170pt Name Run Log ServiceClasses PBXRunSessionModule StatusbarIsVisible TableOfContents 1C0AD2B3069F1EA900FABCE6 AC19AEBE0B77E01400AEC16F 1CD0528B0623707200166675 AC19AEBF0B77E01400AEC16F ToolbarConfiguration xcode.toolbar.config.run WindowString 889 183 527 211 0 0 1440 878 WindowToolGUID 1C0AD2B3069F1EA900FABCE6 WindowToolIsVisible Identifier windowTool.scm Layout Dock ContentConfiguration PBXProjectModuleGUID 1C78EAB2065D492600B07095 PBXProjectModuleLabel <No Editor> PBXSplitModuleInNavigatorKey Split0 PBXProjectModuleGUID 1C78EAB3065D492600B07095 SplitCount 1 StatusBarVisibility 1 GeometryConfiguration Frame {{0, 0}, {452, 0}} RubberWindowFrame 743 379 452 308 0 0 1280 1002 Module PBXNavigatorGroup Proportion 0pt BecomeActive 1 ContentConfiguration PBXProjectModuleGUID 1CD052920623707200166675 PBXProjectModuleLabel SCM GeometryConfiguration ConsoleFrame {{0, 259}, {452, 0}} Frame {{0, 7}, {452, 259}} RubberWindowFrame 743 379 452 308 0 0 1280 1002 TableConfiguration Status 30 FileName 199 Path 197.09500122070312 TableFrame {{0, 0}, {452, 250}} Module PBXCVSModule Proportion 262pt Proportion 266pt Name SCM ServiceClasses PBXCVSModule StatusbarIsVisible 1 TableOfContents 1C78EAB4065D492600B07095 1C78EAB5065D492600B07095 1C78EAB2065D492600B07095 1CD052920623707200166675 ToolbarConfiguration xcode.toolbar.config.scm WindowString 743 379 452 308 0 0 1280 1002 Identifier windowTool.breakpoints IsVertical 0 Layout Dock BecomeActive 1 ContentConfiguration PBXBottomSmartGroupGIDs 1C77FABC04509CD000000102 PBXProjectModuleGUID 1CE0B1FE06471DED0097A5F4 PBXProjectModuleLabel Files PBXProjectStructureProvided no PBXSmartGroupTreeModuleColumnData PBXSmartGroupTreeModuleColumnWidthsKey 168 PBXSmartGroupTreeModuleColumnsKey_v4 MainColumn PBXSmartGroupTreeModuleOutlineStateKey_v7 PBXSmartGroupTreeModuleOutlineStateExpansionKey 1C77FABC04509CD000000102 PBXSmartGroupTreeModuleOutlineStateSelectionKey 0 PBXSmartGroupTreeModuleOutlineStateVisibleRectKey {{0, 0}, {168, 350}} PBXTopSmartGroupGIDs XCIncludePerspectivesSwitch 0 GeometryConfiguration Frame {{0, 0}, {185, 368}} GroupTreeTableConfiguration MainColumn 168 RubberWindowFrame 315 424 744 409 0 0 1440 878 Module PBXSmartGroupTreeModule Proportion 185pt ContentConfiguration PBXProjectModuleGUID 1CA1AED706398EBD00589147 PBXProjectModuleLabel Detail GeometryConfiguration Frame {{190, 0}, {554, 368}} RubberWindowFrame 315 424 744 409 0 0 1440 878 Module XCDetailModule Proportion 554pt Proportion 368pt MajorVersion 2 MinorVersion 0 Name Breakpoints ServiceClasses PBXSmartGroupTreeModule XCDetailModule StatusbarIsVisible 1 TableOfContents 1CDDB66807F98D9800BB5817 1CDDB66907F98D9800BB5817 1CE0B1FE06471DED0097A5F4 1CA1AED706398EBD00589147 ToolbarConfiguration xcode.toolbar.config.breakpoints WindowString 315 424 744 409 0 0 1440 878 WindowToolGUID 1CDDB66807F98D9800BB5817 WindowToolIsVisible 1 Identifier windowTool.debugAnimator Layout Dock Module PBXNavigatorGroup Proportion 100% Proportion 100% Name Debug Visualizer ServiceClasses PBXNavigatorGroup StatusbarIsVisible 1 ToolbarConfiguration xcode.toolbar.config.debugAnimator WindowString 100 100 700 500 0 0 1280 1002 Identifier windowTool.bookmarks Layout Dock Module PBXBookmarksModule Proportion 100% Proportion 100% Name Bookmarks ServiceClasses PBXBookmarksModule StatusbarIsVisible 0 WindowString 538 42 401 187 0 0 1280 1002 Identifier windowTool.classBrowser Layout Dock BecomeActive 1 ContentConfiguration OptionsSetName Hierarchy, all classes PBXProjectModuleGUID 1CA6456E063B45B4001379D8 PBXProjectModuleLabel Class Browser - NSObject GeometryConfiguration ClassesFrame {{0, 0}, {374, 96}} ClassesTreeTableConfiguration PBXClassNameColumnIdentifier 208 PBXClassBookColumnIdentifier 22 Frame {{0, 0}, {630, 331}} MembersFrame {{0, 105}, {374, 395}} MembersTreeTableConfiguration PBXMemberTypeIconColumnIdentifier 22 PBXMemberNameColumnIdentifier 216 PBXMemberTypeColumnIdentifier 97 PBXMemberBookColumnIdentifier 22 PBXModuleWindowStatusBarHidden2 1 RubberWindowFrame 385 179 630 352 0 0 1440 878 Module PBXClassBrowserModule Proportion 332pt Proportion 332pt Name Class Browser ServiceClasses PBXClassBrowserModule StatusbarIsVisible 0 TableOfContents 1C0AD2AF069F1E9B00FABCE6 1C0AD2B0069F1E9B00FABCE6 1CA6456E063B45B4001379D8 ToolbarConfiguration xcode.toolbar.config.classbrowser WindowString 385 179 630 352 0 0 1440 878 WindowToolGUID 1C0AD2AF069F1E9B00FABCE6 WindowToolIsVisible 0 fweelin-0.6/MacOSX/fweelin.xcodeproj/mercury.pbxuser0000644000175000017500000012761710562716653021316 0ustar mercmerc// !$*UTF8*$! { 002F3A2B09D0888800EBEB88 /* SDLMain.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {631, 417}}"; sepNavSelRange = "{486, 0}"; sepNavVisRect = "{{0, 0}, {631, 417}}"; }; }; 002F3A2C09D0888800EBEB88 /* SDLMain.mm */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {818, 6230}}"; sepNavSelRange = "{10608, 7}"; sepNavVisRect = "{{0, 5293}, {740, 180}}"; }; }; 089C165DFE840E0CC02AAC07 /* English */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1092, 611}}"; sepNavSelRange = "{76, 0}"; sepNavVisRect = "{{0, 0}, {1092, 611}}"; sepNavWindowFrame = "{{73, 112}, {1131, 740}}"; }; }; 29B97313FDCFA39411CA2CEA /* Project object */ = { activeBuildConfigurationName = Release; activeExecutable = AC5A53070AC098E000622F72 /* fweelin */; activeTarget = 8D1107260486CEB800E47090 /* fweelin */; addToTargets = ( 8D1107260486CEB800E47090 /* fweelin */, ); breakpoints = ( ); breakpointsGroup = AC5A531F0AC0998E00622F72 /* XCBreakpointsBucket */; codeSenseManager = AC5A53160AC098E400622F72 /* Code sense */; executables = ( AC5A53070AC098E000622F72 /* fweelin */, ); perUserDictionary = { PBXConfiguration.PBXFileTableDataSource3.PBXFileTableDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID; PBXFileTableDataSourceColumnWidthsKey = ( 20, 433, 20, 48, 43, 43, 20, ); PBXFileTableDataSourceColumnsKey = ( PBXFileDataSource_FiletypeID, PBXFileDataSource_Filename_ColumnID, PBXFileDataSource_Built_ColumnID, PBXFileDataSource_ObjectSize_ColumnID, PBXFileDataSource_Errors_ColumnID, PBXFileDataSource_Warnings_ColumnID, PBXFileDataSource_Target_ColumnID, ); }; PBXConfiguration.PBXTargetDataSource.PBXTargetDataSource = { PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID; PBXFileTableDataSourceColumnWidthsKey = ( 20, 200, 253, 20, 48, 43, 43, ); PBXFileTableDataSourceColumnsKey = ( PBXFileDataSource_FiletypeID, PBXFileDataSource_Filename_ColumnID, PBXTargetDataSource_PrimaryAttribute, PBXFileDataSource_Built_ColumnID, PBXFileDataSource_ObjectSize_ColumnID, PBXFileDataSource_Errors_ColumnID, PBXFileDataSource_Warnings_ColumnID, ); }; PBXPerProjectTemplateStateSaveDate = 192405221; PBXWorkspaceStateSaveDate = 192405221; }; perUserProjectItems = { AC12676A0AC8E0C600FE916E = AC12676A0AC8E0C600FE916E /* PBXTextBookmark */; AC1267750AC8E0C600FE916E = AC1267750AC8E0C600FE916E /* PBXTextBookmark */; AC1267760AC8E0C600FE916E = AC1267760AC8E0C600FE916E /* PBXTextBookmark */; AC12677A0AC8E0C600FE916E = AC12677A0AC8E0C600FE916E /* PBXTextBookmark */; AC12677B0AC8E0C600FE916E = AC12677B0AC8E0C600FE916E /* PBXTextBookmark */; AC126BEC0AC8E94900FE916E = AC126BEC0AC8E94900FE916E /* PBXTextBookmark */; AC126C5A0AC8F08000FE916E = AC126C5A0AC8F08000FE916E /* PBXTextBookmark */; AC126C5B0AC8F08000FE916E = AC126C5B0AC8F08000FE916E /* PBXTextBookmark */; AC126C5C0AC8F08000FE916E = AC126C5C0AC8F08000FE916E /* PBXTextBookmark */; AC126C790AC8F26100FE916E = AC126C790AC8F26100FE916E /* PBXTextBookmark */; AC126C930AC8F36000FE916E = AC126C930AC8F36000FE916E /* PBXTextBookmark */; AC19AEB60B77E01400AEC16F /* PBXTextBookmark */ = AC19AEB60B77E01400AEC16F /* PBXTextBookmark */; AC19AEB70B77E01400AEC16F /* PBXTextBookmark */ = AC19AEB70B77E01400AEC16F /* PBXTextBookmark */; AC19AEB80B77E01400AEC16F /* PBXTextBookmark */ = AC19AEB80B77E01400AEC16F /* PBXTextBookmark */; AC19AEB90B77E01400AEC16F /* PBXTextBookmark */ = AC19AEB90B77E01400AEC16F /* PBXTextBookmark */; AC19AEBA0B77E01400AEC16F /* PBXTextBookmark */ = AC19AEBA0B77E01400AEC16F /* PBXTextBookmark */; AC19AEC10B77E09D00AEC16F /* PBXTextBookmark */ = AC19AEC10B77E09D00AEC16F /* PBXTextBookmark */; AC19AEC20B77E09D00AEC16F /* PBXTextBookmark */ = AC19AEC20B77E09D00AEC16F /* PBXTextBookmark */; AC19AEC30B77E09D00AEC16F /* PBXTextBookmark */ = AC19AEC30B77E09D00AEC16F /* PBXTextBookmark */; AC19AEC40B77E09D00AEC16F /* PBXTextBookmark */ = AC19AEC40B77E09D00AEC16F /* PBXTextBookmark */; AC19AEC50B77E09D00AEC16F /* PBXTextBookmark */ = AC19AEC50B77E09D00AEC16F /* PBXTextBookmark */; AC19AEC60B77E09D00AEC16F /* PBXTextBookmark */ = AC19AEC60B77E09D00AEC16F /* PBXTextBookmark */; AC19AEC70B77E09D00AEC16F /* PBXTextBookmark */ = AC19AEC70B77E09D00AEC16F /* PBXTextBookmark */; AC19AEC80B77E09D00AEC16F /* PBXTextBookmark */ = AC19AEC80B77E09D00AEC16F /* PBXTextBookmark */; AC19AECB0B77E57400AEC16F /* PBXTextBookmark */ = AC19AECB0B77E57400AEC16F /* PBXTextBookmark */; AC19AECC0B77E57400AEC16F /* PBXTextBookmark */ = AC19AECC0B77E57400AEC16F /* PBXTextBookmark */; AC19AECD0B77E57400AEC16F /* PBXTextBookmark */ = AC19AECD0B77E57400AEC16F /* PBXTextBookmark */; AC19AECE0B77E57400AEC16F /* PBXTextBookmark */ = AC19AECE0B77E57400AEC16F /* PBXTextBookmark */; AC2080220B6EDC4A002A78E8 = AC2080220B6EDC4A002A78E8 /* PBXTextBookmark */; AC2080240B6EDC4A002A78E8 = AC2080240B6EDC4A002A78E8 /* PBXTextBookmark */; AC2080280B6EDC4A002A78E8 = AC2080280B6EDC4A002A78E8 /* PBXTextBookmark */; AC20802A0B6EDC4A002A78E8 = AC20802A0B6EDC4A002A78E8 /* PBXTextBookmark */; AC20802E0B6F09C5002A78E8 = AC20802E0B6F09C5002A78E8 /* PBXTextBookmark */; AC2AECD60B6AD6CE00AFA3A9 = AC2AECD60B6AD6CE00AFA3A9 /* PBXTextBookmark */; AC2AECD90B6AD6CE00AFA3A9 = AC2AECD90B6AD6CE00AFA3A9 /* PBXTextBookmark */; AC2AECDA0B6AD6CE00AFA3A9 = AC2AECDA0B6AD6CE00AFA3A9 /* PBXTextBookmark */; AC5A54D30AC0EA0200622F72 = AC5A54D30AC0EA0200622F72 /* PBXTextBookmark */; AC5A54E90AC0EA8500622F72 = AC5A54E90AC0EA8500622F72 /* PBXTextBookmark */; AC5A54EA0AC0EA8500622F72 = AC5A54EA0AC0EA8500622F72 /* PBXTextBookmark */; AC5A54EB0AC0EA8500622F72 = AC5A54EB0AC0EA8500622F72 /* PBXTextBookmark */; AC5A54EC0AC0EA8500622F72 = AC5A54EC0AC0EA8500622F72 /* PBXTextBookmark */; AC5A55D80AC2198F00622F72 = AC5A55D80AC2198F00622F72 /* PBXTextBookmark */; AC5A55D90AC2198F00622F72 = AC5A55D90AC2198F00622F72 /* PBXTextBookmark */; AC5A56880AC2419A00622F72 = AC5A56880AC2419A00622F72 /* PBXTextBookmark */; AC5A568E0AC2419A00622F72 = AC5A568E0AC2419A00622F72 /* PBXTextBookmark */; AC5A56900AC2419A00622F72 = AC5A56900AC2419A00622F72 /* PBXTextBookmark */; AC5A56980AC2419A00622F72 = AC5A56980AC2419A00622F72 /* PBXTextBookmark */; AC5A569A0AC2419A00622F72 = AC5A569A0AC2419A00622F72 /* PBXTextBookmark */; AC5A569C0AC2419A00622F72 = AC5A569C0AC2419A00622F72 /* PBXTextBookmark */; AC5A569D0AC2419A00622F72 = AC5A569D0AC2419A00622F72 /* PBXTextBookmark */; AC5A569E0AC2419A00622F72 = AC5A569E0AC2419A00622F72 /* PBXTextBookmark */; AC5A56FE0AC2448600622F72 = AC5A56FE0AC2448600622F72 /* PBXTextBookmark */; AC5A57660AC250C200622F72 = AC5A57660AC250C200622F72 /* PBXTextBookmark */; AC6427D80AD883FA00752A08 = AC6427D80AD883FA00752A08 /* PBXTextBookmark */; AC6427E70AD884EE00752A08 = AC6427E70AD884EE00752A08 /* PBXTextBookmark */; AC642A1E0ADB317200752A08 = AC642A1E0ADB317200752A08 /* PBXTextBookmark */; AC642A270ADB317200752A08 = AC642A270ADB317200752A08 /* PBXTextBookmark */; AC642A280ADB317200752A08 = AC642A280ADB317200752A08 /* PBXTextBookmark */; AC776D5F0B69B290005E3D84 = AC776D5F0B69B290005E3D84 /* PBXTextBookmark */; AC776D600B69B290005E3D84 = AC776D600B69B290005E3D84 /* PBXBookmark */; AC776D620B69B290005E3D84 = AC776D620B69B290005E3D84 /* PBXTextBookmark */; AC776D640B69B290005E3D84 = AC776D640B69B290005E3D84 /* PBXTextBookmark */; AC776D650B69B290005E3D84 = AC776D650B69B290005E3D84 /* PBXBookmark */; ACA2C5D60B06E0F700E02DC6 = ACA2C5D60B06E0F700E02DC6 /* PBXTextBookmark */; ACA2C5D90B06E0F700E02DC6 = ACA2C5D90B06E0F700E02DC6 /* PBXTextBookmark */; ACA2C6CD0B06EC6700E02DC6 = ACA2C6CD0B06EC6700E02DC6 /* PBXTextBookmark */; ACA2C7CF0B07C82F00E02DC6 = ACA2C7CF0B07C82F00E02DC6 /* PBXTextBookmark */; ACA2C81F0B0830F900E02DC6 = ACA2C81F0B0830F900E02DC6 /* PBXTextBookmark */; ACA2CB8A0B0AC86600E02DC6 = ACA2CB8A0B0AC86600E02DC6 /* PBXTextBookmark */; ACA2CB8C0B0AC86600E02DC6 = ACA2CB8C0B0AC86600E02DC6 /* PBXTextBookmark */; ACA2CB8D0B0AC86600E02DC6 = ACA2CB8D0B0AC86600E02DC6 /* PBXTextBookmark */; ACA2CB9E0B0AC89600E02DC6 = ACA2CB9E0B0AC89600E02DC6 /* PBXTextBookmark */; ACA2CE0D0B10369800E02DC6 = ACA2CE0D0B10369800E02DC6 /* PBXTextBookmark */; ACA2CE0E0B10369800E02DC6 = ACA2CE0E0B10369800E02DC6 /* PBXTextBookmark */; ACABFD0E0B6178C500CA3C21 = ACABFD0E0B6178C500CA3C21 /* PBXTextBookmark */; ACABFDBC0B61895200CA3C21 = ACABFDBC0B61895200CA3C21 /* PBXTextBookmark */; ACABFDF70B61D7DB00CA3C21 = ACABFDF70B61D7DB00CA3C21 /* PBXTextBookmark */; ACABFE190B61E19100CA3C21 = ACABFE190B61E19100CA3C21 /* PBXTextBookmark */; ACABFE3E0B61E39100CA3C21 = ACABFE3E0B61E39100CA3C21 /* PBXTextBookmark */; ACBF6FE70B72C07D004A69E7 = ACBF6FE70B72C07D004A69E7 /* PBXTextBookmark */; ACBF6FE80B72C07D004A69E7 = ACBF6FE80B72C07D004A69E7 /* PBXTextBookmark */; ACBF6FEF0B7326D6004A69E7 = ACBF6FEF0B7326D6004A69E7 /* PBXTextBookmark */; ACBF6FF00B7326D6004A69E7 = ACBF6FF00B7326D6004A69E7 /* PBXTextBookmark */; ACBF6FF10B7326D6004A69E7 = ACBF6FF10B7326D6004A69E7 /* PBXTextBookmark */; ACBF6FF20B7326D6004A69E7 = ACBF6FF20B7326D6004A69E7 /* PBXTextBookmark */; ACBF6FF30B7326D6004A69E7 = ACBF6FF30B7326D6004A69E7 /* PBXTextBookmark */; ACE0E72E0AC9CF47007E3ED2 = ACE0E72E0AC9CF47007E3ED2 /* PBXTextBookmark */; ACE0E94B0ACA196D007E3ED2 = ACE0E94B0ACA196D007E3ED2 /* PBXTextBookmark */; ACE0E9A30ACA1CC1007E3ED2 = ACE0E9A30ACA1CC1007E3ED2 /* PBXTextBookmark */; ACF227730B6826DC005CFC14 = ACF227730B6826DC005CFC14 /* PBXTextBookmark */; ACF227B50B682D68005CFC14 = ACF227B50B682D68005CFC14 /* PBXTextBookmark */; ACF227B70B682D68005CFC14 = ACF227B70B682D68005CFC14 /* PBXTextBookmark */; ACF227EF0B689BAA005CFC14 = ACF227EF0B689BAA005CFC14 /* PBXTextBookmark */; ACF227F10B689BAA005CFC14 = ACF227F10B689BAA005CFC14 /* PBXTextBookmark */; ACF227F20B689BAA005CFC14 = ACF227F20B689BAA005CFC14 /* PBXTextBookmark */; ACF2F7A10B4C70B2005197BB = ACF2F7A10B4C70B2005197BB /* PBXTextBookmark */; ACFC0AB00AC99E2E00DAC478 = ACFC0AB00AC99E2E00DAC478 /* PBXTextBookmark */; ACFC0AB10AC99E2E00DAC478 = ACFC0AB10AC99E2E00DAC478 /* PBXTextBookmark */; ACFC0B910AC9A70300DAC478 = ACFC0B910AC9A70300DAC478 /* PBXTextBookmark */; }; sourceControlManager = AC5A53150AC098E400622F72 /* Source Control */; userBuildSettings = { }; }; 32CA4F630368D1EE00C91783 /* fweelin_Prefix.pch */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {730, 610}}"; sepNavSelRange = "{163, 0}"; sepNavVisRect = "{{0, 0}, {730, 610}}"; }; }; 8D1107260486CEB800E47090 /* fweelin */ = { activeExec = 0; executables = ( AC5A53070AC098E000622F72 /* fweelin */, ); }; 8D1107310486CEB800E47090 /* Info.plist */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {686, 417}}"; sepNavSelRange = "{480, 0}"; sepNavVisRect = "{{0, 0}, {631, 417}}"; sepNavWindowFrame = "{{50, 133}, {1131, 740}}"; }; }; AC12676A0AC8E0C600FE916E /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 32CA4F630368D1EE00C91783 /* fweelin_Prefix.pch */; name = "fweelin_Prefix.pch: 10"; rLen = 0; rLoc = 163; rType = 0; vrLen = 163; vrLoc = 0; }; AC1267750AC8E0C600FE916E /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 002F3A2C09D0888800EBEB88 /* SDLMain.mm */; name = "SDLMain.m: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 1339; vrLoc = 0; }; AC1267760AC8E0C600FE916E /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 32CA4F630368D1EE00C91783 /* fweelin_Prefix.pch */; name = "fweelin_Prefix.pch: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 163; vrLoc = 0; }; AC12677A0AC8E0C600FE916E /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53D80AC09A6400622F72 /* fweelin_browser.h */; name = BLINK_DELAY; rLen = 11; rLoc = 2395; rType = 0; vrLen = 1245; vrLoc = 1790; }; AC12677B0AC8E0C600FE916E /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53D70AC09A6400622F72 /* fweelin_browser.cc */; name = "fweelin_browser.cc: BLINK_DELAY"; rLen = 0; rLoc = 337; rType = 0; vrLen = 1062; vrLoc = 0; }; AC126BEC0AC8E94900FE916E /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 002F3A2B09D0888800EBEB88 /* SDLMain.h */; name = "SDLMain.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 307; vrLoc = 0; }; AC126C3E0AC8EED400FE916E /* .fweelin.rc */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {728, 36932}}"; sepNavSelRange = "{104754, 0}"; sepNavVisRect = "{{0, 18911}, {631, 417}}"; sepNavWindowFrame = "{{142, 49}, {1131, 740}}"; }; }; AC126C5A0AC8F08000FE916E /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC126C3E0AC8EED400FE916E /* .fweelin.rc */; name = ".fweelin.rc: 29"; rLen = 0; rLoc = 1545; rType = 0; vrLen = 2188; vrLoc = 0; }; AC126C5B0AC8F08000FE916E /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53E30AC09A6400622F72 /* fweelin_fluidsynth.cc */; name = "fweelin_fluidsynth.cc: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 1362; vrLoc = 0; }; AC126C5C0AC8F08000FE916E /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53E40AC09A6400622F72 /* fweelin_fluidsynth.h */; name = "fweelin_fluidsynth.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 1121; vrLoc = 0; }; AC126C790AC8F26100FE916E /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53E00AC09A6400622F72 /* fweelin_datatypes.h */; name = "fweelin_datatypes.h: 20"; rLen = 0; rLoc = 290; rType = 0; vrLen = 938; vrLoc = 0; }; AC126C930AC8F36000FE916E /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53ED0AC09A6400622F72 /* fweelin_videoio.h */; name = "fweelin_videoio.h: 30"; rLen = 0; rLoc = 738; rType = 0; vrLen = 1183; vrLoc = 0; }; AC19AEB60B77E01400AEC16F /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53E10AC09A6400622F72 /* fweelin_event.cc */; name = "fweelin_event.cc: 310"; rLen = 0; rLoc = 11071; rType = 0; vrLen = 1199; vrLoc = 2596; }; AC19AEB70B77E01400AEC16F /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53E20AC09A6400622F72 /* fweelin_event.h */; name = "fweelin_event.h: 10"; rLen = 0; rLoc = 139; rType = 0; vrLen = 556; vrLoc = 0; }; AC19AEB80B77E01400AEC16F /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53E20AC09A6400622F72 /* fweelin_event.h */; name = "fweelin_event.h: 10"; rLen = 0; rLoc = 139; rType = 0; vrLen = 556; vrLoc = 0; }; AC19AEB90B77E01400AEC16F /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53E10AC09A6400622F72 /* fweelin_event.cc */; name = "fweelin_event.cc: 310"; rLen = 0; rLoc = 11071; rType = 0; vrLen = 1199; vrLoc = 2596; }; AC19AEBA0B77E01400AEC16F /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53E20AC09A6400622F72 /* fweelin_event.h */; name = "fweelin_event.h: 2194"; rLen = 0; rLoc = 60996; rType = 0; vrLen = 1053; vrLoc = 60658; }; AC19AEC10B77E09D00AEC16F /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53E20AC09A6400622F72 /* fweelin_event.h */; name = "fweelin_event.h: 2194"; rLen = 0; rLoc = 60996; rType = 0; vrLen = 1076; vrLoc = 60658; }; AC19AEC20B77E09D00AEC16F /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53E80AC09A6400622F72 /* fweelin_midiio.cc */; name = "fweelin_midiio.cc: 906"; rLen = 0; rLoc = 26017; rType = 0; vrLen = 854; vrLoc = 25452; }; AC19AEC30B77E09D00AEC16F /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53E60AC09A6400622F72 /* fweelin_mem.cc */; name = "fweelin_mem.cc: 159"; rLen = 0; rLoc = 3783; rType = 0; vrLen = 748; vrLoc = 3423; }; AC19AEC40B77E09D00AEC16F /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53EC0AC09A6400622F72 /* fweelin_videoio.cc */; name = "fweelin_videoio.cc: 1828"; rLen = 0; rLoc = 48261; rType = 0; vrLen = 845; vrLoc = 48037; }; AC19AEC50B77E09D00AEC16F /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53E20AC09A6400622F72 /* fweelin_event.h */; name = "fweelin_event.h: 2194"; rLen = 0; rLoc = 60996; rType = 0; vrLen = 1076; vrLoc = 60658; }; AC19AEC60B77E09D00AEC16F /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53E80AC09A6400622F72 /* fweelin_midiio.cc */; name = "fweelin_midiio.cc: 906"; rLen = 0; rLoc = 26017; rType = 0; vrLen = 854; vrLoc = 25452; }; AC19AEC70B77E09D00AEC16F /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53E60AC09A6400622F72 /* fweelin_mem.cc */; name = "fweelin_mem.cc: 159"; rLen = 0; rLoc = 3783; rType = 0; vrLen = 748; vrLoc = 3423; }; AC19AEC80B77E09D00AEC16F /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53EC0AC09A6400622F72 /* fweelin_videoio.cc */; name = "fweelin_videoio.cc: 2328"; rLen = 0; rLoc = 62301; rType = 0; vrLen = 806; vrLoc = 61776; }; AC19AECB0B77E57400AEC16F /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53EC0AC09A6400622F72 /* fweelin_videoio.cc */; name = "fweelin_videoio.cc: 2327"; rLen = 0; rLoc = 62264; rType = 0; vrLen = 806; vrLoc = 61776; }; AC19AECC0B77E57400AEC16F /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53E20AC09A6400622F72 /* fweelin_event.h */; name = "fweelin_event.h: 2194"; rLen = 0; rLoc = 60996; rType = 0; vrLen = 1033; vrLoc = 60658; }; AC19AECD0B77E57400AEC16F /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53EC0AC09A6400622F72 /* fweelin_videoio.cc */; name = "fweelin_videoio.cc: 2327"; rLen = 0; rLoc = 62264; rType = 0; vrLen = 806; vrLoc = 61776; }; AC19AECE0B77E57400AEC16F /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53E20AC09A6400622F72 /* fweelin_event.h */; name = "fweelin_event.h: 2195"; rLen = 0; rLoc = 60995; rType = 0; vrLen = 996; vrLoc = 60658; }; AC2080220B6EDC4A002A78E8 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC2080230B6EDC4A002A78E8 /* ringbuffer.h */; name = "(null): 46"; rLen = 0; rLoc = 1624; rType = 0; vrLen = 991; vrLoc = 6560; }; AC2080230B6EDC4A002A78E8 /* ringbuffer.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ringbuffer.h; path = /Library/Frameworks/Jack.framework/Versions/A/Headers/ringbuffer.h; sourceTree = ""; }; AC2080240B6EDC4A002A78E8 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC2080250B6EDC4A002A78E8 /* ringbuffer.h */; name = "(null): 94"; rLen = 0; rLoc = 3648; rType = 0; vrLen = 1105; vrLoc = 0; }; AC2080250B6EDC4A002A78E8 /* ringbuffer.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ringbuffer.h; path = /Users/mercury/Desktop/portaudio/src/hostapi/coreaudio/ringbuffer.h; sourceTree = ""; }; AC2080280B6EDC4A002A78E8 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC2080290B6EDC4A002A78E8 /* ringbuffer.h */; name = "(null): 46"; rLen = 0; rLoc = 1624; rType = 0; vrLen = 991; vrLoc = 6560; }; AC2080290B6EDC4A002A78E8 /* ringbuffer.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ringbuffer.h; path = /Library/Frameworks/Jack.framework/Versions/A/Headers/ringbuffer.h; sourceTree = ""; }; AC20802A0B6EDC4A002A78E8 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC20802B0B6EDC4A002A78E8 /* ringbuffer.h */; name = "(null): 94"; rLen = 0; rLoc = 3648; rType = 0; vrLen = 1105; vrLoc = 0; }; AC20802B0B6EDC4A002A78E8 /* ringbuffer.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ringbuffer.h; path = /Users/mercury/Desktop/portaudio/src/hostapi/coreaudio/ringbuffer.h; sourceTree = ""; }; AC20802E0B6F09C5002A78E8 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53D40AC09A6400622F72 /* fweelin_audioio.h */; name = "fweelin_audioio.h: 3"; rLen = 0; rLoc = 56; rType = 0; vrLen = 563; vrLoc = 0; }; AC2AECD60B6AD6CE00AFA3A9 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 8D1107310486CEB800E47090 /* Info.plist */; name = "Info.plist: 13"; rLen = 0; rLoc = 480; rType = 0; vrLen = 861; vrLoc = 0; }; AC2AECD90B6AD6CE00AFA3A9 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53DA0AC09A6400622F72 /* fweelin_config.h */; name = "fweelin_config.h: EventBinding"; rLen = 0; rLoc = 4861; rType = 0; vrLen = 969; vrLoc = 5751; }; AC2AECDA0B6AD6CE00AFA3A9 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53EC0AC09A6400622F72 /* fweelin_videoio.cc */; name = "fweelin_videoio.cc: 1828"; rLen = 0; rLoc = 48261; rType = 0; vrLen = 885; vrLoc = 47997; }; AC5A53070AC098E000622F72 /* fweelin */ = { isa = PBXExecutable; activeArgIndex = 2147483647; activeArgIndices = ( ); argumentStrings = ( ); autoAttachOnCrash = 1; configStateDict = { }; customDataFormattersEnabled = 1; debuggerPlugin = GDBDebugging; disassemblyDisplayState = 0; dylibVariantSuffix = ""; enableDebugStr = 1; environmentEntries = ( ); executableSystemSymbolLevel = 0; executableUserSymbolLevel = 0; libgmallocEnabled = 0; name = fweelin; savedGlobals = { }; sourceDirectories = ( ); variableFormatDictionary = { }; }; AC5A53150AC098E400622F72 /* Source Control */ = { isa = PBXSourceControlManager; fallbackIsa = XCSourceControlManager; isSCMEnabled = 0; scmConfiguration = { }; scmType = ""; }; AC5A53160AC098E400622F72 /* Code sense */ = { isa = PBXCodeSenseManager; indexTemplatePath = ""; }; AC5A531F0AC0998E00622F72 /* XCBreakpointsBucket */ = { isa = XCBreakpointsBucket; name = "Project Breakpoints"; objects = ( ); }; AC5A53D30AC09A6400622F72 /* fweelin_audioio.cc */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {631, 4564}}"; sepNavSelRange = "{2864, 32}"; sepNavVisRect = "{{0, 1375}, {631, 417}}"; }; }; AC5A53D40AC09A6400622F72 /* fweelin_audioio.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {631, 1554}}"; sepNavSelRange = "{56, 0}"; sepNavVisRect = "{{0, 0}, {631, 417}}"; sepNavWindowFrame = "{{73, 252}, {950, 600}}"; }; }; AC5A53D50AC09A6400622F72 /* fweelin_block.cc */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {740, 30688}}"; sepNavSelRange = "{266, 0}"; sepNavVisRect = "{{0, 169}, {740, 180}}"; sepNavWindowFrame = "{{326, 119}, {750, 502}}"; }; }; AC5A53D60AC09A6400622F72 /* fweelin_block.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {638, 13706}}"; sepNavSelRange = "{190, 0}"; sepNavVisRect = "{{0, 31}, {631, 417}}"; sepNavWindowFrame = "{{349, 98}, {750, 502}}"; }; }; AC5A53D70AC09A6400622F72 /* fweelin_browser.cc */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {740, 13958}}"; sepNavSelRange = "{11863, 255}"; sepNavVisRect = "{{0, 6147}, {740, 180}}"; }; }; AC5A53D80AC09A6400622F72 /* fweelin_browser.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {631, 7560}}"; sepNavSelRange = "{11587, 0}"; sepNavVisRect = "{{0, 4847}, {631, 417}}"; sepNavWindowFrame = "{{50, 133}, {1131, 740}}"; }; }; AC5A53D90AC09A6400622F72 /* fweelin_config.cc */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {631, 42742}}"; sepNavSelRange = "{74954, 0}"; sepNavVisRect = "{{0, 40693}, {631, 417}}"; sepNavWindowFrame = "{{96, 231}, {950, 600}}"; }; }; AC5A53DA0AC09A6400622F72 /* fweelin_config.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {632, 13230}}"; sepNavSelRange = "{4861, 0}"; sepNavVisRect = "{{0, 2902}, {631, 417}}"; sepNavWindowFrame = "{{73, 252}, {950, 600}}"; }; }; AC5A53DB0AC09A6400622F72 /* fweelin_core_dsp.cc */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {680, 33222}}"; sepNavSelRange = "{11396, 0}"; sepNavVisRect = "{{0, 5530}, {631, 417}}"; sepNavWindowFrame = "{{165, 168}, {950, 600}}"; }; }; AC5A53DC0AC09A6400622F72 /* fweelin_core_dsp.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {631, 11186}}"; sepNavSelRange = "{8873, 0}"; sepNavVisRect = "{{0, 4095}, {631, 417}}"; sepNavWindowFrame = "{{142, 189}, {950, 600}}"; }; }; AC5A53DD0AC09A6400622F72 /* fweelin_core.cc */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {821, 45318}}"; sepNavSelRange = "{27861, 7}"; sepNavVisRect = "{{0, 12125}, {821, 321}}"; sepNavWindowFrame = "{{96, 329}, {750, 502}}"; }; }; AC5A53DE0AC09A6400622F72 /* fweelin_core.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {631, 13384}}"; sepNavSelRange = "{13013, 0}"; sepNavVisRect = "{{0, 6799}, {631, 417}}"; sepNavWindowFrame = "{{73, 350}, {750, 502}}"; }; }; AC5A53DF0AC09A6400622F72 /* fweelin_datatypes.cc */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {631, 518}}"; sepNavSelRange = "{0, 0}"; sepNavVisRect = "{{0, 0}, {631, 417}}"; }; }; AC5A53E00AC09A6400622F72 /* fweelin_datatypes.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {911, 7028}}"; sepNavSelRange = "{2136, 0}"; sepNavVisRect = "{{0, 955}, {911, 471}}"; sepNavWindowFrame = "{{414, 40}, {950, 600}}"; }; }; AC5A53E10AC09A6400622F72 /* fweelin_event.cc */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {631, 5418}}"; sepNavSelRange = "{11071, 0}"; sepNavVisRect = "{{0, 1431}, {631, 417}}"; }; }; AC5A53E20AC09A6400622F72 /* fweelin_event.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {848, 32620}}"; sepNavSelRange = "{60995, 0}"; sepNavVisRect = "{{0, 30576}, {631, 417}}"; sepNavWindowFrame = "{{50, 273}, {950, 600}}"; }; }; AC5A53E30AC09A6400622F72 /* fweelin_fluidsynth.cc */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {631, 3080}}"; sepNavSelRange = "{808, 0}"; sepNavVisRect = "{{0, 199}, {631, 417}}"; }; }; AC5A53E40AC09A6400622F72 /* fweelin_fluidsynth.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {631, 896}}"; sepNavSelRange = "{0, 0}"; sepNavVisRect = "{{0, 0}, {631, 417}}"; }; }; AC5A53E50AC09A6400622F72 /* fweelin_logo.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {730, 17430}}"; sepNavSelRange = "{266, 0}"; sepNavVisRect = "{{0, 0}, {730, 610}}"; }; }; AC5A53E60AC09A6400622F72 /* fweelin_mem.cc */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {631, 8820}}"; sepNavSelRange = "{3783, 0}"; sepNavVisRect = "{{0, 1965}, {631, 417}}"; sepNavWindowFrame = "{{119, 210}, {950, 600}}"; }; }; AC5A53E70AC09A6400622F72 /* fweelin_mem.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {911, 3220}}"; sepNavSelRange = "{210, 56}"; sepNavVisRect = "{{0, 0}, {911, 471}}"; sepNavWindowFrame = "{{96, 231}, {950, 600}}"; }; }; AC5A53E80AC09A6400622F72 /* fweelin_midiio.cc */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {884, 14364}}"; sepNavSelRange = "{26017, 0}"; sepNavVisRect = "{{0, 12359}, {631, 417}}"; sepNavWindowFrame = "{{257, 182}, {750, 502}}"; }; }; AC5A53E90AC09A6400622F72 /* fweelin_midiio.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {631, 2366}}"; sepNavSelRange = "{310, 0}"; sepNavVisRect = "{{0, 0}, {631, 417}}"; sepNavWindowFrame = "{{234, 203}, {750, 502}}"; }; }; AC5A53EA0AC09A6400622F72 /* fweelin_sdlio.cc */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {631, 10374}}"; sepNavSelRange = "{5696, 0}"; sepNavVisRect = "{{0, 5603}, {631, 417}}"; sepNavWindowFrame = "{{280, 161}, {750, 502}}"; }; }; AC5A53EB0AC09A6400622F72 /* fweelin_sdlio.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {631, 1484}}"; sepNavSelRange = "{1757, 0}"; sepNavVisRect = "{{0, 947}, {631, 417}}"; }; }; AC5A53EC0AC09A6400622F72 /* fweelin_videoio.cc */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {631, 34174}}"; sepNavSelRange = "{62264, 0}"; sepNavVisRect = "{{0, 32307}, {631, 417}}"; sepNavWindowFrame = "{{303, 140}, {750, 502}}"; }; }; AC5A53ED0AC09A6400622F72 /* fweelin_videoio.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {631, 2366}}"; sepNavSelRange = "{1931, 0}"; sepNavVisRect = "{{0, 1552}, {631, 417}}"; sepNavWindowFrame = "{{50, 371}, {750, 502}}"; }; }; AC5A53EE0AC09A6400622F72 /* fweelin.cc */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {631, 868}}"; sepNavSelRange = "{621, 0}"; sepNavVisRect = "{{0, 437}, {631, 417}}"; sepNavWindowFrame = "{{142, 49}, {1131, 740}}"; }; }; AC5A54D30AC0EA0200622F72 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53D40AC09A6400622F72 /* fweelin_audioio.h */; name = "fweelin_audioio.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 452; vrLoc = 0; }; AC5A54E90AC0EA8500622F72 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53D30AC09A6400622F72 /* fweelin_audioio.cc */; name = "fweelin_audioio.cc: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 388; vrLoc = 0; }; AC5A54EA0AC0EA8500622F72 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53EE0AC09A6400622F72 /* fweelin.cc */; name = "fweelin.cc: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 195; vrLoc = 0; }; AC5A54EB0AC0EA8500622F72 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53EB0AC09A6400622F72 /* fweelin_sdlio.h */; name = "fweelin_sdlio.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 427; vrLoc = 0; }; AC5A54EC0AC0EA8500622F72 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53EC0AC09A6400622F72 /* fweelin_videoio.cc */; name = "fweelin_videoio.cc: 3"; rLen = 0; rLoc = 31; rType = 0; vrLen = 374; vrLoc = 0; }; AC5A55D80AC2198F00622F72 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53E90AC09A6400622F72 /* fweelin_midiio.h */; name = "fweelin_midiio.h: 59"; rLen = 0; rLoc = 2747; rType = 0; vrLen = 654; vrLoc = 1266; }; AC5A55D90AC2198F00622F72 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53D90AC09A6400622F72 /* fweelin_config.cc */; name = "fweelin_config.cc: 2754"; rLen = 0; rLoc = 73093; rType = 0; vrLen = 499; vrLoc = 71055; }; AC5A56880AC2419A00622F72 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53E50AC09A6400622F72 /* fweelin_logo.h */; name = "fweelin_logo.h: 10"; rLen = 0; rLoc = 266; rType = 0; vrLen = 2955; vrLoc = 0; }; AC5A568E0AC2419A00622F72 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53E80AC09A6400622F72 /* fweelin_midiio.cc */; name = "fweelin_midiio.cc: 316"; rLen = 0; rLoc = 18290; rType = 0; vrLen = 1455; vrLoc = 7840; }; AC5A56900AC2419A00622F72 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53DA0AC09A6400622F72 /* fweelin_config.h */; name = "fweelin_config.h: 37"; rLen = 0; rLoc = 1544; rType = 0; vrLen = 1393; vrLoc = 0; }; AC5A56980AC2419A00622F72 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53DE0AC09A6400622F72 /* fweelin_core.h */; name = "fweelin_core.h: 17"; rLen = 0; rLoc = 279; rType = 0; vrLen = 827; vrLoc = 0; }; AC5A569A0AC2419A00622F72 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53DF0AC09A6400622F72 /* fweelin_datatypes.cc */; name = "fweelin_datatypes.cc: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 649; vrLoc = 0; }; AC5A569C0AC2419A00622F72 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53E00AC09A6400622F72 /* fweelin_datatypes.h */; name = "fweelin_datatypes.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 938; vrLoc = 0; }; AC5A569D0AC2419A00622F72 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53E20AC09A6400622F72 /* fweelin_event.h */; name = "fweelin_event.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 993; vrLoc = 0; }; AC5A569E0AC2419A00622F72 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53E50AC09A6400622F72 /* fweelin_logo.h */; name = "fweelin_logo.h: 10"; rLen = 0; rLoc = 266; rType = 0; vrLen = 2955; vrLoc = 0; }; AC5A56FE0AC2448600622F72 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53DD0AC09A6400622F72 /* fweelin_core.cc */; name = "fweelin_core.cc: 9"; rLen = 0; rLoc = 156; rType = 0; vrLen = 975; vrLoc = 0; }; AC5A57660AC250C200622F72 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53EA0AC09A6400622F72 /* fweelin_sdlio.cc */; name = "fweelin_sdlio.cc: 413"; rLen = 0; rLoc = 5878; rType = 0; vrLen = 1018; vrLoc = 5128; }; AC6427D80AD883FA00752A08 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53EE0AC09A6400622F72 /* fweelin.cc */; name = "fweelin.cc: 49"; rLen = 0; rLoc = 621; rType = 0; vrLen = 543; vrLoc = 313; }; AC6427E70AD884EE00752A08 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53EA0AC09A6400622F72 /* fweelin_sdlio.cc */; name = "fweelin_sdlio.cc: 417"; rLen = 0; rLoc = 5696; rType = 0; vrLen = 741; vrLoc = 5260; }; AC642A1E0ADB317200752A08 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53D50AC09A6400622F72 /* fweelin_block.cc */; name = sndfile; rLen = 0; rLoc = 266; rType = 0; vrLen = 585; vrLoc = 0; }; AC642A270ADB317200752A08 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53D60AC09A6400622F72 /* fweelin_block.h */; name = "#include "; rLen = 0; rLoc = 190; rType = 0; vrLen = 601; vrLoc = 0; }; AC642A280ADB317200752A08 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53DB0AC09A6400622F72 /* fweelin_core_dsp.cc */; name = "fweelin_core_dsp.cc: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 640; vrLoc = 0; }; AC776D5F0B69B290005E3D84 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 089C165DFE840E0CC02AAC07 /* English */; name = "English: 5"; rLen = 0; rLoc = 176; rType = 0; vrLen = 131; vrLoc = 0; }; AC776D600B69B290005E3D84 /* PBXBookmark */ = { isa = PBXBookmark; fRef = AC776D460B69B161005E3D84 /* freewheeling.icns */; }; AC776D620B69B290005E3D84 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 8D1107310486CEB800E47090 /* Info.plist */; name = "Info.plist: 8"; rLen = 0; rLoc = 288; rType = 0; vrLen = 860; vrLoc = 0; }; AC776D640B69B290005E3D84 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 089C165DFE840E0CC02AAC07 /* English */; name = "English: 5"; rLen = 0; rLoc = 176; rType = 0; vrLen = 131; vrLoc = 0; }; AC776D650B69B290005E3D84 /* PBXBookmark */ = { isa = PBXBookmark; fRef = AC776D460B69B161005E3D84 /* freewheeling.icns */; }; ACA2C5CB0B06E03E00E02DC6 /* xmlmemory.h */ = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = xmlmemory.h; path = /Developer/SDKs/MacOSX10.4u.sdk/usr/include/libxml2/libxml/xmlmemory.h; sourceTree = ""; }; ACA2C5D60B06E0F700E02DC6 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = ACA2C5CB0B06E03E00E02DC6 /* xmlmemory.h */; name = "#include "; rLen = 31; rLoc = 339; rType = 0; vrLen = 728; vrLoc = 0; }; ACA2C5D90B06E0F700E02DC6 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = ACA2C5CB0B06E03E00E02DC6 /* xmlmemory.h */; name = "#include "; rLen = 31; rLoc = 339; rType = 0; vrLen = 728; vrLoc = 0; }; ACA2C6CD0B06EC6700E02DC6 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53ED0AC09A6400622F72 /* fweelin_videoio.h */; name = "fweelin_videoio.h: close"; rLen = 0; rLoc = 1931; rType = 0; vrLen = 766; vrLoc = 3092; }; ACA2C7B60B07C73900E02DC6 /* patches-channels.xml */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {631, 417}}"; sepNavSelRange = "{74, 0}"; sepNavVisRect = "{{0, 0}, {631, 417}}"; }; }; ACA2C7CF0B07C82F00E02DC6 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53D60AC09A6400622F72 /* fweelin_block.h */; name = "fweelin_block.h: 10"; rLen = 0; rLoc = 190; rType = 0; vrLen = 565; vrLoc = 52; }; ACA2C81F0B0830F900E02DC6 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53D70AC09A6400622F72 /* fweelin_browser.cc */; name = GetEvent; rLen = 8; rLoc = 11938; rType = 0; vrLen = 809; vrLoc = 11494; }; ACA2CB8A0B0AC86600E02DC6 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = ACFC0A990AC99CDF00DAC478 /* FweelinMac.h */; name = "FweelinMac.h: 27"; rLen = 0; rLoc = 605; rType = 0; vrLen = 803; vrLoc = 32; }; ACA2CB8C0B0AC86600E02DC6 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = ACFC0A9A0AC99CDF00DAC478 /* FweelinMac.mm */; name = "FweelinMac.mm: 56"; rLen = 0; rLoc = 1257; rType = 0; vrLen = 801; vrLoc = 872; }; ACA2CB8D0B0AC86600E02DC6 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 002F3A2B09D0888800EBEB88 /* SDLMain.h */; name = "SDLMain.h: clearMIDIInputList"; rLen = 0; rLoc = 486; rType = 0; vrLen = 565; vrLoc = 0; }; ACA2CB9E0B0AC89600E02DC6 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = 002F3A2C09D0888800EBEB88 /* SDLMain.mm */; name = w; rLen = 1; rLoc = 2643; rType = 0; vrLen = 475; vrLoc = 2423; }; ACA2CE0D0B10369800E02DC6 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = ACA2C7B60B07C73900E02DC6 /* patches-channels.xml */; name = "patches-channels.xml: 3"; rLen = 0; rLoc = 74; rType = 0; vrLen = 886; vrLoc = 0; }; ACA2CE0E0B10369800E02DC6 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = ACA2C7B60B07C73900E02DC6 /* patches-channels.xml */; name = "patches-channels.xml: 3"; rLen = 0; rLoc = 74; rType = 0; vrLen = 886; vrLoc = 0; }; ACABFD0E0B6178C500CA3C21 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53E40AC09A6400622F72 /* fweelin_fluidsynth.h */; name = "fweelin_fluidsynth.h: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 775; vrLoc = 0; }; ACABFDBC0B61895200CA3C21 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53D30AC09A6400622F72 /* fweelin_audioio.cc */; name = "app->getLOOPMGR()->GetCurPulse()"; rLen = 32; rLoc = 2864; rType = 0; vrLen = 1029; vrLoc = 2576; }; ACABFDF70B61D7DB00CA3C21 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53DF0AC09A6400622F72 /* fweelin_datatypes.cc */; name = "fweelin_datatypes.cc: 1"; rLen = 0; rLoc = 0; rType = 0; vrLen = 561; vrLoc = 0; }; ACABFE190B61E19100CA3C21 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53DE0AC09A6400622F72 /* fweelin_core.h */; name = "fweelin_core.h: 501"; rLen = 0; rLoc = 13013; rType = 0; vrLen = 882; vrLoc = 12575; }; ACABFE3E0B61E39100CA3C21 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53DC0AC09A6400622F72 /* fweelin_core_dsp.h */; name = "fweelin_core_dsp.h: SetMIDIClock"; rLen = 0; rLoc = 8873; rType = 0; vrLen = 1016; vrLoc = 8605; }; ACBF6FE70B72C07D004A69E7 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53E20AC09A6400622F72 /* fweelin_event.h */; name = "fweelin_event.h: 13"; rLen = 0; rLoc = 154; rType = 0; vrLen = 556; vrLoc = 0; }; ACBF6FE80B72C07D004A69E7 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53E20AC09A6400622F72 /* fweelin_event.h */; name = "fweelin_event.h: 13"; rLen = 0; rLoc = 154; rType = 0; vrLen = 556; vrLoc = 0; }; ACBF6FEF0B7326D6004A69E7 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53D90AC09A6400622F72 /* fweelin_config.cc */; name = "fweelin_config.cc: 2910"; rLen = 0; rLoc = 74954; rType = 0; vrLen = 902; vrLoc = 74829; }; ACBF6FF00B7326D6004A69E7 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53E10AC09A6400622F72 /* fweelin_event.cc */; name = "fweelin_event.cc: 310"; rLen = 0; rLoc = 11071; rType = 0; vrLen = 1199; vrLoc = 2596; }; ACBF6FF10B7326D6004A69E7 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53D90AC09A6400622F72 /* fweelin_config.cc */; name = "fweelin_config.cc: 2910"; rLen = 0; rLoc = 74954; rType = 0; vrLen = 902; vrLoc = 74829; }; ACBF6FF20B7326D6004A69E7 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53E10AC09A6400622F72 /* fweelin_event.cc */; name = "fweelin_event.cc: 310"; rLen = 0; rLoc = 11071; rType = 0; vrLen = 1199; vrLoc = 2596; }; ACBF6FF30B7326D6004A69E7 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53E20AC09A6400622F72 /* fweelin_event.h */; name = "fweelin_event.h: 13"; rLen = 0; rLoc = 154; rType = 0; vrLen = 556; vrLoc = 0; }; ACE0E72E0AC9CF47007E3ED2 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53D50AC09A6400622F72 /* fweelin_block.cc */; name = "fweelin_block.cc: 5"; rLen = 0; rLoc = 62; rType = 0; vrLen = 884; vrLoc = 0; }; ACE0E94B0ACA196D007E3ED2 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53E10AC09A6400622F72 /* fweelin_event.cc */; name = "fweelin_event.cc: 34"; rLen = 0; rLoc = 513; rType = 0; vrLen = 1168; vrLoc = 2155; }; ACE0E9A30ACA1CC1007E3ED2 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53EB0AC09A6400622F72 /* fweelin_sdlio.h */; name = "fweelin_sdlio.h: 80"; rLen = 0; rLoc = 1751; rType = 0; vrLen = 710; vrLoc = 1415; }; ACF227730B6826DC005CFC14 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53E30AC09A6400622F72 /* fweelin_fluidsynth.cc */; name = "fweelin_fluidsynth.cc: 30"; rLen = 0; rLoc = 808; rType = 0; vrLen = 1161; vrLoc = 201; }; ACF227B50B682D68005CFC14 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53DD0AC09A6400622F72 /* fweelin_core.cc */; name = "fweelin_core.cc: 2474"; rLen = 0; rLoc = 73066; rType = 0; vrLen = 725; vrLoc = 72581; }; ACF227B70B682D68005CFC14 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53D80AC09A6400622F72 /* fweelin_browser.h */; name = "fweelin_browser.h: 389"; rLen = 0; rLoc = 11587; rType = 0; vrLen = 998; vrLoc = 10225; }; ACF227EF0B689BAA005CFC14 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53E80AC09A6400622F72 /* fweelin_midiio.cc */; name = "fweelin_midiio.cc: 897"; rLen = 0; rLoc = 25753; rType = 0; vrLen = 890; vrLoc = 25697; }; ACF227F10B689BAA005CFC14 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53E90AC09A6400622F72 /* fweelin_midiio.h */; name = "fweelin_midiio.h: MIDI_CLOCK_FREQUENCY"; rLen = 0; rLoc = 310; rType = 0; vrLen = 645; vrLoc = 0; }; ACF227F20B689BAA005CFC14 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53DB0AC09A6400622F72 /* fweelin_core_dsp.cc */; name = "fweelin_core_dsp.cc: 399"; rLen = 0; rLoc = 11396; rType = 0; vrLen = 1162; vrLoc = 11269; }; ACF2F7A10B4C70B2005197BB /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC126C3E0AC8EED400FE916E /* .fweelin.rc */; name = ".fweelin.rc: 2635"; rLen = 0; rLoc = 104754; rType = 0; vrLen = 1528; vrLoc = 45506; }; ACFC0A990AC99CDF00DAC478 /* FweelinMac.h */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {631, 504}}"; sepNavSelRange = "{605, 0}"; sepNavVisRect = "{{0, 42}, {631, 417}}"; sepNavWindowFrame = "{{50, 133}, {1131, 740}}"; }; }; ACFC0A9A0AC99CDF00DAC478 /* FweelinMac.mm */ = { uiCtxt = { sepNavIntBoundsRect = "{{0, 0}, {1166, 980}}"; sepNavSelRange = "{902, 0}"; sepNavVisRect = "{{0, 498}, {1166, 279}}"; sepNavWindowFrame = "{{73, 112}, {1131, 740}}"; }; }; ACFC0AB00AC99E2E00DAC478 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = ACFC0A990AC99CDF00DAC478 /* FweelinMac.h */; name = "FweelinMac.h: 9"; rLen = 0; rLoc = 163; rType = 0; vrLen = 105; vrLoc = 0; }; ACFC0AB10AC99E2E00DAC478 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = ACFC0A9A0AC99CDF00DAC478 /* FweelinMac.mm */; name = "FweelinMac.mm: 8"; rLen = 0; rLoc = 1307; rType = 0; vrLen = 61; vrLoc = 0; }; ACFC0B910AC9A70300DAC478 /* PBXTextBookmark */ = { isa = PBXTextBookmark; fRef = AC5A53DC0AC09A6400622F72 /* fweelin_core_dsp.h */; name = "fweelin_core_dsp.h: 25"; rLen = 0; rLoc = 603; rType = 0; vrLen = 1315; vrLoc = 0; }; } fweelin-0.6/MacOSX/fweelin.xcodeproj/project.pbxproj0000644000175000017500000011460511071520617021250 0ustar mercmerc// !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 42; objects = { /* Begin PBXBuildFile section */ 002F39FA09D0881F00EBEB88 /* SDL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 002F39F909D0881F00EBEB88 /* SDL.framework */; }; 002F3A0009D0884600EBEB88 /* SDL.framework in Copy Frameworks into .app bundle */ = {isa = PBXBuildFile; fileRef = 002F39F909D0881F00EBEB88 /* SDL.framework */; }; 002F3A2E09D0888800EBEB88 /* SDLMain.mm in Sources */ = {isa = PBXBuildFile; fileRef = 002F3A2C09D0888800EBEB88 /* SDLMain.mm */; }; 3D8261B70E96C8B600B480B6 /* Jackmp.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3D8261B60E96C8B600B480B6 /* Jackmp.framework */; }; 3D82625C0E96CDC700B480B6 /* fweelin.xml in Resources */ = {isa = PBXBuildFile; fileRef = 3D8262480E96CDC700B480B6 /* fweelin.xml */; }; 3D82625D0E96CDC700B480B6 /* coreinterface.xml in Resources */ = {isa = PBXBuildFile; fileRef = 3D8262490E96CDC700B480B6 /* coreinterface.xml */; }; 3D82625E0E96CDC700B480B6 /* interfaces.xml in Resources */ = {isa = PBXBuildFile; fileRef = 3D82624A0E96CDC700B480B6 /* interfaces.xml */; }; 3D82625F0E96CDC700B480B6 /* patches2.xml in Resources */ = {isa = PBXBuildFile; fileRef = 3D82624B0E96CDC700B480B6 /* patches2.xml */; }; 3D8262600E96CDC700B480B6 /* pcr-m1.xml in Resources */ = {isa = PBXBuildFile; fileRef = 3D82624C0E96CDC700B480B6 /* pcr-m1.xml */; }; 3D8262610E96CDC700B480B6 /* pckeyboard.xml in Resources */ = {isa = PBXBuildFile; fileRef = 3D82624D0E96CDC700B480B6 /* pckeyboard.xml */; }; 3D8262620E96CDC700B480B6 /* patches-strings.xml in Resources */ = {isa = PBXBuildFile; fileRef = 3D82624E0E96CDC700B480B6 /* patches-strings.xml */; }; 3D8262630E96CDC700B480B6 /* mercury.xml in Resources */ = {isa = PBXBuildFile; fileRef = 3D82624F0E96CDC700B480B6 /* mercury.xml */; }; 3D8262640E96CDC700B480B6 /* bcf2000.xml in Resources */ = {isa = PBXBuildFile; fileRef = 3D8262500E96CDC700B480B6 /* bcf2000.xml */; }; 3D8262650E96CDC700B480B6 /* midifootswitch.xml in Resources */ = {isa = PBXBuildFile; fileRef = 3D8262510E96CDC700B480B6 /* midifootswitch.xml */; }; 3D8262660E96CDC700B480B6 /* dancemat.xml in Resources */ = {isa = PBXBuildFile; fileRef = 3D8262520E96CDC700B480B6 /* dancemat.xml */; }; 3D8262670E96CDC700B480B6 /* graphics.xml in Resources */ = {isa = PBXBuildFile; fileRef = 3D8262530E96CDC700B480B6 /* graphics.xml */; }; 3D8262680E96CDC700B480B6 /* patches-channels.xml in Resources */ = {isa = PBXBuildFile; fileRef = 3D8262540E96CDC700B480B6 /* patches-channels.xml */; }; 3D8262690E96CDC700B480B6 /* basics.xml in Resources */ = {isa = PBXBuildFile; fileRef = 3D8262550E96CDC700B480B6 /* basics.xml */; }; 3D82626A0E96CDC700B480B6 /* browsers.xml in Resources */ = {isa = PBXBuildFile; fileRef = 3D8262560E96CDC700B480B6 /* browsers.xml */; }; 3D82626B0E96CDC700B480B6 /* midikeyboard.xml in Resources */ = {isa = PBXBuildFile; fileRef = 3D8262570E96CDC700B480B6 /* midikeyboard.xml */; }; 3D82626C0E96CDC700B480B6 /* patches1.xml in Resources */ = {isa = PBXBuildFile; fileRef = 3D8262580E96CDC700B480B6 /* patches1.xml */; }; 3D82626D0E96CDC700B480B6 /* bindings.xml in Resources */ = {isa = PBXBuildFile; fileRef = 3D8262590E96CDC700B480B6 /* bindings.xml */; }; 3D82626E0E96CDC700B480B6 /* patches-b3.xml in Resources */ = {isa = PBXBuildFile; fileRef = 3D82625A0E96CDC700B480B6 /* patches-b3.xml */; }; 3D82626F0E96CDC700B480B6 /* patches3.xml in Resources */ = {isa = PBXBuildFile; fileRef = 3D82625B0E96CDC700B480B6 /* patches3.xml */; }; 8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */; }; 8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; }; AC12675D0AC8E0BE00FE916E /* CoreMIDI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AC12675C0AC8E0BE00FE916E /* CoreMIDI.framework */; }; AC126C440AC8EF4000FE916E /* verabd.ttf in Resources */ = {isa = PBXBuildFile; fileRef = AC126C420AC8EF4000FE916E /* verabd.ttf */; }; AC126C450AC8EF4000FE916E /* vera.ttf in Resources */ = {isa = PBXBuildFile; fileRef = AC126C430AC8EF4000FE916E /* vera.ttf */; }; AC5A532A0AC099C900622F72 /* Ogg.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AC5A53240AC099C900622F72 /* Ogg.framework */; }; AC5A532B0AC099C900622F72 /* SDL_gfx.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AC5A53250AC099C900622F72 /* SDL_gfx.framework */; }; AC5A532C0AC099C900622F72 /* SDL_ttf.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AC5A53260AC099C900622F72 /* SDL_ttf.framework */; }; AC5A532D0AC099C900622F72 /* Vorbis.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AC5A53270AC099C900622F72 /* Vorbis.framework */; }; AC5A53EF0AC09A6400622F72 /* fweelin_audioio.cc in Sources */ = {isa = PBXBuildFile; fileRef = AC5A53D30AC09A6400622F72 /* fweelin_audioio.cc */; }; AC5A53F10AC09A6400622F72 /* fweelin_block.cc in Sources */ = {isa = PBXBuildFile; fileRef = AC5A53D50AC09A6400622F72 /* fweelin_block.cc */; }; AC5A53F30AC09A6400622F72 /* fweelin_browser.cc in Sources */ = {isa = PBXBuildFile; fileRef = AC5A53D70AC09A6400622F72 /* fweelin_browser.cc */; }; AC5A53F50AC09A6400622F72 /* fweelin_config.cc in Sources */ = {isa = PBXBuildFile; fileRef = AC5A53D90AC09A6400622F72 /* fweelin_config.cc */; }; AC5A53F70AC09A6400622F72 /* fweelin_core_dsp.cc in Sources */ = {isa = PBXBuildFile; fileRef = AC5A53DB0AC09A6400622F72 /* fweelin_core_dsp.cc */; }; AC5A53F90AC09A6400622F72 /* fweelin_core.cc in Sources */ = {isa = PBXBuildFile; fileRef = AC5A53DD0AC09A6400622F72 /* fweelin_core.cc */; }; AC5A53FB0AC09A6400622F72 /* fweelin_datatypes.cc in Sources */ = {isa = PBXBuildFile; fileRef = AC5A53DF0AC09A6400622F72 /* fweelin_datatypes.cc */; }; AC5A53FD0AC09A6400622F72 /* fweelin_event.cc in Sources */ = {isa = PBXBuildFile; fileRef = AC5A53E10AC09A6400622F72 /* fweelin_event.cc */; }; AC5A53FF0AC09A6400622F72 /* fweelin_fluidsynth.cc in Sources */ = {isa = PBXBuildFile; fileRef = AC5A53E30AC09A6400622F72 /* fweelin_fluidsynth.cc */; }; AC5A54020AC09A6400622F72 /* fweelin_mem.cc in Sources */ = {isa = PBXBuildFile; fileRef = AC5A53E60AC09A6400622F72 /* fweelin_mem.cc */; }; AC5A54040AC09A6400622F72 /* fweelin_midiio.cc in Sources */ = {isa = PBXBuildFile; fileRef = AC5A53E80AC09A6400622F72 /* fweelin_midiio.cc */; }; AC5A54060AC09A6400622F72 /* fweelin_sdlio.cc in Sources */ = {isa = PBXBuildFile; fileRef = AC5A53EA0AC09A6400622F72 /* fweelin_sdlio.cc */; }; AC5A54080AC09A6400622F72 /* fweelin_videoio.cc in Sources */ = {isa = PBXBuildFile; fileRef = AC5A53EC0AC09A6400622F72 /* fweelin_videoio.cc */; }; AC5A540A0AC09A6400622F72 /* fweelin.cc in Sources */ = {isa = PBXBuildFile; fileRef = AC5A53EE0AC09A6400622F72 /* fweelin.cc */; }; AC6429D90AD9C85700752A08 /* Sndfile.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AC6429D80AD9C85700752A08 /* Sndfile.framework */; }; AC6429DC0AD9C85C00752A08 /* Sndfile.framework in Copy Frameworks into .app bundle */ = {isa = PBXBuildFile; fileRef = AC6429D80AD9C85700752A08 /* Sndfile.framework */; }; AC776D470B69B161005E3D84 /* freewheeling.icns in Resources */ = {isa = PBXBuildFile; fileRef = AC776D460B69B161005E3D84 /* freewheeling.icns */; }; ACA2C53F0B06DCB600E02DC6 /* SDLMain.nib in Resources */ = {isa = PBXBuildFile; fileRef = ACA2C53E0B06DCB600E02DC6 /* SDLMain.nib */; }; ACE0E9170ACA15B4007E3ED2 /* Ogg.framework in Copy Frameworks into .app bundle */ = {isa = PBXBuildFile; fileRef = AC5A53240AC099C900622F72 /* Ogg.framework */; }; ACE0E9180ACA15B4007E3ED2 /* SDL_gfx.framework in Copy Frameworks into .app bundle */ = {isa = PBXBuildFile; fileRef = AC5A53250AC099C900622F72 /* SDL_gfx.framework */; }; ACE0E9190ACA15B4007E3ED2 /* SDL_ttf.framework in Copy Frameworks into .app bundle */ = {isa = PBXBuildFile; fileRef = AC5A53260AC099C900622F72 /* SDL_ttf.framework */; }; ACE0E91A0ACA15B4007E3ED2 /* Vorbis.framework in Copy Frameworks into .app bundle */ = {isa = PBXBuildFile; fileRef = AC5A53270AC099C900622F72 /* Vorbis.framework */; }; ACFC0A9C0AC99CDF00DAC478 /* FweelinMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = ACFC0A9A0AC99CDF00DAC478 /* FweelinMac.mm */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ 002F39FD09D0883400EBEB88 /* Copy Frameworks into .app bundle */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = ""; dstSubfolderSpec = 10; files = ( AC6429DC0AD9C85C00752A08 /* Sndfile.framework in Copy Frameworks into .app bundle */, ACE0E9190ACA15B4007E3ED2 /* SDL_ttf.framework in Copy Frameworks into .app bundle */, ACE0E9180ACA15B4007E3ED2 /* SDL_gfx.framework in Copy Frameworks into .app bundle */, 002F3A0009D0884600EBEB88 /* SDL.framework in Copy Frameworks into .app bundle */, ACE0E9170ACA15B4007E3ED2 /* Ogg.framework in Copy Frameworks into .app bundle */, ACE0E91A0ACA15B4007E3ED2 /* Vorbis.framework in Copy Frameworks into .app bundle */, ); name = "Copy Frameworks into .app bundle"; runOnlyForDeploymentPostprocessing = 0; }; /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ 002F39F909D0881F00EBEB88 /* SDL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SDL.framework; path = /Library/Frameworks/SDL.framework; sourceTree = ""; }; 002F3A2B09D0888800EBEB88 /* SDLMain.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SDLMain.h; sourceTree = SOURCE_ROOT; }; 002F3A2C09D0888800EBEB88 /* SDLMain.mm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.objcpp; path = SDLMain.mm; sourceTree = ""; }; 089C165DFE840E0CC02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = ""; }; 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = ""; }; 29B97324FDCFA39411CA2CEA /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = ""; }; 29B97325FDCFA39411CA2CEA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = ""; }; 32CA4F630368D1EE00C91783 /* fweelin_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fweelin_Prefix.pch; sourceTree = ""; }; 3D8261B60E96C8B600B480B6 /* Jackmp.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Jackmp.framework; path = /Library/Frameworks/Jackmp.framework; sourceTree = ""; }; 3D8262480E96CDC700B480B6 /* fweelin.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = fweelin.xml; path = ../data/fweelin.xml; sourceTree = SOURCE_ROOT; }; 3D8262490E96CDC700B480B6 /* coreinterface.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = coreinterface.xml; path = ../data/coreinterface.xml; sourceTree = SOURCE_ROOT; }; 3D82624A0E96CDC700B480B6 /* interfaces.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = interfaces.xml; path = ../data/interfaces.xml; sourceTree = SOURCE_ROOT; }; 3D82624B0E96CDC700B480B6 /* patches2.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = patches2.xml; path = ../data/patches2.xml; sourceTree = SOURCE_ROOT; }; 3D82624C0E96CDC700B480B6 /* pcr-m1.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = "pcr-m1.xml"; path = "../data/pcr-m1.xml"; sourceTree = SOURCE_ROOT; }; 3D82624D0E96CDC700B480B6 /* pckeyboard.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = pckeyboard.xml; path = ../data/pckeyboard.xml; sourceTree = SOURCE_ROOT; }; 3D82624E0E96CDC700B480B6 /* patches-strings.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = "patches-strings.xml"; path = "../data/patches-strings.xml"; sourceTree = SOURCE_ROOT; }; 3D82624F0E96CDC700B480B6 /* mercury.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = mercury.xml; path = ../data/mercury.xml; sourceTree = SOURCE_ROOT; }; 3D8262500E96CDC700B480B6 /* bcf2000.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = bcf2000.xml; path = ../data/bcf2000.xml; sourceTree = SOURCE_ROOT; }; 3D8262510E96CDC700B480B6 /* midifootswitch.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = midifootswitch.xml; path = ../data/midifootswitch.xml; sourceTree = SOURCE_ROOT; }; 3D8262520E96CDC700B480B6 /* dancemat.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = dancemat.xml; path = ../data/dancemat.xml; sourceTree = SOURCE_ROOT; }; 3D8262530E96CDC700B480B6 /* graphics.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = graphics.xml; path = ../data/graphics.xml; sourceTree = SOURCE_ROOT; }; 3D8262540E96CDC700B480B6 /* patches-channels.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = "patches-channels.xml"; path = "../data/patches-channels.xml"; sourceTree = SOURCE_ROOT; }; 3D8262550E96CDC700B480B6 /* basics.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = basics.xml; path = ../data/basics.xml; sourceTree = SOURCE_ROOT; }; 3D8262560E96CDC700B480B6 /* browsers.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = browsers.xml; path = ../data/browsers.xml; sourceTree = SOURCE_ROOT; }; 3D8262570E96CDC700B480B6 /* midikeyboard.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = midikeyboard.xml; path = ../data/midikeyboard.xml; sourceTree = SOURCE_ROOT; }; 3D8262580E96CDC700B480B6 /* patches1.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = patches1.xml; path = ../data/patches1.xml; sourceTree = SOURCE_ROOT; }; 3D8262590E96CDC700B480B6 /* bindings.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = bindings.xml; path = ../data/bindings.xml; sourceTree = SOURCE_ROOT; }; 3D82625A0E96CDC700B480B6 /* patches-b3.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = "patches-b3.xml"; path = "../data/patches-b3.xml"; sourceTree = SOURCE_ROOT; }; 3D82625B0E96CDC700B480B6 /* patches3.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = patches3.xml; path = ../data/patches3.xml; sourceTree = SOURCE_ROOT; }; 8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; 8D1107320486CEB800E47090 /* fweelin.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = fweelin.app; sourceTree = BUILT_PRODUCTS_DIR; }; AC12675C0AC8E0BE00FE916E /* CoreMIDI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMIDI.framework; path = /System/Library/Frameworks/CoreMIDI.framework; sourceTree = ""; }; AC126C420AC8EF4000FE916E /* verabd.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = verabd.ttf; path = ../data/verabd.ttf; sourceTree = SOURCE_ROOT; }; AC126C430AC8EF4000FE916E /* vera.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = vera.ttf; path = ../data/vera.ttf; sourceTree = SOURCE_ROOT; }; AC5A53240AC099C900622F72 /* Ogg.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Ogg.framework; path = /Library/Frameworks/Ogg.framework; sourceTree = ""; }; AC5A53250AC099C900622F72 /* SDL_gfx.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SDL_gfx.framework; path = /Library/Frameworks/SDL_gfx.framework; sourceTree = ""; }; AC5A53260AC099C900622F72 /* SDL_ttf.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SDL_ttf.framework; path = /Library/Frameworks/SDL_ttf.framework; sourceTree = ""; }; AC5A53270AC099C900622F72 /* Vorbis.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Vorbis.framework; path = /Library/Frameworks/Vorbis.framework; sourceTree = ""; }; AC5A53D30AC09A6400622F72 /* fweelin_audioio.cc */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = fweelin_audioio.cc; path = ../src/fweelin_audioio.cc; sourceTree = SOURCE_ROOT; tabWidth = 8; }; AC5A53D40AC09A6400622F72 /* fweelin_audioio.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = fweelin_audioio.h; path = ../src/fweelin_audioio.h; sourceTree = SOURCE_ROOT; tabWidth = 8; }; AC5A53D50AC09A6400622F72 /* fweelin_block.cc */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = fweelin_block.cc; path = ../src/fweelin_block.cc; sourceTree = SOURCE_ROOT; tabWidth = 8; }; AC5A53D60AC09A6400622F72 /* fweelin_block.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = fweelin_block.h; path = ../src/fweelin_block.h; sourceTree = SOURCE_ROOT; tabWidth = 8; }; AC5A53D70AC09A6400622F72 /* fweelin_browser.cc */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = fweelin_browser.cc; path = ../src/fweelin_browser.cc; sourceTree = SOURCE_ROOT; tabWidth = 8; }; AC5A53D80AC09A6400622F72 /* fweelin_browser.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = fweelin_browser.h; path = ../src/fweelin_browser.h; sourceTree = SOURCE_ROOT; tabWidth = 8; }; AC5A53D90AC09A6400622F72 /* fweelin_config.cc */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = fweelin_config.cc; path = ../src/fweelin_config.cc; sourceTree = SOURCE_ROOT; tabWidth = 8; }; AC5A53DA0AC09A6400622F72 /* fweelin_config.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = fweelin_config.h; path = ../src/fweelin_config.h; sourceTree = SOURCE_ROOT; tabWidth = 8; }; AC5A53DB0AC09A6400622F72 /* fweelin_core_dsp.cc */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = fweelin_core_dsp.cc; path = ../src/fweelin_core_dsp.cc; sourceTree = SOURCE_ROOT; tabWidth = 8; }; AC5A53DC0AC09A6400622F72 /* fweelin_core_dsp.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = fweelin_core_dsp.h; path = ../src/fweelin_core_dsp.h; sourceTree = SOURCE_ROOT; tabWidth = 8; }; AC5A53DD0AC09A6400622F72 /* fweelin_core.cc */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = fweelin_core.cc; path = ../src/fweelin_core.cc; sourceTree = SOURCE_ROOT; tabWidth = 8; }; AC5A53DE0AC09A6400622F72 /* fweelin_core.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = fweelin_core.h; path = ../src/fweelin_core.h; sourceTree = SOURCE_ROOT; tabWidth = 8; }; AC5A53DF0AC09A6400622F72 /* fweelin_datatypes.cc */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = fweelin_datatypes.cc; path = ../src/fweelin_datatypes.cc; sourceTree = SOURCE_ROOT; tabWidth = 8; }; AC5A53E00AC09A6400622F72 /* fweelin_datatypes.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = fweelin_datatypes.h; path = ../src/fweelin_datatypes.h; sourceTree = SOURCE_ROOT; tabWidth = 8; }; AC5A53E10AC09A6400622F72 /* fweelin_event.cc */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = fweelin_event.cc; path = ../src/fweelin_event.cc; sourceTree = SOURCE_ROOT; tabWidth = 8; }; AC5A53E20AC09A6400622F72 /* fweelin_event.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = fweelin_event.h; path = ../src/fweelin_event.h; sourceTree = SOURCE_ROOT; tabWidth = 8; }; AC5A53E30AC09A6400622F72 /* fweelin_fluidsynth.cc */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = fweelin_fluidsynth.cc; path = ../src/fweelin_fluidsynth.cc; sourceTree = SOURCE_ROOT; tabWidth = 8; }; AC5A53E40AC09A6400622F72 /* fweelin_fluidsynth.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = fweelin_fluidsynth.h; path = ../src/fweelin_fluidsynth.h; sourceTree = SOURCE_ROOT; tabWidth = 8; }; AC5A53E50AC09A6400622F72 /* fweelin_logo.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = fweelin_logo.h; path = ../src/fweelin_logo.h; sourceTree = SOURCE_ROOT; tabWidth = 8; }; AC5A53E60AC09A6400622F72 /* fweelin_mem.cc */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = fweelin_mem.cc; path = ../src/fweelin_mem.cc; sourceTree = SOURCE_ROOT; tabWidth = 8; }; AC5A53E70AC09A6400622F72 /* fweelin_mem.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = fweelin_mem.h; path = ../src/fweelin_mem.h; sourceTree = SOURCE_ROOT; tabWidth = 8; }; AC5A53E80AC09A6400622F72 /* fweelin_midiio.cc */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = fweelin_midiio.cc; path = ../src/fweelin_midiio.cc; sourceTree = SOURCE_ROOT; tabWidth = 8; }; AC5A53E90AC09A6400622F72 /* fweelin_midiio.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = fweelin_midiio.h; path = ../src/fweelin_midiio.h; sourceTree = SOURCE_ROOT; tabWidth = 8; }; AC5A53EA0AC09A6400622F72 /* fweelin_sdlio.cc */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = fweelin_sdlio.cc; path = ../src/fweelin_sdlio.cc; sourceTree = SOURCE_ROOT; tabWidth = 8; usesTabs = 1; }; AC5A53EB0AC09A6400622F72 /* fweelin_sdlio.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = fweelin_sdlio.h; path = ../src/fweelin_sdlio.h; sourceTree = SOURCE_ROOT; tabWidth = 8; }; AC5A53EC0AC09A6400622F72 /* fweelin_videoio.cc */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = fweelin_videoio.cc; path = ../src/fweelin_videoio.cc; sourceTree = SOURCE_ROOT; tabWidth = 8; }; AC5A53ED0AC09A6400622F72 /* fweelin_videoio.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = fweelin_videoio.h; path = ../src/fweelin_videoio.h; sourceTree = SOURCE_ROOT; tabWidth = 8; }; AC5A53EE0AC09A6400622F72 /* fweelin.cc */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = fweelin.cc; path = ../src/fweelin.cc; sourceTree = SOURCE_ROOT; tabWidth = 8; }; AC6429D80AD9C85700752A08 /* Sndfile.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Sndfile.framework; path = /Library/Frameworks/Sndfile.framework; sourceTree = ""; }; AC776D460B69B161005E3D84 /* freewheeling.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = freewheeling.icns; sourceTree = ""; }; ACA2C53E0B06DCB600E02DC6 /* SDLMain.nib */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; path = SDLMain.nib; sourceTree = ""; }; ACFC0A990AC99CDF00DAC478 /* FweelinMac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FweelinMac.h; sourceTree = ""; }; ACFC0A9A0AC99CDF00DAC478 /* FweelinMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = FweelinMac.mm; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 8D11072E0486CEB800E47090 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 002F39FA09D0881F00EBEB88 /* SDL.framework in Frameworks */, 8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */, AC5A532A0AC099C900622F72 /* Ogg.framework in Frameworks */, AC5A532B0AC099C900622F72 /* SDL_gfx.framework in Frameworks */, AC5A532C0AC099C900622F72 /* SDL_ttf.framework in Frameworks */, AC5A532D0AC099C900622F72 /* Vorbis.framework in Frameworks */, AC12675D0AC8E0BE00FE916E /* CoreMIDI.framework in Frameworks */, AC6429D90AD9C85700752A08 /* Sndfile.framework in Frameworks */, 3D8261B70E96C8B600B480B6 /* Jackmp.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 080E96DDFE201D6D7F000001 /* Classes */ = { isa = PBXGroup; children = ( AC5A53D30AC09A6400622F72 /* fweelin_audioio.cc */, AC5A53D40AC09A6400622F72 /* fweelin_audioio.h */, AC5A53D50AC09A6400622F72 /* fweelin_block.cc */, AC5A53D60AC09A6400622F72 /* fweelin_block.h */, AC5A53D70AC09A6400622F72 /* fweelin_browser.cc */, AC5A53D80AC09A6400622F72 /* fweelin_browser.h */, AC5A53D90AC09A6400622F72 /* fweelin_config.cc */, AC5A53DA0AC09A6400622F72 /* fweelin_config.h */, AC5A53DB0AC09A6400622F72 /* fweelin_core_dsp.cc */, AC5A53DC0AC09A6400622F72 /* fweelin_core_dsp.h */, AC5A53DD0AC09A6400622F72 /* fweelin_core.cc */, AC5A53DE0AC09A6400622F72 /* fweelin_core.h */, AC5A53DF0AC09A6400622F72 /* fweelin_datatypes.cc */, AC5A53E00AC09A6400622F72 /* fweelin_datatypes.h */, AC5A53E10AC09A6400622F72 /* fweelin_event.cc */, AC5A53E20AC09A6400622F72 /* fweelin_event.h */, AC5A53E30AC09A6400622F72 /* fweelin_fluidsynth.cc */, AC5A53E40AC09A6400622F72 /* fweelin_fluidsynth.h */, AC5A53E50AC09A6400622F72 /* fweelin_logo.h */, AC5A53E60AC09A6400622F72 /* fweelin_mem.cc */, AC5A53E70AC09A6400622F72 /* fweelin_mem.h */, AC5A53E80AC09A6400622F72 /* fweelin_midiio.cc */, AC5A53E90AC09A6400622F72 /* fweelin_midiio.h */, AC5A53EA0AC09A6400622F72 /* fweelin_sdlio.cc */, AC5A53EB0AC09A6400622F72 /* fweelin_sdlio.h */, AC5A53EC0AC09A6400622F72 /* fweelin_videoio.cc */, AC5A53ED0AC09A6400622F72 /* fweelin_videoio.h */, AC5A53EE0AC09A6400622F72 /* fweelin.cc */, ACFC0A990AC99CDF00DAC478 /* FweelinMac.h */, ACFC0A9A0AC99CDF00DAC478 /* FweelinMac.mm */, 002F3A2B09D0888800EBEB88 /* SDLMain.h */, 002F3A2C09D0888800EBEB88 /* SDLMain.mm */, ACA2C53E0B06DCB600E02DC6 /* SDLMain.nib */, ); name = Classes; sourceTree = ""; }; 1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */ = { isa = PBXGroup; children = ( 3D8261B60E96C8B600B480B6 /* Jackmp.framework */, AC6429D80AD9C85700752A08 /* Sndfile.framework */, AC12675C0AC8E0BE00FE916E /* CoreMIDI.framework */, AC5A53240AC099C900622F72 /* Ogg.framework */, AC5A53250AC099C900622F72 /* SDL_gfx.framework */, AC5A53260AC099C900622F72 /* SDL_ttf.framework */, AC5A53270AC099C900622F72 /* Vorbis.framework */, 002F39F909D0881F00EBEB88 /* SDL.framework */, 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */, ); name = "Linked Frameworks"; sourceTree = ""; }; 1058C7A2FEA54F0111CA2CBB /* Other Frameworks */ = { isa = PBXGroup; children = ( 29B97324FDCFA39411CA2CEA /* AppKit.framework */, 29B97325FDCFA39411CA2CEA /* Foundation.framework */, ); name = "Other Frameworks"; sourceTree = ""; }; 19C28FACFE9D520D11CA2CBB /* Products */ = { isa = PBXGroup; children = ( 8D1107320486CEB800E47090 /* fweelin.app */, ); name = Products; sourceTree = ""; }; 29B97314FDCFA39411CA2CEA /* fweelin */ = { isa = PBXGroup; children = ( 080E96DDFE201D6D7F000001 /* Classes */, 29B97315FDCFA39411CA2CEA /* Other Sources */, 29B97317FDCFA39411CA2CEA /* Resources */, 29B97323FDCFA39411CA2CEA /* Frameworks */, 19C28FACFE9D520D11CA2CBB /* Products */, ); name = fweelin; sourceTree = ""; }; 29B97315FDCFA39411CA2CEA /* Other Sources */ = { isa = PBXGroup; children = ( 32CA4F630368D1EE00C91783 /* fweelin_Prefix.pch */, ); name = "Other Sources"; sourceTree = ""; }; 29B97317FDCFA39411CA2CEA /* Resources */ = { isa = PBXGroup; children = ( 3D8262480E96CDC700B480B6 /* fweelin.xml */, 3D8262490E96CDC700B480B6 /* coreinterface.xml */, 3D82624A0E96CDC700B480B6 /* interfaces.xml */, 3D82624B0E96CDC700B480B6 /* patches2.xml */, 3D82624C0E96CDC700B480B6 /* pcr-m1.xml */, 3D82624D0E96CDC700B480B6 /* pckeyboard.xml */, 3D82624E0E96CDC700B480B6 /* patches-strings.xml */, 3D82624F0E96CDC700B480B6 /* mercury.xml */, 3D8262500E96CDC700B480B6 /* bcf2000.xml */, 3D8262510E96CDC700B480B6 /* midifootswitch.xml */, 3D8262520E96CDC700B480B6 /* dancemat.xml */, 3D8262530E96CDC700B480B6 /* graphics.xml */, 3D8262540E96CDC700B480B6 /* patches-channels.xml */, 3D8262550E96CDC700B480B6 /* basics.xml */, 3D8262560E96CDC700B480B6 /* browsers.xml */, 3D8262570E96CDC700B480B6 /* midikeyboard.xml */, 3D8262580E96CDC700B480B6 /* patches1.xml */, 3D8262590E96CDC700B480B6 /* bindings.xml */, 3D82625A0E96CDC700B480B6 /* patches-b3.xml */, 3D82625B0E96CDC700B480B6 /* patches3.xml */, AC776D460B69B161005E3D84 /* freewheeling.icns */, AC126C420AC8EF4000FE916E /* verabd.ttf */, AC126C430AC8EF4000FE916E /* vera.ttf */, 8D1107310486CEB800E47090 /* Info.plist */, 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */, ); name = Resources; sourceTree = ""; }; 29B97323FDCFA39411CA2CEA /* Frameworks */ = { isa = PBXGroup; children = ( 1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */, 1058C7A2FEA54F0111CA2CBB /* Other Frameworks */, ); name = Frameworks; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 8D1107260486CEB800E47090 /* fweelin */ = { isa = PBXNativeTarget; buildConfigurationList = C01FCF4A08A954540054247B /* Build configuration list for PBXNativeTarget "fweelin" */; buildPhases = ( 8D1107290486CEB800E47090 /* Resources */, 8D11072C0486CEB800E47090 /* Sources */, 8D11072E0486CEB800E47090 /* Frameworks */, 002F39FD09D0883400EBEB88 /* Copy Frameworks into .app bundle */, ); buildRules = ( ); dependencies = ( ); name = fweelin; productInstallPath = "$(HOME)/Applications"; productName = fweelin; productReference = 8D1107320486CEB800E47090 /* fweelin.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 29B97313FDCFA39411CA2CEA /* Project object */ = { isa = PBXProject; buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "fweelin" */; compatibilityVersion = "Xcode 2.4"; hasScannedForEncodings = 1; mainGroup = 29B97314FDCFA39411CA2CEA /* fweelin */; projectDirPath = ""; projectRoot = ""; targets = ( 8D1107260486CEB800E47090 /* fweelin */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 8D1107290486CEB800E47090 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( 8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */, AC126C440AC8EF4000FE916E /* verabd.ttf in Resources */, AC126C450AC8EF4000FE916E /* vera.ttf in Resources */, ACA2C53F0B06DCB600E02DC6 /* SDLMain.nib in Resources */, AC776D470B69B161005E3D84 /* freewheeling.icns in Resources */, 3D82625C0E96CDC700B480B6 /* fweelin.xml in Resources */, 3D82625D0E96CDC700B480B6 /* coreinterface.xml in Resources */, 3D82625E0E96CDC700B480B6 /* interfaces.xml in Resources */, 3D82625F0E96CDC700B480B6 /* patches2.xml in Resources */, 3D8262600E96CDC700B480B6 /* pcr-m1.xml in Resources */, 3D8262610E96CDC700B480B6 /* pckeyboard.xml in Resources */, 3D8262620E96CDC700B480B6 /* patches-strings.xml in Resources */, 3D8262630E96CDC700B480B6 /* mercury.xml in Resources */, 3D8262640E96CDC700B480B6 /* bcf2000.xml in Resources */, 3D8262650E96CDC700B480B6 /* midifootswitch.xml in Resources */, 3D8262660E96CDC700B480B6 /* dancemat.xml in Resources */, 3D8262670E96CDC700B480B6 /* graphics.xml in Resources */, 3D8262680E96CDC700B480B6 /* patches-channels.xml in Resources */, 3D8262690E96CDC700B480B6 /* basics.xml in Resources */, 3D82626A0E96CDC700B480B6 /* browsers.xml in Resources */, 3D82626B0E96CDC700B480B6 /* midikeyboard.xml in Resources */, 3D82626C0E96CDC700B480B6 /* patches1.xml in Resources */, 3D82626D0E96CDC700B480B6 /* bindings.xml in Resources */, 3D82626E0E96CDC700B480B6 /* patches-b3.xml in Resources */, 3D82626F0E96CDC700B480B6 /* patches3.xml in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 8D11072C0486CEB800E47090 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 002F3A2E09D0888800EBEB88 /* SDLMain.mm in Sources */, AC5A53EF0AC09A6400622F72 /* fweelin_audioio.cc in Sources */, AC5A53F10AC09A6400622F72 /* fweelin_block.cc in Sources */, AC5A53F30AC09A6400622F72 /* fweelin_browser.cc in Sources */, AC5A53F50AC09A6400622F72 /* fweelin_config.cc in Sources */, AC5A53F70AC09A6400622F72 /* fweelin_core_dsp.cc in Sources */, AC5A53F90AC09A6400622F72 /* fweelin_core.cc in Sources */, AC5A53FB0AC09A6400622F72 /* fweelin_datatypes.cc in Sources */, AC5A53FD0AC09A6400622F72 /* fweelin_event.cc in Sources */, AC5A53FF0AC09A6400622F72 /* fweelin_fluidsynth.cc in Sources */, AC5A54020AC09A6400622F72 /* fweelin_mem.cc in Sources */, AC5A54040AC09A6400622F72 /* fweelin_midiio.cc in Sources */, AC5A54060AC09A6400622F72 /* fweelin_sdlio.cc in Sources */, AC5A54080AC09A6400622F72 /* fweelin_videoio.cc in Sources */, AC5A540A0AC09A6400622F72 /* fweelin.cc in Sources */, ACFC0A9C0AC99CDF00DAC478 /* FweelinMac.mm in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXVariantGroup section */ 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */ = { isa = PBXVariantGroup; children = ( 089C165DFE840E0CC02AAC07 /* English */, ); name = InfoPlist.strings; sourceTree = ""; }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ C01FCF4B08A954540054247B /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { COPY_PHASE_STRIP = NO; GCC_DYNAMIC_NO_PIC = NO; GCC_ENABLE_FIX_AND_CONTINUE = YES; GCC_MODEL_TUNING = G5; GCC_OPTIMIZATION_LEVEL = 0; INFOPLIST_FILE = Info.plist; INSTALL_PATH = "$(HOME)/Applications"; PRODUCT_NAME = fweelin; WRAPPER_EXTENSION = app; ZERO_LINK = YES; }; name = Debug; }; C01FCF4C08A954540054247B /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ARCHS = ( ppc, i386, ); GCC_GENERATE_DEBUGGING_SYMBOLS = NO; GCC_MODEL_TUNING = G5; INFOPLIST_FILE = Info.plist; INSTALL_PATH = "$(HOME)/Applications"; PRODUCT_NAME = fweelin; WRAPPER_EXTENSION = app; }; name = Release; }; C01FCF4F08A954540054247B /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ARCHS = ( i386, ppc, ); FRAMEWORK_SEARCH_PATHS = ( "$(HOME)/Library/Frameworks", /Library/Frameworks, "$(FRAMEWORK_SEARCH_PATHS)", ); GCC_GENERATE_DEBUGGING_SYMBOLS = YES; GCC_OPTIMIZATION_LEVEL = 3; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = ( "$(HOME)/Library/Frameworks/SDL.framework/Headers", /Library/Frameworks/SDL.framework/Headers, "$(HEADER_SEARCH_PATHS)", /usr/include/libxml2, ); OTHER_CFLAGS = ( "-D", __MACOSX__, "-fpermissive", ); OTHER_LDFLAGS = ( "-lcrypto", "-lxml2", ); PREBINDING = NO; PRODUCT_NAME = FreeWheeling; ZERO_LINK = NO; }; name = Debug; }; C01FCF5008A954540054247B /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ARCHS = ( i386, ppc, ); FRAMEWORK_SEARCH_PATHS = ( "$(HOME)/Library/Frameworks", /Library/Frameworks, "$(FRAMEWORK_SEARCH_PATHS)", ); GCC_GENERATE_DEBUGGING_SYMBOLS = YES; GCC_OPTIMIZATION_LEVEL = 3; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = ( /Library/Frameworks/Jackmp.framework/Headers, "$(HOME)/Library/Frameworks/SDL.framework/Headers", /Library/Frameworks/SDL.framework/Headers, "$(HEADER_SEARCH_PATHS)", /usr/include/libxml2, ); OTHER_CFLAGS = ( "-D", __MACOSX__, "-fpermissive", ); OTHER_LDFLAGS = ( "-lcrypto", "-lxml2", ); PREBINDING = NO; PRODUCT_NAME = FreeWheeling; ZERO_LINK = NO; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ C01FCF4A08A954540054247B /* Build configuration list for PBXNativeTarget "fweelin" */ = { isa = XCConfigurationList; buildConfigurations = ( C01FCF4B08A954540054247B /* Debug */, C01FCF4C08A954540054247B /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; C01FCF4E08A954540054247B /* Build configuration list for PBXProject "fweelin" */ = { isa = XCConfigurationList; buildConfigurations = ( C01FCF4F08A954540054247B /* Debug */, C01FCF5008A954540054247B /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 29B97313FDCFA39411CA2CEA /* Project object */; } fweelin-0.6/MacOSX/Info.plist0000644000175000017500000000153510556277142014525 0ustar mercmerc CFBundleDevelopmentRegion English CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIconFile freewheeling.icns CFBundleIdentifier com.yourcompany.fweelin CFBundleInfoDictionaryVersion 6.0 CFBundleName ${PRODUCT_NAME} CFBundlePackageType APPL CFBundleSignature ???? CFBundleVersion MAC NSMainNibFile SDLMain NSPrincipalClass NSApplication fweelin-0.6/MacOSX/README-MAC0000755000175000017500000001144411071521701014020 0ustar mercmercIntro for Mac OS X ================== FreeWheeling for Mac OS X is a direct port of the Linux version. A Universal binary will be made available for each release, along with source code if you wish to compile it yourself. The user interface remains the same across OS X and Linux versions. This means that FreeWheeling OS X does not make use of Mac's Aqua interface. A few basic commands specific to the Mac version have been provided in a Mac menu. The rest of the functionality is built into the app window. FreeWheeling is designed to be mostly MIDI and keyboard driven. A few things can be done from a mouse, but while playing music, the idea is to keep your hands on your instrument. FreeWheeling is not a music production or DJing tool. FreeWheeling works for instrumentalists, such as drummers, guitarists, keyboardists and vocalists. FreeWheeling is like a second instrument, that you use to reflect back parts of your playing, to build loops in a spontaneous way. You can configure FreeWheeling to work with the PC keyboard, joysticks, or MIDI-enabled devices. Setup for Mac OS X ================== 1. Drag the 'Fweelin' app to the 'Applications' folder. 2. Download and install JACK. http://jackosx.com/ Jack is an audio connection kit similar to Rewire. It allows you to plug FreeWheeling into different audio apps, such as soft synths or sequencers. 3. Start 'Jack Pilot', included with your JACK installation. Set the lowest possible latency that provides stable performance. Set 'Jack Pilot' to 'Full Duplex' (recording and playback enabled), if you wish to record live instruments in FreeWheeling. If you are using the onboard Mac sound, you can get 'Full Duplex' recording and playback by creating an 'Aggregate Audio Device'. To do this, choose 'Open Audio MIDI Setup' from the JackPilot menu, or run 'Applications/Utilities/Audio MIDI Setup'. Then, select 'Open Aggregate Device Editor...' from the Audio menu. 4. If you wish to debug the console output of FreeWheeling for troubleshooting, start 'Applications/Utilities/Console' now. 5. Run 'FreeWheeling'. The main window should appear. If it does not, consult the Console log (step 4), or try running from a Terminal. Using FreeWheeling for Mac OS X =============================== FreeWheeling can be driven from any one MIDI source. To select the source, choose 'Preferences' from the 'Fweelin' menu. By default, FreeWheeling grabs loops with the QWERTY keys as well as one octave of keys on your MIDI keyboard. This can be configured in the configuration files. The main one is ~/.fweelin/fweelin.xml. They are all stored in ~/.fweelin. Some keyboard commands (function keys especially) may conflict with Mac OS X keyboard shortcuts. I suggest using an external USB keyboard, or modifying Freewheeling's configuration. You will have to connect audio to go into and out of FreeWheeling using Jack Pilot. Most often, you will want to route your system audio inputs into FreeWheeling, and FreeWheeling's audio outputs back out to the system, or into a sequencer or effects program. Regular Mac audio apps work with JACK. Simply point them to the 'JACK' device. FreeWheeling can also drive soft-synths and effects. FreeWheeling creates several MIDI outputs, which appear as virtual MIDI sources. You can connect your audio apps to these MIDI sources. FreeWheeling has a built-in configurable patch browser that can be used to select patches on different MIDI outputs. You can also create combination patches that split your MIDI input into a variety of keyboard zones, playing different outputs together. For a crash-course in Freewheeling (albeit, an old version), please refer to the video tutorials at: http://freewheeling.sourceforge.net/ If you'd like to configure Freewheeling, please read the configuration files located in your home folder in the hidden subfolder .fweelin/ (once you've run FreeWheeling, this folder appears) To find this folder through the Finder, you must have hidden files enabled in your Finder. Or, you can access it through the Mac Terminal app. For more help, please browse or sign on to the mailing-list. Happy Looping! -JP Mercury. Compiling FreeWheeling from Source ================================== FreeWheeling for Mac OS X can be compiled from source. Download the source package. You will need Apple's XCode tools. Load MacOSX/fweelin.xcodeproj FreeWheeling depends on several frameworks. Many of these can be installed from third-party sites. However, some, such as libsndfile, require a small amount of tweaking to be compiled as Frameworks. A ZIP file of all dependency Frameworks with xcodeproj files is available. Please contact JP Mercury: http://home.graffiti.net/swirlee/swirlee.jpg If you wish to contribute to the development of FreeWheeling, please be in touch. Happy Compiling! -JP Mercury. fweelin-0.6/MacOSX/SDLMain.h0000644000175000017500000000106510547030013014133 0ustar mercmerc/* SDLMain.m - main entry point for our Cocoa-ized SDL app Initial Version: Darrell Walisser Non-NIB-Code & other changes: Max Horn Feel free to customize this file to suit your needs */ #import @interface SDLMain : NSObject { IBOutlet NSPopUpButton *midiInputSel; } - (IBAction)setMIDIInput:(id)sender; - (IBAction)toggleDebugMode:(id)sender; - (IBAction)quitFW:(id)sender; - (IBAction)showHelp:(id)sender; - (void)clearMIDIInputList; - (void)addMIDIInputSource:(NSString *)name; @end fweelin-0.6/MacOSX/SDLMain.mm0000644000175000017500000003004610547030013014316 0ustar mercmerc/* SDLMain.m - main entry point for our Cocoa-ized SDL app Initial Version: Darrell Walisser Non-NIB-Code & other changes: Max Horn Feel free to customize this file to suit your needs */ #import "SDL.h" #import "SDLMain.h" #include "FweelinMac.h" #import /* for MAXPATHLEN */ #import extern char *FWEELIN_DATADIR; /* For some reaon, Apple removed setAppleMenu from the headers in 10.4, but the method still is there and works. To avoid warnings, we declare it ourselves here. */ @interface NSApplication(SDL_Missing_Methods) - (void)setAppleMenu:(NSMenu *)menu; @end /* Use this flag to determine whether we use SDLMain.nib or not */ #define SDL_USE_NIB_FILE 1 /* Use this flag to determine whether we use CPS (docking) or not */ #define SDL_USE_CPS 1 #ifdef SDL_USE_CPS /* Portions of CPS.h */ typedef struct CPSProcessSerNum { UInt32 lo; UInt32 hi; } CPSProcessSerNum; extern OSErr CPSGetCurrentProcess( CPSProcessSerNum *psn); extern OSErr CPSEnableForegroundOperation( CPSProcessSerNum *psn, UInt32 _arg2, UInt32 _arg3, UInt32 _arg4, UInt32 _arg5); extern OSErr CPSSetFrontProcess( CPSProcessSerNum *psn); #endif /* SDL_USE_CPS */ static int gArgc; static char **gArgv; static BOOL gFinderLaunch; static BOOL gCalledAppMainline = FALSE; static NSString *getApplicationName(void) { NSDictionary *dict; NSString *appName = 0; /* Determine the application name */ dict = (NSDictionary *)CFBundleGetInfoDictionary(CFBundleGetMainBundle()); if (dict) appName = [dict objectForKey: @"CFBundleName"]; if (![appName length]) appName = [[NSProcessInfo processInfo] processName]; return appName; } #if SDL_USE_NIB_FILE /* A helper category for NSString */ @interface NSString (ReplaceSubString) - (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString; @end #endif @interface SDLApplication : NSApplication @end @implementation SDLApplication /* Invoked from the Quit menu item */ - (void)terminate:(id)sender { /* Post a SDL_QUIT event */ SDL_Event event; event.type = SDL_QUIT; SDL_PushEvent(&event); } @end /* The main class of the application, the application's delegate */ @implementation SDLMain - (void)awakeFromNib { // NSLog(@"AWAKE\n"); FweelinMac::LinkSDLMain(self); } - (IBAction)toggleDebugMode:(id)sender { // Toggle debug mode int state = [sender state]; state = (state == 0 ? 1 : 0); [sender setState:state]; FweelinMac::SetDebugMode(state); } - (IBAction)quitFW:(id)sender { FweelinMac::Quit(); } - (IBAction)showHelp:(id)sender { FweelinMac::ShowHelp(); } - (IBAction)setMIDIInput:(id)sender { // printf("IDX: %d\n",idx); int idx = [sender indexOfSelectedItem]; FweelinMac::SetMIDIInput(idx); } - (void)clearMIDIInputList { [midiInputSel removeAllItems]; } - (void)addMIDIInputSource:(NSString *)name { [midiInputSel addItemWithTitle:name]; } // Dummy thread to invoke multithreaded mode - (void) dummyThread:(id)sender { while (1) { printf("Dummy thread!\n"); sleep(1); } //[NSThread exit]; } /* Set the working directory to the .app's parent directory */ - (void) setupWorkingDirectory:(BOOL)shouldChdir { if (shouldChdir) { char parentdir[MAXPATHLEN]; CFURLRef url = CFBundleCopyBundleURL(CFBundleGetMainBundle()); CFURLRef url2 = CFURLCreateCopyDeletingLastPathComponent(0, url); if (CFURLGetFileSystemRepresentation(url2, true, (UInt8 *)parentdir, MAXPATHLEN)) { assert ( chdir (parentdir) == 0 ); /* chdir to the binary app's parent */ } CFRelease(url); CFRelease(url2); } } #if SDL_USE_NIB_FILE /* Fix menu to contain the real app name instead of "SDL App" */ - (void)fixMenu:(NSMenu *)aMenu withAppName:(NSString *)appName { NSRange aRange; NSEnumerator *enumerator; NSMenuItem *menuItem; aRange = [[aMenu title] rangeOfString:@"SDL App"]; if (aRange.length != 0) [aMenu setTitle: [[aMenu title] stringByReplacingRange:aRange with:appName]]; enumerator = [[aMenu itemArray] objectEnumerator]; while ((menuItem = [enumerator nextObject])) { aRange = [[menuItem title] rangeOfString:@"SDL App"]; if (aRange.length != 0) [menuItem setTitle: [[menuItem title] stringByReplacingRange:aRange with:appName]]; if ([menuItem hasSubmenu]) [self fixMenu:[menuItem submenu] withAppName:appName]; } [ aMenu sizeToFit ]; } #else static void setApplicationMenu(void) { /* warning: this code is very odd */ NSMenu *appleMenu; NSMenuItem *menuItem; NSString *title; NSString *appName; appName = getApplicationName(); appleMenu = [[NSMenu alloc] initWithTitle:@""]; /* Add menu items */ title = [@"About " stringByAppendingString:appName]; [appleMenu addItemWithTitle:title action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""]; [appleMenu addItem:[NSMenuItem separatorItem]]; title = [@"Hide " stringByAppendingString:appName]; [appleMenu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@"h"]; menuItem = (NSMenuItem *)[appleMenu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"]; [menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)]; [appleMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""]; [appleMenu addItem:[NSMenuItem separatorItem]]; title = [@"Quit " stringByAppendingString:appName]; [appleMenu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"]; /* Put menu into the menubar */ menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""]; [menuItem setSubmenu:appleMenu]; [[NSApp mainMenu] addItem:menuItem]; /* Tell the application object that this is now the application menu */ [NSApp setAppleMenu:appleMenu]; /* Finally give up our references to the objects */ [appleMenu release]; [menuItem release]; } /* Create a window menu */ static void setupWindowMenu(void) { NSMenu *windowMenu; NSMenuItem *windowMenuItem; NSMenuItem *menuItem; windowMenu = [[NSMenu alloc] initWithTitle:@"Window"]; /* "Minimize" item */ menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"]; [windowMenu addItem:menuItem]; [menuItem release]; /* Put menu into the menubar */ windowMenuItem = [[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""]; [windowMenuItem setSubmenu:windowMenu]; [[NSApp mainMenu] addItem:windowMenuItem]; /* Tell the application object that this is now the window menu */ [NSApp setWindowsMenu:windowMenu]; /* Finally give up our references to the objects */ [windowMenu release]; [windowMenuItem release]; } /* Replacement for NSApplicationMain */ static void CustomApplicationMain (int argc, char **argv) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; SDLMain *sdlMain; /* Ensure the application object is initialised */ [SDLApplication sharedApplication]; #ifdef SDL_USE_CPS { CPSProcessSerNum PSN; /* Tell the dock about us */ if (!CPSGetCurrentProcess(&PSN)) if (!CPSEnableForegroundOperation(&PSN,0x03,0x3C,0x2C,0x1103)) if (!CPSSetFrontProcess(&PSN)) [SDLApplication sharedApplication]; } #endif /* SDL_USE_CPS */ /* Set up the menubar */ [NSApp setMainMenu:[[NSMenu alloc] init]]; setApplicationMenu(); setupWindowMenu(); /* Create SDLMain and make it the app delegate */ sdlMain = [[SDLMain alloc] init]; [NSApp setDelegate:sdlMain]; /* Start the main event loop */ [NSApp run]; [sdlMain release]; [pool release]; } #endif /* * Catch document open requests...this lets us notice files when the app * was launched by double-clicking a document, or when a document was * dragged/dropped on the app's icon. You need to have a * CFBundleDocumentsType section in your Info.plist to get this message, * apparently. * * Files are added to gArgv, so to the app, they'll look like command line * arguments. Previously, apps launched from the finder had nothing but * an argv[0]. * * This message may be received multiple times to open several docs on launch. * * This message is ignored once the app's mainline has been called. */ - (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename { const char *temparg; size_t arglen; char *arg; char **newargv; if (!gFinderLaunch) /* MacOS is passing command line args. */ return FALSE; if (gCalledAppMainline) /* app has started, ignore this document. */ return FALSE; temparg = [filename UTF8String]; arglen = SDL_strlen(temparg) + 1; arg = (char *) SDL_malloc(arglen); if (arg == NULL) return FALSE; newargv = (char **) realloc(gArgv, sizeof (char *) * (gArgc + 2)); if (newargv == NULL) { SDL_free(arg); return FALSE; } gArgv = newargv; SDL_strlcpy(arg, temparg, arglen); gArgv[gArgc++] = arg; gArgv[gArgc] = NULL; return TRUE; } /* Called when the internal event loop has just started running */ - (void) applicationDidFinishLaunching: (NSNotification *) note { int status; /* Set the working directory to the .app's parent directory */ [self setupWorkingDirectory:gFinderLaunch]; #if SDL_USE_NIB_FILE /* Set the main menu to contain the real app name instead of "SDL App" */ [self fixMenu:[NSApp mainMenu] withAppName:getApplicationName()]; #endif /* Hand off to main application code */ gCalledAppMainline = TRUE; status = SDL_main (gArgc, gArgv); /* We're done, thank you for playing */ exit(status); } @end @implementation NSString (ReplaceSubString) - (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString { unsigned int bufferSize; unsigned int selfLen = [self length]; unsigned int aStringLen = [aString length]; unichar *buffer; NSRange localRange; NSString *result; bufferSize = selfLen + aStringLen - aRange.length; buffer = (unichar *) NSAllocateMemoryPages(bufferSize*sizeof(unichar)); /* Get first part into buffer */ localRange.location = 0; localRange.length = aRange.location; [self getCharacters:buffer range:localRange]; /* Get middle part into buffer */ localRange.location = 0; localRange.length = aStringLen; [aString getCharacters:(buffer+aRange.location) range:localRange]; /* Get last part into buffer */ localRange.location = aRange.location + aRange.length; localRange.length = selfLen - localRange.location; [self getCharacters:(buffer+aRange.location+aStringLen) range:localRange]; /* Build output string */ result = [NSString stringWithCharacters:buffer length:bufferSize]; NSDeallocateMemoryPages(buffer, bufferSize); return result; } @end #ifdef main # undef main #endif /* Main entry point to executable - should *not* be SDL_main! */ int main (int argc, char **argv) { /* Copy the arguments into a global variable */ /* This is passed if we are launched by double-clicking */ if ( argc >= 2 && strncmp (argv[1], "-psn", 4) == 0 ) { gArgv = (char **) SDL_malloc(sizeof (char *) * 2); gArgv[0] = argv[0]; gArgv[1] = NULL; gArgc = 1; gFinderLaunch = YES; } else { int i; gArgc = argc; gArgv = (char **) SDL_malloc(sizeof (char *) * (argc+1)); for (i = 0; i <= argc; i++) gArgv[i] = argv[i]; gFinderLaunch = NO; } // Setup multithreaded mode [NSThread detachNewThreadSelector:@selector(dummyThread) toTarget:nil withObject:nil]; // printf("MULTITHREADED: %d\n",[NSThread isMultiThreaded]); #if SDL_USE_NIB_FILE [SDLApplication poseAsClass:[NSApplication class]]; NSApplicationMain (argc, (const char **) argv); #else CustomApplicationMain (argc, argv); #endif return 0; } fweelin-0.6/MacOSX/SDLMain.nib/0000755000175000017500000000000010746301442014537 5ustar mercmercfweelin-0.6/MacOSX/SDLMain.nib/objects.nib0000644000175000017500000001131610547030013016654 0ustar mercmerc streamtyped@NSIBObjectDataNSObjectNSCustomObject)@@NSMutableStringNSString+ NSApplicationi"SDLMainNSView) NSResponder @@@@ffffffffNSMutableArrayNSArray NSTextField NSControl)-icc@NSTextFieldCell> NSActionCellNSCellAii@@@@@+Help For Mac Users: Press / (?) for help inside FreeWheeling. Press repeatedly. There are several pages of help. This will give you a quick reference to most available commands. Essentials: Use the TAB key to switch layouts. The QWERTY keyboard keys start recording and playing loops. *** When the RED light is on, you are recording, and memory is being used. Press U to undo and stop. *** For more info on how to use FreeWheeling: Video Tutorials- http://freewheeling.sourceforge.net FreeWheeling is very configurable. Look in ~/.fweelin/.fweelin.rc for documentation and settings. *** There are some issues with keyboard keys on this Mac version. The internal Mac keyboard does not have all the keys we have bound to. I suggest using a full-size USB keyboard. Also, some international keyboards do not work quite right. If key bindings are not working for you, try enabling debug mode (in the Fweelin menu). From here, you can see all keypresses received on the console. All key bindings can then be edited in the configuration file, ~/.fweelin/.fweelin.rc NSFont$[36c]LucidaGrandef ci:c@@NSColor@@@System controlColorff*?controlTextColor:uu@All The Best... ,[44c]$LucidaGrande-Bold  NSWindowTemplate iiffffi@@@@@cxpFreeWheeling Mac HelpNSWindowViewffffnNSMenui@@@SDL App NSMenuItem i@@IIi@@@@:i@ About SDL AppNSCustomResource)NSImageNSMenuCheckmarkƖDŽNSMenuMixedState’ĂŅɅ’Preferences...ĂŅɅ’ Debug ModeĂŅɅ’ĂŅɅ’ Hide SDL ApphŅɅ’ Hide OthersĂŅɅ’Show AllĂŅɅ’ĂŅɅ’ Quit SDL AppqŅɅ _NSAppleMenu’SDLMainݒ’޹WindowĂŅɄsubmenuAction:Window’MinimizemŅɅ_NSWindowsMenu’޹HelpĂŅɻHelp’FreeWheeling Help?ŅɅ’ FW Mac Help?ŅɅ _NSMainMenuĂŅɻޕhx PreferencesNSPanelViewP P @ MIDI Input:$LucidaGrande  NSPopUpButtonNSButton::NSPopUpButtonCell1NSMenuItemCell NSButtonCell?@A ssii@@@@@K@Ą’ OtherViews’ Item2ĂŅɄ_popUpItemAction:’ Item3ĂŅItem1ĂŅi@i= hhn NSFontManagerؽԽޖ̽н  ޖ˽ٽֽ 얢νѽޖ NSMenuItem NSTextField21 Font Manager Preferences愙 NSMenuItem1Mac Help File's Ownerل1111ꄘ1 PopUpListNSTextField111111ބMainMenu NSTextField2 NSMenuItem2ㄙNSMenu NSPopUpButton섘2ᄙ NSMenuItem1Є NSMenuItem NSMenuItem1 NSMutableSetNSSetI NSNibControlConnectorNSNibConnectororderFrontStandardAboutPanel:-ԕhideOtherApplications:-ѕhide:-֕unhideAllApplications:NSNibOutletConnector.delegate-慄performMiniaturize:-makeKeyAndOrderFront:7 midiInputSel- setMIDIInput:-򸄙makeKeyAndOrderFront:-ΚtoggleDebugMode:-ٚquitFW:- showHelp:0@i2GсЁAU6ԁʢV΁YցJ:84,Mgف؁RʸS N;OCZʽ99 oG]0ʚ=PHI K?Q́%ʜTjLE\ʴXˁ[ʕ^IBCocoaFrameworkfweelin-0.6/MacOSX/SDLMain.nib/classes.nib0000644000175000017500000000061310547030013016656 0ustar mercmerc{ IBClasses = ( {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }, { ACTIONS = {quitFW = id; setMIDIInput = id; showHelp = id; toggleDebugMode = id; }; CLASS = SDLMain; LANGUAGE = ObjC; OUTLETS = {midiInputSel = NSPopUpButton; }; SUPERCLASS = NSObject; } ); IBVersion = 1; }fweelin-0.6/MacOSX/SDLMain.nib/info.nib0000644000175000017500000000106510547030013016156 0ustar mercmerc IBDocumentLocation 987 57 356 240 0 0 1440 878 IBEditorPositions 29 82 376 205 44 0 0 1440 878 IBFramework Version 446.1 IBOpenObjects 339 IBSystem Version 8L2127 fweelin-0.6/install-sh0000755000175000017500000001273610547030013013454 0ustar mercmerc#!/bin/sh # # install - install a program, script, or datafile # This comes from X11R5 (mit/util/scripts/install.sh). # # Copyright 1991 by the Massachusetts Institute of Technology # # Permission to use, copy, modify, distribute, and sell this software and its # documentation for any purpose is hereby granted without fee, provided that # the above copyright notice appear in all copies and that both that # copyright notice and this permission notice appear in supporting # documentation, and that the name of M.I.T. not be used in advertising or # publicity pertaining to distribution of the software without specific, # written prior permission. M.I.T. makes no representations about the # suitability of this software for any purpose. It is provided "as is" # without express or implied warranty. # # Calling this script install-sh is preferred over install.sh, to prevent # `make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. It can only install one file at a time, a restriction # shared with many OS's install programs. # set DOITPROG to echo to test this script # Don't use :- since 4.3BSD and earlier shells don't like it. doit="${DOITPROG-}" # put in absolute paths if you don't have them in your path; or use env. vars. mvprog="${MVPROG-mv}" cpprog="${CPPROG-cp}" chmodprog="${CHMODPROG-chmod}" chownprog="${CHOWNPROG-chown}" chgrpprog="${CHGRPPROG-chgrp}" stripprog="${STRIPPROG-strip}" rmprog="${RMPROG-rm}" mkdirprog="${MKDIRPROG-mkdir}" transformbasename="" transform_arg="" instcmd="$mvprog" chmodcmd="$chmodprog 0755" chowncmd="" chgrpcmd="" stripcmd="" rmcmd="$rmprog -f" mvcmd="$mvprog" src="" dst="" dir_arg="" while [ x"$1" != x ]; do case $1 in -c) instcmd="$cpprog" shift continue;; -d) dir_arg=true shift continue;; -m) chmodcmd="$chmodprog $2" shift shift continue;; -o) chowncmd="$chownprog $2" shift shift continue;; -g) chgrpcmd="$chgrpprog $2" shift shift continue;; -s) stripcmd="$stripprog" shift continue;; -t=*) transformarg=`echo $1 | sed 's/-t=//'` shift continue;; -b=*) transformbasename=`echo $1 | sed 's/-b=//'` shift continue;; *) if [ x"$src" = x ] then src=$1 else # this colon is to work around a 386BSD /bin/sh bug : dst=$1 fi shift continue;; esac done if [ x"$src" = x ] then echo "install: no input file specified" exit 1 else true fi if [ x"$dir_arg" != x ]; then dst=$src src="" if [ -d $dst ]; then instcmd=: chmodcmd="" else instcmd=mkdir fi else # Waiting for this to be detected by the "$instcmd $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if [ -f $src -o -d $src ] then true else echo "install: $src does not exist" exit 1 fi if [ x"$dst" = x ] then echo "install: no destination specified" exit 1 else true fi # If destination is a directory, append the input filename; if your system # does not like double slashes in filenames, you may need to add some logic if [ -d $dst ] then dst="$dst"/`basename $src` else true fi fi ## this sed command emulates the dirname command dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` # Make sure that the destination directory exists. # this part is taken from Noah Friedman's mkinstalldirs script # Skip lots of stat calls in the usual case. if [ ! -d "$dstdir" ]; then defaultIFS=' ' IFS="${IFS-${defaultIFS}}" oIFS="${IFS}" # Some sh's can't handle IFS=/ for some reason. IFS='%' set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` IFS="${oIFS}" pathcomp='' while [ $# -ne 0 ] ; do pathcomp="${pathcomp}${1}" shift if [ ! -d "${pathcomp}" ] ; then $mkdirprog "${pathcomp}" else true fi pathcomp="${pathcomp}/" done fi if [ x"$dir_arg" != x ] then $doit $instcmd $dst && if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi else # If we're going to rename the final executable, determine the name now. if [ x"$transformarg" = x ] then dstfile=`basename $dst` else dstfile=`basename $dst $transformbasename | sed $transformarg`$transformbasename fi # don't allow the sed command to completely eliminate the filename if [ x"$dstfile" = x ] then dstfile=`basename $dst` else true fi # Make a temp file name in the proper directory. dsttmp=$dstdir/#inst.$$# # Move or copy the file name to the temp name $doit $instcmd $src $dsttmp && trap "rm -f ${dsttmp}" 0 && # and set any options; do chmod last to preserve setuid bits # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $instcmd $src $dsttmp" command. if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && # Now rename the file to the real destination. $doit $rmcmd -f $dstdir/$dstfile && $doit $mvcmd $dsttmp $dstdir/$dstfile fi && exit 0 fweelin-0.6/mkinstalldirs0000755000175000017500000000132210547030013014243 0ustar mercmerc#! /bin/sh # mkinstalldirs --- make directory hierarchy # Author: Noah Friedman # Created: 1993-05-16 # Public domain # $Id: mkinstalldirs,v 1.13 1999/01/05 03:18:55 bje Exp $ errstatus=0 for file do set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` shift pathcomp= for d do pathcomp="$pathcomp$d" case "$pathcomp" in -* ) pathcomp=./$pathcomp ;; esac if test ! -d "$pathcomp"; then echo "mkdir $pathcomp" mkdir "$pathcomp" || lasterr=$? if test ! -d "$pathcomp"; then errstatus=$lasterr fi fi pathcomp="$pathcomp/" done done exit $errstatus # mkinstalldirs ends here fweelin-0.6/missing0000755000175000017500000002403610547030013013043 0ustar mercmerc#! /bin/sh # Common stub for a few missing GNU programs while installing. # Copyright (C) 1996, 1997, 1999, 2000, 2002 Free Software Foundation, Inc. # Originally by Fran,cois Pinard , 1996. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA # 02111-1307, USA. # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. if test $# -eq 0; then echo 1>&2 "Try \`$0 --help' for more information" exit 1 fi run=: # In the cases where this matters, `missing' is being run in the # srcdir already. if test -f configure.ac; then configure_ac=configure.ac else configure_ac=configure.in fi case "$1" in --run) # Try to run requested program, and just exit if it succeeds. run= shift "$@" && exit 0 ;; esac # If it does not exist, or fails to run (possibly an outdated version), # try to emulate it. case "$1" in -h|--h|--he|--hel|--help) echo "\ $0 [OPTION]... PROGRAM [ARGUMENT]... Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an error status if there is no known handling for PROGRAM. Options: -h, --help display this help and exit -v, --version output version information and exit --run try to run the given command, and emulate it if it fails Supported PROGRAM values: aclocal touch file \`aclocal.m4' autoconf touch file \`configure' autoheader touch file \`config.h.in' automake touch all \`Makefile.in' files bison create \`y.tab.[ch]', if possible, from existing .[ch] flex create \`lex.yy.c', if possible, from existing .c help2man touch the output file lex create \`lex.yy.c', if possible, from existing .c makeinfo touch the output file tar try tar, gnutar, gtar, then tar without non-portable flags yacc create \`y.tab.[ch]', if possible, from existing .[ch]" ;; -v|--v|--ve|--ver|--vers|--versi|--versio|--version) echo "missing 0.4 - GNU automake" ;; -*) echo 1>&2 "$0: Unknown \`$1' option" echo 1>&2 "Try \`$0 --help' for more information" exit 1 ;; aclocal*) if test -z "$run" && ($1 --version) > /dev/null 2>&1; then # We have it, but it failed. exit 1 fi echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified \`acinclude.m4' or \`${configure_ac}'. You might want to install the \`Automake' and \`Perl' packages. Grab them from any GNU archive site." touch aclocal.m4 ;; autoconf) if test -z "$run" && ($1 --version) > /dev/null 2>&1; then # We have it, but it failed. exit 1 fi echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified \`${configure_ac}'. You might want to install the \`Autoconf' and \`GNU m4' packages. Grab them from any GNU archive site." touch configure ;; autoheader) if test -z "$run" && ($1 --version) > /dev/null 2>&1; then # We have it, but it failed. exit 1 fi echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified \`acconfig.h' or \`${configure_ac}'. You might want to install the \`Autoconf' and \`GNU m4' packages. Grab them from any GNU archive site." files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` test -z "$files" && files="config.h" touch_files= for f in $files; do case "$f" in *:*) touch_files="$touch_files "`echo "$f" | sed -e 's/^[^:]*://' -e 's/:.*//'`;; *) touch_files="$touch_files $f.in";; esac done touch $touch_files ;; automake*) if test -z "$run" && ($1 --version) > /dev/null 2>&1; then # We have it, but it failed. exit 1 fi echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. You might want to install the \`Automake' and \`Perl' packages. Grab them from any GNU archive site." find . -type f -name Makefile.am -print | sed 's/\.am$/.in/' | while read f; do touch "$f"; done ;; autom4te) if test -z "$run" && ($1 --version) > /dev/null 2>&1; then # We have it, but it failed. exit 1 fi echo 1>&2 "\ WARNING: \`$1' is needed, and you do not seem to have it handy on your system. You might have modified some files without having the proper tools for further handling them. You can get \`$1Help2man' as part of \`Autoconf' from any GNU archive site." file=`echo "$*" | sed -n 's/.*--output[ =]*\([^ ]*\).*/\1/p'` test -z "$file" && file=`echo "$*" | sed -n 's/.*-o[ ]*\([^ ]*\).*/\1/p'` if test -f "$file"; then touch $file else test -z "$file" || exec >$file echo "#! /bin/sh" echo "# Created by GNU Automake missing as a replacement of" echo "# $ $@" echo "exit 0" chmod +x $file exit 1 fi ;; bison|yacc) echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified a \`.y' file. You may need the \`Bison' package in order for those modifications to take effect. You can get \`Bison' from any GNU archive site." rm -f y.tab.c y.tab.h if [ $# -ne 1 ]; then eval LASTARG="\${$#}" case "$LASTARG" in *.y) SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` if [ -f "$SRCFILE" ]; then cp "$SRCFILE" y.tab.c fi SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` if [ -f "$SRCFILE" ]; then cp "$SRCFILE" y.tab.h fi ;; esac fi if [ ! -f y.tab.h ]; then echo >y.tab.h fi if [ ! -f y.tab.c ]; then echo 'main() { return 0; }' >y.tab.c fi ;; lex|flex) echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified a \`.l' file. You may need the \`Flex' package in order for those modifications to take effect. You can get \`Flex' from any GNU archive site." rm -f lex.yy.c if [ $# -ne 1 ]; then eval LASTARG="\${$#}" case "$LASTARG" in *.l) SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` if [ -f "$SRCFILE" ]; then cp "$SRCFILE" lex.yy.c fi ;; esac fi if [ ! -f lex.yy.c ]; then echo 'main() { return 0; }' >lex.yy.c fi ;; help2man) if test -z "$run" && ($1 --version) > /dev/null 2>&1; then # We have it, but it failed. exit 1 fi echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified a dependency of a manual page. You may need the \`Help2man' package in order for those modifications to take effect. You can get \`Help2man' from any GNU archive site." file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` if test -z "$file"; then file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'` fi if [ -f "$file" ]; then touch $file else test -z "$file" || exec >$file echo ".ab help2man is required to generate this page" exit 1 fi ;; makeinfo) if test -z "$run" && (makeinfo --version) > /dev/null 2>&1; then # We have makeinfo, but it failed. exit 1 fi echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified a \`.texi' or \`.texinfo' file, or any other file indirectly affecting the aspect of the manual. The spurious call might also be the consequence of using a buggy \`make' (AIX, DU, IRIX). You might want to install the \`Texinfo' package or the \`GNU make' package. Grab either from any GNU archive site." file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` if test -z "$file"; then file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file` fi touch $file ;; tar) shift if test -n "$run"; then echo 1>&2 "ERROR: \`tar' requires --run" exit 1 fi # We have already tried tar in the generic part. # Look for gnutar/gtar before invocation to avoid ugly error # messages. if (gnutar --version > /dev/null 2>&1); then gnutar "$@" && exit 0 fi if (gtar --version > /dev/null 2>&1); then gtar "$@" && exit 0 fi firstarg="$1" if shift; then case "$firstarg" in *o*) firstarg=`echo "$firstarg" | sed s/o//` tar "$firstarg" "$@" && exit 0 ;; esac case "$firstarg" in *h*) firstarg=`echo "$firstarg" | sed s/h//` tar "$firstarg" "$@" && exit 0 ;; esac fi echo 1>&2 "\ WARNING: I can't seem to be able to run \`tar' with the given arguments. You may want to install GNU tar or Free paxutils, or check the command line arguments." exit 1 ;; *) echo 1>&2 "\ WARNING: \`$1' is needed, and you do not seem to have it handy on your system. You might have modified some files without having the proper tools for further handling them. Check the \`README' file, it often tells you about the needed prerequirements for installing this package. You may also peek at any GNU archive site, in case some other package would contain this missing \`$1' program." exit 1 ;; esac exit 0 fweelin-0.6/INSTALL0000755000175000017500000002000710715215037012502 0ustar mercmercQuick Start =========== Run configure, make, and make install! Then run 'fweelin'. For more help, please refer to the video tutorials at: http://freewheeling.sourceforge.net/ And read the configuration file: ~/.fweelin/fweelin.xml (once you've run FreeWheeling, this file appears) Browse or sign on to the mailing-list for help. Happy Looping! -JP Mercury. ... Basic Installation ================== These are generic installation instructions. The `configure' shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses those values to create a `Makefile' in each directory of the package. It may also create one or more `.h' files containing system-dependent definitions. Finally, it creates a shell script `config.status' that you can run in the future to recreate the current configuration, a file `config.cache' that saves the results of its tests to speed up reconfiguring, and a file `config.log' containing compiler output (useful mainly for debugging `configure'). If you need to do unusual things to compile the package, please try to figure out how `configure' could check whether to do them, and mail diffs or instructions to the address given in the `README' so they can be considered for the next release. If at some point `config.cache' contains results you don't want to keep, you may remove or edit it. The file `configure.in' is used to create `configure' by a program called `autoconf'. You only need `configure.in' if you want to change it or regenerate `configure' using a newer version of `autoconf'. The simplest way to compile this package is: 1. `cd' to the directory containing the package's source code and type `./configure' to configure the package for your system. If you're using `csh' on an old version of System V, you might need to type `sh ./configure' instead to prevent `csh' from trying to execute `configure' itself. Running `configure' takes awhile. While running, it prints some messages telling which features it is checking for. 2. Type `make' to compile the package. 3. Optionally, type `make check' to run any self-tests that come with the package. 4. Type `make install' to install the programs and any data files and documentation. 5. You can remove the program binaries and object files from the source code directory by typing `make clean'. To also remove the files that `configure' created (so you can compile the package for a different kind of computer), type `make distclean'. There is also a `make maintainer-clean' target, but that is intended mainly for the package's developers. If you use it, you may have to get all sorts of other programs in order to regenerate files that came with the distribution. Compilers and Options ===================== Some systems require unusual options for compilation or linking that the `configure' script does not know about. You can give `configure' initial values for variables by setting them in the environment. Using a Bourne-compatible shell, you can do that on the command line like this: CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure Or on systems that have the `env' program, you can do it like this: env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure Compiling For Multiple Architectures ==================================== You can compile the package for more than one kind of computer at the same time, by placing the object files for each architecture in their own directory. To do this, you must use a version of `make' that supports the `VPATH' variable, such as GNU `make'. `cd' to the directory where you want the object files and executables to go and run the `configure' script. `configure' automatically checks for the source code in the directory that `configure' is in and in `..'. If you have to use a `make' that does not supports the `VPATH' variable, you have to compile the package for one architecture at a time in the source code directory. After you have installed the package for one architecture, use `make distclean' before reconfiguring for another architecture. Installation Names ================== By default, `make install' will install the package's files in `/usr/local/bin', `/usr/local/man', etc. You can specify an installation prefix other than `/usr/local' by giving `configure' the option `--prefix=PATH'. You can specify separate installation prefixes for architecture-specific files and architecture-independent files. If you give `configure' the option `--exec-prefix=PATH', the package will use PATH as the prefix for installing programs and libraries. Documentation and other data files will still use the regular prefix. In addition, if you use an unusual directory layout you can give options like `--bindir=PATH' to specify different values for particular kinds of files. Run `configure --help' for a list of the directories you can set and what kinds of files go in them. If the package supports it, you can cause programs to be installed with an extra prefix or suffix on their names by giving `configure' the option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. Optional Features ================= Some packages pay attention to `--enable-FEATURE' options to `configure', where FEATURE indicates an optional part of the package. They may also pay attention to `--with-PACKAGE' options, where PACKAGE is something like `gnu-as' or `x' (for the X Window System). The `README' should mention any `--enable-' and `--with-' options that the package recognizes. For packages that use the X Window System, `configure' can usually find the X include and library files automatically, but if it doesn't, you can use the `configure' options `--x-includes=DIR' and `--x-libraries=DIR' to specify their locations. Specifying the System Type ========================== There may be some features `configure' can not figure out automatically, but needs to determine by the type of host the package will run on. Usually `configure' can figure that out, but if it prints a message saying it can not guess the host type, give it the `--host=TYPE' option. TYPE can either be a short name for the system type, such as `sun4', or a canonical name with three fields: CPU-COMPANY-SYSTEM See the file `config.sub' for the possible values of each field. If `config.sub' isn't included in this package, then this package doesn't need to know the host type. If you are building compiler tools for cross-compiling, you can also use the `--target=TYPE' option to select the type of system they will produce code for and the `--build=TYPE' option to select the type of system on which you are compiling the package. Sharing Defaults ================ If you want to set default values for `configure' scripts to share, you can create a site shell script called `config.site' that gives default values for variables like `CC', `cache_file', and `prefix'. `configure' looks for `PREFIX/share/config.site' if it exists, then `PREFIX/etc/config.site' if it exists. Or, you can set the `CONFIG_SITE' environment variable to the location of the site script. A warning: not all `configure' scripts look for a site script. Operation Controls ================== `configure' recognizes the following options to control how it operates. `--cache-file=FILE' Use and save the results of the tests in FILE instead of `./config.cache'. Set FILE to `/dev/null' to disable caching, for debugging `configure'. `--help' Print a summary of the options to `configure', and exit. `--quiet' `--silent' `-q' Do not print messages saying which checks are being made. To suppress all normal output, redirect it to `/dev/null' (any error messages will still be shown). `--srcdir=DIR' Look for the package's source code in directory DIR. Usually `configure' can determine that directory automatically. `--version' Print the version of Autoconf used to generate the `configure' script, and exit. `configure' also accepts some other, not widely useful, options. fweelin-0.6/NEWS0000755000175000017500000000201010547030013012132 0ustar mercmercPlease see http://freewheeling.sourceforge.net for most recent news. 2005- Prereleases. 2004- Naraya @ Wolf Creek. Community ritual process. Moving towards general release. 4 new CDs of improvised audio. Polls hosted on website- open source or commercial software? Linux, Mac, or Windows? Thank you to all who responded and helped me decide on the open-source route! Tessa, Shaun, and Mercury start improvised singing circle. Tessa volunteers her laptop to be guinea pig, and it survives!-- now with a Linux looper. Thank You!, dear woman! 2003- Yoga school. Jude presents looper to his UNCA music class. Thanks, Jude. Shaun, Audrey, and the ACAD family in Calgary- looping sessions. Shaun and Mercury- live looping sets. Freewheeling evolves. Thanks guys! June 26, 2002- Eddie and Mercury are working on testing the Linux prototype with our chants and gurgles. Eddie lends his beautiful voice and creative juices on tap. 2000- Max/MSP version with 4 channels of keyboard controlled looping. Proof of concept. fweelin-0.6/README0000755000175000017500000000005710547030013012324 0ustar mercmercPlease read data/.fweelin.rc or ~/.fweelin.rc. fweelin-0.6/COPYING0000755000175000017500000004311010547030011012472 0ustar mercmerc GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. fweelin-0.6/AUTHORS0000755000175000017500000000003711071521701012514 0ustar mercmercJP Mercury fweelin-0.6/THANKS0000755000175000017500000000251010547030013012353 0ustar mercmercGrateful Pauses for This Beautiful Body for telling me when to stop. .. Mom, Dad, Holly, Aasha, Asha, Melchert, Macon, Jude, Eddie, Tangle, Steve Sandberg, Joshua James, Shaun Free Zen, Tessa, The Naraya and the Wolf Creek Faeries, and Cycling 74. The Linux community! The FSF, RT kernel developers, GNU and Debian people, without whom, FreeWheeling would not be possible. -Wolfgang Woehl, Mark Knecht, Shayne O'Connor, Esben Stien, Gregory Maxwell, Plutek, and Sune Mai, my evangelists, critics, funders, beta-testers, and visionaries. -Jesse Chappell for writing SooperLooper, and being so cool about sharing ideas. -Giuliano Pochini, whose outstanding work on drivers for Echo's CardBus audio line has helped me scale down my setup. -Takashi, Jaroslav and the ALSA development team. -Paul Davis and the JACK and Ardour teams. -Peter Hanappe, Josh Green and the giant FluidSynth team. -The SDL people. -Mark Knecht for his feedback and inspiration. -Sean Bolton and the DSSI softsynth team. -Steve Harris, Tim Goetze, Tom Szilagyi- the makers of fine LADSPA effects plugins. -Bob Ham, for his work on Jack-Rack. -Echo Audio for getting their act together and releasing specs for their audio interfaces. -Countless others Everyone who has been in touch and lended kind thoughts. Thank You All fweelin-0.6/TUNING0000755000175000017500000000167710547030013012404 0ustar mercmercSome Suggestions for Tuning Freewheeling's Audio Performance: ************************************************************ on Linux Updated September, 2004 ----------------------- Run hdparm to set DMA & well behaved disk IO. Try: hdparm -c3 -d1 -m16 -A1 -u1 /dev/hda (do for /dev/hdb .. also) If you have a PCI audio interface, run setpci to set PCI latency. First, run 'lspci -v' and find the address of your audio board. Then run: setpci -s 00:07.5 latency_timer=F8 (if your audio is at 00:07.5) Set video depth to 8 or 16 bits. 24 and 32 bits are generally much slower. Use fluxbox, blackbox, or another lightweight window manager on slower machines. Use lower sampling rates to achieve lower latency. Try 64 samples, 32000 Hz, 3 periods per buffer. This works well on several low end audio boards such as ESS Maestro and AC 97. Lower latency is key for live looping! Otherwise, the latency will lag your timing and it will feel very awkward. fweelin-0.6/ChangeLog0000755000175000017500000010154611071522656013237 0ustar mercmercRELEASE v0.6 Friday October 3rd, 2008 Folks, Here is a full 0.6 release. Included are updated Mac and Linux versions. The new Mac version works with the latest Jack version and under OS X Leopard. As you can see from the SVN updates below, there's quite a bit that's new since 0.5.5. Your feedback is always welcome. -~Mercury v0.5.6 - SVN Thursday September 4th, 2008 New Features ------------ * Logarithmic faders and loop levels, conforming to IEC 60-268-18. Level meters and loop faders are now logarithmic, visually graded with 6dB markings. This means you can create much smoother fades using MIDI controllers, and you can see a broader range of levels on-screen. One new configuration parameter controls the maximum dB selectable: Saturday August 30th, 2008 Fixes ----- * Saving over existing snapshots now preserves name * Upgrades to BCF-2000 template Wednesday August 13th, 2008 New Features ------------ * Rename snapshots Press ALT-1 through ALT-9 to rename a snapshot. Label your song sections for easy recall. * Way overhauled BCF-2000 interface The Behringer BCF-2000 MIDI template has been overhauled. Most major functions can be controlled from the surface. Continuously variable loop volumes, overdubs on knob presses, loop selection and triggering, scenes, pulses, and multiple pages of loops. The whole template can be customized by editing the MIDI CC variables at the top of the file. By changing the CCs, you can use it as a template for other control surfaces. A future configuration editor may build on this concept of 'templates with editable settings'. For now, you can edit the file and adjust the most common commands easily. Saturday July 5th, 2008 New Features ------------ * Multiple pages of snapshots 100 snapshots are provided by default (edit this in basics.xml). You can pageup/pagedown through them by holding CTRL or SHIFT and pressing , or . Then use CTRL 1-9 to trigger and SHIFT 1-9 to store. Fixes ----- * Reworked some of the guts to fix crashes. Race condition fixes in block manager. Thanks to Florent and Andrea for your crash reports. They helped nail the bug. Monday Jun 16th, 2008 New Features ------------ * Create snapshots for playing loops - Create / save / load snapshots. All loop levels and playing loops are remembered. To create a snapshot, hold SHIFT and press 1-9. The snapshot is shown in a popup window. - An easy way to switch between song sections. To switch snapshots, hold CTRL and press 1-9. - Snapshots are saved/loaded in scenes. Still to do on snapshots: Renaming, fading, paging through snapshots on display, more flexible synchronization. * Easily adjust levels for all selected loops To use: Select some loops. Hold CTRL and press UP/DOWN repeatedly to adjust all loop levels. Or, hold CTRL and use the mousewheel on any loop. All selected loops are adjusted. This works well when you have many loops that are overdriving Freewheeling's outputs. The limiter is bouncing around. You could reduce the output level, but this approach is more flexible- and the results are saved in snapshots and scenes. Friday Nov 9th, 2007 New Features ------------ * Completely revamped configuration system- Better splitting and organization- There are now many configuration files. The configuration is divided into 'interfaces'. Each interface defines behavior and display related to a hardware interface. You can build whole functionality for a given MIDI interface such as a fader box, and share it on the Internet. This should help the current situation where people are patching together bits of each other's configurations. Sunday July 8th, 2007 New Features ------------ * Working on real-time pitch and time stretching- not yet usable! * Adjustable global tuning for Fluidsynth: From .fweelin.rc: Adjusts Fluidsynth to -31.76 cents tuning, or 432 Hz tuning. Fixes ----- * Fixed a bug where some non-critical events (such as loading or selecting loops) could be missed. * Fixed glitch in memory manager that could cause spontaneous exits, usually when erasing loops * Better clipping of out-of-range MIDI values * Removed old 'DelayProcess' code for dealing with real-time events. New code uses real-time event manager. Tuesday March 13th, 2007 New Features ------------ * Erase-selected-loops command Shift+Space now erases all selected loops. * New ability to tag patch banks By tagging patch banks, you can change the way Freewheeling responds depending on which patches you have selected. For example, I use Freewheeling with a B3 organ softsynth. My organ patches are arranged in a patch bank. I've tagged that patch bank, and configured Freewheeling to respond differently when that patch bank is active. So, when I am on an organ patch, my faders control the B3 drawbars instead of their usual Freewheeling functions. You can, of course, change any of Freewheeling's behaviors depending on the patch bank selected. For more info, check the 'SYSTEM_cur_patchbank_tag' variable in the configuration. * Receive and transmit MIDI channel pressure (aftertouch) messages * New 'routethroughpatch' configuration option for MIDI events allows you to send deliberate MIDI messages to the port(s) and channel(s) for the current patch. An example configuration is provided that changes the behavior of the modwheel (CC #1). When enabled, the modwheel value is modulated by aftertouch. This allows me to control vibrato (CC #1) on my softsynths with pressure on the keys. The modwheel and pressure values are summed together and sent out as a control change message. If I am playing several softsynth channels from my one keyboard, the aftertouch then affects all the channels seamlessly. Fixes ----- * Fixed problem installing configuration files from folders with spaces. 2007-01-25 v0.5.5 New Features ------------ * MIDI sync transmit - Toggle-able sync transmit on definable output ports A friend of mine who is an avid Ableton Live user asked me to collaborate with him. I realized that this was a perfect opportunity to develop MIDI sync. Freewheeling already syncs via the Jack transport, but Ableton and other hardware sequencers are not Jack-aware. As of this version, Freewheeling transmits MIDI sync on definable MIDI outs. By default, MIDI clock is sent to the first MIDI output. To send MIDI clock, you must first enable it-- Go to the sync panel (shift+F1) and press shift+F2. MIDI Sync Transmit is now enabled (the light glows). Now, you can begin playing, and create a pulse. You can either tap the pulse tempo, or you can record a loop and use it as the pulse tempo. Once the pulse begins, Freewheeling starts the external sequencer at bar 1. If you deselect the pulse (F6 for free timing), Freewheeling will stop your external sequencer. Any pulse you select will begin transmitting MIDI sync. Freewheeling does not yet receive MIDI sync, so you can't yet use Ableton as tempo master. * Selecting and working with multiple loops You can now toggle (t) and fade (MIDI CC89) volume of several loops together. You can select loops by right clicking on them, or by shift+clicking on them, or by shift+pressing their trigger. You can select all playing loops by pressing the keypad asterisk. You can select all idle loops with shift+kp asterisk. Ctrl+kp asterisk inverts the current selection, and alt+kp asterisk unselects all loops. This is the first step towards having multiple scenes of loops that you can trigger/fade between. * New configuration allows MIDI control of: Undo- CC#51 Patch bank changing by fader- CC #88 Patch bank changing by buttons- CC #53 / #54 * Continuously variable feedback for overdubs You can now change the loop feedback during overdubbing. You can realtime vary the amount of the loop that is fed-back into itself. The current feedback level is shown on-screen. By default, MIDI CC#87 controls the loop feedback. The feedback controls are configurable in .fweelin.rc, here: * New configuration allows browsing via MIDI program change I developed this config for the CME-UF8 master controller, which has a rotary encoder that sends MIDI program change messages. With the new config, a MIDI program change knob can be used to spin through scenes, loops, or softsynth patches. Also, controller #50 is configured to act as a shift key for faster scrolling through browsers. * Save Current Scene (F7) now overwrites an existing scene. * Save New Scene (shift + F7) forces a new scene to be created. When overwriting, sequential backups are made with the extensions '.backup.1' '.backup.2' etc. Scene file data is very small. Loops are stored separately, so there is no duplication of unmodified loops. * Sync panel can now be toggled with Shift-F1 Defaults to OFF Fixes ----- - Better stability in Event Manager- should fix crashes - Deliberate MIDI output of events now follows the ports and channels you specify. Incidental echoing of MIDI events follows the settings from the current patch. - Fixed crash on repeat loading of scenes/loading of large scenes - No more console-dependent startup questions when a new version is installed. - Library path can now be specified relative to home folder (for example, ~/fw-lib) - Stream out now shows size in mb, for less frantic update 2006-11-21 v0.5.3 Many thanks to Danni Coy, who has contributed very significantly to this release. Actually, he did most of the work! New Features ------------ * MAC OS X support FreeWheeling is now cross-platform. A universal binary is now available for both Intel & PPC Mac platforms. * Multiple Audio Formats (Contributed by Danni- Thank You!) Save and load loops and live streams in OGG, WAVE, AU, and FLAC. * OGG encoding quality setting in configuration * More flexible MIDI control of external synths. - Combination patches allow you to split one MIDI controller into a range of zones. This allows you to control several different sounds or softsynths from one MIDI control source. A combipatch defines the zones, as well as the output MIDI port and channel that each zone sends to. You can also send MIDI program and bank change messages for each zone, allowing you to switch programs on external synths. All of this functionality is integrated into the patch browser, so you can seamlessly control other synth apps and sound modules from within FreeWheeling. See 'examples/combipatchdemo.xml' for an example configuration. - Added 'suppressprogramchanges' option for patch banks With suppressprogramchanges=1, no MIDI bank and program change messages are sent when patches are changed within a patch bank. This is useful when you have a softsynth loaded with patches on different channels and you merely want to switch channels- each patch is mapped to a different channel, but you don't want program change messages being sent to mess up your patches. Use this for banks of Linuxsampler channels. - Added 'separatechannels' option for patch banks With separatechannels=0, patches mapped to different channels appear in the same patch bank. With this option, you can have a collection of several patches on different channels that appear together in one list for browsing. This is useful for sampling synths where your patches are pre-loaded onto channels. With separatechannels=1, the old behavior is used. The old behavior splits each channel into a separate bank. This works well for DSSI softsynths, where many synths run on the same port, but each channel accesses a different synth and different set of patches. Fixes ----- * MIDI thread now runs at high priority FIFO, rather than low priority FIFO-- this may improve MIDI performance, and hopefully will not affect stability. * Fixed configuration bug that broke 'CTRL+click' loop renaming. 2006-05-17 v0.5.2a Bug Fix Release --------------- * v0.5.2 MIDI port switching was broken. (Problem in the configuration .fweelin.rc). The configuration in this release should work. No other changes have been made. 2006-05-13 v0.5.2 The Patch Browser Upgrade New Features ------------ * Integrated patch browsers for external audio apps * Bank and program changes are now sent based on the patches you define * MIDI outputs are now switched as part of the integrated patch browser * Automatic patch list generation for DSSI softsynths Detail: The Fluidsynth patch browser has been expanded to provide patch browsing for external synths/apps. You can define your patches (MIDI port, channel, bank, program, and name) in external XML patch files. All your patches, internal and external, now appear in the patch browser. The browser now has several pages, one for each MIDI port and channel for which you have defined patches. Therefore, if you have Hexter on channel 1 of MIDI output 1, and WhySynth on channel 2 of MIDI output 1, you can independently browse your Hexter and WhySynth patches right from within Freewheeling. Freewheeling sends the right bank and program changes out the right MIDI port based on your patch definitions. It also echoes your MIDI events to the right place, so that you can switch one keyboard between several softsynths. When you have the patch browser selected, you can use the left/right arrow keys to switch between browser sections. This causes your incoming MIDI events to be switched from one port to another- as defined in your ~/.fweelin.rc and patch XML files. This way, you can quickly switch between softsynths without leaving Freewheeling's interface. To use this feature, please read 'examples/readme.txt' for setup info. I will likely be expanding this to include 'combi' type actions where you can custom configure your MIDI signal to be sent to several softsynths. Then you could, for example, play Hexter with your left hand and Linuxsampler with your right hand. * Configuration files now live in ~/.fweelin/ ~/.fweelin.rc will be moved to ~/.fweelin/.fweelin.rc when you start version 0.5.2. Fixes ----- * Fixed startup segfault when running without integrated FluidSynth 2006-03-22 v0.5.1 Thank you to all for good ideas and inspiration over the summer and winter. Many thanks to Paul Davis for hooking me up with a great Linux Audio development gig. And thanks to an anonymous donor for his contribution, and to Dubphil and Paul Brossier for beta testing. ** FreeWheeling now requires libgnutls11-dev (gnutls-openssl) instead of openssl (Thanks, Piem). New Features ------------ * Significantly less memory usage-- more than 20 megabytes less. Thanks to Drobilla for pointing out the issue with thread stack size. * New scripts (see scripts/ folder) to help you manage a library of loops. You can now bath move, delete, and archive loops & scenes by date. * Jack transport sync- - Master and slave mode For sync to work, you must first create a pulse, either by recording a loop and pressing F1, or by tapping a pulse by tapping F2 twice. Freewheeling tries to become the Jack timebase master, but if another app is master, it switches to slave mode. In master mode, Freewheeling generates beats and bar counts for every repetition of the currently selected pulse. In slave mode, Freewheeling receives beats and bar counts and syncronizes the currently selected pulse to them. For both master and slave modes, you can adjust the number of bars/beats per pulse using: Ctrl/Shift + S - adjust timebase You can also switch between sync to bars or sync to beats using: Alt + S - switch bars/beats sync Note that in master mode, FW is currently hard-wired to generate 4 beats per bar. Since this is preliminary code, not a big deal. * New user interface - Progress bar for saving and loading loops and scenes - Better organization of help page with clear sections - Mouse support - Click on loops triggers them. - Space + Click erases loops. - Mousewheel on loops now adjusts loop volumes-- very convenient when you are mixing and playing with improvisations. These can be configured. See 'loop-clicked' in .fweelin.rc. - Joystick support - Joystick buttons can now trigger events. For example, I have used FW with a DDR dance mat to trigger loops. See 'joybutton' in .fweelin.rc. - New 'engage' and 'shot' options in trigger-loop. 'Engage' forces a loop to ON or OFF, overriding the default toggle behavior. You can use it to create triggers that play short bursts, rather than long loops. 'Shot' to be implemented. * Stability improvements - Better thread safety and design improvements to the real-time memory manager have improved stability. * Significant improvements to loop/scene management and browsing - You can now give loops and scenes your own names - New names are stored within the filename of library files - Expanded browser window shows several items at once - Browser now sorts so that newer loops and scenes are first * Better handling of looppoints - Resolved issue with clicking at the looppoint on reloaded loops. - Resolved sporadic clicks on syncronized loops. * Better handling of loading/saving loops * Adjustable video loop delay - You can now adjust the performance of FreeWheeling by changing the delay between video refreshes. Several people asked for this feature, because FW is processor-heavy on the video side. The video thread does run at a low priority, and so it should not affect the performance of other realtime audio threads. However, the system may get sluggish, and if this happens, you may want to increase the delay in .fweelin.rc: Fixes ----- * Fixed 'glibc double free' segfault- FW should now run when compiled with GCC 4.0. * Adjusted the way F2 tap tempo works- tapping a new tempo with F2 is now more responsive, but less tolerant of mistakes * Fixed 'pure virtual method called' segfault * Fixed segfault when browsing past end of FluidSynth patch list * Various fixes to reduce CPU hogging * Merged patches from Piem's debian package: MaxVol, compile fixes for GCC 4.0, and removal of non-free elements * FW can now run without physical JACK inputs or outputs. Thanks to Piem for this patch. 2005-05-02 v0.5pre4 Many thanks to Sune Mai for several clever fixes, to Plutek for your generous donation, and to all of you for inspiration and feedback: Wolfgang Woehl, Mark Knecht, Shayne O'Connor, Esben Stien, Gregory Maxwell... ** FreeWheeling now requires libvorbisfile. New Features ------------ * Go back to previous improvisations - Saving -and- loading of loops and scenes of many loops - Integrated browser for scenes, loops, and FluidSynth patches - Loops and scenes are sorted by time in browser QuickStart: Use F8 to save a loop, F7 to save a scene of all loops, F9 to toggle auto-saving of all loops, 'b' to switch browsers from FluidSynth to Loops to Scenes, 'enter' to load the selected loop or scene, Shift +/- jumps to the next group of scenes or loops on disk (at least an hour different in time) When loading a scene, the loops are restored to their original placement. When loading a single loop, it goes to the footswitch (SW) by default. You can then move it to any QWERTY or MIDI key by pressing that key. FreeWheeling no longer saves in folders save1, save2, etc. A new library folder (by default, fw-lib/) contains all your loops, scenes, and live mixes. A new script scripts/godelete-date, can be used to delete loops and scenes from your library by date. * Full stereo support - Individual inputs configurable stereo or mono - Automatic stereo or mono loops - FluidSynth in stereo or mono QuickStart: In ~/.fweelin.rc find: This configures two mono and one stereo input. FreeWheeling no longer auto-connects to system inputs and outputs. You only need to configure what kinds of inputs you'd like. Please note that, for now, you need to manually add displays and keyboard mappings for any inputs you add. The rest is handled automatically. * Multiple ALSA MIDI outputs - Send live MIDI messages to different MIDI ports to control different Linux apps in real-time QuickStart: Use "m" key to switch MIDI outputs. The default configuration, defines two MIDI outputs. "m" toggles between the two outputs and the internal FluidSynth. * Configurable limiter - Max gain, threshold, and release rate can be changed - By default, limiter no longer raises gain above 100% See help in ~/.fweelin.rc * Input level displays - Peak levels for each input are now shown * Footpedal volume adjust configuration QuickStart: Use MIDI controller 1 to control individual input levels. Press keyboard 1-4 to select input. Then move CC1 to adjust volume. Or press and hold keyboard 1-4 while moving CC1 to jump to a new pedal value without adjusting volume. In ~/.fweelin.rc, see: You can change the CC# and max volume. * Laptop keyboard configuration QuickStart: If you are using FW on a laptop, you probably don't have easy access to some keys. I've provided a laptop keyboard configuration which remaps some keys. In the help pages, the new keys are shown in square brackets. To enable this configuration, edit ~/.fweelin.rc: init="0" becomes init="1" * Config file version checking - If your config file is out of date, FreeWheeling will ask whether you'd like a new one installed. This means you never have to manually erase ~/.fweelin.rc. Fixes ----- * fixed MIDI note off being misinterpreted on keyboards that send note on with velocity 0 * JACK ports are no longer auto-connected * fixed startup hang on some systems (mutex init problem) * fixed bug in block memory allocator Recycle() that causes a segfault during bursting of many events * compile fix error: 'ISO C++ forbids cast to non-reference type used as l-value' in RTNew() * footswitch is now controller 64 by default, not 67 * several keys have been remapped- see the help for details 2005-03-11 v0.5pre3 New Features ------------ * A new way to tap downbeat and tempo (tap-pulse event) * Switching of metronome sound for pulses (switch-metronome event) * FreeWheeling events can now trigger MIDI events, so you can control other audio apps from within FluidSynth-- For example, you can fire off changes to your modular synths from your keyboard or footpedals. This eliminates the need for an extra MIDI router app, since it is now built in to FreeWheeling. Your custom FreeWheeling setup defines how MIDI events are generated. * More flexible, clearer configuration syntax, with better error checking and colored warning messages. * Full input & output implementation of MIDI program change and pitch bend messages. * An example of the new MIDI output features- A MIDI patch changer has been configured using the left/right arrow keys. An on screen display shows patch number. See .fweelin.rc and video tutorial: Hookups. * Faster, tighter memory management for events. * Scripts are now included that load FreeWheeling and Hexter DX7 softsynth, connect to LADSPA reverb and tube amp sim- see scripts/README. Fixes ----- * fixed config bug that may cause "PreallocatedType: no instance available" errors on startup * compile fix on Mandrake GCC 3.4.x - 'parenthesized type-id' error 2005-01-19 v0.5pre2 New Features * Saving and autosaving of loops in OGG format- loops and live mixes are saved in their own folders * Real-time toggling of FluidSynth * Multipage help * Documentation for 'z'/'x' loop octave Fixes * configure check for SDL_gfx filledPieRGBA vs filledpieRGBA * configure now gives websites for dependent libraries * added XInitThreads to fix 'Xlib async reply' error 2005-01-03 v0.5pre1 - first public prerelease 2003 -2004 v0.1, 0.2, 0.3, 0.4 (internal) many internal changes-- * moving from OpenGL to 2-D SDL * loop visuals * downbeat awareness * memory manager * event manager * block extended data * configuration system * many bugfixes These form the foundation of FreeWheeling as a modular looping platform. 2002-06-05 FreeWheeling (then 'dogon listening device') * initial Linux version based on Mac MAX/MSP prototype