summaryrefslogtreecommitdiff
path: root/muse2/muse/midiedit
diff options
context:
space:
mode:
authorRobert Jonsson <spamatica@gmail.com>2010-10-13 19:34:22 +0000
committerRobert Jonsson <spamatica@gmail.com>2010-10-13 19:34:22 +0000
commit8a2c2824a59d7644e13bc52c9a0ecbd641f21f95 (patch)
tree064ad3f2bf8daab0ad27b128abd86a9bbdb1e496 /muse2/muse/midiedit
parenta27706d9629e8b592cca4659f865b70adef24e6d (diff)
new branch muse2, first checkin
Diffstat (limited to 'muse2/muse/midiedit')
-rw-r--r--muse2/muse/midiedit/Makefile.am36
-rw-r--r--muse2/muse/midiedit/Makefile.in636
-rw-r--r--muse2/muse/midiedit/cmd.h26
-rw-r--r--muse2/muse/midiedit/dcanvas.cpp1291
-rw-r--r--muse2/muse/midiedit/dcanvas.h93
-rw-r--r--muse2/muse/midiedit/dlist.cpp754
-rw-r--r--muse2/muse/midiedit/dlist.h105
-rw-r--r--muse2/muse/midiedit/drumedit.cpp1167
-rw-r--r--muse2/muse/midiedit/drumedit.h151
-rw-r--r--muse2/muse/midiedit/drummap.cpp503
-rw-r--r--muse2/muse/midiedit/drummap.h47
-rw-r--r--muse2/muse/midiedit/ecanvas.cpp363
-rw-r--r--muse2/muse/midiedit/ecanvas.h87
-rw-r--r--muse2/muse/midiedit/piano.cpp557
-rw-r--r--muse2/muse/midiedit/piano.h63
-rw-r--r--muse2/muse/midiedit/pianoroll.cpp1107
-rw-r--r--muse2/muse/midiedit/pianoroll.h146
-rw-r--r--muse2/muse/midiedit/prcanvas.cpp1695
-rw-r--r--muse2/muse/midiedit/prcanvas.h113
-rw-r--r--muse2/muse/midiedit/quantconfig.cpp59
-rw-r--r--muse2/muse/midiedit/quantconfig.h32
21 files changed, 9031 insertions, 0 deletions
diff --git a/muse2/muse/midiedit/Makefile.am b/muse2/muse/midiedit/Makefile.am
new file mode 100644
index 00000000..e817dc99
--- /dev/null
+++ b/muse2/muse/midiedit/Makefile.am
@@ -0,0 +1,36 @@
+include $(top_srcdir)/common.am
+
+if PCH
+AM_CXXFLAGS += -include $(top_srcdir)/all.h
+endif
+
+noinst_LIBRARIES = libmidiedit.a
+
+if PCH
+AM_CXXFLAGS += -include $(top_srcdir)/all-pic.h -DINSTPREFIX=\"$(prefix)\"
+else
+AM_CXXFLAGS += -DINSTPREFIX=\"$(prefix)\"
+endif
+
+dist_libmidiedit_a_SOURCES = \
+ drummap.cpp drummap.h \
+ cmd.h \
+ pianoroll.cpp pianoroll.h \
+ piano.cpp piano.h \
+ prcanvas.cpp prcanvas.h \
+ quantconfig.cpp quantconfig.h \
+ drumedit.cpp drumedit.h \
+ dlist.cpp dlist.h \
+ dcanvas.cpp dcanvas.h \
+ ecanvas.cpp ecanvas.h
+
+nodist_libmidiedit_a_SOURCES = \
+ moc_pianoroll.cpp \
+ moc_piano.cpp \
+ moc_prcanvas.cpp \
+ moc_quantconfig.cpp \
+ moc_drumedit.cpp \
+ moc_dlist.cpp \
+ moc_dcanvas.cpp \
+ moc_ecanvas.cpp
+
diff --git a/muse2/muse/midiedit/Makefile.in b/muse2/muse/midiedit/Makefile.in
new file mode 100644
index 00000000..01425ebc
--- /dev/null
+++ b/muse2/muse/midiedit/Makefile.in
@@ -0,0 +1,636 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
+ $(top_srcdir)/common.am
+@PCH_TRUE@am__append_1 = -include $(top_srcdir)/all.h -include \
+@PCH_TRUE@ $(top_srcdir)/all-pic.h -DINSTPREFIX=\"$(prefix)\"
+@PCH_FALSE@am__append_2 = -DINSTPREFIX=\"$(prefix)\"
+subdir = muse/midiedit
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/aclocal-include.m4 \
+ $(top_srcdir)/m4/alsa.m4 $(top_srcdir)/m4/docbook.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LIBRARIES = $(noinst_LIBRARIES)
+ARFLAGS = cru
+libmidiedit_a_AR = $(AR) $(ARFLAGS)
+libmidiedit_a_LIBADD =
+dist_libmidiedit_a_OBJECTS = drummap.$(OBJEXT) pianoroll.$(OBJEXT) \
+ piano.$(OBJEXT) prcanvas.$(OBJEXT) quantconfig.$(OBJEXT) \
+ drumedit.$(OBJEXT) dlist.$(OBJEXT) dcanvas.$(OBJEXT) \
+ ecanvas.$(OBJEXT)
+nodist_libmidiedit_a_OBJECTS = moc_pianoroll.$(OBJEXT) \
+ moc_piano.$(OBJEXT) moc_prcanvas.$(OBJEXT) \
+ moc_quantconfig.$(OBJEXT) moc_drumedit.$(OBJEXT) \
+ moc_dlist.$(OBJEXT) moc_dcanvas.$(OBJEXT) \
+ moc_ecanvas.$(OBJEXT)
+libmidiedit_a_OBJECTS = $(dist_libmidiedit_a_OBJECTS) \
+ $(nodist_libmidiedit_a_OBJECTS)
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(dist_libmidiedit_a_SOURCES) \
+ $(nodist_libmidiedit_a_SOURCES)
+DIST_SOURCES = $(dist_libmidiedit_a_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALSA_CFLAGS = @ALSA_CFLAGS@
+ALSA_LIBS = @ALSA_LIBS@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DOCBOOKSTYLE = @DOCBOOKSTYLE@
+DOCBOOKTARGETS = @DOCBOOKTARGETS@
+DOT = @DOT@
+DOTPATH = @DOTPATH@
+DOXYGEN = @DOXYGEN@
+DOXYGEN_TREEVIEW = @DOXYGEN_TREEVIEW@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FLUIDSYNTHDIRS = @FLUIDSYNTHDIRS@
+FST_CFLAGS = @FST_CFLAGS@
+FST_LIBS = @FST_LIBS@
+Fluidsynth_CFLAGS = @Fluidsynth_CFLAGS@
+Fluidsynth_LIBS = @Fluidsynth_LIBS@
+GIVERTCAP = @GIVERTCAP@
+GREP = @GREP@
+HAVEDOT = @HAVEDOT@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+JACK_CFLAGS = @JACK_CFLAGS@
+JACK_LIBS = @JACK_LIBS@
+JADE = @JADE@
+LASH_CFLAGS = @LASH_CFLAGS@
+LASH_LIBS = @LASH_LIBS@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LO_CFLAGS = @LO_CFLAGS@
+LO_LIBS = @LO_LIBS@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+MUSECXXFLAGS = @MUSECXXFLAGS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NSGMLS = @NSGMLS@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PCH = @PCH@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_INCLUDES = @PYTHON_INCLUDES@
+PYTHON_LIB = @PYTHON_LIB@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+QTDIR_BIN = @QTDIR_BIN@
+QTDIR_INC = @QTDIR_INC@
+QT_LIBS = @QT_LIBS@
+RANLIB = @RANLIB@
+SAMPLERATE_CFLAGS = @SAMPLERATE_CFLAGS@
+SAMPLERATE_LIBS = @SAMPLERATE_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNDFILE_CFLAGS = @SNDFILE_CFLAGS@
+SNDFILE_LIBS = @SNDFILE_LIBS@
+STRIP = @STRIP@
+SUIDBUILD = @SUIDBUILD@
+SUIDINSTALL = @SUIDINSTALL@
+USE_SSE = @USE_SSE@
+UUID_CFLAGS = @UUID_CFLAGS@
+UUID_LIBS = @UUID_LIBS@
+VERSION = @VERSION@
+XMKMF = @XMKMF@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+have_docbook = @have_docbook@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+synth_fluid = @synth_fluid@
+synth_fluidsynth = @synth_fluidsynth@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+AM_CXXFLAGS = $(MUSECXXFLAGS) -I.. -I$(top_srcdir)/synti \
+ -I$(top_srcdir)/muse/widgets -DQT_SHARED -DQT_THREAD_SUPPORT \
+ -DQT_PLUGIN $(QTDIR_INC) -DQT3_SUPPORT $(am__append_1) \
+ $(am__append_2)
+AM_CPPFLAGS =
+MOC = $(QTDIR_BIN)/moc
+#UIC = $(QTDIR_BIN)/uic3
+UIC = /usr/bin/uic3
+UIFILES = $(wildcard *.ui)
+MOCFILES = $(shell for h in $(filter %.h,$(SOURCES)); do \
+ if grep -q Q_OBJECT $$h; then \
+ echo $$h | sed "s/\(.*\)\.h/moc_\1.cpp/"; \
+ fi; \
+ done)
+
+BUILT_SOURCES = $(MOCFILES) $(UIFILES:%.ui=%.h)
+MOSTLYCLEANFILES = $(MOCFILES) $(UIFILES:%.ui=%.h)
+SUFFIXES = .ui .h.gch
+noinst_LIBRARIES = libmidiedit.a
+dist_libmidiedit_a_SOURCES = \
+ drummap.cpp drummap.h \
+ cmd.h \
+ pianoroll.cpp pianoroll.h \
+ piano.cpp piano.h \
+ prcanvas.cpp prcanvas.h \
+ quantconfig.cpp quantconfig.h \
+ drumedit.cpp drumedit.h \
+ dlist.cpp dlist.h \
+ dcanvas.cpp dcanvas.h \
+ ecanvas.cpp ecanvas.h
+
+nodist_libmidiedit_a_SOURCES = \
+ moc_pianoroll.cpp \
+ moc_piano.cpp \
+ moc_prcanvas.cpp \
+ moc_quantconfig.cpp \
+ moc_drumedit.cpp \
+ moc_dlist.cpp \
+ moc_dcanvas.cpp \
+ moc_ecanvas.cpp
+
+all: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) all-am
+
+.SUFFIXES:
+.SUFFIXES: .ui .h.gch .cpp .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/common.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu muse/midiedit/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu muse/midiedit/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLIBRARIES:
+ -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+libmidiedit.a: $(libmidiedit_a_OBJECTS) $(libmidiedit_a_DEPENDENCIES)
+ -rm -f libmidiedit.a
+ $(libmidiedit_a_AR) libmidiedit.a $(libmidiedit_a_OBJECTS) $(libmidiedit_a_LIBADD)
+ $(RANLIB) libmidiedit.a
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dcanvas.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dlist.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drumedit.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drummap.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ecanvas.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/moc_dcanvas.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/moc_dlist.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/moc_drumedit.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/moc_ecanvas.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/moc_piano.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/moc_pianoroll.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/moc_prcanvas.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/moc_quantconfig.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/piano.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pianoroll.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/prcanvas.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/quantconfig.Po@am__quote@
+
+.cpp.o:
+@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $<
+
+.cpp.obj:
+@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.cpp.lo:
+@am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) check-am
+all-am: Makefile $(LIBRARIES)
+installdirs:
+install: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+ -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+ -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: all check install install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLIBRARIES ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am
+
+
+de:
+ @for base in $(MOCFILES); do echo -e "\t$${base}.cpp $${base}.h \\"; done
+
+nde:
+ @for base in $(MOCFILES); do echo -e "\tmoc_$${base}.cpp \\"; done
+
+.ui.o: %.h
+ $(UIC) -L $(top_srcdir)/muse/widgets -o $*.cpp -impl $*.h $*.ui
+ $(MOC) $*.h >> $*.cpp
+ $(CXXCOMPILE) -c $*.cpp -o $*.o
+ $(RM) $*.cpp moc_$*.cpp moc_$*.o
+
+.ui.lo: %.h
+ $(UIC) -L $(top_srcdir)/muse/widgets -o $*.cpp -impl $*.h $*.ui
+ $(MOC) $*.h >> $*.cpp
+ $(LTCXXCOMPILE) -c $*.cpp -o $*.lo
+ $(RM) $*.cpp moc_$*.cpp moc_$*.lo moc_$*.o
+
+moc_%.cpp: %.h
+ $(MOC) $< -o $@
+
+%.h: %.ui
+ $(UIC) -o $@ $<
+# $(UIC) -L $(top_srcdir)/muse/widgets -o $@ $<
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/muse2/muse/midiedit/cmd.h b/muse2/muse/midiedit/cmd.h
new file mode 100644
index 00000000..abbcdcf3
--- /dev/null
+++ b/muse2/muse/midiedit/cmd.h
@@ -0,0 +1,26 @@
+//=========================================================
+// MusE
+// Linux Music Editor
+// $Id: cmd.h,v 1.1.1.1 2003/10/27 18:52:20 wschweer Exp $
+// (C) Copyright 2000 Werner Schweer (ws@seh.de)
+//=========================================================
+
+#ifndef __CMD_H__
+#define __CMD_H__
+
+#define CMD_LEFT 0
+#define CMD_RIGHT 1
+#define CMD_INSERT 2
+#define CMD_DELETE 3
+#define CMD_1 4
+#define CMD_2 5
+#define CMD_3 6
+#define CMD_4 7
+#define CMD_5 8
+#define CMD_6 9
+#define CMD_7 10
+#define CMD_T 11
+#define CMD_period 12
+
+#endif
+
diff --git a/muse2/muse/midiedit/dcanvas.cpp b/muse2/muse/midiedit/dcanvas.cpp
new file mode 100644
index 00000000..65138bb4
--- /dev/null
+++ b/muse2/muse/midiedit/dcanvas.cpp
@@ -0,0 +1,1291 @@
+//=========================================================
+// MusE
+// Linux Music Editor
+// $Id: dcanvas.cpp,v 1.16.2.10 2009/10/15 22:45:50 terminator356 Exp $
+// (C) Copyright 1999 Werner Schweer (ws@seh.de)
+//=========================================================
+
+#include <qpainter.h>
+#include <qapplication.h>
+#include <qclipboard.h>
+#include <q3dragobject.h>
+//Added by qt3to4:
+#include <QDragLeaveEvent>
+#include <Q3PointArray>
+#include <Q3CString>
+#include <QDragEnterEvent>
+#include <QDragMoveEvent>
+#include <QDropEvent>
+#include <QResizeEvent>
+
+#include <stdio.h>
+#include <values.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+
+#include "dcanvas.h"
+#include "midieditor.h"
+#include "drummap.h"
+#include "event.h"
+#include "mpevent.h"
+#include "xml.h"
+#include "globals.h"
+#include "midiport.h"
+#include "audio.h"
+#include "velocity.h"
+
+#define CARET 10
+#define CARET2 5
+
+//---------------------------------------------------------
+// DEvent
+//---------------------------------------------------------
+
+DEvent::DEvent(Event e, Part* p)
+ : CItem(e, p)
+ {
+ int instr = e.pitch();
+ int y = instr * TH + TH/2;
+ int tick = e.tick() + p->tick();
+ setPos(QPoint(tick, y));
+ setBBox(QRect(-CARET2, -CARET2, CARET, CARET));
+ }
+
+//---------------------------------------------------------
+// addItem
+//---------------------------------------------------------
+
+void DrumCanvas::addItem(Part* part, Event& event)
+ {
+ if (signed(event.tick())<0) {
+ printf("ERROR: trying to add event before current part!\n");
+ return;
+ }
+
+ DEvent* ev = new DEvent(event, part);
+ items.add(ev);
+
+ int diff = event.endTick()-part->lenTick();
+ if (diff > 0) {// too short part? extend it
+ //printf("addItem - this code should not be run!\n");
+ //Part* newPart = part->clone();
+ //newPart->setLenTick(newPart->lenTick()+diff);
+ //audio->msgChangePart(part, newPart,false);
+ //part = newPart;
+ part->setLenTick(part->lenTick()+diff);
+ }
+ }
+
+//---------------------------------------------------------
+// DrumCanvas
+//---------------------------------------------------------
+
+DrumCanvas::DrumCanvas(MidiEditor* pr, QWidget* parent, int sx,
+ int sy, const char* name)
+ : EventCanvas(pr, parent, sx, sy, name)
+ {
+ setVirt(false);
+ songChanged(SC_TRACK_INSERTED);
+ }
+
+//---------------------------------------------------------
+// moveCanvasItems
+//---------------------------------------------------------
+
+void DrumCanvas::moveCanvasItems(CItemList& items, int dp, int dx, DragType dtype, int* pflags)
+{
+ if(editor->parts()->empty())
+ return;
+
+ PartsToChangeMap parts2change;
+
+ int modified = 0;
+ for(iPart ip = editor->parts()->begin(); ip != editor->parts()->end(); ++ip)
+ {
+ Part* part = ip->second;
+ if(!part)
+ continue;
+
+ int npartoffset = 0;
+ for(iCItem ici = items.begin(); ici != items.end(); ++ici)
+ {
+ CItem* ci = ici->second;
+ if(ci->part() != part)
+ continue;
+
+ int x = ci->pos().x() + dx;
+ int y = pitch2y(y2pitch(ci->pos().y()) + dp);
+ QPoint newpos = raster(QPoint(x, y));
+
+ // Test moving the item...
+ DEvent* nevent = (DEvent*) ci;
+ Event event = nevent->event();
+ x = newpos.x();
+ if(x < 0)
+ x = 0;
+ int ntick = editor->rasterVal(x) - part->tick();
+ if(ntick < 0)
+ ntick = 0;
+ int diff = ntick + event.lenTick() - part->lenTick();
+
+ // If moving the item would require a new part size...
+ if(diff > npartoffset)
+ npartoffset = diff;
+ }
+
+ if(npartoffset > 0)
+ {
+ // Create new part...
+ // if there are several events that are moved outside the part, it will be recreated for each
+ // so the part _in_ the event will not be valid, ask the authority.
+// Part* newPart = part->clone();
+ //Part* newPart = Canvas::part()->clone();
+
+// newPart->setLenTick(newPart->lenTick() + npartoffset);
+ //audio->msgChangePart(part, newPart,false);
+
+// modified = SC_PART_MODIFIED;
+
+ // BUG FIX: #1650953
+ // Added by T356.
+ // Fixes posted "select and drag past end of part - crashing" bug
+// for(iPart ip = editor->parts()->begin(); ip != editor->parts()->end(); ++ip)
+// {
+// if(ip->second == part)
+// {
+// editor->parts()->erase(ip);
+// break;
+// }
+// }
+
+// editor->parts()->add(newPart);
+// audio->msgChangePart(part, newPart,false);
+
+// if(parts2change.find(part) == parts2change.end())
+// parts2change.insert(std::pair<Part*, Part*> (part, newPart));
+ iPartToChange ip2c = parts2change.find(part);
+ if(ip2c == parts2change.end())
+ {
+ PartToChange p2c = {0, npartoffset};
+ parts2change.insert(std::pair<Part*, PartToChange> (part, p2c));
+ }
+ else
+ ip2c->second.xdiff = npartoffset;
+
+
+ //part = newPart; // reassign
+ //item->setPart(part);
+ //item->setEvent(newEvent);
+ //curPart = part;
+ //curPartId = curPart->sn();
+
+ }
+ }
+
+ for(iPartToChange ip2c = parts2change.begin(); ip2c != parts2change.end(); ++ip2c)
+ {
+ Part* opart = ip2c->first;
+ int diff = ip2c->second.xdiff;
+
+ Part* newPart = opart->clone();
+
+ newPart->setLenTick(newPart->lenTick() + diff);
+
+ modified = SC_PART_MODIFIED;
+
+ // BUG FIX: #1650953
+ // Added by T356.
+ // Fixes posted "select and drag past end of part - crashing" bug
+ for(iPart ip = editor->parts()->begin(); ip != editor->parts()->end(); ++ip)
+ {
+ if(ip->second == opart)
+ {
+ editor->parts()->erase(ip);
+ break;
+ }
+ }
+
+ editor->parts()->add(newPart);
+ // Indicate no undo, and do port controller values but not clone parts.
+ //audio->msgChangePart(opart, newPart, false);
+ audio->msgChangePart(opart, newPart, false, true, false);
+
+ ip2c->second.npart = newPart;
+
+ }
+
+ iPartToChange icp = parts2change.find(curPart);
+ if(icp != parts2change.end())
+ {
+ curPart = icp->second.npart;
+ curPartId = curPart->sn();
+ }
+
+ std::vector< CItem* > doneList;
+ typedef std::vector< CItem* >::iterator iDoneList;
+
+ for(iCItem ici = items.begin(); ici != items.end(); ++ici)
+ {
+ CItem* ci = ici->second;
+
+ // If this item's part is in the parts2change list, change the item's part to the new part.
+ Part* pt = ci->part();
+ iPartToChange ip2c = parts2change.find(pt);
+ if(ip2c != parts2change.end())
+ ci->setPart(ip2c->second.npart);
+
+ int x = ci->pos().x();
+ int y = ci->pos().y();
+ int nx = x + dx;
+ int ny = pitch2y(y2pitch(y) + dp);
+ QPoint newpos = raster(QPoint(nx, ny));
+ selectItem(ci, true);
+
+ iDoneList idl;
+ for(idl = doneList.begin(); idl != doneList.end(); ++idl)
+ // This compares EventBase pointers to see if they're the same...
+ if((*idl)->event() == ci->event())
+ break;
+
+ // Do not process if the event has already been processed (meaning it's an event in a clone part)...
+ //if(moveItem(ci, newpos, dtype))
+ if(idl != doneList.end())
+ // Just move the canvas item.
+ ci->move(newpos);
+ else
+ {
+ // Currently moveItem always returns true.
+ if(moveItem(ci, newpos, dtype))
+ {
+ // Add the canvas item to the list of done items.
+ doneList.push_back(ci);
+ // Move the canvas item.
+ ci->move(newpos);
+ }
+ }
+
+ if(moving.size() == 1) {
+ itemReleased(curItem, newpos);
+ }
+ if(dtype == MOVE_COPY || dtype == MOVE_CLONE)
+ selectItem(ci, false);
+ }
+
+ if(pflags)
+ *pflags = modified;
+}
+
+//---------------------------------------------------------
+// moveItem
+//---------------------------------------------------------
+
+// Changed by T356.
+//bool DrumCanvas::moveItem(CItem* item, const QPoint& pos, DragType dtype, int* pflags)
+bool DrumCanvas::moveItem(CItem* item, const QPoint& pos, DragType dtype)
+ {
+ DEvent* nevent = (DEvent*) item;
+
+ // Changed by T356.
+ //MidiPart* part = (MidiPart*)Canvas::part(); // part can be dynamically recreated, ask the authority
+ MidiPart* part = (MidiPart*)nevent->part();
+
+ Event event = nevent->event();
+ int x = pos.x();
+ if (x < 0)
+ x = 0;
+ int ntick = editor->rasterVal(x) - part->tick();
+ if (ntick < 0)
+ ntick = 0;
+ int npitch = y2pitch(pos.y());
+ Event newEvent = event.clone();
+
+ newEvent.setPitch(npitch);
+ newEvent.setTick(ntick);
+
+ // Removed by T356.
+ /*
+ // Added by T356.
+ int modified = 0;
+ //song->startUndo();
+ int diff = newEvent.endTick()-part->lenTick();
+ if (diff > 0) // too short part? extend it
+ {
+ // if there are several events that are moved outside the part, it will be recreated for each
+ // so the part _in_ the event will not be valid, ask the authority.
+ //Part* newPart = part->clone();
+ MidiPart* newPart = (MidiPart*)Canvas::part()->clone();
+ newPart->setLenTick(newPart->lenTick()+diff);
+ audio->msgChangePart(Canvas::part(), newPart,false);
+
+ modified = SC_PART_MODIFIED;
+ part = newPart; // reassign
+ for(iPart i = editor->parts()->begin(); i != editor->parts()->end(); ++i)
+ {
+ if(i->second == Canvas::part())
+ {
+ editor->parts()->erase(i);
+ break;
+ }
+ }
+ editor->parts()->add(part);
+ item->setPart(part);
+ item->setEvent(newEvent);
+ curPart = part;
+ curPartId = curPart->sn();
+ }
+ */
+
+ // Added by T356.
+ // msgAddEvent and msgChangeEvent (below) will set these, but set them here first?
+ //item->setPart(part);
+ item->setEvent(newEvent);
+
+ // Added by T356.
+ if(((int)newEvent.endTick() - (int)part->lenTick()) > 0)
+ printf("DrumCanvas::moveItem Error! New event end:%d exceeds length:%d of part:%s\n", newEvent.endTick(), part->lenTick(), part->name().latin1());
+
+ if (dtype == MOVE_COPY || dtype == MOVE_CLONE) {
+ // Indicate no undo, and do not do port controller values and clone parts.
+ //audio->msgAddEvent(newEvent, part, false);
+ audio->msgAddEvent(newEvent, part, false, false, false);
+ }
+ else {
+ // Indicate no undo, and do not do port controller values and clone parts.
+ //audio->msgChangeEvent(event, newEvent, part, false);
+ audio->msgChangeEvent(event, newEvent, part, false, false, false);
+ }
+
+ // Removed by T356.
+ //if(pflags)
+ // *pflags = modified;
+
+ return true;
+ }
+
+//---------------------------------------------------------
+// newItem
+//---------------------------------------------------------
+
+CItem* DrumCanvas::newItem(const QPoint& p, int state)
+ {
+ int instr = y2pitch(p.y()); //drumInmap[y2pitch(p.y())];
+ int velo = drumMap[instr].lv4;
+ if (state == Qt::ShiftModifier)
+ velo = drumMap[instr].lv3;
+ else if (state == Qt::ControlModifier)
+ velo = drumMap[instr].lv2;
+ else if (state == (Qt::ControlModifier | Qt::ShiftModifier))
+ velo = drumMap[instr].lv1;
+ int tick = editor->rasterVal(p.x());
+ tick -= curPart->tick();
+ Event e(Note);
+ e.setTick(tick);
+ e.setPitch(instr);
+ e.setVelo(velo);
+ e.setLenTick(drumMap[instr].len);
+ return new DEvent(e, curPart);
+ }
+
+//---------------------------------------------------------
+// resizeItem
+//---------------------------------------------------------
+
+void DrumCanvas::resizeItem(CItem* item, bool)
+ {
+ DEvent* nevent = (DEvent*) item;
+ Event ev = nevent->event();
+ // Indicate do undo, and do not do port controller values and clone parts.
+ //audio->msgDeleteEvent(ev, nevent->part());
+ audio->msgDeleteEvent(ev, nevent->part(), true, false, false);
+ }
+
+//---------------------------------------------------------
+// newItem
+//---------------------------------------------------------
+
+void DrumCanvas::newItem(CItem* item, bool noSnap)
+ {
+ DEvent* nevent = (DEvent*) item;
+ Event event = nevent->event();
+ int x = item->x();
+ if (!noSnap)
+ x = editor->rasterVal(x);
+ event.setTick(x - nevent->part()->tick());
+ //int npitch = drumMap[y2pitch(item->y())].enote;
+ int npitch = event.pitch();
+ event.setPitch(npitch);
+
+ //
+ // check for existing event
+ // if found change command semantic from insert to delete
+ //
+ EventList* el = nevent->part()->events();
+ iEvent lower = el->lower_bound(event.tick());
+ iEvent upper = el->upper_bound(event.tick());
+
+ for (iEvent i = lower; i != upper; ++i) {
+ Event ev = i->second;
+ // Added by T356. Only do notes.
+ if(!ev.isNote())
+ continue;
+
+ if (ev.pitch() == npitch) {
+ // Indicate do undo, and do not do port controller values and clone parts.
+ //audio->msgDeleteEvent(ev, nevent->part());
+ audio->msgDeleteEvent(ev, nevent->part(), true, false, false);
+ return;
+ }
+ }
+
+ // Added by T356.
+ Part* part = nevent->part();
+ song->startUndo();
+ int modified=SC_EVENT_MODIFIED;
+ int diff = event.endTick()-part->lenTick();
+ if (diff > 0) {// too short part? extend it
+ //printf("extend Part!\n");
+ Part* newPart = part->clone();
+ newPart->setLenTick(newPart->lenTick()+diff);
+ // Indicate no undo, and do port controller values but not clone parts.
+ //audio->msgChangePart(part, newPart,false);
+ audio->msgChangePart(part, newPart, false, true, false);
+ modified=modified|SC_PART_MODIFIED;
+ part = newPart; // reassign
+ }
+ // Indicate no undo, and do not do port controller values and clone parts.
+ //audio->msgAddEvent(event, part,false);
+ audio->msgAddEvent(event, part, false, false, false);
+ song->endUndo(modified);
+
+ //audio->msgAddEvent(event, nevent->part());
+ }
+
+//---------------------------------------------------------
+// deleteItem
+//---------------------------------------------------------
+
+bool DrumCanvas::deleteItem(CItem* item)
+ {
+ Event ev = ((DEvent*)item)->event();
+ // Indicate do undo, and do not do port controller values and clone parts.
+ //audio->msgDeleteEvent(ev, ((DEvent*)item)->part());
+ audio->msgDeleteEvent(ev, ((DEvent*)item)->part(), true, false, false);
+ return false;
+ }
+
+//---------------------------------------------------------
+// drawItem
+//---------------------------------------------------------
+
+void DrumCanvas::drawItem(QPainter&p, const CItem*item, const QRect& rect)
+ {
+ DEvent* e = (DEvent*) item;
+ int x = 0, y = 0;
+ x = mapx(item->pos().x());
+ y = mapy(item->pos().y());
+ Q3PointArray pa(4);
+ pa.setPoint(0, x - CARET2, y);
+ pa.setPoint(1, x, y - CARET2);
+ pa.setPoint(2, x + CARET2, y);
+ pa.setPoint(3, x, y + CARET2);
+ QRect r(pa.boundingRect());
+ r = r.intersect(rect);
+ if(!r.isValid())
+ return;
+
+ p.setPen(Qt::black);
+
+ if (e->part() != curPart)
+ {
+ if(item->isMoving())
+ p.setBrush(Qt::gray);
+ else if(item->isSelected())
+ p.setBrush(Qt::black);
+ else
+ p.setBrush(Qt::lightGray);
+ }
+ else if (item->isMoving()) {
+ p.setBrush(Qt::gray);
+ }
+ else if (item->isSelected())
+ {
+ p.setBrush(Qt::black);
+ }
+ else
+ {
+ int velo = e->event().velo();
+ DrumMap* dm = &drumMap[y2pitch(y)]; //Get the drum item
+ QColor color;
+ if (velo < dm->lv1)
+ color.setRgb(240, 240, 255);
+ else if (velo < dm->lv2)
+ color.setRgb(200, 200, 255);
+ else if (velo < dm->lv3)
+ color.setRgb(170, 170, 255);
+ else
+ color.setRgb(0, 0, 255);
+ p.setBrush(color);
+ }
+
+ p.drawPolygon(pa);
+ }
+
+//---------------------------------------------------------
+// drawMoving
+// draws moving items
+//---------------------------------------------------------
+
+void DrumCanvas::drawMoving(QPainter& p, const CItem* item, const QRect& rect)
+ {
+ //if(((DEvent*)item)->part() != curPart)
+ // return;
+ //if(!item->isMoving())
+ // return;
+ Q3PointArray pa(4);
+ QPoint pt = map(item->mp());
+ int x = pt.x();
+ int y = pt.y();
+ pa.setPoint(0, x-CARET2, y + TH/2);
+ pa.setPoint(1, x, y + TH/2+CARET2);
+ pa.setPoint(2, x+CARET2, y + TH/2);
+ pa.setPoint(3, x, y + (TH-CARET)/2);
+ QRect mr(pa.boundingRect());
+ mr = mr.intersect(rect);
+ if(!mr.isValid())
+ return;
+ p.setPen(Qt::black);
+ p.setBrush(Qt::black);
+ p.drawPolygon(pa);
+ }
+
+//---------------------------------------------------------
+// drawCanvas
+//---------------------------------------------------------
+
+extern void drawTickRaster(QPainter& p, int, int, int, int, int);
+
+void DrumCanvas::drawCanvas(QPainter& p, const QRect& rect)
+ {
+ int x = rect.x();
+ int y = rect.y();
+ int w = rect.width();
+ int h = rect.height();
+
+ //---------------------------------------------------
+ // horizontal lines
+ //---------------------------------------------------
+
+ int yy = ((y-1) / TH) * TH + TH;
+ for (; yy < y + h; yy += TH) {
+ p.setPen(Qt::gray);
+ p.drawLine(x, yy, x + w, yy);
+ }
+
+ //---------------------------------------------------
+ // vertical lines
+ //---------------------------------------------------
+
+ drawTickRaster(p, x, y, w, h, editor->raster());
+ }
+
+//---------------------------------------------------------
+// y2pitch
+//---------------------------------------------------------
+
+int DrumCanvas::y2pitch(int y) const
+ {
+ int pitch = y/TH;
+ if (pitch >= DRUM_MAPSIZE)
+ pitch = DRUM_MAPSIZE-1;
+ return pitch;
+ }
+
+//---------------------------------------------------------
+// pitch2y
+//---------------------------------------------------------
+
+int DrumCanvas::pitch2y(int pitch) const
+ {
+ return pitch * TH;
+ }
+
+//---------------------------------------------------------
+// cmd
+//---------------------------------------------------------
+
+void DrumCanvas::cmd(int cmd)
+ {
+ switch(cmd) {
+ case CMD_CUT:
+ copy();
+ song->startUndo();
+ for (iCItem i = items.begin(); i != items.end(); ++i) {
+ if (!i->second->isSelected())
+ continue;
+ DEvent* e = (DEvent*)(i->second);
+ Event event = e->event();
+ // Indicate no undo, and do not do port controller values and clone parts.
+ //audio->msgDeleteEvent(event, e->part(), false);
+ audio->msgDeleteEvent(event, e->part(), false, false, false);
+ }
+ song->endUndo(SC_EVENT_REMOVED);
+ break;
+ case CMD_COPY:
+ copy();
+ break;
+ case CMD_PASTE:
+ paste();
+ break;
+ case CMD_SELECT_ALL: // select all
+ for (iCItem k = items.begin(); k != items.end(); ++k) {
+ if (!k->second->isSelected())
+ selectItem(k->second, true);
+ }
+ break;
+ case CMD_SELECT_NONE: // select none
+ deselectAll();
+ break;
+ case CMD_SELECT_INVERT: // invert selection
+ for (iCItem k = items.begin(); k != items.end(); ++k) {
+ selectItem(k->second, !k->second->isSelected());
+ }
+ break;
+ case CMD_SELECT_ILOOP: // select inside loop
+ for (iCItem k = items.begin(); k != items.end(); ++k) {
+ DEvent* nevent =(DEvent*)(k->second);
+ Part* part = nevent->part();
+ Event event = nevent->event();
+ unsigned tick = event.tick() + part->tick();
+ if (tick < song->lpos() || tick >= song->rpos())
+ selectItem(k->second, false);
+ else
+ selectItem(k->second, true);
+ }
+ break;
+ case CMD_SELECT_OLOOP: // select outside loop
+ for (iCItem k = items.begin(); k != items.end(); ++k) {
+ DEvent* nevent = (DEvent*)(k->second);
+ Part* part = nevent->part();
+ Event event = nevent->event();
+ unsigned tick = event.tick() + part->tick();
+ if (tick < song->lpos() || tick >= song->rpos())
+ selectItem(k->second, true);
+ else
+ selectItem(k->second, false);
+ }
+ break;
+ case CMD_SELECT_PREV_PART: // select previous part
+ {
+ Part* pt = editor->curCanvasPart();
+ Part* newpt = pt;
+ PartList* pl = editor->parts();
+ for(iPart ip = pl->begin(); ip != pl->end(); ++ip)
+ if(ip->second == pt)
+ {
+ if(ip == pl->begin())
+ ip = pl->end();
+ --ip;
+ newpt = ip->second;
+ break;
+ }
+ if(newpt != pt)
+ editor->setCurCanvasPart(newpt);
+ }
+ break;
+ case CMD_SELECT_NEXT_PART: // select next part
+ {
+ Part* pt = editor->curCanvasPart();
+ Part* newpt = pt;
+ PartList* pl = editor->parts();
+ for(iPart ip = pl->begin(); ip != pl->end(); ++ip)
+ if(ip->second == pt)
+ {
+ ++ip;
+ if(ip == pl->end())
+ ip = pl->begin();
+ newpt = ip->second;
+ break;
+ }
+ if(newpt != pt)
+ editor->setCurCanvasPart(newpt);
+ }
+ break;
+ case CMD_DEL:
+ if (selectionSize()) {
+ song->startUndo();
+ for (iCItem i = items.begin(); i != items.end(); ++i) {
+ if (!i->second->isSelected())
+ continue;
+ Event ev = i->second->event();
+ // Indicate no undo, and do not do port controller values and clone parts.
+ //audio->msgDeleteEvent(ev, i->second->part(), false);
+ audio->msgDeleteEvent(ev, i->second->part(), false, false, false);
+ }
+ song->endUndo(SC_EVENT_REMOVED);
+ }
+ return;
+
+ case CMD_SAVE:
+ case CMD_LOAD:
+ printf("DrumCanvas:: cmd not implemented %d\n", cmd);
+ break;
+
+ case CMD_FIXED_LEN: //Set notes to the length specified in the drummap
+ if (!selectionSize())
+ break;
+ song->startUndo();
+ for (iCItem k = items.begin(); k != items.end(); ++k) {
+ if (k->second->isSelected()) {
+ DEvent* devent = (DEvent*)(k->second);
+ Event event = devent->event();
+ Event newEvent = event.clone();
+ newEvent.setLenTick(drumMap[event.pitch()].len);
+ // Indicate no undo, and do not do port controller values and clone parts.
+ //audio->msgChangeEvent(event, newEvent, devent->part() , false);
+ audio->msgChangeEvent(event, newEvent, devent->part(), false, false, false);
+ }
+ }
+ song->endUndo(SC_EVENT_MODIFIED);
+ break;
+ case CMD_LEFT:
+ {
+ int frames = pos[0] - editor->rasterStep(pos[0]);
+ if (frames < 0)
+ frames = 0;
+ Pos p(frames,true);
+ song->setPos(0, p, true, true, true);
+ }
+ break;
+ case CMD_RIGHT:
+ {
+ Pos p(pos[0] + editor->rasterStep(pos[0]), true);
+ song->setPos(0, p, true, true, true);
+ }
+ break;
+ case CMD_MODIFY_VELOCITY:
+ {
+ Velocity w(this);
+ w.setRange(0); //TODO: Make this work! Probably put _to & _toInit in ecanvas instead
+ if (!w.exec())
+ break;
+ int range = w.range(); // all, selected, looped, sel+loop
+ int rate = w.rateVal();
+ int offset = w.offsetVal();
+
+ song->startUndo();
+ for (iCItem k = items.begin(); k != items.end(); ++k) {
+ DEvent* devent = (DEvent*)(k->second);
+ Event event = devent->event();
+ if (event.type() != Note)
+ continue;
+ unsigned tick = event.tick();
+ bool selected = k->second->isSelected();
+ bool inLoop = (tick >= song->lpos()) && (tick < song->rpos());
+
+ if ((range == 0)
+ || (range == 1 && selected)
+ || (range == 2 && inLoop)
+ || (range == 3 && selected && inLoop)) {
+ int velo = event.velo();
+
+ //velo = rate ? (velo * 100) / rate : 64;
+ velo = (velo * rate) / 100;
+ velo += offset;
+
+ if (velo <= 0)
+ velo = 1;
+ if (velo > 127)
+ velo = 127;
+ if (event.velo() != velo) {
+ Event newEvent = event.clone();
+ newEvent.setVelo(velo);
+ // Indicate no undo, and do not do port controller values and clone parts.
+ //audio->msgChangeEvent(event, newEvent, devent->part(), false);
+ audio->msgChangeEvent(event, newEvent, devent->part(), false, false, false);
+ }
+ }
+ }
+ song->endUndo(SC_EVENT_MODIFIED);
+ }
+ break;
+ }
+ updateSelection();
+ redraw();
+ }
+
+//---------------------------------------------------------
+// getTextDrag
+//---------------------------------------------------------
+
+Q3TextDrag* DrumCanvas::getTextDrag(QWidget* parent)
+ {
+ //---------------------------------------------------
+ // generate event list from selected events
+ //---------------------------------------------------
+
+ EventList el;
+ unsigned startTick = MAXINT;
+ for (iCItem i = items.begin(); i != items.end(); ++i) {
+ if (!i->second->isSelected())
+ continue;
+ DEvent* ne = (DEvent*)(i->second);
+ Event e = ne->event();
+ if (startTick == MAXINT)
+ startTick = e.tick();
+ el.add(e);
+ }
+
+ //---------------------------------------------------
+ // write events as XML into tmp file
+ //---------------------------------------------------
+
+ FILE* tmp = tmpfile();
+ if (tmp == 0) {
+ fprintf(stderr, "EventCanvas::copy() fopen failed: %s\n",
+ strerror(errno));
+ return 0;
+ }
+ Xml xml(tmp);
+
+ int level = 0;
+ for (ciEvent e = el.begin(); e != el.end(); ++e)
+ e->second.write(level, xml, -startTick);
+
+ //---------------------------------------------------
+ // read tmp file into QTextDrag Object
+ //---------------------------------------------------
+
+ fflush(tmp);
+ struct stat f_stat;
+ if (fstat(fileno(tmp), &f_stat) == -1) {
+ fprintf(stderr, "EventCanvas::copy() fstat failes:<%s>\n",
+ strerror(errno));
+ fclose(tmp);
+ return 0;
+ }
+ int n = f_stat.st_size;
+ char* fbuf = (char*)mmap(0, n+1, PROT_READ|PROT_WRITE,
+ MAP_PRIVATE, fileno(tmp), 0);
+ fbuf[n] = 0;
+ Q3TextDrag* drag = new Q3TextDrag(QString(fbuf), parent);
+ drag->setSubtype("eventlist");
+ munmap(fbuf, n);
+ fclose(tmp);
+ return drag;
+ }
+
+//---------------------------------------------------------
+// copy
+// cut copy paste
+//---------------------------------------------------------
+
+void DrumCanvas::copy()
+ {
+ Q3TextDrag* drag = getTextDrag(0);
+ if (drag)
+ QApplication::clipboard()->setData(drag, QClipboard::Clipboard);
+ }
+
+//---------------------------------------------------------
+// paste
+//---------------------------------------------------------
+
+int DrumCanvas::pasteAt(const QString& pt, int pos)
+ {
+ const char* p = pt.latin1();
+ Xml xml(p);
+
+ // Added by T356.
+ int modified = SC_EVENT_INSERTED;
+
+ song->startUndo();
+ for (;;) {
+ Xml::Token token = xml.parse();
+ QString tag = xml.s1();
+ switch (token) {
+ case Xml::Error:
+ case Xml::End:
+ //song->endUndo(SC_EVENT_INSERTED); By T356
+ song->endUndo(modified);
+ return pos;
+ case Xml::TagStart:
+ if (tag == "event") {
+ Event e(Note);
+ e.read(xml);
+
+ // Added by T356.
+ int tick = e.tick() + pos - curPart->tick();
+ if (tick<0) {
+ printf("DrumCanvas::pasteAt ERROR: trying to add event before current part!\n");
+ song->endUndo(SC_EVENT_INSERTED);
+ //delete el;
+ return pos;
+ }
+ e.setTick(tick);
+ int diff = e.endTick() - curPart->lenTick();
+ if (diff > 0) {// too short part? extend it
+ Part* newPart = curPart->clone();
+ newPart->setLenTick(newPart->lenTick()+diff);
+ // Indicate no undo, and do port controller values but not clone parts.
+ //audio->msgChangePart(curPart, newPart,false);
+ audio->msgChangePart(curPart, newPart, false, true, false);
+
+ modified=modified|SC_PART_MODIFIED;
+ curPart = newPart; // reassign
+ }
+
+ // Indicate no undo, and do not do port controller values and clone parts.
+ //audio->msgAddEvent(e, curPart, false);
+ audio->msgAddEvent(e, curPart, false, false, false);
+ }
+ else
+ //xml.unknown("EventCanvas::paste"); By T356
+ xml.unknown("DCanvas::pasteAt");
+ break;
+ case Xml::TagEnd:
+ default:
+ break;
+ }
+ }
+ }
+
+//---------------------------------------------------------
+// paste
+// paste events
+//---------------------------------------------------------
+
+void DrumCanvas::paste()
+ {
+// Q3CString subtype("eventlist"); // ddskrjo
+ QString subtype("eventlist");
+ QMimeSource* ms = QApplication::clipboard()->data();
+ QString pt;
+ if (!Q3TextDrag::decode(ms, pt, subtype)) {
+ printf("cannot paste: bad data type\n");
+ return;
+ }
+ pasteAt(pt, song->cpos());
+ }
+
+//---------------------------------------------------------
+// startDrag
+//---------------------------------------------------------
+
+void DrumCanvas::startDrag(CItem* /* item*/, bool copymode)
+ {
+ Q3TextDrag* drag = getTextDrag(this);
+ if (drag) {
+// QApplication::clipboard()->setData(drag, QClipboard::Clipboard);
+
+ if (copymode)
+ drag->dragCopy();
+ else
+ drag->dragMove();
+ }
+ }
+
+//---------------------------------------------------------
+// dragEnterEvent
+//---------------------------------------------------------
+
+void DrumCanvas::dragEnterEvent(QDragEnterEvent* event)
+ {
+ event->accept(Q3TextDrag::canDecode(event));
+ }
+
+//---------------------------------------------------------
+// dragMoveEvent
+//---------------------------------------------------------
+
+void DrumCanvas::dragMoveEvent(QDragMoveEvent*)
+ {
+// printf("drag move %x\n", this);
+ }
+
+//---------------------------------------------------------
+// dragLeaveEvent
+//---------------------------------------------------------
+
+void DrumCanvas::dragLeaveEvent(QDragLeaveEvent*)
+ {
+// printf("drag leave\n");
+ }
+
+//---------------------------------------------------------
+// dropEvent
+//---------------------------------------------------------
+
+void DrumCanvas::viewDropEvent(QDropEvent* event)
+ {
+ QString text;
+ if (event->source() == this) {
+ printf("local DROP\n");
+ return;
+ }
+ if (Q3TextDrag::decode(event, text)) {
+// printf("drop <%s>\n", text.ascii());
+ int x = editor->rasterVal(event->pos().x());
+ if (x < 0)
+ x = 0;
+ pasteAt(text, x);
+ }
+ }
+
+//---------------------------------------------------------
+// keyPressed
+//---------------------------------------------------------
+
+void DrumCanvas::keyPressed(int index, bool)
+ {
+ int port = drumMap[index].port;
+ int channel = drumMap[index].channel;
+ int pitch = drumMap[index].anote;
+
+ // play note:
+ MidiPlayEvent e(0, port, channel, 0x90, pitch, 127);
+ audio->msgPlayMidiEvent(&e);
+ }
+
+//---------------------------------------------------------
+// keyReleased
+//---------------------------------------------------------
+
+void DrumCanvas::keyReleased(int index, bool)
+ {
+ int port = drumMap[index].port;
+ int channel = drumMap[index].channel;
+ int pitch = drumMap[index].anote;
+
+ // release note:
+ MidiPlayEvent e(0, port, channel, 0x90, pitch, 0);
+ audio->msgPlayMidiEvent(&e);
+ }
+
+//---------------------------------------------------------
+// mapChanged
+//---------------------------------------------------------
+
+void DrumCanvas::mapChanged(int spitch, int dpitch)
+ {
+ //TODO: Circumvent undo behaviour, since this isn't really a true change of the events,
+ // but merely a change in pitch because the pitch relates to the order of the dlist.
+ // Right now the sequencer spits out internalError: undoOp without startUndo() if start/stopundo is there, which is misleading
+ // If start/stopundo is there, undo misbehaves since it doesn't undo but messes things up
+ // Other solution: implement a specific undo-event for this (SC_DRUMMAP_MODIFIED or something) which undoes movement of
+ // dlist-items (ml)
+
+ std::vector< std::pair<Part*, Event*> > delete_events;
+ std::vector< std::pair<Part*, Event> > add_events;
+
+ typedef std::vector< std::pair<Part*, Event*> >::iterator idel_ev;
+ typedef std::vector< std::pair<Part*, Event> >::iterator iadd_ev;
+
+ /*
+ class delete_events : public std::vector< Part*, Event* >
+ {
+ public:
+ idel_ev find(Part* p, Event* e)
+ {
+
+ };
+ };
+ class add_events : public std::vector< Part*, Event >
+ {
+ public:
+ iadd_ev find(Part* p, Event& e)
+ {
+
+ };
+ };
+ */
+
+ MidiTrackList* tracks = song->midis();
+ for (ciMidiTrack t = tracks->begin(); t != tracks->end(); t++) {
+ MidiTrack* curTrack = *t;
+ if (curTrack->type() != Track::DRUM)
+ continue;
+
+ MidiPort* mp = &midiPorts[curTrack->outPort()];
+ PartList* parts= curTrack->parts();
+ for (iPart part = parts->begin(); part != parts->end(); ++part) {
+ EventList* events = part->second->events();
+ Part* thePart = part->second;
+ for (iEvent i = events->begin(); i != events->end(); ++i) {
+ Event event = i->second;
+ if(event.type() != Controller && event.type() != Note)
+ continue;
+ int pitch = event.pitch();
+ bool drc = false;
+ // Is it a drum controller event, according to the track port's instrument?
+ if(event.type() == Controller && mp->drumController(event.dataA()))
+ {
+ drc = true;
+ pitch = event.dataA() & 0x7f;
+ }
+
+ if (pitch == spitch) {
+ Event* spitch_event = &(i->second);
+ delete_events.push_back(std::pair<Part*, Event*>(thePart, spitch_event));
+ Event newEvent = spitch_event->clone();
+ if(drc)
+ newEvent.setA((newEvent.dataA() & ~0xff) | dpitch);
+ else
+ newEvent.setPitch(dpitch);
+ add_events.push_back(std::pair<Part*, Event>(thePart, newEvent));
+ }
+ else if (pitch == dpitch) {
+ Event* dpitch_event = &(i->second);
+ delete_events.push_back(std::pair<Part*, Event*>(thePart, dpitch_event));
+ Event newEvent = dpitch_event->clone();
+ if(drc)
+ newEvent.setA((newEvent.dataA() & ~0xff) | spitch);
+ else
+ newEvent.setPitch(spitch);
+ add_events.push_back(std::pair<Part*, Event>(thePart, newEvent));
+ }
+ }
+ }
+ }
+
+ song->startUndo();
+ for (idel_ev i = delete_events.begin(); i != delete_events.end(); i++) {
+ //std::pair<Part*, Event*> pair = *i;
+ //Part* thePart = pair.first;
+ //Event* theEvent = pair.second;
+ Part* thePart = (*i).first;
+ Event* theEvent = (*i).second;
+ // Indicate no undo, and do port controller values but not clone parts.
+ //audio->msgDeleteEvent(*theEvent, thePart, false);
+ audio->msgDeleteEvent(*theEvent, thePart, false, true, false);
+ }
+
+ DrumMap dm = drumMap[spitch];
+ drumMap[spitch] = drumMap[dpitch];
+ drumMap[dpitch] = dm;
+ drumInmap[int(drumMap[spitch].enote)] = spitch;
+ drumOutmap[int(drumMap[int(spitch)].anote)] = spitch;
+ drumInmap[int(drumMap[int(dpitch)].enote)] = dpitch;
+ drumOutmap[int(drumMap[int(dpitch)].anote)] = dpitch;
+
+ for (iadd_ev i = add_events.begin(); i != add_events.end(); i++) {
+ //std::pair<Part*, Event> pair = *i;
+ //Part* thePart = pair.first;
+ //Event& theEvent = pair.second;
+ Part* thePart = (*i).first;
+ Event& theEvent = (*i).second;
+ // Indicate no undo, and do port controller values but not clone parts.
+ //audio->msgAddEvent(theEvent, thePart, false);
+ audio->msgAddEvent(theEvent, thePart, false, true, false);
+ }
+
+ song->endUndo(SC_EVENT_MODIFIED);
+ song->update(SC_DRUMMAP);
+ }
+
+//---------------------------------------------------------
+// resizeEvent
+//---------------------------------------------------------
+
+void DrumCanvas::resizeEvent(QResizeEvent* ev)
+ {
+ if (ev->size().width() != ev->oldSize().width())
+ emit newWidth(ev->size().width());
+ EventCanvas::resizeEvent(ev);
+ }
+
+
+//---------------------------------------------------------
+// modifySelected
+//---------------------------------------------------------
+
+void DrumCanvas::modifySelected(NoteInfo::ValType type, int delta)
+ {
+ audio->msgIdle(true);
+ song->startUndo();
+ for (iCItem i = items.begin(); i != items.end(); ++i) {
+ if (!(i->second->isSelected()))
+ continue;
+ DEvent* e = (DEvent*)(i->second);
+ Event event = e->event();
+ if (event.type() != Note)
+ continue;
+
+ MidiPart* part = (MidiPart*)(e->part());
+ Event newEvent = event.clone();
+
+ switch (type) {
+ case NoteInfo::VAL_TIME:
+ {
+ int newTime = event.tick() + delta;
+ if (newTime < 0)
+ newTime = 0;
+ newEvent.setTick(newTime);
+ }
+ break;
+ case NoteInfo::VAL_LEN:
+ /*
+ {
+ int len = event.lenTick() + delta;
+ if (len < 1)
+ len = 1;
+ newEvent.setLenTick(len);
+ }
+ */
+ printf("DrumCanvas::modifySelected - NoteInfo::VAL_LEN not implemented\n");
+ break;
+ case NoteInfo::VAL_VELON:
+ /*
+ {
+ int velo = event->velo() + delta;
+ if (velo > 127)
+ velo = 127;
+ else if (velo < 0)
+ velo = 0;
+ newEvent.setVelo(velo);
+ }
+ */
+ printf("DrumCanvas::modifySelected - NoteInfo::VAL_VELON not implemented\n");
+ break;
+ case NoteInfo::VAL_VELOFF:
+ /*
+ {
+ int velo = event.veloOff() + delta;
+ if (velo > 127)
+ velo = 127;
+ else if (velo < 0)
+ velo = 0;
+ newEvent.setVeloOff(velo);
+ }
+ */
+ printf("DrumCanvas::modifySelected - NoteInfo::VAL_VELOFF not implemented\n");
+ break;
+ case NoteInfo::VAL_PITCH:
+ {
+ int pitch = event.pitch() - delta; // Reversing order since the drumlist is displayed in increasing order
+ if (pitch > 127)
+ pitch = 127;
+ else if (pitch < 0)
+ pitch = 0;
+ newEvent.setPitch(pitch);
+ }
+ break;
+ }
+ song->changeEvent(event, newEvent, part);
+ // Indicate do not do port controller values and clone parts.
+ //song->undoOp(UndoOp::ModifyEvent, newEvent, event, part);
+ song->undoOp(UndoOp::ModifyEvent, newEvent, event, part, false, false);
+ }
+ song->endUndo(SC_EVENT_MODIFIED);
+ audio->msgIdle(false);
+ }
+
+//---------------------------------------------------------
+// curPartChanged
+//---------------------------------------------------------
+
+void DrumCanvas::curPartChanged()
+ {
+ editor->setCaption(getCaption());
+ }
+
diff --git a/muse2/muse/midiedit/dcanvas.h b/muse2/muse/midiedit/dcanvas.h
new file mode 100644
index 00000000..7f5034fc
--- /dev/null
+++ b/muse2/muse/midiedit/dcanvas.h
@@ -0,0 +1,93 @@
+//=========================================================
+// MusE
+// Linux Music Editor
+// $Id: dcanvas.h,v 1.8.2.2 2009/02/02 21:38:00 terminator356 Exp $
+// (C) Copyright 1999 Werner Schweer (ws@seh.de)
+//=========================================================
+
+#ifndef __DCANVAS_H__
+#define __DCANVAS_H__
+
+#include "ecanvas.h"
+#include "song.h"
+//Added by qt3to4:
+#include <QResizeEvent>
+#include <QDragEnterEvent>
+#include <QDropEvent>
+#include <QDragMoveEvent>
+#include <QDragLeaveEvent>
+
+#define TH 18
+
+class MidiEditor;
+
+//---------------------------------------------------------
+// DEvent
+// ''visual'' Drum Event
+//---------------------------------------------------------
+
+class DEvent : public CItem {
+ public:
+ DEvent(Event e, Part* p);
+ };
+
+class ScrollScale;
+class PianoRoll;
+class Q3TextDrag;
+
+//---------------------------------------------------------
+// DrumCanvas
+//---------------------------------------------------------
+
+class DrumCanvas : public EventCanvas {
+
+ Q_OBJECT
+ virtual void drawCanvas(QPainter&, const QRect&);
+ virtual void drawItem(QPainter&, const CItem*, const QRect&);
+ virtual void drawMoving(QPainter&, const CItem*, const QRect&);
+ virtual void moveCanvasItems(CItemList&, int, int, DragType, int*);
+ // Changed by T356.
+ //virtual bool moveItem(CItem*, const QPoint&, DragType, int*);
+ virtual bool moveItem(CItem*, const QPoint&, DragType);
+ virtual CItem* newItem(const QPoint&, int);
+ virtual void resizeItem(CItem*, bool);
+ virtual void newItem(CItem*, bool);
+ virtual bool deleteItem(CItem*);
+
+ int y2pitch(int y) const;
+ int pitch2y(int pitch) const;
+ Q3TextDrag* getTextDrag(QWidget* parent);
+ void copy();
+ int pasteAt(const QString& pt, int pos);
+ void paste();
+ void startDrag(CItem*, bool copymode);
+ void dragEnterEvent(QDragEnterEvent* event);
+ void dragMoveEvent(QDragMoveEvent*);
+ void dragLeaveEvent(QDragLeaveEvent*);
+ void viewDropEvent(QDropEvent* event);
+ virtual void addItem(Part*, Event&);
+ virtual void resizeEvent(QResizeEvent*);
+ virtual void curPartChanged();
+
+ signals:
+ void newWidth(int);
+
+ public slots:
+ void mapChanged(int, int);
+ void keyPressed(int, bool);
+ void keyReleased(int, bool);
+
+ public:
+ enum {
+ CMD_CUT, CMD_COPY, CMD_PASTE, CMD_SAVE, CMD_LOAD, CMD_RESET,
+ CMD_SELECT_ALL, CMD_SELECT_NONE, CMD_SELECT_INVERT,
+ CMD_SELECT_ILOOP, CMD_SELECT_OLOOP, CMD_SELECT_PREV_PART, CMD_SELECT_NEXT_PART,
+ CMD_DEL, CMD_FIXED_LEN, CMD_RIGHT, CMD_LEFT, CMD_MODIFY_VELOCITY
+ };
+ DrumCanvas(MidiEditor*, QWidget*, int, int,
+ const char* name = 0);
+ void cmd(int);
+ virtual void modifySelected(NoteInfo::ValType type, int delta);
+ };
+#endif
+
diff --git a/muse2/muse/midiedit/dlist.cpp b/muse2/muse/midiedit/dlist.cpp
new file mode 100644
index 00000000..24ced3d0
--- /dev/null
+++ b/muse2/muse/midiedit/dlist.cpp
@@ -0,0 +1,754 @@
+//=========================================================
+// MusE
+// Linux Music Editor
+// $Id: dlist.cpp,v 1.9.2.7 2009/10/16 21:50:16 terminator356 Exp $
+// (C) Copyright 1999 Werner Schweer (ws@seh.de)
+//=========================================================
+
+#include <qpainter.h>
+#include <q3header.h>
+#include <qcursor.h>
+#include <q3popupmenu.h>
+#include <qlineedit.h>
+//Added by qt3to4:
+#include <QPixmap>
+#include <QMouseEvent>
+
+#include <stdio.h>
+
+#include "audio.h"
+#include "pitchedit.h"
+#include "midiport.h"
+#include "drummap.h"
+#include "icons.h"
+#include "dlist.h"
+#include "song.h"
+#include "scrollscale.h"
+
+// enum DCols { COL_MUTE=0, COL_NAME, COL_QNT, COL_ENOTE, COL_LEN,
+// COL_ANOTE, COL_CHANNEL, COL_PORT,
+// COL_LV1, COL_LV2, COL_LV3, COL_LV4, COL_NONE=-1};
+
+//---------------------------------------------------------
+// draw
+//---------------------------------------------------------
+
+void DList::draw(QPainter& p, const QRect& rect)
+ {
+ int x = rect.x();
+ int y = rect.y();
+ int w = rect.width();
+ int h = rect.height();
+
+ //---------------------------------------------------
+ // Tracks
+ //---------------------------------------------------
+
+ p.setPen(Qt::black);
+
+ for (int i = 0; i < DRUM_MAPSIZE; ++i) {
+ int yy = i * TH;
+ if (yy+TH < y)
+ continue;
+ if (yy > y + h)
+ break;
+ DrumMap* dm = &drumMap[i];
+// if (dm->selected)
+ if (dm == currentlySelected)
+ p.fillRect(x, yy, w, TH, Qt::yellow);
+// else
+// p.eraseRect(x, yy, w, TH);
+ for (int k = 0; k < header->count(); ++k) {
+ int x = header->sectionPos(k);
+ int w = header->sectionSize(k);
+ QRect r = p.xForm(QRect(x+2, yy, w-4, TH));
+ QString s;
+ int align = Qt::AlignVCenter | Qt::AlignHCenter;
+
+ p.save();
+ p.setWorldXForm(false);
+ switch (k) {
+ case COL_VOL:
+ s.setNum(dm->vol);
+ break;
+ case COL_QNT:
+ s.setNum(dm->quant);
+ break;
+ case COL_LEN:
+ s.setNum(dm->len);
+ break;
+ case COL_ANOTE:
+ s = pitch2string(dm->anote);
+ break;
+ case COL_ENOTE:
+ s = pitch2string(dm->enote);
+ break;
+ case COL_LV1:
+ s.setNum(dm->lv1);
+ break;
+ case COL_LV2:
+ s.setNum(dm->lv2);
+ break;
+ case COL_LV3:
+ s.setNum(dm->lv3);
+ break;
+ case COL_LV4:
+ s.setNum(dm->lv4);
+ break;
+ case COL_MUTE:
+ if (dm->mute) {
+ p.setPen(Qt::red);
+ const QPixmap& pm = *muteIcon;
+ p.drawPixmap(
+ r.x() + r.width()/2 - pm.width()/2,
+ r.y() + r.height()/2 - pm.height()/2,
+ pm);
+ p.setPen(Qt::black);
+ }
+ break;
+ case COL_NAME:
+ s = dm->name;
+ align = Qt::AlignVCenter | Qt::AlignLeft;
+ break;
+ case COL_CHANNEL:
+ s.setNum(dm->channel+1);
+ break;
+ case COL_PORT:
+ s.sprintf("%d:%s", dm->port+1, midiPorts[dm->port].portname().latin1());
+ align = Qt::AlignVCenter | Qt::AlignLeft;
+ break;
+ }
+ if (!s.isEmpty())
+ p.drawText(r, align, s);
+ p.restore();
+ }
+ }
+
+ //---------------------------------------------------
+ // horizontal lines
+ //---------------------------------------------------
+
+ p.setPen(Qt::gray);
+ int yy = (y / TH) * TH;
+ for (; yy < y + h; yy += TH) {
+ p.drawLine(x, yy, x + w, yy);
+ }
+
+ if (drag == DRAG) {
+ int y = (startY/TH) * TH;
+ int dy = startY - y;
+ int yy = curY - dy;
+ p.setPen(Qt::green);
+ p.drawLine(x, yy, x + w, yy);
+ p.drawLine(x, yy+TH, x + w, yy+TH);
+ p.setPen(Qt::gray);
+ }
+
+ //---------------------------------------------------
+ // vertical Lines
+ //---------------------------------------------------
+
+ p.setWorldXForm(false);
+ int n = header->count();
+ x = 0;
+ for (int i = 0; i < n; i++) {
+ //x += header->sectionSize(i);
+ x += header->sectionSize(header->mapToSection(i));
+ p.drawLine(x, 0, x, height());
+ }
+ p.setWorldXForm(true);
+ }
+
+//---------------------------------------------------------
+// devicesPopupMenu
+//---------------------------------------------------------
+
+void DList::devicesPopupMenu(DrumMap* t, int x, int y, bool changeAll)
+ {
+ Q3PopupMenu* p = midiPortsPopup(this);
+ int n = p->exec(mapToGlobal(QPoint(x, y)), 0);
+ bool doemit = false;
+ if (n != -1) {
+ if (!changeAll)
+ {
+ if(n != t->port)
+ {
+ audio->msgIdle(true);
+ //audio->msgRemapPortDrumCtlEvents(getSelectedInstrument(), -1, -1, n);
+ song->remapPortDrumCtrlEvents(getSelectedInstrument(), -1, -1, n);
+ audio->msgIdle(false);
+ t->port = n;
+ doemit = true;
+ }
+ }
+ else {
+ audio->msgIdle(true);
+ // Delete all port controller events.
+ //audio->msgChangeAllPortDrumCtrlEvents(false);
+ song->changeAllPortDrumCtrlEvents(false);
+
+ for (int i = 0; i < DRUM_MAPSIZE; i++)
+ drumMap[i].port = n;
+ // Add all port controller events.
+ //audio->msgChangeAllPortDrumCtrlEvents(true);
+ song->changeAllPortDrumCtrlEvents(true);
+
+ audio->msgIdle(false);
+ doemit = true;
+ }
+ }
+ delete p;
+ if(doemit)
+ {
+ int instr = getSelectedInstrument();
+ if(instr != -1)
+ //emit curDrumInstrumentChanged(instr);
+ song->update(SC_DRUMMAP);
+ }
+ }
+
+//---------------------------------------------------------
+// viewMousePressEvent
+//---------------------------------------------------------
+
+void DList::viewMousePressEvent(QMouseEvent* ev)
+ {
+ int x = ev->x();
+ int y = ev->y();
+ int button = ev->button();
+ bool shift = ev->state() & Qt::ShiftButton;
+ unsigned pitch = y / TH;
+ DrumMap* dm = &drumMap[pitch];
+
+ setCurDrumInstrument(pitch);
+
+ startY = y;
+ sPitch = pitch;
+ drag = START_DRAG;
+
+ DCols col = DCols(x2col(x));
+
+ int val;
+ int incVal = 0;
+ if (button == Qt::RightButton)
+ incVal = 1;
+ else if (button == Qt::MidButton)
+ incVal = -1;
+
+ // Check if we're already editing anything and have pressed the mouse
+ // elsewhere
+ // In that case, treat it as if a return was pressed
+
+ if (button == Qt::LeftButton) {
+ if (((editEntry && editEntry != dm) || col != selectedColumn) && editEntry != 0) {
+ returnPressed();
+ }
+ }
+
+ switch (col) {
+ case COL_NONE:
+ break;
+ case COL_MUTE:
+ if (button == Qt::LeftButton)
+ dm->mute = !dm->mute;
+ break;
+ case COL_PORT:
+ if (button == Qt::RightButton) {
+ bool changeAll = ev->state() & Qt::ControlButton;
+ devicesPopupMenu(dm, mapx(x), mapy(pitch * TH), changeAll);
+ }
+ break;
+ case COL_VOL:
+ val = dm->vol + incVal;
+ if (val < 0)
+ val = 0;
+ else if (val > 200)
+ val = 200;
+ dm->vol = (unsigned char)val;
+ break;
+ case COL_QNT:
+ dm->quant += incVal;
+ // ?? range
+ break;
+ case COL_ENOTE:
+ val = dm->enote + incVal;
+ if (val < 0)
+ val = 0;
+ else if (val > 127)
+ val = 127;
+ //Check if there is any other drumMap with the same inmap value (there should be one (and only one):-)
+ //If so, switch the inmap between the instruments
+ for (int i=0; i<DRUM_MAPSIZE; i++) {
+ if (drumMap[i].enote == val && &drumMap[i] != dm) {
+ drumInmap[int(dm->enote)] = i;
+ drumMap[i].enote = dm->enote;
+ break;
+ }
+ }
+ //TODO: Set all the notes on the track with pitch=dm->enote to pitch=val
+ dm->enote = val;
+ drumInmap[val] = pitch;
+ break;
+ case COL_LEN:
+ val = dm->len + incVal;
+ if (val < 0)
+ val = 0;
+ dm->len = val;
+ break;
+ case COL_ANOTE:
+ val = dm->anote + incVal;
+ if (val < 0)
+ val = 0;
+ else if (val > 127)
+ val = 127;
+ if(val != dm->anote)
+ {
+ audio->msgIdle(true);
+ //audio->msgRemapPortDrumCtlEvents(pitch, val, -1, -1);
+ song->remapPortDrumCtrlEvents(pitch, val, -1, -1);
+ audio->msgIdle(false);
+ dm->anote = val;
+ song->update(SC_DRUMMAP);
+ }
+ emit keyPressed(pitch, shift);//(dm->anote, shift);
+ break;
+ case COL_CHANNEL:
+ val = dm->channel + incVal;
+ if (val < 0)
+ val = 0;
+ else if (val > 127)
+ val = 127;
+
+ if (ev->state() & Qt::ControlButton) {
+ audio->msgIdle(true);
+ // Delete all port controller events.
+ //audio->msgChangeAllPortDrumCtrlEvents(false);
+ song->changeAllPortDrumCtrlEvents(false, true);
+
+ for (int i = 0; i < DRUM_MAPSIZE; i++)
+ drumMap[i].channel = val;
+ // Add all port controller events.
+ //audio->msgChangeAllPortDrumCtrlEvents(true);
+ song->changeAllPortDrumCtrlEvents(true, true);
+ audio->msgIdle(false);
+ song->update(SC_DRUMMAP);
+ }
+ else
+ {
+ if(val != dm->channel)
+ {
+ audio->msgIdle(true);
+ //audio->msgRemapPortDrumCtlEvents(pitch, -1, val, -1);
+ song->remapPortDrumCtrlEvents(pitch, -1, val, -1);
+ audio->msgIdle(false);
+ dm->channel = val;
+ song->update(SC_DRUMMAP);
+ }
+ }
+ break;
+ case COL_LV1:
+ val = dm->lv1 + incVal;
+ if (val < 0)
+ val = 0;
+ else if (val > 127)
+ val = 127;
+ dm->lv1 = val;
+ break;
+ case COL_LV2:
+ val = dm->lv2 + incVal;
+ if (val < 0)
+ val = 0;
+ else if (val > 127)
+ val = 127;
+ dm->lv2 = val;
+ break;
+ case COL_LV3:
+ val = dm->lv3 + incVal;
+ if (val < 0)
+ val = 0;
+ else if (val > 127)
+ val = 127;
+ dm->lv3 = val;
+ break;
+ case COL_LV4:
+ val = dm->lv4 + incVal;
+ if (val < 0)
+ val = 0;
+ else if (val > 127)
+ val = 127;
+ dm->lv4 = val;
+ break;
+ case COL_NAME:
+ emit keyPressed(pitch, shift); //Mapping done on other side, send index
+ break;
+#if 0
+ case COL_CHANNEL:
+ {
+ int channel = t->channel();
+ if (button == Qt::RightButton) {
+ if (channel < 15)
+ ++channel;
+ }
+ else if (button == Qt::MidButton) {
+ if (channel > 0)
+ --channel;
+ }
+ if (channel != t->channel()) {
+ t->setChannel(channel);
+ emit channelChanged();
+ }
+ }
+#endif
+ default:
+ break;
+ }
+ redraw();
+ }
+
+//---------------------------------------------------------
+// viewMouseDoubleClickEvent
+//---------------------------------------------------------
+
+void DList::viewMouseDoubleClickEvent(QMouseEvent* ev)
+ {
+ int x = ev->x();
+ int y = ev->y();
+// int button = ev->button();
+ unsigned pitch = y / TH;
+
+ int section = header->sectionAt(x);
+
+ if ((section == COL_NAME || section == COL_VOL || section == COL_LEN || section == COL_LV1 ||
+ section == COL_LV2 || section == COL_LV3 || section == COL_LV4) && (ev->button() == Qt::LeftButton))
+ {
+ lineEdit(pitch, section);
+ }
+ else
+ viewMousePressEvent(ev);
+ }
+
+
+
+//---------------------------------------------------------
+// lineEdit
+//---------------------------------------------------------
+void DList::lineEdit(int line, int section)
+ {
+ DrumMap* dm = &drumMap[line];
+ editEntry = dm;
+ if (editor == 0) {
+ editor = new DLineEdit(this);
+ connect(editor, SIGNAL(returnPressed()),
+ SLOT(returnPressed()));
+ editor->setFrame(true);
+ }
+ int colx = mapx(header->sectionPos(section));
+ int colw = rmapx(header->sectionSize(section));
+ int coly = mapy(line * TH);
+ int colh = rmapy(TH);
+ selectedColumn = section; //Store selected column to have an idea of which one was selected when return is pressed
+ switch (section) {
+ case COL_NAME:
+ editor->setText(dm->name);
+ break;
+
+ case COL_VOL: {
+ editor->setText(QString::number(dm->vol));
+ break;
+ }
+
+ case COL_LEN: {
+ editor->setText(QString::number(dm->len));
+ break;
+ }
+
+ case COL_LV1:
+ editor->setText(QString::number(dm->lv1));
+ break;
+
+ case COL_LV2:
+ editor->setText(QString::number(dm->lv2));
+ break;
+
+ case COL_LV3:
+ editor->setText(QString::number(dm->lv3));
+ break;
+
+ case COL_LV4:
+ editor->setText(QString::number(dm->lv4));
+ break;
+ }
+
+ // editor->setText(dm->name);
+ editor->end(false);
+ editor->setGeometry(colx, coly, colw, colh);
+ // In all cases but the column name, select all text:
+ if (section != COL_NAME)
+ editor->selectAll();
+ editor->show();
+ editor->setFocus();
+
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+//---------------------------------------------------------
+// x2col
+//---------------------------------------------------------
+
+int DList::x2col(int x) const
+ {
+ int col = 0;
+ int w = 0;
+ for (; col < header->count(); col++) {
+ w += header->cellSize(col);
+ if (x < w)
+ break;
+ }
+ if (col == header->count())
+ return -1;
+ return header->mapToLogical(col);
+ }
+
+//---------------------------------------------------------
+// setCurDrumInstrument
+//---------------------------------------------------------
+
+void DList::setCurDrumInstrument(int instr)
+ {
+ if (instr < 0 || instr >= DRUM_MAPSIZE -1)
+ return; // illegal instrument
+ DrumMap* dm = &drumMap[instr];
+ if (currentlySelected != dm) {
+ currentlySelected = &drumMap[instr];
+ emit curDrumInstrumentChanged(instr);
+ song->update(SC_DRUMMAP);
+ }
+ }
+
+//---------------------------------------------------------
+// sizeChange
+//---------------------------------------------------------
+
+void DList::sizeChange(int, int, int)
+ {
+ redraw();
+ }
+
+//---------------------------------------------------------
+// returnPressed
+//---------------------------------------------------------
+
+void DList::returnPressed()
+ {
+ int val = -1;
+ if (selectedColumn != COL_NAME)
+ {
+ val = atoi(editor->text().ascii());
+ if (selectedColumn != COL_LEN)
+ {
+ if(selectedColumn == COL_VOL)
+ {
+ if (val > 200) //Check bounds for volume
+ val = 200;
+ if (val < 0)
+ val = 0;
+ }
+ else
+ {
+ if (val > 127) //Check bounds for lv1-lv4 values
+ val = 127;
+ if (val < 0)
+ val = 0;
+ }
+ }
+ }
+
+ switch(selectedColumn) {
+ case COL_NAME:
+ editEntry->name = editor->text();
+ break;
+
+ case COL_LEN:
+ editEntry->len = atoi(editor->text().ascii());
+ break;
+
+ case COL_VOL:
+ editEntry->vol = val;
+ break;
+
+ case COL_LV1:
+ editEntry->lv1 = val;
+ break;
+
+ case COL_LV2:
+ editEntry->lv2 = val;
+ break;
+
+ case COL_LV3:
+ editEntry->lv3 = val;
+ break;
+
+ case COL_LV4:
+ editEntry->lv4 = val;
+ break;
+
+ default:
+ printf("Return pressed in unknown column\n");
+ break;
+ }
+ selectedColumn = -1;
+ editor->hide();
+ editEntry = 0;
+ setFocus();
+ redraw();
+ }
+
+//---------------------------------------------------------
+// moved
+//---------------------------------------------------------
+
+void DList::moved(int, int)
+ {
+ redraw();
+ }
+
+//---------------------------------------------------------
+// tracklistChanged
+//---------------------------------------------------------
+
+void DList::tracklistChanged()
+ {
+ }
+
+//---------------------------------------------------------
+// songChanged
+//---------------------------------------------------------
+
+void DList::songChanged(int flags)
+ {
+ if (flags & SC_DRUMMAP) {
+ redraw();
+ }
+ }
+
+
+//---------------------------------------------------------
+// DList
+//---------------------------------------------------------
+
+DList::DList(Q3Header* h, QWidget* parent, int ymag)
+ : View(parent, 1, ymag)
+ {
+ setBg(Qt::white);
+ header = h;
+ scroll = 0;
+ header->setTracking(true);
+ connect(header, SIGNAL(sizeChange(int,int,int)),
+ SLOT(sizeChange(int,int,int)));
+ connect(header, SIGNAL(moved(int,int)), SLOT(moved(int,int)));
+ setFocusPolicy(Qt::StrongFocus);
+ drag = NORMAL;
+ editor = 0;
+ editEntry = 0;
+ // always select an drum instrument
+ currentlySelected = &drumMap[0];
+ selectedColumn = -1;
+ }
+
+//---------------------------------------------------------
+// ~DList
+//---------------------------------------------------------
+
+DList::~DList()
+ {
+// if (currentlySelected != 0)
+// currentlySelected->selected = false; //Reset the global thingie
+ }
+
+//---------------------------------------------------------
+// viewMouseMoveEvent
+//---------------------------------------------------------
+
+void DList::viewMouseMoveEvent(QMouseEvent* ev)
+ {
+ curY = ev->y();
+ int delta = curY - startY;
+ switch (drag) {
+ case START_DRAG:
+ if (delta < 0)
+ delta = -delta;
+ if (delta <= 2)
+ return;
+ drag = DRAG;
+ setCursor(QCursor(Qt::sizeVerCursor));
+ redraw();
+ break;
+ case NORMAL:
+ break;
+ case DRAG:
+ redraw();
+ break;
+ }
+ }
+
+//---------------------------------------------------------
+// viewMouseReleaseEvent
+//---------------------------------------------------------
+
+void DList::viewMouseReleaseEvent(QMouseEvent* ev)
+ {
+ if (drag == DRAG) {
+ int y = ev->y();
+ unsigned dPitch = y / TH;
+ setCursor(QCursor(Qt::arrowCursor));
+ currentlySelected = &drumMap[int(dPitch)];
+ emit curDrumInstrumentChanged(dPitch);
+ emit mapChanged(sPitch, dPitch); //Track pitch change done in canvas
+ }
+ drag = NORMAL;
+//?? redraw();
+ if (editEntry)
+ editor->setFocus();
+ int x = ev->x();
+ int y = ev->y();
+ bool shift = ev->state() & Qt::ShiftButton;
+ unsigned pitch = y / TH;
+
+ DCols col = DCols(x2col(x));
+
+ switch (col) {
+ case COL_NAME:
+ emit keyReleased(pitch, shift);
+ break;
+ case COL_ANOTE:
+ emit keyReleased(pitch, shift);
+ break;
+ default:
+ break;
+ }
+ }
+
+//---------------------------------------------------------
+// getSelectedInstrument
+//---------------------------------------------------------
+
+int DList::getSelectedInstrument()
+ {
+ if (currentlySelected == 0)
+ return -1;
+ return drumInmap[int(currentlySelected->enote)];
+ }
+
diff --git a/muse2/muse/midiedit/dlist.h b/muse2/muse/midiedit/dlist.h
new file mode 100644
index 00000000..1d7e0114
--- /dev/null
+++ b/muse2/muse/midiedit/dlist.h
@@ -0,0 +1,105 @@
+//=========================================================
+// MusE
+// Linux Music Editor
+// $Id: dlist.h,v 1.5.2.3 2009/10/16 21:50:16 terminator356 Exp $
+// (C) Copyright 1999 Werner Schweer (ws@seh.de)
+//=========================================================
+
+#ifndef __DLIST_H__
+#define __DLIST_H__
+
+#include <qlineedit.h>
+//Added by qt3to4:
+#include <QMouseEvent>
+#include <QKeyEvent>
+#include "view.h"
+
+#define TH 18 // normal Track-hight
+
+class QPainter;
+class Q3Header;
+class ScrollScale;
+class Device;
+class QLineEdit;
+class DrumMap;
+
+
+//---------------------------------------------------------
+// DLineEdit
+//---------------------------------------------------------
+class DLineEdit: public QLineEdit
+{
+ public:
+ DLineEdit(QWidget* parent) : QLineEdit(parent) {}
+ virtual ~DLineEdit() {};
+
+ virtual void keyPressEvent(QKeyEvent* keyItem) {
+ if(keyItem->key() == Qt::Key_Escape) {
+ parentWidget()->setFocus();
+ hide();
+ }
+ else
+ QLineEdit::keyPressEvent(keyItem);
+
+ }
+};
+
+//---------------------------------------------------------
+// DList
+//---------------------------------------------------------
+
+class DList : public View {
+ Q3Header* header;
+ ScrollScale* scroll;
+ QLineEdit* editor;
+ DrumMap* editEntry;
+ DrumMap* currentlySelected;
+ int selectedColumn;
+
+
+ int startY;
+ int curY;
+ int sPitch;
+ enum { NORMAL, START_DRAG, DRAG } drag;
+
+ virtual void draw(QPainter& p, const QRect&);
+ virtual void viewMousePressEvent(QMouseEvent* event);
+ virtual void viewMouseReleaseEvent(QMouseEvent* event);
+ virtual void viewMouseDoubleClickEvent(QMouseEvent*);
+ virtual void viewMouseMoveEvent(QMouseEvent*);
+
+ int x2col(int x) const;
+ void devicesPopupMenu(DrumMap* t, int x, int y, bool changeAll);
+ Q_OBJECT
+ //void setCurDrumInstrument(int n);
+
+ private slots:
+ void sizeChange(int, int, int);
+ void returnPressed();
+ void moved(int, int);
+
+ signals:
+ void channelChanged();
+ void mapChanged(int, int);
+ void keyPressed(int, bool);
+ void keyReleased(int, bool);
+ void curDrumInstrumentChanged(int);
+
+ public slots:
+ void tracklistChanged();
+ void songChanged(int);
+ public:
+ void lineEdit(int line, int section);
+ void setCurDrumInstrument(int n);
+ DList(Q3Header*, QWidget* parent, int ymag);
+ ~DList();
+ void setScroll(ScrollScale* s) { scroll = s; }
+ int getSelectedInstrument();
+
+enum DCols { COL_MUTE=0, COL_NAME, COL_VOL, COL_QNT, COL_ENOTE, COL_LEN,
+ COL_ANOTE, COL_CHANNEL, COL_PORT,
+ COL_LV1, COL_LV2, COL_LV3, COL_LV4, COL_NONE=-1};
+ };
+
+#endif // __DLIST_H_
+
diff --git a/muse2/muse/midiedit/drumedit.cpp b/muse2/muse/midiedit/drumedit.cpp
new file mode 100644
index 00000000..ebe89ac6
--- /dev/null
+++ b/muse2/muse/midiedit/drumedit.cpp
@@ -0,0 +1,1167 @@
+//=========================================================
+// MusE
+// Linux Music Editor
+// $Id: drumedit.cpp,v 1.22.2.21 2009/11/16 11:29:33 lunar_shuttle Exp $
+// (C) Copyright 1999 Werner Schweer (ws@seh.de)
+//=========================================================
+
+#include <qtoolbutton.h>
+#include <q3accel.h>
+#include <qlayout.h>
+#include <q3hbox.h>
+#include <qsizegrip.h>
+#include <qscrollbar.h>
+#include <qlabel.h>
+#include <qpushbutton.h>
+#include <qradiobutton.h>
+#include <q3buttongroup.h>
+#include <q3listbox.h>
+#include <q3popupmenu.h>
+#include <qmenubar.h>
+#include <qtooltip.h>
+#include <qapplication.h>
+#include <qclipboard.h>
+#include <qmessagebox.h>
+#include <qaction.h>
+//Added by qt3to4:
+#include <QKeyEvent>
+#include <Q3ValueList>
+#include <Q3GridLayout>
+#include <QResizeEvent>
+#include <QCloseEvent>
+
+#include "drumedit.h"
+#include "mtscale.h"
+#include "scrollscale.h"
+#include "xml.h"
+#include "dlist.h"
+#include "dcanvas.h"
+#include "ttoolbar.h"
+#include "tb1.h"
+#include "splitter.h"
+#include "utils.h"
+#include "../ctrl/ctrledit.h"
+#include "vscale.h"
+#include "swidget.h"
+#include "globals.h"
+#include "icons.h"
+#include "filedialog.h"
+#include "drummap.h"
+#include "audio.h"
+#include "gconfig.h"
+
+/*
+static const char* map_file_pattern[] = {
+ "Presets (*.map *.map.gz *.map.bz2)",
+ "All Files (*)",
+ 0
+ };
+static const char* map_file_save_pattern[] = {
+ "Presets (*.map)",
+ "gzip compressed presets (*.map.gz)",
+ "bzip2 compressed presets (*.map.bz2)",
+ "All Files (*)",
+ 0
+ };
+*/
+
+int DrumEdit::_quantInit = 96;
+int DrumEdit::_rasterInit = 96;
+int DrumEdit::_widthInit = 600;
+int DrumEdit::_heightInit = 400;
+int DrumEdit::_dlistWidthInit = 50;
+int DrumEdit::_dcanvasWidthInit = 300;
+int DrumEdit::_toInit = 0;
+
+static const int xscale = -10;
+static const int yscale = 1;
+static const int drumeditTools = PointerTool | PencilTool | RubberTool;
+
+//---------------------------------------------------------
+// DWhatsThis::text
+//---------------------------------------------------------
+
+QString DWhatsThis::text(const QPoint& pos)
+ {
+ int section = header->sectionAt(pos.x());
+ if (section == -1)
+ return QString::null;
+ switch(section) {
+ case 0: return Q3Header::tr("mute instrument"); break;
+ case 1: return Q3Header::tr("sound name"); break;
+ case 2: return Q3Header::tr("volume percent"); break;
+ case 3: return Q3Header::tr("quantisation"); break;
+ case 4: return Q3Header::tr("this input note triggers the sound"); break;
+ case 5: return Q3Header::tr("note length"); break;
+ case 6: return Q3Header::tr("this is the note which is played"); break;
+ case 7: return Q3Header::tr("output channel (hold ctl to affect all rows)"); break;
+ case 8: return Q3Header::tr("output port"); break;
+ case 9: return Q3Header::tr("shift + control key: draw velocity level 1"); break;
+ case 10: return Q3Header::tr("control key: draw velocity level 2"); break;
+ case 11: return Q3Header::tr("shift key: draw velocity level 3"); break;
+ case 12: return Q3Header::tr("draw velocity level 4"); break;
+ default: break;
+ }
+ return QString::null;
+ }
+
+//---------------------------------------------------------
+// DHeaderTip::maybeTip
+//---------------------------------------------------------
+
+void DHeaderTip::maybeTip(const QPoint &pos)
+ {
+#if 0 // ddskrjo
+ Header* w = (Header*)parentWidget();
+ int section = w->sectionAt(pos.x());
+ if (section == -1)
+ return;
+ QRect r(w->sectionPos(section), 0, w->sectionSize(section),
+ w->height());
+ QString p;
+ switch(section) {
+ case 0: p = Q3Header::tr("mute instrument"); break;
+ case 1: p = Q3Header::tr("sound name"); break;
+ case 2: p = Q3Header::tr("volume percent"); break;
+ case 3: p = Q3Header::tr("quantisation"); break;
+ case 4: p = Q3Header::tr("this input note triggers the sound"); break;
+ case 5: p = Q3Header::tr("note length"); break;
+ case 6: p = Q3Header::tr("this is the note which is played"); break;
+ case 7: p = Q3Header::tr("output channel (ctl: affect all rows)"); break;
+ case 8: p = Q3Header::tr("output port"); break;
+ case 9: p = Q3Header::tr("shift + control key: draw velocity level 1"); break;
+ case 10: p = Q3Header::tr("control key: draw velocity level 2"); break;
+ case 11: p = Q3Header::tr("shift key: draw velocity level 3"); break;
+ case 12: p = Q3Header::tr("draw velocity level 4"); break;
+ default: return;
+ }
+ tip(r, p);
+#endif
+ }
+
+//---------------------------------------------------------
+// closeEvent
+//---------------------------------------------------------
+
+void DrumEdit::closeEvent(QCloseEvent* e)
+ {
+ //Store values of the horizontal splitter
+ Q3ValueList<int> sizes = split2->sizes();
+ Q3ValueList<int>::Iterator it = sizes.begin();
+ _dlistWidthInit = *it; //There are only 2 values stored in the sizelist, size of dlist widget and dcanvas widget
+ it++;
+ _dcanvasWidthInit = *it;
+ emit deleted((unsigned long)this);
+ e->accept();
+ }
+
+//---------------------------------------------------------
+// DrumEdit
+//---------------------------------------------------------
+
+DrumEdit::DrumEdit(PartList* pl, QWidget* parent, const char* name, unsigned initPos)
+ : MidiEditor(_quantInit, _rasterInit, pl, parent, name)
+ {
+ split1w1 = 0;
+ resize(_widthInit, _heightInit);
+ selPart = 0;
+ _to = _toInit;
+ //---------Pulldown Menu----------------------------
+ menuFile = new Q3PopupMenu(this);
+ menuBar()->insertItem(tr("&File"), menuFile);
+
+ menuFile->insertItem(QIcon(*openIcon), tr("Load Map"), DrumCanvas::CMD_LOAD);
+ menuFile->insertItem(QIcon(*saveIcon), tr("Save Map"), DrumCanvas::CMD_SAVE);
+ menuFile->insertItem(tr("Reset GM Map"), DrumCanvas::CMD_RESET);
+
+ menuEdit = new Q3PopupMenu(this);
+ menuBar()->insertItem(tr("&Edit"), menuEdit);
+ undoRedo->addTo(menuEdit);
+ Q3Accel* qa = new Q3Accel(this);
+ qa->connectItem(qa->insertItem(Qt::CTRL+Qt::Key_Z), song, SLOT(undo()));
+ menuEdit->insertSeparator();
+ menuEdit->insertItem(tr("Cut"), DrumCanvas::CMD_CUT);
+ menuEdit->insertItem(tr("Copy"), DrumCanvas::CMD_COPY);
+ menuEdit->insertItem(tr("Paste"), DrumCanvas::CMD_PASTE);
+ menuEdit->insertSeparator();
+ menuEdit->insertItem(tr("Delete Events"), DrumCanvas::CMD_DEL);
+
+ // Functions
+ menuFunctions = new Q3PopupMenu(this);
+ menuBar()->insertItem(tr("&Functions"), menuFunctions);
+ menuFunctions->insertTearOffHandle();
+ menuFunctions->insertItem(tr("Set fixed length"), DrumCanvas::CMD_FIXED_LEN);
+ menuFunctions->insertItem(tr("Modify Velocity"), DrumCanvas::CMD_MODIFY_VELOCITY);
+
+ menuSelect = new Q3PopupMenu(this);
+ menuSelect->insertItem(tr("Select All"), DrumCanvas::CMD_SELECT_ALL);
+ menuSelect->insertItem(tr("Select None"), DrumCanvas::CMD_SELECT_NONE);
+ menuSelect->insertItem(tr("Invert"), DrumCanvas::CMD_SELECT_INVERT);
+ menuSelect->insertSeparator();
+ menuSelect->insertItem(tr("Inside Loop"), DrumCanvas::CMD_SELECT_ILOOP);
+ menuSelect->insertItem(tr("Outside Loop"), DrumCanvas::CMD_SELECT_OLOOP);
+
+ menuSelect->insertSeparator();
+
+ menuSelect->insertItem(tr("Previous Part"), DrumCanvas::CMD_SELECT_PREV_PART);
+ menuSelect->insertItem(tr("Next Part"), DrumCanvas::CMD_SELECT_NEXT_PART);
+
+ menuEdit->insertItem(tr("&Select"), menuSelect);
+
+ Q3PopupMenu* menuScriptPlugins = new Q3PopupMenu(this);
+ song->populateScriptMenu(menuScriptPlugins, this);
+ menuBar()->insertItem(tr("&Plugins"), menuScriptPlugins);
+
+ connect(menuFile, SIGNAL(activated(int)), SLOT(cmd(int)));
+ connect(menuEdit, SIGNAL(activated(int)), SLOT(cmd(int)));
+ connect(menuSelect, SIGNAL(activated(int)), SLOT(cmd(int)));
+ connect(menuFunctions, SIGNAL(activated(int)), SLOT(cmd(int)));
+
+ //---------------------------------------------------
+ // Toolbars
+ //---------------------------------------------------
+
+ tools = new Q3ToolBar(this, "drum-tools");
+ new QToolButton(*openIcon, tr("Load Drummap"),
+ QString::null, this, SLOT(load()),
+ tools, "load drummap from file");
+
+ new QToolButton(*saveIcon, tr("Store Drummap"),
+ QString::null,
+ this, SLOT(save()),
+ tools, "store drummap to file");
+
+ Q3WhatsThis::whatsThisButton(tools);
+
+ tools->addSeparator();
+ undoRedo->addTo(tools);
+ tools->addSeparator();
+
+ srec = new QToolButton(tools, "srec");
+ QToolTip::add(srec, tr("Step Record"));
+ srec->setPixmap(*steprecIcon);
+ srec->setToggleButton(true);
+
+ midiin = new QToolButton(tools, "midiin");
+ QToolTip::add(midiin, tr("Midi Input"));
+ midiin->setPixmap(*midiinIcon);
+ midiin->setToggleButton(true);
+
+ tools2 = new EditToolBar(this, drumeditTools);
+
+ Q3ToolBar* transport = new Q3ToolBar(this);
+ transportAction->addTo(transport);
+
+ // dontt show pitch value in toolbar
+ //toolbar = new Toolbar1(this, _rasterInit, _quantInit, false);
+ toolbar = new Toolbar1(this, _rasterInit, _quantInit);
+ info = new NoteInfo(this);
+
+ //---------------------------------------------------
+ // split
+ //---------------------------------------------------
+
+ split1 = new Splitter(Qt::Vertical, mainw, "split1");
+ QPushButton* ctrl = new QPushButton(tr("ctrl"), mainw, "Ctrl");
+ ctrl->setFont(config.fonts[3]);
+ hscroll = new ScrollScale(-25, -2, xscale, 20000, Qt::Horizontal, mainw);
+ ctrl->setFixedSize(40, hscroll->sizeHint().height());
+ QToolTip::add(ctrl, tr("Add Controller View"));
+
+ QSizeGrip* corner = new QSizeGrip(mainw);
+ corner->setFixedHeight(hscroll->sizeHint().height());
+
+ mainGrid->setRowStretch(0, 100);
+ mainGrid->setColStretch(1, 100);
+
+ mainGrid->addMultiCellWidget(split1, 0, 0, 0, 2);
+ mainGrid->addWidget(ctrl, 1, 0);
+ mainGrid->addWidget(hscroll, 1, 1);
+ mainGrid->addWidget(corner, 1, 2, Qt::AlignBottom|Qt::AlignRight);
+// mainGrid->addRowSpacing(1, hscroll->sizeHint().height());
+
+ split2 = new Splitter(Qt::Horizontal, split1, "split2");
+ split1w1 = new QWidget(split2, "split1w1");
+ QWidget* split1w2 = new QWidget(split2, "split1w2");
+ Q3GridLayout* gridS1 = new Q3GridLayout(split1w1);
+ Q3GridLayout* gridS2 = new Q3GridLayout(split1w2);
+ time = new MTScale(&_raster, split1w2, xscale);
+ canvas = new DrumCanvas(this, split1w2, xscale, yscale);
+ vscroll = new ScrollScale(-4, 1, yscale, DRUM_MAPSIZE*TH, Qt::Vertical, split1w2);
+ int offset = -(config.division/4);
+ canvas->setOrigin(offset, 0);
+ canvas->setCanvasTools(drumeditTools);
+ canvas->setFocus();
+ connect(canvas, SIGNAL(toolChanged(int)), tools2, SLOT(set(int)));
+ time->setOrigin(offset, 0);
+
+ Q3ValueList<int> mops;
+ mops.append(_dlistWidthInit);
+ mops.append(_dcanvasWidthInit);
+ split2->setSizes(mops);
+ // By T356. Not much choice but to disable this for now, to stop runaway resize bug.
+ // Can't seem to get the splitter to readjust when manually setting sizes.
+ //split2->setResizeMode(split1w1, QSplitter::KeepSize);
+
+ gridS2->setRowStretch(1, 100);
+ gridS2->setColStretch(0, 100);
+
+ gridS2->addMultiCellWidget(time, 0, 0, 0, 1);
+ gridS2->addMultiCellWidget(hLine(split1w2), 1, 1, 0, 1);
+ gridS2->addWidget(canvas, 2, 0);
+
+ gridS2->addWidget(vscroll, 2, 1);
+ //
+ // Reihenfolge in dlist.c festgeschrieben ("Dcols")
+ //
+ header = new Header(split1w1, "header");
+ header->setFixedHeight(30);
+ header->addLabel(tr("M"), 20);
+ header->addLabel(tr("Sound"), 100);
+ header->addLabel(tr("Vol"));
+ header->addLabel(tr("QNT"));
+ header->addLabel(tr("E-Note"));
+ header->addLabel(tr("Len"));
+ header->addLabel(tr("A-Note"));
+ header->addLabel(tr("Ch"));
+ header->addLabel(tr("Port"), 60);
+ header->addLabel(tr("LV1"));
+ header->addLabel(tr("LV2"));
+ header->addLabel(tr("LV3"));
+ header->addLabel(tr("LV4"));
+ new DHeaderTip(header);
+ new DWhatsThis(header, header);
+
+ dlist = new DList(header, split1w1, yscale);
+ // p3.3.44
+ setCurDrumInstrument(dlist->getSelectedInstrument());
+
+ connect(dlist, SIGNAL(keyPressed(int, bool)), canvas, SLOT(keyPressed(int, bool)));
+ connect(dlist, SIGNAL(keyReleased(int, bool)), canvas, SLOT(keyReleased(int, bool)));
+ connect(dlist, SIGNAL(mapChanged(int, int)), canvas, SLOT(mapChanged(int, int)));
+
+ gridS1->setRowStretch(1, 100);
+ gridS1->setColStretch(0, 100);
+ gridS1->addWidget(header, 0, 0);
+ gridS1->addWidget(dlist, 1, 0);
+
+ connect(canvas, SIGNAL(newWidth(int)), SLOT(newCanvasWidth(int)));
+ connect(canvas, SIGNAL(verticalScroll(unsigned)), vscroll, SLOT(setPos(unsigned)));
+ connect(canvas, SIGNAL(horizontalScroll(unsigned)),hscroll, SLOT(setPos(unsigned)));
+ connect(canvas, SIGNAL(horizontalScrollNoLimit(unsigned)),hscroll, SLOT(setPosNoLimit(unsigned)));
+ connect(song, SIGNAL(songChanged(int)), SLOT(songChanged1(int)));
+ connect(song, SIGNAL(songChanged(int)), dlist, SLOT(songChanged(int)));
+ connect(vscroll, SIGNAL(scrollChanged(int)), canvas, SLOT(setYPos(int)));
+ connect(vscroll, SIGNAL(scaleChanged(int)), canvas, SLOT(setYMag(int)));
+ connect(vscroll, SIGNAL(scaleChanged(int)), dlist, SLOT(setYMag(int)));
+ connect(hscroll, SIGNAL(scrollChanged(int)), canvas, SLOT(setXPos(int)));
+ connect(hscroll, SIGNAL(scaleChanged(int)), canvas, SLOT(setXMag(int)));
+ connect(srec, SIGNAL(toggled(bool)), canvas, SLOT(setSteprec(bool)));
+ connect(midiin, SIGNAL(toggled(bool)), canvas, SLOT(setMidiin(bool)));
+
+ connect(vscroll, SIGNAL(scrollChanged(int)), dlist, SLOT(setYPos(int)));
+ connect(hscroll, SIGNAL(scrollChanged(int)), time, SLOT(setXPos(int)));
+ connect(hscroll, SIGNAL(scaleChanged(int)), time, SLOT(setXMag(int)));
+
+ connect(tools2, SIGNAL(toolChanged(int)), canvas, SLOT(setTool(int)));
+
+ connect(canvas, SIGNAL(selectionChanged(int, Event&, Part*)), this,
+ SLOT(setSelection(int, Event&, Part*)));
+ connect(canvas, SIGNAL(followEvent(int)), SLOT(follow(int)));
+
+ connect(hscroll, SIGNAL(scaleChanged(int)), SLOT(updateHScrollRange()));
+ setCaption(canvas->getCaption());
+
+ updateHScrollRange();
+
+ // connect toolbar
+ connect(canvas, SIGNAL(timeChanged(unsigned)), SLOT(setTime(unsigned)));
+ connect(time, SIGNAL(timeChanged(unsigned)), SLOT(setTime(unsigned)));
+ connect(toolbar, SIGNAL(quantChanged(int)), SLOT(setQuant(int)));
+ connect(toolbar, SIGNAL(rasterChanged(int)), SLOT(setRaster(int)));
+ connect(toolbar, SIGNAL(soloChanged(bool)), SLOT(soloChanged(bool)));
+ connect(info, SIGNAL(valueChanged(NoteInfo::ValType, int)), SLOT(noteinfoChanged(NoteInfo::ValType, int)));
+
+ connect(ctrl, SIGNAL(clicked()), SLOT(addCtrl()));
+
+ QClipboard* cb = QApplication::clipboard();
+ connect(cb, SIGNAL(dataChanged()), SLOT(clipboardChanged()));
+
+ clipboardChanged(); // enable/disable "Paste"
+ selectionChanged(); // enable/disable "Copy" & "Paste"
+ initShortcuts();
+
+ const Pos cpos=song->cPos();
+ canvas->setPos(0, cpos.tick(), true);
+ canvas->selectAtTick(cpos.tick());
+ //canvas->selectFirst();
+
+ if(canvas->track())
+ toolbar->setSolo(canvas->track()->solo());
+
+ unsigned pos;
+ if(initPos >= MAXINT)
+ pos = song->cpos();
+ else
+ pos = initPos;
+ if(pos > MAXINT)
+ pos = MAXINT;
+ hscroll->setOffset((int)pos);
+ }
+
+//---------------------------------------------------------
+// songChanged1
+//---------------------------------------------------------
+
+void DrumEdit::songChanged1(int bits)
+ {
+ if (bits & SC_SOLO)
+ {
+ toolbar->setSolo(canvas->track()->solo());
+ return;
+ }
+ songChanged(bits);
+
+ }
+
+//---------------------------------------------------------
+// updateHScrollRange
+//---------------------------------------------------------
+
+void DrumEdit::updateHScrollRange()
+{
+ int s, e;
+ canvas->range(&s, &e);
+ // Show one more measure.
+ e += sigmap.ticksMeasure(e);
+ // Show another quarter measure due to imprecise drawing at canvas end point.
+ e += sigmap.ticksMeasure(e) / 4;
+ // Compensate for drum list, splitter handle, and vscroll widths.
+ e += canvas->rmapxDev(dlist->width() + split2->handleWidth() - vscroll->width());
+ int s1, e1;
+ hscroll->range(&s1, &e1);
+ if(s != s1 || e != e1)
+ hscroll->setRange(s, e);
+}
+
+//---------------------------------------------------------
+// follow
+//---------------------------------------------------------
+
+void DrumEdit::follow(int pos)
+ {
+ int s, e;
+ canvas->range(&s, &e);
+
+ if (pos < e && pos >= s)
+ hscroll->setOffset(pos);
+ if (pos < s)
+ hscroll->setOffset(s);
+ }
+
+//---------------------------------------------------------
+// setTime
+//---------------------------------------------------------
+
+void DrumEdit::setTime(unsigned tick)
+ {
+ toolbar->setTime(tick);
+ time->setPos(3, tick, false);
+ }
+
+//---------------------------------------------------------
+// ~DrumEdit
+//---------------------------------------------------------
+
+DrumEdit::~DrumEdit()
+ {
+ undoRedo->removeFrom(tools);
+ }
+
+//---------------------------------------------------------
+// setSelection
+// update Info Line
+//---------------------------------------------------------
+
+void DrumEdit::setSelection(int tick, Event& e, Part* p)
+ {
+ selEvent = e;
+ selPart = (MidiPart*)p;
+ selTick = tick;
+ info->setEnabled(!e.empty());
+ if (!e.empty()) {
+ info->setValues(tick,
+ selEvent.lenTick(),
+ selEvent.pitch(),
+ selEvent.velo(),
+ selEvent.veloOff());
+ }
+ selectionChanged();
+ }
+
+//---------------------------------------------------------
+// soloChanged
+//---------------------------------------------------------
+
+void DrumEdit::soloChanged(bool flag)
+ {
+ audio->msgSetSolo(canvas->track(), flag);
+ song->update(SC_SOLO);
+ }
+
+//---------------------------------------------------------
+// setRaster
+//---------------------------------------------------------
+
+void DrumEdit::setRaster(int val)
+ {
+ _rasterInit = val;
+ MidiEditor::setRaster(val);
+ canvas->redrawGrid();
+ }
+
+//---------------------------------------------------------
+// setQuant
+//---------------------------------------------------------
+
+void DrumEdit::setQuant(int val)
+ {
+ _quantInit = val;
+ MidiEditor::setQuant(val);
+ }
+
+//---------------------------------------------------------
+// edit currently selected Event
+//---------------------------------------------------------
+
+void DrumEdit::noteinfoChanged(NoteInfo::ValType type, int val)
+ {
+ if (selEvent.empty()) {
+ printf("noteinfoChanged while note is zero %d\n", type);
+ return;
+ }
+ Event event = selEvent.clone();
+ switch (type) {
+ case NoteInfo::VAL_TIME:
+ event.setTick(val - selPart->tick());
+ break;
+ case NoteInfo::VAL_LEN:
+ event.setLenTick(val);
+ break;
+ case NoteInfo::VAL_VELON:
+ event.setVelo(val);
+ break;
+ case NoteInfo::VAL_VELOFF:
+ event.setVeloOff(val);
+ break;
+ case NoteInfo::VAL_PITCH:
+ event.setPitch(val);
+ break;
+ }
+ // Indicate do undo, and do not do port controller values and clone parts.
+ //audio->msgChangeEvent(selEvent, event, selPart);
+ audio->msgChangeEvent(selEvent, event, selPart, true, false, false);
+ }
+
+//---------------------------------------------------------
+// writeStatus
+//---------------------------------------------------------
+
+void DrumEdit::writeStatus(int level, Xml& xml) const
+ {
+ writePartList(level, xml);
+ xml.tag(level++, "drumedit");
+ MidiEditor::writeStatus(level, xml);
+
+ for (std::list<CtrlEdit*>::const_iterator i = ctrlEditList.begin();
+ i != ctrlEditList.end(); ++i) {
+ (*i)->writeStatus(level, xml);
+ }
+
+ split1->writeStatus(level, xml);
+ split2->writeStatus(level, xml);
+
+ header->writeStatus(level, xml);
+ xml.intTag(level, "steprec", canvas->steprec());
+ xml.intTag(level, "midiin", canvas->midiin());
+ xml.intTag(level, "xpos", hscroll->pos());
+ xml.intTag(level, "xmag", hscroll->mag());
+ xml.intTag(level, "ypos", vscroll->pos());
+ xml.intTag(level, "ymag", vscroll->mag());
+ xml.tag(level, "/drumedit");
+ }
+
+//---------------------------------------------------------
+// readStatus
+//---------------------------------------------------------
+
+void DrumEdit::readStatus(Xml& xml)
+ {
+ for (;;) {
+ Xml::Token token = xml.parse();
+ const QString& tag = xml.s1();
+ switch (token) {
+ case Xml::Error:
+ case Xml::End:
+ return;
+ case Xml::TagStart:
+ if (tag == "steprec") {
+ int val = xml.parseInt();
+ canvas->setSteprec(val);
+ srec->setOn(val);
+ }
+ else if (tag == "midiin") {
+ int val = xml.parseInt();
+ canvas->setMidiin(val);
+ midiin->setOn(val);
+ }
+ else if (tag == "ctrledit") {
+ CtrlEdit* ctrl = addCtrl();
+ ctrl->readStatus(xml);
+ }
+ else if (tag == split1->name())
+ split1->readStatus(xml);
+ else if (tag == split2->name())
+ split2->readStatus(xml);
+ else if (tag == "midieditor")
+ MidiEditor::readStatus(xml);
+ else if (tag == header->name())
+ header->readStatus(xml);
+ else if (tag == "xmag")
+ hscroll->setMag(xml.parseInt());
+ else if (tag == "xpos")
+ hscroll->setPos(xml.parseInt());
+ else if (tag == "ymag")
+ vscroll->setMag(xml.parseInt());
+ else if (tag == "ypos")
+ vscroll->setPos(xml.parseInt());
+ else
+ xml.unknown("DrumEdit");
+ break;
+ case Xml::TagEnd:
+ if (tag == "drumedit") {
+ _quantInit = _quant;
+ _rasterInit = _raster;
+ toolbar->setRaster(_raster);
+ toolbar->setQuant(_quant);
+ canvas->redrawGrid();
+ return;
+ }
+ default:
+ break;
+ }
+ }
+ }
+
+//---------------------------------------------------------
+// readConfiguration
+//---------------------------------------------------------
+
+void DrumEdit::readConfiguration(Xml& xml)
+ {
+ for (;;) {
+ Xml::Token token = xml.parse();
+ const QString& tag = xml.s1();
+ switch (token) {
+ case Xml::Error:
+ case Xml::End:
+ return;
+ case Xml::TagStart:
+ if (tag == "quant")
+ _quantInit = xml.parseInt();
+ else if (tag == "raster")
+ _rasterInit = xml.parseInt();
+ else if (tag == "width")
+ _widthInit = xml.parseInt();
+ else if (tag == "height")
+ _heightInit = xml.parseInt();
+ else if (tag == "dcanvaswidth")
+ _dcanvasWidthInit = xml.parseInt();
+ else if (tag == "dlistwidth")
+ _dlistWidthInit = xml.parseInt();
+ else if (tag == "to") {
+ _toInit = xml.parseInt();
+ }
+ else
+ xml.unknown("DrumEdit");
+ break;
+ case Xml::TagEnd:
+ if (tag == "drumedit") {
+ return;
+ }
+ default:
+ break;
+ }
+ }
+ }
+
+//---------------------------------------------------------
+// writeConfiguration
+//---------------------------------------------------------
+
+void DrumEdit::writeConfiguration(int level, Xml& xml)
+ {
+ xml.tag(level++, "drumedit");
+ xml.intTag(level, "quant", _quantInit);
+ xml.intTag(level, "raster", _rasterInit);
+ xml.intTag(level, "width", _widthInit);
+ xml.intTag(level, "height", _heightInit);
+ xml.intTag(level, "dlistwidth", _dlistWidthInit);
+ xml.intTag(level, "dcanvaswidth", _dcanvasWidthInit);
+ xml.intTag(level, "to", _toInit);
+ xml.tag(level, "/drumedit");
+ }
+
+//---------------------------------------------------------
+// load
+//---------------------------------------------------------
+
+void DrumEdit::load()
+ {
+ //QString fn = getOpenFileName("drummaps", map_file_pattern,
+ QString fn = getOpenFileName("drummaps", drum_map_file_pattern,
+ this, tr("Muse: Load Drum Map"), 0);
+ if (fn.isEmpty())
+ return;
+ bool popenFlag;
+ FILE* f = fileOpen(this, fn, QString(".map"), "r", popenFlag, true);
+ if (f == 0)
+ return;
+
+ Xml xml(f);
+ int mode = 0;
+ for (;;) {
+ Xml::Token token = xml.parse();
+ const QString& tag = xml.s1();
+ switch (token) {
+ case Xml::Error:
+ case Xml::End:
+ return;
+ case Xml::TagStart:
+ if (mode == 0 && tag == "muse")
+ mode = 1;
+ else if (mode == 1 && tag == "drummap") {
+ readDrumMap(xml, true);
+ mode = 0;
+ }
+ else
+ xml.unknown("DrumEdit");
+ break;
+ case Xml::Attribut:
+ break;
+ case Xml::TagEnd:
+ if (!mode && tag == "muse")
+ goto ende;
+ default:
+ break;
+ }
+ }
+ende:
+ if (popenFlag)
+ pclose(f);
+ else
+ fclose(f);
+ dlist->redraw();
+ canvas->redraw();
+ }
+
+//---------------------------------------------------------
+// save
+//---------------------------------------------------------
+
+void DrumEdit::save()
+ {
+ //QString fn = getSaveFileName(QString("drummaps"), map_file_pattern,
+ QString fn = getSaveFileName(QString("drummaps"), drum_map_file_save_pattern,
+ this, tr("MusE: Store Drum Map"));
+ if (fn.isEmpty())
+ return;
+ bool popenFlag;
+ FILE* f = fileOpen(this, fn, QString(".map"), "w", popenFlag, false, true);
+ if (f == 0)
+ return;
+ Xml xml(f);
+ xml.header();
+ xml.tag(0, "muse version=\"1.0\"");
+ writeDrumMap(1, xml, true);
+ xml.tag(1, "/muse");
+
+ if (popenFlag)
+ pclose(f);
+ else
+ fclose(f);
+ }
+
+//---------------------------------------------------------
+// reset
+//---------------------------------------------------------
+
+void DrumEdit::reset()
+{
+ if(QMessageBox::warning(this, tr("Drum map"),
+ tr("Reset the drum map with GM defaults?"),
+ QMessageBox::Ok | QMessageBox::Default, QMessageBox::Cancel | QMessageBox::Escape, Qt::NoButton) == QMessageBox::Ok)
+ {
+ resetGMDrumMap();
+ dlist->redraw();
+ canvas->redraw();
+ }
+}
+
+//---------------------------------------------------------
+// cmd
+// pulldown menu commands
+//---------------------------------------------------------
+
+void DrumEdit::cmd(int cmd)
+ {
+ switch(cmd) {
+ case DrumCanvas::CMD_LOAD:
+ load();
+ break;
+ case DrumCanvas::CMD_SAVE:
+ save();
+ break;
+ case DrumCanvas::CMD_RESET:
+ reset();
+ break;
+ default:
+ ((DrumCanvas*)(canvas))->cmd(cmd);
+ break;
+ }
+ }
+
+//---------------------------------------------------------
+// clipboardChanged
+//---------------------------------------------------------
+
+void DrumEdit::clipboardChanged()
+ {
+ QMimeSource* ms = QApplication::clipboard()->data(QClipboard::Clipboard);
+ if (ms && ms->format(0)) {
+ bool flag = strcmp(ms->format(0), "text/eventlist;charset=UTF-8") == 0;
+ menuEdit->setItemEnabled(DrumCanvas::CMD_PASTE, flag);
+ }
+ }
+
+//---------------------------------------------------------
+// selectionChanged
+//---------------------------------------------------------
+
+void DrumEdit::selectionChanged()
+ {
+ bool flag = canvas->selectionSize() > 0;
+ menuEdit->setItemEnabled(DrumCanvas::CMD_CUT, flag);
+ menuEdit->setItemEnabled(DrumCanvas::CMD_COPY, flag);
+ menuEdit->setItemEnabled(DrumCanvas::CMD_DEL, flag);
+ }
+
+//---------------------------------------------------------
+// addCtrl
+//---------------------------------------------------------
+
+CtrlEdit* DrumEdit::addCtrl()
+ {
+ CtrlEdit* ctrlEdit = new CtrlEdit(split1, this, xscale, true, "drumCtrlEdit");
+ connect(hscroll, SIGNAL(scrollChanged(int)), ctrlEdit, SLOT(setXPos(int)));
+ connect(hscroll, SIGNAL(scaleChanged(int)), ctrlEdit, SLOT(setXMag(int)));
+ connect(ctrlEdit, SIGNAL(timeChanged(unsigned)), SLOT(setTime(unsigned)));
+ connect(ctrlEdit, SIGNAL(destroyedCtrl(CtrlEdit*)), SLOT(removeCtrl(CtrlEdit*)));
+ connect(ctrlEdit, SIGNAL(yposChanged(int)), toolbar, SLOT(setInt(int)));
+ connect(tools2, SIGNAL(toolChanged(int)), ctrlEdit, SLOT(setTool(int)));
+ connect(dlist, SIGNAL(curDrumInstrumentChanged(int)), SLOT(setCurDrumInstrument(int)));
+
+ //printf("DrumEdit::addCtrl curDrumInstrument:%d\n", dlist->getSelectedInstrument());
+
+ setCurDrumInstrument(dlist->getSelectedInstrument());
+
+ // p3.3.44
+ ctrlEdit->setTool(tools2->curTool());
+
+ ctrlEdit->setXPos(hscroll->pos());
+ ctrlEdit->setXMag(hscroll->getScaleValue());
+
+ if(split1w1)
+ {
+ split2->setCollapsible(split1w1, false);
+ split1w1->setMinimumWidth(CTRL_PANEL_FIXED_WIDTH);
+ }
+ ctrlEdit->setCanvasWidth(canvas->width());
+
+ ctrlEdit->show();
+ ctrlEditList.push_back(ctrlEdit);
+ return ctrlEdit;
+ }
+
+//---------------------------------------------------------
+// removeCtrl
+//---------------------------------------------------------
+
+void DrumEdit::removeCtrl(CtrlEdit* ctrl)
+ {
+ for (std::list<CtrlEdit*>::iterator i = ctrlEditList.begin();
+ i != ctrlEditList.end(); ++i) {
+ if (*i == ctrl) {
+ ctrlEditList.erase(i);
+ break;
+ }
+ }
+
+ if(split1w1)
+ {
+ if(ctrlEditList.empty())
+ {
+ split1w1->setMinimumWidth(0);
+ split2->setCollapsible(split1w1, true);
+ }
+ }
+ }
+//---------------------------------------------------------
+// newCanvasWidth
+//---------------------------------------------------------
+
+void DrumEdit::newCanvasWidth(int w)
+ {
+ int nw = w + (vscroll->width() - 18); // 18 is the fixed width of the CtlEdit VScale widget.
+ if(nw < 1)
+ nw = 1;
+
+ for (std::list<CtrlEdit*>::iterator i = ctrlEditList.begin();
+ i != ctrlEditList.end(); ++i) {
+ // Changed by Tim. p3.3.7
+ //(*i)->setCanvasWidth(w);
+ (*i)->setCanvasWidth(nw);
+ }
+
+ updateHScrollRange();
+ }
+
+//---------------------------------------------------------
+// resizeEvent
+//---------------------------------------------------------
+
+void DrumEdit::resizeEvent(QResizeEvent* ev)
+ {
+ QWidget::resizeEvent(ev);
+ _widthInit = ev->size().width();
+ _heightInit = ev->size().height();
+
+ //TODO: Make the dlist not expand/shrink, but the canvas instead
+ }
+
+
+//---------------------------------------------------------
+// configChanged
+//---------------------------------------------------------
+
+void DrumEdit::configChanged()
+ {
+ initShortcuts();
+ }
+
+static int rasterTable[] = {
+ //-9----8- 7 6 5 4 3(1/4) 2 1
+ 4, 8, 16, 32, 64, 128, 256, 512, 1024, // triple
+ 6, 12, 24, 48, 96, 192, 384, 768, 1536,
+ 9, 18, 36, 72, 144, 288, 576, 1152, 2304 // dot
+ };
+
+//---------------------------------------------------------
+// keyPressEvent
+//---------------------------------------------------------
+void DrumEdit::keyPressEvent(QKeyEvent* event)
+ {
+ DrumCanvas* dc = (DrumCanvas*)canvas;
+ int index = 0;
+ int n = sizeof(rasterTable);
+ for (; index < n; ++index)
+ if (rasterTable[index] == raster())
+ break;
+ int off = (index / 9) * 9;
+ index = index % 9;
+ int val;
+ int key = event->key();
+
+ if (event->state() & Qt::ShiftButton)
+ key += Qt::SHIFT;
+ if (event->state() & Qt::AltButton)
+ key += Qt::ALT;
+ if (event->state() & Qt::ControlButton)
+ key+= Qt::CTRL;
+
+ if (key == Qt::Key_Escape) {
+ close();
+ return;
+ }
+ else if (key == Qt::Key_Up) {
+ dlist->setCurDrumInstrument(dlist->getSelectedInstrument()-1);
+ dlist->redraw();
+ return;
+ }
+ else if (key == Qt::Key_F2) {
+ dlist->lineEdit(dlist->getSelectedInstrument(),(int)DList::COL_NAME);
+ return;
+ }
+ else if (key == Qt::Key_Down) {
+ dlist->setCurDrumInstrument(dlist->getSelectedInstrument()+1);
+ dlist->redraw();
+ return;
+ }
+
+ else if (key == shortcuts[SHRT_POS_INC].key) {
+ dc->cmd(DrumCanvas::CMD_RIGHT);
+ return;
+ }
+ else if (key == shortcuts[SHRT_POS_DEC].key) {
+ dc->cmd(DrumCanvas::CMD_LEFT);
+ return;
+ }
+
+ else if (key == shortcuts[SHRT_TOOL_POINTER].key) {
+ tools2->set(PointerTool);
+ return;
+ }
+ else if (key == shortcuts[SHRT_TOOL_PENCIL].key) {
+ tools2->set(PencilTool);
+ return;
+ }
+ else if (key == shortcuts[SHRT_TOOL_RUBBER].key) {
+ tools2->set(RubberTool);
+ return;
+ }
+ else if (key == shortcuts[SHRT_ZOOM_IN].key) {
+ int mag = hscroll->mag();
+ int zoomlvl = ScrollScale::getQuickZoomLevel(mag);
+ if (zoomlvl < 23)
+ zoomlvl++;
+
+ int newmag = ScrollScale::convertQuickZoomLevelToMag(zoomlvl);
+ hscroll->setMag(newmag);
+ //printf("mag = %d zoomlvl = %d newmag = %d\n", mag, zoomlvl, newmag);
+ return;
+ }
+ else if (key == shortcuts[SHRT_ZOOM_OUT].key) {
+ int mag = hscroll->mag();
+ int zoomlvl = ScrollScale::getQuickZoomLevel(mag);
+ if (zoomlvl > 1)
+ zoomlvl--;
+
+ int newmag = ScrollScale::convertQuickZoomLevelToMag(zoomlvl);
+ hscroll->setMag(newmag);
+ //printf("mag = %d zoomlvl = %d newmag = %d\n", mag, zoomlvl, newmag);
+ return;
+ }
+ else if (key == shortcuts[SHRT_SCROLL_LEFT].key) {
+ int pos = hscroll->pos() - config.division;
+ if (pos < 0)
+ pos = 0;
+ hscroll->setPos(pos);
+ return;
+ }
+ else if (key == shortcuts[SHRT_SCROLL_RIGHT].key) {
+ int pos = hscroll->pos() + config.division;
+ hscroll->setPos(pos);
+ return;
+ }
+
+ /*
+ else if (key == shortcuts[SHRT_INSERT_AT_LOCATION].key) {
+ pc->pianoCmd(CMD_INSERT);
+ return;
+ }
+ */
+ else if (key == shortcuts[SHRT_SET_QUANT_1].key)
+ val = rasterTable[8 + off];
+ else if (key == shortcuts[SHRT_SET_QUANT_2].key)
+ val = rasterTable[7 + off];
+ else if (key == shortcuts[SHRT_SET_QUANT_3].key)
+ val = rasterTable[6 + off];
+ else if (key == shortcuts[SHRT_SET_QUANT_4].key)
+ val = rasterTable[5 + off];
+ else if (key == shortcuts[SHRT_SET_QUANT_5].key)
+ val = rasterTable[4 + off];
+ else if (key == shortcuts[SHRT_SET_QUANT_6].key)
+ val = rasterTable[3 + off];
+ else if (key == shortcuts[SHRT_SET_QUANT_7].key)
+ val = rasterTable[2 + off];
+ else if (key == shortcuts[SHRT_TOGGLE_TRIOL].key)
+ val = rasterTable[index + ((off == 0) ? 9 : 0)];
+ /*
+ else if (key == shortcuts[SHRT_EVENT_COLOR].key) {
+ if (colorMode == 0)
+ colorMode = 1;
+ else if (colorMode == 1)
+ colorMode = 2;
+ else
+ colorMode = 0;
+ setEventColorMode(colorMode);
+ return;
+ }*/
+ else if (key == shortcuts[SHRT_TOGGLE_PUNCT].key)
+ val = rasterTable[index + ((off == 18) ? 9 : 18)];
+
+ else if (key == shortcuts[SHRT_TOGGLE_PUNCT2].key) {//CDW
+ if ((off == 18) && (index > 2)) {
+ val = rasterTable[index + 9 - 1];
+ }
+ else if ((off == 9) && (index < 8)) {
+ val = rasterTable[index + 18 + 1];
+ }
+ else
+ return;
+ }
+ else { //Default:
+ event->ignore();
+ return;
+ }
+ setQuant(val);
+ setRaster(val);
+ toolbar->setQuant(_quant);
+ toolbar->setRaster(_raster);
+ }
+
+
+
+//---------------------------------------------------------
+// initShortcuts
+//---------------------------------------------------------
+
+void DrumEdit::initShortcuts()
+ {
+ menuEdit->setAccel(shortcuts[SHRT_CUT].key, DrumCanvas::CMD_CUT);
+ menuEdit->setAccel(shortcuts[SHRT_COPY].key, DrumCanvas::CMD_COPY);;
+ menuEdit->setAccel(shortcuts[SHRT_PASTE].key, DrumCanvas::CMD_PASTE);
+ menuEdit->setAccel(shortcuts[SHRT_DELETE].key, DrumCanvas::CMD_DEL);
+ menuFile->setAccel(shortcuts[SHRT_OPEN].key, DrumCanvas::CMD_LOAD);
+ menuFile->setAccel(shortcuts[SHRT_SAVE].key, DrumCanvas::CMD_SAVE);
+ menuFunctions->setAccel(shortcuts[SHRT_FIXED_LEN].key, DrumCanvas::CMD_FIXED_LEN);
+ menuFunctions->setAccel(shortcuts[SHRT_MODIFY_VELOCITY].key, DrumCanvas::CMD_MODIFY_VELOCITY);
+ menuSelect->setAccel(shortcuts[SHRT_SELECT_ALL].key, DrumCanvas::CMD_SELECT_ALL);
+ menuSelect->setAccel(shortcuts[SHRT_SELECT_NONE].key, DrumCanvas::CMD_SELECT_NONE);
+ menuSelect->setAccel(shortcuts[SHRT_SELECT_INVERT].key, DrumCanvas::CMD_SELECT_INVERT);
+ menuSelect->setAccel(shortcuts[SHRT_SELECT_ILOOP].key, DrumCanvas::CMD_SELECT_ILOOP);
+ menuSelect->setAccel(shortcuts[SHRT_SELECT_OLOOP].key, DrumCanvas::CMD_SELECT_OLOOP);
+
+ menuSelect->setAccel(shortcuts[SHRT_SELECT_PREV_PART].key, DrumCanvas::CMD_SELECT_PREV_PART);
+ menuSelect->setAccel(shortcuts[SHRT_SELECT_NEXT_PART].key, DrumCanvas::CMD_SELECT_NEXT_PART);
+ }
+
+//---------------------------------------------------------
+// execDeliveredScript
+//---------------------------------------------------------
+void DrumEdit::execDeliveredScript(int id)
+{
+ //QString scriptfile = QString(INSTPREFIX) + SCRIPTSSUFFIX + deliveredScriptNames[id];
+ QString scriptfile = song->getScriptPath(id, true);
+ song->executeScript(scriptfile.latin1(), parts(), quant(), true);
+}
+
+//---------------------------------------------------------
+// execUserScript
+//---------------------------------------------------------
+void DrumEdit::execUserScript(int id)
+{
+ QString scriptfile = song->getScriptPath(id, false);
+ song->executeScript(scriptfile.latin1(), parts(), quant(), true);
+}
+
diff --git a/muse2/muse/midiedit/drumedit.h b/muse2/muse/midiedit/drumedit.h
new file mode 100644
index 00000000..5043412f
--- /dev/null
+++ b/muse2/muse/midiedit/drumedit.h
@@ -0,0 +1,151 @@
+//=========================================================
+// MusE
+// Linux Music Editor
+// $Id: drumedit.h,v 1.9.2.7 2009/11/16 11:29:33 lunar_shuttle Exp $
+// (C) Copyright 1999 Werner Schweer (ws@seh.de)
+//=========================================================
+
+#ifndef __DRUM_EDIT_H__
+#define __DRUM_EDIT_H__
+
+#include <qwidget.h>
+#include <q3mainwindow.h>
+#include <qtooltip.h>
+#include <q3whatsthis.h>
+//Added by qt3to4:
+#include <QResizeEvent>
+#include <QLabel>
+#include <QKeyEvent>
+#include <Q3PopupMenu>
+#include <QCloseEvent>
+
+#include <values.h>
+#include "midieditor.h"
+#include "noteinfo.h"
+#include "cobject.h"
+#include "tools.h"
+#include "header.h"
+#include "shortcuts.h"
+#include "event.h"
+
+class MidiPart;
+class QLabel;
+class DrumCanvas;
+class ScrollScale;
+class ScoreConfig;
+class QToolButton;
+class MTScale;
+class Splitter;
+class PartList;
+class Toolbar1;
+class CtrlCanvas;
+class Xml;
+class Q3PopupMenu;
+class DList;
+class Header;
+class CtrlEdit;
+class Part;
+class SNode;
+
+//---------------------------------------------------------
+// DWhatsThis
+//---------------------------------------------------------
+
+class DWhatsThis : public Q3WhatsThis {
+ Header* header;
+ protected:
+ QString text(const QPoint&);
+ public:
+ DWhatsThis(QWidget* parent, Header* h) : Q3WhatsThis(parent) {
+ header = h;
+ }
+ };
+
+//----------------------------------------------------------
+// DHeaderTip
+//----------------------------------------------------------
+
+class DHeaderTip { // : public QToolTip { ddskrjo
+ public:
+ DHeaderTip(QWidget * parent) {} // : QToolTip(parent) {} ddskrjo
+ virtual ~DHeaderTip(){}
+ protected:
+ void maybeTip(const QPoint &);
+ };
+
+//---------------------------------------------------------
+// DrumEdit
+//---------------------------------------------------------
+
+class DrumEdit : public MidiEditor {
+ Event selEvent;
+ MidiPart* selPart;
+ int selTick;
+ Q3PopupMenu* menuEdit, *menuFunctions, *menuFile, *menuSelect;
+
+ NoteInfo* info;
+ QToolButton* srec;
+ QToolButton* midiin;
+ EditToolBar* tools2;
+
+ Toolbar1* toolbar;
+ Splitter* split1;
+ Splitter* split2;
+ QWidget* split1w1;
+ DList* dlist;
+ Header* header;
+ Q3ToolBar* tools;
+
+ static int _quantInit, _rasterInit;
+ static int _widthInit, _heightInit;
+ static int _dlistWidthInit, _dcanvasWidthInit;
+
+ static int _toInit; //Used in function dialog for applying modification to selection
+ Q_OBJECT
+ void initShortcuts();
+
+ virtual void closeEvent(QCloseEvent*);
+ QWidget* genToolbar(QWidget* parent);
+ virtual void resizeEvent(QResizeEvent*);
+ virtual void keyPressEvent(QKeyEvent*);
+ int _to;//TODO: Make this work
+
+
+ private slots:
+ void setRaster(int);
+ void setQuant(int);
+ void noteinfoChanged(NoteInfo::ValType type, int val);
+ CtrlEdit* addCtrl();
+ void removeCtrl(CtrlEdit* ctrl);
+ void cmd(int);
+ void clipboardChanged(); // enable/disable "Paste"
+ void selectionChanged(); // enable/disable "Copy" & "Paste"
+ void load();
+ void save();
+ void reset();
+ void setTime(unsigned);
+ void follow(int);
+ void newCanvasWidth(int);
+ void configChanged();
+ void songChanged1(int);
+
+ public slots:
+ void setSelection(int, Event&, Part*);
+ void soloChanged(bool); // called by Solo button
+ void execDeliveredScript(int);
+ void execUserScript(int);
+
+ virtual void updateHScrollRange();
+ signals:
+ void deleted(unsigned long);
+
+ public:
+ DrumEdit(PartList*, QWidget* parent = 0, const char* name = 0, unsigned initPos = MAXINT);
+ virtual ~DrumEdit();
+ virtual void readStatus(Xml&);
+ virtual void writeStatus(int, Xml&) const;
+ static void readConfiguration(Xml& xml);
+ static void writeConfiguration(int, Xml&);
+ };
+
+#endif
diff --git a/muse2/muse/midiedit/drummap.cpp b/muse2/muse/midiedit/drummap.cpp
new file mode 100644
index 00000000..46bf2057
--- /dev/null
+++ b/muse2/muse/midiedit/drummap.cpp
@@ -0,0 +1,503 @@
+//=========================================================
+// MusE
+// Linux Music Editor
+// $Id: drummap.cpp,v 1.3.2.6 2009/10/29 02:14:37 terminator356 Exp $
+//
+// (C) Copyright 1999/2000 Werner Schweer (ws@seh.de)
+//=========================================================
+
+#include "audio.h"
+#include "drummap.h"
+#include "xml.h"
+#include "song.h"
+
+char drumOutmap[DRUM_MAPSIZE];
+char drumInmap[128];
+
+DrumMap drumMap[DRUM_MAPSIZE];
+
+//---------------------------------------------------------
+// GM default drum map
+//---------------------------------------------------------
+
+const DrumMap blankdm = { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 127, 127, false };
+
+const DrumMap idrumMap[DRUM_MAPSIZE] = {
+ { QString("Acoustic Bass Drum"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 35, 35, false },
+ { QString("Bass Drum 1"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 36, 36, false },
+ { QString("Side Stick"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 37, 37, false },
+ { QString("Acoustic Snare"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 38, 38, false },
+ { QString("Hand Clap"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 39, 39, false },
+ { QString("Electric Snare"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 40, 40, false },
+ { QString("Low Floor Tom"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 41, 41, false },
+ { QString("Closed Hi-Hat"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 42, 42, false },
+ { QString("High Floor Tom"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 43, 43, false },
+ { QString("Pedal Hi-Hat"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 44, 44, false },
+ { QString("Low Tom"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 45, 45, false },
+ { QString("Open Hi-Hat"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 46, 46, false },
+ { QString("Low-Mid Tom"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 47, 47, false },
+ { QString("Hi-Mid Tom"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 48, 48, false },
+ { QString("Crash Cymbal 1"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 49, 49, false },
+ { QString("High Tom"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 50, 50, false },
+
+ { QString("Ride Cymbal 1"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 51, 51, false },
+ { QString("Chinese Cymbal"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 52, 52, false },
+ { QString("Ride Bell"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 53, 53, false },
+ { QString("Tambourine"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 54, 54, false },
+ { QString("Splash Cymbal"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 55, 55, false },
+ { QString("Cowbell"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 56, 56, false },
+ { QString("Crash Cymbal 2"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 57, 57, false },
+ { QString("Vibraslap"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 58, 58, false },
+ { QString("Ride Cymbal 2"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 59, 59, false },
+ { QString("Hi Bongo"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 60, 60, false },
+ { QString("Low Bongo"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 61, 61, false },
+ { QString("Mute Hi Conga"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 62, 62, false },
+ { QString("Open Hi Conga"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 63, 63, false },
+ { QString("Low Conga"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 64, 64, false },
+ { QString("High Timbale"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 65, 65, false },
+ { QString("Low Timbale"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 66, 66, false },
+
+ { QString("High Agogo"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 67, 67, false },
+ { QString("Low Agogo"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 68, 68, false },
+ { QString("Cabasa"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 69, 69, false },
+ { QString("Maracas"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 70, 70, false },
+ { QString("Short Whistle"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 71, 71, false },
+ { QString("Long Whistle"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 72, 72, false },
+ { QString("Short Guiro"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 73, 73, false },
+ { QString("Long Guiro"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 74, 74, false },
+ { QString("Claves"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 75, 75, false },
+ { QString("Hi Wood Block"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 76, 76, false },
+ { QString("Low Wood Block"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 77, 77, false },
+ { QString("Mute Cuica"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 78, 78, false },
+ { QString("Open Cuica"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 79, 79, false },
+ { QString("Mute Triangle"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 80, 80, false },
+ { QString("Open Triangle"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 81, 81, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 82, 82, false },
+
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 83, 83, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 84, 84, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 85, 85, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 86, 86, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 87, 87, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 88, 88, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 89, 89, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 90, 90, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 91, 91, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 92, 92, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 93, 93, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 94, 94, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 95, 95, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 96, 96, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 97, 97, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 98, 98, false },
+
+ /*
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 83, 83, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 84, 84, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 85, 85, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 86, 86, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 87, 87, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 88, 88, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 89, 89, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 90, 90, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 91, 91, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 92, 92, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 93, 93, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 94, 94, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 95, 95, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 96, 96, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 97, 97, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 98, 98, false },
+
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 83, 83, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 84, 84, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 85, 85, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 86, 86, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 87, 87, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 88, 88, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 89, 89, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 90, 90, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 91, 91, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 92, 92, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 93, 93, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 94, 94, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 95, 95, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 96, 96, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 97, 97, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 98, 98, false },
+
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 83, 83, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 84, 84, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 85, 85, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 86, 86, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 87, 87, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 88, 88, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 89, 89, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 90, 90, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 91, 91, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 92, 92, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 93, 93, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 94, 94, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 95, 95, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 96, 96, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 97, 97, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 98, 98, false },
+
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 83, 83, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 84, 84, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 85, 85, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 86, 86, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 87, 87, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 88, 88, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 89, 89, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 90, 90, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 91, 91, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 92, 92, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 93, 93, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 94, 94, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 95, 95, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 96, 96, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 97, 97, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 98, 98, false }
+ };
+ */
+
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 99, 99, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 100, 100, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 101, 101, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 102, 102, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 103, 103, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 104, 104, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 105, 105, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 106, 106, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 107, 107, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 108, 108, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 109, 109, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 110, 110, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 111, 111, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 112, 112, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 113, 113, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 114, 114, false },
+
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 115, 115, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 116, 116, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 117, 117, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 118, 118, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 119, 119, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 120, 120, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 121, 121, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 122, 122, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 123, 123, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 124, 124, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 125, 125, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 126, 126, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 127, 127, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 0, 0, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 1, 1, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 2, 2, false },
+
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 3, 3, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 4, 4, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 5, 5, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 6, 6, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 7, 7, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 8, 8, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 9, 9, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 10, 10, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 11, 11, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 12, 12, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 13, 13, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 14, 14, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 15, 15, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 16, 16, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 17, 17, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 18, 18, false },
+
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 19, 19, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 20, 20, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 21, 21, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 22, 22, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 23, 23, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 24, 24, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 25, 25, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 26, 26, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 27, 27, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 28, 28, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 29, 29, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 30, 30, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 31, 31, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 32, 32, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 33, 33, false },
+ { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 34, 34, false }
+ };
+
+
+//---------------------------------------------------------
+// initDrumMap
+// populate Inmap and Outmap
+//---------------------------------------------------------
+
+void initDrumMap()
+ {
+ for (int i = 0; i < DRUM_MAPSIZE; ++i) {
+ DrumMap d = drumMap[i];
+ //Make sure we're not overwriting any values loaded
+ //On init, all these values are zero. If so, just set the drummap entry to the initial drummap entry.
+ if (!(d.vol || d.len || d.channel || d.port || d.lv1 || d.lv2 || d.lv3 || d.lv4 || d.enote || d.anote || d.mute))
+ drumMap[i] = idrumMap[i];
+ }
+ //Finally, setup the inMap, outMap-values
+ memset(drumInmap, 0, sizeof(drumInmap));
+ memset(drumOutmap, 0, sizeof(drumOutmap));
+ for (int i = 0; i < DRUM_MAPSIZE; ++i) {
+ drumInmap[(unsigned int)(drumMap[i].enote)] = i;
+ drumOutmap[(unsigned int)(drumMap[i].anote)] = i;
+ }
+ }
+
+//---------------------------------------------------------
+// resetGMDrumMap
+//---------------------------------------------------------
+
+void resetGMDrumMap()
+ {
+ audio->msgIdle(true);
+ // Delete all port controller events.
+ //audio->msgChangeAllPortDrumCtrlEvents(false);
+ song->changeAllPortDrumCtrlEvents(false);
+
+ for(int i = 0; i < DRUM_MAPSIZE; ++i)
+ drumMap[i] = idrumMap[i];
+ memset(drumInmap, 0, sizeof(drumInmap));
+ memset(drumOutmap, 0, sizeof(drumOutmap));
+ for (int i = 0; i < DRUM_MAPSIZE; ++i) {
+ drumInmap[(unsigned int)(drumMap[i].enote)] = i;
+ drumOutmap[(unsigned int)(drumMap[i].anote)] = i;
+ }
+ // Add all port controller events.
+ //audio->msgChangeAllPortDrumCtrlEvents(true);
+ song->changeAllPortDrumCtrlEvents(true);
+ audio->msgIdle(false);
+ }
+
+//---------------------------------------------------------
+// operator ==
+//---------------------------------------------------------
+
+//bool const DrumMap::operator==(const DrumMap& map) const
+bool DrumMap::operator==(const DrumMap& map) const
+ {
+ return
+ (name == map.name)
+ && vol == map.vol
+ && quant == map.quant
+ && len == map.len
+ && channel == map.channel
+ && port == map.port
+ && lv1 == map.lv1
+ && lv2 == map.lv2
+ && lv3 == map.lv3
+ && lv4 == map.lv4
+ && enote == map.enote
+ && anote == map.anote
+ && mute == map.mute;
+ }
+
+//---------------------------------------------------------
+// writeDrumMap
+//---------------------------------------------------------
+
+void writeDrumMap(int level, Xml& xml, bool external)
+ {
+ xml.tag(level++, "drummap");
+ for (int i = 0; i < DRUM_MAPSIZE; ++i) {
+ DrumMap* dm = &drumMap[i];
+ const DrumMap* idm = &idrumMap[i];
+
+ if (external) {
+ xml.tag(level++, "entry");
+ xml.strTag(level, "name", dm->name);
+ xml.intTag(level, "vol", dm->vol);
+ xml.intTag(level, "quant", dm->quant);
+ xml.intTag(level, "len", dm->len);
+ xml.intTag(level, "channel", dm->channel);
+ xml.intTag(level, "port", dm->port);
+ xml.intTag(level, "lv1", dm->lv1);
+ xml.intTag(level, "lv2", dm->lv2);
+ xml.intTag(level, "lv3", dm->lv3);
+ xml.intTag(level, "lv4", dm->lv4);
+ xml.intTag(level, "enote", dm->enote);
+ xml.intTag(level, "anote", dm->anote);
+ }
+ else {
+ // write only, if entry is different from initial entry
+ if (!external && *dm == *idm)
+ continue;
+ xml.tag(level++, "entry idx=\"%d\"", i);
+ if (dm->name != idm->name)
+ xml.strTag(level, "name", dm->name);
+ if (dm->vol != idm->vol)
+ xml.intTag(level, "vol", dm->vol);
+ if (dm->quant != idm->quant)
+ xml.intTag(level, "quant", dm->quant);
+ if (dm->len != idm->len)
+ xml.intTag(level, "len", dm->len);
+ if (dm->channel != idm->channel)
+ xml.intTag(level, "channel", dm->channel);
+ if (dm->port != idm->port)
+ xml.intTag(level, "port", dm->port);
+ if (dm->lv1 != idm->lv1)
+ xml.intTag(level, "lv1", dm->lv1);
+ if (dm->lv2 != idm->lv2)
+ xml.intTag(level, "lv2", dm->lv2);
+ if (dm->lv3 != idm->lv3)
+ xml.intTag(level, "lv3", dm->lv3);
+ if (dm->lv4 != idm->lv4)
+ xml.intTag(level, "lv4", dm->lv4);
+ if (dm->enote != idm->enote)
+ xml.intTag(level, "enote", dm->enote);
+ if (dm->anote != idm->anote)
+ xml.intTag(level, "anote", dm->anote);
+ if (dm->mute != idm->mute)
+ xml.intTag(level, "mute", dm->mute);
+ }
+ xml.tag(level--, "/entry");
+ }
+ xml.tag(level--, "/drummap");
+ }
+
+//---------------------------------------------------------
+// readDrummapEntry
+//---------------------------------------------------------
+
+static void readDrummapEntry(Xml& xml, DrumMap* dm)
+ {
+
+ for (;;) {
+ Xml::Token token = xml.parse();
+ const QString& tag = xml.s1();
+ switch (token) {
+ case Xml::Error:
+ case Xml::End:
+ return;
+ case Xml::TagStart:
+ if (tag == "name")
+ dm->name = xml.parse(QString("name"));
+ else if (tag == "vol")
+ dm->vol = (unsigned char)xml.parseInt();
+ else if (tag == "quant")
+ dm->quant = xml.parseInt();
+ else if (tag == "len")
+ dm->len = xml.parseInt();
+ else if (tag == "channel")
+ dm->channel = xml.parseInt();
+ else if (tag == "port")
+ dm->port = xml.parseInt();
+ else if (tag == "lv1")
+ dm->lv1 = xml.parseInt();
+ else if (tag == "lv2")
+ dm->lv2 = xml.parseInt();
+ else if (tag == "lv3")
+ dm->lv3 = xml.parseInt();
+ else if (tag == "lv4")
+ dm->lv4 = xml.parseInt();
+ else if (tag == "enote")
+ dm->enote = xml.parseInt();
+ else if (tag == "anote")
+ dm->anote = xml.parseInt();
+ else if (tag == "mute")
+ dm->mute = xml.parseInt();
+ else if (tag == "selected")
+ //; // dm->selected = xml.parseInt();
+ xml.skip(tag);
+ else
+ xml.unknown("DrumMapEntry");
+ break;
+ case Xml::Attribut:
+ if (tag == "idx") {
+ int idx = xml.s2().toInt() & 0x7f;
+ dm = &drumMap[idx];
+
+ }
+ break;
+ case Xml::TagEnd:
+ if (tag == "entry")
+ {
+ return;
+ }
+ default:
+ break;
+ }
+ }
+ }
+
+//---------------------------------------------------------
+// readDrummap
+//---------------------------------------------------------
+
+void readDrumMap(Xml& xml, bool external)
+ {
+ audio->msgIdle(true);
+ // Delete all port controller events.
+ //audio->msgChangeAllPortDrumCtrlEvents(false);
+ song->changeAllPortDrumCtrlEvents(false);
+
+ if (external) {
+ for (int i = 0; i < DRUM_MAPSIZE; ++i)
+ drumMap[i] = blankdm;
+ }
+ else {
+ for (int i = 0; i < DRUM_MAPSIZE; ++i)
+ drumMap[i] = idrumMap[i];
+ }
+ int i = 0;
+ for (;;) {
+ Xml::Token token = xml.parse();
+ const QString& tag = xml.s1();
+ switch (token) {
+ case Xml::Error:
+ case Xml::End:
+ audio->msgIdle(false);
+ return;
+ case Xml::TagStart:
+ if (tag == "entry") {
+ if(i >= DRUM_MAPSIZE)
+ {
+ audio->msgIdle(false);
+ return;
+ }
+ readDrummapEntry(xml, external ? &drumMap[i] : 0);
+ ++i;
+ }
+ else if (tag == "comment")
+ xml.parse();
+ else
+ xml.unknown("DrumMap");
+ break;
+ case Xml::Attribut:
+ break;
+ case Xml::TagEnd:
+ if (tag == "drummap") {
+ memset(drumInmap, 0, sizeof(drumInmap));
+ memset(drumOutmap, 0, sizeof(drumOutmap));
+ for (int i = 0; i < DRUM_MAPSIZE; ++i) {
+ drumInmap[(unsigned int)(drumMap[i].enote)] = i;
+ drumOutmap[(unsigned int)(drumMap[i].anote)] = i;
+ }
+ // Add all port controller events.
+ //audio->msgChangeAllPortDrumCtrlEvents(true);
+ song->changeAllPortDrumCtrlEvents(true);
+
+ audio->msgIdle(false);
+ return;
+ }
+ default:
+ break;
+ }
+ }
+ // Add all port controller events.
+ //audio->msgChangeAllPortDrumCtrlEvents(true);
+ song->changeAllPortDrumCtrlEvents(true);
+ audio->msgIdle(false);
+ }
+
diff --git a/muse2/muse/midiedit/drummap.h b/muse2/muse/midiedit/drummap.h
new file mode 100644
index 00000000..dfe67254
--- /dev/null
+++ b/muse2/muse/midiedit/drummap.h
@@ -0,0 +1,47 @@
+//=========================================================
+// MusE
+// Linux Music Editor
+// $Id: drummap.h,v 1.3.2.3 2009/10/29 02:14:37 terminator356 Exp $
+//
+// (C) Copyright 1999/2000 Werner Schweer (ws@seh.de)
+//=========================================================
+
+#ifndef __DRUMMAP_H__
+#define __DRUMMAP_H__
+
+#include <qstring.h>
+
+class Xml;
+
+//---------------------------------------------------------
+// DrumMap
+//---------------------------------------------------------
+
+struct DrumMap {
+ QString name;
+ unsigned char vol; // playback volume, percent.
+ int quant;
+ int len; // len of event in ticks
+ int channel; // midi channel
+ int port; // midi port
+ char lv1, lv2, lv3, lv4; // velocities
+ char enote, anote; // input note - output note
+ bool mute;
+// bool selected;
+
+ //bool const operator==(const DrumMap& map) const;
+ bool operator==(const DrumMap& map) const;
+ };
+
+#define DRUM_MAPSIZE 128
+
+extern char drumOutmap[DRUM_MAPSIZE];
+extern char drumInmap[DRUM_MAPSIZE];
+extern DrumMap drumMap[DRUM_MAPSIZE];
+extern void initDrumMap();
+extern void writeDrumMap(int level, Xml& xml, bool external);
+extern void readDrumMap(Xml& xml, bool external);
+extern void resetGMDrumMap();
+
+#endif
+
diff --git a/muse2/muse/midiedit/ecanvas.cpp b/muse2/muse/midiedit/ecanvas.cpp
new file mode 100644
index 00000000..7fc7002d
--- /dev/null
+++ b/muse2/muse/midiedit/ecanvas.cpp
@@ -0,0 +1,363 @@
+//=========================================================
+// MusE
+// Linux Music Editor
+// $Id: ecanvas.cpp,v 1.8.2.6 2009/05/03 04:14:00 terminator356 Exp $
+// (C) Copyright 2001 Werner Schweer (ws@seh.de)
+//=========================================================
+
+#include <values.h>
+
+#include "midieditor.h"
+#include "ecanvas.h"
+#include "song.h"
+#include "event.h"
+#include "shortcuts.h"
+//Added by qt3to4:
+#include <QKeyEvent>
+#include <QEvent>
+
+//---------------------------------------------------------
+// EventCanvas
+//---------------------------------------------------------
+
+EventCanvas::EventCanvas(MidiEditor* pr, QWidget* parent, int sx,
+ int sy, const char* name)
+ : Canvas(parent, sx, sy, name)
+ {
+ editor = pr;
+ _steprec = false;
+ _midiin = false;
+ _playEvents = false;
+ curVelo = 70;
+
+ setBg(Qt::white);
+ setAcceptDrops(true);
+ setFocusPolicy(Qt::StrongFocus);
+ setMouseTracking(true);
+
+ curPart = (MidiPart*)(editor->parts()->begin()->second);
+ curPartId = curPart->sn();
+ }
+
+//---------------------------------------------------------
+// getCaption
+//---------------------------------------------------------
+
+QString EventCanvas::getCaption() const
+ {
+ int bar1, bar2, xx;
+ unsigned x;
+ sigmap.tickValues(curPart->tick(), &bar1, &xx, &x);
+ sigmap.tickValues(curPart->tick() + curPart->lenTick(), &bar2, &xx, &x);
+
+ return QString("MusE: Part <") + curPart->name()
+ + QString("> %1-%2").arg(bar1+1).arg(bar2+1);
+ }
+
+//---------------------------------------------------------
+// leaveEvent
+//---------------------------------------------------------
+
+void EventCanvas::leaveEvent(QEvent*)
+ {
+ emit pitchChanged(-1);
+ emit timeChanged(MAXINT);
+ }
+
+//---------------------------------------------------------
+// enterEvent
+//---------------------------------------------------------
+
+void EventCanvas::enterEvent(QEvent*)
+ {
+ emit enterCanvas();
+ }
+
+//---------------------------------------------------------
+// raster
+//---------------------------------------------------------
+
+QPoint EventCanvas::raster(const QPoint& p) const
+ {
+ int x = p.x();
+ if (x < 0)
+ x = 0;
+ x = editor->rasterVal(x);
+ int pitch = y2pitch(p.y());
+ int y = pitch2y(pitch);
+ return QPoint(x, y);
+ }
+
+//---------------------------------------------------------
+// startUndo
+//---------------------------------------------------------
+
+void EventCanvas::startUndo(DragType)
+ {
+ song->startUndo();
+ }
+
+//---------------------------------------------------------
+// endUndo
+//---------------------------------------------------------
+
+void EventCanvas::endUndo(DragType dtype, int flags)
+ {
+ song->endUndo(flags | ((dtype == MOVE_COPY || dtype == MOVE_CLONE)
+ ? SC_EVENT_INSERTED : SC_EVENT_MODIFIED));
+ }
+
+//---------------------------------------------------------
+// mouseMove
+//---------------------------------------------------------
+
+void EventCanvas::mouseMove(const QPoint& pos)
+ {
+ emit pitchChanged(y2pitch(pos.y()));
+ int x = pos.x();
+ emit timeChanged(editor->rasterVal(x));
+ }
+
+//---------------------------------------------------------
+// updateSelection
+//---------------------------------------------------------
+
+void EventCanvas::updateSelection()
+ {
+ song->update(SC_SELECTION);
+ }
+
+//---------------------------------------------------------
+// songChanged(type)
+//---------------------------------------------------------
+
+void EventCanvas::songChanged(int flags)
+ {
+ // Is it simply a midi controller value adjustment? Forget it.
+ if(flags == SC_MIDI_CONTROLLER)
+ return;
+
+ if (flags & ~SC_SELECTION) {
+ items.clear();
+ start_tick = MAXINT;
+ end_tick = 0;
+ curPart = 0;
+ for (iPart p = editor->parts()->begin(); p != editor->parts()->end(); ++p) {
+ MidiPart* part = (MidiPart*)(p->second);
+ if (part->sn() == curPartId)
+ curPart = part;
+ unsigned stick = part->tick();
+ unsigned len = part->lenTick();
+ unsigned etick = stick + len;
+ if (stick < start_tick)
+ start_tick = stick;
+ if (etick > end_tick)
+ end_tick = etick;
+
+ EventList* el = part->events();
+ for (iEvent i = el->begin(); i != el->end(); ++i) {
+ Event e = i->second;
+ // Added by T356. Do not add events which are either past, or extend past the end of the part.
+ //if(e.tick() > len)
+ if(e.endTick() > len)
+ break;
+
+ if (e.isNote()) {
+ addItem(part, e);
+ }
+ }
+ }
+ }
+
+ Event event;
+ MidiPart* part = 0;
+ int x = 0;
+ CItem* nevent = 0;
+
+ int n = 0; // count selections
+ for (iCItem k = items.begin(); k != items.end(); ++k) {
+ Event ev = k->second->event();
+ bool selected = ev.selected();
+ if (selected) {
+ k->second->setSelected(true);
+ ++n;
+ if (!nevent) {
+ nevent = k->second;
+ Event mi = nevent->event();
+ curVelo = mi.velo();
+ }
+ }
+ }
+ start_tick = song->roundDownBar(start_tick);
+ end_tick = song->roundUpBar(end_tick);
+
+ if (n == 1) {
+ x = nevent->x();
+ event = nevent->event();
+ part = (MidiPart*)nevent->part();
+ if (curPart != part) {
+ curPart = part;
+ curPartId = curPart->sn();
+ curPartChanged();
+ }
+ }
+ emit selectionChanged(x, event, part);
+ if (curPart == 0)
+ curPart = (MidiPart*)(editor->parts()->begin()->second);
+ redraw();
+ }
+
+//---------------------------------------------------------
+// selectAtTick
+//---------------------------------------------------------
+void EventCanvas::selectAtTick(unsigned int tick)
+ {
+ //Select note nearest tick, if none selected and there are any
+ if (!items.empty() && selectionSize() == 0) {
+ iCItem i = items.begin();
+ CItem* nearest = i->second;
+
+ while (i != items.end()) {
+ CItem* cur=i->second;
+ unsigned int curtk=abs(cur->x() + cur->part()->tick() - tick);
+ unsigned int neartk=abs(nearest->x() + nearest->part()->tick() - tick);
+
+ if (curtk < neartk) {
+ nearest=cur;
+ }
+
+ i++;
+ }
+
+ if (!nearest->isSelected()) {
+ selectItem(nearest, true);
+ songChanged(SC_SELECTION);
+ }
+ }
+ }
+
+//---------------------------------------------------------
+// track
+//---------------------------------------------------------
+
+MidiTrack* EventCanvas::track() const
+ {
+ return ((MidiPart*)curPart)->track();
+ }
+
+
+//---------------------------------------------------------
+// keyPress
+//---------------------------------------------------------
+
+void EventCanvas::keyPress(QKeyEvent* event)
+ {
+ int key = event->key();
+ if (event->state() & Qt::ShiftButton)
+ key += Qt::SHIFT;
+ if (event->state() & Qt::AltButton)
+ key += Qt::ALT;
+ if (event->state() & Qt::ControlButton)
+ key+= Qt::CTRL;
+
+ //
+ // Shortcut for DrumEditor & PianoRoll
+ // Sets locators to selected events
+ //
+ if (key == shortcuts[SHRT_LOCATORS_TO_SELECTION].key) {
+ int tick_max = 0;
+ int tick_min = INT_MAX;
+ bool found = false;
+
+ for (iCItem i= items.begin(); i != items.end(); i++) {
+ if (!i->second->isSelected())
+ continue;
+
+ int tick = i->second->x();
+ int len = i->second->event().lenTick();
+ found = true;
+ if (tick + len > tick_max)
+ tick_max = tick + len;
+ if (tick < tick_min)
+ tick_min = tick;
+ }
+ if (found) {
+ Pos p1(tick_min, true);
+ Pos p2(tick_max, true);
+ song->setPos(1, p1);
+ song->setPos(2, p2);
+ }
+ }
+ // Select items by key (PianoRoll & DrumEditor)
+ else if (key == shortcuts[SHRT_SEL_RIGHT].key || key == shortcuts[SHRT_SEL_RIGHT_ADD].key) {
+ iCItem i, iRightmost;
+ CItem* rightmost = NULL;
+ //Get the rightmost selected note (if any)
+ for (i = items.begin(); i != items.end(); ++i) {
+ if (i->second->isSelected()) {
+ iRightmost = i; rightmost = i->second;
+ }
+ }
+ if (rightmost) {
+ iCItem temp = iRightmost; temp++;
+ //If so, deselect current note and select the one to the right
+ if (temp != items.end()) {
+ if (key != shortcuts[SHRT_SEL_RIGHT_ADD].key)
+ deselectAll();
+
+ iRightmost++;
+ iRightmost->second->setSelected(true);
+ updateSelection();
+ }
+ }
+ }
+ //Select items by key: (PianoRoll & DrumEditor)
+ else if (key == shortcuts[SHRT_SEL_LEFT].key || key == shortcuts[SHRT_SEL_LEFT_ADD].key) {
+ iCItem i, iLeftmost;
+ CItem* leftmost = NULL;
+ if (items.size() > 0 ) {
+ for (i = items.end(), i--; i != items.begin(); i--) {
+ if (i->second->isSelected()) {
+ iLeftmost = i; leftmost = i->second;
+ }
+ }
+ if (leftmost) {
+ if (iLeftmost != items.begin()) {
+ //Add item
+ if (key != shortcuts[SHRT_SEL_LEFT_ADD].key)
+ deselectAll();
+
+ iLeftmost--;
+ iLeftmost->second->setSelected(true);
+ updateSelection();
+ }
+ }
+ }
+ }
+ else if (key == shortcuts[SHRT_INC_PITCH].key) {
+ modifySelected(NoteInfo::VAL_PITCH, 1);
+ }
+ else if (key == shortcuts[SHRT_DEC_PITCH].key) {
+ modifySelected(NoteInfo::VAL_PITCH, -1);
+ }
+ else if (key == shortcuts[SHRT_INC_POS].key) {
+ // TODO: Check boundaries
+ modifySelected(NoteInfo::VAL_TIME, editor->raster());
+ }
+ else if (key == shortcuts[SHRT_DEC_POS].key) {
+ // TODO: Check boundaries
+ modifySelected(NoteInfo::VAL_TIME, 0 - editor->raster());
+ }
+
+ else if (key == shortcuts[SHRT_INCREASE_LEN].key) {
+ // TODO: Check boundaries
+ modifySelected(NoteInfo::VAL_LEN, editor->raster());
+ }
+ else if (key == shortcuts[SHRT_DECREASE_LEN].key) {
+ // TODO: Check boundaries
+ modifySelected(NoteInfo::VAL_LEN, 0 - editor->raster());
+ }
+
+ else
+ event->ignore();
+ }
diff --git a/muse2/muse/midiedit/ecanvas.h b/muse2/muse/midiedit/ecanvas.h
new file mode 100644
index 00000000..58df80b5
--- /dev/null
+++ b/muse2/muse/midiedit/ecanvas.h
@@ -0,0 +1,87 @@
+//=========================================================
+// MusE
+// Linux Music Editor
+// $Id: ecanvas.h,v 1.5.2.4 2009/02/02 21:38:00 terminator356 Exp $
+// (C) Copyright 2001 Werner Schweer (ws@seh.de)
+//=========================================================
+
+#ifndef __ECANVAS_H__
+#define __ECANVAS_H__
+
+#include "canvas.h"
+#include "noteinfo.h"
+//Added by qt3to4:
+#include <QEvent>
+#include <QKeyEvent>
+
+class MidiPart;
+class MidiTrack;
+class MidiEditor;
+class Part;
+
+struct PartToChange
+{
+ Part* npart;
+ int xdiff;
+};
+typedef std::map<Part*, PartToChange> PartsToChangeMap;
+typedef std::map<Part*, PartToChange>::iterator iPartToChange;
+
+//---------------------------------------------------------
+// EventCanvas
+//---------------------------------------------------------
+
+class EventCanvas : public Canvas {
+ Q_OBJECT
+ virtual void leaveEvent(QEvent*e);
+ virtual void enterEvent(QEvent*e);
+ // Removed by T356.
+ //virtual QPoint raster(const QPoint&) const;
+
+ virtual void startUndo(DragType);
+
+ virtual void endUndo(DragType, int flags = 0);
+ virtual void mouseMove(const QPoint&);
+
+ protected:
+ bool _playEvents;
+ MidiEditor* editor;
+ unsigned start_tick, end_tick;
+ int curVelo;
+ bool _steprec;
+ bool _midiin;
+
+ void updateSelection();
+ virtual void addItem(Part*, Event&) = 0;
+ // Added by T356.
+ virtual QPoint raster(const QPoint&) const;
+
+ public slots:
+ void redrawGrid() { redraw(); }
+ void setSteprec(bool f) { _steprec = f; }
+ void setMidiin(bool f) { _midiin = f; }
+
+ signals:
+ void pitchChanged(int); // current cursor position
+ void timeChanged(unsigned);
+ void selectionChanged(int, Event&, Part*);
+ void enterCanvas();
+
+ public:
+ EventCanvas(MidiEditor*, QWidget*, int, int, const char* name = 0);
+ MidiTrack* track() const;
+ unsigned start() const { return start_tick; }
+ unsigned end() const { return end_tick; }
+ bool midiin() const { return _midiin; }
+ bool steprec() const { return _steprec; }
+ QString getCaption() const;
+ void songChanged(int);
+ void range(int* s, int* e) const { *s = start_tick; *e = end_tick; }
+ void playEvents(bool flag) { _playEvents = flag; }
+ void selectAtTick(unsigned int tick);
+ virtual void modifySelected(NoteInfo::ValType, int) {}
+ virtual void keyPress(QKeyEvent*);
+ };
+
+#endif
+
diff --git a/muse2/muse/midiedit/piano.cpp b/muse2/muse/midiedit/piano.cpp
new file mode 100644
index 00000000..ed7ac9f5
--- /dev/null
+++ b/muse2/muse/midiedit/piano.cpp
@@ -0,0 +1,557 @@
+//=========================================================
+// MusE
+// Linux Music Editor
+// $Id: piano.cpp,v 1.3 2004/05/31 11:48:55 lunar_shuttle Exp $
+// (C) Copyright 1999 Werner Schweer (ws@seh.de)
+//=========================================================
+
+#include <qpainter.h>
+//Added by qt3to4:
+#include <QPixmap>
+#include <QEvent>
+#include <QMouseEvent>
+
+#include <stdio.h>
+
+#include "piano.h"
+
+static const char *oct_xpm[] = {
+// w h colors
+ "40 91 2 1",
+ ". c #c0c0c0",
+ "# c #000000",
+ // x
+ "####################################### ",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#", // 10
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#", //------------------------
+ "#######################................#",
+ "########################...............#",
+ "########################...............#",
+ "####################################### ", // 7
+ "########################...............#",
+ "########################...............#",
+ "#######################................#", //------------------------
+ ".......................................#",
+ ".......................................#",
+ ".......................................#", // 6
+ ".......................................#",
+ ".......................................#",
+ ".......................................#", //------------------------
+ "#######################................#",
+ "########################...............#",
+ "########################...............#", // 7
+ "####################################### ",
+ "########################...............#",
+ "########################...............#",
+ "#######################................#", //------------------------
+ ".......................................#",
+ ".......................................#",
+ ".......................................#", // 6
+ ".......................................#",
+ ".......................................#",
+ ".......................................#", //------------------------
+ "#######################................#",
+ "########################...............#",
+ "########################...............#", // 7
+ "####################################### ",
+ "########################...............#",
+ "########################...............#",
+ "#######################................#", //------------------------
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#", // 10
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ "####################################### ", //----------------------
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#", // 9
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#", //------------------------
+ "#######################................#",
+ "########################...............#",
+ "########################...............#",
+ "####################################### ", // 7
+ "########################...............#",
+ "########################...............#",
+ "#######################................#", //------------------------
+ ".......................................#",
+ ".......................................#",
+ ".......................................#", // 6
+ ".......................................#",
+ ".......................................#",
+ ".......................................#", //--------------------------
+ "#######################................#",
+ "########################...............#",
+ "########################...............#", // 7
+ "####################################### ",
+ "########################...............#",
+ "########################...............#",
+ "#######################................#", //------------------------
+ ".......................................#",
+ "..........................###..........#",
+ ".........................#...#.........#",
+ ".........................#.............#",
+ ".........................#.............#",
+ ".........................#...#.........#", // 10
+ "..........................###..........#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ };
+
+static const char *mk1_xpmC1[] = {
+ "40 10 2 1",
+ ". c #c0c0c0",
+ "# c #000000",
+ ".......................................#",
+ "..........................###.....#....#",
+ ".........................#...#...##....#",
+ ".........................#........#....#",
+ ".........................#........#....#",
+ ".........................#...#....#....#", // 10
+ "..........................###....###...#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ };
+static const char *mk1_xpmC2[] = {
+ "40 10 2 1",
+ ". c #c0c0c0",
+ "# c #000000",
+ ".......................................#",
+ "..........................###....##....#",
+ ".........................#...#..#..#...#",
+ ".........................#........#....#",
+ ".........................#.......#.....#",
+ ".........................#...#..#......#", // 10
+ "..........................###...####...#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ };
+static const char *mk1_xpmC3[] = {
+ "40 10 2 1",
+ ". c #c0c0c0",
+ "# c #000000",
+ ".......................................#",
+ "..........................###....##....#",
+ ".........................#...#..#..#...#",
+ ".........................#........#....#",
+ ".........................#.........#...#",
+ ".........................#...#..#..#...#", // 10
+ "..........................###....##....#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ };
+static const char *mk1_xpmC4[] = {
+ "40 10 2 1",
+ ". c #c0c0c0",
+ "# c #000000",
+ ".......................................#",
+ "..........................###...#..#...#",
+ ".........................#...#..#..#...#",
+ ".........................#......####...#",
+ ".........................#.........#...#",
+ ".........................#...#.....#...#", // 10
+ "..........................###......#...#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ };
+static const char *mk1_xpmC5[] = {
+ "40 10 2 1",
+ ". c #c0c0c0",
+ "# c #000000",
+ ".......................................#",
+ "..........................###...####...#",
+ ".........................#...#..#......#",
+ ".........................#......###....#",
+ ".........................#.........#...#",
+ ".........................#...#.....#...#", // 10
+ "..........................###...###....#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ };
+
+static const char *mk1_xpmC6[] = {
+ "40 10 2 1",
+ ". c #c0c0c0",
+ "# c #000000",
+ ".......................................#",
+ "..........................###....###...#",
+ ".........................#...#..#......#",
+ ".........................#......###....#",
+ ".........................#......#..#...#",
+ ".........................#...#..#..#...#", // 10
+ "..........................###...###....#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ };
+
+static const char *mk1_xpmC7[] = {
+ "40 10 2 1",
+ ". c #c0c0c0",
+ "# c #000000",
+ ".......................................#",
+ "..........................###...####...#",
+ ".........................#...#.....#...#",
+ ".........................#........#....#",
+ ".........................#.......#.....#",
+ ".........................#...#..#......#", // 10
+ "..........................###...#......#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ };
+static const char *mk1_xpmC8[] = {
+ "40 10 2 1",
+ ". c #c0c0c0",
+ "# c #000000",
+ ".......................................#",
+ "..........................###....##....#",
+ ".........................#...#..#..#....#",
+ ".........................#.......##....#",
+ ".........................#......#..#...#",
+ ".........................#...#..#..#...#", // 10
+ "..........................###....##....#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ };
+
+static const char *mk1_xpm[] = {
+ "40 13 2 1",
+ ". c #ff0000",
+ "# c none",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ "#######################................#",
+ "########################...............#",
+ "########################...............#",
+ "####################################### ",
+ };
+
+static const char *mk2_xpm[] = {
+ "40 13 2 1",
+ ". c #ff0000",
+ "# c none",
+ "########################...............#",
+ "########################...............#",
+ "#######################................#", //------------------------
+ ".......................................#",
+ ".......................................#",
+ ".......................................#", // 6
+ ".......................................#",
+ ".......................................#",
+ ".......................................#", //--------------------------
+ "#######################................#",
+ "########################...............#",
+ "########################...............#", // 7
+ "####################################### ",
+ };
+
+static const char *mk3_xpm[] = {
+ "40 13 2 1",
+ ". c #ff0000",
+ "# c none",
+ "########################...............#",
+ "########################...............#",
+ "#######################................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ "########################################",
+ };
+
+static const char *mk4_xpm[] = {
+ "40 13 2 1",
+ "# c #ff0000",
+ ". c none",
+ "........................................",
+ "........................................",
+ "........................................",
+ "#######################.................",
+ "########################................",
+ "########################................",
+ "########################................",
+ "########################................",
+ "########################................",
+ "#######################.................",
+ "........................................",
+ "........................................",
+ "........................................",
+ };
+/*
+ 0 1 2 3 4 5 6 7 8 9 10
+ c-2 c-1 C0 C1 C2 C3 C4 C5 C6 C7 C8 - G8
+
+ Grid über Oktave:
+
+ +------------+ ------------------------------
+ 11 | |
+ | h | 7
+ +------+ |
+ 10 | a# +-----+ ..............................
+ +------+ a |
+ 9 | | 6
+ +------+ |
+ 8 | g# +-----+ ..............................
+ +------+ g |
+ 7 | | 5
+ +------+ |
+ 6 | f# +-----+ ..............................
+ +------+ f |
+ 5 | | 4
+ | |
+ +------------+ ------------------------------
+ 4 | |
+ | e | 3
+ +------+ |
+ 3 | d# +-----+ ..............................
+ +------+ d |
+ 2 | | 2
+ +------+ |
+ 1 | c# +-----+ ..............................
+ +------+ c |
+ | | 1
+ 0 | |
+ +------------+ ------------------------------
+ */
+
+//---------------------------------------------------------
+// Piano
+//---------------------------------------------------------
+
+Piano::Piano(QWidget* parent, int ymag)
+ : View(parent, 1, ymag)
+ {
+ setMouseTracking(true);
+ curPitch = -1;
+ octave = new QPixmap(oct_xpm);
+ c_keys[0] = new QPixmap(mk1_xpmC8);
+ c_keys[1] = new QPixmap(mk1_xpmC7);
+ c_keys[2] = new QPixmap(mk1_xpmC6);
+ c_keys[3] = new QPixmap(mk1_xpmC5);
+ c_keys[4] = new QPixmap(mk1_xpmC4);
+ c_keys[5] = new QPixmap(mk1_xpmC3);
+ c_keys[6] = new QPixmap(mk1_xpmC2);
+ c_keys[7] = new QPixmap(mk1_xpmC1);
+
+ mk1 = new QPixmap(mk1_xpm);
+ mk2 = new QPixmap(mk2_xpm);
+ mk3 = new QPixmap(mk3_xpm);
+ mk4 = new QPixmap(mk4_xpm);
+ keyDown = -1;
+ button = Qt::NoButton;
+ }
+
+//---------------------------------------------------------
+// draw
+//---------------------------------------------------------
+
+void Piano::draw(QPainter& p, const QRect& r)
+ {
+ QPoint offset(0, KH*2);
+ p.drawTiledPixmap(r, *octave, r.topLeft()+offset);
+
+ // draw C notes
+ for (int drawKey = 0; drawKey < 8;drawKey++) {
+ int octaveSize=91;
+
+ int drawY = octaveSize * drawKey + 81 - KH*2;
+ if (drawY > r.y() && drawY < r.y() + r.height()) {
+ //printf("drawing c %d at %d r.y %d r.x %d\n",drawKey, drawY, r.y(), r.x());
+ p.drawPixmap(0,drawY,*c_keys[drawKey]);
+ }
+ }
+ //p.drawTiledPixmap(r, *c1, r.topLeft()+offset + coffset);
+ //printf("drawText KH %d %d, x %d y %d\n",KH, curPitch, r.x(), r.y());
+ //p.drawText(r,Qt::AlignAuto,"A");
+ if (curPitch == -1)
+ return;
+ int y = pitch2y(curPitch);
+ QPixmap* pm;
+ switch(curPitch % 12) {
+ case 0:
+ case 5:
+ pm = mk3;
+ break;
+ case 2:
+ case 7:
+ case 9:
+ pm = mk2;
+ break;
+ case 4:
+ case 11:
+ pm = mk1;
+ break;
+ default:
+ pm = mk4;
+ break;
+ }
+ p.drawPixmap(0, y, *pm);
+ }
+
+//---------------------------------------------------------
+// pitch2y
+//---------------------------------------------------------
+
+int Piano::pitch2y(int pitch) const
+ {
+ int tt[] = {
+ 12, 19, 25, 32, 38, 51, 58, 64, 71, 77, 84, 90
+ };
+ int y = (75 * KH) - (tt[pitch%12] + (7 * KH) * (pitch/12));
+ if (y < 0)
+ y = 0;
+ return y;
+ }
+
+//---------------------------------------------------------
+// y2pitch
+//---------------------------------------------------------
+
+int Piano::y2pitch(int y) const
+ {
+ const int total = (10 * 7 + 5) * KH; // 75 Ganztonschritte
+ y = total - y;
+ int oct = (y / (7 * KH)) * 12;
+ char kt[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 1, 1,
+ 2, 2, 2, 2, 2, 2,
+ 3, 3, 3, 3, 3, 3, 3,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 6, 6, 6, 6, 6, 6, 6,
+ 7, 7, 7, 7, 7, 7,
+ 8, 8, 8, 8, 8, 8, 8,
+ 9, 9, 9, 9, 9, 9,
+ 10, 10, 10, 10, 10, 10, 10,
+ 11, 11, 11, 11, 11, 11, 11, 11, 11, 11
+ };
+ return kt[y % 91] + oct;
+ }
+
+//---------------------------------------------------------
+// leaveEvent
+//---------------------------------------------------------
+
+void Piano::leaveEvent(QEvent*)
+ {
+ if (keyDown != -1) {
+ emit keyReleased(keyDown, shift);
+ keyDown = -1;
+ }
+ emit pitchChanged(-1);
+ setPitch(-1);
+ }
+
+//---------------------------------------------------------
+// setPitch
+//---------------------------------------------------------
+
+void Piano::setPitch(int pitch)
+ {
+ if (curPitch == pitch)
+ return;
+ curPitch = pitch;
+ redraw();
+ }
+
+//---------------------------------------------------------
+// viewMouseMoveEvent
+//---------------------------------------------------------
+
+void Piano::viewMouseMoveEvent(QMouseEvent* event)
+ {
+ int pitch = y2pitch(event->y());
+ emit pitchChanged(pitch);
+ setPitch(pitch);
+
+ if (button != Qt::NoButton) {
+ int nk = y2pitch(event->y());
+ if (nk < 0 || nk > 127)
+ nk = -1;
+ if (nk != keyDown) {
+ if (keyDown != -1) {
+ emit keyReleased(keyDown, shift);
+ }
+ keyDown = nk;
+ if (keyDown != -1) {
+ int velocity = event->x()*127/40;
+ //emit keyPressed(keyDown, shift);
+ emit keyPressed(keyDown, velocity>127 ? 127 : velocity, shift);
+ }
+ }
+ }
+ }
+
+//---------------------------------------------------------
+// viewMousePressEvent
+//---------------------------------------------------------
+
+void Piano::viewMousePressEvent(QMouseEvent* event)
+ {
+ button = event->button();
+ shift = event->state() & Qt::ShiftButton;
+ if (keyDown != -1) {
+ emit keyReleased(keyDown, shift);
+ keyDown = -1;
+ }
+ keyDown = y2pitch(event->y());
+ if (keyDown < 0 || keyDown > 127) {
+ keyDown = -1;
+ }
+ else {
+ int velocity = event->x()*127/40;
+ emit keyPressed(keyDown, velocity>127 ? 127 : velocity, shift); //emit keyPressed(keyDown, shift);
+ }
+ }
+
+//---------------------------------------------------------
+// viewMouseReleaseEvent
+//---------------------------------------------------------
+
+void Piano::viewMouseReleaseEvent(QMouseEvent* event)
+ {
+ button = Qt::NoButton;
+ shift = event->state() & Qt::ShiftButton;
+ if (keyDown != -1) {
+ emit keyReleased(keyDown, shift);
+ keyDown = -1;
+ }
+ }
+
diff --git a/muse2/muse/midiedit/piano.h b/muse2/muse/midiedit/piano.h
new file mode 100644
index 00000000..2f06b810
--- /dev/null
+++ b/muse2/muse/midiedit/piano.h
@@ -0,0 +1,63 @@
+//=========================================================
+// MusE
+// Linux Music Editor
+// $Id: piano.h,v 1.2 2004/05/31 11:48:55 lunar_shuttle Exp $
+// (C) Copyright 1999 Werner Schweer (ws@seh.de)
+//=========================================================
+
+#ifndef __PIANO_H__
+#define __PIANO_H__
+
+#include "view.h"
+//Added by qt3to4:
+#include <QMouseEvent>
+#include <QEvent>
+#include <QPixmap>
+
+class QPainter;
+
+#define KH 13
+
+//---------------------------------------------------------
+// Piano
+//---------------------------------------------------------
+
+class Piano : public View
+ {
+ int curPitch;
+ QPixmap* octave;
+ QPixmap* c_keys[10];
+ QPixmap* mk1;
+ QPixmap* mk2;
+ QPixmap* mk3;
+ QPixmap* mk4;
+ int keyDown;
+ bool shift;
+ int button;
+
+ Q_OBJECT
+ int y2pitch(int) const;
+ int pitch2y(int) const;
+ void viewMouseMoveEvent(QMouseEvent* event);
+ virtual void leaveEvent(QEvent*e);
+
+ virtual void viewMousePressEvent(QMouseEvent* event);
+ virtual void viewMouseReleaseEvent(QMouseEvent*);
+
+ protected:
+ virtual void draw(QPainter&, const QRect&);
+
+ signals:
+ void pitchChanged(int);
+ void keyPressed(int, int, bool);
+ void keyReleased(int, bool);
+
+ public slots:
+ void setPitch(int);
+
+ public:
+ Piano(QWidget*, int);
+ };
+
+#endif
+
diff --git a/muse2/muse/midiedit/pianoroll.cpp b/muse2/muse/midiedit/pianoroll.cpp
new file mode 100644
index 00000000..93bf615c
--- /dev/null
+++ b/muse2/muse/midiedit/pianoroll.cpp
@@ -0,0 +1,1107 @@
+//=========================================================
+// MusE
+// Linux Music Editor
+// $Id: pianoroll.cpp,v 1.25.2.15 2009/11/16 11:29:33 lunar_shuttle Exp $
+// (C) Copyright 1999 Werner Schweer (ws@seh.de)
+//=========================================================
+
+#include <q3accel.h>
+#include <qlayout.h>
+#include <q3hbox.h>
+#include <qsizegrip.h>
+#include <qlabel.h>
+#include <qpushbutton.h>
+#include <q3buttongroup.h>
+#include <qtoolbutton.h>
+#include <qtooltip.h>
+#include <q3popupmenu.h>
+#include <qmenubar.h>
+#include <qapplication.h>
+#include <qclipboard.h>
+#include <qdir.h>
+#include <qaction.h>
+//Added by qt3to4:
+#include <QKeyEvent>
+#include <Q3GridLayout>
+#include <QResizeEvent>
+#include <QCloseEvent>
+
+#include <stdio.h>
+
+#include "xml.h"
+#include "mtscale.h"
+#include "prcanvas.h"
+#include "pianoroll.h"
+#include "scrollscale.h"
+#include "piano.h"
+#include "../ctrl/ctrledit.h"
+#include "splitter.h"
+#include "ttoolbar.h"
+#include "tb1.h"
+#include "utils.h"
+#include "globals.h"
+#include "gconfig.h"
+#include "icons.h"
+#include "audio.h"
+
+#include "cmd.h"
+#include "quantconfig.h"
+#include "shortcuts.h"
+
+int PianoRoll::_quantInit = 96;
+int PianoRoll::_rasterInit = 96;
+int PianoRoll::_widthInit = 600;
+int PianoRoll::_heightInit = 400;
+int PianoRoll::_quantStrengthInit = 80; // 1 - 100%
+int PianoRoll::_quantLimitInit = 50; // tick value
+bool PianoRoll::_quantLenInit = false;
+int PianoRoll::_toInit = 0;
+int PianoRoll::colorModeInit = 0;
+
+static const int xscale = -10;
+static const int yscale = 1;
+static const int pianoWidth = 40;
+static int pianorollTools = PointerTool | PencilTool | RubberTool | DrawTool;
+
+
+
+
+//---------------------------------------------------------
+// PianoRoll
+//---------------------------------------------------------
+
+PianoRoll::PianoRoll(PartList* pl, QWidget* parent, const char* name, unsigned initPos)
+ : MidiEditor(_quantInit, _rasterInit, pl, parent, name)
+ {
+ deltaMode = false;
+ resize(_widthInit, _heightInit);
+ selPart = 0;
+ quantConfig = 0;
+ _playEvents = false;
+ _quantStrength = _quantStrengthInit;
+ _quantLimit = _quantLimitInit;
+ _quantLen = _quantLenInit;
+ _to = _toInit;
+ colorMode = colorModeInit;
+ //---------Men----------------------------------
+ menuEdit = new Q3PopupMenu(this);
+ menuBar()->insertItem(tr("&Edit"), menuEdit);
+ undoRedo->addTo(menuEdit);
+ Q3Accel* ud = new Q3Accel(this);
+ ud->connectItem(ud->insertItem(Qt::CTRL+Qt::Key_Z), song, SLOT(undo()));
+ Q3Accel* rd = new Q3Accel(this);
+ rd->connectItem(rd->insertItem(Qt::CTRL+Qt::Key_Y), song, SLOT(redo()));
+
+ menuEdit->insertSeparator();
+ menuEdit->insertItem(tr("Cut"), PianoCanvas::CMD_CUT);
+ menuEdit->setAccel(Qt::CTRL+Qt::Key_X, PianoCanvas::CMD_CUT);
+ menuEdit->insertItem(tr("Copy"), PianoCanvas::CMD_COPY);
+ menuEdit->setAccel(Qt::CTRL+Qt::Key_C, PianoCanvas::CMD_COPY);
+ menuEdit->insertItem(tr("Paste"), PianoCanvas::CMD_PASTE);
+ menuEdit->setAccel(Qt::CTRL+Qt::Key_V, PianoCanvas::CMD_PASTE);
+ menuEdit->insertSeparator();
+ menuEdit->insertItem(tr("Delete Events"), PianoCanvas::CMD_DEL);
+ menuEdit->setAccel(Qt::Key_Delete, PianoCanvas::CMD_DEL);
+ menuEdit->insertSeparator();
+
+ menuSelect = new Q3PopupMenu(this);
+ menuSelect->insertItem(tr("Select All"), PianoCanvas::CMD_SELECT_ALL);
+ menuSelect->insertItem(tr("Select None"), PianoCanvas::CMD_SELECT_NONE);
+ menuSelect->insertItem(tr("Invert"), PianoCanvas::CMD_SELECT_INVERT);
+
+ menuSelect->insertSeparator();
+ menuSelect->insertItem(tr("Inside Loop"), PianoCanvas::CMD_SELECT_ILOOP);
+
+ menuSelect->insertItem(tr("Outside Loop"), PianoCanvas::CMD_SELECT_OLOOP);
+
+ menuSelect->insertSeparator();
+
+ menuSelect->insertItem(tr("Previous Part"), PianoCanvas::CMD_SELECT_PREV_PART);
+ menuSelect->insertItem(tr("Next Part"), PianoCanvas::CMD_SELECT_NEXT_PART);
+
+ menuEdit->insertItem(tr("&Select"), menuSelect);
+
+ eventColor = new Q3PopupMenu(this);
+ eventColor->insertItem(tr("blue"), 0);
+ eventColor->insertItem(tr("pitch colors"), 1);
+ eventColor->insertItem(tr("velocity colors"), 2);
+ connect(eventColor, SIGNAL(activated(int)), SLOT(setEventColorMode(int)));
+
+ menuConfig = new Q3PopupMenu(this);
+ menuBar()->insertItem(tr("&Config"), menuConfig);
+ menu_ids[CMD_EVENT_COLOR] = menuConfig->insertItem(tr("event color"), eventColor, 0);
+
+ menuFunctions = new Q3PopupMenu(this);
+ menuBar()->insertItem(tr("&Functions"), menuFunctions);
+ menuFunctions->insertTearOffHandle();
+ menuFunctions->insertItem(tr("Over Quantize"), PianoCanvas::CMD_OVER_QUANTIZE);
+
+ menuFunctions->insertItem(tr("Note On Quantize"), PianoCanvas::CMD_ON_QUANTIZE);
+
+ menuFunctions->insertItem(tr("Note On/Off Quantize"), PianoCanvas::CMD_ONOFF_QUANTIZE);
+ menuFunctions->insertItem(tr("Iterative Quantize"), PianoCanvas::CMD_ITERATIVE_QUANTIZE);
+
+ menuFunctions->insertSeparator();
+ menu_ids[CMD_CONFIG_QUANT] = menuFunctions->insertItem(tr("Config Quant..."), this, SLOT(configQuant()), 0);
+ menuFunctions->insertSeparator();
+ menuFunctions->insertItem(tr("Modify Gate Time"), PianoCanvas::CMD_MODIFY_GATE_TIME);
+ menuFunctions->insertItem(tr("Modify Velocity"), PianoCanvas::CMD_MODIFY_VELOCITY);
+ menuFunctions->insertItem(tr("Crescendo"), PianoCanvas::CMD_CRESCENDO);
+ menuFunctions->insertItem(tr("Transpose"), PianoCanvas::CMD_TRANSPOSE);
+ menuFunctions->insertItem(tr("Thin Out"), PianoCanvas::CMD_THIN_OUT);
+ menuFunctions->insertItem(tr("Erase Event"), PianoCanvas::CMD_ERASE_EVENT);
+ menuFunctions->insertItem(tr("Note Shift"), PianoCanvas::CMD_NOTE_SHIFT);
+ menuFunctions->insertItem(tr("Move Clock"), PianoCanvas::CMD_MOVE_CLOCK);
+ menuFunctions->insertItem(tr("Copy Measure"), PianoCanvas::CMD_COPY_MEASURE);
+ menuFunctions->insertItem(tr("Erase Measure"), PianoCanvas::CMD_ERASE_MEASURE);
+ menuFunctions->insertItem(tr("Delete Measure"), PianoCanvas::CMD_DELETE_MEASURE);
+ menuFunctions->insertItem(tr("Create Measure"), PianoCanvas::CMD_CREATE_MEASURE);
+ menuFunctions->insertItem(tr("Set fixed length"), PianoCanvas::CMD_FIXED_LEN);
+ menuFunctions->insertItem(tr("Delete overlaps"), PianoCanvas::CMD_DELETE_OVERLAPS);
+
+ menuFunctions->setItemEnabled(PianoCanvas::CMD_CRESCENDO, false);
+ menuFunctions->setItemEnabled(PianoCanvas::CMD_TRANSPOSE, false);
+ menuFunctions->setItemEnabled(PianoCanvas::CMD_THIN_OUT, false);
+ menuFunctions->setItemEnabled(PianoCanvas::CMD_ERASE_EVENT, false);
+ menuFunctions->setItemEnabled(PianoCanvas::CMD_NOTE_SHIFT, false);
+ menuFunctions->setItemEnabled(PianoCanvas::CMD_MOVE_CLOCK, false);
+ menuFunctions->setItemEnabled(PianoCanvas::CMD_COPY_MEASURE, false);
+ menuFunctions->setItemEnabled(PianoCanvas::CMD_ERASE_MEASURE, false);
+ menuFunctions->setItemEnabled(PianoCanvas::CMD_DELETE_MEASURE, false);
+ menuFunctions->setItemEnabled(PianoCanvas::CMD_CREATE_MEASURE, false);
+
+ menuPlugins = new Q3PopupMenu(this);
+ song->populateScriptMenu(menuPlugins, this);
+ menuBar()->insertItem(tr("&Plugins"), menuPlugins);
+ connect(menuEdit, SIGNAL(activated(int)), SLOT(cmd(int)));
+ connect(menuSelect, SIGNAL(activated(int)), SLOT(cmd(int)));
+ connect(menuFunctions, SIGNAL(activated(int)), SLOT(cmd(int)));
+
+ //---------ToolBar----------------------------------
+ tools = new Q3ToolBar(this, "pianoroll-tools");
+ tools->setLabel(tr("Pianoroll Tools"));
+ undoRedo->addTo(tools);
+ tools->addSeparator();
+
+ srec = new QToolButton(tools, "srec");
+ QToolTip::add(srec, tr("Step Record"));
+ srec->setPixmap(*steprecIcon);
+ srec->setToggleButton(true);
+
+ midiin = new QToolButton(tools, "midiin");
+ QToolTip::add(midiin, tr("Midi Input"));
+ midiin->setPixmap(*midiinIcon);
+ midiin->setToggleButton(true);
+
+ speaker = new QToolButton(tools, "speaker");
+ QToolTip::add(speaker, tr("Play Events"));
+ speaker->setPixmap(*speakerIcon);
+ speaker->setToggleButton(true);
+
+ tools2 = new EditToolBar(this, pianorollTools);
+
+ Q3ToolBar* panicToolbar = new Q3ToolBar(this);
+ panicAction->addTo(panicToolbar);
+
+ //-------------------------------------------------------------
+ // Transport Bar
+ Q3ToolBar* transport = new Q3ToolBar(this);
+ transportAction->addTo(transport);
+
+ toolbar = new Toolbar1(this, _rasterInit, _quantInit);
+ info = new NoteInfo(this);
+
+ //---------------------------------------------------
+ // split
+ //---------------------------------------------------
+
+ splitter = new Splitter(Qt::Vertical, mainw, "splitter");
+ QPushButton* ctrl = new QPushButton(tr("ctrl"), mainw, "Ctrl");
+ ctrl->setFont(config.fonts[3]);
+ QToolTip::add(ctrl, tr("Add Controller View"));
+ hscroll = new ScrollScale(-25, -2, xscale, 20000, Qt::Horizontal, mainw);
+ ctrl->setFixedSize(pianoWidth, hscroll->sizeHint().height());
+
+ QSizeGrip* corner = new QSizeGrip(mainw);
+
+ mainGrid->setRowStretch(0, 100);
+ mainGrid->setColStretch(1, 100);
+ mainGrid->addMultiCellWidget(splitter, 0, 0, 0, 2);
+ mainGrid->addWidget(ctrl, 1, 0);
+ mainGrid->addWidget(hscroll, 1, 1);
+ mainGrid->addWidget(corner, 1, 2, Qt::AlignBottom|Qt::AlignRight);
+ mainGrid->addRowSpacing(1, hscroll->sizeHint().height());
+
+ QWidget* split1 = new QWidget(splitter, "split1");
+ Q3GridLayout* gridS1 = new Q3GridLayout(split1);
+ time = new MTScale(&_raster, split1, xscale);
+ Piano* piano = new Piano(split1, yscale);
+ canvas = new PianoCanvas(this, split1, xscale, yscale);
+ vscroll = new ScrollScale(-3, 7, yscale, KH * 75, Qt::Vertical, split1);
+
+ int offset = -(config.division/4);
+ canvas->setOrigin(offset, 0);
+ canvas->setCanvasTools(pianorollTools);
+ canvas->setFocus();
+ connect(canvas, SIGNAL(toolChanged(int)), tools2, SLOT(set(int)));
+ time->setOrigin(offset, 0);
+
+ gridS1->setRowStretch(2, 100);
+ gridS1->setColStretch(1, 100);
+
+ gridS1->addMultiCellWidget(time, 0, 0, 1, 2);
+ gridS1->addMultiCellWidget(hLine(split1), 1, 1, 0, 2);
+ gridS1->addWidget(piano, 2, 0);
+ gridS1->addWidget(canvas, 2, 1);
+
+ gridS1->addWidget(vscroll, 2, 2);
+// gridS1->addWidget(time, 0, 1);
+// gridS1->addWidget(hLine(split1), 1, 1);
+// gridS1->addWidget(piano, 2, 0);
+// gridS1->addWidget(canvas, 2, 1);
+// gridS1->addMultiCellWidget(vscroll, 1, 2, 2, 2);
+
+ piano->setFixedWidth(pianoWidth);
+
+ connect(tools2, SIGNAL(toolChanged(int)), canvas, SLOT(setTool(int)));
+
+ connect(ctrl, SIGNAL(clicked()), SLOT(addCtrl()));
+ connect(info, SIGNAL(valueChanged(NoteInfo::ValType, int)), SLOT(noteinfoChanged(NoteInfo::ValType, int)));
+ connect(vscroll, SIGNAL(scrollChanged(int)), piano, SLOT(setYPos(int)));
+ connect(vscroll, SIGNAL(scrollChanged(int)), canvas, SLOT(setYPos(int)));
+ connect(vscroll, SIGNAL(scaleChanged(int)), canvas, SLOT(setYMag(int)));
+ connect(vscroll, SIGNAL(scaleChanged(int)), piano, SLOT(setYMag(int)));
+
+ connect(hscroll, SIGNAL(scrollChanged(int)), canvas, SLOT(setXPos(int)));
+ connect(hscroll, SIGNAL(scrollChanged(int)), time, SLOT(setXPos(int)));
+
+ connect(hscroll, SIGNAL(scaleChanged(int)), canvas, SLOT(setXMag(int)));
+ connect(hscroll, SIGNAL(scaleChanged(int)), time, SLOT(setXMag(int)));
+
+ connect(canvas, SIGNAL(pitchChanged(int)), piano, SLOT(setPitch(int)));
+ connect(canvas, SIGNAL(verticalScroll(unsigned)), vscroll, SLOT(setPos(unsigned)));
+ connect(canvas, SIGNAL(horizontalScroll(unsigned)),hscroll, SLOT(setPos(unsigned)));
+ connect(canvas, SIGNAL(horizontalScrollNoLimit(unsigned)),hscroll, SLOT(setPosNoLimit(unsigned)));
+ connect(canvas, SIGNAL(selectionChanged(int, Event&, Part*)), this,
+ SLOT(setSelection(int, Event&, Part*)));
+
+ connect(piano, SIGNAL(keyPressed(int, int, bool)), canvas, SLOT(pianoPressed(int, int, bool)));
+ connect(piano, SIGNAL(keyReleased(int, bool)), canvas, SLOT(pianoReleased(int, bool)));
+ connect(srec, SIGNAL(toggled(bool)), SLOT(setSteprec(bool)));
+ connect(midiin, SIGNAL(toggled(bool)), canvas, SLOT(setMidiin(bool)));
+ connect(speaker, SIGNAL(toggled(bool)), SLOT(setSpeaker(bool)));
+ connect(canvas, SIGNAL(followEvent(int)), SLOT(follow(int)));
+
+ connect(hscroll, SIGNAL(scaleChanged(int)), SLOT(updateHScrollRange()));
+ piano->setYPos(KH * 30);
+ canvas->setYPos(KH * 30);
+ vscroll->setPos(KH * 30);
+ //setSelection(0, 0, 0); //Really necessary? Causes segfault when only 1 item selected, replaced by the following:
+ info->setEnabled(false);
+
+ connect(song, SIGNAL(songChanged(int)), SLOT(songChanged1(int)));
+
+ setCaption(canvas->getCaption());
+
+ updateHScrollRange();
+ // connect to toolbar
+ connect(canvas, SIGNAL(pitchChanged(int)), toolbar, SLOT(setPitch(int)));
+ connect(canvas, SIGNAL(timeChanged(unsigned)), SLOT(setTime(unsigned)));
+ connect(piano, SIGNAL(pitchChanged(int)), toolbar, SLOT(setPitch(int)));
+ connect(time, SIGNAL(timeChanged(unsigned)), SLOT(setTime(unsigned)));
+ connect(toolbar, SIGNAL(quantChanged(int)), SLOT(setQuant(int)));
+ connect(toolbar, SIGNAL(rasterChanged(int)),SLOT(setRaster(int)));
+ connect(toolbar, SIGNAL(toChanged(int)), SLOT(setTo(int)));
+ connect(toolbar, SIGNAL(soloChanged(bool)), SLOT(soloChanged(bool)));
+
+ setFocusPolicy(Qt::StrongFocus);
+ setEventColorMode(colorMode);
+
+ QClipboard* cb = QApplication::clipboard();
+ connect(cb, SIGNAL(dataChanged()), SLOT(clipboardChanged()));
+
+ clipboardChanged(); // enable/disable "Paste"
+ selectionChanged(); // enable/disable "Copy" & "Paste"
+ initShortcuts(); // initialize shortcuts
+
+ const Pos cpos=song->cPos();
+ canvas->setPos(0, cpos.tick(), true);
+ canvas->selectAtTick(cpos.tick());
+ //canvas->selectFirst();
+//
+ if(canvas->track())
+ toolbar->setSolo(canvas->track()->solo());
+
+ unsigned pos;
+ if(initPos >= MAXINT)
+ pos = song->cpos();
+ else
+ pos = initPos;
+ if(pos > MAXINT)
+ pos = MAXINT;
+ hscroll->setOffset((int)pos);
+ }
+
+//---------------------------------------------------------
+// songChanged1
+//---------------------------------------------------------
+
+void PianoRoll::songChanged1(int bits)
+ {
+
+ if (bits & SC_SOLO)
+ {
+ toolbar->setSolo(canvas->track()->solo());
+ return;
+ }
+ songChanged(bits);
+ }
+
+//---------------------------------------------------------
+// configChanged
+//---------------------------------------------------------
+
+void PianoRoll::configChanged()
+ {
+ initShortcuts();
+ }
+
+//---------------------------------------------------------
+// updateHScrollRange
+//---------------------------------------------------------
+
+void PianoRoll::updateHScrollRange()
+{
+ int s, e;
+ canvas->range(&s, &e);
+ // Show one more measure.
+ e += sigmap.ticksMeasure(e);
+ // Show another quarter measure due to imprecise drawing at canvas end point.
+ e += sigmap.ticksMeasure(e) / 4;
+ // Compensate for the fixed piano and vscroll widths.
+ e += canvas->rmapxDev(pianoWidth - vscroll->width());
+ int s1, e1;
+ hscroll->range(&s1, &e1);
+ if(s != s1 || e != e1)
+ hscroll->setRange(s, e);
+}
+
+//---------------------------------------------------------
+// follow
+//---------------------------------------------------------
+
+void PianoRoll::follow(int pos)
+ {
+ int s, e;
+ canvas->range(&s, &e);
+
+ if (pos < e && pos >= s)
+ hscroll->setOffset(pos);
+ if (pos < s)
+ hscroll->setOffset(s);
+ }
+
+//---------------------------------------------------------
+// setTime
+//---------------------------------------------------------
+
+void PianoRoll::setTime(unsigned tick)
+ {
+ toolbar->setTime(tick);
+ time->setPos(3, tick, false);
+ }
+
+//---------------------------------------------------------
+// ~Pianoroll
+//---------------------------------------------------------
+
+PianoRoll::~PianoRoll()
+ {
+ undoRedo->removeFrom(tools);
+ }
+
+//---------------------------------------------------------
+// cmd
+// pulldown menu commands
+//---------------------------------------------------------
+
+void PianoRoll::cmd(int cmd)
+ {
+ ((PianoCanvas*)canvas)->cmd(cmd, _quantStrength, _quantLimit, _quantLen, _to);
+ }
+
+//---------------------------------------------------------
+// setSelection
+// update Info Line
+//---------------------------------------------------------
+
+void PianoRoll::setSelection(int tick, Event& e, Part* p)
+ {
+ int selections = canvas->selectionSize();
+
+ selEvent = e;
+ selPart = (MidiPart*)p;
+ selTick = tick;
+
+ if (selections > 1) {
+ info->setEnabled(true);
+ info->setDeltaMode(true);
+ if (!deltaMode) {
+ deltaMode = true;
+ info->setValues(0, 0, 0, 0, 0);
+ tickOffset = 0;
+ lenOffset = 0;
+ pitchOffset = 0;
+ veloOnOffset = 0;
+ veloOffOffset = 0;
+ }
+ }
+ else if (selections == 1) {
+ deltaMode = false;
+ info->setEnabled(true);
+ info->setDeltaMode(false);
+ info->setValues(tick,
+ selEvent.lenTick(),
+ selEvent.pitch(),
+ selEvent.velo(),
+ selEvent.veloOff());
+ }
+ else {
+ deltaMode = false;
+ info->setEnabled(false);
+ }
+ selectionChanged();
+ }
+
+//---------------------------------------------------------
+// edit currently selected Event
+//---------------------------------------------------------
+
+void PianoRoll::noteinfoChanged(NoteInfo::ValType type, int val)
+ {
+ int selections = canvas->selectionSize();
+
+ if (selections == 0) {
+ printf("noteinfoChanged while nothing selected\n");
+ }
+ else if (selections == 1) {
+ Event event = selEvent.clone();
+ switch(type) {
+ case NoteInfo::VAL_TIME:
+ event.setTick(val - selPart->tick());
+ break;
+ case NoteInfo::VAL_LEN:
+ event.setLenTick(val);
+ break;
+ case NoteInfo::VAL_VELON:
+ event.setVelo(val);
+ break;
+ case NoteInfo::VAL_VELOFF:
+ event.setVeloOff(val);
+ break;
+ case NoteInfo::VAL_PITCH:
+ event.setPitch(val);
+ break;
+ }
+ // Indicate do undo, and do not do port controller values and clone parts.
+ //audio->msgChangeEvent(selEvent, event, selPart);
+ audio->msgChangeEvent(selEvent, event, selPart, true, false, false);
+ }
+ else {
+ // multiple events are selected; treat noteinfo values
+ // as offsets to event values
+
+ int delta = 0;
+ switch (type) {
+ case NoteInfo::VAL_TIME:
+ delta = val - tickOffset;
+ tickOffset = val;
+ break;
+ case NoteInfo::VAL_LEN:
+ delta = val - lenOffset;
+ lenOffset = val;
+ break;
+ case NoteInfo::VAL_VELON:
+ delta = val - veloOnOffset;
+ veloOnOffset = val;
+ break;
+ case NoteInfo::VAL_VELOFF:
+ delta = val - veloOffOffset;
+ veloOffOffset = val;
+ break;
+ case NoteInfo::VAL_PITCH:
+ delta = val - pitchOffset;
+ pitchOffset = val;
+ break;
+ }
+ if (delta)
+ canvas->modifySelected(type, delta);
+ }
+ }
+
+//---------------------------------------------------------
+// addCtrl
+//---------------------------------------------------------
+
+CtrlEdit* PianoRoll::addCtrl()
+ {
+ CtrlEdit* ctrlEdit = new CtrlEdit(splitter, this, xscale, false, "pianoCtrlEdit");
+ connect(tools2, SIGNAL(toolChanged(int)), ctrlEdit, SLOT(setTool(int)));
+ connect(hscroll, SIGNAL(scrollChanged(int)), ctrlEdit, SLOT(setXPos(int)));
+ connect(hscroll, SIGNAL(scaleChanged(int)), ctrlEdit, SLOT(setXMag(int)));
+ connect(ctrlEdit, SIGNAL(timeChanged(unsigned)), SLOT(setTime(unsigned)));
+ connect(ctrlEdit, SIGNAL(destroyedCtrl(CtrlEdit*)), SLOT(removeCtrl(CtrlEdit*)));
+ connect(ctrlEdit, SIGNAL(yposChanged(int)), toolbar, SLOT(setInt(int)));
+
+ ctrlEdit->setTool(tools2->curTool());
+ ctrlEdit->setXPos(hscroll->pos());
+ ctrlEdit->setXMag(hscroll->getScaleValue());
+
+ ctrlEdit->show();
+ ctrlEditList.push_back(ctrlEdit);
+ return ctrlEdit;
+ }
+
+//---------------------------------------------------------
+// removeCtrl
+//---------------------------------------------------------
+
+void PianoRoll::removeCtrl(CtrlEdit* ctrl)
+ {
+ for (std::list<CtrlEdit*>::iterator i = ctrlEditList.begin();
+ i != ctrlEditList.end(); ++i) {
+ if (*i == ctrl) {
+ ctrlEditList.erase(i);
+ break;
+ }
+ }
+ }
+
+//---------------------------------------------------------
+// closeEvent
+//---------------------------------------------------------
+
+void PianoRoll::closeEvent(QCloseEvent* e)
+ {
+ emit deleted((unsigned long)this);
+ e->accept();
+ }
+
+//---------------------------------------------------------
+// readConfiguration
+//---------------------------------------------------------
+
+void PianoRoll::readConfiguration(Xml& xml)
+ {
+ for (;;) {
+ Xml::Token token = xml.parse();
+ if (token == Xml::Error || token == Xml::End)
+ break;
+ const QString& tag = xml.s1();
+ switch (token) {
+ case Xml::TagStart:
+ if (tag == "quant")
+ _quantInit = xml.parseInt();
+ else if (tag == "raster")
+ _rasterInit = xml.parseInt();
+ else if (tag == "quantStrength")
+ _quantStrengthInit = xml.parseInt();
+ else if (tag == "quantLimit")
+ _quantLimitInit = xml.parseInt();
+ else if (tag == "quantLen")
+ _quantLenInit = xml.parseInt();
+ else if (tag == "to")
+ _toInit = xml.parseInt();
+ else if (tag == "colormode")
+ colorModeInit = xml.parseInt();
+ else if (tag == "width")
+ _widthInit = xml.parseInt();
+ else if (tag == "height")
+ _heightInit = xml.parseInt();
+ else
+ xml.unknown("PianoRoll");
+ break;
+ case Xml::TagEnd:
+ if (tag == "pianoroll")
+ return;
+ default:
+ break;
+ }
+ }
+ }
+
+//---------------------------------------------------------
+// writeConfiguration
+//---------------------------------------------------------
+
+void PianoRoll::writeConfiguration(int level, Xml& xml)
+ {
+ xml.tag(level++, "pianoroll");
+ xml.intTag(level, "quant", _quantInit);
+ xml.intTag(level, "raster", _rasterInit);
+ xml.intTag(level, "quantStrength", _quantStrengthInit);
+ xml.intTag(level, "quantLimit", _quantLimitInit);
+ xml.intTag(level, "quantLen", _quantLenInit);
+ xml.intTag(level, "to", _toInit);
+ xml.intTag(level, "width", _widthInit);
+ xml.intTag(level, "height", _heightInit);
+ xml.intTag(level, "colormode", colorModeInit);
+ xml.etag(level, "pianoroll");
+ }
+
+//---------------------------------------------------------
+// soloChanged
+// signal from solo button
+//---------------------------------------------------------
+
+void PianoRoll::soloChanged(bool flag)
+ {
+ audio->msgSetSolo(canvas->track(), flag);
+ song->update(SC_SOLO);
+ }
+
+//---------------------------------------------------------
+// setRaster
+//---------------------------------------------------------
+
+void PianoRoll::setRaster(int val)
+ {
+ _rasterInit = val;
+ MidiEditor::setRaster(val);
+ canvas->redrawGrid();
+ canvas->setFocus(); // give back focus after kb input
+ }
+
+//---------------------------------------------------------
+// setQuant
+//---------------------------------------------------------
+
+void PianoRoll::setQuant(int val)
+ {
+ _quantInit = val;
+ MidiEditor::setQuant(val);
+ canvas->setFocus();
+ }
+
+//---------------------------------------------------------
+// writeStatus
+//---------------------------------------------------------
+
+void PianoRoll::writeStatus(int level, Xml& xml) const
+ {
+ writePartList(level, xml);
+ xml.tag(level++, "pianoroll");
+ MidiEditor::writeStatus(level, xml);
+ splitter->writeStatus(level, xml);
+
+ for (std::list<CtrlEdit*>::const_iterator i = ctrlEditList.begin();
+ i != ctrlEditList.end(); ++i) {
+ (*i)->writeStatus(level, xml);
+ }
+
+ xml.intTag(level, "steprec", canvas->steprec());
+ xml.intTag(level, "midiin", canvas->midiin());
+ xml.intTag(level, "tool", int(canvas->tool()));
+ xml.intTag(level, "quantStrength", _quantStrength);
+ xml.intTag(level, "quantLimit", _quantLimit);
+ xml.intTag(level, "quantLen", _quantLen);
+ xml.intTag(level, "playEvents", _playEvents);
+ xml.intTag(level, "xpos", hscroll->pos());
+ xml.intTag(level, "xmag", hscroll->mag());
+ xml.intTag(level, "ypos", vscroll->pos());
+ xml.intTag(level, "ymag", vscroll->mag());
+ xml.tag(level, "/pianoroll");
+ }
+
+//---------------------------------------------------------
+// readStatus
+//---------------------------------------------------------
+
+void PianoRoll::readStatus(Xml& xml)
+ {
+ for (;;) {
+ Xml::Token token = xml.parse();
+ if (token == Xml::Error || token == Xml::End)
+ break;
+ const QString& tag = xml.s1();
+ switch (token) {
+ case Xml::TagStart:
+ if (tag == "steprec") {
+ int val = xml.parseInt();
+ canvas->setSteprec(val);
+ srec->setOn(val);
+ }
+ else if (tag == "midiin") {
+ int val = xml.parseInt();
+ canvas->setMidiin(val);
+ midiin->setOn(val);
+ }
+ else if (tag == "tool") {
+ int tool = xml.parseInt();
+ canvas->setTool(tool);
+ tools2->set(tool);
+ }
+ else if (tag == "midieditor")
+ MidiEditor::readStatus(xml);
+ else if (tag == "ctrledit") {
+ CtrlEdit* ctrl = addCtrl();
+ ctrl->readStatus(xml);
+ }
+ else if (tag == splitter->name())
+ splitter->readStatus(xml);
+ else if (tag == "quantStrength")
+ _quantStrength = xml.parseInt();
+ else if (tag == "quantLimit")
+ _quantLimit = xml.parseInt();
+ else if (tag == "quantLen")
+ _quantLen = xml.parseInt();
+ else if (tag == "playEvents") {
+ _playEvents = xml.parseInt();
+ canvas->playEvents(_playEvents);
+ speaker->setOn(_playEvents);
+ }
+ else if (tag == "xmag")
+ hscroll->setMag(xml.parseInt());
+ else if (tag == "xpos")
+ hscroll->setPos(xml.parseInt());
+ else if (tag == "ymag")
+ vscroll->setMag(xml.parseInt());
+ else if (tag == "ypos")
+ vscroll->setPos(xml.parseInt());
+ else
+ xml.unknown("PianoRoll");
+ break;
+ case Xml::TagEnd:
+ if (tag == "pianoroll") {
+ _quantInit = _quant;
+ _rasterInit = _raster;
+ toolbar->setRaster(_raster);
+ toolbar->setQuant(_quant);
+ canvas->redrawGrid();
+ return;
+ }
+ default:
+ break;
+ }
+ }
+ }
+
+static int rasterTable[] = {
+ //-9----8- 7 6 5 4 3(1/4) 2 1
+ 4, 8, 16, 32, 64, 128, 256, 512, 1024, // triple
+ 6, 12, 24, 48, 96, 192, 384, 768, 1536,
+ 9, 18, 36, 72, 144, 288, 576, 1152, 2304 // dot
+ };
+
+//---------------------------------------------------------
+// viewKeyPressEvent
+//---------------------------------------------------------
+
+void PianoRoll::keyPressEvent(QKeyEvent* event)
+ {
+ if (info->hasFocus()) {
+ event->ignore();
+ return;
+ }
+
+ int index;
+ int n = sizeof(rasterTable)/sizeof(*rasterTable);
+ for (index = 0; index < n; ++index)
+ if (rasterTable[index] == raster())
+ break;
+ if (index == n) {
+ index = 0;
+ // raster 1 is not in table
+ }
+ int off = (index / 9) * 9;
+ index = index % 9;
+
+ int val = 0;
+
+ PianoCanvas* pc = (PianoCanvas*)canvas;
+ int key = event->key();
+
+ if (event->state() & Qt::ShiftButton)
+ key += Qt::SHIFT;
+ if (event->state() & Qt::AltButton)
+ key += Qt::ALT;
+ if (event->state() & Qt::ControlButton)
+ key+= Qt::CTRL;
+
+ if (key == Qt::Key_Escape) {
+ close();
+ return;
+ }
+ else if (key == shortcuts[SHRT_TOOL_POINTER].key) {
+ tools2->set(PointerTool);
+ return;
+ }
+ else if (key == shortcuts[SHRT_TOOL_PENCIL].key) {
+ tools2->set(PencilTool);
+ return;
+ }
+ else if (key == shortcuts[SHRT_TOOL_RUBBER].key) {
+ tools2->set(RubberTool);
+ return;
+ }
+ else if (key == shortcuts[SHRT_TOOL_LINEDRAW].key) {
+ tools2->set(DrawTool);
+ return;
+ }
+ else if (key == shortcuts[SHRT_POS_INC].key) {
+ pc->pianoCmd(CMD_RIGHT);
+ return;
+ }
+ else if (key == shortcuts[SHRT_POS_DEC].key) {
+ pc->pianoCmd(CMD_LEFT);
+ return;
+ }
+ else if (key == shortcuts[SHRT_INSERT_AT_LOCATION].key) {
+ pc->pianoCmd(CMD_INSERT);
+ return;
+ }
+ else if (key == Qt::Key_Delete) {
+ pc->pianoCmd(CMD_DELETE);
+ return;
+ }
+ else if (key == shortcuts[SHRT_ZOOM_IN].key) {
+ int mag = hscroll->mag();
+ int zoomlvl = ScrollScale::getQuickZoomLevel(mag);
+ if (zoomlvl < 23)
+ zoomlvl++;
+
+ int newmag = ScrollScale::convertQuickZoomLevelToMag(zoomlvl);
+ hscroll->setMag(newmag);
+ //printf("mag = %d zoomlvl = %d newmag = %d\n", mag, zoomlvl, newmag);
+ return;
+ }
+ else if (key == shortcuts[SHRT_ZOOM_OUT].key) {
+ int mag = hscroll->mag();
+ int zoomlvl = ScrollScale::getQuickZoomLevel(mag);
+ if (zoomlvl > 1)
+ zoomlvl--;
+
+ int newmag = ScrollScale::convertQuickZoomLevelToMag(zoomlvl);
+ hscroll->setMag(newmag);
+ //printf("mag = %d zoomlvl = %d newmag = %d\n", mag, zoomlvl, newmag);
+ return;
+ }
+ else if (key == shortcuts[SHRT_GOTO_CPOS].key) {
+ PartList* p = this->parts();
+ Part* first = p->begin()->second;
+ hscroll->setPos(song->cpos() - first->tick() );
+ return;
+ }
+ else if (key == shortcuts[SHRT_SCROLL_LEFT].key) {
+ int pos = hscroll->pos() - config.division;
+ if (pos < 0)
+ pos = 0;
+ hscroll->setPos(pos);
+ return;
+ }
+ else if (key == shortcuts[SHRT_SCROLL_RIGHT].key) {
+ int pos = hscroll->pos() + config.division;
+ hscroll->setPos(pos);
+ return;
+ }
+ else if (key == shortcuts[SHRT_SET_QUANT_1].key)
+ val = rasterTable[8 + off];
+ else if (key == shortcuts[SHRT_SET_QUANT_2].key)
+ val = rasterTable[7 + off];
+ else if (key == shortcuts[SHRT_SET_QUANT_3].key)
+ val = rasterTable[6 + off];
+ else if (key == shortcuts[SHRT_SET_QUANT_4].key)
+ val = rasterTable[5 + off];
+ else if (key == shortcuts[SHRT_SET_QUANT_5].key)
+ val = rasterTable[4 + off];
+ else if (key == shortcuts[SHRT_SET_QUANT_6].key)
+ val = rasterTable[3 + off];
+ else if (key == shortcuts[SHRT_SET_QUANT_7].key)
+ val = rasterTable[2 + off];
+ else if (key == shortcuts[SHRT_TOGGLE_TRIOL].key)
+ val = rasterTable[index + ((off == 0) ? 9 : 0)];
+ else if (key == shortcuts[SHRT_EVENT_COLOR].key) {
+ if (colorMode == 0)
+ colorMode = 1;
+ else if (colorMode == 1)
+ colorMode = 2;
+ else
+ colorMode = 0;
+ setEventColorMode(colorMode);
+ return;
+ }
+ else if (key == shortcuts[SHRT_TOGGLE_PUNCT].key)
+ val = rasterTable[index + ((off == 18) ? 9 : 18)];
+
+ else if (key == shortcuts[SHRT_TOGGLE_PUNCT2].key) {//CDW
+ if ((off == 18) && (index > 2)) {
+ val = rasterTable[index + 9 - 1];
+ }
+ else if ((off == 9) && (index < 8)) {
+ val = rasterTable[index + 18 + 1];
+ }
+ else
+ return;
+ }
+ else { //Default:
+ event->ignore();
+ return;
+ }
+ setQuant(val);
+ setRaster(val);
+ toolbar->setQuant(_quant);
+ toolbar->setRaster(_raster);
+ }
+
+//---------------------------------------------------------
+// configQuant
+//---------------------------------------------------------
+
+void PianoRoll::configQuant()
+ {
+ if (!quantConfig) {
+ quantConfig = new QuantConfig(_quantStrength, _quantLimit, _quantLen);
+ connect(quantConfig, SIGNAL(setQuantStrength(int)), SLOT(setQuantStrength(int)));
+ connect(quantConfig, SIGNAL(setQuantLimit(int)), SLOT(setQuantLimit(int)));
+ connect(quantConfig, SIGNAL(setQuantLen(bool)), SLOT(setQuantLen(bool)));
+ }
+ quantConfig->show();
+ }
+
+//---------------------------------------------------------
+// setSteprec
+//---------------------------------------------------------
+
+void PianoRoll::setSteprec(bool flag)
+ {
+ canvas->setSteprec(flag);
+ if (flag == false)
+ midiin->setOn(flag);
+ }
+
+//---------------------------------------------------------
+// setEventColorMode
+//---------------------------------------------------------
+
+void PianoRoll::setEventColorMode(int mode)
+ {
+ colorMode = mode;
+ colorModeInit = colorMode;
+ eventColor->setItemChecked(0, mode == 0);
+ eventColor->setItemChecked(1, mode == 1);
+ eventColor->setItemChecked(2, mode == 2);
+ ((PianoCanvas*)(canvas))->setColorMode(colorMode);
+ }
+
+//---------------------------------------------------------
+// clipboardChanged
+//---------------------------------------------------------
+
+void PianoRoll::clipboardChanged()
+ {
+ QMimeSource* ms = QApplication::clipboard()->data(QClipboard::Clipboard);
+ bool flag = false;
+ if (ms) {
+ for (int i = 0;; ++i) {
+ if (ms->format(i) == 0)
+ break;
+// printf("clipboard changed %s\n", ms->format(i));
+ flag = strcmp(ms->format(i), "text/eventlist;charset=UTF-8") == 0;
+ if (flag)
+ break;
+ }
+ }
+ menuEdit->setItemEnabled(PianoCanvas::CMD_PASTE, flag);
+ }
+
+//---------------------------------------------------------
+// selectionChanged
+//---------------------------------------------------------
+
+void PianoRoll::selectionChanged()
+ {
+ bool flag = canvas->selectionSize() > 0;
+ menuEdit->setItemEnabled(PianoCanvas::CMD_CUT, flag);
+ menuEdit->setItemEnabled(PianoCanvas::CMD_COPY, flag);
+ menuEdit->setItemEnabled(PianoCanvas::CMD_DEL, flag);
+ }
+
+//---------------------------------------------------------
+// setSpeaker
+//---------------------------------------------------------
+
+void PianoRoll::setSpeaker(bool val)
+ {
+ _playEvents = val;
+ canvas->playEvents(_playEvents);
+ }
+
+//---------------------------------------------------------
+// resizeEvent
+//---------------------------------------------------------
+
+void PianoRoll::resizeEvent(QResizeEvent* ev)
+ {
+ QWidget::resizeEvent(ev);
+ _widthInit = ev->size().width();
+ _heightInit = ev->size().height();
+ }
+
+
+//---------------------------------------------------------
+// initShortcuts
+//---------------------------------------------------------
+
+void PianoRoll::initShortcuts()
+ {
+ menuSelect->setAccel(shortcuts[SHRT_SELECT_ALL].key, PianoCanvas::CMD_SELECT_ALL);
+ menuSelect->setAccel(shortcuts[SHRT_SELECT_NONE].key, PianoCanvas::CMD_SELECT_NONE);
+ menuSelect->setAccel(shortcuts[SHRT_SELECT_INVERT].key, PianoCanvas::CMD_SELECT_INVERT);
+ menuSelect->setAccel(shortcuts[SHRT_SELECT_ILOOP].key, PianoCanvas::CMD_SELECT_ILOOP);
+ menuSelect->setAccel(shortcuts[SHRT_SELECT_OLOOP].key, PianoCanvas::CMD_SELECT_OLOOP);
+
+ menuSelect->setAccel(shortcuts[SHRT_SELECT_PREV_PART].key, PianoCanvas::CMD_SELECT_PREV_PART);
+ menuSelect->setAccel(shortcuts[SHRT_SELECT_NEXT_PART].key, PianoCanvas::CMD_SELECT_NEXT_PART);
+
+ menuConfig->setAccel(shortcuts[SHRT_EVENT_COLOR].key, menu_ids[CMD_EVENT_COLOR]);
+
+ menuFunctions->setAccel(shortcuts[SHRT_OVER_QUANTIZE].key, PianoCanvas::CMD_OVER_QUANTIZE);
+ menuFunctions->setAccel(shortcuts[SHRT_ON_QUANTIZE].key, PianoCanvas::CMD_ON_QUANTIZE);
+ menuFunctions->setAccel(shortcuts[SHRT_ONOFF_QUANTIZE].key, PianoCanvas::CMD_ONOFF_QUANTIZE);
+ menuFunctions->setAccel(shortcuts[SHRT_ITERATIVE_QUANTIZE].key, PianoCanvas::CMD_ITERATIVE_QUANTIZE);
+ menuFunctions->setAccel(shortcuts[SHRT_MODIFY_GATE_TIME].key, PianoCanvas::CMD_MODIFY_GATE_TIME);
+ menuFunctions->setAccel(shortcuts[SHRT_MODIFY_VELOCITY].key, PianoCanvas::CMD_MODIFY_VELOCITY);
+ menuFunctions->setAccel(shortcuts[SHRT_CRESCENDO].key, PianoCanvas::CMD_CRESCENDO);
+ menuFunctions->setAccel(shortcuts[SHRT_TRANSPOSE].key, PianoCanvas::CMD_TRANSPOSE);
+ menuFunctions->setAccel(shortcuts[SHRT_THIN_OUT].key, PianoCanvas::CMD_THIN_OUT);
+ menuFunctions->setAccel(shortcuts[SHRT_ERASE_EVENT].key, PianoCanvas::CMD_ERASE_EVENT);
+ menuFunctions->setAccel(shortcuts[SHRT_NOTE_SHIFT].key, PianoCanvas::CMD_NOTE_SHIFT);
+ menuFunctions->setAccel(shortcuts[SHRT_MOVE_CLOCK].key, PianoCanvas::CMD_MOVE_CLOCK);
+ menuFunctions->setAccel(shortcuts[SHRT_COPY_MEASURE].key, PianoCanvas::CMD_COPY_MEASURE);
+ menuFunctions->setAccel(shortcuts[SHRT_ERASE_MEASURE].key, PianoCanvas::CMD_ERASE_MEASURE);
+ menuFunctions->setAccel(shortcuts[SHRT_DELETE_MEASURE].key, PianoCanvas::CMD_DELETE_MEASURE);
+ menuFunctions->setAccel(shortcuts[SHRT_CREATE_MEASURE].key, PianoCanvas::CMD_CREATE_MEASURE);
+ menuFunctions->setAccel(shortcuts[SHRT_CONFIG_QUANT].key, menu_ids[CMD_CONFIG_QUANT]);
+ menuFunctions->setAccel(shortcuts[SHRT_FIXED_LEN].key, PianoCanvas::CMD_FIXED_LEN);
+ menuFunctions->setAccel(shortcuts[SHRT_DELETE_OVERLAPS].key, PianoCanvas::CMD_DELETE_OVERLAPS);
+ }
+
+//---------------------------------------------------------
+// execDeliveredScript
+//---------------------------------------------------------
+void PianoRoll::execDeliveredScript(int id)
+{
+ //QString scriptfile = QString(INSTPREFIX) + SCRIPTSSUFFIX + deliveredScriptNames[id];
+ QString scriptfile = song->getScriptPath(id, true);
+ song->executeScript(scriptfile.latin1(), parts(), quant(), true);
+}
+
+//---------------------------------------------------------
+// execUserScript
+//---------------------------------------------------------
+void PianoRoll::execUserScript(int id)
+{
+ QString scriptfile = song->getScriptPath(id, false);
+ song->executeScript(scriptfile.latin1(), parts(), quant(), true);
+}
+
diff --git a/muse2/muse/midiedit/pianoroll.h b/muse2/muse/midiedit/pianoroll.h
new file mode 100644
index 00000000..8987915a
--- /dev/null
+++ b/muse2/muse/midiedit/pianoroll.h
@@ -0,0 +1,146 @@
+//=========================================================
+// MusE
+// Linux Music Editor
+// $Id: pianoroll.h,v 1.5.2.4 2009/11/16 11:29:33 lunar_shuttle Exp $
+// (C) Copyright 1999 Werner Schweer (ws@seh.de)
+//=========================================================
+
+#ifndef __PIANOROLL_H__
+#define __PIANOROLL_H__
+
+#include <qwidget.h>
+#include <q3mainwindow.h>
+//Added by qt3to4:
+#include <QCloseEvent>
+#include <QResizeEvent>
+#include <QLabel>
+#include <Q3PopupMenu>
+#include <QKeyEvent>
+
+#include <values.h>
+#include "noteinfo.h"
+#include "cobject.h"
+#include "midieditor.h"
+#include "tools.h"
+#include "event.h"
+
+class MidiPart;
+class TimeLabel;
+class PitchLabel;
+class QLabel;
+class PianoCanvas;
+class IntLabel;
+class MTScale;
+class Track;
+class QToolButton;
+class QPushButton;
+class CtrlEdit;
+class Splitter;
+class PartList;
+class Toolbar1;
+class Xml;
+class QuantConfig;
+class ScrollScale;
+class Part;
+class SNode;
+
+//---------------------------------------------------------
+// PianoRoll
+//---------------------------------------------------------
+
+class PianoRoll : public MidiEditor {
+ Event selEvent;
+ MidiPart* selPart;
+ int selTick;
+
+ enum { CMD_EVENT_COLOR, CMD_CONFIG_QUANT, CMD_LAST };
+ int menu_ids[CMD_LAST];
+ Q3PopupMenu *menuEdit, *menuFunctions, *menuSelect, *menuConfig, *menuPlugins;
+
+ int tickOffset;
+ int lenOffset;
+ int pitchOffset;
+ int veloOnOffset;
+ int veloOffOffset;
+ bool deltaMode;
+
+ NoteInfo* info;
+ QToolButton* srec;
+ QToolButton* midiin;
+
+ Toolbar1* toolbar;
+ Splitter* splitter;
+
+ QToolButton* speaker;
+ Q3ToolBar* tools;
+ EditToolBar* tools2;
+
+ Q3PopupMenu* eventColor;
+ int colorMode;
+
+ static int _quantInit, _rasterInit;
+ static int _widthInit, _heightInit;
+
+ static int _quantStrengthInit;
+ static int _quantLimitInit;
+ static bool _quantLenInit;
+ static int _toInit;
+ static int colorModeInit;
+
+ int _quantStrength;
+ int _quantLimit;
+ int _to;
+ bool _quantLen;
+ QuantConfig* quantConfig;
+ bool _playEvents;
+
+
+ Q_OBJECT
+ void initShortcuts();
+ QWidget* genToolbar(QWidget* parent);
+ virtual void closeEvent(QCloseEvent*);
+ virtual void keyPressEvent(QKeyEvent*);
+ virtual void resizeEvent(QResizeEvent*);
+
+ private slots:
+ void setSelection(int, Event&, Part*);
+ void noteinfoChanged(NoteInfo::ValType, int);
+ CtrlEdit* addCtrl();
+ void removeCtrl(CtrlEdit* ctrl);
+ void soloChanged(bool flag);
+ void setRaster(int);
+ void setQuant(int);
+ void configQuant();
+ void setQuantStrength(int val) { _quantStrength = val; }
+ void setQuantLimit(int val) { _quantLimit = val; }
+ void setQuantLen(bool val) { _quantLen = val; }
+ void cmd(int);
+ void setSteprec(bool);
+ void setTo(int val) { _to = val; }
+ void setEventColorMode(int);
+ void clipboardChanged(); // enable/disable "Paste"
+ void selectionChanged(); // enable/disable "Copy" & "Paste"
+ void setSpeaker(bool);
+ void setTime(unsigned);
+ void follow(int pos);
+ void songChanged1(int);
+ void configChanged();
+
+ signals:
+ void deleted(unsigned long);
+
+ public slots:
+ virtual void updateHScrollRange();
+ void execDeliveredScript(int id);
+ void execUserScript(int id);
+ public:
+ PianoRoll(PartList*, QWidget* parent = 0, const char* name = 0, unsigned initPos = MAXINT);
+ ~PianoRoll();
+ virtual void readStatus(Xml&);
+ virtual void writeStatus(int, Xml&) const;
+ static void readConfiguration(Xml&);
+ static void writeConfiguration(int, Xml&);
+ };
+
+#endif
+
diff --git a/muse2/muse/midiedit/prcanvas.cpp b/muse2/muse/midiedit/prcanvas.cpp
new file mode 100644
index 00000000..484a12ad
--- /dev/null
+++ b/muse2/muse/midiedit/prcanvas.cpp
@@ -0,0 +1,1695 @@
+//=========================================================
+// MusE
+// Linux Music Editor
+// $Id: prcanvas.cpp,v 1.20.2.19 2009/11/16 11:29:33 lunar_shuttle Exp $
+// (C) Copyright 1999-2004 Werner Schweer (ws@seh.de)
+//=========================================================
+
+#include <qapplication.h>
+#include <qclipboard.h>
+#include <qpainter.h>
+#include <q3dragobject.h>
+#include <qmessagebox.h>
+//Added by qt3to4:
+#include <QDragLeaveEvent>
+#include <Q3CString>
+#include <QDragEnterEvent>
+#include <QDragMoveEvent>
+#include <QDropEvent>
+#include <QMouseEvent>
+
+#include <values.h>
+#include <stdio.h>
+#include <math.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <dirent.h>
+
+#include "xml.h"
+#include "prcanvas.h"
+#include "midiport.h"
+#include "event.h"
+#include "mpevent.h"
+#include "globals.h"
+#include "cmd.h"
+#include "gatetime.h"
+#include "velocity.h"
+#include "song.h"
+#include "audio.h"
+
+//---------------------------------------------------------
+// NEvent
+//---------------------------------------------------------
+
+NEvent::NEvent(Event& e, Part* p, int y) : CItem(e, p)
+ {
+ y = y - KH/4;
+ unsigned tick = e.tick() + p->tick();
+ setPos(QPoint(tick, y));
+ setBBox(QRect(tick, y, e.lenTick(), KH/2));
+ }
+
+//---------------------------------------------------------
+// addItem
+//---------------------------------------------------------
+
+void PianoCanvas::addItem(Part* part, Event& event)
+ {
+ if (signed(event.tick())<0) {
+ printf("ERROR: trying to add event before current part!\n");
+ return;
+ }
+
+ NEvent* ev = new NEvent(event, part, pitch2y(event.pitch()));
+ items.add(ev);
+
+ int diff = event.endTick()-part->lenTick();
+ if (diff > 0) {// too short part? extend it
+ //printf("addItem - this code should not be run!\n");
+ //Part* newPart = part->clone();
+ //newPart->setLenTick(newPart->lenTick()+diff);
+ //audio->msgChangePart(part, newPart,false);
+ //part = newPart;
+ part->setLenTick(part->lenTick()+diff);
+ }
+ }
+
+//---------------------------------------------------------
+// PianoCanvas
+//---------------------------------------------------------
+
+PianoCanvas::PianoCanvas(MidiEditor* pr, QWidget* parent, int sx, int sy)
+ : EventCanvas(pr, parent, sx, sy)
+ {
+ colorMode = 0;
+ cmdRange = 0; // all Events
+ playedPitch = -1;
+
+ songChanged(SC_TRACK_INSERTED);
+ connect(song, SIGNAL(midiNote(int, int)), SLOT(midiNote(int,int)));
+ }
+
+//---------------------------------------------------------
+// pitch2y
+//---------------------------------------------------------
+
+int PianoCanvas::pitch2y(int pitch) const
+ {
+ int tt[] = {
+ 5, 12, 19, 26, 33, 44, 51, 58, 64, 71, 78, 85
+ };
+ int y = (75 * KH) - (tt[pitch%12] + (7 * KH) * (pitch/12));
+ if (y < 0)
+ y = 0;
+ return y;
+ }
+
+//---------------------------------------------------------
+// y2pitch
+//---------------------------------------------------------
+
+int PianoCanvas::y2pitch(int y) const
+ {
+ const int total = (10 * 7 + 5) * KH; // 75 Ganztonschritte
+ y = total - y;
+ int oct = (y / (7 * KH)) * 12;
+ char kt[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 5
+ 1, 1, 1, 1, 1, 1, 1, // 13
+ 2, 2, 2, 2, 2, 2, // 19
+ 3, 3, 3, 3, 3, 3, 3, // 26
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, // 34
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, // 43
+ 6, 6, 6, 6, 6, 6, 6, // 52
+ 7, 7, 7, 7, 7, 7, // 58
+ 8, 8, 8, 8, 8, 8, 8, // 65
+ 9, 9, 9, 9, 9, 9, // 71
+ 10, 10, 10, 10, 10, 10, 10, // 78
+ 11, 11, 11, 11, 11, 11, 11, 11, 11, 11 // 87
+ };
+ return kt[y % 91] + oct;
+ }
+
+//---------------------------------------------------------
+// drawEvent
+// draws a note
+//---------------------------------------------------------
+
+void PianoCanvas::drawItem(QPainter& p, const CItem* item,
+ const QRect& rect)
+ {
+ QRect r = item->bbox();
+ if(!virt())
+ r.moveCenter(map(item->pos()));
+ r = r.intersect(rect);
+ if(!r.isValid())
+ return;
+ p.setPen(Qt::black);
+ struct Triple {
+ int r, g, b;
+ };
+
+ static Triple myColors /*Qt::color1*/[12] = { // ddskrjp
+ { 0xff, 0x3d, 0x39 },
+ { 0x39, 0xff, 0x39 },
+ { 0x39, 0x3d, 0xff },
+ { 0xff, 0xff, 0x39 },
+ { 0xff, 0x3d, 0xff },
+ { 0x39, 0xff, 0xff },
+ { 0xff, 0x7e, 0x7a },
+ { 0x7a, 0x7e, 0xff },
+ { 0x7a, 0xff, 0x7a },
+ { 0xff, 0x7e, 0xbf },
+ { 0x7a, 0xbf, 0xff },
+ { 0xff, 0xbf, 0x7a }
+ };
+
+ NEvent* nevent = (NEvent*) item;
+ Event event = nevent->event();
+ if (nevent->part() != curPart){
+ if(item->isMoving())
+ p.setBrush(Qt::gray);
+ else if(item->isSelected())
+ p.setBrush(Qt::black);
+ else
+ p.setBrush(Qt::lightGray);
+ }
+ else {
+ if (item->isMoving()) {
+ p.setBrush(Qt::gray);
+ }
+ else if (item->isSelected()) {
+ p.setBrush(Qt::black);
+ }
+ else {
+ QColor color;
+ color.setRgb(0, 0, 255);
+ switch(colorMode) {
+ case 0:
+ break;
+ case 1: // pitch
+ {
+ Triple* c = &myColors/*Qt::color1*/[event.pitch() % 12];
+ color.setRgb(c->r, c->g, c->b);
+ }
+ break;
+ case 2: // velocity
+ {
+ int velo = event.velo();
+ if (velo < 64)
+ color.setRgb(velo*4, 0, 0xff);
+ else
+ color.setRgb(0xff, 0, (127-velo) * 4);
+ }
+ break;
+ }
+ p.setBrush(color);
+ }
+ }
+ p.drawRect(r);
+ }
+
+
+//---------------------------------------------------------
+// drawMoving
+// draws moving items
+//---------------------------------------------------------
+
+void PianoCanvas::drawMoving(QPainter& p, const CItem* item, const QRect& rect)
+ {
+ //if(((NEvent*)item)->part() != curPart)
+ // return;
+ //if(!item->isMoving())
+ // return;
+ QRect mr = QRect(item->mp().x(), item->mp().y() - item->height()/2, item->width(), item->height());
+ mr = mr.intersect(rect);
+ if(!mr.isValid())
+ return;
+ p.setPen(Qt::black);
+ p.setBrush(Qt::NoBrush);
+ p.drawRect(mr);
+ }
+
+//---------------------------------------------------------
+// viewMouseDoubleClickEvent
+//---------------------------------------------------------
+
+void PianoCanvas::viewMouseDoubleClickEvent(QMouseEvent* event)
+ {
+ if ((_tool != PointerTool) && (event->button() != Qt::LeftButton)) {
+ mousePress(event);
+ return;
+ }
+ }
+
+//---------------------------------------------------------
+// moveCanvasItems
+//---------------------------------------------------------
+
+void PianoCanvas::moveCanvasItems(CItemList& items, int dp, int dx, DragType dtype, int* pflags)
+{
+ if(editor->parts()->empty())
+ return;
+
+ PartsToChangeMap parts2change;
+
+ int modified = 0;
+ for(iPart ip = editor->parts()->begin(); ip != editor->parts()->end(); ++ip)
+ {
+ Part* part = ip->second;
+ if(!part)
+ continue;
+
+ int npartoffset = 0;
+ for(iCItem ici = items.begin(); ici != items.end(); ++ici)
+ {
+ CItem* ci = ici->second;
+ if(ci->part() != part)
+ continue;
+
+ int x = ci->pos().x() + dx;
+ int y = pitch2y(y2pitch(ci->pos().y()) + dp);
+ QPoint newpos = raster(QPoint(x, y));
+
+ // Test moving the item...
+ NEvent* nevent = (NEvent*) ci;
+ Event event = nevent->event();
+ x = newpos.x();
+ if(x < 0)
+ x = 0;
+ int ntick = editor->rasterVal(x) - part->tick();
+ if(ntick < 0)
+ ntick = 0;
+ int diff = ntick + event.lenTick() - part->lenTick();
+
+ // If moving the item would require a new part size...
+ if(diff > npartoffset)
+ npartoffset = diff;
+ }
+
+ if(npartoffset > 0)
+ {
+ // Create new part...
+ // if there are several events that are moved outside the part, it will be recreated for each
+ // so the part _in_ the event will not be valid, ask the authority.
+// Part* newPart = part->clone();
+ //Part* newPart = Canvas::part()->clone();
+
+// newPart->setLenTick(newPart->lenTick() + npartoffset);
+ //audio->msgChangePart(part, newPart,false);
+
+// modified = SC_PART_MODIFIED;
+
+ // BUG FIX: #1650953
+ // Added by T356.
+ // Fixes posted "select and drag past end of part - crashing" bug
+// for(iPart ip = editor->parts()->begin(); ip != editor->parts()->end(); ++ip)
+// {
+// if(ip->second == part)
+// {
+// editor->parts()->erase(ip);
+// break;
+// }
+// }
+
+// editor->parts()->add(newPart);
+// audio->msgChangePart(part, newPart,false);
+
+ //if(parts2change.find(part) == parts2change.end())
+ // parts2change.insert(std::pair<Part*, Part*> (part, newPart));
+ iPartToChange ip2c = parts2change.find(part);
+ if(ip2c == parts2change.end())
+ {
+ PartToChange p2c = {0, npartoffset};
+ parts2change.insert(std::pair<Part*, PartToChange> (part, p2c));
+ }
+ else
+ ip2c->second.xdiff = npartoffset;
+
+ //part = newPart; // reassign
+ //item->setPart(part);
+ //item->setEvent(newEvent);
+ //curPart = part;
+ //curPartId = curPart->sn();
+
+ }
+ }
+
+ for(iPartToChange ip2c = parts2change.begin(); ip2c != parts2change.end(); ++ip2c)
+ {
+ Part* opart = ip2c->first;
+ int diff = ip2c->second.xdiff;
+
+ Part* newPart = opart->clone();
+
+ newPart->setLenTick(newPart->lenTick() + diff);
+
+ modified = SC_PART_MODIFIED;
+
+ // BUG FIX: #1650953
+ // Added by T356.
+ // Fixes posted "select and drag past end of part - crashing" bug
+ for(iPart ip = editor->parts()->begin(); ip != editor->parts()->end(); ++ip)
+ {
+ if(ip->second == opart)
+ {
+ editor->parts()->erase(ip);
+ break;
+ }
+ }
+
+ editor->parts()->add(newPart);
+ // Indicate no undo, and do port controller values but not clone parts.
+ audio->msgChangePart(opart, newPart, false, true, false);
+
+ ip2c->second.npart = newPart;
+
+ }
+
+ iPartToChange icp = parts2change.find(curPart);
+ if(icp != parts2change.end())
+ {
+ curPart = icp->second.npart;
+ curPartId = curPart->sn();
+ }
+
+ std::vector< CItem* > doneList;
+ typedef std::vector< CItem* >::iterator iDoneList;
+
+ for(iCItem ici = items.begin(); ici != items.end(); ++ici)
+ {
+ CItem* ci = ici->second;
+
+ // If this item's part is in the parts2change list, change the item's part to the new part.
+ Part* pt = ci->part();
+ iPartToChange ip2c = parts2change.find(pt);
+ if(ip2c != parts2change.end())
+ ci->setPart(ip2c->second.npart);
+
+ int x = ci->pos().x();
+ int y = ci->pos().y();
+ int nx = x + dx;
+ int ny = pitch2y(y2pitch(y) + dp);
+ QPoint newpos = raster(QPoint(nx, ny));
+ selectItem(ci, true);
+
+ iDoneList idl;
+ for(idl = doneList.begin(); idl != doneList.end(); ++idl)
+ // This compares EventBase pointers to see if they're the same...
+ if((*idl)->event() == ci->event())
+ break;
+
+ // Do not process if the event has already been processed (meaning it's an event in a clone part)...
+ //if(moveItem(ci, newpos, dtype))
+ if(idl != doneList.end())
+ // Just move the canvas item.
+ ci->move(newpos);
+ else
+ {
+ // Currently moveItem always returns true.
+ if(moveItem(ci, newpos, dtype))
+ {
+ // Add the canvas item to the list of done items.
+ doneList.push_back(ci);
+ // Move the canvas item.
+ ci->move(newpos);
+ }
+ }
+
+ if(moving.size() == 1)
+ itemReleased(curItem, newpos);
+ if(dtype == MOVE_COPY || dtype == MOVE_CLONE)
+ selectItem(ci, false);
+ }
+
+ if(pflags)
+ *pflags = modified;
+}
+
+//---------------------------------------------------------
+// moveItem
+// called after moving an object
+//---------------------------------------------------------
+
+// Changed by T356.
+//bool PianoCanvas::moveItem(CItem* item, const QPoint& pos, DragType dtype, int* pflags)
+bool PianoCanvas::moveItem(CItem* item, const QPoint& pos, DragType dtype)
+ {
+ NEvent* nevent = (NEvent*) item;
+ Event event = nevent->event();
+ int npitch = y2pitch(pos.y());
+ Event newEvent = event.clone();
+ int x = pos.x();
+ if (x < 0)
+ x = 0;
+ if (event.pitch() != npitch && _playEvents) {
+ int port = track()->outPort();
+ int channel = track()->outChannel();
+ // release note:
+ MidiPlayEvent ev1(0, port, channel, 0x90, event.pitch() + track()->transposition, 0);
+ audio->msgPlayMidiEvent(&ev1);
+ MidiPlayEvent ev2(0, port, channel, 0x90, npitch + track()->transposition, event.velo());
+ audio->msgPlayMidiEvent(&ev2);
+ }
+
+ // Changed by T356.
+ Part* part = nevent->part(); //
+ //Part * part = Canvas::part(); // part can be dynamically recreated, ask the authority
+
+ newEvent.setPitch(npitch);
+ int ntick = editor->rasterVal(x) - part->tick();
+ if (ntick < 0)
+ ntick = 0;
+ newEvent.setTick(ntick);
+ newEvent.setLenTick(event.lenTick());
+
+ // Removed by T356.
+ /*
+ int modified=0;
+ //song->startUndo();
+ int diff = newEvent.endTick()-part->lenTick();
+ if (diff > 0){// too short part? extend it
+ // if there are several events that are moved outside the part, it will be recreated for each
+ // so the part _in_ the event will not be valid, ask the authority.
+ //Part* newPart = part->clone();
+ Part* newPart = Canvas::part()->clone();
+
+ newPart->setLenTick(newPart->lenTick()+diff);
+ audio->msgChangePart(Canvas::part(), newPart,false);
+
+ modified = SC_PART_MODIFIED;
+ part = newPart; // reassign
+
+ // BUG FIX: #1650953
+ // Added by T356.
+ // Fixes posted "select and drag past end of part - crashing" bug
+ for(iPart i = editor->parts()->begin(); i != editor->parts()->end(); ++i)
+ {
+ if(i->second == Canvas::part())
+ {
+ editor->parts()->erase(i);
+ break;
+ }
+ }
+ editor->parts()->add(part);
+ item->setPart(part);
+ item->setEvent(newEvent);
+ curPart = part;
+ curPartId = curPart->sn();
+
+ }
+ */
+
+ // Added by T356.
+ // msgAddEvent and msgChangeEvent (below) will set these, but set them here first?
+ //item->setPart(part);
+ item->setEvent(newEvent);
+
+ // Added by T356.
+ if(((int)newEvent.endTick() - (int)part->lenTick()) > 0)
+ printf("PianoCanvas::moveItem Error! New event end:%d exceeds length:%d of part:%s\n", newEvent.endTick(), part->lenTick(), part->name().latin1());
+
+ if (dtype == MOVE_COPY || dtype == MOVE_CLONE)
+ // Indicate no undo, and do not do port controller values and clone parts.
+ //audio->msgAddEvent(newEvent, part, false);
+ audio->msgAddEvent(newEvent, part, false, false, false);
+ else
+ // Indicate no undo, and do not do port controller values and clone parts.
+ //audio->msgChangeEvent(event, newEvent, part, false);
+ audio->msgChangeEvent(event, newEvent, part, false, false, false);
+ //song->endUndo(modified);
+
+ // Removed by T356.
+ //if(pflags)
+ // *pflags = modified;
+
+ return true;
+ }
+
+//---------------------------------------------------------
+// newItem(p, state)
+//---------------------------------------------------------
+
+CItem* PianoCanvas::newItem(const QPoint& p, int)
+ {
+ //printf("newItem point\n");
+ int pitch = y2pitch(p.y());
+ int tick = editor->rasterVal1(p.x());
+ int len = p.x() - tick;
+ tick -= curPart->tick();
+ if (tick < 0)
+ tick=0;
+ Event e = Event(Note);
+ e.setTick(tick);
+ e.setPitch(pitch);
+ e.setVelo(curVelo);
+ e.setLenTick(len);
+ return new NEvent(e, curPart, pitch2y(pitch));
+ }
+
+void PianoCanvas::newItem(CItem* item, bool noSnap)
+ {
+ //printf("newItem citem\n");
+ NEvent* nevent = (NEvent*) item;
+ Event event = nevent->event();
+ int x = item->x();
+ if (x<0)
+ x=0;
+ int w = item->width();
+
+ if (!noSnap) {
+ x = editor->rasterVal1(x); //round down
+ w = editor->rasterVal(x + w) - x;
+ if (w == 0)
+ w = editor->raster();
+ }
+ Part* part = nevent->part();
+ event.setTick(x - part->tick());
+ event.setLenTick(w);
+ event.setPitch(y2pitch(item->y()));
+
+ song->startUndo();
+ int modified=SC_EVENT_MODIFIED;
+ int diff = event.endTick()-part->lenTick();
+ if (diff > 0) {// too short part? extend it
+ //printf("extend Part!\n");
+ Part* newPart = part->clone();
+ newPart->setLenTick(newPart->lenTick()+diff);
+ // Indicate no undo, and do port controller values but not clone parts.
+ //audio->msgChangePart(part, newPart,false);
+ audio->msgChangePart(part, newPart, false, true, false);
+ modified=modified|SC_PART_MODIFIED;
+ part = newPart; // reassign
+ }
+ // Indicate no undo, and do not do port controller values and clone parts.
+ //audio->msgAddEvent(event, part,false);
+ audio->msgAddEvent(event, part, false, false, false);
+ song->endUndo(modified);
+ }
+
+//---------------------------------------------------------
+// resizeItem
+//---------------------------------------------------------
+
+void PianoCanvas::resizeItem(CItem* item, bool noSnap) // experimental changes to try dynamically extending parts
+ {
+ //printf("resizeItem!\n");
+ NEvent* nevent = (NEvent*) item;
+ Event event = nevent->event();
+ Event newEvent = event.clone();
+ int len;
+
+ Part* part = nevent->part();
+
+ if (noSnap)
+ len = nevent->width();
+ else {
+ //Part* part = nevent->part();
+ unsigned tick = event.tick() + part->tick();
+ len = editor->rasterVal(tick + nevent->width()) - tick;
+ if (len <= 0)
+ len = editor->raster();
+ }
+ song->startUndo();
+ int modified=SC_EVENT_MODIFIED;
+ //printf("event.tick()=%d len=%d part->lenTick()=%d\n",event.endTick(),len,part->lenTick());
+ int diff = event.tick()+len-part->lenTick();
+ if (diff > 0) {// too short part? extend it
+ //printf("extend Part!\n");
+ Part* newPart = part->clone();
+ newPart->setLenTick(newPart->lenTick()+diff);
+ // Indicate no undo, and do port controller values but not clone parts.
+ //audio->msgChangePart(part, newPart,false);
+ audio->msgChangePart(part, newPart, false, true, false);
+ modified=modified|SC_PART_MODIFIED;
+ part = newPart; // reassign
+ }
+
+ newEvent.setLenTick(len);
+ // Indicate no undo, and do not do port controller values and clone parts.
+ //audio->msgChangeEvent(event, newEvent, nevent->part(),false);
+ audio->msgChangeEvent(event, newEvent, nevent->part(), false, false, false);
+ song->endUndo(modified);
+ }
+
+//---------------------------------------------------------
+// deleteItem
+//---------------------------------------------------------
+
+bool PianoCanvas::deleteItem(CItem* item)
+ {
+ NEvent* nevent = (NEvent*) item;
+ if (nevent->part() == curPart) {
+ Event ev = nevent->event();
+ // Indicate do undo, and do not do port controller values and clone parts.
+ //audio->msgDeleteEvent(ev, curPart);
+ audio->msgDeleteEvent(ev, curPart, true, false, false);
+ return true;
+ }
+ return false;
+ }
+
+//---------------------------------------------------------
+// pianoCmd
+//---------------------------------------------------------
+
+void PianoCanvas::pianoCmd(int cmd)
+ {
+ switch(cmd) {
+ case CMD_LEFT:
+ {
+ int frames = pos[0] - editor->rasterStep(pos[0]);
+ if (frames < 0)
+ frames = 0;
+ Pos p(frames,true);
+ song->setPos(0, p, true, true, true); //CDW
+ }
+ break;
+ case CMD_RIGHT:
+ {
+ Pos p(pos[0] + editor->rasterStep(pos[0]), true);
+ //if (p > part->tick())
+ // p = part->tick();
+ song->setPos(0, p, true, true, true); //CDW
+ }
+ break;
+ case CMD_INSERT:
+ {
+ if (pos[0] < start() || pos[0] >= end())
+ break;
+ MidiPart* part = (MidiPart*)curPart;
+
+ if (part == 0)
+ break;
+ song->startUndo();
+ EventList* el = part->events();
+
+ std::list <Event> elist;
+ for (iEvent e = el->lower_bound(pos[0] - part->tick()); e != el->end(); ++e)
+ elist.push_back((Event)e->second);
+ for (std::list<Event>::iterator i = elist.begin(); i != elist.end(); ++i) {
+ Event event = *i;
+ Event newEvent = event.clone();
+ newEvent.setTick(event.tick() + editor->raster());// - part->tick());
+ // Indicate no undo, and do not do port controller values and clone parts.
+ //audio->msgChangeEvent(event, newEvent, part, false);
+ audio->msgChangeEvent(event, newEvent, part, false, false, false);
+ }
+ song->endUndo(SC_EVENT_MODIFIED);
+ Pos p(editor->rasterVal(pos[0] + editor->rasterStep(pos[0])), true);
+ song->setPos(0, p, true, false, true);
+ }
+ return;
+ case CMD_DELETE:
+ if (pos[0] < start() || pos[0] >= end())
+ break;
+ {
+ MidiPart* part = (MidiPart*)curPart;
+ if (part == 0)
+ break;
+ song->startUndo();
+ EventList* el = part->events();
+
+ std::list<Event> elist;
+ for (iEvent e = el->lower_bound(pos[0]); e != el->end(); ++e)
+ elist.push_back((Event)e->second);
+ for (std::list<Event>::iterator i = elist.begin(); i != elist.end(); ++i) {
+ Event event = *i;
+ Event newEvent = event.clone();
+ newEvent.setTick(event.tick() - editor->raster() - part->tick());
+ // Indicate no undo, and do not do port controller values and clone parts.
+ //audio->msgChangeEvent(event, newEvent, part, false);
+ audio->msgChangeEvent(event, newEvent, part, false, false, false);
+ }
+ song->endUndo(SC_EVENT_MODIFIED);
+ Pos p(editor->rasterVal(pos[0] - editor->rasterStep(pos[0])), true);
+ song->setPos(0, p, true, false, true);
+ }
+ break;
+ }
+ }
+
+//---------------------------------------------------------
+// pianoPressed
+//---------------------------------------------------------
+
+void PianoCanvas::pianoPressed(int pitch, int velocity, bool shift)
+ {
+ int port = track()->outPort();
+ int channel = track()->outChannel();
+ pitch += track()->transposition;
+
+ // play note:
+ //MidiPlayEvent e(0, port, channel, 0x90, pitch, 127);
+ MidiPlayEvent e(0, port, channel, 0x90, pitch, velocity);
+ audio->msgPlayMidiEvent(&e);
+
+ if (_steprec && pos[0] >= start_tick && pos[0] < end_tick) {
+ if (curPart == 0)
+ return;
+ int len = editor->raster();
+ unsigned tick = pos[0] - curPart->tick(); //CDW
+ if (shift)
+ tick -= editor->rasterStep(tick);
+ Event e(Note);
+ e.setTick(tick);
+ e.setPitch(pitch);
+ e.setVelo(127);
+ e.setLenTick(len);
+ // Indicate do undo, and do not do port controller values and clone parts.
+ //audio->msgAddEvent(e, curPart);
+ audio->msgAddEvent(e, curPart, true, false, false);
+ tick += editor->rasterStep(tick) + curPart->tick();
+ if (tick != song->cpos()) {
+ Pos p(tick, true);
+ song->setPos(0, p, true, false, true);
+ }
+ }
+ }
+
+//---------------------------------------------------------
+// pianoReleased
+//---------------------------------------------------------
+
+void PianoCanvas::pianoReleased(int pitch, bool)
+ {
+ int port = track()->outPort();
+ int channel = track()->outChannel();
+ pitch += track()->transposition;
+
+ // release key:
+ MidiPlayEvent e(0, port, channel, 0x90, pitch, 0);
+ audio->msgPlayMidiEvent(&e);
+ }
+
+//---------------------------------------------------------
+// drawTickRaster
+//---------------------------------------------------------
+
+void drawTickRaster(QPainter& p, int x, int y, int w, int h, int raster)
+ {
+ int bar1, bar2, beat;
+ unsigned tick;
+ sigmap.tickValues(x, &bar1, &beat, &tick);
+ sigmap.tickValues(x+w, &bar2, &beat, &tick);
+ ++bar2;
+ int y2 = y + h;
+ for (int bar = bar1; bar < bar2; ++bar) {
+ unsigned x = sigmap.bar2tick(bar, 0, 0);
+ p.setPen(Qt::black);
+ p.drawLine(x, y, x, y2);
+ int z, n;
+ sigmap.timesig(x, z, n);
+ int q = p.xForm(QPoint(raster, 0)).x() - p.xForm(QPoint(0, 0)).x();
+ int qq = raster;
+ if (q < 8) // grid too dense
+ qq *= 2;
+ //switch (quant) {
+ // case 32:
+ // case 48:
+ // case 64:
+ // case 96:
+ // case 192: // 8tel
+ // case 128: // 8tel Triolen
+ // case 288:
+ p.setPen(Qt::lightGray);
+ if (raster>=4) {
+ int xx = x + qq;
+ int xxx = sigmap.bar2tick(bar, z, 0);
+ while (xx <= xxx) {
+ p.drawLine(xx, y, xx, y2);
+ xx += qq;
+ }
+ xx = xxx;
+ }
+ // break;
+ // default:
+ // break;
+ // }
+ p.setPen(Qt::gray);
+ for (int beat = 1; beat < z; beat++) {
+ int xx = sigmap.bar2tick(bar, beat, 0);
+ p.drawLine(xx, y, xx, y2);
+ }
+
+ }
+ }
+
+//---------------------------------------------------------
+// draw
+//---------------------------------------------------------
+
+void PianoCanvas::drawCanvas(QPainter& p, const QRect& rect)
+ {
+ int x = rect.x();
+ int y = rect.y();
+ int w = rect.width();
+ int h = rect.height();
+
+ //---------------------------------------------------
+ // horizontal lines
+ //---------------------------------------------------
+
+ int yy = ((y-1) / KH) * KH + KH;
+ int key = 75 - (yy / KH);
+ for (; yy < y + h; yy += KH) {
+ switch (key % 7) {
+ case 0:
+ case 3:
+ p.setPen(Qt::black);
+ p.drawLine(x, yy, x + w, yy);
+ break;
+ default:
+ //p.setPen(lightGray);
+ p.fillRect(x, yy-3, w, 6, QBrush(QColor(230,230,230)));
+ //p.drawLine(x, yy, x + w, yy);
+ break;
+ }
+ --key;
+ }
+
+ //---------------------------------------------------
+ // vertical lines
+ //---------------------------------------------------
+
+ drawTickRaster(p, x, y, w, h, editor->raster());
+ }
+
+//---------------------------------------------------------
+// cmd
+// pulldown menu commands
+//---------------------------------------------------------
+
+void PianoCanvas::cmd(int cmd, int quantStrength,
+ int quantLimit, bool quantLen, int range)
+ {
+ cmdRange = range;
+ switch (cmd) {
+ case CMD_CUT:
+ copy();
+ song->startUndo();
+ for (iCItem i = items.begin(); i != items.end(); ++i) {
+ if (!(i->second->isSelected()))
+ continue;
+ NEvent* e = (NEvent*)(i->second);
+ Event ev = e->event();
+ // Indicate no undo, and do not do port controller values and clone parts.
+ //audio->msgDeleteEvent(ev, e->part(), false);
+ audio->msgDeleteEvent(ev, e->part(), false, false, false);
+ }
+ song->endUndo(SC_EVENT_REMOVED);
+ break;
+ case CMD_COPY:
+ copy();
+ break;
+ case CMD_PASTE:
+ paste();
+ break;
+ case CMD_DEL:
+ if (selectionSize()) {
+ song->startUndo();
+ for (iCItem i = items.begin(); i != items.end(); ++i) {
+ if (!i->second->isSelected())
+ continue;
+ Event ev = i->second->event();
+ // Indicate no undo, and do not do port controller values and clone parts.
+ //audio->msgDeleteEvent(ev, i->second->part(), false);
+ audio->msgDeleteEvent(ev, i->second->part(), false, false, false);
+ }
+ song->endUndo(SC_EVENT_REMOVED);
+ }
+ return;
+ case CMD_OVER_QUANTIZE: // over quantize
+ quantize(100, 1, quantLen);
+ break;
+ case CMD_ON_QUANTIZE: // note on quantize
+ quantize(50, 1, false);
+ break;
+ case CMD_ONOFF_QUANTIZE: // note on/off quantize
+ quantize(50, 1, true);
+ break;
+ case CMD_ITERATIVE_QUANTIZE: // Iterative Quantize
+ quantize(quantStrength, quantLimit, quantLen);
+ break;
+ case CMD_SELECT_ALL: // select all
+ for (iCItem k = items.begin(); k != items.end(); ++k) {
+ if (!k->second->isSelected())
+ selectItem(k->second, true);
+ }
+ break;
+ case CMD_SELECT_NONE: // select none
+ deselectAll();
+ break;
+ case CMD_SELECT_INVERT: // invert selection
+ for (iCItem k = items.begin(); k != items.end(); ++k) {
+ selectItem(k->second, !k->second->isSelected());
+ }
+ break;
+ case CMD_SELECT_ILOOP: // select inside loop
+ for (iCItem k = items.begin(); k != items.end(); ++k) {
+ NEvent* nevent = (NEvent*)(k->second);
+ Part* part = nevent->part();
+ Event event = nevent->event();
+ unsigned tick = event.tick() + part->tick();
+ if (tick < song->lpos() || tick >= song->rpos())
+ selectItem(k->second, false);
+ else
+ selectItem(k->second, true);
+ }
+ break;
+ case CMD_SELECT_OLOOP: // select outside loop
+ for (iCItem k = items.begin(); k != items.end(); ++k) {
+ NEvent* nevent = (NEvent*)(k->second);
+ Part* part = nevent->part();
+ Event event = nevent->event();
+ unsigned tick = event.tick() + part->tick();
+ if (tick < song->lpos() || tick >= song->rpos())
+ selectItem(k->second, true);
+ else
+ selectItem(k->second, false);
+ }
+ break;
+ case CMD_SELECT_PREV_PART: // select previous part
+ {
+ Part* pt = editor->curCanvasPart();
+ Part* newpt = pt;
+ PartList* pl = editor->parts();
+ for(iPart ip = pl->begin(); ip != pl->end(); ++ip)
+ if(ip->second == pt)
+ {
+ if(ip == pl->begin())
+ ip = pl->end();
+ --ip;
+ newpt = ip->second;
+ break;
+ }
+ if(newpt != pt)
+ editor->setCurCanvasPart(newpt);
+ }
+ break;
+ case CMD_SELECT_NEXT_PART: // select next part
+ {
+ Part* pt = editor->curCanvasPart();
+ Part* newpt = pt;
+ PartList* pl = editor->parts();
+ for(iPart ip = pl->begin(); ip != pl->end(); ++ip)
+ if(ip->second == pt)
+ {
+ ++ip;
+ if(ip == pl->end())
+ ip = pl->begin();
+ newpt = ip->second;
+ break;
+ }
+ if(newpt != pt)
+ editor->setCurCanvasPart(newpt);
+ }
+ break;
+ case CMD_MODIFY_GATE_TIME:
+ {
+ GateTime w(this);
+ w.setRange(range);
+ if (!w.exec())
+ break;
+ int range = w.range(); // all, selected, looped, sel+loop
+ int rate = w.rateVal();
+ int offset = w.offsetVal();
+
+ song->startUndo();
+ for (iCItem k = items.begin(); k != items.end(); ++k) {
+ NEvent* nevent =(NEvent*)(k->second);
+ Event event = nevent->event();
+ if (event.type() != Note)
+ continue;
+ unsigned tick = event.tick();
+ bool selected = k->second->isSelected();
+ bool inLoop = (tick >= song->lpos()) && (tick < song->rpos());
+
+ if ((range == 0)
+ || (range == 1 && selected)
+ || (range == 2 && inLoop)
+ || (range == 3 && selected && inLoop)) {
+ unsigned int len = event.lenTick(); //prevent compiler warning: comparison singed/unsigned
+
+ len = rate ? (len * 100) / rate : 1;
+ len += offset;
+ if (len < 1)
+ len = 1;
+
+ if (event.lenTick() != len) {
+ Event newEvent = event.clone();
+ newEvent.setLenTick(len);
+ // Indicate no undo, and do not do port controller values and clone parts.
+ //audio->msgChangeEvent(event, newEvent, nevent->part(), false);
+ audio->msgChangeEvent(event, newEvent, nevent->part(), false, false, false);
+ }
+ }
+ }
+ song->endUndo(SC_EVENT_MODIFIED);
+ }
+ break;
+
+ case CMD_MODIFY_VELOCITY:
+ {
+ Velocity w(this);
+ w.setRange(range);
+ if (!w.exec())
+ break;
+ int range = w.range(); // all, selected, looped, sel+loop
+ int rate = w.rateVal();
+ int offset = w.offsetVal();
+
+ song->startUndo();
+ for (iCItem k = items.begin(); k != items.end(); ++k) {
+ NEvent* nevent = (NEvent*)(k->second);
+ Event event = nevent->event();
+ if (event.type() != Note)
+ continue;
+ unsigned tick = event.tick();
+ bool selected = k->second->isSelected();
+ bool inLoop = (tick >= song->lpos()) && (tick < song->rpos());
+
+ if ((range == 0)
+ || (range == 1 && selected)
+ || (range == 2 && inLoop)
+ || (range == 3 && selected && inLoop)) {
+ int velo = event.velo();
+
+ //velo = rate ? (velo * 100) / rate : 64;
+ velo = (velo * rate) / 100;
+ velo += offset;
+
+ if (velo <= 0)
+ velo = 1;
+ if (velo > 127)
+ velo = 127;
+ if (event.velo() != velo) {
+ Event newEvent = event.clone();
+ newEvent.setVelo(velo);
+ // Indicate no undo, and do not do port controller values and clone parts.
+ //audio->msgChangeEvent(event, newEvent, nevent->part(), false);
+ audio->msgChangeEvent(event, newEvent, nevent->part(), false, false, false);
+ }
+ }
+ }
+ song->endUndo(SC_EVENT_MODIFIED);
+ }
+ break;
+
+ case CMD_FIXED_LEN: //Set notes to the length specified in the drummap
+ if (!selectionSize())
+ break;
+ song->startUndo();
+ for (iCItem k = items.begin(); k != items.end(); ++k) {
+ if (k->second->isSelected()) {
+ NEvent* nevent = (NEvent*)(k->second);
+ Event event = nevent->event();
+ Event newEvent = event.clone();
+ newEvent.setLenTick(editor->raster());
+ // Indicate no undo, and do not do port controller values and clone parts.
+ //audio->msgChangeEvent(event, newEvent, nevent->part() , false);
+ audio->msgChangeEvent(event, newEvent, nevent->part(), false, false, false);
+ }
+ }
+ song->endUndo(SC_EVENT_MODIFIED);
+ break;
+
+ case CMD_DELETE_OVERLAPS:
+ if (!selectionSize())
+ break;
+
+ song->startUndo();
+ for (iCItem k = items.begin(); k != items.end(); k++) {
+ if (k->second->isSelected() == false)
+ continue;
+
+ NEvent* e1 = (NEvent*) (k->second); // first note
+ NEvent* e2 = NULL; // ptr to next selected note (which will be checked for overlap)
+ Event ce1 = e1->event();
+ Event ce2;
+
+ if (ce1.type() != Note)
+ continue;
+
+ // Find next selected item on the same pitch
+ iCItem l = k; l++;
+ for (; l != items.end(); l++) {
+ if (l->second->isSelected() == false)
+ continue;
+
+ e2 = (NEvent*) l->second;
+ ce2 = e2->event();
+
+ // Same pitch?
+ if (ce1.dataA() == ce2.dataA())
+ break;
+
+ // If the note has the same len and place we treat it as a duplicate note and not a following note
+ // The best thing to do would probably be to delete the duplicate note, we just want to avoid
+ // matching against the same note
+ if ( ce1.tick() + e1->part()->tick() == ce2.tick() + e2->part()->tick()
+ && ce1.lenTick() + e1->part()->tick() == ce2.lenTick() + e2->part()->tick())
+ {
+ e2 = NULL; // this wasn't what we were looking for
+ continue;
+ }
+
+ }
+
+ if (e2 == NULL) // None found
+ break;
+
+ Part* part1 = e1->part();
+ Part* part2 = e2->part();
+ if (ce2.type() != Note)
+ continue;
+
+
+ unsigned event1pos = ce1.tick() + part1->tick();
+ unsigned event1end = event1pos + ce1.lenTick();
+ unsigned event2pos = ce2.tick() + part2->tick();
+
+ //printf("event1pos %u event1end %u event2pos %u\n", event1pos, event1end, event2pos);
+ if (event1end > event2pos) {
+ Event newEvent = ce1.clone();
+ unsigned newlen = ce1.lenTick() - (event1end - event2pos);
+ //printf("newlen: %u\n", newlen);
+ newEvent.setLenTick(newlen);
+ // Indicate no undo, and do not do port controller values and clone parts.
+ //audio->msgChangeEvent(ce1, newEvent, e1->part(), false);
+ audio->msgChangeEvent(ce1, newEvent, e1->part(), false, false, false);
+ }
+ }
+ song->endUndo(SC_EVENT_MODIFIED);
+ break;
+
+
+ case CMD_CRESCENDO:
+ case CMD_TRANSPOSE:
+ case CMD_THIN_OUT:
+ case CMD_ERASE_EVENT:
+ case CMD_NOTE_SHIFT:
+ case CMD_MOVE_CLOCK:
+ case CMD_COPY_MEASURE:
+ case CMD_ERASE_MEASURE:
+ case CMD_DELETE_MEASURE:
+ case CMD_CREATE_MEASURE:
+ break;
+ default:
+// printf("unknown ecanvas cmd %d\n", cmd);
+ break;
+ }
+ updateSelection();
+ redraw();
+ }
+
+//---------------------------------------------------------
+// quantize
+//---------------------------------------------------------
+
+void PianoCanvas::quantize(int strength, int limit, bool quantLen)
+ {
+ song->startUndo();
+ for (iCItem k = items.begin(); k != items.end(); ++k) {
+ NEvent* nevent = (NEvent*)(k->second);
+ Event event = nevent->event();
+ Part* part = nevent->part();
+ if (event.type() != Note)
+ continue;
+
+ if ((cmdRange & CMD_RANGE_SELECTED) && !k->second->isSelected())
+ continue;
+
+ unsigned tick = event.tick() + part->tick();
+
+ if ((cmdRange & CMD_RANGE_LOOP)
+ && ((tick < song->lpos() || tick >= song->rpos())))
+ continue;
+
+ unsigned int len = event.lenTick(); //prevent compiler warning: comparison singed/unsigned
+ int tick2 = tick + len;
+
+ // quant start position
+ int diff = sigmap.raster(tick, editor->quant()) - tick;
+ if (abs(diff) > limit)
+ tick += ((diff * strength) / 100);
+
+ // quant len
+ diff = sigmap.raster(tick2, editor->quant()) - tick2;
+ if (quantLen && (abs(diff) > limit))
+ len += ((diff * strength) / 100);
+
+ // something changed?
+ if (((event.tick() + part->tick()) != tick) || (event.lenTick() != len)) {
+ Event newEvent = event.clone();
+ newEvent.setTick(tick - part->tick());
+ newEvent.setLenTick(len);
+ // Indicate no undo, and do not do port controller values and clone parts.
+ //audio->msgChangeEvent(event, newEvent, part, false);
+ audio->msgChangeEvent(event, newEvent, part, false, false, false);
+ }
+ }
+ song->endUndo(SC_EVENT_MODIFIED);
+ }
+
+//---------------------------------------------------------
+// midiNote
+//---------------------------------------------------------
+
+void PianoCanvas::midiNote(int pitch, int velo)
+ {
+ if (_midiin && _steprec && curPart
+ && !audio->isPlaying() && velo && pos[0] >= start_tick
+ && pos[0] < end_tick
+ && !(globalKeyState & Qt::AltButton)) {
+ unsigned int len = editor->quant();//prevent compiler warning: comparison singed/unsigned
+ unsigned tick = pos[0]; //CDW
+ unsigned starttick = tick;
+ if (globalKeyState & Qt::ShiftButton)
+ tick -= editor->rasterStep(tick);
+
+ //
+ // extend len of last note?
+ //
+ EventList* events = curPart->events();
+ if (globalKeyState & Qt::ControlButton) {
+ for (iEvent i = events->begin(); i != events->end(); ++i) {
+ Event ev = i->second;
+ if (!ev.isNote())
+ continue;
+ if (ev.pitch() == pitch && ((ev.tick() + ev.lenTick()) == /*(int)*/starttick)) {
+ Event e = ev.clone();
+ e.setLenTick(ev.lenTick() + editor->rasterStep(starttick));
+ // Indicate do undo, and do not do port controller values and clone parts.
+ //audio->msgChangeEvent(ev, e, curPart);
+ audio->msgChangeEvent(ev, e, curPart, true, false, false);
+ tick += editor->rasterStep(tick);
+ if (tick != song->cpos()) {
+ Pos p(tick, true);
+ song->setPos(0, p, true, false, true);
+ }
+ return;
+ }
+ }
+ }
+
+ //
+ // if we already entered the note, delete it
+ //
+ EventRange range = events->equal_range(tick);
+ for (iEvent i = range.first; i != range.second; ++i) {
+ Event ev = i->second;
+ if (ev.isNote() && ev.pitch() == pitch) {
+ // Indicate do undo, and do not do port controller values and clone parts.
+ //audio->msgDeleteEvent(ev, curPart);
+ audio->msgDeleteEvent(ev, curPart, true, false, false);
+ if (globalKeyState & Qt::ShiftButton)
+ tick += editor->rasterStep(tick);
+ return;
+ }
+ }
+ Event e(Note);
+ e.setTick(tick - curPart->tick());
+ e.setPitch(pitch);
+ e.setVelo(velo);
+ e.setLenTick(len);
+ // Indicate do undo, and do not do port controller values and clone parts.
+ //audio->msgAddEvent(e, curPart);
+ audio->msgAddEvent(e, curPart, true, false, false);
+ tick += editor->rasterStep(tick);
+ if (tick != song->cpos()) {
+ Pos p(tick, true);
+ song->setPos(0, p, true, false, true);
+ }
+ }
+ }
+
+//---------------------------------------------------------
+// getTextDrag
+//---------------------------------------------------------
+
+Q3TextDrag* PianoCanvas::getTextDrag(QWidget* parent)
+ {
+ //---------------------------------------------------
+ // generate event list from selected events
+ //---------------------------------------------------
+
+ EventList el;
+ unsigned startTick = MAXINT;
+ for (iCItem i = items.begin(); i != items.end(); ++i) {
+ if (!i->second->isSelected())
+ continue;
+ NEvent* ne = (NEvent*)(i->second);
+ Event e = ne->event();
+ if (startTick == MAXINT)
+ startTick = e.tick();
+ el.add(e);
+ }
+
+ //---------------------------------------------------
+ // write events as XML into tmp file
+ //---------------------------------------------------
+
+ FILE* tmp = tmpfile();
+ if (tmp == 0) {
+ fprintf(stderr, "PianoCanvas::copy() fopen failed: %s\n",
+ strerror(errno));
+ return 0;
+ }
+ Xml xml(tmp);
+
+ int level = 0;
+ xml.tag(level++, "eventlist");
+ for (ciEvent e = el.begin(); e != el.end(); ++e)
+ e->second.write(level, xml, -startTick);
+ xml.etag(--level, "eventlist");
+
+ //---------------------------------------------------
+ // read tmp file into QTextDrag Object
+ //---------------------------------------------------
+
+ fflush(tmp);
+ struct stat f_stat;
+ if (fstat(fileno(tmp), &f_stat) == -1) {
+ fprintf(stderr, "PianoCanvas::copy() fstat failes:<%s>\n",
+ strerror(errno));
+ fclose(tmp);
+ return 0;
+ }
+ int n = f_stat.st_size;
+ char* fbuf = (char*)mmap(0, n+1, PROT_READ|PROT_WRITE,
+ MAP_PRIVATE, fileno(tmp), 0);
+ fbuf[n] = 0;
+ Q3TextDrag* drag = new Q3TextDrag(QString(fbuf), parent);
+ drag->setSubtype("eventlist");
+ munmap(fbuf, n);
+ fclose(tmp);
+ return drag;
+ }
+
+//---------------------------------------------------------
+// copy
+// cut copy paste
+//---------------------------------------------------------
+
+void PianoCanvas::copy()
+ {
+ Q3TextDrag* drag = getTextDrag(0);
+ if (drag)
+ QApplication::clipboard()->setData(drag, QClipboard::Clipboard);
+ }
+
+//---------------------------------------------------------
+// paste
+//---------------------------------------------------------
+
+void PianoCanvas::pasteAt(const QString& pt, int pos)
+ {
+ const char* p = pt.latin1();
+ Xml xml(p);
+ for (;;) {
+ Xml::Token token = xml.parse();
+ const QString& tag = xml.s1();
+ switch (token) {
+ case Xml::Error:
+ case Xml::End:
+ return;
+ case Xml::TagStart:
+ if (tag == "eventlist") {
+ song->startUndo();
+ EventList* el = new EventList();
+ el->read(xml, "eventlist", true);
+ int modified = SC_EVENT_INSERTED;
+ for (iEvent i = el->begin(); i != el->end(); ++i) {
+ Event e = i->second;
+ int tick = e.tick() + pos - curPart->tick();
+ if (tick<0) {
+ printf("ERROR: trying to add event before current part!\n");
+ song->endUndo(SC_EVENT_INSERTED);
+ delete el;
+ return;
+ }
+
+ e.setTick(tick);
+ int diff = e.endTick()-curPart->lenTick();
+ if (diff > 0) {// too short part? extend it
+ Part* newPart = curPart->clone();
+ newPart->setLenTick(newPart->lenTick()+diff);
+ // Indicate no undo, and do port controller values but not clone parts.
+ //audio->msgChangePart(curPart, newPart,false);
+ audio->msgChangePart(curPart, newPart, false, true, false);
+ modified=modified|SC_PART_MODIFIED;
+ curPart = newPart; // reassign
+ }
+ // Indicate no undo, and do not do port controller values and clone parts.
+ //audio->msgAddEvent(e, curPart, false);
+ audio->msgAddEvent(e, curPart, false, false, false);
+ }
+ song->endUndo(modified);
+ delete el;
+ return;
+ }
+ else
+ xml.unknown("pasteAt");
+ break;
+ case Xml::Attribut:
+ case Xml::TagEnd:
+ default:
+ break;
+ }
+ }
+ }
+//---------------------------------------------------------
+// paste
+// paste events
+//---------------------------------------------------------
+
+void PianoCanvas::paste()
+ {
+ //Q3CString subtype("eventlist"); ddskrjo
+ QString subtype("eventlist");
+ QMimeSource* ms = QApplication::clipboard()->data(QClipboard::Clipboard);
+ QString pt;
+ if (!Q3TextDrag::decode(ms, pt, subtype)) {
+ printf("cannot paste: bad data type\n");
+ return;
+ }
+ pasteAt(pt, song->cpos());
+ }
+
+//---------------------------------------------------------
+// startDrag
+//---------------------------------------------------------
+
+void PianoCanvas::startDrag(CItem* /* item*/, bool copymode)
+ {
+ Q3TextDrag* drag = getTextDrag(this);
+ if (drag) {
+// QApplication::clipboard()->setData(drag, QClipboard::Clipboard);
+
+ if (copymode)
+ drag->dragCopy();
+ else
+ drag->dragMove();
+ }
+ }
+
+//---------------------------------------------------------
+// dragEnterEvent
+//---------------------------------------------------------
+
+void PianoCanvas::dragEnterEvent(QDragEnterEvent* event)
+ {
+ event->accept(Q3TextDrag::canDecode(event));
+ }
+
+//---------------------------------------------------------
+// dragMoveEvent
+//---------------------------------------------------------
+
+void PianoCanvas::dragMoveEvent(QDragMoveEvent*)
+ {
+// printf("drag move %x\n", this);
+ }
+
+//---------------------------------------------------------
+// dragLeaveEvent
+//---------------------------------------------------------
+
+void PianoCanvas::dragLeaveEvent(QDragLeaveEvent*)
+ {
+// printf("drag leave\n");
+ }
+
+//---------------------------------------------------------
+// dropEvent
+//---------------------------------------------------------
+
+void PianoCanvas::viewDropEvent(QDropEvent* event)
+ {
+ QString text;
+ if (event->source() == this) {
+ printf("local DROP\n");
+ return;
+ }
+ if (Q3TextDrag::decode(event, text)) {
+ int x = editor->rasterVal(event->pos().x());
+ if (x < 0)
+ x = 0;
+ pasteAt(text, x);
+ }
+ else {
+ printf("cannot decode drop\n");
+ }
+ }
+
+//---------------------------------------------------------
+// itemPressed
+//---------------------------------------------------------
+
+void PianoCanvas::itemPressed(const CItem* item)
+ {
+ if (!_playEvents)
+ return;
+
+ int port = track()->outPort();
+ int channel = track()->outChannel();
+ NEvent* nevent = (NEvent*) item;
+ Event event = nevent->event();
+ playedPitch = event.pitch() + track()->transposition;
+ int velo = event.velo();
+
+ // play note:
+ MidiPlayEvent e(0, port, channel, 0x90, playedPitch, velo);
+ audio->msgPlayMidiEvent(&e);
+ }
+
+//---------------------------------------------------------
+// itemReleased
+//---------------------------------------------------------
+
+void PianoCanvas::itemReleased(const CItem*, const QPoint&)
+ {
+ if (!_playEvents)
+ return;
+ int port = track()->outPort();
+ int channel = track()->outChannel();
+
+ // release note:
+ MidiPlayEvent ev(0, port, channel, 0x90, playedPitch, 0);
+ audio->msgPlayMidiEvent(&ev);
+ playedPitch = -1;
+ }
+
+//---------------------------------------------------------
+// itemMoved
+//---------------------------------------------------------
+
+void PianoCanvas::itemMoved(const CItem* item, const QPoint& pos)
+ {
+ int npitch = y2pitch(pos.y());
+ if ((playedPitch != -1) && (playedPitch != npitch)) {
+ int port = track()->outPort();
+ int channel = track()->outChannel();
+ NEvent* nevent = (NEvent*) item;
+ Event event = nevent->event();
+
+ // release note:
+ MidiPlayEvent ev1(0, port, channel, 0x90, playedPitch, 0);
+ audio->msgPlayMidiEvent(&ev1);
+ // play note:
+ MidiPlayEvent e2(0, port, channel, 0x90, npitch + track()->transposition, event.velo());
+ audio->msgPlayMidiEvent(&e2);
+ playedPitch = npitch + track()->transposition;
+ }
+ }
+
+//---------------------------------------------------------
+// curPartChanged
+//---------------------------------------------------------
+
+void PianoCanvas::curPartChanged()
+ {
+ editor->setCaption(getCaption());
+ }
+
+//---------------------------------------------------------
+// modifySelected
+//---------------------------------------------------------
+
+void PianoCanvas::modifySelected(NoteInfo::ValType type, int delta)
+ {
+ audio->msgIdle(true);
+ song->startUndo();
+ for (iCItem i = items.begin(); i != items.end(); ++i) {
+ if (!(i->second->isSelected()))
+ continue;
+ NEvent* e = (NEvent*)(i->second);
+ Event event = e->event();
+ if (event.type() != Note)
+ continue;
+
+ MidiPart* part = (MidiPart*)(e->part());
+ Event newEvent = event.clone();
+
+ switch (type) {
+ case NoteInfo::VAL_TIME:
+ {
+ int newTime = event.tick() + delta;
+ if (newTime < 0)
+ newTime = 0;
+ newEvent.setTick(newTime);
+ }
+ break;
+ case NoteInfo::VAL_LEN:
+ {
+ int len = event.lenTick() + delta;
+ if (len < 1)
+ len = 1;
+ newEvent.setLenTick(len);
+ }
+ break;
+ case NoteInfo::VAL_VELON:
+ {
+ int velo = event.velo() + delta;
+ if (velo > 127)
+ velo = 127;
+ else if (velo < 0)
+ velo = 0;
+ newEvent.setVelo(velo);
+ }
+ break;
+ case NoteInfo::VAL_VELOFF:
+ {
+ int velo = event.veloOff() + delta;
+ if (velo > 127)
+ velo = 127;
+ else if (velo < 0)
+ velo = 0;
+ newEvent.setVeloOff(velo);
+ }
+ break;
+ case NoteInfo::VAL_PITCH:
+ {
+ int pitch = event.pitch() + delta;
+ if (pitch > 127)
+ pitch = 127;
+ else if (pitch < 0)
+ pitch = 0;
+ newEvent.setPitch(pitch);
+ }
+ break;
+ }
+ song->changeEvent(event, newEvent, part);
+ // Indicate do not do port controller values and clone parts.
+ //song->undoOp(UndoOp::ModifyEvent, newEvent, event, part);
+ song->undoOp(UndoOp::ModifyEvent, newEvent, event, part, false, false);
+ }
+ song->endUndo(SC_EVENT_MODIFIED);
+ audio->msgIdle(false);
+ }
+
diff --git a/muse2/muse/midiedit/prcanvas.h b/muse2/muse/midiedit/prcanvas.h
new file mode 100644
index 00000000..2f50be2e
--- /dev/null
+++ b/muse2/muse/midiedit/prcanvas.h
@@ -0,0 +1,113 @@
+//=========================================================
+// MusE
+// Linux Music Editor
+// $Id: prcanvas.h,v 1.5.2.6 2009/11/16 11:29:33 lunar_shuttle Exp $
+// (C) Copyright 1999 Werner Schweer (ws@seh.de)
+//=========================================================
+
+#ifndef __PRCANVAS_H__
+#define __PRCANVAS_H__
+
+#include "ecanvas.h"
+#include "pianoroll.h"
+//Added by qt3to4:
+#include <QDragEnterEvent>
+#include <QDropEvent>
+#include <QMouseEvent>
+#include <QDragMoveEvent>
+#include <QDragLeaveEvent>
+
+#define KH 13
+
+//---------------------------------------------------------
+// NEvent
+// ''visual'' Note Event
+//---------------------------------------------------------
+
+class NEvent : public CItem {
+ public:
+ NEvent(Event& e, Part* p, int y);
+ };
+
+class ScrollScale;
+class PianoRoll;
+class Q3TextDrag;
+class QRect;
+
+//---------------------------------------------------------
+// PianoCanvas
+//---------------------------------------------------------
+
+class PianoCanvas : public EventCanvas {
+ int cmdRange;
+ int colorMode;
+ int playedPitch;
+
+ Q_OBJECT
+ virtual void viewMouseDoubleClickEvent(QMouseEvent*);
+ virtual void drawItem(QPainter&, const CItem*, const QRect&);
+ virtual void drawMoving(QPainter&, const CItem*, const QRect&);
+ virtual void moveCanvasItems(CItemList&, int, int, DragType, int*);
+ // Changed by T356.
+ //virtual bool moveItem(CItem*, const QPoint&, DragType, int*);
+ virtual bool moveItem(CItem*, const QPoint&, DragType);
+ virtual CItem* newItem(const QPoint&, int);
+ virtual void resizeItem(CItem*, bool noSnap);
+ virtual void newItem(CItem*, bool noSnap);
+ virtual bool deleteItem(CItem*);
+ virtual void startDrag(CItem* item, bool copymode);
+ virtual void dragEnterEvent(QDragEnterEvent* event);
+ virtual void dragMoveEvent(QDragMoveEvent*);
+ virtual void dragLeaveEvent(QDragLeaveEvent*);
+ virtual void viewDropEvent(QDropEvent* event);
+ virtual void addItem(Part*, Event&);
+
+ int y2pitch(int) const;
+ int pitch2y(int) const;
+ virtual void drawCanvas(QPainter&, const QRect&);
+ void quantize(int, int, bool);
+ void copy();
+ void paste();
+ void pasteAt(const QString& pt, int pos);
+ Q3TextDrag* getTextDrag(QWidget*);
+ virtual void itemPressed(const CItem*);
+ virtual void itemReleased(const CItem*, const QPoint&);
+ virtual void itemMoved(const CItem*, const QPoint&);
+ virtual void curPartChanged();
+
+ private slots:
+ void midiNote(int pitch, int velo);
+
+ signals:
+ void quantChanged(int);
+ void rasterChanged(int);
+
+ public slots:
+ void pianoCmd(int);
+ void pianoPressed(int pitch, int velocity, bool shift);
+ void pianoReleased(int pitch, bool);
+
+ public:
+ enum {
+ CMD_CUT, CMD_COPY, CMD_PASTE, CMD_DEL,
+ CMD_OVER_QUANTIZE, CMD_ON_QUANTIZE, CMD_ONOFF_QUANTIZE,
+ CMD_ITERATIVE_QUANTIZE,
+ CMD_SELECT_ALL, CMD_SELECT_NONE, CMD_SELECT_INVERT,
+ CMD_SELECT_ILOOP, CMD_SELECT_OLOOP, CMD_SELECT_PREV_PART, CMD_SELECT_NEXT_PART,
+ CMD_MODIFY_GATE_TIME, CMD_MODIFY_VELOCITY,
+ CMD_CRESCENDO, CMD_TRANSPOSE, CMD_THIN_OUT, CMD_ERASE_EVENT,
+ CMD_NOTE_SHIFT, CMD_MOVE_CLOCK, CMD_COPY_MEASURE,
+ CMD_ERASE_MEASURE, CMD_DELETE_MEASURE, CMD_CREATE_MEASURE,
+ CMD_FIXED_LEN, CMD_DELETE_OVERLAPS
+ };
+
+ PianoCanvas(MidiEditor*, QWidget*, int, int);
+ void cmd(int, int, int, bool, int);
+ void setColorMode(int mode) {
+ colorMode = mode;
+ redraw();
+ }
+ virtual void modifySelected(NoteInfo::ValType type, int delta);
+ };
+#endif
+
diff --git a/muse2/muse/midiedit/quantconfig.cpp b/muse2/muse/midiedit/quantconfig.cpp
new file mode 100644
index 00000000..f00b713f
--- /dev/null
+++ b/muse2/muse/midiedit/quantconfig.cpp
@@ -0,0 +1,59 @@
+//=========================================================
+// MusE
+// Linux Music Editor
+// $Id: quantconfig.cpp,v 1.2 2004/04/24 14:58:52 wschweer Exp $
+//
+// (C) Copyright 1999/2003 Werner Schweer (ws@seh.de)
+//=========================================================
+
+#include <qspinbox.h>
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qradiobutton.h>
+#include <q3groupbox.h>
+#include <q3whatsthis.h>
+
+#include "quantconfig.h"
+//Added by qt3to4:
+#include <Q3VBoxLayout>
+
+const char* wtStrengthTxt = QT_TR_NOOP("sets amount of quantization:\n"
+ "0 - no quantization\n"
+ "100 - full quantization");
+const char* wtQLimitTxt = QT_TR_NOOP("don't quantize notes above this tick limit");
+const char* wtQLenTxt = QT_TR_NOOP("quantize also note len as default");
+
+//---------------------------------------------------------
+// QuantConfig
+//---------------------------------------------------------
+
+QuantConfig::QuantConfig(int s, int l, bool lenFlag)
+ : QDialog()
+ {
+ setCaption(tr("MusE: Config Quantize"));
+ Q3VBoxLayout* layout = new Q3VBoxLayout(this);
+ Q3GroupBox* gb = new Q3GroupBox(2, Qt::Horizontal, tr("Config Quantize"), this);
+ layout->addWidget(gb);
+
+ QLabel* l1 = new QLabel(tr("Strength"), gb);
+ QSpinBox* sb1 = new QSpinBox(0, 100, 1, gb);
+ sb1->setSuffix(QString("%"));
+ sb1->setValue(s);
+ QLabel* l2 = new QLabel(tr("Donīt Quantize"), gb);
+ QSpinBox* sb2 = new QSpinBox(0, 500, 1, gb);
+ sb2->setValue(l);
+ QLabel* l3 = new QLabel(tr("Quant Len"), gb);
+ QRadioButton* but = new QRadioButton(gb);
+ but->setChecked(lenFlag);
+ connect(sb1, SIGNAL(valueChanged(int)), SIGNAL(setQuantStrength(int)));
+ connect(sb2, SIGNAL(valueChanged(int)), SIGNAL(setQuantLimit(int)));
+ connect(but, SIGNAL(toggled(bool)), SIGNAL(setQuantLen(bool)));
+
+ Q3WhatsThis::add(l1, tr(wtStrengthTxt));
+ Q3WhatsThis::add(sb1, tr(wtStrengthTxt));
+ Q3WhatsThis::add(l2, tr(wtQLimitTxt));
+ Q3WhatsThis::add(sb2, tr(wtQLimitTxt));
+ Q3WhatsThis::add(l3, tr(wtQLenTxt));
+ Q3WhatsThis::add(but, tr(wtQLenTxt));
+ }
+
diff --git a/muse2/muse/midiedit/quantconfig.h b/muse2/muse/midiedit/quantconfig.h
new file mode 100644
index 00000000..31ab2285
--- /dev/null
+++ b/muse2/muse/midiedit/quantconfig.h
@@ -0,0 +1,32 @@
+//=========================================================
+// MusE
+// Linux Music Editor
+// $Id: quantconfig.h,v 1.1.1.1 2003/10/27 18:52:23 wschweer Exp $
+//
+// (C) Copyright 1999/2000 Werner Schweer (ws@seh.de)
+//=========================================================
+
+#ifndef __QCONFIG_H__
+#define __QCONFIG_H__
+
+#include <qdialog.h>
+
+//---------------------------------------------------------
+// QuantConfig
+//---------------------------------------------------------
+
+class QuantConfig : public QDialog {
+ Q_OBJECT
+
+ signals:
+ void setQuantStrength(int);
+ void setQuantLimit(int);
+ void setQuantLen(bool);
+
+ public:
+ QuantConfig(int, int, bool);
+ };
+
+
+#endif
+