├── Makefile.am ├── AUTHORS ├── data ├── basic.sf2 ├── bcf2000-preset.mid ├── fonts │ └── truetype │ │ └── ttf-bitstream-vera │ │ ├── Vera.ttf │ │ ├── VeraBd.ttf │ │ └── COPYING ├── gdb-stackdump-cmds ├── patches-b3.xml ├── Makefile.am ├── patches-channels.xml ├── interfaces.xml ├── bcf2000-help.txt ├── fweelin.xml ├── midifootswitch.xml ├── browsers.xml ├── rme-hdsp.xml ├── patches3.xml ├── graphics.xml ├── dancemat.xml ├── pckeyboard.xml └── basics.xml ├── scripts ├── phat1-echo.rack ├── vocalverb.rack ├── phat1-basic.rack ├── gofweel-dx7 ├── killfweel ├── waitjackports ├── godelete-date ├── gomv-date ├── goarchive-date ├── patch-jack-rack-loadfile ├── waitalsaports ├── goarchive-scene ├── go-import-markers ├── godx7 ├── README ├── gofweel └── patch-ghostess-xml-patchlist ├── MacOSX ├── freewheeling.icns ├── SDLMain.nib │ ├── objects.nib │ ├── classes.nib │ └── info.nib ├── English.lproj │ └── InfoPlist.strings ├── fweelin_Prefix.pch ├── SDLMain.h ├── Info.plist ├── FweelinMac.h ├── FweelinMac.mm └── README-MAC ├── README ├── .gitignore ├── .travis.yml ├── TUNING ├── NEWS ├── src ├── fweelin_rcu.cc ├── fweelin_osc.h ├── Makefile.am ├── fweelin_datatypes.cc ├── stacktrace.h ├── fweelin_fluidsynth.h ├── fweelin_sdlio.h ├── fweelin_amixer.h ├── fweelin.cc ├── fweelin_audioio.h ├── fweelin_paramset.h ├── fweelin_looplibrary.h ├── fweelin_osc.cc ├── fweelin_rcu.h ├── fweelin_paramset.cc ├── fweelin_videoio.h ├── fweelin_midiio.h └── fweelin_fluidsynth.cc ├── THANKS ├── examples ├── combipatchdemo.xml └── README ├── configure.ac ├── missing ├── compile └── README.md /Makefile.am: -------------------------------------------------------------------------------- 1 | SUBDIRS = src data 2 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | JP Mercury 2 | -------------------------------------------------------------------------------- /data/basic.sf2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/free-wheeling/freewheeling/HEAD/data/basic.sf2 -------------------------------------------------------------------------------- /data/bcf2000-preset.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/free-wheeling/freewheeling/HEAD/data/bcf2000-preset.mid -------------------------------------------------------------------------------- /scripts/phat1-echo.rack: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/free-wheeling/freewheeling/HEAD/scripts/phat1-echo.rack -------------------------------------------------------------------------------- /scripts/vocalverb.rack: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/free-wheeling/freewheeling/HEAD/scripts/vocalverb.rack -------------------------------------------------------------------------------- /MacOSX/freewheeling.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/free-wheeling/freewheeling/HEAD/MacOSX/freewheeling.icns -------------------------------------------------------------------------------- /scripts/phat1-basic.rack: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/free-wheeling/freewheeling/HEAD/scripts/phat1-basic.rack -------------------------------------------------------------------------------- /MacOSX/SDLMain.nib/objects.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/free-wheeling/freewheeling/HEAD/MacOSX/SDLMain.nib/objects.nib -------------------------------------------------------------------------------- /scripts/gofweel-dx7: -------------------------------------------------------------------------------- 1 | #Restart FreeWheeling, and Hexter, and link them together with FX 2 | ./killfweel 3 | ./gofweel 4 | ./godx7 5 | -------------------------------------------------------------------------------- /MacOSX/English.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/free-wheeling/freewheeling/HEAD/MacOSX/English.lproj/InfoPlist.strings -------------------------------------------------------------------------------- /data/fonts/truetype/ttf-bitstream-vera/Vera.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/free-wheeling/freewheeling/HEAD/data/fonts/truetype/ttf-bitstream-vera/Vera.ttf -------------------------------------------------------------------------------- /data/fonts/truetype/ttf-bitstream-vera/VeraBd.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/free-wheeling/freewheeling/HEAD/data/fonts/truetype/ttf-bitstream-vera/VeraBd.ttf -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Please read data/config-help.txt in the source tree 2 | 3 | The same file can also be found at ~/.fweelin/config-help.txt 4 | after freewheeling is installed and has run for the first time 5 | -------------------------------------------------------------------------------- /MacOSX/fweelin_Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'fweelin' target in the 'fweelin' project 3 | // 4 | 5 | #include "SDL.h" 6 | 7 | #ifdef __OBJC__ 8 | #import 9 | #endif 10 | -------------------------------------------------------------------------------- /scripts/killfweel: -------------------------------------------------------------------------------- 1 | #Stop all of these tasks.. 2 | killall jack-dssi-host 3 | killall ghostess 4 | killall -s KILL fweelin 5 | killall -s KILL beatrix 6 | killall linuxsampler 7 | killall jack-rack 8 | killall md 9 | ~/gokeys 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | Makefile 2 | autom4te.cache/ 3 | config.log 4 | config.status 5 | data/Makefile 6 | src/Makefile 7 | src/*.o 8 | src/.Tpo 9 | src/.deps/ 10 | src/fweelin 11 | src/elastin/.deps/ 12 | src/elastin/.dirstamp 13 | src/elastin/*.o 14 | **/fweelin-stackdump 15 | -------------------------------------------------------------------------------- /data/gdb-stackdump-cmds: -------------------------------------------------------------------------------- 1 | set prompt 2 | echo \n\n*** Stacktrace\n 3 | where 4 | echo \n\n*** Symbols\n 5 | frame 4 6 | set $x = 50 7 | while ($x) 8 | info locals 9 | up 10 | set $x-- 11 | end 12 | echo \n*** Backtrace All Threads\n\n 13 | thread apply all bt 14 | echo \n--- 15 | detach 16 | quit 17 | -------------------------------------------------------------------------------- /scripts/waitjackports: -------------------------------------------------------------------------------- 1 | # Script to wait for named JACK ports to appear 2 | # 3 | # usage: waitjackports 4 | # 5 | # where name is the full or partial client name (grep search will be done) 6 | # 7 | # prints all ports belonging to the named client 8 | 9 | JACK_NAME=$1 10 | 11 | while ((`jack_lsp | grep $JACK_NAME | awk 'END { print NR }'` == 0)) 12 | do 13 | sleep 0.1 14 | done 15 | 16 | jack_lsp | grep $JACK_NAME 17 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | dist: bionic 2 | language: cpp 3 | compiler: gcc 4 | 5 | if: branch IN (master , development) 6 | 7 | before_install: 8 | - sudo apt-get update -qq 9 | - sudo apt-get -y build-dep freewheeling 10 | # build-dep is not sufficient, we need to explicitly install liblo-dev 11 | - sudo apt-get -y install liblo-dev 12 | 13 | script: 14 | - autoreconf -if 15 | - ./configure 16 | - make 17 | - sudo make install 18 | - make installcheck 19 | -------------------------------------------------------------------------------- /MacOSX/SDLMain.nib/classes.nib: -------------------------------------------------------------------------------- 1 | { 2 | IBClasses = ( 3 | {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }, 4 | { 5 | ACTIONS = {quitFW = id; setMIDIInput = id; showHelp = id; toggleDebugMode = id; }; 6 | CLASS = SDLMain; 7 | LANGUAGE = ObjC; 8 | OUTLETS = {midiInputSel = NSPopUpButton; }; 9 | SUPERCLASS = NSObject; 10 | } 11 | ); 12 | IBVersion = 1; 13 | } -------------------------------------------------------------------------------- /data/patches-b3.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /scripts/godelete-date: -------------------------------------------------------------------------------- 1 | # Aid for trimming loop/scene libraries 2 | # 3 | # This script can be used in the FreeWheeling library folder (fw-lib/ by default) 4 | # to delete all loops & scenes with a specific date- 5 | # 6 | # For example: godelete-date "Apr 15" deletes all files from April 15. Don't forget quotes! 7 | # godelete-date "Apr 16 21:" deletes all files from April 16 from 9pm-10pm. 8 | # 9 | # No files are deleted before prompting you 10 | # 11 | echo Found these files.. 12 | ls -lt | grep "$1" 13 | rm -i `ls -lt | grep "$1" | awk '{ print $9 }'` 14 | -------------------------------------------------------------------------------- /data/Makefile.am: -------------------------------------------------------------------------------- 1 | fweelin_dirname=fweelin 2 | fonts_path=fonts/truetype/ttf-bitstream-vera 3 | fweelindir = $(datadir)/$(fweelin_dirname) 4 | fontsdir = ${datadir}/$(fweelin_dirname)/${fonts_path} 5 | 6 | fweelin_DATA = *.txt *.xml *.mid basic.sf2 gdb-stackdump-cmds 7 | fonts_DATA = fonts/truetype/ttf-bitstream-vera/* 8 | 9 | 10 | install-data-hook: 11 | sed -i "s///" $(DESTDIR)$(fweelindir)/fweelin.xml 12 | 13 | uninstall-hook: 14 | -cd ${fweelindir} && rmdir -p ${fonts_path} 15 | -rmdir $(fweelindir) 16 | -------------------------------------------------------------------------------- /MacOSX/SDLMain.h: -------------------------------------------------------------------------------- 1 | /* SDLMain.m - main entry point for our Cocoa-ized SDL app 2 | Initial Version: Darrell Walisser 3 | Non-NIB-Code & other changes: Max Horn 4 | 5 | Feel free to customize this file to suit your needs 6 | */ 7 | 8 | #import 9 | 10 | @interface SDLMain : NSObject 11 | { 12 | IBOutlet NSPopUpButton *midiInputSel; 13 | } 14 | - (IBAction)setMIDIInput:(id)sender; 15 | - (IBAction)toggleDebugMode:(id)sender; 16 | - (IBAction)quitFW:(id)sender; 17 | - (IBAction)showHelp:(id)sender; 18 | 19 | - (void)clearMIDIInputList; 20 | - (void)addMIDIInputSource:(NSString *)name; 21 | @end 22 | -------------------------------------------------------------------------------- /scripts/gomv-date: -------------------------------------------------------------------------------- 1 | # Aid for managing loop/scene libraries 2 | # 3 | # This script can be used in the FreeWheeling library folder (fw-lib/ by default) 4 | # to move all loops & scenes with a specific date- 5 | # 6 | # For example: gomv-date "Apr 15" test/ moves all files from April 15 to folder 'test'. Don't forget quotes! 7 | # gomv-date "Apr 16 21:" old/ moves all files from April 16 from 9pm-10pm to folder 'old'. 8 | # 9 | # No files are moved before prompting you. 10 | # 11 | echo Found these files.. 12 | ls -lt | grep "$1" 13 | echo "Move these files to $2? (Enter=Yes, CTRL-C=Abort)" 14 | read 15 | mv -i -v `ls -lt | grep "$1" | awk '{ print $9 }'` $2 16 | -------------------------------------------------------------------------------- /MacOSX/SDLMain.nib/info.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBDocumentLocation 6 | 987 57 356 240 0 0 1440 878 7 | IBEditorPositions 8 | 9 | 29 10 | 82 376 205 44 0 0 1440 878 11 | 12 | IBFramework Version 13 | 446.1 14 | IBOpenObjects 15 | 16 | 339 17 | 18 | IBSystem Version 19 | 8L2127 20 | 21 | 22 | -------------------------------------------------------------------------------- /scripts/goarchive-date: -------------------------------------------------------------------------------- 1 | # Aid for managing loop/scene libraries 2 | # 3 | # This script can be used in the FreeWheeling library folder (fw-lib/ by default) 4 | # to archive all loops & scenes with a specific date- 5 | # 6 | # For example: goarchive-date "Apr 15" test archives all files from April 15 to archive 'test.tar.bz2'. 7 | # Don't forget quotes! 8 | # goarchive-date "Apr 16 21:" old archives all files from April 16 from 9pm-10pm to archive 'old.tar.bz2'. 9 | # 10 | # No files are archived before prompting you. 11 | # 12 | echo Found these files.. 13 | ls -lt | grep "$1" 14 | echo "Archive these files to $2.tar.bz2? (Enter=Yes, CTRL-C=Abort)" 15 | read 16 | tar cjvf $2.tar.bz2 `ls -lt | grep "$1" | awk '{ print $9 }'` 17 | -------------------------------------------------------------------------------- /scripts/patch-jack-rack-loadfile: -------------------------------------------------------------------------------- 1 | --- jack-rack-1.4.3/src/main.c 2 | +++ jack-rack-1.4.3/src/main.c 3 | 96a97 4 | > printf(" -f, --file %s\n", _("Load .rack at start")); 5 | 106,107c107,109 6 | < 7 | < const char * options = "hps:ionc:tD:"; 8 | --- 9 | > char *loadfile = 0; 10 | > 11 | > const char * options = "hps:ionc:tDf:"; 12 | 118a121 13 | > { "file", 1, NULL, 'f' }, 14 | 211a215,219 15 | > 16 | > case 'f': 17 | > loadfile = (char *) malloc(sizeof(char) * (strlen(optarg)+1)); 18 | > strcpy(loadfile,optarg); 19 | > break; 20 | 237c245,256 21 | < 22 | --- 23 | > 24 | > /* Load a file at startup? */ 25 | > if (loadfile) { 26 | > int err; 27 | > 28 | > printf("Loading file: '%s'\n",loadfile); 29 | > err = ui_open_file (global_ui, loadfile); 30 | > 31 | > if (!err) 32 | > ui_set_filename (global_ui, loadfile); 33 | > } 34 | > 35 | -------------------------------------------------------------------------------- /data/patches-channels.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /MacOSX/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIconFile 10 | freewheeling.icns 11 | CFBundleIdentifier 12 | com.yourcompany.fweelin 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | MAC 23 | NSMainNibFile 24 | SDLMain 25 | NSPrincipalClass 26 | NSApplication 27 | 28 | 29 | -------------------------------------------------------------------------------- /scripts/waitalsaports: -------------------------------------------------------------------------------- 1 | # Script to wait for named ALSA midi ports to appear 2 | # 3 | # usage: waitalsaports 4 | # 5 | # where name is the full or partial client name (grep search will be done) 6 | # 7 | # prints the port numbers for system MIDI input and client MIDI input, 8 | # respectively 9 | # 10 | # typically they are 72:0 128:0 11 | 12 | ALSA_NAME=$1 13 | 14 | # **** You will have to change the following line to reflect the name of your MIDI hardware 15 | # On my system aconnect -li reports client 72: 'MidiSport 2x2', so the name can be any subset of that: 16 | 17 | #ALSA_IN_NAME=MidiSport 18 | #ALSA_IN_NAME=PCR 19 | ALSA_IN_NAME=BCF 20 | 21 | while ((`aconnect -lo | grep $ALSA_NAME | awk 'END { print NR }'` == 0)) 22 | do 23 | sleep 0.1 24 | done 25 | 26 | ALSA_SYSTEM_MIDI=`aconnect -lo | grep $ALSA_IN_NAME | grep client | awk '{ print $2 }'`0 27 | ALSA_CLIENT_MIDI=`aconnect -lo | grep $ALSA_NAME | grep client | awk '{ print $2 }'`0 28 | echo $ALSA_SYSTEM_MIDI $ALSA_CLIENT_MIDI 29 | -------------------------------------------------------------------------------- /MacOSX/FweelinMac.h: -------------------------------------------------------------------------------- 1 | // 2 | // FweelinMac.h 3 | // fweelin 4 | // 5 | 6 | #ifndef __FWEELIN_MAC_H__ 7 | #define __FWEELIN_MAC_H__ 8 | 9 | // Interface class between Objective-C Mac OS X code and C++ Fweelin code 10 | class FweelinMac { 11 | public: 12 | 13 | // Performs setup/takedown on a new pthread to make it behave well with Cocoa 14 | void SetupCocoaThread(); 15 | void TakedownCocoaThread(); 16 | 17 | void *autoreleasepool; 18 | 19 | // MIDI input list 20 | static void ClearMIDIInputList(); 21 | static void AddMIDIInputSource(char *name); 22 | static void SetMIDIInput(int idx); 23 | 24 | // Menu shortcuts to commands 25 | static void SetDebugMode(int active); 26 | static void Quit(); 27 | static void ShowHelp(); 28 | 29 | static void LinkSDLMain (void *m) { sdlmain = m; }; 30 | static void *sdlmain; // Pointer to instance of SDLMain 31 | 32 | static void LinkFweelin (void *fw) { fweelin = fw; }; 33 | static void *fweelin; // Pointer to instance of Fweelin 34 | }; 35 | 36 | #endif -------------------------------------------------------------------------------- /TUNING: -------------------------------------------------------------------------------- 1 | Some Suggestions for Tuning Freewheeling's Audio Performance: 2 | ************************************************************ 3 | 4 | on Linux 5 | 6 | Updated September, 2004 7 | ----------------------- 8 | 9 | Run hdparm to set DMA & well behaved disk IO. Try: 10 | hdparm -c3 -d1 -m16 -A1 -u1 /dev/hda (do for /dev/hdb .. also) 11 | 12 | If you have a PCI audio interface, run setpci to set PCI latency. 13 | First, run 'lspci -v' and find the address of your audio board. Then run: 14 | setpci -s 00:07.5 latency_timer=F8 15 | (if your audio is at 00:07.5) 16 | 17 | Set video depth to 8 or 16 bits. 24 and 32 bits are generally much slower. 18 | 19 | Use fluxbox, blackbox, or another lightweight window manager on slower 20 | machines. 21 | 22 | Use lower sampling rates to achieve lower latency. Try 64 samples, 32000 Hz, 23 | 3 periods per buffer. This works well on several low end audio boards such as 24 | ESS Maestro and AC 97. 25 | 26 | Lower latency is key for live looping! Otherwise, the latency will lag your 27 | timing and it will feel very awkward. 28 | 29 | 30 | -------------------------------------------------------------------------------- /scripts/goarchive-scene: -------------------------------------------------------------------------------- 1 | # Aid for managing loop/scene libraries 2 | # 3 | # This script can be used in the FreeWheeling library folder (fw-lib/ by default) 4 | # to archive -one scene plus all the loops it uses- 5 | # 6 | # This is useful for sharing scenes between people. You simply archive up the scene with the loops, 7 | # send the archive to the person, and they extract it into their fw-lib/ folder. Then they can 8 | # build on your improvisation. 9 | # 10 | # For example: goarchive-scene "scene-504B642155558670C0DD84717E4B4DF8-Hacking the Database 2.xml" hacking 11 | # archives the above named scene and all loops it refers to into the archive 'hacking.tar.bz2' 12 | # 13 | # No files are archived before prompting you. 14 | # 15 | echo Files to archive: 16 | 17 | awk '{ if ($1 == ". */ 22 | 23 | #include 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #include 31 | #include 32 | 33 | #include 34 | #include 35 | #include 36 | 37 | #include "fweelin_rcu.h" 38 | -------------------------------------------------------------------------------- /scripts/go-import-markers: -------------------------------------------------------------------------------- 1 | if [ -z $1 ]; then 2 | echo "This script imports timing (downbeat) information from a Freewheeling session stream into an Ardour session." 3 | echo 4 | echo This is useful when you want to make a mix using live material from Freewheeling. 5 | echo "Freewheeling dumps timing information to Gnusound format (.wav.usx). For every live stream," 6 | echo Freewheeling also creates a .wav.usx file. 7 | echo 8 | echo To use a Freewheeling stream in Ardour: 9 | echo 10 | echo 1- Run 'oggdec live??.ogg'. 11 | echo 2- Create or load your Ardour project. 12 | echo 3- Add a track, and import 'live??.wav' as a source 13 | echo 4- Save your Ardour session, and close it. 14 | echo 15 | echo Now run go-import-markers session.ardour live??.wav.usx 16 | echo This script makes a backup of your session.ardour. 17 | echo The timing information is imported as location markers. 18 | echo 19 | echo Reload your Ardour project. 20 | echo You can now grab, copy, and work with regions on the downbeat, making editing a lot easier. 21 | echo 22 | echo "Usage: go-import-markers " 23 | else 24 | echo Importing markers from $2 into $1... 25 | mv $1 $1.orig 26 | 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 27 | fi 28 | -------------------------------------------------------------------------------- /THANKS: -------------------------------------------------------------------------------- 1 | Grateful Pauses for 2 | 3 | This Beautiful Body for telling me when to stop. 4 | .. 5 | Mom, Dad, Holly, Aasha, Asha, Melchert, Macon, Jude, Eddie, Tangle, Steve Sandberg, Joshua James, Shaun Free Zen, 6 | Tessa, The Naraya and the Wolf Creek Faeries, and Cycling 74. 7 | 8 | The Linux community! The FSF, RT kernel developers, GNU and Debian people, 9 | without whom, FreeWheeling would not be possible. 10 | 11 | -Wolfgang Woehl, Mark Knecht, Shayne O'Connor, Esben Stien, Gregory Maxwell, 12 | Plutek, and Sune Mai, my evangelists, critics, funders, beta-testers, and visionaries. 13 | 14 | -Jesse Chappell for writing SooperLooper, and being so cool about sharing ideas. 15 | 16 | -Giuliano Pochini, whose outstanding work on drivers for Echo's CardBus audio line 17 | has helped me scale down my setup. 18 | 19 | -Takashi, Jaroslav and the ALSA development team. 20 | 21 | -Paul Davis and the JACK and Ardour teams. 22 | 23 | -Peter Hanappe, Josh Green and the giant FluidSynth team. 24 | 25 | -The SDL people. 26 | 27 | -Mark Knecht for his feedback and inspiration. 28 | 29 | -Sean Bolton and the DSSI softsynth team. 30 | 31 | -Steve Harris, Tim Goetze, Tom Szilagyi- the makers of fine 32 | LADSPA effects plugins. 33 | 34 | -Bob Ham, for his work on Jack-Rack. 35 | 36 | -Echo Audio for getting their act together and releasing specs for their audio interfaces. 37 | 38 | -Countless others 39 | 40 | Everyone who has been in touch and lended kind thoughts. 41 | 42 | Thank You All 43 | -------------------------------------------------------------------------------- /examples/combipatchdemo.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /src/fweelin_osc.h: -------------------------------------------------------------------------------- 1 | #ifndef __FWEELIN_OSC_H 2 | #define __FWEELIN_OSC_H 3 | 4 | /* Copyright 2004-2011 Jan Pekau 5 | 6 | This file is part of Freewheeling. 7 | 8 | Freewheeling is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 2 of the License, or 11 | (at your option) any later version. 12 | 13 | Freewheeling is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with Freewheeling. If not, see . */ 20 | 21 | #ifndef __MACOSX__ 22 | 23 | #include 24 | 25 | class Fweelin; 26 | 27 | #define QTRACTOR_OSC_PORT 5000 28 | 29 | class OSCClient : public EventListener { 30 | 31 | public: 32 | OSCClient (Fweelin *app); 33 | virtual ~OSCClient (); 34 | 35 | void ReceiveEvent(Event *ev, EventProducer */*from*/); 36 | 37 | protected: 38 | // Core app 39 | Fweelin *app; 40 | 41 | // Opens a connection to the Qtractor DAW, for transmitting 42 | // loops. 43 | // 44 | // Returns zero on success. 45 | char open_qtractor_connection (); 46 | 47 | // Send all playing loops to a DAW via OSC 48 | void SendPlayingLoops(); 49 | 50 | // Qtractor interface 51 | lo_address qtractor_addr; 52 | // 53 | 54 | pthread_mutex_t osc_client_lock; 55 | }; 56 | 57 | #endif 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /data/interfaces.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /scripts/godx7: -------------------------------------------------------------------------------- 1 | # Script to run DX7 emulator 2 | # and to run it through FreeWheeling if it's running 3 | 4 | RUN_CMD="jack-dssi-host hexter.so" 5 | HEXTER_MIDI_NAME="hexter" 6 | HEXTER_JACK_NAME="hexter" 7 | 8 | if ((RUNNING_MERCURY != 0)) 9 | then 10 | echo Running with Mercury config. 11 | cd ~/audio 12 | killall -s KILL ghostess 13 | RUN_CMD="./gohexter-1" 14 | HEXTER_MIDI_NAME="ghostess" 15 | HEXTER_JACK_NAME="ghostess" 16 | #RUN_CMD="ghostess hexter.so" 17 | fi 18 | 19 | JACK_PCM1="alsa_pcm:playback_1" 20 | JACK_PCM2="alsa_pcm:playback_2" 21 | JACK_IN_DISCONNECT="alsa_pcm:capture_2" 22 | FWEELIN_DX7_IN="FreeWheeling:in_2" 23 | 24 | # Startup 25 | killall -s KILL jack-dssi-host 26 | sleep 1 27 | $RUN_CMD & 28 | # Now check if FreeWheeling is running 29 | FWEELIN_RUNNING=`ps -ef | grep fweelin | awk 'END { print NR }'` 30 | 31 | echo Connect JACK. 32 | HEXTER_JACK_PORT=`./waitjackports $HEXTER_JACK_NAME` 33 | 34 | echo Hexter port: $HEXTER_JACK_PORT 35 | echo Hookup DX7.. 36 | 37 | if ((FWEELIN_RUNNING < 2)) 38 | then 39 | echo Standalone use... 40 | 41 | echo Connect ALSA MIDI. 42 | aconnect `./waitalsaports $HEXTER_MIDI_NAME` 43 | else 44 | echo Connect to FreeWheeling... 45 | 46 | sleep 1 47 | jack_disconnect "$HEXTER_JACK_PORT" $JACK_PCM1 48 | sleep 1 49 | jack_disconnect "$HEXTER_JACK_PORT" $JACK_PCM2 50 | 51 | echo Connect MIDI from FW. 52 | HEXTER_MIDI_PORT=`./waitalsaports $HEXTER_MIDI_NAME | awk '{ print $2 }'` 53 | FWEELIN_MIDI_PORT=`./waitalsaports FreeWheeling | awk '{ print $2 }' | cut -d ':' -f 1`:2 54 | echo MIDI ports: $FWEELIN_MIDI_PORT $HEXTER_MIDI_PORT 55 | aconnect $FWEELIN_MIDI_PORT $HEXTER_MIDI_PORT 56 | 57 | echo Connect DX7 to FW. 58 | jack_connect "$HEXTER_JACK_PORT" $FWEELIN_DX7_IN 59 | fi 60 | -------------------------------------------------------------------------------- /data/bcf2000-help.txt: -------------------------------------------------------------------------------- 1 | Mr Thraz & Folks, 2 | 3 | I've been remiss about not yet distributing my BCF-2000 setup for Freewheeling. But I'd like to give you guys somewhere to start configuring. 4 | 5 | So I've attached my current BCF-2000 preset for Freewheeling. Send it to your BCF-2000 with 'aplaymidi' or similar. 6 | 7 | Instructions for Use: 8 | 9 | Top row of 8 buttons: capture/play loops 10 | Bottom row of 8 buttons: 11 | 1- Shift (hold) 12 | Hold shift & press top 8 buttons to erase loops 13 | 2- Undo (erase last loop) 14 | 1 (Hold) + 2- Erase all loops 15 | 3- Previous page of 8 loops (or snapshots in snap mode) 16 | 4- Next page of 8 loops (or snapshots in snap mode) 17 | 5- Deselect all looops 18 | 6- Select playing loops 19 | 7- Toggle selected loops 20 | 8- Create pulse (press this after recording your first loop to lock other loops to it) 21 | 22 | Faders: 23 | 24 | 1-4 are input levels 25 | 5 is master input level 26 | 6 is master output level 27 | 7 is feedback 28 | 8 is a quick patch change slider (patches are not actually changed until you press a button- see below) 29 | 30 | Group 1 Knobs: Press 1-8 to toggle overdub for loops, Turn 1-8 to adjust loop levels 31 | Group 2 Knobs: Press 1-8 to select loops, Turn to adjust relative level of ALL selected loops 32 | Group 3 Knobs: Turn & Press Knob 8 to browse through and load scenes. 33 | Press Knob 7 to save a scene of all loops. 34 | 35 | 4 Buttons on bottom right of BCF: 36 | 37 | Top Left: Fader mode- switches BCF faders to toggle loop levels 38 | Top Right: Unused 39 | Bottom Left: Patch Change button (activate the MIDI patch you've browsed to). 40 | Bottom Right: Toggle Snap mode 41 | (In snap mode: Shows snapshots. 42 | Select snapshots with loop buttons 1-8 (top row of 8 buttons). 43 | Page through snapshots with buttons 3 and 4 on the bottom row of 8 buttons.) 44 | 45 | That's all for now. I hope this helps. 46 | 47 | -Mercury 48 | -------------------------------------------------------------------------------- /src/Makefile.am: -------------------------------------------------------------------------------- 1 | #LIBTOOL = libtool 2 | # 3 | #COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ 4 | # $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) 5 | #LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) \ 6 | # $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) 7 | #CCLD = $(CC) 8 | #LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ 9 | # $(AM_LDFLAGS) $(LDFLAGS) -o $@ 10 | ## CFLAGS = @CFLAGS@ 11 | #CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ 12 | # $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) 13 | #LTCXXCOMPILE = $(LIBTOOL) --mode=compile $(CXX) $(DEFS) \ 14 | # $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ 15 | # $(AM_CXXFLAGS) $(CXXFLAGS) 16 | #CXXLD = $(CXX) 17 | #CXXLINK = $(LIBTOOL) --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ 18 | # $(AM_LDFLAGS) $(LDFLAGS) -o $@ 19 | ## CXXFLAGS = @CXXFLAGS@ 20 | 21 | bin_PROGRAMS = fweelin 22 | 23 | fweelin_SOURCES = stacktrace.c fweelin.cc fweelin_datatypes.cc fweelin_rcu.cc fweelin_osc.cc fweelin_event.cc fweelin_config.cc fweelin_paramset.cc fweelin_browser.cc fweelin_audioio.cc fweelin_sdlio.cc fweelin_midiio.cc fweelin_amixer.cc fweelin_videoio.cc fweelin_videoio_displays.cc fweelin_core.cc fweelin_mem.cc fweelin_block.cc fweelin_core_dsp.cc fweelin_fluidsynth.cc 24 | 25 | fweelindir = $(datadir)/fweelin 26 | 27 | FWEELIN_CFLAGS = -I. -g -Wall -Wextra -Wno-write-strings -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 28 | FWEELIN_CXXFLAGS = -Wno-non-virtual-dtor 29 | 30 | AM_CFLAGS = $(CFLAGS) $(FWEELIN_CFLAGS) 31 | AM_CXXFLAGS = $(CFLAGS) $(CXXFLAGS) $(FWEELIN_CFLAGS) $(FWEELIN_CXXFLAGS) 32 | -------------------------------------------------------------------------------- /src/fweelin_datatypes.cc: -------------------------------------------------------------------------------- 1 | /* 2 | To change the world, 3 | I aspire to perceive it differently. 4 | */ 5 | 6 | /* Copyright 2004-2011 Jan Pekau 7 | 8 | This file is part of Freewheeling. 9 | 10 | Freewheeling is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 2 of the License, or 13 | (at your option) any later version. 14 | 15 | Freewheeling is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with Freewheeling. If not, see . */ 22 | 23 | #include 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #include 31 | #include 32 | 33 | #include 34 | #include 35 | #include 36 | 37 | #include "fweelin_datatypes.h" 38 | 39 | int RT_RWThreads::num_rw_threads = 0; 40 | pthread_t RT_RWThreads::ids[MAX_RW_THREADS]; 41 | pthread_mutex_t RT_RWThreads::register_rw_lock; 42 | 43 | int RT_RWThreads::num_rt_structs = 0; 44 | RTDataStruct_Updater *RT_RWThreads::rtsructs[MAX_RT_STRUCTS]; 45 | pthread_mutex_t RT_RWThreads::register_rtstruct_lock; 46 | 47 | CoreDataType GetCoreDataType(char *name) { 48 | if (!strcmp(name, "char")) 49 | return T_char; 50 | else if (!strcmp(name, "int")) 51 | return T_int; 52 | else if (!strcmp(name, "long")) 53 | return T_long; 54 | else if (!strcmp(name, "float")) 55 | return T_float; 56 | else if (!strcmp(name, "range")) 57 | return T_range; 58 | else 59 | return T_invalid; 60 | }; 61 | 62 | -------------------------------------------------------------------------------- /MacOSX/FweelinMac.mm: -------------------------------------------------------------------------------- 1 | // 2 | // FweelinMac.mm 3 | // fweelin 4 | // 5 | 6 | #import 7 | #include "FweelinMac.h" 8 | #include "SDLMain.h" 9 | 10 | #include "fweelin_core.h" 11 | 12 | void *FweelinMac::sdlmain = 0; 13 | void *FweelinMac::fweelin = 0; 14 | 15 | void FweelinMac::ClearMIDIInputList() { 16 | // printf("***SDLMAIN: %p\n",sdlmain); 17 | 18 | SDLMain *s = (SDLMain *)sdlmain; 19 | [s clearMIDIInputList]; 20 | }; 21 | 22 | void FweelinMac::AddMIDIInputSource(char *name) { 23 | SDLMain *s = (SDLMain *)sdlmain; 24 | [s addMIDIInputSource:[NSString stringWithUTF8String:name]]; 25 | }; 26 | 27 | void FweelinMac::SetMIDIInput(int idx) { 28 | // Connect MIDI 29 | Fweelin *fw = (Fweelin *)fweelin; 30 | 31 | fw->getMIDI()->SetMIDIInput(idx); 32 | }; 33 | 34 | void FweelinMac::SetDebugMode(int active) { 35 | Fweelin *fw = (Fweelin *)fweelin; 36 | 37 | ShowDebugInfoEvent *devt = (ShowDebugInfoEvent *) 38 | Event::GetEventByType(T_EV_ShowDebugInfo); 39 | devt->show = active; 40 | fw->getEMG()->BroadcastEventNow(devt, fw); 41 | }; 42 | 43 | void FweelinMac::Quit() { 44 | Fweelin *fw = (Fweelin *)fweelin; 45 | 46 | ExitSessionEvent *evt = (ExitSessionEvent *) 47 | Event::GetEventByType(T_EV_ExitSession); 48 | fw->getEMG()->BroadcastEventNow(evt, fw); 49 | }; 50 | 51 | void FweelinMac::ShowHelp() { 52 | Fweelin *fw = (Fweelin *)fweelin; 53 | 54 | VideoShowHelpEvent *evt = (VideoShowHelpEvent *) 55 | Event::GetEventByType(T_EV_VideoShowHelp); 56 | evt->page = 1; 57 | fw->getEMG()->BroadcastEventNow(evt, fw); 58 | }; 59 | 60 | // Performs initialization on a new pthread to make it behave well with Cocoa 61 | void FweelinMac::SetupCocoaThread() { 62 | // printf("MULTITHREADED: %d\n",[NSThread isMultiThreaded]); 63 | autoreleasepool = [[NSAutoreleasePool alloc] init]; 64 | }; 65 | 66 | void FweelinMac::TakedownCocoaThread() { 67 | NSAutoreleasePool *tmp = (NSAutoreleasePool *) autoreleasepool; 68 | [tmp release]; 69 | }; 70 | -------------------------------------------------------------------------------- /data/fweelin.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | ]> 7 | 8 | 41 | 42 | 43 | 44 | &basics; 45 | &graphics; 46 | &interfaces; 47 | 48 | 49 | -------------------------------------------------------------------------------- /src/stacktrace.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | * 3 | * Copyright (c) 1998 by Bjorn Reese 4 | * 5 | * Permission to use, copy, modify, and distribute this software for any 6 | * purpose with or without fee is hereby granted, provided that the above 7 | * copyright notice and this permission notice appear in all copies. 8 | * 9 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 10 | * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 11 | * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND 12 | * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER. 13 | * 14 | ************************************************************************ 15 | * 16 | * Purpose: 17 | * To generate a stacktrace of a program. 18 | * 19 | * Description: 20 | * If a debugger is located on the machine we will try this first, 21 | * as it usually give better information than built-in methods. 22 | * The debugger needs the name of the program to be able to attach 23 | * to it, so this must be passed to StackTraceInit(). The second 24 | * argument is a filedescriptor that StackTrace() writes to. If this 25 | * argument is -1 then standard output will be used. 26 | * 27 | * Compilation: 28 | * Some platforms have a built-in method to generate stacktraces, but 29 | * they are usually located in some non-standard library. The following 30 | * are supported: 31 | * 32 | * IRIX Compile with -DUSE_BUILTIN and -lexc 33 | * HP/UX Compile with -DUSE_BUILTIN and -lcl 34 | * GCC Compile with -DUSE_BUILTIN 35 | * 36 | ************************************************************************/ 37 | 38 | #ifndef H_DEBUG_STACKTRACE 39 | #define H_DEBUG_STACKTRACE 40 | 41 | #if defined(__cplusplus) 42 | extern "C" { 43 | #endif // __cplusplus 44 | 45 | void StackTrace(char *gdb_command_file); 46 | void StackTraceInit(const char *progname, int handle); 47 | 48 | #if defined(__cplusplus) 49 | } 50 | #endif // __cplusplus 51 | 52 | #endif /* H_DEBUG_STACKTRACE */ 53 | -------------------------------------------------------------------------------- /scripts/README: -------------------------------------------------------------------------------- 1 | Managing A Library Of Loops & Scenes 2 | ------------------------------------ 3 | 4 | ** godelete-date, gomv-date, goarchive-date scripts 5 | 6 | Delete/Move, and Archive loops & scenes by date. 7 | See individual files for instructions. 8 | 9 | ** goarchive-scene script 10 | 11 | Archive a scene and all the loops it uses. 12 | 13 | Connecting FreeWheeling with Other Linux Audio apps 14 | --------------------------------------------------- 15 | 16 | -Hexter 17 | -Jack-Rack 18 | 19 | Example Scripts and Presets: 20 | --------------------------- 21 | 22 | Several Jack-Racks that use tube amp sims and reverb, and some scripts to load FreeWheeling and Hexter, a killer 23 | DX7 synth emulator. 24 | 25 | - 26 | Running 'gofweel' will load FreeWheeling and hook it up to reverb and tube amp. Your live mix will still be 27 | saved to disk dry, so you can tweak the FX later. 28 | 29 | - 30 | Running 'godx7' will load Hexter DX7 emulator and connect to tube amp. If FreeWheeling is running, DX7 becomes 31 | an input into FreeWheeling (channel 2). If not, DX7 is loaded standalone. 32 | 33 | - 34 | Running 'gofweel-dx7' will load FreeWheeling and DX7 as above, and connect them. You get the DX7 synth connected 35 | through a light phaser, then into FreeWheeling. FreeWheeling is channeled through valve saturation and tube amp 36 | plugins, and a wide open reverb. This is the whole enchilada. 37 | 38 | *** 39 | You will have to tweak the scripts to change your MIDI hardware name- see script 'waitalsaports'. 40 | *** 41 | 42 | *** 43 | You will also have to patch Jack-Rack (see included patch-) to load a .rack at startup. 44 | This is a feature that the author, I think, intends to implement, but I have done it for him. 45 | The scripts use this feature to autoload a rack. 46 | For more info, type 'jack-rack -?' after patching and recompiling and look at the -f option. 47 | *** 48 | 49 | *** Note these scripts are rather aggressive at killing tasks. If you have running versions of 50 | freewheeling, ghostess, jack-dssi-host, or jack-rack, expect them to suddenly stop! ** 51 | 52 | *** I recommend ghostess for hosting your DSSI synths- it allows you to save patch banks for auto startup. 53 | 54 | Good Luck! 55 | -Mercury 56 | -------------------------------------------------------------------------------- /scripts/gofweel: -------------------------------------------------------------------------------- 1 | #Start FreeWheeling and link it to nice Jack-Rack FX 2 | JACK_PCM1="alsa_pcm:playback_1" 3 | JACK_PCM2="alsa_pcm:playback_2" 4 | JACK_IN_PCM1="alsa_pcm:capture_1" 5 | JACK_IN_PCM2="alsa_pcm:capture_2" 6 | 7 | if ((RUNNING_MERCURY != 0)) 8 | then 9 | echo Running with Mercury config. 10 | cd ~/audio 11 | cp ~/.fweelin/fweelin.xml ~/.fweelin/fweelin.xml.2 12 | ~/gokeys-std 13 | fi 14 | 15 | fweelin & 16 | 17 | running=`ps -ef | grep jack-rack | awk 'END { print NR }'` 18 | if ((running < 2)) 19 | then 20 | jack-rack -n -o vocalverb-canyon.rack & 21 | sleep 1 22 | else 23 | echo Rack already running.. 24 | fi 25 | 26 | # MIDI ports 27 | if ((RUNNING_MERCURY != 0)) 28 | then 29 | aconnect `~/waitalsaports-jv80 FreeWheeling` 30 | aconnect `~/waitalsaports-pcr FreeWheeling` 31 | else 32 | aconnect `./waitalsaports FreeWheeling` 33 | fi 34 | 35 | # SYSTEM_MIDI=`echo $FWEELIN_MIDI_PORTS | awk '{ print $1 }'` 36 | # FWEELIN_MIDI=`echo $FWEELIN_MIDI_PORTS | awk '{ print $2 }'` 37 | 38 | # Audio ports 39 | FWEELIN_JACK_IPORTS=`./waitjackports FreeWheeling | grep in` 40 | FWEELIN_JACK_OPORTS=`./waitjackports FreeWheeling | grep out` 41 | FWEELIN_JACK_IP1=`echo $FWEELIN_JACK_IPORTS | awk '{ print $1 }'` 42 | FWEELIN_JACK_IP2=`echo $FWEELIN_JACK_IPORTS | awk '{ print $2 }'` 43 | FWEELIN_JACK_OP1=`echo $FWEELIN_JACK_OPORTS | awk '{ print $1 }'` 44 | FWEELIN_JACK_OP2=`echo $FWEELIN_JACK_OPORTS | awk '{ print $2 }'` 45 | 46 | #echo Ins: $FWEELIN_JACK_IP1 $FWEELIN_JACK_IP2 47 | #echo Outs: $FWEELIN_JACK_OP1 $FWEELIN_JACK_OP2 48 | 49 | JRACK_JACK_IPORTS=`./waitjackports jack_rack | grep in` 50 | JRACK_JACK_OPORTS=`./waitjackports jack_rack | grep out` 51 | JRACK_JACK_IP1=`echo $JRACK_JACK_IPORTS | awk '{ print $1 }'` 52 | JRACK_JACK_IP2=`echo $JRACK_JACK_IPORTS | awk '{ print $2 }'` 53 | JRACK_JACK_OP1=`echo $JRACK_JACK_OPORTS | awk '{ print $1 }'` 54 | JRACK_JACK_OP2=`echo $JRACK_JACK_OPORTS | awk '{ print $2 }'` 55 | 56 | #echo Ins: $JRACK_JACK_IP1 $JRACK_JACK_IP2 57 | #echo Outs: $JRACK_JACK_OP1 $JRACK_JACK_OP2 58 | 59 | sleep 1 60 | 61 | jack_connect $JACK_IN_PCM1 $FWEELIN_JACK_IP1 62 | jack_connect $JACK_IN_PCM2 $FWEELIN_JACK_IP2 63 | jack_connect $FWEELIN_JACK_OP1 $JRACK_JACK_IP1 64 | jack_connect $FWEELIN_JACK_OP2 $JRACK_JACK_IP2 65 | jack_connect $JRACK_JACK_OP1 $JACK_PCM1 66 | jack_connect $JRACK_JACK_OP2 $JACK_PCM2 67 | -------------------------------------------------------------------------------- /data/fonts/truetype/ttf-bitstream-vera/COPYING: -------------------------------------------------------------------------------- 1 | Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is a trademark of Bitstream, Inc. 2 | 3 | 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: 4 | 5 | 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. 6 | 7 | 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”. 8 | 9 | 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. 10 | 11 | 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. 12 | 13 | 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. 14 | 15 | 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. 16 | -------------------------------------------------------------------------------- /src/fweelin_fluidsynth.h: -------------------------------------------------------------------------------- 1 | #ifndef __FWEELIN_FLUIDSYNTH_H 2 | #define __FWEELIN_FLUIDSYNTH_H 3 | 4 | /* Copyright 2004-2011 Jan Pekau 5 | 6 | This file is part of Freewheeling. 7 | 8 | Freewheeling is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 2 of the License, or 11 | (at your option) any later version. 12 | 13 | Freewheeling is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with Freewheeling. If not, see . */ 20 | 21 | 22 | #if USE_FLUIDSYNTH 23 | 24 | #include 25 | 26 | #include "fweelin_core_dsp.h" 27 | #include "fweelin_browser.h" 28 | 29 | // Whacky FluidSynth center of pitchbend is 0x2000 not 0 30 | #define FLUIDSYNTH_PITCHBEND_CENTER 0x2000 31 | 32 | // Integrated soft-synth based on libfluidsynth 33 | class FluidSynthProcessor : public Processor, public EventListener { 34 | friend class Fweelin; 35 | 36 | public: 37 | FluidSynthProcessor(Fweelin *app, char stereo); 38 | virtual ~FluidSynthProcessor(); 39 | 40 | virtual void process(char pre, nframes_t len, AudioBuffers *ab); 41 | 42 | virtual void ReceiveEvent(Event *ev, EventProducer */*from*/); 43 | 44 | // Send a new patch to synth 45 | void SendPatchChange(PatchItem *p); 46 | 47 | // Receive MIDI events for synth 48 | void ReceiveMIDIEvent(Event *ev); 49 | 50 | // Enable/disable FluidSynth- if disabled, bypasses 51 | // processor stage to reduce CPU usage, but leaves memory allocated 52 | inline void SetEnable(char en) { 53 | // Preprocess audio for smoothing 54 | //dopreprocess(); 55 | this->enable = en; 56 | }; 57 | 58 | char GetEnable() { return enable; }; 59 | 60 | // Sets up browser patches based on loaded soundfonts 61 | void SetupPatches(); 62 | 63 | private: 64 | 65 | // Run FluidSynth in stereo? 66 | char stereo; 67 | 68 | // Left and right output buffers 69 | sample_t *leftbuf, 70 | *rightbuf; 71 | 72 | // And fluidsynth variables.. 73 | fluid_settings_t *settings; 74 | fluid_synth_t *synth; 75 | 76 | // Currently processing? 77 | char enable; 78 | }; 79 | 80 | #endif 81 | #endif 82 | -------------------------------------------------------------------------------- /examples/README: -------------------------------------------------------------------------------- 1 | Loops and Scenes Examples 2 | ------------------------- 3 | 4 | You can find sample loops and scenes in the 'Remix Playground' area of the Freewheeling website. 5 | http://freewheeling.sourceforge.net/#scenes 6 | 7 | NEW in V0.5.3- Combination Zone Patches 8 | --------------------------------------- 9 | 10 | * More flexible MIDI patch routing. 11 | 12 | - Combination patches allow you to split one MIDI controller 13 | into a range of zones. This allows you to control several 14 | different sounds or softsynths from one MIDI control source. 15 | 16 | A patch defines the zones, as well as the output port and 17 | channel that each zone sends to. You can also send 18 | MIDI program and bank change messages for each zone, allowing 19 | you to switch programs on external synths. 20 | 21 | All of this functionality is integrated into the patch browser, 22 | so you can seamlessly control other synth apps and 23 | sound modules from within FreeWheeling. 24 | 25 | See 'examples/combipatchdemo.xml' for an example 26 | configuration. 27 | 28 | Patch Browser Definition Example 29 | -------------------------------- 30 | 31 | The file patches1.xml contains an example for how to define patches for an external soft synth. 32 | In this case it's an example for a Ghostess DSSI host running one instance of WhySynth and 33 | one instance of Hexter. 34 | 35 | To use this example, copy 'examples/patches1.xml' to the ~/.fweelin/ folder 36 | (this folder is created by version 0.5.2 and forward). 37 | 38 | The WhySynth instance is on channel 0 (first channel), 39 | and the Hexter instance is on channel 1 (second channel). 40 | 41 | When you specify this patch list in Freewheeling's .fweelin.rc configuration file: 42 | 43 | 44 | 45 | you will then be able to play both your WhySynth and your Hexter patches, and 46 | switch between them. 47 | 48 | The WhySynth and Hexter patches will appear in separate sections of the patch browser. 49 | 50 | ------------------------------------------------------------------------------------------- 51 | 52 | You can automatically generate a patch list from a set of DSSI plugin patches. 53 | This saves the work of manually entering all of your patch information. 54 | 55 | To do this, apply the included patch to Ghostess (scripts/patch-ghostess-xml-patchlist). 56 | The patch modifies Ghostess so that when you select 'Save Configuration...' from the 57 | File menu, you get both a script to startup Ghostess with the current config and patchset, 58 | -as well as- an .XML file with the same base name, that contains the patch list for Freewheeling. 59 | 60 | I've submitted this patch to Sean Bolton for inclusion in an upcoming Ghostess release. 61 | Please nudge him if it has been useful for you (http://home.jps.net/~musound/). 62 | 63 | ------------------------------------------------------------------------------------------- 64 | -------------------------------------------------------------------------------- /src/fweelin_sdlio.h: -------------------------------------------------------------------------------- 1 | #ifndef __FWEELIN_SDLIO_H 2 | #define __FWEELIN_SDLIO_H 3 | 4 | /* Copyright 2004-2011 Jan Pekau 5 | 6 | This file is part of Freewheeling. 7 | 8 | Freewheeling is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 2 of the License, or 11 | (at your option) any later version. 12 | 13 | Freewheeling is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with Freewheeling. If not, see . */ 20 | 21 | #include 22 | 23 | #include "fweelin_event.h" 24 | 25 | #ifdef __MACOSX__ 26 | #include "FweelinMac.h" 27 | #endif 28 | 29 | class Fweelin; 30 | 31 | // Deprecated! 32 | class KeySettings { 33 | public: 34 | KeySettings() : 35 | leftshift(0), rightshift(0), leftctrl(0), rightctrl(0), 36 | leftalt(0), rightalt(0), upkey(0), downkey(0), spacekey(0) {}; 37 | 38 | // Function modifier keys 39 | char leftshift, 40 | rightshift, 41 | leftctrl, 42 | rightctrl, 43 | leftalt, 44 | rightalt, 45 | upkey, 46 | downkey, 47 | spacekey; 48 | }; 49 | 50 | class SDLKeyList { 51 | public: 52 | SDLKeyList (SDLKey k) : k(k), next(0) {}; 53 | 54 | SDLKey k; 55 | SDLKeyList *next; 56 | }; 57 | 58 | // SDL Input Handler 59 | class SDLIO : public EventProducer, public EventListener { 60 | public: 61 | SDLIO (Fweelin *app) : app(app), sdlthreadgo(0) { 62 | keyheld = new char[SDLK_LAST]; 63 | for (int i = 0; i < SDLK_LAST; i++) 64 | keyheld[i] = 0; 65 | }; 66 | virtual ~SDLIO() { 67 | delete[] keyheld; 68 | }; 69 | 70 | int activate (); 71 | void close (); 72 | 73 | char IsActive () { return sdlthreadgo; }; 74 | char *GetKeysHeld () { return keyheld; }; 75 | 76 | KeySettings *getSETS() { return &sets; }; 77 | 78 | void ReceiveEvent(Event *ev, EventProducer */*from*/); 79 | 80 | // We use slightly modified keynames for the config system: 81 | // Gets the SDL keysym that corresponds to key with a given name 82 | static SDLKey GetSDLKey(char *keyname); 83 | // And the name corresponding to the keysym.. 84 | static const char *GetSDLName(SDLKey sym); 85 | 86 | inline void EnableUNICODE(int enable) { SDL_EnableUNICODE(enable); }; 87 | inline void EnableKeyRepeat(int enable) { 88 | if (enable) 89 | SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, 90 | SDL_DEFAULT_REPEAT_INTERVAL); 91 | else 92 | SDL_EnableKeyRepeat(0,0); 93 | }; 94 | 95 | // SDL event handler thread 96 | static void *run_sdl_thread (void *ptr); 97 | 98 | protected: 99 | #ifdef __MACOSX__ 100 | FweelinMac cocoa; // Cocoa thread setup 101 | #endif 102 | 103 | // Core app 104 | Fweelin *app; 105 | 106 | // Joysticks 107 | int numjoy; // Number of joysticks 108 | SDL_Joystick **joys; // Control structure for each joystick 109 | 110 | // Keys currently held down- array for all SDLKeys, nonzero if held 111 | char *keyheld; 112 | 113 | // Deprecated 114 | KeySettings sets; 115 | 116 | void handle_key(int keycode, char press); 117 | 118 | pthread_t sdl_thread; 119 | char sdlthreadgo; 120 | }; 121 | 122 | #endif 123 | -------------------------------------------------------------------------------- /data/midifootswitch.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 18 | 19 | 20 | 25 | 30 | 31 | 32 | 37 | 38 | 39 | 50 | 51 | 60 | 61 | 62 | 69 | 70 | 71 | 72 | 74 | 76 | 77 | 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /src/fweelin_amixer.h: -------------------------------------------------------------------------------- 1 | #ifndef __FWEELIN_AMIXER_H 2 | #define __FWEELIN_AMIXER_H 3 | 4 | /* Copyright 2004-2011 Jan Pekau 5 | 6 | This file is part of Freewheeling. 7 | 8 | Freewheeling is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 2 of the License, or 11 | (at your option) any later version. 12 | 13 | Freewheeling is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with Freewheeling. If not, see . */ 20 | 21 | /* This file contains code from amixer.c, ALSA's command line mixer utility: 22 | * 23 | * ALSA command line mixer utility 24 | * Copyright (c) 1999-2000 by Jaroslav Kysela 25 | * 26 | * This program is free software; you can redistribute it and/or modify 27 | * it under the terms of the GNU General Public License as published by 28 | * the Free Software Foundation; either version 2 of the License, or 29 | * (at your option) any later version. 30 | * 31 | * This program is distributed in the hope that it will be useful, 32 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 33 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 34 | * GNU General Public License for more details. 35 | * 36 | * You should have received a copy of the GNU General Public License 37 | * along with this program; if not, write to the Free Software 38 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 39 | * 40 | */ 41 | 42 | #include 43 | #include 44 | #include 45 | #include 46 | 47 | #ifndef __MACOSX__ 48 | #include 49 | #endif 50 | 51 | #include "fweelin_core.h" 52 | 53 | class Fweelin; 54 | 55 | /** 56 | * Interface class for directly talking to the audio hardware (ALSA) mixer 57 | * 58 | * Taken almost verbatim from amixer.c in alsa-utils, with minor changes to fit 59 | * Freewheeling. 60 | */ 61 | class HardwareMixerInterface { 62 | public: 63 | HardwareMixerInterface(Fweelin *app) : app(app), prev_hwid(-1) {}; 64 | 65 | #ifndef __MACOSX__ 66 | /* 67 | * Set an ALSA Mixer control 68 | * 69 | * Parameters: 70 | * the HW id (ie hw:0, hw:1, etc) 71 | * the control numid (ie numid=5) 72 | * and between 1 and 4 values. 73 | * 74 | * Returns zero on success. 75 | */ 76 | int ALSAMixerControlSet(int hwid, int numid, int val1, int val2 = -1, int val3 = -1, int val4 = -1); 77 | 78 | private: 79 | const char *control_type(snd_ctl_elem_info_t *info); 80 | const char *control_access(snd_ctl_elem_info_t *info); 81 | long get_integer(char **ptr, long min, long max); 82 | long get_integer64(char **ptr, long long min, long long max); 83 | int parse_control_id(const char *str, snd_ctl_elem_id_t *id); 84 | const char *control_iface(snd_ctl_elem_id_t *id); 85 | void show_control_id(snd_ctl_elem_id_t *id); 86 | void print_spaces(unsigned int spaces); 87 | void print_dB(long dB); 88 | void decode_tlv(unsigned int spaces, unsigned int *tlv, unsigned int tlv_size); 89 | int show_control(char *card, const char *space, snd_hctl_elem_t *elem, 90 | int level); 91 | int get_ctl_enum_item_index(snd_ctl_t *handle, snd_ctl_elem_info_t *info, 92 | char **ptrp); 93 | int cset(char *card, int argc, char *argv[], int roflag, int keep_handle, int debugflag); 94 | #endif 95 | 96 | Fweelin *app; 97 | int prev_hwid; // Previous cset call, what was the hwid? 98 | }; 99 | 100 | #endif 101 | -------------------------------------------------------------------------------- /src/fweelin.cc: -------------------------------------------------------------------------------- 1 | /* ************ 2 | FreeWheeling 3 | ************ 4 | 5 | What is music, 6 | if it is not shared in community, 7 | held in friendship, 8 | alive and breathing, 9 | soil and soul? 10 | 11 | THANKS & PRAISE 12 | */ 13 | 14 | /* Copyright 2004-2011 Jan Pekau 15 | 16 | This file is part of Freewheeling. 17 | 18 | Freewheeling is free software: you can redistribute it and/or modify 19 | it under the terms of the GNU General Public License as published by 20 | the Free Software Foundation, either version 2 of the License, or 21 | (at your option) any later version. 22 | 23 | Freewheeling is distributed in the hope that it will be useful, 24 | but WITHOUT ANY WARRANTY; without even the implied warranty of 25 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 26 | GNU General Public License for more details. 27 | 28 | You should have received a copy of the GNU General Public License 29 | along with Freewheeling. If not, see . */ 30 | 31 | #include 32 | #include 33 | 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | #include 40 | #include 41 | 42 | #include 43 | #include 44 | #include 45 | 46 | #include "stacktrace.h" 47 | 48 | #include "fweelin_midiio.h" 49 | #include "fweelin_videoio.h" 50 | #include "fweelin_sdlio.h" 51 | #include "fweelin_audioio.h" 52 | 53 | #include "fweelin_core.h" 54 | #include "fweelin_core_dsp.h" 55 | 56 | pid_t main_pid; 57 | 58 | void signal_handler (int iSignal) { 59 | switch (iSignal) { 60 | case SIGINT: 61 | return; 62 | #if defined(WIN32) 63 | #else 64 | case SIGSEGV: 65 | printf(">>> FATAL ERROR: Segmentation fault (SIGSEGV) occured! <<<\n"); 66 | break; 67 | case SIGBUS: 68 | printf(">>> FATAL ERROR: Access to undefined portion of a memory object (SIGBUS) occured! <<<\n"); 69 | break; 70 | case SIGILL: 71 | printf(">>> FATAL ERROR: Illegal instruction (SIGILL) occured! <<<\n"); 72 | break; 73 | case SIGFPE: 74 | printf(">>> FATAL ERROR: Erroneous arithmetic operation (SIGFPE) occured! <<<\n"); 75 | break; 76 | case SIGUSR1: 77 | printf(">>> User defined signal 1 (SIGUSR1) received <<<\n"); 78 | break; 79 | case SIGUSR2: 80 | printf(">>> User defined signal 2 (SIGUSR2) received <<<\n"); 81 | break; 82 | #endif 83 | default: { // this should never happen, as we register for the signals we want 84 | printf(">>> FATAL ERROR: Unknown signal received! <<<\n"); 85 | break; 86 | } 87 | } 88 | signal(iSignal, SIG_DFL); // Reinstall default handler to prevent race conditions 89 | printf("Saving stack trace to file 'fweelin-stackdump'...\n"); 90 | 91 | char buf[256]; 92 | snprintf(buf,255,"%s%s",FWEELIN_DATADIR,"/gdb-stackdump-cmds"); 93 | StackTrace(buf); 94 | 95 | sleep(10); 96 | printf("Exit Freewheeling...\n"); 97 | // Use abort() if we want to generate a core dump. 98 | kill(main_pid, SIGKILL); 99 | } 100 | 101 | 102 | #ifndef NO_COMPILE_MAIN 103 | int main (int /*argc*/, char *argv[]) { 104 | #if !defined(WIN32) 105 | main_pid = getpid(); 106 | #endif // WIN32 107 | 108 | // Initialize the stack trace mechanism 109 | StackTraceInit(argv[0], -1); 110 | 111 | signal(SIGINT, signal_handler); 112 | 113 | #if !defined(WIN32) 114 | // Register signal handlers 115 | struct sigaction sact; 116 | sigemptyset(&sact.sa_mask); 117 | sact.sa_flags = 0; 118 | sact.sa_handler = signal_handler; 119 | sigaction(SIGSEGV, &sact, NULL); 120 | sigaction(SIGBUS, &sact, NULL); 121 | sigaction(SIGILL, &sact, NULL); 122 | sigaction(SIGFPE, &sact, NULL); 123 | sigaction(SIGUSR1, &sact, NULL); 124 | sigaction(SIGUSR2, &sact, NULL); 125 | #endif // WIN32 126 | 127 | Fweelin flo; 128 | 129 | printf("FreeWheeling %s\n",VERSION); 130 | printf("May we return to the circle.\n\n"); 131 | 132 | if (!flo.setup()) 133 | flo.go(); 134 | else 135 | printf("Error starting FreeWheeling!\n"); 136 | 137 | return 0; 138 | } 139 | #endif // NO_COMPILE_MAIN 140 | 141 | 142 | // Improvisation is loving what is. 143 | -------------------------------------------------------------------------------- /data/browsers.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 9 | 59 | 60 | 65 | 66 | 69 | 70 | 71 | 72 | 76 | 77 | 81 | 82 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /src/fweelin_audioio.h: -------------------------------------------------------------------------------- 1 | #ifndef __FWEELIN_AUDIOIO_H 2 | #define __FWEELIN_AUDIOIO_H 3 | 4 | /* Copyright 2004-2011 Jan Pekau 5 | 6 | This file is part of Freewheeling. 7 | 8 | Freewheeling is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 2 of the License, or 11 | (at your option) any later version. 12 | 13 | Freewheeling is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with Freewheeling. If not, see . */ 20 | 21 | extern "C" 22 | { 23 | #include 24 | } 25 | 26 | typedef jack_default_audio_sample_t sample_t; 27 | typedef jack_nframes_t nframes_t; 28 | 29 | class Fweelin; 30 | class Processor; 31 | 32 | // **************** SYSTEM LEVEL AUDIO 33 | 34 | class AudioIO { 35 | public: 36 | AudioIO(Fweelin *app) : sync_start_frame(0), timebase_master(0), sync_active(0), audio_thread(0), app(app) {}; 37 | 38 | // Open up system level audio 39 | int open (); 40 | 41 | // Activate system level audio 42 | int activate (Processor *rp); 43 | 44 | // Close system level audio 45 | void close (); 46 | 47 | // Get realtime buffer size 48 | nframes_t getbufsz(); 49 | 50 | // **Callbacks** 51 | 52 | // Realtime process function.. the beginning of the DSP chain 53 | static int process (nframes_t nframes, void *arg); 54 | 55 | // Timebase (jack transport sync) callback 56 | static void timebase_callback(jack_transport_state_t /*state*/, 57 | jack_nframes_t /*nframes*/, 58 | jack_position_t *pos, int new_pos, void *arg); 59 | 60 | // Sampling rate change callback 61 | static int srate_callback (nframes_t nframes, void *arg); 62 | 63 | // Callback for audio shutdown 64 | static void audio_shutdown (void */*arg*/); 65 | 66 | // Get current sampling rate 67 | inline nframes_t get_srate() { return srate; }; 68 | 69 | // Get approximate audio CPU load 70 | inline float GetAudioCPULoad() { return cpuload; }; 71 | 72 | inline float GetTimeScale() { return timescale; }; 73 | 74 | // Transport sync methods 75 | 76 | // Reposition transport to the given position 77 | // Used for syncing external apps 78 | void RelocateTransport(nframes_t pos); 79 | 80 | // Get current bar in transport mechanism 81 | inline int GetTransport_Bar() { return jpos.bar; }; 82 | 83 | // Get current beat in transport mechaniasm 84 | inline int GetTransport_Beat() { return jpos.beat; }; 85 | 86 | // Get current BPM in transport mechanism 87 | inline double GetTransport_BPM() { return jpos.beats_per_minute; }; 88 | 89 | // Get current # of beats per bar in transport mechanism 90 | inline float GetTransport_BPB() { return jpos.beats_per_bar; }; 91 | 92 | // Are we sending or receiving sync? 93 | inline char IsSync() { return sync_active; }; 94 | 95 | // Are we the timebase master? 96 | inline char IsTimebaseMaster() { return timebase_master; }; 97 | 98 | // Is the transport rolling? 99 | inline char IsTransportRolling() { return transport_roll; }; 100 | 101 | // Audio system client 102 | jack_client_t *client; 103 | 104 | // Inputs and outputs- stereo pairs 105 | jack_port_t **iport[2], **oport[2]; 106 | 107 | float cpuload; // Current approximate audio CPU load 108 | float timescale; // fragment length/sample rate = length (s) of one fragment 109 | nframes_t srate; // Sampling rate 110 | 111 | // Variables for audio (Jack transport) sync 112 | 113 | // Jack frame where the first bar began in transport 114 | int32_t sync_start_frame; 115 | char repos; // Nonzero if we have repositioned JACK internally 116 | jack_position_t jpos; // Current JACK position 117 | char timebase_master; // Nonzero if we are the JACK timebase master 118 | char sync_active; // Nonzero if sync is active 119 | char transport_roll; // Nonzero if the transport is rolling 120 | 121 | volatile pthread_t audio_thread; // RT audio thread (created by JACK) 122 | 123 | // Pointer to the main app 124 | Fweelin *app; 125 | // Processor which is basically the root of the signal flow 126 | Processor *rp; 127 | }; 128 | 129 | #endif 130 | -------------------------------------------------------------------------------- /data/rme-hdsp.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 21 | 22 | 23 | 24 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 51 | 52 | 53 | 56 | 57 | 58 | 61 | 62 | 63 | 66 | 67 | 68 | 69 | 70 | 75 | 76 | 77 | 80 | 81 | 82 | 85 | 86 | 87 | 90 | 91 | 92 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /data/patches3.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | -------------------------------------------------------------------------------- /MacOSX/README-MAC: -------------------------------------------------------------------------------- 1 | Intro for Mac OS X 2 | ================== 3 | 4 | FreeWheeling for Mac OS X is a direct port of the Linux version. 5 | A Universal binary will be made available for each release, along 6 | with source code if you wish to compile it yourself. 7 | 8 | The user interface remains the same across OS X and Linux versions. 9 | This means that FreeWheeling OS X does not make use of Mac's Aqua interface. 10 | A few basic commands specific to the Mac version have been provided in a Mac menu. 11 | The rest of the functionality is built into the app window. 12 | 13 | FreeWheeling is designed to be mostly MIDI and keyboard driven. 14 | A few things can be done from a mouse, but while playing music, 15 | the idea is to keep your hands on your instrument. FreeWheeling is not a music production 16 | or DJing tool. FreeWheeling works for instrumentalists, such as drummers, 17 | guitarists, keyboardists and vocalists. FreeWheeling is like a second 18 | instrument, that you use to reflect back parts of your playing, to build 19 | loops in a spontaneous way. 20 | 21 | You can configure FreeWheeling to work with the PC keyboard, joysticks, 22 | or MIDI-enabled devices. 23 | 24 | Setup for Mac OS X 25 | ================== 26 | 27 | 1. Drag the 'Fweelin' app to the 'Applications' folder. 28 | 29 | 2. Download and install JACK. http://jackosx.com/ 30 | 31 | Jack is an audio connection kit similar to Rewire. 32 | 33 | It allows you to plug FreeWheeling into different audio apps, 34 | such as soft synths or sequencers. 35 | 36 | 3. Start 'Jack Pilot', included with your JACK installation. 37 | 38 | Set the lowest possible latency that provides stable performance. 39 | 40 | Set 'Jack Pilot' to 'Full Duplex' (recording and playback enabled), 41 | if you wish to record live instruments in FreeWheeling. 42 | 43 | If you are using the onboard Mac sound, you can get 'Full Duplex' 44 | recording and playback by creating an 'Aggregate Audio Device'. 45 | To do this, choose 'Open Audio MIDI Setup' from the JackPilot 46 | menu, or run 'Applications/Utilities/Audio MIDI Setup'. Then, 47 | select 'Open Aggregate Device Editor...' from the Audio menu. 48 | 49 | 4. If you wish to debug the console output of FreeWheeling for 50 | troubleshooting, start 'Applications/Utilities/Console' now. 51 | 52 | 5. Run 'FreeWheeling'. The main window should appear. If it does not, 53 | consult the Console log (step 4), or try running from a Terminal. 54 | 55 | Using FreeWheeling for Mac OS X 56 | =============================== 57 | 58 | FreeWheeling can be driven from any one MIDI source. To select 59 | the source, choose 'Preferences' from the 'Fweelin' menu. 60 | 61 | By default, FreeWheeling grabs loops with the QWERTY keys as well as 62 | one octave of keys on your MIDI keyboard. This can be configured in 63 | the configuration files. The main one is ~/.fweelin/fweelin.xml. 64 | They are all stored in ~/.fweelin. 65 | 66 | Some keyboard commands (function keys especially) may conflict 67 | with Mac OS X keyboard shortcuts. I suggest using an external USB keyboard, 68 | or modifying Freewheeling's configuration. 69 | 70 | You will have to connect audio to go into and out of FreeWheeling using 71 | Jack Pilot. Most often, you will want to route your system audio inputs 72 | into FreeWheeling, and FreeWheeling's audio outputs back out to the system, 73 | or into a sequencer or effects program. Regular Mac audio apps work with JACK. 74 | Simply point them to the 'JACK' device. 75 | 76 | FreeWheeling can also drive soft-synths and effects. FreeWheeling creates 77 | several MIDI outputs, which appear as virtual MIDI sources. 78 | You can connect your audio apps to these MIDI sources. 79 | FreeWheeling has a built-in configurable patch browser that can be used to select 80 | patches on different MIDI outputs. You can also create combination patches that 81 | split your MIDI input into a variety of keyboard zones, playing different outputs 82 | together. 83 | 84 | For a crash-course in Freewheeling (albeit, an old version), 85 | please refer to the video tutorials at: 86 | http://freewheeling.sourceforge.net/ 87 | 88 | If you'd like to configure Freewheeling, 89 | please read the configuration files located 90 | in your home folder in the hidden subfolder .fweelin/ 91 | (once you've run FreeWheeling, this folder appears) 92 | 93 | To find this folder through the Finder, 94 | you must have hidden files enabled in your Finder. 95 | Or, you can access it through the Mac Terminal app. 96 | 97 | For more help, please browse or sign on to the mailing-list. 98 | 99 | Happy Looping! 100 | -JP Mercury. 101 | 102 | Compiling FreeWheeling from Source 103 | ================================== 104 | 105 | FreeWheeling for Mac OS X can be compiled from source. 106 | Download the source package. 107 | You will need Apple's XCode tools. 108 | 109 | Load MacOSX/fweelin.xcodeproj 110 | FreeWheeling depends on several frameworks. 111 | Many of these can be installed from third-party sites. 112 | 113 | However, some, such as libsndfile, 114 | require a small amount of tweaking to be compiled as Frameworks. 115 | A ZIP file of all dependency Frameworks with xcodeproj files is 116 | available. Please contact JP Mercury: 117 | 118 | http://home.graffiti.net/swirlee/swirlee.jpg 119 | 120 | If you wish to contribute to the development of FreeWheeling, 121 | please be in touch. 122 | 123 | Happy Compiling! 124 | -JP Mercury. 125 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | # -*- Autoconf -*- 2 | # Process this file with autoconf to produce a configure script. 3 | AC_PREREQ([2.69]) 4 | AC_INIT([fweelin],[0.6.6],[https://github.com/free-wheeling/freewheeling/issues]) 5 | AM_INIT_AUTOMAKE([subdir-objects]) 6 | AC_CONFIG_SRCDIR([src/fweelin.cc]) 7 | #AM_CONFIG_HEADER(config.h) 8 | 9 | AC_ARG_ENABLE(fluidsynth,[ --enable-fluidsynth use integrated FluidSynth softsynth (libfluidsynth) (default=auto) ]) 10 | AC_ARG_ENABLE(video,[ --disable-video disable video output ]) 11 | AC_ARG_ENABLE(lcd,[ --enable-lcd enable USB LCD display output ]) 12 | 13 | # Checks for programs. 14 | AC_PROG_CXX 15 | AC_PROG_CC 16 | 17 | # Add Xtra Paths for Checking 18 | AC_PATH_XTRA 19 | #if test x"$no_x" = xyes; then 20 | # AC_ERROR([Can not find X11 development headers or libraries.]) 21 | #fi 22 | 23 | # Checks for libraries. 24 | 25 | #AC_CHECK_LIB([X11], [XOpenDisplay], , [AC_MSG_ERROR(VIDEO: You need libx11-dev installed)]) 26 | AC_CHECK_LIB([nettle], [main], , [AC_MSG_ERROR(You need nettle-dev installed)]) 27 | AC_CHECK_LIB([dl], [main], , [AC_MSG_ERROR(You need libc6-dev installed)]) 28 | AC_CHECK_LIB([freetype], [FT_Init_FreeType], , 29 | [AC_MSG_ERROR(VIDEO: You need libfreetype6-dev installed. 30 | http://freetype.sourceforge.net/index2.html)]) 31 | 32 | # Check for SDL_gfx with different function names.. 33 | AC_CHECK_LIB([SDL_gfx], [main], , 34 | [AC_MSG_ERROR(VIDEO: You need libsdl-gfx1.2-dev installed. 35 | http://www.ferzkopp.net/wordpress/2016/01/02/sdl_gfx-sdl2_gfx/)]) 36 | AC_CHECK_FUNC(filledPieRGBA, [AC_DEFINE(CAPITAL_FILLED_PIE)]) 37 | AC_CHECK_LIB([SDL_ttf], [main], , 38 | [AC_MSG_ERROR(VIDEO: You need libsdl-ttf2.0-dev installed. 39 | http://www.libsdl.org/projects/SDL_ttf/release-1.2.html)]) 40 | PKG_CHECK_MODULES([SDL], [sdl >= 1.2 sdl < 1.3], , 41 | [AC_MSG_ERROR(VIDEO: You need libsdl1.2-dev installed. http://www.libsdl.org/)]) 42 | 43 | AC_CHECK_LIB([lo], [main], , [AC_MSG_ERROR(CONFIG: You need liblo-dev installed. 44 | http://http://liblo.sourceforge.net/)]) 45 | 46 | AC_CHECK_LIB([xml2], [main], , 47 | [AC_MSG_ERROR(CONFIG: You need libxml2-dev installed. 48 | http://www.xmlsoft.org/)]) 49 | 50 | AC_CHECK_LIB([m], [sqrt], , [AC_MSG_ERROR(CORE: You need libm installed)]) 51 | AC_CHECK_LIB([pthread], [pthread_self], , [AC_MSG_ERROR(CORE: You need libpthread installed)]) 52 | 53 | AC_CHECK_LIB([asound], [main], , 54 | [AC_MSG_ERROR(AUDIO: You need ALSA installed (libasound2-dev). 55 | http://www.alsa-project.org/)]) 56 | 57 | AC_CHECK_LIB([jack], [jack_client_open], , 58 | [AC_MSG_ERROR(AUDIO: You need JACK audio library (libjack-dev) installed. 59 | http://jackit.sourceforge.net/)]) 60 | 61 | if test "$enable_fluidsynth" != "no"; then 62 | AC_CHECK_LIB([fluidsynth], [main], fluidsynth=yes, fluidsynth=no) 63 | if test "$fluidsynth" = "yes"; then 64 | LIBS="$LIBS -lfluidsynth" 65 | AC_DEFINE(USE_FLUIDSYNTH, 1, 66 | [Define if FluidSynth support should be enabled]) 67 | echo "--- Enabling integrated FluidSynth synth ---"; 68 | else 69 | echo "--- No libfluidsynth -- FluidSynth support will not be built! ---"; 70 | fi 71 | else 72 | echo "--- Disabling integrated FluidSynth synth ---"; 73 | fi 74 | 75 | if test "$enable_video" == "no"; then 76 | AC_DEFINE(NO_VIDEO, 1, [Define if video output is disabled]) 77 | echo "--- Disabling video output --"; 78 | fi 79 | 80 | if test "$enable_lcd" == "yes"; then 81 | AC_DEFINE(LCD_DISPLAY, 1, [Define if USB LCD display is enabled]) 82 | echo "--- Enabling USB LCD display --"; 83 | fi 84 | 85 | #SDL_VERSION=1.2.4 86 | #AM_PATH_SDL($SDL_VERSION, 87 | # :, 88 | # AC_MSG_ERROR([VIDEO: *** SDL version $SDL_VERSION not found! 89 | # http://www.libsdl.org/]) 90 | #) 91 | 92 | AC_CHECK_LIB([vorbis], [main], , 93 | [AC_MSG_ERROR(AUDIO: You need libvorbis-dev installed. 94 | http://www.xiph.org/ogg/vorbis/)]) 95 | AC_CHECK_LIB([vorbisfile], [main], , 96 | [AC_MSG_ERROR(AUDIO: You need libvorbisfile installed. 97 | http://www.xiph.org/ogg/vorbis/)]) 98 | AC_CHECK_LIB([vorbisenc], [main], , 99 | [AC_MSG_ERROR(AUDIO: You need libvorbis-dev installed. 100 | http://www.xiph.org/ogg/vorbis/)]) 101 | AC_CHECK_LIB([ogg], [main], , 102 | [AC_MSG_ERROR(AUDIO: You need libogg-dev installed. 103 | http://www.xiph.org/ogg/vorbis/)]) 104 | 105 | AC_CHECK_LIB([sndfile], [main], , 106 | [AC_MSG_ERROR(AUDIO: you need libsndfile-dev installed. 107 | http://www.http://www.mega-nerd.com/libsndfile/)]) 108 | 109 | CFLAGS="$CFLAGS $SDL_CFLAGS" 110 | LIBS="$X_LIBS $X_PRE_LIBS -L/usr/X11R6/lib -lX11 $X_EXTRA_LIBS $LIBS" 111 | LIBS="$LIBS $SDL_LIBS" 112 | 113 | # Checks for header files. 114 | AC_PATH_X 115 | AC_HEADER_STDC 116 | AC_CHECK_HEADERS([errno.h fcntl.h inttypes.h limits.h stdint.h stdlib.h string.h sys/resource.h sys/time.h termios.h unistd.h utime.h]) 117 | 118 | # Checks for typedefs, structures, and compiler characteristics. 119 | AC_C_CONST 120 | AC_HEADER_TIME 121 | AC_C_INLINE 122 | AC_TYPE_INT32_T 123 | AC_TYPE_PID_T 124 | AC_TYPE_SIZE_T 125 | AC_CHECK_HEADER_STDBOOL 126 | AC_TYPE_UINT32_T 127 | AC_TYPE_UINT8_T 128 | 129 | # Checks for library functions. 130 | AC_FUNC_ALLOCA 131 | AC_FUNC_ERROR_AT_LINE 132 | AC_FUNC_FORK 133 | AC_FUNC_MALLOC 134 | AC_FUNC_STRTOD 135 | AC_CHECK_FUNCS([atexit dup2 floor gettimeofday memset pow realpath select sqrt strcasecmp strchr strncasecmp strrchr strtol]) 136 | 137 | AC_OUTPUT(Makefile src/Makefile data/Makefile) 138 | -------------------------------------------------------------------------------- /src/fweelin_paramset.h: -------------------------------------------------------------------------------- 1 | #ifndef __FWEELIN_PARAMSET_H 2 | #define __FWEELIN_PARAMSET_H 3 | 4 | /* Copyright 2004-2011 Jan Pekau 5 | 6 | This file is part of Freewheeling. 7 | 8 | Freewheeling is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 2 of the License, or 11 | (at your option) any later version. 12 | 13 | Freewheeling is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with Freewheeling. If not, see . */ 20 | 21 | #include "fweelin_event.h" 22 | #include "fweelin_config.h" 23 | 24 | class ParamSetParam { 25 | public: 26 | ParamSetParam(char *name = 0, float value = 0) : name(0), value(value) { 27 | SetName(name); 28 | }; 29 | 30 | void SetName(char *name) { 31 | if (this->name != 0) 32 | delete[] this->name; 33 | 34 | if (name != 0) { 35 | printf("(param name: %s) ",name); 36 | 37 | this->name = new char[strlen(name)+1]; 38 | strcpy(this->name,name); 39 | } 40 | } 41 | 42 | char *name; // Name of parameter 43 | float value; // Value of parameter 44 | }; 45 | 46 | class ParamSetBank { 47 | public: 48 | ParamSetBank() : name(0), firstparamidx(0), maxvalue(1.0), params(0) {}; 49 | ~ParamSetBank() { 50 | if (params != 0) 51 | delete[] params; 52 | }; 53 | 54 | void Setup(char *name, int numparams, float maxvalue) { 55 | this->numparams = numparams; 56 | this->maxvalue = maxvalue; 57 | SetName(name); 58 | params = new ParamSetParam[numparams]; 59 | 60 | printf("(bank %s with %d params) ",name,numparams); 61 | }; 62 | 63 | void SetName(char *name) { 64 | if (this->name != 0) 65 | delete[] this->name; 66 | 67 | if (name != 0) { 68 | this->name = new char[strlen(name)+1]; 69 | strcpy(this->name,name); 70 | } 71 | } 72 | 73 | char *name; // Of bank 74 | int numparams, // Number of parameters in bank 75 | firstparamidx; // Index of first parameter currently shown 76 | float maxvalue; // Maximum value of any parameter in this bank 77 | // (used for scaling the visual) 78 | 79 | ParamSetParam *params; // Array of parameters 80 | }; 81 | 82 | class FloDisplayParamSet : public FloDisplay, public EventListener, public EventProducer { 83 | public: 84 | FloDisplayParamSet (Fweelin *app, char *name, int iid, int numactiveparams, int numbanks, int sx, int sy) : FloDisplay(iid), 85 | app(app), name(name), numactiveparams(numactiveparams), invalidparam(0.), sx(sx), sy(sy), numbanks(numbanks), curbank(0) { 86 | this->name = new char[strlen(name)+1]; 87 | strcpy(this->name,name); 88 | 89 | banks = new ParamSetBank[numbanks]; 90 | activeparam = new UserVariable *[numactiveparams]; 91 | 92 | // SetupSystemVariables(); 93 | }; 94 | ~FloDisplayParamSet() { 95 | app->getEMG()->UnlistenEvent(this,0,T_EV_VideoShowParamSetBank); 96 | app->getEMG()->UnlistenEvent(this,0,T_EV_VideoShowParamSetPage); 97 | app->getEMG()->UnlistenEvent(this,0,T_EV_ParamSetGetAbsoluteParamIdx); 98 | app->getEMG()->UnlistenEvent(this,0,T_EV_ParamSetSetParam); 99 | app->getEMG()->UnlistenEvent(this,0,T_EV_ParamSetGetParam); 100 | 101 | delete[] name; 102 | delete[] banks; 103 | delete[] activeparam; 104 | }; 105 | 106 | #if 0 107 | // Link system variables for each active parameter to the actual parameter 108 | // values, based on the current bank and parameter page. 109 | void LinkActiveParams(); 110 | 111 | void SetupSystemVariables() { 112 | int slen = strlen(name) + 255; 113 | char tmp[slen+1]; 114 | 115 | for (int i = 0; i < numactiveparams; i++) { 116 | snprintf(tmp,slen,"SYSTEM_paramset_%s_activeparam%d_value",name,i); 117 | activeparam[i] = app->getCFG()->AddEmptyVariable(tmp); 118 | printf("CONFIG: Add parameter set global variable: %s\n",tmp); 119 | } 120 | 121 | LinkActiveParams(); 122 | }; 123 | #endif 124 | 125 | void ListenEvents() { 126 | app->getEMG()->ListenEvent(this,0,T_EV_VideoShowParamSetBank); 127 | app->getEMG()->ListenEvent(this,0,T_EV_VideoShowParamSetPage); 128 | app->getEMG()->ListenEvent(this,0,T_EV_ParamSetGetAbsoluteParamIdx); 129 | app->getEMG()->ListenEvent(this,0,T_EV_ParamSetGetParam); 130 | app->getEMG()->ListenEvent(this,0,T_EV_ParamSetSetParam); 131 | }; 132 | 133 | virtual FloDisplayType GetFloDisplayType() { return FD_ParamSet; }; 134 | 135 | virtual void Draw(SDL_Surface *screen); 136 | 137 | virtual void ReceiveEvent(Event *ev, EventProducer */*from*/); 138 | 139 | Fweelin *app; 140 | char *name; // Of parameter set 141 | 142 | int numactiveparams; // Number of parameters active & displayed at a time 143 | UserVariable **activeparam; // Array of pointers to active parameters, 144 | // stored as system variables 145 | float invalidparam; // Placeholder value for invalid parameter 146 | 147 | int sx, sy, // Size of parameter set display 148 | margin; // Margin for text 149 | 150 | int numbanks, // Number of banks 151 | curbank; // Currently active bank 152 | ParamSetBank *banks; // Array of all banks 153 | }; 154 | 155 | #endif 156 | -------------------------------------------------------------------------------- /data/graphics.xml: -------------------------------------------------------------------------------- 1 | 2 | 26 | 27 | 28 | 29 | 30 | 33 | 34 | 35 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 54 | 55 | 112 | 113 | 114 | 115 | -------------------------------------------------------------------------------- /src/fweelin_looplibrary.h: -------------------------------------------------------------------------------- 1 | #ifndef __FWEELIN_LOOPLIBRARY_H 2 | #define __FWEELIN_LOOPLIBRARY_H 3 | 4 | /* Copyright 2004-2011 Jan Pekau 5 | 6 | This file is part of Freewheeling. 7 | 8 | Freewheeling is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 2 of the License, or 11 | (at your option) any later version. 12 | 13 | Freewheeling is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with Freewheeling. If not, see . */ 20 | 21 | #include 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include "fweelin_core.h" 29 | 30 | class LibraryFileInfo { 31 | public: 32 | LibraryFileInfo () : exists(0), c(UNKNOWN), name("") {}; 33 | 34 | char exists; // File exists? 35 | codec c; // Codec (extension of file) for audio files 36 | std::string name; // Name of file 37 | }; 38 | 39 | class LibraryHelper { 40 | public: 41 | // Returns the stub (base of filename) for a given loop in memory 42 | static const std::string GetStubnameFromLoop (Fweelin *app, Loop *l) { 43 | std::ostringstream tmp; 44 | GET_SAVEABLE_HASH_TEXT(l->GetSaveHash()); 45 | tmp << app->getCFG()->GetLibraryPath() << "/" << FWEELIN_OUTPUT_LOOP_NAME << "-" << 46 | hashtext; 47 | 48 | return tmp.str(); 49 | }; 50 | 51 | // Returns, for example, fw-lib/live24. Does not return the file extension. 52 | static const std::string GetNextAvailableStreamOutFilename (Fweelin *app, int &stream_num, std::string &display_name) { 53 | // Create appropriate filename for output 54 | char go = 1; 55 | 56 | do { 57 | // Scan for already existing output streams, using the timing file as a check 58 | std::ostringstream tmp; 59 | tmp << app->getCFG()->GetLibraryPath() << "/" << FWEELIN_OUTPUT_STREAM_NAME << stream_num << 60 | FWEELIN_OUTPUT_TIMING_EXT; 61 | const std::string s = tmp.str(); 62 | 63 | struct stat st; 64 | printf("DISK: Test '%s' for streaming.\n",s.c_str()); 65 | fflush(stdout); 66 | if (stat(s.c_str(),&st) == 0) { 67 | printf("DISK: File exists, trying another.\n"); 68 | stream_num++; 69 | } else { 70 | // No file with this name. Name is free. 71 | 72 | // Prepare base name with and without path 73 | go = 0; 74 | std::ostringstream tmp2; 75 | tmp2 << app->getCFG()->GetLibraryPath() << "/" << FWEELIN_OUTPUT_STREAM_NAME << stream_num; 76 | const std::string s2 = tmp2.str(); 77 | 78 | std::ostringstream display_tmp; 79 | display_tmp << FWEELIN_OUTPUT_STREAM_NAME << stream_num; 80 | display_name = display_tmp.str(); 81 | 82 | return s2; 83 | } 84 | } while (go); 85 | 86 | return ""; 87 | }; 88 | 89 | // Finds the loop with given stubname in the loop library. Returns information about it. 90 | static LibraryFileInfo GetLoopFilenameFromStub (Fweelin *app, const char *stubname) { 91 | struct stat st; 92 | 93 | LibraryFileInfo ret; 94 | 95 | // Try exact filename with all format types 96 | for (codec i = FIRST_FORMAT; i < END_OF_FORMATS; i = (codec) (i+1)) { 97 | std::ostringstream tmp; 98 | tmp << stubname << app->getCFG()->GetAudioFileExt(i); 99 | const std::string s = tmp.str(); 100 | if (stat(s.c_str(),&st) == 0) { 101 | // Found it 102 | ret.exists = 1; 103 | ret.c = i; 104 | ret.name = s; 105 | return ret; 106 | } 107 | } 108 | 109 | // No go, try wildcard search with all format types 110 | for (codec i = FIRST_FORMAT; i < END_OF_FORMATS; i = (codec) (i+1)) { 111 | std::ostringstream tmp; 112 | tmp << stubname << "*" << app->getCFG()->GetAudioFileExt(i); 113 | const std::string s = tmp.str(); 114 | 115 | glob_t globbuf; 116 | if (glob(s.c_str(), 0, NULL, &globbuf) == 0) { 117 | for (size_t j = 0; j < globbuf.gl_pathc; j++) { 118 | if (stat(globbuf.gl_pathv[j],&st) == 0) { 119 | // Found it 120 | ret.exists = 1; 121 | ret.c = i; 122 | ret.name = globbuf.gl_pathv[j]; 123 | globfree(&globbuf); 124 | return ret; 125 | } 126 | } 127 | globfree(&globbuf); 128 | } 129 | } 130 | 131 | return ret; 132 | }; 133 | 134 | // Finds the data (XML) file with given stubname in the loop library. Returns information about it. 135 | static LibraryFileInfo GetDataFilenameFromStub (Fweelin */*app*/, const char *stubname) { 136 | struct stat st; 137 | 138 | LibraryFileInfo ret; 139 | 140 | // Try exact filename 141 | { 142 | std::ostringstream tmp; 143 | tmp << stubname << FWEELIN_OUTPUT_DATA_EXT; 144 | const std::string s = tmp.str(); 145 | 146 | if (stat(s.c_str(),&st) == 0) { 147 | // Found it 148 | ret.exists = 1; 149 | ret.name = s; 150 | return ret; 151 | } 152 | } 153 | 154 | // No go, try wildcard search 155 | { 156 | std::ostringstream tmp; 157 | tmp << stubname << "*" << FWEELIN_OUTPUT_DATA_EXT; 158 | const std::string s = tmp.str(); 159 | 160 | glob_t globbuf; 161 | if (glob(s.c_str(), 0, NULL, &globbuf) == 0) { 162 | for (size_t j = 0; j < globbuf.gl_pathc; j++) { 163 | if (stat(globbuf.gl_pathv[j],&st) == 0) { 164 | // Found it 165 | ret.exists = 1; 166 | ret.name = globbuf.gl_pathv[j]; 167 | globfree(&globbuf); 168 | return ret; 169 | } 170 | } 171 | globfree(&globbuf); 172 | } 173 | } 174 | 175 | return ret; 176 | }; 177 | }; 178 | 179 | #endif 180 | -------------------------------------------------------------------------------- /scripts/patch-ghostess-xml-patchlist: -------------------------------------------------------------------------------- 1 | diff -u ghostess-20050916/src/ghostess.c ghostess-20050916-nw/src/ghostess.c 2 | --- ghostess-20050916/src/ghostess.c 2005-09-16 10:03:16.000000000 -0700 3 | +++ ghostess-20050916-nw/src/ghostess.c 2006-03-29 11:46:38.000000000 -0800 4 | @@ -14,6 +14,9 @@ 5 | * Chris Cannam, and Richard Bown. 6 | * - midisine.c, copyright (C) 2004 Ian Esten. 7 | * 8 | + * Modifications for outputting XML formatted patch list 9 | + * by JP Mercury 10 | + * 11 | * This is a host for DSSI plugins. It listens for MIDI events on an 12 | * ALSA sequencer or CoreMIDI port, delivers them to DSSI synths and 13 | * outputs the result via JACK. 14 | @@ -848,7 +851,7 @@ 15 | } 16 | 17 | int 18 | -write_configuration(FILE *fp) 19 | +write_configuration(char *filename) 20 | { 21 | int rc = 0; 22 | int id, instno, i, in, port; 23 | @@ -856,6 +859,21 @@ 24 | char *arg1 = NULL, 25 | *arg2 = NULL; 26 | configure_item_t *item; 27 | + FILE *fp, *fp2; 28 | + char fn2[strlen(filename)+strlen(".xml")+1]; 29 | + char tmp[255]; 30 | + int j, slen; 31 | + 32 | + // Save configuration 33 | + if ((fp = fopen(filename, "w")) == NULL) 34 | + return 0; 35 | + 36 | + // Save XML patch list 37 | + strcpy(fn2,filename); 38 | + strcat(fn2,".xml"); 39 | + if ((fp2 = fopen(fn2, "w")) == NULL) 40 | + return 0; 41 | + fprintf(fp2,"\n"); 42 | 43 | if (fprintf(fp, "#!/bin/sh\n") < 0) goto error; 44 | if (dssi_path) { 45 | @@ -878,6 +896,7 @@ 46 | for (instno = 0; instances[instno].id != id; instno++); 47 | instance = &instances[instno]; 48 | 49 | + // Write config 50 | escape_for_shell(&arg1, instance->friendly_name); 51 | if (fprintf(fp, "-comment %s \\\n", arg1) < 0) goto error; 52 | 53 | @@ -910,14 +929,59 @@ 54 | escape_for_shell(&arg1, instance->plugin->dll->name); 55 | escape_for_shell(&arg2, instance->plugin->label); 56 | if (fprintf(fp, " %s:%s \\\n", arg1, arg2) < 0) goto error; 57 | + 58 | + // Write patch list 59 | + 60 | +#if 0 61 | + instance->pluginProgramCount = i; 62 | + instance->pluginPrograms = (DSSI_Program_Descriptor *) 63 | + malloc(i * sizeof(DSSI_Program_Descriptor)); 64 | + while (i > 0) { 65 | + const DSSI_Program_Descriptor *descriptor; 66 | + --i; 67 | + descriptor = instance->plugin->descriptor-> 68 | + get_program(instanceHandles[instance->number], i); 69 | + instance->pluginPrograms[i].Bank = descriptor->Bank; 70 | + instance->pluginPrograms[i].Program = descriptor->Program; 71 | + instance->pluginPrograms[i].Name = strdup(descriptor->Name); 72 | + ghss_debug(GDB_PROGRAM, " %s: program %d is MIDI bank %lu program %lu, named '%s'", 73 | + instance->friendly_name, i, 74 | + instance->pluginPrograms[i].Bank, 75 | + instance->pluginPrograms[i].Program, 76 | + instance->pluginPrograms[i].Name); 77 | + } 78 | +#endif 79 | + 80 | + for (i = 0; i < instance->pluginProgramCount; i++) { 81 | + // Replace < and > characters in name (bad XML) 82 | + strncpy(tmp,instance->pluginPrograms[i].Name,254); 83 | + tmp[254] = '\0'; 84 | + slen = strlen(tmp); 85 | + for (j = 0; j < slen; j++) 86 | + if (tmp[j] == '<' || 87 | + tmp[j] == '>') 88 | + tmp[j] = ' '; 89 | + 90 | + fprintf(fp2,"\n", 92 | + instance->channel, 93 | + tmp, 94 | + (int) instance->pluginPrograms[i].Bank, 95 | + (int) instance->pluginPrograms[i].Program); 96 | + } 97 | } 98 | if (fprintf(fp, "\n") < 0) goto error; 99 | rc = 1; 100 | 101 | + fprintf(fp2,"\n"); 102 | + 103 | error: 104 | if (arg1) free(arg1); 105 | if (arg2) free(arg2); 106 | 107 | + fclose(fp); 108 | + fclose(fp2); 109 | + 110 | return rc; 111 | } 112 | 113 | @@ -1670,7 +1734,10 @@ 114 | if (itemplate->program_set) { 115 | instance->currentBank = itemplate->bank; 116 | instance->currentProgram = itemplate->program; 117 | - instance->pendingProgramChange = 0; 118 | + // JPM-Changed pendingProgramChange from 0 to -1 119 | + // was causing program list to not be dumped when 120 | + // -prog specified 121 | + instance->pendingProgramChange = -1; 122 | } else { 123 | instance->currentBank = 0; 124 | instance->currentProgram = 0; 125 | diff -u ghostess-20050916/src/ghostess.h ghostess-20050916-nw/src/ghostess.h 126 | --- ghostess-20050916/src/ghostess.h 2005-09-16 09:12:13.000000000 -0700 127 | +++ ghostess-20050916-nw/src/ghostess.h 2006-03-29 11:05:57.000000000 -0800 128 | @@ -188,7 +188,7 @@ 129 | extern int midi_thread_running; 130 | extern pthread_mutex_t midiEventBufferMutex; 131 | 132 | -int write_configuration(FILE *fp); 133 | +int write_configuration(char *filename); 134 | void ui_osc_free(d3h_instance_t *instance); 135 | void start_ui(d3h_instance_t *instance); 136 | 137 | diff -u ghostess-20050916/src/gui_callbacks.c ghostess-20050916-nw/src/gui_callbacks.c 138 | --- ghostess-20050916/src/gui_callbacks.c 2005-09-16 10:09:22.000000000 -0700 139 | +++ ghostess-20050916-nw/src/gui_callbacks.c 2006-03-29 11:08:32.000000000 -0800 140 | @@ -120,8 +120,6 @@ 141 | void 142 | on_save_file_ok( GtkWidget *widget, gpointer data ) 143 | { 144 | - FILE *fp; 145 | - 146 | gtk_widget_hide(save_file_selection); 147 | file_selection_last_filename = (gchar *)gtk_file_selection_get_filename( 148 | GTK_FILE_SELECTION(save_file_selection)); 149 | @@ -129,14 +127,9 @@ 150 | ghss_debug(GDB_GUI, " on_save_file_ok: file '%s' selected", 151 | file_selection_last_filename); 152 | 153 | - if ((fp = fopen(file_selection_last_filename, "w")) == NULL) { 154 | - display_notice("Save Configuration failed:", strerror(errno)); 155 | - return; 156 | - } 157 | - if (!write_configuration(fp)) { 158 | + if (!write_configuration(file_selection_last_filename)) { 159 | display_notice("Save Configuration failed:", strerror(errno)); 160 | } 161 | - fclose(fp); 162 | display_notice("Configuration Saved.", ""); 163 | } 164 | 165 | -------------------------------------------------------------------------------- /src/fweelin_osc.cc: -------------------------------------------------------------------------------- 1 | /* 2 | Recovery is a long process-- 3 | 4 | 1 day 5 | at 6 | a 7 | time 8 | */ 9 | 10 | /* Copyright 2004-2011 Jan Pekau 11 | 12 | This file is part of Freewheeling. 13 | 14 | Freewheeling is free software: you can redistribute it and/or modify 15 | it under the terms of the GNU General Public License as published by 16 | the Free Software Foundation, either version 2 of the License, or 17 | (at your option) any later version. 18 | 19 | Freewheeling is distributed in the hope that it will be useful, 20 | but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 | GNU General Public License for more details. 23 | 24 | You should have received a copy of the GNU General Public License 25 | along with Freewheeling. If not, see . */ 26 | 27 | #ifndef __MACOSX__ 28 | 29 | #include 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | #include 37 | #include 38 | 39 | #include 40 | #include 41 | #include 42 | 43 | #include 44 | #include 45 | 46 | #include "fweelin_core.h" 47 | #include "fweelin_osc.h" 48 | #include "fweelin_looplibrary.h" 49 | 50 | OSCClient::OSCClient(Fweelin *app) : app(app), qtractor_addr(0) { 51 | printf("OSC: Start.\n"); 52 | 53 | // Init mutex/conditions 54 | pthread_mutex_init(&osc_client_lock,0); 55 | 56 | app->getEMG()->ListenEvent(this,0,T_EV_TransmitPlayingLoopsToDAW); 57 | }; 58 | 59 | OSCClient::~OSCClient() { 60 | printf("OSC: End.\n"); 61 | 62 | if (qtractor_addr != 0) 63 | lo_address_free(qtractor_addr); 64 | 65 | app->getEMG()->UnlistenEvent(this,0,T_EV_TransmitPlayingLoopsToDAW); 66 | 67 | pthread_mutex_destroy (&osc_client_lock); 68 | } 69 | 70 | void OSCClient::ReceiveEvent(Event *evt, EventProducer */*from*/) { 71 | switch (evt->GetType()) { 72 | case T_EV_TransmitPlayingLoopsToDAW : 73 | { 74 | // OK! 75 | if (CRITTERS) 76 | printf("OSC: Received TransmitPlayingLoopsToDAWEvent\n"); 77 | 78 | SendPlayingLoops(); 79 | } 80 | break; 81 | 82 | default: 83 | break; 84 | } 85 | } 86 | 87 | void OSCClient::SendPlayingLoops() { 88 | pthread_mutex_lock(&osc_client_lock); 89 | 90 | if (!open_qtractor_connection()) { 91 | // Get long count 92 | Pulse *p = 0; 93 | int lc = app->getLOOPMGR()->GetLongCountForAllPlayingLoops(p); 94 | nframes_t max_len = 0; 95 | 96 | // Set QTractor tempo based on pulse 97 | if (p != 0) { 98 | nframes_t bar_len; 99 | int sync_speed = (app->GetSyncSpeed() > 0 ? app->GetSyncSpeed() : 1), 100 | beats_per_bar = 4; 101 | 102 | if (!app->GetSyncType()) 103 | // Bar-sync, one pulse represents several bars 104 | bar_len = p->GetLength()/sync_speed; 105 | else { 106 | // Beat-sync, one pulse represents one bar of several beats 107 | bar_len = p->GetLength(); 108 | beats_per_bar = sync_speed; 109 | } 110 | 111 | // frames/sec * beats/bar / (frames/bar) == beats / sec 112 | float tempo = 60. * (float) app->getAUDIO()->get_srate() * beats_per_bar / bar_len; 113 | printf("OSC: Send tempo: %f, %d beats per bar - from pulse & sync settings\n",tempo,beats_per_bar); 114 | 115 | if (lo_send(qtractor_addr, "/SetGlobalTempo", "fi", tempo, beats_per_bar) == -1) { 116 | printf("OSC: Error %d: %s\n", lo_address_errno(qtractor_addr), lo_address_errstr(qtractor_addr)); 117 | } 118 | } 119 | 120 | // Scan all loops for playing loops 121 | for (int i = 0; i < app->getCFG()->GetNumTriggers(); i++) { 122 | if (app->getLOOPMGR()->GetStatus(i) == T_LS_Playing) { 123 | Loop *l = app->getTMAP()->GetMap(i); 124 | if (l != 0 && l->GetSaveStatus() == SAVE_DONE) { 125 | // Saved loop. Get filename 126 | const std::string s = LibraryHelper::GetStubnameFromLoop(app,l); 127 | 128 | LibraryFileInfo loopfile = LibraryHelper::GetLoopFilenameFromStub(app,s.c_str()); 129 | if (loopfile.exists) { 130 | char buf[PATH_MAX + 1]; 131 | char *res = realpath(loopfile.name.c_str(), buf); 132 | 133 | if (res != 0) { 134 | // Do not send overlapping regions- this seems to cause clicks in QTractor. 135 | // Region ends look like fadeout then fadein (currently). 136 | nframes_t cflen = app->getAUDIO()->getbufsz() * 2, 137 | len = app->getLOOPMGR()->GetRoundedLength(i); // + cflen; 138 | float gain = l->vol; 139 | 140 | printf("OSC: Transfer loop: %s to Qtractor (nbeats: %d, lc: %d, cflen: %d, len: %d, gain: %0.2f)\n", 141 | buf,(int) l->nbeats,lc,cflen,len,gain); 142 | 143 | // Fill pattern with reps 144 | int nbeats = (l->pulse != 0 && l->nbeats > 0 ? l->nbeats : lc); // Only 1 rep if there is no pulse 145 | nframes_t curstart = 0; 146 | 147 | for (int reps = 0; reps < lc; reps += nbeats, curstart += app->getLOOPMGR()->GetRoundedLength(i)) { 148 | printf("OSC: Send loop @ %d\n",(int) curstart); 149 | if (lo_send(qtractor_addr, "/AddAudioClipOnUniqueTrack", "iiiifs", 150 | (int) curstart, 0, len, cflen, gain, buf) == -1) { 151 | printf("OSC: Error %d: %s\n", lo_address_errno(qtractor_addr), lo_address_errstr(qtractor_addr)); 152 | } 153 | if (curstart + len > max_len) 154 | max_len = curstart + len; // Length of pattern in frames 155 | } 156 | } else 157 | printf("OSC: Can't get path for loop: %s\n",loopfile.name.c_str()); 158 | } else 159 | printf("OSC: Can't find loop: %s\n",s.c_str()); 160 | } 161 | } 162 | } 163 | 164 | // Update loop point 165 | if (lo_send(qtractor_addr, "/AdvanceLoopRange", "ii", 0, max_len) == -1) { 166 | printf("OSC: Error %d: %s\n", lo_address_errno(qtractor_addr), lo_address_errstr(qtractor_addr)); 167 | } 168 | } else { 169 | printf("OSC: Couldn't open an OSC connection to QTractor on port %d\n",QTRACTOR_OSC_PORT); 170 | } 171 | 172 | pthread_mutex_unlock(&osc_client_lock); 173 | } 174 | 175 | // Open or refresh connection to qtractor 176 | char OSCClient::open_qtractor_connection() { 177 | if (qtractor_addr != 0) 178 | lo_address_free(qtractor_addr); 179 | 180 | char portbuf[256]; 181 | snprintf(portbuf,255,"%d",QTRACTOR_OSC_PORT); 182 | qtractor_addr = lo_address_new(NULL, portbuf); 183 | 184 | return (qtractor_addr == 0); 185 | } 186 | 187 | #endif 188 | -------------------------------------------------------------------------------- /src/fweelin_rcu.h: -------------------------------------------------------------------------------- 1 | #ifndef __FWEELIN_RCU_H 2 | #define __FWEELIN_RCU_H 3 | 4 | /* Copyright 2004-2011 Jan Pekau 5 | 6 | This file is part of Freewheeling. 7 | 8 | Freewheeling is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 2 of the License, or 11 | (at your option) any later version. 12 | 13 | Freewheeling is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with Freewheeling. If not, see . */ 20 | 21 | #include 22 | 23 | #include "fweelin_datatypes.h" 24 | #include "fweelin_mem.h" 25 | 26 | // Realtime RCU (Read-Copy-Update) implementation 27 | // That allows light-weight read access to a data structure without locking. 28 | // And more heavy-weight write access 29 | // 30 | // RT_RCU protects one or more pointers to Preallocated objects. 31 | // (More than one pointer can be protected only if they are independent pointers (update can only happen atomically to one pointer)). 32 | class RT_RCU : public RTDataStruct_Updater { 33 | friend class RT_RWThreads; 34 | 35 | public: 36 | 37 | // Create an RCU helper class T 38 | RT_RCU () : global_time_count(1), last_update_time(0), num_readers(RT_RWThreads::num_rw_threads) { 39 | reader_lock_times = new uint32_t[MAX_RW_THREADS]; 40 | for (int i = 0; i < MAX_RW_THREADS; i++) 41 | reader_lock_times[i] = 0; 42 | 43 | // Register this RCU 44 | RT_RWThreads::RegisterRTDataStruct(this); 45 | }; 46 | ~RT_RCU() { 47 | // Unregister this RCU 48 | RT_RWThreads::UnregisterRTDataStruct(this); 49 | 50 | delete[] reader_lock_times; 51 | }; 52 | 53 | // Instance methods 54 | 55 | // Begin read-side critical section - RT and thread-safe 56 | inline int ReadLock () { 57 | if (num_readers != RT_RWThreads::num_rw_threads) { 58 | printf("CORE: ERROR: RT_RCU thread count mismatch.\n"); 59 | exit(1); 60 | } 61 | 62 | // Determine which read thread we are 63 | pthread_t id = pthread_self(); 64 | for (int i = 0; i < num_readers; i++) 65 | if (pthread_equal(id,RT_RWThreads::ids[i])) { 66 | // Increment global time count atomically, storing old value 67 | // (then, no two threads will ever lock with the same time count) 68 | uint32_t cnt = __sync_fetch_and_add(&global_time_count,1); 69 | 70 | // Store global count in reader-specific time count 71 | reader_lock_times[i] = cnt; 72 | 73 | // Must ensure that reader_locktimes[i] has actually been updated before we return, because that's all that protects the 74 | // reader from having the data freed from under their feet 75 | __sync_synchronize(); 76 | 77 | return 0; 78 | } 79 | 80 | printf("CORE: RT_RCU ReadLock from unregistered read thread: %lu!\n",id); 81 | return -1; 82 | }; 83 | 84 | // End read-side critical section - RT and thread-safe 85 | inline int ReadUnlock () { 86 | if (num_readers != RT_RWThreads::num_rw_threads) { 87 | printf("CORE: ERROR: RT_RCU thread count mismatch.\n"); 88 | exit(1); 89 | } 90 | 91 | // Determine which read thread we are 92 | pthread_t id = pthread_self(); 93 | for (int i = 0; i < num_readers; i++) 94 | if (pthread_equal(id,RT_RWThreads::ids[i])) { 95 | // Reset state of this reader thread to unlocked 96 | reader_lock_times[i] = 0; 97 | 98 | __sync_synchronize(); 99 | return 0; 100 | } 101 | 102 | printf("CORE: RT_RCU ReadUnlock from unregistered read thread: %lu!\n",id); 103 | return -1; 104 | }; 105 | 106 | // Update your reference from old_ptr to new_ptr. 107 | // *old_ptr = new_ptr; 108 | // Does this atomically, remembering the time when it was done 109 | inline void Update (volatile Preallocated **old_ptr, Preallocated *new_ptr) { 110 | // Update pointer atomically 111 | *old_ptr = new_ptr; 112 | 113 | // Ensure it has happened in memory by this point 114 | __sync_synchronize(); 115 | 116 | // Increment global time count atomically and store as the last update time 117 | // (guarantees that *old_ptr == new_ptr by last_update_time) 118 | last_update_time = __sync_fetch_and_add(&global_time_count,1); 119 | } 120 | 121 | // Synchronize() is called by the reclaiming thread. 122 | // It waits (using sleep_time microsecond granules), until all read-side critical sections that started BEFORE the last Update() have completed- 123 | // This ensures that no readers are holding a pointer to a structure. After this call returns, the old_ptr (before update) may be freed. 124 | inline void Synchronize (int sleep_time) { 125 | // A warning is issued after waiting for this many microseconds 126 | const static int WARNING_WAIT_TIME = 1000000; 127 | int wait_time = 0; 128 | 129 | char recheck; 130 | do { 131 | recheck = 0; 132 | for (int i = 0; !recheck && i < num_readers; i++) 133 | if (reader_lock_times[i] != 0 && reader_lock_times[i] < last_update_time) 134 | // Pointer was updated during grace period (read-side critical section). Therefore, we must wait til this section unlocks. 135 | recheck = 1; 136 | 137 | if (recheck) { 138 | if ((wait_time + sleep_time) % WARNING_WAIT_TIME < wait_time % WARNING_WAIT_TIME) 139 | // Warn that we are waiting too long 140 | printf("CORE: WARNING: RCU Synchronize() is still waiting (%d secs)...\n",(wait_time + sleep_time) / 1000000); 141 | 142 | // Wait 143 | wait_time += sleep_time; 144 | usleep(sleep_time); 145 | } 146 | } while (recheck); 147 | }; 148 | 149 | private: 150 | 151 | virtual void UpdateNumRWThreads(int new_num_rw_threads) { 152 | printf("CORE: RT_RCU %p: Update reader and writer threads to %d\n",this,new_num_rw_threads); 153 | if (new_num_rw_threads <= num_readers) { 154 | printf("CORE: ERROR: Can't go from %d to %d threads during initialization.\n",num_readers, 155 | new_num_rw_threads); 156 | exit(1); 157 | } else { 158 | // Fixed size structure used, no problem. 159 | } 160 | }; 161 | 162 | volatile uint32_t global_time_count, // Every time a lock, or update occurs, this count is incremented. This allows us to easily tell 163 | // whether a read-side critical section is underway before we reclaim. 164 | last_update_time; // Time when the ptr this RT_RCU protects 165 | volatile uint32_t *reader_lock_times; // Every reader thread has a value that says what was the global_time_count when it was locked, or 0 166 | // if that reader thread is unlocked. 167 | int num_readers; // Local copy of RT_RWThreads::num_rw_threads 168 | }; 169 | 170 | #endif 171 | -------------------------------------------------------------------------------- /data/dancemat.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 14 | 15 | 16 | 17 | 18 | 23 | 28 | 29 | 30 | 35 | 36 | 37 | 38 | 39 | 42 | 43 | 44 | 49 | 52 | 53 | 58 | 59 | 60 | 63 | 64 | 65 | 68 | 69 | 70 | 75 | 76 | 77 | 84 | 85 | 86 | 92 | 93 | 94 | 95 | 101 | 102 | 107 | 108 | 109 | 110 | 113 | 115 | 117 | 118 | 119 | 121 | 122 | 123 | 125 | 126 | 127 | 128 | 130 | 131 | 132 | 134 | 135 | 136 | 137 | 139 | 140 | 141 | 143 | 144 | 145 | 147 | 148 | 149 | 150 | 151 | -------------------------------------------------------------------------------- /src/fweelin_paramset.cc: -------------------------------------------------------------------------------- 1 | /* Copyright 2004-2011 Jan Pekau 2 | 3 | This file is part of Freewheeling. 4 | 5 | Freewheeling is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | Freewheeling is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with Freewheeling. If not, see . */ 17 | 18 | #include 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include 26 | #include 27 | 28 | #include 29 | #include 30 | #include 31 | 32 | #include "fweelin_core.h" 33 | #include "fweelin_paramset.h" 34 | 35 | // Link system variables for each active parameter to the actual parameter 36 | // values, based on the current bank and parameter page. 37 | #if 0 38 | void FloDisplayParamSet::LinkActiveParams() { 39 | for (int i = 0; i < numactiveparams; i++) { 40 | activeparam[i]->type = T_float; 41 | 42 | ParamSetBank *b = &banks[curbank]; 43 | if (b->firstparamidx + i < b->numparams) 44 | activeparam[i]->value = (char *) &(b->params[b->firstparamidx].value); 45 | else 46 | activeparam[i]->value = (char *) &invalidparam; 47 | } 48 | }; 49 | #endif 50 | 51 | void FloDisplayParamSet::ReceiveEvent(Event *ev, EventProducer */*from*/) { 52 | switch (ev->GetType()) { 53 | case T_EV_ParamSetGetAbsoluteParamIdx : 54 | { 55 | ParamSetGetAbsoluteParamIdxEvent *psev = (ParamSetGetAbsoluteParamIdxEvent *) ev; 56 | 57 | if (psev->interfaceid == iid && psev->displayid == id) { 58 | // Message is for this param set display 59 | 60 | if (psev->absidx == 0 || psev->absidx->IsSystemVariable()) 61 | printf(" ParamSetGetAbsoluteParamIdxEvent: The variable provided for the 'absidx' parameter is missing or invalid\n"); 62 | else { 63 | if (psev->absidx->GetType() != T_int) 64 | printf("PARAMSET: ParamSetGetAbsoluteParamIdxEvent: 'absidx' parameter requires a variable of type int."); 65 | else { 66 | ParamSetBank *b = &banks[curbank]; 67 | int idx = b->firstparamidx + psev->paramidx; 68 | if (idx < 0) 69 | idx = 0; 70 | else if (idx >= b->numparams) 71 | idx = b->numparams-1; 72 | 73 | *psev->absidx = idx; 74 | 75 | if (CRITTERS) 76 | printf("PARAMSET: Received ParamSetGetAbsoluteParamIdx (interfaceid: %d displayid: %d) Relative index: %d Returned absolute index: %d\n", 77 | psev->interfaceid,psev->displayid,psev->paramidx,idx); 78 | } 79 | } 80 | } 81 | } 82 | break; 83 | 84 | case T_EV_ParamSetSetParam : 85 | { 86 | ParamSetSetParamEvent *psev = (ParamSetSetParamEvent *) ev; 87 | 88 | if (psev->interfaceid == iid && psev->displayid == id) { 89 | // Message is for this param set display 90 | 91 | ParamSetBank *b = &banks[curbank]; 92 | int idx = b->firstparamidx + psev->paramidx; 93 | if (idx >= 0 && idx < b->numparams) 94 | b->params[idx].value = psev->value; 95 | 96 | if (CRITTERS) { 97 | printf("PARAMSET: Received ParamSetSetParam (interfaceid: %d displayid: %d) Relative index: %d Absolute index: %d Value: %f", 98 | psev->interfaceid,psev->displayid,psev->paramidx,idx,psev->value); 99 | printf("\n"); 100 | } 101 | } 102 | } 103 | break; 104 | 105 | case T_EV_ParamSetGetParam : 106 | { 107 | ParamSetGetParamEvent *psev = (ParamSetGetParamEvent *) ev; 108 | 109 | if (psev->interfaceid == iid && psev->displayid == id) { 110 | // Message is for this param set display 111 | 112 | if (psev->var == 0 || psev->var->IsSystemVariable()) 113 | printf(" ParamSetGetParamEvent: Invalid variable!\n"); 114 | else { 115 | if (psev->var->GetType() != T_float) 116 | printf("PARAMSET: ParamSetGetParamEvent: 'var' must be of type float."); 117 | else { 118 | ParamSetBank *b = &banks[curbank]; 119 | int idx = b->firstparamidx + psev->paramidx; 120 | if (idx >= 0 && idx < b->numparams) 121 | *psev->var = b->params[idx].value; 122 | else 123 | *psev->var = (float) 0.; 124 | 125 | if (CRITTERS) { 126 | printf("PARAMSET: Received ParamSetGetParam (interfaceid: %d displayid: %d) Relative index: %d Absolute index: %d Val: ", 127 | psev->interfaceid,psev->displayid,psev->paramidx,idx); 128 | psev->var->Print(); 129 | printf("\n"); 130 | } 131 | } 132 | } 133 | } 134 | } 135 | break; 136 | 137 | case T_EV_VideoShowParamSetBank : 138 | { 139 | VideoShowParamSetBankEvent *psev = (VideoShowParamSetBankEvent *) ev; 140 | 141 | if (psev->interfaceid == iid && psev->displayid == id) { 142 | // Message is for this param set display 143 | 144 | // Adjust bank 145 | int newbank = curbank + psev->bank; 146 | if (newbank < 0) 147 | newbank = 0; 148 | if (newbank >= numbanks) 149 | newbank = numbanks-1; 150 | curbank = newbank; 151 | 152 | // LinkActiveParams(); 153 | 154 | if (CRITTERS) 155 | printf("PARAMSET: Received VideoShowParamSetBank(interfaceid: %d displayid: %d bank: %d) - Bank # is now %d\n", 156 | psev->interfaceid,psev->displayid,psev->bank,curbank); 157 | } 158 | } 159 | break; 160 | 161 | case T_EV_VideoShowParamSetPage : 162 | { 163 | VideoShowParamSetPageEvent *psev = (VideoShowParamSetPageEvent *) ev; 164 | 165 | if (psev->interfaceid == iid && psev->displayid == id) { 166 | // Message is for this param set display 167 | 168 | // Adjust page in the bank 169 | int newfirstidx = banks[curbank].firstparamidx + numactiveparams * psev->page; 170 | if (newfirstidx < 0) 171 | newfirstidx = 0; 172 | if (newfirstidx >= banks[curbank].numparams) 173 | newfirstidx = banks[curbank].firstparamidx; 174 | 175 | banks[curbank].firstparamidx = newfirstidx; 176 | 177 | // LinkActiveParams(); 178 | 179 | if (CRITTERS) 180 | printf("PARAMSET: Received VideoShowParamSetPage(interfaceid: %d displayid: %d page: %d) - First parameter index is now %d\n", 181 | psev->interfaceid,psev->displayid,psev->page,newfirstidx); 182 | } 183 | break; 184 | } 185 | 186 | default: 187 | break; 188 | } 189 | } 190 | -------------------------------------------------------------------------------- /missing: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # Common wrapper for a few potentially missing GNU programs. 3 | 4 | scriptversion=2018-03-07.03; # UTC 5 | 6 | # Copyright (C) 1996-2018 Free Software Foundation, Inc. 7 | # Originally written by Fran,cois Pinard , 1996. 8 | 9 | # This program is free software; you can redistribute it and/or modify 10 | # it under the terms of the GNU General Public License as published by 11 | # the Free Software Foundation; either version 2, or (at your option) 12 | # any later version. 13 | 14 | # This program is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | # GNU General Public License for more details. 18 | 19 | # You should have received a copy of the GNU General Public License 20 | # along with this program. If not, see . 21 | 22 | # As a special exception to the GNU General Public License, if you 23 | # distribute this file as part of a program that contains a 24 | # configuration script generated by Autoconf, you may include it under 25 | # the same distribution terms that you use for the rest of that program. 26 | 27 | if test $# -eq 0; then 28 | echo 1>&2 "Try '$0 --help' for more information" 29 | exit 1 30 | fi 31 | 32 | case $1 in 33 | 34 | --is-lightweight) 35 | # Used by our autoconf macros to check whether the available missing 36 | # script is modern enough. 37 | exit 0 38 | ;; 39 | 40 | --run) 41 | # Back-compat with the calling convention used by older automake. 42 | shift 43 | ;; 44 | 45 | -h|--h|--he|--hel|--help) 46 | echo "\ 47 | $0 [OPTION]... PROGRAM [ARGUMENT]... 48 | 49 | Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due 50 | to PROGRAM being missing or too old. 51 | 52 | Options: 53 | -h, --help display this help and exit 54 | -v, --version output version information and exit 55 | 56 | Supported PROGRAM values: 57 | aclocal autoconf autoheader autom4te automake makeinfo 58 | bison yacc flex lex help2man 59 | 60 | Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and 61 | 'g' are ignored when checking the name. 62 | 63 | Send bug reports to ." 64 | exit $? 65 | ;; 66 | 67 | -v|--v|--ve|--ver|--vers|--versi|--versio|--version) 68 | echo "missing $scriptversion (GNU Automake)" 69 | exit $? 70 | ;; 71 | 72 | -*) 73 | echo 1>&2 "$0: unknown '$1' option" 74 | echo 1>&2 "Try '$0 --help' for more information" 75 | exit 1 76 | ;; 77 | 78 | esac 79 | 80 | # Run the given program, remember its exit status. 81 | "$@"; st=$? 82 | 83 | # If it succeeded, we are done. 84 | test $st -eq 0 && exit 0 85 | 86 | # Also exit now if we it failed (or wasn't found), and '--version' was 87 | # passed; such an option is passed most likely to detect whether the 88 | # program is present and works. 89 | case $2 in --version|--help) exit $st;; esac 90 | 91 | # Exit code 63 means version mismatch. This often happens when the user 92 | # tries to use an ancient version of a tool on a file that requires a 93 | # minimum version. 94 | if test $st -eq 63; then 95 | msg="probably too old" 96 | elif test $st -eq 127; then 97 | # Program was missing. 98 | msg="missing on your system" 99 | else 100 | # Program was found and executed, but failed. Give up. 101 | exit $st 102 | fi 103 | 104 | perl_URL=https://www.perl.org/ 105 | flex_URL=https://github.com/westes/flex 106 | gnu_software_URL=https://www.gnu.org/software 107 | 108 | program_details () 109 | { 110 | case $1 in 111 | aclocal|automake) 112 | echo "The '$1' program is part of the GNU Automake package:" 113 | echo "<$gnu_software_URL/automake>" 114 | echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" 115 | echo "<$gnu_software_URL/autoconf>" 116 | echo "<$gnu_software_URL/m4/>" 117 | echo "<$perl_URL>" 118 | ;; 119 | autoconf|autom4te|autoheader) 120 | echo "The '$1' program is part of the GNU Autoconf package:" 121 | echo "<$gnu_software_URL/autoconf/>" 122 | echo "It also requires GNU m4 and Perl in order to run:" 123 | echo "<$gnu_software_URL/m4/>" 124 | echo "<$perl_URL>" 125 | ;; 126 | esac 127 | } 128 | 129 | give_advice () 130 | { 131 | # Normalize program name to check for. 132 | normalized_program=`echo "$1" | sed ' 133 | s/^gnu-//; t 134 | s/^gnu//; t 135 | s/^g//; t'` 136 | 137 | printf '%s\n' "'$1' is $msg." 138 | 139 | configure_deps="'configure.ac' or m4 files included by 'configure.ac'" 140 | case $normalized_program in 141 | autoconf*) 142 | echo "You should only need it if you modified 'configure.ac'," 143 | echo "or m4 files included by it." 144 | program_details 'autoconf' 145 | ;; 146 | autoheader*) 147 | echo "You should only need it if you modified 'acconfig.h' or" 148 | echo "$configure_deps." 149 | program_details 'autoheader' 150 | ;; 151 | automake*) 152 | echo "You should only need it if you modified 'Makefile.am' or" 153 | echo "$configure_deps." 154 | program_details 'automake' 155 | ;; 156 | aclocal*) 157 | echo "You should only need it if you modified 'acinclude.m4' or" 158 | echo "$configure_deps." 159 | program_details 'aclocal' 160 | ;; 161 | autom4te*) 162 | echo "You might have modified some maintainer files that require" 163 | echo "the 'autom4te' program to be rebuilt." 164 | program_details 'autom4te' 165 | ;; 166 | bison*|yacc*) 167 | echo "You should only need it if you modified a '.y' file." 168 | echo "You may want to install the GNU Bison package:" 169 | echo "<$gnu_software_URL/bison/>" 170 | ;; 171 | lex*|flex*) 172 | echo "You should only need it if you modified a '.l' file." 173 | echo "You may want to install the Fast Lexical Analyzer package:" 174 | echo "<$flex_URL>" 175 | ;; 176 | help2man*) 177 | echo "You should only need it if you modified a dependency" \ 178 | "of a man page." 179 | echo "You may want to install the GNU Help2man package:" 180 | echo "<$gnu_software_URL/help2man/>" 181 | ;; 182 | makeinfo*) 183 | echo "You should only need it if you modified a '.texi' file, or" 184 | echo "any other file indirectly affecting the aspect of the manual." 185 | echo "You might want to install the Texinfo package:" 186 | echo "<$gnu_software_URL/texinfo/>" 187 | echo "The spurious makeinfo call might also be the consequence of" 188 | echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" 189 | echo "want to install GNU make:" 190 | echo "<$gnu_software_URL/make/>" 191 | ;; 192 | *) 193 | echo "You might have modified some files without having the proper" 194 | echo "tools for further handling them. Check the 'README' file, it" 195 | echo "often tells you about the needed prerequisites for installing" 196 | echo "this package. You may also peek at any GNU archive site, in" 197 | echo "case some other package contains this missing '$1' program." 198 | ;; 199 | esac 200 | } 201 | 202 | give_advice "$1" | sed -e '1s/^/WARNING: /' \ 203 | -e '2,$s/^/ /' >&2 204 | 205 | # Propagate the correct exit status (expected to be 127 for a program 206 | # not found, 63 for a program that failed due to version mismatch). 207 | exit $st 208 | 209 | # Local variables: 210 | # eval: (add-hook 'before-save-hook 'time-stamp) 211 | # time-stamp-start: "scriptversion=" 212 | # time-stamp-format: "%:y-%02m-%02d.%02H" 213 | # time-stamp-time-zone: "UTC0" 214 | # time-stamp-end: "; # UTC" 215 | # End: 216 | -------------------------------------------------------------------------------- /data/pckeyboard.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 14 | 15 | 16 | 17 | 18 | 23 | 28 | 29 | 30 | 34 | 35 | 36 | 39 | 40 | 41 | 47 | 48 | 49 | 54 | 55 | 56 | 59 | 60 | 61 | 62 | 63 | 65 | 67 | 68 | 69 | 71 | 72 | 73 | 75 | 76 | 77 | 79 | 80 | 81 | 83 | 84 | 85 | 87 | 88 | 89 | 91 | 92 | 93 | 95 | 96 | 97 | 99 | 100 | 101 | 103 | 104 | 105 | 106 | 108 | 109 | 110 | 112 | 113 | 114 | 116 | 117 | 118 | 120 | 121 | 122 | 124 | 125 | 126 | 128 | 129 | 130 | 132 | 133 | 134 | 136 | 137 | 138 | 140 | 141 | 142 | 143 | 145 | 146 | 147 | 149 | 150 | 151 | 153 | 154 | 155 | 157 | 158 | 159 | 161 | 162 | 163 | 165 | 166 | 167 | 169 | 170 | 171 | 172 | 173 | -------------------------------------------------------------------------------- /src/fweelin_videoio.h: -------------------------------------------------------------------------------- 1 | #ifndef __FWEELIN_VIDEOIO_H 2 | #define __FWEELIN_VIDEOIO_H 3 | 4 | /* Copyright 2004-2011 Jan Pekau 5 | 6 | This file is part of Freewheeling. 7 | 8 | Freewheeling is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 2 of the License, or 11 | (at your option) any later version. 12 | 13 | Freewheeling is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with Freewheeling. If not, see . */ 20 | 21 | #include "fweelin_event.h" 22 | 23 | #include 24 | 25 | #ifdef __MACOSX__ 26 | #include 27 | #include 28 | #include "FweelinMac.h" 29 | #else 30 | #include 31 | #include 32 | #endif 33 | 34 | #ifdef __MACOSX__ 35 | #define CAPITAL_FILLED_PIE 36 | #endif 37 | 38 | // Different versions of sdl-gfx have different naming 39 | #ifdef CAPITAL_FILLED_PIE 40 | #define FILLED_PIE filledPieRGBA 41 | #else 42 | #define FILLED_PIE filledpieRGBA 43 | #endif 44 | 45 | // Convert from 640,480 screen size to the user's coordinate system 46 | #define OCX(x) (app->getCFG()->XCvt((float)(x)/640)) 47 | #define OCY(y) (app->getCFG()->YCvt((float)(y)/480)) 48 | 49 | #define FWEELIN_TITLE_IMAGE FWEELIN_DATADIR "/fweelin.bmp" 50 | 51 | extern double mygettime(void); 52 | extern int myround(float num); 53 | 54 | class Fweelin; 55 | class LoopManager; 56 | class FloConfig; 57 | class FloLayoutElement; 58 | 59 | // This crazy class computes a mapping 60 | // to bend a flat strip bitmap into a circle-- good for makin wheels! 61 | class CircularMap { 62 | public: 63 | // Create a mapping from the flat surface 'in' to a circular region 64 | // of the given dimensions-- the output surface location is specified when 65 | // actually mapping 66 | CircularMap(SDL_Surface *in, 67 | int map_xs, int map_ys, 68 | int in_xs, int in_ys, 69 | int rinner, int rsize); 70 | // Frees this map 71 | ~CircularMap(); 72 | 73 | // Map flat scope onto circle 74 | char Map(SDL_Surface *out, int dstx, int dsty); 75 | 76 | // Scans for a map with map_xs == sz 77 | CircularMap *Scan(int sz) { 78 | CircularMap *cur = this; 79 | while (cur != 0 && cur->map_xs != sz) 80 | cur = cur->next; 81 | return cur; 82 | }; 83 | // Links the given map to the end of this map list 84 | void Link(CircularMap *nw) { 85 | CircularMap *cur = this; 86 | while (cur->next != 0) 87 | cur = cur->next; 88 | cur->next = nw; 89 | }; 90 | 91 | SDL_Surface *in; 92 | Uint8 **map; 93 | int *scanmap; 94 | int map_xs, map_ys, 95 | in_xs, in_ys, 96 | rinner, rsize; 97 | 98 | CircularMap *next; 99 | }; 100 | 101 | // Video Handler 102 | class VideoIO : public EventProducer, public EventListener { 103 | friend class Fweelin; 104 | 105 | public: 106 | VideoIO (Fweelin *app) : app(app), screen(0), cmaps(0), 107 | showlooprange(0,0), showhelppage(0), cur_iid(0), videothreadgo(0) {}; 108 | 109 | virtual ~VideoIO() {}; 110 | 111 | int activate (); 112 | void close (); 113 | 114 | char IsActive () { return videothreadgo; }; 115 | 116 | double GetVideoTime() { return video_time; }; 117 | 118 | void SetVideoMode(char fullscreen); 119 | char GetVideoMode() { return fullscreen; }; 120 | 121 | void ReceiveEvent(Event *ev, EventProducer */*from*/); 122 | 123 | // Draw text, and optionally return size of text drawn in sx and sy 124 | static int draw_text(SDL_Surface *out, TTF_Font *font, 125 | char *str, int x, int y, SDL_Color clr, char centerx = 0, 126 | char centery = 0, int *sx = 0, int *sy = 0); 127 | 128 | // If no suitable map exists in list 'cmaps', creates a planar>circular map 129 | // of diameter 'sz', mapping from the given surface. 130 | CircularMap *CreateMap(SDL_Surface *lscopepic, int sz); 131 | 132 | inline SDL_Surface *getLSCOPEPIC() { return lscopepic; }; 133 | 134 | // Draw the circular scope and status information for one loop-- 135 | // given by loopid 'i' and optional layout element 'curel'.. 136 | // if curel is null, we draw direct with the given circular map 137 | // and position. 138 | // Returns nonzero if loop not drawn 139 | char DrawLoop(LoopManager *loopmgr, int i, 140 | SDL_Surface *screen, SDL_Surface *lscopepic, 141 | SDL_Color *loopcolors, float colormag, 142 | FloConfig *fs, FloLayoutElement *curel, 143 | 144 | CircularMap *direct_map, int direct_xpos, 145 | int direct_ypos, 146 | 147 | float lvol, 148 | char drawtext = 1); 149 | 150 | protected: 151 | 152 | // Core app 153 | Fweelin *app; 154 | 155 | // Video event handler thread 156 | static void *run_video_thread (void *ptr); 157 | void video_event_loop (); 158 | 159 | // This is a custom surface blitter that doesn't use large block 160 | // memory writes and thus avoids the strange video glitch of introducing 161 | // audio pops on some machines-- some loss in performance! 162 | void Custom_BlitSurface(SDL_Surface *in, SDL_Surface *out, 163 | SDL_Rect *dstrect); 164 | 165 | void Squeeze_BlitSurface(SDL_Surface *in, SDL_Surface *out, 166 | SDL_Rect *dstrect); 167 | 168 | #ifdef __MACOSX__ 169 | FweelinMac cocoa; // Cocoa thread setup 170 | #endif 171 | 172 | char fullscreen; // Fullscreen video? 173 | 174 | SDL_Surface *screen; 175 | 176 | // Pointers to fonts that video uses - links into FloFont structures 177 | TTF_Font *mainfont, *helpfont, *smallfont, *tinyfont; 178 | 179 | // Planar->Circular mapping variables 180 | CircularMap *cmaps; 181 | int lscopewidth, lscopeheight; 182 | SDL_Surface *lscopepic; 183 | 184 | nframes_t *curpeakidx, 185 | *lastpeakidx; 186 | float *oldpeak; 187 | 188 | Range showlooprange; // Which loops to show onscreen 189 | int showhelppage, // Which help page to show (0=off) 190 | numhelppages; // Number of help pages that are defined 191 | 192 | int cur_iid; // ID of currently visible (switchable) interface 193 | 194 | // Length of time taken (s) for one iteration of video loop 195 | double video_time; 196 | 197 | pthread_t video_thread; 198 | char videothreadgo; 199 | 200 | pthread_mutex_t video_thread_lock; 201 | 202 | #ifdef LCD_DISPLAY 203 | #define LCD_ROWS 4 204 | #define LCD_COLS 20 205 | 206 | // Initialize LCD connection 207 | int InitLCD (char *devname, int baud); 208 | 209 | // Writing directly to LCD 210 | inline void LCD_Send (unsigned char dat) { 211 | if (lcd_handle) 212 | while (write(lcd_handle, &dat, 1) != 1) { 213 | printf("LCD_Send failed\n"); 214 | usleep(1000); 215 | } 216 | }; 217 | 218 | inline void LCD_SendStr (char *data) { 219 | while (*data) 220 | LCD_Send(*data++); 221 | } 222 | 223 | // Writing to LCD via double buffer (more efficient) 224 | inline void LCDB_SetChar (int row, int col, char dat) { 225 | if (row >= 0 && row < LCD_ROWS && col >= 0 && col < LCD_COLS) 226 | lcd_dat[lcd_curb][row][col] = dat; 227 | }; 228 | 229 | inline void LCDB_SetStr (int row, int col, char *data) { 230 | while (*data) 231 | LCDB_SetChar(row,col++,*data++); 232 | } 233 | 234 | inline void LCDB_Clear () { 235 | memset(lcd_dat[lcd_curb],' ',sizeof(char) * LCD_ROWS * LCD_COLS); 236 | }; 237 | 238 | inline void LCDB_Debug () { 239 | char buf[LCD_COLS+1]; 240 | buf[LCD_COLS] = '\0'; 241 | for (int r = 0; r < LCD_ROWS; r++) { 242 | strncpy(buf,lcd_dat[lcd_curb][r],LCD_COLS); 243 | printf("%s\n",buf); 244 | } 245 | }; 246 | 247 | // Dump buffer to LCD, writing any changes, then switch buffer 248 | void LCDB_Dump (); 249 | 250 | // Handle for LCD output 251 | int lcd_handle; 252 | char lcd_dat[2][LCD_ROWS][LCD_COLS]; // Double buffer for LCD screen 253 | int lcd_curb; // Which of two double buffers is 254 | // being written to 255 | #endif 256 | }; 257 | 258 | #endif 259 | -------------------------------------------------------------------------------- /src/fweelin_midiio.h: -------------------------------------------------------------------------------- 1 | #ifndef __FWEELIN_MIDIIO_H 2 | #define __FWEELIN_MIDIIO_H 3 | 4 | /* Copyright 2004-2011 Jan Pekau 5 | 6 | This file is part of Freewheeling. 7 | 8 | Freewheeling is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 2 of the License, or 11 | (at your option) any later version. 12 | 13 | Freewheeling is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with Freewheeling. If not, see . */ 20 | 21 | #ifdef __MACOSX__ 22 | #include 23 | // Small MIDI output buffer- must be large enough to hold any one MIDI message 24 | #define OBUF_LEN 128 25 | #else 26 | #include 27 | #endif 28 | 29 | #include "fweelin_event.h" 30 | 31 | #define MIDI_CLOCK_FREQUENCY 24 // 24 MIDI clock messages per quarter note (beat) MIDI standard 32 | 33 | class Fweelin; 34 | class PatchItem; 35 | 36 | class BypassInfo { 37 | public: 38 | BypassInfo () : notepresscnt(0), releasecnt(0), bypasslen1(0), bypasslen2(0), numheld(0), sp(0), active(0), bypassed(1), 39 | bypasscc(0) {}; 40 | 41 | nframes_t notepresscnt, // Sample count when this channel last had a note pressed 42 | releasecnt, // Sample count when all notes were last released on this channel 43 | bypasslen1, // Number of audio samples (time) of channel inactivity with notes sustained before this channel is bypassed 44 | bypasslen2; // Number of audio samples (time) of channel inactivity with notes released before this channel is bypassed 45 | 46 | int numheld; // Number of notes held down on this port/channel 47 | char sp, // Sustain pedal is down for this port/channel 48 | active, // Auto-Bypassing is enabled for this port/channel? 49 | bypassed, // Is this channel bypassed? 50 | bypasscc; // MIDI CC to send for bypass 51 | }; 52 | 53 | class MidiIO : public EventProducer, public EventListener { 54 | friend class Fweelin; 55 | 56 | public: 57 | MidiIO (Fweelin *app); 58 | virtual ~MidiIO (); 59 | 60 | void ReceiveEvent(Event *ev, EventProducer */*from*/); 61 | 62 | int activate (); 63 | void close (); 64 | 65 | void SetBenderTune(int tuning) { bendertune = tuning; }; 66 | int GetBenderTune() { return bendertune; }; 67 | void ResetBenderTune() { bendertune = 0; }; 68 | 69 | // Sets up MIDI (echo and auto-bypass). Echo is set to one or more ports and channels based on: 70 | // a default MIDI output port (def_port) 71 | // and the given patch. 72 | // 73 | // Regular patches use the default MIDI output port and one channel, given 74 | // within the patch. 75 | // 76 | // Combi patches split the keyboard into multiple zones. 77 | // Each zone can output to any channel, and can optionally override and send 78 | // to a different MIDI output port altogether. This allows one MIDI 79 | // controller to control many instruments, even on different softsynths, 80 | // at the same time. 81 | 82 | // Zones can overlap, so that one key sends to multiple channels/ports 83 | void SetMIDIForPatch (int def_port, PatchItem *patch); 84 | 85 | // Send bank and program change messages where appropriate for the given 86 | // patch 87 | void SendBankProgramChange (PatchItem *patch); 88 | 89 | #ifndef __MACOSX__ 90 | char IsActive () { return midithreadgo; }; 91 | #else 92 | // Switch MIDI inputs (which system MIDI input source feeds Fweelin?) 93 | void SetMIDIInput (int idx); 94 | #endif 95 | 96 | // MIDI Sync 97 | inline int GetMIDISyncTransmit() { return midisyncxmit; }; 98 | inline void SetMIDISyncTransmit(int midisyncxmit) { this->midisyncxmit = midisyncxmit; }; 99 | 100 | // Value to offset bender amounts by-- used to do tuning from 101 | // bender 102 | int bendertune; 103 | // Current bender value (before tuning adjustment) 104 | int curbender; 105 | 106 | // MIDI ECHO 107 | 108 | // Single channel echo- 109 | 110 | // Echo MIDI events out which MIDI port? 111 | // (0 is off, port #s ascending from 1 reference out_ports) 112 | int echoport; 113 | // Echo out which MIDI channel? 114 | // (-1 echoes without changing channel information) 115 | int echochan; 116 | 117 | PatchItem *curpatch; // Current patch- gives which channel(s) 118 | // to map to 119 | 120 | // Number of MIDI in/out ports 121 | int numins, numouts; 122 | 123 | protected: 124 | // Core app 125 | Fweelin *app; 126 | 127 | // Open MIDI engine with num_in writeable ports and num_out readable ports. 128 | // Nonzero is returned on error 129 | char open_midi (int num_in, int num_out); 130 | 131 | // Listen/unlisten to events (used in startup & shutdown) 132 | void listen_events (); 133 | void unlisten_events (); 134 | 135 | // Methods that send one MIDI message to one system MIDI out 136 | void OutputController (int port, int chan, int ctrl, int val); 137 | void OutputProgramChange (int port, int chan, int val); 138 | void OutputChannelPressure (int port, int chan, int val); 139 | void OutputPitchBend (int port, int chan, int val); 140 | void OutputNote (int port, int chan, char down, int notenum, int vel); 141 | 142 | // MIDI Sync messages 143 | void OutputClock (int port); 144 | void OutputSPP (int port); 145 | void OutputStart (int port); 146 | void OutputStop (int port); 147 | 148 | // Start/End pass messages 149 | void OutputStartOnPort (); // First message for this port in this pass 150 | void OutputEndOnPort (int /*port*/); // Last message for this port in this pass 151 | 152 | // Echo MIDI event to a single port and channel, and update bypass settings for the given channel 153 | // Return the port echoed to 154 | int EchoEventToPortChannel (Event *ev, int port, int channel, int bypasschannel); 155 | 156 | // Echo MIDI event back to MIDI outs, according to current patch settings 157 | void EchoEvent (Event *ev); 158 | 159 | // Receive incoming MIDI events from the system and broadcast FreeWheeling 160 | // MIDI events internally 161 | void ReceiveNoteOffEvent (int channel, int notenum, int vel); 162 | void ReceiveNoteOnEvent (int channel, int notenum, int vel); 163 | void ReceivePitchBendEvent (int channel, int value); 164 | void ReceiveChannelPressureEvent (int channel, int value); 165 | void ReceiveProgramChangeEvent (int channel, int value); 166 | void ReceiveControlChangeEvent (int channel, int ctrl, int value); 167 | 168 | // Send bank and program change message to port/channel 169 | void SendBankProgramChangeToPortChannel (int bank, int program, 170 | int port, int channel); 171 | 172 | void CheckBypass(); // Time to bypass any channels yet? 173 | void CheckUnbypass(); // Unbypass channels still bypassed but needing use 174 | nframes_t checkfreq, // How often (samples) to check whether to bypass unused channels 175 | lastchecktime; // Last time (samples) auto-bypass conditions checked 176 | 177 | #ifdef __MACOSX__ 178 | MIDIClientRef client; 179 | MIDIPortRef *in_ports, *out_ports; 180 | MIDIEndpointRef *out_sources; 181 | MIDIEndpointRef dest; // Deprecated 182 | int inputidx; // Index of last selected MIDI input source 183 | 184 | MIDIPacket *curPacket; 185 | MIDIPacketList *packetList; 186 | Byte obuf[OBUF_LEN]; // Small MIDI event output buffer 187 | 188 | void static MidiInputProc (const MIDIPacketList *pktlist, void *refCon, void *connRefCon); 189 | #else 190 | // Midi event handler thread 191 | static void *run_midi_thread (void *ptr); 192 | 193 | snd_seq_t *seq_handle; 194 | int *in_ports, *out_ports; 195 | 196 | pthread_t midi_thread; 197 | char midithreadgo; 198 | #endif 199 | 200 | // For each MIDI note on the scale, what default port and patch was the note 201 | // played with? This allows us to send note off(s) to the right place(s), 202 | // even when the patch is changed while notes are held 203 | 204 | // Note: this assumes only 1 keyboard 205 | int *note_def_port; 206 | PatchItem **note_patch; 207 | 208 | // Data for automatic toggling of Soft-synth Bypass based on active MIDI channels 209 | // One instance for each MIDI channel and port 210 | BypassInfo *bp; 211 | BypassInfo *getBP (int port, int channel); 212 | 213 | // MIDI Sync 214 | int midisyncxmit; // Nonzero if we should transmit MIDI sync messages 215 | }; 216 | 217 | #endif 218 | -------------------------------------------------------------------------------- /compile: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # Wrapper for compilers which do not understand '-c -o'. 3 | 4 | scriptversion=2018-03-07.03; # UTC 5 | 6 | # Copyright (C) 1999-2018 Free Software Foundation, Inc. 7 | # Written by Tom Tromey . 8 | # 9 | # This program is free software; you can redistribute it and/or modify 10 | # it under the terms of the GNU General Public License as published by 11 | # the Free Software Foundation; either version 2, or (at your option) 12 | # any later version. 13 | # 14 | # This program is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | # GNU General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with this program. If not, see . 21 | 22 | # As a special exception to the GNU General Public License, if you 23 | # distribute this file as part of a program that contains a 24 | # configuration script generated by Autoconf, you may include it under 25 | # the same distribution terms that you use for the rest of that program. 26 | 27 | # This file is maintained in Automake, please report 28 | # bugs to or send patches to 29 | # . 30 | 31 | nl=' 32 | ' 33 | 34 | # We need space, tab and new line, in precisely that order. Quoting is 35 | # there to prevent tools from complaining about whitespace usage. 36 | IFS=" "" $nl" 37 | 38 | file_conv= 39 | 40 | # func_file_conv build_file lazy 41 | # Convert a $build file to $host form and store it in $file 42 | # Currently only supports Windows hosts. If the determined conversion 43 | # type is listed in (the comma separated) LAZY, no conversion will 44 | # take place. 45 | func_file_conv () 46 | { 47 | file=$1 48 | case $file in 49 | / | /[!/]*) # absolute file, and not a UNC file 50 | if test -z "$file_conv"; then 51 | # lazily determine how to convert abs files 52 | case `uname -s` in 53 | MINGW*) 54 | file_conv=mingw 55 | ;; 56 | CYGWIN*) 57 | file_conv=cygwin 58 | ;; 59 | *) 60 | file_conv=wine 61 | ;; 62 | esac 63 | fi 64 | case $file_conv/,$2, in 65 | *,$file_conv,*) 66 | ;; 67 | mingw/*) 68 | file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` 69 | ;; 70 | cygwin/*) 71 | file=`cygpath -m "$file" || echo "$file"` 72 | ;; 73 | wine/*) 74 | file=`winepath -w "$file" || echo "$file"` 75 | ;; 76 | esac 77 | ;; 78 | esac 79 | } 80 | 81 | # func_cl_dashL linkdir 82 | # Make cl look for libraries in LINKDIR 83 | func_cl_dashL () 84 | { 85 | func_file_conv "$1" 86 | if test -z "$lib_path"; then 87 | lib_path=$file 88 | else 89 | lib_path="$lib_path;$file" 90 | fi 91 | linker_opts="$linker_opts -LIBPATH:$file" 92 | } 93 | 94 | # func_cl_dashl library 95 | # Do a library search-path lookup for cl 96 | func_cl_dashl () 97 | { 98 | lib=$1 99 | found=no 100 | save_IFS=$IFS 101 | IFS=';' 102 | for dir in $lib_path $LIB 103 | do 104 | IFS=$save_IFS 105 | if $shared && test -f "$dir/$lib.dll.lib"; then 106 | found=yes 107 | lib=$dir/$lib.dll.lib 108 | break 109 | fi 110 | if test -f "$dir/$lib.lib"; then 111 | found=yes 112 | lib=$dir/$lib.lib 113 | break 114 | fi 115 | if test -f "$dir/lib$lib.a"; then 116 | found=yes 117 | lib=$dir/lib$lib.a 118 | break 119 | fi 120 | done 121 | IFS=$save_IFS 122 | 123 | if test "$found" != yes; then 124 | lib=$lib.lib 125 | fi 126 | } 127 | 128 | # func_cl_wrapper cl arg... 129 | # Adjust compile command to suit cl 130 | func_cl_wrapper () 131 | { 132 | # Assume a capable shell 133 | lib_path= 134 | shared=: 135 | linker_opts= 136 | for arg 137 | do 138 | if test -n "$eat"; then 139 | eat= 140 | else 141 | case $1 in 142 | -o) 143 | # configure might choose to run compile as 'compile cc -o foo foo.c'. 144 | eat=1 145 | case $2 in 146 | *.o | *.[oO][bB][jJ]) 147 | func_file_conv "$2" 148 | set x "$@" -Fo"$file" 149 | shift 150 | ;; 151 | *) 152 | func_file_conv "$2" 153 | set x "$@" -Fe"$file" 154 | shift 155 | ;; 156 | esac 157 | ;; 158 | -I) 159 | eat=1 160 | func_file_conv "$2" mingw 161 | set x "$@" -I"$file" 162 | shift 163 | ;; 164 | -I*) 165 | func_file_conv "${1#-I}" mingw 166 | set x "$@" -I"$file" 167 | shift 168 | ;; 169 | -l) 170 | eat=1 171 | func_cl_dashl "$2" 172 | set x "$@" "$lib" 173 | shift 174 | ;; 175 | -l*) 176 | func_cl_dashl "${1#-l}" 177 | set x "$@" "$lib" 178 | shift 179 | ;; 180 | -L) 181 | eat=1 182 | func_cl_dashL "$2" 183 | ;; 184 | -L*) 185 | func_cl_dashL "${1#-L}" 186 | ;; 187 | -static) 188 | shared=false 189 | ;; 190 | -Wl,*) 191 | arg=${1#-Wl,} 192 | save_ifs="$IFS"; IFS=',' 193 | for flag in $arg; do 194 | IFS="$save_ifs" 195 | linker_opts="$linker_opts $flag" 196 | done 197 | IFS="$save_ifs" 198 | ;; 199 | -Xlinker) 200 | eat=1 201 | linker_opts="$linker_opts $2" 202 | ;; 203 | -*) 204 | set x "$@" "$1" 205 | shift 206 | ;; 207 | *.cc | *.CC | *.cxx | *.CXX | *.[cC]++) 208 | func_file_conv "$1" 209 | set x "$@" -Tp"$file" 210 | shift 211 | ;; 212 | *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO]) 213 | func_file_conv "$1" mingw 214 | set x "$@" "$file" 215 | shift 216 | ;; 217 | *) 218 | set x "$@" "$1" 219 | shift 220 | ;; 221 | esac 222 | fi 223 | shift 224 | done 225 | if test -n "$linker_opts"; then 226 | linker_opts="-link$linker_opts" 227 | fi 228 | exec "$@" $linker_opts 229 | exit 1 230 | } 231 | 232 | eat= 233 | 234 | case $1 in 235 | '') 236 | echo "$0: No command. Try '$0 --help' for more information." 1>&2 237 | exit 1; 238 | ;; 239 | -h | --h*) 240 | cat <<\EOF 241 | Usage: compile [--help] [--version] PROGRAM [ARGS] 242 | 243 | Wrapper for compilers which do not understand '-c -o'. 244 | Remove '-o dest.o' from ARGS, run PROGRAM with the remaining 245 | arguments, and rename the output as expected. 246 | 247 | If you are trying to build a whole package this is not the 248 | right script to run: please start by reading the file 'INSTALL'. 249 | 250 | Report bugs to . 251 | EOF 252 | exit $? 253 | ;; 254 | -v | --v*) 255 | echo "compile $scriptversion" 256 | exit $? 257 | ;; 258 | cl | *[/\\]cl | cl.exe | *[/\\]cl.exe | \ 259 | icl | *[/\\]icl | icl.exe | *[/\\]icl.exe ) 260 | func_cl_wrapper "$@" # Doesn't return... 261 | ;; 262 | esac 263 | 264 | ofile= 265 | cfile= 266 | 267 | for arg 268 | do 269 | if test -n "$eat"; then 270 | eat= 271 | else 272 | case $1 in 273 | -o) 274 | # configure might choose to run compile as 'compile cc -o foo foo.c'. 275 | # So we strip '-o arg' only if arg is an object. 276 | eat=1 277 | case $2 in 278 | *.o | *.obj) 279 | ofile=$2 280 | ;; 281 | *) 282 | set x "$@" -o "$2" 283 | shift 284 | ;; 285 | esac 286 | ;; 287 | *.c) 288 | cfile=$1 289 | set x "$@" "$1" 290 | shift 291 | ;; 292 | *) 293 | set x "$@" "$1" 294 | shift 295 | ;; 296 | esac 297 | fi 298 | shift 299 | done 300 | 301 | if test -z "$ofile" || test -z "$cfile"; then 302 | # If no '-o' option was seen then we might have been invoked from a 303 | # pattern rule where we don't need one. That is ok -- this is a 304 | # normal compilation that the losing compiler can handle. If no 305 | # '.c' file was seen then we are probably linking. That is also 306 | # ok. 307 | exec "$@" 308 | fi 309 | 310 | # Name of file we expect compiler to create. 311 | cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` 312 | 313 | # Create the lock directory. 314 | # Note: use '[/\\:.-]' here to ensure that we don't use the same name 315 | # that we are using for the .o file. Also, base the name on the expected 316 | # object file name, since that is what matters with a parallel build. 317 | lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d 318 | while true; do 319 | if mkdir "$lockdir" >/dev/null 2>&1; then 320 | break 321 | fi 322 | sleep 1 323 | done 324 | # FIXME: race condition here if user kills between mkdir and trap. 325 | trap "rmdir '$lockdir'; exit 1" 1 2 15 326 | 327 | # Run the compile. 328 | "$@" 329 | ret=$? 330 | 331 | if test -f "$cofile"; then 332 | test "$cofile" = "$ofile" || mv "$cofile" "$ofile" 333 | elif test -f "${cofile}bj"; then 334 | test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" 335 | fi 336 | 337 | rmdir "$lockdir" 338 | exit $ret 339 | 340 | # Local Variables: 341 | # mode: shell-script 342 | # sh-indentation: 2 343 | # eval: (add-hook 'before-save-hook 'time-stamp) 344 | # time-stamp-start: "scriptversion=" 345 | # time-stamp-format: "%:y-%02m-%02d.%02H" 346 | # time-stamp-time-zone: "UTC0" 347 | # time-stamp-end: "; # UTC" 348 | # End: 349 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | Introduction to Freewheeling 3 | ---------------------------- 4 | 5 | ![freewheeling screenshot][Freewheeling_Screenshot] 6 | 7 | ### Free and Open Source Audio Tool for Live Looping 8 | 9 | Freewheeling provides a highly configurable, intuitive, and fluid user 10 | interface for instrumentalists to capture audio loops in real-time. Best 11 | way to understand Freewheeling?? [See and hear it][Freewheeling_Screenshots] in action. 12 | [Demo Video][Freewheeling_Demo_Video]. 13 | 14 | 15 | ### Philosophy 16 | 17 | ``` 18 | Freewheeling is 19 | a new way 'to be' 20 | In The Muse-ical Moment. 21 | It's a live looping instrument 22 | that returns us to the joy 23 | of making music 'spontaneously'. 24 | ``` 25 | 26 | Freewheeling allows us to build repetitive grooves by sampling and 27 | directing loops from within spirited improvisation. It works because, 28 | down to the core, it's built around improv. We leave mice and menus, and 29 | dive into our own process of making sound. The principle author of 30 | Freewheeling is JP Mercury. Freewheeling was also originally a Max/MSP 31 | external. Since 2016, it is maintained by the user community. 32 | 33 | 34 | ### Technical Details 35 | 36 | Freewheeling runs under GNU/Linux (PC/Mac) and Mac OS X (PPC/Intel) 37 | using the [Jack Audio Connection Kit][JACK] sound server, and 38 | is Free and Open Source Software, released under the GNU GPL license. 39 | The ChangeLog is a good resource, because all major new features have 40 | been documented there. It is humble enough to run on modest hardware but 41 | can take advantage of the gobs of RAM on modern machines as well. The 42 | only limits are your imagination. 43 | 44 | **Focus on the ideation process:** 45 | 46 | - Freewheeling empowers the trance of immediate creativity by bringing 47 | us into a circular process. Time is utterly relative, and we are 48 | freed from the future-oriented mindset of product sequencing. If 49 | inspiration flows, later arranging and editing on a timeline can be 50 | done with other tools. 51 | 52 | See the [Technical Features][Technical_Features]. 53 | 54 | 55 | Getting Started 56 | --------------- 57 | 58 | ### Downloading 59 | 60 | Pre-compiled Freewheeling binaries are available for several of today's 61 | popular operating systems. If you prefer using your favorite graphical 62 | package manager (such as synaptic) or your distro's Add/Remove Software 63 | Control Panel, search for a package named *freewheeling* or *fweelin*. 64 | 65 | - Install one of the [Packages][OS_Specific_Packages] for your distro - (recommended) 66 | - or, [Download][Freewheeling_Tarballs] a tarball - (advanced) 67 | - or, Checkout the latest git sources - (advanced) 68 | 69 | ``` 70 | $ git clone https://github.com/free-wheeling/freewheeling.git 71 | $ git clone https://pagure.io/freewheeling.git 72 | ``` 73 | 74 | 75 | ### Installing 76 | 77 | - [OS Specific Packages][OS_Specific_Packages] - (recommended) 78 | - [Compiling][Compiling] - (advanced) 79 | - [Dependencies][Dependencies] 80 | 81 | 82 | ### Configuring 83 | 84 | - [Configuration Basics][Configuration_Basics] - how does it work? 85 | - [XML Configuration System][XML_Configuration_System] - 86 | the full Freewheeling XML API from config-help.txt in wiki form 87 | - [Configurations][Configurations] - 88 | a store for users to submit their custom interfaces, layouts, patches, etc 89 | 90 | 91 | ### Troubleshooting and Support 92 | 93 | - [FAQS][FAQS] - Freeq-wheely Asked Questions 94 | - [Known Issues][Known_Issues] - Resolutions to common 95 | pitfalls, snags, and glitches (notice i did not say bugs) 96 | - [Freewheeling Users Mailing List][Freewheeling_Users_Mailing_List] - 97 | If you're looking for help with Freewheeling, 98 | your question may already be answered there. If not, feel free to 99 | [join the mailing list][Freewheeling_Users_Mailing_List] 100 | and ask your question to the community 101 | - [Feature Requests][Freewheeling_Users_Mailing_List] - 102 | Please join the 'freewheeling-user' mailing list 103 | - [Bug Reporting][Github_Bug_Tracker] - 104 | Please reports bugs on the [GitHub issue tracker][Github_Bug_Tracker] or the 105 | [NotABug issue tracker][Notabug_Bug_Tracker] 106 | 107 | 108 | ### Using 109 | 110 | - [Quick Start Guide][Quick_Start_Guide] - handy defaults for the impatient user 111 | - [Freewheeling Video Tutorials][Freewheeling_Video_Tutorials] - watch 112 | freewheeling in action 113 | - [Controlling Freewheeling][Controlling_Freewheeling] - using external midi devices 114 | - [Default Key Bindings][Default_Key_Bindings] - what did I just pressed? 115 | - [Tips and Tricks for Studio and Live Use][Tips_and_Tricks_for_Studio_and_Live_Use] 116 | 117 | 118 | NOTE: You will also need the JACK audio server and a way to configure it 119 | (such as qJackCtl or Cadence). A very easy way to setup a GNU/Linux audio workstation 120 | is by installing the [KxStudio Operating System][KxStudio_Downloads]. 121 | 122 | NOTE: Debian (and derrivatives such as Trisquel, Ubuntu, and Mint) can transform 123 | their system into KxStudio simply by adding the [KxStudio repos][KxStudio_Repos] 124 | and installing the 'kxstudio-meta-all' package (or 'kxstudio-meta-audio' for just the 125 | pro-audio programs). It is highly recommended that you install at least 126 | the 'kxstudio-default-settings' package which optimizes your system 127 | performance for real-time audio use. 128 | 129 | NOTE: ArchLinux (and derrivatives such as Parabola, Hyperbola, and Manjaro) 130 | can simply install the 'pro-audio' package group, which includes Freewheeling. 131 | It is highly recommended that you install at least the 'realtime-privileges' package 132 | which configures your system for real-time audio use. 133 | 134 | 135 | The Freewheeling Community 136 | -------------------------- 137 | 138 | ### Community Interaction 139 | 140 | - [Music made with Freewheeling][Music_made_with_Freewheeling] 141 | - [Freewheeling Users Mailing List][Freewheeling_Users_Mailing_List] - 142 | technical support, new releases, shared ideas and music 143 | 144 | ### How can I help? 145 | 146 | - Submit or edit wiki articles 147 | - Submit your interfaces and layouts for specific hardware to the 148 | [Configurations][Configurations] article 149 | - Submit screen-casts demonstrating your interfaces or the advanced 150 | features of freewheeling 151 | - Submit audio/video creations to the 152 | [Music made with Freewheeling][Music_made_with_Freewheeling] article 153 | 154 | 155 | [Freewheeling_Screenshot]: http://freewheeling.sourceforge.net/flo-051-looptray-t.png 156 | [Freewheeling_Screenshots]: http://freewheeling.sourceforge.net/shots.shtml 157 | [Freewheeling_Demo_Video]: http://freewheeling.sourceforge.net/video/fw-demo1.avi 158 | [JACK]: http://jackaudio.org 159 | [Technical_Features]: https://github.com/free-wheeling/freewheeling/wiki/Technical-Features 160 | [OS_Specific_Packages]: https://github.com/free-wheeling/freewheeling/wiki/OS-Specific-Packages 161 | [Freewheeling_Tarballs]: https://github.com/free-wheeling/freewheeling/releases 162 | [Compiling]: https://github.com/free-wheeling/freewheeling/wiki/Compiling 163 | [Dependencies]: https://github.com/free-wheeling/freewheeling/wiki/Dependencies 164 | [Configuration_Basics]: https://github.com/free-wheeling/freewheeling/wiki/Configuration-Basics 165 | [XML_Configuration_System]: https://github.com/free-wheeling/freewheeling/wiki/XML-Configuration-System 166 | [Configurations]: https://github.com/free-wheeling/freewheeling/wiki/Configurations 167 | [FAQS]: https://github.com/free-wheeling/freewheeling/wiki/FAQS 168 | [Known_Issues]: https://github.com/free-wheeling/freewheeling/wiki/Known-Issues 169 | [Freewheeling_Users_Mailing_List]: https://github.com/free-wheeling/freewheeling/wiki/Freewheeling-Users-Mailing-List 170 | [Github_Bug_Tracker]: https://github.com/free-wheeling/freewheeling/issues 171 | [Notabug_Bug_Tracker]: https://notabug.org/freewheeling/freewheeling/issues 172 | [Quick_Start_Guide]: https://github.com/free-wheeling/freewheeling/wiki/Quick-Start-Guide 173 | [Freewheeling_Video_Tutorials]: https://github.com/free-wheeling/freewheeling/wiki/Freewheeling-Video-Tutorials 174 | [Controlling_Freewheeling]: https://github.com/free-wheeling/freewheeling/wiki/Controlling-Freewheeling 175 | [Default_Key_Bindings]: https://github.com/free-wheeling/freewheeling/wiki/Default-Key-Bindings 176 | [Tips_and_Tricks_for_Studio_and_Live_Use]: https://github.com/free-wheeling/freewheeling/wiki/Tips-and-Tricks-for-Studio-and-Live-Use 177 | [KxStudio_Downloads]: https://kxstudio.linuxaudio.org/Downloads 178 | [KxStudio_Repos]: https://kxstudio.linuxaudio.org/Repositories 179 | [Music_made_with_Freewheeling]: https://github.com/free-wheeling/freewheeling/wiki/Music-made-with-Freewheeling 180 | -------------------------------------------------------------------------------- /data/basics.xml: -------------------------------------------------------------------------------- 1 | 2 | 20 | 21 | 22 | 26 | 27 | 28 | 30 | 31 | 32 | 37 | 38 | 39 | 43 | 44 | 45 | 57 | 58 | 59 | 60 | 61 | 63 | 64 | 65 | 66 | 67 | 68 | 70 | 71 | 72 | 73 | 74 | 75 | 84 | 85 | 86 | 91 | 92 | 93 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 123 | 124 | 125 | 126 | 127 | 130 | 131 | 132 | 133 | 135 | 136 | 137 | 141 | 142 | 143 | 144 | 145 | 146 | 156 | 157 | 158 | 159 | 195 | 196 | -------------------------------------------------------------------------------- /src/fweelin_fluidsynth.cc: -------------------------------------------------------------------------------- 1 | /* Copyright 2004-2011 Jan Pekau 2 | 3 | This file is part of Freewheeling. 4 | 5 | Freewheeling is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | Freewheeling is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with Freewheeling. If not, see . */ 17 | 18 | 19 | #if USE_FLUIDSYNTH 20 | 21 | #include 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include 29 | #include 30 | 31 | #include 32 | #include 33 | #include 34 | 35 | #include "fweelin_fluidsynth.h" 36 | 37 | 38 | void FluidSynthParam_Int::Send(fluid_settings_t *settings) { 39 | printf("FLUID: Setting parameter '%s' = '%d'\n",name,val); 40 | fluid_settings_setint(settings, name, val); 41 | }; 42 | 43 | void FluidSynthParam_Num::Send(fluid_settings_t *settings) { 44 | printf("FLUID: Setting parameter '%s' = '%f'\n",name,val); 45 | fluid_settings_setnum(settings, name, val); 46 | }; 47 | 48 | void FluidSynthParam_Str::Send(fluid_settings_t *settings) { 49 | printf("FLUID: Setting parameter '%s' = '%s'\n",name,val); 50 | fluid_settings_setstr(settings, name, val); 51 | }; 52 | 53 | FluidSynthProcessor::FluidSynthProcessor(Fweelin *app, char stereo) : 54 | Processor(app), stereo(stereo), enable(1) { 55 | nframes_t bufsz = app->getBUFSZ(); 56 | leftbuf = new sample_t[bufsz]; 57 | rightbuf = new sample_t[bufsz]; 58 | 59 | // Setup FluidSynth 60 | settings = new_fluid_settings(); 61 | { 62 | FluidSynthParam *cur = app->getCFG()->GetFluidParam(); 63 | while (cur != 0) { 64 | cur->Send(settings); 65 | cur = cur->next; 66 | } 67 | } 68 | // Set sampling rate 69 | fluid_settings_setnum(settings, "synth.sample-rate", 70 | app->getAUDIO()->get_srate()); 71 | // Create synth 72 | synth = new_fluid_synth(settings); 73 | 74 | // Set interpolation quality 75 | printf("FLUID: Setting interpolation quality: %d\n", 76 | app->getCFG()->GetFluidInterpolation()); 77 | fluid_synth_set_interp_method(synth,-1, 78 | app->getCFG()->GetFluidInterpolation()); 79 | 80 | // User-specified global fluidsynth tuning 81 | float tuning = app->getCFG()->GetFluidTuning(); 82 | if (tuning != 0.0) { 83 | printf("FLUID: Setting pitch tuning: %.2f cents\n", 84 | tuning); 85 | 86 | // Create tuning for each key in octave 87 | double pitches[12]; 88 | for (int i = 0; i < 12; i++) 89 | pitches[i] = tuning; 90 | fluid_synth_activate_octave_tuning(synth, 0, 0, "DETUNE", pitches, false); 91 | 92 | // Select tuning 93 | for (int i = 0; i < MAX_MIDI_CHANNELS; i++) 94 | fluid_synth_activate_tuning(synth, i, 0, 0, false); 95 | } else 96 | printf("FLUID: Using default tuning\n"); 97 | 98 | // Load soundfonts 99 | { 100 | FluidSynthSoundFont *cur = app->getCFG()->GetFluidFont(); 101 | while (cur != 0) { 102 | printf("FLUID: Loading SoundFont '%s'\n",cur->name); 103 | fluid_synth_sfload(synth,cur->name,1); 104 | cur = cur->next; 105 | } 106 | } 107 | 108 | app->getEMG()->ListenEvent(this,0,T_EV_FluidSynthEnable); 109 | }; 110 | 111 | FluidSynthProcessor::~FluidSynthProcessor() { 112 | app->getEMG()->UnlistenEvent(this,0,T_EV_FluidSynthEnable); 113 | 114 | delete_fluid_synth(synth); 115 | delete_fluid_settings(settings); 116 | 117 | delete[] leftbuf; 118 | delete[] rightbuf; 119 | }; 120 | 121 | void FluidSynthProcessor::process(char pre, nframes_t len, 122 | AudioBuffers *ab) { 123 | if (!pre) { 124 | // Map our output to the end of the external inputs 125 | ab->ins[0][ab->numins_ext] = leftbuf; 126 | if (stereo) 127 | ab->ins[1][ab->numins_ext] = rightbuf; 128 | else 129 | ab->ins[1][ab->numins_ext] = 0; 130 | 131 | if (enable) { 132 | // Run synth DSP 133 | fluid_synth_write_float(synth, len, 134 | leftbuf, 0, 1, 135 | rightbuf, 0, 1); 136 | 137 | if (!stereo) { 138 | // Mono, so fold the right channel into the left like pudding 139 | for (nframes_t l = 0; l < len; l++) 140 | leftbuf[l] = (leftbuf[l] + rightbuf[l]) / 2; 141 | } 142 | } else { 143 | // Silence, not enabled 144 | memset(leftbuf,0,sizeof(sample_t) * len); 145 | if (stereo) 146 | memset(rightbuf,0,sizeof(sample_t) * len); 147 | } 148 | } 149 | }; 150 | 151 | // Read new current patch from 'patches' and send patch change to synth 152 | void FluidSynthProcessor::SendPatchChange(PatchItem *p) { 153 | fluid_synth_program_select(synth, p->channel, 154 | p->id, p->bank, p->prog); 155 | }; 156 | 157 | // Sets up our internal patch list based on loaded soundfonts 158 | void FluidSynthProcessor::SetupPatches() { 159 | PatchBrowser *br = (PatchBrowser *) app->getBROWSER(B_Patch); 160 | #if FLUIDSYNTH_VERSION_MAJOR == 1 161 | // NOTE: fluidsynth v2 implements these 162 | #define fluid_sfont_iteration_start(_sf) (*(_sf)->iteration_start)(_sf) 163 | #define fluid_sfont_iteration_next(_sf,_pr) (*(_sf)->iteration_next)(_sf,_pr) 164 | #define fluid_preset_get_name(_preset) (*(_preset)->get_name)(_preset) 165 | #define fluid_preset_get_banknum(_preset) (*(_preset)->get_banknum)(_preset) 166 | #define fluid_preset_get_num(_preset) (*(_preset)->get_num)(_preset) 167 | fluid_preset_t preset; 168 | #elif FLUIDSYNTH_VERSION_MAJOR == 2 169 | fluid_preset_t* preset; 170 | #endif // FLUIDSYNTH_VERSION_MAJOR 171 | 172 | if (br != 0) { 173 | // Add FluidSynth patch bank 174 | int fluidchan = app->getCFG()->GetFluidChannel(); 175 | br->PB_AddBegin(new PatchBank(0,-1,0)); // Use port 0 for FluidSynth 176 | 177 | // Store patches 178 | int sfcnt = fluid_synth_sfcount(synth); 179 | for (int i = 0; i < sfcnt; i++) { 180 | fluid_sfont_t *curfont = fluid_synth_get_sfont(synth,i); 181 | fluid_sfont_iteration_start(curfont); 182 | #if FLUIDSYNTH_VERSION_MAJOR == 1 183 | while (fluid_sfont_iteration_next(curfont, &preset)) 184 | br->AddItem(new PatchItem(fluid_sfont_get_id(curfont), 185 | fluid_preset_get_banknum(&preset), 186 | fluid_preset_get_num(&preset), 187 | fluidchan, 188 | fluid_preset_get_name(&preset))); 189 | #elif FLUIDSYNTH_VERSION_MAJOR == 2 190 | while ((preset = fluid_sfont_iteration_next(curfont)) != NULL) 191 | br->AddItem(new PatchItem(fluid_sfont_get_id(curfont), 192 | fluid_preset_get_banknum(preset), 193 | fluid_preset_get_num(preset), 194 | fluidchan, 195 | fluid_preset_get_name(preset))); 196 | #endif // FLUIDSYNTH_VERSION_MAJOR 197 | 198 | if (i+1 < sfcnt) { 199 | // End of soundfont- put in a divider 200 | br->AddItem(new BrowserDivision()); 201 | } 202 | } 203 | } 204 | }; 205 | 206 | void FluidSynthProcessor::ReceiveMIDIEvent(Event *ev) { 207 | FloConfig *fs = app->getCFG(); 208 | 209 | switch (ev->GetType()) { 210 | case T_EV_Input_MIDIController : 211 | if (enable) 212 | { 213 | MIDIControllerInputEvent *mcev = (MIDIControllerInputEvent *) ev; 214 | fluid_synth_cc(synth,app->getCFG()->GetFluidChannel(), 215 | mcev->ctrl,mcev->val); 216 | } 217 | break; 218 | 219 | case T_EV_Input_MIDIPitchBend : 220 | if (enable) 221 | { 222 | MIDIPitchBendInputEvent *mpev = (MIDIPitchBendInputEvent *) ev; 223 | fluid_synth_pitch_bend(synth,app->getCFG()->GetFluidChannel(), 224 | mpev->val + FLUIDSYNTH_PITCHBEND_CENTER); 225 | } 226 | break; 227 | 228 | case T_EV_Input_MIDIKey : 229 | if (enable) 230 | { 231 | MIDIKeyInputEvent *mkev = (MIDIKeyInputEvent *) ev; 232 | if (mkev->down) 233 | fluid_synth_noteon(synth, 234 | app->getCFG()->GetFluidChannel(), 235 | mkev->notenum+fs->transpose, 236 | mkev->vel); 237 | else 238 | fluid_synth_noteoff(synth, 239 | app->getCFG()->GetFluidChannel(), 240 | mkev->notenum+fs->transpose); 241 | } 242 | break; 243 | 244 | default: 245 | break; 246 | } 247 | }; 248 | 249 | void FluidSynthProcessor::ReceiveEvent(Event *ev, EventProducer */*from*/) { 250 | switch (ev->GetType()) { 251 | case T_EV_FluidSynthEnable : 252 | { 253 | FluidSynthEnableEvent *fev = (FluidSynthEnableEvent *) ev; 254 | 255 | // OK! 256 | if (CRITTERS) 257 | printf("FLUID: Received FluidSynthEnable (%s)\n", 258 | (fev->enable ? "on" : "off")); 259 | SetEnable(fev->enable); 260 | } 261 | break; 262 | 263 | default: 264 | break; 265 | } 266 | } 267 | 268 | #endif 269 | --------------------------------------------------------------------------------