kluppe-0.6.14/0000755000000000000000000000000011171364311011576 5ustar rootrootkluppe-0.6.14/CHANGES.log0000644000175000017500000001557211131762772014210 0ustar dieterdieter0.6.14 *) avoid sudden volume changes in midi grain playmode 0.6.13 ------ *) added preliminary support for M-audio xsession-pro *) added support for frontier alphatrack remote control *) canged range of playback-vol sliders to -48 - +18 db 0.6.12 ------- *) fixed some segfaults when peakview runs out of mem *) fixed position-interpolation for long buffers *) fixed midi-channel chaos *) peakview generation runs faster now *) try harder to find a a free port for osc-server *) allow bigger empty buffers (1000 sec) 0.6.11 ------ *) relax jack-client startup 0.6.10 ---- *) "suspend" buttons for rec. and playback *) threshold-driven recording 0.6.9 ----- *) try to raise priority of mix thread on startup *) fixed resize at project loading *) fixed wrong samplerate-conversion for filebuffers *) fixed slow peakview calculation when recording 0.6.8 ----- *) fixed mono playback and recording *) repaired "save *selection to file" again 0.6.7 ----- *) fixed segfault on recselection-resize *) fixed deadlock in pixel calculation *) fixed multiple broken recording 0.6.6 ----- *) fixed graphical loop-resize behaviour *) fixed spinbox behaviour in looper.c *) fixed broken peakview at block-borders *) improved buffering for disc-streams *) clean up peakview on close/change *) avoid double calculation of peakviews *) fixed some memory leaks *) added up/down buttons looper-position *) repaired handling of mono buffers *) repaired "save *selection to file" *) make configfiles language-independent (this may break some old config files) 0.6.5 ----- *) fixed behaviour when jackd is not running *) added "stereo diversity" for granular mode *) added click-mode (vinyl & cd for now) thanks to oliver stotz for the idea. *) midi-only mode for grains now keeps pitch *) optimized lists-handling 0.6.4 ----- *) don't let second kluppe crash on start *) check buffer loading and warn if failed *) add "de-normalize" option for loopers *) bounce correctly in back'n'forth-mode *) fuzzy logic quit dialog *) included manpage from debian package *) various improvements and buxfixes (thanks a lot to piem) 0.6.3 ----- *) better graphical handling of loop-wrap *) "new project" option in file dialog *) fixed compilation for klopfer (thanks to toni again) 0.6.2 ----- *) fixed soundfile samplerate conversion *) clear loopview before painting new data 0.6.1 ----- *) improved peakview 0.6.0 ----- *) disc stream support *) "play once" and "rec single" modes *) generation of peak-data in own thread 0.5.4 ----- *) yet another Makefile-fix-release (thanks to toni for the help) 0.5.3 ----- *) preliminary osc support using liblo when compiled with -DHAVE_OSC *) fixed compiling without libusb (-DHAVE_USB) 0.5.2 ---- *) tranzport(tm) support for klopfer *) added some simple presets for kloper *) fixed debian/unstable compile problem *) fixed occasional segfault on project loading *) grid from play/rec-selection *) make midi more responsive *) correct URL in about dialog *) handle note-off events *) fix gridoffset-bug in configfile loading *) regard midi volumes (velocity) *) save and restore window geometry 0.5.1 ----- *) corrected grain wrap around loopborders *) reduce grain offsets to smoothen pitch shift *) fix possible segfault for very small grains *) improve klopfers shuttle control *) simple midi control for granular pitchhift + bend *) avoid "differ in signedness" warnings for gcc4 *) fix stepsize for output-volume fader *) fix grainsize spinbutton behaviour *) moved parts of main menu to "Edit" menu 0.5 ----- *) set grid to 120 bpm by default *) insert some yield points in gtk parts for smoother task switching *) moved kluppe homepage to http://kluppe.klingt.org *) startet online documentation *) integrated klopfer frontend 0.4.7 ----- *) change (mouse-)pointer over selections 0.4.6 ----- *) return 0 (int) instead of nothing (void) on xrun (small change, big result for stability) *) added a minimal "about" dialog 0.4.5 ----- *) fixed gcc compile flags (-pthread) *) improve memory check on file loading *) fix a bug in (buffer-, looper-...)list handling *) fixed occasional crash on configfile-load 0.4.4 ----- *) more work to allow low latencies *) added "normalize play/rec selection" *) bypass pointer calcualtions when not in use 0.4.3 ----- *) revert to pthread for jackmixer to prevent being kicked off by jack *) fix a possible segfault on "new empty buffer" 0.4.2 ----- *) start loadfile thread at startup to prevent being kicked off by jack *) optimize peak calculations for loopview *) set filename of buffer after saving contents. *) correctly remove from jack on quit 0.4.1 ----- *) (re-)added kluppe.png to tarball 0.4 --- *) save buffer/playloop/recloop content to file for now it's always .wav 16bit unsigned (needs more work - eg. different filetypes) *) improved mouse control for loopview *) meter grid in loopview (+ settings dialog) *) "CV sync": drive loopers by "external pointer" this allows jack apps (eg. supercollider, pd, ...) to crontrol/be controlled by kluppe's playback. *) prevent loading of soundfiles bigger than the available physical memory *) display error dialog on failed soundfile-load *) fixed segfault when recording into mono buffer *) add "reset custom position" and "reset custom speed" *) fixed occasional segfault when closing loopers *) include version in path of .tar.gz 0.3 -- *) save / load projects *) loopers can be closed now *) loopers can be minimized *) very simple "limiter" instead of clipping *) moved normalize to buffer-menu *) added clear buffer option *) auto panner *) kluppe now works in "free wheeling" mode *) cpu load in progress bar *) refreshing of gui relaxes at cpu load > 40% *) optimized loopview-widget to reduce load *) use kluppe1, kluppe2 ... as jack names (instead of kluppePID) *) relax buffer initialisation to avoid "zombifying" through jack *) soundfile info in "new buffer from file" dialog *) usb-shuttle-interface is now linux 2.4 compatible 0.2 --- *) found and fixed an infinite loop *) fixed waveform view for normalize across loopers *) "overdrive" feature for rec-mix slider *) added random "grain density" *) added support for shuttle-Xpress HID device *) monofiles are now internally handled as mono input to mono-buffers is mixed L+R -> mono output ist always 2 channels (mono can be panned) *) update all affected loopviews for a buffer while recording *) split "custom mode" into "custom speed" and "custom position" *) "normalize" function in menu for custom mode *) occasional segfaults on file loading fixed 0.1 initial version ------------------- features so far: *) gtk2.0 interface *) different threads (jack, mixer, gui, bufferactions) *) creating of (stereo-)buffers *) gtkloopview widget *) loading of files (libsoundfile) *) playback master and singletracks (jack) *) recording into buffers *) playmodes: loop, back-forth, sinewave, custom *) (0 - 15) grains with variing size and speed kluppe-0.6.14/TODO0000644000175000017500000000114710657331442013114 0ustar dieterdietertodo: imrpove memory management handle dead jack ports improve 4point interpolation or use libsamplerate stopwatch for klopfer (shift+in/+out) fix playback for many grains plaing a DS insert act-number somewhere visible fix rec-peakview calculation allow longer grainsizes fix sample block calculation to reduce load syncing/linking of loopers per-loop routing dialog move jack-connect to gui-thread better colors aubio-lib for attack-detection much later: other views (spiral, rolling...) ? volume curve for gtkloopview internal clipboard, cut, copy, paste... undo redo for buffer operations ladcca/lash support kluppe-0.6.14/README.txt0000644000175000017500000000710110476073522014117 0ustar dieterdieterINTRO: ------ kluppe is a loop-player and recorder, designed for live use. kluppe is open source (see LICENSE.txt) kluppe is the austrian word for clip or peg and sounds even crazier if you loop it for details about the word kluppe see http://lists.debian.org/debian-devel/2004/05/msg00182.html ;-) kluppe is written in c using jack, gtk, libasound, libxml libusb liblo and libsndfile. libasound: http://www.alsa-project.orh libsndfile: http://www.mega-nerd.com/libsndfile/ libjack: http://jackit.sf.net (at least version 0.90) gtk2.0: http://gtk.org (at least version 2.6) libxml2 http://xmlsoft.org/ libusb http://libusb.sourceforge.net/ liblo http://liblo.sourceforge.net/ kluppe is linux only (kernel >= 2.4) so far. in theory it should work on all platforms with existing ports for the used libraries... COMPILING: ---------- if you have all libraries (and their corresponding developer-sources) installed, it should simply compile with 'make'. 'make install' as root copies the binary to /usr/local/bin sorry - no nifty autogen, configure... yet if you run into any troubles please let me know. KLOPFER: -------- there is a special non-gui version of kluppe. i use it for my self-built mini-itx stage computer. it's called klopfer and you will most likely *not* need it. in case you still want to compile it, you can do so with "make klopfer" and "make klopfer_install". FEATURES: --------- *) loading of (.wav, .aiff...) soundfiles into (memory-)buffers *) saving / loading of settings *) creating of empty buffers *) playing and recording of multiple buffers via loop-players *) playing directly from disc via "disc-streams" *) direct (gui-) access to all loopers *) combined- and per loop output-ports for jack *) different playmodes including "granular" *) uses 32bit buffers internally USAGE: ------ after starting the program you first have to create one or more "new looper" and at least one buffer (either from file or empty). then you can select the buffer for every looper in the "buffer" menu and start playing. since kluppe is a jack-app it's easy to connect the output(s) to other aplications like jack-rack. - using the waveformview: *) with the left moude-button you can change the play-selection in the loopview (shift to keep length, ctrl to change position of the locator or "scratch" ). *) right mousebutton is for the rec-selection (shift to keep length, ctrl to change position of the locator) *) middle-button is for zoom (shift for unzoom) - the vu-meters will keep you informed about playback and recordingvolumes - the "playmodes"-menu gives you options about the playback-modes. "edit custom playmode" lets you draw a speedchange-over-time-curve. - the "N" button normalizes the whole buffer - you will find out what the "volume"- "pan"- and "recmix"- slider do. - also the spinbuttons for position and speed are self-explainig. - if you set the number of grains to more than zero, you enter the granular playmode. see also "option" -> "grainsettings" for more - kluppe supports a usb HID device called "contour shuttle Xpress". if such a device is found at /dev/input/event[0-9] it will be automatically used. all you need to make it work is loading the usb hid and input kerneldrivers. if you need help or want to use other usb devices for "remote" controlling kluppe, let me know. CONTRIBUTIONS: ------------- ideas, suggestions, bugreports by: billy roisz, oliver stotz, michael aschauer, arnold haberl, klaus filip, steve harris, dave griffith, esben stien CONTACT: -------- written by dieter kovacic kluppe at klingt dot org http://kluppe.klingt.org kluppe-0.6.14/Makefile0000644000175000017500000000221411171364234014055 0ustar dieterdieterCC = gcc VERSION = `cat VERSION` INSTALL_PREFIX = /usr/local BIN_DIR = $(INSTALL_PREFIX)/bin PIXMAPS_DIR = $(INSTALL_PREFIX)/share/pixmaps TEMP_ROOT = /tmp TEMP_DIR = kluppe-$(VERSION) #CFLAGS = -pthread -march=pentium-m -mfpmath=sse -msse3 -g -O3 -Wall -DHAVE_ALSA -DHAVE_USB -DHAVE_OSC CFLAGS = -pthread -O3 -Wall -DHAVE_ALSA -DHAVE_USB -DHAVE_OSC export kluppe: commons rm -f src/frontend/kluppe/kluppe.o cd src/frontend/kluppe && $(MAKE) klopfer: commons rm -f src/frontend/klopfer/klopfer.o cd src/frontend/klopfer && $(MAKE) commons: cd src/common/ && $(MAKE) common install: kluppe cd src/frontend/kluppe && $(MAKE) install klopfer_install: klopfer cd src/frontend/klopfer && $(MAKE) install clean: cd src/common && $(MAKE) clean cd src/frontend/kluppe && $(MAKE) clean cd src/frontend/klopfer && $(MAKE) clean tgz: clean mkdir $(TEMP_ROOT)/$(TEMP_DIR) cp -faR src Makefile TODO VERSION CHANGES.log LICENSE.txt README.txt $(TEMP_ROOT)/$(TEMP_DIR) tar -C $(TEMP_ROOT) -cvzpf kluppe-$(VERSION).tar.gz $(TEMP_DIR) rm -R $(TEMP_ROOT)/$(TEMP_DIR) # cd ..;tar --exclude *.wav --exclude *.o -cvzpf kluppe-`cat kluppe/VERSION`.tar.gz kluppe/ kluppe-0.6.14/VERSION0000644000175000017500000000000711131762705013464 0ustar dieterdieter0.6.14 kluppe-0.6.14/src/0002755000175000017500000000000010247334355013213 5ustar dieterdieterkluppe-0.6.14/src/frontend/0002755000175000017500000000000010421307342015020 5ustar dieterdieterkluppe-0.6.14/src/frontend/klopfer/0002755000175000017500000000000011033406130016455 5ustar dieterdieterkluppe-0.6.14/src/frontend/klopfer/klopfer.c0000644000175000017500000016370710475132536020316 0ustar dieterdieter#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../../common/buffer.h" #include "../../common/jackmixer.h" #include "../../common/looperdata.h" #include "../../common/shuttle.h" #include "../../common/tranzport.h" #include "../../common/serialio.h" #include "../../common/speciallist.h" #ifndef SOUND_MIXER_READ # define SOUND_MIXER_READ(x) MIXER_READ(x) #endif #ifndef SOUND_MIXER_WRITE # define SOUND_MIXER_WRITE(x) MIXER_WRITE(x) #endif #ifdef MAX # undef MAX #endif #ifdef MIN # undef MIN #endif #define MAX(a,b) (((a)>(b))?(a):(b)) #define MIN(a,b) (((a)<(b))?(a):(b)) typedef struct _looper_settings { char name[21]; looper_data_t* looper_data; } looper_settings_t; int startup_linelevel; int last_foot = 0; int last_footled = 0; double last_tap = 0; struct timeval timeout_tv; long tranzport_lcd_timeout; int tranzport_mode = 0; int tranzport_status = TRANZPORT_STATUS_OFFLINE; char *lcd_value_text = NULL; char *lcd_stereo_buf = NULL; speciallist_t *settingslist = NULL; looper_settings_t *active_settings = NULL; const float initial_length = 0.05; /* in seconds (was 0.05)*/ const float initial_speed = 1; const float initial_ngrains = 15; const float max_ngrains = 15; const float initial_volume = 0.9; const int initial_graindensity = 100; const double mintimediff = 20000.; const double semitone = 1.059463094359; int ossmixer_getlevel_line (){ int fd = -1; int vol = 0; fd = open("/dev/mixer", O_RDONLY); if (fd > 0){ if (ioctl(fd, SOUND_MIXER_READ(SOUND_MIXER_LINE), &vol) == -1){ close (fd); return -2; } else { close (fd); return (vol & 255); } } return -1; } int ossmixer_getlevel_pcm (){ int fd = -1; int vol = 0; fd = open("/dev/mixer", O_RDONLY); if (fd > 0){ if (ioctl(fd, SOUND_MIXER_READ(SOUND_MIXER_PCM), &vol) == -1){ close (fd); return -2; } else { close (fd); return (vol & 255); } } return -1; } void ossmixer_setlevel_line (int vol){ int fd = -1; int svol = vol | (vol << 8); fd = open("/dev/mixer", O_WRONLY); ioctl(fd, SOUND_MIXER_WRITE(SOUND_MIXER_LINE), &svol); close (fd); } void ossmixer_setlevel_pcm (int vol){ int fd = -1; int svol = vol | (vol << 8); fd = open("/dev/mixer", O_WRONLY); ioctl(fd, SOUND_MIXER_WRITE(SOUND_MIXER_PCM), &svol); close (fd); } static double midi2pitch (int note){ double pitch = pow(2.,(double)(note - 48.)/12.); return pitch; } void set_distortion (looper_data_t *ld, float dist){ if (dist < 0.) dist = 0.; if (dist > 1.) dist = 1.; looperdata_lock(ld); looperdata_set_vol(ld, initial_volume + (dist * 10)); looperdata_set_limknee (ld, .6 - (dist * .57)); looperdata_set_limit (ld, 1. - (dist * .9)); looperdata_set_recmix(ld, 1. - (dist * .5)); /* also see get_distortion */ looperdata_unlock(ld); } float get_distortion (looper_data_t *ld){ return (1. - looperdata_get_recmix(ld)) * 2.; } void reset_looperdata(looper_data_t *looper_data, jack_info_t *jack_info){ looperdata_set_playing(looper_data,1); looperdata_set_recording(looper_data,1); looperdata_set_ngrains(looper_data, initial_ngrains); looperdata_set_graindensity(looper_data, initial_graindensity); looperdata_set_mingrainspeed(looper_data, initial_speed); looperdata_set_maxgrainspeed(looper_data, initial_speed); looperdata_set_speed(looper_data, initial_speed); looperdata_set_vol(looper_data, initial_volume); looperdata_set_recmix(looper_data, 1); looperdata_set_loopend(looper_data, jack_info->samplerate * initial_length); /* .1 sec */ looperdata_set_recend(looper_data, jack_info->samplerate * initial_length); looperdata_set_mingrainlength(looper_data, jack_info->samplerate * initial_length); looperdata_set_maxgrainlength(looper_data, jack_info->samplerate * initial_length); looperdata_set_stereodiversity(looper_data, 0.); looperdata_set_playpos (looper_data, 0); looperdata_set_recpos (looper_data, 0); set_distortion(looper_data,0); } void serialio_pollall (serialio_data_t *serialio, speciallist_t *looperdatalist){ looper_data_t *wld; int i; wld = speciallist_get_first(looperdatalist); if (wld->isrecording != last_footled){ if (wld->isrecording) serialio_set_footled(serialio,0); else serialio_set_footled(serialio,1); last_footled = wld->isrecording ; } if (!wld->isrecording){ serialio_toggle_footled(serialio); } /* check footswitch */ if ((i = serialio_get_foot(serialio)) && !last_foot){ printf ("foot changed\n"); if (wld->isrecording){ serialio_set_footled(serialio,1); while (wld){ wld->isrecording = 0; wld = speciallist_get_next(looperdatalist,wld); } }else{ serialio_set_footled(serialio,0); while (wld){ wld->isrecording = 1; wld = speciallist_get_next(looperdatalist,wld); } } } /* printf ("last_foot:%d, i:%d\n",last_foot,i);*/ last_foot = i; } int set_lcd (tranzport_t *tranzport, const char* lcd0, int offset1, const char* lcd1, int offset2, int timeout){ struct timeval tv; int ok = 0; if (lcd0) ok += tranzport_write_lcd(tranzport,lcd0,offset1,0); else ok += tranzport_write_lcd(tranzport," ",0,0); if (lcd1) ok += tranzport_write_lcd(tranzport,lcd1,offset1,1); else if (!lcd_stereo_buf) ok += tranzport_write_lcd(tranzport," ",0,1); if (lcd_value_text){ free (lcd_value_text); /* reset text */ lcd_value_text = NULL; } if (lcd_stereo_buf){ free (lcd_stereo_buf); lcd_stereo_buf = NULL; } gettimeofday(&tv,0); if (timeout) tranzport_lcd_timeout = (tv.tv_sec * 10 ) + (long)(tv.tv_usec / 100000) + timeout; else tranzport_lcd_timeout = 0; return ok; } void set_lcd_slider_stereo (tranzport_t *tranzport, long left, long right, long min, long max){ char charbuf[2]; int sliderleft = (int)((float)(left - min) / (float)(max - min) * 40.); int sliderright = (int)((float)(right - min) / (float)(max - min) * 40.); int i = 0; if (!lcd_stereo_buf){ tranzport_write_lcd(tranzport," ",0,1); lcd_stereo_buf = malloc(21 * sizeof(char)); memset (lcd_stereo_buf,0,21); } for (i = 0; i < 39; i += 2){ if (sliderleft < i){ /* left empty */ if (sliderright < i) charbuf[0] = 0x20;/* both empty */ else if (sliderright == i) charbuf[0] = 0x02;/* left none, right one */ else charbuf[0] = 0x05;/* left none, right two */ }else if (sliderleft == i){ /* left == one */ if (sliderright < i) charbuf[0] = 0x08;/* left one, right none */ else if (sliderright == i) charbuf[0] = 0x03;/* left one, right one */ else charbuf[0] = 0x06;/* left one, right two */ }else { /* left = both */ if (sliderright < i) charbuf[0] = 0x01;/* left two, right none */ else if (sliderright == i) charbuf[0] = 0x04;/* left two, right one */ else charbuf[0] = 0x07;/* left two, right two */ } charbuf[1] = 0x00; if (strncmp((char*)(lcd_stereo_buf + (int)(i/2)),(char*)&charbuf,1)){ tranzport_write_lcd(tranzport,(char*)&charbuf,(int)(i/2),1); lcd_stereo_buf[(int)(i/2)] = charbuf[0]; } } } void set_lcd_value (tranzport_t *tranzport, const char* text, long value, long min, long max){ char *buf = malloc (21 * sizeof(char)); struct timeval tv; int maxlen; snprintf (buf,20,"%ld",max); maxlen = strlen(buf); if (!lcd_value_text){ lcd_value_text = malloc (21 * sizeof(char)); memset(lcd_value_text,0,21); } if (!strncmp(lcd_value_text,text,20)){ snprintf (buf,20,"%ld ",value); tranzport_write_lcd(tranzport,buf,(20 - maxlen),0); set_lcd_slider_stereo(tranzport,value, value, min, max); }else{ strncpy (lcd_value_text,text,20); snprintf (buf,20,"%s ",text); tranzport_write_lcd(tranzport,buf,0,0); snprintf (buf,20,"%ld ",value); tranzport_write_lcd(tranzport,buf,(20 - maxlen),0); set_lcd_slider_stereo(tranzport,value,value, min, max); } gettimeofday(&tv,0); tranzport_lcd_timeout = (tv.tv_sec * 10) + (long)(tv.tv_usec / 100000) + 50; free(buf); } void set_lcd_value_float (tranzport_t *tranzport, const char* text, float value, float min, float max){ char *buf = malloc (21 * sizeof(char)); struct timeval tv; int maxlen; snprintf (buf,20,"%d",(int)max); maxlen = strlen(buf) + 5; if (!lcd_value_text){ lcd_value_text = malloc (21 * sizeof(char)); memset(lcd_value_text,0,21); } if (!strncmp(lcd_value_text,text,20)){ snprintf (buf,20,"%.4f ",value); tranzport_write_lcd(tranzport,buf,(20 - maxlen),0); }else{ strncpy (lcd_value_text,text,20); snprintf (buf,20,"%s ",text); tranzport_write_lcd(tranzport,buf,0,0); snprintf (buf,20,"%.4f ",value); tranzport_write_lcd(tranzport,buf,(20 - maxlen),0); tranzport_write_lcd(tranzport," ",0,1); } gettimeofday(&tv,0); tranzport_lcd_timeout = (tv.tv_sec * 10) + (long)(tv.tv_usec / 100000) + 50; free(buf); } void tranzport_pollall (tranzport_t *tranzport, speciallist_t *looperdatalist, jack_info_t *jack_info){ looper_data_t *wld; struct timeval tv; int wheel = 0; /* LATER: include a clock */ /* check the state of serial foot */ wld = speciallist_get_first(looperdatalist); if (!looperdata_get_recording(wld) && !tranzport_get_led(tranzport,TRANZPORT_LIGHT_RECORD)){ tranzport_set_led(tranzport,TRANZPORT_LIGHT_RECORD,1); set_lcd (tranzport," LOOPING ",0,NULL,0,50); } if (looperdata_get_recording(wld) && tranzport_get_led(tranzport,TRANZPORT_LIGHT_RECORD)){ tranzport_set_led(tranzport,TRANZPORT_LIGHT_RECORD,0); set_lcd (tranzport," RECORDING ",0,NULL,0,50); } while (!tranzport_do_io(tranzport)){ if (tranzport_get_status(tranzport) == TRANZPORT_STATUS_OFFLINE){ printf ("offline!\n"); if(lcd_value_text){ free (lcd_value_text); /* reset text */ lcd_value_text = NULL; } // tranzport_status = TRANZPORT_STATUS_OFFLINE; return; } if (tranzport_status == TRANZPORT_STATUS_OFFLINE){ tranzport_status = TRANZPORT_STATUS_ONLINE; tranzport_clear_leds(tranzport); set_lcd (tranzport," klopfer says hello! ",0," kluppe.klingt.org ",0,30); } /* ****************** CHECK the BUTTONS: ************ */ if (tranzport_pressed(tranzport, TRANZPORT_BUTTON_TRACKLEFT)){ int l = 0; if (tranzport_buttonstate(tranzport, TRANZPORT_BUTTON_SHIFT)){ l = 0; ossmixer_setlevel_pcm(l); }else{ l = ossmixer_getlevel_pcm(); l -= 5; if (tranzport_buttonstate(tranzport, TRANZPORT_BUTTON_SHIFT)) l -= 5; if (l < 0) l = 0; ossmixer_setlevel_pcm(l); } set_lcd_value (tranzport,"OutputVolume",l,0,100); } if (tranzport_pressed(tranzport, TRANZPORT_BUTTON_TRACKRIGHT)){ int l; if (tranzport_buttonstate(tranzport, TRANZPORT_BUTTON_SHIFT)){ l = 100; ossmixer_setlevel_pcm(l); }else{ l = ossmixer_getlevel_pcm(); l += 5; if (tranzport_buttonstate(tranzport, TRANZPORT_BUTTON_SHIFT)) l += 5; if (l > 100) l = 100; ossmixer_setlevel_pcm(l); } set_lcd_value (tranzport,"OutputVolume",l,0,100); } if (tranzport_pressed(tranzport, TRANZPORT_BUTTON_RECORD | TRANZPORT_FOOTSWITCH)){ wld = speciallist_get_first(looperdatalist); if (looperdata_get_recording(wld)){ /* LED AND LCD is DONE at the top of this function */ while (wld){ looperdata_set_recording(wld,0); wld = speciallist_get_next(looperdatalist,wld); } }else{ while (wld){ looperdata_set_recording(wld,1); wld = speciallist_get_next(looperdatalist,wld); } } } /* RECORD BUTTON PRESSED */ if (tranzport_pressed(tranzport, TRANZPORT_BUTTON_PLAY)){ wld = speciallist_get_first(looperdatalist); if (looperdata_get_playing(wld)){ set_lcd (tranzport," THROUGH ",0,NULL,0,50); while (wld){ looperdata_set_playing(wld,0); wld = speciallist_get_next(looperdatalist,wld); } ossmixer_setlevel_line(startup_linelevel); }else{ set_lcd (tranzport," PROCESS ",0,NULL,0,50); while (wld){ looperdata_set_playing(wld,1); wld = speciallist_get_next(looperdatalist,wld); } ossmixer_setlevel_line(0); } } /* PLAY BUTTON PRESSED */ if (tranzport_pressed(tranzport, TRANZPORT_BUTTON_TRACKREC)){ if (tranzport_mode & TRANZPORT_BUTTON_TRACKREC){ tranzport_mode ^= TRANZPORT_BUTTON_TRACKREC; tranzport_set_led(tranzport, TRANZPORT_LIGHT_TRACKREC,0); set_lcd (tranzport,"SpreadStereoBtn off ",0," ",0,20); }else{ float f; tranzport_mode |= TRANZPORT_BUTTON_TRACKREC; tranzport_set_led(tranzport, TRANZPORT_LIGHT_TRACKREC,1); wld = speciallist_get_first(looperdatalist); f = looperdata_get_stereodiversity(wld); set_lcd_value_float (tranzport,"SpreadStereo",f,0.,1.); } } /* TRACKREC BUTTON == PITCH SHIFT PRESSED */ if (tranzport_pressed(tranzport, TRANZPORT_BUTTON_TRACKMUTE)){ if (tranzport_mode & TRANZPORT_BUTTON_TRACKMUTE){ tranzport_mode ^= TRANZPORT_BUTTON_TRACKMUTE; tranzport_set_led(tranzport, TRANZPORT_LIGHT_TRACKMUTE,0); set_lcd (tranzport,"LoopLengthButton off",0," ",0,20); }else{ long d; tranzport_mode |= TRANZPORT_BUTTON_TRACKMUTE; tranzport_set_led(tranzport, TRANZPORT_LIGHT_TRACKMUTE,1); wld = speciallist_get_first(looperdatalist); d = looperdata_get_mingrainlength(wld); set_lcd_value (tranzport,"LoopLength",d,0, jack_info->samplerate * 60); } } /* TRACKMUTE BUTTON == LOOP LENGTH PRESSED */ if (tranzport_pressed(tranzport, TRANZPORT_BUTTON_TRACKSOLO)){ if (tranzport_mode & TRANZPORT_BUTTON_TRACKSOLO){ tranzport_mode ^= TRANZPORT_BUTTON_TRACKSOLO; tranzport_set_led(tranzport, TRANZPORT_LIGHT_TRACKSOLO,0); set_lcd (tranzport,"DistortionButton off",0," ",0,20); }else{ float f; tranzport_mode |= TRANZPORT_BUTTON_TRACKSOLO; tranzport_set_led(tranzport, TRANZPORT_LIGHT_TRACKSOLO,1); wld = speciallist_get_first(looperdatalist); f = get_distortion(wld); set_lcd_value (tranzport,"Distortion",(int)(f * 100),0, 100); } } /* TRACKMUTE BUTTON == LOOP LENGTH PRESSED */ if (tranzport_pressed(tranzport, TRANZPORT_BUTTON_PUNCH)){ if (tranzport_mode & TRANZPORT_BUTTON_PUNCH){ tranzport_mode ^= TRANZPORT_BUTTON_PUNCH; tranzport_set_led(tranzport, TRANZPORT_LIGHT_PUNCH,0); set_lcd (tranzport,"GrainDensityBtn off ",0," ",0,20); }else{ long d; tranzport_mode |= TRANZPORT_BUTTON_PUNCH; tranzport_set_led(tranzport, TRANZPORT_LIGHT_PUNCH,1); wld = speciallist_get_first(looperdatalist); d = looperdata_get_graindensity(wld); set_lcd_value (tranzport,"GrainDensity",d,1,100); } } /* PUNCH BUTTON == FRAIN DENSITY PRESSED */ if (tranzport_pressed(tranzport, TRANZPORT_BUTTON_LOOP)){ if (tranzport_mode & TRANZPORT_BUTTON_LOOP){ tranzport_mode ^= TRANZPORT_BUTTON_LOOP; tranzport_set_led(tranzport, TRANZPORT_LIGHT_LOOP,0); set_lcd (tranzport,"NrGrainsBtn off ",0," ",0,20); }else{ long d; tranzport_mode |= TRANZPORT_BUTTON_LOOP; tranzport_set_led(tranzport, TRANZPORT_LIGHT_LOOP,1); wld = speciallist_get_first(looperdatalist); d = looperdata_get_ngrains(wld); set_lcd_value (tranzport,"Nr. of Grains",d,1,max_ngrains); } } /* LOOP BUTTON == NRofGRAINS PRESSED */ if (tranzport_pressed(tranzport, TRANZPORT_BUTTON_IN)){ if (tranzport_mode & TRANZPORT_BUTTON_IN){ tranzport_mode ^= TRANZPORT_BUTTON_IN; tranzport_set_led(tranzport, TRANZPORT_LIGHT_ANYSOLO,0); set_lcd (tranzport,"ReverbTime off ",0," ",0,20); }else{ long d; tranzport_mode |= TRANZPORT_BUTTON_IN; tranzport_set_led(tranzport, TRANZPORT_LIGHT_ANYSOLO,1); wld = speciallist_get_first(looperdatalist); d = looperdata_get_reverblength(wld); set_lcd_value (tranzport,"ReverbTime",((d * 1000) / jack_info->samplerate),0,1000); } } if (tranzport_pressed(tranzport, TRANZPORT_BUTTON_OUT)){ if (tranzport_mode & TRANZPORT_BUTTON_OUT){ tranzport_mode ^= TRANZPORT_BUTTON_OUT; tranzport_set_led(tranzport, TRANZPORT_LIGHT_ANYSOLO,0); set_lcd (tranzport,"Feedback off ",0," ",0,20); }else{ float f; tranzport_mode |= TRANZPORT_BUTTON_OUT; tranzport_set_led(tranzport, TRANZPORT_LIGHT_ANYSOLO,1); wld = speciallist_get_first(looperdatalist); f = looperdata_get_reverblength(wld); set_lcd_value_float (tranzport,"Feedback",f,0.,1.); } } if (tranzport_pressed(tranzport, TRANZPORT_BUTTON_NEXT)){ char msg[21] = " "; active_settings = speciallist_get_next(settingslist,active_settings); if (!active_settings) active_settings = speciallist_get_first(settingslist); snprintf (msg,21,"preset: %s ",active_settings->name); set_lcd (tranzport,msg,0,NULL,0,20); } if (tranzport_pressed(tranzport, TRANZPORT_BUTTON_PREV)){ char msg[21] = " "; active_settings = speciallist_get_previous(settingslist,active_settings); if (!active_settings) active_settings = speciallist_get_last(settingslist); snprintf (msg,21,"preset: %s ",active_settings->name); set_lcd (tranzport,msg,0,NULL,0,20); } if (tranzport_pressed(tranzport, TRANZPORT_BUTTON_REWIND)){ float f; wld = speciallist_get_first(looperdatalist); f = looperdata_get_mingrainspeed(wld); f *= pow(semitone,-1.); if (tranzport_buttonstate(tranzport, TRANZPORT_BUTTON_SHIFT)) f *= pow(semitone,-1.); if ((f > 0.0001) && (f < 100.)){ while (wld){ /* grain speed */ looperdata_lock(wld); looperdata_set_mingrainspeed(wld,f); looperdata_set_maxgrainspeed(wld,f); looperdata_unlock(wld); wld = speciallist_get_next(looperdatalist,wld); } set_lcd_value_float (tranzport,"GrainPitch",f,0.,100.); } } if (tranzport_pressed(tranzport, TRANZPORT_BUTTON_FASTFORWARD)){ float f; wld = speciallist_get_first(looperdatalist); f = looperdata_get_mingrainspeed(wld); f *= pow(semitone,1.); if (tranzport_buttonstate(tranzport, TRANZPORT_BUTTON_SHIFT)) f *= pow(semitone,1.); if ((f > 0.0001) && (f < 100.)){ while (wld){ /* grain speed */ looperdata_lock(wld); looperdata_set_mingrainspeed(wld,f); looperdata_set_maxgrainspeed(wld,f); looperdata_unlock(wld); wld = speciallist_get_next(looperdatalist,wld); } set_lcd_value_float (tranzport,"GrainPitch",f,0.,100.); } } if (tranzport_pressed(tranzport, TRANZPORT_BUTTON_STOP)){ while (wld){ /* grain speed */ looperdata_lock(wld); looperdata_set_mingrainspeed(wld,1.); looperdata_set_maxgrainspeed(wld,1.); looperdata_unlock(wld); wld = speciallist_get_next(looperdatalist,wld); } set_lcd_value_float (tranzport,"GrainPitch",1.,0.,100.); } if (tranzport_pressed(tranzport, TRANZPORT_BUTTON_ADD)){ char msg[21] = " "; wld = speciallist_get_first(looperdatalist); while (wld){ if (active_settings){ int isrec = looperdata_get_recording(wld); looperdata_lock(wld); looperdata_copy_settings(wld,active_settings->looper_data); looperdata_set_recording(wld,isrec); looperdata_unlock(wld); } wld = speciallist_get_next(looperdatalist,wld); } snprintf (msg,21,"active: %s ",active_settings->name); set_lcd (tranzport,msg,0,NULL,0,20); } /* ***************** RESET *************************/ if (tranzport_pressed(tranzport, TRANZPORT_BUTTON_UNDO)){ /* if (tranzport_mode & TRANZPORT_BUTTON_TRACKREC){ set_lcd_value_float (tranzport,"GrainPitch",1.,0.,100.); wld = speciallist_get_first(looperdatalist); while (wld){ looperdata_lock(wld); looperdata_set_mingrainspeed(wld,1.); looperdata_set_maxgrainspeed(wld,1.); looperdata_unlock(wld); wld = speciallist_get_next(looperdatalist,wld); } } */ if (tranzport_mode & TRANZPORT_BUTTON_TRACKREC){ set_lcd_value_float (tranzport,"SpreadStereo",0.,0.,1.); wld = speciallist_get_first(looperdatalist); while (wld){ looperdata_lock(wld); looperdata_set_stereodiversity(wld,0.); looperdata_unlock(wld); wld = speciallist_get_next(looperdatalist,wld); } } if (tranzport_mode & TRANZPORT_BUTTON_TRACKMUTE){ long d = jack_info->samplerate * initial_length; set_lcd_value (tranzport,"LoopLength",d ,0, jack_info->samplerate * 60); wld = speciallist_get_first(looperdatalist); while (wld){ /* grain speed */ looperdata_lock(wld); looperdata_set_maxgrainlength (wld, d); looperdata_set_loopend (wld, d); looperdata_set_recend (wld, d); looperdata_set_mingrainlength(wld,d); looperdata_unlock(wld); wld = speciallist_get_next(looperdatalist,wld); } } if (tranzport_mode & TRANZPORT_BUTTON_TRACKSOLO){ set_lcd_value (tranzport,"Distortion",0,0,100); wld = speciallist_get_first(looperdatalist); while (wld){ set_distortion(wld,0.); wld = speciallist_get_next(looperdatalist,wld); } } if (tranzport_mode & TRANZPORT_BUTTON_LOOP){ set_lcd_value (tranzport,"Nr. of Grains",max_ngrains,1,max_ngrains); wld = speciallist_get_first(looperdatalist); while (wld){ /* grain speed */ looperdata_lock(wld); looperdata_set_ngrains(wld,max_ngrains); looperdata_unlock(wld); wld = speciallist_get_next(looperdatalist,wld); } } if (tranzport_mode & TRANZPORT_BUTTON_PUNCH){ set_lcd_value (tranzport,"GrainDensity",100,0,100); wld = speciallist_get_first(looperdatalist); while (wld){ /* grain speed */ looperdata_lock(wld); looperdata_set_graindensity(wld,100.); looperdata_unlock(wld); wld = speciallist_get_next(looperdatalist,wld); } } if (tranzport_mode & TRANZPORT_BUTTON_IN){ set_lcd_value (tranzport,"ReverbTime",100,0,1000); wld = speciallist_get_first(looperdatalist); while (wld){ /* grain speed */ looperdata_lock(wld); looperdata_set_reverblength(wld,100.); looperdata_unlock(wld); wld = speciallist_get_next(looperdatalist,wld); } } if (tranzport_mode & TRANZPORT_BUTTON_OUT){ set_lcd_value_float (tranzport,"Feedback",0.,0.,1.); wld = speciallist_get_first(looperdatalist); while (wld){ /* grain speed */ looperdata_lock(wld); looperdata_set_feedback(wld,0.); looperdata_unlock(wld); wld = speciallist_get_next(looperdatalist,wld); } } /* restart */ if (tranzport_buttonstate(tranzport, TRANZPORT_BUTTON_SHIFT)){ set_lcd (tranzport," EXIT ",0," kluppe.klingt.org ",0,1); exit(0); } } /* end RESET */ /* *************************** SHUTTLE WHEEL ************************** */ if ((wheel = tranzport_get_wheel(tranzport))){ if (!tranzport_mode){ float f; wld = speciallist_get_first(looperdatalist); f = looperdata_get_mingrainspeed(wld); if (tranzport_buttonstate(tranzport, TRANZPORT_BUTTON_SHIFT)) f *= 1 + ((double)wheel * .1); else f *= 1 + ((double)wheel * .01); if ((f > 0.0001) && (f < 100.)){ while (wld){ /* grain speed */ looperdata_lock(wld); looperdata_set_mingrainspeed(wld,f); looperdata_set_maxgrainspeed(wld,f); looperdata_unlock(wld); wld = speciallist_get_next(looperdatalist,wld); } set_lcd_value_float (tranzport,"GrainPitch",f,0.,100.); } } /* end pitch shift == NO BUTTON PRESSED */ if (tranzport_mode & TRANZPORT_BUTTON_TRACKREC){ float f; wld = speciallist_get_first(looperdatalist); f = looperdata_get_stereodiversity(wld); f += (double)wheel * .05; if (tranzport_buttonstate(tranzport, TRANZPORT_BUTTON_SHIFT)) f += (double)wheel * .05; if (f < 0.) f = 0.; if (f > 1.) f = 1.; while (wld){ looperdata_lock(wld); looperdata_set_stereodiversity(wld,f); looperdata_unlock(wld); wld = speciallist_get_next(looperdatalist,wld); } set_lcd_value_float (tranzport,"SpreadStereo",f,0.,1.); }/* end stereo diversity = TRACKREC */ if (tranzport_mode & TRANZPORT_BUTTON_TRACKMUTE){ long d = 0; wld = speciallist_get_first(looperdatalist); while (wld){ /* grain length */ looperdata_lock(wld); if (looperdata_get_mingrainlength(wld) > 40){ d = looperdata_get_mingrainlength(wld); d = (long)((float)d * ( 1. + (float)wheel * .03)); } else d = looperdata_get_mingrainlength(wld) + wheel; if (d > buffer_get_size(wld->buf)) d = buffer_get_size(wld->buf); if (d < 3) d = 3; looperdata_set_maxgrainlength (wld, d); looperdata_set_loopend (wld, d); looperdata_set_recend (wld, d); looperdata_set_mingrainlength(wld,d); looperdata_unlock(wld); wld = speciallist_get_next(looperdatalist,wld); } set_lcd_value (tranzport,"LoopLength",d,1,jack_info->samplerate * 60); } if (tranzport_mode & TRANZPORT_BUTTON_TRACKSOLO){ float f; wld = speciallist_get_first(looperdatalist); f = get_distortion(wld); f += wheel * .05; if (f < 0.) f = 0.; if (f > 1.) f = 1.; while (wld){ /* grain speed */ set_distortion(wld,f); wld = speciallist_get_next(looperdatalist,wld); } set_lcd_value (tranzport,"Distortion",(int)(f * 100),0,100); } /* end pitch shift == TRACKSOLO */ if (tranzport_mode & TRANZPORT_BUTTON_LOOP){ long d = 0; wld = speciallist_get_first(looperdatalist); while (wld){ d = looperdata_get_ngrains(wld); d += wheel; if (d < 1) d = 1; if (d > max_ngrains) d = max_ngrains; looperdata_lock(wld); /* printf ("ngrains:%d\n", diff);*/ looperdata_set_ngrains(wld, d); looperdata_unlock(wld); wld = speciallist_get_next(looperdatalist,wld); } set_lcd_value (tranzport,"Nr. of Grains",d,1,max_ngrains); } if (tranzport_mode & TRANZPORT_BUTTON_PUNCH){ long d = 0; wld = speciallist_get_first(looperdatalist); while (wld){ d = looperdata_get_graindensity(wld); if (tranzport_buttonstate(tranzport, TRANZPORT_BUTTON_SHIFT)) d += wheel * 10; else d += wheel * wheel * wheel; if (d < 1) d = 1; if (d > 100) d = 100; looperdata_lock(wld); looperdata_set_graindensity(wld, d); looperdata_unlock(wld); wld = speciallist_get_next(looperdatalist,wld); } set_lcd_value (tranzport,"GrainDensity",d,1,100); } /* end if PUNCH */ if (tranzport_mode & TRANZPORT_BUTTON_IN){ long d = 0; wld = speciallist_get_first(looperdatalist); while (wld){ d = looperdata_get_reverblength(wld); if (tranzport_buttonstate(tranzport, TRANZPORT_BUTTON_SHIFT)) d += wheel * wheel * wheel; else d += wheel * wheel * wheel * 250; if (d < 1) d = 1; if (d > 44100) d = 44100; looperdata_lock(wld); looperdata_set_reverblength(wld, d); looperdata_unlock(wld); wld = speciallist_get_next(looperdatalist,wld); } set_lcd_value (tranzport,"ReverbTime (ms)",((d * 1000) / jack_info->samplerate),0,1000); }/* end if IN */ if (tranzport_mode & TRANZPORT_BUTTON_OUT){ float f = 0; wld = speciallist_get_first(looperdatalist); while (wld){ f = looperdata_get_feedback(wld); if (tranzport_buttonstate(tranzport, TRANZPORT_BUTTON_SHIFT)) f += wheel * .1; else f += wheel * wheel * wheel / 100.; if (f < 0.) f = 0.; if (f > 1.) f = 1.; looperdata_lock(wld); looperdata_set_feedback(wld, f); looperdata_unlock(wld); wld = speciallist_get_next(looperdatalist,wld); } set_lcd_value_float (tranzport,"Feedback",f,0.,1.); }/* end if OUT */ }/* end if wheel */ } /* end while poll */ if (tranzport_lcd_timeout){ /* idle lcd ? */ gettimeofday(&tv,0); if (((tv.tv_sec * 10) + (long)(tv.tv_usec / 100000)) >= tranzport_lcd_timeout){ wld = speciallist_get_first(looperdatalist); if (looperdata_get_playing(wld)){ float vL,vR; set_lcd (tranzport,ctime(&tv.tv_sec),0,NULL,0,1); wld = speciallist_get_first(looperdatalist); looperdata_get_recmeters(wld, &vL, &vR); vL = 20.0f * log10f(vL); vR = 20.0f * log10f(vR); if (vL > -50.) vL += 50.; else vL = 0.; if (vR > -50.) vR += 50.; else vR = 0.; set_lcd_slider_stereo(tranzport,(int)vL,(int)vR,0,50); }else set_lcd (tranzport,ctime(&tv.tv_sec),0," SOUND THROUGH ",0,10); } } /* end of idle stuff */ } void shuttle_pollall (shuttle_data_t *shuttle, speciallist_t *looperdatalist, jack_info_t *jack_info){ looper_data_t *wld; wld = speciallist_get_first(looperdatalist); if (shuttle->fd < 1) return; /* not so clever */ if (shuttle->fd < 1) { shuttle_open(shuttle); if (shuttle->fd > 0) printf ("shuttle device found\n"); } if (shuttle->fd < 1) return; while (shuttle_poll (shuttle) > 0){ switch (shuttle->code){ case SHUTTLE_LEFTMOST :/* play */ if ((!shuttle->value) && (shuttle->lastcode == shuttle->code)){ if (wld->isplaying){ while (wld){ wld->isplaying = 0; wld = speciallist_get_next(looperdatalist,wld); } ossmixer_setlevel_line(startup_linelevel); }else{ while (wld){ wld->isplaying = 1; wld = speciallist_get_next(looperdatalist,wld); } ossmixer_setlevel_line(0); } } break; case SHUTTLE_LEFT : /* invert grain speed */ if ((!shuttle->value) && (shuttle->lastcode == shuttle->code)){ while (wld){ looperdata_lock(wld); looperdata_set_mingrainspeed(wld, looperdata_get_mingrainspeed(wld) * -1.); looperdata_set_maxgrainspeed(wld, looperdata_get_maxgrainspeed(wld) * -1.); looperdata_unlock(wld); wld = speciallist_get_next(looperdatalist,wld); } } break; case SHUTTLE_MIDDLE : /* reset */ if ((!shuttle->value) && (shuttle->lastcode == shuttle->code)){ if (shuttle->buttonstates & SHUTTLE_LEFTMOST){ while (wld){ looperdata_lock(wld); looperdata_set_loopend (wld, jack_info->samplerate * initial_length); looperdata_set_recend (wld, jack_info->samplerate * initial_length); looperdata_set_maxgrainlength (wld, jack_info->samplerate * initial_length); looperdata_set_mingrainlength(wld, jack_info->samplerate * initial_length); looperdata_unlock(wld); wld = speciallist_get_next(looperdatalist,wld); } } else if (shuttle->buttonstates & SHUTTLE_LEFT){ while (wld){ looperdata_lock(wld); looperdata_set_mingrainspeed(wld,1.); looperdata_set_maxgrainspeed(wld,1.); looperdata_unlock(wld); wld = speciallist_get_next(looperdatalist,wld); } } else if (shuttle->buttonstates & SHUTTLE_RIGHTMOST){ while (wld){ looperdata_lock(wld); looperdata_set_recpos(wld, looperdata_get_recstart(wld)); looperdata_unlock(wld); wld = speciallist_get_next(looperdatalist,wld); } } else if (shuttle->buttonstates & SHUTTLE_RIGHT){ } else { while (wld){ looperdata_lock(wld); reset_looperdata (wld, jack_info); looperdata_unlock(wld); wld = speciallist_get_next(looperdatalist,wld); } } } break; case SHUTTLE_RIGHT : /* distortion */ if ((!shuttle->value) && (shuttle->lastcode == shuttle->code)){ if (looperdata_get_vol(wld) < 1.){ while (wld){ looperdata_lock(wld); looperdata_set_vol(wld, 3); looperdata_set_limknee (wld, .1); looperdata_set_limit (wld, .4); looperdata_set_recmix(wld, .6); looperdata_unlock(wld); wld = speciallist_get_next(looperdatalist,wld); } } else { while (wld){ looperdata_lock(wld); looperdata_set_vol(wld, .9); looperdata_set_limknee (wld, .6); looperdata_set_limit (wld, 1.); looperdata_set_recmix(wld, 1.); looperdata_unlock(wld); wld = speciallist_get_next(looperdatalist,wld); } } } break; case SHUTTLE_RIGHTMOST : /* tap loop length */ if ((!shuttle->value) && (shuttle->lastcode == shuttle->code)){ struct timeval tv; double now; long diff; /* milliseconds between last two events */ long since; /* milliseconds since event */ gettimeofday(&tv,NULL); since = (tv.tv_sec - shuttle->lastevent.tv_sec) * 1000; since += (long)((tv.tv_usec - shuttle->lastevent.tv_usec) / 1000.); now = (double)shuttle->lastevent.tv_sec * 1000. + (double)shuttle->lastevent.tv_usec / 1000.; diff = (long)(now - last_tap); if (diff < 3000){ while (wld){ looperdata_lock(wld); looperdata_set_playpos(wld, since * jack_info->samplerate / 1000); looperdata_set_recpos(wld, since * jack_info->samplerate / 1000); looperdata_set_loopend(wld, diff * jack_info->samplerate / 1000); looperdata_set_recend(wld, diff * jack_info->samplerate / 1000); looperdata_unlock(wld); wld = speciallist_get_next(looperdatalist,wld); } } /* printf ("now:%lf, last:%lf, since:%ld, diff:%ld\n",now, last_tap, since, diff);*/ last_tap = now; } #if 0 /* record */ if ((!shuttle->value) && (shuttle->lastcode == shuttle->code)){ if (wld->isrecording){ while (wld){ wld->isrecording = 0; wld = speciallist_get_next(looperdatalist,wld); } }else{ while (wld){ wld->isrecording = 1; wld = speciallist_get_next(looperdatalist,wld); } } } #endif break; case SHUTTLE_SHUTTLE : if (!shuttle->buttonstates){ while (wld){ /* no button = number of grains */ int d = looperdata_get_ngrains(wld); int diff = d + (shuttle->shuttledelta / 4); if (diff < 1) diff = 1; if (diff > max_ngrains) diff = max_ngrains; if ((diff > 0) && (diff < 16)){ looperdata_lock(wld); /* printf ("ngrains:%d\n", diff);*/ looperdata_set_ngrains(wld, diff); looperdata_unlock(wld); } wld = speciallist_get_next(looperdatalist,wld); } } else if (shuttle->buttonstates & SHUTTLE_LEFT){ while (wld){ /* grain speed */ float f = looperdata_get_mingrainspeed(wld); /* f = f + f * .0002 * (double)(shuttle->jogstate * shuttle->jogstate * shuttle->jogstate);*/ f *= pow(semitone,(double)shuttle->shuttledelta); /* printf ("factor:%lf, f:%lf\n",pow(semitone,(double)shuttle->shuttledelta),f);*/ if ((f > 0) && (f < 100)){ looperdata_lock(wld); looperdata_set_mingrainspeed(wld,f); looperdata_set_maxgrainspeed(wld,f); looperdata_unlock(wld); } wld = speciallist_get_next(looperdatalist,wld); } } else if (shuttle->buttonstates & SHUTTLE_LEFTMOST){ /* grain length */ while (wld){ long d = looperdata_get_mingrainlength (wld) + shuttle->shuttledelta; if (d > buffer_get_size(wld->buf)) d = buffer_get_size(wld->buf); if (d < 3) d = 3; looperdata_lock(wld); looperdata_set_loopend (wld, d); looperdata_set_recend (wld, d); looperdata_set_maxgrainlength (wld, d); looperdata_set_mingrainlength(wld,(long)(d)); looperdata_unlock(wld); wld = speciallist_get_next(looperdatalist,wld); } } break; } } if (shuttle->jogstate){ if (!shuttle->buttonstates){ while (wld){ /* grain density */ int d = looperdata_get_graindensity(wld); if ((d + shuttle->jogstate > 1) && ((d + (int)( shuttle->jogstate / 4)) <= 100)){ looperdata_lock(wld); looperdata_set_graindensity(wld, d + (int)(shuttle->jogstate / 4)); looperdata_unlock(wld); } /* this will most likely not go down to 1. */ wld = speciallist_get_next(looperdatalist,wld); } } else if (shuttle->buttonstates & SHUTTLE_LEFTMOST){ while (wld){ /* grain length */ looperdata_lock(wld); long d; /* float f = (float)looperdata_get_mingrainlength(wld) / (float)looperdata_get_maxgrainlength(wld); */ if (looperdata_get_mingrainlength(wld) > 20){ double f = (double)looperdata_get_mingrainlength(wld) * .0002 * (double)(shuttle->jogstate * shuttle->jogstate * shuttle->jogstate); if (f > 0.0) f += 0.999; else f -= 0.999; d = looperdata_get_mingrainlength(wld) + (long)f; } else d = looperdata_get_mingrainlength(wld) + shuttle->jogstate; if (d > buffer_get_size(wld->buf)) d = buffer_get_size(wld->buf); if (d < 3) d = 3; looperdata_set_maxgrainlength (wld, d); looperdata_set_loopend (wld, d); looperdata_set_recend (wld, d); /* if ((long)(d) > 5)*/ looperdata_set_mingrainlength(wld,(long)(d)); looperdata_unlock(wld); /* printf ("2:size:%ld, min:%ld, max:%ld\n", d,looperdata_get_mingrainlength(wld),looperdata_get_maxgrainlength(wld)); */ wld = speciallist_get_next(looperdatalist,wld); } } else if (shuttle->buttonstates & SHUTTLE_LEFT){ while (wld){ /* grain speed */ /* grain speed */ float f = looperdata_get_mingrainspeed(wld); f = f + f * .0002 * (double)(shuttle->jogstate * shuttle->jogstate * shuttle->jogstate); if ((f > 0) && (f < 100)){ looperdata_lock(wld); /* looperdata_set_speed(wld,f);*/ looperdata_set_mingrainspeed(wld,f); looperdata_set_maxgrainspeed(wld,f); looperdata_unlock(wld); } /* printf ("speed:%f\n",looperdata_get_speed(wld));*/ wld = speciallist_get_next(looperdatalist,wld); } } else if (shuttle->buttonstates & SHUTTLE_RIGHTMOST){ while (wld){ /* just the minimum grain length */ float f = (float)looperdata_get_mingrainlength(wld) / (float)looperdata_get_maxgrainlength(wld); f = f + f * .0005 * (float)(shuttle->jogstate * shuttle->jogstate * shuttle->jogstate); if (f > 1.) f = 1.; if (f <= .1) f = .1; if ((long)(looperdata_get_maxgrainlength(wld) * f) > 10){ looperdata_lock(wld); looperdata_set_mingrainlength(wld,(long)(looperdata_get_maxgrainlength(wld) * f)); looperdata_unlock(wld); } /* printf ("mingrain:%ld, maxgrain:%ld, f:%f\n", looperdata_get_mingrainlength(wld),looperdata_get_maxgrainlength(wld),f);*/ wld = speciallist_get_next(looperdatalist,wld); } } } return; } #if 0 void sigproc(){ signal(SIGINT, sigproc); /* */ /* NOTE some versions of UNIX will reset signal to default after each call. So for portability reset signal each time */ } void quitproc(){ printf ("exiting\n"); exit(0); } #endif void create_settings(buffer_info_t* buf, jack_info_t* jack_info){ looper_data_t *ld; looper_settings_t *ls; double note; settingslist = speciallist_new(); /* plain and empty */ ld = looperdata_new(buf, jack_info->samplerate, 1); reset_looperdata(ld,jack_info); ld->isrecording = 1; ls = malloc(sizeof(looper_settings_t)); ls->looper_data = ld; snprintf((char*)&ls->name,20,"PLAIN"); speciallist_append(settingslist,(void*)ls); active_settings = ls; /* dominantseptakkord */ ld = looperdata_new(buf, jack_info->samplerate, 1); reset_looperdata(ld,jack_info); looperdata_lock(ld); looperdata_set_grainpitchmode(ld,GRAINPITCH_CHORD); note = midi2pitch(48); looperdata_set_grainpitchtablevalue (ld, note, 1.0); note = midi2pitch(51); looperdata_set_grainpitchtablevalue (ld, note, 1.0); note = midi2pitch(54); looperdata_set_grainpitchtablevalue (ld, note, 1.0); note = midi2pitch(56); looperdata_set_grainpitchtablevalue (ld, note, 1.0); looperdata_set_stereodiversity(ld,0.); ld->isrecording = 1; looperdata_unlock(ld); ls = malloc(sizeof(looper_settings_t)); ls->looper_data = ld; snprintf((char*)&ls->name,20,"D7"); speciallist_append(settingslist,(void*)ls); /* resonator / ringmod-like */ ld = looperdata_new(buf, jack_info->samplerate, 1); reset_looperdata(ld,jack_info); looperdata_lock(ld); looperdata_set_ngrains(ld,1); looperdata_set_stereodiversity(ld,0.4); looperdata_set_maxgrainlength (ld, 56); looperdata_set_loopend (ld, 56); looperdata_set_recend (ld, 56); looperdata_set_mingrainlength(ld,56); looperdata_set_stereodiversity(ld,0.); ld->isrecording = 1; looperdata_unlock(ld); set_distortion(ld,0.6); ls = malloc(sizeof(looper_settings_t)); ls->looper_data = ld; snprintf((char*)&ls->name,20,"Resonator"); speciallist_append(settingslist,(void*)ls); /* dominantseptakkord miniloop distorted*/ ld = looperdata_new(buf, jack_info->samplerate, 1); reset_looperdata(ld,jack_info); looperdata_lock(ld); looperdata_set_grainpitchmode(ld,GRAINPITCH_CHORD); note = midi2pitch(48); looperdata_set_grainpitchtablevalue (ld, note, 1.0); note = midi2pitch(51); looperdata_set_grainpitchtablevalue (ld, note, 1.0); note = midi2pitch(54); looperdata_set_grainpitchtablevalue (ld, note, 1.0); note = midi2pitch(56); looperdata_set_grainpitchtablevalue (ld, note, 1.0); looperdata_set_maxgrainlength (ld, 256); looperdata_set_loopend (ld, 256); looperdata_set_recend (ld, 256); looperdata_set_mingrainlength(ld,256); looperdata_set_stereodiversity(ld,0.); ld->isrecording = 1; looperdata_unlock(ld); set_distortion(ld,1.); ls = malloc(sizeof(looper_settings_t)); ls->looper_data = ld; snprintf((char*)&ls->name,20,"D7 DIST 256"); speciallist_append(settingslist,(void*)ls); /* miniloop */ ld = looperdata_new(buf, jack_info->samplerate, 1); reset_looperdata(ld,jack_info); looperdata_lock(ld); looperdata_set_maxgrainlength (ld, 13); looperdata_set_loopend (ld, 13); looperdata_set_recend (ld, 13); looperdata_set_mingrainlength(ld,13); looperdata_set_stereodiversity(ld,0.); ld->isrecording = 1; looperdata_unlock(ld); ls = malloc(sizeof(looper_settings_t)); ls->looper_data = ld; snprintf((char*)&ls->name,20,"LENGTH 13"); speciallist_append(settingslist,(void*)ls); /* miniloop */ ld = looperdata_new(buf, jack_info->samplerate, 1); reset_looperdata(ld,jack_info); looperdata_lock(ld); looperdata_set_graindensity(ld,13); looperdata_set_ngrains(ld,5); looperdata_set_maxgrainlength (ld, 79); looperdata_set_loopend (ld, 79); looperdata_set_recend (ld, 79); looperdata_set_mingrainlength(ld,79); looperdata_set_stereodiversity(ld,0.); ld->isrecording = 1; looperdata_unlock(ld); ls = malloc(sizeof(looper_settings_t)); ls->looper_data = ld; snprintf((char*)&ls->name,20,"ROUGH"); speciallist_append(settingslist,(void*)ls); /* dominantseptakkord miniloop distorted*/ ld = looperdata_new(buf, jack_info->samplerate, 1); reset_looperdata(ld,jack_info); looperdata_lock(ld); looperdata_set_mingrainspeed(ld,2.); looperdata_set_maxgrainspeed(ld,2.); looperdata_set_stereodiversity(ld,0.); ld->isrecording = 1; looperdata_unlock(ld); set_distortion(ld,1.); ls = malloc(sizeof(looper_settings_t)); ls->looper_data = ld; snprintf((char*)&ls->name,20,"PITCH 2."); speciallist_append(settingslist,(void*)ls); /* dominantseptakkord miniloop distorted*/ ld = looperdata_new(buf, jack_info->samplerate, 1); reset_looperdata(ld,jack_info); looperdata_lock(ld); looperdata_set_mingrainspeed(ld,.5); looperdata_set_maxgrainspeed(ld,.5); looperdata_set_stereodiversity(ld,0.); ld->isrecording = 1; looperdata_unlock(ld); set_distortion(ld,1.); ls = malloc(sizeof(looper_settings_t)); ls->looper_data = ld; snprintf((char*)&ls->name,20,"PITCH .5"); speciallist_append(settingslist,(void*)ls); /* dominantseptakkord miniloop distorted*/ ld = looperdata_new(buf, jack_info->samplerate, 1); reset_looperdata(ld,jack_info); looperdata_lock(ld); looperdata_set_mingrainspeed(ld,.25); looperdata_set_maxgrainspeed(ld,.25); looperdata_set_stereodiversity(ld,0.); ld->isrecording = 1; looperdata_unlock(ld); set_distortion(ld,1.); ls = malloc(sizeof(looper_settings_t)); ls->looper_data = ld; snprintf((char*)&ls->name,20,"PITCH .25"); speciallist_append(settingslist,(void*)ls); /* dominantseptakkord miniloop distorted*/ ld = looperdata_new(buf, jack_info->samplerate, 1); reset_looperdata(ld,jack_info); looperdata_lock(ld); looperdata_set_mingrainspeed(ld,.05); looperdata_set_maxgrainspeed(ld,.05); looperdata_set_stereodiversity(ld,0.); ld->isrecording = 1; looperdata_unlock(ld); set_distortion(ld,1.); ls = malloc(sizeof(looper_settings_t)); ls->looper_data = ld; snprintf((char*)&ls->name,20,"PITCH .05"); speciallist_append(settingslist,(void*)ls); } /*--------MAIN--------*/ int main(int argc, char *argv[]){ int i; buffer_info_t *buf; looper_data_t *looper_data; struct timeval tv; speciallist_t *looperdatalist; speciallist_t *buffer_list; /* int looperindexcounter = 0;*/ int bufferindexcounter = 0; jack_info_t *jack_info; int alive = 1; long lastxruns = 0; shuttle_data_t *shuttle; tranzport_t *tranzport; serialio_data_t *serialio; /* int rounds = 0;*/ #if 0 struct timeval ts; double ta; double tb = 0; #endif /* signal(SIGINT, sigproc); signal(SIGQUIT, quitproc); */ /* printf ("zwzw: %.12lf\n",pow (2, 1./12.));*/ startup_linelevel = ossmixer_getlevel_line(); if (startup_linelevel < 1) startup_linelevel = 80; /* printf ("line:%d\n",startup_linelevel);*/ printf ("pcm:%d\n", ossmixer_getlevel_pcm()); shuttle = shuttle_new(); if (shuttle_open(shuttle) < 1){ fprintf(stderr,"could not open shuttle device!\n"); /* exit (0); */ } serialio = serialio_new(); if (serialio_open(serialio) < 1){ fprintf(stderr,"could not open serial device!"); } tranzport = tranzport_new(); if (!tranzport){ /* LATER: check for actual device */ fprintf(stderr,"could not open tranzport device!"); }else{ tranzport_set_nativemode(tranzport); } /* global data initialisation */ buffer_list = speciallist_new(); looperdatalist = speciallist_new(); /* start the loadbuffer thread */ buffer_discthread_launch(buffer_list); /* start the jack threads */ jack_info = mixer_launch(looperdatalist); if (!jack_info->samplerate){ fprintf(stderr,"could not connect to jack!\n no playback/recording possible."); sleep (2); exit (0); } /* create 3 players of 10sec each: */ for (i = 0;i < 1; i++){ buf = buffer_new(bufferindexcounter++,jack_info->samplerate); buffer_set_channels(buf,2); buffer_lock(buf); buffer_resize (buf, jack_info->samplerate * 60 ); /* one minute size */ buf->status = BUFFER_STATUS_READY; buffer_unlock(buf); speciallist_append(buffer_list,buf); looper_data = looperdata_new(buf, jack_info->samplerate, bufferindexcounter); reset_looperdata (looper_data, jack_info); speciallist_append(looperdatalist,(void*)looper_data); } ossmixer_setlevel_line(0); create_settings(buf, jack_info); looper_data = speciallist_get_first(looperdatalist); while (looper_data){ looper_data->isrecording = 1; looper_data = speciallist_get_next(looperdatalist,looper_data); } while(1){ /* check_buffer_list(buffer_list);*/ #if 0 gettimeofday(&ts, NULL); ta = (double)ts.tv_sec * 1000000.0 + (double)ts.tv_usec; if (ta > tb + mintimediff){ shuttle_pollall(shuttle, looperdatalist, jack_info); tb = ta; } #endif shuttle_pollall (shuttle, looperdatalist, jack_info); serialio_pollall (serialio, looperdatalist); tranzport_pollall (tranzport, looperdatalist, jack_info); if (alive && !jack_info->alive){ alive = jack_info->alive; if (tranzport) set_lcd (tranzport," EXITING ",0," (jack error) ",0,10); fprintf(stderr,"jack kicked us out.\n restarting.\n"); ossmixer_setlevel_line(startup_linelevel); exit (0); } if (jack_info->xruns != lastxruns){ lastxruns = jack_info->xruns; if (tranzport) set_lcd (tranzport," X-RUN ",0,NULL,0,10); fprintf(stderr,"XRUN! [%ld xruns total]\n",lastxruns); } tv.tv_sec = 0; tv.tv_usec = 30000; /*was 30000 */ if (!tranzport) select(0, NULL, NULL, NULL, &tv); } mixer_close(jack_info); ossmixer_setlevel_line(startup_linelevel); printf ("bye\n"); return 0; } kluppe-0.6.14/src/frontend/klopfer/Makefile0000644000175000017500000000050110417446405020125 0ustar dieterdieterSOURCES = klopfer.c TARGETS = $(SOURCES:.c=.o) klopfer: klopfer.o $(CC) $(CFLAGS) ../../common/*.o klopfer.o -o klopfer -ljack -lsndfile -lasound -lusb -llo .c.o: $(CC) $(CFLAGS) -c -o $@ $*.c install: klopfer install -m 755 klopfer $(BIN_DIR) install -m 644 klopfer.png $(PIXMAPS_DIR) clean: rm -f *.o klopfer kluppe-0.6.14/src/frontend/kluppe/0002755000175000017500000000000011171364301016321 5ustar dieterdieterkluppe-0.6.14/src/frontend/kluppe/kluppe.xpm0000644000175000017500000000772510423110776020364 0ustar dieterdieter/* XPM */ static char *kluppe[] = { /* columns rows colors chars-per-pixel */ "32 32 111 2", " c #00003E", ". c #00003F", "X c #1D0032", "o c #1D0033", "O c #1D0034", "+ c #26003B", "@ c #000040", "# c #040047", "$ c #040048", "% c #0B0045", "& c #0A0046", "* c #0F004D", "= c #2B0055", "- c #2A0056", "; c #2C0055", ": c #2E005B", "> c #3F004E", ", c #4D0079", "< c #4E0079", "1 c #53007A", "2 c #5F007B", "3 c #71005D", "4 c #71005E", "5 c #730061", "6 c #760069", "7 c #720079", "8 c #730079", "9 c #750078", "0 c #7A007E", "q c #7D007B", "w c #7E007E", "e c #7E007F", "r c #7F007E", "t c #7F007F", "y c #7A0083", "u c #7B0082", "i c #7C0081", "p c #7D0080", "a c #7C0082", "s c #7F0080", "d c #7F0081", "f c #9E005F", "g c #82007B", "h c #83007A", "j c #80007D", "k c #80007F", "l c #840079", "z c #850078", "x c #8A0073", "c c #8B0072", "v c #880075", "b c #890074", "n c #8C0071", "m c #8D0070", "M c #8C0072", "N c #8E0070", "B c #970066", "V c #92006B", "C c #93006A", "Z c #9B0062", "A c #A70056", "S c #A70057", "D c #A2005B", "F c #A2005C", "G c #A50058", "H c #AB0052", "J c #A80055", "K c #A80056", "L c #AA0054", "P c #AC0051", "I c #AC0052", "U c #B70046", "Y c #B70047", "T c #B3004A", "R c #B1004C", "E c #B1004D", "W c #B80045", "Q c #B90044", "! c #BE0040", "~ c #DF001F", "^ c #C0003D", "/ c #C50038", "( c #C50039", ") c #CB0033", "_ c #C80036", "` c #D60027", "' c #D70026", "] c #D3002A", "[ c #D3002B", "{ c #D0002E", "} c #D60028", "| c #DB0023", " . c #D80026", ".. c #DC0022", "X. c #EF000E", "o. c #EF000F", "O. c #E4001A", "+. c #E90015", "@. c #ED0011", "#. c #EE0010", "$. c #F3000B", "%. c #F1000C", "&. c #F1000D", "*. c #F0000E", "=. c #F50009", "-. c #F4000A", ";. c #FB0003", ":. c #F90005", ">. c #FA0004", ",. c red", "<. c None", /* pixels */ "<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.", "<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.", "<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.", "<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.", "<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.", "<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.", "<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.", "<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.", "<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.", "<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.", "<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.", "<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.", "<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.", "<.<.<.e b m m x x x x x x x x x x x x x x x x x x x x b m l <.<.", "<.<.<.F o.` ( O.-.$.$.$.$.$.$.$.$.$.-.$.$.$.$.$.$.$.-.%.) B <.<.", "<.<.<.[ ~ m <.F %.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.;.-.| S h <.<.<.", "<.<.<._ C <.<.<.R ,.,.,.,.,.,.,.,.;.} o.,.,.%.[ U x v <.<.<.<.<.", "<.<.<.f v <.<.<.V U Y Y Y Y Y U Y R e F U Y F <.<.<.<.<.<.<.<.<.", "<.<.<.! x <.<.<.G %.%.#.%.#.#.#.%.+.R ' %.%.` H Z <.<.<.<.<.<.<.", "<.<.<.{ ^ e <.x ' ,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.o.[ Q v e <.<.<.", "<.<.<.Q :.( H | ,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.;.o.T S h <.", "<.<.<.h G P P P P P H H H H H H H H H H H H H H H H H P P H h <.", "<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.", "<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.", "<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.", "<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.", "<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.", "<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.", "<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.", "<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.", "<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.", "<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<." }; kluppe-0.6.14/src/frontend/kluppe/customcurve.c0000644000175000017500000001465110247332465021062 0ustar dieterdieter#include #include #include #include #include #include #include "customcurve.h" #include "../../common/looperdata.h" #define WIDTH 320 #define HEIGHT 240 void customcurve_update(GtkWidget* curve, looper_data_t* looperdata){ looperdata_lock(looperdata); gtk_curve_get_vector ((GtkCurve*)curve, looperdata->cm_size,looperdata->customplaymode); looperdata_unlock(looperdata); } GtkWidget* customcurvedialog_get_curve(GtkWidget* dialog){ return g_object_get_data (G_OBJECT (dialog),"curve"); } static void menu_callback(GtkMenuItem* menuitem, GtkWidget* curve){ gtk_curve_set_curve_type((GtkCurve*)curve, GPOINTER_TO_UINT(g_object_get_data (G_OBJECT(menuitem),"mode"))); } static void normalize_callback(GtkMenuItem* menuitem, GtkWidget* curve){ int j = WIDTH; int i; float* buf; float f = 0.0f; buf = malloc(sizeof(float) * j); gtk_curve_get_vector ((GtkCurve*)curve, j, buf); for (i=0; i < j; i++){ f += 1.0f / *(buf + i); } f /= (float)j; for (i=0; i < j; i++){ *(buf + i) *= f; } gtk_curve_set_vector ((GtkCurve*)curve, j, buf); free(buf); } static void reset_customspeed_callback(GtkMenuItem* menuitem, GtkWidget* curve){ int j = WIDTH; int i; float* buf; buf = malloc(sizeof(float) * j); for (i=0; i < j; i++) *(buf + i) = 1.; gtk_curve_set_vector ((GtkCurve*)curve, j, buf); free(buf); } static void reset_custompos_callback(GtkMenuItem* menuitem, GtkWidget* curve){ int j = WIDTH; int i; float* buf; buf = malloc(sizeof(float) * j); for (i=0; i < j; i++) *(buf + i) = (float)i / (float)j * 4.999; /* bad magic number */ gtk_curve_set_vector ((GtkCurve*)curve, j, buf); gtk_curve_set_curve_type((GtkCurve*)curve,GTK_CURVE_TYPE_LINEAR); free(buf); } GtkWidget* customcurvedialog_new(GtkWidget* parent, looper_data_t* data, int id){ GtkWidget *label1; GtkWidget *customcurve; GtkWidget *dialog; GtkWidget *topmenu; GtkWidget *menu; GtkWidget *menu_items; GtkWidget *menubar; GSList *group = NULL; label1 = gtk_label_new ("custom curve"); customcurve = gtk_curve_new(); gtk_curve_set_range ((GtkCurve*)customcurve,0., WIDTH, data->cm_min, data->cm_max); gtk_widget_set_size_request (customcurve, WIDTH, HEIGHT); topmenu = gtk_menu_item_new_with_label ("drawing options"); menu = gtk_menu_new (); menu_items = gtk_radio_menu_item_new_with_label (group,"curve"); group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (menu_items)); g_object_set_data (G_OBJECT (menu_items), "mode",GUINT_TO_POINTER(GTK_CURVE_TYPE_SPLINE)); gtk_check_menu_item_set_active ((GtkCheckMenuItem*)menu_items,FALSE); g_signal_connect (G_OBJECT (menu_items), "activate", G_CALLBACK (menu_callback), (gpointer)customcurve); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_items); menu_items = gtk_radio_menu_item_new_with_label (group,"free"); group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (menu_items)); gtk_check_menu_item_set_active ((GtkCheckMenuItem*)menu_items,TRUE); g_object_set_data (G_OBJECT (menu_items), "mode",GUINT_TO_POINTER(GTK_CURVE_TYPE_FREE)); g_signal_connect (G_OBJECT (menu_items), "activate", G_CALLBACK (menu_callback), (gpointer)customcurve); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_items); menu_items = gtk_radio_menu_item_new_with_label (group,"linear"); group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (menu_items)); gtk_check_menu_item_set_active ((GtkCheckMenuItem*)menu_items,FALSE); g_object_set_data (G_OBJECT (menu_items), "mode",GUINT_TO_POINTER(GTK_CURVE_TYPE_LINEAR)); g_signal_connect (G_OBJECT (menu_items), "activate", G_CALLBACK (menu_callback), (gpointer)customcurve); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_items); menu_items = gtk_separator_menu_item_new(); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_items); menu_items = gtk_menu_item_new_with_label ("normalize"); g_signal_connect (G_OBJECT (menu_items), "activate", G_CALLBACK (normalize_callback), (gpointer)customcurve); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_items); menu_items = gtk_menu_item_new_with_label ("reset custom speed"); g_signal_connect (G_OBJECT (menu_items), "activate", G_CALLBACK (reset_customspeed_callback), (gpointer)customcurve); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_items); menu_items = gtk_menu_item_new_with_label ("reset custom position"); g_signal_connect (G_OBJECT (menu_items), "activate", G_CALLBACK (reset_custompos_callback), (gpointer)customcurve); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_items); gtk_menu_item_set_submenu (GTK_MENU_ITEM (topmenu), menu); menubar = gtk_menu_bar_new(); gtk_menu_shell_append(GTK_MENU_SHELL(menubar), topmenu); dialog = gtk_dialog_new_with_buttons ("drawing area for custom modes", (GtkWindow*)parent, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_OK, GTK_RESPONSE_OK, NULL); g_object_set_data (G_OBJECT (dialog),"curve",customcurve); gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox),label1); gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox),customcurve); gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox),menubar); gtk_widget_show_all (dialog); gtk_curve_set_vector (GTK_CURVE(customcurve), data->cm_size,data->customplaymode); if (!(data->playmode == LOOP_PLAYMODE_POSITION)) gtk_curve_set_curve_type((GtkCurve*)customcurve,GTK_CURVE_TYPE_FREE); else gtk_curve_set_curve_type((GtkCurve*)customcurve,GTK_CURVE_TYPE_LINEAR); gtk_window_set_modal ((GtkWindow*)dialog, FALSE); return (dialog); } kluppe-0.6.14/src/frontend/kluppe/kluppe2.png0000644000175000017500000000027410206501025020404 0ustar dieterdieter‰PNG  IHDR Rå¯ÉPLTEÿ\_÷òtRNS@æØfbKGDˆH pHYs  šœtIMEÕ (v%çO/IDAT×c¨ÿÿÿÃãÿÿ0üÿ¿¡áÿ††Ï Ì‹eÁê€:þJD‹Ç&aIEND®B`‚kluppe-0.6.14/src/frontend/kluppe/sfpreview.c0000644000175000017500000000251210207220765020501 0ustar dieterdieter#ifndef __SFPREVIEW_H__ #define __SFPREVIEW_H__ #include #include #include #include "sfpreview.h" void sfpreview_update(GtkFileChooser* filechooser, gpointer data){ GtkWidget *sfp = (GtkWidget*) data; SF_INFO* sfinfo = (SF_INFO*) malloc(sizeof(SF_INFO)); SNDFILE* sf = NULL; char *filename; char *txt = malloc(sizeof(char) * 256); filename = gtk_file_chooser_get_preview_filename(filechooser); if (filename) sf = sf_open (filename, SFM_READ, sfinfo); if (sf != NULL){ sprintf(txt,"%.1f seconds %s, %d hz", (float)((float)sfinfo->frames / (float)sfinfo->samplerate), (sfinfo->channels == 1) ? "mono" : "stereo", (int)sfinfo->samplerate); /* printf ("%s\n",txt); */ if (txt) gtk_label_set_label((GtkLabel*)sfp,txt); gtk_file_chooser_set_preview_widget_active ( filechooser,TRUE); sf_close(sf); }else{ gtk_label_set_label((GtkLabel*)sfp,"no info"); gtk_file_chooser_set_preview_widget_active ( filechooser,TRUE); } free(txt); } GtkWidget *sfpreview_new(){ GtkWidget *sfp = gtk_label_new ("no info"); gtk_label_set_angle((GtkLabel*)sfp,90); /* gtk_label_set_ellipsize((GtkLabel*)sfp,PANGO_ELLIPSIZE_MIDDLE);*/ gtk_label_set_use_underline ((GtkLabel*)sfp,FALSE); gtk_label_set_single_line_mode ((GtkLabel*)sfp,FALSE); gtk_widget_show(sfp); return sfp; } #endif kluppe-0.6.14/src/frontend/kluppe/alphatrack_callback.c0000644000175000017500000004765311037704360022434 0ustar dieterdieter#include #include "alphatrack_callback.h" #include "looper.h" looper_gui_t *get_next_rc_looper(looper_list_t *ll, looper_gui_t *looper){ GList *tmpptr, *tp2 = NULL; tmpptr = g_list_first (ll->listptr); if (!looper){ if (((looper_gui_t*)tmpptr->data)->remote_controlled) return (looper_gui_t*)tmpptr->data; } else { while (tmpptr){ if ((looper_gui_t*)tmpptr->data == looper) tp2 = tmpptr; tmpptr = g_list_next(tmpptr); } tmpptr = tp2; } while ((tmpptr = g_list_next(tmpptr))){ if (((looper_gui_t*)tmpptr->data)->remote_controlled) return (looper_gui_t*)tmpptr->data; } return NULL; } looper_gui_t *get_prev_rc_looper(looper_list_t *ll, looper_gui_t *looper){ GList *tmpptr, *tp2 = NULL; tmpptr = g_list_first (ll->listptr); while (tmpptr){ if ((looper_gui_t*)tmpptr->data == looper) break; if (((looper_gui_t*)tmpptr->data)->remote_controlled) tp2 = tmpptr; tmpptr = g_list_next(tmpptr); } if (!tp2) return NULL; return (looper_gui_t*)tp2->data; } looper_gui_t *get_next_looper(looper_list_t *ll, looper_gui_t *looper){ GList *tmpptr, *tp2 = NULL; tmpptr = g_list_first (ll->listptr); if (!tmpptr) return NULL; if (!looper) return (looper_gui_t*)tmpptr->data; while (tmpptr){ if ((looper_gui_t*)tmpptr->data == looper) tp2 = tmpptr; tmpptr = g_list_next(tmpptr); } tmpptr = tp2; tmpptr = g_list_next(tmpptr); if (!tmpptr) return NULL; return (looper_gui_t*)tmpptr->data; } looper_gui_t *get_prev_looper(looper_list_t *ll, looper_gui_t *looper){ GList *tmpptr, *tp2 = g_list_last(ll->listptr); tmpptr = g_list_first (ll->listptr); if (!tmpptr) return NULL; if (!looper) return (looper_gui_t*)(g_list_last(ll->listptr)->data); while (tmpptr){ if ((looper_gui_t*)tmpptr->data == looper) break; tp2 = tmpptr; tmpptr = g_list_next(tmpptr); } return (looper_gui_t*)tp2->data; } void setlcd_float(looper_gui_t *looper, const char *format, float f, int row){ char *txt = calloc (20, sizeof(char)); snprintf (txt, 17, format, f); alphatrack_write_lcd (looper->alphatrack,txt,0,row); free (txt); } void setlcd_int(looper_gui_t *looper, const char *format, int i, int row){ char *txt = calloc (20, sizeof(char)); snprintf (txt, 17, format, i); alphatrack_write_lcd (looper->alphatrack,txt,0,row); free (txt); } void init_alphatrack(looper_gui_t *looper){ float f; if (!looper) return; f = gtk_range_get_value(GTK_RANGE(looper->volslider)); if (f < -47.) alphatrack_write_lcd(looper->alphatrack, "Volume off ... ",0,1); else setlcd_float(looper, "Volume: %3.2fdb ", f, 1); f += 48.; f *= (1023./ 66.); alphatrack_set_faderpos(looper->alphatrack, (int)f); alphatrack_clear_leds(looper->alphatrack); if (gtk_toggle_button_get_active((GtkToggleButton*)looper->playbutton)) alphatrack_set_led(looper->alphatrack, ALPHATRACK_LED_READ, 1); else alphatrack_set_led(looper->alphatrack, ALPHATRACK_LED_READ, 0); if (gtk_toggle_button_get_active((GtkToggleButton*)looper->recbutton)) alphatrack_set_led(looper->alphatrack, ALPHATRACK_LED_WRITE, 1); else alphatrack_set_led(looper->alphatrack, ALPHATRACK_LED_WRITE, 0); if (looper->data){ if (looper->data->buf){ alphatrack_write_lcd (looper->alphatrack, looper->data->buf->shortname,0,0); } } } void alphatrack_event_callback(alphatrack_event_t *ev, void *ptr){ looper_list_t *ll = (looper_list_t*)ptr; looper_gui_t *looper = NULL; float f = 0.; /* printf ("callback event: %010Lx (%010Lx)\n", ev->mask, ev->states); */ if ((ev->mask & ALPHATRACK_BUTTON_TRACKR) && (ev->states & ALPHATRACK_BUTTON_TRACKR)){ looper = get_next_rc_looper(ll,NULL); if (looper){ /* remove rc_flag and search for next looper in the list */ g_mutex_lock(ll->listmutex); looper_set_remote_controlled(looper,0); g_mutex_unlock(ll->listmutex); looper = get_next_looper(ll,looper); if (looper){ g_mutex_lock(ll->listmutex); looper_set_remote_controlled(looper,1); g_mutex_unlock(ll->listmutex); }else{ /* no next looper - try first one */ looper = get_next_looper(ll,NULL); if (looper){ g_mutex_lock(ll->listmutex); looper_set_remote_controlled(looper,1); g_mutex_unlock(ll->listmutex); } } } else { looper = get_next_looper(ll,NULL); g_mutex_lock(ll->listmutex); if (looper)looper_set_remote_controlled(looper,1); g_mutex_unlock(ll->listmutex); } if (looper) init_alphatrack(looper); } else if ((ev->mask & ALPHATRACK_BUTTON_TRACKL) && (ev->states & ALPHATRACK_BUTTON_TRACKL)){ looper = get_prev_rc_looper(ll,NULL); if (looper){ /* remove rc_flag and search for next looper in the list */ g_mutex_lock(ll->listmutex); looper_set_remote_controlled(looper,0); g_mutex_unlock(ll->listmutex); looper = get_prev_looper(ll,looper); if (looper){ g_mutex_lock(ll->listmutex); looper_set_remote_controlled(looper,1); g_mutex_unlock(ll->listmutex); }else{ /* no next looper - try last one */ looper = get_prev_looper(ll,NULL); if (looper){ g_mutex_lock(ll->listmutex); looper_set_remote_controlled(looper,1); g_mutex_unlock(ll->listmutex); } } } else { looper = get_prev_looper(ll,NULL); g_mutex_lock(ll->listmutex); if (looper)looper_set_remote_controlled(looper,1); g_mutex_unlock(ll->listmutex); } if (looper) init_alphatrack(looper); } g_mutex_lock(ll->listmutex); /* encoders: */ if (ev->encoderdelta_l){ looper = NULL; while ((looper = get_next_rc_looper(ll, looper))){ looper->encoderdelta_l += ev->encoderdelta_l; setlcd_int(looper, "select Grains:%2d", gtk_range_get_value ((GtkRange*)looper->ngrainslider) + looper->encoderdelta_l, 1); } } if (ev->states & ALPHATRACK_BUTTON_ENCODER_L){ looper = NULL; while ((looper = get_next_rc_looper(ll, looper))){ /* if (ev->leds[ALPHATRACK_LED_SHIFT]){*/ if (ev->states & ALPHATRACK_BUTTON_FLIP){ gtk_range_set_value ((GtkRange*)looper->ngrainslider, 0); looper->encoderdelta_l = 0; setlcd_int(looper, "set Grains: %02d", 0, 1); } else if (looper->encoderdelta_l){ gtk_range_set_value ((GtkRange*)looper->ngrainslider, gtk_range_get_value ((GtkRange*)looper->ngrainslider) + looper->encoderdelta_l); looper->encoderdelta_l = 0; setlcd_int(looper, "set Grains: %02d", gtk_range_get_value ((GtkRange*)looper->ngrainslider) + looper->encoderdelta_l, 1); } } } if (ev->encoderdelta_m){ looper = NULL; while ((looper = get_next_rc_looper(ll, looper))){ looper->encoderdelta_m += ev->encoderdelta_m * ev->encoderdelta_m * ev->encoderdelta_m; setlcd_int(looper, "sel Graindns:%03d", gtk_spin_button_get_value ((GtkSpinButton*)looper->densityspin) + looper->encoderdelta_m,1); } } if (ev->states & ALPHATRACK_BUTTON_ENCODER_M){ looper = NULL; while ((looper = get_next_rc_looper(ll, looper))){ /* if (ev->leds[ALPHATRACK_LED_SHIFT]){*/ if (ev->states & ALPHATRACK_BUTTON_FLIP){ gtk_spin_button_set_value((GtkSpinButton*)looper->densityspin, 100.0); looper->encoderdelta_m = 0; setlcd_int(looper, "Graindensity:%03d ", 100, 1); } else if (looper->encoderdelta_m){ gtk_spin_button_set_value((GtkSpinButton*)looper->densityspin, gtk_spin_button_get_value ((GtkSpinButton*)looper->densityspin) + looper->encoderdelta_m); looper->encoderdelta_m = 0; setlcd_int(looper, "Grainsdensty:%03d ", gtk_spin_button_get_value ((GtkSpinButton*)looper->densityspin),1); } } } if (ev->encoderdelta_r){ looper = NULL; while ((looper = get_next_rc_looper(ll, looper))){ if (alphatrack_get_led(looper->alphatrack, ALPHATRACK_LED_AUTO)){ looper->encoderdelta_r += ev->encoderdelta_r * ev->encoderdelta_r * ev->encoderdelta_r; setlcd_float(looper, "sel GrnSpd:%03.3f", looperdata_get_mingrainspeed(looper->data) * powf(1.011, (float)looper->encoderdelta_r),1); } else { looper->encoderdelta_r += ev->encoderdelta_r * ev->encoderdelta_r * ev->encoderdelta_r; setlcd_float(looper, "sel Sped:%3.3f ", (float)gtk_spin_button_get_value ((GtkSpinButton*)looper->speedspin) * powf(1.011, (float)looper->encoderdelta_r), 1); } } } if (ev->states & ALPHATRACK_BUTTON_ENCODER_R){ looper = NULL; while ((looper = get_next_rc_looper(ll, looper))){ /* if (ev->leds[ALPHATRACK_LED_SHIFT]){*/ if (alphatrack_get_led(looper->alphatrack, ALPHATRACK_LED_AUTO)){ if (ev->states & ALPHATRACK_BUTTON_FLIP){ /* reset grainspeed */ if (looper->data){ looperdata_lock(looper->data); looperdata_set_mingrainspeed(looper->data, 1.); looperdata_set_maxgrainspeed(looper->data, 1.); looperdata_unlock(looper->data); setlcd_float(looper, "Grainspeed:%03.3f",1.0,1); } looper->encoderdelta_r = 0; } else if (looper->encoderdelta_r) { if (looper->data){ looperdata_lock(looper->data); looperdata_set_mingrainspeed(looper->data, looperdata_get_mingrainspeed(looper->data) * powf(1.011, (float)looper->encoderdelta_r)); looperdata_set_maxgrainspeed(looper->data, looperdata_get_mingrainspeed(looper->data) * powf(1.011, (float)looper->encoderdelta_r)); looperdata_unlock(looper->data); setlcd_float(looper, "Grainspeed:%03.3f", looperdata_get_mingrainspeed(looper->data),1); } looper->encoderdelta_r = 0; } } else { if (ev->states & ALPHATRACK_BUTTON_FLIP){ gtk_spin_button_set_value((GtkSpinButton*)looper->speedspin, 1.0); looper->encoderdelta_r = 0; setlcd_float(looper, "Speed: %03.3f ", 1.0, 1); } else if (looper->encoderdelta_r){ gtk_spin_button_set_value((GtkSpinButton*)looper->speedspin, (float)gtk_spin_button_get_value ((GtkSpinButton*)looper->speedspin) * powf(1.011, (float)looper->encoderdelta_r)); looper->encoderdelta_r = 0; setlcd_float(looper, "Speed: %03.3f ", (float)gtk_spin_button_get_value ((GtkSpinButton*)looper->speedspin) * powf(1.011, (float)looper->encoderdelta_r), 1); } } } } /* touchstrip and buttons: */ if ((ev->mask & ALPHATRACK_CONTACT_TOUCHSTRIP_1) && (ev->states & ALPHATRACK_CONTACT_TOUCHSTRIP_1)){ looper = NULL; while ((looper = get_next_rc_looper(ll, looper))){ if (!ev->leds[ALPHATRACK_LED_SHIFT]){ /* semitones pitch / speed change: */ double f = (float)((ev->touchpos / 64) - 2); if (f >= 0.) f += 1.; f = pow(2.,f / 12.); if (looper->data){ looperdata_lock(looper->data); f *= (float)looperdata_get_speed(looper->data); looperdata_set_speed(looper->data,(double)f); looperdata_unlock(looper->data); setlcd_float(looper, "Speed: %3.3f ",(float)f,1); looper->dirty = 1; } } else { /* just store the touch position */ looper->touchstrippos = ev->touchpos /* + 1*/; if (looper->data){ looper->touchstripposval = looperdata_get_loopstart(looper->data); looper->touchstripposrange = looperdata_get_loopend(looper->data) - looper->touchstripposval; } } } } if ((ev->mask & ALPHATRACK_CONTACT_TOUCHSTRIP_2) && (ev->states & ALPHATRACK_CONTACT_TOUCHSTRIP_2)){ looper = NULL; while ((looper = get_next_rc_looper(ll, looper))){ if (!ev->leds[ALPHATRACK_LED_SHIFT]){ /* full tones pitch / speed change */ double f = (float)((ev->touchpos / 64) - 2); if (f >= 0.) f += 1.; f = pow(2.,f / 6.); if (looper->data){ looperdata_lock(looper->data); f *= (float)looperdata_get_speed(looper->data); looperdata_set_speed(looper->data,(double)f); looperdata_unlock(looper->data); setlcd_float(looper, "Speed: %3.3f ",(float)f,1); looper->dirty = 1; } } else { /* just store the touch position */ looper->touchstrippos = ev->touchpos /* + 1*/; if (looper->data){ looper->touchstripposval = looperdata_get_loopstart(looper->data); looper->touchstripposrange = looperdata_get_loopend(looper->data) - looper->touchstripposval; } } } } if ((ev->mask & ALPHATRACK_POS_TOUCHSTRIP) && ev->leds[ALPHATRACK_LED_SHIFT]){ /* change loop */ looper = NULL; while ((looper = get_next_rc_looper(ll, looper))){ if (ev->states & ALPHATRACK_CONTACT_TOUCHSTRIP_1){ /* set loopstart and keep the length intact */ float f = ((float)ev->touchpos - (float)looper->touchstrippos) / 256.; f = (float)looper->touchstripposval + (float)(looper->touchstripposrange * f); if (looper->data){ looperdata_lock(looper->data); looperdata_set_loopend(looper->data, (long)(f + looper->touchstripposrange)); looperdata_set_loopstart(looper->data,(long)f); if (looper->data->linkrec2play) looperdata_set_recstart(looper->data, looperdata_get_loopstart(looper->data)); looperdata_set_recend(looper->data, looperdata_get_loopend(looper->data)); looperdata_unlock(looper->data); looper->dirty = 1; } } else if (ev->states & ALPHATRACK_CONTACT_TOUCHSTRIP_2){ /* set the length */ float f = ((float)ev->touchpos - (float)looper->touchstrippos) / 256.; f = (float)looper->touchstripposrange + (float)(looper->touchstripposrange * f); if (looper->data){ looperdata_lock(looper->data); looperdata_set_loopend(looper->data,(long)f + looperdata_get_loopstart(looper->data)); if (looper->data->linkrec2play) looperdata_set_recend(looper->data, looperdata_get_loopend(looper->data)); looperdata_unlock(looper->data); looper->dirty = 1; } } /*else printf ("strange: touch without finger info\n");*/ } } if ((ev->mask & ALPHATRACK_BUTTON_SHIFT) && (ev->states & ALPHATRACK_BUTTON_SHIFT)){ looper = NULL; while ((looper = get_next_rc_looper(ll, looper))){ if (ev->leds[ALPHATRACK_LED_SHIFT]) alphatrack_set_led(looper->alphatrack, ALPHATRACK_LED_SHIFT, 0); else alphatrack_set_led(looper->alphatrack, ALPHATRACK_LED_SHIFT, 1); } } if ((ev->mask & ALPHATRACK_BUTTON_PLAY) && (ev->states & ALPHATRACK_BUTTON_PLAY)){ looper = NULL; while ((looper = get_next_rc_looper(ll, looper))){ if (gtk_toggle_button_get_active((GtkToggleButton*)looper->playbutton)) { gtk_toggle_button_set_active((GtkToggleButton*)looper->playbutton, FALSE); alphatrack_set_led(looper->alphatrack, ALPHATRACK_LED_READ, 0); } else { gtk_toggle_button_set_active((GtkToggleButton*)looper->playbutton, TRUE); alphatrack_set_led(looper->alphatrack, ALPHATRACK_LED_READ, 1); } } } if ((ev->mask & ALPHATRACK_BUTTON_RECORD) && (ev->states & ALPHATRACK_BUTTON_RECORD)){ looper = NULL; while ((looper = get_next_rc_looper(ll, looper))){ if (gtk_toggle_button_get_active((GtkToggleButton*)looper->recbutton)){ gtk_toggle_button_set_active((GtkToggleButton*)looper->recbutton, FALSE); alphatrack_set_led(looper->alphatrack, ALPHATRACK_LED_WRITE, 0); } else { gtk_toggle_button_set_active((GtkToggleButton*)looper->recbutton, TRUE); alphatrack_set_led(looper->alphatrack, ALPHATRACK_LED_WRITE, 1); } } } if (ev->mask & ALPHATRACK_BUTTON_FLIP){ looper = NULL; while ((looper = get_next_rc_looper(ll, looper))){ if (ev->states & ALPHATRACK_BUTTON_FLIP) alphatrack_set_led(looper->alphatrack, ALPHATRACK_LED_FLIP, 1); else alphatrack_set_led(looper->alphatrack, ALPHATRACK_LED_FLIP, 0); } } if ((ev->mask & ALPHATRACK_BUTTON_AUTO) && (ev->states & ALPHATRACK_BUTTON_AUTO)){ looper = NULL; while ((looper = get_next_rc_looper(ll, looper))){ if (alphatrack_get_led(looper->alphatrack, ALPHATRACK_LED_AUTO)) alphatrack_set_led(looper->alphatrack, ALPHATRACK_LED_AUTO, 0); else alphatrack_set_led(looper->alphatrack, ALPHATRACK_LED_AUTO, 1); } } /* fader: */ if (ev->mask & ALPHATRACK_POS_FADER){ looper = NULL; while ((looper = get_next_rc_looper(ll, looper))){ f = ((float)ev->faderpos / 1023. * 66.) - 48.; if (looper->data){ looperdata_lock(looper->data); if (f > -47.0) { setlcd_float(looper, "Volume: %3.2fdb ",f,1); looperdata_set_vol(looper->data, powf(10.0f, f * 0.05f)); } else { alphatrack_write_lcd(looper->alphatrack, "Volume off ... ",0,1); looperdata_set_vol(looper->data, 0.); } looperdata_unlock(looper->data); looper->dirty = 1; } } } g_mutex_unlock(ll->listmutex); } kluppe-0.6.14/src/frontend/kluppe/griddialog.c0000644000175000017500000001112310273677402020601 0ustar dieterdieter#include #include #include #include #include #include "griddialog.h" #include "gtkloopview.h" static void bpm_callback(GtkWidget* bpmspin, gpointer data){ GtkLoopview *loopview = GTK_LOOPVIEW(data); GtkWidget* offsetspin = g_object_get_data (G_OBJECT(bpmspin),"offsetspin"); gdouble save; gtk_loopview_set_bpm(loopview,(double)gtk_spin_button_get_value ((GtkSpinButton*)bpmspin)); save = gtk_spin_button_get_value(GTK_SPIN_BUTTON(offsetspin)); gtk_spin_button_set_range(GTK_SPIN_BUTTON(offsetspin),0,(gdouble)(gtk_loopview_get_gridwidth(loopview))); gtk_spin_button_set_value(GTK_SPIN_BUTTON(offsetspin),save); /* LATER: set maximum value for offset */ } static void bpb_callback(GtkWidget* bpbspin, gpointer data){ GtkLoopview *loopview = GTK_LOOPVIEW(data); gtk_loopview_set_bpb(loopview,(double)gtk_spin_button_get_value ((GtkSpinButton*)bpbspin)); } static void offset_callback(GtkWidget* offsetspin, gpointer data){ GtkLoopview *loopview = GTK_LOOPVIEW(data); gtk_loopview_set_gridoffset(loopview,(guint32)gtk_spin_button_get_value ((GtkSpinButton*)offsetspin)); } void griddialog_new(GtkWidget* parent, GtkLoopview *loopview){ GtkAdjustment *adj; GtkTooltips *tooltips; GtkWidget *dialog; GtkWidget *bpmlabel; GtkWidget *bpblabel; GtkWidget *offsetlabel; /* GtkWidget *lengthlabel;*/ GtkWidget *bpmbox; GtkWidget *bpbbox; GtkWidget *offsetbox; GtkWidget *mainbox; GtkWidget *bpmspin; /* spinbutton */ GtkWidget *bpbspin; /* spinbutton */ GtkWidget *offsetspin; /* spinbutton */ gint result; tooltips = gtk_tooltips_new (); bpmlabel = gtk_label_new ("beats per minute"); bpblabel = gtk_label_new ("beats per bar"); offsetlabel = gtk_label_new ("offset (in samples)"); /* gtk_tooltips_set_tip(tooltips,bpmlabel,"beats per minute",NULL);*/ adj = (GtkAdjustment *) gtk_adjustment_new (gtk_loopview_get_bpm(GTK_LOOPVIEW(loopview)), 0.01, 1720.0, .1, 1, 4); bpmspin = gtk_spin_button_new (adj, 1, 2); adj = (GtkAdjustment *) gtk_adjustment_new (gtk_loopview_get_bpb(GTK_LOOPVIEW(loopview)), 0.0, 64, 1, 1, 2); bpbspin = gtk_spin_button_new (adj, 1, 0); adj = (GtkAdjustment *) gtk_adjustment_new (gtk_loopview_get_gridoffset(GTK_LOOPVIEW(loopview)), 0.0, gtk_loopview_get_gridwidth(GTK_LOOPVIEW(loopview)), 1, 1000, 10000); offsetspin = gtk_spin_button_new (adj, 1, 0); /* lengthlabel = gtk_label_new ("length per beat");*/ g_object_set_data (G_OBJECT (bpbspin),"bpmspin",bpmspin); g_object_set_data (G_OBJECT (bpmspin),"bpbspin",bpbspin); g_object_set_data (G_OBJECT (bpbspin),"offsetspin",offsetspin); g_object_set_data (G_OBJECT (bpmspin),"offsetspin",offsetspin); /* g_object_set_data (G_OBJECT (bpbspin),"lengthlabel",lengthlabel);*/ /* g_object_set_data (G_OBJECT (bpmspin),"lengthlabel",lengthlabel);*/ g_signal_connect (G_OBJECT (bpmspin), "value_changed", G_CALLBACK (bpm_callback), (gpointer) loopview); g_signal_connect (G_OBJECT (bpbspin), "value_changed", G_CALLBACK (bpb_callback), (gpointer) loopview); g_signal_connect (G_OBJECT (offsetspin), "value_changed", G_CALLBACK (offset_callback), (gpointer) loopview); bpmbox = gtk_hbox_new(TRUE,10); bpbbox = gtk_hbox_new(TRUE,10); offsetbox = gtk_hbox_new(TRUE,10); gtk_box_pack_start (GTK_BOX (bpmbox),bpmlabel, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (bpmbox),bpmspin, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (bpbbox),bpblabel, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (bpbbox),bpbspin, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (offsetbox),offsetlabel, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (offsetbox),offsetspin, TRUE, TRUE, 0); mainbox = gtk_vbox_new (FALSE,5); gtk_box_pack_start (GTK_BOX(mainbox), bpmbox, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX(mainbox), bpbbox, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX(mainbox), offsetbox, FALSE, FALSE, 0); /* gtk_box_pack_start (GTK_BOX(mainbox), lengthlabel, FALSE, FALSE, 0);*/ dialog = gtk_dialog_new_with_buttons ("settings for beat grid", (GtkWindow*)parent, /*GTK_DIALOG_MODAL |*/ GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, NULL); gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox),mainbox); gtk_widget_show_all (dialog); result = gtk_dialog_run (GTK_DIALOG (dialog)); gtk_widget_destroy (dialog); } kluppe-0.6.14/src/frontend/kluppe/kluppe.png0000644000175000017500000000051110206501025020314 0ustar dieterdieter‰PNG  IHDR00Wù‡bKGDB{ Ì pHYs  šœtIMEÔ çÁ…LÖIDATxÚí™A E? ‡ñÞÂW¡žÌÄ…÷ð]è¢1iH§"¥¤o¶ üù&¤N:ë_qÑK']U2î’zJ$I¨.( 4ÞúÐëöÞcÁ½‚[˜?]P*.ü' Å‹¬$¥ _Ú×§ Ë*‘Ò(_Ãs ÈU·ùIl⥎äZ¨„[È·n¾, }“Í%Úú*]ƒéR:VcŒv¶÷5ñ^'q¬ ïÿ&æ€|È%DÜ9Ƨ·IEND®B`‚kluppe-0.6.14/src/frontend/kluppe/threshdialog.c0000644000175000017500000001102410575505406021150 0ustar dieterdieter#include #include #include #include #include #include "threshdialog.h" #include "gtkloopview.h" static void low_callback(GtkWidget* lowspin, gpointer data){ looper_data_t *looperdata = (looper_data_t*)data; GtkWidget* highspin = g_object_get_data (G_OBJECT(lowspin),"highspin"); looperdata_lock(looperdata); looperdata_set_low_threshold(looperdata, (double)gtk_spin_button_get_value ((GtkSpinButton*)lowspin)); looperdata_unlock(looperdata); if (looperdata_get_low_threshold(looperdata) > looperdata_get_high_threshold(looperdata)){ gtk_spin_button_set_value ((GtkSpinButton*)highspin, looperdata_get_low_threshold(looperdata)); } } static void high_callback(GtkWidget* highspin, gpointer data){ looper_data_t *looperdata = (looper_data_t*)data; GtkWidget* lowspin = g_object_get_data (G_OBJECT(highspin),"lowspin"); looperdata_lock(looperdata); looperdata_set_high_threshold(looperdata, (double)gtk_spin_button_get_value ((GtkSpinButton*)highspin)); looperdata_unlock(looperdata); if (looperdata_get_low_threshold(looperdata) > looperdata_get_high_threshold(looperdata)){ gtk_spin_button_set_value ((GtkSpinButton*)lowspin, looperdata_get_high_threshold(looperdata)); } } static void size_callback(GtkWidget* sizespin, gpointer data){ looper_data_t *looperdata = (looper_data_t*)data; looperdata_lock(looperdata); looperdata_set_thresholdbuffersize(looperdata, (double)gtk_spin_button_get_value ((GtkSpinButton*)sizespin)); looperdata_unlock(looperdata); } void threshdialog_new(GtkWidget* parent, looper_data_t* looperdata){ GtkAdjustment *adj; GtkTooltips *tooltips; GtkWidget *dialog; GtkWidget *lowlabel; GtkWidget *highlabel; GtkWidget *sizelabel; GtkWidget *lowbox; GtkWidget *highbox; GtkWidget *sizebox; GtkWidget *mainbox; GtkWidget *lowspin; /* spinbutton */ GtkWidget *highspin; /* spinbutton */ GtkWidget *sizespin; /* spinbutton */ gint result; tooltips = gtk_tooltips_new (); lowlabel = gtk_label_new ("low threshold"); highlabel = gtk_label_new ("high threshold"); sizelabel = gtk_label_new ("buffer size (in samples)"); adj = (GtkAdjustment *) gtk_adjustment_new (looperdata_get_low_threshold(looperdata), 0., 1., .001, .01, .01); lowspin = gtk_spin_button_new (adj, .01, 3); adj = (GtkAdjustment *) gtk_adjustment_new (looperdata_get_high_threshold(looperdata), 0., 1., .001, .01, .01); highspin = gtk_spin_button_new (adj, .01, 3); adj = (GtkAdjustment *) gtk_adjustment_new (looperdata_get_thresholdbuffersize(looperdata), 64, 882000, 1, 1000, 100); sizespin = gtk_spin_button_new (adj, 1, 0); g_object_set_data (G_OBJECT (lowspin),"highspin",highspin); g_object_set_data (G_OBJECT (highspin),"lowspin",lowspin); g_signal_connect (G_OBJECT (lowspin), "value_changed", G_CALLBACK (low_callback), (gpointer) looperdata); g_signal_connect (G_OBJECT (highspin), "value_changed", G_CALLBACK (high_callback), (gpointer) looperdata); g_signal_connect (G_OBJECT (sizespin), "value_changed", G_CALLBACK (size_callback), (gpointer) looperdata); lowbox = gtk_hbox_new(TRUE,10); highbox = gtk_hbox_new(TRUE,10); sizebox = gtk_hbox_new(TRUE,10); gtk_box_pack_start (GTK_BOX (lowbox),lowlabel, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (lowbox),lowspin, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (highbox),highlabel, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (highbox),highspin, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (sizebox),sizelabel, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (sizebox),sizespin, TRUE, TRUE, 0); mainbox = gtk_vbox_new (FALSE,5); gtk_box_pack_start (GTK_BOX(mainbox), lowbox, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX(mainbox), highbox, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX(mainbox), sizebox, FALSE, FALSE, 0); dialog = gtk_dialog_new_with_buttons ("settings for automatic recording", (GtkWindow*)parent, /*GTK_DIALOG_MODAL |*/ GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, NULL); gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox),mainbox); gtk_widget_show_all (dialog); result = gtk_dialog_run (GTK_DIALOG (dialog)); gtk_widget_destroy (dialog); } kluppe-0.6.14/src/frontend/kluppe/kluppe.10000644000175000017500000000347310423142565017715 0ustar dieterdieter.\" Hey, EMACS: -*- nroff -*- .\" First parameter, NAME, should be all caps .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection .\" other parameters are allowed: see man(7), man(1) .TH KLUPPE 1 "May 3, 2004" .\" Please adjust this date whenever revising the manpage. .\" .\" Some roff macros, for reference: .\" .nh disable hyphenation .\" .hy enable hyphenation .\" .ad l left justify .\" .ad b justify to both left and right margins .\" .nf disable filling .\" .fi enable filling .\" .br insert line break .\" .sp insert n+1 empty lines .\" for manpage-specific macros, see man(7) .SH NAME kluppe \- loop-player and recorder designed for live use .SH SYNOPSIS .B kluppe .br .SH DESCRIPTION This manual page documents briefly the .B kluppe program, a graphical loop player and recorder. .PP To start using .B kluppe , first start the jackd server, then kluppe, and create a new looper. You can either start recording a new sound (using create a new buffer), or load a sound file. For each looper, select the buffer you want to use. .PP .\" TeX users may be more comfortable with the \fB\fP and .\" \fI\fP escape sequences to invode bold face and italics, .\" respectively. \fBkluppe\fP features include: .br - multiple files buffers, multiple 'loopers' tracks .br - direct (gui) access to all loopers .br - combined and per loop output ports for jack .br - different playmodes including "granular" .br .SH OPTIONS If a projectfile is given as startup argument, \fBkluppe\fP will try to open it. .SH SEE ALSO .B jackd (1) .br The program homepage is at .IR http://kluppe.klingt.org/ .SH AUTHOR This manual page was written by Paul Brossier , for the Debian project (but may be used by others). kluppe-0.6.14/src/frontend/kluppe/griddialog.h0000644000175000017500000000033310217770533020604 0ustar dieterdieter/* definitions for a looper */ #ifndef __GRIDDIALOG_H__ #define __GRIDDIALOG_H__ #include #include #include "gtkloopview.h" void griddialog_new(GtkWidget* parent, GtkLoopview *loopview); #endif kluppe-0.6.14/src/frontend/kluppe/alphatrack_callback.h0000644000175000017500000000035211033634307022421 0ustar dieterdieter/* definitions for a looper */ #ifndef __ALPHATRACK_CALLBACK_H__ #define __ALPHATRACK_CALLBACK_H__ #include "looper.h" #include "../../common/alphatrack.h" void alphatrack_event_callback(alphatrack_event_t *ev, void *ptr); #endif kluppe-0.6.14/src/frontend/kluppe/gtkloopview.c0000644000175000017500000017244011034663251021051 0ustar dieterdieter/************************************************* * a gtk widget for displaying of waveforms * * supporting a play selection, a rec-selection * * zooming and various mouse-actions * * written by dieb13 at klingt.org 2003/2004 * **************************************************/ #include #include #include #include #include #include #include #include #include "gtkloopview.h" #include "../../common/looperdata.h" #define SCROLL_DELAY_LENGTH 300 #define LOOPVIEW_DEFAULT_WIDTH 100 #define LOOPVIEW_DEFAULT_HEIGHT 50 static guint gtk_loopview_signals[LAST_SIGNAL] = { 0 }; static GtkWidgetClass *parent_class = NULL; /* forward declarations */ GtkType gtk_loopview_get_type (void); static void gtk_loopview_class_init (GtkLoopviewClass *class); static void gtk_loopview_init (GtkLoopview *loopview); GtkWidget* gtk_loopview_new (looper_data_t *looperdata); static void gtk_loopview_destroy (GtkObject *object); looper_data_t* gtk_loopview_get_looperdata (GtkLoopview *loopview); void gtk_loopview_set_update_policy (GtkLoopview *loopview,GtkUpdateType policy); void gtk_loopview_update_gplayposition (GtkLoopview *loopview); void gtk_loopview_set_looperdata (GtkLoopview *loopview,looper_data_t *looperdata); void gtk_loopview_update_waveform (GtkLoopview *loopview); /*void gtk_loopview_calc_peaks(GtkLoopview *loopview,guint32 startx, guint32 endx);*/ void gtk_loopview_copy_peaks(GtkLoopview *loopview, peakdata_t *pd); static void gtk_loopview_realize (GtkWidget *widget); static void gtk_loopview_size_request (GtkWidget *widget, GtkRequisition *requisition); static void gtk_loopview_size_allocate (GtkWidget *widget, GtkAllocation *allocation); static gboolean gtk_loopview_expose( GtkWidget *widget,GdkEventExpose *event ); static gboolean gtk_loopview_button_press( GtkWidget *widget, GdkEventButton *event ); static gboolean gtk_loopview_button_release( GtkWidget *widget, GdkEventButton *event ); static gboolean gtk_loopview_motion_notify( GtkWidget *widget,GdkEventMotion *event ); /* static gboolean gtk_loopview_key_release_notify( GtkWidget *widget,GdkEventKey *key); static gboolean gtk_loopview_key_press_notify( GtkWidget *widget,GdkEventKey *key); */ static gint gtk_loopview_focus_in (GtkWidget * widget, GdkEventFocus * event); static gint gtk_loopview_focus_out (GtkWidget * widget, GdkEventFocus * event); static gint gtk_loopview_enter_notify (GtkWidget *widget, GdkEventCrossing *event); static gint gtk_loopview_leave_notify (GtkWidget *widget, GdkEventCrossing *event); /*static gboolean gtk_loopview_timer( GtkLoopview *loopview );*/ static void gtk_loopview_update_mouse (GtkLoopview *loopview, gint x, gint y); /*static void gtk_loopview_update (GtkLoopview *loopview);*/ /* functions */ GtkType gtk_loopview_get_type () { static GtkType loopview_type = 0; if (!loopview_type){ static const GtkTypeInfo loopview_info = { "GtkLoopview", sizeof (GtkLoopview), sizeof (GtkLoopviewClass), (GtkClassInitFunc) gtk_loopview_class_init, (GtkObjectInitFunc) gtk_loopview_init, /* reserved_1 */ NULL, /* reserved_1 */ NULL, (GtkClassInitFunc) NULL }; loopview_type = gtk_type_unique (GTK_TYPE_WIDGET, &loopview_info); } return loopview_type; } static void gtk_loopview_class_init (GtkLoopviewClass *class){ GtkObjectClass *object_class; GtkWidgetClass *widget_class; object_class = (GtkObjectClass*) class; widget_class = (GtkWidgetClass*) class; parent_class = gtk_type_class (gtk_widget_get_type ()); object_class->destroy = gtk_loopview_destroy; widget_class->realize = gtk_loopview_realize; widget_class->expose_event = gtk_loopview_expose; widget_class->size_request = gtk_loopview_size_request; widget_class->size_allocate = gtk_loopview_size_allocate; widget_class->button_press_event = gtk_loopview_button_press; widget_class->button_release_event = gtk_loopview_button_release; widget_class->motion_notify_event = gtk_loopview_motion_notify; /* widget_class->key_release_event = gtk_loopview_key_release_notify; widget_class->key_press_event = gtk_loopview_key_press_notify; */ widget_class->focus_in_event = gtk_loopview_focus_in; widget_class->focus_out_event = gtk_loopview_focus_out; widget_class->enter_notify_event = gtk_loopview_enter_notify; widget_class->leave_notify_event = gtk_loopview_leave_notify; gtk_loopview_signals[SIG_LOOPBORDERS_CHANGED] = g_signal_new ("loopborders-changed", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_FIRST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, NULL); gtk_loopview_signals[SIG_RECBORDERS_CHANGED] = g_signal_new ("recborders-changed", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_FIRST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, NULL); gtk_loopview_signals[SIG_ZOOMBORDERS_CHANGED] = g_signal_new ("zoomborders-changed", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_FIRST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, NULL); gtk_loopview_signals[SIG_SPEED_CHANGED] = g_signal_new ("speed-changed", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_FIRST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, NULL); class->loopborders_changed = NULL; } static void gtk_loopview_init (GtkLoopview *loopview) { loopview->button = 0; loopview->policy = GTK_UPDATE_CONTINUOUS; loopview->timer = 0; loopview->suspended = FALSE; loopview->peakview = NULL; loopview->looperdata = looperdata_new(NULL,44100, 0); /* loopview->buffer_group = 0;*/ loopview->Lmin = NULL; loopview->Rmin = NULL; loopview->Lmax = NULL; loopview->Rmax = NULL; loopview->npeaks = 0; loopview->lastnup = 0; loopview->width = 0; loopview->height = 0; loopview->Lmid = 0; loopview->Rmid = 0; loopview->Hmax = 0; loopview->zoomstart = 0; loopview->zoomend = 0; loopview->gzoomstart = 0; loopview->gzoomend = 0; loopview->gloopstart = 0; loopview->gloopend = 0; loopview->grecstart = 0; loopview->grecend = 0; loopview->gplaypos = 0; loopview->grecpos = 0; loopview->grabsel = 0; loopview->lastmouseX = 0; loopview->lastmouseY = 0; loopview->bpm = 120; loopview->bpb = 4; loopview->gridwidth = 22050; loopview->gridoffset = 0; loopview->ggridstart = 0; loopview->ggridwidth = 1; loopview->snap2grid = FALSE; loopview->showgrid = FALSE; loopview->showattac = TRUE; loopview->fgc = NULL; loopview->bgc = NULL; loopview->bg_plain = (GdkColor){0, 0, 0, 16535}; loopview->bg_play = (GdkColor){0, 0, 0, 32767}; loopview->bg_rec = (GdkColor){0, 32767, 0, 0}; loopview->bg_zoom = (GdkColor){0, 0, 32767, 0}; loopview->bg_recplay = (GdkColor){0, 32767, 0, 32767}; loopview->bg_reczoom = (GdkColor){0, 32767, 32767, 0}; loopview->bg_playzoom = (GdkColor){0, 0, 32767, 32767}; loopview->bg_recplayzoom = (GdkColor){0, 32767, 32767, 32767}; loopview->bg_grid = (GdkColor){0, 32767, 32767, 32767}; loopview->bg_bar = (GdkColor){0, 65535, 65535, 65535}; loopview->bg_beat = (GdkColor){0, 32767, 32767, 32767}; loopview->fg_plain = (GdkColor){0, 32767, 32767, 0}; loopview->fg_lit = (GdkColor){0, 65535, 65535, 0}; loopview->playcursor = (GdkColor){0, 0, 65535, 0}; loopview->reccursor = (GdkColor){0, 65535, 0, 0}; gdk_color_alloc (gdk_colormap_get_system (), &loopview->bg_plain); gdk_color_alloc (gdk_colormap_get_system (), &loopview->bg_play); gdk_color_alloc (gdk_colormap_get_system (), &loopview->bg_rec); gdk_color_alloc (gdk_colormap_get_system (), &loopview->bg_zoom); gdk_color_alloc (gdk_colormap_get_system (), &loopview->bg_recplay); gdk_color_alloc (gdk_colormap_get_system (), &loopview->bg_reczoom); gdk_color_alloc (gdk_colormap_get_system (), &loopview->bg_playzoom); gdk_color_alloc (gdk_colormap_get_system (), &loopview->bg_recplayzoom); gdk_color_alloc (gdk_colormap_get_system (), &loopview->bg_grid); gdk_color_alloc (gdk_colormap_get_system (), &loopview->bg_bar); gdk_color_alloc (gdk_colormap_get_system (), &loopview->bg_beat); gdk_color_alloc (gdk_colormap_get_system (), &loopview->fg_plain); gdk_color_alloc (gdk_colormap_get_system (), &loopview->fg_lit); gdk_color_alloc (gdk_colormap_get_system (), &loopview->playcursor); gdk_color_alloc (gdk_colormap_get_system (), &loopview->reccursor); } GtkWidget* gtk_loopview_new (looper_data_t * looperdata) { GtkLoopview *loopview; loopview = gtk_type_new (gtk_loopview_get_type ()); gtk_loopview_set_looperdata (loopview, looperdata); gtk_loopview_update_waveform(loopview); return GTK_WIDGET (loopview); } static void gtk_loopview_destroy (GtkObject *object) { GtkLoopview *loopview; g_return_if_fail (object != NULL); g_return_if_fail (GTK_IS_LOOPVIEW (object)); loopview = GTK_LOOPVIEW (object); if (loopview->peakview) peakview_delete(loopview->peakview); if (GTK_OBJECT_CLASS (parent_class)->destroy) (* GTK_OBJECT_CLASS (parent_class)->destroy) (object); } looper_data_t* gtk_loopview_get_looperdata (GtkLoopview *loopview) { g_return_val_if_fail (loopview != NULL, NULL); g_return_val_if_fail (GTK_IS_LOOPVIEW (loopview), NULL); return loopview->looperdata; } void gtk_loopview_set_update_policy (GtkLoopview *loopview, GtkUpdateType policy) { g_return_if_fail (loopview != NULL); g_return_if_fail (GTK_IS_LOOPVIEW (loopview)); loopview->policy = policy; } void gtk_loopview_suspend_gui (GtkLoopview *loopview, int suspend){ g_return_if_fail (loopview != NULL); g_return_if_fail (GTK_IS_LOOPVIEW (loopview)); if (suspend){ loopview->suspended = TRUE; if (loopview->peakview) peakview_clear(loopview->peakview, 0, 0); } else { loopview->suspended = FALSE; if (loopview->looperdata) if (loopview->looperdata->buf){ if (!loopview->peakview) loopview->peakview = peakview_new(loopview->looperdata->buf); peakview_set_area(loopview->peakview,loopview->zoomstart, loopview->zoomend, loopview->npeaks); peakview_calculate(loopview->peakview,loopview->zoomstart, loopview->zoomend); } } } void gtk_loopview_set_looperdata (GtkLoopview *loopview, looper_data_t *looperdata){ g_return_if_fail (loopview != NULL); g_return_if_fail (GTK_IS_LOOPVIEW (loopview)); loopview->looperdata = looperdata; loopview->zoomstart = 0; loopview->zoomend = 0; /* if (loopview->peakview) { peakview_delete(loopview->peakview); loopview->peakview = NULL; } */ if (loopview->looperdata->buf){ loopview->zoomend = buffer_get_size(loopview->looperdata->buf); if (!loopview->peakview) loopview->peakview = peakview_new(loopview->looperdata->buf); else peakview_set_buffer(loopview->peakview, loopview->looperdata->buf); peakview_set_area(loopview->peakview,loopview->zoomstart, loopview->zoomend, loopview->npeaks); }else{ peakview_set_buffer(loopview->peakview, NULL); gtk_loopview_update_area(loopview,0,loopview->npeaks); } gtk_loopview_set_bpm(loopview,120); /* peakview_calculate(loopview->peakview,loopview->zoomstart, loopview->zoomend);*/ /* gtk_loopview_calc_peaks(loopview,0,loopview->npeaks);*/ /* gtk_loopview_update (loopview);*/ } void gtk_loopview_update_waveform (GtkLoopview *loopview){ g_return_if_fail (loopview != NULL); g_return_if_fail (GTK_IS_LOOPVIEW (loopview)); if (loopview->looperdata->buf && !loopview->suspended) peakview_calculate(loopview->peakview,0, loopview->zoomend); else gtk_loopview_update_area(loopview,0,loopview->npeaks); /* gtk_loopview_calc_peaks(loopview,0,loopview->npeaks);*/ /* gtk_loopview_update (loopview);*/ } static gint32 gtk_loopview_sample2graphical (GtkLoopview *loopview, gdouble sample){ gint64 gr; gr = (gint64)(loopview->zoomend - loopview->zoomstart); if (gr){ gr = (gint64)(sample - loopview->zoomstart ) * loopview->npeaks / gr; return (gint32)gr; }else{ return 0; } } static gdouble gtk_loopview_graphical2sample (GtkLoopview *loopview, gint32 gr){ gdouble sample; if (!loopview->npeaks){ return 0; }else{ sample = (gdouble)loopview->zoomstart + (gdouble)gr * (gdouble)(loopview->zoomend - loopview->zoomstart) / (gdouble)loopview->npeaks; return sample; } } void gtk_loopview_set_play_pos (GtkLoopview *loopview, gdouble playpos){ gint32 temp,t2; if (loopview->looperdata){ temp = gtk_loopview_sample2graphical (loopview,playpos); if (temp < 0){temp = 0;} if (temp > loopview->npeaks){temp = loopview->npeaks;} if (temp != loopview->gplaypos){ t2 = loopview->gplaypos; loopview->gplaypos = temp; /* printf ("playcursor: %d -> %d\n",(int)t2,(int)temp);*/ if (abs(loopview->gplaypos - t2) < 3){ gtk_loopview_update_area(loopview,t2,loopview->gplaypos); }else{ gtk_loopview_update_area(loopview,t2,t2); gtk_loopview_update_area(loopview,loopview->gplaypos,loopview->gplaypos); } /* printf ("playcursor\n");*/ } } } void gtk_loopview_set_rec_pos (GtkLoopview *loopview, gdouble recpos){ gint32 temp,t2; if (loopview->looperdata){ temp = gtk_loopview_sample2graphical (loopview,recpos); if (temp < 0){temp = 0;} if (temp > loopview->npeaks){temp = loopview->npeaks;} if (temp != loopview->grecpos){ t2 = loopview->grecpos; loopview->grecpos = temp; if (abs(loopview->grecpos - t2) < 3){ /* printf ("recpos update: %ld - %ld\n",t2,loopview->grecpos);*/ gtk_loopview_update_area(loopview,t2,loopview->grecpos); }else{ /* printf ("recpos update: %ld , %ld\n",t2,loopview->grecpos);*/ gtk_loopview_update_area(loopview,t2,t2); gtk_loopview_update_area(loopview,loopview->grecpos,loopview->grecpos); } } } } void gtk_loopview_zoom_to_playselection (GtkLoopview *loopview){ if (loopview->looperdata){ loopview->zoomstart = loopview->looperdata->loopstart; loopview->zoomend = loopview->looperdata->loopend; loopview->gloopstart = gtk_loopview_sample2graphical(loopview,loopview->looperdata->loopstart); loopview->gloopend = gtk_loopview_sample2graphical(loopview,loopview->looperdata->loopend); loopview->grecstart = gtk_loopview_sample2graphical(loopview,loopview->looperdata->recstart); loopview->grecend = gtk_loopview_sample2graphical(loopview,loopview->looperdata->recend); /* gtk_loopview_calc_peaks(loopview,0,loopview->npeaks);*/ peakview_set_area(loopview->peakview,loopview->zoomstart, loopview->zoomend, loopview->npeaks); if (!loopview->suspended) peakview_calculate(loopview->peakview,loopview->zoomstart, loopview->zoomend); } } void gtk_loopview_zoom_to_recselection (GtkLoopview *loopview){ if (loopview->looperdata){ loopview->zoomstart = loopview->looperdata->recstart; loopview->zoomend = loopview->looperdata->recend; loopview->gloopstart = gtk_loopview_sample2graphical(loopview,loopview->looperdata->loopstart); loopview->gloopend = gtk_loopview_sample2graphical(loopview,loopview->looperdata->loopend); loopview->grecstart = gtk_loopview_sample2graphical(loopview,loopview->looperdata->recstart); loopview->grecend = gtk_loopview_sample2graphical(loopview,loopview->looperdata->recend); /* gtk_loopview_calc_peaks(loopview,0,loopview->npeaks);*/ peakview_set_area(loopview->peakview,loopview->zoomstart, loopview->zoomend, loopview->npeaks); if (!loopview->suspended) peakview_calculate(loopview->peakview,loopview->zoomstart, loopview->zoomend); } } void gtk_loopview_zoom_to_overview (GtkLoopview *loopview){ if (loopview->looperdata){ loopview->zoomstart = 0; loopview->zoomend = 0; if (loopview->looperdata) if (loopview->looperdata->buf) loopview->zoomend = buffer_get_size(loopview->looperdata->buf); loopview->gloopstart = gtk_loopview_sample2graphical(loopview,loopview->looperdata->loopstart); loopview->gloopend = gtk_loopview_sample2graphical(loopview,loopview->looperdata->loopend); loopview->grecstart = gtk_loopview_sample2graphical(loopview,loopview->looperdata->recstart); loopview->grecend = gtk_loopview_sample2graphical(loopview,loopview->looperdata->recend); /* gtk_loopview_calc_peaks(loopview,0,loopview->npeaks);*/ peakview_set_area(loopview->peakview,loopview->zoomstart, loopview->zoomend, loopview->npeaks); if (!loopview->suspended) peakview_calculate(loopview->peakview,loopview->zoomstart, loopview->zoomend); } } void gtk_loopview_set_zoom (GtkLoopview *loopview, gdouble zoomstart, gdouble zoomend){ gdouble temp; /* printf ("set zoom\n");*/ if (zoomend < zoomstart){ temp = zoomend; zoomend = zoomstart; zoomstart = temp; } if (loopview->looperdata){ if ((loopview->zoomstart == zoomstart) && (loopview->zoomend == zoomend)) return; if (loopview->looperdata->buf){ if (zoomend < 0) zoomend = 0; if (zoomend > buffer_get_size(loopview->looperdata->buf)) zoomend = buffer_get_size(loopview->looperdata->buf); if (zoomstart < 0) zoomstart = 0; if (zoomstart > buffer_get_size(loopview->looperdata->buf)) zoomstart = buffer_get_size(loopview->looperdata->buf); if (zoomstart < zoomend){ loopview->zoomstart = zoomstart; loopview->zoomend = zoomend; loopview->gloopstart = gtk_loopview_sample2graphical(loopview,loopview->looperdata->loopstart); loopview->gloopend = gtk_loopview_sample2graphical(loopview,loopview->looperdata->loopend); loopview->grecstart = gtk_loopview_sample2graphical(loopview,loopview->looperdata->recstart); loopview->grecend = gtk_loopview_sample2graphical(loopview,loopview->looperdata->recend); /* gtk_loopview_calc_peaks(loopview,0,loopview->npeaks);*/ peakview_set_area(loopview->peakview,loopview->zoomstart, loopview->zoomend, loopview->npeaks); if (!loopview->suspended) peakview_calculate(loopview->peakview,loopview->zoomstart, loopview->zoomend); } } } } long gtk_loopview_get_zoomstart (GtkLoopview *loopview){ if (loopview->looperdata) if (loopview->looperdata->buf) return (long)loopview->zoomstart; return 0; } long gtk_loopview_get_zoomend (GtkLoopview *loopview){ if (loopview->looperdata) if (loopview->looperdata->buf) return (long)loopview->zoomend; return 0; } void gtk_loopview_update_loopstart (GtkLoopview *loopview){ gint32 temp = loopview->gloopstart; loopview->gloopstart = gtk_loopview_sample2graphical(loopview, (gdouble)looperdata_get_loopstart(loopview->looperdata)); gtk_loopview_update_area (loopview, MIN (temp, loopview->gloopstart), MAX (temp, loopview->gloopstart)); } void gtk_loopview_update_loopend (GtkLoopview *loopview){ gint32 temp = loopview->gloopend; loopview->gloopend = gtk_loopview_sample2graphical(loopview, (gdouble)looperdata_get_loopend(loopview->looperdata)); gtk_loopview_update_area (loopview, MIN (temp, loopview->gloopend), MAX (temp, loopview->gloopend)); } void gtk_loopview_update_recstart (GtkLoopview *loopview){ gint32 temp = loopview->grecstart; loopview->grecstart = gtk_loopview_sample2graphical(loopview, (gdouble)loopview->looperdata->recstart); gtk_loopview_update_area (loopview, MIN (temp, loopview->grecstart), MAX (temp, loopview->grecstart)); } void gtk_loopview_set_snap2grid (GtkLoopview *loopview, gboolean snap){ loopview->snap2grid = snap; } gboolean gtk_loopview_getsnap2grid (GtkLoopview *loopview){ return loopview->snap2grid; } void gtk_loopview_set_showgrid (GtkLoopview *loopview, gboolean show){ loopview->showgrid = show; gtk_loopview_update_area (loopview,0,loopview->npeaks); } gboolean gtk_loopview_get_showgrid (GtkLoopview *loopview){ return loopview->showgrid; } void gtk_loopview_set_bpm (GtkLoopview *loopview, gdouble bpm){ if (bpm > 0.0001) { loopview->bpm = bpm; if (loopview->looperdata){ loopview->gridwidth = loopview->looperdata->samplerate * 60. / bpm; } gtk_loopview_update_area (loopview,0,loopview->npeaks); } } gdouble gtk_loopview_get_bpm (GtkLoopview *loopview){ return loopview->bpm; } void gtk_loopview_set_gridoffset (GtkLoopview *loopview, guint32 offset){ if (loopview->looperdata){ if (loopview->looperdata->buf){ if(offset <= buffer_get_size(loopview->looperdata->buf)) loopview->gridoffset = offset; else loopview->gridoffset = buffer_get_size(loopview->looperdata->buf); /* printf ("offset:%ld\n",(long)loopview->gridoffset);*/ gtk_loopview_update_area (loopview,0,loopview->npeaks); } else loopview->gridoffset = 0; } else loopview->gridoffset = 0; } guint32 gtk_loopview_get_gridoffset (GtkLoopview *loopview){ return loopview->gridoffset; } guint32 gtk_loopview_get_gridwidth (GtkLoopview *loopview){ return loopview->gridwidth; } void gtk_loopview_set_bpb (GtkLoopview *loopview, gdouble bpb){ if (bpb >= 1.){ loopview->bpb = bpb; gtk_loopview_update_area (loopview,0,loopview->npeaks); } } gdouble gtk_loopview_get_bpb (GtkLoopview *loopview){ return loopview->bpb; } void gtk_loopview_update_recend (GtkLoopview *loopview){ gint32 temp = loopview->grecend; loopview->grecend = gtk_loopview_sample2graphical(loopview, (gdouble)loopview->looperdata->recend); gtk_loopview_update_area (loopview, MIN (temp, loopview->grecend), MAX (temp, loopview->grecend)); } void gtk_loopview_update_cursorposition (GtkLoopview *loopview){ g_return_if_fail (loopview != NULL); g_return_if_fail (GTK_IS_LOOPVIEW (loopview)); double start = 0.; double end = 0.; gint x = 0; gint y = 0; GdkModifierType mods; peakdata_t *pd; if (loopview->looperdata){ if (loopview->looperdata->buf){ gdk_window_get_pointer (GTK_WIDGET(loopview)->window, &x, &y, &mods); // looperdata_lock(loopview->looperdata); while (looperdata_read_once_dirtyblock(loopview->looperdata, &start, &end)){ if (!loopview->suspended){ /* printf ("dirtyblock: %.2lf - %.2lf\n", start, end);*/ peakview_calculate(loopview->peakview, (long)start, (long)end); } } // looperdata_unlock(loopview->looperdata); if (loopview->peakview){ peakview_lock(loopview->peakview); while ((pd = peakview_get_next(loopview->peakview))){ gtk_loopview_copy_peaks(loopview,pd); } peakview_unlock(loopview->peakview); } gtk_loopview_set_play_pos (loopview, looperdata_get_playpos(loopview->looperdata)); gtk_loopview_set_rec_pos (loopview, (double)looperdata_get_recpos(loopview->looperdata)); } } } static void gtk_loopview_realize (GtkWidget *widget) { GtkLoopview *loopview; GdkWindowAttr attributes; gint attributes_mask; g_return_if_fail (widget != NULL); g_return_if_fail (GTK_IS_LOOPVIEW (widget)); GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED); loopview = GTK_LOOPVIEW (widget); attributes.x = widget->allocation.x; attributes.y = widget->allocation.y; attributes.width = widget->allocation.width; attributes.height = widget->allocation.height; attributes.wclass = GDK_INPUT_OUTPUT; attributes.window_type = GDK_WINDOW_CHILD; /* attributes.event_mask = (gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK ); */ attributes.event_mask = GDK_ALL_EVENTS_MASK; attributes.visual = gtk_widget_get_visual (widget); attributes.colormap = gtk_widget_get_colormap (widget); attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; widget->window = gdk_window_new (widget->parent->window, &attributes, attributes_mask); widget->style = gtk_style_attach (widget->style, widget->window); gdk_window_set_user_data (widget->window, widget); gtk_style_set_background (widget->style, widget->window, GTK_STATE_ACTIVE); gtk_widget_add_events(widget, GDK_ALL_EVENTS_MASK); /* printf ("realized\n");*/ } static void gtk_loopview_size_request (GtkWidget *widget, GtkRequisition *requisition) { requisition->width = LOOPVIEW_DEFAULT_WIDTH; requisition->height = LOOPVIEW_DEFAULT_HEIGHT; } static void gtk_loopview_size_allocate (GtkWidget *widget, GtkAllocation *allocation) { GtkLoopview *loopview; g_return_if_fail (widget != NULL); g_return_if_fail (GTK_IS_LOOPVIEW (widget)); g_return_if_fail (allocation != NULL); widget->allocation = *allocation; if (GTK_WIDGET_REALIZED (widget)){ loopview = GTK_LOOPVIEW (widget); /* printf ("size allocate:%ldx%ld\n",(long)allocation->width,(long)allocation->height);*/ gdk_window_move_resize (widget->window, allocation->x, allocation->y, allocation->width, allocation->height); /* reinitialize the offscreen pixmap */ if (loopview->pixmap) g_object_unref(loopview->pixmap); loopview->pixmap = gdk_pixmap_new(widget->window,allocation->width,allocation->height,-1); if (loopview->width != allocation->width){ if (loopview->npeaks){ loopview->gloopstart = loopview->gloopstart * allocation->width / loopview->npeaks; loopview->gloopend = loopview->gloopend * allocation->width / loopview->npeaks; loopview->grecstart = loopview->grecstart * allocation->width / loopview->npeaks; loopview->grecend = loopview->grecend * allocation->width / loopview->npeaks; } loopview->Lmin = realloc (loopview->Lmin,sizeof(gint8) * (allocation->width + 1)); memset(loopview->Lmin,0,sizeof(gint8) * allocation->width); loopview->Lmax = realloc (loopview->Lmax,sizeof(gint8) * (allocation->width + 1)); memset(loopview->Lmax,0,sizeof(gint8) * allocation->width); loopview->Rmin = realloc (loopview->Rmin,sizeof(gint8) * (allocation->width + 1)); memset(loopview->Rmin,0,sizeof(gint8) * allocation->width); loopview->Rmax = realloc (loopview->Rmax,sizeof(gint8) * (allocation->width + 1)); memset(loopview->Rmax,0,sizeof(gint8) * allocation->width); loopview->npeaks = allocation->width; loopview->width = allocation->width; loopview->height = allocation->height; /* gtk_loopview_calc_peaks(loopview,0,allocation->width);*/ peakview_set_area(loopview->peakview,loopview->zoomstart, loopview->zoomend, allocation->width); if (!loopview->suspended) peakview_calculate(loopview->peakview,loopview->zoomstart, loopview->zoomend); gtk_loopview_update_area(loopview,0,allocation->width); } else if (loopview->height != allocation->height){ loopview->height = allocation->height; gtk_loopview_update_area(loopview,0,allocation->width); } else{ gtk_loopview_update_area(loopview,0,allocation->width); } }/*else printf("not realized\n");*/ } void gtk_loopview_update_column (GtkLoopview *loopview, int i){ /* float d1, d2;*/ gdouble diff = 0.; if (i == loopview->grecpos){ gdk_gc_set_foreground(loopview->fgc,&loopview->reccursor); gdk_draw_line (loopview->pixmap,loopview->fgc,loopview->grecpos,1, loopview->grecpos,loopview->height); }else if (i == loopview->gplaypos){ gdk_gc_set_foreground(loopview->fgc,&loopview->playcursor); gdk_draw_line (loopview->pixmap,loopview->fgc,loopview->gplaypos,1, loopview->gplaypos,loopview->height); }else{ if (loopview->showgrid){ diff = (gtk_loopview_graphical2sample(loopview,i) - loopview->gridoffset) / loopview->gridwidth; diff = gtk_loopview_sample2graphical(loopview,(gint)(diff + .5) * loopview->gridwidth + loopview->gridoffset); diff = fabs(diff - i); } if ((loopview->showgrid) && (diff < .5)){ if (((int)((float)gtk_loopview_graphical2sample(loopview,i) / (float)loopview->gridwidth + .5) % (int)loopview->bpb) == 0) gdk_gc_set_foreground(loopview->bgc,&loopview->bg_bar); else gdk_gc_set_foreground(loopview->bgc,&loopview->bg_beat); gdk_gc_set_foreground(loopview->fgc,&loopview->fg_plain); }else if ((i >= loopview->gloopstart) && (i <= loopview->gloopend) && (i >= loopview->grecstart) && (i <= loopview->grecend) && (i >= loopview->gzoomstart) && (i <= loopview->gzoomend)){ gdk_gc_set_foreground(loopview->bgc,&loopview->bg_recplayzoom); gdk_gc_set_foreground(loopview->fgc,&loopview->fg_lit); }else if ((i >= loopview->gloopstart) && (i <= loopview->gloopend) && (i >= loopview->grecstart) && (i <= loopview->grecend)){ gdk_gc_set_foreground(loopview->bgc,&loopview->bg_recplay); gdk_gc_set_foreground(loopview->fgc,&loopview->fg_lit); }else if ((i >= loopview->gloopstart) && (i <= loopview->gloopend) && (i >= loopview->gzoomstart) && (i <= loopview->gzoomend)){ gdk_gc_set_foreground(loopview->bgc,&loopview->bg_playzoom); gdk_gc_set_foreground(loopview->fgc,&loopview->fg_lit); }else if ((i >= loopview->grecstart) && (i <= loopview->grecend) && (i >= loopview->gzoomstart) && (i <= loopview->gzoomend)){ gdk_gc_set_foreground(loopview->bgc,&loopview->bg_reczoom); gdk_gc_set_foreground(loopview->fgc,&loopview->fg_lit); }else if ((i >= loopview->grecstart) && (i <= loopview->grecend)){ gdk_gc_set_foreground(loopview->bgc,&loopview->bg_rec); gdk_gc_set_foreground(loopview->fgc,&loopview->fg_lit); }else if ((i >= loopview->gloopstart) && (i <= loopview->gloopend)){ gdk_gc_set_foreground(loopview->bgc,&loopview->bg_play); gdk_gc_set_foreground(loopview->fgc,&loopview->fg_lit); }else if ((i >= loopview->gzoomstart) && (i <= loopview->gzoomend)){ gdk_gc_set_foreground(loopview->bgc,&loopview->bg_zoom); gdk_gc_set_foreground(loopview->fgc,&loopview->fg_lit); }else{ gdk_gc_set_foreground(loopview->bgc,&loopview->bg_plain); gdk_gc_set_foreground(loopview->fgc,&loopview->fg_plain); } gdk_draw_line (loopview->pixmap,loopview->bgc, i,0,i,loopview->height); gdk_draw_line (loopview->pixmap,loopview->fgc, i,loopview->Lmid + (*(loopview->Lmin + i) * loopview->Hmax) / 127, i,loopview->Lmid + (*(loopview->Lmax + i) * loopview->Hmax) / 127); if (buffer_get_channels(loopview->looperdata->buf) > 1) gdk_draw_line (loopview->pixmap,loopview->fgc, i,loopview->Rmid + (*(loopview->Rmin + i) * loopview->Hmax) / 127, i,loopview->Rmid + (*(loopview->Rmax + i) * loopview->Hmax) / 127); /* printf ("updated:%d\n",(int)i);*/ } /* printf ("updated:%d,height: %d\n",(int)i,(int)loopview->height);*/ } void gtk_loopview_update_area(GtkLoopview *loopview, gint32 startx, gint32 endx){ GdkRectangle update_rect; GtkWidget *widget = (GtkWidget*)loopview; guint32 i; gboolean docalc = FALSE; if (loopview->npeaks < 1) return; if (loopview->looperdata) if (loopview->looperdata->buf) docalc = TRUE; /* printf ("update area: %d - %d\n",(int)startx, (int)endx);*/ if (!loopview->fgc){ loopview->bgc = gdk_gc_new (loopview->pixmap); loopview->fgc = gdk_gc_new (loopview->pixmap); gdk_gc_copy (loopview->fgc,widget->style->bg_gc[widget->state]); gdk_gc_copy (loopview->bgc,widget->style->bg_gc[widget->state]); } if (docalc){ loopview->gridstart = ((int)(loopview->zoomstart / loopview->gridwidth)) * loopview->gridwidth; loopview->ggridstart = gtk_loopview_sample2graphical(loopview, loopview->gridstart); loopview->ggridwidth = (gdouble)(loopview->zoomend - loopview->zoomstart) / (gdouble)loopview->gridwidth; /* loopview->ggridwidth = gtk_loopview_sample2graphical(loopview, loopview->zoomstart + loopview->gridwidth); */ if (buffer_get_channels(loopview->looperdata->buf) > 1) { loopview->Lmid = loopview->height / 4; loopview->Rmid = loopview->height * 3 / 4; loopview->Hmax = (loopview->height / 4 ) - 2; }else{ loopview->Lmid = loopview->height / 2; loopview->Hmax = (loopview->height / 2) - 2; } if (startx < 0) startx = 0; if (startx > loopview->npeaks) startx = loopview->npeaks; if (endx < 0) endx = 0; if (endx > loopview->npeaks) endx = loopview->npeaks; if (startx > endx){ gint32 tmp = endx; endx = startx; startx = tmp; } for (i = startx; i <= endx; i++){ gtk_loopview_update_column(loopview, i); loopview->lastnup++; } /* middle line */ if (buffer_get_channels(loopview->looperdata->buf) > 1) gdk_draw_line (loopview->pixmap, widget->style->fg_gc[widget->state], 1,loopview->height / 2, loopview->width,loopview->height / 2); /* printf ("updated: %d - %d , %d\n",startx, endx, loopview->height);*/ }else{ gdk_gc_set_foreground(loopview->bgc,&loopview->bg_plain); gdk_draw_rectangle (loopview->pixmap,loopview->bgc,TRUE, startx,0,(endx - startx + 1),loopview->height); /* printf ("blanked: %d - %d , %d\n",startx, endx, loopview->height);*/ } update_rect.x = startx; update_rect.y = 0; update_rect.height = loopview->height; update_rect.width = endx - startx + 1; gtk_widget_draw (GTK_WIDGET(loopview),&update_rect); } #if 0 void gtk_loopview_calc_peaks(GtkLoopview *loopview,guint32 startx, guint32 endx){ float Lval; float Rval; float drift; gint8 *Lminp = NULL; gint8 *Rminp = NULL; gint8 *Lmaxp = NULL; gint8 *Rmaxp = NULL; guint64 i; guint64 j; guint64 steps; guint64 samples; guint64 peaks; /* printf ("calc peaks, "); printf ("height:%ld\n",(long)loopview->height);*/ if (loopview->npeaks < 1) return; if (loopview->looperdata == NULL){ gtk_loopview_update_area(loopview, startx, endx); return; } if (loopview->looperdata->buf == NULL){ gtk_loopview_update_area(loopview, startx, endx); return; } drift = buffer_get_sampleratefactor(loopview->looperdata->buf, loopview->looperdata->samplerate); if (endx > loopview->npeaks){endx = loopview->npeaks;} if (startx > endx){ guint32 tmp = endx; endx = startx; startx = tmp; } peaks = endx - startx; if (loopview->npeaks > 0 && loopview->looperdata){ if (loopview->looperdata->buf){ samples = (guint32)(loopview->zoomend - loopview->zoomstart); steps = (guint32)(samples / loopview->npeaks); Lminp = loopview->Lmin + startx; Lmaxp = loopview->Lmax + startx; if (buffer_get_channels(loopview->looperdata->buf) > 1){ Rminp = loopview->Rmin + startx; Rmaxp = loopview->Rmax + startx; } for (i = 0; i < peaks; i++){ *Lminp = 127; *Lmaxp = -127; if (buffer_get_channels(loopview->looperdata->buf) > 1){ *Rminp = 127; *Rmaxp = -127; } for (j = 0; j < steps; j++){ float pos = loopview->zoomstart; pos += (startx + i) * (long)samples / (long)loopview->npeaks + j; pos *= drift; Lval = buffer_readsample_interpolated(loopview->looperdata->buf,1, pos, loopview->buffer_group) * 127.; if ((gint8)Lval < *Lminp ){*Lminp = (gint8)Lval;} if ((gint8)Lval > *Lmaxp ){*Lmaxp = (gint8)Lval;} if (buffer_get_channels(loopview->looperdata->buf) > 1){ Rval = buffer_readsample_interpolated(loopview->looperdata->buf,2, pos, loopview->buffer_group) * 127.; if ((gint8)Rval < *Rminp ){*Rminp = (gint8)Rval;} if ((gint8)Rval > *Rmaxp ){*Rmaxp = (gint8)Rval;} } } Lminp++; Lmaxp++; if (buffer_get_channels(loopview->looperdata->buf) > 1){ Rminp++; Rmaxp++; } } /* printf ("calc peaks update:i * j = %ld\n",(long)(i*j));*/ gtk_loopview_update_area(loopview, startx, endx); } } /* printf ("calc peaks done\n");*/ } #endif void gtk_loopview_copy_peaks(GtkLoopview *loopview, peakdata_t *pd){ long i; long len = pd->pend - pd->pstart; /* printf ("copy: %p. done:%d\n",pd,pd->done);*/ /* printf ("copy: pstart:%ld, pend:%ld\n", pd->pstart, pd->pend);*/ if (buffer_get_channels(loopview->looperdata->buf) > 1){ for (i = 0; i < len;i++){ *(loopview->Lmin + i + pd->pstart) = (gint8)*(pd->Lmin + i); *(loopview->Lmax + i + pd->pstart) = (gint8)*(pd->Lmax + i); *(loopview->Rmin + i + pd->pstart) = (gint8)*(pd->Rmin + i); *(loopview->Rmax + i + pd->pstart) = (gint8)*(pd->Rmax + i); } } else { for (i = 0; i < len;i++){ *(loopview->Lmin + i + pd->pstart) = (gint8)*(pd->Lmin + i); *(loopview->Lmax + i + pd->pstart) = (gint8)*(pd->Lmax + i); } } peakdata_set_status(pd,PD_STATUS_DEAD); /* printf ("updated:...%ld - %ld\n",pd->pstart, (pd->pstart + i));*/ gtk_loopview_update_area(loopview, pd->pstart, pd->pend); } static gboolean gtk_loopview_expose( GtkWidget *widget, GdkEventExpose *event){ GtkLoopview *loopview = GTK_LOOPVIEW (widget); /* printf ("expose\n");*/ g_return_val_if_fail (widget != NULL, FALSE); g_return_val_if_fail (GTK_IS_LOOPVIEW (widget), FALSE); g_return_val_if_fail (event != NULL, FALSE); if (event->count > 0) return FALSE; gdk_draw_drawable ((GdkDrawable*)widget->window, widget->style->fg_gc[GTK_WIDGET_STATE(widget)], loopview->pixmap, event->area.x, event->area.y, event->area.x, event->area.y, event->area.width, event->area.height); /* printf ("expose done\n");*/ return FALSE; } /* static gdouble gsnap2grid(GtkLoopview *loopview, gdouble x){ gint diff; gint delta = 7; if (loopview->snap2grid == TRUE){ diff = (gint)((x - loopview->ggridstart) / loopview->ggridwidth + .5) * loopview->ggridwidth; diff -= (x - loopview->ggridstart); if (abs(diff) < delta){ x = loopview->ggridstart + ((gint)((x - loopview->ggridstart) / loopview->ggridwidth) * loopview->ggridwidth); } } return x; } */ static gdouble snap2grid(GtkLoopview *loopview, gdouble x){ gdouble diff; gdouble delta; gdouble nearest; gint gdelta = 7; if (loopview->snap2grid == TRUE){ /* equivalent of gdelta pixels */ delta = gtk_loopview_graphical2sample(loopview, loopview->gloopstart + gdelta) - gtk_loopview_graphical2sample(loopview, loopview->gloopstart); nearest = (gint)((x - loopview->gridoffset) / loopview->gridwidth + .5) * loopview->gridwidth + loopview->gridoffset; /* nearest = (gint)(x / loopview->gridwidth + .5) * loopview->gridwidth; */ diff = x - nearest; if (fabs(diff) < delta) x = nearest; /* printf ("x:%lf, nearest:%lf, diff:%lf, delta:%lf\n", (double)x,(double)nearest,(double)nearest,(double)delta);*/ } return x; } static void gtk_loopview_set_loopstartend(GtkLoopview *loopview, gdouble temps, gdouble tempe){ /* printf ("%ld - %ld | %lf - %lf\n", looperdata_get_loopstart(loopview->looperdata),looperdata_get_loopend(loopview->looperdata),temps,tempe); */ if (temps < .0){temps = 0.;} if (temps > buffer_get_size(loopview->looperdata->buf)){ temps = buffer_get_size(loopview->looperdata->buf); } if (tempe < .0){tempe = 0.;} if (tempe > buffer_get_size(loopview->looperdata->buf)){ tempe = buffer_get_size(loopview->looperdata->buf); } if (temps > tempe){ gdouble temp = temps; temps = tempe; tempe = temp; } looperdata_lock(loopview->looperdata); looperdata_set_loopstart(loopview->looperdata, temps); looperdata_set_loopend(loopview->looperdata, tempe); looperdata_unlock(loopview->looperdata); } static void gtk_loopview_set_recstartend(GtkLoopview *loopview, gdouble temps, gdouble tempe){ if (temps < .0){temps = 0.;} if (temps > buffer_get_size(loopview->looperdata->buf)){ temps = buffer_get_size(loopview->looperdata->buf); } if (tempe < .0){tempe = 0.;} if (tempe > buffer_get_size(loopview->looperdata->buf)){ tempe = buffer_get_size(loopview->looperdata->buf); } if (temps > tempe){ gdouble temp = temps; temps = tempe; tempe = temp; } looperdata_lock(loopview->looperdata); looperdata_set_recstart(loopview->looperdata, temps); looperdata_set_recend(loopview->looperdata, tempe); looperdata_unlock(loopview->looperdata); } static gboolean gtk_loopview_button_press( GtkWidget *widget, GdkEventButton *origevent ){ GdkEventButton *event = origevent; GtkLoopview *loopview; GdkCursor *cursor; gint maxd = 20; gint sdiff = 0; gint ediff = 0; gint bdiff = 0; gint t1, t2; g_return_val_if_fail (widget != NULL, FALSE); g_return_val_if_fail (GTK_IS_LOOPVIEW (widget), FALSE); g_return_val_if_fail (event != NULL, FALSE); loopview = GTK_LOOPVIEW(widget); if (!loopview->looperdata) return FALSE; if (!loopview->looperdata->buf) return FALSE; loopview->button = event->button; if ((event->button == 1) && (event->state & GDK_CONTROL_MASK)){ if (loopview->looperdata->buf){ gettimeofday(&loopview->lastmousetime,0); looperdata_lock(loopview->looperdata); looperdata_set_playpos(loopview->looperdata, gtk_loopview_graphical2sample(loopview,event->x)); /* loopview->looperdata->playpos = gtk_loopview_graphical2sample(loopview,event->x); */ looperdata_unlock(loopview->looperdata); t1 = loopview->gplaypos; loopview->gplaypos = gtk_loopview_sample2graphical(loopview, looperdata_get_playpos(loopview->looperdata)); gtk_loopview_update_area(loopview,t1,t1); gtk_loopview_update_area(loopview,loopview->gplaypos,loopview->gplaypos); loopview->grabsel = 6 ; /* "scratch" with playhead */ loopview->speedbeforescratch = loopview->looperdata->speed; } }else if (event->button == 1){ /* change selection */ sdiff = loopview->gloopstart - event->x; ediff = event->x - loopview->gloopend; bdiff = loopview->gloopend - loopview->gloopstart; if (((sdiff < maxd) && (sdiff >= 0)) || ((sdiff <= 0) && (sdiff > (maxd * -1) && (sdiff <(bdiff / 8 ))))){ /* resize gloopstart */ loopview->grabsel = 1; /* grab the start */ cursor = gdk_cursor_new(GDK_LEFT_SIDE); gdk_window_set_cursor(widget->window,cursor); }else if (((ediff < maxd) && (ediff >= 0)) || ((ediff <= 0) && (ediff > (maxd * -1) && (sdiff <(bdiff / 8 ))))){ /* resize gloopend */ cursor = gdk_cursor_new(GDK_RIGHT_SIDE); gdk_window_set_cursor(widget->window,cursor); loopview->grabsel = 2; /* grab the end */ }else if ((event->x > loopview->gloopstart) && (event->x gloopend)){ /* move and resize the whole selection */ cursor = gdk_cursor_new(GDK_FLEUR); gdk_window_set_cursor(widget->window,cursor); if (event->state & GDK_SHIFT_MASK){ loopview->grabsel = 5; /* grab the whole loop, dont resize*/ }else{ loopview->grabsel = 3;/* grab the whole loop */ } loopview->lastmouseX = event->x; loopview->lastmouseY = event->y; }else{ /* new selection */ t1 = loopview->gloopstart; t2 = loopview->gloopend; loopview->grabsel = 4; cursor = gdk_cursor_new(GDK_SB_H_DOUBLE_ARROW); gdk_window_set_cursor(widget->window,cursor); gtk_loopview_set_loopstartend(loopview, snap2grid(loopview,gtk_loopview_graphical2sample(loopview,event->x)), snap2grid(loopview,gtk_loopview_graphical2sample(loopview,event->x))); loopview->gloopstart = gtk_loopview_sample2graphical(loopview, looperdata_get_loopstart(loopview->looperdata)); loopview->gloopend = gtk_loopview_sample2graphical(loopview, looperdata_get_loopend(loopview->looperdata)); gtk_loopview_update_area(loopview,t1,t2); } }else if (event->button == 2){ if (event->state & GDK_SHIFT_MASK){ loopview->grabsel = 2; }else{ loopview->grabsel = 1; } cursor = gdk_cursor_new(GDK_SB_H_DOUBLE_ARROW); gdk_window_set_cursor(widget->window,cursor); loopview->gzoomstart = event->x; loopview->gzoomend = event->x; loopview->lastmouseX = event->x; loopview->lastmouseY = event->y; gtk_widget_draw (GTK_WIDGET(loopview),NULL); /* LATER: menu for ctr-button: http://developer.gnome.org/doc/API/2.0/gtk/GtkMenu.html#gtk-menu-popup*/ } else if ((event->button == 3) && (event->state & GDK_CONTROL_MASK)){ if (loopview->looperdata->buf){ looperdata_lock(loopview->looperdata); looperdata_set_recpos(loopview->looperdata, (double)gtk_loopview_graphical2sample(loopview,event->x)); looperdata_unlock(loopview->looperdata); } } else if (event->button == 3){ sdiff = loopview->grecstart - event->x; ediff = event->x - loopview->grecend; bdiff = loopview->grecend - loopview->grecstart; /* change rec selection */ if (((sdiff < maxd) && (sdiff > 0)) || ((sdiff < 0) && (sdiff > (maxd * -1) && (sdiff <(bdiff / 8 ))))){ /* resize grecstart */ loopview->grabsel = 1; /* grab the start */ cursor = gdk_cursor_new(GDK_LEFT_SIDE); gdk_window_set_cursor(widget->window,cursor); }else if (((ediff < maxd) && (ediff > 0)) || ((ediff < 0) && (ediff > (maxd * -1) && (ediff <(bdiff / 8 ))))){ /* resize grecend */ cursor = gdk_cursor_new(GDK_RIGHT_SIDE); gdk_window_set_cursor(widget->window,cursor); loopview->grabsel = 2; /* grab the end */ }else if ((event->x > loopview->grecstart) && (event->x grecend)){ /* move and resize the whole selection */ cursor = gdk_cursor_new(GDK_FLEUR); gdk_window_set_cursor(widget->window,cursor); if (event->state & GDK_SHIFT_MASK){ loopview->grabsel = 5; /* grab the whole loop, dont resize*/ }else{ loopview->grabsel = 3;/* grab the whole loop */ } loopview->lastmouseX = event->x; loopview->lastmouseY = event->y; }else{ /* new selection */ t1 = loopview->grecstart; t2 = loopview->grecend; loopview->grabsel = 4; cursor = gdk_cursor_new(GDK_SB_H_DOUBLE_ARROW); gdk_window_set_cursor(widget->window,cursor); gtk_loopview_set_recstartend(loopview, snap2grid(loopview,gtk_loopview_graphical2sample(loopview,event->x)), snap2grid(loopview,gtk_loopview_graphical2sample(loopview,event->x) /*+ 1*/)); loopview->grecstart = gtk_loopview_sample2graphical(loopview, looperdata_get_recstart(loopview->looperdata)); loopview->grecend = gtk_loopview_sample2graphical(loopview, looperdata_get_recend(loopview->looperdata)); gtk_loopview_update_area(loopview,t1,t2); } } return FALSE; } static gboolean gtk_loopview_button_release( GtkWidget *widget, GdkEventButton *event ) { GtkLoopview *loopview; GdkCursor *cursor; gdouble temps = 0.; gdouble tempe = 0.; gdouble temp = 0.; g_return_val_if_fail (widget != NULL, FALSE); g_return_val_if_fail (GTK_IS_LOOPVIEW (widget), FALSE); g_return_val_if_fail (event != NULL, FALSE); loopview = GTK_LOOPVIEW(widget); if (!loopview->looperdata) return FALSE; if (!loopview->looperdata->buf) return FALSE; /* if (event->state & GDK_SHIFT_MASK){printf ("shift release\n");}*/ if (loopview->button == event->button){ if (loopview->button == 1){ if ((loopview->grabsel == 6) && !(event->state & GDK_SHIFT_MASK)){ /* restore original speed if shift is not pressed */ looperdata_lock(loopview->looperdata); looperdata_set_speed(loopview->looperdata,loopview->speedbeforescratch); looperdata_unlock(loopview->looperdata); g_signal_emit(GTK_OBJECT(loopview), gtk_loopview_signals[SIG_SPEED_CHANGED],0); } } else if (loopview->button == 2){ /* zoom to new area if not at maximum already*/ if (loopview->gzoomstart < 0 ){loopview->gzoomstart = 0;} if (loopview->gzoomend > loopview->npeaks){loopview->gzoomend = loopview->npeaks;} if (loopview->grabsel == 1){ /* zoom in */ temps = gtk_loopview_graphical2sample(loopview,loopview->gzoomstart); tempe = gtk_loopview_graphical2sample(loopview,loopview->gzoomend); }else if (loopview->grabsel == 2){ /* shift was pressed: zoom out */ temp = (gdouble)loopview->npeaks / (gdouble)(loopview->gzoomend - loopview->gzoomstart); loopview->gzoomstart = (loopview->npeaks - loopview->npeaks * temp ) / 2; loopview->gzoomend = loopview->npeaks + (gint32)(loopview->npeaks * temp -loopview->npeaks ) / 2; temps = gtk_loopview_graphical2sample(loopview,loopview->gzoomstart); tempe = gtk_loopview_graphical2sample(loopview,loopview->gzoomend); /* printf ("temps:%f, tempe:%f\n",(float)temps, (float)tempe);*/ if (temps < 0){temps = 0;} if (loopview->looperdata->buf){ if (tempe > buffer_get_size(loopview->looperdata->buf)){ tempe = buffer_get_size(loopview->looperdata->buf); } } } if ((gint32)(tempe - temps) > loopview->npeaks){ loopview->zoomstart = temps; loopview->zoomend = tempe; loopview->gloopstart = gtk_loopview_sample2graphical(loopview,loopview->looperdata->loopstart); loopview->gloopend = gtk_loopview_sample2graphical(loopview,loopview->looperdata->loopend); loopview->grecstart = gtk_loopview_sample2graphical(loopview,loopview->looperdata->recstart); loopview->grecend = gtk_loopview_sample2graphical(loopview,loopview->looperdata->recend); /* gtk_loopview_calc_peaks(loopview,0,loopview->npeaks);*/ if (!loopview->suspended) peakview_set_area(loopview->peakview,loopview->zoomstart, loopview->zoomend, loopview->npeaks); } loopview->gzoomstart = 0; loopview->gzoomend = 0; /* gtk_loopview_calc_peaks(loopview,0,loopview->npeaks);*/ if (!loopview->suspended) peakview_calculate(loopview->peakview, loopview->zoomstart, loopview->zoomend); /* gtk_widget_draw (GTK_WIDGET(loopview),NULL);*/ } cursor = gdk_cursor_new(GDK_TOP_LEFT_ARROW); gdk_window_set_cursor(widget->window,cursor); /* gtk_grab_remove (widget);*/ loopview->button = 0; loopview->grabsel = 0; if (loopview->policy == GTK_UPDATE_DELAYED) g_source_remove (loopview->timer); } return FALSE; } static gboolean gtk_loopview_motion_notify( GtkWidget *widget, GdkEventMotion *event ) { GtkLoopview *loopview; GdkModifierType mods; gint x, y, mask; gint maxd = 20; GdkCursor *cursor; g_return_val_if_fail (widget != NULL, FALSE); g_return_val_if_fail (GTK_IS_LOOPVIEW (widget), FALSE); g_return_val_if_fail (event != NULL, FALSE); loopview = GTK_LOOPVIEW(widget); if (loopview->button){ x = event->x; y = event->y; if (event->is_hint || (event->window != widget->window)) gdk_window_get_pointer (widget->window, &x, &y, &mods); switch (loopview->button){ case 1: mask = GDK_BUTTON1_MASK; break; case 2: mask = GDK_BUTTON2_MASK; break; case 3: mask = GDK_BUTTON3_MASK; break; default: mask = 0; break; } if (mods & mask) gtk_loopview_update_mouse (loopview,x,y); }else{ /* printf ("motion notify x:%d, y:%d\n",(int)event->x,(int)event->y);*/ if ((loopview->pointerX != x) || (loopview->pointerY != y)){ if (abs(event->x - loopview->gloopstart) < maxd){ cursor = gdk_cursor_new(GDK_LEFT_SIDE); gdk_window_set_cursor(widget->window,cursor); }else if (abs(event->x - loopview->gloopend) < maxd){ cursor = gdk_cursor_new(GDK_RIGHT_SIDE); gdk_window_set_cursor(widget->window,cursor); }else if ((event->x > loopview->gloopstart) && (event->x gloopend)){ cursor = gdk_cursor_new(GDK_SB_H_DOUBLE_ARROW); gdk_window_set_cursor(widget->window,cursor); }else if (abs(event->x - loopview->grecstart) < maxd){ cursor = gdk_cursor_new(GDK_LEFT_SIDE); gdk_window_set_cursor(widget->window,cursor); }else if (abs(event->x - loopview->grecend) < maxd){ cursor = gdk_cursor_new(GDK_RIGHT_SIDE); gdk_window_set_cursor(widget->window,cursor); }else if ((event->x > loopview->grecstart) && (event->x grecend)){ cursor = gdk_cursor_new(GDK_SB_H_DOUBLE_ARROW); gdk_window_set_cursor(widget->window,cursor); }else{ cursor = gdk_cursor_new(GDK_TOP_LEFT_ARROW); gdk_window_set_cursor(widget->window,cursor); } loopview->pointerX = event->x; loopview->pointerY = event->y; } } return FALSE; } static void gtk_loopview_update_mouse (GtkLoopview *loopview, gint x, gint y) { gint looplen; gint resize; gint tmp,t1,t2,t3,t4; suseconds_t tdiff; /* GdkRectangle update_rect;*/ gdouble temp, diff; g_return_if_fail (loopview != NULL); g_return_if_fail (GTK_IS_LOOPVIEW (loopview)); if (!loopview->looperdata) return; if (!loopview->looperdata->buf) return; if (loopview->button == 1){ switch (loopview->grabsel){ case 1: tmp = loopview->gloopstart; gtk_loopview_set_loopstartend(loopview, snap2grid(loopview,gtk_loopview_graphical2sample(loopview,x)), looperdata_get_loopend(loopview->looperdata)); loopview->gloopstart = gtk_loopview_sample2graphical(loopview, looperdata_get_loopstart(loopview->looperdata)); gtk_loopview_update_area(loopview,tmp,loopview->gloopstart); break; case 2: tmp = loopview->gloopend; gtk_loopview_set_loopstartend(loopview, looperdata_get_loopstart(loopview->looperdata), snap2grid(loopview,gtk_loopview_graphical2sample(loopview,x))); loopview->gloopend = gtk_loopview_sample2graphical(loopview, looperdata_get_loopend(loopview->looperdata)); gtk_loopview_update_area(loopview,tmp,loopview->gloopend); break; case 3: looplen = loopview->gloopend - loopview->gloopstart; resize = y - loopview->lastmouseY; t1 = loopview->gloopstart + 1 + x - loopview->lastmouseX - resize; t2 = loopview->gloopstart; t3 = loopview->gloopend + 1 + x - loopview->lastmouseX + resize; t4 = loopview->gloopend; gtk_loopview_set_loopstartend(loopview, snap2grid(loopview,gtk_loopview_graphical2sample(loopview,t1)), snap2grid(loopview,gtk_loopview_graphical2sample(loopview,t3))); loopview->gloopstart = gtk_loopview_sample2graphical(loopview, looperdata_get_loopstart(loopview->looperdata)); loopview->gloopend = gtk_loopview_sample2graphical(loopview, looperdata_get_loopend(loopview->looperdata)); gtk_loopview_update_area(loopview,loopview->gloopstart,t2); gtk_loopview_update_area(loopview,loopview->gloopend,t4); break; case 4: if ((abs(x - loopview->gloopend) >= abs(x - loopview->gloopstart)) && (x < loopview->gloopend)){ tmp = loopview->gloopstart; gtk_loopview_set_loopstartend(loopview, snap2grid(loopview,gtk_loopview_graphical2sample(loopview,x)), looperdata_get_loopend(loopview->looperdata)); loopview->gloopstart = gtk_loopview_sample2graphical(loopview, looperdata_get_loopstart(loopview->looperdata)); gtk_loopview_update_area(loopview,tmp,loopview->gloopstart); }else{ tmp = loopview->gloopend; gtk_loopview_set_loopstartend(loopview, looperdata_get_loopstart(loopview->looperdata), snap2grid(loopview,gtk_loopview_graphical2sample(loopview,x))); loopview->gloopend = gtk_loopview_sample2graphical(loopview, looperdata_get_loopend(loopview->looperdata)); gtk_loopview_update_area(loopview,tmp,loopview->gloopend); } break; case 5: t2 = loopview->gloopstart; t4 = loopview->gloopend; diff = looperdata_get_loopend(loopview->looperdata) - looperdata_get_loopstart(loopview->looperdata); temp = snap2grid(loopview, gtk_loopview_graphical2sample(loopview, loopview->gloopstart + 1 + x - loopview->lastmouseX)); gtk_loopview_set_loopstartend(loopview, temp, temp+diff); loopview->gloopstart = gtk_loopview_sample2graphical(loopview, looperdata_get_loopstart(loopview->looperdata)); loopview->gloopend = gtk_loopview_sample2graphical(loopview, looperdata_get_loopend(loopview->looperdata)); gtk_loopview_update_area(loopview,loopview->gloopstart,t2); gtk_loopview_update_area(loopview,loopview->gloopend,t4); break; case 6: tdiff = loopview->lastmousetime.tv_usec; int xdiff = x - loopview->lastmouseX; gettimeofday(&loopview->lastmousetime,0); tdiff -= loopview->lastmousetime.tv_usec; loopview->lastmouseX = x; temp = (double)(xdiff / (float)tdiff) * -1000.; if (fabs(temp)> .01){ looperdata_lock(loopview->looperdata); loopview->looperdata->speed = (double)(xdiff / (float)tdiff) * -1000.; looperdata_unlock(loopview->looperdata); g_signal_emit(GTK_OBJECT(loopview), gtk_loopview_signals[SIG_SPEED_CHANGED],0); } break; default: /* printf ("don't know what to do\n");*/ break; } if (loopview->grabsel != 6){ g_signal_emit(GTK_OBJECT(loopview), gtk_loopview_signals[SIG_LOOPBORDERS_CHANGED],0); } }else if (loopview->button == 2){ if ((abs(x - loopview->gzoomend) >= abs(x - loopview->gzoomstart)) && (x < loopview->gzoomend)){ tmp = loopview->gzoomstart; loopview->gzoomstart = x; gtk_loopview_update_area(loopview,tmp,loopview->gzoomstart); }else{ tmp = loopview->gzoomend; loopview->gzoomend = x; gtk_loopview_update_area(loopview,tmp,loopview->gzoomend); } g_signal_emit(GTK_OBJECT(loopview), gtk_loopview_signals[SIG_ZOOMBORDERS_CHANGED],0); }else if (loopview->button == 3){ switch (loopview->grabsel){ case 1: tmp = loopview->grecstart; gtk_loopview_set_recstartend(loopview, snap2grid(loopview,gtk_loopview_graphical2sample(loopview,x)), looperdata_get_recend(loopview->looperdata)); loopview->grecstart = gtk_loopview_sample2graphical(loopview, looperdata_get_recstart(loopview->looperdata)); gtk_loopview_update_area(loopview,tmp,loopview->grecstart); break; case 2: tmp = loopview->grecend; gtk_loopview_set_recstartend(loopview, looperdata_get_recstart(loopview->looperdata), snap2grid(loopview,gtk_loopview_graphical2sample(loopview,x))); loopview->grecend = gtk_loopview_sample2graphical(loopview, looperdata_get_recend(loopview->looperdata)); gtk_loopview_update_area(loopview,tmp,loopview->grecend); break; case 3: looplen = loopview->grecend - loopview->grecstart; resize = y - loopview->lastmouseY; t1 = loopview->grecstart + 1 + x - loopview->lastmouseX - resize; t2 = loopview->grecstart; t3 = loopview->grecend + 1 + x - loopview->lastmouseX + resize; t4 = loopview->grecend; gtk_loopview_set_recstartend(loopview, snap2grid(loopview,gtk_loopview_graphical2sample(loopview,t1)), snap2grid(loopview,gtk_loopview_graphical2sample(loopview,t3))); loopview->grecstart = gtk_loopview_sample2graphical(loopview, looperdata_get_recstart(loopview->looperdata)); loopview->grecend = gtk_loopview_sample2graphical(loopview, looperdata_get_recend(loopview->looperdata)); gtk_loopview_update_area(loopview,loopview->grecstart,t2); gtk_loopview_update_area(loopview,loopview->grecend,t4); break; case 4: if ((abs(x - loopview->grecend) >= abs(x - loopview->grecstart)) && (x < loopview->grecend)){ tmp = loopview->grecstart; gtk_loopview_set_recstartend(loopview, snap2grid(loopview,gtk_loopview_graphical2sample(loopview,x)), looperdata_get_recend(loopview->looperdata)); loopview->grecstart = gtk_loopview_sample2graphical(loopview, looperdata_get_recstart(loopview->looperdata)); gtk_loopview_update_area(loopview,tmp,loopview->grecstart); }else{ tmp = loopview->grecend; gtk_loopview_set_recstartend(loopview, looperdata_get_recstart(loopview->looperdata), snap2grid(loopview,gtk_loopview_graphical2sample(loopview,x))); loopview->grecend = gtk_loopview_sample2graphical(loopview, looperdata_get_recend(loopview->looperdata)); gtk_loopview_update_area(loopview,tmp,loopview->grecend); } break; case 5: t2 = loopview->grecstart; t4 = loopview->grecend; diff = looperdata_get_recend(loopview->looperdata) - looperdata_get_recstart(loopview->looperdata); temp = snap2grid(loopview, gtk_loopview_graphical2sample(loopview, loopview->grecstart + 1 + x - loopview->lastmouseX)); gtk_loopview_set_recstartend(loopview,temp, temp+diff); loopview->grecstart = gtk_loopview_sample2graphical(loopview, looperdata_get_recstart(loopview->looperdata)); loopview->grecend = gtk_loopview_sample2graphical(loopview, looperdata_get_recend(loopview->looperdata)); gtk_loopview_update_area(loopview,loopview->grecstart,t2); gtk_loopview_update_area(loopview,loopview->grecend,t4); break; default: /* printf ("don't know what to do\n");*/ break; } g_signal_emit(GTK_OBJECT(loopview), gtk_loopview_signals[SIG_RECBORDERS_CHANGED],0); } loopview->lastmouseX = x; loopview->lastmouseY = y; } static gint gtk_loopview_focus_in (GtkWidget * widget, GdkEventFocus * event){ g_return_val_if_fail (widget != NULL,FALSE); g_return_val_if_fail (GTK_IS_LOOPVIEW (widget),FALSE); /* printf ("focus in\n");*/ GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS); /* gtk_widget_draw_focus (widget);*/ return FALSE; } static gint gtk_loopview_focus_out (GtkWidget * widget, GdkEventFocus * event){ g_return_val_if_fail (widget != NULL,FALSE); g_return_val_if_fail (GTK_IS_LOOPVIEW (widget),FALSE); /* printf ("focus out\n");*/ GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS); /* gtk_widget_draw_focus (widget);*/ return FALSE; } static gint gtk_loopview_enter_notify (GtkWidget *widget, GdkEventCrossing *event){ /* printf ("enter\n");*/ gtk_widget_grab_focus (widget); gtk_grab_add (widget); return TRUE; } static gint gtk_loopview_leave_notify (GtkWidget *widget, GdkEventCrossing *event){ /* printf ("leave\n");*/ gtk_grab_remove(widget); return TRUE; } /* static void gtk_loopview_update (GtkLoopview *loopview) g_return_if_fail (loopview != NULL); g_return_if_fail (GTK_IS_LOOPVIEW (loopview)); gtk_widget_draw (GTK_WIDGET(loopview), NULL); } */ kluppe-0.6.14/src/frontend/kluppe/configfile.h0000644000175000017500000000213410513677003020602 0ustar dieterdieter#ifndef __CONFIGFILE_H__ #define __CONFIGFILE_H__ #include #include #include "../../common/buffer.h" #include "looper.h" typedef struct _configfile_handler { xmlDocPtr doc; xmlNodePtr kluppe; xmlNodePtr looperptr; xmlNodePtr bufferptr; long samplerate; } configfile_handler_t; int save_config (GList *looperlist, speciallist_t *bufferlist, char* spath, char* cpath, char *filename, gint x, gint y, gint width, gint height, long samplerate); char* config_check_filename (char *filename); configfile_handler_t* open_config_reader (char *filename, long samplerate); void close_config_reader (configfile_handler_t* handler); void config_get_geometry(configfile_handler_t* handler,gint* x, gint* y, gint* width, gint* height); int config_get_looper_minimized (configfile_handler_t* handler, int id); int config_next_looper (configfile_handler_t* handler); int config_read_looper (configfile_handler_t* handler, looper_gui_t *looper); int config_next_buffer (configfile_handler_t* handler); int config_read_buffer (configfile_handler_t* handler, buffer_info_t* buf); #endif kluppe-0.6.14/src/frontend/kluppe/threshdialog.h0000644000175000017500000000040310575502710021147 0ustar dieterdieter/* definitions for a threhold settings dialog */ #ifndef __THRESHDIALOG_H__ #define __THRESHDIALOG_H__ #include #include #include "../../common/looperdata.h" void threshdialog_new(GtkWidget* parent, looper_data_t *looperdata); #endif kluppe-0.6.14/src/frontend/kluppe/Makefile0000644000175000017500000000170311033633352017762 0ustar dieterdieterBIN_DIR = $(INSTALL_PREFIX)/bin PIXMAPS_DIR = $(INSTALL_PREFIX)/share/pixmaps MAN_DIR = $(INSTALL_PREFIX)/man/man1 SOURCES = sfpreview.c configfile.c griddialog.c threshdialog.c graindialog.c customcurve.c looper.c gtkmeter.c gtkloopview.c kluppe.c alphatrack_callback.c TARGETS = $(SOURCES:.c=.o) kluppe: $(TARGETS) $(CC) $(CFLAGS) -DPIXMAPS_DIR=\"$(PIXMAPS_DIR)\" *.o ../../common/*.o -o kluppe `pkg-config gtk+-2.0 gthread-2.0 libusb alsa jack sndfile liblo libxml-2.0 --libs gthread-2.0` .c.o: $(CC) $(CFLAGS) -DPIXMAPS_DIR=\"$(PIXMAPS_DIR)\" -c -o $@ $*.c `pkg-config gtk+-2.0 --cflags` `xml2-config --cflags` install: kluppe install -d $(DESTDIR)$(BIN_DIR) install -m 755 kluppe $(DESTDIR)$(BIN_DIR) install -d $(DESTDIR)$(PIXMAPS_DIR) install -m 644 kluppe.png $(DESTDIR)$(PIXMAPS_DIR) install -m 644 kluppe.xpm $(DESTDIR)$(PIXMAPS_DIR) install -d $(DESTDIR)$(MAN_DIR) install -m 644 kluppe.1 $(DESTDIR)$(MAN_DIR) clean: rm -f *.o kluppe kluppe-0.6.14/src/frontend/kluppe/configfile.c0000644000175000017500000006106410575507515020614 0ustar dieterdieter#include #include #include #include #include #include #include "../../common/looperdata.h" #include "gtkloopview.h" #include "configfile.h" char* config_check_filename (char *filename){ if (strcmp (".klp",(char*)(filename + strlen(filename) - 4))){ filename = realloc(filename, sizeof(char) * (strlen(filename) + 5)); filename = strcat(filename,".klp"); } return filename; } int save_config (GList *looperlist, speciallist_t *bufferlist, char* spath, char* cpath, char *filename, gint x, gint y, gint width, gint height, long samplerate){ xmlDocPtr doc; int err; char txt[128]; char *cmd = NULL; char *old_locale; GList *listptr = looperlist; looper_gui_t *looper = NULL; buffer_info_t *buf = NULL; xmlNodePtr topptr, looperptr, bufferptr; old_locale = setlocale(LC_NUMERIC,"C"); doc = xmlNewDoc((xmlChar*)XML_DEFAULT_VERSION); topptr = xmlNewDocNode(doc, NULL, (xmlChar*)"kluppe", NULL); xmlAddChild ((xmlNodePtr)doc, topptr); xmlNewChild (topptr, NULL, (xmlChar*)"soundfilepath", (xmlChar*)spath); xmlNewChild (topptr, NULL, (xmlChar*)"configfilepath", (xmlChar*)cpath); sprintf (txt, "%d",(int)x); xmlNewChild (topptr, NULL, (xmlChar*)"window-xpos",(xmlChar*)txt); sprintf (txt, "%d",(int)y); xmlNewChild (topptr, NULL, (xmlChar*)"window-ypos",(xmlChar*)txt); sprintf (txt, "%d",(int)width); xmlNewChild (topptr, NULL, (xmlChar*)"window-width",(xmlChar*)txt); sprintf (txt, "%d",(int)height); xmlNewChild (topptr, NULL, (xmlChar*)"window-height",(xmlChar*)txt); sprintf (txt, "%ld",samplerate); xmlNewChild (topptr, NULL, (xmlChar*)"system-samplerate",(xmlChar*)txt); while (listptr){ if ((looper = (looper_gui_t*)listptr->data) != NULL){ looperptr = xmlNewChild (topptr, NULL, (xmlChar*)"looper", NULL); sprintf (txt, "%d", looper->id); xmlNewChild (looperptr, NULL, (xmlChar*)"id", (xmlChar*)txt); sprintf (txt, "%d", looper_get_position(looper)); xmlNewChild (looperptr, NULL, (xmlChar*)"position",(xmlChar*)txt); if (looper->data){ /* BUF??? */ if (looper->data->buf){ sprintf (txt, "%d", looper->data->buf->id); xmlNewChild (looperptr, NULL, (xmlChar*)"buffer", (xmlChar*)txt); }else xmlNewChild (looperptr, NULL, (xmlChar*)"buffer", (xmlChar*)"0"); /*should use looperdatai's functions insetad of writing directly */ sprintf (txt, "%f", looper->data->vol); xmlNewChild (looperptr, NULL, (xmlChar*)"vol", (xmlChar*)txt); sprintf (txt, "%f", looper->data->pan); xmlNewChild (looperptr, NULL, (xmlChar*)"pan",(xmlChar*)txt); sprintf (txt, "%f", looper->data->panswing); xmlNewChild (looperptr, NULL, (xmlChar*)"panswing",(xmlChar*)txt); sprintf (txt, "%f", looper->data->recmix); xmlNewChild (looperptr, NULL, (xmlChar*)"recmix",(xmlChar*)txt); sprintf (txt, "%f", looper->data->speed); xmlNewChild (looperptr, NULL, (xmlChar*)"speed",(xmlChar*)txt); sprintf (txt, "%f", looper->data->playpos); xmlNewChild (looperptr, NULL, (xmlChar*)"playpos",(xmlChar*)txt); sprintf (txt, "%ld", looper->data->recpos); xmlNewChild (looperptr, NULL, (xmlChar*)"recpos",(xmlChar*)txt); sprintf (txt, "%ld", looper->data->loopstart); xmlNewChild (looperptr, NULL, (xmlChar*)"loopstart",(xmlChar*)txt); sprintf (txt, "%ld", looper->data->loopend); xmlNewChild (looperptr, NULL, (xmlChar*)"loopend",(xmlChar*)txt); sprintf (txt, "%ld", looper->data->recstart); xmlNewChild (looperptr, NULL, (xmlChar*)"recstart",(xmlChar*)txt); sprintf (txt, "%ld", looper->data->recend); xmlNewChild (looperptr, NULL, (xmlChar*)"recend",(xmlChar*)txt); sprintf (txt, "%d", looper->data->isplaying); xmlNewChild (looperptr, NULL, (xmlChar*)"isplaying",(xmlChar*)txt); sprintf (txt, "%d", looper->data->isrecording); xmlNewChild (looperptr, NULL, (xmlChar*)"isrecording",(xmlChar*)txt); sprintf (txt, "%d", looper->data->linkrec2play); xmlNewChild (looperptr, NULL, (xmlChar*)"linkrec2play",(xmlChar*)txt); sprintf (txt, "%d", looper->data->keepabsolute); xmlNewChild (looperptr, NULL, (xmlChar*)"keepabsolute",(xmlChar*)txt); sprintf (txt, "%d", looper->data->limiter); xmlNewChild (looperptr, NULL, (xmlChar*)"limiter",(xmlChar*)txt); if (gtk_toggle_button_get_active((GtkToggleButton*)looper->shuttlebutton)) xmlNewChild (looperptr, NULL, (xmlChar*)"shuttle",(xmlChar*)"1"); else xmlNewChild (looperptr, NULL, (xmlChar*)"shuttle",(xmlChar*)"0"); if (gtk_toggle_button_get_active((GtkToggleButton*)looper->minimizebutton)) xmlNewChild (looperptr, NULL, (xmlChar*)"minimized",(xmlChar*)"1"); else xmlNewChild (looperptr, NULL, (xmlChar*)"minimized",(xmlChar*)"0"); if (gtk_check_menu_item_get_active((GtkCheckMenuItem*)looper->snap2griditem)) xmlNewChild (looperptr, NULL, (xmlChar*)"snap2grid",(xmlChar*)"1"); else xmlNewChild (looperptr, NULL, (xmlChar*)"snap2grid",(xmlChar*)"0"); if (gtk_check_menu_item_get_active((GtkCheckMenuItem*)looper->showgriditem)) xmlNewChild (looperptr, NULL, (xmlChar*)"showgrid",(xmlChar*)"1"); else xmlNewChild (looperptr, NULL, (xmlChar*)"showgrid",(xmlChar*)"0"); sprintf (txt, "%.4lf",gtk_loopview_get_bpm(GTK_LOOPVIEW(looper->loopview))); xmlNewChild (looperptr, NULL, (xmlChar*)"bpm",(xmlChar*)txt); sprintf (txt, "%.4lf",gtk_loopview_get_bpb(GTK_LOOPVIEW(looper->loopview))); xmlNewChild (looperptr, NULL, (xmlChar*)"bpb",(xmlChar*)txt); sprintf (txt, "%ld",(long)gtk_loopview_get_gridoffset(GTK_LOOPVIEW(looper->loopview))); xmlNewChild (looperptr, NULL, (xmlChar*)"gridoffset",(xmlChar*)txt); sprintf (txt, "%d", looper->data->playmode); xmlNewChild (looperptr, NULL, (xmlChar*)"playmode",(xmlChar*)txt); sprintf (txt, "%d", looper->data->recmode); xmlNewChild (looperptr, NULL, (xmlChar*)"recmode",(xmlChar*)txt); sprintf (txt, "%d", looper->data->ngrains); xmlNewChild (looperptr, NULL, (xmlChar*)"ngrains",(xmlChar*)txt); sprintf (txt, "%d", looper->data->graindensity); xmlNewChild (looperptr, NULL, (xmlChar*)"graindensity",(xmlChar*)txt); sprintf (txt, "%f", looper->data->stereodiversity); xmlNewChild (looperptr, NULL, (xmlChar*)"stereodiversity",(xmlChar*)txt); sprintf (txt, "%f", looper->data->mingrainspeed); xmlNewChild (looperptr, NULL, (xmlChar*)"mingrainspeed",(xmlChar*)txt); sprintf (txt, "%f", looper->data->maxgrainspeed); xmlNewChild (looperptr, NULL, (xmlChar*)"maxgrainspeed",(xmlChar*)txt); sprintf (txt, "%ld", looper->data->mingrainlength); xmlNewChild (looperptr, NULL, (xmlChar*)"mingrainlength",(xmlChar*)txt); sprintf (txt, "%ld", looper->data->maxgrainlength); xmlNewChild (looperptr, NULL, (xmlChar*)"maxgrainlength",(xmlChar*)txt); sprintf (txt, "%d", looperdata_get_grainpitchmode(looper->data)); xmlNewChild (looperptr, NULL, (xmlChar*)"grainpitchmode",(xmlChar*)txt); sprintf (txt, "%d", looperdata_get_thresholdmode(looper->data)); xmlNewChild (looperptr, NULL, (xmlChar*)"thresholdmode",(xmlChar*)txt); sprintf (txt, "%d", looperdata_get_thresholdbuffersize(looper->data)); xmlNewChild (looperptr, NULL, (xmlChar*)"thresholdbuffersize",(xmlChar*)txt); sprintf (txt, "%lf",looperdata_get_low_threshold(looper->data)); xmlNewChild (looperptr, NULL, (xmlChar*)"low_threshold",(xmlChar*)txt); sprintf (txt, "%lf",looperdata_get_high_threshold(looper->data)); xmlNewChild (looperptr, NULL, (xmlChar*)"high_threshold",(xmlChar*)txt); sprintf (txt, "%s", buffer_get_shortname( looperdata_get_clickmode_buf(looper->data))); xmlNewChild (looperptr, NULL, (xmlChar*)"clickmode",(xmlChar*)txt); /* grainpitchbend??? */ sprintf (txt, "%d", looperdata_get_midichannel(looper->data)); xmlNewChild (looperptr, NULL, (xmlChar*)"midichannel",(xmlChar*)txt); sprintf (txt, "%ld", gtk_loopview_get_zoomstart((GtkLoopview*)looper->loopview)); xmlNewChild (looperptr, NULL, (xmlChar*)"zoomstart",(xmlChar*)txt); sprintf (txt, "%ld", gtk_loopview_get_zoomend((GtkLoopview*)looper->loopview)); xmlNewChild (looperptr, NULL, (xmlChar*)"zoomend",(xmlChar*)txt); sprintf (txt, "%d", looper->data->cm_size); xmlNewChild (looperptr, NULL, (xmlChar*)"cm_size",(xmlChar*)txt); cmd = looperdata_cm2str(looper->data,cmd); xmlNewChild (looperptr, NULL, (xmlChar*)"custommode_data",(xmlChar*)cmd); } } listptr = g_list_next(listptr); } buf = speciallist_get_first(bufferlist); while(buf){ /* printf ("saving buffer %d:%s\n",buf->id,buf->shortname);*/ bufferptr = xmlNewChild (topptr, NULL, (xmlChar*)"buffer",NULL); sprintf (txt, "%d", buf->id); xmlNewChild (bufferptr, NULL, (xmlChar*)"id",(xmlChar*)txt); xmlNewChild (bufferptr, NULL, (xmlChar*)"shortname",(xmlChar*)buf->shortname); xmlNewChild (bufferptr, NULL, (xmlChar*)"filename",(xmlChar*)buf->filename); sprintf (txt, "%d", buf->status); xmlNewChild (bufferptr, NULL, (xmlChar*)"status",(xmlChar*)txt); sprintf (txt, "%d", buffer_get_type(buf)); xmlNewChild (bufferptr, NULL, (xmlChar*)"type",(xmlChar*)txt); sprintf (txt, "%d", buffer_get_channels(buf)); xmlNewChild (bufferptr, NULL, (xmlChar*)"channels",(xmlChar*)txt); sprintf (txt, "%ld", buffer_get_size(buf)); xmlNewChild (bufferptr, NULL, (xmlChar*)"size",(xmlChar*)txt); sprintf (txt, "%lf", buffer_get_volume_factor(buf)); xmlNewChild (bufferptr, NULL, (xmlChar*)"volumefactor",(xmlChar*)txt); buf = speciallist_get_next(bufferlist,buf); } if ((err = xmlSaveFormatFile (filename, doc, TRUE)) == -1 ){ xmlFreeDoc (doc); return -1; } setlocale(LC_NUMERIC,old_locale); return 0; } configfile_handler_t* open_config_reader (char *filename, long samplerate){ configfile_handler_t *handler = (configfile_handler_t*)malloc (sizeof(configfile_handler_t)); xmlNodePtr node; LIBXML_TEST_VERSION handler->doc = xmlReadFile(filename, NULL, 0); handler->kluppe = NULL; if (!xmlDocGetRootElement(handler->doc)) return NULL; for (node = handler->doc->children; node; node = node->next) if (strcmp ((char*)node->name, (char*)"kluppe") == 0) handler->kluppe = node; handler->looperptr = NULL; handler->bufferptr = NULL; handler->samplerate = samplerate; if (handler->kluppe) return handler; else{ close_config_reader (handler); return NULL; } } void close_config_reader (configfile_handler_t* handler){ xmlFreeDoc(handler->doc); xmlCleanupParser(); } static int subnode2int (xmlNodePtr parent, const char *key){ xmlNodePtr node; xmlChar *content; int i; char * old_locale = setlocale(LC_NUMERIC,"C"); for (node = parent->children; node; node = node->next){ if (!strcmp((char*)node->name, (char*)key)){ content = xmlNodeGetContent (node); i = atoi ((char*)content); setlocale(LC_NUMERIC, old_locale); return i; } } setlocale(LC_NUMERIC, old_locale); return 0; } static long subnode2long (xmlNodePtr parent, const char *key){ xmlNodePtr node; xmlChar *content; long l; char * old_locale = setlocale(LC_NUMERIC,"C"); for (node = parent->children; node; node = node->next){ if (!strcmp((char*)node->name, (char*)key)){ content = xmlNodeGetContent (node); l = atol ((char*)content); setlocale(LC_NUMERIC, old_locale); return l; } } setlocale(LC_NUMERIC, old_locale); return 0; } static float subnode2float (xmlNodePtr parent, const char *key){ xmlNodePtr node; xmlChar *content; float f; char * old_locale = setlocale(LC_NUMERIC,"C"); for (node = parent->children; node; node = node->next){ if (!strcmp((char*)node->name, (char*)key)){ content = xmlNodeGetContent (node); f = (float)atof ((char*)content); setlocale(LC_NUMERIC, old_locale); return f; } } setlocale(LC_NUMERIC, old_locale); return 0.0; } static double subnode2double (xmlNodePtr parent, const char *key){ xmlNodePtr node; xmlChar *content; double d; char * old_locale = setlocale(LC_NUMERIC,"C"); for (node = parent->children; node; node = node->next){ if (!strcmp((char*)node->name,(char*) key)){ content = xmlNodeGetContent (node); d = atof ((char*)content); setlocale(LC_NUMERIC, old_locale); return d; } } setlocale(LC_NUMERIC, old_locale); return 0.0; } static char* subnode2string (xmlNodePtr parent, const char *key){ xmlNodePtr node; xmlChar *content; for (node = parent->children; node; node = node->next){ if (!strcmp((char*)node->name, (char*)key)){ content = xmlNodeGetContent (node); return (char*)content; } } return NULL; } void config_get_geometry(configfile_handler_t* handler,gint* x, gint* y, gint* width,gint* height){ *x = subnode2int (handler->kluppe,"window-xpos"); *y = subnode2int (handler->kluppe,"window-ypos"); *width = subnode2int (handler->kluppe,"window-width"); *height = subnode2int (handler->kluppe,"window-height"); return; } int config_next_looper (configfile_handler_t* handler){ xmlNodePtr node; int found_old = 0; if (!handler->looperptr) found_old = 1; for (node = handler->kluppe->children; node; node = node->next){ if (!strcmp((char*)node->name, (char*)"looper")){ if (found_old){ /*search and return id */ handler->looperptr = node; return subnode2int (node,"id"); }else if (node == handler->looperptr) found_old = 1; } } return 0; } int config_get_looper_minimized (configfile_handler_t* handler, int id){ xmlNodePtr node; xmlNodePtr lptr = NULL; for (node = handler->kluppe->children; node; node = node->next){ if (!strcmp((char*)node->name, (char*)"looper")) if (subnode2int(node, "id") == id) lptr = node; } if (lptr) return subnode2int(lptr,"minimized"); return 0; } int config_read_looper (configfile_handler_t* handler, looper_gui_t *looper){ xmlNodePtr node; xmlNodePtr lptr = NULL; buffer_info_t *buf; for (node = handler->kluppe->children; node; node = node->next){ if (!strcmp((char*)node->name, (char*)"looper")) if (subnode2int(node, "id") == looper->id) lptr = node; } if (looper && lptr){ /*LATER: do correct samplerate conversion */ if (looper->data && subnode2int(lptr,"buffer")){ gtk_toggle_button_set_active((GtkToggleButton*)looper->minimizebutton, (subnode2int(lptr,"minimized") ? TRUE : FALSE)); looper_set_buffer_by_id(looper,subnode2int(lptr,"buffer")); if (subnode2string(lptr,"clickmode")) looper_set_position(looper,subnode2int(lptr,"position")); looperdata_set_vol(looper->data, subnode2float(lptr,"vol")); looperdata_set_pan(looper->data, subnode2float(lptr,"pan")); looperdata_set_panswing(looper->data, subnode2float(lptr,"panswing")); looperdata_set_recmix(looper->data, subnode2float(lptr,"recmix")); looperdata_set_speed(looper->data, subnode2double(lptr,"speed")); looperdata_set_loopstart(looper->data, subnode2long(lptr,"loopstart")); looperdata_set_loopend(looper->data, subnode2long(lptr,"loopend")); looperdata_set_recstart(looper->data, subnode2long(lptr,"recstart")); looperdata_set_recend(looper->data, subnode2long(lptr,"recend")); looperdata_set_playpos(looper->data, subnode2double(lptr,"playpos")); looperdata_set_recpos(looper->data, subnode2long(lptr,"recpos")); looperdata_set_ngrains(looper->data, subnode2int(lptr,"ngrains")); looperdata_set_graindensity(looper->data, subnode2int(lptr,"graindensity")); looperdata_set_stereodiversity(looper->data, subnode2double(lptr,"stereodiversity")); looperdata_set_mingrainspeed(looper->data, subnode2double(lptr,"mingrainspeed")); looperdata_set_maxgrainspeed(looper->data, subnode2double(lptr,"maxgrainspeed")); looperdata_set_mingrainlength(looper->data, subnode2long(lptr,"mingrainlength")); looperdata_set_maxgrainlength(looper->data, subnode2long(lptr,"maxgrainlength")); looperdata_set_grainpitchmode(looper->data, subnode2int(lptr,"grainpitchmode")); looperdata_set_midichannel(looper->data, subnode2int(lptr,"midichannel")); looperdata_set_thresholdbuffersize(looper->data, subnode2int(lptr,"thresholdbuffersize")); looperdata_set_thresholdmode(looper->data, subnode2int(lptr,"thresholdmode")); looperdata_set_low_threshold(looper->data, subnode2double(lptr,"low_threshold")); looperdata_set_high_threshold(looper->data, subnode2double(lptr,"high_threshold")); if (subnode2int(lptr,"cm_size")){ looperdata_str2cm(looper->data, subnode2string (lptr,"custommode_data"), subnode2int (lptr,"cm_size")); } looperdata_set_playmode(looper->data, subnode2int(lptr,"playmode")); looperdata_set_recmode(looper->data, subnode2int(lptr,"recmode")); /* gtk_toggle_button_set_active((GtkToggleButton*)looper->limiterbutton, (subnode2int(lptr,"limiter") ? TRUE : FALSE)); */ gtk_check_menu_item_set_active((GtkCheckMenuItem*)looper->limiteritem, (subnode2int(lptr,"limiter") ? TRUE : FALSE)); gtk_check_menu_item_set_active((GtkCheckMenuItem*)looper->snap2griditem, (subnode2int(lptr,"snap2grid") ? TRUE : FALSE)); gtk_check_menu_item_set_active((GtkCheckMenuItem*)looper->showgriditem, (subnode2int(lptr,"showgrid") ? TRUE : FALSE)); gtk_check_menu_item_set_active((GtkCheckMenuItem*)looper->thresholdtoggle, (subnode2int(lptr,"thresholdmode") ? TRUE : FALSE)); gtk_toggle_button_set_active((GtkToggleButton*)looper->shuttlebutton, (subnode2int(lptr,"shuttle") ? TRUE : FALSE)); gtk_toggle_button_set_active((GtkToggleButton*)looper->recbutton, (subnode2int(lptr,"isrecording") ? TRUE : FALSE)); gtk_toggle_button_set_active((GtkToggleButton*)looper->playbutton, (subnode2int(lptr,"isplaying") ? TRUE : FALSE)); gtk_loopview_set_bpm(GTK_LOOPVIEW(looper->loopview), subnode2double(lptr,"bpm")); gtk_loopview_set_bpb(GTK_LOOPVIEW(looper->loopview), subnode2double(lptr,"bpb")); gtk_loopview_set_gridoffset(GTK_LOOPVIEW(looper->loopview), subnode2long(lptr,"gridoffset")); if (subnode2string(lptr,"clickmode")){ /* old configfiles have no clickmode*/ buf = speciallist_get_first(looper->clickmodes); /* printf ("clickmode buf #1: %p, %p\n",buf, looper->clickmodes);*/ while (buf){ if (!strcmp(buffer_get_shortname(buf), subnode2string(lptr,"clickmode"))){ looperdata_set_clickmode_buf(looper->data, buf); } buf = speciallist_get_next(looper->clickmodes,buf); } } switch (subnode2int(lptr,"playmode")){ case LOOP_PLAYMODE_LOOP: gtk_check_menu_item_set_active( (GtkCheckMenuItem*)looper->loopmode, TRUE); break; case LOOP_PLAYMODE_BACKFORTH: gtk_check_menu_item_set_active( (GtkCheckMenuItem*)looper->backforthmode, TRUE); break; case LOOP_PLAYMODE_SINE: gtk_check_menu_item_set_active( (GtkCheckMenuItem*)looper->sinewavemode, TRUE); break; case LOOP_PLAYMODE_CUSTOMSPEED: gtk_check_menu_item_set_active( (GtkCheckMenuItem*)looper->customspeedmode, TRUE); break; case LOOP_PLAYMODE_POSITION: gtk_check_menu_item_set_active( (GtkCheckMenuItem*)looper->customposmode, TRUE); break; case LOOP_PLAYMODE_ONCE: gtk_check_menu_item_set_active( (GtkCheckMenuItem*)looper->oncemode, TRUE); break; } switch (subnode2int(lptr,"recmode")){ case LOOP_RECMODE_LOOP: gtk_check_menu_item_set_active( (GtkCheckMenuItem*)looper->recloopmode, TRUE); break; case LOOP_RECMODE_ONCE: gtk_check_menu_item_set_active( (GtkCheckMenuItem*)looper->reconcemode, TRUE); break; } if (subnode2int(lptr,"zoomend")) gtk_loopview_set_zoom((GtkLoopview*)looper->loopview, subnode2long(lptr,"zoomstart"), subnode2long(lptr,"zoomend")); looper_update_widgets(looper); return looper->id; } } return 0; } int config_next_buffer (configfile_handler_t* handler){ xmlNodePtr node; int found_old = 0; if (!handler->bufferptr) found_old = 1; for (node = handler->kluppe->children; node; node = node->next){ if (!strcmp((char*)node->name, (char*)"buffer")){ if (found_old){ /*search and return id */ handler->bufferptr = node; return subnode2int (node,"id"); }else if (node == handler->bufferptr) found_old = 1; } } return 0; } int config_read_buffer (configfile_handler_t* handler, buffer_info_t* buf){ int type = 0; int file_ok = 0; char *filename; struct stat fstat; float vol = 0.; if (buf && handler->bufferptr){ type = subnode2int (handler->bufferptr,"type"); filename = subnode2string (handler->bufferptr,"filename"); if (type == BUFFER_TYPE_DISCSTREAM){ buffer_open_discstream(buf,filename,handler->samplerate); }else{ /* old configfiles don't have a type for buffers -> check for filenames */ if (filename && !stat(filename,&fstat)) file_ok = 1; if ((type == BUFFER_TYPE_FILEBUFFER) || ((type == 0) && (file_ok == 1))){ buffer_loadfile(buf,filename,handler->samplerate); }else{ buffer_resize(buf, subnode2long(handler->bufferptr,"size")); buffer_set_shortname(buf, subnode2string(handler->bufferptr,"shortname")); buffer_set_channels(buf, subnode2int(handler->bufferptr,"channels")); buf->pending = BUFFER_STATUS_READY; } } vol = subnode2double(handler->bufferptr,"volumefactor"); if(vol) buffer_set_volume_factor(buf,vol); } return 0; } kluppe-0.6.14/src/frontend/kluppe/graindialog.h0000644000175000017500000000036010247333113020747 0ustar dieterdieter/* definitions for a looper */ #ifndef __GRAINDIALOG_H__ #define __GRAINDIALOG_H__ #include #include #include "../../common/looperdata.h" void graindialog_new(GtkWidget* parent, looper_data_t* data, int id); #endif kluppe-0.6.14/src/frontend/kluppe/kluppe.c0000644000175000017500000011114511034710472017770 0ustar dieterdieter#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "looper.h" #include "../../common/jackmixer.h" #include "configfile.h" #include "sfpreview.h" #include "../../common/speciallist.h" #include "../../common/clickmodes.h" #include "../../common/alphatrack.h" #include "alphatrack_callback.h" #ifdef HAVE_ALSA #include "../../common/midi.h" #include "../../common/xsession.h" #endif #ifdef HAVE_OSC #include "../../common/osc.h" #endif #define DIR_MODE (S_IRWXU|S_IRGRP) #define DEFAULT_IDLETIME 80 /* global widgets: */ GtkWidget *globalbox; GtkWidget *footertable; GtkWidget *footerbox; GtkWidget *newlooperbutton; GtkWidget *newbufferbutton; GtkWidget *suspend_playingbutton; GtkWidget *suspend_recordingbutton; GtkWidget *newemptybufferbutton; GtkWidget *savebutton; GtkWidget *openbutton; GtkWidget *status; GtkWidget *pbar; GtkWidget *menu; GtkWidget *menu_bar; GtkWidget *file_menu; GtkWidget *help_menu; GtkWidget *edit_menu; GtkWidget *load_menu = NULL; GtkWidget *menu_items; GtkWidget *waitdialog; GtkWidget *warndialog; GtkWidget *window; /* global data */ speciallist_t *buffer_list; alphatrack_t *alphatrack = NULL; int emptybuffercounter = 0; configfile_handler_t *ch; int loadfilestate = 0; int freewheelstate = 0; int alive = 1; int countdown = 0; guint idle_id = 0; guint context = 0; guint status_id = 0; long laststatus = 0; char *lastpath = NULL; char *lastconfigfilepath = NULL; char *projectfilename = NULL; char *txt = NULL; /* buffer_list_t *buffer_list; */ looper_list_t *looperlist; speciallist_t *looperdatalist; speciallist_t *clickmode_list; int looperindexcounter = 0; int bufferindexcounter = 0; long last_pbar_action = 0; double lastuptime = 0.0; double lastidle = 0.0; float lastload = 0.0; long lastxruns = 0; jack_info_t *jack_info; #ifdef HAVE_ALSA midi_info_t *midi_info; xsession_info_t *xsession_info; #endif #ifdef HAVE_OSC osc_info_t *osc_info; #endif /*------- EVENT FUNCTIONS -------*/ void set_status (const char* message){ char* mws; laststatus = time(NULL); if (status_id) gtk_statusbar_pop ((GtkStatusbar*)status,status_id); status_id = 0; if (message) { mws = malloc (sizeof(char) * (strlen(message) + 3)); sprintf (mws," %s ",message); status_id = gtk_statusbar_push((GtkStatusbar*)status,context,(gchar*)mws); free(mws); }else{ status_id = gtk_statusbar_push((GtkStatusbar*)status,context," "); } } void destroy(GtkWidget *widget, gpointer data){ GtkWidget *dialog; gint response; dialog = gtk_message_dialog_new (GTK_WINDOW(window), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO, "are you sure you want to quit?\n"); gtk_dialog_add_button (GTK_DIALOG (dialog), "Maybe",1783); response = gtk_dialog_run (GTK_DIALOG (dialog)); gtk_widget_destroy (dialog); if (response == GTK_RESPONSE_YES){ mixer_close(jack_info); gtk_main_quit(); }else if (response == 1783){ int i = (int)(3.0*rand()/(RAND_MAX+1.0)); /* printf ("i:%d\n",i);*/ if (i == 1) gtk_main_quit(); else set_status("maybe not quitting"); }else set_status("not quitting"); } static gboolean delete_event( GtkWidget *widget, GdkEvent *event, gpointer data ){ /* Change TRUE to FALSE and the main window will be destroyed with a "delete_event". */ destroy(GTK_WIDGET(widget),data); return TRUE; } static void close_all_loopers (){ GList *tmpptr = g_list_first (looperlist->listptr); looper_gui_t *looper = NULL; while (tmpptr){ if ((looper = (looper_gui_t*)tmpptr->data) != NULL){ speciallist_delete(looperdatalist, looper->data); g_mutex_lock (looperlist->listmutex); looper_list_remove_looper(looperlist, looper); g_mutex_unlock (looperlist->listmutex); looper_close(looper); tmpptr = g_list_first (looperlist->listptr); }else tmpptr = g_list_next(tmpptr); } } static void close_all_buffers(){ buffer_info_t *buf = speciallist_get_first(buffer_list); while (buf){ speciallist_delete(buffer_list,buf); buffer_delete(buf); buf = speciallist_get_first(buffer_list); } } static void update_bufferlists(){ GList *tmpptr = NULL; looper_gui_t *looper = NULL; tmpptr = g_list_first (looperlist->listptr); /* printf ("update bufferlist\n");*/ while (tmpptr){ looper = (looper_gui_t*)tmpptr->data; if (looper != NULL){ /*should do some cleanup here maybe */ if (!looper->id){ /* printf ("looper removed from list\n");*/ speciallist_delete(looperdatalist, looper->data); g_mutex_lock(looperlist->listmutex); looper_list_remove_looper(looperlist, looper); g_mutex_unlock(looperlist->listmutex); tmpptr = looperlist->listptr; }else looper_update_bufferlist (looper,buffer_list); } tmpptr = g_list_next(tmpptr); } return; } void update_cursorpositions(){ GList *tmpptr = NULL; looper_gui_t *looper = NULL; tmpptr = g_list_first (looperlist->listptr); while (tmpptr){ looper = (looper_gui_t*)tmpptr->data; if (looper != NULL){ /*should do some cleanup here maybe */ if (!looper->id){ /* printf ("looper removed from list\n");*/ speciallist_delete(looperdatalist, looper->data); looper_list_remove_looper(looperlist, looper); tmpptr = looperlist->listptr; } else looper_update_cursorposition (looper); } tmpptr = g_list_next(tmpptr); } } void get_load (){ FILE *ufile; int ok = 0; long ut, id; int utk, idk; double uptime = 0; double idle = 0; ufile = fopen("/proc/uptime","r"); if (ufile){ ok = fscanf(ufile,"%ld.%d %ld.%d",&ut,&utk,&id,&idk); if (ok == 4){ uptime = ut + utk * .01; idle = id + idk * .01; lastload = 1.0 - (float)(idle - lastidle) / (float)(uptime - lastuptime) ; /* printf ("up:%.2lf, %.2lf, idle:%.2lf, %.2lf, lastload:%.2lf ", uptime,lastuptime,idle,lastidle,lastload);*/ lastuptime = uptime; lastidle = idle; /* if (!(0.0 < lastload <= 1.0)) lastload = 0.0;*/ if (!((lastload > 0.0) && ((lastload < 1.0) || (lastload == 1.0)))) lastload = 0.0; /* printf ("lastload after:%.2lf\n",lastload);*/ } fclose(ufile); } } /* ------------- dialog functions --------------*/ static gint confirm_error (GtkWidget *parent, char *fmt, ...) { va_list args; gint response = 0; GtkWidget *edialog; char *message = malloc(256 * sizeof(char)); va_start(args,fmt); vsnprintf(message,255,fmt,args); va_end(args); edialog = gtk_message_dialog_new (GTK_WINDOW(parent), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, message); gtk_widget_show(GTK_WIDGET(edialog)); g_signal_connect_swapped (edialog, "response", G_CALLBACK (gtk_widget_destroy), edialog); free(message); return response; } static gint confirm_overwrite (GtkWidget *parent, const gchar *filename){ GtkWidget *dialog; gint response; dialog = gtk_message_dialog_new (GTK_WINDOW (parent), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE, "\"%s\" already exists. Do you want to replace it ?", filename); gtk_dialog_add_buttons (GTK_DIALOG (dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, "_Replace", GTK_RESPONSE_ACCEPT, NULL); response = gtk_dialog_run (GTK_DIALOG (dialog)); gtk_widget_destroy (dialog); return response; } /* main loop function: */ gint main_idlefunc(gpointer data){ buffer_info_t *buf; buffer_info_t *tbuf; GList *tmpptr = NULL; looper_gui_t *looper; gboolean looper_dirty = FALSE; int not_ready = 0; int ti; long thetime = time(NULL); /* go through buffers and look for changes if buffermutex is available*/ buf = speciallist_get_first(buffer_list); if (alive && !jack_info->alive){ alive = jack_info->alive; confirm_error(window,"jack kicked us out.\n please save and restart.\n"); } if (!alive) set_status ("no jack - no playback !"); while (buf){ if (buf->pending == BUFFER_STATUS_READY){ gtk_progress_bar_update ((GtkProgressBar*)pbar,buf->percent_filled); /* printf ("%s... bufferloading finished\n",buf->shortname);*/ /* this would be the place for size and mono/stereo in shortname */ set_status ("buffer ready"); last_pbar_action = thetime; looper_dirty = TRUE; } if (buf->pending && (buf->pending != buf->status)){ buffer_lock(buf); buf->status = buf->pending; buf->pending = 0; buffer_unlock(buf); } if (buf->status == BUFFER_STATUS_LOADING){ gtk_progress_bar_update ((GtkProgressBar*)pbar,buf->percent_filled); gtk_progress_bar_set_text ((GtkProgressBar*)pbar,"buffer loading"); last_pbar_action = thetime; set_status ("loading file"); } if (buf->status == BUFFER_STATUS_DEAD){ /* this should only happen when loading fails*/ set_status ("loading failed!"); if (buf->error == BUFFER_ERROR_ALLOC) confirm_error (window, "loading of %s failed \nnot enough memory",buf->shortname); else if (buf->error == BUFFER_ERROR_NOSF) confirm_error (window, "could not read soundfile %s\n",buf->shortname); else confirm_error (window, "could not load soundfile %s",buf->filename); tbuf = speciallist_get_next(buffer_list,buf); speciallist_delete(buffer_list,buf); buf = tbuf; /* LATER: clean up buf */ } else { if (!(buf->status == BUFFER_STATUS_READY)) not_ready++; buf = speciallist_get_next(buffer_list,buf); } } if (countdown) countdown--; else if (loadfilestate == 1){ /* gint x,y,w,h;*/ /* printf ("stage 1\n");*/ /* config_get_geometry(ch, &x,&y,&w,&h); gtk_window_resize((GtkWindow*)window,w,h); gtk_window_move((GtkWindow*)window,x,y); */ while ((ti = config_next_buffer(ch)) != 0){ if (bufferindexcounter < ti) bufferindexcounter = ti; buf = buffer_new(ti,jack_info->samplerate); config_read_buffer (ch,buf); /* printf ("buffer nr:%d created\n",ti);*/ if (buffer_get_status(buf) != BUFFER_STATUS_DEAD) speciallist_append(buffer_list,buf); else confirm_error(window,"could not load %s",buf->filename); } buf = speciallist_get_first(buffer_list); while (buf){ buf = speciallist_get_next(buffer_list,buf); } loadfilestate++; }else if (!not_ready && (loadfilestate == 2)){ while ((ti = config_next_looper(ch)) != 0){ /* printf ("new looper:%d\n",ti);*/ if (looperindexcounter < ti) looperindexcounter = ti; looper = looper_new(window, globalbox, alphatrack, looperdatalist, clickmode_list, ti, config_get_looper_minimized (ch, ti)); if (jack_info->samplerate) looper_set_samplerate(looper,jack_info->samplerate); looper_list_append_looper(looperlist, looper); speciallist_append(looperdatalist, looper->data); gtk_box_pack_start (GTK_BOX (globalbox), looper->mainbox, FALSE, FALSE, 0); looper_update_bufferlist(looper,buffer_list); } /* printf ("stage 2\n");*/ loadfilestate++; countdown = 5; /* wait a while to settle widgets */ }else if (loadfilestate == 3){ gint x,y,w,h; /* printf ("stage 3\n");*/ tmpptr = g_list_first (looperlist->listptr); while (tmpptr){ looper = (looper_gui_t*)tmpptr->data; if (looper != NULL) if (looper->id) config_read_looper (ch,looper); tmpptr = g_list_next(tmpptr); } config_get_geometry(ch, &x,&y,&w,&h); gtk_window_move((GtkWindow*)window,x,y); gtk_window_resize((GtkWindow*)window,w,h); /* printf ("w:%d, h:%d, x:%d, y:%d\n",w,h,x,y);*/ gtk_widget_destroy (waitdialog); loadfilestate = 0; set_status("project loaded"); close_config_reader(ch); } /* reset statusbar if inactive for 2+ seconds */ if ((thetime - last_pbar_action) > 1){ last_pbar_action = thetime; /* change idle scheduling to relax at high loads*/ get_load(); /* timeout version: */ if (idle_id) g_source_remove (idle_id); if (lastload > .4) idle_id = g_timeout_add((guint)(lastload * 100),(GSourceFunc)main_idlefunc,NULL); else idle_id = g_timeout_add(DEFAULT_IDLETIME,(GSourceFunc)main_idlefunc,NULL); txt = realloc(txt,sizeof(char) * 256); memset (txt,0,255); snprintf(txt,255,"cpu load:%.1f%%",(float)(lastload * 100.)); gtk_progress_bar_set_text ((GtkProgressBar*)pbar,txt); gtk_progress_bar_update ((GtkProgressBar*)pbar,lastload); } if (jack_info->freewheeling != freewheelstate){ freewheelstate = jack_info->freewheeling; if (freewheelstate) set_status("entering free wheeling mode"); else set_status("leaving free wheeling mode"); } if (jack_info->xruns != lastxruns){ lastxruns = jack_info->xruns; txt = realloc(txt,sizeof(char) * 256); memset (txt,0,255); snprintf(txt,255,"XRUN! [%ld xruns total]",lastxruns); set_status (txt); } if (looper_dirty) update_bufferlists(); update_cursorpositions(); if ((thetime - laststatus) > 10) set_status(NULL); /* g_usleep(25000);*/ g_thread_yield(); return 1; } /*-------GUI CREATE FUNCTIONS----------*/ static char* loadbufferdialog(char* filename){ GtkWidget *gfc; GtkWidget *sfp; struct stat fstat; gfc = gtk_file_chooser_dialog_new("select a soundfile for the new buffer", GTK_WINDOW(window), GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL); sfp = sfpreview_new(); g_signal_connect (G_OBJECT (gfc), "update-preview", G_CALLBACK (sfpreview_update), (gpointer) sfp); gtk_file_chooser_set_use_preview_label(GTK_FILE_CHOOSER (gfc),FALSE); gtk_file_chooser_set_preview_widget(GTK_FILE_CHOOSER (gfc),GTK_WIDGET(sfp)); gtk_file_chooser_set_show_hidden(GTK_FILE_CHOOSER (gfc),TRUE); if (lastpath) gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (gfc),lastpath); /* LATER: add a preview-function to listen to files in advance, and a GtkFileFilter */ if (gtk_dialog_run (GTK_DIALOG (gfc)) == GTK_RESPONSE_ACCEPT){ filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (gfc)); if (stat (filename, &fstat)){ printf ("file not found!\n"); if(filename) free(filename); filename = NULL; } } gtk_widget_destroy (sfp); gtk_widget_destroy (gfc); return filename; } static void load_buffer(gpointer data){ char *filename = NULL; buffer_info_t *buf = NULL; char* pathend = NULL; filename = loadbufferdialog (filename); if (filename){ pathend = strrchr (filename, '/'); if (pathend){ lastpath = realloc (lastpath,sizeof(char) * (pathend - filename + 2)); strncpy (lastpath, filename, (pathend - filename + 1)); strncpy ((char*)(lastpath + (long)(pathend - filename + 1)),"\0",1); } buf = buffer_new(++bufferindexcounter,jack_info->samplerate); if (jack_info->samplerate){ buffer_loadfile(buf,(char*)filename,jack_info->samplerate); } speciallist_append(buffer_list,buf); } else set_status("loading failed"); g_free (filename); } static void open_discstream(gpointer data){ char *filename = NULL; buffer_info_t *buf = NULL; char* pathend = NULL; filename = loadbufferdialog (filename); if (filename){ pathend = strrchr (filename, '/'); if (pathend){ lastpath = realloc (lastpath,sizeof(char) * (pathend - filename + 2)); strncpy (lastpath, filename, (pathend - filename + 1)); strncpy ((char*)(lastpath + (long)(pathend - filename + 1)),"\0",1); } buf = buffer_new(++bufferindexcounter,jack_info->samplerate); if (jack_info->samplerate){ buffer_open_discstream(buf,(char*)filename,jack_info->samplerate); } speciallist_append(buffer_list,buf); } else set_status("loading failed"); g_free (filename); } static void suspend_playing(gpointer data){ GtkWidget* suspend_playingbutton = (GtkWidget*)data; if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(suspend_playingbutton))) jack_info->suspend_playing = 1; else jack_info->suspend_playing = 0; } static void suspend_recording(gpointer data){ GtkWidget* suspend_recordingbutton = (GtkWidget*)data; if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(suspend_recordingbutton))) jack_info->suspend_recording = 1; else jack_info->suspend_recording = 0; } static void open_project (char *filename){ char* pathend = NULL; struct stat fstat; if (stat (filename, &fstat)) printf ("file not found!\n"); else{ pathend = strrchr (filename, '/'); if (pathend){ lastconfigfilepath = realloc (lastconfigfilepath,sizeof(char) * (pathend - filename + 2)); strncpy (lastconfigfilepath, filename, (pathend - filename + 1)); strncpy ((char*)(lastconfigfilepath + (long)(pathend - filename + 1)),"\0",1); } if ((ch = open_config_reader(filename,jack_info->samplerate)) != NULL){ projectfilename = realloc (projectfilename, sizeof(char) * (strlen(filename) +1)); strcpy (projectfilename,filename); waitdialog = gtk_message_dialog_new (GTK_WINDOW (window), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_INFO, GTK_BUTTONS_NONE, "please wait while loading \n \"%s\"", filename); gtk_widget_show_all (waitdialog); gtk_window_set_transient_for(GTK_WINDOW (waitdialog),GTK_WINDOW (window)); txt = realloc(txt,sizeof(char) * 256); memset(txt,0,255); snprintf(txt,255,"%s : %s",jack_info->name, filename); gtk_window_set_title(GTK_WINDOW(window),(gchar*)txt); close_all_loopers(); close_all_buffers(); looperindexcounter = 0; bufferindexcounter = 0; loadfilestate = 1; countdown = 5; } else { /* warndialog = gtk_message_dialog_new (GTK_WINDOW (window), GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "Error loading file '%s'", filename); gtk_dialog_run (GTK_DIALOG (warndialog)); gtk_widget_destroy (warndialog); printf ("could not read config file!\n"); */ set_status("loading failed"); } } } static void about_callback(gpointer data){ GtkWidget *dialog; gint response; dialog = gtk_message_dialog_new (GTK_WINDOW(window), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE, "kluppe looper is developed by dieter kovacic\n" "http://kluppe.klingt.org\n" "contact: kluppe" "@" "klingt.org.\n"); response = gtk_dialog_run (GTK_DIALOG (dialog)); gtk_widget_destroy (dialog); } static void open_project_menucallback(gpointer data){ GtkWidget *gfc; gfc = gtk_file_chooser_dialog_new("select a projectfile to be loaded", GTK_WINDOW(window), GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL); gtk_file_chooser_set_show_hidden(GTK_FILE_CHOOSER (gfc),TRUE); if (lastconfigfilepath) gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (gfc),lastconfigfilepath); if (gtk_dialog_run (GTK_DIALOG (gfc)) == GTK_RESPONSE_ACCEPT){ char *filename; filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (gfc)); open_project (filename); g_free (filename); } gtk_widget_destroy (gfc); } static void new_project(){ close_all_loopers(); close_all_buffers(); looperindexcounter = 0; bufferindexcounter = 0; if (projectfilename){ free(projectfilename); projectfilename = NULL; } } static void new_project_menucallback(gpointer data){ GtkWidget *dialog; gint response; dialog = gtk_message_dialog_new (GTK_WINDOW(window), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO, "do you really want to close\n" "this project and remove all buffers?\n"); response = gtk_dialog_run (GTK_DIALOG (dialog)); gtk_widget_destroy (dialog); if (response == GTK_RESPONSE_YES){ new_project(); set_status("project colsed"); }else set_status("not coling project"); } static void save_project_as_menucallback(gpointer data){ GtkWidget *gfc; char* pathend = NULL; struct stat fstat; int ret; gint x,y,w,h; gint response = 0; gfc = gtk_file_chooser_dialog_new("select a projectfilename for saving", GTK_WINDOW(window), GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, NULL); gtk_file_chooser_set_show_hidden(GTK_FILE_CHOOSER (gfc),TRUE); if (lastconfigfilepath) gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (gfc),lastconfigfilepath); if (gtk_dialog_run (GTK_DIALOG (gfc)) == GTK_RESPONSE_ACCEPT){ char *filename; filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (gfc)); filename = config_check_filename(filename); response = GTK_RESPONSE_ACCEPT; if (!stat (filename, &fstat)) response = confirm_overwrite(window,(gchar*)filename); if (response == GTK_RESPONSE_ACCEPT){ /* gtk_window_get_position () to save position too ??? */ gtk_window_get_size(GTK_WINDOW (window),&w,&h); gtk_window_get_position(GTK_WINDOW (window),&x,&y); ret = save_config (looperlist->listptr, buffer_list, lastpath, lastconfigfilepath, filename,x,y,w,h,jack_info->samplerate); if (ret < 0) set_status("saving failed !"); else { projectfilename = realloc (projectfilename, sizeof(char) * (strlen(filename) +1)); strcpy (projectfilename,filename); printf ("filename:%s\n",projectfilename); set_status ("project saved"); snprintf(txt,255,"%s : %s",jack_info->name, filename); gtk_window_set_title(GTK_WINDOW(window),(gchar*)txt); } pathend = strrchr (filename, '/'); if (pathend){ lastconfigfilepath = realloc (lastconfigfilepath,sizeof(char) * (pathend - filename + 2)); strncpy (lastconfigfilepath, filename, (pathend - filename + 1)); strncpy ((char*)(lastconfigfilepath + (long)(pathend - filename + 1)),"\0",1); } } g_free (filename); } gtk_widget_destroy (gfc); } static void save_project_menucallback(gpointer data){ int ret = 0; gint x,y,w,h; gtk_window_get_size(GTK_WINDOW (window),&w,&h); gtk_window_get_position(GTK_WINDOW (window),&x,&y); if (projectfilename) ret = save_config (looperlist->listptr, buffer_list, lastpath, lastconfigfilepath, projectfilename,x,y,w,h,jack_info->samplerate); else save_project_as_menucallback(data); if (ret < 0) set_status("saving failed !"); } static void create_empty_buffer(gpointer data){ GtkWidget *dialog, *label1, *label2, *label3, *nameline ,*stereo, *spin; GtkAdjustment *adj; /* gint result;*/ buffer_info_t *buf; /* char* shortname = malloc (sizeof(char) * 255);*/ label1 = gtk_label_new ("\ncreate a new buffer with"); adj = (GtkAdjustment *) gtk_adjustment_new (10.0, 0.0, 1000.0, 1, .1, 2); spin = gtk_spin_button_new (adj, 1, 4); stereo = gtk_check_button_new_with_label ("stereo"); txt = realloc(txt,sizeof(char) * 256); memset(txt,0,sizeof(char) * 255); sprintf (txt,"MB: buffer nr. %d",++bufferindexcounter); nameline = gtk_entry_new(); gtk_entry_set_max_length((GtkEntry*)nameline,255); gtk_entry_set_text((GtkEntry*)nameline,(gchar*)txt); gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(stereo),TRUE); label2 = gtk_label_new ("seconds size.\n"); label3 = gtk_label_new ("name:"); dialog = gtk_dialog_new_with_buttons ("create empty buffer", (GtkWindow*)window, GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, NULL); gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox),label1); gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox),spin); gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox),label2); gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox),stereo); gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox),label3); gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox),nameline); gtk_widget_show_all (dialog); if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT){ buf = buffer_new(bufferindexcounter,jack_info->samplerate); buffer_lock(buf); buf->pending = BUFFER_STATUS_LOADING; if (jack_info->samplerate) buffer_resize (buf, (long)(gtk_spin_button_get_value ((GtkSpinButton*)spin) * jack_info->samplerate)); /* printf ("i'm here:%ld\n",buffer_get_size(buf));*/ if (buffer_get_size(buf)){ buffer_set_shortname(buf,(char*)gtk_entry_get_text((GtkEntry*)nameline)); buf->pending = BUFFER_STATUS_READY; }else{ buffer_set_shortname(buf,"empty buffer"); buf->pending = BUFFER_STATUS_DEAD; } if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(stereo))) buffer_set_channels(buf,1); else buffer_set_channels(buf,2); buffer_unlock(buf); speciallist_append(buffer_list,buf); } gtk_widget_destroy (dialog); set_status ("buffer created"); } static void create_looper(gpointer data){ looper_gui_t *loop = looper_new(window, globalbox, alphatrack, looperdatalist, clickmode_list, ++looperindexcounter, 0); /* printf ("counter:%d\n",looperindexcounter);*/ if (jack_info->samplerate) looper_set_samplerate(loop,jack_info->samplerate); looper_list_append_looper(looperlist, loop); speciallist_append(looperdatalist, loop->data); gtk_box_pack_start (GTK_BOX (globalbox), loop->mainbox, FALSE, FALSE, 0); looper_update_bufferlist(loop,buffer_list); set_status("new looper created"); } static void create_mainlayout(){ /* footer */ footerbox = gtk_hbox_new (FALSE,3); /* http://developer.gnome.org/doc/API/2.0/gtk/GtkUIManager.html */ newlooperbutton = gtk_button_new_with_label (" new looper "); g_signal_connect (G_OBJECT(newlooperbutton), "clicked", G_CALLBACK(create_looper), NULL); gtk_box_pack_start (GTK_BOX (footerbox),newlooperbutton,FALSE, FALSE, 0); gtk_widget_show (newlooperbutton); newbufferbutton = gtk_button_new_with_label (" new buffer from file "); g_signal_connect (G_OBJECT(newbufferbutton), "clicked", G_CALLBACK(load_buffer), NULL); gtk_box_pack_start (GTK_BOX (footerbox),newbufferbutton,FALSE, FALSE, 0); gtk_widget_show (newbufferbutton); newbufferbutton = gtk_button_new_with_label (" new discstream "); g_signal_connect (G_OBJECT(newbufferbutton), "clicked", G_CALLBACK(open_discstream), NULL); gtk_box_pack_start (GTK_BOX (footerbox),newbufferbutton,FALSE, FALSE, 0); gtk_widget_show (newbufferbutton); newemptybufferbutton = gtk_button_new_with_label (" new empty buffer "); g_signal_connect (G_OBJECT(newemptybufferbutton), "clicked", G_CALLBACK(create_empty_buffer), NULL); gtk_box_pack_start (GTK_BOX (footerbox),newemptybufferbutton,FALSE, FALSE, 0); gtk_widget_show (newemptybufferbutton); suspend_playingbutton = gtk_toggle_button_new_with_label (" suspend playback "); g_signal_connect (G_OBJECT(suspend_playingbutton), "toggled", G_CALLBACK(suspend_playing), NULL); gtk_box_pack_start (GTK_BOX (footerbox),suspend_playingbutton,FALSE, FALSE, 0); gtk_widget_show (suspend_playingbutton); suspend_recordingbutton = gtk_toggle_button_new_with_label (" suspend rec. "); g_signal_connect (G_OBJECT(suspend_recordingbutton), "toggled", G_CALLBACK(suspend_recording), NULL); gtk_box_pack_start (GTK_BOX (footerbox),suspend_recordingbutton,FALSE, FALSE, 0); gtk_widget_show (suspend_recordingbutton); status = gtk_statusbar_new(); gtk_statusbar_set_has_resize_grip((GtkStatusbar*)status, TRUE); gtk_box_pack_start (GTK_BOX (footerbox),status, TRUE, TRUE, 0); gtk_widget_set_size_request (status,200,10); /* was 250,10 */ gtk_widget_show (status); context = gtk_statusbar_get_context_id ((GtkStatusbar*)status,"mainwindow"); pbar = gtk_progress_bar_new(); gtk_box_pack_start (GTK_BOX (footerbox),pbar, TRUE, TRUE, 0); gtk_widget_set_size_request (pbar,150,10); /* was 400,10 */ gtk_widget_show (pbar); gtk_widget_show (footerbox); /* top menu */ menu = gtk_menu_new (); menu_items = gtk_menu_item_new_with_label ("new empty project"); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_items); g_signal_connect_swapped (G_OBJECT (menu_items), "activate", G_CALLBACK (new_project_menucallback),NULL); gtk_widget_show (menu_items); menu_items = gtk_menu_item_new_with_label ("open project"); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_items); g_signal_connect_swapped (G_OBJECT (menu_items), "activate", G_CALLBACK (open_project_menucallback),NULL); gtk_widget_show (menu_items); menu_items = gtk_menu_item_new_with_label ("save project as..."); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_items); g_signal_connect_swapped (G_OBJECT (menu_items), "activate", G_CALLBACK (save_project_as_menucallback),NULL); gtk_widget_show (menu_items); menu_items = gtk_menu_item_new_with_label ("save project"); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_items); /* gtk_widget_set_sensitive (menu_items, FALSE);*/ g_signal_connect_swapped (G_OBJECT (menu_items), "activate", G_CALLBACK (save_project_menucallback),NULL); gtk_widget_show (menu_items); menu_items = gtk_separator_menu_item_new(); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_items); gtk_widget_show (menu_items); menu_items = gtk_menu_item_new_with_label ("quit"); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_items); g_signal_connect_swapped (G_OBJECT (menu_items), "activate", G_CALLBACK (destroy), (gpointer) "quit"); gtk_widget_show (menu_items); file_menu = gtk_menu_item_new_with_label ("File"); gtk_widget_show (file_menu); gtk_menu_item_set_submenu (GTK_MENU_ITEM (file_menu), menu); menu_bar = gtk_menu_bar_new (); gtk_menu_shell_append (GTK_MENU_SHELL (menu_bar), file_menu); /* edit menu */ menu = gtk_menu_new (); menu_items = gtk_menu_item_new_with_label ("new looper"); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_items); g_signal_connect_swapped (G_OBJECT (menu_items), "activate", G_CALLBACK (create_looper), NULL); gtk_widget_show (menu_items); menu_items = gtk_menu_item_new_with_label ("new buffer from file"); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_items); g_signal_connect_swapped (G_OBJECT (menu_items), "activate", G_CALLBACK (load_buffer), NULL); gtk_widget_show (menu_items); menu_items = gtk_menu_item_new_with_label ("new discstream"); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_items); g_signal_connect_swapped (G_OBJECT (menu_items), "activate", G_CALLBACK (open_discstream), NULL); gtk_widget_show (menu_items); menu_items = gtk_menu_item_new_with_label ("new empty buffer"); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_items); g_signal_connect_swapped (G_OBJECT (menu_items), "activate", G_CALLBACK (create_empty_buffer), NULL); gtk_widget_show (menu_items); edit_menu = gtk_menu_item_new_with_label ("Edit"); gtk_widget_show (edit_menu); gtk_menu_item_set_submenu (GTK_MENU_ITEM (edit_menu), menu); /* menu_items = gtk_separator_menu_item_new(); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_items); gtk_widget_show (menu_items); */ gtk_menu_shell_append (GTK_MENU_SHELL (menu_bar), edit_menu); /* help menu */ menu = gtk_menu_new (); menu_items = gtk_menu_item_new_with_label ("about"); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_items); g_signal_connect_swapped (G_OBJECT (menu_items), "activate", G_CALLBACK (about_callback), NULL); gtk_widget_show (menu_items); help_menu = gtk_menu_item_new_with_label ("Help"); gtk_widget_show (help_menu); gtk_menu_item_set_submenu (GTK_MENU_ITEM (help_menu), menu); /* finalize: */ gtk_menu_shell_append (GTK_MENU_SHELL (menu_bar), help_menu); gtk_widget_show (menu_bar); /* main area */ globalbox = gtk_vbox_new (FALSE,0); gtk_widget_show (globalbox); gtk_box_pack_start (GTK_BOX (globalbox), menu_bar, FALSE, FALSE, 0); /* gtk_box_pack_end (GTK_BOX (globalbox), footertable, FALSE, FALSE, 0);*/ gtk_box_pack_end (GTK_BOX (globalbox), footerbox, FALSE, FALSE, 0); set_status("welcome"); } /*--------MAIN--------*/ int main(int argc, char *argv[]) { int retval/*, count = 0*/; const char *defaultdir = NULL; struct stat fstat; defaultdir = g_get_home_dir (); defaultdir = g_strconcat (defaultdir,"/.kluppe",NULL); /* global data initialisation */ buffer_list = speciallist_new(); looperdatalist = speciallist_new(); /* start the loadbuffer thread */ buffer_discthread_launch(buffer_list); #ifdef HAVE_ALSA /* create midi thread: */ midi_info = midi_info_new(looperdatalist); /* xsession somehow interferes with note-off events - check before enabling while (!midi_info->seq && (count++ < 10000)) usleep(10); xsession_info = xsession_new(looperdatalist, midi_info->seq); */ #endif #ifdef HAVE_OSC osc_info = osc_info_new(looperdatalist); #endif /* start the jack threads */ jack_info = mixer_launch(looperdatalist); g_thread_init(NULL); gdk_threads_init(); /* gdk_threads_enter();*/ gtk_init(&argc, &argv); looperlist = looper_list_new(); /*alphatrack: */ alphatrack = alphatrack_new(); if (alphatrack){ alphatrack_set_event_callback(alphatrack,alphatrack_event_callback,looperlist); alphatrack_write_lcd(alphatrack,"kluppe says hi! ",0,0); alphatrack_write_lcd(alphatrack," ",0,1); alphatrack_set_faderpos(alphatrack,0); alphatrack_clear_leds(alphatrack); } /* create main gui elements */ window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title (GTK_WINDOW (window), jack_info->name); g_signal_connect(window, "destroy",G_CALLBACK(destroy), NULL); g_signal_connect (G_OBJECT (window), "delete_event",G_CALLBACK (delete_event), NULL); /* gtk_container_set_border_width(GTK_CONTAINER (window), 10);*/ create_mainlayout(); gtk_container_add(GTK_CONTAINER(window), globalbox); /* load the icon for the window; here we just load one, default icon */ gtk_window_set_default_icon_from_file (PIXMAPS_DIR "/kluppe.png",NULL); /* gtk_window_set_icon (GTK_WINDOW (window), gdk_pixbuf_new_from_file ("kluppe.png",NULL));*/ gtk_widget_show (window); if (!jack_info->samplerate){ confirm_error(window,"could not connect to jack!\n no playback/recording possible."); jack_info->samplerate = 44100; } if (!jack_info->alive) alive = 0; clickmode_list = clickmodes_create(jack_info->samplerate); /* idle callback looks for changes in buffers and loopers */ /* timeout version: */ idle_id = g_timeout_add(DEFAULT_IDLETIME,(GSourceFunc)main_idlefunc,NULL); /* idle version (eats a lot of cpu */ /* gtk_idle_add_priority(G_PRIORITY_LOW,main_idlefunc,NULL);*/ retval = mkdir(defaultdir, DIR_MODE); if (retval) if (errno != EEXIST) printf ("%s %s\n",defaultdir,strerror(errno)); if (!stat(defaultdir, &fstat)) { lastconfigfilepath = malloc (sizeof(char) * (strlen(defaultdir) + 1)); strcpy (lastconfigfilepath, defaultdir); } if (argc > 1) open_project(argv[1]); gtk_main(); /* gdk_threads_leave();*/ mixer_close(jack_info); printf ("bye\n"); return 0; } kluppe-0.6.14/src/frontend/kluppe/gtkmeter.c0000644000175000017500000003355510204256334020322 0ustar dieterdieter/* * Copyright (C) 2003 Steve Harris * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * $Id: gtkmeter.c,v 1.6 2003/11/19 15:28:17 theno23 Exp $ */ #include #include #include #include #include "gtkmeter.h" #define METER_DEFAULT_WIDTH 10 #define METER_DEFAULT_LENGTH 150 /* Forward declarations */ static void gtk_meter_class_init (GtkMeterClass *klass); static void gtk_meter_init (GtkMeter *meter); static void gtk_meter_destroy (GtkObject *object); static void gtk_meter_realize (GtkWidget *widget); static void gtk_meter_size_request (GtkWidget *widget, GtkRequisition *requisition); static void gtk_meter_size_allocate (GtkWidget *widget, GtkAllocation *allocation); static gint gtk_meter_expose (GtkWidget *widget, GdkEventExpose *event); static void gtk_meter_update (GtkMeter *meter); static void gtk_meter_adjustment_changed (GtkAdjustment *adjustment, gpointer data); static void gtk_meter_adjustment_value_changed (GtkAdjustment *adjustment, gpointer data); static float iec_scale(float db); /* Local data */ static GtkWidgetClass *parent_class = NULL; guint gtk_meter_get_type () { static guint meter_type = 0; if (!meter_type) { GtkTypeInfo meter_info = { "GtkMeter", sizeof (GtkMeter), sizeof (GtkMeterClass), (GtkClassInitFunc) gtk_meter_class_init, (GtkObjectInitFunc) gtk_meter_init, /*(GtkArgSetFunc)*/ NULL, /*(GtkArgGetFunc)*/ NULL, }; meter_type = gtk_type_unique (gtk_widget_get_type (), &meter_info); } return meter_type; } static void gtk_meter_class_init (GtkMeterClass *class) { GtkObjectClass *object_class; GtkWidgetClass *widget_class; object_class = (GtkObjectClass*) class; widget_class = (GtkWidgetClass*) class; parent_class = gtk_type_class (gtk_widget_get_type ()); object_class->destroy = gtk_meter_destroy; widget_class->realize = gtk_meter_realize; widget_class->expose_event = gtk_meter_expose; widget_class->size_request = gtk_meter_size_request; widget_class->size_allocate = gtk_meter_size_allocate; } static void gtk_meter_init (GtkMeter *meter) { meter->button = 0; meter->direction = GTK_METER_UP; meter->timer = 0; meter->amber_level = -6.0f; meter->amber_frac = 0.0f; meter->iec_lower = 0.0f; meter->iec_upper = 0.0f; meter->old_value = 0.0; meter->old_lower = 0.0; meter->old_upper = 0.0; meter->adjustment = NULL; } GtkWidget* gtk_meter_new (GtkAdjustment *adjustment, gint direction) { GtkMeter *meter; meter = gtk_type_new (gtk_meter_get_type ()); if (!adjustment) adjustment = (GtkAdjustment*) gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0); gtk_meter_set_adjustment (meter, adjustment); meter->direction = direction; gtk_object_ref(GTK_OBJECT(meter)); return GTK_WIDGET (meter); } static void gtk_meter_destroy (GtkObject *object) { GtkMeter *meter; g_return_if_fail (object != NULL); g_return_if_fail (GTK_IS_METER (object)); meter = GTK_METER (object); if (meter->adjustment) gtk_object_unref (GTK_OBJECT (meter->adjustment)); if (GTK_OBJECT_CLASS (parent_class)->destroy) (* GTK_OBJECT_CLASS (parent_class)->destroy) (object); } GtkAdjustment* gtk_meter_get_adjustment (GtkMeter *meter) { g_return_val_if_fail (meter != NULL, NULL); g_return_val_if_fail (GTK_IS_METER (meter), NULL); return meter->adjustment; } void gtk_meter_set_adjustment (GtkMeter *meter, GtkAdjustment *adjustment) { g_return_if_fail (meter != NULL); g_return_if_fail (GTK_IS_METER (meter)); if (meter->adjustment) { gtk_signal_disconnect_by_data (GTK_OBJECT (meter->adjustment), (gpointer) meter); gtk_object_unref (GTK_OBJECT (meter->adjustment)); } meter->adjustment = adjustment; gtk_object_ref (GTK_OBJECT (meter->adjustment)); gtk_signal_connect (GTK_OBJECT (adjustment), "changed", (GtkSignalFunc) gtk_meter_adjustment_changed, (gpointer) meter); gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed", (GtkSignalFunc) gtk_meter_adjustment_value_changed, (gpointer) meter); meter->old_value = adjustment->value; meter->old_lower = adjustment->lower; meter->old_upper = adjustment->upper; meter->iec_lower = iec_scale(adjustment->lower); meter->iec_upper = iec_scale(adjustment->upper); meter->amber_frac = (iec_scale(meter->amber_level) - meter->iec_lower) / (meter->iec_upper - meter->iec_lower); gtk_meter_update (meter); } static void gtk_meter_realize (GtkWidget *widget) { GtkMeter *meter; GdkWindowAttr attributes; GdkColor green, amber, red, peak; gint attributes_mask; g_return_if_fail (widget != NULL); g_return_if_fail (GTK_IS_METER (widget)); GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED); meter = GTK_METER (widget); attributes.x = widget->allocation.x; attributes.y = widget->allocation.y; attributes.width = widget->allocation.width; attributes.height = widget->allocation.height; attributes.wclass = GDK_INPUT_OUTPUT; attributes.window_type = GDK_WINDOW_CHILD; attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK; attributes.visual = gtk_widget_get_visual (widget); attributes.colormap = gtk_widget_get_colormap (widget); attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; widget->window = gdk_window_new (widget->parent->window, &attributes, attributes_mask); widget->style = gtk_style_attach (widget->style, widget->window); gdk_window_set_user_data (widget->window, widget); gtk_style_set_background (widget->style, widget->window, GTK_STATE_ACTIVE); meter->green_gc = gdk_gc_new(widget->window); green.red = 0; green.green = 60000; green.blue = 0; gdk_colormap_alloc_color (attributes.colormap, &green, FALSE, TRUE); gdk_gc_set_foreground(meter->green_gc, &green); meter->amber_gc = gdk_gc_new(widget->window); amber.red = 50000; amber.green = 55000; amber.blue = 0; gdk_colormap_alloc_color (attributes.colormap, &amber, FALSE, TRUE); gdk_gc_set_foreground(meter->amber_gc, &amber); meter->red_gc = gdk_gc_new(widget->window); red.red = 60000; red.green = 0; red.blue = 0; gdk_colormap_alloc_color (attributes.colormap, &red, FALSE, TRUE); gdk_gc_set_foreground(meter->red_gc, &red); meter->peak_gc = gdk_gc_new(widget->window); peak.red = 60000; peak.green = 60000; peak.blue = 0; gdk_colormap_alloc_color (attributes.colormap, &peak, FALSE, TRUE); gdk_gc_set_foreground(meter->peak_gc, &peak); } static void gtk_meter_size_request (GtkWidget *widget, GtkRequisition *requisition) { GtkMeter *meter = GTK_METER(widget); if (meter->direction == GTK_METER_UP || meter->direction == GTK_METER_DOWN) { requisition->width = METER_DEFAULT_WIDTH; requisition->height = METER_DEFAULT_LENGTH; } else { requisition->width = METER_DEFAULT_LENGTH; requisition->height = METER_DEFAULT_WIDTH; } } static void gtk_meter_size_allocate (GtkWidget *widget, GtkAllocation *allocation) { GtkMeter *meter; g_return_if_fail (widget != NULL); g_return_if_fail (GTK_IS_METER (widget)); g_return_if_fail (allocation != NULL); widget->allocation = *allocation; meter = GTK_METER (widget); if (GTK_WIDGET_REALIZED (widget)) { gdk_window_move_resize (widget->window, allocation->x, allocation->y, allocation->width, allocation->height); } } static gint gtk_meter_expose (GtkWidget *widget, GdkEventExpose *event) { GtkMeter *meter; float val, frac, peak_frac; int g_h, a_h, r_h; int length = 0, width = 0; g_return_val_if_fail (widget != NULL, FALSE); g_return_val_if_fail (GTK_IS_METER (widget), FALSE); g_return_val_if_fail (event != NULL, FALSE); if (event->count > 0) return FALSE; meter = GTK_METER (widget); switch (meter->direction) { case GTK_METER_UP: case GTK_METER_DOWN: length = widget->allocation.height - 2; width = widget->allocation.width - 2; break; case GTK_METER_LEFT: case GTK_METER_RIGHT: length = widget->allocation.width - 2; width = widget->allocation.height - 2; break; } val = iec_scale(meter->adjustment->value); if (val > meter->peak) { if (val > meter->iec_upper) { meter->peak = meter->iec_upper; } else { meter->peak = val; } } frac = (val - meter->iec_lower) / (meter->iec_upper - meter->iec_lower); peak_frac = (meter->peak - meter->iec_lower) / (meter->iec_upper - meter->iec_lower); /* Draw the background */ gtk_paint_box (widget->style, widget->window, GTK_STATE_NORMAL, GTK_SHADOW_IN, NULL, widget, "trough", 0, 0, widget->allocation.width, widget->allocation.height); if (frac < meter->amber_frac) { g_h = frac * length; a_h = g_h; r_h = g_h; } else if (val <= 100.0f) { g_h = meter->amber_frac * length; a_h = frac * length; r_h = a_h; } else { g_h = meter->amber_frac * length; a_h = length * (100.0f - meter->iec_lower) / (meter->iec_upper - meter->iec_lower); r_h = frac * length; } if (a_h > length) { a_h = length; } if (r_h > length) { r_h = length; } switch (meter->direction) { case GTK_METER_LEFT: gdk_draw_rectangle (widget->window, meter->amber_gc, TRUE, a_h + 1, 1, length - a_h, width); /* gdk_draw_rectangle (widget->window, meter->peak_gc, TRUE, length * (1.0 - peak_frac) + 1, 1, 1, width); */ break; case GTK_METER_RIGHT: gdk_draw_rectangle (widget->window, meter->green_gc, TRUE, 1, 1, g_h, width); if (a_h > g_h) { gdk_draw_rectangle (widget->window, meter->amber_gc, TRUE, 1+g_h, 1, a_h - g_h, width); } if (r_h > a_h) { gdk_draw_rectangle (widget->window, meter->red_gc, TRUE, 1+a_h, 1, r_h - a_h, width); } gdk_draw_rectangle (widget->window, meter->peak_gc, TRUE, length * peak_frac, 1, 1, width); break; case GTK_METER_UP: default: gdk_draw_rectangle (widget->window, meter->green_gc, TRUE, 1, length - g_h + 1, width, g_h); if (a_h > g_h) { gdk_draw_rectangle (widget->window, meter->amber_gc, TRUE, 1, length - a_h + 1, width, a_h - g_h); } if (r_h > a_h) { gdk_draw_rectangle (widget->window, meter->red_gc, TRUE, 1, length - r_h + 1, width, r_h - a_h); } if (peak_frac > 0) { gdk_draw_rectangle (widget->window, meter->peak_gc, TRUE, 1, length * (1.0f - peak_frac) + 1, width, 1); } break; } return FALSE; } static void gtk_meter_update (GtkMeter *meter) { gfloat new_value; g_return_if_fail (meter != NULL); g_return_if_fail (GTK_IS_METER (meter)); new_value = meter->adjustment->value; if (new_value < meter->adjustment->lower) new_value = meter->adjustment->lower; if (new_value > meter->adjustment->upper) new_value = meter->adjustment->upper; if (new_value != meter->adjustment->value) { meter->adjustment->value = new_value; gtk_signal_emit_by_name (GTK_OBJECT (meter->adjustment), "value_changed"); } gtk_widget_draw(GTK_WIDGET(meter), NULL); } static void gtk_meter_adjustment_changed (GtkAdjustment *adjustment, gpointer data) { GtkMeter *meter; g_return_if_fail (adjustment != NULL); g_return_if_fail (data != NULL); meter = GTK_METER (data); if ((meter->old_lower != adjustment->lower) || (meter->old_upper != adjustment->upper)) { meter->iec_lower = iec_scale(adjustment->lower); meter->iec_upper = iec_scale(adjustment->upper); gtk_meter_set_warn_point(meter, meter->amber_level); gtk_meter_update (meter); meter->old_value = adjustment->value; meter->old_lower = adjustment->lower; meter->old_upper = adjustment->upper; } else if (meter->old_value != adjustment->value) { gtk_meter_update (meter); meter->old_value = adjustment->value; } } static void gtk_meter_adjustment_value_changed (GtkAdjustment *adjustment, gpointer data) { GtkMeter *meter; g_return_if_fail (adjustment != NULL); g_return_if_fail (data != NULL); meter = GTK_METER (data); if (meter->old_value != adjustment->value) { gtk_meter_update (meter); meter->old_value = adjustment->value; } } static float iec_scale(float db) { float def = 0.0f; /* Meter deflection %age */ if (db < -70.0f) { def = 0.0f; } else if (db < -60.0f) { def = (db + 70.0f) * 0.25f; } else if (db < -50.0f) { def = (db + 60.0f) * 0.5f + 5.0f; } else if (db < -40.0f) { def = (db + 50.0f) * 0.75f + 7.5; } else if (db < -30.0f) { def = (db + 40.0f) * 1.5f + 15.0f; } else if (db < -20.0f) { def = (db + 30.0f) * 2.0f + 30.0f; } else { def = (db + 20.0f) * 2.5f + 50.0f; } return def; } void gtk_meter_reset_peak(GtkMeter *meter) { meter->peak = 0.0f; } void gtk_meter_set_warn_point(GtkMeter *meter, gfloat pt) { meter->amber_level = pt; if (meter->direction == GTK_METER_LEFT || meter->direction == GTK_METER_DOWN) { meter->amber_frac = 1.0f - (iec_scale(meter->amber_level) - meter->iec_lower) / (meter->iec_upper - meter->iec_lower); } else { meter->amber_frac = (iec_scale(meter->amber_level) - meter->iec_lower) / (meter->iec_upper - meter->iec_lower); } gtk_widget_draw(GTK_WIDGET(meter), NULL); } kluppe-0.6.14/src/frontend/kluppe/looper.h0000644000175000017500000001164711075100662020002 0ustar dieterdieter/* definitions for a looper */ #ifndef __LOOPER_H__ #define __LOOPER_H__ #include #include #include "../../common/looperdata.h" #include "gtkloopview.h" #include "../../common/speciallist.h" #include "../../common/shuttle.h" #include "../../common/alphatrack.h" typedef struct _looper_list { GList *listptr; GMutex *listmutex; } looper_list_t; typedef struct _looper_gui { /* for usb hid interaction */ shuttle_data_t *shuttle; alphatrack_t *alphatrack; /* alphatrack specific:*/ int encoderdelta_l; int encoderdelta_m; int encoderdelta_r; long touchstrippos; long touchstripposval; long touchstripposrange; /* for mix <-> gui communication */ looper_data_t *data; int id; int gid; int dirty; GtkWidget *parent; GtkWidget *parentcontainer; int vposition; int remote_controlled; int bg_set; long samplerate; /* GList *bufferlist;*/ speciallist_t *bufferlist; speciallist_t *looperdatalist; speciallist_t *clickmodes; /* for avoiding gui-loopbacks */ gboolean loopstartblock; gboolean loopendblock; gboolean looplengthblock; gboolean recstartblock; gboolean recendblock; gboolean reclengthblock; gboolean speedblock; gboolean volblock; /* update meters every second round */ gboolean vublock; /* meta-gui widgets */ PangoFontDescription *font; GtkTooltips *tooltips; GtkWidget *mainbox; /* hbox */ GtkWidget *topbox; GtkWidget *controlbox; /* vbox */ GtkWidget *middletable; /* table */ GtkWidget *middlebox; /* hbox */ GtkWidget *smalltable; /* vbox */ GtkWidget *smallbox; /* vbox */ GtkWidget *grainbox; /* hbox */ GtkWidget *panbox; /* hbox */ GtkWidget *controlframe; GtkWidget *customcurvedialog; /* specific widgets */ GtkWidget *loopview; /* loopview */ GtkWidget *buffermenu; /* menu */ GtkWidget *menu_bar; /* menubar */ GtkWidget *optionsmenu; /* menu */ GtkWidget *limiteritem; /* menu item */ GtkWidget *snap2griditem; /* menu item */ GtkWidget *showgriditem; /* menu item */ GtkWidget *loopmode; /* menu item */ GtkWidget *backforthmode; /* menu item */ GtkWidget *oncemode; /* menu item */ GtkWidget *sinewavemode; /* menu item */ GtkWidget *externalposmode; /* menu item */ GtkWidget *customspeedmode; /* menu item */ GtkWidget *customposmode; /* menu item */ GtkWidget *recloopmode; /* menu item */ GtkWidget *reconcemode; /* menu item */ GtkWidget *thresholdtoggle; /* menu item */ GtkWidget *playmodemenu; /* menu */ GtkWidget *playbutton; /* toggle_button */ GtkWidget *recbutton; /* toggle_button */ GtkWidget *normbutton; /* button */ GtkWidget *shuttlebutton; /* toggle_button */ GtkWidget *minimizebutton; /* toggle_button */ GtkWidget *upbutton; /* button */ GtkWidget *downbutton; /* button */ GtkWidget *upimage; /* image.*/ GtkWidget *downimage; /* image */ GtkWidget *playimage; /* image */ GtkWidget *recimage; /* image */ GtkWidget *outLmeter; /* vumeter */ GtkWidget *outRmeter; /* vumeter */ GtkWidget *inLmeter; /* vumeter */ GtkWidget *inRmeter; /* vumeter */ GtkWidget *volslider; /* vscale */ GtkWidget *recmixslider; /* vscale */ GtkWidget *panslider; /* hscale */ GtkWidget *ngrainslider; /* hscale */ GtkWidget *loopstartspin; /* spinbutton */ GtkWidget *loopendspin; /* spinbutton */ GtkWidget *looplengthspin; /* spinbutton */ GtkWidget *recstartspin; /* spinbutton */ GtkWidget *recendspin; /* spinbutton */ GtkWidget *reclengthspin; /* spinbutton */ GtkWidget *speedspin; /* spinbutton */ GtkWidget *diversityspin; /* spinbutton */ GtkWidget *densityspin; /* spinbutton */ GtkWidget *panswingspin; /* spinbutton */ GtkWidget *recloopcheck; /* checkbutton */ GtkWidget *playloopcheck; /* checkbutton */ } looper_gui_t; looper_gui_t* looper_new(GtkWidget* parent, GtkWidget* parentcontainer, alphatrack_t *alphatrack, speciallist_t *looperdatalist, speciallist_t *clickmodes, int id, int minimized); int looper_update_bufferlist(looper_gui_t* loop, speciallist_t *bufferlist); int looper_update_loopername(gchar* name); void looper_update_cursorposition (looper_gui_t *looper); void looper_update_widgets(looper_gui_t *looper); void looper_set_samplerate (looper_gui_t *looper,long samplerate); void looper_set_buffer_by_id (looper_gui_t *looper, int id); void looper_suspend_gui (looper_gui_t *looper, int suspend); void looper_set_remote_controlled (looper_gui_t *looper, int rc); int looper_get_remote_controlled (looper_gui_t *looper); looper_data_t* looper_get_looperdata (looper_gui_t *looper); looper_list_t* looper_list_new(); void looper_close (looper_gui_t *looper); looper_list_t* looper_list_append_looper(looper_list_t* list, looper_gui_t *loop); looper_list_t* looper_list_remove_looper(looper_list_t* list, looper_gui_t *loop); int looper_get_position(looper_gui_t *loop); void looper_set_position(looper_gui_t *loop, int pos); /* LATER*/ looper_list_t* looper_list_delete(looper_list_t* list); #endif kluppe-0.6.14/src/frontend/kluppe/gtkloopview.h0000644000175000017500000001221110464105357021047 0ustar dieterdieter#ifndef __GTK_LOOPVIEW_H__ #define __GTK_LOOPVIEW_H__ #include #include #include #include #include "../../common/peakview.h" #include "looper.h" #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ #define GTK_LOOPVIEW(obj) GTK_CHECK_CAST (obj, gtk_loopview_get_type (), GtkLoopview) #define GTK_LOOPVIEW_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_loopview_get_type (), GtkLoopviewClass) #define GTK_IS_LOOPVIEW(obj) GTK_CHECK_TYPE (obj, gtk_loopview_get_type ()) typedef struct _GtkLoopview GtkLoopview; typedef struct _GtkLoopviewClass GtkLoopviewClass; struct _GtkLoopview { GtkWidget widget; GdkPixmap *pixmap; /* update policy (GTK_UPDATE_[CONTINUOUS/DELAYED/DISCONTINUOUS]) */ guint policy : 2; /* Button currently pressed or 0 if none */ guint8 button; /* ID of update timer, or 0 if none */ guint32 timer; /* number of last samples updated */ guint32 lastnup; /* our looper_data */ looper_data_t *looperdata; /* peakview */ peakview_t *peakview; /* graphics active ? */ gboolean suspended; /* pointer position */ gint pointerX; gint pointerY; /* peakdata L,R,min,max */ gint8 *Lmin; gint8 *Rmin; gint8 *Lmax; gint8 *Rmax; /* gint8 *attac;*/ gint32 npeaks; gint32 width; gint32 height; gint32 Lmid; gint32 Rmid; gint32 Hmax; /* sample domain indices */ guint32 zoomstart; guint32 zoomend; guint32 gridstart; guint32 gridwidth; guint32 gridoffset; /* 'graphical' indices */ gint32 gloopstart; gint32 gloopend; gint32 grecstart; gint32 grecend; gint32 gzoomstart; gint32 gzoomend; gint32 gplaypos; gint32 grecpos; gint32 grabsel; gint32 lastmouseX; gint32 lastmouseY; /* gint32 ggridwidth; */ /* gint32 ggridstart; */ gdouble ggridwidth; gdouble ggridstart; gdouble bpm; gdouble bpb; /* beats per bar */ struct timeval lastmousetime; double speedbeforescratch; gboolean nearby; gboolean snap2grid; gboolean showgrid; gboolean showattac; /* colors and GCs*/ GdkGC *bgc; GdkGC *fgc; GdkColor bg_plain; GdkColor bg_play; GdkColor bg_rec; GdkColor bg_zoom; GdkColor bg_recplay; GdkColor bg_reczoom; GdkColor bg_playzoom; GdkColor bg_recplayzoom; GdkColor bg_grid; GdkColor bg_bar; GdkColor bg_beat; GdkColor fg_plain; GdkColor fg_lit; GdkColor playcursor; GdkColor reccursor; }; struct _GtkLoopviewClass { GtkWidgetClass parent_class; void (*loopborders_changed)(GtkLoopviewClass *loop, long start, long end); }; enum { SIG_LOOPBORDERS_CHANGED, SIG_RECBORDERS_CHANGED, SIG_ZOOMBORDERS_CHANGED, SIG_SPEED_CHANGED, LAST_SIGNAL }; GtkWidget* gtk_loopview_new (looper_data_t *looperdata); GtkType gtk_loopview_get_type (void); looper_data_t* gtk_loopview_get_looperdata (GtkLoopview *loopview); void gtk_loopview_set_update_policy (GtkLoopview *loopview, GtkUpdateType policy); void gtk_loopview_set_looperdata (GtkLoopview *loopview, looper_data_t *looperdata); void gtk_loopview_suspend_gui (GtkLoopview *loopview, int suspend); void gtk_loopview_set_play_pos (GtkLoopview *loopview, gdouble playpos); void gtk_loopview_set_rec_pos (GtkLoopview *loopview, gdouble recpos); /*void gtk_loopview_calc_peaks (GtkLoopview *loopview,guint32 startx, guint32 endx);*/ void gtk_loopview_copy_peaks (GtkLoopview *loopview, peakdata_t* pd); void gtk_loopview_update_cursorposition (GtkLoopview *loopview); void gtk_loopview_update_area (GtkLoopview *loopview, gint32 startx, gint32 endx); void gtk_loopview_zoom_to_playselection (GtkLoopview *loopview); void gtk_loopview_zoom_to_recselection (GtkLoopview *loopview); void gtk_loopview_zoom_to_overview (GtkLoopview *loopview); void gtk_loopview_set_zoom (GtkLoopview *loopview, gdouble zoomstart, gdouble zoomend); long gtk_loopview_get_zoomstart (GtkLoopview *loopview); long gtk_loopview_get_zoomend (GtkLoopview *loopview); void gtk_loopview_update_loopstart (GtkLoopview *loopview); void gtk_loopview_update_loopend (GtkLoopview *loopview); void gtk_loopview_update_recstart (GtkLoopview *loopview); void gtk_loopview_update_recend (GtkLoopview *loopview); void gtk_loopview_update_waveform (GtkLoopview *loopview); void gtk_loopview_set_snap2grid (GtkLoopview *loopview, gboolean snap); gboolean gtk_loopview_getsnap2grid (GtkLoopview *loopview); void gtk_loopview_set_showgrid (GtkLoopview *loopview, gboolean show); gboolean gtk_loopview_get_showgrid (GtkLoopview *loopview); void gtk_loopview_set_bpm (GtkLoopview *loopview, gdouble bpm); gdouble gtk_loopview_get_bpm (GtkLoopview *loopview); guint32 gtk_loopview_get_gridwidth (GtkLoopview *loopview); void gtk_loopview_set_gridoffset (GtkLoopview *loopview, guint32 offset); guint32 gtk_loopview_get_gridoffset (GtkLoopview *loopview); void gtk_loopview_set_bpb (GtkLoopview *loopview, gdouble bpb); gdouble gtk_loopview_get_bpb (GtkLoopview *loopview); #ifdef __cplusplus } #endif /* __cplusplus */ #endif /* __GTK_LOOPVIEW_H__ */ kluppe-0.6.14/src/frontend/kluppe/graindialog.c0000644000175000017500000002776710271643256020777 0ustar dieterdieter#include #include #include #include #include #include "graindialog.h" static void minspeed_callback(GtkWidget* minspeedspin, gpointer data){ looper_data_t* looperdata = (looper_data_t*)data; GtkWidget* maxspeedspin = g_object_get_data (G_OBJECT(minspeedspin),"maxspeedspin"); looperdata_lock(looperdata); looperdata_set_mingrainspeed(looperdata, (double)gtk_spin_button_get_value ((GtkSpinButton*)minspeedspin)); looperdata_unlock(looperdata); if (looperdata->mingrainspeed > looperdata->maxgrainspeed){ gtk_spin_button_set_value ((GtkSpinButton*)maxspeedspin, (gdouble)looperdata->mingrainspeed); } } static void maxspeed_callback(GtkWidget* maxspeedspin, gpointer data){ looper_data_t* looperdata = (looper_data_t*)data; GtkWidget* minspeedspin = g_object_get_data (G_OBJECT(maxspeedspin),"minspeedspin"); looperdata_lock(looperdata); looperdata_set_maxgrainspeed(looperdata, (double)gtk_spin_button_get_value ((GtkSpinButton*)maxspeedspin)); looperdata_unlock(looperdata); if (looperdata->maxgrainspeed < looperdata->mingrainspeed){ gtk_spin_button_set_value ((GtkSpinButton*)minspeedspin, (gdouble)looperdata->maxgrainspeed); } } static void minlength_callback(GtkWidget* minlengthspin, gpointer data){ looper_data_t* looperdata = (looper_data_t*)data; GtkWidget* maxlengthspin = g_object_get_data (G_OBJECT(minlengthspin),"maxlengthspin"); looperdata_lock(looperdata); looperdata_set_mingrainlength(looperdata, (long)gtk_spin_button_get_value ((GtkSpinButton*)minlengthspin)); looperdata_unlock(looperdata); gtk_spin_button_set_value ((GtkSpinButton*)maxlengthspin, (gdouble)looperdata_get_maxgrainlength(looperdata)); } static void maxlength_callback(GtkWidget* maxlengthspin, gpointer data){ looper_data_t* looperdata = (looper_data_t*)data; GtkWidget* minlengthspin = g_object_get_data (G_OBJECT(maxlengthspin),"minlengthspin"); looperdata_lock(looperdata); looperdata_set_maxgrainlength(looperdata, (long)gtk_spin_button_get_value ((GtkSpinButton*)maxlengthspin)); looperdata_unlock(looperdata); gtk_spin_button_set_value ((GtkSpinButton*)minlengthspin, (gdouble)looperdata_get_mingrainlength(looperdata)); } static void channelspin_callback(GtkWidget* channelspin, gpointer data){ looper_data_t* looperdata = (looper_data_t*)data; looperdata_lock(looperdata); looperdata_set_midichannel(looperdata, (int)gtk_spin_button_get_value ((GtkSpinButton*)channelspin)); looperdata_unlock(looperdata); } static void grainpitch_nomidi_callback(GtkToggleButton* modeselect, gpointer data){ looper_data_t* looperdata = (looper_data_t*)data; if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(modeselect))){ looperdata_lock(looperdata); looperdata_set_grainpitchmode(looperdata,GRAINPITCH_RANGE); looperdata_unlock(looperdata); } } static void grainpitch_auto_callback(GtkWidget* modeselect, gpointer data){ looper_data_t* looperdata = (looper_data_t*)data; if ( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(modeselect))){ looperdata_lock(looperdata); looperdata_set_grainpitchmode(looperdata,GRAINPITCH_AUTO); looperdata_unlock(looperdata); } } static void grainpitch_midi_callback(GtkWidget* modeselect, gpointer data){ looper_data_t* looperdata = (looper_data_t*)data; if ( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(modeselect))){ looperdata_lock(looperdata); looperdata_set_grainpitchmode(looperdata,GRAINPITCH_CHORD); looperdata_unlock(looperdata); } } void graindialog_new(GtkWidget* parent, looper_data_t* data, int id){ GtkAdjustment *adj; GtkTooltips *tooltips; GtkWidget *dialog; GtkWidget *minspeedlabel; GtkWidget *maxspeedlabel; GtkWidget *minlengthlabel; GtkWidget *maxlengthlabel; GtkWidget *envelopelabel; GtkWidget *speedtable; GtkWidget *lengthtable; GtkWidget *settingsbox; GtkWidget *modebox; GtkWidget *mainbox; /* hbox */ GtkWidget *speedframe; GtkWidget *lengthframe; GtkWidget *modeframe; GtkWidget *modeselect; GtkWidget *channelspin; GSList *group; /* GtkWidget *envelopeselector; */ /* combobox */ GtkWidget *minspeedspin; /* spinbutton */ GtkWidget *maxspeedspin; /* spinbutton */ GtkWidget *minlengthspin; /* spinbutton */ GtkWidget *maxlengthspin; /* spinbutton */ /* GtkWidget *testcurve; */ gint result; int actual_mode; tooltips = gtk_tooltips_new (); speedtable = gtk_table_new (2, 2, TRUE); lengthtable = gtk_table_new (2, 2, TRUE); minspeedlabel = gtk_label_new ("min"); maxspeedlabel = gtk_label_new ("max"); minlengthlabel = gtk_label_new ("min"); gtk_tooltips_set_tip(tooltips,minlengthlabel,"minimum length for a grain",NULL); maxlengthlabel = gtk_label_new ("max"); envelopelabel = gtk_label_new ("volume envelopes:"); /* testcurve = gtk_curve_new(); gtk_curve_set_range ((GtkCurve*)testcurve,0., 1., 0., 1.); gtk_curve_set_gamma ((GtkCurve*)testcurve,3); gtk_widget_set_size_request (testcurve, 100, 100); */ /* envelopeselector */ adj = (GtkAdjustment *) gtk_adjustment_new (looperdata_get_mingrainspeed(data), -50.0, 50.0, .1, 1, 4); minspeedspin = gtk_spin_button_new (adj, 1, 4); adj = (GtkAdjustment *) gtk_adjustment_new (looperdata_get_maxgrainspeed(data), -50.0, 50.0, .1, 1, 4); maxspeedspin = gtk_spin_button_new (adj, 1, 4); adj = (GtkAdjustment *) gtk_adjustment_new (looperdata_get_mingrainlength(data), 10,44100,10,100,0); minlengthspin = gtk_spin_button_new (adj, 1, 0); adj = (GtkAdjustment *) gtk_adjustment_new (looperdata_get_maxgrainlength(data), 10,44100,10,100,0); maxlengthspin = gtk_spin_button_new (adj, 1, 0); g_object_set_data (G_OBJECT (minspeedspin),"maxspeedspin",maxspeedspin); g_object_set_data (G_OBJECT (maxspeedspin),"minspeedspin",minspeedspin); g_signal_connect (G_OBJECT (minspeedspin), "value_changed", G_CALLBACK (minspeed_callback), (gpointer) data); g_signal_connect (G_OBJECT (maxspeedspin), "value_changed", G_CALLBACK (maxspeed_callback), (gpointer) data); g_object_set_data (G_OBJECT (minlengthspin),"maxlengthspin",maxlengthspin); g_object_set_data (G_OBJECT (maxlengthspin),"minlengthspin",minlengthspin); g_signal_connect (G_OBJECT (minlengthspin), "value_changed", G_CALLBACK (minlength_callback), (gpointer) data); g_signal_connect (G_OBJECT (maxlengthspin), "value_changed", G_CALLBACK (maxlength_callback), (gpointer) data); gtk_tooltips_set_tip(tooltips,minspeedspin,"min. speed for a single grain",NULL); gtk_tooltips_set_tip(tooltips,maxspeedspin,"max. speed for a single grain",NULL); gtk_tooltips_set_tip(tooltips,minlengthspin, "min. length (in samples) for a single grain",NULL); gtk_tooltips_set_tip(tooltips,maxlengthspin, "max. length (in samples) for a single grain",NULL); speedframe = gtk_frame_new ("grain speed"); gtk_frame_set_shadow_type((GtkFrame*)speedframe, GTK_SHADOW_ETCHED_IN); gtk_table_attach((GtkTable*)speedtable, minspeedlabel, 0, 1, 0, 1, GTK_FILL,GTK_FILL,3,3); gtk_table_attach((GtkTable*)speedtable, maxspeedlabel, 1, 2, 0, 1, GTK_FILL,GTK_FILL,3,3); gtk_table_attach((GtkTable*)speedtable, minspeedspin, 0, 1, 1, 2, GTK_FILL,GTK_FILL,3,3); gtk_table_attach((GtkTable*)speedtable, maxspeedspin, 1, 2, 1, 2, GTK_FILL,GTK_FILL,3,3); gtk_container_add (GTK_CONTAINER (speedframe),speedtable); lengthframe = gtk_frame_new ("grain length"); gtk_frame_set_shadow_type((GtkFrame*)lengthframe, GTK_SHADOW_ETCHED_IN); gtk_table_attach((GtkTable*)lengthtable, minlengthlabel, 0, 1, 0, 1, GTK_FILL,GTK_FILL,3,3); gtk_table_attach((GtkTable*)lengthtable, maxlengthlabel, 1, 2, 0, 1, GTK_FILL,GTK_FILL,3,3); gtk_table_attach((GtkTable*)lengthtable, minlengthspin, 0, 1, 1, 2, GTK_FILL,GTK_FILL,3,3); gtk_table_attach((GtkTable*)lengthtable, maxlengthspin, 1, 2, 1, 2, GTK_FILL,GTK_FILL,3,3); gtk_container_add (GTK_CONTAINER (lengthframe),lengthtable); settingsbox = gtk_hbox_new(FALSE,5); gtk_box_pack_start (GTK_BOX(settingsbox), speedframe, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX(settingsbox), lengthframe, FALSE, FALSE, 0); /* the midi mode selctor (radiobuttons): */ actual_mode = looperdata_get_grainpitchmode(data); modebox = gtk_hbox_new(FALSE,5); adj = (GtkAdjustment *) gtk_adjustment_new ((gdouble)looperdata_get_midichannel(data), 0,16,1,1,1); channelspin = gtk_spin_button_new (adj, 1, 0); gtk_tooltips_set_tip(tooltips, channelspin,"midi channel filter (0 = all)",NULL); g_signal_connect (G_OBJECT (channelspin), "value_changed", G_CALLBACK (channelspin_callback), (gpointer) data); gtk_box_pack_start (GTK_BOX (modebox), channelspin, TRUE, TRUE, 0); gtk_widget_show (channelspin); modeselect = gtk_radio_button_new_with_label (NULL, "no midi"); gtk_box_pack_start (GTK_BOX (modebox), modeselect, TRUE, TRUE, 0); if (actual_mode == GRAINPITCH_RANGE) gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (modeselect), TRUE); else gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (modeselect), FALSE); g_signal_connect (G_OBJECT (modeselect), "toggled", G_CALLBACK (grainpitch_nomidi_callback), data); gtk_widget_show (modeselect); group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (modeselect)); modeselect = gtk_radio_button_new_with_label (group, "automatic"); if (actual_mode == GRAINPITCH_AUTO) gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (modeselect), TRUE); else gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (modeselect), FALSE); g_signal_connect (G_OBJECT (modeselect), "toggled", G_CALLBACK (grainpitch_auto_callback), data); gtk_box_pack_start (GTK_BOX (modebox), modeselect, TRUE, TRUE, 0); gtk_widget_show (modeselect); modeselect = gtk_radio_button_new_with_label_from_widget ( GTK_RADIO_BUTTON (modeselect), "just midi"); if (actual_mode == GRAINPITCH_CHORD) gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (modeselect), TRUE); else gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (modeselect), FALSE); g_signal_connect (G_OBJECT (modeselect), "toggled", G_CALLBACK (grainpitch_midi_callback), data); gtk_box_pack_start (GTK_BOX (modebox), modeselect, TRUE, TRUE, 0); gtk_widget_show (modeselect); modeframe = gtk_frame_new ("grain midi mode"); gtk_frame_set_shadow_type((GtkFrame*)modeframe, GTK_SHADOW_ETCHED_IN); gtk_container_add (GTK_CONTAINER (modeframe), modebox); /* the main layout box: */ mainbox = gtk_vbox_new (FALSE,5); gtk_box_pack_start (GTK_BOX(mainbox), settingsbox, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX(mainbox), modeframe, FALSE, FALSE, 0); dialog = gtk_dialog_new_with_buttons ("settings for granular player", (GtkWindow*)parent, /*GTK_DIALOG_MODAL |*/ GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, NULL); gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox),mainbox); /* gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox),testcurve); */ gtk_widget_show_all (dialog); result = gtk_dialog_run (GTK_DIALOG (dialog)); /* switch (result){ case GTK_RESPONSE_ACCEPT: printf ("dialog done\n"); break; default: printf ("dialog cancelled\n"); break; } */ gtk_widget_destroy (dialog); } kluppe-0.6.14/src/frontend/kluppe/gtkmeter.h0000644000175000017500000000511310204256334020314 0ustar dieterdieter/* * Copyright (C) 2003 Steve Harris * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * $Id: gtkmeter.h,v 1.3 2003/11/19 15:28:17 theno23 Exp $ */ #ifndef __GTK_METER_H__ #define __GTK_METER_H__ #include #include #include #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ #define GTK_METER(obj) GTK_CHECK_CAST (obj, gtk_meter_get_type (), GtkMeter) #define GTK_METER_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_meter_get_type (), GtkMeterClass) #define GTK_IS_METER(obj) GTK_CHECK_TYPE (obj, gtk_meter_get_type ()) #define GTK_METER_UP 0 #define GTK_METER_DOWN 1 #define GTK_METER_LEFT 2 #define GTK_METER_RIGHT 3 typedef struct _GtkMeter GtkMeter; typedef struct _GtkMeterClass GtkMeterClass; struct _GtkMeter { GtkWidget widget; /* update policy (GTK_UPDATE_[CONTINUOUS/DELAYED/DISCONTINUOUS]) */ guint direction : 2; /* Button currently pressed or 0 if none */ guint8 button; /* Amber dB and deflection points */ gfloat amber_level; gfloat amber_frac; /* Deflection limits */ gfloat iec_lower; gfloat iec_upper; /* Peak deflection */ gfloat peak; /* ID of update timer, or 0 if none */ guint32 timer; /* Old values from adjustment stored so we know when something changes */ gfloat old_value; gfloat old_lower; gfloat old_upper; GdkGC *green_gc; GdkGC *amber_gc; GdkGC *red_gc; GdkGC *peak_gc; /* The adjustment object that stores the data for this meter */ GtkAdjustment *adjustment; }; struct _GtkMeterClass { GtkWidgetClass parent_class; }; GtkWidget* gtk_meter_new (GtkAdjustment *adjustment, gint direction); guint gtk_meter_get_type (void); GtkAdjustment* gtk_meter_get_adjustment (GtkMeter *meter); void gtk_meter_set_adjustment (GtkMeter *meter, GtkAdjustment *adjustment); void gtk_meter_reset_peak (GtkMeter *meter); void gtk_meter_set_warn_point (GtkMeter *meter, gfloat pt); #ifdef __cplusplus } #endif /* __cplusplus */ #endif /* __GTK_METER */ kluppe-0.6.14/src/frontend/kluppe/customcurve.h0000644000175000017500000000057510247332447021067 0ustar dieterdieter/* definitions for a looper */ #ifndef __CUSTOMCURVE_H__ #define __CUSTOMCURVE_H__ #include #include #include "../../common/looperdata.h" GtkWidget* customcurvedialog_new(GtkWidget* parent, looper_data_t* data, int id); void customcurve_update(GtkWidget* curve, looper_data_t* looperdata); GtkWidget* customcurvedialog_get_curve(GtkWidget* dialog); #endif kluppe-0.6.14/src/frontend/kluppe/sfpreview.h0000644000175000017500000000030310206702071020474 0ustar dieterdieter#ifndef __SFPREVIEW_H__ #define __SFPREVIEW_H__ #include #include void sfpreview_update(GtkFileChooser* filechooser, gpointer data); GtkWidget *sfpreview_new(); #endif kluppe-0.6.14/src/frontend/kluppe/looper.c0000644000175000017500000032616411075100662020000 0ustar dieterdieter#include #include #include #include #include #include "looper.h" #include "../../common/looperdata.h" #include "gtkmeter.h" #include "graindialog.h" #include "griddialog.h" #include "threshdialog.h" #include "customcurve.h" #include "../../common/speciallist.h" #include "../../common/alphatrack.h" #define LOGTEN 2.302585092994 /* conversion helper functions */ static gdouble samples2secs (looper_gui_t* looper, long samples){ return (gdouble)samples / (gdouble)looper->samplerate; } static guint32 secs2samples (looper_gui_t* looper, gdouble secs){ return (guint32)((gdouble)secs * (gdouble)looper->samplerate); } static gdouble samples2speedsecs (looper_gui_t* looper, long samples){ return (gdouble)samples / (gdouble)looper->samplerate / fabs(looper->data->speed); } static guint32 speedsecs2samples (looper_gui_t* looper, gdouble secs){ return (guint32)((gdouble)secs * (gdouble)looper->samplerate * fabs(looper->data->speed)); } /* looperlist functions */ looper_list_t* looper_list_new(){ looper_list_t *list = (looper_list_t*) malloc(sizeof(looper_list_t)); list->listptr = NULL; list->listmutex = g_mutex_new(); return list; } looper_list_t* looper_list_append_looper(looper_list_t* list, looper_gui_t *loop){ g_mutex_lock(list->listmutex); list->listptr = g_list_append(list->listptr, loop); g_mutex_unlock(list->listmutex); return list; } looper_list_t* looper_list_remove_looper(looper_list_t* list, looper_gui_t *looper){ GList *tmp; tmp = list->listptr; while (tmp){ if (looper == (looper_gui_t*)tmp->data){ list->listptr = g_list_remove(list->listptr, looper); tmp = list->listptr; } tmp = g_list_next(tmp); } looperdata_lock(looper->data); if (looper->data){ looper->data->isplaying = 0; looper->data->isrecording = 0; } looperdata_unlock(looper->data); looperdata_free (looper->data); return list; } /* looper functions */ void looper_set_samplerate (looper_gui_t* looper, long samplerate){ looper->samplerate = samplerate; return; } void looper_close (looper_gui_t *looper){ gint lastwidth; gint lastheight; if (looper->data){ looper->data->isplaying = 0; looper->data->isrecording = 0; } if (looper->customcurvedialog){ gtk_widget_destroy (looper->customcurvedialog); looper->customcurvedialog = NULL; } gtk_widget_destroy (looper->mainbox); gtk_window_get_size ((GtkWindow*)looper->parent,&lastwidth,&lastheight); gtk_window_resize((GtkWindow*)looper->parent,lastwidth,1); looper->parent = NULL; looper->id = 0; } static void looper_close_looper_callback (GtkMenuItem *menuitem, gpointer data){ looper_gui_t *looper = (looper_gui_t *)data; looper_close (looper); } void looper_set_remote_controlled (looper_gui_t *looper, int rc){ if (!looper) return; looper->remote_controlled = rc; looper->bg_set = 0; looper->dirty = 1; } int looper_get_remote_controlled (looper_gui_t *looper){ if (!looper) return 0; return looper->remote_controlled; } static void looper_normalize_callback (GtkWidget *normbutton, gpointer data ){ looper_gui_t *looper = (looper_gui_t*)data; float factor; if (looper->data->buf){ factor = buffer_analyze (looper->data->buf, looper->gid, 0 , 0); if (factor != 0){ factor = 1. / factor; /* buffer_normalize (looper->data->buf, factor, 0, 0);*/ buffer_set_volume_factor(looper->data->buf, factor); looper_update_bufferlist (looper, looper->bufferlist); } } } static void looper_upbutton_callback (GtkWidget *upbutton, gpointer data ){ looper_gui_t *looper = (looper_gui_t*)data; GValue value = { 0, }; g_value_init (&value, G_TYPE_INT); gint pos; if (looper->parentcontainer){ gtk_container_child_get_property(GTK_CONTAINER(looper->parentcontainer), looper->mainbox, "position", &value); pos = g_value_get_int (&value) - 1; if (pos < 2) pos = -1; gtk_box_reorder_child (GTK_BOX(looper->parentcontainer),looper->mainbox,pos); looper->vposition = pos; } } static void looper_downbutton_callback (GtkWidget *downbutton, gpointer data ){ looper_gui_t *looper = (looper_gui_t*)data; GValue value = { 0, }; g_value_init (&value, G_TYPE_INT); gint pos; if (looper->parentcontainer){ gtk_container_child_get_property(GTK_CONTAINER(looper->parentcontainer), looper->mainbox, "position", &value); pos = g_value_get_int (&value) + 1; /* LATER: search for highest value and eventually wrap around*/ gtk_box_reorder_child (GTK_BOX(looper->parentcontainer),looper->mainbox,pos); looper->vposition = pos; } } int looper_get_position(looper_gui_t *looper){ GValue value = { 0, }; g_value_init (&value, G_TYPE_INT); gint pos = looper->vposition; if (looper->parentcontainer){ gtk_container_child_get_property(GTK_CONTAINER(looper->parentcontainer), looper->mainbox, "position", &value); pos = g_value_get_int (&value); looper->vposition = pos; } return pos; } looper_data_t* looper_get_looperdata (looper_gui_t *looper){ if (looper) if (looper->data) return looper->data; return NULL; } void looper_set_position(looper_gui_t *looper, int pos){ GValue value = { 0, }; g_value_init (&value, G_TYPE_INT); if (looper->parentcontainer && pos){ gtk_box_reorder_child (GTK_BOX(looper->parentcontainer),looper->mainbox,pos); looper->vposition = pos; } } static void looper_denormalize_callback (GtkWidget *normbutton, gpointer data ){ looper_gui_t *looper = (looper_gui_t*)data; if (looper->data->buf){ buffer_set_volume_factor(looper->data->buf, 1.); } gtk_widget_set_sensitive(GTK_WIDGET(normbutton),FALSE); } static void looper_normalize_playselection_callback (GtkWidget *normbutton, gpointer data ){ looper_gui_t *looper = (looper_gui_t*)data; float factor; if (looper->data->buf){ factor = buffer_analyze (looper->data->buf, looper->gid, looperdata_get_loopstart(looper->data), looperdata_get_loopend(looper->data)); if (factor != 0){ factor = 1. / factor; buffer_normalize (looper->data->buf, factor, looperdata_get_loopstart(looper->data), looperdata_get_loopend(looper->data)); } } } static void looper_normalize_recselection_callback (GtkWidget *normbutton, gpointer data ){ looper_gui_t *looper = (looper_gui_t*)data; float factor; if (looper->data->buf){ factor = buffer_analyze (looper->data->buf, looper->gid, looperdata_get_recstart(looper->data), looperdata_get_recend(looper->data)); if (factor != 0){ factor = 1. / factor; buffer_normalize (looper->data->buf, factor, looperdata_get_recstart(looper->data), looperdata_get_recend(looper->data)); } } } static void looper_clear_callback (GtkWidget *normbutton,gpointer data ){ looper_gui_t *looper = (looper_gui_t*)data; if (looper->data->buf){ buffer_normalize (looper->data->buf, 0.0, 0, 0); } } static void looper_clear_playselection_callback (GtkWidget *normbutton,gpointer data ){ looper_gui_t *looper = (looper_gui_t*)data; if (looper->data->buf){ buffer_normalize (looper->data->buf, 0.0, looperdata_get_loopstart(looper->data), looperdata_get_loopend(looper->data)); } } static void looper_clear_recselection_callback (GtkWidget *normbutton,gpointer data ){ looper_gui_t *looper = (looper_gui_t*)data; if (looper->data->buf){ buffer_normalize (looper->data->buf, 0.0, looperdata_get_recstart(looper->data), looperdata_get_recend(looper->data)); } } static gint confirm_overwrite (GtkWindow *parent, const gchar *filename){ GtkWidget *dialog; gint response; dialog = gtk_message_dialog_new (parent, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE, "\"%s\" already exists. Do you want to replace it ?", filename); gtk_dialog_add_buttons (GTK_DIALOG (dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, "_Replace", GTK_RESPONSE_ACCEPT, NULL); response = gtk_dialog_run (GTK_DIALOG (dialog)); gtk_widget_destroy (dialog); return response; } static char* looper_get_save_filename(GtkWindow *parent){ GtkWidget *gfc; struct stat fstat; char* filename = NULL; gint response = GTK_RESPONSE_ACCEPT; gfc = gtk_file_chooser_dialog_new("select a soundfile to save the buffer", GTK_WINDOW(parent), GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, NULL); gtk_file_chooser_set_show_hidden(GTK_FILE_CHOOSER (gfc),TRUE); if (gtk_dialog_run (GTK_DIALOG (gfc)) == GTK_RESPONSE_ACCEPT){ filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (gfc)); if (strncasecmp (".wav",(char*)(filename + strlen(filename) - 4),4)){ int i = strlen(filename); filename = realloc (filename,(sizeof(char)*(i + 5))); memset((char*)(filename + i),0,4); strncpy((filename + i),".wav",4); } if (!stat (filename, &fstat)) response = confirm_overwrite(parent,(gchar*)filename); if (!(response == GTK_RESPONSE_ACCEPT)){ free(filename); filename = NULL; } gtk_widget_destroy (gfc); }else gtk_widget_destroy (gfc); return filename; } static void looper_savebuffer2file_callback (GtkWidget *dummy, gpointer data){ looper_gui_t *looper = (looper_gui_t*)data; buffer_info_t *buf = NULL; char* filename; int ret; if (looper->data) if (looper->data->buf) buf = looper->data->buf; if (!buf) return; filename = looper_get_save_filename(GTK_WINDOW(looper->parent)); if (filename){ ret = buffer_save(looper->data->buf, filename, looper->samplerate, 0, buffer_get_size(looper->data->buf)); if (ret < 1) printf ("error saving file\n"); else{ /* printf("saved");*/ buffer_set_filename(buf,filename); } free(filename); }else printf ("filename error saving file\n"); } static void looper_saveplayselection2file_callback (GtkWidget *dummy, gpointer data){ looper_gui_t *looper = (looper_gui_t*)data; buffer_info_t *buf = NULL; char* filename; int ret; if (looper->data) if (looper->data->buf) buf = looper->data->buf; if (!buf) return; filename = looper_get_save_filename(GTK_WINDOW(looper->parent)); if (filename){ ret = buffer_save(looper->data->buf, filename, looper->samplerate, looperdata_get_loopstart(looper->data), looperdata_get_loopend(looper->data)); if (ret < 1) printf ("error saving file\n"); else printf("saved"); free(filename); }else printf ("filename error saving file\n"); } static void looper_saverecselection2file_callback (GtkWidget *dummy, gpointer data){ looper_gui_t *looper = (looper_gui_t*)data; buffer_info_t *buf = NULL; char* filename; int ret; if (looper->data) if (looper->data->buf) buf = looper->data->buf; if (!buf) return; filename = looper_get_save_filename(GTK_WINDOW(looper->parent)); if (filename){ ret = buffer_save(looper->data->buf, filename, looper->samplerate, looperdata_get_recstart(looper->data), looperdata_get_recend(looper->data)); if (ret < 1) printf ("error saving file\n"); else printf("saved"); free(filename); }else printf ("filename error saving file\n"); } /* not in use any more: */ /* static void looper_normbutton_callback (GtkWidget *normbutton,gpointer data ){ looper_gui_t *looper = (looper_gui_t*)data; float factor; if (looper->data->buf){ factor = buffer_analyze (looper->data->buf, 0 , 0); if (factor){ printf ("factor:%f\n",factor); factor = 1.0 / factor; buffer_normalize (looper->data->buf, factor, 0, 0); } } } */ void looper_update_widgets(looper_gui_t *looper){ if (!looper->data) return; if (!looper->data->buf) return; if (!buffer_get_size(looper->data->buf)) return; if (!looper->bg_set){ if (looper->remote_controlled) gtk_widget_modify_bg(GTK_WIDGET(looper->menu_bar), GTK_STATE_NORMAL, &(GdkColor){65535, 65535, 0 ,0}); else gtk_widget_modify_bg(GTK_WIDGET(looper->menu_bar), GTK_STATE_NORMAL, NULL); looper->bg_set = 1; } if (looper->data->keepabsolute){ looper->looplengthblock = 1; gtk_spin_button_set_range((GtkSpinButton*)looper->loopstartspin, 0,samples2speedsecs(looper,buffer_get_size(looper->data->buf))); gtk_spin_button_set_range((GtkSpinButton*)looper->loopendspin, 0,samples2speedsecs(looper,buffer_get_size(looper->data->buf))); gtk_spin_button_set_range((GtkSpinButton*)looper->looplengthspin, 0,samples2speedsecs(looper,buffer_get_size(looper->data->buf))); looper->looplengthblock = 1; gtk_spin_button_set_value ((GtkSpinButton*)looper->looplengthspin, samples2speedsecs(looper, (looper->data->loopend - looper->data->loopstart))); gtk_spin_button_set_value ((GtkSpinButton*)looper->loopstartspin, samples2speedsecs(looper,looper->data->loopstart)); gtk_spin_button_set_value ((GtkSpinButton*)looper->loopendspin, samples2speedsecs(looper,looper->data->loopend)); looper->recstartblock = 1; gtk_spin_button_set_range((GtkSpinButton*)looper->recstartspin, 0,samples2speedsecs(looper,buffer_get_size(looper->data->buf))); gtk_spin_button_set_range((GtkSpinButton*)looper->recendspin, 0,samples2speedsecs(looper,buffer_get_size(looper->data->buf))); gtk_spin_button_set_range((GtkSpinButton*)looper->reclengthspin, 0,samples2speedsecs(looper,buffer_get_size(looper->data->buf))); looper->reclengthblock = 1; gtk_spin_button_set_value ((GtkSpinButton*)looper->reclengthspin, samples2speedsecs(looper, (looper->data->recend - looper->data->recstart))); gtk_spin_button_set_value ((GtkSpinButton*)looper->recstartspin, samples2speedsecs(looper,looper->data->recstart)); gtk_spin_button_set_value ((GtkSpinButton*)looper->recendspin, samples2speedsecs(looper,looper->data->recend)); }else{ looper->looplengthblock = 1; gtk_spin_button_set_range((GtkSpinButton*)looper->looplengthspin, 0,samples2secs(looper,buffer_get_size(looper->data->buf))); gtk_spin_button_set_range((GtkSpinButton*)looper->loopstartspin, 0,samples2secs(looper,buffer_get_size(looper->data->buf))); gtk_spin_button_set_range((GtkSpinButton*)looper->loopendspin, 0,samples2secs(looper,buffer_get_size(looper->data->buf))); looper->looplengthblock = 1; gtk_spin_button_set_value ((GtkSpinButton*)looper->looplengthspin, samples2secs(looper, (looper->data->loopend - looper->data->loopstart))); gtk_spin_button_set_value ((GtkSpinButton*)looper->loopstartspin, samples2secs(looper,looper->data->loopstart)); gtk_spin_button_set_value ((GtkSpinButton*)looper->loopendspin, samples2secs(looper,looper->data->loopend)); looper->reclengthblock = 1; gtk_spin_button_set_range((GtkSpinButton*)looper->reclengthspin, 0,samples2secs(looper,buffer_get_size(looper->data->buf))); gtk_spin_button_set_range((GtkSpinButton*)looper->recstartspin, 0,samples2secs(looper,buffer_get_size(looper->data->buf))); gtk_spin_button_set_range((GtkSpinButton*)looper->recendspin, 0,samples2secs(looper,buffer_get_size(looper->data->buf))); looper->reclengthblock = 1; gtk_spin_button_set_value ((GtkSpinButton*)looper->reclengthspin, samples2secs(looper, (looper->data->recend - looper->data->recstart))); gtk_spin_button_set_value ((GtkSpinButton*)looper->recstartspin, samples2secs(looper,looper->data->recstart)); gtk_spin_button_set_value ((GtkSpinButton*)looper->recendspin, samples2secs(looper,looper->data->recend)); } if (looperdata_get_vol(looper->data)){ looper->volblock = 1; gtk_range_set_value ((GtkRange*)looper->volslider, /* logf(looper->data->vol) * 70.0 / 8.0590477);*/ logf(looperdata_get_vol(looper->data)) * 8.656170245); } else gtk_range_set_value ((GtkRange*)looper->volslider, -48.); /* printf ("vol_sliderset:%f\n",logf(looperdata_get_vol(looper->data)) * 8.656170245);*/ gtk_range_set_value ((GtkRange*)looper->ngrainslider, looper->data->ngrains); gtk_range_set_value ((GtkRange*)looper->panslider, looper->data->pan); gtk_range_set_value ((GtkRange*)looper->recmixslider, looper->data->recmix); gtk_spin_button_set_value ((GtkSpinButton*)looper->speedspin, looper->data->speed); gtk_spin_button_set_value ((GtkSpinButton*)looper->panswingspin, looper->data->panswing); gtk_spin_button_set_value ((GtkSpinButton*)looper->densityspin, looper->data->graindensity); gtk_spin_button_set_value ((GtkSpinButton*)looper->diversityspin, looperdata_get_stereodiversity(looper->data)); gtk_loopview_update_loopstart((GtkLoopview*)looper->loopview); gtk_loopview_update_loopend((GtkLoopview*)looper->loopview); gtk_loopview_update_recstart((GtkLoopview*)looper->loopview); gtk_loopview_update_recend((GtkLoopview*)looper->loopview); /* gtk_loopview_update_waveform(GTK_LOOPVIEW(looper->loopview)); */ } void looper_set_buffer_by_id (looper_gui_t *looper, int id){ looper_data_t *new_data; looper_data_t *old_data; buffer_info_t *buf = NULL; buffer_info_t *tmp = NULL; if (looper->customcurvedialog){ gtk_widget_destroy (looper->customcurvedialog); looper->customcurvedialog = NULL; } tmp = speciallist_get_first(looper->bufferlist); while(tmp){ if (tmp->id == id) buf = tmp; tmp = speciallist_get_next(looper->bufferlist,tmp); } if (buf){ gtk_loopview_suspend_gui(GTK_LOOPVIEW(looper->loopview),1); if (looper->gid && looper->data->buf){ /* printf ("looper deleting gid:%d\n",looper->gid);*/ buffer_lock(looper->data->buf); buffer_delete_group(looper->data->buf, looper->gid); buffer_unlock(looper->data->buf); } looperdata_lock(looper->data); new_data = looperdata_new(buf, looper->samplerate, looper->id); looper->gid = buffer_get_group (buf, DS_PRIORITY_RELAXED); /* printf ("looper get gid:%d\n",looper->gid);*/ if (looper->data){ looperdata_copy_settings (new_data, looper->data); looper->data->isplaying = 0; looper->data->isrecording = 0; } if (buffer_get_type(buf) == BUFFER_TYPE_DISCSTREAM) looperdata_set_recording(new_data,0); /* looperdata_set_thresholdmode (new_data, 1);*/ old_data = looper->data; looper->data = new_data; /* try: */ /* LATER: replayce with gui */ /* printf ("set reverb\n"); looperdata_set_reverblength(looper->data,10000); looperdata_set_feedback(looper->data,.9); printf ("done\n"); */ looperdata_unlock(old_data); /* printf ("set buffer:%s\n",looper->data->buf->shortname);*/ speciallist_lock(looper->looperdatalist); speciallist_delete_nolock(looper->looperdatalist, (void*)old_data); speciallist_append_nolock(looper->looperdatalist, (void*)new_data); speciallist_unlock(looper->looperdatalist); gtk_frame_set_label(GTK_FRAME(looper->controlframe),(gchar*)buf->shortname); gtk_loopview_set_looperdata(GTK_LOOPVIEW(looper->loopview),looper->data); if (buffer_get_type(buf) == BUFFER_TYPE_DISCSTREAM) gtk_widget_set_sensitive(GTK_WIDGET(looper->recbutton), FALSE); else gtk_widget_set_sensitive(GTK_WIDGET(looper->recbutton), TRUE); looper_update_widgets(looper); looper_update_bufferlist(looper,looper->bufferlist); gtk_loopview_update_waveform(GTK_LOOPVIEW(looper->loopview)); gtk_loopview_suspend_gui(GTK_LOOPVIEW(looper->loopview),0); looperdata_free (old_data); } /* printf ("set_bufferby_id callback done\n");*/ } static void looper_set_buffer_callback(GtkMenuItem *menuitem, gpointer data){ looper_gui_t *looper = (looper_gui_t *)data; buffer_info_t *buf = g_object_get_data (G_OBJECT(menuitem),"kluppe-buffer"); looper_set_buffer_by_id(looper, buf->id); } int looper_update_bufferlist (looper_gui_t* looper, speciallist_t *bufferlist){ GtkWidget *menu_item; GtkWidget *menu; buffer_info_t *buf; if (looper != NULL){ looper->bufferlist = bufferlist; gtk_widget_destroy (looper->buffermenu); menu = gtk_menu_new (); if (speciallist_get_first(bufferlist) && looper->data->buf){ menu_item = gtk_menu_item_new_with_label ("normalize active buffer"); g_signal_connect (G_OBJECT (menu_item), "activate", G_CALLBACK (looper_normalize_callback), (gpointer)looper); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item); gtk_widget_show (menu_item); menu_item = gtk_menu_item_new_with_label ("de-normalize active buffer"); g_signal_connect (G_OBJECT (menu_item), "activate", G_CALLBACK (looper_denormalize_callback), (gpointer)looper); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item); if (buffer_get_volume_factor(looper->data->buf) == 1.) gtk_widget_set_sensitive(GTK_WIDGET(menu_item), FALSE); gtk_widget_show (menu_item); menu_item = gtk_menu_item_new_with_label ("normalize play selection"); g_signal_connect (G_OBJECT (menu_item), "activate", G_CALLBACK (looper_normalize_playselection_callback), (gpointer)looper); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item); if (buffer_get_type(looper->data->buf) == BUFFER_TYPE_DISCSTREAM) gtk_widget_set_sensitive(GTK_WIDGET(menu_item), FALSE); gtk_widget_show (menu_item); menu_item = gtk_menu_item_new_with_label ("normalize rec selection"); g_signal_connect (G_OBJECT (menu_item), "activate", G_CALLBACK (looper_normalize_recselection_callback), (gpointer)looper); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item); if (buffer_get_type(looper->data->buf) == BUFFER_TYPE_DISCSTREAM) gtk_widget_set_sensitive(GTK_WIDGET(menu_item), FALSE); gtk_widget_show (menu_item); menu_item = gtk_separator_menu_item_new(); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item); gtk_widget_show (menu_item); menu_item = gtk_menu_item_new_with_label ("clear active buffer"); g_signal_connect (G_OBJECT (menu_item), "activate", G_CALLBACK (looper_clear_callback), (gpointer)looper); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item); if (buffer_get_type(looper->data->buf) == BUFFER_TYPE_DISCSTREAM) gtk_widget_set_sensitive(GTK_WIDGET(menu_item), FALSE); gtk_widget_show (menu_item); menu_item = gtk_menu_item_new_with_label ("clear play selection"); g_signal_connect (G_OBJECT (menu_item), "activate", G_CALLBACK (looper_clear_playselection_callback), (gpointer)looper); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item); if (buffer_get_type(looper->data->buf) == BUFFER_TYPE_DISCSTREAM) gtk_widget_set_sensitive(GTK_WIDGET(menu_item), FALSE); gtk_widget_show (menu_item); menu_item = gtk_menu_item_new_with_label ("clear rec selection"); g_signal_connect (G_OBJECT (menu_item), "activate", G_CALLBACK (looper_clear_recselection_callback), (gpointer)looper); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item); if (buffer_get_type(looper->data->buf) == BUFFER_TYPE_DISCSTREAM) gtk_widget_set_sensitive(GTK_WIDGET(menu_item), FALSE); gtk_widget_show (menu_item); menu_item = gtk_separator_menu_item_new(); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item); gtk_widget_show (menu_item); menu_item = gtk_menu_item_new_with_label ("save buffer content to file"); g_signal_connect (G_OBJECT (menu_item), "activate", G_CALLBACK (looper_savebuffer2file_callback), (gpointer)looper); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item); gtk_widget_show (menu_item); menu_item = gtk_menu_item_new_with_label ("save play selection to file"); g_signal_connect (G_OBJECT (menu_item), "activate", G_CALLBACK (looper_saveplayselection2file_callback), (gpointer)looper); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item); gtk_widget_show (menu_item); menu_item = gtk_menu_item_new_with_label ("save rec selection to file"); g_signal_connect (G_OBJECT (menu_item), "activate", G_CALLBACK (looper_saverecselection2file_callback), (gpointer)looper); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item); gtk_widget_show (menu_item); menu_item = gtk_separator_menu_item_new(); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item); gtk_widget_show (menu_item); } buf = speciallist_get_first(bufferlist); while(buf){ if (buf->status == BUFFER_STATUS_READY){ menu_item = gtk_menu_item_new_with_label ((gchar*)buffer_get_shortname(buf)); /* gtk_widget_modify_font(menu_item,looper->font);*/ gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item); g_object_set_data (G_OBJECT (menu_item), "kluppe-buffer",&buf->id); g_signal_connect (G_OBJECT (menu_item), "activate", G_CALLBACK (looper_set_buffer_callback), looper); gtk_widget_show (menu_item); } buf = speciallist_get_next(bufferlist,buf); } gtk_widget_show (menu); looper->buffermenu = gtk_menu_item_new_with_label ("buffer"); gtk_menu_item_set_submenu (GTK_MENU_ITEM (looper->buffermenu), menu); gtk_widget_modify_font(looper->buffermenu,looper->font); gtk_widget_show (looper->buffermenu); gtk_menu_shell_prepend (GTK_MENU_SHELL (looper->menu_bar), looper->buffermenu); return 0; } return -1; } void looper_shuttle_poll (looper_gui_t* looper){ while (shuttle_poll (looper->shuttle) > 0){ switch (looper->shuttle->code){ case SHUTTLE_LEFTMOST : if ((!looper->shuttle->value) && (looper->shuttle->lastcode == looper->shuttle->code)){ if (gtk_toggle_button_get_active((GtkToggleButton*)looper->playbutton)) gtk_toggle_button_set_active((GtkToggleButton*)looper->playbutton, FALSE); else gtk_toggle_button_set_active((GtkToggleButton*)looper->playbutton, TRUE); } break; case SHUTTLE_MIDDLE : if ((!looper->shuttle->value) && (looper->shuttle->lastcode == looper->shuttle->code)){ if (looper->shuttle->buttonstates & SHUTTLE_LEFTMOST){ looperdata_lock(looper->data); looperdata_set_playpos(looper->data, looperdata_get_loopstart(looper->data)); looperdata_unlock(looper->data); } if (looper->shuttle->buttonstates & SHUTTLE_RIGHTMOST){ looperdata_lock(looper->data); looperdata_set_recpos(looper->data, looperdata_get_recstart(looper->data)); looperdata_unlock(looper->data); } } break; case SHUTTLE_RIGHTMOST : if ((!looper->shuttle->value) && (looper->shuttle->lastcode == looper->shuttle->code)){ if (gtk_toggle_button_get_active((GtkToggleButton*)looper->recbutton)) gtk_toggle_button_set_active((GtkToggleButton*)looper->recbutton, FALSE); else gtk_toggle_button_set_active((GtkToggleButton*)looper->recbutton, TRUE); } break; case SHUTTLE_SHUTTLE: /* printf ("delta:%0.04f, %d\n",looper->shuttle->shuttledelta,looper->shuttle->shuttlestate);*/ if (!looper->shuttle->buttonstates){ gtk_range_set_value ((GtkRange*)looper->panslider, gtk_range_get_value((GtkRange*)looper->panslider) + looper->shuttle->shuttledelta * .01); }else if (looper->shuttle->buttonstates & SHUTTLE_LEFTMOST){ gtk_spin_button_set_value ((GtkSpinButton*)looper->loopstartspin, (gfloat)looper->shuttle->shuttledelta / 100. * gtk_spin_button_get_value ((GtkSpinButton*)looper->looplengthspin) + gtk_spin_button_get_value ((GtkSpinButton*)looper->loopstartspin) ); }else if (looper->shuttle->buttonstates & SHUTTLE_LEFT){ gtk_spin_button_set_value ((GtkSpinButton*)looper->densityspin, (gfloat)looper->shuttle->shuttledelta / 2. + gtk_spin_button_get_value ((GtkSpinButton*)looper->densityspin) ); }else if (looper->shuttle->buttonstates & SHUTTLE_MIDDLE){ gtk_range_set_value ((GtkRange*)looper->ngrainslider,0); }else if (looper->shuttle->buttonstates & SHUTTLE_RIGHT){ gtk_range_set_value ((GtkRange*)looper->recmixslider, gtk_range_get_value((GtkRange*)looper->recmixslider) + looper->shuttle->shuttledelta * .05); }else if (looper->shuttle->buttonstates & SHUTTLE_RIGHTMOST){ gtk_spin_button_set_value ((GtkSpinButton*)looper->recstartspin, (gfloat)looper->shuttle->shuttledelta / 100. * gtk_spin_button_get_value ((GtkSpinButton*)looper->reclengthspin) + gtk_spin_button_get_value ((GtkSpinButton*)looper->recstartspin) ); }/* end if shuttle and !buttons */ break; } } if (looper->shuttle->jogstate){ if (!looper->shuttle->buttonstates){ gtk_spin_button_set_value ((GtkSpinButton*)looper->speedspin, /* gtk_spin_button_get_value ((GtkSpinButton*)looper->speedspin) / 100. * looper->shuttle->value +*/ looper->shuttle->jogstate * looper->shuttle->jogstate * looper->shuttle->jogstate * .002 + gtk_spin_button_get_value ((GtkSpinButton*)looper->speedspin) ); } else if (looper->shuttle->buttonstates & SHUTTLE_LEFTMOST){ gtk_spin_button_set_value ((GtkSpinButton*)looper->looplengthspin, (gfloat)looper->shuttle->jogstate / 100. * gtk_spin_button_get_value ((GtkSpinButton*)looper->looplengthspin) + gtk_spin_button_get_value ((GtkSpinButton*)looper->looplengthspin) ); } else if (looper->shuttle->buttonstates & SHUTTLE_LEFT){ gtk_range_set_value ((GtkRange*)looper->ngrainslider, gtk_range_get_value((GtkRange*)looper->ngrainslider) + looper->shuttle->jogstate / 10.); } else if (looper->shuttle->buttonstates & SHUTTLE_MIDDLE){ gtk_spin_button_set_value ((GtkSpinButton*)looper->speedspin,1.0); } else if (looper->shuttle->buttonstates & SHUTTLE_RIGHT){ gtk_range_set_value ((GtkRange*)looper->volslider, gtk_range_get_value((GtkRange*)looper->volslider) + looper->shuttle->jogstate / 5.); } else if (looper->shuttle->buttonstates & SHUTTLE_RIGHTMOST){ gtk_spin_button_set_value ((GtkSpinButton*)looper->reclengthspin, (gfloat)looper->shuttle->jogstate / 100. * gtk_spin_button_get_value ((GtkSpinButton*)looper->reclengthspin) + gtk_spin_button_get_value ((GtkSpinButton*)looper->reclengthspin) ); }else printf ("buttonstate:%d\n",looper->shuttle->buttonstates);/* end if jog and !buttons */ } /* cosmetics: */ if (looper->shuttle->fd < 1) gtk_toggle_button_set_active((GtkToggleButton*)looper->shuttlebutton,FALSE); } void looper_update_cursorposition (looper_gui_t* looper){ GtkAdjustment *adj; float vL, vR; gdouble v; if (looper->customcurvedialog){ customcurve_update( customcurvedialog_get_curve(looper->customcurvedialog), looper->data); } if (looper->dirty){ looper_update_widgets(looper); looper->dirty = 0;} looper_shuttle_poll (looper); if (looper->vublock) looper->vublock = FALSE; else{ looper->vublock = TRUE; /* play meters */ adj = gtk_meter_get_adjustment(GTK_METER(looper->outLmeter)); /* looperdata_lock(looper->data);*/ looperdata_get_playmeters(looper->data, &vL, &vR); /* looperdata_unlock(looper->data);*/ v = 20.0f * log10f(vL); if (v > -70.){ gtk_adjustment_set_value(adj,v); }else{ gtk_adjustment_set_value(adj,-70.); } v = 20.0f * log10f(vR); adj = gtk_meter_get_adjustment(GTK_METER(looper->outRmeter)); if (v > -70.){ gtk_adjustment_set_value(adj,v); }else{ gtk_adjustment_set_value(adj,-70.); } /* rec meters */ /* looperdata_lock(looper->data);*/ looperdata_get_recmeters(looper->data, &vL, &vR); /* looperdata_unlock(looper->data);*/ adj = gtk_meter_get_adjustment(GTK_METER(looper->inLmeter)); v = 20.0f * log10f(vL); if (v > -70.){ gtk_adjustment_set_value(adj,v); }else{ gtk_adjustment_set_value(adj,-70.); } v = 20.0f * log10f(vR); adj = gtk_meter_get_adjustment(GTK_METER(looper->inRmeter)); if (v > -70.){ gtk_adjustment_set_value(adj,v); }else{ gtk_adjustment_set_value(adj,-70.); } } if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(looper->playbutton))) if (!looperdata_get_playing(looper->data)) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(looper->playbutton),FALSE); if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(looper->recbutton))) if (!looperdata_get_recording(looper->data)) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(looper->recbutton),FALSE); gtk_loopview_update_cursorposition(GTK_LOOPVIEW(looper->loopview)); return; } /* callback functions */ static void looper_grainsettings_callback (GtkMenuItem *menuitem, gpointer data){ looper_gui_t *looper = (looper_gui_t *)data; graindialog_new(looper->parent, looper->data, looper->id); } static void looper_threshsettings_callback (GtkMenuItem *menuitem, gpointer data){ looper_gui_t *looper = (looper_gui_t *)data; threshdialog_new(looper->parent, looper->data); } static void looper_gridsettings_callback (GtkMenuItem *menuitem, gpointer data){ looper_gui_t *looper = (looper_gui_t *)data; griddialog_new(looper->parent, GTK_LOOPVIEW(looper->loopview)); } static void looper_gridfromplayselection_callback (GtkMenuItem *menuitem, gpointer data){ looper_gui_t *looper = (looper_gui_t *)data; long s, e, o; if (looper->data){ if (looper->data->buf){ s = looperdata_get_loopstart(looper->data); e = looperdata_get_loopend(looper->data); o = s % (e - s); /* printf ("o:%ld, s:%ld, e:%ld, l:%ld\n",(long)o,(long)s,(long)e,(long)(e - s));*/ gtk_loopview_set_bpm(GTK_LOOPVIEW(looper->loopview), (gdouble)(looper->samplerate * 60.)/ (gdouble)(e - s)); gtk_loopview_set_bpb(GTK_LOOPVIEW(looper->loopview),1); gtk_loopview_set_gridoffset(GTK_LOOPVIEW(looper->loopview),o); /* printf ("o:%ld, bpm:%ld, bpb:%ld\n", (long)gtk_loopview_get_gridoffset(GTK_LOOPVIEW(looper->loopview)), (long)gtk_loopview_get_bpm(GTK_LOOPVIEW(looper->loopview)), (long)gtk_loopview_get_bpb(GTK_LOOPVIEW(looper->loopview)));*/ } } } static void looper_gridfromrecselection_callback (GtkMenuItem *menuitem, gpointer data){ looper_gui_t *looper = (looper_gui_t *)data; long s, e, o; if (looper->data){ if (looper->data->buf){ s = looperdata_get_recstart(looper->data); e = looperdata_get_recend(looper->data); o = s % (e - s); gtk_loopview_set_bpm(GTK_LOOPVIEW(looper->loopview), (gdouble)(looper->samplerate * 60.)/ (gdouble)(e - s)); gtk_loopview_set_bpb(GTK_LOOPVIEW(looper->loopview),1); gtk_loopview_set_gridoffset(GTK_LOOPVIEW(looper->loopview),o); } } } static void looper_custommode_destroy_callback(GtkWidget *dialog, gpointer data){ /* looper_gui_t *looper = (looper_gui_t *)data; this doesn't work because data=responsecode*/ looper_gui_t *looper = g_object_get_data (G_OBJECT (dialog),"looper"); looper->customcurvedialog = NULL; gtk_widget_destroy (dialog); } static void looper_custommode_callback(GtkMenuItem *menuitem, gpointer data){ looper_gui_t *looper = (looper_gui_t *)data; if (!looper->customcurvedialog){ looper->customcurvedialog = customcurvedialog_new (looper->parent, looper->data, looper->id); g_object_set_data (G_OBJECT (looper->customcurvedialog), "looper", data); g_signal_connect (G_OBJECT(looper->customcurvedialog), "response", G_CALLBACK (looper_custommode_destroy_callback),data); } } static void loopview_changed_loopborders (GtkWidget *loopview, gpointer data){ looper_gui_t *looper = (looper_gui_t*)data; looper->loopstartblock = 1; looper->loopendblock = 1; looper->looplengthblock = 1; if (looper->data->keepabsolute){ gtk_spin_button_set_value ((GtkSpinButton*)looper->loopstartspin, samples2speedsecs(looper,looper->data->loopstart)); gtk_spin_button_set_value ((GtkSpinButton*)looper->loopendspin, samples2speedsecs(looper,looper->data->loopend)); gtk_spin_button_set_value ((GtkSpinButton*)looper->looplengthspin, samples2speedsecs(looper,(looper->data->loopend - looper->data->loopstart))); }else{ gtk_spin_button_set_value ((GtkSpinButton*)looper->loopstartspin, samples2secs(looper,looper->data->loopstart)); gtk_spin_button_set_value ((GtkSpinButton*)looper->loopendspin, samples2secs(looper,looper->data->loopend)); gtk_spin_button_set_value ((GtkSpinButton*)looper->looplengthspin, samples2secs(looper,(looper->data->loopend - looper->data->loopstart))); } if (looper->data->linkrec2play){ looperdata_lock(looper->data); looper->data->recstart = looper->data->loopstart; looper->data->recend = looper->data->loopend; looperdata_unlock(looper->data); looper->recstartblock = 1; looper->recstartblock = 1; looper->reclengthblock = 1; gtk_spin_button_set_value ((GtkSpinButton*)looper->recstartspin, samples2secs(looper,looper->data->recstart)); gtk_spin_button_set_value ((GtkSpinButton*)looper->recendspin, samples2secs(looper,looper->data->recend)); gtk_spin_button_set_value ((GtkSpinButton*)looper->reclengthspin, samples2secs(looper, looper->data->recend - looper->data->recstart)); gtk_loopview_update_recstart((GtkLoopview*)looper->loopview); gtk_loopview_update_recend((GtkLoopview*)looper->loopview); } } static void loopview_changed_recborders (GtkWidget *loopview, gpointer data){ looper_gui_t *looper = (looper_gui_t*)data; looper->recstartblock = 1; looper->recendblock = 1; looper->reclengthblock = 1; gtk_spin_button_set_value ((GtkSpinButton*)looper->recstartspin, samples2secs(looper,looper->data->recstart)); gtk_spin_button_set_value ((GtkSpinButton*)looper->recendspin, samples2secs(looper,looper->data->recend)); gtk_spin_button_set_value ((GtkSpinButton*)looper->reclengthspin, samples2secs(looper,(looper->data->recend - looper->data->recstart))); } static void loopview_changed_speed (GtkWidget *loopview, gpointer data){ looper_gui_t *looper = (looper_gui_t*)data; looper->speedblock = 1; gtk_spin_button_set_value ((GtkSpinButton*)looper->speedspin, looper->data->speed); } static void looper_playbutton_callback (GtkWidget *playbutton,gpointer data ){ looper_gui_t *looper = (looper_gui_t*)data; if (gtk_toggle_button_get_active((GtkToggleButton*)playbutton)) { looperdata_lock(looper->data); looper->data->isplaying = 1; looperdata_unlock(looper->data); }else{ looperdata_lock(looper->data); looper->data->isplaying = 0; looperdata_unlock(looper->data); } } static void looper_recbutton_callback (GtkWidget *recbutton,gpointer data ){ looper_gui_t *looper = (looper_gui_t*)data; if (gtk_toggle_button_get_active((GtkToggleButton*)recbutton)) { looperdata_lock(looper->data); looper->data->isrecording = 1; looperdata_unlock(looper->data); }else{ looperdata_lock(looper->data); looper->data->isrecording = 0; looperdata_unlock(looper->data); } } void looper_set_minimized (looper_gui_t* looper, gboolean minimized){ gint lastwidth = 0; gint lastheight = 0; if (minimized){ gtk_widget_hide((GtkWidget*)looper->smallbox); gtk_widget_hide((GtkWidget*)looper->middlebox); gtk_window_get_size ((GtkWindow*)looper->parent,&lastwidth,&lastheight); gtk_window_resize((GtkWindow*)looper->parent,lastwidth,1); }else{ gtk_widget_show((GtkWidget*)looper->smallbox); gtk_widget_show((GtkWidget*)looper->middlebox); } } static void looper_minimizebutton_callback(GtkWidget *minimizebutton,gpointer data ){ looper_gui_t *looper = (looper_gui_t*)data; if (gtk_toggle_button_get_active((GtkToggleButton*)minimizebutton)) looper_set_minimized (looper, TRUE); else looper_set_minimized (looper, FALSE); } static void looper_shuttlebutton_callback (GtkWidget *shuttlebutton,gpointer data ){ looper_gui_t *looper = (looper_gui_t*)data; if (gtk_toggle_button_get_active((GtkToggleButton*)shuttlebutton)) { if (shuttle_open(looper->shuttle) < 1){ gtk_toggle_button_set_active((GtkToggleButton*)shuttlebutton,FALSE); } }else{ shuttle_close(looper->shuttle); } } static void looper_panslider_callback (GtkWidget *panslider, gpointer data ){ looper_gui_t *looper = (looper_gui_t*)data; looperdata_lock(looper->data); /* looper->data->pan = gtk_range_get_value(GTK_RANGE(looper->panslider));*/ looperdata_set_pan(looper->data, gtk_range_get_value(GTK_RANGE(looper->panslider)) ); looperdata_unlock(looper->data); } static void looper_ngrainslider_callback (GtkWidget *ngrainslider, gpointer data ){ looper_gui_t *looper = (looper_gui_t*)data; looperdata_lock(looper->data); looperdata_set_ngrains(looper->data, (int)gtk_range_get_value(GTK_RANGE(looper->ngrainslider))); looperdata_unlock(looper->data); } static void looper_densityspin_callback (GtkWidget *densityspin, gpointer data ){ looper_gui_t *looper = (looper_gui_t*)data; // printf ("densityspin callback\n"); looperdata_lock(looper->data); looperdata_set_graindensity(looper->data, (int)gtk_spin_button_get_value((GtkSpinButton*)looper->densityspin)); looperdata_unlock(looper->data); } static void looper_panswingspin_callback (GtkWidget *panswingspin, gpointer data ){ looper_gui_t *looper = (looper_gui_t*)data; looperdata_lock(looper->data); looperdata_set_panswing(looper->data, (float)gtk_spin_button_get_value((GtkSpinButton*)looper->panswingspin)); looperdata_unlock(looper->data); } /* static void looper_grainlenslider_callback (GtkWidget *grainlenslider, gpointer data ){ looper_gui_t *looper = (looper_gui_t*)data; looperdata_lock(looper->data); looperdata_set_grainlength(looper->data, (int)gtk_range_get_value(GTK_RANGE(looper->grainlenslider))); looperdata_unlock(looper->data); } */ static void looper_recmixslider_callback (GtkWidget *recmixslider, gpointer data ){ looper_gui_t *looper = (looper_gui_t*)data; looperdata_lock(looper->data); /* looper->data->recmix = gtk_range_get_value(GTK_RANGE(looper->recmixslider));*/ looperdata_set_recmix(looper->data, gtk_range_get_value(GTK_RANGE(looper->recmixslider)) ); looperdata_unlock(looper->data); } static void looper_toggle_link_rec2play(GtkWidget *menu_item, gpointer data ){ looper_gui_t *looper = (looper_gui_t*)data; if (gtk_check_menu_item_get_active((GtkCheckMenuItem*)menu_item)){ looperdata_lock(looper->data); looper->data->linkrec2play = 1; looperdata_unlock(looper->data); }else{ looperdata_lock(looper->data); looper->data->linkrec2play = 0; looperdata_unlock(looper->data); } } static void looper_toggle_keep_looplength(GtkWidget *menu_item, gpointer data ){ looper_gui_t *looper = (looper_gui_t*)data; if (gtk_check_menu_item_get_active((GtkCheckMenuItem*)menu_item)){ looperdata_lock(looper->data); looper->data->keepabsolute = 1; looperdata_unlock(looper->data); }else{ looperdata_lock(looper->data); looper->data->keepabsolute = 0; looperdata_unlock(looper->data); } } static void looper_toggle_limiter_callback(GtkWidget *menu_item, gpointer data ){ looper_gui_t *looper = (looper_gui_t*)data; if (gtk_check_menu_item_get_active((GtkCheckMenuItem*)menu_item)) { looperdata_lock(looper->data); looper->data->limiter = 1; looperdata_unlock(looper->data); }else{ looperdata_lock(looper->data); looper->data->limiter = 0; looperdata_unlock(looper->data); } } static void looper_toggle_snap2grid_callback(GtkWidget *menu_item, gpointer data ){ looper_gui_t *looper = (looper_gui_t*)data; looperdata_lock(looper->data); gtk_loopview_set_snap2grid(GTK_LOOPVIEW(looper->loopview), gtk_check_menu_item_get_active((GtkCheckMenuItem*)menu_item)); looperdata_unlock(looper->data); } static void looper_toggle_showgrid_callback(GtkWidget *menu_item, gpointer data ){ looper_gui_t *looper = (looper_gui_t*)data; looperdata_lock(looper->data); gtk_loopview_set_showgrid(GTK_LOOPVIEW(looper->loopview), gtk_check_menu_item_get_active((GtkCheckMenuItem*)menu_item)); looperdata_unlock(looper->data); } static void looper_zoom_to_play_selection_callback(GtkWidget *menu_item, gpointer data ){ looper_gui_t *looper = (looper_gui_t*)data; gtk_loopview_zoom_to_playselection((GtkLoopview*)looper->loopview); } static void looper_zoom_to_rec_selection_callback(GtkWidget *menu_item, gpointer data ){ looper_gui_t *looper = (looper_gui_t*)data; gtk_loopview_zoom_to_recselection((GtkLoopview*)looper->loopview); } static void looper_zoom_to_overview_callback(GtkWidget *menu_item, gpointer data ){ looper_gui_t *looper = (looper_gui_t*)data; gtk_loopview_zoom_to_overview((GtkLoopview*)looper->loopview); } static void looper_playmode_callback(GtkWidget *menu_item, gpointer data ){ looper_gui_t *looper = (looper_gui_t*)data; if (GTK_CHECK_MENU_ITEM(menu_item)->active) { looperdata_lock(looper->data); looperdata_set_playmode(looper->data, GPOINTER_TO_UINT(g_object_get_data (G_OBJECT(menu_item),"playmode"))); looperdata_unlock(looper->data); } } static void looper_clickmode_callback(GtkWidget *menu_item, gpointer data ){ looper_gui_t *looper = (looper_gui_t*)data; if (GTK_CHECK_MENU_ITEM(menu_item)->active) { looperdata_lock(looper->data); looperdata_set_clickmode_buf(looper->data, g_object_get_data (G_OBJECT(menu_item),"buffer")); looperdata_unlock(looper->data); } } static void looper_recmode_callback(GtkWidget *menu_item, gpointer data ){ looper_gui_t *looper = (looper_gui_t*)data; if (GTK_CHECK_MENU_ITEM(menu_item)->active) { looperdata_lock(looper->data); looperdata_set_recmode(looper->data, GPOINTER_TO_UINT(g_object_get_data (G_OBJECT(menu_item),"recmode"))); looperdata_unlock(looper->data); } } static void looper_toggle_thresholdmode_callback(GtkWidget *menu_item, gpointer data ){ looper_gui_t *looper = (looper_gui_t*)data; if (looper->data){ looperdata_lock(looper->data); if (GTK_CHECK_MENU_ITEM(menu_item)->active) { looperdata_set_thresholdmode(looper->data,1); } else looperdata_set_thresholdmode(looper->data,0); looperdata_unlock(looper->data); } } static void looper_volslider_callback (GtkWidget *volslider, gpointer data ){ looper_gui_t *looper = (looper_gui_t*)data; float f; if (!looper->volblock){ f = gtk_range_get_value(GTK_RANGE(looper->volslider)); looperdata_lock(looper->data); if (f < -47.) looperdata_set_vol (looper->data, 0); else looperdata_set_vol (looper->data, powf(10.0f, f * 0.05f)); /* printf ("vol_slidercallback:%f\n",f);*/ looperdata_unlock(looper->data); } looper->volblock = 0; } static void looper_diversityspin_callback (GtkWidget *speedspin, gpointer data ){ looper_gui_t *looper = (looper_gui_t*)data; GtkSpinButton *spin = GTK_SPIN_BUTTON (looper->diversityspin); if (looper->data){ looperdata_lock(looper->data); looperdata_set_stereodiversity(looper->data,gtk_spin_button_get_value (spin)); looperdata_unlock(looper->data); } } static void looper_speedspin_callback (GtkWidget *speedspin, gpointer data ){ looper_gui_t *looper = (looper_gui_t*)data; GtkSpinButton *spin = GTK_SPIN_BUTTON (looper->speedspin); float ltmp, rtmp; if (looper->speedblock){ looper->speedblock = 0; }else{ looperdata_lock(looper->data); if (gtk_spin_button_get_value(spin) && looper->data->keepabsolute){ /* LATER: enhance this */ ltmp = looper->data->loopend - looper->data->loopstart; ltmp *= fabs(looper->data->speed) / fabs(gtk_spin_button_get_value (spin)); rtmp = looper->data->recend - looper->data->recstart; rtmp *= fabs(looper->data->speed) / fabs(gtk_spin_button_get_value (spin)); looper->data->loopend = looper->data->loopstart + (long)ltmp; if (looper->data->loopend > buffer_get_size(looper->data->buf)){ looper->data->loopend = buffer_get_size(looper->data->buf); } if (looper->data->linkrec2play){ looper->data->recend = looper->data->loopend; }else{ looper->data->recend = looper->data->recstart + (long)rtmp; if (looper->data->recend > buffer_get_size(looper->data->buf)){ looper->data->recend = buffer_get_size(looper->data->buf); } } } looper->data->speed = gtk_spin_button_get_value (spin); looperdata_unlock(looper->data); if (looper->data->keepabsolute && looper->data->speed){ /* crazy: set_range emits "value_changed" */ looper->loopstartblock = 1; looper->loopendblock = 1; looper->looplengthblock = 1; gtk_spin_button_set_range((GtkSpinButton*)looper->loopstartspin, 0,samples2speedsecs(looper,buffer_get_size(looper->data->buf))); gtk_spin_button_set_range((GtkSpinButton*)looper->loopendspin, 0,samples2speedsecs(looper,buffer_get_size(looper->data->buf))); gtk_spin_button_set_range((GtkSpinButton*)looper->looplengthspin, 0,samples2speedsecs(looper,buffer_get_size(looper->data->buf))); looper->recstartblock = 1; looper->recendblock = 1; looper->reclengthblock = 1; gtk_spin_button_set_range((GtkSpinButton*)looper->recstartspin, 0,samples2secs(looper,buffer_get_size(looper->data->buf))); gtk_spin_button_set_range((GtkSpinButton*)looper->recendspin, 0,samples2secs(looper,buffer_get_size(looper->data->buf))); gtk_spin_button_set_range((GtkSpinButton*)looper->reclengthspin, 0,samples2secs(looper,buffer_get_size(looper->data->buf))); looper->looplengthblock = 1; looper->loopendblock = 1; gtk_spin_button_set_value ((GtkSpinButton*)looper->looplengthspin, samples2speedsecs(looper, looper->data->loopend - looper->data->loopstart)); gtk_spin_button_set_value ((GtkSpinButton*)looper->loopendspin, looper->data->loopend); gtk_loopview_update_loopend((GtkLoopview*)looper->loopview); looper->reclengthblock = 1; looper->recendblock = 1; gtk_spin_button_set_value ((GtkSpinButton*)looper->reclengthspin, samples2speedsecs(looper, looper->data->recend - looper->data->recstart)); gtk_spin_button_set_value ((GtkSpinButton*)looper->recendspin, samples2speedsecs(looper,looper->data->recend)); gtk_loopview_update_recend((GtkLoopview*)looper->loopview); } } } static void looper_loopstartspin_callback (GtkWidget *loopstartspin, gpointer data ){ looper_gui_t *looper = (looper_gui_t*)data; GtkSpinButton *spin = GTK_SPIN_BUTTON (looper->loopstartspin); long samples; if (looper->loopstartblock){ looper->loopstartblock = 0; }else{ if (looper->data->keepabsolute){ samples = (long)speedsecs2samples(looper,gtk_spin_button_get_value (spin)); looperdata_lock(looper->data); looper->data->loopend += samples - looper->data->loopstart; looperdata_unlock(looper->data); looper->loopendblock = 1; gtk_spin_button_set_value ((GtkSpinButton*)looper->loopendspin, samples2speedsecs(looper,looper->data->loopend)); }else{ samples = (long)secs2samples(looper,gtk_spin_button_get_value (spin)); looperdata_lock(looper->data); /* looper->data->loopend += samples - looper->data->loopstart; */ looperdata_set_loopend(looper->data, looperdata_get_loopend(looper->data) + samples - looper->data->loopstart); looperdata_unlock(looper->data); looper->loopendblock = 1; gtk_spin_button_set_value ((GtkSpinButton*)looper->loopendspin, samples2secs(looper,looper->data->loopend)); } looperdata_lock(looper->data); looper->data->loopstart = samples; looperdata_unlock(looper->data); gtk_loopview_update_loopstart((GtkLoopview*)looper->loopview); gtk_loopview_update_loopend((GtkLoopview*)looper->loopview); if (looper->data->linkrec2play){ looperdata_lock(looper->data); /* looper->data->recstart = looper->data->loopstart;*/ /* looper->data->recend = looper->data->loopend;*/ looperdata_set_recstart(looper->data, looperdata_get_loopstart(looper->data)); looperdata_set_recend(looper->data, looperdata_get_loopend(looper->data)); looperdata_unlock(looper->data); looper->recstartblock = 1; looper->recstartblock = 1; gtk_spin_button_set_value ((GtkSpinButton*)looper->recstartspin, samples2secs(looper,looper->data->recstart)); gtk_spin_button_set_value ((GtkSpinButton*)looper->recendspin, samples2secs(looper,looper->data->recend)); gtk_loopview_update_recstart((GtkLoopview*)looper->loopview); gtk_loopview_update_recend((GtkLoopview*)looper->loopview); } } } static void looper_loopendspin_callback (GtkWidget *loopendspin, gpointer data ){ looper_gui_t *looper = (looper_gui_t*)data; GtkSpinButton *spin = GTK_SPIN_BUTTON (looper->loopendspin); long samples; if (looper->data->keepabsolute){ samples = (long)speedsecs2samples(looper,gtk_spin_button_get_value (spin)); }else{ samples = (long)secs2samples(looper,gtk_spin_button_get_value (spin)); } if (looper->loopendblock){ looper->loopendblock = 0; }else{ looperdata_lock(looper->data); /* looper->data->loopend = samples;*/ looperdata_set_loopend (looper->data,samples); looperdata_unlock(looper->data); looper->looplengthblock = 1; if (looper->data->keepabsolute){ gtk_spin_button_set_value ((GtkSpinButton*)looper->looplengthspin, samples2speedsecs(looper, looper->data->loopend - looper->data->loopstart)); }else{ gtk_spin_button_set_value ((GtkSpinButton*)looper->looplengthspin, samples2secs(looper, looper->data->loopend - looper->data->loopstart)); } gtk_loopview_update_loopend((GtkLoopview*)looper->loopview); if (looper->data->linkrec2play){ looperdata_lock(looper->data); /* looper->data->recend = looper->data->loopend;*/ looperdata_set_recend (looper->data,looperdata_get_loopend(looper->data)); looperdata_unlock(looper->data); looper->recendblock = 1; looper->reclengthblock = 1; gtk_spin_button_set_value ((GtkSpinButton*)looper->recendspin, samples2secs(looper,looper->data->recend)); gtk_spin_button_set_value ((GtkSpinButton*)looper->reclengthspin, samples2secs(looper, looper->data->recend - looper->data->recstart)); gtk_loopview_update_recend((GtkLoopview*)looper->loopview); } } } static void looper_looplengthspin_callback (GtkWidget *looplengthspin, gpointer data ){ looper_gui_t *looper = (looper_gui_t*)data; GtkSpinButton *spin = GTK_SPIN_BUTTON (looper->looplengthspin); long samples; if (looper->data->keepabsolute){ samples = (long)speedsecs2samples(looper,gtk_spin_button_get_value (spin)); }else{ samples = (long)secs2samples(looper,gtk_spin_button_get_value (spin)); } if (looper->looplengthblock){ looper->looplengthblock = 0; }else{ if (looper->data->buf){ if ((samples + looper->data->loopstart) > buffer_get_size(looper->data->buf)){ looperdata_lock(looper->data); looper->data->loopend = buffer_get_size(looper->data->buf); looperdata_unlock(looper->data); }else{ looperdata_lock(looper->data); looper->data->loopend = looper->data->loopstart + samples; looperdata_unlock(looper->data); } looper->loopendblock = 1; looper->looplengthblock = 1; if (looper->data->keepabsolute){ gtk_spin_button_set_value ((GtkSpinButton*)looper->loopendspin, samples2speedsecs(looper,looper->data->loopend) ); }else{ gtk_spin_button_set_value ((GtkSpinButton*)looper->loopendspin, samples2secs(looper,looper->data->loopend) ); } if (looper->data->linkrec2play){ looperdata_lock(looper->data); looper->data->recend = looper->data->loopend; looperdata_unlock(looper->data); looper->recendblock = 1; looper->reclengthblock = 1; gtk_spin_button_set_value ((GtkSpinButton*)looper->recendspin, samples2secs(looper,looper->data->recend)); gtk_spin_button_set_value ((GtkSpinButton*)looper->reclengthspin, samples2secs(looper, looper->data->recend - looper->data->recstart)); gtk_loopview_update_recend((GtkLoopview*)looper->loopview); } gtk_loopview_update_loopend((GtkLoopview*)looper->loopview); } } } static void looper_recstartspin_callback (GtkWidget *recstartspin, gpointer data ){ looper_gui_t *looper = (looper_gui_t*)data; GtkSpinButton *spin = GTK_SPIN_BUTTON (looper->recstartspin); long samples = (long)secs2samples(looper,gtk_spin_button_get_value (spin)); if (looper->recstartblock){ looper->recstartblock = 0; }else{ looperdata_lock(looper->data); looper->data->recend += samples - looper->data->recstart; looper->data->recstart = samples; looperdata_unlock(looper->data); looper->recstartblock = 1; looper->recendblock = 1; looper->reclengthblock = 1; if (looper->data->keepabsolute){ gtk_spin_button_set_value ((GtkSpinButton*)looper->recendspin, samples2speedsecs(looper,looper->data->recend)); gtk_spin_button_set_value ((GtkSpinButton*)looper->reclengthspin, samples2speedsecs(looper,looper->data->recend - looper->data->recstart)); }else{ gtk_spin_button_set_value ((GtkSpinButton*)looper->recendspin, samples2secs(looper,looper->data->recend)); gtk_spin_button_set_value ((GtkSpinButton*)looper->reclengthspin, samples2secs(looper,looper->data->recend - looper->data->recstart)); } gtk_loopview_update_recstart((GtkLoopview*)looper->loopview); gtk_loopview_update_recend((GtkLoopview*)looper->loopview); } } static void looper_recendspin_callback (GtkWidget *recendspin, gpointer data ){ looper_gui_t *looper = (looper_gui_t*)data; GtkSpinButton *spin = GTK_SPIN_BUTTON (looper->recendspin); long samples = (long)secs2samples(looper,gtk_spin_button_get_value (spin)); if (looper->recendblock){ looper->recendblock = 0; }else{ looper->reclengthblock = 1; looperdata_lock(looper->data); looper->data->recend = samples; looperdata_unlock(looper->data); if (looper->data->keepabsolute){ gtk_spin_button_set_value ((GtkSpinButton*)looper->reclengthspin, samples2speedsecs(looper, looper->data->recend - looper->data->recstart)); }else{ gtk_spin_button_set_value ((GtkSpinButton*)looper->reclengthspin, samples2secs(looper, looper->data->recend - looper->data->recstart)); } gtk_loopview_update_recend((GtkLoopview*)looper->loopview); } } static void looper_reclengthspin_callback (GtkWidget *reclengthspin, gpointer data ){ looper_gui_t *looper = (looper_gui_t*)data; GtkSpinButton *spin = GTK_SPIN_BUTTON (looper->reclengthspin); long samples = (long)secs2samples(looper,gtk_spin_button_get_value (spin)); if (looper->reclengthblock){ looper->reclengthblock = 0; }else{ if (looper->data->buf){ looperdata_lock(looper->data); if ((samples + looper->data->recstart) > buffer_get_size(looper->data->buf)){ looper->data->recend = buffer_get_size(looper->data->buf); }else{ looper->data->recend = looper->data->recstart + samples; } looperdata_unlock(looper->data); /* looper->recendblock = 1; */ looper->reclengthblock = 1; if (looper->data->keepabsolute){ gtk_spin_button_set_value ((GtkSpinButton*)looper->recendspin, samples2speedsecs(looper,looper->data->recend)); }else{ gtk_spin_button_set_value ((GtkSpinButton*)looper->recendspin, samples2secs(looper,looper->data->recend) ); } } } } /**** setup ******/ looper_gui_t* looper_new(GtkWidget* parent, GtkWidget* parentcontainer, alphatrack_t *alphatrack, speciallist_t *looperdatalist, speciallist_t *clickmodes, int id, int minimized){ looper_gui_t *looper; buffer_info_t *buf = NULL; GSList *group = NULL; GSList *recgroup = NULL; GSList *clickgroup = NULL; GtkAdjustment *adj; GtkWidget *menu_items; GtkWidget *menu1; GtkWidget *menu2; GtkWidget *menu3; GtkWidget *dummylabel; /* data initialisation */ looper = (looper_gui_t*) malloc (sizeof(looper_gui_t)); looper->data = looperdata_new(NULL, 44100, id); looper->parent = parent; looper->parentcontainer = parentcontainer; looper->id = id; looper->gid = 0; looper->dirty = 0; looper->bufferlist = speciallist_new(); looper->vposition = 0; looper->remote_controlled = 0; looper->bg_set = 1; looper->looperdatalist = looperdatalist; looper->clickmodes = clickmodes; looper->shuttle = shuttle_new(); looper->alphatrack = alphatrack; looper->encoderdelta_l = 0; looper->encoderdelta_m = 0; looper->encoderdelta_r = 0; looper->loopstartblock = 0; looper->loopendblock = 0; looper->looplengthblock = 0; looper->recstartblock = 0; looper->recendblock = 0; looper->reclengthblock = 0; looper->speedblock = 0; looper->vublock = 0; looper->volblock = 0; #if 0 /* try: */ /* LATER: replayce with gui */ printf ("set\n"); looperdata_set_reverblength(looper->data,44100); looperdata_set_feedback(looper->data,.8); printf ("done\n"); #endif /* widget initialisation */ looper->customcurvedialog = NULL; looper->tooltips = gtk_tooltips_new (); looper->font = pango_font_description_from_string("Sans 7"); /* small control widgets */ looper->smalltable = gtk_table_new (3, 3, TRUE); /* playback loop control */ adj = (GtkAdjustment *) gtk_adjustment_new (0.0, 0.0, 10.0, .001, .1, 0.0); looper->loopstartspin = gtk_spin_button_new (adj, .01, 4); g_signal_connect (G_OBJECT (adj), "value_changed", G_CALLBACK (looper_loopstartspin_callback), (gpointer) looper); gtk_table_attach((GtkTable*)looper->smalltable, looper->loopstartspin,0,1,0,1,GTK_FILL,GTK_FILL,1,3); gtk_tooltips_set_tip (looper->tooltips,looper->loopstartspin, "playback start position", NULL); gtk_widget_modify_font(looper->loopstartspin,looper->font); gtk_widget_show (looper->loopstartspin); adj = (GtkAdjustment *) gtk_adjustment_new (0.0, 0.0, 10.0, .001, .1, 0.0); looper->loopendspin = gtk_spin_button_new (adj, 1, 4); g_signal_connect (G_OBJECT (adj), "value_changed", G_CALLBACK (looper_loopendspin_callback), (gpointer) looper); gtk_table_attach((GtkTable*)looper->smalltable, looper->loopendspin,1,2,0,1,GTK_FILL,GTK_FILL,1,3); gtk_tooltips_set_tip (looper->tooltips,looper->loopendspin, "playback end position", NULL); gtk_widget_modify_font(looper->loopendspin,looper->font); gtk_widget_show (looper->loopendspin); adj = (GtkAdjustment *) gtk_adjustment_new (0.0, 0.0, 10.0, .001, .1, 0.0); looper->looplengthspin = gtk_spin_button_new (adj, .01, 4); g_signal_connect (G_OBJECT (adj), "value_changed", G_CALLBACK (looper_looplengthspin_callback), (gpointer) looper); gtk_table_attach((GtkTable*)looper->smalltable, looper->looplengthspin,2,3,0,1,GTK_FILL,GTK_FILL,1,3); gtk_tooltips_set_tip (looper->tooltips,looper->looplengthspin, "playback looplength", NULL); gtk_widget_modify_font(looper->looplengthspin,looper->font); gtk_widget_show (looper->looplengthspin); /* recording loop control */ adj = (GtkAdjustment *) gtk_adjustment_new (0.0, 0.0, 10.0, .001, .1, 0.0); looper->recstartspin = gtk_spin_button_new (adj, .01, 4); g_signal_connect (G_OBJECT (adj), "value_changed", G_CALLBACK (looper_recstartspin_callback), (gpointer) looper); gtk_table_attach((GtkTable*)looper->smalltable, looper->recstartspin,0,1,1,2,GTK_FILL,GTK_FILL,1,3); gtk_tooltips_set_tip (looper->tooltips,looper->recstartspin, "rec start position", NULL); gtk_widget_modify_font(looper->recstartspin,looper->font); gtk_widget_show (looper->recstartspin); adj = (GtkAdjustment *) gtk_adjustment_new (0.0, 0.0, 10.0, .001, .1, 0.0); looper->recendspin = gtk_spin_button_new (adj, .01, 4); g_signal_connect (G_OBJECT (adj), "value_changed", G_CALLBACK (looper_recendspin_callback), (gpointer) looper); gtk_table_attach((GtkTable*)looper->smalltable, looper->recendspin,1,2,1,2,GTK_FILL,GTK_FILL,1,3); gtk_tooltips_set_tip (looper->tooltips,looper->recendspin, "rec end position", NULL); gtk_widget_modify_font(looper->recendspin,looper->font); gtk_widget_show (looper->recendspin); adj = (GtkAdjustment *) gtk_adjustment_new (0.0, 0.0, 10.0, .001, .1, 0.0); looper->reclengthspin = gtk_spin_button_new (adj, .01, 4); g_signal_connect (G_OBJECT (adj), "value_changed", G_CALLBACK (looper_reclengthspin_callback), (gpointer) looper); gtk_table_attach((GtkTable*)looper->smalltable, looper->reclengthspin,2,3,1,2,GTK_FILL,GTK_FILL,1,3); gtk_tooltips_set_tip (looper->tooltips,looper->reclengthspin, "recloop length", NULL); gtk_widget_modify_font(looper->reclengthspin,looper->font); gtk_widget_show (looper->reclengthspin); /* speed control */ adj = (GtkAdjustment *) gtk_adjustment_new (1.0, -100.0, 100.0, .001, 1., 1.0); /* page smaller than tick */ looper->speedspin = gtk_spin_button_new (adj, .005, 4); g_signal_connect (G_OBJECT (adj), "value_changed", G_CALLBACK (looper_speedspin_callback), (gpointer) looper); gtk_table_attach((GtkTable*)looper->smalltable, looper->speedspin,0,2,2,3,GTK_FILL,GTK_FILL,1,3); gtk_tooltips_set_tip (looper->tooltips,looper->speedspin, "playback speed", NULL); gtk_widget_modify_font(looper->speedspin,looper->font); gtk_widget_show (looper->speedspin); /* stereodiversity control */ adj = (GtkAdjustment *) gtk_adjustment_new (0.0, 0.0, 1.0, .01, .1, .1); /* page smaller than tick */ looper->diversityspin = gtk_spin_button_new (adj, .0, 2); g_signal_connect (G_OBJECT (adj), "value_changed", G_CALLBACK (looper_diversityspin_callback), (gpointer) looper); gtk_table_attach((GtkTable*)looper->smalltable, looper->diversityspin,2,3,2,3,GTK_FILL,GTK_FILL,1,3); gtk_tooltips_set_tip (looper->tooltips,looper->diversityspin, "stereo diversity", NULL); gtk_widget_modify_font(looper->diversityspin,looper->font); gtk_widget_show (looper->diversityspin); gtk_widget_show (looper->smalltable); looper->smallbox = gtk_vbox_new (FALSE,5); gtk_box_pack_start (GTK_BOX (looper->smallbox),looper->smalltable,FALSE, FALSE, 0); looper->grainbox = gtk_hbox_new (FALSE,5); /* number of grains */ looper->ngrainslider = gtk_hscale_new_with_range (0, 15, 1); gtk_scale_set_draw_value((GtkScale *)looper->ngrainslider, TRUE); gtk_scale_set_digits((GtkScale *)looper->ngrainslider, 0); gtk_scale_set_value_pos((GtkScale *)looper->ngrainslider, GTK_POS_LEFT); gtk_range_set_value (GTK_RANGE(looper->ngrainslider),0); /* gtk_table_attach((GtkTable*)looper->smalltable, looper->ngrainslider,0,3,3,4,GTK_FILL,GTK_FILL,1,3); */ gtk_box_pack_start (GTK_BOX (looper->grainbox),looper->ngrainslider,TRUE, TRUE, 0); gtk_tooltips_set_tip (looper->tooltips,looper->ngrainslider, "number of grains", NULL); gtk_widget_modify_font(looper->ngrainslider,looper->font); gtk_widget_show (looper->ngrainslider); adj = (GtkAdjustment *) gtk_adjustment_new (100.0, 0.0, 100.0, .1, 1., 1.0); looper->densityspin = gtk_spin_button_new (adj, 1.0, 0); g_signal_connect (G_OBJECT (adj), "value_changed", G_CALLBACK (looper_densityspin_callback), (gpointer)looper); gtk_box_pack_end (GTK_BOX (looper->grainbox),looper->densityspin,FALSE, FALSE, 0); gtk_tooltips_set_tip (looper->tooltips,looper->densityspin, "grain density", NULL); gtk_widget_modify_font(looper->densityspin,looper->font); gtk_widget_show (looper->densityspin); gtk_box_pack_start (GTK_BOX (looper->smallbox),looper->grainbox, FALSE, FALSE, 0); gtk_widget_show (looper->grainbox); /* looper->grainlenslider = gtk_hscale_new_with_range (256, 44100, 1); gtk_scale_set_draw_value((GtkScale *)looper->grainlenslider, TRUE); gtk_scale_set_digits((GtkScale *)looper->grainlenslider, 0); gtk_scale_set_value_pos((GtkScale *)looper->grainlenslider, GTK_POS_LEFT); gtk_range_set_value (GTK_RANGE(looper->grainlenslider),0); gtk_box_pack_start (GTK_BOX (looper->smallbox),looper->grainlenslider,FALSE, FALSE, 0); gtk_tooltips_set_tip (looper->tooltips,looper->grainlenslider, "length of grains (samples)", NULL); gtk_widget_modify_font(looper->grainlenslider,looper->font); gtk_widget_show (looper->grainlenslider); */ looper->panbox = gtk_hbox_new (FALSE,5); looper->panslider = gtk_hscale_new_with_range (-1., 1., .01); gtk_scale_set_draw_value((GtkScale *)looper->panslider, TRUE); gtk_scale_set_digits((GtkScale *)looper->panslider, 2); gtk_scale_set_value_pos((GtkScale *)looper->panslider, GTK_POS_BOTTOM); gtk_range_set_value (GTK_RANGE(looper->panslider),.0); gtk_box_pack_start (GTK_BOX (looper->panbox),looper->panslider, TRUE, TRUE, 0); gtk_tooltips_set_tip (looper->tooltips,looper->panslider, "pan L<->R", NULL); gtk_widget_modify_font(looper->panslider,looper->font); gtk_widget_show (looper->panslider); adj = (GtkAdjustment *) gtk_adjustment_new (0.0, 0.0, 30.0, .01, 1., 1.); looper->panswingspin = gtk_spin_button_new (adj, .01, 2); g_signal_connect (G_OBJECT (adj), "value-changed", G_CALLBACK (looper_panswingspin_callback), (gpointer) looper); gtk_box_pack_end (GTK_BOX (looper->panbox),looper->panswingspin,FALSE, FALSE, 0); gtk_tooltips_set_tip (looper->tooltips,looper->panswingspin, "auto panner (hz)", NULL); gtk_widget_modify_font(looper->panswingspin,looper->font); gtk_widget_show (looper->panswingspin); gtk_box_pack_start (GTK_BOX (looper->smallbox),looper->panbox, FALSE, FALSE, 0); gtk_widget_show (looper->panbox); gtk_widget_show (looper->smallbox); /* middle control elements */ looper->middletable = gtk_table_new (1, 13, TRUE); adj = (GtkAdjustment *) gtk_adjustment_new (.0, -70., 6.0, .0, .0, 0.0); looper->outLmeter = gtk_meter_new(adj, GTK_METER_UP); gtk_table_attach((GtkTable*)looper->middletable, looper->outLmeter,0,1,0,1,GTK_FILL,GTK_FILL,1,3); gtk_tooltips_set_tip (looper->tooltips,looper->outLmeter, "left output", NULL); gtk_widget_show (looper->outLmeter); adj = (GtkAdjustment *) gtk_adjustment_new (.0, -70., 6.0, .0, .0, 0.0); looper->outRmeter = gtk_meter_new(adj, GTK_METER_UP); gtk_table_attach((GtkTable*)looper->middletable, looper->outRmeter,1,2,0,1,GTK_FILL,GTK_FILL,1,3); gtk_tooltips_set_tip (looper->tooltips,looper->outRmeter, "right output", NULL); gtk_widget_show (looper->outRmeter); looper->volslider = gtk_vscale_new (GTK_ADJUSTMENT (gtk_adjustment_new (0., -48., 18., 1., 6., 0.))); gtk_scale_set_draw_value((GtkScale *)looper->volslider, TRUE); gtk_scale_set_digits((GtkScale *)looper->volslider, 0); gtk_range_set_inverted (GTK_RANGE (looper->volslider), TRUE); gtk_scale_set_value_pos((GtkScale *)looper->volslider, GTK_POS_BOTTOM); gtk_range_set_value (GTK_RANGE(looper->volslider),.0); gtk_table_attach((GtkTable*)looper->middletable, looper->volslider,2,6,0,1,GTK_FILL,GTK_FILL,3,3); gtk_tooltips_set_tip (looper->tooltips,looper->volslider, "output volume", NULL); gtk_widget_modify_font(looper->volslider,looper->font); gtk_widget_show (looper->volslider); adj = (GtkAdjustment *) gtk_adjustment_new (.0, -70., 6.0, .0, .0, 0.0); looper->inLmeter = gtk_meter_new(adj, GTK_METER_UP); gtk_table_attach((GtkTable*)looper->middletable, looper->inLmeter,7,8,0,1,GTK_FILL,GTK_FILL,1,3); gtk_tooltips_set_tip (looper->tooltips,looper->inLmeter, "left input", NULL); gtk_widget_show (looper->inLmeter); adj = (GtkAdjustment *) gtk_adjustment_new (.0, -70., 6.0, .0, .0, 0.0); looper->inRmeter = gtk_meter_new(adj, GTK_METER_UP); gtk_table_attach((GtkTable*)looper->middletable, looper->inRmeter,8,9,0,1,GTK_FILL,GTK_FILL,1,3); gtk_tooltips_set_tip (looper->tooltips,looper->inRmeter, "right input", NULL); gtk_widget_show (looper->inRmeter); looper->recmixslider = gtk_vscale_new_with_range (-2., 2, .01); gtk_scale_set_draw_value((GtkScale *)looper->recmixslider, TRUE); gtk_scale_set_digits((GtkScale *)looper->recmixslider, 2); gtk_range_set_inverted (GTK_RANGE (looper->recmixslider), TRUE); gtk_scale_set_value_pos((GtkScale *)looper->recmixslider, GTK_POS_BOTTOM); gtk_range_set_value (GTK_RANGE(looper->recmixslider),1); gtk_table_attach((GtkTable*)looper->middletable, looper->recmixslider,9,13,0,1,GTK_FILL,GTK_FILL,3,3); gtk_tooltips_set_tip (looper->tooltips,looper->recmixslider, "recording<->original mix (>1 = overdrive)", NULL); gtk_widget_modify_font(looper->recmixslider,looper->font); gtk_widget_show (looper->recmixslider); gtk_widget_show (looper->middletable); looper->middlebox = gtk_hbox_new (FALSE,3); gtk_box_pack_start (GTK_BOX (looper->middlebox),looper->middletable, FALSE, FALSE, 0); /* gtk_box_pack_start (GTK_BOX (looper->middlebox),looper->smalltable, FALSE, FALSE, 0);*/ gtk_box_pack_start (GTK_BOX (looper->middlebox),looper->smallbox, FALSE, FALSE, 0); gtk_widget_show (looper->middlebox); /* topbox with bufferselector, play-rec-buttons */ looper->topbox = gtk_hbox_new (FALSE,5); /* GtkOptionMenu might be easier ...??? */ menu1 = gtk_menu_new (); /* menu_items = gtk_menu_item_new_with_label ("normalize buffer"); g_signal_connect (G_OBJECT (menu_items), "activate", G_CALLBACK (looper_normalize_callback), (gpointer)looper); gtk_menu_shell_append (GTK_MENU_SHELL (menu1), menu_items); gtk_widget_show (menu_items); menu_items = gtk_menu_item_new_with_label ("clear buffer"); g_signal_connect (G_OBJECT (menu_items), "activate", G_CALLBACK (looper_clear_callback), (gpointer)looper); gtk_menu_shell_append (GTK_MENU_SHELL (menu1), menu_items); gtk_widget_show (menu_items); menu_items = gtk_separator_menu_item_new(); gtk_menu_shell_append (GTK_MENU_SHELL (menu1), menu_items); gtk_widget_show (menu_items); */ menu_items = gtk_menu_item_new_with_label ("no buffer available"); gtk_menu_shell_append (GTK_MENU_SHELL (menu1), menu_items); gtk_widget_show (menu_items); gtk_widget_show (menu1); looper->buffermenu = gtk_menu_item_new_with_label ("select buffer"); gtk_menu_item_set_submenu (GTK_MENU_ITEM (looper->buffermenu), menu1); gtk_widget_show (looper->buffermenu); /* options menu */ menu2 = gtk_menu_new (); menu_items = gtk_check_menu_item_new_with_label ("link rec to play loop"); gtk_check_menu_item_set_active ((GtkCheckMenuItem*)menu_items,TRUE); g_signal_connect (G_OBJECT (menu_items), "activate", G_CALLBACK (looper_toggle_link_rec2play), looper); gtk_menu_shell_append (GTK_MENU_SHELL (menu2), menu_items); gtk_widget_show (menu_items); menu_items = gtk_check_menu_item_new_with_label ("keep absolute looplength"); gtk_check_menu_item_set_active ((GtkCheckMenuItem*)menu_items,FALSE); g_signal_connect (G_OBJECT (menu_items), "activate", G_CALLBACK (looper_toggle_keep_looplength), looper); gtk_menu_shell_append (GTK_MENU_SHELL (menu2), menu_items); gtk_widget_show (menu_items); looper->limiteritem = gtk_check_menu_item_new_with_label ("limit i/o signal"); gtk_check_menu_item_set_active ((GtkCheckMenuItem*)looper->limiteritem,TRUE); g_signal_connect (G_OBJECT (looper->limiteritem), "activate", G_CALLBACK (looper_toggle_limiter_callback), looper); gtk_menu_shell_append (GTK_MENU_SHELL (menu2), looper->limiteritem); gtk_widget_show (looper->limiteritem); menu_items = gtk_separator_menu_item_new(); gtk_menu_shell_append (GTK_MENU_SHELL (menu2), menu_items); gtk_widget_show (menu_items); menu_items = gtk_menu_item_new_with_label ("zoom to play selection"); g_signal_connect (G_OBJECT (menu_items), "activate", G_CALLBACK (looper_zoom_to_play_selection_callback), (gpointer)looper); gtk_menu_shell_append (GTK_MENU_SHELL (menu2), menu_items); gtk_widget_show (menu_items); menu_items = gtk_menu_item_new_with_label ("zoom to rec selection"); g_signal_connect (G_OBJECT (menu_items), "activate", G_CALLBACK (looper_zoom_to_rec_selection_callback), (gpointer)looper); gtk_menu_shell_append (GTK_MENU_SHELL (menu2), menu_items); gtk_widget_show (menu_items); menu_items = gtk_menu_item_new_with_label ("zoom to overview"); g_signal_connect (G_OBJECT (menu_items), "activate", G_CALLBACK (looper_zoom_to_overview_callback), (gpointer)looper); gtk_menu_shell_append (GTK_MENU_SHELL (menu2), menu_items); gtk_widget_show (menu_items); menu_items = gtk_separator_menu_item_new(); gtk_menu_shell_append (GTK_MENU_SHELL (menu2), menu_items); gtk_widget_show (menu_items); /* grid stuff */ looper->snap2griditem = gtk_check_menu_item_new_with_label ("snap to grid"); gtk_check_menu_item_set_active ((GtkCheckMenuItem*)looper->snap2griditem,FALSE); g_signal_connect (G_OBJECT (looper->snap2griditem), "activate", G_CALLBACK (looper_toggle_snap2grid_callback), looper); gtk_menu_shell_append (GTK_MENU_SHELL (menu2), looper->snap2griditem); gtk_widget_show (looper->snap2griditem); looper->showgriditem = gtk_check_menu_item_new_with_label ("show grid"); gtk_check_menu_item_set_active ((GtkCheckMenuItem*)looper->showgriditem,FALSE); g_signal_connect (G_OBJECT (looper->showgriditem), "activate", G_CALLBACK (looper_toggle_showgrid_callback), looper); gtk_menu_shell_append (GTK_MENU_SHELL (menu2), looper->showgriditem); gtk_widget_show (looper->showgriditem); menu_items = gtk_menu_item_new_with_label ("grid from play selection"); g_signal_connect (G_OBJECT (menu_items), "activate", G_CALLBACK (looper_gridfromplayselection_callback), (gpointer)looper); gtk_menu_shell_append (GTK_MENU_SHELL (menu2), menu_items); gtk_widget_show (menu_items); menu_items = gtk_menu_item_new_with_label ("grid from rec selection"); g_signal_connect (G_OBJECT (menu_items), "activate", G_CALLBACK (looper_gridfromrecselection_callback), (gpointer)looper); gtk_menu_shell_append (GTK_MENU_SHELL (menu2), menu_items); gtk_widget_show (menu_items); menu_items = gtk_menu_item_new_with_label ("grid settings"); g_signal_connect (G_OBJECT (menu_items), "activate", G_CALLBACK (looper_gridsettings_callback), (gpointer)looper); gtk_menu_shell_append (GTK_MENU_SHELL (menu2), menu_items); gtk_widget_show (menu_items); menu_items = gtk_separator_menu_item_new(); gtk_menu_shell_append (GTK_MENU_SHELL (menu2), menu_items); gtk_widget_show (menu_items); /* grain stuff */ menu_items = gtk_menu_item_new_with_label ("grain settings"); g_signal_connect (G_OBJECT (menu_items), "activate", G_CALLBACK (looper_grainsettings_callback), (gpointer)looper); gtk_menu_shell_append (GTK_MENU_SHELL (menu2), menu_items); gtk_widget_show (menu_items); menu_items = gtk_separator_menu_item_new(); gtk_menu_shell_append (GTK_MENU_SHELL (menu2), menu_items); gtk_widget_show (menu_items); menu_items = gtk_menu_item_new_with_label ("threshold recording settings"); g_signal_connect (G_OBJECT (menu_items), "activate", G_CALLBACK (looper_threshsettings_callback), (gpointer)looper); gtk_menu_shell_append (GTK_MENU_SHELL (menu2), menu_items); gtk_widget_show (menu_items); menu_items = gtk_separator_menu_item_new(); gtk_menu_shell_append (GTK_MENU_SHELL (menu2), menu_items); gtk_widget_show (menu_items); menu_items = gtk_menu_item_new_with_label ("close this looper"); g_signal_connect (G_OBJECT (menu_items), "activate", G_CALLBACK (looper_close_looper_callback), (gpointer)looper); gtk_menu_shell_append (GTK_MENU_SHELL (menu2), menu_items); gtk_widget_show (menu_items); gtk_widget_show (menu2); looper->optionsmenu = gtk_menu_item_new_with_label ("options"); gtk_menu_item_set_submenu (GTK_MENU_ITEM (looper->optionsmenu), menu2); gtk_widget_show (looper->optionsmenu); /* playmode menu */ menu3 = gtk_menu_new (); looper->loopmode = gtk_radio_menu_item_new_with_label (group,"loop"); group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (looper->loopmode)); g_object_set_data (G_OBJECT (looper->loopmode), "playmode",GUINT_TO_POINTER(LOOP_PLAYMODE_LOOP)); gtk_check_menu_item_set_active ((GtkCheckMenuItem*)looper->loopmode,TRUE); g_signal_connect (G_OBJECT (looper->loopmode), "activate", G_CALLBACK (looper_playmode_callback), looper); gtk_menu_shell_append (GTK_MENU_SHELL (menu3), looper->loopmode); gtk_widget_show (looper->loopmode); looper->backforthmode = gtk_radio_menu_item_new_with_label (group,"back'n'forth"); group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (looper->backforthmode)); gtk_check_menu_item_set_active ((GtkCheckMenuItem*)looper->backforthmode,FALSE); g_object_set_data (G_OBJECT (looper->backforthmode), "playmode",GUINT_TO_POINTER(LOOP_PLAYMODE_BACKFORTH)); g_signal_connect (G_OBJECT (looper->backforthmode), "activate", G_CALLBACK (looper_playmode_callback), (gpointer)looper); gtk_menu_shell_append (GTK_MENU_SHELL (menu3), looper->backforthmode); gtk_widget_show (looper->backforthmode); looper->oncemode = gtk_radio_menu_item_new_with_label (group,"once"); group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (looper->oncemode)); gtk_check_menu_item_set_active ((GtkCheckMenuItem*)looper->oncemode,FALSE); g_object_set_data (G_OBJECT (looper->oncemode), "playmode",GUINT_TO_POINTER(LOOP_PLAYMODE_ONCE)); g_signal_connect (G_OBJECT (looper->oncemode), "activate", G_CALLBACK (looper_playmode_callback), (gpointer)looper); gtk_menu_shell_append (GTK_MENU_SHELL (menu3), looper->oncemode); gtk_widget_show (looper->oncemode); looper->sinewavemode = gtk_radio_menu_item_new_with_label (group,"sinewave"); group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (looper->sinewavemode)); gtk_check_menu_item_set_active ((GtkCheckMenuItem*)looper->sinewavemode,FALSE); g_object_set_data (G_OBJECT (looper->sinewavemode), "playmode",GUINT_TO_POINTER(LOOP_PLAYMODE_SINE)); g_signal_connect (G_OBJECT (looper->sinewavemode), "activate", G_CALLBACK (looper_playmode_callback), (gpointer)looper); gtk_menu_shell_append (GTK_MENU_SHELL (menu3), looper->sinewavemode); gtk_widget_show (looper->sinewavemode); looper->externalposmode = gtk_radio_menu_item_new_with_label (group,"external pointer"); group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (looper->externalposmode)); gtk_check_menu_item_set_active ((GtkCheckMenuItem*)looper->externalposmode,FALSE); g_object_set_data (G_OBJECT (looper->externalposmode), "playmode",GUINT_TO_POINTER(LOOP_PLAYMODE_EXTERNALPOS)); g_signal_connect (G_OBJECT (looper->externalposmode), "activate", G_CALLBACK (looper_playmode_callback), (gpointer)looper); gtk_menu_shell_append (GTK_MENU_SHELL (menu3), looper->externalposmode); gtk_widget_show (looper->externalposmode); looper->customspeedmode = gtk_radio_menu_item_new_with_label (group,"custom speed"); group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (looper->customspeedmode)); gtk_check_menu_item_set_active ((GtkCheckMenuItem*)looper->customspeedmode,FALSE); g_object_set_data (G_OBJECT (looper->customspeedmode), "playmode",GUINT_TO_POINTER(LOOP_PLAYMODE_CUSTOMSPEED)); g_signal_connect (G_OBJECT (looper->customspeedmode), "activate", G_CALLBACK (looper_playmode_callback), (gpointer)looper); gtk_menu_shell_append (GTK_MENU_SHELL (menu3), looper->customspeedmode); gtk_widget_show (looper->customspeedmode); looper->customposmode = gtk_radio_menu_item_new_with_label (group,"custom position"); group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (looper->customposmode)); gtk_check_menu_item_set_active ((GtkCheckMenuItem*)looper->customposmode,FALSE); g_object_set_data (G_OBJECT (looper->customposmode), "playmode",GUINT_TO_POINTER(LOOP_PLAYMODE_POSITION)); g_signal_connect (G_OBJECT (looper->customposmode), "activate", G_CALLBACK (looper_playmode_callback), (gpointer)looper); gtk_menu_shell_append (GTK_MENU_SHELL (menu3), looper->customposmode); gtk_widget_show (looper->customposmode); /* clickmode menu */ menu_items = gtk_separator_menu_item_new(); gtk_menu_shell_append (GTK_MENU_SHELL (menu3), menu_items); gtk_widget_show (menu_items); menu_items = gtk_radio_menu_item_new_with_label (clickgroup,"no click"); clickgroup = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (menu_items)); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM(menu_items),TRUE); g_signal_connect (G_OBJECT (menu_items), "activate", G_CALLBACK (looper_clickmode_callback), looper); gtk_menu_shell_append (GTK_MENU_SHELL (menu3), menu_items); gtk_widget_show (menu_items); buf = speciallist_get_first(looper->clickmodes); while(buf){ menu_items = gtk_radio_menu_item_new_with_label (clickgroup,buffer_get_shortname(buf)); clickgroup = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (menu_items)); g_object_set_data (G_OBJECT (menu_items), "buffer",buf); g_signal_connect (G_OBJECT (menu_items), "activate", G_CALLBACK (looper_clickmode_callback), looper); gtk_menu_shell_append (GTK_MENU_SHELL (menu3), menu_items); gtk_widget_show (menu_items); buf = speciallist_get_next(looper->clickmodes,buf); } menu_items = gtk_separator_menu_item_new(); gtk_menu_shell_append (GTK_MENU_SHELL (menu3), menu_items); gtk_widget_show (menu_items); menu_items = gtk_menu_item_new_with_label ("edit custom playmode"); g_signal_connect (G_OBJECT (menu_items), "activate", G_CALLBACK (looper_custommode_callback), (gpointer)looper); gtk_menu_shell_append (GTK_MENU_SHELL (menu3), menu_items); gtk_widget_show (menu_items); menu_items = gtk_separator_menu_item_new(); gtk_menu_shell_append (GTK_MENU_SHELL (menu3), menu_items); gtk_widget_show (menu_items); looper->recloopmode = gtk_radio_menu_item_new_with_label (recgroup,"looped recording"); recgroup = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (looper->recloopmode)); g_object_set_data (G_OBJECT (looper->recloopmode), "recmode",GUINT_TO_POINTER(LOOP_RECMODE_LOOP)); gtk_check_menu_item_set_active ((GtkCheckMenuItem*)looper->recloopmode,TRUE); g_signal_connect (G_OBJECT (looper->recloopmode), "activate", G_CALLBACK (looper_recmode_callback), looper); gtk_menu_shell_append (GTK_MENU_SHELL (menu3), looper->recloopmode); gtk_widget_show (looper->recloopmode); looper->reconcemode = gtk_radio_menu_item_new_with_label (recgroup,"single recording"); recgroup = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (looper->reconcemode)); gtk_check_menu_item_set_active ((GtkCheckMenuItem*)looper->reconcemode,FALSE); g_object_set_data (G_OBJECT (looper->reconcemode), "recmode",GUINT_TO_POINTER(LOOP_RECMODE_ONCE)); g_signal_connect (G_OBJECT (looper->reconcemode), "activate", G_CALLBACK (looper_recmode_callback), (gpointer)looper); gtk_menu_shell_append (GTK_MENU_SHELL (menu3), looper->reconcemode); gtk_widget_show (looper->reconcemode); /*looperdata_set_thresholdmode (new_data, 1); */ looper->thresholdtoggle = gtk_check_menu_item_new_with_label ("threshold recording"); gtk_check_menu_item_set_active ((GtkCheckMenuItem*)looper->thresholdtoggle,FALSE); g_signal_connect (G_OBJECT (looper->thresholdtoggle), "activate", G_CALLBACK (looper_toggle_thresholdmode_callback), looper); gtk_menu_shell_append (GTK_MENU_SHELL (menu3), looper->thresholdtoggle); gtk_widget_show (looper->thresholdtoggle); gtk_widget_show (menu3); looper->playmodemenu = gtk_menu_item_new_with_label ("modes"); gtk_menu_item_set_submenu (GTK_MENU_ITEM (looper->playmodemenu), menu3); gtk_widget_show (looper->playmodemenu); /* menu bar */ looper->menu_bar = gtk_menu_bar_new (); gtk_menu_shell_append (GTK_MENU_SHELL (looper->menu_bar), looper->buffermenu); gtk_menu_shell_append (GTK_MENU_SHELL (looper->menu_bar), looper->optionsmenu); gtk_menu_shell_append (GTK_MENU_SHELL (looper->menu_bar), looper->playmodemenu); gtk_box_pack_start (GTK_BOX (looper->topbox),looper->menu_bar,FALSE, FALSE, 0); gtk_widget_modify_font(looper->menu_bar,looper->font); gtk_widget_show (looper->menu_bar); looper->playimage = gtk_image_new_from_stock (GTK_STOCK_GO_FORWARD,GTK_ICON_SIZE_SMALL_TOOLBAR); looper->playbutton = gtk_toggle_button_new (); gtk_container_add (GTK_CONTAINER (looper->playbutton),looper->playimage); gtk_box_pack_start (GTK_BOX (looper->topbox),looper->playbutton,FALSE, FALSE, 0); gtk_tooltips_set_tip (looper->tooltips,looper->playbutton,"play/loop", NULL); gtk_widget_show (looper->playimage); gtk_widget_show (looper->playbutton); looper->recimage = gtk_image_new_from_stock (GTK_STOCK_NO,GTK_ICON_SIZE_SMALL_TOOLBAR); looper->recbutton = gtk_toggle_button_new (); gtk_container_add (GTK_CONTAINER (looper->recbutton),looper->recimage); gtk_box_pack_start (GTK_BOX (looper->topbox),looper->recbutton,FALSE, FALSE, 0); gtk_tooltips_set_tip (looper->tooltips,looper->recbutton,"record", NULL); gtk_widget_show (looper->recimage); gtk_widget_show (looper->recbutton); looper->shuttlebutton = gtk_toggle_button_new_with_label ("S"); gtk_box_pack_start (GTK_BOX (looper->topbox),looper->shuttlebutton,FALSE, FALSE, 0); gtk_tooltips_set_tip (looper->tooltips,looper->shuttlebutton,"toggle external shuttle control", NULL); gtk_widget_show (looper->shuttlebutton); /* looper->limiterbutton = gtk_toggle_button_new_with_label ("L"); gtk_box_pack_start (GTK_BOX (looper->topbox),looper->limiterbutton,FALSE, FALSE, 0); gtk_tooltips_set_tip (looper->tooltips,looper->limiterbutton,"activate input-/output limiter", NULL); gtk_widget_show (looper->limiterbutton); */ /* looper->normbutton = gtk_button_new_with_label ("N"); gtk_box_pack_start (GTK_BOX (looper->topbox),looper->normbutton,FALSE, FALSE, 0); gtk_tooltips_set_tip (looper->tooltips,looper->normbutton,"normalize buffer", NULL); gtk_widget_show (looper->normbutton); */ looper->minimizebutton = gtk_toggle_button_new_with_label ("M"); gtk_box_pack_start (GTK_BOX (looper->topbox),looper->minimizebutton,FALSE, FALSE, 0); gtk_tooltips_set_tip (looper->tooltips,looper->minimizebutton,"minimize looper", NULL); gtk_widget_show (looper->minimizebutton); looper->upimage = gtk_image_new_from_stock (GTK_STOCK_GO_UP,GTK_ICON_SIZE_SMALL_TOOLBAR); looper->upbutton = gtk_button_new(); gtk_container_add (GTK_CONTAINER (looper->upbutton),looper->upimage); gtk_box_pack_start (GTK_BOX (looper->topbox),looper->upbutton,FALSE, FALSE, 0); gtk_tooltips_set_tip (looper->tooltips,looper->upbutton,"move looper up", NULL); gtk_widget_show (looper->upimage); gtk_widget_show (looper->upbutton); looper->downimage = gtk_image_new_from_stock (GTK_STOCK_GO_DOWN,GTK_ICON_SIZE_SMALL_TOOLBAR); looper->downbutton = gtk_button_new (); gtk_container_add (GTK_CONTAINER (looper->downbutton),looper->downimage); gtk_box_pack_start (GTK_BOX (looper->topbox),looper->downbutton,FALSE, FALSE, 0); gtk_tooltips_set_tip (looper->tooltips,looper->downbutton,"move looper down", NULL); gtk_widget_show (looper->downimage); gtk_widget_show (looper->downbutton); dummylabel = gtk_label_new(" "); gtk_box_pack_start (GTK_BOX (looper->topbox),dummylabel,FALSE, FALSE, 0); gtk_widget_show (dummylabel); gtk_widget_show (looper->topbox); /* controlbox with controlframe */ looper->controlframe = gtk_frame_new ("..."); gtk_frame_set_shadow_type((GtkFrame*)looper->controlframe, GTK_SHADOW_ETCHED_IN); gtk_widget_show (looper->controlframe); looper->controlbox = gtk_vbox_new (FALSE,0); gtk_box_pack_start (GTK_BOX (looper->controlbox),looper->topbox, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (looper->controlbox),looper->middlebox, FALSE, FALSE, 0); /* looper->panslider = gtk_hscale_new_with_range (-1., 1., .01); gtk_scale_set_draw_value((GtkScale *)looper->panslider, TRUE); gtk_scale_set_digits((GtkScale *)looper->panslider, 2); gtk_scale_set_value_pos((GtkScale *)looper->panslider, GTK_POS_BOTTOM); gtk_range_set_value (GTK_RANGE(looper->panslider),.0); gtk_box_pack_start (GTK_BOX (looper->controlbox),looper->panslider, FALSE, FALSE, 0); gtk_tooltips_set_tip (looper->tooltips,looper->panslider, "pan L<->R", NULL); gtk_widget_modify_font(looper->panslider,looper->font); gtk_widget_show (looper->panslider); */ gtk_widget_show (looper->controlbox); gtk_container_add (GTK_CONTAINER (looper->controlframe), looper->controlbox); /* and finally the mainbox */ looper->mainbox = gtk_hbox_new (FALSE,0); gtk_box_pack_start (GTK_BOX (looper->mainbox),looper->controlframe, FALSE, FALSE, 0); looper->loopview = gtk_loopview_new(looper->data); gtk_loopview_suspend_gui (GTK_LOOPVIEW(looper->loopview), 1); gtk_box_pack_end (GTK_BOX (looper->mainbox),looper->loopview, TRUE, TRUE, 0); gtk_widget_show (looper->loopview); gtk_widget_show (looper->mainbox); /* CONNECT SIGNALS */ g_signal_connect (G_OBJECT (looper->playbutton), "toggled", G_CALLBACK (looper_playbutton_callback), (gpointer) looper); g_signal_connect (G_OBJECT (looper->recbutton), "toggled", G_CALLBACK (looper_recbutton_callback), (gpointer) looper); g_signal_connect (G_OBJECT (looper->shuttlebutton), "toggled", G_CALLBACK (looper_shuttlebutton_callback), (gpointer) looper); gtk_toggle_button_set_active((GtkToggleButton*)looper->shuttlebutton,TRUE); /* g_signal_connect (G_OBJECT (looper->limiterbutton), "toggled", G_CALLBACK (looper_limiterbutton_callback), (gpointer) looper); gtk_toggle_button_set_active((GtkToggleButton*)looper->limiterbutton,TRUE); */ g_signal_connect (G_OBJECT (looper->minimizebutton), "toggled", G_CALLBACK (looper_minimizebutton_callback), (gpointer) looper); g_signal_connect (G_OBJECT (looper->upbutton), "clicked", G_CALLBACK (looper_upbutton_callback), (gpointer) looper); g_signal_connect (G_OBJECT (looper->downbutton), "clicked", G_CALLBACK (looper_downbutton_callback), (gpointer) looper); /* g_signal_connect (G_OBJECT (looper->normbutton), "clicked", G_CALLBACK (looper_normbutton_callback), (gpointer) looper); */ g_signal_connect (G_OBJECT (looper->panslider), "value-changed", G_CALLBACK (looper_panslider_callback), (gpointer) looper); /* g_signal_connect (G_OBJECT (looper->panswingspin), "value-changed", G_CALLBACK (looper_panswingspin_callback), (gpointer) looper); */ g_signal_connect (G_OBJECT (looper->ngrainslider), "value-changed", G_CALLBACK (looper_ngrainslider_callback), (gpointer) looper); /* g_signal_connect (G_OBJECT (looper->densityspin), "value-changed", G_CALLBACK (looper_densityspin_callback), (gpointer) looper); g_signal_connect (G_OBJECT (looper->grainlenslider), "value-changed", G_CALLBACK (looper_grainlenslider_callback), (gpointer) looper); */ g_signal_connect (G_OBJECT (looper->volslider), "value-changed", G_CALLBACK (looper_volslider_callback), (gpointer) looper); g_signal_connect (G_OBJECT (looper->recmixslider), "value-changed", G_CALLBACK (looper_recmixslider_callback), (gpointer) looper); /* g_signal_connect (G_OBJECT (looper->speedspin), "value_changed", G_CALLBACK (looper_speedspin_callback), (gpointer) looper); */ /* g_signal_connect (G_OBJECT (looper->diversityspin), "value_changed", G_CALLBACK (looper_diversity_callback), (gpointer) looper); g_signal_connect (G_OBJECT (looper->loopstartspin), "value_changed", G_CALLBACK (looper_loopstartspin_callback), (gpointer) looper); g_signal_connect (G_OBJECT (looper->loopendspin), "value_changed", G_CALLBACK (looper_loopendspin_callback), (gpointer) looper); g_signal_connect (G_OBJECT (looper->looplengthspin), "value_changed", G_CALLBACK (looper_looplengthspin_callback), (gpointer) looper); g_signal_connect (G_OBJECT (looper->recstartspin), "value_changed", G_CALLBACK (looper_recstartspin_callback), (gpointer) looper); g_signal_connect (G_OBJECT (looper->recendspin), "value_changed", G_CALLBACK (looper_recendspin_callback), (gpointer) looper); g_signal_connect (G_OBJECT (looper->reclengthspin), "value_changed", G_CALLBACK (looper_reclengthspin_callback), (gpointer) looper); */ g_signal_connect (G_OBJECT (looper->loopview), "loopborders-changed", G_CALLBACK (loopview_changed_loopborders),(gpointer)looper); g_signal_connect (G_OBJECT (looper->loopview), "recborders-changed", G_CALLBACK (loopview_changed_recborders),(gpointer)looper); g_signal_connect (G_OBJECT (looper->loopview), "speed-changed", G_CALLBACK (loopview_changed_speed),(gpointer)looper); looper_set_minimized (looper, minimized); gtk_loopview_suspend_gui (GTK_LOOPVIEW(looper->loopview), 0); return looper; } kluppe-0.6.14/src/common/0002755000175000017500000000000011171364301014472 5ustar dieterdieterkluppe-0.6.14/src/common/midi.h0000644000175000017500000000074511032266335015575 0ustar dieterdieter#ifdef HAVE_ALSA #ifndef __MIDI_H__ #define __MIDI_H__ #include #include "speciallist.h" #include typedef struct _midi_info{ pthread_t midithread; snd_seq_t *seq; int seq_nfds; struct pollfd *pfds; speciallist_t *looperdatalist; int input; int quit; } midi_info_t; midi_info_t* midi_info_new (speciallist_t* looperdatalist); void midi_info_destroy (); #endif /* __MIDI_H__ */ #endif /* HAVE_ALSA */ kluppe-0.6.14/src/common/interpol.h0000644000175000017500000000040110652370543016500 0ustar dieterdieter#ifndef __INTERPOL_H__ #define __INTERPOL_H__ float inter4pol (short* buf, float index, long size); /*float inter4pol_stereo (short* buf, float index, long size);*/ float inter4pol_float (float* buf, double index, long size); #endif /* __INTERPOL_H__ */ kluppe-0.6.14/src/common/xsession.c0000644000175000017500000002434111032277342016517 0ustar dieterdieter/* xsession code is partly taken from robert ham's jack rack */ #ifdef HAVE_ALSA #include #include #include #include #include #include #include "xsession.h" #include "looperdata.h" static void * xsession_run (void * data); xsession_info_t* xsession_new (speciallist_t* looperdatalist, snd_seq_t *seq) { xsession_info_t* xsinfo; xsinfo = malloc (sizeof (xsession_info_t)); xsinfo->seq = seq; xsinfo->quit = 0; xsinfo->looperdatalist = looperdatalist; pthread_create (&xsinfo->xsessionthread, NULL, xsession_run, xsinfo); return xsinfo; } void xsession_info_destroy (xsession_info_t* xsinfo){ xsinfo->quit = 1; pthread_join (xsinfo->xsessionthread, NULL); free(xsinfo); } static int open_seq(const char* name, snd_seq_t *seq_handle) { int portid, problem; snd_seq_client_info_t *cinfo; snd_seq_port_info_t *pinfo; snd_seq_addr_t addr; snd_seq_client_info_alloca(&cinfo); snd_seq_port_info_alloca(&pinfo); if ((portid = snd_seq_create_simple_port(seq_handle, name, SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE, SND_SEQ_PORT_TYPE_APPLICATION)) < 0) { fprintf(stderr, "Error creating sequencer port.\n"); return -1; // exit(1); } /* try to auto-connect: */ problem = snd_seq_parse_address (seq_handle,&addr, "USB X-Session:MIDI 1"); if (!problem){ snd_seq_port_subscribe_t *subs; snd_seq_port_subscribe_alloca(&subs); snd_seq_port_subscribe_set_sender(subs, &addr); problem = snd_seq_parse_address (seq_handle,&addr, "kluppe:1"); snd_seq_port_subscribe_set_dest(subs, &addr); snd_seq_subscribe_port(seq_handle, subs); if (!problem) printf ("found x-session alsa device!!!\n"); } #if 0 snd_seq_client_info_set_client(cinfo, -1); while (snd_seq_query_next_client(seq_handle, cinfo) >= 0) { int client = snd_seq_client_info_get_client(cinfo); snd_seq_port_info_set_client(pinfo, client); snd_seq_port_info_set_port(pinfo, -1); while (snd_seq_query_next_port(seq_handle, pinfo) >= 0) { /* printf("%3d:%-3d %-32.32s %s\n", snd_seq_port_info_get_client(pinfo), snd_seq_port_info_get_port(pinfo), snd_seq_client_info_get_name(cinfo), snd_seq_port_info_get_name(pinfo));*/ if (!strcmp(snd_seq_port_info_get_name(pinfo),"USB X-Session MIDI 1")){ snd_seq_port_subscribe_t *subs; snd_seq_port_subscribe_alloca(&subs); addr.client = snd_seq_port_info_get_client(pinfo); addr.port = snd_seq_port_info_get_port(pinfo); snd_seq_port_subscribe_set_sender(subs, &addr); addr.client = snd_seq_port_info_get_client(&portid); addr.port = snd_seq_port_info_get_port(&portid); snd_seq_port_subscribe_set_dest(subs, &addr); snd_seq_subscribe_port(seq_handle, subs); printf ("found x-session alsa device!!!\n"); } } } #endif return 1; } static double xsession2pitch (int note){ /* double pitch = pow(2.,(double)(note - 57)/12.); */ double pitch = pow(2.,(double)(note - 48.)/12.); return pitch; } void setvol_helper(xsession_info_t *xsinfo, int id, float vol){ looper_data_t *ld; ld = speciallist_get_first_nolock (xsinfo->looperdatalist); while(ld){ if (ld->id == id){ looperdata_lock(ld); looperdata_set_vol(ld, vol); looperdata_unlock(ld); } ld = speciallist_get_next_nolock ( xsinfo->looperdatalist, ld); } } void setngrains_helper(xsession_info_t *xsinfo, int id, int ngrains){ looper_data_t *ld; ld = speciallist_get_first_nolock (xsinfo->looperdatalist); while(ld){ if (ld->id == id){ looperdata_lock(ld); looperdata_set_ngrains(ld, ngrains); looperdata_unlock(ld); } ld = speciallist_get_next_nolock ( xsinfo->looperdatalist, ld); } } void graindensity_helper(xsession_info_t *xsinfo, int id, int density){ looper_data_t *ld; ld = speciallist_get_first_nolock (xsinfo->looperdatalist); while(ld){ if (ld->id == id){ looperdata_lock(ld); looperdata_set_graindensity(ld, density); looperdata_unlock(ld); } ld = speciallist_get_next_nolock ( xsinfo->looperdatalist, ld); } } void pan_helper(xsession_info_t *xsinfo, int id, float pan){ looper_data_t *ld; ld = speciallist_get_first_nolock (xsinfo->looperdatalist); while(ld){ if (ld->id == id){ looperdata_lock(ld); looperdata_set_pan(ld, pan); looperdata_unlock(ld); } ld = speciallist_get_next_nolock ( xsinfo->looperdatalist, ld); } } void xsession_action(xsession_info_t *xsinfo) { snd_seq_event_t *ev; double note = 0.0; double vol = 0.0; do { snd_seq_event_input(xsinfo->seq, &ev); /* printf ("event: type %d\n",ev->type);*/ switch (ev->type) { case SND_SEQ_EVENT_CONTROLLER: /* fprintf(stderr, "Control event on Channel %2d: %d, %5d \n", ev->data.control.channel, ev->data.control.param, ev->data.control.value); */ switch (ev->data.control.param){ case XSESSION_FADER_1: setvol_helper(xsinfo, 1, (float)ev->data.control.value / 127.); break; case XSESSION_FADER_2: setvol_helper(xsinfo, 2, (float)ev->data.control.value / 127.); break; case XSESSION_FADER_3: setvol_helper(xsinfo, 3, (float)ev->data.control.value / 127.); break; case XSESSION_FADER_4: setvol_helper(xsinfo, 4, (float)ev->data.control.value / 127.); break; case XSESSION_POTI_1_1: setngrains_helper(xsinfo, 1, (int)((float)ev->data.control.value * 15. / 127.)); break; case XSESSION_POTI_2_1: setngrains_helper(xsinfo, 2, (int)((float)ev->data.control.value * 15. / 127.)); break; case XSESSION_POTI_3_1: setngrains_helper( xsinfo, 3, (int)((float)ev->data.control.value * 15. / 127.)); break; case XSESSION_POTI_4_1: setngrains_helper(xsinfo, 4, (int)((float)ev->data.control.value * 15. / 127.)); break; case XSESSION_POTI_1_2: graindensity_helper(xsinfo, 1, (int)((float)ev->data.control.value * 100. / 127.)); break; case XSESSION_POTI_2_2: graindensity_helper(xsinfo, 2, (int)((float)ev->data.control.value * 100. / 127.)); break; case XSESSION_POTI_3_2: graindensity_helper(xsinfo, 3, (int)((float)ev->data.control.value * 100. / 127.)); break; case XSESSION_POTI_4_2: graindensity_helper(xsinfo, 4, (int)((float)ev->data.control.value * 100. / 127.)); break; case XSESSION_POTI_1_3: pan_helper(xsinfo, 1, (float)ev->data.control.value / 64. - 1.); break; case XSESSION_POTI_2_3: pan_helper(xsinfo, 2, (float)ev->data.control.value / 64. - 1.); break; case XSESSION_POTI_3_3: pan_helper(xsinfo, 3, (float)ev->data.control.value / 64. - 1.); break; case XSESSION_POTI_4_3: pan_helper(xsinfo, 4, (float)ev->data.control.value / 64. - 1.); break; } break; case SND_SEQ_EVENT_PITCHBEND: fprintf(stderr, "Pitchbender event on Channel %2d: %5d \n", ev->data.control.channel, ev->data.control.value); break; case SND_SEQ_EVENT_NOTEON: note = xsession2pitch(ev->data.note.note); vol = (double)ev->data.note.velocity / 127.; fprintf(stderr, "Note On event on Channel %2d: %d (%lf) (v:%d/%lf) \n", ev->data.control.channel, ev->data.note.note,note, ev->data.note.velocity,vol); break; case SND_SEQ_EVENT_NOTEOFF: note = xsession2pitch(ev->data.note.note); fprintf(stderr, "Note Off event on Channel %2d: %d (%lf) (0) \n", ev->data.control.channel, ev->data.note.note,note); break; } snd_seq_free_event(ev); } while (snd_seq_event_input_pending(xsinfo->seq, 0) > 0); } static void xsession_process (xsession_info_t *xsinfo){ if (poll(xsinfo->pfds, xsinfo->seq_nfds, 40) > 0) { xsession_action(xsinfo); } } static void* xsession_run (void * data) { xsession_info_t* xsinfo = (xsession_info_t*) data; /* this is dealt with by the jack thread */ signal (SIGHUP, SIG_IGN); open_seq("xsession_input", xsinfo->seq); /* while (!xsinfo->seq && (count < 1000)){ usleep(10); count++;}*/ if (xsinfo->seq < 0) return NULL; printf ("created xsession thread \n"); xsinfo->seq_nfds = snd_seq_poll_descriptors_count(xsinfo->seq, POLLIN); xsinfo->pfds = (struct pollfd*)alloca(xsinfo->seq_nfds * sizeof(struct pollfd)); snd_seq_poll_descriptors(xsinfo->seq, xsinfo->pfds, xsinfo->seq_nfds, POLLIN); /* http://howtos.linux.com/howtos/MIDI-HOWTO-9.shtml */ while (!xsinfo->quit){ xsession_process (xsinfo); } free (xsinfo->pfds); return NULL; } #endif /* HAVE_ALSA */ kluppe-0.6.14/src/common/shuttle.h0000644000175000017500000000151110204256334016331 0ustar dieterdieter#ifndef __SHUTTLE_H__ #define __SHUTTLE_H__ #include #include #define SHUTTLE_SHUTTLE 1 #define SHUTTLE_JOG 2 #define SHUTTLE_LEFTMOST 4 #define SHUTTLE_LEFT 8 #define SHUTTLE_MIDDLE 16 #define SHUTTLE_RIGHT 32 #define SHUTTLE_RIGHTMOST 64 #define SHUTTLE_TYPE_KEY 1 #define SHUTTLE_TYPE_JOGSHUTTLE 2 typedef struct _shuttle_data { int fd; int value; int lastvalue; int code; int lastcode; int type; int buttonstates; int jogstate; int shuttlestate; float shuttledelta; long timediff; struct timeval lastevent; } shuttle_data_t; shuttle_data_t* shuttle_new(); int shuttle_open (shuttle_data_t* shuttle); int shuttle_close (shuttle_data_t* shuttle); int shuttle_poll (shuttle_data_t* shuttle); #endif /* __SHUTTLE_H__ */ kluppe-0.6.14/src/common/shuttle.c0000644000175000017500000001107610211046473016332 0ustar dieterdieter/* * based on xcshuttle by David Arendt */ #include #include #include #include #include #include #include #include "shuttle.h" int shuttle_open(shuttle_data_t* shuttle){ if (shuttle != NULL){ int i = 0; char name[256] = "unknown"; char *device; char shuttlename[256] = "Contour Design ShuttleXpress"; device = malloc(18 * sizeof(char)); if (shuttle->fd) close(shuttle->fd); shuttle->fd = 0; for (i = 0;(i < 10) && !shuttle->fd;i++){ snprintf(device,18,"/dev/input/event%d",i); shuttle->fd = open(device, O_RDONLY); if (shuttle->fd > 0){ if (ioctl(shuttle->fd, EVIOCGNAME(sizeof(name)), name) < 0){ shuttle->fd = close (shuttle->fd); }else{ if (strncmp(name,shuttlename,22) != 0){ shuttle->fd = close (shuttle->fd); }else{ /* printf ("Found %s at %s\n",name,device);*/ } } }else{shuttle->fd = 0;} } return shuttle->fd; } return 0; } shuttle_data_t* shuttle_new(){ shuttle_data_t* shuttle; shuttle = (shuttle_data_t*) malloc (sizeof(shuttle_data_t)); shuttle->fd = 0; shuttle->value = 0; shuttle->lastvalue = 0; shuttle->code = 0; shuttle->lastcode = 0; shuttle->type = 0; shuttle->buttonstates = 0; shuttle->jogstate = 0; shuttle->shuttlestate = 0; shuttle->shuttledelta = 0.0; shuttle->timediff = 0; shuttle->lastevent.tv_sec = 0; shuttle->lastevent.tv_usec = 0; return shuttle; } int shuttle_close (shuttle_data_t* shuttle){ if (shuttle != NULL){ if (shuttle->fd > 0){ shuttle->fd = close(shuttle->fd); printf ("Shuttle device closed\n"); } return shuttle->fd; }else return -1; } int shuttle_poll (shuttle_data_t* shuttle){ struct timeval tv; struct input_event ev; char name[256] = "unknown"; int retval; int type; int code; int value; int ok; fd_set rfds; if (shuttle != NULL){ if (shuttle->fd > 0){ tv.tv_sec = 0; tv.tv_usec = 0; if (ioctl(shuttle->fd, EVIOCGNAME(sizeof(name)), name) < 0) return shuttle_close (shuttle); FD_ZERO(&rfds); FD_SET(shuttle->fd, &rfds); retval = select(shuttle->fd + 1, &rfds, NULL, NULL, &tv); /* printf ("retval:%d, %d\n",retval,shuttle->fd);*/ if (retval < 0){ return shuttle_close (shuttle); }else if (retval > 0){ ok = read(shuttle->fd, &ev, sizeof(ev)); if (ok != sizeof(ev)) return shuttle_close (shuttle); type = ev.type; if ((type != SHUTTLE_TYPE_KEY) && (type != SHUTTLE_TYPE_JOGSHUTTLE)){ return 0;} switch (ev.code){ case 8 : code = SHUTTLE_JOG; break; case 7 : code = SHUTTLE_SHUTTLE; break; case 260 : code = SHUTTLE_LEFTMOST; break; case 261 : code = SHUTTLE_LEFT; break; case 262 : code = SHUTTLE_MIDDLE; break; case 263 : code = SHUTTLE_RIGHT; break; case 264 : code = SHUTTLE_RIGHTMOST; break; default : code = 0; printf ("unknown code\n"); break; } value = ev.value; if (code == SHUTTLE_JOG){ /* joq of shuttle xpress doesn't have 0 */ if (value < 0) value++; else value--; } if (type == SHUTTLE_TYPE_KEY){ if (value) shuttle->buttonstates |= code; else shuttle->buttonstates ^= code; /* printf ("buttonstates:%d\n",shuttle->buttonstates);*/ } if ((value != shuttle->shuttlestate) || (code != SHUTTLE_SHUTTLE)){ shuttle->lastvalue = shuttle->value; shuttle->lastcode = shuttle->code; shuttle->value = value; shuttle->code = code; shuttle->type = type; /* gettimeofday(&tv, NULL);*/ tv = ev.time; if (shuttle->lastevent.tv_sec || shuttle->lastevent.tv_usec){ shuttle->timediff = (tv.tv_sec - shuttle->lastevent.tv_sec) * 1000; shuttle->timediff = tv.tv_usec - shuttle->lastevent.tv_usec; } if (code == SHUTTLE_JOG) {shuttle->jogstate = value;} if (code == SHUTTLE_SHUTTLE){ if ((value - shuttle->shuttlestate) < -200){ shuttle->shuttlestate -= 253; } if ((value - shuttle->shuttlestate) > 200){ shuttle->shuttlestate += 253; } if (shuttle->timediff){ shuttle->shuttledelta = (float)(value - shuttle->shuttlestate) * 200000. / (float)shuttle->timediff; } shuttle->shuttlestate = value; } shuttle->lastevent.tv_sec = tv.tv_sec; shuttle->lastevent.tv_usec = tv.tv_usec; return code; } } } return -1; } return 0; } kluppe-0.6.14/src/common/alphatrack.h0000644000175000017500000001067311034126761016766 0ustar dieterdieter/* * alphatrack.h * alphatrack callback interface * based on transport.c by arthur@artcmusic.com */ #ifndef __ALPHATRACK_H__ #define __ALPHATRACK_H__ #include #include #define ALPHATRACK_VENDORID 0x165b #define ALPHATRACK_PRODUCTID 0xFAD1 #define ALPHATRACK_READ_ENDPOINT 0x81 #define ALPHATRACK_WRITE_ENDPOINT 0x02 #define MAXLED 23 enum { ALPHATRACK_LED_EQ = 0, ALPHATRACK_LED_RIGHT, ALPHATRACK_LED_F2, ALPHATRACK_LED_SEND, ALPHATRACK_LED_LEFT, ALPHATRACK_LED_F1, ALPHATRACK_LED_PAN, ALPHATRACK_LED_EMPTY, ALPHATRACK_LED_EMPTY2, ALPHATRACK_LED_SHIFT, ALPHATRACK_LED_MUTE, ALPHATRACK_LED_SOLO, ALPHATRACK_LED_REC, ALPHATRACK_LED_READ, ALPHATRACK_LED_WRITE, ALPHATRACK_LED_ANY, ALPHATRACK_LED_AUTO, ALPHATRACK_LED_F4, ALPHATRACK_LED_PUNCH, ALPHATRACK_LED_FLIP, ALPHATRACK_LED_PLUGIN, ALPHATRACK_LED_F3, ALPHATRACK_LED_LOOP }; /* read-bytes: 2 3 4 5 */ #define ALPHATRACK_BUTTON_REW 0x0000000001LL #define ALPHATRACK_BUTTON_RECORD 0x0000000002LL #define ALPHATRACK_BUTTON_FFWD 0x0000000004LL #define ALPHATRACK_BUTTON_PLAY 0x0000000008LL #define ALPHATRACK_BUTTON_STOP 0x0000000010LL #define ALPHATRACK_BUTTON_SHIFT 0x0000000020LL #define ALPHATRACK_BUTTON_FLIP 0x0000000040LL #define ALPHATRACK_BUTTON_TRACKL 0x0000000080LL #define ALPHATRACK_BUTTON_LOOP 0x0000000100LL #define ALPHATRACK_BUTTON_TRACKR 0x0000000200LL #define ALPHATRACK_BUTTON_MUTE 0x0000000400LL #define ALPHATRACK_BUTTON_F4 0x0000000800LL #define ALPHATRACK_BUTTON_F1 0x0000001000LL #define ALPHATRACK_BUTTON_F3 0x0000002000LL #define ALPHATRACK_BUTTON_F2 0x0000004000LL #define ALPHATRACK_BUTTON_SOLO 0x0000008000LL #define ALPHATRACK_BUTTON_AUTO 0x0000010000LL #define ALPHATRACK_BUTTON_PAN 0x0000020000LL #define ALPHATRACK_BUTTON_PLUGIN 0x0000040000LL #define ALPHATRACK_BUTTON_SEND 0x0000080000LL #define ALPHATRACK_BUTTON_REC 0x0000100000LL #define ALPHATRACK_BUTTON_ENCODER_R 0x0000200000LL #define ALPHATRACK_BUTTON_EQ 0x0000400000LL #define ALPHATRACK_BUTTON_ENCODER_M 0x0000800000LL #define ALPHATRACK_BUTTON_ENCODER_L 0x0001000000LL #define ALPHATRACK_CONTACT_TOUCHSTRIP_1 0x0002000000LL #define ALPHATRACK_CONTACT_TOUCHSTRIP_2 0x0004000000LL #define ALPHATRACK_CONTACT_ENCODER_L 0x0008000000LL #define ALPHATRACK_CONTACT_ENCODER_M 0x0010000000LL #define ALPHATRACK_CONTACT_ENCODER_R 0x0020000000LL #define ALPHATRACK_CONTACT_FADER 0x0040000000LL #define ALPHATRACK_BUTTON_FOOTSW 0x0080000000LL /* for fader, encoders and touchstrip, * any unique value to signal position-changes */ #define ALPHATRACK_POS_FADER 0x1000000000LL #define ALPHATRACK_POS_TOUCHSTRIP 0x2000000000LL #define ALPHATRACK_DELTA_ENCODER_L 0x0100000000LL #define ALPHATRACK_DELTA_ENCODER_M 0x0200000000LL #define ALPHATRACK_DELTA_ENCODER_R 0x0400000000LL #define ALPHATRACK_STATUS_OFFLINE 0xff /* makes sense for tranzport only */ #define ALPHATRACK_STATUS_ONLINE 0x01 /* makes sense for tranzport only */ typedef struct _alphatrack_event { uint64_t mask; uint64_t states; int leds[MAXLED]; int touchpos; int faderpos; int encoderdelta_l; int encoderdelta_m; int encoderdelta_r; } alphatrack_event_t; typedef struct _alphatrack { struct usb_device *dev; usb_dev_handle *udev; pthread_t pollthread; pthread_mutex_t alphatrackmutex; void (*callbackfunc)(alphatrack_event_t *ev, void *ptr); void *callbackptr; uint8_t status; uint64_t buttons; uint64_t buttondiff; int touchstate; int touchpos; int faderpos; int faderpos_dirty; int encoderdelta_l; int encoderdelta_m; int encoderdelta_r; int polltimeout; char* lcd; int lcd_dirty[10]; int lcd_ptr; int leds[MAXLED]; int led_dirty[MAXLED]; int led_ptr; int quit; } alphatrack_t; alphatrack_t *alphatrack_new(); void alphatrack_close(alphatrack_t *z); void alphatrack_set_event_callback(alphatrack_t *z, void (*callback)(alphatrack_event_t *ev, void *ptr) , void *ptr); uint8_t alphatrack_get_status(alphatrack_t *z); int alphatrack_clear_lcd (alphatrack_t *z); int alphatrack_write_lcd (alphatrack_t *z, const char* txt, int x, int y); int alphatrack_set_led(alphatrack_t *z, uint8_t led,int status); int alphatrack_get_led(alphatrack_t *z, uint8_t led); void alphatrack_clear_leds(alphatrack_t *z); int alphatrack_set_faderpos(alphatrack_t *z, int faderpos); #endif /* end ifndef ALPHATRACK.H */ kluppe-0.6.14/src/common/looperdata.c0000644000175000017500000014425411156445524017012 0ustar dieterdieter#include #include #include #include /*#include */ #include "looperdata.h" #include "interpol.h" const float PI = 3.14159265358979323846f; const float S2M_FACTOR = 0.7071; typedef struct _dirty_block { double start; double end; } dirty_block_t; /* predefine:*/ static void looperdata_reset_grain (looper_data_t* data, int grain); static void inform_buffer(looper_data_t* data); looper_data_t* looperdata_new(buffer_info_t* buf, long samplerate,int id){ int i; looper_data_t *data = (looper_data_t*) malloc (sizeof(looper_data_t)); data->buf = buf; data->looper_id = -1; data->clickmode_buf = NULL; data->reverb = buffer_new(id,samplerate); buffer_set_channels(data->reverb,2); data->reverblength = 0; data->feedback = 0.; data->revpos = 0; data->id = id; data->buffer_group = 0; data->samplerate = samplerate; data->speed = 1.; data->modespeed = 1.; data->vol = 1.; data->pan = 0.; data->panswing = 0.0; data->panpos = 0.; data->pandir = 1.; data->Lfact = 1.; data->Rfact = 1.; data->inmaxL = .0; data->inmaxR = .0; data->outmaxL = .0; data->outmaxR = .0; data->recmix = 1.; data->recmixnew = 1.; data->recmixorig = 0.; data->playpos = 0.; data->playindex = 0.; data->pointer = 0.; data->loopstart = 0; data->loopend = 0; data->recstart = 0; data->recend = 0; if (data->buf){ /* printf ("looperdata, get group\n");*/ data->buffer_group = buffer_get_group(data->buf,DS_PRIORITY_NORMAL); data->loopend = buffer_get_size(data->buf); data->recend = buffer_get_size(data->buf); } data->recpos = 0; data->isplaying = 0; data->isrecording = 0; data->linkrec2play = 1; data->keepabsolute = 0; data->limiter = 1; data->limit = 1.; data->limknee = .5; data->limconst = .25; data->thresholdstate = THRESHOLDSTATE_ANY; data->low_threshold = .01; data->high_threshold = .015; data->thresholdmode = 0; data->threshringptr = 0; data->threshringsize = 22050; /* half a second at regular speed should be a good start */ data->threshring = malloc (sizeof(float) * data->threshringsize); data->playvuL = .0; data->playvuR = .0; data->recvuL = .0; data->recvuR = .0; data->playmode = LOOP_PLAYMODE_LOOP; data->recmode = LOOP_RECMODE_LOOP; data->cm_size = 1024; data->cm_min = 0.001; data->cm_max = 5.; data->customplaymode = malloc (data->cm_size * sizeof(float)); for (i=0;i < data->cm_size; i++){ *(data->customplaymode + i) = 1.; } data->midichannel = 0; data->ngrains = 0; data->grainmixfactor = 1.; data->mingrainspeed = 1.; data->maxgrainspeed = 1.; data->mingrainlength = 1024; data->maxgrainlength = 1024; data->grainpitchmode = GRAINPITCH_AUTO; data->grainpitchbend = 1.; data->graindensity = 100; data->stereodiversity = 0.; data->grainindexes = NULL; data->grainoffsets = NULL; data->grainsizes = NULL; data->grainfadelengths = NULL; data->grainspeeds = NULL; data->grainsactive = NULL; data->grainpitchtable = NULL; data->grainpitchvolumes = NULL; data->grainpansL = NULL; data->grainpansR = NULL; data->dirtylist = speciallist_new(); pthread_mutex_init (&data->looperdatamutex, NULL); return data; } void looperdata_free(looper_data_t* data){ /* LATER free dirty block list */ speciallist_destroy(data->dirtylist); buffer_delete(data->reverb); if (data->buf){ buffer_lock(data->buf); buffer_delete_group(data->buf, data->buffer_group); buffer_unlock(data->buf); } free (data->customplaymode); free (data->grainindexes); free (data->grainoffsets); free (data->grainsizes); free (data->grainfadelengths); free (data->grainspeeds); free (data->grainsactive); free (data->grainpitchtable); free (data->grainpitchvolumes); free (data->grainpansL); free (data->grainpansR); free (data); data = NULL; } void looperdata_lock(looper_data_t* data){ pthread_mutex_lock (&data->looperdatamutex); } void looperdata_unlock(looper_data_t* data){ pthread_mutex_unlock (&data->looperdatamutex); } void looperdata_copy_settings (looper_data_t* dst, looper_data_t* src){ int i; if (dst && src){ /* ??? dst->samplerate = src->samplerate; */ dst->speed = src->speed; dst->playmode = src->playmode; dst->modespeed = src->modespeed; dst->vol = src->vol; dst->pan = src->pan; dst->panswing = src->panswing; dst->panpos = src->panpos; dst->pandir = src->pandir; dst->Lfact = src->Lfact; dst->Rfact = src->Rfact; dst->inmaxL = src->inmaxL; dst->inmaxR = src->inmaxR; dst->outmaxL = src->outmaxL; dst->outmaxR = src->outmaxR; dst->recmix = src->recmix; dst->recmixnew = src->recmixnew; dst->recmixorig = src->recmixorig; dst->linkrec2play = src->linkrec2play; dst->keepabsolute = src->keepabsolute; dst->limiter = src->limiter; dst->limit = src->limit; dst->limknee = src->limknee; dst->limconst = src->limconst; dst->midichannel = src->midichannel; dst->graindensity = src->graindensity; dst->grainpitchmode = src->grainpitchmode; dst->stereodiversity = src->stereodiversity; if (dst->buf && src->buf){ dst->isplaying = src->isplaying; dst->isrecording = src->isrecording; dst->playpos = src->playpos; dst->playindex = src->playindex; if (dst->playpos > buffer_get_size(dst->buf)){ dst->playpos = buffer_get_size(dst->buf); } if (dst->playindex > buffer_get_size(dst->buf)){ dst->playindex = buffer_get_size(dst->buf); } dst->recpos = src->recpos; dst->pointer = src->pointer; if (dst->recpos > buffer_get_size(dst->buf)){ dst->recpos = buffer_get_size(dst->buf); } dst->loopstart = src->loopstart; if (dst->loopstart > buffer_get_size(dst->buf)){ dst->loopstart = 0; /* LATER find a more intelligent solution */ } dst->loopend = src->loopend; if (dst->loopend > buffer_get_size(dst->buf)){ dst->loopend = buffer_get_size(dst->buf); } dst->recstart = src->recstart; if (dst->recstart > buffer_get_size(dst->buf)){ dst->recstart = 0; /* LATER find a more intelligent solution */ } dst->recend = src->recend; if (dst->recend > buffer_get_size(dst->buf)){ dst->recend = buffer_get_size(dst->buf); } inform_buffer(dst); } if (dst->cm_size != src->cm_size){ dst->customplaymode = realloc(dst->customplaymode, src->cm_size * sizeof(float)); dst->cm_size = src->cm_size; } for (i = 0; i < dst->cm_size; i++){ *(dst->customplaymode + i) = *(src->customplaymode + i); } dst->mingrainlength = src->mingrainlength; dst->maxgrainlength = src->maxgrainlength; dst->mingrainspeed = src->mingrainspeed; dst->maxgrainspeed = src->maxgrainspeed; looperdata_set_ngrains(dst,src->ngrains); /* printf ("size:%ld\n",buffer_get_size(src->reverb));*/ buffer_resize(dst->reverb,buffer_get_size(src->reverb)); dst->reverblength = src->reverblength; dst->feedback = src->feedback; for (i = 0; i < src->ngrains; i++){ looperdata_reset_grain(dst,i); dst->grainpitchtable[i] = src->grainpitchtable[i]; dst->grainpitchvolumes[i] = src->grainpitchvolumes[i]; dst->grainpansL[i] = src->grainpansL[i]; dst->grainpansR[i] = src->grainpansR[i]; } } } char* looperdata_cm2str (looper_data_t* data, char* str){ int i; long s = 0; char *num = malloc(sizeof(char) * 32); if (str){ free(str); str = NULL; } for (i = 0; i < data->cm_size; i++){ sprintf (num,"%f ",*(data->customplaymode + i)); s += strlen(num); /* printf ("s:%ld,num:%s-\n",(s + 1),num);*/ str = (char*)realloc (str,sizeof(char) * (s + 1)); memset((void*)(str + s - strlen(num)),0,strlen(num)); str = strcat(str, num); } free(num); return str; } void looperdata_str2cm (looper_data_t* data, char* str, int cm_size){ char *a = str; char *b; char *num = malloc(sizeof(char) * 32); int i; data->cm_size = cm_size; data->customplaymode = realloc(data->customplaymode, data->cm_size * sizeof(float)); for (i = 0;i < data->cm_size; i++){ b = strstr((char*)(a + 1)," "); if (b){ memset((void*)num,0,31); num = strncpy (num,(a),(b-a)); *(data->customplaymode + i) = (float)atof (num); a = b; } } } void looperdata_set_clickmode_buf(looper_data_t* data, buffer_info_t* buf){ if (data) data->clickmode_buf = buf; } buffer_info_t* looperdata_get_clickmode_buf(looper_data_t* data){ if (data) return data->clickmode_buf; else return NULL; } void looperdata_write_dirtyblock(looper_data_t* data, double start, double end){ /* return number of blocks including this one */ dirty_block_t* block; int overlap = 0; block = speciallist_get_first(data->dirtylist); while (block){ /* if (((block->start <= start) && (block->end >= start)) || ((block->start <= end) && (block->end >= end)) ){ */ if (((block->start <= (start + 1.)) && (block->end >= start)) || ((block->start <= end) && (block->end >= (end - 1.))) ){ if (block->start > start) block->start = start; if (block->end < end) block->end = end; overlap = 1; break; } block = speciallist_get_next(data->dirtylist,(void*)block); } if (!overlap){ block = malloc (sizeof(dirty_block_t)); block->start = start; block->end = end; speciallist_append(data->dirtylist,(void*)block); } } int looperdata_read_once_dirtyblock(looper_data_t* data, double* start, double* end){ /* return 1 if a block exists otherwise 0 */ /* set start and end */ /* delete after read */ dirty_block_t* block; block = speciallist_get_first(data->dirtylist); if (block){ *start = block->start; *end = block->end; looperdata_lock(data); speciallist_delete(data->dirtylist, (void*)block); looperdata_unlock(data); /* LATER: is this right? */ free(block); return 1; } *start = 0.0; *end = 0.0; return 0; } void looperdata_set_playing(looper_data_t* data, int isplaying){ if (data) data->isplaying = isplaying; } void looperdata_set_recording(looper_data_t* data, int isrecording){ if (data) data->isrecording = isrecording; } int looperdata_get_playing(looper_data_t* data){ if (data) return data->isplaying; else return 0; } int looperdata_get_recording(looper_data_t* data){ if (data) return data->isrecording; else return 0; } void looperdata_calc_pan (looper_data_t* data){ if (data->panswing > 0.){ data->panpos += data->pandir * data->panswing * 2 / data->samplerate; if (data->panpos > 1.){ data->panpos = 1.; data->pandir = -1.; }else if (data->panpos < -1.){ data->panpos = -1.; data->pandir = 1.; } if (data->panpos > .0){ data->Lfact = 1. - data->panpos; data->Rfact = 1.; }else{ data->Lfact = 1.; data->Rfact = 1. + data->panpos; } if (data->pan > .0){ } }else{ if (data->pan > .0){ data->Lfact = 1. - data->pan; data->Rfact = 1.; }else{ data->Lfact = 1.; data->Rfact = 1. + data->pan; } } data->Lfact *= data->vol; data->Rfact *= data->vol; } void looperdata_set_pan(looper_data_t* data, float pan){ if (pan < -1.) pan = -1.; if (pan > 1.) pan = 1.; data->pan = pan; looperdata_calc_pan(data); } void looperdata_set_panswing(looper_data_t* data, float panswing){ data->panswing = panswing; looperdata_calc_pan(data); } void looperdata_set_vol(looper_data_t* data, float vol){ if (vol < .0){vol = 0.;} data->vol = vol; /* if (data->buf) printf ("data:%s, vol:%f\n",data->buf->shortname, vol);*/ /* recalculate Lfact + Rfact */ looperdata_calc_pan(data); } float looperdata_get_vol(looper_data_t* data){ return data->vol; } void looperdata_set_recmix(looper_data_t* data, float recmix){ /* if (recmix < -1.){recmix = -1.;} if (recmix > 1.){recmix = 1.;}*/ data->recmix = recmix; if (data->recmix > 1.){ data->recmixorig = 0.; data->recmixnew = data->recmix; }else if (data->recmix < -1.){ data->recmixorig = data->recmix; data->recmixnew = 0.; }else if (data->recmix > .0){ data->recmixorig = 1. - data->recmix; data->recmixnew = 1.; }else{ data->recmixorig = 1.; data->recmixnew = 1. + data->recmix; } /* printf ("recmixnew:%.2f, recmixorig:%.2f\n",data->recmixnew,data->recmixorig);*/ } float looperdata_get_recmix(looper_data_t* data){ return data->recmix; } int looperdata_get_midichannel (looper_data_t* data){ /* muse and my keyboard send 0 when they say 1 ?!? */ return (data->midichannel - 1); } void looperdata_set_midichannel (looper_data_t* data, int channel){ if ((channel > -1) && (channel < 16)) data->midichannel = channel + 1; else data->midichannel = -1; } void looperdata_set_mingrainspeed(looper_data_t* data,double speed){ if (data){ data->mingrainspeed = speed; } inform_buffer(data); } void looperdata_set_maxgrainspeed(looper_data_t* data,double speed){ if (data){ data->maxgrainspeed = speed; } inform_buffer(data); } void looperdata_set_mingrainlength(looper_data_t* data,long length){ /* if ((data) && (length > 10)){*/ if (data && (length > 1)){ data->mingrainlength = length; if (data->maxgrainlength < data->mingrainlength) data->maxgrainlength = data->mingrainlength; } inform_buffer(data); } void looperdata_set_maxgrainlength(looper_data_t* data,long length){ if (data && (length > 1)){ data->maxgrainlength = length; if (data->maxgrainlength < data->mingrainlength) data->mingrainlength = data->maxgrainlength; } inform_buffer(data); } void looperdata_set_graindensity(looper_data_t* data,int density){ if (data) data->graindensity = density; } void looperdata_set_stereodiversity(looper_data_t* data, double diversity){ if (diversity < 0.) diversity = 0.; if (diversity > 1.) diversity = 1.; if (data) data->stereodiversity = diversity; } double looperdata_get_stereodiversity(looper_data_t* data){ if (data) return data->stereodiversity; else return 0.; } double looperdata_get_mingrainspeed(looper_data_t* data){ if (data){ return data->mingrainspeed; }else{ return 0.; } } double looperdata_get_maxgrainspeed(looper_data_t* data){ if (data){ return data->maxgrainspeed; }else{ return 0.; } } long looperdata_get_mingrainlength(looper_data_t* data){ if (data){ return data->mingrainlength; }else{ return 0; } } long looperdata_get_maxgrainlength(looper_data_t* data){ if (data){ return data->maxgrainlength; }else{ return 0; } } int looperdata_get_graindensity(looper_data_t* data){ if (data) return data->graindensity; else return 0; } int looperdata_get_cm_size(looper_data_t* data){ return data->cm_size; } void looperdata_get_playmeters(looper_data_t* data,float* L,float* R){ *L = data->outmaxL; *R = data->outmaxR; data->outmaxL = 0.; data->outmaxR = 0.; } void looperdata_get_recmeters(looper_data_t* data,float* L,float* R){ *L = data->inmaxL; *R = data->inmaxR; data->inmaxL = 0.; data->inmaxR = 0.; } static void looperdata_reset_grain (looper_data_t* data, int grain){ int i,a = 0; double d = 1.; *(data->grainindexes + grain) = 0; if (data->ngrains > 1) *(data->grainoffsets + grain) = data->playpos + rand()%(data->maxgrainlength / 15 * (data->ngrains + 1) + 1); else *(data->grainoffsets + grain) = data->playpos; *(data->grainsizes + grain) = data->mingrainlength + rand()%(data->maxgrainlength - data->mingrainlength + 1); *(data->grainfadelengths + grain) = *(data->grainsizes + grain) / 10 + 2; /* random stereo factor: */ if (data->stereodiversity){ d = data->stereodiversity * rand()/(RAND_MAX+1.0); if ((int)rand()%(2)) d*= -1.; if (d > .0){ *(data->grainpansL + grain) = 1. - d; *(data->grainpansR + grain) = 1.; }else{ *(data->grainpansL + grain) = 1.; *(data->grainpansR + grain) = 1. + d; } } else{ *(data->grainpansL + grain) = 1.; *(data->grainpansR + grain) = 1.; } /* is it correct to multiply with speeds ? */ if ((*(data->grainfadelengths + grain) * *(data->grainspeeds + grain)) > 200) *(data->grainfadelengths + grain) = 200; if (*(data->grainfadelengths + grain) < 5) *(data->grainfadelengths + grain) = 5; /* pitch according to pitchmode: */ if (data->grainpitchmode == GRAINPITCH_CHORD){ if (*(data->grainpitchtable + grain) != 0.){ /* the next line to include the min-max range correctly: */ *(data->grainspeeds + grain) = data->mingrainspeed + (double)(rand()%100001) / 100000. * (data->maxgrainspeed - data->mingrainspeed); *(data->grainspeeds + grain) *= *(data->grainpitchtable + grain); if (data->grainpitchbend) *(data->grainspeeds + grain) *= data->grainpitchbend; *(data->grainsactive + grain) = 1; }else{ *(data->grainspeeds + grain) = 1; *(data->grainsactive + grain) = 0; *(data->grainpitchvolumes + grain) = 0.0; } } else { /* GRAINPITCH_AUTO and GRAINPITCH_RANGE are based on the predefined pitch range */ *(data->grainspeeds + grain) = data->mingrainspeed + (double)(rand()%100001) / 100000. * (data->maxgrainspeed - data->mingrainspeed); if (data->grainpitchmode == GRAINPITCH_AUTO){ if (*(data->grainpitchtable + grain) != 0.){ *(data->grainspeeds + grain) *= *(data->grainpitchtable + grain); if (data->grainpitchbend) *(data->grainspeeds + grain) *= data->grainpitchbend; /* *(data->grainsactive + grain) = 1; */ if (data->graindensity > (int)(100.0*rand()/(RAND_MAX+1.0)) ) *(data->grainsactive + grain) = 1; else *(data->grainsactive + grain) = 0; }else{ *(data->grainsactive + grain) = 0; } }else{ /* this should be GRAINPITCH_RANGE */ if (data->graindensity > (int)(100.0*rand()/(RAND_MAX+1.0)) ) *(data->grainsactive + grain) = 1; else *(data->grainsactive + grain) = 0; } } /* LATER: this might wrap wrong !?!*/ if (*(data->grainoffsets + grain) > data->loopend){ *(data->grainoffsets + grain) -= data->loopend - data->loopstart; } if (data->grainpitchmode == GRAINPITCH_CHORD){ /* avoid stuttering volumechanges */ data->grainmixfactor = 1.0f / sqrt((float)data->ngrains); } else { /*calculate mix factor for volume: */ for (i = 0; i < data->ngrains;i++){ if (*(data->grainsactive + grain)) a++; } if (a < 1) a = 1; data->grainmixfactor = 1.0f / sqrt((float)a); /* printf ("mixfactor:%lf\n", data->grainmixfactor); */ } } void looperdata_set_grainpitchmode ( looper_data_t* data, int mode){ int i; if (mode == GRAINPITCH_AUTO){ data->grainpitchmode = GRAINPITCH_AUTO; for (i = 0; i < data->ngrains; i++){ *(data->grainpitchtable + i) = 1.; *(data->grainpitchvolumes + i) = 1.; } data->grainpitchbend = 1.; }else if (mode == GRAINPITCH_CHORD){ data->grainpitchmode = GRAINPITCH_CHORD; for (i = 0; i < data->ngrains; i++){ *(data->grainpitchtable + i) = 0.; *(data->grainpitchvolumes + i) = 0.; } data->grainpitchbend = 1.; }else{ data->grainpitchmode = GRAINPITCH_RANGE; for (i = 0; i < data->ngrains; i++){ *(data->grainpitchtable + i) = 1.; *(data->grainpitchvolumes + i) = 1.; } data->grainpitchbend = 1.; } inform_buffer(data); } int looperdata_get_grainpitchmode (looper_data_t* data){ return data->grainpitchmode; } void looperdata_set_grainpitchtablevalue ( looper_data_t* data, double value, double vol){ int i = 0; int found = 0; /* printf ("set grainpitch:%lf - %lf\n",value,vol);*/ if (vol == 0.){ /* printf ("vol 0\n");*/ while (!found && (i < data->ngrains)){ if (*(data->grainpitchtable + i) == value){ if (data->grainpitchmode == GRAINPITCH_CHORD){ *(data->grainpitchtable + i) = 0.; /* *(data->grainpitchvolumes + i) = 0.; */ /* mute without fade !!!*/ }else{ *(data->grainpitchtable + i) = 1.; /* fall back to regular volume */ *(data->grainpitchvolumes + i) = 0; } found++; } i++; } }else{ while (!found && (i < data->ngrains)){ if (data->grainpitchmode == GRAINPITCH_CHORD){ if (*(data->grainsactive + i) == 0){ /* if (*(data->grainpitchtable + i) == 0.){*/ *(data->grainpitchtable + i) = value; *(data->grainpitchvolumes + i) = vol; found++; } }else{ if (*(data->grainpitchtable + i) == 1.){ *(data->grainpitchtable + i) = value; *(data->grainpitchvolumes + i) = vol; found++; } } i++; } } } static void inform_buffer(looper_data_t* data){ long bw = 0; if (!data->buf) return; if (buffer_get_type(data->buf) != BUFFER_TYPE_DISCSTREAM) return; if (data->ngrains > 1){ /* calculate the maximum distance between two grain-playheads:*/ long slow, fast, cursor; long tmp, offset; offset = data->maxgrainlength * (data->ngrains + 1); offset /= 15; slow = (long)((float)data->maxgrainlength * data->mingrainspeed); fast = (long)((float)data->maxgrainlength * data->maxgrainspeed); cursor = (long)((float)data->maxgrainlength * data->speed); bw = abs(cursor - slow) + offset; tmp = abs(fast - slow) + offset; if (tmp > bw) bw = tmp; /* printf ("max distance between two grains:%ld\n",bw);*/ } else bw = 16384; buffer_set_area(data->buf,data->buffer_group, data->loopstart,data->loopend,bw); } void looperdata_set_grainpitchbend (looper_data_t* data, double bend){ /* printf ("set grainpitchbend\n");*/ if ((bend > -1.) && (bend < 2.)) data->grainpitchbend = bend; inform_buffer(data); } void looperdata_set_loopstart(looper_data_t* data, long start){ if (!data) return; if (data->buf){ if (start > buffer_get_size(data->buf)) start = buffer_get_size(data->buf) - 1; if (start < 1) start = 1; data->loopstart = start; if (data->loopstart >= data->loopend) data->loopend = data->loopstart + 1; } inform_buffer(data); } void looperdata_set_loopend(looper_data_t* data, long end){ if (!data) return; if (data->buf){ if (end > buffer_get_size(data->buf)) end = buffer_get_size(data->buf) - 1; if (end < 2) end = 2; data->loopend = end; if (data->loopstart >= data->loopend) data->loopend = data->loopstart + 1; } inform_buffer(data); } void looperdata_set_playmode(looper_data_t* data,int mode){ data->playmode = mode; if (data->playmode == LOOP_PLAYMODE_EXTERNALPOS) data->modespeed = 0.; else data->modespeed = 1.; } void looperdata_set_recmode(looper_data_t* data,int mode){ data->recmode = mode; } long looperdata_get_loopstart(looper_data_t* data){ return data->loopstart; } long looperdata_get_loopend(looper_data_t* data){ return data->loopend; } void looperdata_set_recstart(looper_data_t* data, long start){ if (!data) return; if (data->buf){ if (start > buffer_get_size(data->buf)) start = buffer_get_size(data->buf) - 2; if (start < 1) start = 1; data->recstart = start; if (data->recstart >= data->recend) data->recend = data->loopstart + 1; } inform_buffer(data); } void looperdata_set_recend(looper_data_t* data, long end){ if (!data) return; if (data->buf){ if (end > buffer_get_size(data->buf)) end = buffer_get_size(data->buf) - 1; if (end < 2) end = 2; data->recend = end; if (data->recstart >= data->recend) data->recend = data->recstart + 1; } inform_buffer(data); } void looperdata_set_playpos(looper_data_t* data, double playpos){ data->playpos = playpos; data->playindex = playpos; if (data->buf) buffer_readsample_interpolated(data->buf, 1, (long)data->playpos, 0); } void looperdata_set_recpos(looper_data_t* data, long recpos){ data->recpos = recpos; } long looperdata_get_recstart(looper_data_t* data){ return data->recstart; } long looperdata_get_recend(looper_data_t* data){ return data->recend; } void looperdata_set_speed(looper_data_t* data, double speed){ data->speed = speed; } double looperdata_get_speed(looper_data_t* data){ return data->speed; } double looperdata_get_playpos(looper_data_t* data){ return data->playpos; } long looperdata_get_recpos(looper_data_t* data){ return data->recpos; } static void calc_limconst (looper_data_t* data){ data->limconst = (data->limit - data->limknee) * data->limknee; /* printf ("knee:%f, limit:%f, const:%f\n",data->limknee,data->limit,data->limconst);*/ } int looperdata_get_limiter(looper_data_t* data){ return data->limiter; } void looperdata_set_limiter(looper_data_t* data, int limiter){ if (limiter) data->limiter = 1; else data->limiter = 0; } float looperdata_get_limknee(looper_data_t* data){ return data->limknee; } void looperdata_set_limknee(looper_data_t* data, float limknee){ data->limknee = limknee; calc_limconst(data); } float looperdata_get_limit(looper_data_t* data){ return data->limit; } void looperdata_set_limit(looper_data_t* data, float limit){ data->limit = limit; calc_limconst(data); } int looperdata_get_thresholdmode(looper_data_t* data){ return data->thresholdmode; } void looperdata_set_thresholdmode(looper_data_t* data, int mode){ if (mode){ data->thresholdmode = 1; data->thresholdstate = THRESHOLDSTATE_LOW; } else { data->thresholdmode = 0; data->thresholdstate = THRESHOLDSTATE_ANY; } } double looperdata_get_low_threshold(looper_data_t* data){ return data->low_threshold;; } void looperdata_set_low_threshold(looper_data_t* data, double low){ if (low >= 0.) data->low_threshold = low; } double looperdata_get_high_threshold(looper_data_t* data){ return data->high_threshold; } void looperdata_set_high_threshold(looper_data_t* data, double high){ if (high >= 0.) data->high_threshold = high; } int looperdata_get_thresholdbuffersize(looper_data_t* data){ return data->threshringsize; } void looperdata_set_thresholdbuffersize(looper_data_t* data, int size){ if ((size > 64) && (size < 882000)){ /* could be more sophisticated */ data->threshringsize = size; if (data->threshringptr > data->threshringsize) data->threshringptr = 0; data->threshring = (float*) realloc (data->threshring, sizeof(float) * data->threshringsize); } } /* void looperdata_set_grainlength (looper_data_t* data, long length){ if (length < 256){length = 256;} data->grainlength = length; } */ void looperdata_set_pointer (looper_data_t* data, float *pointer){ buffer_lock(data->buf); data->pointer = *pointer; buffer_unlock(data->buf); } void looperdata_get_pointer (looper_data_t* data, float *pointer){ float f = data->playindex - data->loopstart; if (f == 0.0) *pointer = 0.; else *pointer = f / (float)(data->loopend - data->loopstart); // if (f) // printf ("diff:%ld ,end:%ld pointer:%f\n",(data->loopend - data->loopstart),data->loopend,*pointer); } int looperdata_get_ngrains (looper_data_t* data){ return data->ngrains; } void looperdata_set_ngrains (looper_data_t* data, int ngrains){ int i; /* int a = 0;*/ if (ngrains == data->ngrains) return; if (ngrains < 0) ngrains = 0; if (ngrains > 15) ngrains = 15; /* printf ("ngrains:%d\n",ngrains);*/ if (ngrains){ data->grainindexes = realloc (data->grainindexes, sizeof(float) * ngrains); data->grainoffsets = realloc (data->grainoffsets, sizeof(long) * ngrains); data->grainsizes = realloc (data->grainsizes, sizeof(long) * ngrains); data->grainfadelengths = realloc (data->grainfadelengths, sizeof(long) * ngrains); data->grainspeeds = realloc (data->grainspeeds, sizeof(double) * ngrains); data->grainsactive = realloc (data->grainsactive, sizeof(int) * ngrains); data->grainpitchtable = realloc (data->grainpitchtable, sizeof(double) * ngrains); data->grainpitchvolumes = realloc (data->grainpitchvolumes, sizeof(double) * ngrains); data->grainpansL = realloc (data->grainpansL, sizeof(double) * ngrains); data->grainpansR = realloc (data->grainpansR, sizeof(double) * ngrains); if (data->buf){ for (i = data->ngrains; i < ngrains; i++){ /* printf ("initialising grain nr. %d\n",i);*/ looperdata_reset_grain(data,i); if (data->grainpitchmode == GRAINPITCH_CHORD){ data->grainpitchtable[i] = 0.; data->grainpitchvolumes[i] = 0.; }else{ data->grainpitchtable[i] = 1.; data->grainpitchvolumes[i] = 1.; } /* if (data->grainsactive[i]) a++;*/ } } /* data->grainmixfactor = 1.0f / (1. + log10f(sqrt(ngrains)) * 3.333);*/ data->grainmixfactor = 1.0f / sqrt(ngrains); /* printf ("mixfactor:%lf\n",data->grainmixfactor);*/ /* change = 20 * log10(sqrt(number)) db; 6db = factor 2 */ } data->ngrains = ngrains; inform_buffer(data); } /* reverb : */ void looperdata_set_reverblength(looper_data_t* data, long length){ if (length < 0) length = 0; if (length > 441000) length = 441000; /* any upper border for now */ if (data){ buffer_resize(data->reverb,length); data->reverblength = buffer_get_size(data->reverb); } } long looperdata_get_reverblength(looper_data_t* data){ if (data) return data->reverblength; else return 0; } void looperdata_set_feedback(looper_data_t* data, double feedback){ if (feedback < 0.) feedback = 0.; if (feedback > 1.) feedback = 1.; /* printf ("set feedback:%lf\n",feedback);*/ if (data) data->feedback = feedback; } double looperdata_get_feedback(looper_data_t* data){ if (data) return data->feedback; else return 0; } void looperdata_write_sample(looper_data_t* data,float* L, float* R){ if (!data->buf) return; if (!buffer_get_size(data->buf)) return; if (buffer_get_channels(data->buf) > 1){ if (data->inmaxL < fabs(*L)){data->inmaxL = fabs(*L);} if (data->inmaxR < fabs(*R)){data->inmaxR = fabs(*R);} buffer_lock(data->buf); *L = *L * data->recmixnew + buffer_readsample_interpolated(data->buf, 1,data->recpos, data->buffer_group) * data->recmixorig; *R = *R * data->recmixnew + buffer_readsample_interpolated(data->buf, 2,data->recpos, data->buffer_group) * data->recmixorig; if (data->limiter){ if (*L > data->limknee) *L = data->limit - data->limconst / *L; else if (*L < -data->limknee) *L = -data->limit - data->limconst / *L; if (*R > data->limknee) *R = data->limit - data->limconst / *R; else if (*R < -data->limknee) *R = -data->limit - data->limconst / *R; } buffer_writesample(data->buf, 1, data->recpos, 0, *L); buffer_writesample(data->buf, 2, data->recpos, 0, *R); buffer_unlock(data->buf); }else{ if (data->inmaxL < fabs(*L)){data->inmaxL = fabs(*L);} buffer_lock(data->buf); *L = *L * data->recmixnew + buffer_readsample_interpolated(data->buf, 1,data->recpos, data->buffer_group) * data->recmixorig; if (data->limiter){ if (*L > data->limknee) *L = data->limit - data->limconst / *L; else if (*L < -data->limknee) *L = -data->limit - data->limconst / *L; } buffer_writesample(data->buf, 1, data->recpos, 0, *L); buffer_unlock(data->buf); } if (++data->recpos > data->recend){ data->recpos = data->recstart; if (data->recmode == LOOP_RECMODE_ONCE) data->isrecording = 0; } if (data->recpos < data->recstart){ data->recpos = data->recstart; } } void looperdata_write_sampleblock(looper_data_t* data, long size, float* Lbuf, float* Rbuf){ long l, part; float *L; float *R; if (!data->buf) return; if (!buffer_get_size(data->buf)) return; if (data->isrecording){ if (buffer_get_channels(data->buf) > 1){ for (l = 0; l < size; l++){ L = (Lbuf + l); R = (Rbuf + l); if (data->inmaxL < fabs(*L)) data->inmaxL = fabs(*L); if (data->inmaxR < fabs(*R)) data->inmaxR = fabs(*R); *L *= data->recmixnew; *R *= data->recmixnew; if (data->recmixorig){ *L += buffer_readsample_interpolated(data->buf, 1, data->recpos, data->buffer_group) * data->recmixorig; *R += buffer_readsample_interpolated(data->buf, 2, data->recpos, data->buffer_group) * data->recmixorig; } if (data->limiter){ if (*L > data->limknee) *L = data->limit - data->limconst / *L; else if (*L < -data->limknee) *L = -data->limit - data->limconst / *L; if (*R > data->limknee) *R = data->limit - data->limconst / *R; else if (*R < -data->limknee) *R = -data->limit - data->limconst / *R; } } }else{ for (l = 0; l < size; l++){ L = (Lbuf + l); R = (Rbuf + l); if (data->inmaxL < fabs(*(Lbuf + l))) data->inmaxL = fabs(*(Lbuf + l)); *L *= data->recmixnew; if (data->recmixorig) *L += buffer_readsample_interpolated(data->buf, 1, data->recpos, data->buffer_group) * data->recmixorig; if (data->limiter){ if (*L > data->limknee) *L = data->limit - data->limconst / *L; else if (*L < -data->limknee) *L = -data->limit - data->limconst / *L; } } } if (data->recpos < data->recstart) data->recpos = data->recstart; if (data->recpos >= data->recend) data->recpos = data->recstart; while (size > 0){ part = size; if ((part + data->recpos) > data->recend) /* avoid writing behind the end */ part = data->recend - data->recpos; buffer_lock(data->buf); buffer_write_sampleblock(data->buf, data->recpos, part, 0, Lbuf, Rbuf); /* write sampleblock = ok */ buffer_unlock(data->buf); size -= part; data->recpos += part; if (data->recpos >= data->recend){ /* wrap around */ data->recpos = data->recstart; if (data->recmode == LOOP_RECMODE_ONCE){ size = 0; data->isrecording = 0; } } } } } static double grain_inc(looper_data_t* data, int i){ double pos = data->playpos; *(data->grainindexes + i) += 1; if (*(data->grainindexes + i) >= *(data->grainsizes + i)){ /* printf ("index:%ld, size:%ld\n",*(data->grainindexes + i), *(data->grainsizes + i));*/ looperdata_reset_grain (data,i); } else { pos = (float)*(data->grainoffsets + i) + *(data->grainindexes + i) * *(data->grainspeeds + i); /* check if still inside the loop: */ if (pos > (float)data->loopend){ *(data->grainoffsets + i) -= (data->loopend - data->loopstart)/* * *(data->grainspeeds + i)*/; /* printf ("loopend:%ld, recend:%ld, pos:%.2lf\n",data->loopend, data->recend,pos);*/ pos = (float)*(data->grainoffsets + i) + *(data->grainindexes + i) * *(data->grainspeeds + i); } else if (pos < (float)data->loopstart){ *(data->grainoffsets + i) += (data->loopend - data->loopstart)/* * *(data->grainspeeds + i)*/; pos = (float)*(data->grainoffsets + i) + *(data->grainindexes + i) * *(data->grainspeeds + i); } } return pos; } void looperdata_calc_sample_stereo(looper_data_t* data, float* L, float* R){ int i; float vol = 1.; double pos, ipos; if (data->ngrains < 1){ /* single playhead */ pos = data->playpos; *L = buffer_readsample_interpolated(data->buf,1,pos, data->buffer_group); *R = buffer_readsample_interpolated(data->buf,2,pos, data->buffer_group); }else{ /* granular playhead(s) */ *L = .0; *R = .0; for (i = 0; i < data->ngrains; i++){ pos = grain_inc(data,i); if (*(data->grainsactive + i)){ if (*(data->grainindexes + i) < *(data->grainfadelengths + i)){ vol = (float)*(data->grainindexes + i) / (float)*(data->grainfadelengths + i); } else if ( (ipos = (*(data->grainsizes + i) - *(data->grainindexes + i))) < *(data->grainfadelengths + i)){ vol = ipos / (float)*(data->grainfadelengths + i); } else vol = 1.; vol *= data->grainmixfactor * *(data->grainpitchvolumes + i); *L += buffer_readsample_interpolated(data->buf,1,pos, data->buffer_group) * vol * *(data->grainpansL); *R += buffer_readsample_interpolated(data->buf,2,pos, data->buffer_group) * vol * *(data->grainpansR); } } } /* clickmode ?: */ if (data->clickmode_buf){ pos = (float)(data->playpos - data->loopstart) / data->speed; if (pos < buffer_get_size(data->clickmode_buf)){ *L += buffer_readsample_interpolated(data->clickmode_buf,1,pos,0); *R += buffer_readsample_interpolated(data->clickmode_buf,2,pos,0); } } if (data->playmode == LOOP_PLAYMODE_SINE){ data->modespeed = sin((data->playpos - data->loopstart) * PI / (data->loopend - data->loopstart)) * 1.5 + .5; }else if (data->playmode == LOOP_PLAYMODE_CUSTOMSPEED){ data->modespeed = inter4pol_float(data->customplaymode, (float)(data->playpos - data->loopstart) * (float)data->cm_size / (float)(data->loopend - data->loopstart),data->cm_size); }else if (data->playmode == LOOP_PLAYMODE_EXTERNALPOS){ data->playindex = data->loopstart + (int)(data->pointer * (data->loopend - data->loopstart)); } data->playindex += data->speed * data->modespeed; if (data->playmode == LOOP_PLAYMODE_EXTERNALPOS){ if (data->playindex > data->loopend) data->playindex = data->loopstart + ((long)(data->playindex - data->loopstart) % (long)(data->loopend - data->loopstart)); if (data->playindex < data->loopstart) data->playindex = data->loopend - ((long)(data->loopend - data->playindex) % (long)(data->loopend - data->loopstart)); } else if (data->playindex > data->loopend){ if (data->playmode == LOOP_PLAYMODE_BACKFORTH){ /* printf ("bounce dir\n");*/ data->modespeed *= -1; }else if (data->playmode == LOOP_PLAYMODE_LOOP){ data->modespeed = 1; } if ((data->speed * data->modespeed) > .0){ if (data->playmode == LOOP_PLAYMODE_ONCE){ data->playindex = data->loopstart; looperdata_set_playing(data,0); } else data->playindex += data->loopstart - data->loopend; }else{ data->playindex = data->loopend; } /* printf ("wrap around forward\n");*/ } else if (data->playindex < data->loopstart){ if (data->playmode == LOOP_PLAYMODE_BACKFORTH){ data->modespeed *= -1; }else if ((data->playmode == LOOP_PLAYMODE_LOOP) && (data->modespeed < 0)){ data->modespeed = 1; } if ((data->speed * data->modespeed) > .0){ data->playindex = data->loopstart; }else{ if (data->playmode == LOOP_PLAYMODE_ONCE){ data->playindex = data->loopend; looperdata_set_playing(data,0); } else data->playindex += data->loopend - data->loopstart; } } if (data->playmode == LOOP_PLAYMODE_POSITION){ data->playpos = data->loopstart + (data->loopend - data->loopstart) / (data->cm_max - data->cm_min) * (inter4pol_float (data->customplaymode, (data->playindex - data->loopstart) * data->cm_size / (data->loopend - data->loopstart),data->cm_size) - data->cm_min); }else{ data->playpos = data->playindex; } } void looperdata_calc_sample_mono(looper_data_t* data, float* L){ int i; float vol = 1.; double pos, ipos; if (data->ngrains < 1){ /* single playhead */ pos = data->playpos; *L = buffer_readsample_interpolated(data->buf,1,pos, data->buffer_group); }else{ /* granular playhead(s) */ *L = .0; for (i = 0; i < data->ngrains; i++){ pos = grain_inc(data,i); if (*(data->grainsactive + i)){ if (*(data->grainindexes + i) < *(data->grainfadelengths + i)) vol = (float)*(data->grainindexes + i) / (float)*(data->grainfadelengths + i); else if ( (ipos = (*(data->grainsizes + i) - *(data->grainindexes + i))) < *(data->grainfadelengths + i)) vol = ipos / (float)*(data->grainfadelengths + i); else vol = 1.; vol *= data->grainmixfactor * *(data->grainpitchvolumes + i); *L += buffer_readsample_interpolated(data->buf,1,pos, data->buffer_group) * vol * *(data->grainpansL); } } } /* clickmode ?: */ if (data->clickmode_buf){ pos = (float)(data->playpos - data->loopstart) / data->speed; if (pos < buffer_get_size(data->clickmode_buf)){ *L += buffer_readsample_interpolated(data->clickmode_buf,1,pos,0); } } if (data->playmode == LOOP_PLAYMODE_SINE){ data->modespeed = sin((data->playpos - data->loopstart) * PI / (data->loopend - data->loopstart)) * 1.5 + .5; }else if (data->playmode == LOOP_PLAYMODE_CUSTOMSPEED){ data->modespeed = inter4pol_float(data->customplaymode, (float)(data->playpos - data->loopstart) * (float)data->cm_size / (float)(data->loopend - data->loopstart),data->cm_size); }else if (data->playmode == LOOP_PLAYMODE_EXTERNALPOS){ data->playindex = data->loopstart + (int)(data->pointer * (data->loopend - data->loopstart)); } data->playindex += data->speed * data->modespeed; if (data->playmode == LOOP_PLAYMODE_EXTERNALPOS){ if (data->playindex > data->loopend) data->playindex = data->loopstart + ((long)(data->playindex - data->loopstart) % (long)(data->loopend - data->loopstart)); if (data->playindex < data->loopstart) data->playindex = data->loopend - ((long)(data->loopend - data->playindex) % (long)(data->loopend - data->loopstart)); } else if (data->playindex > data->loopend){ if (data->playmode == LOOP_PLAYMODE_BACKFORTH){ /* printf ("bounce dir\n");*/ data->modespeed *= -1; }else if (data->playmode == LOOP_PLAYMODE_LOOP){ data->modespeed = 1; } if ((data->speed * data->modespeed) > .0){ if (data->playmode == LOOP_PLAYMODE_ONCE){ data->playindex = data->loopstart; looperdata_set_playing(data,0); } else data->playindex += data->loopstart - data->loopend; }else{ data->playindex = data->loopend; } /* printf ("wrap around forward\n");*/ } else if (data->playindex < data->loopstart){ if (data->playmode == LOOP_PLAYMODE_BACKFORTH){ data->modespeed *= -1; }else if ((data->playmode == LOOP_PLAYMODE_LOOP) && (data->modespeed < 0)){ data->modespeed = 1; } if ((data->speed * data->modespeed) > .0){ data->playindex = data->loopstart; }else{ if (data->playmode == LOOP_PLAYMODE_ONCE){ data->playindex = data->loopend; looperdata_set_playing(data,0); } else data->playindex += data->loopend - data->loopstart; } } if (data->playmode == LOOP_PLAYMODE_POSITION){ data->playpos = data->loopstart + (data->loopend - data->loopstart) / (data->cm_max - data->cm_min) * (inter4pol_float (data->customplaymode, (data->playindex - data->loopstart) * data->cm_size / (data->loopend - data->loopstart),data->cm_size) - data->cm_min); }else{ data->playpos = data->playindex; } } void looperdata_calc_sampleblock (looper_data_t* data, long size, float* Lbuf, float* Rbuf, float* Pbuf, int do_play, int do_rec){ long l; long rp; double pp; if (!data->buf) return; pp = data->playpos; rp = data->recpos; if ((size <= (data->recend - data->recstart) || !data->isrecording) && 0 && /* this part is broken, use the single sample copy mode instead */ (buffer_get_sampleratefactor(data->buf, data->samplerate) == 1.0)){ /* LATER: include rec-threshold here when reactivating blockwise operation */ if (data->isrecording && do_rec){ /* same result for l++ mode */ looperdata_write_sampleblock(data, size, Lbuf, Rbuf); } if (data->isplaying && do_play){ if (buffer_get_channels(data->buf) > 1){ if (data->panswing){ for (l = 0; (l < size) && (data->isplaying); l++){ data->pointer = *(Pbuf + l); looperdata_calc_sample_stereo (data, (Lbuf + l), (Rbuf + l)); *(Pbuf + l) = (data->playpos - (float)data->loopstart) / (float)(data->loopend - (float)data->loopstart); looperdata_calc_pan(data); *(Lbuf + l) *= data->Lfact; *(Rbuf + l) *= data->Rfact; } } else { /* no panswing: */ for (l = 0; (l < size) && (data->isplaying); l++){ data->pointer = *(Pbuf + l); looperdata_calc_sample_stereo (data, (Lbuf + l), (Rbuf + l)); *(Pbuf + l) = (data->playpos - (float)data->loopstart) / (float)(data->loopend - (float)data->loopstart); *(Lbuf + l) *= data->Lfact; *(Rbuf + l) *= data->Rfact; } } /* end if panswing */ } else { /* mono: */ for (l = 0; (l < size) && (data->isplaying); l++){ data->pointer = *(Pbuf + l); looperdata_calc_sample_mono (data, (Lbuf + l)); *(Pbuf + l) = (data->playpos - (float)data->loopstart) / (float)(data->loopend - (float)data->loopstart); } if (data->panswing){ for (l = 0;l < size;l++){ looperdata_calc_pan(data); *(Rbuf + l) = *(Lbuf + l) * data->Rfact; *(Lbuf + l) *= data->Lfact; } } else { for (l = 0;l < size;l++){ *(Lbuf + l) *= data->Lfact; *(Rbuf + l) = *(Lbuf + l); } } } /* end if stereo/mono */ } } else { /* else have to work sample by sample */ if (data->thresholdmode){ /* check recording thresholds: */ double max = 0.; /* write new data to ringbuffer first:*/ for (l = 0; l < size ; l++){ if (buffer_get_channels(data->buf) > 1){ if (fabs(*(Lbuf + l)) > fabs(*(Rbuf + l))) *(data->threshring + data->threshringptr) = fabs(*(Lbuf + l)); else *(data->threshring + data->threshringptr) = fabs(*(Rbuf + l)); } else *(data->threshring + data->threshringptr) = fabs(*(Lbuf + l)); if (++data->threshringptr >= data->threshringsize) data->threshringptr = 0; } /* check ringbuffer for maximum: */ for (l = 0; l < data->threshringsize ; l++){ if (*(data->threshring + l) > max) max = *(data->threshring + l); } if (max < data->low_threshold){ data->thresholdstate = THRESHOLDSTATE_LOW; } else if (max > data->high_threshold) { data->thresholdstate = THRESHOLDSTATE_HIGH; } } if ((buffer_get_sampleratefactor(data->buf, data->samplerate) == 1.0) && data->isrecording && !data->isplaying && do_rec && data->thresholdstate){ /* copy at once anyway */ looperdata_write_sampleblock(data, size, Lbuf, Rbuf); } else { if (buffer_get_channels(data->buf) > 1){ for (l = 0; l < size ; l++){ if (data->isrecording && do_rec && data->thresholdstate) looperdata_write_sample (data, (Lbuf + l), (Rbuf + l)); if (data->isplaying && do_play){ if (data->panswing){ data->pointer = *(Pbuf + l); looperdata_calc_sample_stereo (data, (Lbuf + l), (Rbuf + l)); *(Pbuf + l) = (data->playpos - (float)data->loopstart) / (float)(data->loopend - (float)data->loopstart); looperdata_calc_pan(data); *(Lbuf + l) *= data->Lfact; *(Rbuf + l) *= data->Rfact; } else { /* no panswing: */ data->pointer = *(Pbuf + l); looperdata_calc_sample_stereo (data, (Lbuf + l), (Rbuf + l)); *(Pbuf + l) = (data->playpos - (float)data->loopstart) / (float)(data->loopend - (float)data->loopstart); *(Lbuf + l) *= data->Lfact; *(Rbuf + l) *= data->Rfact; } /* end if panswing */ } /* end if recording */ } } else { /* mono: */ for (l = 0; l < size; l++){ if (data->isrecording && do_rec && data->thresholdstate) looperdata_write_sample (data, (Lbuf + l), NULL); if (data->isplaying && do_play){ if (data->panswing){ data->pointer = *(Pbuf + l); looperdata_calc_sample_mono (data, (Lbuf + l)); *(Pbuf + l) = (data->playpos - (float)data->loopstart) / (float)(data->loopend - (float)data->loopstart); *(Rbuf + l) = *(Lbuf + l); looperdata_calc_pan(data); *(Lbuf + l) *= data->Lfact; *(Rbuf + l) *= data->Rfact; } else { data->pointer = *(Pbuf + l); looperdata_calc_sample_mono (data, (Lbuf + l)); *(Pbuf + l) = (data->playpos - (float)data->loopstart) / (float)(data->loopend - (float)data->loopstart); *(Rbuf + l) = *(Lbuf + l); *(Lbuf + l) *= data->Lfact; *(Rbuf + l) *= data->Rfact; }/* end if panswing */ } /* end if playing */ } } /* end if mono */ } /* end if playing */ } /* end if size < loopsize */ if (data->isplaying && do_play){ /* reverb?: */ if (data->reverblength > 0){ for (l = 0;l < size;l++){ if (++data->revpos >= data->reverblength) data->revpos = 0; *(Lbuf + l) += buffer_readsample_interpolated(data->reverb, 1, data->revpos, 0); buffer_writesample(data->reverb, 1, data->revpos, 0, *(Lbuf + l) * data->feedback); *(Rbuf + l) += buffer_readsample_interpolated(data->reverb, 1, data->revpos, 0); buffer_writesample(data->reverb, 1, data->revpos, 0, *(Rbuf + l) * data->feedback); } } if (data->limiter){ for (l = 0;l < size;l++){ if (*(Lbuf + l) > data->limknee) *(Lbuf + l) = data->limit - data->limconst / *(Lbuf + l); else if (*(Lbuf + l) < -data->limknee) *(Lbuf + l) = -data->limit - data->limconst / *(Lbuf + l); if (*(Rbuf + l) > data->limknee) *(Rbuf + l) = data->limit - data->limconst / *(Rbuf + l); else if (*(Rbuf + l) < -data->limknee) *(Rbuf + l) = -data->limit - data->limconst / *(Rbuf + l); } }/* end limiter */ for (l = 0;l < size;l++){ if (data->outmaxL < *(Lbuf + l)){data->outmaxL = *(Lbuf + l);} if (data->outmaxR < *(Rbuf + l)){data->outmaxR = *(Rbuf + l);} } /* end max */ /* printf ("j:%ld, %ld after: rcpos:%ld(%ld, %ld), playpos: %.2lf(%.2lf, %.2lf)\n",size, data->recend, data->recpos, rp, (data->recpos - rp), data->playpos, pp, (data->playpos - pp)); */ } /* end if active */ } kluppe-0.6.14/src/common/serialio.h0000644000175000017500000000077710316237215016466 0ustar dieterdieter#ifndef __SERIALIO_H__ #define __SERIALIO_H__ #include #include #define SERIALIO_FOOT 1 typedef struct _serialio_data { int fd; } serialio_data_t; serialio_data_t* serialio_new(); int serialio_open(serialio_data_t* serialio); void serialio_close(serialio_data_t* serialio); int serialio_set_footled (serialio_data_t* serialio, int led); int serialio_toggle_footled (serialio_data_t* serialio); int serialio_get_foot (serialio_data_t* serialio); #endif /* __SERIALIO_H__ */ kluppe-0.6.14/src/common/tranzport.c0000644000175000017500000001513510417446322016712 0ustar dieterdieter/* * transport.c * tranzport interface for klopfer & kluppe * based on transport.c by arthur@artcmusic.com */ #ifdef HAVE_USB #include #include #include #include #include #include "tranzport.h" #define RINGBUFFER_MAX 100 int tranzport_poll(tranzport_t *z) { uint8_t buf[8]; int val; uint32_t newbuttons = 0; memset(buf, 0, 8); val = usb_interrupt_read(z->udev, TRANZPORT_READ_ENDPOINT, (char*)(&buf), 8, z->polltimeout); if (val < 0) return val; if (val != 8) return -1; /* printf("read: %02x %02x %02x %02x %02x %02x %02x %02x\n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);*/ z->status = buf[1]; newbuttons |= buf[2] << 24; newbuttons |= buf[3] << 16; newbuttons |= buf[4] << 8; newbuttons |= buf[5]; z->buttondiff = z->buttons ^ newbuttons; // XOR z->buttons = newbuttons; z->datawheel = buf[6]; return 0; } static int tranzport_write_core(tranzport_t *z, uint8_t *cmd){ int val; val = usb_interrupt_write(z->udev, TRANZPORT_WRITE_ENDPOINT, (char*)cmd, 8, z->timeout); if (val < 0) return val; if (val != 8) return -1; return 0; } static int tranzport_write_queued (tranzport_t *z){ /* try to send lcd data */ uint8_t cmd[8]; int count = -1; int realcount = 0; while (count < 7){ count++; if (z->led_dirty[z->led_ptr]){ cmd[0] = 0x00; cmd[1] = 0x00; cmd[2] = z->led_ptr; if (z->leds[z->led_ptr]) cmd[3] = 0x01; else cmd[3] = 0x00; cmd[4] = 0x00; cmd[5] = 0x00; cmd[6] = 0x00; cmd[7] = 0x00; if (tranzport_write_core(z, cmd)){ /* printf ("short write in led (%d,%d)\n",count,realcount);*/ return realcount; } z->led_dirty[z->led_ptr] = 0; realcount++; } z->led_ptr = ++z->led_ptr % 7; } count = -1; while (count < 10){ count++; if (z->lcd_dirty[z->lcd_ptr]){ cmd[0] = 0x00; cmd[1] = 0x01; cmd[2] = z->lcd_ptr; cmd[3] = z->lcd[(z->lcd_ptr * 4)]; cmd[4] = z->lcd[(z->lcd_ptr * 4) + 1]; cmd[5] = z->lcd[(z->lcd_ptr * 4) + 2]; cmd[6] = z->lcd[(z->lcd_ptr * 4) + 3]; cmd[7] = 0x00; if (tranzport_write_core(z, cmd)){ /* printf ("short write in lcd (%d,%d)\n",count,realcount);*/ return realcount; } z->lcd_dirty[z->lcd_ptr] = 0; realcount++; } z->lcd_ptr = ++z->lcd_ptr % 10; } return realcount; } int tranzport_do_io (tranzport_t *z){ int poll = tranzport_poll(z); tranzport_write_queued (z); return poll; } static tranzport_t *open_tranzport_core(struct usb_device *dev){ tranzport_t *z; int val; z = malloc(sizeof(tranzport_t)); if (!z){ printf("not enough memory"); return NULL; } memset(z, 0, sizeof(tranzport_t)); z->dev = dev; z->udev = usb_open(z->dev); if (!z->udev){ printf("unable to open tranzport"); return NULL; } usb_reset (z->udev); val = usb_claim_interface(z->udev, 0); if (val < 0){ printf("unable to claim tranzport"); return NULL; } z->lcd = calloc(41,sizeof(char)); /* memset(z->lcd,0,sizeof(char) * 41);*/ memset(z->lcd_dirty,0,sizeof(int) * 10); printf ("reset\n"); memset(z->leds,0,sizeof(int) * 7); memset(z->led_dirty,0,sizeof(int) * 7); z->lcd_ptr = 0; z->led_ptr = 0; z->status = 0; z->buttons = 0; z->buttondiff = 0; z->datawheel = 0; z->timeout = 15; z->polltimeout = 15; return z; } int tranzport_set_nativemode(tranzport_t *z){ uint8_t nativemodemessage[8]; nativemodemessage[0] = 0xf0; nativemodemessage[1] = 0x00; nativemodemessage[2] = 0x01; nativemodemessage[3] = 0x40; nativemodemessage[4] = 0x10; nativemodemessage[5] = 0x01; nativemodemessage[6] = 0x00; nativemodemessage[7] = 0xf7; return tranzport_write_core(z, nativemodemessage); } tranzport_t *tranzport_new() { struct usb_bus *bus; struct usb_device *dev; usb_init(); usb_find_busses(); usb_find_devices(); for(bus=usb_busses; bus; bus=bus->next) { for(dev=bus->devices; dev; dev=dev->next) { if (dev->descriptor.idVendor != TRANZPORT_VENDORID) continue; if (dev->descriptor.idProduct != TRANZPORT_PRODUCTID) continue; // printf ("found\n"); return open_tranzport_core(dev); } } printf("can't find tranzport"); return NULL; } void tranzport_set_timeout(tranzport_t *z, int timeout){ if ((timeout < 100) && (timeout > 0)) z->timeout = timeout; } void tranzport_set_polltimeout(tranzport_t *z, int timeout){ if ((timeout < 100) && (timeout > 0)) z->polltimeout = timeout; } uint8_t tranzport_get_status(tranzport_t *z){ return z->status; } void close_tranzport(tranzport_t *z) { int val; val = usb_release_interface(z->udev, 0); if (val < 0) printf("unable to release tranzport"); val = usb_close(z->udev); if (val < 0) printf("unable to close tranzport"); free(z); } /* ***************** LEDs *************************************/ int tranzport_set_led(tranzport_t *z, uint8_t led, int status){ if (led > 7) return -1; z->leds[led] = status; z->led_dirty[led] = 1; return 0; } int tranzport_get_led(tranzport_t *z, uint8_t led){ if (led > 7) return -1; return z->leds[led]; } void tranzport_clear_leds(tranzport_t *z){ tranzport_set_led(z, TRANZPORT_LIGHT_RECORD, 0); tranzport_set_led(z, TRANZPORT_LIGHT_TRACKREC, 0); tranzport_set_led(z, TRANZPORT_LIGHT_TRACKMUTE, 0); tranzport_set_led(z, TRANZPORT_LIGHT_TRACKSOLO, 0); tranzport_set_led(z, TRANZPORT_LIGHT_ANYSOLO, 0); tranzport_set_led(z, TRANZPORT_LIGHT_LOOP, 0); tranzport_set_led(z, TRANZPORT_LIGHT_PUNCH, 0); } int tranzport_pressed(tranzport_t *z, int button){ if ((z->buttons & button) && (z->buttondiff & button)) return 1; else return 0; } int tranzport_buttonstate (tranzport_t *z, int button){ if (z->buttons & button) return 1; else return 0; } int tranzport_get_wheel(tranzport_t *z){ int w = z->datawheel; if (w > 128) w -= 256; z->datawheel = 0; return w; } /************************* LCD FUNCTIONS: ****************************/ void tranzport_lcd_readcell(tranzport_t *z, uint8_t cell, char *text){ strncpy(text,(char*)(z->lcd + (cell * 4)),4); } int tranzport_clear_lcd(tranzport_t *z){ memset(z->lcd,0x20,20); memset(z->lcd_dirty,1,10); return 0; } int tranzport_write_lcd (tranzport_t *z, const char* txt, int x, int y){ int i = 0; int j; int length = strlen(txt); if (y > 1) y = 1; if (y < 0) y = 0; if (x < 0) x = 0; if ((length + x) > 20) length = 20 - x; for (i = 0; i < length;i++){ j = x + i + (y * 20); if ((j < 40) && (j >= 0)){ /* printf ("vor copy\n");*/ z->lcd[j] = txt[i]; z->lcd_dirty[(int)(j / 4)] = 1; /* printf ("j:%d,txt[i]:%c\n",j,(int)txt[i]);*/ } } return 0; } #endif /* HAVE_USB */ kluppe-0.6.14/src/common/midi.c0000644000175000017500000001172611156442307015573 0ustar dieterdieter/* midi code is partly taken from robert ham's jack rack */ #ifdef HAVE_ALSA #include #include #include #include #include #include #include "midi.h" #include "looperdata.h" static void * midi_run (void * data); midi_info_t* midi_info_new (speciallist_t* looperdatalist) { midi_info_t* minfo; minfo = malloc (sizeof (midi_info_t)); minfo->seq = NULL; minfo->quit = 0; minfo->looperdatalist = looperdatalist; printf ("creating midi thread \n"); pthread_create (&minfo->midithread, NULL, midi_run, minfo); return minfo; } void midi_info_destroy (midi_info_t* minfo){ minfo->quit = 1; pthread_join (minfo->midithread, NULL); free(minfo); } snd_seq_t *open_seq(const char* name) { snd_seq_t *seq_handle; int portid; if (snd_seq_open(&seq_handle, "hw", SND_SEQ_OPEN_DUPLEX, 0) < 0) { fprintf(stderr, "Error opening ALSA sequencer.\n"); return NULL; // exit(1); } snd_seq_set_client_name(seq_handle, name); if ((portid = snd_seq_create_simple_port(seq_handle, "midi_input", SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE, SND_SEQ_PORT_TYPE_APPLICATION)) < 0) { fprintf(stderr, "Error creating sequencer port.\n"); return NULL; // exit(1); } return(seq_handle); } static double midi2pitch (int note){ /* double pitch = pow(2.,(double)(note - 57)/12.); */ double pitch = pow(2.,(double)(note - 48.)/12.); return pitch; } void midi_action(midi_info_t *minfo) { snd_seq_event_t *ev; looper_data_t *ld; double note = 0.0; double vol = 0.0; do { snd_seq_event_input(minfo->seq, &ev); /* printf ("event: type %d\n",ev->type);*/ switch (ev->type) { case SND_SEQ_EVENT_CONTROLLER: /* fprintf(stderr, "Control event on Channel %2d: %d, %5d \n", ev->data.control.channel, ev->data.control.param, ev->data.control.value); */ break; /* PITCHBEND */ case SND_SEQ_EVENT_PITCHBEND: /* fprintf(stderr, "Pitchbender event on Channel %2d: %5d \n", ev->data.control.channel, ev->data.control.value); */ vol = 1. + (double)ev->data.control.value / 16384.; /* bendrange = -8192 - 8192 */ ld = speciallist_get_first_nolock (minfo->looperdatalist); while(ld){ int mc = looperdata_get_midichannel (ld); if ((mc < 0) || (mc == ev->data.control.channel)){ looperdata_set_grainpitchbend (ld, vol); } ld = speciallist_get_next_nolock (minfo->looperdatalist, ld); } break; case SND_SEQ_EVENT_NOTEON: note = midi2pitch(ev->data.note.note); /* printf ("note %d becomes pitch %f\n",ev->data.note.note, note);*/ vol = (double)ev->data.note.velocity / 127.; /* fprintf(stderr, "Note On event on Channel %2d: %d (%lf) (v:%d/%lf) \n", ev->data.control.channel, ev->data.note.note,note, ev->data.note.velocity,vol); */ ld = speciallist_get_first_nolock (minfo->looperdatalist); while(ld){ int mc = looperdata_get_midichannel (ld); if ((mc < 0) || (mc == ev->data.control.channel)){ looperdata_set_grainpitchtablevalue (ld, note, vol); } ld = speciallist_get_next_nolock (minfo->looperdatalist, ld); } break; case SND_SEQ_EVENT_NOTEOFF: note = midi2pitch(ev->data.note.note); /* fprintf(stderr, "Note Off event on Channel %2d: %d (%lf) (0) \n", ev->data.control.channel, ev->data.note.note,note); */ ld = speciallist_get_first_nolock (minfo->looperdatalist); while(ld){ int mc = looperdata_get_midichannel (ld); if ((mc < 0) || (mc == ev->data.control.channel)){ looperdata_set_grainpitchtablevalue (ld, note, 0.); } ld = speciallist_get_next_nolock (minfo->looperdatalist, ld); } break; } snd_seq_free_event(ev); } while (snd_seq_event_input_pending(minfo->seq, 0) > 0); } static void midi_process (midi_info_t *minfo){ /* printf ("poll\n");*/ if (poll(minfo->pfds, minfo->seq_nfds, 40) > 0) { /* printf ("action\n");*/ midi_action(minfo); } } static void* midi_run (void * data) { midi_info_t* minfo = (midi_info_t*) data; /* this is dealt with by the jack thread */ signal (SIGHUP, SIG_IGN); minfo->seq = open_seq("kluppe"); if (!minfo->seq) return NULL; minfo->seq_nfds = snd_seq_poll_descriptors_count(minfo->seq, POLLIN); minfo->pfds = (struct pollfd*)alloca(minfo->seq_nfds * sizeof(struct pollfd)); snd_seq_poll_descriptors(minfo->seq, minfo->pfds, minfo->seq_nfds, POLLIN); /* http://howtos.linux.com/howtos/MIDI-HOWTO-9.shtml */ while (!minfo->quit){ midi_process (minfo); } free (minfo->pfds); return NULL; } #endif /* HAVE_ALSA */ kluppe-0.6.14/src/common/tranzport.h0000644000175000017500000000552210417027071016712 0ustar dieterdieter/* * partly taken from * tranzport 0.1 * oct 18, 2005 * arthur@artcmusic.com */ #ifdef HAVE_USB #ifndef __TRANZPORT_H__ #define __TRANZPORT_H__ #include #define TRANZPORT_VENDORID 0x165b #define TRANZPORT_PRODUCTID 0x8101 #define TRANZPORT_READ_ENDPOINT 0x81 #define TRANZPORT_WRITE_ENDPOINT 0x02 enum { TRANZPORT_LIGHT_RECORD = 0, TRANZPORT_LIGHT_TRACKREC, TRANZPORT_LIGHT_TRACKMUTE, TRANZPORT_LIGHT_TRACKSOLO, TRANZPORT_LIGHT_ANYSOLO, TRANZPORT_LIGHT_LOOP, TRANZPORT_LIGHT_PUNCH }; #define TRANZPORT_BUTTON_RECORD 0x00000100 #define TRANZPORT_BUTTON_NEXT 0x00000200 #define TRANZPORT_BUTTON_TRACKSOLO 0x00000400 #define TRANZPORT_FOOTSWITCH 0x00001000 #define TRANZPORT_BUTTON_BATTERY 0x00004000 #define TRANZPORT_BUTTON_BACKLIGHT 0x00008000 #define TRANZPORT_BUTTON_STOP 0x00010000 #define TRANZPORT_BUTTON_PREV 0x00020000 #define TRANZPORT_BUTTON_TRACKREC 0x00040000 #define TRANZPORT_BUTTON_LOOP 0x00080000 #define TRANZPORT_BUTTON_PLAY 0x00100000 #define TRANZPORT_BUTTON_ADD 0x00200000 #define TRANZPORT_BUTTON_TRACKMUTE 0x00400000 #define TRANZPORT_BUTTON_PUNCH 0x00800000 #define TRANZPORT_BUTTON_REWIND 0x01000000 #define TRANZPORT_BUTTON_IN 0x02000000 #define TRANZPORT_BUTTON_TRACKLEFT 0x04000000 #define TRANZPORT_BUTTON_SHIFT 0x08000000 #define TRANZPORT_BUTTON_FASTFORWARD 0x10000000 #define TRANZPORT_BUTTON_OUT 0x20000000 #define TRANZPORT_BUTTON_TRACKRIGHT 0x40000000 #define TRANZPORT_BUTTON_UNDO 0x80000000 #define TRANZPORT_STATUS_OFFLINE 0xff #define TRANZPORT_STATUS_ONLINE 0x01 typedef struct _tranzport { struct usb_device *dev; usb_dev_handle *udev; uint8_t status; uint32_t buttons; uint32_t buttondiff; uint8_t datawheel; int polltimeout; int timeout; char* lcd; int lcd_dirty[10]; int lcd_ptr; int leds[7]; int led_dirty[7]; int led_ptr; } tranzport_t; tranzport_t *tranzport_new(); void close_tranzport(tranzport_t *z); /*int tranzport_write_core(tranzport_t *z, uint8_t *cmd);*/ int tranzport_poll(tranzport_t *z); int tranzport_do_io (tranzport_t *z); void tranzport_set_timeout(tranzport_t *z, int timeout); void tranzport_set_polltimeout(tranzport_t *z, int timeout); int tranzport_set_nativemode(tranzport_t *z); uint8_t tranzport_get_status(tranzport_t *z); int tranzport_pressed(tranzport_t *z, int button); int tranzport_buttonstate (tranzport_t *z, int button); int tranzport_get_wheel(tranzport_t *z); int tranzport_clear_lcd (tranzport_t *z); int tranzport_write_lcd (tranzport_t *z, const char* txt, int x, int y); int tranzport_set_led(tranzport_t *z, uint8_t led,int status); int tranzport_get_led(tranzport_t *z, uint8_t led); void tranzport_clear_leds(tranzport_t *z); #endif /* end ifndef TRANZPORT.H */ #endif /* HAVE_USB */ kluppe-0.6.14/src/common/buffer.c0000644000175000017500000007036611156445316016132 0ustar dieterdieter/* creation and destruction of buffers */ #include #include #include #include #include #include #include #include #include "interpol.h" #include "speciallist.h" #include "buffer.h" #define MAXPATHLEN 256 const long ds_buffersize = 44100; void buffer_lock(buffer_info_t* buf){ pthread_mutex_lock (&buf->buffermutex); } void buffer_unlock(buffer_info_t* buf){ pthread_mutex_unlock (&buf->buffermutex); } static int strnflst(const char *s1,const char *s2,int n){ /* sucht s2 in s1 bis maximal s1[n]*/ int i; int len2 = strlen(s2); int found = -1; if (n > strlen(s1)){n = strlen(s1);} if (n < 0){ n = 0;} for (i=0;iid = id; buf->type = BUFFER_TYPE_MEMORY; buf->status = BUFFER_STATUS_NEW; buf->parent_samplerate = rate; buf->samplerate_factor = 1.; buf->group_max = -1; buf->pending = 0; buf->error = 0; buf->percent_filled = 0.; buf->normalized = 0; buf->snap_offset = 0; buf->volume_factor = 1.; buf->filename= NULL; buf->shortname = NULL; buf->chunk_list = NULL; // printf ("buffer get initial group\n"); buffer_get_group(buf, DS_PRIORITY_NORMAL); pthread_mutex_init (&buf->buffermutex, NULL); return buf; } void buffer_delete_group(buffer_info_t* buf, int gid){ /* int i;*/ if (!buf) return; if (!buf->chunk_list) return; if (buf->group_max < gid) return; if (!buf->chunk_list[gid]) return; /* delete only when DISCSTREAM */ if (gid > 1){ chunkgroup_delete(buf->chunk_list[gid]); buf->chunk_list[gid] = NULL; } /* printf ("deleting group %d from %s -> ",gid, buf->shortname); printf ("state now: "); for (i = 0; i <=buf->group_max; i++){ if (buf->chunk_list[i]) printf ("%d, ",i); } printf ("\n"); */ } int buffer_delete(buffer_info_t* buf){ int i; /* LATER: care for filechunks !*/ for (i = buf->group_max; i > 0; i--) buffer_delete_group(buf, i); /* delete the initial group: */ if (buf->chunk_list[0]) { chunkgroup_delete(buf->chunk_list[0]); buf->chunk_list[0] = NULL; } free (buf->chunk_list); buf->chunk_list = NULL; buf->pending = BUFFER_STATUS_DEAD; if (buf->filename) free (buf->filename); buf->filename = NULL; if (buf->shortname) free (buf->shortname); buf->shortname = NULL; return 0; } int buffer_get_type(buffer_info_t* buf){ if (!buf) return 0; return buf->type; } /* filechunk group funktions: */ void buffer_set_area(buffer_info_t* buf, int group, long start, long end, long bandwith){ if (!buf->chunk_list) return; if (!buf->chunk_list[group]) return; if (start < 0) start = 0; if (start > buffer_get_size(buf)) start = buffer_get_size(buf); if (end < 0) end = 0; if (end > buffer_get_size(buf)) end = buffer_get_size(buf); start = (long)((float)start * buf->samplerate_factor); end = (long)((float)end * buf->samplerate_factor); if (start > end){ long tmp = start; start = end; end = tmp; } /* printf ("area set: %ld - %ld of %ld, bandwidth:%ld\n", start,end, buffer_get_size(buf),bandwith); */ buf->chunk_list[group]->area_start = start; buf->chunk_list[group]->area_end = end; buf->chunk_list[group]->area_bandwith = bandwith; } static int buffer_append_group(buffer_info_t* buf, int priority){ chunk_group_t* group = chunkgroup_new(++buf->group_max, priority); buf->chunk_list = realloc(buf->chunk_list, sizeof(chunk_group_t) * (buf->group_max)); buf->chunk_list[buf->group_max] = group; return buf->group_max; } int buffer_get_group(buffer_info_t* buf, int priority){ if (buf->type == BUFFER_TYPE_DISCSTREAM){ int i = buffer_append_group(buf, priority); buf->chunk_list[i]->priority = priority; return i; }else{ if (buf->chunk_list == NULL){ return buffer_append_group(buf, DS_PRIORITY_NORMAL); } return 0; } } int buffer_get_channels(buffer_info_t* buf){ if (!buf->chunk_list) return 0; if (!buf->chunk_list[0]) return 0; if (!buf->chunk_list[0]->readfc) return 0; return filechunk_get_channels(buf->chunk_list[0]->readfc); } /* feedback functions: */ float buffer_get_sampleratefactor(buffer_info_t* buf, long srate){ if (!buf) return 0; if (!buf->chunk_list) return 0; if (!buf->chunk_list[0]->readfc) return 0; if (buf->type != BUFFER_TYPE_MEMORY) return ((float)filechunk_get_samplerate(buf->chunk_list[0]->readfc) / (float)srate ) ; else return 1.; } void buffer_set_channels(buffer_info_t* buf, int channels){ if (!buf) return; if (!buf->chunk_list[0]) return; if (buf->type != BUFFER_TYPE_MEMORY) return; if (filechunk_get_channels(buf->chunk_list[0]->readfc) == channels) return; /* printf ("%s set channels to %d\n",buf->shortname, channels); */ if ((channels > 0) && (channels < 3)){ int gid; for (gid = 0; gid <= buf->group_max; gid++){ if (buf->chunk_list[gid]){ filechunk_set_channels(buf->chunk_list[gid]->readfc, channels); filechunk_set_channels(buf->chunk_list[gid]->prevfc, channels); filechunk_set_channels(buf->chunk_list[gid]->nextfc, channels); filechunk_set_channels(buf->chunk_list[gid]->wrapfc, channels); } } } } /* not in use: void buffer_set_snap_offset(buffer_info_t* buf, long offset){ if (buf) { if (offset < 0) offset = 0; if (offset > buffer_get_size(buf)) offset = buffer_get_size(buf); buf->snap_offset = offset; } } long buffer_get_snap_offset(buffer_info_t* buf){ if (buf) return buf->snap_offset; return 0; } */ int buffer_get_status(buffer_info_t* buf){ if (!buf) return 0; return buf->status; } long buffer_get_size(buffer_info_t* buf){ if (!buf) return 0; if (!buf->chunk_list) return 0; if (!buf->chunk_list[0]) return 0; if (!buf->chunk_list[0]->readfc) return 0; if (buf->type == BUFFER_TYPE_DISCSTREAM) return (long)((float)filechunk_get_filelength(buf->chunk_list[0]->readfc) / buf->samplerate_factor); else return (long)((float)filechunk_get_length(buf->chunk_list[0]->readfc) / buf->samplerate_factor); } /* long buffer_get_corrected_size(buffer_info_t* buf, long srate){ float f = buffer_get_sampleratefactor(buf,srate); if (!buf->chunk_list) return 0; if (!buf->chunk_list[0]->readfc) return 0; if (buf->type == BUFFER_TYPE_DISCSTREAM) return (long)((float)filechunk_get_filelength(buf->chunk_list[0]->readfc) * f); else return (long)((float)filechunk_get_length(buf->chunk_list[0]->readfc) * f); } */ int is_inside (filechunk_t* fc, long index) { if (filechunk_get_end(fc) < index) return 0; if (filechunk_get_start(fc) > index) return 0; return 1; } int is_inside_done (filechunk_t* fc, long index) { if (filechunk_get_done(fc) < index) return 0; if (filechunk_get_start(fc) > index) return 0; return 1; } static void shift_right(chunk_group_t * cg){ filechunk_t* tempfc = cg->readfc; cg->readfc = cg->nextfc; cg->nextfc = cg->prevfc; cg->prevfc = tempfc; } static void shift_left(chunk_group_t * cg){ filechunk_t* tempfc = cg->readfc; cg->readfc = cg->prevfc; cg->prevfc = cg->nextfc; cg->nextfc = tempfc; } static float valuehelper(filechunk_t* fc, int channel, double index){ if (filechunk_get_priority(fc) == DS_PRIORITY_RELAXED){ struct timeval tv; long l = 0; while (((filechunk_get_done(fc) + filechunk_get_start(fc)) < index) && (l++ < 10 /* was 1000 */)){ /* printf ("sleepwait\n");*/ tv.tv_sec = 0; tv.tv_usec = 10000; /* was 100*/ select(0, NULL, NULL, NULL, &tv); } } if (filechunk_get_length (fc) < 1 ) return 0.0; if (channel == 1){ return inter4pol_float(fc->L, index - filechunk_get_start(fc), filechunk_get_done(fc)); } else { return inter4pol_float(fc->R, index - filechunk_get_start(fc), filechunk_get_done(fc)); } } static long wrapindex (long index, long start, long end){ if ((index >= start) && (index <= end)) return index; /* printf ("start:%ld, end:%ld, index:%ld\n",start,end,index);*/ if (index > end) return start + (index - start) % (end - start); if (index < start) return end - (end - index) % (end - start); return index; } float buffer_readsample_interpolated(buffer_info_t* buf, int channel, double index, int group){ if (!buf) return 0.; if (!buf->chunk_list) return 0; if (!buf->chunk_list[group]) return 0; index *= buf->samplerate_factor; double dindex = index; if (buf->type == BUFFER_TYPE_DISCSTREAM){ if (buf->group_max < group) return 0; if (!buf->chunk_list[group]->readfc){ buf->chunk_list[group]->readfc = filechunk_new(buf->filename); if (buf->type == BUFFER_TYPE_DISCSTREAM){ /* printf ("make new filechunks for %s, group %d\n", buf->shortname, group);*/ buf->chunk_list[group]->nextfc = filechunk_new(buf->filename); buf->chunk_list[group]->prevfc = filechunk_new(buf->filename); buf->chunk_list[group]->wrapfc = filechunk_new(buf->filename); } } if ( is_inside(buf->chunk_list[group]->readfc,index)){ return valuehelper(buf->chunk_list[group]->readfc,channel,index) * buf->volume_factor; }else{ chunk_group_t* cg = buf->chunk_list[group]; /* printf ("not inside index:%lf.0, this=%ld-%ld, next=%ld-%ld, prev=%ld-%ld, wrap=%ld-%ld\n", index, filechunk_get_start(cg->readfc),filechunk_get_end(cg->readfc), filechunk_get_start(cg->nextfc),filechunk_get_end(cg->nextfc), filechunk_get_start(cg->prevfc),filechunk_get_end(cg->prevfc), filechunk_get_start(cg->wrapfc),filechunk_get_end(cg->wrapfc)); */ long goodsize = cg->area_bandwith * 2; if (goodsize < ds_buffersize) goodsize = ds_buffersize; if (!is_inside(cg->readfc,index) && is_inside(cg->nextfc,index) ) { long wi = (long)index - cg->area_bandwith; wi = wrapindex(wi, cg->area_start, cg->area_end ? cg->area_end : filechunk_get_filelength (cg->readfc)); if (is_inside(cg->readfc,wi)){ /* still in acceptable range */ return valuehelper(cg->nextfc,channel,index) * buf->volume_factor; }else{ /* not still in acceptable range */ /* printf ("next index:%.0lf, this=%ld-%ld, next=%ld-%ld, prev=%ld-%ld, wrap=%ld-%ld\n", index, filechunk_get_start(cg->readfc),filechunk_get_end(cg->readfc), filechunk_get_start(cg->nextfc),filechunk_get_end(cg->nextfc), filechunk_get_start(cg->prevfc),filechunk_get_end(cg->prevfc), filechunk_get_start(cg->wrapfc),filechunk_get_end(cg->wrapfc)); */ long s,e; buffer_lock(buf); shift_right(cg); s = filechunk_get_end(cg->readfc) - 5; e = s + goodsize; if (e > filechunk_get_filelength(cg->readfc)) e = filechunk_get_filelength(cg->readfc); if (cg->area_end && (s >= cg->area_end)){ /* printf ("wrap\n");*/ s = cg->area_start; e = s + goodsize; if (e > filechunk_get_filelength(cg->readfc)) e = filechunk_get_filelength(cg->readfc); }else if (cg->area_end && (e >= cg->area_end)){ long ws = cg->area_start; long we = ws + goodsize; if (we > filechunk_get_filelength(cg->readfc)) we = filechunk_get_filelength(cg->readfc); /* printf ("set read\n");*/ filechunk_set(cg->wrapfc,ws, we, cg->priority, group); } /* printf ("set next, start:%ld, area_end:%ld \n",s,cg->area_end);*/ filechunk_set(cg->nextfc,s, e, cg->priority, group); buffer_unlock(buf); return valuehelper(cg->readfc,channel,index) * buf->volume_factor; } }else if ( !is_inside(cg->readfc,index) && is_inside(cg->prevfc,index)) { long wi = (long)index + cg->area_bandwith; wi = wrapindex(wi, cg->area_start, cg->area_end ? cg->area_end : filechunk_get_filelength (cg->readfc)); if (is_inside(cg->readfc, wi)){ /* printf ("still ok\n");*/ return valuehelper(cg->prevfc,channel,index) * buf->volume_factor; }else{ /* not still in acceptable range */ /* printf ("previous\n");*/ long s,e; buffer_lock(buf); shift_left(cg); e = filechunk_get_start(cg->readfc) + 5; s = e - goodsize; if (s < 0) s = 0; if (cg->area_start >= s){ e = cg->area_end; s = e - goodsize; if (s < 0) s = 0; }else if (cg->area_end && (s <= cg->area_end)){ long we = cg->area_end; long ws = we - goodsize; if (ws < 1) ws = 0; filechunk_set(cg->wrapfc, ws, we, cg->priority, group); } filechunk_set(cg->prevfc,s, e, cg->priority, group); buffer_unlock(buf); return valuehelper(cg->readfc,channel,index) * buf->volume_factor; } }else if ( !is_inside(cg->readfc,index) && is_inside_done(cg->wrapfc,index)) { return valuehelper(cg->wrapfc,channel,index) * buf->volume_factor; /* should be more sophisticated here */ }else{ /* printf ("different: index:%.0lf this=%ld-%ld, next=%ld-%ld, prev=%ld-%ld, wrap=%ld-%ld\n", index, filechunk_get_start(cg->readfc),filechunk_get_end(cg->readfc), filechunk_get_start(cg->nextfc),filechunk_get_end(cg->nextfc), filechunk_get_start(cg->prevfc),filechunk_get_end(cg->prevfc), filechunk_get_start(cg->wrapfc),filechunk_get_end(cg->wrapfc)); */ long s,e; s = (long)index - (goodsize / 2); e = (long)index + (goodsize / 2); if (s < 0) s = 0; if (e > filechunk_get_filelength(cg->readfc)) e = filechunk_get_filelength(cg->readfc); buffer_lock(buf); if (cg->priority == DS_PRIORITY_RELAXED) filechunk_set(cg->readfc,s, e, cg->priority, group); else filechunk_set(cg->readfc,s, e, DS_PRIORITY_URGENT, group); s += goodsize; if (s < cg->area_end) e = s + goodsize; else { s = cg->area_start; e = s + goodsize; } filechunk_set(cg->nextfc, s, e, cg->priority, group); s -= goodsize * 2; e = s + goodsize; if (s < cg->area_start){ e = cg->area_end; s -= goodsize; } filechunk_set(cg->prevfc, s, e, cg->priority, group); buffer_unlock(buf); if (cg->priority == DS_PRIORITY_RELAXED) return valuehelper(cg->readfc,channel,index) * buf->volume_factor; /* printf ("sample = zero because cpu = too slow\n");*/ return 0.; } } } else { if (dindex >= (double)buffer_get_size(buf)) return 0; /* LATER: wrap interpolation around loopborders */ /* this is quite expensive: */ if (filechunk_get_length (buf->chunk_list[group]->readfc) < 1) return 0.0; if (channel == 1){ return inter4pol_float(buf->chunk_list[group]->readfc->L, dindex,(double)buffer_get_size(buf) * (double)buf->samplerate_factor) * buf->volume_factor; } else { return inter4pol_float(buf->chunk_list[group]->readfc->R, dindex,(double)buffer_get_size(buf) * (double)buf->samplerate_factor) * buf->volume_factor; } } return 0.; } void buffer_writesample(buffer_info_t* buf, int channel, long index, int group, float sample){ if (!buf) return; if (!buf->chunk_list) return; if (!buf->group_max < group) return; if (!buf->chunk_list[0]->readfc) return; if (buf->type == BUFFER_TYPE_DISCSTREAM) return; /* never write to a discstream */ index *= buf->samplerate_factor; filechunk_write_sample(buf->chunk_list[group]->readfc, channel, index, sample); } void buffer_write_sampleblock(buffer_info_t* buf, long index, long size, int group, float* Lbuf, float* Rbuf){ if (!buf) return; if (!buf->chunk_list) return; if (!buf->group_max < group) return; if (!buf->chunk_list[0]->readfc) return; if (buf->type == BUFFER_TYPE_DISCSTREAM) return; /* never write to a discstream */ index *= buf->samplerate_factor; filechunk_write_sampleblock(buf->chunk_list[group]->readfc, index, size, Lbuf, Rbuf); } float buffer_analyze(buffer_info_t* buf, int gid, long start,long end){ // int group = gid; struct timeval tv; float val = .0; float max = .0; long l; int group; if (!buf) return 0.; if (!buf->chunk_list) return 0; if (buf->type != BUFFER_TYPE_DISCSTREAM) group = 0; group = buffer_get_group (buf, DS_PRIORITY_RELAXED); buffer_set_area(buf, group, start, end, 32767); /* start = (long)((float)start * buf->samplerate_factor); end = (long)((float)end * buf->samplerate_factor); */ if (end < 1) { end = buffer_get_size(buf);} if (start < 0) { start = 0; } if (end < start) { end = buffer_get_size(buf);} if (start > buffer_get_size(buf)) { start = 0; } if (end > buffer_get_size(buf)) { end = buffer_get_size(buf); } /* printf ("analyze from %ld to %ld\n",start,end);*/ for (l=start; l <= end;l++){ val = fabs(buffer_readsample_interpolated(buf,1,l,group) / buf->volume_factor); if (val > max) max = val; if (buffer_get_channels(buf) > 1){ val = fabs(buffer_readsample_interpolated(buf,2,(float)l,group) / buf->volume_factor); if (val > max) max = val; } if (!(l % 1000000)){ /* printf ("normalize:%ld\n",l);*/ tv.tv_sec = 0; tv.tv_usec = 100; select(0, NULL, NULL, NULL, &tv); } } buffer_delete_group(buf, group); // printf ("max:%f\n",max); return max; } void buffer_normalize(buffer_info_t* buf, float factor, long start, long end){ /* normalze all if end < start or end == 0 */ long l; struct timeval tv; float val; int group; if (!buf) return; if (!buf->chunk_list) return; if (buf->type == BUFFER_TYPE_DISCSTREAM) return; group = buffer_get_group (buf, DS_PRIORITY_RELAXED); buffer_set_area(buf, group, start, end, 32767); /* start = (long)((float)start * buf->samplerate_factor); end = (long)((float)end * buf->samplerate_factor); */ if (start < 0) { start = 0; } if (!(end > start)) { end = buffer_get_size(buf);} if (start > buffer_get_size(buf)) { start = 0; } if (end > buffer_get_size(buf)) { end = buffer_get_size(buf); } buffer_lock(buf); for (l = start; l <= end; l++){ val = buffer_readsample_interpolated(buf,1,(float)l,group) * factor; buffer_writesample(buf,1,(float)l,0,val); if (buffer_get_channels(buf) > 1){ val = buffer_readsample_interpolated(buf,2,(float)l,group) * factor; buffer_writesample(buf,2,(float)l,group,val); } if (!(l % 100000)){ tv.tv_sec = 0; tv.tv_usec = 1000; buffer_unlock(buf); select(0, NULL, NULL, NULL, &tv); buffer_lock(buf); } } buf->normalized = 1; /* printf ("%s normalized:%d\n",buf->shortname, buf->normalized);*/ buffer_unlock(buf); buffer_delete_group (buf, group); } void buffer_set_volume_factor(buffer_info_t* buf, float factor){ if (!buf) return; buffer_lock(buf); buf->volume_factor = factor; buf->normalized = 1; buffer_unlock(buf); } float buffer_get_volume_factor(buffer_info_t* buf){ if (buf) return buf->volume_factor; return 0.; } void buffer_set_filename(buffer_info_t* buf, char* name){ buf->filename = (char*) realloc(buf->filename,sizeof(char) * strlen(name) + 1); strcpy(buf->filename,name); return; } void buffer_set_shortname(buffer_info_t* buf, char* name){ buf->shortname = (char*) realloc(buf->shortname,sizeof(char) * strlen(name) + 1); strcpy(buf->shortname,name); return; } char* buffer_get_shortname(buffer_info_t* buf){ if (!buf) return "no buffer"; if (!buf->shortname) return "no name"; return buf->shortname; } static filechunk_t* buffer_order_filechunk(buffer_info_t* buf, long start, long end, int priority, int group){ filechunk_t* fc; if (buf->filename) fc = filechunk_new(buf->filename); else fc = filechunk_new(NULL); if (!fc){ fprintf(stderr, "could not open filechunk for reading!\n"); return NULL; } if (start > filechunk_get_filelength(fc)){ fprintf (stderr,"wrong start - not creating filechunk\n"); filechunk_delete(fc); return NULL; } if (end < 0) end = filechunk_get_length(fc); if (!filechunk_set(fc, start, end, priority, group)){ filechunk_delete(fc); return NULL; } return fc; } void buffer_resize(buffer_info_t* buf, long new_size){ filechunk_t* fc; if (buf->type == BUFFER_TYPE_DISCSTREAM){ return; /* not possible for discstreams */ }else{ if (!buf->chunk_list[0]->readfc){ fc = buffer_order_filechunk(buf, 0, new_size, DS_PRIORITY_NONE,0); buf->chunk_list[0]->readfc = fc; }else { filechunk_set(buf->chunk_list[0]->readfc,0,new_size,DS_PRIORITY_NONE,0); } /* buf->pending = BUFFER_STATUS_READY;*/ } } void buffer_open_discstream (buffer_info_t* buf, char* fname, long srate){ int lp; /* long s,l; */ filechunk_t* fc; char* sn; float min,sec; buf->type = BUFFER_TYPE_DISCSTREAM; buf->filename = (char*) malloc (sizeof(char) * (strlen(fname) + 1)); strcpy(buf->filename,fname); if ((fc = buffer_order_filechunk(buf,0,1,DS_PRIORITY_URGENT,0))){ lp = strnflst (fname,"/",-1); sn = calloc(sizeof(char), (strlen(fname) - lp + 16)); sec = (float)filechunk_get_filelength(fc) / (float)filechunk_get_samplerate (fc); min = (int)(sec / 60.); sec -= min * 60; snprintf (sn,strlen(fname) - lp + 16,"DS: %s (%0.0f:%02.0f)",(char*)(buf->filename + lp + 1),min,sec); buffer_set_shortname(buf,sn); buf->chunk_list[0]->readfc = fc; buf->chunk_list[0]->nextfc = filechunk_new(buf->filename); buf->chunk_list[0]->prevfc = filechunk_new(buf->filename); buf->chunk_list[0]->wrapfc = filechunk_new(buf->filename); buf->pending = BUFFER_STATUS_READY; buf->samplerate_factor = (float)filechunk_get_samplerate(fc) / (float)buf->parent_samplerate; }else buf->status = BUFFER_STATUS_DEAD; /* printf ("samplerate factor :%.4f\n",buf->samplerate_factor);*/ return; } void buffer_loadfile(buffer_info_t* buf, char* fname, long srate){ /* create a reding thread, wait for join, return success*/ int lp; filechunk_t* fc; char* sn; float min,sec; buf->type = BUFFER_TYPE_FILEBUFFER; buf->filename = (char*) malloc (sizeof(char) * (strlen(fname) + 1)); strcpy(buf->filename,fname); if ((fc = buffer_order_filechunk(buf,0,-1, DS_PRIORITY_NORMAL,0))){ lp = strnflst (fname,"/",-1); sn = calloc(sizeof(char), (strlen(fname) - lp + 16)); sec = (float)filechunk_get_filelength(fc) / (float)filechunk_get_samplerate (fc); min = (int)(sec / 60.); sec -= min * 60; snprintf (sn,strlen(fname) - lp + 16,"FB: %s (%0.0f:%02.0f)",(char*)(buf->filename + lp + 1),min,sec); buffer_set_shortname(buf,sn); buf->chunk_list[0]->readfc = fc; buf->pending = BUFFER_STATUS_TOLOAD; buf->samplerate_factor = (float)filechunk_get_samplerate(fc) / (float)buf->parent_samplerate; }else buf->status = BUFFER_STATUS_DEAD; return; } static int check_fc_disc(filechunk_t *fc, int priority){ if (!fc) return 0; if (fc->priority != priority) return 0; if ((fc->length == fc->done)) return 0; if (!fc->L) return 0; /* if (!fc->L) printf ("!fc->L !!! :l:%ld, done:%ld\n ",fc->length,fc->done); */ return filechunk_read_chunk(fc); } static void* buffer_discthread(void *ptr){ speciallist_t *buffer_list = (speciallist_t*)ptr; buffer_info_t *buf; int dirty,i,j,k,d; struct timeval tv; /* printf ("buffer disc thread launched\n");*/ while(1){ dirty = 0; /* check for pending disc operations sorted by priority: */ /* actions for lower priority will only happen if higher ones didn't */ for (i = 0; (i < DS_PRIORITY_NONE) && !dirty; i++){ buf = speciallist_get_first(buffer_list); while (buf){ k = 0; buffer_lock(buf); for (j = 0; j <= buf->group_max; j++){ if (buf->chunk_list[j]){ /* printf ("j:%d\n",j);*/ d = check_fc_disc(buf->chunk_list[j]->readfc, i); if (d > 0) k += d; d = check_fc_disc(buf->chunk_list[j]->nextfc, i); if (d < 1) k = 0; d = check_fc_disc(buf->chunk_list[j]->prevfc, i); if (d < 1) k = 0; d = check_fc_disc(buf->chunk_list[j]->wrapfc, i); if (d < 1) k = 0; } } if (k){ dirty++; if (buf->type == BUFFER_TYPE_FILEBUFFER){ buf->pending = BUFFER_STATUS_LOADING; buf->percent_filled = (double)filechunk_get_done(buf->chunk_list[0]->readfc) / (double)filechunk_get_length(buf->chunk_list[0]->readfc); } }else{ if (buf->chunk_list[0]){ buf->percent_filled = (double)filechunk_get_done(buf->chunk_list[0]->readfc) / (double)filechunk_get_length(buf->chunk_list[0]->readfc); if ((buf->percent_filled == 1.) && (buf->status != BUFFER_STATUS_READY)) buf->pending = BUFFER_STATUS_READY; } } buffer_unlock(buf); buf = speciallist_get_next(buffer_list,buf); } } if (!dirty){ tv.tv_sec = 0; tv.tv_usec = 10000; /* max 100 times a sec */ select(0, NULL, NULL, NULL, &tv); } } /* won't happen: */ return NULL; } void buffer_discthread_launch(speciallist_t *buffer_list){ pthread_t lt; pthread_create (<, NULL, buffer_discthread, buffer_list); } int buffer_save (buffer_info_t* buf, char* fname, long srate, long start, long end){ SF_INFO* sfinfo = (SF_INFO*) malloc(sizeof(SF_INFO)); SNDFILE* sf; sf_count_t frames; sf_count_t frames_done = 0; sf_count_t frames_at_once = 32767; struct timeval tv; float *tbuf; long i; int channels = buffer_get_channels(buf); int group = buffer_get_group (buf, DS_PRIORITY_RELAXED); buffer_set_area(buf, group, start, end, frames_at_once); /* LATER: move this to disc thread */ tv.tv_sec = 0; tv.tv_usec = 100000; sfinfo->samplerate = srate; sfinfo->channels = buffer_get_channels(buf); /* LATER allow other formats */ sfinfo->format = SF_FORMAT_WAV | SF_FORMAT_PCM_16; sf = sf_open (fname, SFM_WRITE, sfinfo); if (!sf) return -1; tbuf = calloc (sizeof(float), frames_at_once * channels); if (!tbuf) return -1; while (frames_done < (end - start)){ frames = end - (start + frames_done); if (frames > frames_at_once) frames = frames_at_once; if (channels > 1){ for (i = 0; i < frames; i++){ *(tbuf + i * channels) = buffer_readsample_interpolated(buf, 1, (float)(start + frames_done + i),group); *(tbuf + i * channels + 1) = buffer_readsample_interpolated(buf, 2, (float)(start + frames_done + i),group); } }else{ for (i = 0; i < frames; i++){ *(tbuf + i * channels) = buffer_readsample_interpolated(buf, 1, (float)(start + frames_done + i),group); } } frames = sf_writef_float(sf, tbuf, frames); if (frames < 1){ free(tbuf); if (group) buffer_delete_group(buf, group); return -1; }/* else printf ("%ld frames written\n",(long)frames);*/ frames_done += frames; select(0, NULL, NULL, NULL, &tv); } sf_close(sf); free(tbuf); if (group) buffer_delete_group(buf, group); return 1; } kluppe-0.6.14/src/common/jackmixer.c0000644000175000017500000006515110615334677016640 0ustar dieterdieter#include #include #include #include #include #include #include #include #include #include #include #include "looperdata.h" #include "jackmixer.h" #include "speciallist.h" #define DEFAULT_RB_SIZE 16384 #define MAX_NAMESIZE 255 typedef struct _submix { jack_ringbuffer_t *rb_inL; jack_ringbuffer_t *rb_inR; jack_ringbuffer_t *rb_inP; jack_ringbuffer_t *rb_outL; jack_ringbuffer_t *rb_outR; jack_ringbuffer_t *rb_outP; jack_port_t *port_inL; jack_port_t *port_inR; jack_port_t *port_inP; jack_port_t *port_outL; jack_port_t *port_outR; jack_port_t *port_outP; int needs_input; int did_output; int did_pointer; int needs_pointer; char *name; int id; } submix_t; typedef struct _thread_info{ volatile size_t sample_size; submix_t **submixes; speciallist_t *looperdatalist; volatile int nmixes; volatile jack_nframes_t rb_size; volatile jack_nframes_t last_nframes; volatile int can_process; volatile int inside; volatile int outside; volatile long inrounds; volatile long outrounds; jack_info_t *jack_info; pthread_t mix_thread_id; volatile long xruns; volatile int freewheeling; pthread_mutex_t mix_thread_lock;/* = PTHREAD_MUTEX_INITIALIZER;*/ pthread_cond_t data_ready;/* = PTHREAD_COND_INITIALIZER;*/ } thread_info_t; /* submix helpers */ submix_t* submix_new (thread_info_t *info, int id, char* name){ submix_t *submix = (submix_t*) malloc(sizeof(submix_t)); char *tmp; submix->rb_inL = jack_ringbuffer_create (info->sample_size * info->rb_size); submix->rb_inR = jack_ringbuffer_create (info->sample_size * info->rb_size); submix->rb_inP = jack_ringbuffer_create (info->sample_size * info->rb_size); submix->rb_outL = jack_ringbuffer_create (info->sample_size * info->rb_size); submix->rb_outR = jack_ringbuffer_create (info->sample_size * info->rb_size); submix->rb_outP = jack_ringbuffer_create (info->sample_size * info->rb_size); memset(submix->rb_inL->buf, 0, submix->rb_inL->size); memset(submix->rb_inR->buf, 0, submix->rb_inR->size); memset(submix->rb_inP->buf, 0, submix->rb_inP->size); memset(submix->rb_outL->buf, 0, submix->rb_outL->size); memset(submix->rb_outR->buf, 0, submix->rb_outR->size); memset(submix->rb_outP->buf, 0, submix->rb_outP->size); /* try mlock */ jack_ringbuffer_mlock(submix->rb_inL); jack_ringbuffer_mlock(submix->rb_inR); jack_ringbuffer_mlock(submix->rb_inP); jack_ringbuffer_mlock(submix->rb_outL); jack_ringbuffer_mlock(submix->rb_outR); jack_ringbuffer_mlock(submix->rb_outP); submix->needs_input = 0; submix->did_output = 0; submix->needs_pointer = 0; submix->did_pointer = 0; tmp = (char*) malloc (MAX_NAMESIZE * sizeof(char)); if (id > 0){ /* this is a hack, because we don't need main in L+R */ info->outside = 100; snprintf(tmp,MAX_NAMESIZE,"%s_in_L",name); submix->port_inL = jack_port_register (info->jack_info->client, tmp, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); if (!submix->port_inL) fprintf (stderr,"could not create %s_in_L\n",name); snprintf(tmp,MAX_NAMESIZE,"%s_in_R",name); submix->port_inR = jack_port_register (info->jack_info->client, tmp, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); if (!submix->port_inR) fprintf (stderr,"could not create %s_in_R\n",name); snprintf(tmp,MAX_NAMESIZE,"%s_in_Position",name); submix->port_inP = jack_port_register (info->jack_info->client, tmp, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); if (!submix->port_inP) fprintf (stderr,"could not create %s_in_Position\n",name); snprintf(tmp,MAX_NAMESIZE,"%s_out_Position",name); submix->port_outP = jack_port_register (info->jack_info->client, tmp, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); if (!submix->port_outP) fprintf (stderr,"could not create %s_out_L\n",name); info->outside = 101; } snprintf(tmp,MAX_NAMESIZE,"%s_out_L",name); submix->port_outL = jack_port_register (info->jack_info->client, tmp, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); if (!submix->port_outL) fprintf (stderr,"could not create %s_out_L\n",name); snprintf(tmp,MAX_NAMESIZE,"%s_out_R",name); submix->port_outR = jack_port_register (info->jack_info->client, tmp, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); if (!submix->port_outR) fprintf (stderr,"could not create %s_out_R\n",name); free(tmp); submix->id = id; /* printf ("registering id:%d\n",id);*/ submix->name = (char*) malloc(sizeof(char) * (strlen(name)+1)); strcpy (submix->name,name); return submix; } void submix_append(thread_info_t* info,submix_t* mix, int id){ int i; int s = info->nmixes; if ((id + 1) > info->nmixes){ info->nmixes = id + 1; info->submixes = (submix_t**) realloc(info->submixes, sizeof(submix_t*) * info->nmixes); for (i = s; i < info->nmixes; i++) info->submixes[i] = NULL; } *(info->submixes + id) = mix; } void submix_remove_by_id(thread_info_t* info,int id){ submix_t* submix; int i; int err; for (i = 1;i < info->nmixes;i++){ submix = (submix_t*)(info->submixes[i]); if (submix){ if (submix->id == id){ err = jack_port_unregister (info->jack_info->client,submix->port_inL); if (err) printf ("could not unregister jack port"); jack_ringbuffer_free(submix->rb_inL); err = jack_port_unregister (info->jack_info->client,submix->port_inR); if (err) printf ("could not unregister jack port"); jack_ringbuffer_free(submix->rb_inR); err = jack_port_unregister (info->jack_info->client,submix->port_inP); if (err) printf ("could not unregister jack port"); jack_ringbuffer_free(submix->rb_inP); err = jack_port_unregister (info->jack_info->client,submix->port_outL); if (err) printf ("could not unregister jack port"); jack_ringbuffer_free(submix->rb_outL); err = jack_port_unregister (info->jack_info->client,submix->port_outR); if (err) printf ("could not unregister jack port"); jack_ringbuffer_free(submix->rb_outR); err = jack_port_unregister (info->jack_info->client,submix->port_outP); if (err) printf ("could not unregister jack port"); jack_ringbuffer_free(submix->rb_outP); submix->did_output = 0; submix->needs_input = 0; free (submix->name); free (submix); info->submixes[i] = NULL; /* printf("submix:%d, unregistered\n",id);*/ } } } } submix_t* search_submix_by_id(thread_info_t* info, int id){ int i; submix_t* submix; if (!info->nmixes){return NULL;} for (i = 0;i < info->nmixes;i++){ submix = (submix_t*)(info->submixes[i]); if (submix) if (submix->id == id){return submix;} } return NULL; } looper_data_t* search_looper_data_by_id(thread_info_t* info, int id){ looper_data_t *ld = speciallist_get_first_nolock (info->looperdatalist); while(ld){ if (ld->id == id) return ld; ld = speciallist_get_next_nolock (info->looperdatalist, ld); } return NULL; } int search_lost_submix(thread_info_t* info){ submix_t *submix; int i; for (i = 1;i < info->nmixes;i++){ submix = (submix_t*)(info->submixes[i]); /* printf ("i:%d,id:%d\n",i,submix->id);*/ if (submix && (search_looper_data_by_id(info, i) == NULL)) if (submix->did_output || submix->needs_input) return submix->id; } return 0; } /* jack administrative functions */ void jack_shutdown (void *arg){ thread_info_t *info = (thread_info_t*) arg; fprintf (stderr, "JACK shutdown - mixer is a zombie (process status: %d,%d)\n",info->inside,info->outside); /* fprintf (stderr, "JACK shutdown - mixer is a zombie\n");*/ info->jack_info->alive = 0; /* abort(); */ } void errfunc(const char *msg){ printf ("jack error: %s\n",msg); } void freewheelfunc (int starting, void *arg){ thread_info_t *info = (thread_info_t*) arg; info->freewheeling = starting; } int xrunfunc (void *arg){ thread_info_t *info = (thread_info_t*)arg; info->outside = 401; info->xruns++; info->outside = 402; printf ("jack xrun\n"); return 0; } void mixer_close(jack_info_t *jack_info){ if (jack_info) if (jack_info->client){ jack_client_close(jack_info->client); jack_info->client = 0; } } /* the work functions */ int process (jack_nframes_t nframes, void *arg){ thread_info_t *info = (thread_info_t *) arg; int i,rs; jack_ringbuffer_t *rb; jack_port_t *port; jack_default_audio_sample_t *rh; info->inside = -3; if (pthread_mutex_trylock (&info->mix_thread_lock)){ /* printf ("lock not possible \n");*/ return 0; } /* wait for data if freewheeling; else go on */ info->inside = -2; if (info->freewheeling) while (info->can_process != 1); else if (info->can_process == 0){ /* -1 for free wheeling, 1 for new data, 2 for init*/ /* printf ("srun in process\n");*/ info->xruns++; return 0; } else if (info->can_process != 1) { /* printf ("xrun in process\n");*/ return 0; } info->inside = -1; info->inrounds++; info->last_nframes = nframes; if (info->submixes){ for (i = 0; i < info->nmixes;i++){ if (info->submixes[i]){ info->inside = 1; if (info->submixes[i]->did_output){ port = info->submixes[i]->port_outL; rb = info->submixes[i]->rb_outL; rh = (jack_default_audio_sample_t *) jack_port_get_buffer (port,nframes); if ((rs = jack_ringbuffer_read (rb,(void*)rh,info->sample_size * nframes)) < nframes * info->sample_size){ info->xruns++; /* printf ("xrun in %d_did_output (outside:%d, rs:%d != %d, rounds:%ld/%ld)\n", i,info->outside, rs, (info->sample_size * nframes), info->inrounds, info->outrounds); */ /* printf("%s->outL, %d/%d/%d frames\n",jack_port_name (info->submixes[i]->port_outL), nframes,info->last_nframes,rs);*/ } port = info->submixes[i]->port_outR; rb = info->submixes[i]->rb_outR; rh = (jack_default_audio_sample_t *) jack_port_get_buffer (port,nframes); if ((rs = jack_ringbuffer_read (rb,(void*)rh,info->sample_size * nframes)) < nframes * info->sample_size){ info->xruns++;} } if (info->submixes[i]->needs_input){ port = info->submixes[i]->port_inL; rb = info->submixes[i]->rb_inL; rh = (jack_default_audio_sample_t *) jack_port_get_buffer (port,nframes); if (jack_ringbuffer_write_space(rb) >= nframes * info->sample_size){ if (jack_ringbuffer_write (rb,(void*)rh,info->sample_size * nframes) < nframes * info->sample_size){info->xruns++;} }else{info->xruns++;} port = info->submixes[i]->port_inR; rb = info->submixes[i]->rb_inR; rh = (jack_default_audio_sample_t *) jack_port_get_buffer (port,nframes); if (jack_ringbuffer_write_space(rb) >= nframes * info->sample_size){ if (jack_ringbuffer_write (rb,(void*)rh,info->sample_size * nframes) < nframes * info->sample_size){info->xruns++;} }else{info->xruns++;} } if (info->submixes[i]->did_pointer){ port = info->submixes[i]->port_outP; rb = info->submixes[i]->rb_outP; rh = (jack_default_audio_sample_t *) jack_port_get_buffer (port,nframes); if ((rs = jack_ringbuffer_read (rb,(void*)rh,info->sample_size * nframes)) < nframes * info->sample_size){ info->xruns++;} } if (info->submixes[i]->needs_pointer){ port = info->submixes[i]->port_inP; rb = info->submixes[i]->rb_inP; rh = (jack_default_audio_sample_t *) jack_port_get_buffer (port,nframes); if (jack_ringbuffer_write_space(rb) >= nframes * info->sample_size){ if (jack_ringbuffer_write (rb,(void*)rh,info->sample_size * nframes) < nframes * info->sample_size){info->xruns++;} }else{info->xruns++;} } info->inside = 0; } } } /* pthread_cond_signal (&info->data_ready);*/ pthread_cond_broadcast (&info->data_ready); info->inside = 2; pthread_mutex_unlock (&info->mix_thread_lock); info->inside = 3; return 0; } static void* mix_thread(void *arg){ thread_info_t *info = (thread_info_t*)arg; struct sched_param rtparam; jack_nframes_t i,j = 0; looper_data_t* data = NULL; looper_data_t* data2 = NULL; submix_t* submix; char* name = NULL; int noutports = 0; float mixfactor = .0; const char **ports; /* float L,R,P;*/ float *Lbuf = NULL; float *Rbuf = NULL; float *Pbuf = NULL; double oldrecpos = 0.0; double newrecpos = 0.0; float* mainbufL = (float*) malloc(sizeof(float) * DEFAULT_RB_SIZE); float* mainbufR = (float*) malloc(sizeof(float) * DEFAULT_RB_SIZE); int cc = 0; char *clientname = malloc(jack_client_name_size() * sizeof(char)); jack_set_error_function ((void*)errfunc); while (!info->jack_info->client && (cc < 99)){ memset(clientname,0,jack_client_name_size()); sprintf(clientname,"kluppe%d",++cc); info->jack_info->client = jack_client_new (clientname); } if (cc > 98){ fprintf (stderr, "jack server not running?\n"); info->jack_info->name = malloc(sizeof(char) * 10); strncpy (info->jack_info->name,"nojack!",7); return info->jack_info; } printf ("jack client name: %s\n",clientname); info->jack_info->name = calloc(sizeof(char) , (strlen(clientname) + 1)); strncpy (info->jack_info->name,clientname,strlen(clientname)) ; /* launch jack process thread and activate */ /* bad status for client event handling (type = 8) ??? */ jack_set_process_callback (info->jack_info->client, process, info); jack_set_freewheel_callback(info->jack_info->client, freewheelfunc, info); jack_set_xrun_callback(info->jack_info->client, xrunfunc, info); jack_on_shutdown (info->jack_info->client, jack_shutdown, info); info->jack_info->samplerate = (long)jack_get_sample_rate(info->jack_info->client); info->can_process = 2; /* try to reach higher priority */ memset (&rtparam, 0, sizeof (rtparam)); rtparam.sched_priority = /*sched_get_priority_max(SCHED_RR) - */10; i = pthread_setschedparam(pthread_self(),SCHED_RR,&rtparam); /* if (i) printf ("couldn't set priority\n");*/ pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL); pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL); pthread_mutex_lock (&info->mix_thread_lock); /* printf ("mixer thread:%d\n",(int)getpid());*/ while (1){ if ((info->can_process == 1) || (info->can_process == -1)){ info->can_process = 0; info->jack_info->load = jack_cpu_load (info->jack_info->client); info->jack_info->freewheeling = info->freewheeling; info->outside = 300; if (!info->submixes){ info->outside = 301; /* no main in/out yet: */ submix_append (info,submix_new (info,0,"main"),0); /* printf ("main outputs created\n");*/ submix = search_submix_by_id(info,0); if ((ports = jack_get_ports ( info->jack_info->client, NULL, NULL, JackPortIsPhysical|JackPortIsInput)) == NULL) { fprintf(stderr, "Cannot find any physical playback ports!\n"); }else{ info->outside = 302; if (jack_connect (info->jack_info->client, jack_port_name (submix->port_outL),ports[0])){ fprintf (stderr, "cannot connect main port\n"); } if (jack_connect (info->jack_info->client, jack_port_name (submix->port_outR),ports[1])){ fprintf (stderr, "cannot connect main ports\n"); } info->submixes[0]->did_output = 1; /* always play on main out */ free (ports); info->outside = 303; } } /* xruns even if all the processing is switched off: #if 0 */ info->outside = 304; memset (mainbufL,0,info->rb_size/*last_nframes*/ * info->sample_size); memset (mainbufR,0,info->rb_size/*last_nframes*/ * info->sample_size); info->outside = 305; noutports = 0; while (search_lost_submix(info)) submix_remove_by_id(info,search_lost_submix(info)); speciallist_lock(info->looperdatalist); data = speciallist_get_first_nolock(info->looperdatalist); while (data){ submix = search_submix_by_id(info,data->id); info->outside = 306; if (!submix){ /* new looper: setup submix... */ name = (char*) malloc (MAX_NAMESIZE * sizeof(char)); sprintf (name,"act%d",data->id); submix = submix_new (info,data->id,name); /* connecting takes a while and can cause xruns */ /* LATER: move connecting to gui thread / looper.c */ if ((ports = jack_get_ports (info->jack_info->client, NULL, NULL, JackPortIsPhysical|JackPortIsOutput))){ if (jack_connect (info->jack_info->client,ports[0], jack_port_name (submix->port_inL))){ fprintf (stderr, "cannot connect looper input port\n"); } if (jack_connect (info->jack_info->client,ports[1], jack_port_name (submix->port_inR))){ fprintf (stderr, "cannot connect looper input port\n"); } free (ports); }else{ printf ("can't find physical input ports for looper\n"); } submix_append (info,submix,data->id); free(name); info->outside = 307; } info->outside = 309; if (data->buf && data->id){ if (data->buf->status == BUFFER_STATUS_READY){ info->outside = 310; if (jack_port_connected(submix->port_outP)) submix->did_pointer = 1; else submix->did_pointer = 0; if (data->isrecording && (data->recend > data->recstart)) submix->needs_input = 1; else submix->needs_input = 0; if ((data->playmode == LOOP_PLAYMODE_EXTERNALPOS) && jack_port_connected(submix->port_inP)) submix->needs_pointer = 1; else submix->needs_pointer = 0; /* LATER calculate the number of samples from jacks buffer_size_callback */ /* for now, it's just the last number of samples from process() */ i = j; j = info->last_nframes; if (jack_ringbuffer_read_space(submix->rb_inL) > j * info->sample_size){ j = jack_ringbuffer_read_space(submix->rb_inL) / info->sample_size; } if (i != j){ /* check buffer sizes */ /* printf ("n_frames change: %ld -> %ld\n",(long)i, (long)j);*/ if (Lbuf){ Lbuf = realloc (Lbuf, info->sample_size * j); Rbuf = realloc (Rbuf, info->sample_size * j); Pbuf = realloc (Pbuf, info->sample_size * j); } else { Lbuf = calloc (info->sample_size, j); Rbuf = calloc (info->sample_size, j); Pbuf = calloc (info->sample_size, j); } } oldrecpos = looperdata_get_recpos(data); looperdata_lock(data); info->outside = 311; if (submix->needs_input){ jack_ringbuffer_read (submix->rb_inL, (void *) Lbuf, info->sample_size * j); jack_ringbuffer_read (submix->rb_inR, (void *) Rbuf, info->sample_size * j); /* looperdata_write_sampleblock(data, j, Lbuf, Rbuf);*/ } if (submix->needs_pointer){ jack_ringbuffer_read (submix->rb_inP, (void *) Pbuf, info->sample_size * j); } submix->did_output = 0; looperdata_calc_sampleblock(data, j, Lbuf, Rbuf, Pbuf, !info->jack_info->suspend_playing, !info->jack_info->suspend_recording); if (data->isplaying){ looperdata_unlock (data); if (submix->did_pointer) jack_ringbuffer_write (submix->rb_outP, (void *)Pbuf, info->sample_size * j); noutports++; if (!info->jack_info->suspend_playing) for (i = 0; i < j;i++){ *(mainbufL + i) += *(Lbuf + i); *(mainbufR + i) += *(Rbuf + i); } if ((submix->port_outL) && (submix->port_outR)){ if (jack_port_connected(submix->port_outL) || jack_port_connected(submix->port_outR)){ jack_ringbuffer_write (submix->rb_outL, (void *)Lbuf, info->sample_size * j); jack_ringbuffer_write (submix->rb_outR, (void *)Rbuf, info->sample_size * j); submix->did_output = 1; } } } else looperdata_unlock (data); info->outside = 312; /* info->last_nframes = j;*/ if ((oldrecpos != looperdata_get_recpos(data)) || data->buf->normalized){ info->outside = 313; /* update dirty_blocks_list for all affected loopers */ data2 = speciallist_get_first_nolock(info->looperdatalist); while (data2){ if (data2->buf == data->buf){ if (data->buf->normalized){ looperdata_lock(data2); looperdata_write_dirtyblock( data2,0.,(double)( buffer_get_size(data2->buf))); looperdata_unlock(data2); }else{ newrecpos = looperdata_get_recpos(data); looperdata_lock(data2); if (newrecpos < oldrecpos){ looperdata_write_dirtyblock(data2, oldrecpos, looperdata_get_recend(data)); if (newrecpos > looperdata_get_recstart(data)){ looperdata_write_dirtyblock(data2, looperdata_get_recstart(data),newrecpos); } }else{ looperdata_write_dirtyblock(data2, oldrecpos, newrecpos); } looperdata_unlock (data2); } } data2 = speciallist_get_next_nolock(info->looperdatalist, data2); } if (data->buf->normalized){ looperdata_lock(data); data->buf->normalized = 0; looperdata_unlock(data); } } info->outside = 313; } } data = speciallist_get_next_nolock(info->looperdatalist, data); } speciallist_unlock(info->looperdatalist); /* printf ("unlock:%d\n",count);*/ /* LATER delete unused submixes */ info->outside = 314; if ((noutports > 1) && (!info->jack_info->suspend_playing)){ /* normalize main out signal */ mixfactor = 1.0f / sqrt(noutports); for (i = 0; i < j/*info->last_nframes*/; i++){ *(mainbufL + i ) *= mixfactor; *(mainbufR + i ) *= mixfactor; } } info->outside = 315; /* warn if there were xruns */ if (info->xruns != info->jack_info->xruns){ info->jack_info->xruns = info->xruns; /* info->xruns = 0;*/ } /* end of xrun test #endif */ info->outside = 316; /* write main out data */ /* printf ("write:%d bytes\n",info->last_nframes * info->sample_size);*/ jack_ringbuffer_write (info->submixes[0]->rb_outL,(void *)mainbufL,info->last_nframes * info->sample_size); jack_ringbuffer_write (info->submixes[0]->rb_outR,(void *)mainbufR,info->last_nframes * info->sample_size); info->outside = 317; info->can_process = 1; }/* end if can_process*/ /* wait until process() signals more data */ ++info->outrounds; info->outside = 318; pthread_cond_wait (&info->data_ready, &info->mix_thread_lock); info->outside = 319; }/* end while always*/ /* this will never happen */ pthread_mutex_unlock (&info->mix_thread_lock); return NULL; } jack_info_t* mixer_launch (speciallist_t *looperdatalist){ thread_info_t *info; long waited = 0; /* set up communication data */ info = (thread_info_t*) malloc(sizeof(thread_info_t)); memset (info, 0, sizeof (thread_info_t)); info->looperdatalist = looperdatalist; info->can_process = 0; info->submixes = NULL; info->nmixes = 0; info->last_nframes = 0; info->freewheeling = 0; info->inside = 0; info->outside = 0; info->inrounds = 0; info->outrounds = 0; info->sample_size = sizeof(jack_default_audio_sample_t); info->jack_info = (jack_info_t*) malloc(sizeof(jack_info_t)); info->jack_info->client = 0; info->jack_info->samplerate = 0; info->jack_info->load = 0.0; info->jack_info->xruns = 0; info->jack_info->name = NULL; info->jack_info->freewheeling = 0; info->jack_info->suspend_playing = 0; info->jack_info->suspend_recording = 0; info->jack_info->alive = 0; /* LATER handle buffersize changes while processing */ /* info->rb_size = jack_get_buffer_size (info->jack_info->client) + info->sample_size; */ info->rb_size = DEFAULT_RB_SIZE; /* launch mix thread */ pthread_cond_init(&info->data_ready, NULL); pthread_mutex_init(&info->mix_thread_lock,NULL); pthread_create (&info->mix_thread_id, NULL, mix_thread, info); while (!info->can_process && (++waited < 50000)){ usleep(10); } if (info->can_process < 1) return info->jack_info; if (jack_activate (info->jack_info->client)) { fprintf (stderr, "cannot activate client\n"); }else{ info->can_process = 1; info->jack_info->alive = 1; } return info->jack_info; } kluppe-0.6.14/src/common/filechunk.h0000644000175000017500000000400010464736147016622 0ustar dieterdieter/* filechunk.h definitions */ #ifndef __FILECHUNK_H__ #define __FILECHUNK_H__ #include #include #include #include "speciallist.h" enum { DS_PRIORITY_URGENT, DS_PRIORITY_NORMAL, DS_PRIORITY_RELAXED, DS_PRIORITY_NONE, DS_PRIORITY_LAST }; typedef struct filechunk { char* filename; SF_INFO* sfinfo; SNDFILE* sf; int group; int priority; int channels; long start; long end; long length; long done; float* L; float* R; } filechunk_t; typedef struct _chunk_group { int gid; int priority; long area_start; long area_end; long area_bandwith; filechunk_t* readfc; filechunk_t* nextfc; filechunk_t* prevfc; filechunk_t* wrapfc; } chunk_group_t; chunk_group_t* chunkgroup_new(int gid, int priority); void chunkgroup_delete(chunk_group_t* group); filechunk_t* filechunk_new(char* filename); void filechunk_delete(filechunk_t* fc); int filechunk_get_group(filechunk_t* fc); long filechunk_resize(filechunk_t* fc, long new_size); long filechunk_set (filechunk_t* fc, long start, long end, int priority, int group); long filechunk_read_chunk (filechunk_t* fc); long filechunk_get_length (filechunk_t* fc); long filechunk_get_start (filechunk_t* fc); long filechunk_get_end (filechunk_t* fc); long filechunk_get_done (filechunk_t* fc); void filechunk_set_channels (filechunk_t* fc, int channels); int filechunk_get_channels (filechunk_t* fc); long filechunk_get_filelength (filechunk_t* fc); long filechunk_get_samplerate (filechunk_t* fc); int filechunk_get_priority (filechunk_t* fc); float filechunk_get_sample(filechunk_t* fc, int channel, long sample); void filechunk_write_sample(filechunk_t* fc, int channel, long sample, float value); void filechunk_write_sampleblock(filechunk_t* fc, long index, long size, float* Lbuf, float* Rbuf); #endif kluppe-0.6.14/src/common/vinyl.h0000644000175000017500000011411010441623140015776 0ustar dieterdieter#include "filechunk.h" static float vinyl_L[3552] = { 0.000000, 0.000305, 0.000061, -0.000366, -0.000763, -0.000397, -0.000031, 0.000000, -0.000580, -0.000732, -0.000458, -0.000458, -0.000946, -0.000183, 0.001953, 0.010956, 0.027924, 0.048553, 0.064301, 0.072723, 0.077057, 0.088531, 0.111816, 0.139893, 0.166931, 0.193237, 0.217651, 0.237762, 0.252441, 0.262695, 0.273621, 0.285980, 0.301392, 0.319092, 0.340454, 0.361176, 0.384125, 0.406982, 0.431122, 0.455353, 0.478943, 0.500336, 0.520233, 0.538635, 0.561005, 0.581909, 0.601501, 0.618896, 0.635864, 0.650970, 0.664459, 0.676392, 0.687622, 0.700073, 0.712036, 0.725891, 0.740540, 0.756683, 0.773804, 0.790649, 0.806183, 0.820404, 0.833649, 0.845520, 0.857208, 0.868927, 0.879547, 0.889465, 0.899536, 0.908722, 0.918243, 0.927094, 0.933990, 0.940247, 0.943756, 0.944031, 0.941315, 0.934296, 0.921722, 0.899384, 0.864410, 0.810364, 0.734650, 0.632477, 0.511444, 0.388153, 0.265137, 0.151001, 0.041992, -0.062775, -0.166229, -0.286774, -0.404816, -0.444153, -0.410553, -0.413361, -0.375336, -0.340179, -0.359558, -0.323761, -0.327972, -0.320465, -0.328247, -0.346954, -0.378876, -0.432343, -0.495575, -0.554199, -0.604980, -0.658142, -0.695801, -0.721344, -0.742096, -0.767395, -0.779175, -0.784271, -0.774139, -0.748749, -0.731110, -0.721130, -0.701324, -0.677551, -0.661469, -0.653656, -0.644592, -0.628815, -0.616882, -0.603790, -0.589081, -0.573059, -0.558197, -0.546631, -0.532501, -0.518005, -0.504913, -0.494507, -0.483795, -0.471405, -0.458740, -0.446289, -0.432739, -0.418274, -0.403656, -0.388641, -0.373138, -0.353973, -0.330261, -0.299042, -0.256683, -0.202667, -0.141968, -0.074646, 0.002625, 0.089294, 0.178558, 0.265381, 0.348328, 0.419525, 0.474823, 0.506866, 0.511230, 0.488068, 0.442596, 0.379059, 0.302094, 0.218658, 0.133575, 0.053070, -0.018829, -0.073608, -0.108307, -0.121552, -0.111603, -0.081940, -0.036835, 0.020844, 0.086761, 0.154205, 0.219025, 0.275055, 0.316620, 0.341919, 0.352844, 0.347900, 0.329712, 0.301086, 0.267426, 0.226257, 0.182892, 0.141663, 0.104156, 0.070709, 0.045013, 0.025421, 0.011688, 0.003601, 0.001953, 0.006714, 0.017548, 0.031799, 0.047699, 0.068390, 0.104340, 0.160248, 0.215332, 0.251801, 0.289551, 0.329926, 0.364563, 0.400024, 0.434845, 0.461853, 0.482452, 0.505066, 0.525879, 0.545135, 0.562927, 0.575409, 0.588135, 0.596893, 0.602570, 0.604706, 0.600555, 0.589874, 0.575165, 0.556885, 0.533600, 0.500763, 0.453705, 0.384277, 0.303497, 0.219208, 0.144135, 0.085815, 0.035919, -0.001068, 0.017181, 0.096375, 0.124481, 0.157227, 0.217316, 0.231873, 0.276947, 0.287903, 0.311310, 0.321228, 0.327423, 0.330414, 0.325684, 0.322052, 0.306671, 0.293152, 0.273529, 0.251984, 0.224487, 0.191803, 0.149384, 0.105286, 0.070251, 0.053955, 0.032684, 0.004059, -0.027191, -0.066284, -0.104065, -0.134613, -0.157135, -0.182556, -0.209290, -0.240631, -0.271057, -0.300262, -0.327606, -0.348572, -0.363739, -0.354065, -0.328278, -0.321533, -0.318329, -0.312012, -0.310547, -0.309296, -0.320770, -0.326080, -0.340424, -0.353546, -0.368103, -0.382080, -0.397125, -0.411865, -0.425751, -0.437988, -0.447113, -0.455719, -0.459259, -0.461792, -0.462189, -0.462402, -0.461548, -0.459045, -0.456909, -0.454590, -0.449432, -0.442932, -0.440552, -0.439819, -0.439789, -0.437988, -0.436218, -0.432556, -0.429962, -0.429718, -0.432343, -0.434967, -0.436676, -0.437134, -0.442261, -0.451447, -0.461487, -0.467926, -0.474579, -0.479523, -0.483337, -0.488037, -0.490509, -0.490479, -0.488892, -0.484894, -0.479767, -0.473999, -0.466309, -0.458069, -0.449615, -0.440948, -0.432953, -0.425323, -0.418152, -0.412506, -0.406952, -0.402435, -0.398926, -0.396027, -0.396332, -0.398499, -0.402954, -0.408997, -0.415955, -0.422302, -0.428040, -0.430298, -0.432983, -0.438354, -0.443420, -0.449402, -0.453888, -0.455902, -0.455658, -0.452301, -0.447113, -0.440521, -0.433319, -0.428802, -0.425751, -0.422333, -0.416290, -0.409973, -0.410919, -0.411774, -0.411835, -0.413025, -0.413727, -0.415100, -0.414429, -0.416077, -0.417297, -0.419891, -0.421295, -0.421448, -0.421387, -0.422638, -0.424072, -0.425354, -0.424042, -0.422119, -0.418762, -0.415588, -0.411255, -0.406372, -0.401154, -0.394348, -0.388275, -0.384705, -0.382568, -0.379517, -0.375397, -0.372498, -0.371002, -0.369873, -0.367462, -0.365601, -0.362671, -0.359833, -0.356110, -0.350189, -0.342712, -0.335022, -0.327698, -0.321503, -0.317322, -0.313202, -0.308594, -0.304108, -0.299347, -0.294952, -0.290802, -0.287781, -0.285034, -0.282288, -0.279205, -0.274750, -0.268585, -0.262787, -0.257843, -0.252808, -0.247772, -0.241608, -0.234039, -0.228149, -0.222504, -0.215820, -0.208496, -0.200592, -0.192841, -0.186310, -0.179901, -0.172394, -0.164764, -0.156982, -0.149323, -0.143799, -0.137695, -0.133484, -0.130463, -0.126190, -0.122986, -0.121735, -0.121033, -0.119568, -0.119812, -0.120422, -0.119019, -0.116364, -0.112274, -0.108673, -0.105774, -0.101715, -0.096558, -0.092285, -0.087799, -0.083344, -0.078613, -0.073761, -0.069275, -0.065063, -0.060242, -0.055389, -0.051331, -0.048309, -0.045837, -0.044861, -0.044434, -0.044098, -0.044678, -0.045563, -0.046112, -0.045990, -0.045990, -0.046021, -0.046692, -0.046265, -0.045990, -0.045593, -0.044037, -0.042023, -0.040741, -0.038208, -0.036133, -0.034058, -0.031647, -0.029907, -0.028900, -0.028259, -0.027252, -0.026306, -0.025482, -0.024750, -0.024384, -0.023193, -0.021484, -0.019501, -0.017609, -0.014893, -0.012268, -0.009644, -0.007812, -0.006287, -0.004974, -0.004181, -0.003174, -0.001587, -0.000305, 0.000610, 0.002228, 0.004028, 0.005676, 0.007660, 0.009857, 0.012115, 0.014618, 0.017578, 0.020416, 0.023438, 0.025818, 0.028503, 0.031128, 0.033234, 0.036194, 0.039734, 0.043701, 0.048279, 0.052917, 0.057983, 0.062775, 0.067139, 0.071594, 0.075287, 0.079376, 0.083740, 0.087097, 0.089264, 0.091919, 0.094574, 0.097534, 0.099884, 0.102844, 0.105896, 0.109528, 0.113098, 0.116272, 0.119293, 0.121887, 0.124481, 0.127930, 0.131592, 0.134796, 0.139252, 0.142761, 0.145142, 0.149048, 0.154358, 0.158875, 0.162231, 0.165771, 0.169342, 0.172638, 0.175323, 0.178467, 0.180847, 0.182648, 0.184845, 0.186188, 0.187805, 0.188812, 0.189758, 0.190918, 0.191345, 0.191528, 0.191956, 0.192810, 0.194183, 0.194855, 0.195557, 0.196808, 0.197662, 0.199005, 0.200226, 0.201752, 0.203705, 0.205017, 0.207275, 0.209076, 0.210876, 0.212158, 0.212952, 0.213959, 0.214935, 0.216034, 0.216156, 0.216339, 0.216309, 0.215302, 0.214081, 0.212646, 0.211426, 0.210052, 0.208862, 0.207642, 0.206757, 0.205566, 0.204529, 0.204102, 0.203156, 0.203033, 0.202759, 0.202393, 0.202087, 0.202179, 0.202759, 0.203461, 0.203888, 0.204895, 0.204895, 0.205414, 0.206635, 0.207306, 0.207733, 0.207855, 0.207733, 0.207886, 0.207886, 0.207001, 0.206024, 0.204681, 0.203827, 0.202576, 0.201233, 0.199554, 0.197693, 0.195221, 0.193939, 0.192322, 0.191315, 0.189972, 0.189209, 0.188507, 0.188171, 0.188232, 0.187592, 0.187744, 0.187286, 0.187042, 0.186798, 0.186493, 0.185852, 0.185089, 0.184326, 0.183838, 0.182739, 0.181549, 0.180115, 0.179047, 0.178528, 0.177032, 0.175568, 0.173859, 0.171783, 0.169708, 0.167694, 0.166656, 0.164307, 0.160736, 0.157318, 0.155212, 0.152588, 0.149719, 0.146851, 0.144928, 0.142944, 0.141724, 0.141785, 0.140106, 0.138611, 0.135803, 0.133911, 0.131744, 0.130432, 0.129608, 0.128448, 0.127502, 0.126740, 0.125122, 0.124054, 0.122620, 0.121002, 0.118439, 0.116058, 0.114471, 0.111786, 0.108368, 0.104614, 0.101318, 0.098724, 0.095520, 0.091583, 0.088440, 0.084656, 0.081055, 0.077454, 0.074158, 0.071167, 0.067902, 0.065125, 0.061768, 0.059204, 0.056610, 0.054291, 0.052063, 0.050049, 0.047638, 0.045441, 0.043274, 0.040833, 0.039093, 0.036530, 0.034393, 0.032257, 0.029510, 0.026794, 0.023926, 0.021301, 0.017914, 0.015320, 0.012360, 0.009277, 0.005920, 0.002808, -0.000366, -0.002777, -0.006073, -0.008698, -0.010529, -0.012573, -0.014374, -0.016449, -0.018555, -0.020477, -0.022064, -0.024048, -0.025574, -0.026886, -0.028168, -0.029816, -0.030975, -0.032379, -0.033478, -0.034821, -0.035675, -0.036499, -0.037506, -0.038818, -0.039978, -0.041107, -0.042542, -0.043915, -0.045105, -0.046692, -0.048187, -0.050049, -0.051178, -0.052094, -0.053192, -0.054199, -0.054871, -0.055939, -0.056824, -0.058136, -0.058807, -0.059998, -0.060791, -0.061615, -0.061798, -0.062073, -0.063019, -0.063812, -0.065125, -0.066101, -0.067261, -0.068665, -0.071045, -0.073181, -0.073486, -0.072845, -0.073456, -0.074310, -0.074585, -0.075073, -0.076721, -0.078094, -0.078094, -0.079041, -0.080048, -0.080597, -0.080383, -0.081116, -0.083191, -0.085510, -0.086121, -0.086365, -0.087097, -0.087677, -0.088104, -0.089355, -0.089661, -0.089111, -0.088989, -0.089630, -0.089691, -0.089081, -0.088257, -0.087921, -0.087830, -0.087830, -0.087708, -0.088135, -0.088989, -0.089630, -0.090240, -0.090851, -0.091644, -0.091309, -0.091492, -0.092651, -0.093079, -0.092926, -0.092072, -0.092163, -0.090973, -0.089630, -0.088409, -0.086639, -0.084686, -0.083252, -0.082336, -0.080048, -0.077087, -0.074646, -0.072723, -0.071045, -0.069672, -0.068085, -0.066711, -0.065277, -0.063843, -0.062347, -0.060669, -0.058929, -0.056946, -0.055908, -0.054688, -0.053467, -0.051910, -0.050720, -0.049622, -0.047638, -0.045837, -0.044189, -0.042694, -0.041534, -0.040558, -0.038452, -0.036804, -0.034698, -0.033203, -0.031616, -0.029694, -0.027954, -0.026001, -0.024292, -0.022888, -0.021332, -0.019623, -0.017853, -0.016479, -0.015472, -0.015259, -0.015015, -0.014587, -0.013458, -0.012665, -0.012146, -0.011261, -0.010223, -0.008484, -0.007629, -0.006256, -0.005280, -0.003845, -0.002350, -0.001038, -0.000031, 0.000519, 0.001678, 0.002319, 0.003113, 0.003326, 0.003265, 0.003113, 0.003326, 0.002655, 0.002533, 0.002808, 0.004120, 0.005951, 0.005615, 0.004364, 0.006287, 0.006897, 0.007690, 0.008148, 0.007538, 0.007812, 0.007843, 0.007629, 0.007477, 0.007690, 0.007233, 0.007477, 0.007263, 0.007965, 0.007904, 0.008209, 0.008331, 0.009369, 0.009552, 0.009735, 0.010132, 0.009857, 0.009857, 0.009583, 0.009277, 0.008850, 0.008972, 0.008911, 0.008667, 0.008514, 0.008209, 0.007843, 0.008118, 0.008118, 0.008392, 0.008636, 0.009491, 0.009918, 0.010437, 0.011261, 0.012146, 0.012878, 0.013245, 0.013153, 0.014008, 0.014832, 0.015808, 0.016724, 0.016296, 0.016174, 0.016724, 0.016968, 0.016296, 0.015137, 0.013580, 0.012512, 0.011169, 0.010284, 0.009064, 0.007965, 0.006409, 0.005493, 0.005127, 0.004242, 0.003265, 0.002228, 0.001007, 0.000092, -0.000580, -0.001251, -0.001801, -0.002106, -0.002625, -0.003357, -0.003784, -0.004547, -0.005249, -0.005829, -0.006561, -0.006927, -0.007660, -0.008667, -0.009674, -0.011597, -0.013367, -0.014893, -0.016541, -0.018555, -0.020844, -0.022461, -0.024323, -0.026062, -0.027527, -0.028503, -0.030060, -0.030457, -0.031097, -0.032257, -0.032562, -0.033417, -0.034637, -0.035797, -0.036377, -0.037689, -0.038879, -0.040100, -0.041656, -0.043243, -0.044403, -0.046295, -0.048157, -0.049774, -0.050751, -0.052307, -0.054077, -0.055878, -0.057465, -0.058838, -0.060364, -0.061279, -0.062500, -0.063293, -0.063873, -0.064392, -0.064056, -0.064362, -0.064789, -0.065247, -0.065735, -0.066864, -0.068085, -0.069092, -0.070160, -0.071564, -0.073273, -0.074738, -0.076569, -0.078186, -0.078918, -0.079285, -0.079529, -0.079956, -0.080719, -0.081024, -0.080383, -0.079651, -0.078583, -0.078369, -0.077942, -0.077881, -0.078308, -0.078735, -0.079102, -0.080048, -0.080750, -0.081085, -0.082062, -0.082611, -0.083405, -0.084839, -0.085785, -0.086975, -0.087830, -0.088531, -0.088776, -0.088348, -0.088104, -0.087921, -0.087341, -0.086395, -0.086182, -0.085388, -0.085114, -0.084747, -0.083954, -0.083038, -0.082092, -0.080963, -0.080109, -0.079437, -0.078705, -0.078156, -0.077576, -0.077881, -0.078491, -0.077881, -0.076508, -0.075897, -0.075287, -0.074768, -0.074646, -0.074615, -0.074219, -0.074066, -0.073761, -0.073639, -0.073212, -0.072052, -0.071442, -0.070984, -0.070465, -0.069153, -0.067841, -0.065979, -0.064423, -0.062653, -0.061066, -0.058929, -0.056641, -0.054443, -0.052094, -0.050293, -0.048126, -0.046051, -0.044525, -0.043243, -0.042084, -0.040802, -0.039368, -0.037811, -0.036713, -0.035400, -0.033905, -0.032410, -0.030487, -0.028473, -0.026154, -0.024048, -0.021942, -0.020050, -0.018341, -0.016418, -0.015167, -0.013947, -0.012817, -0.012421, -0.011292, -0.010132, -0.009003, -0.007660, -0.005646, -0.003693, -0.001770, 0.000580, 0.003113, 0.006256, 0.008331, 0.011230, 0.013672, 0.016418, 0.019012, 0.021301, 0.023621, 0.025757, 0.026917, 0.027954, 0.028595, 0.029358, 0.029968, 0.030396, 0.030457, 0.030701, 0.032562, 0.034058, 0.035919, 0.037994, 0.039795, 0.042084, 0.044830, 0.047485, 0.050049, 0.052643, 0.054230, 0.056458, 0.058502, 0.060394, 0.061981, 0.063080, 0.064301, 0.064697, 0.065399, 0.065948, 0.066498, 0.067413, 0.068146, 0.069397, 0.070618, 0.072327, 0.074127, 0.076172, 0.078430, 0.080597, 0.083160, 0.084473, 0.085999, 0.088287, 0.090637, 0.092987, 0.094269, 0.095947, 0.097260, 0.098114, 0.099182, 0.099640, 0.099823, 0.099915, 0.100342, 0.101685, 0.102356, 0.103577, 0.104919, 0.105652, 0.106934, 0.108246, 0.109222, 0.110596, 0.111633, 0.112762, 0.113922, 0.114899, 0.116150, 0.117584, 0.117828, 0.118927, 0.118835, 0.119537, 0.119690, 0.120178, 0.120575, 0.120941, 0.121094, 0.121460, 0.122131, 0.122620, 0.122986, 0.123322, 0.123962, 0.124756, 0.126007, 0.126495, 0.127472, 0.128265, 0.128601, 0.129547, 0.130157, 0.130371, 0.130585, 0.131042, 0.131653, 0.131927, 0.132172, 0.131927, 0.132294, 0.132904, 0.133362, 0.132904, 0.132874, 0.132812, 0.132965, 0.133179, 0.133362, 0.132782, 0.132050, 0.131531, 0.131317, 0.130920, 0.129761, 0.128967, 0.128601, 0.128265, 0.128387, 0.128052, 0.127655, 0.126862, 0.126465, 0.126038, 0.124969, 0.123260, 0.121796, 0.120453, 0.119202, 0.117920, 0.115753, 0.114075, 0.112640, 0.111847, 0.110565, 0.108673, 0.107178, 0.105591, 0.104187, 0.103363, 0.102783, 0.102112, 0.101105, 0.099670, 0.098419, 0.096466, 0.093872, 0.091766, 0.089691, 0.088257, 0.086334, 0.083984, 0.081573, 0.079468, 0.077301, 0.074768, 0.071869, 0.069336, 0.066711, 0.065033, 0.063385, 0.061493, 0.059387, 0.057678, 0.056335, 0.055054, 0.053406, 0.051117, 0.048798, 0.047119, 0.044769, 0.042450, 0.039703, 0.036987, 0.034515, 0.032104, 0.029541, 0.027344, 0.024750, 0.022583, 0.020538, 0.018097, 0.016296, 0.014252, 0.012360, 0.010681, 0.008789, 0.007019, 0.004944, 0.003326, 0.001434, -0.000549, -0.002380, -0.003265, -0.004883, -0.006439, -0.008179, -0.009918, -0.011566, -0.013031, -0.014618, -0.016205, -0.018005, -0.019592, -0.020905, -0.022186, -0.023895, -0.025604, -0.027374, -0.029236, -0.030273, -0.031830, -0.032379, -0.033264, -0.034302, -0.035065, -0.036224, -0.037323, -0.038788, -0.040344, -0.041626, -0.042114, -0.043396, -0.044098, -0.045349, -0.046539, -0.047577, -0.048492, -0.049683, -0.050201, -0.051086, -0.052368, -0.053436, -0.054565, -0.054779, -0.055054, -0.055756, -0.056183, -0.056885, -0.057739, -0.058685, -0.059265, -0.059753, -0.060059, -0.060883, -0.061615, -0.062378, -0.063080, -0.063965, -0.064362, -0.065002, -0.065979, -0.066589, -0.067200, -0.067505, -0.067963, -0.068237, -0.068573, -0.068878, -0.068787, -0.069305, -0.069458, -0.069733, -0.069885, -0.070221, -0.070587, -0.070618, -0.070374, -0.070404, -0.070709, -0.070587, -0.070801, -0.070648, -0.070953, -0.071136, -0.071564, -0.071960, -0.072571, -0.073242, -0.073883, -0.074402, -0.074829, -0.075317, -0.075867, -0.076324, -0.076630, -0.077087, -0.077667, -0.077087, -0.076782, -0.076416, -0.075897, -0.075623, -0.075073, -0.074707, -0.074463, -0.073822, -0.073608, -0.073395, -0.072876, -0.072876, -0.072723, -0.072937, -0.072845, -0.072784, -0.072723, -0.072327, -0.072052, -0.071716, -0.071350, -0.071136, -0.070862, -0.070587, -0.070465, -0.070282, -0.069885, -0.069366, -0.068878, -0.068512, -0.068237, -0.067963, -0.067627, -0.067444, -0.067444, -0.067291, -0.067230, -0.067169, -0.067108, -0.066864, -0.066742, -0.066528, -0.066254, -0.066010, -0.065796, -0.065369, -0.065308, -0.064972, -0.064819, -0.064636, -0.064911, -0.064667, -0.064270, -0.064056, -0.063721, -0.063599, -0.062988, -0.062439, -0.062103, -0.061584, -0.061005, -0.060455, -0.059967, -0.059509, -0.058929, -0.058105, -0.057495, -0.057129, -0.057098, -0.057098, -0.056763, -0.056610, -0.056580, -0.056427, -0.056427, -0.056427, -0.056396, -0.056152, -0.055695, -0.055298, -0.055115, -0.054840, -0.054382, -0.053833, -0.053619, -0.053497, -0.053223, -0.052948, -0.052612, -0.052765, -0.052917, -0.052765, -0.052246, -0.052002, -0.051910, -0.051697, -0.051392, -0.051147, -0.050781, -0.050354, -0.049927, -0.049500, -0.049072, -0.048706, -0.048218, -0.047760, -0.047302, -0.046875, -0.046295, -0.045776, -0.045288, -0.044830, -0.044495, -0.044159, -0.043823, -0.043518, -0.043213, -0.042877, -0.042603, -0.042236, -0.041779, -0.041321, -0.040985, -0.040863, -0.040771, -0.040802, -0.040497, -0.040222, -0.039978, -0.039703, -0.039642, -0.039307, -0.039093, -0.038544, -0.038055, -0.037689, -0.037506, -0.037079, -0.036743, -0.036407, -0.035919, -0.035431, -0.034912, -0.034668, -0.034607, -0.034424, -0.034302, -0.034180, -0.034119, -0.034393, -0.034729, -0.034698, -0.034760, -0.034912, -0.035156, -0.034882, -0.034485, -0.034302, -0.034149, -0.033905, -0.033783, -0.033539, -0.033020, -0.032715, -0.032349, -0.032074, -0.031769, -0.031555, -0.031250, -0.030945, -0.030609, -0.030243, -0.029846, -0.029510, -0.029144, -0.028687, -0.028412, -0.028137, -0.027985, -0.027924, -0.027985, -0.028107, -0.028290, -0.028595, -0.028717, -0.028778, -0.028778, -0.028870, -0.028931, -0.028900, -0.028870, -0.028839, -0.028748, -0.028809, -0.028900, -0.028809, -0.028656, -0.028503, -0.028412, -0.028290, -0.028198, -0.028046, -0.027618, -0.027191, -0.026855, -0.026520, -0.026276, -0.026184, -0.026001, -0.025787, -0.025543, -0.025299, -0.025055, -0.024628, -0.024231, -0.023895, -0.023621, -0.023407, -0.023315, -0.023224, -0.022980, -0.022736, -0.022552, -0.022400, -0.022247, -0.022064, -0.021912, -0.022278, -0.022644, -0.023010, -0.023407, -0.023651, -0.023682, -0.023712, -0.023285, -0.022797, -0.022522, -0.022339, -0.022186, -0.022186, -0.022186, -0.022125, -0.022003, -0.021881, -0.021576, -0.021271, -0.021088, -0.020874, -0.020630, -0.020355, -0.020081, -0.019745, -0.019409, -0.019165, -0.018951, -0.018738, -0.018585, -0.018402, -0.018219, -0.018005, -0.017822, -0.017670, -0.017517, -0.017212, -0.016815, -0.016449, -0.016083, -0.015717, -0.015320, -0.014954, -0.014587, -0.014313, -0.014069, -0.013702, -0.013275, -0.012848, -0.012482, -0.012146, -0.011810, -0.011505, -0.011230, -0.010864, -0.010468, -0.010101, -0.009857, -0.009613, -0.009338, -0.009033, -0.008759, -0.008545, -0.008362, -0.008179, -0.008057, -0.007904, -0.007782, -0.007660, -0.007538, -0.007324, -0.007111, -0.006897, -0.006744, -0.006592, -0.006378, -0.006073, -0.005798, -0.005463, -0.005127, -0.004761, -0.004364, -0.003967, -0.003662, -0.003693, -0.003693, -0.003784, -0.004028, -0.004242, -0.004425, -0.004547, -0.004700, -0.005005 }; static float vinyl_R[3552] = { -0.000305, -0.000183, -0.000519, -0.000580, -0.000641, -0.000610, -0.000458, -0.000580, -0.000885, -0.001038, -0.000610, -0.001007, -0.001495, -0.000885, 0.001404, 0.009827, 0.024658, 0.042236, 0.056183, 0.063202, 0.067139, 0.077423, 0.097473, 0.121887, 0.145264, 0.168518, 0.189636, 0.207275, 0.219055, 0.227570, 0.237030, 0.247925, 0.261322, 0.276428, 0.295074, 0.312866, 0.332672, 0.352966, 0.373932, 0.394745, 0.414642, 0.432983, 0.450623, 0.466858, 0.485748, 0.503601, 0.520233, 0.535522, 0.550232, 0.562927, 0.574493, 0.584320, 0.593903, 0.604675, 0.615326, 0.627136, 0.639221, 0.653381, 0.668152, 0.682861, 0.696045, 0.708221, 0.719147, 0.729248, 0.739807, 0.750153, 0.759186, 0.767609, 0.775726, 0.783936, 0.792603, 0.800415, 0.805939, 0.811188, 0.813782, 0.814148, 0.811798, 0.805756, 0.794373, 0.774078, 0.742615, 0.694641, 0.626953, 0.535767, 0.427795, 0.317657, 0.208618, 0.107605, 0.010803, -0.083038, -0.175812, -0.283875, -0.388977, -0.423706, -0.394592, -0.398895, -0.366058, -0.336151, -0.354034, -0.322968, -0.327515, -0.322052, -0.330048, -0.347443, -0.376251, -0.424286, -0.480591, -0.532471, -0.576599, -0.623199, -0.655853, -0.677551, -0.695435, -0.717346, -0.726532, -0.729279, -0.718994, -0.695343, -0.678436, -0.667908, -0.648193, -0.625519, -0.610046, -0.602142, -0.593170, -0.577850, -0.565887, -0.552979, -0.539032, -0.523682, -0.508881, -0.497101, -0.483002, -0.469116, -0.456909, -0.446594, -0.435638, -0.422882, -0.410278, -0.397919, -0.384857, -0.370270, -0.355530, -0.339874, -0.324738, -0.306274, -0.282745, -0.251923, -0.209595, -0.155853, -0.095581, -0.027832, 0.049896, 0.136810, 0.225983, 0.312439, 0.394714, 0.464935, 0.520081, 0.552002, 0.556427, 0.533081, 0.487274, 0.423431, 0.346710, 0.263336, 0.178284, 0.097137, 0.025238, -0.029602, -0.064423, -0.078430, -0.069031, -0.040161, 0.004639, 0.063019, 0.128998, 0.196075, 0.260315, 0.315399, 0.356995, 0.382324, 0.392914, 0.387512, 0.369202, 0.340240, 0.305725, 0.264343, 0.220673, 0.178894, 0.140503, 0.106903, 0.081024, 0.060791, 0.046539, 0.037872, 0.035431, 0.039581, 0.049286, 0.061066, 0.072113, 0.079468, 0.076477, 0.065887, 0.057404, 0.056305, 0.052856, 0.050507, 0.057129, 0.065674, 0.076843, 0.077179, 0.055817, 0.043915, 0.041290, 0.030273, 0.026642, 0.014130, 0.006958, -0.000610, -0.006927, -0.012970, -0.016449, -0.019562, -0.013428, 0.001007, 0.028107, 0.065277, 0.117340, 0.192200, 0.273621, 0.340271, 0.381073, 0.396698, 0.395111, 0.380371, 0.334015, 0.256714, 0.227875, 0.209290, 0.179474, 0.183075, 0.161438, 0.146271, 0.127258, 0.113098, 0.092560, 0.076294, 0.054810, 0.032990, 0.006989, -0.018768, -0.041992, -0.066406, -0.083801, -0.100647, -0.111908, -0.116394, -0.113617, -0.116730, -0.114502, -0.108612, -0.103729, -0.092010, -0.081604, -0.080811, -0.088776, -0.100250, -0.113861, -0.123535, -0.128571, -0.137634, -0.136658, -0.144501, -0.146362, -0.149841, -0.149567, -0.150330, -0.152740, -0.155792, -0.159515, -0.163055, -0.170868, -0.182617, -0.194275, -0.210327, -0.223969, -0.238586, -0.252380, -0.267639, -0.282257, -0.294189, -0.304504, -0.311310, -0.317017, -0.319916, -0.321869, -0.322174, -0.322174, -0.321228, -0.319855, -0.319275, -0.314758, -0.309845, -0.308167, -0.309326, -0.309387, -0.308533, -0.306152, -0.302795, -0.300781, -0.301575, -0.304382, -0.306000, -0.306519, -0.307098, -0.312134, -0.322235, -0.332794, -0.339478, -0.345917, -0.352020, -0.356415, -0.362396, -0.365417, -0.366058, -0.365570, -0.363373, -0.360016, -0.355896, -0.349670, -0.342834, -0.335876, -0.329437, -0.324829, -0.317780, -0.311279, -0.307281, -0.302643, -0.300110, -0.297180, -0.295074, -0.295319, -0.298370, -0.303528, -0.309662, -0.316650, -0.322601, -0.328430, -0.330994, -0.334564, -0.340637, -0.345276, -0.350952, -0.355652, -0.358002, -0.358734, -0.356049, -0.351471, -0.345795, -0.340271, -0.337280, -0.335358, -0.332642, -0.330536, -0.328949, -0.328918, -0.329987, -0.331482, -0.334229, -0.336517, -0.339142, -0.341064, -0.343445, -0.346313, -0.348511, -0.351227, -0.351654, -0.352661, -0.354218, -0.355682, -0.356262, -0.355652, -0.353607, -0.351379, -0.347778, -0.343018, -0.338257, -0.333130, -0.327179, -0.321716, -0.318085, -0.315704, -0.312836, -0.309967, -0.308014, -0.307251, -0.306396, -0.304565, -0.303345, -0.302185, -0.299896, -0.297058, -0.291718, -0.285126, -0.278687, -0.272400, -0.266876, -0.262634, -0.258301, -0.254425, -0.249786, -0.245789, -0.240906, -0.237000, -0.234192, -0.231293, -0.229034, -0.225922, -0.221497, -0.214966, -0.209747, -0.205200, -0.200836, -0.195709, -0.189331, -0.182343, -0.177185, -0.171783, -0.165894, -0.158813, -0.150818, -0.144104, -0.137970, -0.132019, -0.125275, -0.117828, -0.110107, -0.103424, -0.098206, -0.092865, -0.088531, -0.085266, -0.081665, -0.078857, -0.078217, -0.077911, -0.076141, -0.076782, -0.077606, -0.076477, -0.074219, -0.070282, -0.066956, -0.064056, -0.060364, -0.056122, -0.052307, -0.047974, -0.044128, -0.040131, -0.036499, -0.032684, -0.029266, -0.024750, -0.020905, -0.017487, -0.015656, -0.014282, -0.013580, -0.013550, -0.014038, -0.015442, -0.017334, -0.018127, -0.018005, -0.018311, -0.018738, -0.019775, -0.019745, -0.019440, -0.018860, -0.018005, -0.016113, -0.015045, -0.012604, -0.010162, -0.008270, -0.006378, -0.004944, -0.004364, -0.003448, -0.002533, -0.001831, -0.001465, -0.001678, -0.001587, -0.000031, 0.001068, 0.002625, 0.003754, 0.006042, 0.008392, 0.011017, 0.012512, 0.013275, 0.014282, 0.014832, 0.015900, 0.017151, 0.018158, 0.019012, 0.019989, 0.021942, 0.023987, 0.025879, 0.027771, 0.029968, 0.033081, 0.036072, 0.038818, 0.041565, 0.044006, 0.046600, 0.049591, 0.052155, 0.054657, 0.058197, 0.061768, 0.066254, 0.071381, 0.076447, 0.080780, 0.085419, 0.089111, 0.092682, 0.097015, 0.101440, 0.104218, 0.106354, 0.108612, 0.111420, 0.114197, 0.116394, 0.119232, 0.121582, 0.125397, 0.129028, 0.131897, 0.134888, 0.136932, 0.139343, 0.142853, 0.146515, 0.149414, 0.153534, 0.156219, 0.158356, 0.162781, 0.167511, 0.171509, 0.174438, 0.177399, 0.180786, 0.184052, 0.186768, 0.189087, 0.190674, 0.193115, 0.194916, 0.195831, 0.197083, 0.197784, 0.198486, 0.199707, 0.200073, 0.199890, 0.200378, 0.200653, 0.201721, 0.202942, 0.203827, 0.204773, 0.205444, 0.206177, 0.207581, 0.209290, 0.210754, 0.211761, 0.213318, 0.215027, 0.217102, 0.218079, 0.218689, 0.219391, 0.219849, 0.220673, 0.221252, 0.221130, 0.220642, 0.219208, 0.217896, 0.216919, 0.215485, 0.213928, 0.212280, 0.210846, 0.209930, 0.209442, 0.208344, 0.207581, 0.206573, 0.206573, 0.206299, 0.206482, 0.205994, 0.206268, 0.206848, 0.207428, 0.208557, 0.209869, 0.209503, 0.210144, 0.211090, 0.212616, 0.213531, 0.213196, 0.213043, 0.213013, 0.212952, 0.212494, 0.211914, 0.210297, 0.209076, 0.207611, 0.206848, 0.205200, 0.203247, 0.200989, 0.199219, 0.197632, 0.197144, 0.195618, 0.194427, 0.193756, 0.193054, 0.192993, 0.192993, 0.192657, 0.192047, 0.191376, 0.191101, 0.191193, 0.190369, 0.189117, 0.188019, 0.187012, 0.186340, 0.185486, 0.184052, 0.182709, 0.181549, 0.180206, 0.178986, 0.176971, 0.174835, 0.172241, 0.169769, 0.168060, 0.165741, 0.162659, 0.159912, 0.157410, 0.154449, 0.152557, 0.149963, 0.147278, 0.145294, 0.143677, 0.143524, 0.142242, 0.139954, 0.137451, 0.134674, 0.132385, 0.131500, 0.130554, 0.128693, 0.127747, 0.126282, 0.124725, 0.124054, 0.122437, 0.120544, 0.117706, 0.114929, 0.113281, 0.110596, 0.107483, 0.103271, 0.099640, 0.097137, 0.094360, 0.090729, 0.087402, 0.083740, 0.080048, 0.076843, 0.074066, 0.070831, 0.067657, 0.064789, 0.061768, 0.059540, 0.057098, 0.054504, 0.052216, 0.050140, 0.048157, 0.046356, 0.043823, 0.041870, 0.039398, 0.037354, 0.035583, 0.033203, 0.030334, 0.027496, 0.024353, 0.022064, 0.019318, 0.016022, 0.013123, 0.009644, 0.006409, 0.003601, 0.000458, -0.002258, -0.005707, -0.008209, -0.010071, -0.011383, -0.013855, -0.015747, -0.018036, -0.020355, -0.021545, -0.023071, -0.024994, -0.026306, -0.027771, -0.029083, -0.030121, -0.031494, -0.032715, -0.034271, -0.035400, -0.036072, -0.036987, -0.038574, -0.039825, -0.041229, -0.042664, -0.043579, -0.045044, -0.046875, -0.048645, -0.050568, -0.051575, -0.052429, -0.053864, -0.054901, -0.055939, -0.057343, -0.057526, -0.058685, -0.059998, -0.061432, -0.062683, -0.063507, -0.063293, -0.063568, -0.065247, -0.066071, -0.067322, -0.068146, -0.069427, -0.070862, -0.073395, -0.075775, -0.075928, -0.075134, -0.076050, -0.076904, -0.077759, -0.078461, -0.079315, -0.080811, -0.081055, -0.081726, -0.083160, -0.083160, -0.082642, -0.083527, -0.085510, -0.087646, -0.088623, -0.088257, -0.088715, -0.089417, -0.089691, -0.090790, -0.090942, -0.090088, -0.090149, -0.090698, -0.090942, -0.090424, -0.089142, -0.088257, -0.088379, -0.089142, -0.089478, -0.089935, -0.090057, -0.089813, -0.090546, -0.092224, -0.092316, -0.092407, -0.092804, -0.093842, -0.094147, -0.093567, -0.092560, -0.092102, -0.091919, -0.089935, -0.089233, -0.087433, -0.085388, -0.083527, -0.082306, -0.080109, -0.077515, -0.075073, -0.072601, -0.071045, -0.069702, -0.068146, -0.066711, -0.065216, -0.063446, -0.062347, -0.060669, -0.058746, -0.057068, -0.056030, -0.054657, -0.053528, -0.052368, -0.051300, -0.050018, -0.047638, -0.046265, -0.044678, -0.043396, -0.042542, -0.041534, -0.039734, -0.037872, -0.035797, -0.034790, -0.033112, -0.030884, -0.029175, -0.027466, -0.025940, -0.024750, -0.023041, -0.021301, -0.019592, -0.018402, -0.017609, -0.017273, -0.016815, -0.016266, -0.015411, -0.014618, -0.014130, -0.013123, -0.012115, -0.010590, -0.009521, -0.008789, -0.007416, -0.005615, -0.004364, -0.002777, -0.002197, -0.001373, -0.000031, 0.000397, 0.001251, 0.001465, 0.001007, 0.001373, 0.001801, 0.001770, 0.000732, 0.001251, 0.001831, 0.002625, 0.003174, 0.004333, 0.005463, 0.005768, 0.006561, 0.007080, 0.007141, 0.006805, 0.006897, 0.006622, 0.006714, 0.007111, 0.006805, 0.006958, 0.006653, 0.007111, 0.007416, 0.007782, 0.007629, 0.008484, 0.008728, 0.009216, 0.009796, 0.009644, 0.009247, 0.009399, 0.008972, 0.008850, 0.009125, 0.008789, 0.008911, 0.008423, 0.007965, 0.008392, 0.008331, 0.008331, 0.008484, 0.008789, 0.009705, 0.010101, 0.010651, 0.011505, 0.012268, 0.012726, 0.013672, 0.013550, 0.014130, 0.014709, 0.015442, 0.016113, 0.015869, 0.015594, 0.015961, 0.015717, 0.014893, 0.014099, 0.012848, 0.011292, 0.009583, 0.008270, 0.007538, 0.006500, 0.004822, 0.004181, 0.003387, 0.002625, 0.001831, 0.000916, -0.000305, -0.001190, -0.002411, -0.002838, -0.003174, -0.003540, -0.004364, -0.005188, -0.005615, -0.005676, -0.006348, -0.007080, -0.007690, -0.008545, -0.009003, -0.009491, -0.011017, -0.012817, -0.014984, -0.016479, -0.018402, -0.020142, -0.022125, -0.024139, -0.025787, -0.027191, -0.028381, -0.029480, -0.030762, -0.031250, -0.032104, -0.032196, -0.032623, -0.033478, -0.034546, -0.035583, -0.036438, -0.037354, -0.038422, -0.040039, -0.041412, -0.042542, -0.043671, -0.045197, -0.047028, -0.048737, -0.049866, -0.051514, -0.052795, -0.054016, -0.056122, -0.057770, -0.058990, -0.059845, -0.060577, -0.061523, -0.062012, -0.062531, -0.062256, -0.062347, -0.062683, -0.063385, -0.064056, -0.064850, -0.065887, -0.066528, -0.067963, -0.069611, -0.071167, -0.072968, -0.074310, -0.075989, -0.077148, -0.077332, -0.078003, -0.078278, -0.078522, -0.079071, -0.078766, -0.078156, -0.077301, -0.076996, -0.076447, -0.076752, -0.077332, -0.077911, -0.078369, -0.079285, -0.079895, -0.080597, -0.081726, -0.082489, -0.083221, -0.083984, -0.085114, -0.086212, -0.087708, -0.088043, -0.087982, -0.087830, -0.088043, -0.087708, -0.086914, -0.086090, -0.085358, -0.085083, -0.085114, -0.083954, -0.083496, -0.082489, -0.081635, -0.080719, -0.080170, -0.079315, -0.078339, -0.077637, -0.077362, -0.077759, -0.078613, -0.077576, -0.075897, -0.075134, -0.075073, -0.074768, -0.074493, -0.073730, -0.073425, -0.073547, -0.073456, -0.073456, -0.073059, -0.071564, -0.070526, -0.070312, -0.069550, -0.068542, -0.066559, -0.064636, -0.062958, -0.061707, -0.059540, -0.057404, -0.054779, -0.052673, -0.050323, -0.048218, -0.046631, -0.044189, -0.041870, -0.041168, -0.039734, -0.038666, -0.037292, -0.035431, -0.034058, -0.032898, -0.031311, -0.030182, -0.028015, -0.025604, -0.023468, -0.021484, -0.019592, -0.017700, -0.015564, -0.013550, -0.012604, -0.011169, -0.010590, -0.010101, -0.008698, -0.007629, -0.006805, -0.005402, -0.003937, -0.001648, 0.000458, 0.002594, 0.004852, 0.007538, 0.010132, 0.013214, 0.015472, 0.018402, 0.020355, 0.022888, 0.025879, 0.027832, 0.028656, 0.029907, 0.030182, 0.030975, 0.032074, 0.032135, 0.032135, 0.032623, 0.033508, 0.035492, 0.037872, 0.039307, 0.041016, 0.043030, 0.045868, 0.048645, 0.051666, 0.053650, 0.055481, 0.057343, 0.059631, 0.061829, 0.063354, 0.064209, 0.064880, 0.065735, 0.066711, 0.067383, 0.067596, 0.068390, 0.069031, 0.070404, 0.072021, 0.073578, 0.075226, 0.077179, 0.079376, 0.082336, 0.084778, 0.086121, 0.087494, 0.089813, 0.092682, 0.095245, 0.096527, 0.097809, 0.099152, 0.099823, 0.101074, 0.101837, 0.102142, 0.102020, 0.102417, 0.103760, 0.105225, 0.106323, 0.107452, 0.107971, 0.109589, 0.111206, 0.112488, 0.113678, 0.114563, 0.115692, 0.116730, 0.118225, 0.119446, 0.120667, 0.120544, 0.121368, 0.121979, 0.122742, 0.122803, 0.123169, 0.123230, 0.123810, 0.123993, 0.124847, 0.124756, 0.125153, 0.125397, 0.125702, 0.126678, 0.127563, 0.128113, 0.128632, 0.129364, 0.130432, 0.131042, 0.131592, 0.131653, 0.132019, 0.132599, 0.132904, 0.133789, 0.134186, 0.133514, 0.133606, 0.134064, 0.134613, 0.134918, 0.134216, 0.134064, 0.134003, 0.134491, 0.134766, 0.134583, 0.133545, 0.132904, 0.132812, 0.132660, 0.132141, 0.130585, 0.129486, 0.128937, 0.129028, 0.129669, 0.128937, 0.128174, 0.127228, 0.127197, 0.127014, 0.125732, 0.123627, 0.121643, 0.120636, 0.119781, 0.118591, 0.116425, 0.114471, 0.113007, 0.112305, 0.111023, 0.109161, 0.107941, 0.106171, 0.104950, 0.104431, 0.103546, 0.102783, 0.101654, 0.100372, 0.099091, 0.097626, 0.095062, 0.092896, 0.090790, 0.089142, 0.087677, 0.085358, 0.082672, 0.080231, 0.078278, 0.076111, 0.073517, 0.071106, 0.068542, 0.066498, 0.065125, 0.063477, 0.061890, 0.059906, 0.058411, 0.056976, 0.055573, 0.053833, 0.051666, 0.049438, 0.047119, 0.045074, 0.042633, 0.040131, 0.037231, 0.034546, 0.032074, 0.029938, 0.027771, 0.025482, 0.023376, 0.020752, 0.018768, 0.016907, 0.015106, 0.013336, 0.011444, 0.009399, 0.007904, 0.006622, 0.004364, 0.002289, 0.000305, -0.000732, -0.002289, -0.003632, -0.005280, -0.007385, -0.009186, -0.010376, -0.012024, -0.013489, -0.015503, -0.017517, -0.019073, -0.019989, -0.021759, -0.023712, -0.025635, -0.027405, -0.028473, -0.029755, -0.030426, -0.031494, -0.032928, -0.033752, -0.034546, -0.035858, -0.037323, -0.039368, -0.040497, -0.041138, -0.042206, -0.043121, -0.044434, -0.045715, -0.046692, -0.047485, -0.048187, -0.048981, -0.049988, -0.051208, -0.052490, -0.053253, -0.053375, -0.053833, -0.054688, -0.055420, -0.055939, -0.056824, -0.057556, -0.058014, -0.058990, -0.059021, -0.059570, -0.060364, -0.061279, -0.061920, -0.062775, -0.063049, -0.063629, -0.064392, -0.065247, -0.065887, -0.066132, -0.066254, -0.066711, -0.066986, -0.067474, -0.067413, -0.067444, -0.067352, -0.067810, -0.068268, -0.068848, -0.068878, -0.068787, -0.068451, -0.068268, -0.068665, -0.068848, -0.068787, -0.068542, -0.068695, -0.069031, -0.069702, -0.070068, -0.070374, -0.071106, -0.071808, -0.072510, -0.073120, -0.073425, -0.073608, -0.074066, -0.074585, -0.075043, -0.075256, -0.074677, -0.074402, -0.074249, -0.074127, -0.073822, -0.073273, -0.072815, -0.072266, -0.071747, -0.071442, -0.070984, -0.070587, -0.070526, -0.070557, -0.071014, -0.071289, -0.071167, -0.070770, -0.070404, -0.069977, -0.069794, -0.069489, -0.069122, -0.069122, -0.068726, -0.068695, -0.068390, -0.067902, -0.067383, -0.066833, -0.066742, -0.066742, -0.066650, -0.066254, -0.065796, -0.065704, -0.065643, -0.065857, -0.065613, -0.065643, -0.065491, -0.065399, -0.065399, -0.065369, -0.064575, -0.064026, -0.063965, -0.063721, -0.063782, -0.063690, -0.063416, -0.063416, -0.063141, -0.062836, -0.062561, -0.062195, -0.061951, -0.061584, -0.061279, -0.061035, -0.060486, -0.059601, -0.058838, -0.058350, -0.057831, -0.057159, -0.056427, -0.055756, -0.055450, -0.055420, -0.055450, -0.055267, -0.054962, -0.054871, -0.054749, -0.054901, -0.055054, -0.054871, -0.054871, -0.054474, -0.054169, -0.053864, -0.053375, -0.052979, -0.052368, -0.052063, -0.052032, -0.052002, -0.051697, -0.051422, -0.051331, -0.051178, -0.051392, -0.051086, -0.050598, -0.050476, -0.050476, -0.050293, -0.050171, -0.049774, -0.049103, -0.048676, -0.048309, -0.047974, -0.047699, -0.047211, -0.046906, -0.046570, -0.046204, -0.045837, -0.045166, -0.044617, -0.044037, -0.043610, -0.043549, -0.043396, -0.042999, -0.042786, -0.042694, -0.042389, -0.041931, -0.041504, -0.041077, -0.040710, -0.040497, -0.040497, -0.040436, -0.040283, -0.040192, -0.040253, -0.040131, -0.039612, -0.039124, -0.038666, -0.038300, -0.038147, -0.037842, -0.037537, -0.037140, -0.037048, -0.036713, -0.036469, -0.036072, -0.035492, -0.035187, -0.035065, -0.034912, -0.034851, -0.034882, -0.034851, -0.034882, -0.035065, -0.034973, -0.034912, -0.034821, -0.034698, -0.034485, -0.034210, -0.034119, -0.034058, -0.033844, -0.033752, -0.033508, -0.033051, -0.032623, -0.032074, -0.031525, -0.031128, -0.030823, -0.030762, -0.030640, -0.030426, -0.030182, -0.029755, -0.029449, -0.029114, -0.028595, -0.028046, -0.027496, -0.027252, -0.027130, -0.027313, -0.027405, -0.027588, -0.027924, -0.028107, -0.028198, -0.028229, -0.028076, -0.027954, -0.027985, -0.028015, -0.028015, -0.027985, -0.028076, -0.028290, -0.028290, -0.028229, -0.027985, -0.027557, -0.027222, -0.027161, -0.027069, -0.026672, -0.026245, -0.025909, -0.025574, -0.025391, -0.025269, -0.025146, -0.024841, -0.024536, -0.024292, -0.024017, -0.023560, -0.023041, -0.022644, -0.022400, -0.022186, -0.022186, -0.022186, -0.022064, -0.021973, -0.021698, -0.021393, -0.021118, -0.020905, -0.020660, -0.020905, -0.021149, -0.021301, -0.021423, -0.021576, -0.021851, -0.022095, -0.021912, -0.021667, -0.021393, -0.021057, -0.020782, -0.020660, -0.020538, -0.020477, -0.020386, -0.020325, -0.020172, -0.019989, -0.019958, -0.019928, -0.019775, -0.019531, -0.019257, -0.018677, -0.018097, -0.017761, -0.017517, -0.017334, -0.017242, -0.017181, -0.017120, -0.017090, -0.017059, -0.016907, -0.016724, -0.016296, -0.015747, -0.015198, -0.014862, -0.014526, -0.014160, -0.013794, -0.013428, -0.013123, -0.012848, -0.012604, -0.012390, -0.012177, -0.011719, -0.011261, -0.010834, -0.010529, -0.010223, -0.009888, -0.009552, -0.009216, -0.008911, -0.008606, -0.008453, -0.008392, -0.008331, -0.008270, -0.008240, -0.008148, -0.007812, -0.007507, -0.007233, -0.006989, -0.006775, -0.006622, -0.006500, -0.006378, -0.006287, -0.006195, -0.006073, -0.005951, -0.005798, -0.005524, -0.005157, -0.004791, -0.004517, -0.004211, -0.003967, -0.003967, -0.003937, -0.003998, -0.004150, -0.004303, -0.004578, -0.004944, -0.005310, -0.005524 }; struct filechunk vinyl = { NULL, NULL, NULL, 0, DS_PRIORITY_NORMAL, 2, 0, 3552, 3552, 1, (float*)&vinyl_L, (float*)&vinyl_R }; kluppe-0.6.14/src/common/looperdata.h0000644000175000017500000001722311032254353017001 0ustar dieterdieter/* definitions for a looper */ #ifndef __LOOPERDATA_H__ #define __LOOPERDATA_H__ #include #include "buffer.h" #include "speciallist.h" #define GRAINPITCH_AUTO 1 #define GRAINPITCH_RANGE 2 #define GRAINPITCH_CHORD 3 #define THRESHOLDSTATE_LOW 0 #define THRESHOLDSTATE_HIGH 1 #define THRESHOLDSTATE_ANY 2 enum { LOOP_PLAYMODE_LOOP, LOOP_PLAYMODE_BACKFORTH, LOOP_PLAYMODE_SINE, LOOP_PLAYMODE_CUSTOMSPEED, LOOP_PLAYMODE_POSITION, LOOP_PLAYMODE_EXTERNALPOS, LOOP_PLAYMODE_ONCE, LOOP_PLAYMODE_LAST }; enum { LOOP_RECMODE_LOOP, LOOP_RECMODE_ONCE, LOOP_RECMODE_LAST }; typedef struct _looper_data { /* GMutex *looperdatamutex; */ pthread_mutex_t looperdatamutex; buffer_info_t *buf; buffer_info_t *clickmode_buf; int buffer_group; int id; int looper_id; long samplerate; int playmode; int recmode; double speed; double modespeed; float vol; float pan; float panswing; float panpos; float pandir; float Lfact; float Rfact; float recmix; float recmixnew; float recmixorig; float playvuL; float playvuR; float recvuL; float recvuR; float inmaxL; float inmaxR; float outmaxL; float outmaxR; double playpos; double playindex; long recpos; float pointer; long loopstart; long loopend; long recstart; long recend; int isplaying; int isrecording; int linkrec2play; int grainpitchmode; double grainpitchbend; double stereodiversity; int keepabsolute; int limiter; float limit; float limknee; float limconst; int cm_size; float cm_min; float cm_max; float* customplaymode; int midichannel; double low_threshold; double high_threshold; int thresholdstate; int thresholdmode; float* threshring; int threshringsize; int threshringptr; /* reverb */ buffer_info_t *reverb; long reverblength; long revpos; double feedback; /* the granular player part */ int ngrains; int graindensity; float grainmixfactor; double mingrainspeed; double maxgrainspeed; long mingrainlength; long maxgrainlength; long* grainindexes; double* grainspeeds; double* grainpitchtable; double* grainpitchvolumes; double* grainpansL; double* grainpansR; long* grainoffsets; long* grainsizes; int* grainfadelengths; int* grainsactive; /* list of bufferchanges */ /* GList* dirtylist;*/ speciallist_t* dirtylist; } looper_data_t; looper_data_t* looperdata_new(buffer_info_t* buf, long samplerate, int id); void looperdata_free(looper_data_t* data); void looperdata_lock(looper_data_t* data); void looperdata_unlock(looper_data_t* data); void looperdata_copy_settings (looper_data_t* dst, looper_data_t* src); void looperdata_set_clickmode_buf(looper_data_t* data, buffer_info_t* buf); buffer_info_t* looperdata_get_clickmode_buf(looper_data_t* data); void looperdata_write_dirtyblock(looper_data_t* data, double start, double end); int looperdata_read_once_dirtyblock(looper_data_t* data, double* start, double* end); void looperdata_set_playing(looper_data_t* data, int isplaying); void looperdata_set_recording(looper_data_t* data, int isrecording); int looperdata_get_playing(looper_data_t* data); int looperdata_get_recording(looper_data_t* data); void looperdata_set_vol(looper_data_t* data, float vol); float looperdata_get_vol(looper_data_t* data); void looperdata_set_pan(looper_data_t* data, float pan); void looperdata_set_panswing(looper_data_t* data, float pan); void looperdata_set_recmix(looper_data_t* data, float recmix); float looperdata_get_recmix(looper_data_t* data); void looperdata_set_loopstart(looper_data_t* data, long start); long looperdata_get_loopstart(looper_data_t* data); void looperdata_set_loopend(looper_data_t* data, long end); long looperdata_get_loopend(looper_data_t* data); void looperdata_set_recstart(looper_data_t* data, long start); long looperdata_get_recstart(looper_data_t* data); void looperdata_set_recend(looper_data_t* data, long end); long looperdata_get_recend(looper_data_t* data); void looperdata_set_mingrainspeed(looper_data_t* data,double speed); void looperdata_set_maxgrainspeed(looper_data_t* data,double speed); void looperdata_set_mingrainlength(looper_data_t* data,long length); void looperdata_set_maxgrainlength(looper_data_t* data,long length); void looperdata_set_graindensity(looper_data_t* data,int density); void looperdata_set_playmode(looper_data_t* data,int mode); void looperdata_set_recmode(looper_data_t* data,int mode); void looperdata_set_playpos(looper_data_t* data, double playpos); void looperdata_set_recpos(looper_data_t* data, long recpos); void looperdata_set_grainpitchmode (looper_data_t* data, int mode); int looperdata_get_grainpitchmode (looper_data_t* data); void looperdata_set_grainpitchtablevalue (looper_data_t* data, double value, double vol); void looperdata_set_grainpitchbend (looper_data_t* data, double bend); double looperdata_get_mingrainspeed(looper_data_t* data); double looperdata_get_maxgrainspeed(looper_data_t* data); long looperdata_get_mingrainlength(looper_data_t* data); long looperdata_get_maxgrainlength(looper_data_t* data); int looperdata_get_graindensity(looper_data_t* data); void looperdata_set_stereodiversity(looper_data_t* data, double diversity); double looperdata_get_stereodiversity(looper_data_t* data); void looperdata_set_reverblength(looper_data_t* data, long length); long looperdata_get_reverblength(looper_data_t* data); void looperdata_set_feedback(looper_data_t* data, double feedback); double looperdata_get_feedback(looper_data_t* data); void looperdata_set_speed(looper_data_t* data, double speed); int looperdata_get_limiter(looper_data_t* data); void looperdata_set_limiter(looper_data_t* data, int limiter); float looperdata_get_limknee(looper_data_t* data); void looperdata_set_limknee(looper_data_t* data, float limknee); float looperdata_get_limit(looper_data_t* data); void looperdata_set_limit(looper_data_t* data, float limit); double looperdata_get_speed(looper_data_t* data); double looperdata_get_playpos(looper_data_t* data); long looperdata_get_recpos(looper_data_t* data); int looperdata_get_cm_size(looper_data_t* data); char* looperdata_cm2str (looper_data_t* data, char* str); void looperdata_str2cm (looper_data_t* data, char* str, int cm_size); int looperdata_get_thresholdmode(looper_data_t* data); void looperdata_set_thresholdmode(looper_data_t* data, int mode); double looperdata_get_low_threshold(looper_data_t* data); void looperdata_set_low_threshold(looper_data_t* data, double low); double looperdata_get_high_threshold(looper_data_t* data); void looperdata_set_high_threshold(looper_data_t* data, double high); int looperdata_get_thresholdbuffersize(looper_data_t* data); void looperdata_set_thresholdbuffersize(looper_data_t* data, int size); void looperdata_get_playmeters(looper_data_t* data,float* L,float* R); void looperdata_get_recmeters(looper_data_t* data,float* L,float* R); /*void looperdata_write_sample(looper_data_t* data,float* L, float* R);*/ void looperdata_write_sampleblock(looper_data_t* data, long size, float* Lbuf, float* Rbuf); /*void looperdata_calc_sample(looper_data_t* data,float* L, float* R);*/ void looperdata_calc_sampleblock(looper_data_t* data, long size, float* Lbuf, float* Rbuf, float* Pbuf,int do_play, int do_rec); void looperdata_set_pointer(looper_data_t* data, float *P); void looperdata_get_pointer(looper_data_t* data, float *P); /* granular player functions */ int looperdata_get_ngrains (looper_data_t* data); void looperdata_set_ngrains (looper_data_t* data, int ngrains); void looperdata_set_grainlength (looper_data_t* data, long length); int looperdata_get_midichannel (looper_data_t* data); void looperdata_set_midichannel (looper_data_t* data, int channel); #endif kluppe-0.6.14/src/common/filechunk.c0000644000175000017500000002144310660633461016620 0ustar dieterdieter/* soundfile i/o */ #include #include #include #include #include #include #include #include #include "interpol.h" #include "filechunk.h" #include "speciallist.h" #define MAXBLOCKSIZE 65536 filechunk_t* filechunk_new(char* filename){ filechunk_t* fc = (filechunk_t*) malloc(sizeof(filechunk_t)); fc->start = 0; fc->end = 0; fc->length = 0; fc->done = 0; fc->sf = 0; fc->group = 0; fc->channels = 2; fc->sfinfo = NULL; fc->filename = NULL; fc->L = NULL; fc->R = NULL; if (filename){ fc->filename = calloc (sizeof(char),strlen(filename) + 1); strncpy (fc->filename, filename, strlen(filename)); fc->sfinfo = (SF_INFO*) malloc(sizeof(SF_INFO)); fc->sf = sf_open (fc->filename, SFM_READ, fc->sfinfo); if ((fc->sf == NULL) || (fc->sfinfo == NULL)){ fprintf (stderr,"could not open soundfile %s\n%s\n",fc->filename,sf_strerror(fc->sf)); free(fc->sfinfo); fc->sfinfo = NULL; free(fc->filename); fc->filename = NULL; return NULL; } fc->length = fc->sfinfo->frames; fc->channels = fc->sfinfo->channels; } return fc; } void filechunk_delete(filechunk_t* fc){ if (!fc) return; /* printf ("delete fc:%s\n",fc->filename);*/ if (fc->sf) sf_close(fc->sf); if (fc->sfinfo) free(fc->sfinfo); if (fc->filename) free(fc->filename); if (fc->L) free(fc->L); if (fc->R) free(fc->R); free(fc); fc = NULL; } long filechunk_get_start (filechunk_t* fc){ if (!fc) return -1; return fc->start; } long filechunk_get_end (filechunk_t* fc){ if (!fc) return -1; return fc->end; } long filechunk_get_length (filechunk_t* fc){ if (!fc) return -1; return fc->length; } long filechunk_get_done (filechunk_t* fc){ if (!fc) return -1; return fc->done; } int filechunk_get_channels (filechunk_t* fc){ if (!fc) return 0; return fc->channels; } void filechunk_set_channels (filechunk_t* fc, int channels){ if (!fc) return; if (fc->sfinfo) return; if (channels == fc->channels) return; if (channels < 1) channels = 1; if (channels > 2) channels = 2; if (channels == 1){ if (fc->R) free(fc->R); fc->R = NULL; fc->channels = channels; }else{ long oldsize = filechunk_get_length(fc); filechunk_resize(fc, 0); fc->channels = channels; filechunk_resize(fc, oldsize); } } long filechunk_get_filelength (filechunk_t* fc){ if (!fc) return 0; if (!fc->sfinfo) return 0; return fc->sfinfo->frames; } long filechunk_get_samplerate (filechunk_t* fc){ if (!fc) return 0; if (!fc->sfinfo) return 0; return fc->sfinfo->samplerate; } int filechunk_get_priority (filechunk_t* fc){ if (!fc) return 0; return fc->priority; } float filechunk_get_sample(filechunk_t* fc, int channel, long sample){ if (channel) return *(fc->R + sample); else return *(fc->L + sample); } void filechunk_write_sample(filechunk_t* fc, int channel, long sample, float value){ if ((channel > 1) && (fc->R)) *(fc->R + sample) = value; else if (fc->L) *(fc->L + sample) = value; } void filechunk_write_sampleblock(filechunk_t* fc, long index, long size, float* Lbuf, float* Rbuf){ if (Lbuf) memcpy ((void*)(fc->L + index), (void*)Lbuf, size * sizeof(float)); if ((fc->channels > 1) && Rbuf) memcpy ((void*)(fc->R + index), (void*)Rbuf, size * sizeof(float)); } long filechunk_resize(filechunk_t* fc, long new_size){ long l,i,max; max = 44100; /* ~1 secs at once */ float* tmp = NULL; if (!new_size){ if (fc->L) free(fc->L); if (fc->R) free(fc->R); fc->L = NULL; fc->R = NULL; fc->length = 0; fc->done = 0; return 0; } if ((getpagesize() * sysconf (_SC_AVPHYS_PAGES)) < (new_size * sizeof(float) * fc->channels)){ if (fc->L) free (fc->L); if (fc->R) free (fc->R); fc->L = NULL; fc->R = NULL; fc->length = 0; fc->done = 0; fprintf(stderr,"not enough memory!\n"); return 0; } for (i = 0;i < (new_size / max);i++){ tmp = (float*) realloc(fc->L, sizeof(float) * (i + 1) * max); if (tmp){ fc->L = tmp; memset ((void*)(fc->L + (i * max)),0,max * sizeof(float)); }else{ free (fc->L); free (fc->R); fc->length = 0; return 0; } if (fc->channels > 1){ tmp = (float*) realloc(fc->R, sizeof(float) * (i + 1) * max); if (tmp){ fc->R = tmp; memset ((void*)(fc->R + (i * max)),0,max * sizeof(float)); }else{ free (fc->L); free (fc->R); fc->length = 0; return 0; } } } l = new_size % max; tmp = (float*) realloc(fc->L, sizeof(float) * (i * max + l)); if (tmp){ fc->L = tmp; memset ((void*)(fc->L + (i * max)),0,l * sizeof(float)); }else{ free (fc->L); free (fc->R); fc->length = 0; return 0; } if (fc->channels > 1){ tmp = (float*) realloc(fc->R, sizeof(float) * (i * max + l)); if (tmp){ fc->R = tmp; memset ((void*)(fc->R + (i * max)),0,l * sizeof(float)); }else{ free (fc->R); free (fc->L); fc->length = 0; return 0; } } fc->length = new_size; /* printf ("length:%ld, L:%d, R:%d\n",fc->length,(int)fc->L,(int)fc->R);*/ return fc->length; } int filechunk_get_group(filechunk_t* fc){ return fc->group; } long filechunk_set (filechunk_t* fc, long start, long end, int priority, int group){ if (!fc) return 0; fc->priority = priority; fc->group = group; if (start > end){ long t = end; end = start; start = t; } if ((start < 0) || (end == start)) return 0; fc->start = start; fc->end = end; if (fc->sfinfo){ if (fc->sfinfo->frames < fc->start){ /* fprintf (stderr,"error: start(%ld) > filesize(%ld)!\n", fc->start, (long)fc->sfinfo->frames); */ fc->start = 0; fc->end = 0; fc->length = 0; fc->done = 0; return 0; } if (fc->sfinfo->frames < fc->end){ fc->end = fc->sfinfo->frames; } } fc->length = fc->end - fc->start; if (fc->sfinfo){ sf_seek(fc->sf,(sf_count_t)fc->start,SEEK_SET); /* if (fc->channels == 1) fc->R = fc->L;*/ if (fc->channels == 1) fc->R = NULL; } if (!filechunk_resize(fc,fc->length)) return 0; /* if (priority == DS_PRIORITY_NONE) fc->done = fc->length; else */fc->done = 0; /* printf ("resized to:%ld, with priority %d and group %d\n",fc->length,fc->priority, fc->group);*/ return fc->length; } long filechunk_read_chunk (filechunk_t* fc){ float* tmp; long l; sf_count_t frames_read = 1; long blocksize = MAXBLOCKSIZE; /* a maximum of 32768 frames at once */ if (!fc->sf) return -1; if ((fc->length - fc->done) < blocksize) blocksize = fc->length - fc->done; tmp = (float*) malloc (sizeof(float) * blocksize * fc->channels); if (tmp == NULL){ fprintf(stderr,"could not allocate enough memory for the temporary buffer\n"); return -1; } /* sf_seek ? */ /* printf ("sf:%d, tmp:%d, size:%ld\n",(int)fc->sf,(int)tmp,blocksize);*/ frames_read = sf_readf_float(fc->sf,tmp,(sf_count_t)blocksize); /* printf ("%ld read, %ld done, size:%ld\n",blocksize, fc->done,fc->length);*/ if (fc->channels > 1){ for (l = 0;l < frames_read;l++){ *(fc->L + l + fc->done) = *(tmp + l * fc->channels); *(fc->R + l + fc->done) = *(tmp + (l * fc->channels + 1)); } }else{ for (l = 0;l < frames_read;l++){ *(fc->L + l + fc->done) = *(tmp + l * fc->channels); } } fc->done += frames_read; free (tmp); return frames_read; } chunk_group_t* chunkgroup_new(int gid, int priority){ chunk_group_t* group = (chunk_group_t*)malloc(sizeof(chunk_group_t)); group->gid = gid; group->priority = priority; group->readfc = NULL; group->nextfc = NULL; group->prevfc = NULL; group->wrapfc = NULL; group->area_start = 0; group->area_end = 0; group->area_bandwith = 0; return group; } void chunkgroup_delete(chunk_group_t* group){ if (!group) return; if (group->readfc) filechunk_delete(group->readfc); if (group->nextfc) filechunk_delete(group->nextfc); if (group->prevfc) filechunk_delete(group->prevfc); if (group->wrapfc) filechunk_delete(group->wrapfc); free(group); } kluppe-0.6.14/src/common/interpol.c0000644000175000017500000000334710652370560016506 0ustar dieterdieter#include #include #include #include "interpol.h" float inter4pol (short* buf, float index, long size){ double frac, a, b, c, d, cminusb; short* fp; long lindex = (long)index; /* 4 point interpolation taken from tabread4~ of pd (pure-data.org) */ if ((float)lindex == index) // no need to interpolate: return (*(buf + lindex) / 32767.); if (!size) return 0.; if (lindex < 1){ lindex = 1, frac = .0; }else if (lindex > (size - 3)){ lindex = size - 3; frac = 1.; }else{ frac = (double)index - lindex; } fp = buf + lindex; a = (double)(fp[-1]) / 32767.; b = (double)(fp[0]) / 32767.; c = (double)(fp[1]) / 32767.; d = (double)(fp[2]) / 32767.; cminusb = c-b; return (float)(b + frac * (cminusb - 0.5f * (frac - 1.) * ((a - d + 3.0f * cminusb) * frac + (b - a - cminusb)))); } float inter4pol_float (float* buf, double index, long size){ double frac, a, b, c, d, cminusb; float* fp; long lindex = (long)index; /* 4 point interpolation taken from tabread4~ of pd (pure-data.org) */ if (!size) return 0.; if ((float)lindex == index) // no need to interpolate: return (*(buf + lindex)); if (lindex < 1){ lindex = 1, frac = .0; }else if (lindex > (size - 3)){ lindex = size - 3; frac = 1.; }else{ frac = index - lindex; } fp = buf + lindex; a = fp[-1]; b = fp[0]; c = fp[1]; d = fp[2]; cminusb = c-b; return (float)(b + frac * (cminusb - 0.5f * (frac - 1.) * ((a - d + 3.0f * cminusb) * frac + (b - a - cminusb)))); } kluppe-0.6.14/src/common/Makefile0000644000175000017500000000043511033630321016125 0ustar dieterdieterSOURCES = speciallist.c interpol.c buffer.c looperdata.c jackmixer.c shuttle.c \ tranzport.c serialio.c midi.c osc.c filechunk.c peakview.c clickmodes.c xsession.c \ alphatrack.c TARGETS = $(SOURCES:.c=.o) common: $(TARGETS) .c.o: $(CC) $(CFLAGS) -c -o $@ $*.c clean: rm -f *.o kluppe-0.6.14/src/common/alphatrack.c0000644000175000017500000002606311034126761016761 0ustar dieterdieter/* * alphatrack.c * alphatrack callback interface * based on transport.c by arthur@artcmusic.com */ #include #include #include #include #include #include "alphatrack.h" #define POLLSIZE 12 #define POLL_INTERVAL 40 /* ms */ void alphatrack_lock(alphatrack_t* z){ pthread_mutex_lock (&z->alphatrackmutex); } void alphatrack_unlock(alphatrack_t* z){ pthread_mutex_unlock (&z->alphatrackmutex); } static int alphatrack_write_core(alphatrack_t *z, uint8_t *cmd){ int val; val = usb_interrupt_write(z->udev, ALPHATRACK_WRITE_ENDPOINT, (char*)cmd, 8, z->polltimeout); if (val < 0) return val; if (val != 8) return -1; return 0; } static int alphatrack_set_nativemode(alphatrack_t *z){ uint8_t nativemodemessage[8]; nativemodemessage[0] = 0xf0; nativemodemessage[1] = 0x00; nativemodemessage[2] = 0x01; nativemodemessage[3] = 0x40; nativemodemessage[4] = 0x20;/* tranzport = 0x10 , manual says f0 00 01 40 20 01 00 f7 */ nativemodemessage[5] = 0x01; nativemodemessage[6] = 0x00; nativemodemessage[7] = 0xf7; return alphatrack_write_core(z, nativemodemessage); } int alphatrack_poll(alphatrack_t *z) { uint8_t buf[POLLSIZE]; uint64_t newbuttons = 0x0LL; int val; memset(buf, 0, POLLSIZE); val = usb_interrupt_read(z->udev, ALPHATRACK_READ_ENDPOINT, (char*)(&buf), POLLSIZE, z->polltimeout); if (val < 0){return val;} if (val != POLLSIZE) {if (val != -110) printf ("poll failed:%d\n",val); return -1;} /* buf[0] empty ??? */ /* buf[1] status ? */ /* buf[2-4] buttons */ /* buf[5] touch + encioder_L + foot*/ /* buf[6-7] fader pos*/ /* buf[8-10 encoders 1 - 3 */ /* touch-strip pos */ z->status = buf[1]; /* 00 for alphatrack, interesting for tranzport */ newbuttons |= buf[5] << 24; newbuttons |= buf[4] << 16; newbuttons |= buf[3] << 8; newbuttons |= buf[2]; newbuttons &= 0xffffffffLL; /* hack:make sure that only bit 0-32 are in use */ /* if (newbuttons) printf ("newbuttons: 0x%010Lx\n",newbuttons);*/ if (buf[8] < 128) z->encoderdelta_l = (int)buf[8]; else if (buf[8] > 127) z->encoderdelta_l = (256 - (int)buf[8]) * -1; if (buf[9] < 128) z->encoderdelta_m = (int)buf[9]; else if (buf[9] > 127) z->encoderdelta_m = (256 - (int)buf[9]) * -1; if (buf[10] < 128) z->encoderdelta_r = (int)buf[10]; else if (buf[10] > 127) z->encoderdelta_r = (256 - (int)buf[10]) * -1; if (z->encoderdelta_l) newbuttons |= ALPHATRACK_DELTA_ENCODER_L; if (z->encoderdelta_m) newbuttons |= ALPHATRACK_DELTA_ENCODER_M; if (z->encoderdelta_r) newbuttons |= ALPHATRACK_DELTA_ENCODER_R; z->buttondiff = z->buttons ^ newbuttons; // XOR z->buttons = newbuttons; if (z->touchpos != buf[11]){ z->touchpos = buf[11]; z->buttondiff |= ALPHATRACK_POS_TOUCHSTRIP; } val = (buf[6] << 2) | (buf[7] >> 2); /* this only happens when fader was moved manually: */ if ((z->faderpos != val) && (buf[5] & 0x40)){ z->faderpos_dirty = val; z->buttondiff |= ALPHATRACK_POS_FADER; } return 0; } int alphatrack_set_faderpos(alphatrack_t *z, int faderpos){ alphatrack_lock(z); z->faderpos_dirty = faderpos; alphatrack_unlock(z); return 0; } static int alphatrack_write_queued (alphatrack_t *z){ /* try to send lcd data */ uint8_t cmd[8]; int count = -1; int realcount = 0; int faderpos_dirty; while (count < 25){ count++; if (z->led_dirty[z->led_ptr]){ cmd[0] = 0x00; cmd[1] = 0x00; cmd[2] = z->led_ptr; if (z->leds[z->led_ptr]) cmd[3] = 0x01; else cmd[3] = 0x00; cmd[4] = 0x00; cmd[5] = 0x00; cmd[6] = 0x00; cmd[7] = 0x00; if (alphatrack_write_core(z, cmd)){ return realcount; } alphatrack_lock(z); z->led_dirty[z->led_ptr] = 0; alphatrack_unlock(z); realcount++; } alphatrack_lock(z); z->led_ptr = ++z->led_ptr % MAXLED; alphatrack_unlock(z); } count = -1; while (count < 19){ count++; if (z->lcd_dirty[z->lcd_ptr]){ cmd[0] = 0x00; cmd[1] = 0x01; cmd[2] = z->lcd_ptr; cmd[3] = z->lcd[(z->lcd_ptr * 4)]; cmd[4] = z->lcd[(z->lcd_ptr * 4) + 1]; cmd[5] = z->lcd[(z->lcd_ptr * 4) + 2]; cmd[6] = z->lcd[(z->lcd_ptr * 4) + 3]; cmd[7] = 0x00; if (alphatrack_write_core(z, cmd)){ /* printf ("short write in lcd (%d,%d)\n",count,realcount);*/ return realcount; } alphatrack_lock(z); z->lcd_dirty[z->lcd_ptr] = 0; alphatrack_unlock(z); realcount++; } alphatrack_lock(z); z->lcd_ptr = ++z->lcd_ptr % 10; alphatrack_unlock(z); } faderpos_dirty = z->faderpos_dirty; if (faderpos_dirty < 0) faderpos_dirty = 0; if (faderpos_dirty > 1023) faderpos_dirty = 1023; /*update faderposition if not touched: */ if ((z->faderpos != faderpos_dirty) && (!(z->buttons & ALPHATRACK_CONTACT_FADER))){ cmd[0] = 0x00; cmd[1] = 0x02; cmd[2] = (faderpos_dirty & 0xff0) >> 2; cmd[3] = (faderpos_dirty & 0xf) << 2; cmd[4] = 0x00; cmd[5] = 0x00; cmd[6] = 0x00; cmd[7] = 0x00; if (alphatrack_write_core(z, cmd)){ /* printf ("short write\n");*/ return -1; } alphatrack_lock(z); z->faderpos = z->faderpos_dirty = faderpos_dirty; alphatrack_unlock(z); } return realcount; } static void* alphatrack_run (void *ptr){ alphatrack_t *z = (alphatrack_t*)ptr; int val; if (!z) return NULL; while (!z->quit){ alphatrack_poll(z); if (z->buttondiff || z->encoderdelta_l || z->encoderdelta_m || z->encoderdelta_r ){ /* create a new event */ alphatrack_event_t *ev = malloc (sizeof(alphatrack_event_t)); ev->mask = z->buttondiff; ev->states = z->buttons; memcpy(ev->leds, z->leds, sizeof(int) * MAXLED); ev->touchpos = z->touchpos; ev->faderpos = z->faderpos_dirty; ev->encoderdelta_l = z->encoderdelta_l; ev->encoderdelta_m = z->encoderdelta_m; ev->encoderdelta_r = z->encoderdelta_r; if (z->callbackfunc) z->callbackfunc(ev, z->callbackptr); free(ev); } alphatrack_write_queued (z); usleep(POLL_INTERVAL * 1000); }/* end while not quit */ val = usb_release_interface(z->udev, 0); if (val < 0) printf("unable to release alphatrack"); val = usb_close(z->udev); if (val < 0) printf("unable to close alphatrack"); free(z); return NULL; } void alphatrack_set_event_callback(alphatrack_t *z, void (*callback)(alphatrack_event_t *ev, void *ptr) ,void *ptr){ if (!callback) return; z->callbackfunc = callback; z->callbackptr = ptr; } static alphatrack_t *open_alphatrack_core(struct usb_device *dev){ alphatrack_t *z; int val; z = malloc(sizeof(alphatrack_t)); if (!z){ printf("not enough memory"); return NULL; } memset(z, 0, sizeof(alphatrack_t)); z->dev = dev; z->udev = usb_open(z->dev); if (!z->udev){ printf("unable to open alphatrack"); free(z); return NULL; } usb_reset (z->udev); val = usb_claim_interface(z->udev, 0); if (val < 0){ printf("unable to claim alphatrack"); free(z); return NULL; } alphatrack_set_nativemode(z); z->lcd = calloc(41,sizeof(char)); memset(z->lcd_dirty,0,sizeof(int) * 10); memset(z->leds,0,sizeof(int) * MAXLED); memset(z->led_dirty,0,sizeof(int) * MAXLED); z->lcd_ptr = 0; z->led_ptr = 0; z->status = 0; z->buttons = 0; z->buttondiff = 0; z->encoderdelta_l = 0; z->encoderdelta_m = 0; z->encoderdelta_r = 0; z->faderpos = -1; z->faderpos_dirty = -1; z->polltimeout = 15; z->quit = 0; pthread_mutex_init (&z->alphatrackmutex, NULL); pthread_create (&z->pollthread, NULL, alphatrack_run, z); return z; } alphatrack_t *alphatrack_new(){ struct usb_bus *bus; struct usb_device *dev; usb_init(); usb_find_busses(); usb_find_devices(); for(bus=usb_busses; bus; bus=bus->next) { for(dev=bus->devices; dev; dev=dev->next) { if (dev->descriptor.idVendor != ALPHATRACK_VENDORID) continue; if (dev->descriptor.idProduct != ALPHATRACK_PRODUCTID) continue; printf ("alphatrack device found\n"); return open_alphatrack_core(dev); } } printf("can't find alphatrack"); return NULL; } uint8_t alphatrack_get_status(alphatrack_t *z){ return z->status; } void alphatrack_close(alphatrack_t *z){ z->quit = 1; } /* ***************** LEDs *************************************/ int alphatrack_set_led(alphatrack_t *z, uint8_t led, int status){ if (led > MAXLED) return -1; alphatrack_lock(z); z->leds[led] = status; z->led_dirty[led] = 1; alphatrack_unlock(z); return 0; } int alphatrack_get_led(alphatrack_t *z, uint8_t led){ if (led > MAXLED) return -1; return z->leds[led]; } void alphatrack_clear_leds(alphatrack_t *z){ alphatrack_set_led(z, ALPHATRACK_LED_EQ, 0); alphatrack_set_led(z, ALPHATRACK_LED_RIGHT, 0); alphatrack_set_led(z, ALPHATRACK_LED_F2, 0); alphatrack_set_led(z, ALPHATRACK_LED_SEND, 0); alphatrack_set_led(z, ALPHATRACK_LED_LEFT, 0); alphatrack_set_led(z, ALPHATRACK_LED_F1, 0); alphatrack_set_led(z, ALPHATRACK_LED_PAN, 0); alphatrack_set_led(z, ALPHATRACK_LED_EMPTY, 0); alphatrack_set_led(z, ALPHATRACK_LED_EMPTY2, 0); alphatrack_set_led(z, ALPHATRACK_LED_SHIFT, 0); alphatrack_set_led(z, ALPHATRACK_LED_MUTE, 0); alphatrack_set_led(z, ALPHATRACK_LED_SOLO, 0); alphatrack_set_led(z, ALPHATRACK_LED_REC, 0); alphatrack_set_led(z, ALPHATRACK_LED_READ, 0); alphatrack_set_led(z, ALPHATRACK_LED_WRITE, 0); alphatrack_set_led(z, ALPHATRACK_LED_ANY, 0); alphatrack_set_led(z, ALPHATRACK_LED_AUTO, 0); alphatrack_set_led(z, ALPHATRACK_LED_F4, 0); alphatrack_set_led(z, ALPHATRACK_LED_PUNCH, 0); alphatrack_set_led(z, ALPHATRACK_LED_FLIP, 0); alphatrack_set_led(z, ALPHATRACK_LED_PLUGIN, 0); alphatrack_set_led(z, ALPHATRACK_LED_F3, 0); alphatrack_set_led(z, ALPHATRACK_LED_LOOP, 0); } /* int alphatrack_pressed(alphatrack_t *z, int button){ if ((z->buttons & button) && (z->buttondiff & button)) return 1; else return 0; } int alphatrack_buttonstate (alphatrack_t *z, int button){ if (z->buttons & button) return 1; else return 0; } */ /************************* PUBLIC LCD FUNCTIONS: ****************************/ void alphatrack_lcd_readcell(alphatrack_t *z, uint8_t cell, char *text){ strncpy(text,(char*)(z->lcd + (cell * 4)),4); } int alphatrack_clear_lcd(alphatrack_t *z){ alphatrack_lock(z); memset(z->lcd,0x20,16); memset(z->lcd_dirty,1,16); alphatrack_unlock(z); return 0; } int alphatrack_write_lcd (alphatrack_t *z, const char* txt, int x, int y){ int i = 0; int j; int length = strlen(txt); if (y > 1) y = 1; if (y < 0) y = 0; if (x < 0) x = 0; if ((length + x) > 16) length = 16 - x; alphatrack_lock(z); for (i = 0; i < length;i++){ j = x + i + (y * 16); if ((j < 40) && (j >= 0)){ z->lcd[j] = txt[i]; z->lcd_dirty[(int)(j / 4)] = 1; /* printf ("j:%d,txt[i]:%c\n",j,(int)txt[i]);*/ } } alphatrack_unlock(z); return 0; } kluppe-0.6.14/src/common/jackmixer.h0000644000175000017500000000054510575262511016631 0ustar dieterdieter/*#include */ #include typedef struct _jack_info{ char *name; jack_client_t *client; long samplerate; int freewheeling; int suspend_playing; int suspend_recording; int alive; long xruns; float load; } jack_info_t; jack_info_t* mixer_launch (speciallist_t *looperlist); void mixer_close(jack_info_t *jinfo); kluppe-0.6.14/src/common/peakview.h0000644000175000017500000000250710465467345016501 0ustar dieterdieter/* definitions for a looper */ #ifndef __PEAKVIEW_H__ #define __PEAKVIEW_H__ #include #include "buffer.h" #include "speciallist.h" enum { PD_STATUS_NEW, PD_STATUS_TODO, PD_STATUS_DONE, PD_STATUS_DEAD, PD_STATUS_LAST }; typedef struct _peakdata { long start; long end; long pstart; long pend; int status; signed char *Lmin; signed char *Lmax; signed char *Rmin; signed char *Rmax; float samplesperpixel; } peakdata_t; typedef struct _peakview { pthread_mutex_t peakviewmutex; buffer_info_t *buf; int group; int dead; long pixels; long start; long end; float samplesperpixel; speciallist_t* returnlist; } peakview_t; peakdata_t *peakdata_new(); /*void peakdata_delete(peakdata_t *pd);*/ void peakdata_set_status(peakdata_t *pd, int status); peakview_t* peakview_new(buffer_info_t* buf); void peakview_delete(peakview_t* view); void peakview_clear(peakview_t* view, long start, long end); void peakview_set_buffer(peakview_t* view,buffer_info_t* buf); void peakview_lock(peakview_t* view); void peakview_unlock(peakview_t* view); void peakview_set_area(peakview_t* view, long start, long end, long pixels); void peakview_calculate(peakview_t* view, long start, long end); peakdata_t *peakview_get_next(peakview_t* view); #endif kluppe-0.6.14/src/common/serialio.c0000644000175000017500000000467710316237215016464 0ustar dieterdieter#include #include #include #include #include #include /* String function definitions */ #include /* Error number definitions */ #include /* POSIX terminal control definitions */ #include #include "serialio.h" int fd; int status; serialio_data_t* serialio_new(){ serialio_data_t* serialio; serialio = (serialio_data_t*) malloc (sizeof(serialio_data_t)); serialio->fd = 0; return serialio; } int serialio_open(serialio_data_t* serialio){ int status; serialio->fd = open ("/dev/ttyS1", O_RDWR | O_NOCTTY | O_NDELAY); if (serialio->fd > 0){ ioctl(serialio->fd, TIOCMGET, &status); // status &= ~TIOCM_RTS; status |= TIOCM_DTR; ioctl(fd, TIOCMSET, &status); } return serialio->fd; } void serialio_close(serialio_data_t* serialio){ if (serialio->fd) close (serialio->fd); } int serialio_get_foot (serialio_data_t* serialio){ int status; if (serialio->fd){ ioctl(serialio->fd, TIOCMGET, &status); return (status & TIOCM_CTS); /* CTS = 32 */ }else return -1; } int serialio_set_footled (serialio_data_t* serialio, int led){ int status; if (serialio->fd){ ioctl(serialio->fd, TIOCMGET, &status); if (led > 0) status &= ~TIOCM_RTS; else status |= TIOCM_RTS; ioctl(serialio->fd, TIOCMSET, &status); return TIOCM_RTS; }else return -1; } int serialio_toggle_footled (serialio_data_t* serialio){ int status; if (serialio->fd){ ioctl(serialio->fd, TIOCMGET, &status); status ^= TIOCM_RTS; ioctl(serialio->fd, TIOCMSET, &status); return (status & TIOCM_RTS); }else return -1; } /* int main(int argc, char **argv){ if (argc < 2){printf ("device als argument!\n");exit (0);} fd = open(argv[1], O_RDWR | O_NOCTTY | O_NDELAY); if (fd < 1){printf ("couldn't open\n");exit(0);} while(1){ ioctl(fd, TIOCMGET, &status); printf ("DSR:%d ",(status & TIOCM_LE)); printf ("DTR:%d ",(status & TIOCM_DTR)); printf ("RTS:%d ",(status & TIOCM_RTS)); printf ("TxD:%d ",(status & TIOCM_ST)); printf ("RxD:%d ",(status & TIOCM_SR)); printf ("CTS:%d ",(status & TIOCM_CTS)); printf ("DCD:%d ",(status & TIOCM_CAR)); printf ("CD: %d ",(status & TIOCM_CD)); printf ("RNG:%d ",(status & TIOCM_RNG)); printf ("DSR:%d ",(status & TIOCM_DSR)); printf ("\n"); sleep(1); } } */ kluppe-0.6.14/src/common/xsession.h0000644000175000017500000000204411032266614016520 0ustar dieterdieter#ifdef HAVE_ALSA #ifndef __XSESSION_H__ #define __XSESSION_H__ #include #include "speciallist.h" #include #define XSESSION_FADER_1 12 #define XSESSION_FADER_2 11 #define XSESSION_FADER_3 15 #define XSESSION_FADER_4 14 #define XSESSION_POTI_1_1 24 #define XSESSION_POTI_1_2 25 #define XSESSION_POTI_1_3 26 #define XSESSION_POTI_2_1 27 #define XSESSION_POTI_2_2 28 #define XSESSION_POTI_2_3 29 #define XSESSION_POTI_3_1 31 #define XSESSION_POTI_3_2 32 #define XSESSION_POTI_3_3 33 #define XSESSION_POTI_4_1 34 #define XSESSION_POTI_4_2 35 #define XSESSION_POTI_4_3 36 #define XSESSION_CROSSFADER_1 17 #define XSESSION_CROSSFADER_2 20 typedef struct _xsession_info{ pthread_t xsessionthread; snd_seq_t *seq; int seq_nfds; struct pollfd *pfds; speciallist_t *looperdatalist; int input; int quit; } xsession_info_t; xsession_info_t* xsession_new (speciallist_t* looperdatalist, snd_seq_t *seq); void xsession_destroy (); #endif /* __XSESSION_H__ */ #endif /* HAVE_ALSA */ kluppe-0.6.14/src/common/osc.h0000644000175000017500000000056110416043616015433 0ustar dieterdieter#ifdef HAVE_OSC #ifndef __OSC_H__ #define __OSC_H__ #include #include #include "speciallist.h" typedef struct _osc_info{ lo_server_thread st; speciallist_t *looperdatalist; int quit; } osc_info_t; osc_info_t* osc_info_new (speciallist_t* looperdatalist); void osc_info_destroy (); #endif /* __OSC_H__ */ #endif /* HAVE_OSC */ kluppe-0.6.14/src/common/osc.c0000644000175000017500000001441710660612325015433 0ustar dieterdieter/* osc code is partly taken from steve harris' and uwe koloska's liblo examples */ #ifdef HAVE_OSC #include #include #include #include #include #include #include #include "osc.h" #include "looperdata.h" #include "speciallist.h" static int osc_data_handler (const char *path, const char *types, lo_arg **argv, int argc, void *data, void *user_data); void osc_create_error(int num, const char *msg, const char *path){ printf("liblo server error %d in path %s: %s\n", num, path, msg); fflush(stdout); } static int path_find_first(const char* path, const char* searched){ int i = 0; int j = 0; int pos = 0; for (i = 0; i <= strlen(path); i++){ if (!(strncmp ((char*)(path + i),"/",1)) || ((i) == strlen(path))){ if (i > j){ if (strlen(searched) == (i - j - 1)) if (!(strncasecmp((char*)(path + j + 1),searched,(i - j - 1)))){ return pos; } pos++; } j = i; } } return -1; } static long path_pos_to_l(const char* path, int p){ int i = 0; int a = -1; int b = -1; int pos = -2; long result = -1; char* substr = calloc(sizeof(char),255); for (i = 0; i <= strlen(path); i++){ if (!(strncmp ((char*)(path + i),"/",1)) || (i == strlen(path))){a = b; b = i;pos++;} if (pos == p){ strncpy(substr,(char*)(path + a + 1),(b-a-1)); result = strtol(substr,NULL,0); /* printf ("substr:%s: %ld\n",substr,result);*/ free(substr); return result; } } free(substr); return result; } osc_info_t* osc_info_new (speciallist_t* looperdatalist) { char port[5]; lo_server_thread st = NULL; osc_info_t* oinfo = calloc (sizeof (osc_info_t),1); int i = 1783; printf ("creating osc thread\n"); while ((++i < 1794) && !st){ sprintf (port,"%d",i); /* st = lo_server_thread_new(&port, osc_create_error);*/ st = lo_server_thread_new(port, NULL); } if (st) {printf ("osc server listening at port %s\n",port);} else { printf ("failed to create osc server!.");} if (st){ oinfo->quit = 0; oinfo->looperdatalist = looperdatalist; oinfo->st = st; lo_server_thread_add_method(st, NULL,NULL,osc_data_handler, (void*)oinfo); lo_server_thread_start(st); }else{ free(oinfo); oinfo = NULL;} return oinfo; } void osc_info_destroy (osc_info_t* oinfo){ oinfo->quit = 1; lo_server_thread_stop(oinfo->st); lo_server_thread_free(oinfo->st); free(oinfo); } static int osc_data_handler(const char *path, const char *types, lo_arg **argv, int argc, void *data, void *user_data){ /*int i;*/ osc_info_t* oinfo = (osc_info_t*) user_data; looper_data_t *ld = speciallist_get_first_nolock (oinfo->looperdatalist); /* printf ("path:%s, %d, val:%f\n",path, path_find_first(path,"loop"),(float)lo_hires_val(types[0],argv[0])); */ if (path_find_first(path,"loop") == 1){ long loopnr = path_pos_to_l(path,2); /* printf ("loop message\n");*/ if (path_find_first(path,"Speed") == 3){ double df = 0; if (argc > 0) df = (float)lo_hires_val(types[0],argv[0]); while(ld){ if ((ld->id == loopnr) || (loopnr < 1)){ looperdata_lock(ld); looperdata_set_speed (ld, df); looperdata_unlock(ld); } ld = speciallist_get_next_nolock (oinfo->looperdatalist, ld); } }else if (path_find_first(path,"Volume") == 3){ double df = 0; // printf ("nr:%ld, vol:%f\n",loopnr,df); if (argc > 0) df = (float)lo_hires_val(types[0],argv[0]); while(ld){ if ((ld->id == loopnr) || (loopnr < 1)){ looperdata_lock(ld); looperdata_set_vol (ld, df); looperdata_unlock(ld); } ld = speciallist_get_next_nolock (oinfo->looperdatalist, ld); } }else if (path_find_first(path,"Pan") == 3){ double df = 0; if (argc > 0) df = (float)lo_hires_val(types[0],argv[0]); // printf ("nr:%ld, pan:%f\n",loopnr,(float)df); while(ld){ if ((ld->id == loopnr) || (loopnr < 1)){ looperdata_lock(ld); looperdata_set_pan (ld, df); looperdata_unlock(ld); } ld = speciallist_get_next_nolock (oinfo->looperdatalist, ld); } }else if (path_find_first(path,"NumberOfGrains") == 3){ int i = 0; if (argc > 0) i = lo_hires_val(types[0],argv[0]); // printf ("nr:%ld, ngrains:%d\n",loopnr,i); while(ld){ if ((ld->id == loopnr) || (loopnr < 1)){ looperdata_lock(ld); looperdata_set_ngrains (ld, i); looperdata_unlock(ld); } ld = speciallist_get_next_nolock (oinfo->looperdatalist, ld); } }else if (path_find_first(path,"Play") == 3){ int i = 0; if (argc > 0) i = lo_hires_val(types[0],argv[0]); while(ld){ if ((ld->id == loopnr) || (loopnr < 1)){ looperdata_lock(ld); looperdata_set_playing (ld, i); looperdata_unlock(ld); } ld = speciallist_get_next_nolock (oinfo->looperdatalist, ld); } }else if (path_find_first(path,"Record") == 3){ int i = 0; if (argc > 0) i = lo_hires_val(types[0],argv[0]); while(ld){ if ((ld->id == loopnr) || (loopnr < 1)){ looperdata_lock(ld); looperdata_set_recording (ld, i); looperdata_unlock(ld); } ld = speciallist_get_next_nolock (oinfo->looperdatalist, ld); } } } /* printf("path: <%s>\n", path); for (i=0; i typedef struct _speciallist_node_t{ struct _speciallist_node_t *next; void *data; } speciallist_node_t; typedef struct _speciallist_t{ pthread_mutex_t mutex; speciallist_node_t *first; speciallist_node_t *last; speciallist_node_t *latest; } speciallist_t; speciallist_t* speciallist_new (); void speciallist_destroy (speciallist_t *list); void speciallist_lock (speciallist_t *list); void speciallist_unlock (speciallist_t *list); int speciallist_count (speciallist_t *list); int speciallist_append (speciallist_t *list, void *data); int speciallist_delete (speciallist_t *list, void *data); void* speciallist_get_first (speciallist_t *list); void* speciallist_get_last (speciallist_t *list); void* speciallist_get_next (speciallist_t *list, void *data); void* speciallist_get_previous (speciallist_t *list, void *data); int speciallist_count_nolock (speciallist_t *list); int speciallist_append_nolock (speciallist_t *list, void *data); int speciallist_delete_nolock (speciallist_t *list, void *data); void* speciallist_get_first_nolock (speciallist_t *list); void* speciallist_get_last_nolock (speciallist_t *list); void* speciallist_get_next_nolock (speciallist_t *list, void *data); void* speciallist_get_previous_nolock (speciallist_t *list, void *data); #endif kluppe-0.6.14/src/common/clickmodes.c0000644000175000017500000000207210441623212016750 0ustar dieterdieter#include #include #include #include "clickmodes.h" #include "buffer.h" #include "vinyl.h" #include "cd.h" speciallist_t* clickmodes_create(long rate){ speciallist_t *sl = speciallist_new(); buffer_info_t *buf = buffer_new (0, rate); buf->chunk_list[0]->readfc = &vinyl; buf->pending = BUFFER_STATUS_READY; /* LATER: deal with samplerates correctly */ buf->samplerate_factor = 44100 / (float)rate; buffer_set_shortname(buf,"vinyl click"); speciallist_append (sl,buf); buf = buffer_new (0, rate); buf->chunk_list[0]->readfc = &cd; buf->pending = BUFFER_STATUS_READY; /* LATER: deal with samplerates correctly */ buf->samplerate_factor = 44100 / (float)rate; buffer_set_shortname(buf,"cd click"); speciallist_append (sl,buf); return sl; } void clickmodes_free(speciallist_t *sl){ buffer_info_t *buf; buffer_info_t *tmp; if (sl){ buf = speciallist_get_first(sl); while (buf){ tmp = buf; buf = speciallist_get_next(sl,tmp); buffer_delete(tmp); } } sl = NULL; } kluppe-0.6.14/src/common/clickmodes.h0000644000175000017500000000032710441576111016763 0ustar dieterdieter/* definitions for a list of click-modes */ #ifndef __CLICKMODES_H__ #define __CLICKMODES_H__ #include "speciallist.h" speciallist_t* clickmodes_create(long rate); void clickmode_free(speciallist_t *sl); #endif kluppe-0.6.14/src/common/buffer.h0000644000175000017500000000641610652371054016127 0ustar dieterdieter/* buffer.h definitions for administration * * of filebuffers (always stereo) */ #ifndef __BUFFER_H__ #define __BUFFER_H__ #include #include #include #include "filechunk.h" #include "speciallist.h" /* how many frames will we read at once */ #define TBS = 32768 #define BUFFER_STATUS_NEW 1 #define BUFFER_STATUS_TOLOAD 2 #define BUFFER_STATUS_LOADING 3 #define BUFFER_STATUS_READY 4 #define BUFFER_STATUS_DEAD 5 #define BUFFER_ERROR_UNKNOWN -1 #define BUFFER_ERROR_ALLOC -2 #define BUFFER_ERROR_NOSF -3 #define BUFFER_TYPE_MEMORY 1 #define BUFFER_TYPE_FILEBUFFER 2 #define BUFFER_TYPE_DISCSTREAM 3 typedef struct _buffer_info { int id; int type; int status; int pending; int error; int group_max; pthread_mutex_t buffermutex; char* filename; /* only if data comes from file */ char* shortname; double percent_filled; int normalized; float volume_factor; long parent_samplerate; long snap_offset; float samplerate_factor; chunk_group_t** chunk_list; } buffer_info_t; typedef struct _buffer_save_data{ buffer_info_t *buf; long start; long end; } buffer_save_data_t; buffer_info_t* buffer_new(int id, long rate); int buffer_get_type(buffer_info_t* buf); void buffer_lock(buffer_info_t* buf); void buffer_unlock(buffer_info_t* buf); void buffer_open_discstream (buffer_info_t* buf, char* fname, long srate); void buffer_loadfile(buffer_info_t* buf, char* fname,long srate); int buffer_save (buffer_info_t* buf, char* fname, long srate, long start, long end); void buffer_set_filename(buffer_info_t* buf, char* name); void buffer_set_shortname(buffer_info_t* buf, char* name); char* buffer_get_shortname(buffer_info_t* buf); int buffer_get_group(buffer_info_t* buf, int priority); void buffer_delete_group(buffer_info_t* buf, int gid); int buffer_get_status(buffer_info_t* buf); int buffer_get_channels(buffer_info_t* buf); void buffer_set_channels(buffer_info_t* buf, int channels); /*void buffer_set_ds(buffer_info_t* buf, int is_ds);*/ void buffer_set_area(buffer_info_t* buf, int group, long start, long end, long bandwith); void buffer_resize(buffer_info_t* buf, long new_size); long buffer_get_size(buffer_info_t* buf); /*long buffer_get_corrected_size(buffer_info_t* buf, long srate);*/ int buffer_delete(buffer_info_t* b); float buffer_analyze(buffer_info_t* buf, int group, long start, long end); void buffer_normalize(buffer_info_t* buf, float factor,long start, long end); void buffer_set_volume_factor(buffer_info_t* buf, float factor); float buffer_get_volume_factor(buffer_info_t* buf); /* void buffer_set_snap_offset(buffer_info_t* buf, long offset); long buffer_get_snap_offset(buffer_info_t* buf); */ /*speciallist_t* buffer_list_new();*/ void buffer_discthread_launch(speciallist_t *buffer_list); /*float buffer_readsample(buffer_info_t* buf, int channel, long index, int group);*/ float buffer_readsample_interpolated(buffer_info_t* buf, int channel, double index, int group); void buffer_writesample(buffer_info_t* buf, int channel, long index, int group, float sample); void buffer_write_sampleblock(buffer_info_t* buf, long index, long size, int group, float* Lbuf, float* Rbuf); float buffer_get_sampleratefactor(buffer_info_t* buf, long srate); #endif kluppe-0.6.14/src/common/peakview.c0000644000175000017500000002527610657103275016474 0ustar dieterdieter#include #include #include #include #include "buffer.h" #include "interpol.h" #include "peakview.h" #define BANDWITH 131072 peakdata_t *peakdata_new(){ peakdata_t *pd = malloc(sizeof(peakdata_t)); /* printf ("new pd\n");*/ pd->start = 0; pd->end = 0; pd->pstart = 0; pd->pend = 0; pd->status = PD_STATUS_NEW; pd->Lmin = NULL; pd->Lmax = NULL; pd->Rmin = NULL; pd->Rmax = NULL; return pd; } static void peakdata_delete(peakdata_t *pd){ if (!pd) return; if (pd->status != PD_STATUS_DEAD) return; /* printf ("delete : %p (%ld - %ld)\n",pd,pd->pstart,pd->pend);*/ if (pd->Lmin) free(pd->Lmin); pd->Lmin = NULL; if (pd->Lmax) free(pd->Lmax); pd->Lmax = NULL; if (pd->Rmin) free(pd->Rmin); pd->Rmin = NULL; if (pd->Rmax) free(pd->Rmax); pd->Rmax = NULL; free(pd); pd = NULL; } void peakdata_set_status(peakdata_t *pd, int status){ if (!pd) return; if (pd->status == PD_STATUS_DEAD) return; pd->status = status; } static void* peakview_workthread(void *ptr){ peakview_t *view = (peakview_t*)ptr; peakdata_t *pd, *tmp; struct timeval tv; int dirty; long l; pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL); while (!view->dead){ dirty = 0; peakview_lock(view); pd = speciallist_get_first(view->returnlist); while (pd && !dirty){ tmp = NULL; if (pd->status == PD_STATUS_TODO){ long oldpixel = 0; long newpixel = 0; signed char Lmin = 127; signed char Lmax = -127; signed char Rmin = 127; signed char Rmax = -127; signed char val; long gstart = (long)((float)pd->start / (float)pd->samplesperpixel); oldpixel = gstart; /* printf ("start:%ld -> end:%ld\n", pd->start, pd->end);*/ for (l = pd->start; l <= pd->end; l++){ val = (signed char) (buffer_readsample_interpolated( view->buf,1,(float)l,view->group) * 127.); if (val < Lmin) Lmin = val; if (val > Lmax) Lmax = val; if (buffer_get_channels(view->buf) > 1){ val = (signed char) (buffer_readsample_interpolated( view->buf,2,(float)l,view->group) * 127.); if (val < Rmin) Rmin = val; if (val > Rmax) Rmax = val; } newpixel = (long)((float)l / (float)pd->samplesperpixel); if (newpixel > oldpixel){ *(pd->Lmin + oldpixel - gstart) = Lmin; *(pd->Lmax + oldpixel - gstart) = Lmax; if (buffer_get_channels(view->buf) > 1){ *(pd->Rmin + oldpixel - gstart) = Rmin; *(pd->Rmax + oldpixel - gstart) = Rmax; } Lmin = 127; Lmax = -127; Rmin = 127; Rmax = -127; oldpixel = newpixel; }/* else if (newpixel > oldpixel) */ } *(pd->Lmin + oldpixel - gstart) = Lmin; *(pd->Lmax + oldpixel - gstart) = Lmax; if (buffer_get_channels(view->buf) > 1){ *(pd->Rmin + oldpixel - gstart) = Rmin; *(pd->Rmax + oldpixel - gstart) = Rmax; } pd->status = PD_STATUS_DONE; dirty = 1; }else if (pd->status == PD_STATUS_DEAD){ tmp = pd; } pd = speciallist_get_next(view->returnlist,pd); if (tmp){ speciallist_delete(view->returnlist,tmp); peakdata_delete(tmp); } } peakview_unlock(view); tv.tv_sec = 0; if (dirty) tv.tv_usec = 100; else tv.tv_usec = 10000; select(0, NULL, NULL, NULL, &tv); } /* dying -> clean up */ pd = speciallist_get_first(view->returnlist); while(pd){ peakdata_t *tmp = pd; pd = speciallist_get_next(view->returnlist,pd); peakdata_set_status(tmp, PD_STATUS_DEAD); peakdata_delete(tmp); } if (view->buf && view->group){ buffer_lock(view->buf); buffer_delete_group(view->buf, view->group); buffer_unlock(view->buf); } speciallist_destroy(view->returnlist); free (view); view = NULL; /* printf ("peakview closed - return\n");*/ return NULL; } peakview_t* peakview_new(buffer_info_t* buf){ pthread_attr_t tattr; pthread_t wt; int ret; peakview_t *view; if (!buf) return NULL; view = (peakview_t*) malloc (sizeof(peakview_t)); /* printf ("peakview new\n");*/ view->buf = buf; view->dead = 0; /* printf ("peakview get group\n");*/ view->group = buffer_get_group(buf, DS_PRIORITY_RELAXED); buffer_set_area(buf, view->group,0, buffer_get_size(buf), BANDWITH); view->returnlist = speciallist_new(); ret = pthread_attr_init(&tattr); ret = pthread_attr_setdetachstate(&tattr,PTHREAD_CREATE_DETACHED); pthread_mutex_init (&view->peakviewmutex, NULL); pthread_create (&wt, &tattr, peakview_workthread, view); return view; } void peakview_delete(peakview_t* view){ if (!view) return; /* printf ("peakview->delete"); if (view->buf) if (view->buf->shortname) printf (" (%s)",view->buf->shortname); printf ("\n"); */ peakview_lock(view); view->dead = 1; peakview_unlock(view); } void peakview_clear(peakview_t* view, long start, long end){ peakdata_t* pd; if (!view) return; if (view->dead) return; peakview_lock(view); pd = speciallist_get_first(view->returnlist); while(pd){ if ((end < 1) || ((pd->start >= start) && (pd->end <= end))){ peakdata_set_status(pd,PD_STATUS_DEAD); } pd = speciallist_get_next(view->returnlist,pd); } peakview_unlock(view); } void peakview_set_buffer(peakview_t* view,buffer_info_t* buf){ peakdata_t* pd; if (!view) return; if (view->dead) return; peakview_lock(view); pd = speciallist_get_first(view->returnlist); while(pd){ peakdata_set_status(pd,PD_STATUS_DEAD); pd = speciallist_get_next(view->returnlist,pd); } if (view->buf && view->group){ buffer_lock(view->buf); buffer_delete_group(view->buf, view->group); buffer_unlock(view->buf); } view->buf = buf; view->start = 0; view->end = 0; view->pixels = 0; view->samplesperpixel = .0; if (buf){ /* printf ("peakview get group\n");*/ view->group = buffer_get_group(buf, DS_PRIORITY_RELAXED); buffer_set_area(buf, view->group, 0, buffer_get_size(buf), BANDWITH); } peakview_unlock(view); } void peakview_lock(peakview_t* view){ pthread_mutex_lock (&view->peakviewmutex); } void peakview_unlock(peakview_t* view){ pthread_mutex_unlock (&view->peakviewmutex); } void peakview_set_area(peakview_t* view, long start, long end, long pixels){ /* int ok = 0;*/ if (!view) return; if (view->dead) return; /* delete old list blocks */ peakview_clear(view, 0, 0); peakview_lock(view); view->start = start; view->end = end; view->pixels = pixels; view->samplesperpixel = (float)(end - start) / (float)pixels; /* printf ("set area: %ld, %ld = %ldpixels (%.2f spp)\n",start,end,pixels,view->samplesperpixel);*/ peakview_unlock(view); } void peakview_calculate(peakview_t* view, long start, long end){ long blocklength; long l; if (!view) return; if (view->dead) return; if (!view->buf) return; if (!view->end) return; if (!view->returnlist) return; if (start < view->start) start = view->start; if (end >= view->end) end = view->end; if (buffer_get_type(view->buf) != BUFFER_TYPE_DISCSTREAM){ /* was ~10 seconds at once */ blocklength = (long)((float)(end - start) / (float)(view->end - view->start) * view->samplesperpixel * 200); if (blocklength > 441000) blocklength = 441000; if (blocklength < 1) blocklength = 1; }else{ /* 200 pixels at once (max) */ blocklength = (long)((float)(end - start) / (float)(view->end - view->start) * view->samplesperpixel * 200); if (blocklength > 88200) blocklength = 88200; if (blocklength < 1) blocklength = 1; } peakview_clear(view, start, end); peakview_lock(view); if (buffer_get_type(view->buf) == BUFFER_TYPE_DISCSTREAM){ /* this one is just empty to make waiting more comfortable */ peakdata_t* pd = peakdata_new(); pd->start = start; pd->end = end; pd->samplesperpixel = view->samplesperpixel; pd->pstart = (long)((float)(pd->start - view->start) / view->samplesperpixel); pd->pend = (long)((float)(pd->end - view->start) / view->samplesperpixel); /* printf ("pstart:%ld, pend:%ld\n",pd->pstart,pd->pend);*/ pd->Lmin = calloc (sizeof(signed char), (pd->pend - pd->pstart + 2)); pd->Lmax = calloc (sizeof(signed char), (pd->pend - pd->pstart + 2)); if (!(pd->Lmin && pd->Lmax)) printf ("memory allocation error!"); if (buffer_get_channels(view->buf) > 1){ pd->Rmin = calloc (sizeof(signed char), (pd->pend - pd->pstart + 2)); pd->Rmax = calloc (sizeof(signed char), (pd->pend - pd->pstart + 2)); if (!(pd->Rmin && pd->Rmax)) printf ("memory allocation error!"); }else { pd->Rmin = NULL; pd->Rmax = NULL; } pd->status = PD_STATUS_DONE; speciallist_append(view->returnlist,pd); } for (l = start; l < end; l += blocklength){ peakdata_t* pd = peakdata_new(); pd->start = l; pd->end = l + blocklength; if (pd->end > end) pd->end = end; if (pd->start < pd->end){ pd->pstart = (long)((float)(pd->start - view->start) / view->samplesperpixel); pd->pend = (long)((float)(pd->end - view->start) / view->samplesperpixel); pd->samplesperpixel = view->samplesperpixel; /* printf (" %ld - %ld = %ld - %ld\n",pd->start,pd->end,pd->pstart,pd->pend);*/ pd->Lmin = malloc (sizeof(signed char) * (pd->pend - pd->pstart + 2)); pd->Lmax = malloc (sizeof(signed char) * (pd->pend - pd->pstart + 2)); if (!(pd->Lmin && pd->Lmax)) printf ("memory allocation error!"); if (buffer_get_channels(view->buf) > 1){ pd->Rmin = malloc (sizeof(signed char) * (pd->pend - pd->pstart + 2)); pd->Rmax = malloc (sizeof(signed char) * (pd->pend - pd->pstart + 2)); if (!(pd->Rmin && pd->Rmax)) printf ("memory allocation error!"); }else { pd->Rmin = NULL; pd->Rmax = NULL; } pd->status = PD_STATUS_TODO; speciallist_append(view->returnlist,pd); } else peakdata_delete(pd); } peakview_unlock(view); } peakdata_t *peakview_get_next(peakview_t* view){ if (!view) return NULL; if (view->dead) return NULL; peakdata_t* pd = speciallist_get_first(view->returnlist); while(pd){ if (pd->status == PD_STATUS_DONE){ return pd; } pd = speciallist_get_next(view->returnlist,pd); } return NULL; } kluppe-0.6.14/src/common/speciallist.c0000644000175000017500000001273510444466630017172 0ustar dieterdieter#include #include #include #include "speciallist.h" static speciallist_node_t* node_new(){ speciallist_node_t *node; node = malloc(sizeof(speciallist_node_t)); node->data = NULL; node->next = NULL; return node; } speciallist_t* speciallist_new (){ speciallist_t *list = malloc (sizeof(speciallist_t)); pthread_mutex_init (&list->mutex, NULL); list->first = NULL; list->last = NULL; list->latest = NULL; return list; } void speciallist_destroy (speciallist_t *list){ speciallist_node_t *last = list->first; speciallist_node_t *next; speciallist_lock(list); while (last){ next = last->next; free(last); last = next; } speciallist_unlock(list); free(list); list = NULL; } void speciallist_lock (speciallist_t *list){ pthread_mutex_lock(&list->mutex); } void speciallist_unlock (speciallist_t *list){ pthread_mutex_unlock(&list->mutex); } int speciallist_count (speciallist_t *list){ int result; speciallist_lock(list); result = speciallist_count_nolock(list); speciallist_unlock(list); return result; } int speciallist_append (speciallist_t *list, void *data){ int result; speciallist_lock(list); result = speciallist_append_nolock(list,data); speciallist_unlock(list); return result; } int speciallist_delete (speciallist_t *list, void *data){ int result; speciallist_lock(list); result = speciallist_delete_nolock(list,data); speciallist_unlock(list); return result; } void* speciallist_get_first (speciallist_t *list){ return speciallist_get_first_nolock (list); } void* speciallist_get_last (speciallist_t *list){ void *result; speciallist_lock(list); result = speciallist_get_last_nolock (list); speciallist_unlock(list); return result; } void* speciallist_get_next (speciallist_t *list, void *data){ void *result; speciallist_lock(list); result = speciallist_get_next_nolock (list, data); speciallist_unlock(list); return result; } void* speciallist_get_previous (speciallist_t *list, void *data){ void *result; speciallist_lock(list); result = speciallist_get_previous_nolock (list, data); speciallist_unlock(list); return result; } int speciallist_count_nolock (speciallist_t *list){ int i = 0; speciallist_node_t *ptr = list->first; while (ptr){ i++; ptr = ptr->next; } return i; } int speciallist_append_nolock (speciallist_t *list, void *data){ speciallist_node_t *ptr = list->first; speciallist_node_t *new = node_new(); new->data = data; if (ptr){ list->last->next = new; list->last = list->last->next; /* while (ptr->next) ptr = ptr->next; ptr->next = new; */ return 1; } list->latest = new; list->first = new; list->last = new; return 1; } int speciallist_delete_nolock (speciallist_t *list, void *data){ speciallist_node_t *found; speciallist_node_t *last; if (!list) return 0; if (!list->first || !data) return 0; if (list->first->data == data){ found = list->first; if (list->last == list->first) list->last = NULL; if (list->latest == list->first) list->latest = list->first->next; list->first = list->first->next; free(found); return 1; } last = list->first; found = list->first->next; while (found){ if (found->data == data){ if (found == list->last) list->last = last; if (found == list->latest) list->latest = list->first; last->next = found->next; free(found); return 1; } last = found; found = found->next; } return 0; } void* speciallist_get_first_nolock (speciallist_t *list){ if (!list->first) return NULL; return list->first->data; } void* speciallist_get_last_nolock (speciallist_t *list){ /* speciallist_node_t *ptr; speciallist_node_t *rptr = NULL; ptr = list->first; while(ptr){ rptr = ptr; ptr = ptr->next; } if (rptr) return rptr->data; else return NULL; */ return list->last->data; } void* speciallist_get_next_nolock (speciallist_t *list, void *data){ speciallist_node_t *ptr; if (!list) return NULL; if (!data) return NULL; if (!list->first) return NULL; if (list->first == list->last) return NULL; /* only one member -> no next */ if (!list->latest) {printf ("no list->latest\n"); return NULL;} /* this should not happen */ if (list->latest->data != data) list->latest = list->first; ptr = list->latest; while (ptr){ if (ptr->data == data) { if (ptr->next){ list->latest = ptr->next; return ptr->next->data; } else { list->latest = list->first; return NULL; } } ptr = ptr->next; } /* ptr = list->first; while(ptr){ if (ptr->data == data) { if (ptr->next){ list->latest = ptr->next; return ptr->next->data; } else return list->latest = NULL; } ptr = ptr->next; } */ return NULL; } void* speciallist_get_previous_nolock (speciallist_t *list, void *data){ speciallist_node_t *ptr; speciallist_node_t *rptr = NULL; if (!list) return NULL; if (!list->first || !data) return NULL; ptr = list->first; while(ptr){ if (ptr->data == data) { if (rptr){ list->latest = rptr; return rptr->data; } else { list->latest = list->first; return NULL; } } rptr = ptr; ptr = ptr->next; } return NULL; } kluppe-0.6.14/LICENSE.txt0000644000175000017500000004313110204616765014250 0ustar dieterdieter GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License.