📄 piano.c
字号:
/*================================================================== * piano.c - piano widget * * Smurf Sound Font Editor * Copyright (C) 1999-2001 Josh Green * * 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 or point your web browser to http://www.gnu.org. * * To contact the author of this program: * Email: Josh Green <jgreen@users.sourceforge.net> * Smurf homepage: http://smurf.sourceforge.net *==================================================================*/#include <stdio.h>#include <gtk/gtkmain.h>#include <gtk/gtksignal.h>#include "piano.h"/* Forward declarations */static void piano_class_init (PianoClass * klass);static void piano_init (Piano * piano);static void piano_destroy (GtkObject * object);static void piano_realize (GtkWidget * widget);static void piano_size_request (GtkWidget * widget, GtkRequisition * requisition);static void piano_size_allocate (GtkWidget * widget, GtkAllocation * allocation);static gint piano_expose (GtkWidget * widget, GdkEventExpose * event);static gint piano_button_press (GtkWidget * widget, GdkEventButton * event);static gint piano_button_release (GtkWidget * widget, GdkEventButton * event);static gint piano_motion_notify (GtkWidget * widget, GdkEventMotion * event);static void piano_update_mouse (Piano * piano, gint x, gint y);#define POFSY 0static struct{ guint8 selx; guint8 dispx; gboolean white; /* white key or black key? */}keyinfo[12] = { {6, 2, TRUE}, {11, 7, FALSE}, {15, 11, TRUE}, {20, 16, FALSE}, {26, 20, TRUE}, {33, 29, TRUE}, {38, 34, FALSE}, {42, 38, TRUE}, {47, 43, FALSE}, {51, 47, TRUE}, {56, 52, FALSE}, {62, 56, TRUE}};static GtkWidgetClass *parent_class = NULL;guintpiano_get_type (void){ static guint piano_type = 0; if (!piano_type) { GtkTypeInfo piano_info = { "Piano", sizeof (Piano), sizeof (PianoClass), (GtkClassInitFunc) piano_class_init, (GtkObjectInitFunc) piano_init, (GtkArgSetFunc) NULL, (GtkArgGetFunc) NULL, }; piano_type = gtk_type_unique (gtk_widget_get_type (), &piano_info); } return piano_type;}enum{ NOTE_ON, NOTE_OFF, DUMMY_SIGNAL /* used to count signals */};static gint piano_signals[DUMMY_SIGNAL] = { 0 };static voidpiano_class_init (PianoClass * klass){ GtkObjectClass *object_class; GtkWidgetClass *widget_class; object_class = (GtkObjectClass *) klass; widget_class = (GtkWidgetClass *) klass; parent_class = gtk_type_class (gtk_widget_get_type ()); piano_signals[NOTE_ON] = gtk_signal_new ("note-on", GTK_RUN_FIRST, object_class->type, GTK_SIGNAL_OFFSET (PianoClass, note_on), gtk_marshal_NONE__UINT, GTK_TYPE_NONE, 1, GTK_TYPE_UINT); piano_signals[NOTE_OFF] = gtk_signal_new ("note-off", GTK_RUN_FIRST, object_class->type, GTK_SIGNAL_OFFSET (PianoClass, note_off), gtk_marshal_NONE__UINT, GTK_TYPE_NONE, 1, GTK_TYPE_UINT); gtk_object_class_add_signals (object_class, piano_signals, DUMMY_SIGNAL); klass->note_on = NULL; klass->note_off = NULL; object_class->destroy = piano_destroy; widget_class->realize = piano_realize; widget_class->expose_event = piano_expose; widget_class->size_request = piano_size_request; widget_class->size_allocate = piano_size_allocate; widget_class->button_press_event = piano_button_press; widget_class->button_release_event = piano_button_release; widget_class->motion_notify_event = piano_motion_notify;}/* ----------------------------------------------- initialize piano widget Draws piano pixmap and black/white (un)selected state pixmaps Sets variables to default states----------------------------------------------- */static voidpiano_init (Piano * piano){ piano->key_mouse = 255; /* no key selected with mouse */ piano->key_lospan = 255; /* no lo span indicator */ piano->key_hispan = 255; /* no high span indicator */ piano->key_root = 255; /* no root key indicator */}GtkWidget *piano_new (gboolean * selkeys){ Piano *piano; piano = gtk_type_new (piano_get_type ()); piano->selkeys = selkeys; return GTK_WIDGET (piano);}/* draws specified key in its "on" state */voidpiano_note_on (Piano * piano, guint8 keynum){ gint xval, mod; GdkRectangle uparea; /* update area rectangle */ g_return_if_fail (piano != NULL); g_return_if_fail (IS_PIANO (piano)); g_return_if_fail (keynum < 128); if (piano->selkeys[keynum]) return; /* already selected? */ piano->selkeys[keynum] = TRUE; mod = keynum % 12; xval = keynum / 12 * 63 + keyinfo[mod].dispx; if (keyinfo[mod].white) { gdk_draw_pixmap (piano->keyb_pm, piano->widget.style->fg_gc[GTK_WIDGET_STATE (&piano->widget)], piano->selw_pm, 0, 0, xval - 1, 39 + POFSY, 8, 8); uparea.x = xval - 1; uparea.y = 39 + POFSY; uparea.width = 8; } else { gdk_draw_pixmap (piano->keyb_pm, piano->widget.style->fg_gc[GTK_WIDGET_STATE (&piano->widget)], piano->selb_pm, 0, 0, xval, 20 + POFSY, 5, 8); uparea.x = xval; uparea.y = 20 + POFSY; uparea.width = 5; } uparea.height = 8; gtk_widget_draw (&piano->widget, &uparea);}/* draws specified key in its "released" state */voidpiano_note_off (Piano * piano, guint8 keynum){ gint xval, mod; GdkRectangle uparea; /* update area */ g_return_if_fail (piano != NULL); g_return_if_fail (IS_PIANO (piano)); g_return_if_fail (keynum < 128); if (!piano->selkeys[keynum]) return; /* already unselected? */ piano->selkeys[keynum] = FALSE; mod = keynum % 12; xval = keynum / 12 * 63 + keyinfo[mod].dispx; if (keyinfo[mod].white) { gdk_draw_pixmap (piano->keyb_pm, piano->widget.style->fg_gc[GTK_WIDGET_STATE (&piano->widget)], piano->unsw_pm, 0, 0, xval - 1, 39 + POFSY, 8, 8); uparea.x = xval - 1; uparea.y = 39 + POFSY; uparea.width = 8; } else { gdk_draw_pixmap (piano->keyb_pm, piano->widget.style->fg_gc[GTK_WIDGET_STATE (&piano->widget)], piano->unsb_pm, 0, 0, xval, 20 + POFSY, 5, 8); uparea.x = xval; uparea.y = 20 + POFSY; uparea.width = 5; } uparea.height = 8; gtk_widget_draw (&piano->widget, &uparea);}/* converts a key number to x position in pixels to center of key */gintpiano_key_to_xpos (guint8 keynum){ gint mod, xval; if (keynum > 127) keynum = 127; mod = keynum % 12; xval = keynum / 12 * 63 + keyinfo[mod].dispx; if (keyinfo[mod].white) xval += 2; else xval += 2; /* slight adjustments for adjacent white keys, looks like center */ if (mod == 4 || mod == 11) xval++; else if (mod == 5 || mod == 0) xval--; return (xval);}/* converts a pixel x position to key number */guint8piano_xpos_to_key (gint xpos){ gint xval, i; guint8 keynum; xval = xpos % 63; /* pixel offset into keyboard octave */ for (i = 0; i < 12; i++) /* loop through key selection offsets */ if (xval <= keyinfo[i].selx) break; /* is offset within key select */ keynum = xpos / 63 * 12 + i; /* calc key number */ if (keynum > 127) keynum = 127; return (keynum);}static voidpiano_destroy (GtkObject * object){ Piano *piano; g_return_if_fail (object != NULL); g_return_if_fail (IS_PIANO (object)); piano = PIANO (object); gdk_pixmap_unref (piano->keyb_pm); gdk_pixmap_unref (piano->selw_pm); gdk_pixmap_unref (piano->unsw_pm); gdk_pixmap_unref (piano->selb_pm); gdk_pixmap_unref (piano->unsb_pm); gdk_gc_unref (piano->shadowgc); gdk_color_free (&piano->shadclr); if (GTK_OBJECT_CLASS (parent_class)->destroy) (*GTK_OBJECT_CLASS (parent_class)->destroy) (object);}static voidpiano_realize (GtkWidget * widget){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -