From e2de64d6f1beb9e492daf5b886e19933c1fa41dd Mon Sep 17 00:00:00 2001 From: toma Date: Wed, 25 Nov 2009 17:56:58 +0000 Subject: Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features. BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdemultimedia@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da --- kscd/kscdmagic/Makefile.am | 40 ++ kscd/kscdmagic/README | 146 ++++++ kscd/kscdmagic/core.cpp | 410 +++++++++++++++++ kscd/kscdmagic/logo.h | 50 +++ kscd/kscdmagic/magicconf.h | 23 + kscd/kscdmagic/main.cpp | 300 +++++++++++++ kscd/kscdmagic/polygon.h | 106 +++++ kscd/kscdmagic/sound.cpp | 252 +++++++++++ kscd/kscdmagic/symbol.h | 1028 +++++++++++++++++++++++++++++++++++++++++++ kscd/kscdmagic/syna.h | 180 ++++++++ kscd/kscdmagic/version.h | 1 + kscd/kscdmagic/xlib.c | 781 ++++++++++++++++++++++++++++++++ kscd/kscdmagic/xlib.h | 139 ++++++ kscd/kscdmagic/xlibwrap.cpp | 209 +++++++++ 14 files changed, 3665 insertions(+) create mode 100644 kscd/kscdmagic/Makefile.am create mode 100644 kscd/kscdmagic/README create mode 100644 kscd/kscdmagic/core.cpp create mode 100644 kscd/kscdmagic/logo.h create mode 100644 kscd/kscdmagic/magicconf.h create mode 100644 kscd/kscdmagic/main.cpp create mode 100644 kscd/kscdmagic/polygon.h create mode 100644 kscd/kscdmagic/sound.cpp create mode 100644 kscd/kscdmagic/symbol.h create mode 100644 kscd/kscdmagic/syna.h create mode 100644 kscd/kscdmagic/version.h create mode 100644 kscd/kscdmagic/xlib.c create mode 100644 kscd/kscdmagic/xlib.h create mode 100644 kscd/kscdmagic/xlibwrap.cpp (limited to 'kscd/kscdmagic') diff --git a/kscd/kscdmagic/Makefile.am b/kscd/kscdmagic/Makefile.am new file mode 100644 index 00000000..c5cc3a21 --- /dev/null +++ b/kscd/kscdmagic/Makefile.am @@ -0,0 +1,40 @@ + +# this 10 paths are KDE specific. Use them: +# kde_htmldir Where your docs should go to. (contains lang subdirs) +# kde_appsdir Where your application file (.kdelnk) should go to. +# kde_icondir Where your icon should go to. +# kde_minidir Where your mini icon should go to. +# kde_datadir Where you install application data. (Use a subdir) +# kde_locale Where translation files should go to.(contains lang subdirs) +# kde_cgidir Where cgi-bin executables should go to. +# kde_confdir Where config files should go to. +# kde_mimedir Where mimetypes should go to. +# kde_toolbardir Where general toolbar icons should go to. +# kde_wallpaperdir Where general wallpapers should go to. + +# just set the variable +APPSDIR = $(kde_appsdir)/Multimedia + +# set the include path for X, qt and KDE +INCLUDES= $(all_includes) + +####### This part is very kscdmagic specific +# you can add here more. This one gets installed +bin_PROGRAMS = kscdmagic + +# Which sources should be compiled for kscdmagic +kscdmagic_SOURCES = core.cpp main.cpp sound.cpp xlibwrap.cpp xlib.c + +# the library search path. +kscdmagic_LDFLAGS = $(all_libraries) $(KDE_RPATH) + +# the libraries to link against. Be aware of the order. First the libraries, +# that depend on the following ones. +kscdmagic_LDADD = -lm $(LIB_KDEUI) + +# this option you can leave out. Just, if you use "make dist", you need it +noinst_HEADERS = symbol.h syna.h xlib.h magicconf.h + +messages: +# $(XGETTEXT) -kTRANS $(kscdmagic_SOURCES) + diff --git a/kscd/kscdmagic/README b/kscd/kscdmagic/README new file mode 100644 index 00000000..64af4f6f --- /dev/null +++ b/kscd/kscdmagic/README @@ -0,0 +1,146 @@ + +kscdmagic is based on synaesthesia +by Paul Harrison . + + -dirk + + + + +SYNAESTHESIA v2.0 + +Introduction +============ + +This is a program for representing sounds visually from a CD or line +input or piped from another program. It goes beyond the usual oscilliscope +style program by combining an FFT and stereo positioning information to +give a two dimensional display. Some of the shapes I have observed are: + * Drums: clouds of color, fairly high + * Clean guitar: several horizontal lines, low down + * Rough guitar: a cloud, low down + * Trumpet: Lots of horizontal lines everywhere + * Flute: A single horizontal line, low down + * Voice: A vertical line with some internal structure + * Synthesizer: All kinds of weird shapes! + +Synaesthesia can run in a window in X or full screen using SVGAlib. + +The display represents frequency as vertical position on screen, +left-right position as left-right position on screen. It can also +understand surround sound encoded music, and shows ambient noise +in orange. + +X-Windows support was added in version 1.3, as well as a major redesign +of the interface. You can use Synaesthesia as a fully functional +CD player, suitable for use while working. + +There is command line support for play lists and piping from another +program (such as an mp3 player). + +Usage +===== + +Synaesthesia should work on Linux and BSD systems. (Note: I don't +have access to a BSD system myself, I have to rely on patches -- if it +doesn't work, please tell me!) LinuxPPC users may have to use the pipe +mode rather than taking sound input from the CD player, as I believe +sound recording is not yet implemented. + +Compile Synaesthesia by typing + + make + +then install it by typing + + make install + +This will create three versions of Synaesthesia: + + synaesthesia - full screen SVGAlib version (Linux only) + xsynaesthesia - Version that runs as a window in X + sdlsynaesthesia - Version that uses the SDL graphics library + +If you want to use the SDL version, you need to get SDL from +http://www.devolution.com/~slouken/SDL. + +You will need to run Synaesthesia as root to run it full screen +with SVGAlib. Other varieties can be run by any user providing you +provide permissions on /dev/dsp, /dev/cdrom, and /dev/mixer. + +Synaesthesia creates a configuration file, named ~/.synaesthesia, +to store settings such as brightness, color, and window size, as +well as which devices to use to control sound input. + +BSD users will have to edit this file to set the CD-ROM device name +before using Synaesthesia in order to control the CD. + +Run Synaesthesia with no parameters for further information on how to +use it. + +Notes for code rippers +====================== + +This program contains code that you may wish to use in your own projects. +If you want to, please do. (For example, you might want to add some +snazzy visual effects to your favorite MP3 or CD player) + +The actual code to do the mapping from sound to visual display is +all in core.cpp, it should be fairly easy to disentangle from other +parts of the program. It does make reference to some globals defined +in syna.h, namely the #defines m (log2 of the sample size for each +frame) and brightness, data (which stores the sound input), outputBmp, +lastOutputBmp and lastLastOutputBmp (which hold the output), outWidth +and outHeight (size of the bitmaps), and fadeMode, brightnessTwiddler, +starSize and pointsAreDiamonds (various parameters affecting the display). + +The normal way to use it would be: + + Call coreInit() to set up some look-up tables + Call setStarSize(starSize) to set up some more look-up tables + Loop + Put data into the data array + Call fade() to apply the fade/wave/heat effect to the output + Call coreGo() to add the next fragment of sound input to the output + Display contents of outputBmp to screen + +There is a simple anti-aliased polygon drawing engine in the file +polygon.h. sound.cpp contains code for driving the CD. xlib.c and +xlibwrap.cpp contain code for setting up a window under X (originally +ripped from the Xaos fractal viewer program :-) ). + +Authors +======= + +This program is free. If you like it, or have any suggestions, please +send me (Paul Harrison) an email (pfh@yoyo.cc.monash.edu.au). + +Thanks to Asger Alstrup Nielsen for many great suggestions, and for +writing optimized 32 bit loops for fading and drawing to screen. + +Thanks to Roger Knobbe for porting Synaesthesia to FreeBSD. + +Thanks to Ben Gertzfield and Martin Mitchell for some small fixes to the +CD controlling code. + +Thanks to Simon Budig for an improvement to the X code. + +Changes +======= + +1.1 - Added surround sound decoding. +1.2 - Fixed a bug in the ioctl calls to /dev/dsp. +1.3 - Asger Alstrup Nielsen's optimizations added. + Added X-Windows support. + More options, redesigned interface. +1.4 - Bug fixes, including a great reduction in + "Sound: Recording overrun" warnings. + New command line options: play lists and piping. + Support for SDL. +2.0 - Bug fixes: Fixed problem in xlib.c that caused occasional segfaults, + several endianness problems fixed. + New effects: Wave, heat, diamond shaped points. + Piping sound now longer requires the twiddle factor. + Yet another interface redesign. + Partial support for LinuxPPC (pipe mode only) + diff --git a/kscd/kscdmagic/core.cpp b/kscd/kscdmagic/core.cpp new file mode 100644 index 00000000..49fce661 --- /dev/null +++ b/kscd/kscdmagic/core.cpp @@ -0,0 +1,410 @@ +/* Synaesthesia - program to display sound graphically + Copyright (C) 1997 Paul Francis Harrison + + 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. + + The author may be contacted at: + pfh@yoyo.cc.monash.edu.au + or + 27 Bond St., Mt. Waverley, 3149, Melbourne, Australia +*/ + +#include +#include +#include +#include +#include "syna.h" + +double cosTable[n], negSinTable[n]; +int bitReverse[n]; +int scaleDown[256]; +int maxStarRadius; + +int bitReverser(int i) { + int sum=0,j; + for(j=0;j>= 1; + } + return sum; +} + +void fft(double *x,double *y) { + int n2 = n, n1; + int twoToTheK; + for(twoToTheK=1;twoToTheK 0.0) + factor = int(exp(log(fadeModeFudge) / (size*8.0))*255); + else + factor = 0; + + if (factor > 255) factor = 255; + + for(int i=0;i<256;i++) + scaleDown[i] = i*factor>>8; + + maxStarRadius = 1; + for(int i=255;i;i = scaleDown[i]) + maxStarRadius++; +} + +inline void addPixel(int x,int y,int br1,int br2) { + if (x < 0 || x >= outWidth || y < 0 || y >= outHeight) return; + + unsigned char *p = ucoutput+x*2+y*outWidth*2; + if (p[0] < 255-br1) p[0] += br1; else p[0] = 255; + if (p[1] < 255-br2) p[1] += br2; else p[1] = 255; + //p += lastOutput-output; + //if (p[0] < 255-br1) p[0] += br1; else p[0] = 255; + //if (p[1] < 255-br2) p[1] += br2; else p[1] = 255; +} + +inline void addPixelFast(unsigned char *p,int br1,int br2) { + if (p[0] < 255-br1) p[0] += br1; else p[0] = 255; + if (p[1] < 255-br2) p[1] += br2; else p[1] = 255; + //p += lastOutput-output; + //if (p[0] < 255-br1) p[0] += br1; else p[0] = 255; + //if (p[1] < 255-br2) p[1] += br2; else p[1] = 255; +} + +void fadeFade() { + register unsigned long *ptr = (unsigned long*)ucoutput; + int i = outWidth*outHeight*2/4; + do { + //Bytewize version was: *(ptr++) -= *ptr+(*ptr>>1)>>4; + if (*ptr) + //if (*ptr & 0xf0f0f0f0ul) + *(ptr++) -= ((*ptr & 0xf0f0f0f0ul) >> 4) + ((*ptr & 0xe0e0e0e0ul) >> 5); + //else { + // *(ptr++) = (*ptr * 14 >> 4) & 0x0f0f0f0ful; + //} + else + ptr++; + } while(--i > 0); +} + +inline unsigned char getPixel(int x,int y,int where) { + if (x < 0 || y < 0 || x >= outWidth || y >= outHeight) return 0; + return lastOutput[where]; +} + +inline void fadePixelWave(int x,int y,int where,int step) { + short j = + ( short(getPixel(x-1,y,where-2))+ + getPixel(x+1,y,where+2)+ + getPixel(x,y-1,where-step)+ + getPixel(x,y+1,where+step) + >> 2) + +lastOutput[where]; + if (!j) { ucoutput[where] = 0; return; } + j = j + -lastLastOutput[where] + -1; + if (j < 0) ucoutput[where] = 0; + else if (j & (255*256)) ucoutput[where] = 255; + else ucoutput[where] = j; +} + +void fadeWave() { + unsigned short *t = lastLastOutputBmp.data; + lastLastOutputBmp.data = lastOutputBmp.data; + lastOutputBmp.data = outputBmp.data; + outputBmp.data = t; + + int x,y,i,j,start,end; + int step = outWidth*2; + for(x=0,i=0,j=outWidth*(outHeight-1)*2;x> 2) + +lastOutput[i]; + if (!j) { + ucoutput[i] = 0; + } else { + j = j + -lastLastOutput[i] + -1; + if (j < 0) ucoutput[i] = 0; + else if (j & (255*256)) ucoutput[i] = 255; + else ucoutput[i] = j; + } + } while(++i < end); + } +} + +inline void fadePixelHeat(int x,int y,int where,int step) { + short j = + ( short(getPixel(x-1,y,where-2))+ + getPixel(x+1,y,where+2)+ + getPixel(x,y-1,where-step)+ + getPixel(x,y+1,where+step) + >> 2) + +lastOutput[where]; + if (!j) { ucoutput[where] = 0; return; } + j = j + -lastLastOutput[where] + -1; + if (j < 0) ucoutput[where] = 0; + else if (j & (255*256)) ucoutput[where] = 255; + else ucoutput[where] = j; +} + +void fadeHeat() { + unsigned short *t = lastLastOutputBmp.data; + lastLastOutputBmp.data = lastOutputBmp.data; + lastOutputBmp.data = outputBmp.data; + outputBmp.data = t; + + int x,y,i,j,start,end; + int step = outWidth*2; + for(x=0,i=0,j=outWidth*(outHeight-1)*2;x> 2) + +lastOutput[i]; + if (!j) { + ucoutput[i] = 0; + } else { + j = j + -lastLastOutput[i] + +(lastLastOutput[i] + -lastOutput[i]>>2) + -1; + if (j < 0) ucoutput[i] = 0; + else if (j & (255*256)) ucoutput[i] = 255; + else ucoutput[i] = j; + } + } while(++i < end); + } +} + +void fade() { + switch(fadeMode) { + case Stars : + fadeFade(); + break; + case Flame : + fadeHeat(); + break; + case Wave : + fadeWave(); + break; + default: + break; + } +} + +int coreGo() { + double x[n], y[n]; + double a[n], b[n]; + int clarity[n]; //Surround sound + int i,j,k; + + int brightFactor = int(brightness * brightnessTwiddler /(starSize+0.01)); + + if (-1 == getNextFragment()) + { + fprintf(stderr, "no frag\n" ); + return -1; + } + + for(i=0;i>1)>>4; + if (*ptr) + if (*ptr & 0xf0f0f0f0ul) + *(ptr++) -= ((*ptr & 0xf0f0f0f0ul) >> 4) + ((*ptr & 0xe0e0e0e0ul) >> 5); + else { + *(ptr++) = (*ptr * 14 >> 4) & 0x0f0f0f0ful; + //Should be 29/32 to be consistent. Who cares. This is totally + // hacked anyway. + //unsigned char *subptr = (unsigned char*)(ptr++); + //subptr[0] = (int)subptr[0] * 29 / 32; + //subptr[1] = (int)subptr[0] * 29 / 32; + //subptr[2] = (int)subptr[0] * 29 / 32; + //subptr[3] = (int)subptr[0] * 29 / 32; + } + else + ptr++; + } while(--i > 0); + */ + + int heightFactor = n/2 / outHeight + 1; + int actualHeight = n/2/heightFactor; + int heightAdd = outHeight + actualHeight >> 1; + + /* Correct for window size */ + double brightFactor2 = (brightFactor/65536.0/n)* + sqrt(actualHeight*outWidth/(320.0*200.0)); + + for(i=1;i 0 || b[i] > 0) { + int h = (int)( b[i]*outWidth / (a[i]+b[i]) ); + int br1, br2, br = (int)( + (a[i]+b[i])*i*brightFactor2 ); + br1 = br*(clarity[i]+128)>>8; + br2 = br*(128-clarity[i])>>8; + if (br1 < 0) br1 = 0; else if (br1 > 255) br1 = 255; + if (br2 < 0) br2 = 0; else if (br2 > 255) br2 = 255; + //unsigned char *p = output+ h*2+(164-((i<<8)>>m))*(outWidth*2); + int px = h, + py = heightAdd - i / heightFactor; + + if (pointsAreDiamonds) { + addPixel(px,py,br1,br2); + br1=scaleDown[br1];br2=scaleDown[br2]; + + //TODO: Use addpixelfast + for(j=1;br1>0||br2>0;j++,br1=scaleDown[br1],br2=scaleDown[br2]) { + for(k=0;k outWidth-maxStarRadius || py > outHeight-maxStarRadius) { + addPixel(px,py,br1,br2); + for(j=1;br1>0||br2>0;j++,br1=scaleDown[br1],br2=scaleDown[br2]) { + addPixel(px+j,py,br1,br2); + addPixel(px,py+j,br1,br2); + addPixel(px-j,py,br1,br2); + addPixel(px,py-j,br1,br2); + } + } else { + unsigned char *p = ucoutput+px*2+py*outWidth*2, *p1=p, *p2=p, *p3=p, *p4=p; + addPixelFast(p,br1,br2); + for(;br1>0||br2>0;br1=scaleDown[br1],br2=scaleDown[br2]) { + p1 += 2; + addPixelFast(p1,br1,br2); + p2 -= 2; + addPixelFast(p2,br1,br2); + p3 += outWidth*2; + addPixelFast(p3,br1,br2); + p4 -= outWidth*2; + addPixelFast(p4,br1,br2); + } + } + } + } + } + return 0; +} diff --git a/kscd/kscdmagic/logo.h b/kscd/kscdmagic/logo.h new file mode 100644 index 00000000..478f8c70 --- /dev/null +++ b/kscd/kscdmagic/logo.h @@ -0,0 +1,50 @@ +int logo[48][48] = { +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,17,17,0,0,0,17,17,0,0,17,0,0,0,17,0,17,17,17,0,0,0,17,0,0,0,17,17,0,0,17,17,17}, +{0,0,0,0,0,0,0,0,17,17,17,17,17,0,0,17,0,0,17,0,17,0,0,17,0,17,17,0,17,17,0,17,0,0,17,0,17,0,17,0,17,0,0,17,0,0,17,0}, +{0,0,0,0,0,0,0,0,17,0,0,0,17,0,0,17,0,0,0,0,17,0,0,17,0,17,0,17,0,17,0,17,0,0,17,0,17,0,17,0,17,0,0,0,0,0,17,0}, +{0,0,0,0,0,0,0,0,17,0,0,0,17,0,0,17,0,0,17,0,17,0,0,17,0,17,0,17,0,17,0,17,17,17,0,0,17,17,17,0,17,0,0,17,0,0,17,0}, +{0,0,0,0,0,0,0,0,17,0,0,0,17,0,0,0,17,17,0,0,0,17,17,0,0,17,0,0,0,17,0,17,0,0,0,0,17,0,17,0,0,17,17,0,0,0,17,0}, +{0,0,0,0,0,0,0,0,17,0,0,0,17,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,17,0,0,0,17,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,17,0,0,0,17,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,17,17,17,17,17,17,17,0,0,0,17,0,0,17,17,17,17,17,0,0,0,0,17,17,17,17,17,17,17,17,17,17,0,0,0,0,17,17,17,17,17,17,17,17,0,0}, +{0,17,0,0,0,0,0,0,0,0,0,0,17,0,0,17,0,0,0,17,0,0,0,17,0,0,0,0,0,0,0,0,0,17,0,0,0,17,0,0,0,0,0,0,0,0,17,0}, +{17,0,0,0,0,0,0,0,0,0,0,0,17,0,0,17,0,0,0,17,0,0,17,0,0,0,0,0,0,0,0,0,0,17,0,0,17,0,0,0,0,0,0,0,0,0,0,17}, +{17,0,0,0,0,17,17,17,0,0,0,0,17,0,0,17,0,0,0,17,0,0,17,0,0,0,0,0,0,0,0,0,0,17,0,0,17,0,0,0,0,17,17,0,0,0,0,17}, +{17,0,0,0,17,0,0,0,17,0,0,0,17,0,0,17,0,0,0,17,0,0,17,0,0,0,17,17,17,17,17,17,17,17,0,0,17,0,0,0,17,0,0,17,0,0,0,17}, +{17,0,0,0,17,0,0,0,17,0,0,0,17,0,0,17,0,0,0,17,0,0,17,0,0,17,0,0,0,0,0,0,0,0,0,0,17,0,0,0,17,0,0,17,0,0,0,17}, +{17,0,0,0,17,0,0,0,17,0,0,0,17,0,0,17,0,0,0,17,0,0,17,0,0,0,17,17,17,17,17,17,0,0,0,0,17,0,0,0,17,0,0,17,0,0,0,17}, +{17,0,0,0,17,0,0,0,17,0,0,0,17,0,0,17,0,0,0,17,0,0,17,0,0,0,0,0,0,0,0,0,17,0,0,0,17,0,0,0,17,0,0,17,17,17,17,17}, +{17,0,0,0,17,0,0,0,17,0,0,0,17,0,0,17,0,0,0,17,0,0,17,0,0,0,0,0,0,0,0,0,0,17,0,0,17,0,0,0,17,0,0,0,0,0,0,0}, +{17,0,0,0,17,0,0,0,17,0,0,0,17,0,0,17,0,0,0,17,0,0,0,17,0,0,0,0,0,0,0,0,0,17,0,0,17,0,0,0,17,0,0,17,17,17,17,17}, +{17,0,0,0,17,0,0,0,17,0,0,0,17,0,0,17,0,0,0,17,0,0,0,0,17,17,17,17,17,17,0,0,0,17,0,0,17,0,0,0,17,0,0,17,0,0,0,17}, +{17,0,0,0,17,0,0,0,17,0,0,0,17,0,0,17,0,0,0,17,0,0,0,0,0,0,0,0,0,0,17,0,0,17,0,0,17,0,0,0,17,0,0,17,0,0,0,17}, +{17,0,0,0,17,0,0,0,17,0,0,0,17,0,0,17,0,0,0,17,0,0,17,17,17,17,17,17,17,17,0,0,0,17,0,0,17,0,0,0,17,0,0,17,0,0,0,17}, +{17,0,0,0,0,17,17,17,0,0,0,0,17,0,0,17,0,0,0,17,0,0,17,0,0,0,0,0,0,0,0,0,0,17,0,0,17,0,0,0,0,17,17,0,0,0,0,17}, +{17,0,0,0,0,0,0,0,0,0,0,0,17,0,0,17,0,0,0,17,0,0,17,0,0,0,0,0,0,0,0,0,0,17,0,0,17,0,0,0,0,0,0,0,0,0,0,17}, +{0,17,0,0,0,0,0,0,0,0,0,0,17,0,0,17,0,0,0,17,0,0,17,0,0,0,0,0,0,0,0,0,17,0,0,0,0,17,0,0,0,0,0,0,0,0,17,0}, +{0,0,17,17,17,17,17,17,17,17,17,17,17,0,0,17,17,17,17,17,0,0,17,17,17,17,17,17,17,17,17,17,0,0,0,0,0,0,17,17,17,17,17,17,17,17,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{17,17,17,0,0,17,0,0,17,17,17,0,17,0,17,17,17,0,0,17,0,0,17,0,0,0,0,0,0,17,0,0,17,0,0,17,0,17,17,17,0,0,17,0,0,17,17,0}, +{17,0,0,17,0,17,0,17,0,0,0,0,17,0,0,17,0,0,17,0,17,0,17,0,0,0,0,0,17,0,17,0,17,0,0,17,0,17,0,0,17,0,17,0,17,0,0,17}, +{17,0,0,17,0,17,0,17,0,17,17,0,17,0,0,17,0,0,17,0,17,0,17,0,0,0,0,0,17,0,17,0,17,0,0,17,0,17,0,0,17,0,17,0,17,0,0,17}, +{17,0,0,17,0,17,0,17,0,0,17,0,17,0,0,17,0,0,17,17,17,0,17,0,0,0,0,0,17,17,17,0,17,0,0,17,0,17,0,0,17,0,17,0,17,0,0,17}, +{17,17,17,0,0,17,0,0,17,17,17,0,17,0,0,17,0,0,17,0,17,0,17,17,17,0,0,0,17,0,17,0,0,17,17,0,0,17,17,17,0,0,17,0,0,17,17,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} +}; diff --git a/kscd/kscdmagic/magicconf.h b/kscd/kscdmagic/magicconf.h new file mode 100644 index 00000000..86ed42de --- /dev/null +++ b/kscd/kscdmagic/magicconf.h @@ -0,0 +1,23 @@ + +#ifndef __MAGIC_CONF_H_ +#define __MAGIC_CONF_H_ + +/***************************************/ +/* For the incurably fiddle prone: */ + +/* log2 of sample size */ +#define m 8 + +/* overlap amount between samples. Set to 1 or 2 if you have a fast computer */ +#define overlap 0 + +/* Brightness */ +#define brightness 150 + +/* Sample frequency*/ +#define frequency 22050 + +#define MITSHM 1 /* use MIT X11 shared memory*/ + +/***************************************/ +#endif diff --git a/kscd/kscdmagic/main.cpp b/kscd/kscdmagic/main.cpp new file mode 100644 index 00000000..7196d3a2 --- /dev/null +++ b/kscd/kscdmagic/main.cpp @@ -0,0 +1,300 @@ +/* + + $Id$ + + kscdmagic 2.0 Dirk Försterling + + based on: + + kscdmagic 1.0 Bernd Johannes Wuebben + + based on: + + Synaesthesia - program to display sound graphically + Copyright (C) 1997 Paul Francis Harrison + + 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. + + The author may be contacted at: + pfh@yoyo.cc.monash.edu.au + 27 Bond St., Mt. Waverley, 3149, Melbourne, Australia + +*/ + +#include +#include +#include + +#if defined(__linux__) || defined(__svr4__) || defined(__osf__) + +#include +#include +#include +#include +#include +#include +#include +#if defined(__linux__) +#include +#endif + +#include +#include +#include +#include +#include +#include + +#include "logo.h" +#include "magicconf.h" +#include "syna.h" +#include "version.h" + +volatile short *data; + +int outWidth, outHeight; +double brightnessTwiddler; +SymbolID fadeMode = Stars; +double starSize = 0.125; +bool pointsAreDiamonds = true; + + +const int numRows = 4; +const int rowHeight = 50; +const int leftColWidth = 40; +const int rowMaxWidth = 310; +const int sliderBorder = 20; +const int sliderWidth = rowMaxWidth - leftColWidth - sliderBorder*2; +const int numberSpacing = 15; +const int uiWidth = 330; +const int uiHeight = 135; + + +static int isExpanded = 0; +static double bright = 1.0; + +Bitmap outputBmp, lastOutputBmp, lastLastOutputBmp; +PolygonEngine polygonEngine; + +void +allocOutput(int w,int h) +{ + outputBmp.size(w,h); + lastOutputBmp.size(w,h); + lastLastOutputBmp.size(w,h); + polygonEngine.size(w,h); + outWidth = w; + outHeight = h; +} // allocOutput() + +void +setBrightness(double bright) +{ + brightnessTwiddler = bright; +} // setBrightness() + + + +static void +cleanup( int sig ) +{ + (void) sig; + closeSound(); + exit(0); +} // cleanup() + + +// make sure the pid file is cleaned up when exiting unexpectedly. + +void +catchSignals() +{ + signal(SIGHUP, cleanup); /* Hangup */ + signal(SIGINT, cleanup); /* Interrupt */ + signal(SIGTERM, cleanup); /* Terminate */ + signal(SIGPIPE, cleanup); + signal(SIGQUIT, cleanup); +} // catchSignals() + +void +usage(char*) +{ + fprintf(stderr, "Valid command line options:\n"); + fprintf(stderr, " -b set brightness (1 - 10)\n"); + fprintf(stderr, " -w set width\n"); + fprintf(stderr, " -h set height\n"); + exit(1); +} // usage() + +void +error(const char *str, bool syscall) { + fprintf(stderr, PROGNAME ": Error %s\n",str); + if (syscall) + fprintf(stderr,"(reason for error: %s)\n",strerror(errno)); + exit(1); +} // error() + +void +warning(const char *str, bool syscall) { + fprintf(stderr, PROGNAME ": Possible error %s\n",str); + if (syscall) + fprintf(stderr,"(reason for error: %s)\n",strerror(errno)); +} // warning() + + + +int +processUserInput() +{ + + int mouseX, mouseY, mouseButtons; + char keyHit; + + inputUpdate(mouseX,mouseY,mouseButtons,keyHit); + + if( keyHit == 'q' ) + return -1; + + + if (sizeUpdate()) + { + isExpanded = 0; + } + + return 0; +} // processUserInput() + +int +main(int argc, char **argv) +{ + int windX=10; + int windY=30; + int windWidth=uiWidth; + int windHeight=uiHeight; + int c; + int xx, xy; + opterr = 0; + + /* + KAboutData aboutData( "kscdmagic", I18N_NOOP("kscdmagic"), + KSCDMAGICVERSION, I18N_NOOP("sound visualisation"), + KAboutData::License_GPL, + "(c) 2000, Dirk Försterling"); + aboutData.addAuthor("Paul Harrison",0, "pfh@yoyo.cc.monash.edu.au"); + aboutData.addAuthor("Dirk Försterling",0, "milliByte@gmx.net"); + + KCmdLineArgs::init( argc, argv, &aboutData ); + + KApplication magicApp; + */ + + + openSound(SourceCD, 44100, "/dev/dsp", NULL); + + catchSignals(); + + while ((c = getopt(argc, argv, "b:h:w:")) != -1){ + switch (c) + { + case '?': + fprintf(stderr, "%s: unknown option \"%s\"\n", + argv[0], argv[optind-1]); + usage(argv[0]); + exit(1); + case 'b': + bright = (double) atoi(optarg); + bright = bright/10; + break; + case 'w': + windWidth = atoi(optarg); + break; + case 'h': + windHeight = atoi(optarg); + break; + } + } + + if (bright > 1.0) + bright = 1.0; + else if (bright < 0.0) + bright = 0.0; + + if (windWidth < 1) + windWidth = uiWidth; + if (windHeight < 1) + windHeight = uiHeight; + + screenInit(windX,windY,windWidth,windHeight); + + allocOutput(outWidth,outHeight); + + coreInit(); + + + setStarSize(starSize); + setBrightness(bright); + + time_t timer = time(NULL); + + int frames = 0; + + for(;;) { + fade(); + if (-1 == coreGo()) + break; + + polygonEngine.clear(); + + for( xy = 0; xy < 48; xy++) + { + for( xx = 0; xx < 48; xx++) + { + if ( logo[xy][xx] != 0) + { + polygonEngine.add(32769, xx+10, xy+3); + } + } + } + polygonEngine.apply(outputBmp.data); + screenShow(); + + + + frames++; + if(processUserInput() == -1) + break; + } + + + timer = time(NULL) - timer; + delete ucoutput; + closeSound(); + + if (timer > 10) + fprintf(stderr,"Frames per second: %f\n", double(frames)/timer); + + return 0; +} // main() /* linux */ + +#else + +int main() +{ + fprintf(stderr,"KSCD Magic works currently only on Linux.\n"\ + "It should however be trivial to port it to other platforms ...\n"); +} // main() /* non-linux */ + +#endif + diff --git a/kscd/kscdmagic/polygon.h b/kscd/kscdmagic/polygon.h new file mode 100644 index 00000000..4337ab10 --- /dev/null +++ b/kscd/kscdmagic/polygon.h @@ -0,0 +1,106 @@ +#include + +template +struct Bitmap { + Pixel *data; + int width, height; + + Bitmap() : data(0) { }; + ~Bitmap() { delete[] data; }; + + void size(int w,int h) { + delete[] data; + width = w; + height = h; + data = new Pixel[w*h+extra]; + clear(); + } + + void clear() { + memset(data,0,sizeof(Pixel)*(width*height+extra)); + } +}; + +template +struct PolygonEngine : public Bitmap { +#define super (1<= height) return; + if (x < 0) x = 0; + if (x > width) x = width; + data[x+y*width] += color; + } + + /* Color is char[layers] */ + + // zwoosh, yknow, it goes... zwoosh an all these bars and lines and + // crap intersect. + Pixel colorTable[2][super+1]; + void pen(Pixel color) { + for(int i=0;i>16)&(super-1))], + x>>(16+superSampleShift),y>>superSampleShift); + add(colors[(x>>16)&(super-1)], + 1+(x>>(16+superSampleShift)),y>>superSampleShift); + x += slope; + y++; + } + } + + void icon(double icon[][4],Pixel color,double x,double y, + double scaleX, double scaleY) { + pen(color); + x *= super; + y *= super; + scaleX *= super; + scaleY *= super; + for(int i=0;icon[i][1] != icon[i][3];i++) + line(int(icon[i][0]*scaleX+x),int(icon[i][1]*scaleY+y), + int(icon[i][2]*scaleX+x),int(icon[i][3]*scaleY+y)); + } +#undef super +}; diff --git a/kscd/kscdmagic/sound.cpp b/kscd/kscdmagic/sound.cpp new file mode 100644 index 00000000..0bcb8d8d --- /dev/null +++ b/kscd/kscdmagic/sound.cpp @@ -0,0 +1,252 @@ +/* Synaesthesia - program to display sound graphically + Copyright (C) 1997 Paul Francis Harrison + + 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. + + The author may be contacted at: + pfh@yoyo.cc.monash.edu.au + or + 27 Bond St., Mt. Waverley, 3149, Melbourne, Australia +*/ + +#if defined(__linux__) || defined(__svr4__) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined (__linux__) +#include +#ifndef __GNUC__ +#define __GNUC__ 1 +#endif +#undef __STRICT_ANSI__ +#include +#include +#endif + +#if defined (__svr4__) +#include +#endif + + +// who knows when we'll need that... +#if defined (FreeBSD) +#include +#include +#define CDROM_LEADOUT 0xAA +#define CD_FRAMES 75 /* frames per second */ +#define CDROM_DATA_TRACK 0x4 +#endif + +#include + +#include +#include +#include +#include "syna.h" +#include "magicconf.h" + + +/* Sound Recording ================================================= */ + +#ifdef LITTLEENDIAN +#define SOUNDFORMAT AFMT_S16_LE +#else +#define SOUNDFORMAT AFMT_S16_BE +#endif + +//If kernel starts running out of sound memory playing mp3s, this could +//be the problem. OTOH if it is too small, it will start ticking on slow +//computers +#define MAXWINDOWSIZE 32 + +static SoundSource source; +static int inFrequency, downFactor, windowSize, pipeIn, device; +static short *dataIn; +static char *mixer; + +void +openSound(SoundSource source, int inFrequency, const char *dspName, + char *mixerName) +{ + ::source = source; + ::inFrequency = inFrequency; + ::windowSize = 1; + mixer = mixerName; + downFactor = inFrequency / frequency; + if (downFactor <= 0) + downFactor = 1; + + int format, stereo, fragment, fqc; + +#ifdef __FreeBSD__ + attempt(device = open(dspName,O_WRONLY),"opening dsp device",true); + format = SOUNDFORMAT; + attempt(ioctl(device,SNDCTL_DSP_SETFMT,&format),"setting format",true); + if (format != SOUNDFORMAT) error("setting format (2)"); + close(device); +#endif + if (source == SourcePipe) + attempt(device = open(dspName,O_WRONLY),"opening dsp device",true); + else + attempt(device = open(dspName,O_RDONLY),"opening dsp device",true); + + //Probably not needed + //attemptNoDie(ioctl(device,SNDCTL_DSP_RESET,0),"reseting dsp"); + format = SOUNDFORMAT; + fqc = (source == SourcePipe ? inFrequency : frequency); + stereo = 1; + + //int logWindowSize = -1, tmp = windowSize*downFactor; + //while(tmp) { + // tmp /= 2; + // logWindowSize++; + //} + + if (source == SourcePipe) + //fragment = 0x00020000 + (m-overlap+1)+logWindowSize; + fragment = 0x00010000*(MAXWINDOWSIZE+1) + (m-overlap+1);//+logWindowSize; + //Soundcard should read in windowSize + // blocks of sound before blocking + else + //fragment = 0x00020000 + (m-overlap+1); //2 fragments of size 2*(2^(m-overlap+1)) bytes + + //Added extra fragments to allow recording overrun (9/7/98) + fragment = 0x00080000 + (m-overlap+1); //8 fragments of size 2*(2^(m-overlap+1)) bytes + + + + + //Was 0x00010000 + m; + + attemptNoDie(ioctl(device,SNDCTL_DSP_SETFRAGMENT,&fragment),"setting fragment",true); +#ifndef __FreeBSD__ + attempt(ioctl(device,SNDCTL_DSP_SETFMT,&format),"setting format",true); + if (format != SOUNDFORMAT) error("setting format (2)"); +#endif + attempt(ioctl(device,SNDCTL_DSP_STEREO,&stereo),"setting stereo",true); + attemptNoDie(ioctl(device,SNDCTL_DSP_SPEED,&fqc),"setting frequency",true); + + data = new short[n*2]; + + if (source == SourcePipe) { + dataIn = new short[n*2*downFactor*MAXWINDOWSIZE]; + memset(dataIn,0,n*4*downFactor*MAXWINDOWSIZE); + pipeIn = dup(0); + close(0); + } +} + +void closeSound() { + delete data; + if (source == SourcePipe) { + delete dataIn; + close(pipeIn); + } + close(device); +} + +int readWholeBlock(int pipe,char *dest,int length) { + while(length > 0) { + int result = read(pipe,dest,length); + if (result < 1) + return -1; + dest += result; + length -= result; + } + return 0; +} + +int getNextFragment(void) { + if (source == SourcePipe) { + static int lastTime = 0; + int nowTime; + timeval timeVal1, timeVal2; + + gettimeofday(&timeVal1,0); + write(device, (char*)dataIn, n*4*downFactor*windowSize); + gettimeofday(&timeVal2,0); + + nowTime = timeVal1.tv_usec + timeVal1.tv_sec * 1000000; + if (nowTime > lastTime) { + int optimumFrags = + int(double(nowTime-lastTime)*inFrequency/1000000.0/(n*downFactor)) + +1; + if (optimumFrags > MAXWINDOWSIZE) + optimumFrags = MAXWINDOWSIZE; + + windowSize = optimumFrags; + } + + lastTime = timeVal2.tv_usec + timeVal2.tv_sec * 1000000; + + if (readWholeBlock(pipeIn, ((char*)dataIn), n*4*downFactor*windowSize) == -1) + return -1; + + int i,j; + for(i=0,j=0;i 8 || info.blocks < 1) /* Sanity check */ + info.blocks = 1; + + for(i=0;i +#else +#include +#endif +#if BYTE_ORDER == BIG_ENDIAN +#define BIGENDIAN +#else +#define LITTLEENDIAN +#endif + + +#define n (1< outputBmp, lastOutputBmp, lastLastOutputBmp; +#define ucoutput ((unsigned char*)outputBmp.data) +#define lastOutput ((unsigned char*)lastOutputBmp.data) +#define lastLastOutput ((unsigned char*)lastLastOutputBmp.data) + +inline unsigned short combiner(unsigned short a,unsigned short b) { + //Not that i want to give the compiler a hint or anything... + unsigned char ah = a>>8, al = a&255, bh = b>>8, bl = b&255; + if (ah < 64) ah *= 4; else ah = 255; + if (al < 64) al *= 4; else al = 255; + if (bh > ah) ah = bh; + if (bl > al) al = bl; + return ah*256+al; +} + +extern PolygonEngine polygonEngine; + +extern int outWidth, outHeight; + +void allocOutput(int w,int h); + +void coreInit(); +void setStarSize(double size); +int coreGo(); +void fade(); + +/* *wrap */ +void screenInit(int xHint,int yHint,int widthHint,int heightHint); +void screenSetPalette(unsigned char *palette); +void screenEnd(void); +void screenShow(void); +int sizeUpdate(void); + +void inputUpdate(int &mouseX,int &mouseY,int &mouseButtons,char &keyHit); + +/* ui */ +void interfaceInit(); +void interfaceSyncToState(); +void interfaceEnd(); +bool interfaceGo(); + +enum SymbolID { + Speaker, Bulb, + Play, Pause, Stop, SkipFwd, SkipBack, + Handle, Pointer, Open, NoCD, Exit, + Zero, One, Two, Three, Four, + Five, Six, Seven, Eight, Nine, + Slider, Selector, Plug, Loop, Box, Bar, + Flame, Wave, Stars, Star, Diamond, Size, FgColor, BgColor, + Save, Reset, TrackSelect, + NotASymbol +}; + +/* State information */ + +extern SymbolID state; +extern int track, frames; +extern double trackProgress; +extern char **playList; +extern int playListLength, playListPosition; +extern SymbolID fadeMode; +extern bool pointsAreDiamonds; +extern double brightnessTwiddler; +extern double starSize; +extern double fgRedSlider, fgGreenSlider, bgRedSlider, bgGreenSlider; + +extern double volume; + +void setStateToDefaults(); +void saveConfig(); + +void putString(char *string,int x,int y,int red,int blue); + +/* sound */ +enum SoundSource { SourceLine, SourceCD, SourcePipe }; + +void cdOpen(char *cdromName); +void cdClose(void); +void cdGetStatus(int &track, int &frames, SymbolID &state); +void cdPlay(int trackFrame, int endFrame=-1); +void cdStop(void); +void cdPause(void); +void cdResume(void); +void cdEject(void); +void cdCloseTray(void); +int cdGetTrackCount(void); +int cdGetTrackFrame(int track); +void openSound(SoundSource sound, int downFactor, const char *dspName, char *mixerName); +void closeSound(); +void setupMixer(double &loudness); +void setVolume(double loudness); +int getNextFragment(void); + + +#endif // linux || svr4 +#endif // __SYNA_H__ diff --git a/kscd/kscdmagic/version.h b/kscd/kscdmagic/version.h new file mode 100644 index 00000000..aa5df67c --- /dev/null +++ b/kscd/kscdmagic/version.h @@ -0,0 +1 @@ +#define KSCDMAGICVERSION "2.0" diff --git a/kscd/kscdmagic/xlib.c b/kscd/kscdmagic/xlib.c new file mode 100644 index 00000000..2fb15c19 --- /dev/null +++ b/kscd/kscdmagic/xlib.c @@ -0,0 +1,781 @@ +/* + * XaoS, a fast portable realtime fractal zoomer + * Copyright (C) 1996,1997 by + * + * Jan Hubicka (hubicka@paru.cas.cz) + * Thomas Marsh (tmarsh@austin.ibm.com) + * + * 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. + * + * + * Shamelessly ripped for use in xsynaesthesia + */ +/*#include "aconfig.h"*/ +#define X11_DRIVER +/*#define MITSHM*/ + +#ifdef X11_DRIVER +#include +#include +#include +#include +#include +#include +#ifndef __FreeBSD__ +#include +#else +#include +#endif +#include "xlib.h" +#ifdef AMIGA +#define XFlush(x) while(0) +#endif + +#undef PIXMAP + +#define chkalloc(n) if (!n) fprintf(stderr, "out of memory\n"), exit(-1) + +int xupdate_size(xdisplay * d) +{ + int tmp; + Window wtmp; + int width = d->width, height = d->height; + XGetGeometry(d->display, d->window, &wtmp, &tmp, &tmp, &d->width, &d->height, (unsigned int *) &tmp, (unsigned int *) &tmp); + if ((int)d->width != width || (int)d->height != height) + return 1; + return 0; +} + +void xflip_buffers(xdisplay * d) +{ + d->back = d->vbuffs[d->current]; + d->current ^= 1; + d->vbuff = d->vbuffs[d->current]; +} + +void draw_screen(xdisplay * d) +{ + switch (d->image[0]->bits_per_pixel) { + case 16:{ + unsigned short *de; + unsigned char *s; + unsigned char *e; + for (s = (unsigned char *) d->vbuffs[d->current], + e = (unsigned char *) d->vbuffs[d->current] + (d->linewidth * d->height), + de = (unsigned short *) d->data[d->current]; s < e; s += 8, de += 8) + *de = d->pixels[*s], + *(de + 1) = d->pixels[*(s + 1)], + *(de + 2) = d->pixels[*(s + 2)], + *(de + 3) = d->pixels[*(s + 3)], + *(de + 4) = d->pixels[*(s + 4)], + *(de + 5) = d->pixels[*(s + 5)], + *(de + 6) = d->pixels[*(s + 6)], + *(de + 7) = d->pixels[*(s + 7)]; + s -= 8; + de -= 8; + for (; s < e; s++, de++) + *de = d->pixels[*s]; + break; + } + case 24:{ + unsigned char *de; + unsigned char *s; + unsigned char *e; + for (s = (unsigned char *) d->vbuffs[d->current], + e = (unsigned char *) d->vbuffs[d->current] + (d->linewidth * d->height), + de = (unsigned char *) d->data[d->current]; s < e; s++, de+=3) + de[0] = d->pixels[*s], + de[1] = d->pixels[*s]>>8, + de[2] = d->pixels[*s]>>16; + + break; + } + case 32:{ + unsigned long *de; + unsigned char *s; + unsigned char *e; + for (s = (unsigned char *) d->vbuffs[d->current], + e = (unsigned char *) d->vbuffs[d->current] + (d->linewidth * d->height), + de = (unsigned long *) d->data[d->current]; s < e; s += 8, de += 8) + *de = d->pixels[*s], + *(de + 1) = d->pixels[*(s + 1)], + *(de + 2) = d->pixels[*(s + 2)], + *(de + 3) = d->pixels[*(s + 3)], + *(de + 4) = d->pixels[*(s + 4)], + *(de + 5) = d->pixels[*(s + 5)], + *(de + 6) = d->pixels[*(s + 6)], + *(de + 7) = d->pixels[*(s + 7)]; + s -= 8; + de -= 8; + for (; s < e; s++, de++) + *de = d->pixels[*s]; + break; + } + } +#ifdef MITSHM + if (d->SharedMemFlag) { + XShmPutImage(d->display, d->window, d->gc, d->image[d->current], 0, 0, 0, + 0, d->width, d->height, True); + XFlush(d->display); + } else +#endif + { + XPutImage(d->display, d->window, d->gc, d->image[d->current], 0, 0, 0, 0, d->width, d->height); + XFlush(d->display); + } + d->screen_changed = 0; +} + +#ifdef MITSHM +int alloc_shm_image(xdisplay * new) +{ + register char *ptr; + int temp, size = 0, i; + ptr = DisplayString(new->display); + if (!ptr || (*ptr == ':') || !strncmp(ptr, "localhost:", 10) || + !strncmp(ptr, "unix:", 5) || !strncmp(ptr, "local:", 6)) { + new->SharedMemOption = XQueryExtension(new->display, "MIT-SHM", &temp, &temp, &temp); + } else { + new->SharedMemOption = False; + return 0; + } + new->SharedMemFlag = False; +#if 0 + new->SharedMemOption = True; + new->SharedMemFlag = False; +#endif + + if (new->SharedMemFlag) { + XShmDetach(new->display, &new->xshminfo[0]); + XShmDetach(new->display, &new->xshminfo[1]); + new->image[0]->data = (char *) NULL; + new->image[1]->data = (char *) NULL; + shmdt(new->xshminfo[0].shmaddr); + shmdt(new->xshminfo[1].shmaddr); + } + for (i = 0; i < 2; i++) { + if (new->SharedMemOption) { + int mul; + if (new->depth == 8) + mul = 1; + else if (new->depth <= 24) + mul = 2; + else + mul = 4; + new->SharedMemFlag = False; + new->image[i] = XShmCreateImage(new->display, new->visual, new->depth, ZPixmap, + NULL, &new->xshminfo[i], new->width, new->height * mul); + if (new->image[i]) { + temp = new->image[i]->bytes_per_line * new->image[i]->height; + new->linewidth = new->image[i]->bytes_per_line * 8 / new->image[i]->bits_per_pixel; + if (temp > size) + size = temp; + new->xshminfo[i].shmid = shmget(IPC_PRIVATE, size, IPC_CREAT | 0777); + if (new->xshminfo[i].shmid != -1) { + new->xshminfo[i].shmaddr = (char *) shmat(new->xshminfo[i].shmid, 0, 0); + if (new->xshminfo[i].shmaddr != (char *) -1) { + new->image[i]->data = new->xshminfo[i].shmaddr; + new->data[i] = new->vbuffs[i] = (char *) new->image[i]->data; + new->xshminfo[i].readOnly = True; + + new->SharedMemFlag = XShmAttach(new->display, &new->xshminfo[i]); + XSync(new->display, False); + if (!new->SharedMemFlag) { + XDestroyImage(new->image[i]); + new->image[i] = (XImage *) NULL; + new->SharedMemFlag = 0; + return 0; + } + } + /* Always Destroy Shared Memory Ident */ + shmctl(new->xshminfo[i].shmid, IPC_RMID, 0); + } + if (!new->SharedMemFlag) { + XDestroyImage(new->image[i]); + new->image[i] = (XImage *) NULL; + new->SharedMemFlag = 0; + return 0; + } + } else { + new->SharedMemFlag = 0; + return 0; + } + } else { + new->SharedMemFlag = 0; + return 0; + } + } + new->current = 0; + xflip_buffers(new); + return 1; +} + +void free_shm_image(xdisplay * d) +{ + if (d->SharedMemFlag) { + XDestroyImage(d->image[0]); + XDestroyImage(d->image[1]); + XShmDetach(d->display, &d->xshminfo[0]); + XShmDetach(d->display, &d->xshminfo[1]); + shmdt(d->xshminfo[0].shmaddr); + shmdt(d->xshminfo[1].shmaddr); + } +} + +#endif + +int alloc_image(xdisplay * d) +{ + int i; +#ifdef MITSHM + if (!d->params->nomitshm && alloc_shm_image(d)) { + if (d->depth != 8) { + for (i = 0; i < 2; i++) + d->vbuffs[i] = malloc(d->linewidth * d->height); + } + return 1; + } +#endif + for (i = 0; i < 2; i++) { + d->image[i] = XCreateImage(d->display, d->visual, d->depth, ZPixmap, 0, + NULL, d->width, d->height, 8, 0); + if (d->image[i] == NULL) { + printf("Out of memory for image..exiting\n"); + exit(3); + } + /*Add a little extra memory to catch overruns when dumping image to buffer in draw_screen*/ + d->image[i]->data = malloc(d->image[i]->bytes_per_line * d->height + 32); + memset(d->image[i]->data,0,d->image[i]->bytes_per_line * d->height); + + if (d->image[i]->data == NULL) { + printf("Out of memory for image buffers..exiting\n"); + exit(3); + } + d->data[i] = d->vbuffs[i] = (char *) d->image[i]->data; + d->linewidth = d->image[i]->bytes_per_line * 8 / d->image[i]->bits_per_pixel; + } + if (d->depth != 8) { + for (i = 0; i < 2; i++) { + /* Add a little extra memory to catch overruns */ + /* when dumping image to buffer in draw_screen */ + d->vbuffs[i] = malloc(d->linewidth * d->height + 32); + memset(d->vbuffs[i],0,d->linewidth * d->height); + + if (d->vbuffs[i] == NULL) { + printf("Out of memory for image buffers2..exiting\n"); + exit(3); + } + } + } + xflip_buffers(d); + return 1; +} + +void free_image(xdisplay * d) +{ + if (d->depth != 8) + free(d->vbuffs[0]), free(d->vbuffs[1]); +#ifdef MITSHM + if (d->SharedMemFlag) { + free_shm_image(d); + return; + } +#endif + XDestroyImage(d->image[0]); + XDestroyImage(d->image[1]); +} +#define MAX(x,y) ((x)>(y)?(x):(y)) + + +xdisplay *xalloc_display(const char *s, int xHint, int yHint, int x, int y, xlibparam * params) +{ + xdisplay *xd; + Visual *defaultvisual; + XVisualInfo vis; + + + xd = (xdisplay *) calloc(sizeof(xdisplay), 1); + chkalloc(xd); + xd->display = XOpenDisplay((char *) NULL); + if (!xd->display) { + free((void *) xd); + return NULL; + } + xd->screen = DefaultScreen(xd->display); + xd->attributes = (XSetWindowAttributes *) + malloc(sizeof(XSetWindowAttributes)); + chkalloc(xd->attributes); + xd->attributes->background_pixel = BlackPixel(xd->display, + xd->screen); + xd->attributes->border_pixel = BlackPixel(xd->display, xd->screen); + xd->attributes->event_mask = ButtonPressMask | StructureNotifyMask | ButtonReleaseMask | ButtonMotionMask | KeyPressMask | ExposureMask | KeyReleaseMask; + xd->attributes->override_redirect = False; + xd->attr_mask = CWBackPixel | CWBorderPixel | CWEventMask; + xd->classX = InputOutput; + xd->xcolor.n = 0; + xd->parent_window = RootWindow(xd->display, xd->screen); + defaultvisual = DefaultVisual(xd->display, xd->screen); + xd->params = params; + if (!params->usedefault) { + if (defaultvisual->class != PseudoColor || (!XMatchVisualInfo(xd->display, xd->screen, 8, PseudoColor, &vis) && vis.colormap_size > 128)) { + xd->fixedcolormap = 1; + if (!XMatchVisualInfo(xd->display, xd->screen, 15, TrueColor, &vis)) { + if (!XMatchVisualInfo(xd->display, xd->screen, 16, TrueColor, &vis)) { + if (!XMatchVisualInfo(xd->display, xd->screen, 32, TrueColor, &vis) && + !XMatchVisualInfo(xd->display, xd->screen, 24, TrueColor, &vis)) { + if (!XMatchVisualInfo(xd->display, xd->screen, 8, PseudoColor, &vis) && + !XMatchVisualInfo(xd->display, xd->screen, 7, PseudoColor, &vis)) { + if (!XMatchVisualInfo(xd->display, xd->screen, 8, TrueColor, &vis) && + !XMatchVisualInfo(xd->display, xd->screen, 8, StaticColor, &vis) && + !XMatchVisualInfo(xd->display, xd->screen, 8, StaticGray, &vis)) { + printf("Display does not support PseudoColor depth 7,8,StaticColor depth 8, StaticGray depth 8, Truecolor depth 8,15,16,24 nor 32!\n"); + return NULL; + } else + xd->truecolor = 1; + } else + xd->fixedcolormap = 0, xd->truecolor = 0; + } else + xd->truecolor = 1; + } else + xd->truecolor = 1; + } else + xd->truecolor = 1; + } else { + xd->truecolor = 0; + } + xd->depth = vis.depth; + xd->visual = vis.visual; + } else { /*usedefault */ + vis.depth = xd->depth = DefaultDepth(xd->display, xd->screen); + xd->visual = defaultvisual; + switch (defaultvisual->class) { + case PseudoColor: + if (xd->depth <= 8) { + xd->depth = 8; + xd->truecolor = 0; + xd->fixedcolormap = 0; + } else { + printf("Pseudocolor visual on unsuported depth\n"); + return NULL; + } + break; + case TrueColor: + case StaticColor: + case StaticGray: + xd->truecolor = 1; + xd->fixedcolormap = 1; + if (xd->depth <= 8) + xd->depth = 8; + else if (xd->depth <= 16) + xd->depth = 16; + else if (xd->depth <= 32) + xd->depth = 32; + else { + printf("Truecolor visual on unsuported depth\n"); + return NULL; + } + break; + default: + printf("Unusuported visual\n"); + break; + } + } + /*xd->visual->map_entries = 256; */ + xd->colormap = xd->defaultcolormap = DefaultColormap(xd->display, xd->screen); + + xd->window_name = s; + xd->height = y; + xd->width = x; + xd->border_width = 2; + xd->lastx = 0; + xd->lasty = 0; + xd->font_struct = (XFontStruct *) NULL; + + xd->window = XCreateWindow(xd->display, xd->parent_window, xHint, yHint, + xd->width, xd->height, xd->border_width, + vis.depth, xd->classX, xd->visual, + xd->attr_mask, xd->attributes); + if (!xd->fixedcolormap && params->privatecolormap) { + unsigned long pixels[256]; + int i; + xd->colormap = XCreateColormap(xd->display, xd->window, xd->visual, AllocNone); + XAllocColorCells(xd->display, xd->colormap, 1, 0, 0, pixels, MAX(xd->visual->map_entries, 256)); + for (i = 0; i < 16; i++) { + xd->xcolor.c[i].pixel = pixels[i]; + } + XQueryColors(xd->display, xd->defaultcolormap, xd->xcolor.c, 16); + XStoreColors(xd->display, xd->colormap, xd->xcolor.c, 16); + xd->privatecolormap = 1; + } + if (!xd->fixedcolormap) + XSetWindowColormap(xd->display, xd->window, xd->colormap); + xd->gc = XCreateGC(xd->display, xd->window, 0L, &(xd->xgcvalues)); + XSetBackground(xd->display, xd->gc, + BlackPixel(xd->display, xd->screen)); + XSetForeground(xd->display, xd->gc, + WhitePixel(xd->display, xd->screen)); + XStoreName(xd->display, xd->window, xd->window_name); + XMapWindow(xd->display, xd->window); +#if 1 + XSelectInput(xd->display, xd->window, + /* ExposureMask | */ + KeyPress | + /* KeyRelease | */ + /* ConfigureRequest | */ + /* FocusChangeMask | */ + StructureNotifyMask | + ButtonPressMask | ButtonReleaseMask); +#endif +#ifdef PIXAMP + xd->pixmap = XCreatePixmap(xd->display, xd->window, xd->width, + xd->height, xd->depth); +#endif + + { + XColor c; + Pixmap p = XCreatePixmap(xd->display, xd->window, 1,1,1); + memset(&c,0,sizeof(c)); + xd->cursor = XCreatePixmapCursor(xd->display, p,p, + &c,&c, 0,0); + /* We don't need no fancy cursor + XDefineCursor(xd->display,xd->window,xd->cursor); + */ + XFreePixmap(xd->display, p); + } + + return (xd); +} + +void xsetcolor(xdisplay * d, int col) +{ + switch (col) { + case 0: + XSetForeground(d->display, d->gc, + BlackPixel(d->display, d->screen)); + break; + case 1: + XSetForeground(d->display, d->gc, + WhitePixel(d->display, d->screen)); + break; + default: + if ((col - 2) > d->xcolor.n) { + fprintf(stderr, "color error\n"); + exit(3); + } + XSetForeground(d->display, d->gc, + d->xcolor.c[col - 2].pixel); + break; + } +} +void xrotate_palette(xdisplay * d, int direction, unsigned char co[3][256], int ncolors) +{ + int i, p; + + if (d->privatecolormap) { + for (i = 0; i < d->xcolor.n; i++) { + p = d->xcolor.c[i].pixel; + d->xcolor.c[i].red = (int) co[0][p] * 256; + d->xcolor.c[i].green = (int) co[1][p] * 256; + d->xcolor.c[i].blue = (int) co[2][p] * 256; + } + XStoreColors(d->display, d->colormap, d->xcolor.c, d->xcolor.n); + } + if (d->truecolor) { + unsigned long oldpixels[256]; + memcpy(oldpixels, d->pixels, sizeof(oldpixels)); + p = (ncolors - 1 + direction) % (ncolors - 1) + 1; + for (i = 1; i < ncolors; i++) { /*this is ugly..I know */ + d->pixels[i] = oldpixels[p]; + p++; + if (p >= ncolors) + p = 1; + } + draw_screen(d); + } +} +int xalloc_color(xdisplay * d, int r, int g, int b, int readwrite) +{ + d->xcolor.n++; + d->xcolor.c[d->xcolor.n - 1].flags = DoRed | DoGreen | DoBlue; + d->xcolor.c[d->xcolor.n - 1].red = r; + d->xcolor.c[d->xcolor.n - 1].green = g; + d->xcolor.c[d->xcolor.n - 1].blue = b; + d->xcolor.c[d->xcolor.n - 1].pixel = d->xcolor.n - 1; + if ((readwrite && !d->fixedcolormap) || d->privatecolormap) { + unsigned long cell; + if (d->privatecolormap) { + cell = d->xcolor.c[d->xcolor.n - 1].pixel += 16; + if (d->xcolor.c[d->xcolor.n - 1].pixel >= d->visual->map_entries) { + d->xcolor.n--; + return (-1); + } + } else { + if (!XAllocColorCells(d->display, d->colormap, 0, 0, 0, &cell, 1)) { + d->xcolor.n--; + if (d->xcolor.n <= 32) + printf("Colormap is too full! close some colorfull aplications or use -private\n"); + return (-1); + } + d->xcolor.c[d->xcolor.n - 1].pixel = cell; + } + XStoreColor(d->display, d->colormap, &(d->xcolor.c[d->xcolor.n - 1])); + return (cell); + } + if (!XAllocColor(d->display, d->colormap, &(d->xcolor.c[d->xcolor.n - 1]))) { + d->xcolor.n--; + if (d->xcolor.n <= 32) + printf("Colormap is too full! close some colorfull aplications or use -private\n"); + return (-1); + } + d->pixels[d->xcolor.n - 1] = d->xcolor.c[d->xcolor.n - 1].pixel; + return (d->depth != 8 ? d->xcolor.n - 1 : d->xcolor.c[d->xcolor.n - 1].pixel); +} + +void xfree_colors(xdisplay * d) +{ + unsigned long pixels[256]; + int i; + for (i = 0; i < d->xcolor.n; i++) + pixels[i] = d->xcolor.c[i].pixel; + if (!d->privatecolormap) + XFreeColors(d->display, d->colormap, pixels, d->xcolor.n, 0); + d->xcolor.n = 0; +} + +void xfree_display(xdisplay * d) +{ + XSync(d->display, 0); + if (d->font_struct != (XFontStruct *) NULL) { + XFreeFont(d->display, d->font_struct); + } + XUnmapWindow(d->display, d->window); +#ifdef PIXMAP + XFreePixmap(d->display, d->pixmap); +#endif + XDestroyWindow(d->display, d->window); + XFreeCursor(d->display, d->cursor); + XCloseDisplay(d->display); + free((void *) d->attributes); + free((void *) d); +} + +#ifdef PIXMAP +void xline(xdisplay * d, int x1, int y1, int x2, int y2) +{ + XDrawLine(d->display, d->pixmap, d->gc, x1, y1, x2, y2); + d->lastx = x2, d->lasty = y2; + d->screen_changed = 1; +} void xlineto(xdisplay * d, int x, int y) +{ + + XDrawLine(d->display, d->pixmap, d->gc, d->lastx, d->lasty, x, y); + d->lastx = x, d->lasty = y; + d->screen_changed = 1; +} void xrect(xdisplay * d, int x1, int y1, int x2, int y2) +{ + + XDrawRectangle(d->display, d->pixmap, d->gc, x1, y1, + (x2 - x1), (y2 - y1)); + d->lastx = x2, d->lasty = y2; + d->screen_changed = 1; +} void xfillrect(xdisplay * d, int x1, int y1, int x2, int y2) +{ + + XFillRectangle(d->display, d->pixmap, d->gc, x1, y1, + (x2 - x1), (y2 - y1)); + d->lastx = x2, d->lasty = y2; + d->screen_changed = 1; +} void xpoint(xdisplay * d, int x, int y) +{ + + XDrawPoint(d->display, d->pixmap, d->gc, x, y); + d->lastx = x, d->lasty = y; + d->screen_changed = 1; +} void xflush(xdisplay * d) +{ + + draw_screen(d); + XFlush(d->display); +} + +void xclear_screen(xdisplay * d) +{ + xfillrect(d, 0, 0, d->width, d->height); + d->screen_changed = 1; +} + +#endif +void xmoveto(xdisplay * d, int x, int y) +{ + d->lastx = x, d->lasty = y; +} int xsetfont(xdisplay * d, char *font_name) +{ + + if (d->font_struct != (XFontStruct *) NULL) { + XFreeFont(d->display, d->font_struct); + } + d->font_struct = XLoadQueryFont(d->display, font_name); + if (!d->font_struct) { + fprintf(stderr, "could not load font: %s\n", font_name); + exit(3); + } + return (d->font_struct->max_bounds.ascent + d->font_struct->max_bounds.descent); +} + +void xouttext(xdisplay * d, char *string) +{ + int sz; + + sz = strlen(string); + XDrawImageString(d->display, d->window, d->gc, d->lastx, d->lasty, + string, sz); +#if 0 + d->lastx += XTextWidth(d->font_struct, string, sz); + d->screen_changed = 1; +#endif +} void xresize(xdisplay * d, XEvent * ev) +{ + +#ifdef PIXMAP + XFreePixmap(d->display, d->pixmap); +#endif + d->width = ev->xconfigure.width; + d->height = ev->xconfigure.height; +#ifdef PIXMAP + d->pixmap = XCreatePixmap(d->display, d->window, d->width, + d->height, d->depth); +#endif +} + +#ifdef PIXMAP +void xarc(xdisplay * d, int x, int y, unsigned int w, + unsigned int h, int a1, int a2) +{ + XDrawArc(d->display, d->pixmap, d->gc, x, y, w, h, a1, a2); +} void xfillarc(xdisplay * d, int x, int y, unsigned int w, + unsigned int h, int a1, int a2) +{ + XFillArc(d->display, d->pixmap, d->gc, x, y, w, h, a1, a2); +} +#endif + +void xsize_set(xdisplay *d, int width, int height) +{ + XResizeWindow(d->display, d->window, width, height); +} + +int xmouse_x(xdisplay * d) +{ + + return d->mouse_x; +} + +int xmouse_y(xdisplay * d) +{ + return d->mouse_y; +} + +void xmouse_update(xdisplay * d) +{ + Window rootreturn, childreturn; + int rootx = 0, rooty = 0, buttons = 0; + + XEvent event; + + if (XCheckMaskEvent(d->display,ButtonPressMask | ButtonReleaseMask, &event)) { + if (event.type == ButtonPress) + d->mouse_buttons |= 1 << ((XButtonEvent*)(&event))->button; + else + d->mouse_buttons &= ~( 1 << ((XButtonEvent*)(&event))->button ); + } + + XQueryPointer(d->display, d->window, &rootreturn, &childreturn, + &rootx, &rooty, &(d->mouse_x), &(d->mouse_y), + &buttons); +} + +char xkeyboard_query(xdisplay * d) { + XEvent event; + + if (XCheckMaskEvent(d->display,KeyPressMask | KeyReleaseMask, &event)) { + char *str = + XKeysymToString(XLookupKeysym((XKeyPressedEvent*)(&event),0)); + + if ( ((XKeyPressedEvent*)(&event))->state & + (ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask) ) + return 0; + + if (str) { + char key; + + if (strlen(str) == 1) + key = str[0]; + else if (strcmp(str,"equal") == 0) + key = '='; + else if (strcmp(str,"minus") == 0) + key = '-'; + else if (strcmp(str,"bracketleft") == 0) + key = '['; + else if (strcmp(str,"bracketright") == 0) + key = ']'; + else if (strcmp(str,"comma") == 0) + key = ','; + else if (strcmp(str,"period") == 0) + key = '.'; + else if (strcmp(str,"slash") == 0) + key = '/'; + else return 0; + + if ( ((XKeyPressedEvent*)(&event))->state & ShiftMask ) + switch(key) { + case '=' : key = '+'; break; + case '[' : key = '{'; break; + case ']' : key = '}'; break; + case ',' : key = '<'; break; + case '/' : key = '?'; break; + default : + if (key >= 'a' && key <= 'z') + key = key+'A'-'a'; + break; + } + return key; + } + } + + return 0; +} + +int xsize_update(xdisplay *d,int *width,int *height) { + XEvent event; + + if (XCheckMaskEvent(d->display,StructureNotifyMask, &event)) { + if (event.type == ConfigureNotify) { + xupdate_size(d); + free_image(d); + alloc_image(d); + *width = d->linewidth; + *height = d->height; + return 1; + } + } + + return 0; +} + +unsigned int xmouse_buttons(xdisplay * d) +{ + return d->mouse_buttons; +} +#endif diff --git a/kscd/kscdmagic/xlib.h b/kscd/kscdmagic/xlib.h new file mode 100644 index 00000000..077a9052 --- /dev/null +++ b/kscd/kscdmagic/xlib.h @@ -0,0 +1,139 @@ +/* + * XaoS, a fast portable realtime fractal zoomer + * Copyright (C) 1996,1997 by + * + * Jan Hubicka (hubicka@paru.cas.cz) + * Thomas Marsh (tmarsh@austin.ibm.com) + * + * 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. + */ +#ifndef XAOS_X11_H +#define XAOS_X11_H + +#include +#include +#include +#include +/*#include "config.h"*/ +/*#define MITSHM*/ + +#ifdef MITSHM +#include +#include +#include +#include +#endif /* MITSHM */ + +#ifdef n +#undef n +#endif + +typedef struct { + int n; + XColor c[256]; +} xcol_t; + +typedef struct { + int privatecolormap; + int usedefault; + int nomitshm; +} xlibparam; + +typedef struct { + Colormap colormap; + Colormap defaultcolormap; + int fixedcolormap; + int privatecolormap; + xlibparam *params; + Display *display; + Window parent_window; + Window window; + unsigned int width, height; + unsigned int border_width; + unsigned long background; + int depth; + unsigned int classX; + Visual *visual; + unsigned long valuemask; + XSetWindowAttributes *attributes; + unsigned long attr_mask; + XSizeHints sizehints; + int screen; + const char *window_name; + int status; + GC gc; + XGCValues xgcvalues; + xcol_t xcolor; + Pixmap pixmap; + XFontStruct *font_struct; + int screen_changed; + int lastx, lasty; + int mouse_x, mouse_y; + unsigned int mouse_buttons; + int current; + XImage *image[2]; +#ifdef MITSHM + XShmSegmentInfo xshminfo[2]; + int SharedMemOption; + int SharedMemFlag; +#endif /* MITSHM */ + unsigned long pixels[256]; + char *vbuffs[2]; + char *data[2]; + char *vbuff; + char *back; + int truecolor; + int linewidth; + + Cursor cursor; +} xdisplay; + +extern int alloc_shm_image(xdisplay * d); +extern void free_shm_image(xdisplay * d); +extern int alloc_image(xdisplay * d); +extern void free_image(xdisplay * d); +extern int xupdate_size(xdisplay * d); +extern void xflip_buffers(xdisplay * d); +extern xdisplay *xalloc_display(const char *n, int x, int y, int width,int height, xlibparam * p); +extern void xfree_display(xdisplay * d); +extern void xsetcolor(xdisplay * d, int col); +extern int xsetfont(xdisplay * d, char *font_name); +extern int xalloc_color(xdisplay * d, int r, int g, int b, int readwrite); +extern void xfree_colors(xdisplay * d); +extern void xline(xdisplay * d, int x1, int y1, int x2, int y2); +extern void xmoveto(xdisplay * d, int x, int y); +extern void xlineto(xdisplay * d, int x, int y); +extern void xrect(xdisplay * d, int x1, int y1, int x2, int y2); +extern void xfillrect(xdisplay * d, int x1, int y1, int x2, int y2); +extern void xarc(xdisplay * d, int x, int y, unsigned int w, + unsigned int h, int a1, int a2); +extern void xfillarc(xdisplay * d, int x, int y, unsigned int w, + unsigned int h, int a1, int a2); +extern void xpoint(xdisplay * d, int x, int y); +extern void xflush(xdisplay * d); +extern void xclear_screen(xdisplay * d); +extern void xrotate_palette(xdisplay * d, int direction, unsigned char c[3][256], int ncolors); +extern void draw_screen(xdisplay * d); +extern void xouttext(xdisplay * d, char *string); +extern void xresize(xdisplay * d, XEvent * ev); +extern void xsize_set(xdisplay *d, int width, int height); +extern int xsize_update(xdisplay *d,int *width,int *height); +extern int xmouse_x(xdisplay * d); +extern int xmouse_y(xdisplay * d); +extern void xmouse_update(xdisplay * d); +extern char xkeyboard_query(xdisplay * d); +extern unsigned int xmouse_buttons(xdisplay * d); + +#endif /* XAOS_X11_H */ diff --git a/kscd/kscdmagic/xlibwrap.cpp b/kscd/kscdmagic/xlibwrap.cpp new file mode 100644 index 00000000..b5241326 --- /dev/null +++ b/kscd/kscdmagic/xlibwrap.cpp @@ -0,0 +1,209 @@ +/* Synaesthesia - program to display sound graphically + Copyright (C) 1997 Paul Francis Harrison + + 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. + + The author may be contacted at: + pfh@yoyo.cc.monash.edu.au + or + 27 Bond St., Mt. Waverley, 3149, Melbourne, Australia +*/ + +#if defined(__linux__) || defined (__svr4__) || defined(__osf__) + +#include + +extern "C" { +#include "xlib.h" +} + +#include "magicconf.h" +#include "syna.h" + +static xlibparam xparams = { 0, 0, 0 }; +static xdisplay *d; + +static bool lowColor, paletteInstalled; +static unsigned char mapping[64]; + +int setPalette(int ,int r,int g,int b) { + return xalloc_color(d,r*257,g*257,b*257,0); +} + +void screenInit(int xHint,int yHint,int widthHint,int heightHint) +{ + + int i; + + d = xalloc_display("KSCD Magic",xHint,yHint,widthHint,heightHint,&xparams); + + if (d == 0) + error("setting up a window"); + + if (!alloc_image(d)) + error("allocating window buffer"); + outWidth = widthHint; + outHeight = heightHint; + + //XMoveWindow(d->display,d->window,xHint,yHint); + +#define BOUND(x) ((x) > 255 ? 255 : (x)) +#define PEAKIFY(x) BOUND((x) - (x)*(255-(x))/255/2) + + lowColor = (d->depth <= 8); + + /* Set up palette immediately. + * Original code has the following commented out. + */ + if (!lowColor) { + for(i=0;i<256;i++) + attempt(setPalette(i,PEAKIFY((i&15*16)), + PEAKIFY((i&15)*16+(i&15*16)/4), + PEAKIFY((i&15)*16)), + " in X: could not allocate sufficient palette entries"); + } else { + for(i=0;i<64;i++) + attempt(mapping[i] = setPalette(i,PEAKIFY((i&7*8)*4), + PEAKIFY((i&7)*32+(i&7*8)*2), + PEAKIFY((i&7)*32)), + " in X: could not allocate sufficient palette entries"); + } +} + +void screenSetPalette(unsigned char *palette) { + int i; + + if (paletteInstalled) + xfree_colors(d); + + if (!lowColor) { + for(i=0;i<256;i++) + attempt(setPalette(i,palette[i*3],palette[i*3+1],palette[i*3+2]), + " in X: could not allocate sufficient palette entries"); + } else { + const int array[8] = {0,2,5,7,9,11,13,15}; + for(i=0;i<64;i++) { + int p = (array[i&7]+array[i/8]*16) *3; + attempt(mapping[i] = setPalette(i,palette[p],palette[p+1],palette[p+2]), + " in X: could not allocate sufficient palette entries"); + } + } + + paletteInstalled = true; +} + +void screenEnd() { + if (paletteInstalled) + xfree_colors(d); + xfree_display(d); +} + +int sizeUpdate() +{ + int newWidth,newHeight; + + if (xsize_update(d,&newWidth,&newHeight)) + { + if (newWidth == outWidth && newHeight == outHeight) + return 0; + //delete[] output; + //outWidth = newWidth; + //outHeight = newHeight; + //output = new unsigned char [outWidth*outHeight*2]; + //memset(output,32,outWidth*outHeight*2); + allocOutput(newWidth,newHeight); + return 1; + } + return 0; +} + +void inputUpdate(int &mouseX,int &mouseY,int &mouseButtons,char &keyHit) { + xmouse_update(d); + mouseX = xmouse_x(d); + mouseY = xmouse_y(d); + mouseButtons = xmouse_buttons(d); + keyHit = xkeyboard_query(d); +} + +void screenShow(void) { + register unsigned long *ptr2 = (unsigned long*)ucoutput; + unsigned long *ptr1 = (unsigned long*)d->back; + int i = outWidth*outHeight/4; + if (lowColor) + do { + register unsigned int const r1 = *(ptr2++); + register unsigned int const r2 = *(ptr2++); + + //if (r1 || r2) { +#ifdef LITTLEENDIAN + register unsigned int const v = + mapping[((r1&0xe0ul)>>5)|((r1&0xe000ul)>>10)] + |mapping[((r1&0xe00000ul)>>21)|((r1&0xe0000000ul)>>26)]*256U; + *(ptr1++) = v | + mapping[((r2&0xe0ul)>>5)|((r2&0xe000ul)>>10)]*65536U + |mapping[((r2&0xe00000ul)>>21)|((r2&0xe0000000ul)>>26)]*16777216U; +#else + register unsigned int const v = + mapping[((r2&0xe0ul)>>5)|((r2&0xe000ul)>>10)] + |mapping[((r2&0xe00000ul)>>21)|((r2&0xe0000000ul)>>26)]*256U; + *(ptr1++) = v | + mapping[((r1&0xe0ul)>>5)|((r1&0xe000ul)>>10)]*65536U + |mapping[((r1&0xe00000ul)>>21)|((r1&0xe0000000ul)>>26)]*16777216U; +#endif + //} else ptr1++; + } while (--i); + else + do { + // Asger Alstrup Nielsen's (alstrup@diku.dk) + // optimized 32 bit screen loop + register unsigned int const r1 = *(ptr2++); + register unsigned int const r2 = *(ptr2++); + + //if (r1 || r2) { +#ifdef LITTLEENDIAN + register unsigned int const v = + ((r1 & 0x000000f0ul) >> 4) + | ((r1 & 0x0000f000ul) >> 8) + | ((r1 & 0x00f00000ul) >> 12) + | ((r1 & 0xf0000000ul) >> 16); + *(ptr1++) = v | + ((r2 & 0x000000f0ul) << 16 -4) + | ((r2 & 0x0000f000ul) << 16 -8) + | ((r2 & 0x00f00000ul) << 16 -12) + | ((r2 & 0xf0000000ul) << 16 -16); +#else + register unsigned int const v = + ((r2 & 0x000000f0ul) >> 4) + | ((r2 & 0x0000f000ul) >> 8) + | ((r2 & 0x00f00000ul) >> 12) + | ((r2 & 0xf0000000ul) >> 16); + *(ptr1++) = v | + ((r1 & 0x000000f0ul) << 16 -4) + | ((r1 & 0x0000f000ul) << 16 -8) + | ((r1 & 0x00f00000ul) << 16 -12) + | ((r1 & 0xf0000000ul) << 16 -16); +#endif + //} else ptr1++; + } while (--i); + + xflip_buffers(d); + draw_screen(d); + XFlush(d->display); +} + + + +#endif // linux || svr4 + -- cgit v1.2.1