Compare commits
	
		
			10 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 2f5b69c021 | ||
|  | 44980fc2f5 | ||
|  | c1fe0e7c15 | ||
|  | f57e31dba5 | ||
|  | 6d5bbaca0a | ||
|  | 2bd9ca2b9b | ||
|  | 2f4bdf615b | ||
|  | 884ded8b95 | ||
|  | 0941f4abaa | ||
|  | bb80fe24b2 | 
							
								
								
									
										21
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										21
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -1,21 +0,0 @@ | ||||
| *.[oa] | ||||
| Makefile.in | ||||
| Makefile | ||||
| config.h | ||||
| /build | ||||
| /man/Makefile.in | ||||
| /pixmaps/Makefile.in | ||||
| /src/Makefile.in | ||||
| /src/.deps/ | ||||
| /src/jack-keyboard | ||||
| stamp-h1 | ||||
| config.h.in | ||||
| config.log | ||||
| config.status | ||||
| configure | ||||
| depcomp | ||||
| install-sh | ||||
| missing | ||||
| aclocal.m4 | ||||
| autom4te.cache | ||||
| compile | ||||
							
								
								
									
										2
									
								
								AUTHORS
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								AUTHORS
									
									
									
									
									
								
							| @ -2,5 +2,3 @@ Edward Tomasz Napierała <trasz@FreeBSD.org> | ||||
| Hans Petter Selasky <hselasky@FreeBSD.org> | ||||
| Jeff Snyder <jeff@caffeinated.me.uk> | ||||
| Dan Muresan <danmbox@gmail.com> | ||||
| Markus Schmidt <schmidt@boomshop.net> | ||||
| AlkorZ3 <alkorz2@rx3.net> | ||||
							
								
								
									
										91
									
								
								CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,91 @@ | ||||
| # | ||||
| # Copyright (c) 2011 Hans Petter Selasky. All rights reserved. | ||||
| # | ||||
| # Redistribution and use in source and binary forms, with or without | ||||
| # modification, are permitted provided that the following conditions | ||||
| # are met: | ||||
| # 1. Redistributions of source code must retain the above copyright | ||||
| #    notice, this list of conditions and the following disclaimer. | ||||
| # 2. Redistributions in binary form must reproduce the above copyright | ||||
| #    notice, this list of conditions and the following disclaimer in the | ||||
| #    documentation and/or other materials provided with the distribution. | ||||
| # | ||||
| # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | ||||
| # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||
| # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||
| # ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | ||||
| # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||||
| # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||||
| # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||||
| # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||||
| # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||||
| # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||||
| # SUCH DAMAGE. | ||||
| # | ||||
| # | ||||
| # Makefile for Jack Keyboard | ||||
| # | ||||
| cmake_minimum_required(VERSION 2.8) | ||||
| 
 | ||||
| option(ENABLE_GTK2 "Enable GTK2 Version" ON) | ||||
| option(ENABLE_GTK3 "Enable GTK3 Version" OFF) | ||||
| 
 | ||||
| set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/") | ||||
| set(VERSION "2.7.2") | ||||
| 
 | ||||
| set(JackEnable ON CACHE BOOL "Enable support for Jack") | ||||
| set(LashEnable ON CACHE BOOL "Enable support for Lash") | ||||
| set(X11Enable ON CACHE BOOL "Enable support for X11") | ||||
| 
 | ||||
| project(jack-keyboard) | ||||
| 
 | ||||
| add_executable(jack-keyboard src/jack-keyboard src/pianokeyboard) | ||||
| 
 | ||||
| find_package(PkgConfig REQUIRED) | ||||
| 
 | ||||
| if(ENABLE_GTK3) | ||||
|   set(ENABLE_GTK2 OFF) | ||||
|   PKG_CHECK_MODULES(GTK3 "gtk+-3.0 >= 3.16" REQUIRED) | ||||
|   include_directories(${GTK3_INCLUDE_DIRS}) | ||||
|   target_link_libraries(jack-keyboard ${GTK3_LIBRARIES}) | ||||
| endif() | ||||
| 
 | ||||
| if(ENABLE_GTK2) | ||||
|   PKG_CHECK_MODULES(GTK2 "gtk+-2.0 >= 2.20" REQUIRED) | ||||
|   include_directories(${GTK2_INCLUDE_DIRS}) | ||||
|   target_link_libraries(jack-keyboard ${GTK2_LIBRARIES}) | ||||
| endif() | ||||
| 
 | ||||
| # In preparation for GTK+3: | ||||
| # Set GDK/GTK+ flags to report deprecated includes and symbols. | ||||
| set(GTK_DEPRECATED_FLAGS "-DGTK_DISABLE_SINGLE_INCLUDES \ | ||||
|   -DGDK_DISABLE_DEPRECATED \ | ||||
|   -DGTK_DISABLE_DEPRECATED \ | ||||
|   -DGSEAL_ENABLE") | ||||
| set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${GTK_DEPRECATED_FLAGS}") | ||||
| 
 | ||||
| if(JackEnable) | ||||
| find_package(JACK) | ||||
| include_directories(${JACK_INCLUDE_DIR}) | ||||
| target_link_libraries(jack-keyboard ${JACK_LIBRARIES}) | ||||
| add_definitions(-DHAVE_JACK=1) | ||||
| endif() | ||||
| 
 | ||||
| if(LashEnable) | ||||
| find_package(LASH) | ||||
| include_directories(${LASH_INCLUDE_DIR}) | ||||
| target_link_libraries(jack-keyboard ${LASH_LIBRARIES}) | ||||
| add_definitions(-DHAVE_LASH=1) | ||||
| endif() | ||||
| 
 | ||||
| if(X11Enable) | ||||
| find_package(X11) | ||||
| include_directories(${X11_INCLUDE_DIR}) | ||||
| target_link_libraries(jack-keyboard ${X11_LIBRARIES}) | ||||
| add_definitions(-DHAVE_X11=1) | ||||
| endif() | ||||
| 
 | ||||
| install(TARGETS jack-keyboard RUNTIME DESTINATION bin) | ||||
| install(FILES pixmaps/jack-keyboard.png DESTINATION share/pixmaps) | ||||
| install(FILES src/jack-keyboard.desktop DESTINATION share/applications) | ||||
| install(FILES man/jack-keyboard.1 DESTINATION man/man1) | ||||
							
								
								
									
										48
									
								
								Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								Makefile
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,48 @@ | ||||
| VERSION?=2.7.2 | ||||
| 
 | ||||
| help: | ||||
| 	@echo "Targets: configure all clean install package" | ||||
| 
 | ||||
| configure: | ||||
| 
 | ||||
| 	rm -rf build | ||||
| 
 | ||||
| 	mkdir build | ||||
| 
 | ||||
| 	cd build ; cmake .. | ||||
| 
 | ||||
| all: | ||||
| 	make -C build all | ||||
| 
 | ||||
| install: | ||||
| 	make -C build install | ||||
| 
 | ||||
| clean: | ||||
| 	make -C build clean | ||||
| 
 | ||||
| package: | ||||
| 	make -C build clean || echo -n | ||||
| 
 | ||||
| 	tar -cvf temp.tar --exclude="*~" --exclude="*#" \
 | ||||
| 		--exclude=".svn" --exclude="*.orig" --exclude="*.rej" \
 | ||||
| 		AUTHORS \
 | ||||
| 		CMakeLists.txt \
 | ||||
| 		COPYING \
 | ||||
| 		Makefile \
 | ||||
| 		NEWS \
 | ||||
| 		README \
 | ||||
| 		TODO \
 | ||||
| 		cmake \
 | ||||
| 		man \
 | ||||
| 		pixmaps \
 | ||||
| 		src | ||||
| 
 | ||||
| 	rm -rf jack-keyboard-${VERSION} | ||||
| 
 | ||||
| 	mkdir jack-keyboard-${VERSION} | ||||
| 
 | ||||
| 	tar -xvf temp.tar -C jack-keyboard-${VERSION} | ||||
| 
 | ||||
| 	rm -rf temp.tar | ||||
| 
 | ||||
| 	tar -zcvf jack-keyboard-${VERSION}.tar.gz jack-keyboard-${VERSION} | ||||
| @ -1,2 +0,0 @@ | ||||
| SUBDIRS = src man pixmaps | ||||
| 
 | ||||
							
								
								
									
										6
									
								
								NEWS
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								NEWS
									
									
									
									
									
								
							| @ -1,9 +1,3 @@ | ||||
| User-visible changes between 2.8.0 and 2.8.1 include: | ||||
|  - Add bank MSB/LSB support | ||||
| 
 | ||||
| User-visible changes between 2.7.2 and 2.8.0 include: | ||||
|  - Drop CMake and now use autotools | ||||
| 
 | ||||
| User-visible changes between 2.7.1 and 2.7.2 include: | ||||
| 
 | ||||
| User-visible changes between 2.6 and 2.7.1 include: | ||||
|  | ||||
							
								
								
									
										5
									
								
								README
									
									
									
									
									
								
							
							
						
						
									
										5
									
								
								README
									
									
									
									
									
								
							| @ -15,9 +15,8 @@ If you're using FreeBSD, install from ports - audio/jack-keyboard. | ||||
| 
 | ||||
| Otherwise, you need JACK with MIDI support, gtk+ 2.6 or higher, | ||||
| make(1), gcc and all the standard headers.  Untar the file, type | ||||
| 'make install' and that's it. | ||||
| If Makefile is not present, you can generate it with: | ||||
| aclocal && autoheader && automake --add-missing && autoconf && ./configure | ||||
| 'make install' and that's it.  If there is any problem, drop me | ||||
| an email (trasz@FreeBSD.org) and I will help you.  Really. | ||||
| 
 | ||||
| How to use it? | ||||
| -------------- | ||||
|  | ||||
							
								
								
									
										128
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										128
									
								
								README.md
									
									
									
									
									
								
							| @ -1,128 +0,0 @@ | ||||
| # jack-keyboard | ||||
| 
 | ||||
|  | ||||
| 
 | ||||
| ## What is it? | ||||
| 
 | ||||
| jack-keyboard is a virtual MIDI keyboard - a program that allows you to | ||||
| send JACK MIDI events (play ;-) using your PC keyboard.  It's  somewhat | ||||
| similar  to  vkeybd,  except it uses JACK MIDI instead of ALSA, and the | ||||
| keyboard mapping is much better - it uses the same layout  as  trackers | ||||
| (like Impulse Tracker) did, so you have two and half octaves under your | ||||
| fingers. | ||||
| 
 | ||||
| ## How to compile it? | ||||
| 
 | ||||
| If you're using FreeBSD, install from ports - audio/jack-keyboard. | ||||
| 
 | ||||
| Otherwise, you need JACK with MIDI support, gtk+ 2.6 or higher, | ||||
| make(1), gcc and all the standard headers.  Untar the file, type | ||||
| 'make install' and that's it. | ||||
| If Makefile is not present, you can generate it with: | ||||
| aclocal && autoheader && automake --add-missing && autoconf && ./configure | ||||
| 
 | ||||
| ## How to use it? | ||||
| 
 | ||||
| You need JACK with MIDI support and some softsynth that accepts | ||||
| JACK MIDI as input.  Ghostess, http://home.jps.net/~musound/, | ||||
| is a good choice.  Of course you will also need some DSSI plugin | ||||
| that will make the actual sound.  WhySynth is nice. | ||||
| 
 | ||||
| When you have all of these installed: first, run jackd.  Then run | ||||
| ghostess with a plugin of choice.  Then run jack-keyboard.  Press | ||||
| 'z' key.  You should hear sound. | ||||
| 
 | ||||
| ## Keyboard | ||||
| 
 | ||||
| Keyboard mapping is the same as in Impulse Tracker.  This is your | ||||
| QWERTY keyboard: | ||||
| 
 | ||||
|        +----+----+    +----+----+----+    +----+----+ | ||||
|        | 2  | 3  |    | 5  | 6  | 7  |    | 9  | 0  | | ||||
|     +----+----+----+----+----+----+----+----+----+----+ | ||||
|     | q  | w  | e  | r  | t  | y  | u  | i  | o  | p  | | ||||
|     +----+----+----+----+----+----+----+----+----+----+ | ||||
|            | s  | d  |    | g  | h  | j  | | ||||
|         +----+----+----+----+----+----+----+ | ||||
|         | z  | x  | c  | v  | b  | n  | m  | | ||||
|         +----+----+----+----+----+----+----+ | ||||
| 
 | ||||
| And this is MIDI mapping. | ||||
| 
 | ||||
|        +----+----+    +----+----+----+    +----+----+ | ||||
|        |C#5 |D#5 |    |F#5 |G#5 |A#5 |    |C#6 |D#6 | | ||||
|     +----+----+----+----+----+----+----+----+----+----+ | ||||
|     | C5 | D5 | E5 | F5 | G5 | A5 | B5 | C6 | D6 | E6 | | ||||
|     +----+----+----+----+----+----+----+----+----+----+ | ||||
|            |C#4 |D#4 |    |F#4 |G#4 |A#4 | | ||||
|         +----+----+----+----+----+----+----+ | ||||
|         | C4 | D4 | E4 | F4 | G4 | A4 | B4 | | ||||
|         +----+----+----+----+----+----+----+ | ||||
| 
 | ||||
| Spacebar  is  a sustain key.  Holding it when pressing or releasing key | ||||
| will make that key sustained, i.e. Note Off MIDI event  won't  be  sent | ||||
| after  releasing  the  key.  To release (stop) all the sustained notes, | ||||
| press and release spacebar. | ||||
| 
 | ||||
| Holding Shift when pressing note will  make  it  louder  (it  increases | ||||
| velocity).   Holding  Ctrl  will  do  the opposite.  You can change the | ||||
| default velocity by moving the Velocity slider.   You  can  change  the | ||||
| "high"  and  "low"  velocity  values by moving the slider while holding | ||||
| Shift or Ctrl keys. | ||||
| 
 | ||||
| Pressing "-" and "+" keys on numeric keypad  changes  the  octave  your | ||||
| keyboard  is mapped to.  Pressing "*" and "/" on numeric keypad changes | ||||
| MIDI program (instrument).  Pressing Insert or Delete keys will connect | ||||
| jack-keyboard  to  the  next/previous  MIDI  input  port (it will cycle | ||||
| between running instances of ghostess, for example).  Home and End keys | ||||
| change  the  MIDI  channel.  Page Up and Page Down keys switch the MIDI | ||||
| bank. | ||||
| 
 | ||||
| Esc works as a panic key - when you press it, all sound stops. | ||||
| 
 | ||||
| ## Setting channel/bank/program number directly | ||||
| 
 | ||||
| To switch directly to a channel, bank or program, enter its  number  on | ||||
| the numeric keypad (it won't be shown in any way) and press Home or End | ||||
| (to change channel), Page Up or Page Down (to change bank)  or  "/"  or | ||||
| "*" (to change program).  For example, to change to program number 123, | ||||
| type, on the numeric keypad, "123/", without quotes. | ||||
| 
 | ||||
| ## Titlebar | ||||
| 
 | ||||
| When -G xor -T is given, some informational messages in the  title  bar | ||||
| appear.  They  are  supposed  to  be  self  explanatory.   If  you  see | ||||
| "bank/program change not sent", it means that the bank/program  numbers | ||||
| as  seen  in  the  title  bar were not sent.  In other words, synth the | ||||
| jack-keyboard is connected to may use different values.   This  happens | ||||
| at  startup  and  after  switching  between synths (using Insert/Delete | ||||
| keys).  To send bank/program change at startup, use -b and  -p  parame- | ||||
| ters.   To  automatically send bank/program change after reconnect, use | ||||
| the -u option. | ||||
| 
 | ||||
| ## Pianola mode | ||||
| 
 | ||||
| In addition to the MIDI output  port,  jack-keyboard  also  opens  MIDI | ||||
| input  (listening)  port.   MIDI  events  going  into this port will be | ||||
| passed to the output port unmodified, except for channel number,  which | ||||
| will be set to the one jack-keyboard is configured to use.  Note On and | ||||
| Note Off MIDI events will cause visible effect (pressing and releasing) | ||||
| on  keys, just like if they were being pressed using keyboard or mouse. | ||||
| 
 | ||||
| jack-keyboard will never connect to it's own MIDI input port.  It  will | ||||
| also  refuse to connect to any other client whose name begins in "jack- | ||||
| keyboard", unless the "-k" option is given.  It is,  however,  possible | ||||
| to  connect  these ports manually, using jack_connect or qjackctl; this | ||||
| may create feedback loop. | ||||
| 
 | ||||
| ## License  | ||||
| 
 | ||||
| JACK Keyboard is distributed under the BSD license, two clause. | ||||
| 
 | ||||
| ## Contact  | ||||
| 
 | ||||
| If you have any questions, comments, suggestions, patches or anything, | ||||
| let us know: | ||||
| * Edward Tomasz Napierala <trasz@FreeBSD.org> (initial version) | ||||
| * Hans Petter Selasky <hselasky@FreeBSD.org> (further development, gtk3) | ||||
| * Markus Schmidt <schmidt@boomshop.net> (further development, UX/UI) | ||||
							
								
								
									
										2
									
								
								TODO
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								TODO
									
									
									
									
									
								
							| @ -1,5 +1,7 @@ | ||||
| Things to do, eventually: | ||||
| 
 | ||||
|  - I know nothing about designing GUIs, and I'm afraid it shows.  Redesign. | ||||
| 
 | ||||
|  - Jack-keyboard does strange things to input focus and keyboard event | ||||
|    handling.  Verify that it does not cause any problems. | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										28
									
								
								cmake/FindJACK.cmake
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								cmake/FindJACK.cmake
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,28 @@ | ||||
| # - Try to find Jack library | ||||
| # Once done this will define: | ||||
| #  JACK_FOUND        - system has JACK | ||||
| #  JACK_INCLUDE_DIR  - incude paths to use | ||||
| #  JACK_LIBRARIES    - Link these to use | ||||
| 
 | ||||
| SET(JACK_FOUND 0) | ||||
| 
 | ||||
| FIND_PATH(JACK_INCLUDE_DIR jack/ringbuffer.h | ||||
| 	/usr/local/include | ||||
| 	/usr/include | ||||
| ) | ||||
| 
 | ||||
| FIND_LIBRARY(JACK_LIBRARIES jack | ||||
| 	/usr/local/lib | ||||
| 	/usr/lib | ||||
| ) | ||||
| 
 | ||||
| # handle the QUIETLY and REQUIRED arguments and set JACK_FOUND to TRUE | ||||
| # if all listed variables are TRUE | ||||
| INCLUDE(FindPackageHandleStandardArgs) | ||||
| FIND_PACKAGE_HANDLE_STANDARD_ARGS(JACK DEFAULT_MSG JACK_LIBRARIES JACK_INCLUDE_DIR) | ||||
| 
 | ||||
| MARK_AS_ADVANCED( | ||||
|   JACK_INCLUDE_DIR | ||||
|   JACK_LIBRARIES | ||||
| ) | ||||
| 
 | ||||
							
								
								
									
										27
									
								
								cmake/FindLASH.cmake
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								cmake/FindLASH.cmake
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,27 @@ | ||||
| # - Try to find Lash library | ||||
| # Once done this will define: | ||||
| #  LASH_FOUND        - system has LASH | ||||
| #  LASH_INCLUDE_DIR  - incude paths to use | ||||
| #  LASH_LIBRARIES    - Link these to use | ||||
| 
 | ||||
| SET(LASH_FOUND 0) | ||||
| 
 | ||||
| FIND_PATH(LASH_INCLUDE_DIR lash/lash.h | ||||
| 	/usr/local/include/lash-1.0 | ||||
| 	/usr/include/lash-1.0 | ||||
| ) | ||||
| 
 | ||||
| FIND_LIBRARY(LASH_LIBRARIES lash | ||||
| 	/usr/local/lib | ||||
| 	/usr/lib | ||||
| ) | ||||
| 
 | ||||
| # handle the QUIETLY and REQUIRED arguments and set LASH_FOUND to TRUE | ||||
| # if all listed variables are TRUE | ||||
| INCLUDE(FindPackageHandleStandardArgs) | ||||
| FIND_PACKAGE_HANDLE_STANDARD_ARGS(LASH DEFAULT_MSG LASH_LIBRARIES LASH_INCLUDE_DIR) | ||||
| 
 | ||||
| MARK_AS_ADVANCED( | ||||
|   LASH_INCLUDE_DIR | ||||
|   LASH_LIBRARIES | ||||
| ) | ||||
							
								
								
									
										81
									
								
								configure.ac
									
									
									
									
									
								
							
							
						
						
									
										81
									
								
								configure.ac
									
									
									
									
									
								
							| @ -1,81 +0,0 @@ | ||||
| #                                               -*- Autoconf -*- | ||||
| # Process this file with autoconf to produce a configure script. | ||||
| 
 | ||||
| AC_PREREQ(2.61) | ||||
| AC_INIT([jack-keyboard], [2.8], [alkorz3@rx3.net]) | ||||
| AM_INIT_AUTOMAKE([-Wall foreign]) | ||||
| AC_CONFIG_SRCDIR([config.h.in]) | ||||
| AC_CONFIG_HEADERS([config.h]) | ||||
| 
 | ||||
| # Checks for programs. | ||||
| AC_PROG_CC | ||||
| 
 | ||||
| # Checks for libraries. | ||||
| 
 | ||||
| # Checks for header files. | ||||
| AC_HEADER_STDC | ||||
| AC_CHECK_HEADERS([stdlib.h string.h sys/time.h unistd.h]) | ||||
| 
 | ||||
| # Checks for typedefs, structures, and compiler characteristics. | ||||
| AC_C_CONST | ||||
| AC_HEADER_TIME | ||||
| AC_C_VOLATILE | ||||
| 
 | ||||
| # Checks for library functions. | ||||
| AC_FUNC_MALLOC | ||||
| AC_FUNC_STRTOD | ||||
| AC_CHECK_FUNCS([gettimeofday memset strcasecmp strdup]) | ||||
| 
 | ||||
| PKG_CHECK_MODULES(GTK, gtk+-2.0 >= 2.2) | ||||
| AC_SUBST(GTK_CFLAGS) | ||||
| AC_SUBST(GTK_LIBS) | ||||
| 
 | ||||
| PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.2) | ||||
| AC_SUBST(GLIB_CFLAGS) | ||||
| AC_SUBST(GLIB_LIBS) | ||||
| 
 | ||||
| PKG_CHECK_MODULES(GTHREAD, gthread-2.0 >= 2.2) | ||||
| AC_SUBST(GTHREAD_CFLAGS) | ||||
| AC_SUBST(GTHREAD_LIBS) | ||||
| 
 | ||||
| AC_ARG_WITH([x11], | ||||
| 	    [AS_HELP_STRING([--with-x11], | ||||
| 	    [support keyboard grabbing @<:@default=check@:>@])], | ||||
| 	    [], | ||||
| 	    [with_x11=check]) | ||||
| 
 | ||||
| AS_IF([test "x$with_x11" != xno], | ||||
|       [PKG_CHECK_MODULES(X11, x11, AC_DEFINE([HAVE_X11], [], [Defined if we have X11 support.]), | ||||
|       [if test "x$with_x11" != xcheck; then | ||||
|        AC_MSG_FAILURE([--with-x11 was given, but x11 was not found]) | ||||
|        fi | ||||
|        ])]) | ||||
| 
 | ||||
| AC_SUBST(X11_CFLAGS) | ||||
| AC_SUBST(X11_LIBS) | ||||
| 
 | ||||
| PKG_CHECK_MODULES(JACK, jack >= 0.102.0) | ||||
| AC_SUBST(JACK_CFLAGS) | ||||
| AC_SUBST(JACK_LIBS) | ||||
| 
 | ||||
| PKG_CHECK_MODULES(JACK_MIDI_NEEDS_NFRAMES, jack < 0.105.00, AC_DEFINE(JACK_MIDI_NEEDS_NFRAMES, 1, [whether or not JACK routines need nframes parameter]), true) | ||||
| 
 | ||||
| AC_ARG_WITH([lash], | ||||
| 	    [AS_HELP_STRING([--with-lash], | ||||
| 	    [support LASH @<:@default=check@:>@])], | ||||
| 	    [], | ||||
| 	    [with_lash=check]) | ||||
| 
 | ||||
| AS_IF([test "x$with_lash" != xno], | ||||
|       [PKG_CHECK_MODULES(LASH, lash-1.0, AC_DEFINE([HAVE_LASH], [], [Defined if we have LASH support.]), | ||||
|       [if test "x$with_lash" != xcheck; then | ||||
|        AC_MSG_FAILURE([--with-lash was given, but LASH was not found]) | ||||
|        fi | ||||
|        ])]) | ||||
| 
 | ||||
| AC_SUBST(LASH_CFLAGS) | ||||
| AC_SUBST(LASH_LIBS) | ||||
| 
 | ||||
| AC_CONFIG_FILES([Makefile src/Makefile man/Makefile pixmaps/Makefile]) | ||||
| AC_OUTPUT | ||||
| 
 | ||||
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 17 KiB | 
| @ -1,4 +0,0 @@ | ||||
| man_MANS = jack-keyboard.1 | ||||
| 
 | ||||
| EXTRA_DIST = $(man_MANS) | ||||
| 
 | ||||
| @ -1,17 +0,0 @@ | ||||
| pixmapsdir = $(datadir)/pixmaps | ||||
| pixmaps_DATA = jack-keyboard.png | ||||
| EXTRA_DIST = $(pixmaps_DATA) | ||||
| 
 | ||||
| gtk_update_icon_cache = gtk-update-icon-cache -f -t $(datadir)/icons/hicolor | ||||
| 
 | ||||
| install-data-hook: update-icon-cache | ||||
| uninstall-hook: update-icon-cache | ||||
| update-icon-cache: | ||||
| 	@-if test -z "$(DESTDIR)"; then \
 | ||||
| 		echo "Updating Gtk icon cache."; \
 | ||||
| 		$(gtk_update_icon_cache); \
 | ||||
| 	else \
 | ||||
| 		echo "*** Icon cache not updated.  After (un)install, run this:"; \
 | ||||
| 		echo "***   $(gtk_update_icon_cache)"; \
 | ||||
| 	fi | ||||
| 
 | ||||
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 161 B | 
| @ -1,205 +0,0 @@ | ||||
| <?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||||
| <!-- Created with Inkscape (http://www.inkscape.org/) --> | ||||
| 
 | ||||
| <svg | ||||
|    xmlns:dc="http://purl.org/dc/elements/1.1/" | ||||
|    xmlns:cc="http://creativecommons.org/ns#" | ||||
|    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" | ||||
|    xmlns:svg="http://www.w3.org/2000/svg" | ||||
|    xmlns="http://www.w3.org/2000/svg" | ||||
|    xmlns:xlink="http://www.w3.org/1999/xlink" | ||||
|    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" | ||||
|    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" | ||||
|    width="256" | ||||
|    height="256" | ||||
|    viewBox="0 0 256 256" | ||||
|    id="svg2" | ||||
|    version="1.1" | ||||
|    inkscape:version="0.92.2 (5c3e80d, 2017-08-06)" | ||||
|    sodipodi:docname="jack-keyboard.svg" | ||||
|    inkscape:export-filename="/home/markus/Programmierung/jack-keyboard/pixmaps/jack-keyboard.png" | ||||
|    inkscape:export-xdpi="48" | ||||
|    inkscape:export-ydpi="48"> | ||||
|   <defs | ||||
|      id="defs"> | ||||
|     <linearGradient | ||||
|        inkscape:collect="always" | ||||
|        id="linearGradient932"> | ||||
|       <stop | ||||
|          style="stop-color:#ffffff;stop-opacity:0.38283062" | ||||
|          offset="0" | ||||
|          id="stop928" /> | ||||
|       <stop | ||||
|          style="stop-color:#ffffff;stop-opacity:1" | ||||
|          offset="1" | ||||
|          id="stop930" /> | ||||
|     </linearGradient> | ||||
|     <linearGradient | ||||
|        inkscape:collect="always" | ||||
|        id="linearGradient918"> | ||||
|       <stop | ||||
|          style="stop-color:#ffffff;stop-opacity:0.07656612" | ||||
|          offset="0" | ||||
|          id="stop914" /> | ||||
|       <stop | ||||
|          id="stop926" | ||||
|          offset="0.13388273" | ||||
|          style="stop-color:#ffffff;stop-opacity:0.66473317" /> | ||||
|       <stop | ||||
|          id="stop922" | ||||
|          offset="0.46153846" | ||||
|          style="stop-color:#ffffff;stop-opacity:0.45011601" /> | ||||
|       <stop | ||||
|          style="stop-color:#ffffff;stop-opacity:0.29234338" | ||||
|          offset="0.46153846" | ||||
|          id="stop924" /> | ||||
|       <stop | ||||
|          style="stop-color:#ffffff;stop-opacity:0.23433875" | ||||
|          offset="1" | ||||
|          id="stop916" /> | ||||
|     </linearGradient> | ||||
|     <linearGradient | ||||
|        inkscape:collect="always" | ||||
|        id="linearGradient901"> | ||||
|       <stop | ||||
|          style="stop-color:#000000;stop-opacity:1;" | ||||
|          offset="0" | ||||
|          id="stop897" /> | ||||
|       <stop | ||||
|          id="stop905" | ||||
|          offset="0.11764706" | ||||
|          style="stop-color:#4f4f4f;stop-opacity:1" /> | ||||
|       <stop | ||||
|          style="stop-color:#000000;stop-opacity:1" | ||||
|          offset="1" | ||||
|          id="stop899" /> | ||||
|     </linearGradient> | ||||
|     <linearGradient | ||||
|        inkscape:collect="always" | ||||
|        id="linearGradient828"> | ||||
|       <stop | ||||
|          style="stop-color:#6f6f5d;stop-opacity:1" | ||||
|          offset="0" | ||||
|          id="stop824" /> | ||||
|       <stop | ||||
|          id="stop832" | ||||
|          offset="0.125" | ||||
|          style="stop-color:#fbfbfb;stop-opacity:1" /> | ||||
|       <stop | ||||
|          style="stop-color:#d7d6b6;stop-opacity:1" | ||||
|          offset="1" | ||||
|          id="stop826" /> | ||||
|     </linearGradient> | ||||
|     <linearGradient | ||||
|        inkscape:collect="always" | ||||
|        xlink:href="#linearGradient828" | ||||
|        id="linearGradient830" | ||||
|        x1="128" | ||||
|        y1="0" | ||||
|        x2="128" | ||||
|        y2="256" | ||||
|        gradientUnits="userSpaceOnUse" /> | ||||
|     <linearGradient | ||||
|        inkscape:collect="always" | ||||
|        xlink:href="#linearGradient901" | ||||
|        id="linearGradient903" | ||||
|        x1="128" | ||||
|        y1="0" | ||||
|        x2="128" | ||||
|        y2="136" | ||||
|        gradientUnits="userSpaceOnUse" /> | ||||
|     <linearGradient | ||||
|        inkscape:collect="always" | ||||
|        xlink:href="#linearGradient918" | ||||
|        id="linearGradient920" | ||||
|        x1="128" | ||||
|        y1="0" | ||||
|        x2="128" | ||||
|        y2="104" | ||||
|        gradientUnits="userSpaceOnUse" /> | ||||
|     <linearGradient | ||||
|        inkscape:collect="always" | ||||
|        xlink:href="#linearGradient932" | ||||
|        id="linearGradient934" | ||||
|        x1="8" | ||||
|        y1="0" | ||||
|        x2="8" | ||||
|        y2="80" | ||||
|        gradientUnits="userSpaceOnUse" /> | ||||
|   </defs> | ||||
|   <sodipodi:namedview | ||||
|      id="base" | ||||
|      pagecolor="#ffffff" | ||||
|      bordercolor="#666666" | ||||
|      borderopacity="1.0" | ||||
|      inkscape:pageopacity="0.0" | ||||
|      inkscape:pageshadow="2" | ||||
|      inkscape:zoom="0.44097686" | ||||
|      inkscape:cx="685.32502" | ||||
|      inkscape:cy="-202.20348" | ||||
|      inkscape:document-units="px" | ||||
|      inkscape:current-layer="svg2" | ||||
|      showgrid="true" | ||||
|      units="px" | ||||
|      inkscape:window-width="2880" | ||||
|      inkscape:window-height="1553" | ||||
|      inkscape:window-x="0" | ||||
|      inkscape:window-y="41" | ||||
|      inkscape:window-maximized="1" | ||||
|      inkscape:snap-bbox="true" | ||||
|      inkscape:bbox-nodes="true" | ||||
|      inkscape:object-paths="true" | ||||
|      inkscape:object-nodes="true" | ||||
|      inkscape:snap-smooth-nodes="true" | ||||
|      inkscape:snap-object-midpoints="true" | ||||
|      inkscape:snap-center="true" | ||||
|      inkscape:snap-others="false" | ||||
|      showborder="false"> | ||||
|     <inkscape:grid | ||||
|        type="xygrid" | ||||
|        id="grid1" | ||||
|        empspacing="8" | ||||
|        visible="false" /> | ||||
|   </sodipodi:namedview> | ||||
|   <metadata | ||||
|      id="metadata"> | ||||
|     <rdf:RDF> | ||||
|       <cc:Work | ||||
|          rdf:about=""> | ||||
|         <dc:format>image/svg+xml</dc:format> | ||||
|         <dc:type | ||||
|            rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> | ||||
|         <dc:title></dc:title> | ||||
|       </cc:Work> | ||||
|     </rdf:RDF> | ||||
|   </metadata> | ||||
|   <g | ||||
|      inkscape:label="Ebene 1" | ||||
|      inkscape:groupmode="layer" | ||||
|      id="layer1" /> | ||||
|   <rect | ||||
|      style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:url(#linearGradient830);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.51181102;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;paint-order:stroke fill markers;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" | ||||
|      id="rect816" | ||||
|      width="256" | ||||
|      height="256" | ||||
|      x="0" | ||||
|      y="0" /> | ||||
|   <path | ||||
|      style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.921;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:url(#linearGradient934);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.51181102;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;paint-order:stroke fill markers;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" | ||||
|      d="M 0 0 L 0 256 L 4 256 L 4 0 L 0 0 z M 64 0 L 64 256 L 68 256 L 68 0 L 64 0 z M 128 0 L 128 256 L 132 256 L 132 0 L 128 0 z M 192 0 L 192 256 L 196 256 L 196 0 L 192 0 z " | ||||
|      id="rect818" /> | ||||
|   <path | ||||
|      style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.51300001;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.51181102;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;paint-order:stroke fill markers;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" | ||||
|      d="m 60,0 v 256 h 4 V 0 Z m 64,0 v 256 h 4 V 0 Z m 64,0 v 256 h 4 V 0 Z" | ||||
|      id="rect834" | ||||
|      inkscape:connector-curvature="0" | ||||
|      sodipodi:nodetypes="ccccccccccccccc" /> | ||||
|   <path | ||||
|      style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:url(#linearGradient903);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.5118109;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;paint-order:stroke fill markers;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" | ||||
|      d="M 40 0 L 40 136 L 88 136 L 88 0 L 40 0 z M 104 0 L 104 136 L 152 136 L 152 0 L 104 0 z M 168 0 L 168 136 L 216 136 L 216 0 L 168 0 z " | ||||
|      id="rect820" /> | ||||
|   <path | ||||
|      style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:url(#linearGradient920);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.51181102;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;paint-order:stroke fill markers;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" | ||||
|      d="M 48 0 L 48 104 L 80 104 L 80 0 L 48 0 z M 112 0 L 112 104 L 144 104 L 144 0 L 112 0 z M 176 0 L 176 104 L 208 104 L 208 0 L 176 0 z " | ||||
|      id="rect907" /> | ||||
| </svg> | ||||
| Before Width: | Height: | Size: 8.8 KiB | 
| @ -1,10 +0,0 @@ | ||||
| bin_PROGRAMS = jack-keyboard | ||||
| jack_keyboard_SOURCES = jack-keyboard.c pianokeyboard.c pianokeyboard.h | ||||
| jack_keyboard_LDADD = $(GTK_LIBS) $(GLIB_LIBS) $(GTHREAD_LIBS) $(X11_LIBS) $(JACK_LIBS) $(LASH_LIBS) | ||||
| jack_keyboard_CFLAGS = $(GTK_CFLAGS) $(GLIB_CFLAGS) $(GTHREAD_CFLAGS) $(X11_CFLAGS) $(JACK_CFLAGS) $(LASH_CFLAGS) \
 | ||||
| 	-DG_LOG_DOMAIN=\"jack-keyboard\" | ||||
| 
 | ||||
| desktopdir = $(datadir)/applications | ||||
| desktop_DATA = jack-keyboard.desktop | ||||
| EXTRA_DIST = $(desktop_DATA) | ||||
| 
 | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -35,8 +35,6 @@ | ||||
| #include <string.h> | ||||
| #include <gtk/gtk.h> | ||||
| #include <gdk/gdkkeysyms.h> | ||||
| #include <cairo.h> | ||||
| #include <math.h> | ||||
| 
 | ||||
| #include "pianokeyboard.h" | ||||
| 
 | ||||
| @ -57,34 +55,53 @@ draw_keyboard_cue(PianoKeyboard *pk) | ||||
| 	int w, h, first_note_in_lower_row, last_note_in_lower_row, | ||||
| 	    first_note_in_higher_row, last_note_in_higher_row; | ||||
| 
 | ||||
| 	GdkGC *gc; | ||||
| 
 | ||||
| 	w = pk->notes[0].w; | ||||
| 	h = pk->notes[0].h; | ||||
| 
 | ||||
| 	gc = GTK_WIDGET(pk)->style->fg_gc[0]; | ||||
| 
 | ||||
| 	first_note_in_lower_row = (pk->octave + 5) * 12; | ||||
| 	last_note_in_lower_row = (pk->octave + 6) * 12 - 1; | ||||
| 	first_note_in_higher_row = (pk->octave + 6) * 12; | ||||
| 	last_note_in_higher_row = (pk->octave + 7) * 12 + 4; | ||||
| 
 | ||||
| 	gdk_draw_line(GTK_WIDGET(pk)->window, gc, pk->notes[first_note_in_lower_row].x + 3, | ||||
| 	    h - 6, pk->notes[last_note_in_lower_row].x + w - 3, h - 6); | ||||
| 	cairo_t *cr = gdk_cairo_create(gtk_widget_get_window(GTK_WIDGET(pk))); | ||||
| 
 | ||||
| 	gdk_draw_line(GTK_WIDGET(pk)->window, gc, pk->notes[first_note_in_higher_row].x + 3, | ||||
| 	    h - 9, pk->notes[last_note_in_higher_row].x + w - 3, h - 9); | ||||
| 	cairo_move_to(cr, pk->notes[first_note_in_lower_row].x + 3, h - 6); | ||||
| 	cairo_line_to(cr, pk->notes[last_note_in_lower_row].x + w - 3, h - 6); | ||||
| 
 | ||||
| 	cairo_move_to(cr, pk->notes[first_note_in_higher_row].x + 3, h - 9); | ||||
| 	cairo_line_to(cr, pk->notes[last_note_in_higher_row].x + w - 3, h - 9); | ||||
| 
 | ||||
| 	cairo_destroy(cr); | ||||
| } | ||||
| 
 | ||||
| static void  | ||||
| static void | ||||
| #if GTK_CHECK_VERSION(3,0,0) | ||||
| draw_note(PianoKeyboard *pk, cairo_t *cr, int note) | ||||
| #else | ||||
| draw_note(PianoKeyboard *pk, int note) | ||||
| #endif | ||||
| { | ||||
| 	GtkWidget *widget = GTK_WIDGET(pk); | ||||
| 	if (note < pk->min_note) | ||||
| 		return; | ||||
| 	if (note > pk->max_note) | ||||
| 		return; | ||||
| 	int is_white, x, w, h, pressed; | ||||
| 	int is_white, x, w, h; | ||||
| 
 | ||||
| #if GTK_CHECK_VERSION(3,0,0) | ||||
| 	if (!cr) | ||||
| 		cr = gdk_cairo_create(gtk_widget_get_window(GTK_WIDGET(pk))); | ||||
| 
 | ||||
| 	GdkRGBA black = { .red = 0.0, .green = 0.0, .blue = 0.0, .alpha = 1.0}; | ||||
| 	GdkRGBA white = { .red = 1.0, .green = 1.0, .blue = 1.0, .alpha = 1.0}; | ||||
| #else | ||||
| 	cairo_t *cr = gdk_cairo_create(gtk_widget_get_window(GTK_WIDGET(pk))); | ||||
| 
 | ||||
| 	GdkColor black = {0, 0, 0, 0}; | ||||
| 	GdkColor white = {0, 65535, 65535, 65535}; | ||||
| 
 | ||||
| 	GtkWidget *widget; | ||||
| 	GtkAllocation allocation; | ||||
| #endif | ||||
| 
 | ||||
| 	is_white = pk->notes[note].white; | ||||
| 
 | ||||
| @ -92,23 +109,53 @@ draw_note(PianoKeyboard *pk, int note) | ||||
| 	w = pk->notes[note].w; | ||||
| 	h = pk->notes[note].h; | ||||
| 
 | ||||
| 	pressed = (int)(pk->notes[note].pressed || pk->notes[note].sustained); | ||||
| 	 | ||||
| 	if (is_white) { | ||||
| 		piano_keyboard_draw_white_key(widget, x, 0, w, h, pressed, pk->notes[note].velocity); | ||||
| 	} else { | ||||
| 		piano_keyboard_draw_black_key(widget, x, 0, w, h, pressed, pk->notes[note].velocity); | ||||
| 	} | ||||
| 	 | ||||
| 	if (note < NNOTES - 2 && !pk->notes[note + 1].white) | ||||
| 		draw_note(pk, note + 1); | ||||
| 	 | ||||
| 	if (note > 0 && !pk->notes[note - 1].white) | ||||
| 		draw_note(pk, note - 1); | ||||
| 			 | ||||
| 	if (pk->notes[note].pressed || pk->notes[note].sustained) | ||||
| 		is_white = !is_white; | ||||
| 
 | ||||
| 	if (is_white) | ||||
| #if GTK_CHECK_VERSION(3,0,0) | ||||
| 		gdk_cairo_set_source_rgba(cr, &white); | ||||
| #else | ||||
| 		gdk_cairo_set_source_color(cr, &white); | ||||
| #endif | ||||
| 	else | ||||
| #if GTK_CHECK_VERSION(3,0,0) | ||||
| 		gdk_cairo_set_source_rgba(cr, &black); | ||||
| #else | ||||
| 		gdk_cairo_set_source_color(cr, &black); | ||||
| #endif | ||||
| 
 | ||||
| 	cairo_rectangle(cr, x, 0, w, h); | ||||
| 	cairo_fill(cr); | ||||
| #if GTK_CHECK_VERSION(3,0,0) | ||||
| 	gdk_cairo_set_source_rgba(cr, &black); | ||||
| #else | ||||
| 	gdk_cairo_set_source_color(cr, &black); | ||||
| #endif | ||||
| 	cairo_rectangle(cr, x, 0, w, h); | ||||
| 	cairo_stroke(cr); | ||||
| 
 | ||||
| #if !GTK_CHECK_VERSION(3,0,0) | ||||
| 	cairo_destroy(cr); | ||||
| #endif | ||||
| 
 | ||||
| 	if (pk->enable_keyboard_cue) | ||||
| 		draw_keyboard_cue(pk); | ||||
| 		 | ||||
| 
 | ||||
| 	/* We need to redraw black keys that partially obscure the white one. */ | ||||
| 	if (note < NNOTES - 2 && !pk->notes[note + 1].white) | ||||
| #if GTK_CHECK_VERSION(3,0,0) | ||||
| 		draw_note(pk, cr, note + 1); | ||||
| #else | ||||
| 		draw_note(pk, note + 1); | ||||
| #endif | ||||
| 
 | ||||
| 	if (note > 0 && !pk->notes[note - 1].white) | ||||
| #if GTK_CHECK_VERSION(3,0,0) | ||||
| 		draw_note(pk, cr, note - 1); | ||||
| #else | ||||
| 		draw_note(pk, note - 1); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * XXX: This doesn't really belong here.  Originally I wanted to pack PianoKeyboard into GtkFrame | ||||
| 	 * packed into GtkAlignment.  I failed to make it behave the way I want.  GtkFrame would need | ||||
| @ -116,12 +163,14 @@ draw_note(PianoKeyboard *pk, int note) | ||||
| 	 * that didn't work. | ||||
| 	 */ | ||||
| 	widget = GTK_WIDGET(pk); | ||||
| 	gtk_paint_shadow(widget->style, widget->window, GTK_STATE_NORMAL, GTK_SHADOW_IN, NULL, | ||||
| 	    widget, NULL, pk->widget_margin, 0, widget->allocation.width - pk->widget_margin * 2 + 1, | ||||
| 	    widget->allocation.height); | ||||
| 	gtk_widget_get_allocation(widget, &allocation); | ||||
| 	gtk_paint_shadow(gtk_widget_get_style(widget), gtk_widget_get_window(widget), GTK_STATE_NORMAL, GTK_SHADOW_IN, NULL, | ||||
| 	    widget, NULL, pk->widget_margin, 0, allocation.width - pk->widget_margin * 2 + 1, | ||||
| 	    allocation.height); | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| static int  | ||||
| static int | ||||
| press_key(PianoKeyboard *pk, int key) | ||||
| { | ||||
| 	assert(key >= 0); | ||||
| @ -139,15 +188,18 @@ press_key(PianoKeyboard *pk, int key) | ||||
| 		pk->notes[key].sustained = 0; | ||||
| 
 | ||||
| 	pk->notes[key].pressed = 1; | ||||
| 	pk->notes[key].velocity = pk->current_velocity; | ||||
| 
 | ||||
| 	g_signal_emit_by_name(GTK_WIDGET(pk), "note-on", key); | ||||
| #if GTK_CHECK_VERSION(3,0,0) | ||||
| 	draw_note(pk, NULL, key); | ||||
| #else | ||||
| 	draw_note(pk, key); | ||||
| #endif | ||||
| 
 | ||||
| 	return (1); | ||||
| } | ||||
| 
 | ||||
| static int  | ||||
| static int | ||||
| release_key(PianoKeyboard *pk, int key) | ||||
| { | ||||
| 	assert(key >= 0); | ||||
| @ -167,12 +219,16 @@ release_key(PianoKeyboard *pk, int key) | ||||
| 		return (0); | ||||
| 
 | ||||
| 	g_signal_emit_by_name(GTK_WIDGET(pk), "note-off", key); | ||||
| #if GTK_CHECK_VERSION(3,0,0) | ||||
| 	draw_note(pk, NULL, key); | ||||
| #else | ||||
| 	draw_note(pk, key); | ||||
| #endif | ||||
| 
 | ||||
| 	return (1); | ||||
| } | ||||
| 
 | ||||
| static void  | ||||
| static void | ||||
| stop_unsustained_notes(PianoKeyboard *pk) | ||||
| { | ||||
| 	int i; | ||||
| @ -181,12 +237,16 @@ stop_unsustained_notes(PianoKeyboard *pk) | ||||
| 		if (pk->notes[i].pressed && !pk->notes[i].sustained) { | ||||
| 			pk->notes[i].pressed = 0; | ||||
| 			g_signal_emit_by_name(GTK_WIDGET(pk), "note-off", i); | ||||
| #if GTK_CHECK_VERSION(3,0,0) | ||||
| 			draw_note(pk, NULL, i); | ||||
| #else | ||||
| 			draw_note(pk, i); | ||||
| #endif | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static void  | ||||
| static void | ||||
| stop_sustained_notes(PianoKeyboard *pk) | ||||
| { | ||||
| 	int i; | ||||
| @ -196,7 +256,11 @@ stop_sustained_notes(PianoKeyboard *pk) | ||||
| 			pk->notes[i].pressed = 0; | ||||
| 			pk->notes[i].sustained = 0; | ||||
| 			g_signal_emit_by_name(GTK_WIDGET(pk), "note-off", i); | ||||
| #if GTK_CHECK_VERSION(3,0,0) | ||||
| 			draw_note(pk, NULL, i); | ||||
| #else | ||||
| 			draw_note(pk, i); | ||||
| #endif | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @ -230,7 +294,7 @@ clear_notes(PianoKeyboard *pk) | ||||
| 	g_array_set_size(pk->key_bindings, 0); | ||||
| } | ||||
| 
 | ||||
| static void  | ||||
| static void | ||||
| bind_keys_qwerty(PianoKeyboard *pk) | ||||
| { | ||||
| 	clear_notes(pk); | ||||
| @ -284,7 +348,7 @@ bind_keys_qwerty(PianoKeyboard *pk) | ||||
| 	bind_key(pk, 51, 45); /* yes, really, at least here... */ | ||||
| } | ||||
| 
 | ||||
| static gint  | ||||
| static gint | ||||
| keyboard_event_handler(GtkWidget *mk, GdkEventKey *event, gpointer notused) | ||||
| { | ||||
| 	int note; | ||||
| @ -312,12 +376,14 @@ keyboard_event_handler(GtkWidget *mk, GdkEventKey *event, gpointer notused) | ||||
| 	return (TRUE); | ||||
| } | ||||
| 
 | ||||
| static int  | ||||
| static int | ||||
| get_note_for_xy(PianoKeyboard *pk, int x, int y) | ||||
| { | ||||
| 	int height, note; | ||||
| 	GtkAllocation allocation; | ||||
| 
 | ||||
| 	height = GTK_WIDGET(pk)->allocation.height; | ||||
| 	gtk_widget_get_allocation(GTK_WIDGET(pk), &allocation); | ||||
| 	height = allocation.height; | ||||
| 
 | ||||
| 	if (y <= ((height * 2) / 3)) { /* might be a black key */ | ||||
| 		for (note = 0; note <= pk->max_note; ++note) { | ||||
| @ -340,7 +406,7 @@ get_note_for_xy(PianoKeyboard *pk, int x, int y) | ||||
| 	return (-1); | ||||
| } | ||||
| 
 | ||||
| static gboolean  | ||||
| static gboolean | ||||
| mouse_button_event_handler(PianoKeyboard *pk, GdkEventButton *event, gpointer notused) | ||||
| { | ||||
| 	int x, y, note; | ||||
| @ -382,7 +448,7 @@ mouse_button_event_handler(PianoKeyboard *pk, GdkEventButton *event, gpointer no | ||||
| 	return (TRUE); | ||||
| } | ||||
| 
 | ||||
| static gboolean  | ||||
| static gboolean | ||||
| mouse_motion_event_handler(PianoKeyboard *pk, GdkEventMotion *event, gpointer notused) | ||||
| { | ||||
| 	int note; | ||||
| @ -393,7 +459,7 @@ mouse_motion_event_handler(PianoKeyboard *pk, GdkEventMotion *event, gpointer no | ||||
| 	note = get_note_for_xy(pk, event->x, event->y); | ||||
| 
 | ||||
| 	if (note != pk->note_being_pressed_using_mouse && note >= 0) { | ||||
| 		 | ||||
| 
 | ||||
| 		if (pk->note_being_pressed_using_mouse >= 0) | ||||
| 			release_key(pk, pk->note_being_pressed_using_mouse); | ||||
| 		press_key(pk, note); | ||||
| @ -404,23 +470,45 @@ mouse_motion_event_handler(PianoKeyboard *pk, GdkEventMotion *event, gpointer no | ||||
| } | ||||
| 
 | ||||
| static gboolean | ||||
| #if GTK_CHECK_VERSION(3,0,0) | ||||
| piano_keyboard_draw(GtkWidget *widget, cairo_t *cr) | ||||
| #else | ||||
| piano_keyboard_expose(GtkWidget *widget, GdkEventExpose *event) | ||||
| #endif | ||||
| { | ||||
| 	int i; | ||||
| 	PianoKeyboard *pk = PIANO_KEYBOARD(widget); | ||||
| 
 | ||||
| 	for (i = 0; i < NNOTES; i++) | ||||
| #if GTK_CHECK_VERSION(3,0,0) | ||||
| 		draw_note(pk, NULL, i); | ||||
| #else | ||||
| 		draw_note(pk, i); | ||||
| #endif | ||||
| 
 | ||||
| 	return (TRUE); | ||||
| } | ||||
| 
 | ||||
| static void  | ||||
| #if GTK_CHECK_VERSION(3,0,0) | ||||
| static void | ||||
| piano_keyboard_get_preferred_width(GtkWidget *widget, gint *minimal_width, gint *natural_width) | ||||
| { | ||||
| 	*minimal_width = *natural_width = PIANO_KEYBOARD_DEFAULT_WIDTH; | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| piano_keyboard_get_preferred_height(GtkWidget *widget, gint *minimal_height, gint *natural_height) | ||||
| { | ||||
| 	*minimal_height = *natural_height = PIANO_KEYBOARD_DEFAULT_HEIGHT; | ||||
| } | ||||
| #else | ||||
| static void | ||||
| piano_keyboard_size_request(GtkWidget *widget, GtkRequisition *requisition) | ||||
| { | ||||
| 	requisition->width = PIANO_KEYBOARD_DEFAULT_WIDTH; | ||||
| 	requisition->height = PIANO_KEYBOARD_DEFAULT_HEIGHT; | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| static int is_black(int key) | ||||
| { | ||||
| @ -457,6 +545,7 @@ recompute_dimensions(PianoKeyboard *pk) | ||||
| { | ||||
| 	int number_of_white_keys = 0, skipped_white_keys = 0, key_width, black_key_width, useful_width, note, | ||||
| 	    white_key, width, height; | ||||
| 	GtkAllocation allocation; | ||||
| 
 | ||||
| 	for (note = pk->min_note; note <= pk->max_note; ++note) | ||||
| 		if (!is_black(note)) | ||||
| @ -465,8 +554,9 @@ recompute_dimensions(PianoKeyboard *pk) | ||||
| 		if (!is_black(note)) | ||||
| 			++skipped_white_keys; | ||||
| 
 | ||||
| 	width = GTK_WIDGET(pk)->allocation.width; | ||||
| 	height = GTK_WIDGET(pk)->allocation.height; | ||||
| 	gtk_widget_get_allocation(GTK_WIDGET(pk), &allocation); | ||||
| 	width = allocation.width; | ||||
| 	height = allocation.height; | ||||
| 
 | ||||
| 	key_width = width / number_of_white_keys; | ||||
| 	black_key_width = key_width * 0.8; | ||||
| @ -476,11 +566,11 @@ recompute_dimensions(PianoKeyboard *pk) | ||||
| 	for (note = 0, white_key = -skipped_white_keys; note < NNOTES; note++) { | ||||
| 		if (is_black(note)) { | ||||
| 			/* This note is black key. */ | ||||
| 			pk->notes[note].x = pk->widget_margin +  | ||||
| 			pk->notes[note].x = pk->widget_margin + | ||||
| 			    (white_key * key_width) - | ||||
| 			    (black_key_width * black_key_left_shift(note)); | ||||
| 			pk->notes[note].w = black_key_width; | ||||
| 			pk->notes[note].h = (height * 3) / 5; | ||||
| 			pk->notes[note].h = (height * 2) / 3; | ||||
| 			pk->notes[note].white = 0; | ||||
| 			continue; | ||||
| 		} | ||||
| @ -502,12 +592,12 @@ piano_keyboard_size_allocate(GtkWidget *widget, GtkAllocation *allocation) | ||||
| 	g_return_if_fail(widget != NULL); | ||||
| 	g_return_if_fail(allocation != NULL); | ||||
| 
 | ||||
| 	widget->allocation = *allocation; | ||||
| 	gtk_widget_set_allocation(widget, allocation); | ||||
| 
 | ||||
| 	recompute_dimensions(PIANO_KEYBOARD(widget)); | ||||
| 
 | ||||
| 	if (GTK_WIDGET_REALIZED(widget)) | ||||
| 		gdk_window_move_resize (widget->window, allocation->x, allocation->y, allocation->width, allocation->height); | ||||
| 	if (gtk_widget_get_realized(widget)) | ||||
| 		gdk_window_move_resize (gtk_widget_get_window(widget), allocation->x, allocation->y, allocation->width, allocation->height); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| @ -524,10 +614,16 @@ piano_keyboard_class_init(PianoKeyboardClass *klass) | ||||
| 	    G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, | ||||
| 	    0, NULL, NULL, g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT); | ||||
| 
 | ||||
| 	widget_klass = (GtkWidgetClass*)klass;	 | ||||
| 	widget_klass = (GtkWidgetClass*)klass; | ||||
| 
 | ||||
| #if GTK_CHECK_VERSION(3,0,0) | ||||
| 	widget_klass->draw = piano_keyboard_draw; | ||||
| 	widget_klass->get_preferred_width = piano_keyboard_get_preferred_width; | ||||
| 	widget_klass->get_preferred_height = piano_keyboard_get_preferred_height; | ||||
| #else | ||||
| 	widget_klass->expose_event = piano_keyboard_expose; | ||||
| 	widget_klass->size_request = piano_keyboard_size_request; | ||||
| #endif | ||||
| 	widget_klass->size_allocate = piano_keyboard_size_allocate; | ||||
| } | ||||
| 
 | ||||
| @ -573,7 +669,7 @@ piano_keyboard_new(void) | ||||
| 	GtkWidget *widget; | ||||
| 	PianoKeyboard *pk; | ||||
| 
 | ||||
| 	widget = gtk_type_new(piano_keyboard_get_type()); | ||||
| 	widget = g_object_new(TYPE_PIANO_KEYBOARD, NULL); | ||||
| 	pk = PIANO_KEYBOARD(widget); | ||||
| 
 | ||||
| 	pk->maybe_stop_sustained_notes = 0; | ||||
| @ -606,7 +702,7 @@ piano_keyboard_sustain_press(PianoKeyboard *pk) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void	 | ||||
| void | ||||
| piano_keyboard_sustain_release(PianoKeyboard *pk) | ||||
| { | ||||
| 	if (pk->maybe_stop_sustained_notes) | ||||
| @ -616,12 +712,15 @@ piano_keyboard_sustain_release(PianoKeyboard *pk) | ||||
| } | ||||
| 
 | ||||
| void | ||||
| piano_keyboard_set_note_on(PianoKeyboard *pk, int note, int vel) | ||||
| piano_keyboard_set_note_on(PianoKeyboard *pk, int note) | ||||
| { | ||||
| 	if (pk->notes[note].pressed == 0) { | ||||
| 		pk->notes[note].pressed = 1; | ||||
| 		pk->notes[note].velocity = vel; | ||||
| #if GTK_CHECK_VERSION(3,0,0) | ||||
| 		draw_note(pk, NULL, note); | ||||
| #else | ||||
| 		draw_note(pk, note); | ||||
| #endif | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| @ -631,7 +730,11 @@ piano_keyboard_set_note_off(PianoKeyboard *pk, int note) | ||||
| 	if (pk->notes[note].pressed || pk->notes[note].sustained) { | ||||
| 		pk->notes[note].pressed = 0; | ||||
| 		pk->notes[note].sustained = 0; | ||||
| #if GTK_CHECK_VERSION(3,0,0) | ||||
| 		draw_note(pk, NULL, note); | ||||
| #else | ||||
| 		draw_note(pk, note); | ||||
| #endif | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| @ -667,137 +770,3 @@ piano_keyboard_enable_all_midi_notes(PianoKeyboard* pk) | ||||
| 	recompute_dimensions(pk); | ||||
| } | ||||
| 
 | ||||
| void | ||||
| piano_keyboard_draw_white_key (GtkWidget *widget, int x, int y, int w, int h, int pressed, int vel) | ||||
| { | ||||
| 	cairo_pattern_t *pat; | ||||
| 	GdkWindow *window = widget->window; | ||||
| 	cairo_t *c = gdk_cairo_create(GDK_DRAWABLE(window)); | ||||
| 	cairo_set_line_join(c, CAIRO_LINE_JOIN_MITER); | ||||
| 	cairo_set_line_width(c, 1); | ||||
| 	 | ||||
| 	cairo_rectangle(c, x, y, w, h); | ||||
| 	cairo_clip_preserve(c); | ||||
| 	 | ||||
| 	pat = cairo_pattern_create_linear (x, y, x, y + h); | ||||
| 	cairo_pattern_add_color_stop_rgb (pat, 0.0, 0.25, 0.25, 0.2); | ||||
| 	cairo_pattern_add_color_stop_rgb (pat, 0.1, 0.957, 0.914, 0.925); | ||||
| 	cairo_pattern_add_color_stop_rgb (pat, 1.0, 0.796, 0.787, 0.662); | ||||
| 	cairo_set_source(c, pat); | ||||
| 	cairo_fill(c); | ||||
| 	 | ||||
| 	cairo_move_to(c, x + 0.5, y); | ||||
| 	cairo_line_to(c, x + 0.5, y + h); | ||||
| 	cairo_set_source_rgba(c, 1, 1, 1, 0.75); | ||||
| 	cairo_stroke(c); | ||||
| 	 | ||||
| 	cairo_move_to(c, x + w - 0.5, y); | ||||
| 	cairo_line_to(c, x + w - 0.5, y + h); | ||||
| 	cairo_set_source_rgba(c, 0, 0, 0, 0.5); | ||||
| 	cairo_stroke(c); | ||||
| 	 | ||||
| 	if (pressed) | ||||
| 		piano_keyboard_draw_pressed(c, x, y, w, h, vel); | ||||
| 		 | ||||
| 	piano_keyboard_draw_key_shadow(c, x, y, w, h); | ||||
| 	 | ||||
| 	cairo_destroy(c); | ||||
| } | ||||
| 
 | ||||
| void | ||||
| piano_keyboard_draw_black_key (GtkWidget *widget, int x, int y, int w, int h, int pressed, int vel) | ||||
| { | ||||
| 	cairo_pattern_t *pat; | ||||
| 	GdkWindow *window = widget->window; | ||||
| 	cairo_t *c = gdk_cairo_create(GDK_DRAWABLE(window)); | ||||
| 	cairo_set_line_join(c, CAIRO_LINE_JOIN_MITER); | ||||
| 	cairo_set_line_width(c, 1); | ||||
| 	 | ||||
| 	cairo_rectangle(c, x, y, w, h); | ||||
| 	cairo_clip_preserve(c); | ||||
| 	 | ||||
| 	pat = cairo_pattern_create_linear (x, y, x, y + h); | ||||
| 	cairo_pattern_add_color_stop_rgb (pat, 0.0, 0, 0, 0); | ||||
| 	cairo_pattern_add_color_stop_rgb (pat, 0.1, 0.27, 0.27, 0.27); | ||||
| 	cairo_pattern_add_color_stop_rgb (pat, 1.0, 0, 0, 0); | ||||
| 	cairo_set_source(c, pat); | ||||
| 	cairo_fill(c); | ||||
| 	 | ||||
| 	pat = cairo_pattern_create_linear (x + 1, y, x + 1, y + h - w); | ||||
| 	cairo_pattern_add_color_stop_rgb (pat, 0.0, 0, 0, 0); | ||||
| 	cairo_pattern_add_color_stop_rgb (pat, 0.1, 0.55, 0.55, 0.55); | ||||
| 	cairo_pattern_add_color_stop_rgb (pat, 0.5, 0.45, 0.45, 0.45); | ||||
| 	cairo_pattern_add_color_stop_rgb (pat, 0.5001, 0.35, 0.35, 0.35); | ||||
| 	cairo_pattern_add_color_stop_rgb (pat, 1.0, 0.25, 0.25, 0.25); | ||||
| 	cairo_set_source(c, pat); | ||||
| 	cairo_rectangle(c, x + 1, y, w - 2, y + h - w); | ||||
| 	cairo_fill(c); | ||||
| 	 | ||||
| 	if (pressed) | ||||
| 		piano_keyboard_draw_pressed(c, x, y, w, h, vel); | ||||
| 	 | ||||
| 	piano_keyboard_draw_key_shadow(c, x, y, w, h); | ||||
| 	 | ||||
| 	cairo_destroy(c); | ||||
| } | ||||
| 
 | ||||
| void | ||||
| piano_keyboard_draw_pressed (cairo_t *c, int x, int y, int w, int h, int vel) | ||||
| { | ||||
| 	float m = w * .15; // margin
 | ||||
| 	float s = w - m * 2.; // size
 | ||||
| 	float _vel = ((float)vel / 127.); | ||||
| 	float hue = _vel * 140 + 220; // hue 220 .. 360 - blue over pink to red
 | ||||
| 	float sat = .5 + _vel * 0.3; // saturation 0.5 .. 0.8
 | ||||
| 	float val = 1. - _vel * 0.2; // lightness 1.0 .. 0.8
 | ||||
| 	cairo_rectangle(c, x + m, y + h - m - s * 2, s, s * 2); | ||||
| 	hsv HSV = {hue, sat, val}; | ||||
| 	rgb RGB = hsv2rgb(HSV); | ||||
| 	cairo_set_source_rgb(c, RGB.r, RGB.g, RGB.b); | ||||
| 	cairo_fill(c); | ||||
| } | ||||
| 
 | ||||
| void | ||||
| piano_keyboard_draw_key_shadow (cairo_t *c, int x, int y, int w, int h) | ||||
| { | ||||
| 	cairo_pattern_t *pat; | ||||
| 	pat = cairo_pattern_create_linear (x, y, x, y + (int)(h * 0.2)); | ||||
| 	cairo_pattern_add_color_stop_rgba (pat, 0.0, 0, 0, 0, 0.4); | ||||
| 	cairo_pattern_add_color_stop_rgba (pat, 1.0, 0, 0, 0, 0); | ||||
| 	cairo_rectangle(c, x, y, w, (int)(h * 0.2)); | ||||
| 	cairo_set_source(c, pat); | ||||
| 	cairo_fill(c); | ||||
| } | ||||
| 
 | ||||
| rgb | ||||
| hsv2rgb(hsv HSV) | ||||
| { | ||||
| 	rgb RGB; | ||||
| 	double H = HSV.h, S = HSV.s, V = HSV.v, | ||||
| 			P, Q, T, | ||||
| 			fract; | ||||
| 
 | ||||
| 	(H == 360.)?(H = 0.):(H /= 60.); | ||||
| 	fract = H - floor(H); | ||||
| 
 | ||||
| 	P = V*(1. - S); | ||||
| 	Q = V*(1. - S*fract); | ||||
| 	T = V*(1. - S*(1. - fract)); | ||||
| 
 | ||||
| 	if (0. <= H && H < 1.) | ||||
| 		RGB = (rgb){.r = V, .g = T, .b = P}; | ||||
| 	else if (1. <= H && H < 2.) | ||||
| 		RGB = (rgb){.r = Q, .g = V, .b = P}; | ||||
| 	else if (2. <= H && H < 3.) | ||||
| 		RGB = (rgb){.r = P, .g = V, .b = T}; | ||||
| 	else if (3. <= H && H < 4.) | ||||
| 		RGB = (rgb){.r = P, .g = Q, .b = V}; | ||||
| 	else if (4. <= H && H < 5.) | ||||
| 		RGB = (rgb){.r = T, .g = P, .b = V}; | ||||
| 	else if (5. <= H && H < 6.) | ||||
| 		RGB = (rgb){.r = V, .g = P, .b = Q}; | ||||
| 	else | ||||
| 		RGB = (rgb){.r = 0., .g = 0., .b = 0.}; | ||||
| 
 | ||||
| 	return RGB; | ||||
| } | ||||
|  | ||||
| @ -6,10 +6,10 @@ | ||||
|  * modification, are permitted provided that the following conditions | ||||
|  * are met: | ||||
|  * 1. Redistributions of source code must retain the above copyright | ||||
|  *	notice, this list of conditions and the following disclaimer. | ||||
|  *    notice, this list of conditions and the following disclaimer. | ||||
|  * 2. Redistributions in binary form must reproduce the above copyright | ||||
|  *	notice, this list of conditions and the following disclaimer in the | ||||
|  *	documentation and/or other materials provided with the distribution. | ||||
|  *    notice, this list of conditions and the following disclaimer in the | ||||
|  *    documentation and/or other materials provided with the distribution. | ||||
|  * | ||||
|  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | ||||
|  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||
| @ -65,7 +65,6 @@ struct Note { | ||||
| 	int			w;			/* Width of the key, in pixels. */ | ||||
| 	int			h;			/* Height of the key, in pixels. */ | ||||
| 	int			white;			/* 1 if key is white; 0 otherwise. */ | ||||
| 	int			velocity; | ||||
| }; | ||||
| 
 | ||||
| struct _PianoKeyboard | ||||
| @ -79,7 +78,6 @@ struct _PianoKeyboard | ||||
| 	int			note_being_pressed_using_mouse; | ||||
| 	int			min_note; | ||||
| 	int			max_note; | ||||
| 	int			current_velocity; | ||||
| 	volatile struct Note 	notes[NNOTES]; | ||||
| 	/* Table used to translate from PC keyboard character to MIDI note number. */ | ||||
| 	GArray			*key_bindings; | ||||
| @ -90,33 +88,16 @@ struct _PianoKeyboardClass | ||||
| 	GtkDrawingAreaClass	parent_class; | ||||
| }; | ||||
| 
 | ||||
| typedef struct { | ||||
| 	double r; | ||||
| 	double g; | ||||
| 	double b; | ||||
| } rgb; | ||||
| 
 | ||||
| typedef struct { | ||||
| 	double h; | ||||
| 	double s; | ||||
| 	double v; | ||||
| } hsv; | ||||
| 
 | ||||
| GType		piano_keyboard_get_type		(void) G_GNUC_CONST; | ||||
| GtkWidget*	piano_keyboard_new		(void); | ||||
| void		piano_keyboard_sustain_press	(PianoKeyboard *pk); | ||||
| void		piano_keyboard_sustain_release	(PianoKeyboard *pk); | ||||
| void		piano_keyboard_set_note_on	(PianoKeyboard *pk, int note, int vel); | ||||
| void		piano_keyboard_set_note_on	(PianoKeyboard *pk, int note); | ||||
| void		piano_keyboard_set_note_off	(PianoKeyboard *pk, int note); | ||||
| void		piano_keyboard_set_keyboard_cue	(PianoKeyboard *pk, int enabled); | ||||
| void		piano_keyboard_set_octave (PianoKeyboard *pk, int octave); | ||||
| gboolean	piano_keyboard_set_keyboard_layout (PianoKeyboard *pk, const char *layout); | ||||
| void		piano_keyboard_enable_all_midi_notes(PianoKeyboard* pk); | ||||
| void		piano_keyboard_draw_white_key (GtkWidget *widget, int x, int y, int w, int h, int pressed, int val); | ||||
| void		piano_keyboard_draw_black_key (GtkWidget *widget, int x, int y, int w, int h, int pressed, int val); | ||||
| void		piano_keyboard_draw_pressed (cairo_t *c, int x, int y, int w, int h, int val); | ||||
| void		piano_keyboard_draw_key_shadow (cairo_t *c, int x, int y, int w, int h); | ||||
| rgb			hsv2rgb(hsv HSV); | ||||
| 
 | ||||
| G_END_DECLS | ||||
| 
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user