diff options
author | Jeong-Seok Yang <jseok.yang@samsung.com> | 2010-08-25 18:32:24 -0700 |
---|---|---|
committer | Ed Heyl <edheyl@google.com> | 2010-08-25 18:52:19 -0700 |
commit | ec456383c58adf2d4c4818438a703e5a2ca949b5 (patch) | |
tree | 6d7b1ddc2610c37e911917dad5be7ebdebc6c6ad /alsa-utils/seq | |
parent | 1206fad9881e5bca592fcd0fbdafc9d7f195d539 (diff) | |
download | device_samsung_crespo-ec456383c58adf2d4c4818438a703e5a2ca949b5.zip device_samsung_crespo-ec456383c58adf2d4c4818438a703e5a2ca949b5.tar.gz device_samsung_crespo-ec456383c58adf2d4c4818438a703e5a2ca949b5.tar.bz2 |
S5PC11X: crespo: add alsa-lib, alsa-utils, libaudio, libcamera
Change-Id: I4a6ee248b407c67682eb8884d1176f4807288c7c
Diffstat (limited to 'alsa-utils/seq')
22 files changed, 6282 insertions, 0 deletions
diff --git a/alsa-utils/seq/Makefile.am b/alsa-utils/seq/Makefile.am new file mode 100644 index 0000000..2c84cee --- /dev/null +++ b/alsa-utils/seq/Makefile.am @@ -0,0 +1 @@ +SUBDIRS=aconnect aplaymidi aseqdump aseqnet diff --git a/alsa-utils/seq/Makefile.in b/alsa-utils/seq/Makefile.in new file mode 100644 index 0000000..8c7c0ba --- /dev/null +++ b/alsa-utils/seq/Makefile.in @@ -0,0 +1,485 @@ +# Makefile.in generated by automake 1.9.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005 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@ +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = .. +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +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@ +subdir = seq +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/include/aconfig.h +CONFIG_CLEAN_FILES = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ + html-recursive info-recursive install-data-recursive \ + install-exec-recursive install-info-recursive \ + install-recursive installcheck-recursive installdirs-recursive \ + pdf-recursive ps-recursive uninstall-info-recursive \ + uninstall-recursive +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALSACONF_FALSE = @ALSACONF_FALSE@ +ALSACONF_TRUE = @ALSACONF_TRUE@ +ALSAMIXER_FALSE = @ALSAMIXER_FALSE@ +ALSAMIXER_TRUE = @ALSAMIXER_TRUE@ +ALSA_CFLAGS = @ALSA_CFLAGS@ +ALSA_LIBS = @ALSA_LIBS@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CURSESINC = @CURSESINC@ +CURSESLIB = @CURSESLIB@ +CURSES_CFLAGS = @CURSES_CFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GREP = @GREP@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LN_S = @LN_S@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +POSUB = @POSUB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SND_UTIL_MAJOR = @SND_UTIL_MAJOR@ +SND_UTIL_MINOR = @SND_UTIL_MINOR@ +SND_UTIL_SUBMINOR = @SND_UTIL_SUBMINOR@ +SND_UTIL_VERSION = @SND_UTIL_VERSION@ +STRIP = @STRIP@ +TESTSOUND = @TESTSOUND@ +USE_NLS = @USE_NLS@ +USE_XMLTO_FALSE = @USE_XMLTO_FALSE@ +USE_XMLTO_TRUE = @USE_XMLTO_TRUE@ +VERSION = @VERSION@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +ac_ct_CC = @ac_ct_CC@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +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@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +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@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +ncurses5_config = @ncurses5_config@ +ncursesw5_config = @ncursesw5_config@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +xmlto = @xmlto@ +SUBDIRS = aconnect aplaymidi aseqdump aseqnet +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign seq/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --foreign seq/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 +uninstall-info-am: + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. +$(RECURSIVE_TARGETS): + @failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +mostlyclean-recursive clean-recursive distclean-recursive \ +maintainer-clean-recursive: + @failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + rev=''; for subdir in $$list; do \ + if test "$$subdir" = "."; then :; else \ + rev="$$subdir $$rev"; \ + fi; \ + done; \ + rev="$$rev ."; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done + +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; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + 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; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + 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; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && 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)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkdir_p) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done + list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -d "$(distdir)/$$subdir" \ + || $(mkdir_p) "$(distdir)/$$subdir" \ + || exit 1; \ + distdir=`$(am__cd) $(distdir) && pwd`; \ + top_distdir=`$(am__cd) $(top_distdir) && pwd`; \ + (cd $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$top_distdir" \ + distdir="$$distdir/$$subdir" \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +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: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +info: info-recursive + +info-am: + +install-data-am: + +install-exec-am: + +install-info: install-info-recursive + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: uninstall-info-am + +uninstall-info: uninstall-info-recursive + +.PHONY: $(RECURSIVE_TARGETS) CTAGS GTAGS all all-am check check-am \ + clean clean-generic clean-recursive ctags ctags-recursive \ + distclean distclean-generic distclean-recursive distclean-tags \ + distdir dvi dvi-am html html-am info info-am install \ + install-am install-data install-data-am install-exec \ + install-exec-am install-info install-info-am install-man \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + maintainer-clean-recursive mostlyclean mostlyclean-generic \ + mostlyclean-recursive pdf pdf-am ps ps-am tags tags-recursive \ + uninstall uninstall-am uninstall-info-am + +# 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/alsa-utils/seq/aconnect/Makefile.am b/alsa-utils/seq/aconnect/Makefile.am new file mode 100644 index 0000000..507b9fe --- /dev/null +++ b/alsa-utils/seq/aconnect/Makefile.am @@ -0,0 +1,7 @@ +INCLUDES = -I$(top_srcdir)/include +EXTRA_DIST = README.aconnect aconnect.1 +LDADD = $(LIBINTL) + +bin_PROGRAMS = aconnect +aconnect_SOURCES = aconnect.c +man_MANS = aconnect.1 diff --git a/alsa-utils/seq/aconnect/Makefile.in b/alsa-utils/seq/aconnect/Makefile.in new file mode 100644 index 0000000..ccf0aeb --- /dev/null +++ b/alsa-utils/seq/aconnect/Makefile.in @@ -0,0 +1,502 @@ +# Makefile.in generated by automake 1.9.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005 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@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = ../.. +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +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@ +bin_PROGRAMS = aconnect$(EXEEXT) +subdir = seq/aconnect +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/include/aconfig.h +CONFIG_CLEAN_FILES = +am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)" +binPROGRAMS_INSTALL = $(INSTALL_PROGRAM) +PROGRAMS = $(bin_PROGRAMS) +am_aconnect_OBJECTS = aconnect.$(OBJEXT) +aconnect_OBJECTS = $(am_aconnect_OBJECTS) +aconnect_LDADD = $(LDADD) +am__DEPENDENCIES_1 = +aconnect_DEPENDENCIES = $(am__DEPENDENCIES_1) +DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)/include +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +SOURCES = $(aconnect_SOURCES) +DIST_SOURCES = $(aconnect_SOURCES) +man1dir = $(mandir)/man1 +NROFF = nroff +MANS = $(man_MANS) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALSACONF_FALSE = @ALSACONF_FALSE@ +ALSACONF_TRUE = @ALSACONF_TRUE@ +ALSAMIXER_FALSE = @ALSAMIXER_FALSE@ +ALSAMIXER_TRUE = @ALSAMIXER_TRUE@ +ALSA_CFLAGS = @ALSA_CFLAGS@ +ALSA_LIBS = @ALSA_LIBS@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CURSESINC = @CURSESINC@ +CURSESLIB = @CURSESLIB@ +CURSES_CFLAGS = @CURSES_CFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GREP = @GREP@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LN_S = @LN_S@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +POSUB = @POSUB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SND_UTIL_MAJOR = @SND_UTIL_MAJOR@ +SND_UTIL_MINOR = @SND_UTIL_MINOR@ +SND_UTIL_SUBMINOR = @SND_UTIL_SUBMINOR@ +SND_UTIL_VERSION = @SND_UTIL_VERSION@ +STRIP = @STRIP@ +TESTSOUND = @TESTSOUND@ +USE_NLS = @USE_NLS@ +USE_XMLTO_FALSE = @USE_XMLTO_FALSE@ +USE_XMLTO_TRUE = @USE_XMLTO_TRUE@ +VERSION = @VERSION@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +ac_ct_CC = @ac_ct_CC@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +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@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +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@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +ncurses5_config = @ncurses5_config@ +ncursesw5_config = @ncursesw5_config@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +xmlto = @xmlto@ +INCLUDES = -I$(top_srcdir)/include +EXTRA_DIST = README.aconnect aconnect.1 +LDADD = $(LIBINTL) +aconnect_SOURCES = aconnect.c +man_MANS = aconnect.1 +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign seq/aconnect/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --foreign seq/aconnect/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 +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + test -z "$(bindir)" || $(mkdir_p) "$(DESTDIR)$(bindir)" + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + if test -f $$p \ + ; then \ + f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \ + $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \ + else :; fi; \ + done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \ + rm -f "$(DESTDIR)$(bindir)/$$f"; \ + done + +clean-binPROGRAMS: + -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) +aconnect$(EXEEXT): $(aconnect_OBJECTS) $(aconnect_DEPENDENCIES) + @rm -f aconnect$(EXEEXT) + $(LINK) $(aconnect_LDFLAGS) $(aconnect_OBJECTS) $(aconnect_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/aconnect.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \ +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` +uninstall-info-am: +install-man1: $(man1_MANS) $(man_MANS) + @$(NORMAL_INSTALL) + test -z "$(man1dir)" || $(mkdir_p) "$(DESTDIR)$(man1dir)" + @list='$(man1_MANS) $(dist_man1_MANS) $(nodist_man1_MANS)'; \ + l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ + for i in $$l2; do \ + case "$$i" in \ + *.1*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \ + else file=$$i; fi; \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + case "$$ext" in \ + 1*) ;; \ + *) ext='1' ;; \ + esac; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed -e 's/^.*\///'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \ + $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst"; \ + done +uninstall-man1: + @$(NORMAL_UNINSTALL) + @list='$(man1_MANS) $(dist_man1_MANS) $(nodist_man1_MANS)'; \ + l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ + for i in $$l2; do \ + case "$$i" in \ + *.1*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + case "$$ext" in \ + 1*) ;; \ + *) ext='1' ;; \ + esac; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed -e 's/^.*\///'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " rm -f '$(DESTDIR)$(man1dir)/$$inst'"; \ + rm -f "$(DESTDIR)$(man1dir)/$$inst"; \ + done + +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; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + 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; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + 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; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && 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)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkdir_p) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$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: check-am +all-am: Makefile $(PROGRAMS) $(MANS) +installdirs: + for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)"; do \ + test -z "$$dir" || $(mkdir_p) "$$dir"; \ + done +install: 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: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-binPROGRAMS clean-generic 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 + +info: info-am + +info-am: + +install-data-am: install-man + +install-exec-am: install-binPROGRAMS + +install-info: install-info-am + +install-man: install-man1 + +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 + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-binPROGRAMS uninstall-info-am uninstall-man + +uninstall-man: uninstall-man1 + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ + clean-generic ctags distclean distclean-compile \ + distclean-generic distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-binPROGRAMS \ + install-data install-data-am install-exec install-exec-am \ + install-info install-info-am install-man install-man1 \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-binPROGRAMS \ + uninstall-info-am uninstall-man uninstall-man1 + +# 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/alsa-utils/seq/aconnect/README.aconnect b/alsa-utils/seq/aconnect/README.aconnect new file mode 100644 index 0000000..1f6237a --- /dev/null +++ b/alsa-utils/seq/aconnect/README.aconnect @@ -0,0 +1,46 @@ +================================================================ + aconnect - control subscriptions + ver.0.1.3 + Copyright (C) 1999-2000 Takashi Iwai +================================================================ + +aconnect is a utility to control subscriptions of two ports as the +third "manager" client. + +For example, the following connects two ports, from 64:0 to 65:0. + + % aconnect 64:0 65:0 + +To disconnect the existing subscription, use -d option. + + % aconnect -d 64:0 65:0 + +To see which port is available as input port, run the following +command: + + % aconnect -i + client 0: 'System' [type=kernel] + 0 'Timer ' + 1 'Announce ' + client 64: '0: MIDI Synth' [type=kernel] + 0 'card 0: synth-midi: 0' + +Similary, to see the output ports, use -o flag. + + % aconnect -o + client 64: '0: MIDI Synth' [type=kernel] + 0 'card 0: synth-midi: 0' + client 65: 'AWE Wave Table Synth : 0' [type=kernel] + 0 'Emu8000 port 0 ' + 1 'Emu8000 port 1 ' + 2 'Emu8000 port 2 ' + 3 'Emu8000 port 3 ' + +The option -l together with -i or -o shows subscribers for each port. + +Ports are connected exclusively when the option -e is specified. + +For modifying time-stamp with a queue, use -r or -t option followed by +a queue index which updates the time-stamp. Former uses real-time queue, +while the latter uses tick queue. The queue must be used (not necessarily +owned) by the receiver client. diff --git a/alsa-utils/seq/aconnect/aconnect.1 b/alsa-utils/seq/aconnect/aconnect.1 new file mode 100644 index 0000000..2050187 --- /dev/null +++ b/alsa-utils/seq/aconnect/aconnect.1 @@ -0,0 +1,145 @@ +.TH aconnect 1 "August 31, 2000" +.de EX +.nf +.ft CW +.. +.de EE +.ft R +.fi +.. +.SH NAME +aconnect \- ALSA sequencer connection manager + +.SH SYNOPSIS +.B aconnect +[\-d] [\-options] sender receiver +.br +.B aconnect +\-i|\-o [\-options] +.br +.B aconnect +\-x + +.SH DESCRIPTION +.B aconnect +is a utility to connect and disconnect two existing ports on ALSA sequencer +system. +The ports with the arbitrary subscription permission, such as created +by +.B aseqview(1), +can be connected to any (MIDI) device ports using +.B aconnect. +For example, to connect from port 64:0 to 65:0, run as follows: +.IP "" 4 +% aconnect 64:0 65:0 +.PP +The connection is one-way, and the whole data to the sender port (64:0) +is redirected to the receiver port (65:0). When another port (e.g. 65:1) +is attached to the same sender port, the data is sent to both receiver +ports. +For disconnection, use +.B \-d +option. +.sp +.EX +% aconnect \-d 64:0 65:0 +.EE +.PP +The address can be given using the client's name. +.sp +.EX +% aconnect External:0 Emu8000:1 +.EE +.PP +Then the port 0 of the client matching with the string "External" is +connected to the port 1 of the client matching with the "Emu8000". +.PP +Another function of +.B aconnect +is to list the present ports +on the given condition. +The input ports, which may become +.I sender +ports, can be listed with +.B \-i +option. +.sp +.EX +% aconnect \-i +client 0: 'System' [type=kernel] + 0 'Timer ' + 1 'Announce ' +client 64: 'External MIDI\-0' [type=kernel] + 0 'MIDI 0\-0 ' +.EE +.PP +Similarly, to see the output ports, use +.B \-o +flag. +.PP +You can remove all existing exported connections using +.B \-x +option. This function is useful for terminating the ALSA drivers, +because the modules with sequencer connections cannot be unloaded +unless their connections are removed. + +.SH OPTIONS +.SS CONNECTION MANAGEMENT +.TP +.B \-d, \-\-disconnect +Disconnect the given subscription. +.TP +.B \-e, \-\-exclusive +Connect ports with exclusive mode. +Both sender and receiver ports can be no longer connected by any other ports. +.TP +.B \-r, \-\-real queue +Convert time-stamps of event packets to the current value of the given +.I real-time +queue. +This is option is, however, not so useful, since +the receiver port must use (not necessarily own) the specified queue. +.TP +.B \-t, \-\-tick queue +Like +.B \-r +option, but +time-stamps are converted to the current value of the given +.I tick +queue. + +.SS LIST PORTS +.TP +.B \-i, \-\-input +List existing input (readable) ports. +This option is exclusive to +.B \-o. +.TP +.B \-o, \-\-output +List existing output (writable) ports. +This option is exclusive to +.B \-i. +.TP +.B \-l, \-\-list +List the current connection status. The connected and connecting ports +from/to each port are listed together. +The suffix flag +.B [ex] +means the connection is exclusive. +The suffix flag +.B [real:#] +and +.B [tick:#] +mean the connection includes real-time and tick conversion on the listed +queue, respectively. + +.SS REMOVE ALL CONNECTIONS +.TP +.B \-x, \-\-removeall +Remove all exported connections. + +.SH "SEE ALSO" +aseqnet(1), aseqview(1) + +.SH AUTHOR +Takashi Iwai <tiwai@suse.de> diff --git a/alsa-utils/seq/aconnect/aconnect.c b/alsa-utils/seq/aconnect/aconnect.c new file mode 100644 index 0000000..1a50666 --- /dev/null +++ b/alsa-utils/seq/aconnect/aconnect.c @@ -0,0 +1,411 @@ +/* + * connect / disconnect two subscriber ports + * ver.0.1.3 + * + * Copyright (C) 1999 Takashi Iwai + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <stdio.h> +#include <ctype.h> +#include <string.h> +#include <stdlib.h> +#include <errno.h> +#include <fcntl.h> +#include <getopt.h> +#include <stdarg.h> +#include <locale.h> +#include <sys/ioctl.h> +#include <alsa/asoundlib.h> +#include "aconfig.h" +#include "gettext.h" + +static void error_handler(const char *file, int line, const char *function, int err, const char *fmt, ...) +{ + va_list arg; + + if (err == ENOENT) /* Ignore those misleading "warnings" */ + return; + va_start(arg, fmt); + fprintf(stderr, "ALSA lib %s:%i:(%s) ", file, line, function); + vfprintf(stderr, fmt, arg); + if (err) + fprintf(stderr, ": %s", snd_strerror(err)); + putc('\n', stderr); + va_end(arg); +} + +static void usage(void) +{ + printf(_("aconnect - ALSA sequencer connection manager\n")); + printf(_("Copyright (C) 1999-2000 Takashi Iwai\n")); + printf(_("Usage:\n")); + printf(_(" * Connection/disconnection between two ports\n")); + printf(_(" aconnect [-options] sender receiver\n")); + printf(_(" sender, receiver = client:port pair\n")); + printf(_(" -d,--disconnect disconnect\n")); + printf(_(" -e,--exclusive exclusive connection\n")); + printf(_(" -r,--real # convert real-time-stamp on queue\n")); + printf(_(" -t,--tick # convert tick-time-stamp on queue\n")); + printf(_(" * List connected ports (no subscription action)\n")); + printf(_(" aconnect -i|-o [-options]\n")); + printf(_(" -i,--input list input (readable) ports\n")); + printf(_(" -o,--output list output (writable) ports\n")); + printf(_(" -l,--list list current connections of each port\n")); + printf(_(" * Remove all exported connections\n")); + printf(_(" -x, --removeall\n")); +} + +/* + * check permission (capability) of specified port + */ + +#define LIST_INPUT 1 +#define LIST_OUTPUT 2 + +#define perm_ok(pinfo,bits) ((snd_seq_port_info_get_capability(pinfo) & (bits)) == (bits)) + +static int check_permission(snd_seq_port_info_t *pinfo, int perm) +{ + if (perm) { + if (perm & LIST_INPUT) { + if (perm_ok(pinfo, SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ)) + goto __ok; + } + if (perm & LIST_OUTPUT) { + if (perm_ok(pinfo, SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE)) + goto __ok; + } + return 0; + } + __ok: + if (snd_seq_port_info_get_capability(pinfo) & SND_SEQ_PORT_CAP_NO_EXPORT) + return 0; + return 1; +} + +/* + * list subscribers of specified type + */ +static void list_each_subs(snd_seq_t *seq, snd_seq_query_subscribe_t *subs, int type, const char *msg) +{ + int count = 0; + snd_seq_query_subscribe_set_type(subs, type); + snd_seq_query_subscribe_set_index(subs, 0); + while (snd_seq_query_port_subscribers(seq, subs) >= 0) { + const snd_seq_addr_t *addr; + if (count++ == 0) + printf("\t%s: ", msg); + else + printf(", "); + addr = snd_seq_query_subscribe_get_addr(subs); + printf("%d:%d", addr->client, addr->port); + if (snd_seq_query_subscribe_get_exclusive(subs)) + printf("[ex]"); + if (snd_seq_query_subscribe_get_time_update(subs)) + printf("[%s:%d]", + (snd_seq_query_subscribe_get_time_real(subs) ? "real" : "tick"), + snd_seq_query_subscribe_get_queue(subs)); + snd_seq_query_subscribe_set_index(subs, snd_seq_query_subscribe_get_index(subs) + 1); + } + if (count > 0) + printf("\n"); +} + +/* + * list subscribers + */ +static void list_subscribers(snd_seq_t *seq, const snd_seq_addr_t *addr) +{ + snd_seq_query_subscribe_t *subs; + snd_seq_query_subscribe_alloca(&subs); + snd_seq_query_subscribe_set_root(subs, addr); + list_each_subs(seq, subs, SND_SEQ_QUERY_SUBS_READ, _("Connecting To")); + list_each_subs(seq, subs, SND_SEQ_QUERY_SUBS_WRITE, _("Connected From")); +} + +/* + * search all ports + */ +typedef void (*action_func_t)(snd_seq_t *seq, snd_seq_client_info_t *cinfo, snd_seq_port_info_t *pinfo, int count); + +static void do_search_port(snd_seq_t *seq, int perm, action_func_t do_action) +{ + snd_seq_client_info_t *cinfo; + snd_seq_port_info_t *pinfo; + int count; + + snd_seq_client_info_alloca(&cinfo); + snd_seq_port_info_alloca(&pinfo); + snd_seq_client_info_set_client(cinfo, -1); + while (snd_seq_query_next_client(seq, cinfo) >= 0) { + /* reset query info */ + snd_seq_port_info_set_client(pinfo, snd_seq_client_info_get_client(cinfo)); + snd_seq_port_info_set_port(pinfo, -1); + count = 0; + while (snd_seq_query_next_port(seq, pinfo) >= 0) { + if (check_permission(pinfo, perm)) { + do_action(seq, cinfo, pinfo, count); + count++; + } + } + } +} + + +static void print_port(snd_seq_t *seq, snd_seq_client_info_t *cinfo, + snd_seq_port_info_t *pinfo, int count) +{ + if (! count) { + printf(_("client %d: '%s' [type=%s]\n"), + snd_seq_client_info_get_client(cinfo), + snd_seq_client_info_get_name(cinfo), + (snd_seq_client_info_get_type(cinfo) == SND_SEQ_USER_CLIENT ? + _("user") : _("kernel"))); + } + printf(" %3d '%-16s'\n", + snd_seq_port_info_get_port(pinfo), + snd_seq_port_info_get_name(pinfo)); +} + +static void print_port_and_subs(snd_seq_t *seq, snd_seq_client_info_t *cinfo, + snd_seq_port_info_t *pinfo, int count) +{ + print_port(seq, cinfo, pinfo, count); + list_subscribers(seq, snd_seq_port_info_get_addr(pinfo)); +} + + +/* + * remove all (exported) connections + */ +static void remove_connection(snd_seq_t *seq, snd_seq_client_info_t *cinfo, + snd_seq_port_info_t *pinfo, int count) +{ + snd_seq_query_subscribe_t *query; + + snd_seq_query_subscribe_alloca(&query); + snd_seq_query_subscribe_set_root(query, snd_seq_port_info_get_addr(pinfo)); + + snd_seq_query_subscribe_set_type(query, SND_SEQ_QUERY_SUBS_READ); + snd_seq_query_subscribe_set_index(query, 0); + for (; snd_seq_query_port_subscribers(seq, query) >= 0; + snd_seq_query_subscribe_set_index(query, snd_seq_query_subscribe_get_index(query) + 1)) { + snd_seq_port_info_t *port; + snd_seq_port_subscribe_t *subs; + const snd_seq_addr_t *sender = snd_seq_query_subscribe_get_root(query); + const snd_seq_addr_t *dest = snd_seq_query_subscribe_get_addr(query); + snd_seq_port_info_alloca(&port); + if (snd_seq_get_any_port_info(seq, dest->client, dest->port, port) < 0) + continue; + if (!(snd_seq_port_info_get_capability(port) & SND_SEQ_PORT_CAP_SUBS_WRITE)) + continue; + if (snd_seq_port_info_get_capability(port) & SND_SEQ_PORT_CAP_NO_EXPORT) + continue; + snd_seq_port_subscribe_alloca(&subs); + snd_seq_port_subscribe_set_queue(subs, snd_seq_query_subscribe_get_queue(query)); + snd_seq_port_subscribe_set_sender(subs, sender); + snd_seq_port_subscribe_set_dest(subs, dest); + snd_seq_unsubscribe_port(seq, subs); + } + + snd_seq_query_subscribe_set_type(query, SND_SEQ_QUERY_SUBS_WRITE); + snd_seq_query_subscribe_set_index(query, 0); + for (; snd_seq_query_port_subscribers(seq, query) >= 0; + snd_seq_query_subscribe_set_index(query, snd_seq_query_subscribe_get_index(query) + 1)) { + snd_seq_port_info_t *port; + snd_seq_port_subscribe_t *subs; + const snd_seq_addr_t *dest = snd_seq_query_subscribe_get_root(query); + const snd_seq_addr_t *sender = snd_seq_query_subscribe_get_addr(query); + snd_seq_port_info_alloca(&port); + if (snd_seq_get_any_port_info(seq, sender->client, sender->port, port) < 0) + continue; + if (!(snd_seq_port_info_get_capability(port) & SND_SEQ_PORT_CAP_SUBS_READ)) + continue; + if (snd_seq_port_info_get_capability(port) & SND_SEQ_PORT_CAP_NO_EXPORT) + continue; + snd_seq_port_subscribe_alloca(&subs); + snd_seq_port_subscribe_set_queue(subs, snd_seq_query_subscribe_get_queue(query)); + snd_seq_port_subscribe_set_sender(subs, sender); + snd_seq_port_subscribe_set_dest(subs, dest); + snd_seq_unsubscribe_port(seq, subs); + } +} + +static void remove_all_connections(snd_seq_t *seq) +{ + do_search_port(seq, 0, remove_connection); +} + + +/* + * main.. + */ + +enum { + SUBSCRIBE, UNSUBSCRIBE, LIST, REMOVE_ALL +}; + +static const struct option long_option[] = { + {"disconnect", 0, NULL, 'd'}, + {"input", 0, NULL, 'i'}, + {"output", 0, NULL, 'o'}, + {"real", 1, NULL, 'r'}, + {"tick", 1, NULL, 't'}, + {"exclusive", 0, NULL, 'e'}, + {"list", 0, NULL, 'l'}, + {"removeall", 0, NULL, 'x'}, + {NULL, 0, NULL, 0}, +}; + +int main(int argc, char **argv) +{ + int c; + snd_seq_t *seq; + int queue = 0, convert_time = 0, convert_real = 0, exclusive = 0; + int command = SUBSCRIBE; + int list_perm = 0; + int client; + int list_subs = 0; + snd_seq_port_subscribe_t *subs; + snd_seq_addr_t sender, dest; + +#ifdef ENABLE_NLS + setlocale(LC_ALL, ""); + textdomain(PACKAGE); +#endif + + while ((c = getopt_long(argc, argv, "dior:t:elx", long_option, NULL)) != -1) { + switch (c) { + case 'd': + command = UNSUBSCRIBE; + break; + case 'i': + command = LIST; + list_perm |= LIST_INPUT; + break; + case 'o': + command = LIST; + list_perm |= LIST_OUTPUT; + break; + case 'e': + exclusive = 1; + break; + case 'r': + queue = atoi(optarg); + convert_time = 1; + convert_real = 1; + break; + case 't': + queue = atoi(optarg); + convert_time = 1; + convert_real = 0; + break; + case 'l': + list_subs = 1; + break; + case 'x': + command = REMOVE_ALL; + break; + default: + usage(); + exit(1); + } + } + + if (snd_seq_open(&seq, "default", SND_SEQ_OPEN_DUPLEX, 0) < 0) { + fprintf(stderr, _("can't open sequencer\n")); + return 1; + } + + snd_lib_error_set_handler(error_handler); + + switch (command) { + case LIST: + do_search_port(seq, list_perm, + list_subs ? print_port_and_subs : print_port); + snd_seq_close(seq); + return 0; + case REMOVE_ALL: + remove_all_connections(seq); + snd_seq_close(seq); + return 0; + } + + /* connection or disconnection */ + + if (optind + 2 > argc) { + snd_seq_close(seq); + usage(); + exit(1); + } + + if ((client = snd_seq_client_id(seq)) < 0) { + snd_seq_close(seq); + fprintf(stderr, _("can't get client id\n")); + return 1; + } + + /* set client info */ + if (snd_seq_set_client_name(seq, "ALSA Connector") < 0) { + snd_seq_close(seq); + fprintf(stderr, _("can't set client info\n")); + return 1; + } + + /* set subscription */ + if (snd_seq_parse_address(seq, &sender, argv[optind]) < 0) { + snd_seq_close(seq); + fprintf(stderr, _("invalid sender address %s\n"), argv[optind]); + return 1; + } + if (snd_seq_parse_address(seq, &dest, argv[optind + 1]) < 0) { + snd_seq_close(seq); + fprintf(stderr, _("invalid destination address %s\n"), argv[optind + 1]); + return 1; + } + snd_seq_port_subscribe_alloca(&subs); + snd_seq_port_subscribe_set_sender(subs, &sender); + snd_seq_port_subscribe_set_dest(subs, &dest); + snd_seq_port_subscribe_set_queue(subs, queue); + snd_seq_port_subscribe_set_exclusive(subs, exclusive); + snd_seq_port_subscribe_set_time_update(subs, convert_time); + snd_seq_port_subscribe_set_time_real(subs, convert_real); + + if (command == UNSUBSCRIBE) { + if (snd_seq_get_port_subscription(seq, subs) < 0) { + snd_seq_close(seq); + fprintf(stderr, _("No subscription is found\n")); + return 1; + } + if (snd_seq_unsubscribe_port(seq, subs) < 0) { + snd_seq_close(seq); + fprintf(stderr, _("Disconnection failed (%s)\n"), snd_strerror(errno)); + return 1; + } + } else { + if (snd_seq_get_port_subscription(seq, subs) == 0) { + snd_seq_close(seq); + fprintf(stderr, _("Connection is already subscribed\n")); + return 1; + } + if (snd_seq_subscribe_port(seq, subs) < 0) { + snd_seq_close(seq); + fprintf(stderr, _("Connection failed (%s)\n"), snd_strerror(errno)); + return 1; + } + } + + snd_seq_close(seq); + + return 0; +} diff --git a/alsa-utils/seq/aplaymidi/Makefile.am b/alsa-utils/seq/aplaymidi/Makefile.am new file mode 100644 index 0000000..bed2a0e --- /dev/null +++ b/alsa-utils/seq/aplaymidi/Makefile.am @@ -0,0 +1,5 @@ +INCLUDES = -I$(top_srcdir)/include +EXTRA_DIST = aplaymidi.1 arecordmidi.1 + +bin_PROGRAMS = aplaymidi arecordmidi +man_MANS = aplaymidi.1 arecordmidi.1 diff --git a/alsa-utils/seq/aplaymidi/Makefile.in b/alsa-utils/seq/aplaymidi/Makefile.in new file mode 100644 index 0000000..4e623db --- /dev/null +++ b/alsa-utils/seq/aplaymidi/Makefile.in @@ -0,0 +1,505 @@ +# Makefile.in generated by automake 1.9.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005 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@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = ../.. +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +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@ +bin_PROGRAMS = aplaymidi$(EXEEXT) arecordmidi$(EXEEXT) +subdir = seq/aplaymidi +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/include/aconfig.h +CONFIG_CLEAN_FILES = +am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)" +binPROGRAMS_INSTALL = $(INSTALL_PROGRAM) +PROGRAMS = $(bin_PROGRAMS) +aplaymidi_SOURCES = aplaymidi.c +aplaymidi_OBJECTS = aplaymidi.$(OBJEXT) +aplaymidi_LDADD = $(LDADD) +arecordmidi_SOURCES = arecordmidi.c +arecordmidi_OBJECTS = arecordmidi.$(OBJEXT) +arecordmidi_LDADD = $(LDADD) +DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)/include +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +SOURCES = aplaymidi.c arecordmidi.c +DIST_SOURCES = aplaymidi.c arecordmidi.c +man1dir = $(mandir)/man1 +NROFF = nroff +MANS = $(man_MANS) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALSACONF_FALSE = @ALSACONF_FALSE@ +ALSACONF_TRUE = @ALSACONF_TRUE@ +ALSAMIXER_FALSE = @ALSAMIXER_FALSE@ +ALSAMIXER_TRUE = @ALSAMIXER_TRUE@ +ALSA_CFLAGS = @ALSA_CFLAGS@ +ALSA_LIBS = @ALSA_LIBS@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CURSESINC = @CURSESINC@ +CURSESLIB = @CURSESLIB@ +CURSES_CFLAGS = @CURSES_CFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GREP = @GREP@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LN_S = @LN_S@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +POSUB = @POSUB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SND_UTIL_MAJOR = @SND_UTIL_MAJOR@ +SND_UTIL_MINOR = @SND_UTIL_MINOR@ +SND_UTIL_SUBMINOR = @SND_UTIL_SUBMINOR@ +SND_UTIL_VERSION = @SND_UTIL_VERSION@ +STRIP = @STRIP@ +TESTSOUND = @TESTSOUND@ +USE_NLS = @USE_NLS@ +USE_XMLTO_FALSE = @USE_XMLTO_FALSE@ +USE_XMLTO_TRUE = @USE_XMLTO_TRUE@ +VERSION = @VERSION@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +ac_ct_CC = @ac_ct_CC@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +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@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +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@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +ncurses5_config = @ncurses5_config@ +ncursesw5_config = @ncursesw5_config@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +xmlto = @xmlto@ +INCLUDES = -I$(top_srcdir)/include +EXTRA_DIST = aplaymidi.1 arecordmidi.1 +man_MANS = aplaymidi.1 arecordmidi.1 +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign seq/aplaymidi/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --foreign seq/aplaymidi/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 +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + test -z "$(bindir)" || $(mkdir_p) "$(DESTDIR)$(bindir)" + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + if test -f $$p \ + ; then \ + f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \ + $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \ + else :; fi; \ + done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \ + rm -f "$(DESTDIR)$(bindir)/$$f"; \ + done + +clean-binPROGRAMS: + -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) +aplaymidi$(EXEEXT): $(aplaymidi_OBJECTS) $(aplaymidi_DEPENDENCIES) + @rm -f aplaymidi$(EXEEXT) + $(LINK) $(aplaymidi_LDFLAGS) $(aplaymidi_OBJECTS) $(aplaymidi_LDADD) $(LIBS) +arecordmidi$(EXEEXT): $(arecordmidi_OBJECTS) $(arecordmidi_DEPENDENCIES) + @rm -f arecordmidi$(EXEEXT) + $(LINK) $(arecordmidi_LDFLAGS) $(arecordmidi_OBJECTS) $(arecordmidi_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/aplaymidi.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arecordmidi.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \ +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` +uninstall-info-am: +install-man1: $(man1_MANS) $(man_MANS) + @$(NORMAL_INSTALL) + test -z "$(man1dir)" || $(mkdir_p) "$(DESTDIR)$(man1dir)" + @list='$(man1_MANS) $(dist_man1_MANS) $(nodist_man1_MANS)'; \ + l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ + for i in $$l2; do \ + case "$$i" in \ + *.1*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \ + else file=$$i; fi; \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + case "$$ext" in \ + 1*) ;; \ + *) ext='1' ;; \ + esac; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed -e 's/^.*\///'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \ + $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst"; \ + done +uninstall-man1: + @$(NORMAL_UNINSTALL) + @list='$(man1_MANS) $(dist_man1_MANS) $(nodist_man1_MANS)'; \ + l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ + for i in $$l2; do \ + case "$$i" in \ + *.1*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + case "$$ext" in \ + 1*) ;; \ + *) ext='1' ;; \ + esac; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed -e 's/^.*\///'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " rm -f '$(DESTDIR)$(man1dir)/$$inst'"; \ + rm -f "$(DESTDIR)$(man1dir)/$$inst"; \ + done + +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; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + 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; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + 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; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && 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)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkdir_p) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$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: check-am +all-am: Makefile $(PROGRAMS) $(MANS) +installdirs: + for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)"; do \ + test -z "$$dir" || $(mkdir_p) "$$dir"; \ + done +install: 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: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-binPROGRAMS clean-generic 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 + +info: info-am + +info-am: + +install-data-am: install-man + +install-exec-am: install-binPROGRAMS + +install-info: install-info-am + +install-man: install-man1 + +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 + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-binPROGRAMS uninstall-info-am uninstall-man + +uninstall-man: uninstall-man1 + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ + clean-generic ctags distclean distclean-compile \ + distclean-generic distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-binPROGRAMS \ + install-data install-data-am install-exec install-exec-am \ + install-info install-info-am install-man install-man1 \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-binPROGRAMS \ + uninstall-info-am uninstall-man uninstall-man1 + +# 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/alsa-utils/seq/aplaymidi/aplaymidi.1 b/alsa-utils/seq/aplaymidi/aplaymidi.1 new file mode 100644 index 0000000..0134129 --- /dev/null +++ b/alsa-utils/seq/aplaymidi/aplaymidi.1 @@ -0,0 +1,55 @@ +.TH APLAYMIDI 1 "15 Feb 2004" + +.SH NAME +aplaymidi \- play Standard MIDI Files + +.SH SYNOPSIS +.B aplaymidi +\-p client:port[,...] [\-d delay] midifile ... + +.SH DESCRIPTION +.B aplaymidi +is a command-line utility that plays the specified MIDI file(s) to one +or more ALSA sequencer ports. + +.SH OPTIONS + +.TP +.I \-h, \-\-help +Prints a list of options. + +.TP +.I \-V, \-\-version +Prints the current version. + +.TP +.I \-l, \-\-list +Prints a list of possible output ports. + +.TP +.I \-p, \-\-port=client:port,... +Sets the sequencer port(s) to which the events in the MIDI file(s) are +sent. + +A client can be specified by its number, its name, or a prefix of its +name. A port is specified by its number; for port 0 of a client, the +":0" part of the port specification can be omitted. + +For compatibility with +.B pmidi(1), +the port specification is taken from the +.I ALSA_OUTPUT_PORTS +environment variable if none is given on the command line. + +.TP +.I \-d, \-\-delay=seconds +Specifies how long to wait after the end of each MIDI file, +to allow the last notes to die away. + +.SH SEE ALSO +pmidi(1) +.br +playmidi(1) + +.SH AUTHOR +Clemens Ladisch <clemens@ladisch.de> diff --git a/alsa-utils/seq/aplaymidi/aplaymidi.c b/alsa-utils/seq/aplaymidi/aplaymidi.c new file mode 100644 index 0000000..5ed7bab --- /dev/null +++ b/alsa-utils/seq/aplaymidi/aplaymidi.c @@ -0,0 +1,927 @@ +/* + * aplaymidi.c - play Standard MIDI Files to sequencer port(s) + * + * Copyright (c) 2004-2006 Clemens Ladisch <clemens@ladisch.de> + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* TODO: sequencer queue timer selection */ + +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <getopt.h> +#include <unistd.h> +#include <alsa/asoundlib.h> +#include "aconfig.h" +#include "version.h" + +#define MIDI_BYTES_PER_SEC 3125 + +/* + * A MIDI event after being parsed/loaded from the file. + * There could be made a case for using snd_seq_event_t instead. + */ +struct event { + struct event *next; /* linked list */ + + unsigned char type; /* SND_SEQ_EVENT_xxx */ + unsigned char port; /* port index */ + unsigned int tick; + union { + unsigned char d[3]; /* channel and data bytes */ + int tempo; + unsigned int length; /* length of sysex data */ + } data; + unsigned char sysex[0]; +}; + +struct track { + struct event *first_event; /* list of all events in this track */ + int end_tick; /* length of this track */ + + struct event *current_event; /* used while loading and playing */ +}; + +static snd_seq_t *seq; +static int client; +static int port_count; +static snd_seq_addr_t *ports; +static int queue; +static int end_delay = 2; +static const char *file_name; +static FILE *file; +static int file_offset; /* current offset in input file */ +static int num_tracks; +static struct track *tracks; +static int smpte_timing; + +/* prints an error message to stderr */ +static void errormsg(const char *msg, ...) +{ + va_list ap; + + va_start(ap, msg); + vfprintf(stderr, msg, ap); + va_end(ap); + fputc('\n', stderr); +} + +/* prints an error message to stderr, and dies */ +static void fatal(const char *msg, ...) +{ + va_list ap; + + va_start(ap, msg); + vfprintf(stderr, msg, ap); + va_end(ap); + fputc('\n', stderr); + exit(EXIT_FAILURE); +} + +/* memory allocation error handling */ +static void check_mem(void *p) +{ + if (!p) + fatal("Out of memory"); +} + +/* error handling for ALSA functions */ +static void check_snd(const char *operation, int err) +{ + if (err < 0) + fatal("Cannot %s - %s", operation, snd_strerror(err)); +} + +static void init_seq(void) +{ + int err; + + /* open sequencer */ + err = snd_seq_open(&seq, "default", SND_SEQ_OPEN_DUPLEX, 0); + check_snd("open sequencer", err); + + /* set our name (otherwise it's "Client-xxx") */ + err = snd_seq_set_client_name(seq, "aplaymidi"); + check_snd("set client name", err); + + /* find out who we actually are */ + client = snd_seq_client_id(seq); + check_snd("get client id", client); +} + +/* parses one or more port addresses from the string */ +static void parse_ports(const char *arg) +{ + char *buf, *s, *port_name; + int err; + + /* make a copy of the string because we're going to modify it */ + buf = strdup(arg); + check_mem(buf); + + for (port_name = s = buf; s; port_name = s + 1) { + /* Assume that ports are separated by commas. We don't use + * spaces because those are valid in client names. */ + s = strchr(port_name, ','); + if (s) + *s = '\0'; + + ++port_count; + ports = realloc(ports, port_count * sizeof(snd_seq_addr_t)); + check_mem(ports); + + err = snd_seq_parse_address(seq, &ports[port_count - 1], port_name); + if (err < 0) + fatal("Invalid port %s - %s", port_name, snd_strerror(err)); + } + + free(buf); +} + +static void create_source_port(void) +{ + snd_seq_port_info_t *pinfo; + int err; + + snd_seq_port_info_alloca(&pinfo); + + /* the first created port is 0 anyway, but let's make sure ... */ + snd_seq_port_info_set_port(pinfo, 0); + snd_seq_port_info_set_port_specified(pinfo, 1); + + snd_seq_port_info_set_name(pinfo, "aplaymidi"); + + snd_seq_port_info_set_capability(pinfo, 0); /* sic */ + snd_seq_port_info_set_type(pinfo, + SND_SEQ_PORT_TYPE_MIDI_GENERIC | + SND_SEQ_PORT_TYPE_APPLICATION); + + err = snd_seq_create_port(seq, pinfo); + check_snd("create port", err); +} + +static void create_queue(void) +{ + queue = snd_seq_alloc_named_queue(seq, "aplaymidi"); + check_snd("create queue", queue); + /* the queue is now locked, which is just fine */ +} + +static void connect_ports(void) +{ + int i, err; + + /* + * We send MIDI events with explicit destination addresses, so we don't + * need any connections to the playback ports. But we connect to those + * anyway to force any underlying RawMIDI ports to remain open while + * we're playing - otherwise, ALSA would reset the port after every + * event. + */ + for (i = 0; i < port_count; ++i) { + err = snd_seq_connect_to(seq, 0, ports[i].client, ports[i].port); + if (err < 0) + fatal("Cannot connect to port %d:%d - %s", + ports[i].client, ports[i].port, snd_strerror(err)); + } +} + +static int read_byte(void) +{ + ++file_offset; + return getc(file); +} + +/* reads a little-endian 32-bit integer */ +static int read_32_le(void) +{ + int value; + value = read_byte(); + value |= read_byte() << 8; + value |= read_byte() << 16; + value |= read_byte() << 24; + return !feof(file) ? value : -1; +} + +/* reads a 4-character identifier */ +static int read_id(void) +{ + return read_32_le(); +} +#define MAKE_ID(c1, c2, c3, c4) ((c1) | ((c2) << 8) | ((c3) << 16) | ((c4) << 24)) + +/* reads a fixed-size big-endian number */ +static int read_int(int bytes) +{ + int c, value = 0; + + do { + c = read_byte(); + if (c == EOF) + return -1; + value = (value << 8) | c; + } while (--bytes); + return value; +} + +/* reads a variable-length number */ +static int read_var(void) +{ + int value, c; + + c = read_byte(); + value = c & 0x7f; + if (c & 0x80) { + c = read_byte(); + value = (value << 7) | (c & 0x7f); + if (c & 0x80) { + c = read_byte(); + value = (value << 7) | (c & 0x7f); + if (c & 0x80) { + c = read_byte(); + value = (value << 7) | c; + if (c & 0x80) + return -1; + } + } + } + return !feof(file) ? value : -1; +} + +/* allocates a new event */ +static struct event *new_event(struct track *track, int sysex_length) +{ + struct event *event; + + event = malloc(sizeof(struct event) + sysex_length); + check_mem(event); + + event->next = NULL; + + /* append at the end of the track's linked list */ + if (track->current_event) + track->current_event->next = event; + else + track->first_event = event; + track->current_event = event; + + return event; +} + +static void skip(int bytes) +{ + while (bytes > 0) + read_byte(), --bytes; +} + +/* reads one complete track from the file */ +static int read_track(struct track *track, int track_end) +{ + int tick = 0; + unsigned char last_cmd = 0; + unsigned char port = 0; + + /* the current file position is after the track ID and length */ + while (file_offset < track_end) { + unsigned char cmd; + struct event *event; + int delta_ticks, len, c; + + delta_ticks = read_var(); + if (delta_ticks < 0) + break; + tick += delta_ticks; + + c = read_byte(); + if (c < 0) + break; + + if (c & 0x80) { + /* have command */ + cmd = c; + if (cmd < 0xf0) + last_cmd = cmd; + } else { + /* running status */ + ungetc(c, file); + file_offset--; + cmd = last_cmd; + if (!cmd) + goto _error; + } + + switch (cmd >> 4) { + /* maps SMF events to ALSA sequencer events */ + static const unsigned char cmd_type[] = { + [0x8] = SND_SEQ_EVENT_NOTEOFF, + [0x9] = SND_SEQ_EVENT_NOTEON, + [0xa] = SND_SEQ_EVENT_KEYPRESS, + [0xb] = SND_SEQ_EVENT_CONTROLLER, + [0xc] = SND_SEQ_EVENT_PGMCHANGE, + [0xd] = SND_SEQ_EVENT_CHANPRESS, + [0xe] = SND_SEQ_EVENT_PITCHBEND + }; + + case 0x8: /* channel msg with 2 parameter bytes */ + case 0x9: + case 0xa: + case 0xb: + case 0xe: + event = new_event(track, 0); + event->type = cmd_type[cmd >> 4]; + event->port = port; + event->tick = tick; + event->data.d[0] = cmd & 0x0f; + event->data.d[1] = read_byte() & 0x7f; + event->data.d[2] = read_byte() & 0x7f; + break; + + case 0xc: /* channel msg with 1 parameter byte */ + case 0xd: + event = new_event(track, 0); + event->type = cmd_type[cmd >> 4]; + event->port = port; + event->tick = tick; + event->data.d[0] = cmd & 0x0f; + event->data.d[1] = read_byte() & 0x7f; + break; + + case 0xf: + switch (cmd) { + case 0xf0: /* sysex */ + case 0xf7: /* continued sysex, or escaped commands */ + len = read_var(); + if (len < 0) + goto _error; + if (cmd == 0xf0) + ++len; + event = new_event(track, len); + event->type = SND_SEQ_EVENT_SYSEX; + event->port = port; + event->tick = tick; + event->data.length = len; + if (cmd == 0xf0) { + event->sysex[0] = 0xf0; + c = 1; + } else { + c = 0; + } + for (; c < len; ++c) + event->sysex[c] = read_byte(); + break; + + case 0xff: /* meta event */ + c = read_byte(); + len = read_var(); + if (len < 0) + goto _error; + + switch (c) { + case 0x21: /* port number */ + if (len < 1) + goto _error; + port = read_byte() % port_count; + skip(len - 1); + break; + + case 0x2f: /* end of track */ + track->end_tick = tick; + skip(track_end - file_offset); + return 1; + + case 0x51: /* tempo */ + if (len < 3) + goto _error; + if (smpte_timing) { + /* SMPTE timing doesn't change */ + skip(len); + } else { + event = new_event(track, 0); + event->type = SND_SEQ_EVENT_TEMPO; + event->port = port; + event->tick = tick; + event->data.tempo = read_byte() << 16; + event->data.tempo |= read_byte() << 8; + event->data.tempo |= read_byte(); + skip(len - 3); + } + break; + + default: /* ignore all other meta events */ + skip(len); + break; + } + break; + + default: /* invalid Fx command */ + goto _error; + } + break; + + default: /* cannot happen */ + goto _error; + } + } +_error: + errormsg("%s: invalid MIDI data (offset %#x)", file_name, file_offset); + return 0; +} + +/* reads an entire MIDI file */ +static int read_smf(void) +{ + int header_len, type, time_division, i, err; + snd_seq_queue_tempo_t *queue_tempo; + + /* the curren position is immediately after the "MThd" id */ + header_len = read_int(4); + if (header_len < 6) { +invalid_format: + errormsg("%s: invalid file format", file_name); + return 0; + } + + type = read_int(2); + if (type != 0 && type != 1) { + errormsg("%s: type %d format is not supported", file_name, type); + return 0; + } + + num_tracks = read_int(2); + if (num_tracks < 1 || num_tracks > 1000) { + errormsg("%s: invalid number of tracks (%d)", file_name, num_tracks); + num_tracks = 0; + return 0; + } + tracks = calloc(num_tracks, sizeof(struct track)); + if (!tracks) { + errormsg("out of memory"); + num_tracks = 0; + return 0; + } + + time_division = read_int(2); + if (time_division < 0) + goto invalid_format; + + /* interpret and set tempo */ + snd_seq_queue_tempo_alloca(&queue_tempo); + smpte_timing = !!(time_division & 0x8000); + if (!smpte_timing) { + /* time_division is ticks per quarter */ + snd_seq_queue_tempo_set_tempo(queue_tempo, 500000); /* default: 120 bpm */ + snd_seq_queue_tempo_set_ppq(queue_tempo, time_division); + } else { + /* upper byte is negative frames per second */ + i = 0x80 - ((time_division >> 8) & 0x7f); + /* lower byte is ticks per frame */ + time_division &= 0xff; + /* now pretend that we have quarter-note based timing */ + switch (i) { + case 24: + snd_seq_queue_tempo_set_tempo(queue_tempo, 500000); + snd_seq_queue_tempo_set_ppq(queue_tempo, 12 * time_division); + break; + case 25: + snd_seq_queue_tempo_set_tempo(queue_tempo, 400000); + snd_seq_queue_tempo_set_ppq(queue_tempo, 10 * time_division); + break; + case 29: /* 30 drop-frame */ + snd_seq_queue_tempo_set_tempo(queue_tempo, 100000000); + snd_seq_queue_tempo_set_ppq(queue_tempo, 2997 * time_division); + break; + case 30: + snd_seq_queue_tempo_set_tempo(queue_tempo, 500000); + snd_seq_queue_tempo_set_ppq(queue_tempo, 15 * time_division); + break; + default: + errormsg("%s: invalid number of SMPTE frames per second (%d)", + file_name, i); + return 0; + } + } + err = snd_seq_set_queue_tempo(seq, queue, queue_tempo); + if (err < 0) { + errormsg("Cannot set queue tempo (%u/%i)", + snd_seq_queue_tempo_get_tempo(queue_tempo), + snd_seq_queue_tempo_get_ppq(queue_tempo)); + return 0; + } + + /* read tracks */ + for (i = 0; i < num_tracks; ++i) { + int len; + + /* search for MTrk chunk */ + for (;;) { + int id = read_id(); + len = read_int(4); + if (feof(file)) { + errormsg("%s: unexpected end of file", file_name); + return 0; + } + if (len < 0 || len >= 0x10000000) { + errormsg("%s: invalid chunk length %d", file_name, len); + return 0; + } + if (id == MAKE_ID('M', 'T', 'r', 'k')) + break; + skip(len); + } + if (!read_track(&tracks[i], file_offset + len)) + return 0; + } + return 1; +} + +static int read_riff(void) +{ + /* skip file length */ + read_byte(); + read_byte(); + read_byte(); + read_byte(); + + /* check file type ("RMID" = RIFF MIDI) */ + if (read_id() != MAKE_ID('R', 'M', 'I', 'D')) { +invalid_format: + errormsg("%s: invalid file format", file_name); + return 0; + } + /* search for "data" chunk */ + for (;;) { + int id = read_id(); + int len = read_32_le(); + if (feof(file)) { +data_not_found: + errormsg("%s: data chunk not found", file_name); + return 0; + } + if (id == MAKE_ID('d', 'a', 't', 'a')) + break; + if (len < 0) + goto data_not_found; + skip((len + 1) & ~1); + } + /* the "data" chunk must contain data in SMF format */ + if (read_id() != MAKE_ID('M', 'T', 'h', 'd')) + goto invalid_format; + return read_smf(); +} + +static void cleanup_file_data(void) +{ + int i; + struct event *event; + + for (i = 0; i < num_tracks; ++i) { + event = tracks[i].first_event; + while (event) { + struct event *next = event->next; + free(event); + event = next; + } + } + num_tracks = 0; + free(tracks); + tracks = NULL; +} + +static void handle_big_sysex(snd_seq_event_t *ev) +{ + unsigned int length; + ssize_t event_size; + int err; + + length = ev->data.ext.len; + if (length > MIDI_BYTES_PER_SEC) + ev->data.ext.len = MIDI_BYTES_PER_SEC; + event_size = snd_seq_event_length(ev); + if (event_size + 1 > snd_seq_get_output_buffer_size(seq)) { + err = snd_seq_drain_output(seq); + check_snd("drain output", err); + err = snd_seq_set_output_buffer_size(seq, event_size + 1); + check_snd("set output buffer size", err); + } + while (length > MIDI_BYTES_PER_SEC) { + err = snd_seq_event_output(seq, ev); + check_snd("output event", err); + err = snd_seq_drain_output(seq); + check_snd("drain output", err); + err = snd_seq_sync_output_queue(seq); + check_snd("sync output", err); + if (sleep(1)) + fatal("aborted"); + ev->data.ext.ptr += MIDI_BYTES_PER_SEC; + length -= MIDI_BYTES_PER_SEC; + } + ev->data.ext.len = length; +} + +static void play_midi(void) +{ + snd_seq_event_t ev; + int i, max_tick, err; + + /* calculate length of the entire file */ + max_tick = -1; + for (i = 0; i < num_tracks; ++i) { + if (tracks[i].end_tick > max_tick) + max_tick = tracks[i].end_tick; + } + + /* initialize current position in each track */ + for (i = 0; i < num_tracks; ++i) + tracks[i].current_event = tracks[i].first_event; + + /* common settings for all our events */ + snd_seq_ev_clear(&ev); + ev.queue = queue; + ev.source.port = 0; + ev.flags = SND_SEQ_TIME_STAMP_TICK; + + err = snd_seq_start_queue(seq, queue, NULL); + check_snd("start queue", err); + /* The queue won't be started until the START_QUEUE event is + * actually drained to the kernel, which is exactly what we want. */ + + for (;;) { + struct event* event = NULL; + struct track* event_track = NULL; + int i, min_tick = max_tick + 1; + + /* search next event */ + for (i = 0; i < num_tracks; ++i) { + struct track *track = &tracks[i]; + struct event *e2 = track->current_event; + if (e2 && e2->tick < min_tick) { + min_tick = e2->tick; + event = e2; + event_track = track; + } + } + if (!event) + break; /* end of song reached */ + + /* advance pointer to next event */ + event_track->current_event = event->next; + + /* output the event */ + ev.type = event->type; + ev.time.tick = event->tick; + ev.dest = ports[event->port]; + switch (ev.type) { + case SND_SEQ_EVENT_NOTEON: + case SND_SEQ_EVENT_NOTEOFF: + case SND_SEQ_EVENT_KEYPRESS: + snd_seq_ev_set_fixed(&ev); + ev.data.note.channel = event->data.d[0]; + ev.data.note.note = event->data.d[1]; + ev.data.note.velocity = event->data.d[2]; + break; + case SND_SEQ_EVENT_CONTROLLER: + snd_seq_ev_set_fixed(&ev); + ev.data.control.channel = event->data.d[0]; + ev.data.control.param = event->data.d[1]; + ev.data.control.value = event->data.d[2]; + break; + case SND_SEQ_EVENT_PGMCHANGE: + case SND_SEQ_EVENT_CHANPRESS: + snd_seq_ev_set_fixed(&ev); + ev.data.control.channel = event->data.d[0]; + ev.data.control.value = event->data.d[1]; + break; + case SND_SEQ_EVENT_PITCHBEND: + snd_seq_ev_set_fixed(&ev); + ev.data.control.channel = event->data.d[0]; + ev.data.control.value = + ((event->data.d[1]) | + ((event->data.d[2]) << 7)) - 0x2000; + break; + case SND_SEQ_EVENT_SYSEX: + snd_seq_ev_set_variable(&ev, event->data.length, + event->sysex); + handle_big_sysex(&ev); + break; + case SND_SEQ_EVENT_TEMPO: + snd_seq_ev_set_fixed(&ev); + ev.dest.client = SND_SEQ_CLIENT_SYSTEM; + ev.dest.port = SND_SEQ_PORT_SYSTEM_TIMER; + ev.data.queue.queue = queue; + ev.data.queue.param.value = event->data.tempo; + break; + default: + fatal("Invalid event type %d!", ev.type); + } + + /* this blocks when the output pool has been filled */ + err = snd_seq_event_output(seq, &ev); + check_snd("output event", err); + } + + /* schedule queue stop at end of song */ + snd_seq_ev_set_fixed(&ev); + ev.type = SND_SEQ_EVENT_STOP; + ev.time.tick = max_tick; + ev.dest.client = SND_SEQ_CLIENT_SYSTEM; + ev.dest.port = SND_SEQ_PORT_SYSTEM_TIMER; + ev.data.queue.queue = queue; + err = snd_seq_event_output(seq, &ev); + check_snd("output event", err); + + /* make sure that the sequencer sees all our events */ + err = snd_seq_drain_output(seq); + check_snd("drain output", err); + + /* + * There are three possibilities how to wait until all events have + * been played: + * 1) send an event back to us (like pmidi does), and wait for it; + * 2) wait for the EVENT_STOP notification for our queue which is sent + * by the system timer port (this would require a subscription); + * 3) wait until the output pool is empty. + * The last is the simplest. + */ + err = snd_seq_sync_output_queue(seq); + check_snd("sync output", err); + + /* give the last notes time to die away */ + if (end_delay > 0) + sleep(end_delay); +} + +static void play_file(void) +{ + int ok; + + if (!strcmp(file_name, "-")) + file = stdin; + else + file = fopen(file_name, "rb"); + if (!file) { + errormsg("Cannot open %s - %s", file_name, strerror(errno)); + return; + } + + file_offset = 0; + ok = 0; + + switch (read_id()) { + case MAKE_ID('M', 'T', 'h', 'd'): + ok = read_smf(); + break; + case MAKE_ID('R', 'I', 'F', 'F'): + ok = read_riff(); + break; + default: + errormsg("%s is not a Standard MIDI File", file_name); + break; + } + + if (file != stdin) + fclose(file); + + if (ok) + play_midi(); + + cleanup_file_data(); +} + +static void list_ports(void) +{ + snd_seq_client_info_t *cinfo; + snd_seq_port_info_t *pinfo; + + snd_seq_client_info_alloca(&cinfo); + snd_seq_port_info_alloca(&pinfo); + + puts(" Port Client name Port name"); + + snd_seq_client_info_set_client(cinfo, -1); + while (snd_seq_query_next_client(seq, cinfo) >= 0) { + int client = snd_seq_client_info_get_client(cinfo); + + snd_seq_port_info_set_client(pinfo, client); + snd_seq_port_info_set_port(pinfo, -1); + while (snd_seq_query_next_port(seq, pinfo) >= 0) { + /* port must understand MIDI messages */ + if (!(snd_seq_port_info_get_type(pinfo) + & SND_SEQ_PORT_TYPE_MIDI_GENERIC)) + continue; + /* we need both WRITE and SUBS_WRITE */ + if ((snd_seq_port_info_get_capability(pinfo) + & (SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE)) + != (SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE)) + continue; + printf("%3d:%-3d %-32.32s %s\n", + snd_seq_port_info_get_client(pinfo), + snd_seq_port_info_get_port(pinfo), + snd_seq_client_info_get_name(cinfo), + snd_seq_port_info_get_name(pinfo)); + } + } +} + +static void usage(const char *argv0) +{ + printf( + "Usage: %s -p client:port[,...] [-d delay] midifile ...\n" + "-h, --help this help\n" + "-V, --version print current version\n" + "-l, --list list all possible output ports\n" + "-p, --port=client:port,... set port(s) to play to\n" + "-d, --delay=seconds delay after song ends\n", + argv0); +} + +static void version(void) +{ + puts("aplaymidi version " SND_UTIL_VERSION_STR); +} + +int main(int argc, char *argv[]) +{ + static const char short_options[] = "hVlp:d:"; + static const struct option long_options[] = { + {"help", 0, NULL, 'h'}, + {"version", 0, NULL, 'V'}, + {"list", 0, NULL, 'l'}, + {"port", 1, NULL, 'p'}, + {"delay", 1, NULL, 'd'}, + {} + }; + int c; + int do_list = 0; + + init_seq(); + + while ((c = getopt_long(argc, argv, short_options, + long_options, NULL)) != -1) { + switch (c) { + case 'h': + usage(argv[0]); + return 0; + case 'V': + version(); + return 0; + case 'l': + do_list = 1; + break; + case 'p': + parse_ports(optarg); + break; + case 'd': + end_delay = atoi(optarg); + break; + default: + usage(argv[0]); + return 1; + } + } + + if (do_list) { + list_ports(); + } else { + if (port_count < 1) { + /* use env var for compatibility with pmidi */ + const char *ports_str = getenv("ALSA_OUTPUT_PORTS"); + if (ports_str) + parse_ports(ports_str); + if (port_count < 1) { + errormsg("Please specify at least one port with --port."); + return 1; + } + } + if (optind >= argc) { + errormsg("Please specify a file to play."); + return 1; + } + + create_source_port(); + create_queue(); + connect_ports(); + + for (; optind < argc; ++optind) { + file_name = argv[optind]; + play_file(); + } + } + snd_seq_close(seq); + return 0; +} diff --git a/alsa-utils/seq/aplaymidi/arecordmidi.1 b/alsa-utils/seq/aplaymidi/arecordmidi.1 new file mode 100644 index 0000000..78b3a3a --- /dev/null +++ b/alsa-utils/seq/aplaymidi/arecordmidi.1 @@ -0,0 +1,82 @@ +.TH ARECORDMIDI 1 "17 Sep 2007" + +.SH NAME +arecordmidi \- record Standard MIDI Files + +.SH SYNOPSIS +.B arecordmidi +\-p client:port[,...] [options] midifile + +.SH DESCRIPTION +.B arecordmidi +is a command-line utility that records a Standard MIDI File from one or +more ALSA sequencer ports. + +To stop recording, press Ctrl+C. + +.SH OPTIONS + +.TP +.I \-h,\-\-help +Prints a list of options. + +.TP +.I \-V,\-\-version +Prints the current version. + +.TP +.I \-l,\-\-list +Prints a list of possible input ports. + +.TP +.I \-p,\-\-port=client:port,... +Sets the sequencer port(s) from which events are recorded. + +A client can be specified by its number, its name, or a prefix of its +name. A port is specified by its number; for port 0 of a client, the +":0" part of the port specification can be omitted. + +.TP +.I \-b,\-\-bpm=beats +Sets the musical tempo of the MIDI file, in beats per minute. +The default value is 120 BPM. + +.TP +.I \-f,\-\-fps=frames +Sets the SMPTE resolution, in frames per second. +Possible values are 24, 25, 29.97 (for 30 drop-frame), and 30. + +.TP +.I \-t,\-\-ticks=ticks +Sets the resolution of timestamps (ticks) in the MIDI file, +in ticks per beat (when using musical tempo) or ticks per frame +(when using SMPTE timing). +The default value is 384 ticks/beat or 40 ticks/frame, respectively. + +.TP +.I \-s,\-\-split\-channels +Specifies that the data for each MIDI channel should be written to a +separate track in the MIDI file. +This will result in a "format 1" file. +Otherwise, when there is only one track, +.B arecordmidi +will generate a "format 0" file. + +.TP +.I \-m,\-\-metronome=client:port +Plays a metronome signal on the specified sequencer port. + +Metronome sounds are played on channel 10, MIDI notes 33 & 34 (GM2/GS/XG +metronome standard notes), with velocity 100 and duration 1. + +.TP +.I \-i,\-\-timesig=numerator:denominator +Sets the time signature for the MIDI file and metronome. + +The time signature is specified as usual with two numbers, representing +the numerator and denominator of the time signature as it would be +notated. The denominator must be a power of two. Both numbers should be +separated by a colon. The time signature is 4:4 by default. + +.SH AUTHOR +Clemens Ladisch <clemens@ladisch.de> diff --git a/alsa-utils/seq/aplaymidi/arecordmidi.c b/alsa-utils/seq/aplaymidi/arecordmidi.c new file mode 100644 index 0000000..9628086 --- /dev/null +++ b/alsa-utils/seq/aplaymidi/arecordmidi.c @@ -0,0 +1,880 @@ +/* + * arecordmidi.c - record standard MIDI files from sequencer ports + * + * Copyright (c) 2004-2005 Clemens Ladisch <clemens@ladisch.de> + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* TODO: sequencer queue timer selection */ + +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <signal.h> +#include <getopt.h> +#include <sys/poll.h> +#include <alsa/asoundlib.h> +#include "aconfig.h" +#include "version.h" + +#define BUFFER_SIZE 4088 + +/* linked list of buffers, stores data as in the .mid file */ +struct buffer { + struct buffer *next; + unsigned char buf[BUFFER_SIZE]; +}; + +struct smf_track { + int size; /* size of entire data */ + int cur_buf_size; /* size of cur_buf */ + struct buffer *cur_buf; + snd_seq_tick_time_t last_tick; /* end of track */ + unsigned char last_command; /* used for running status */ + int used; /* anything record on this track */ + struct buffer first_buf; /* list head */ +}; + +/* timing/sysex + 16 channels */ +#define TRACKS_PER_PORT 17 + +/* metronome settings */ +/* TODO: create options for this */ +#define METRONOME_CHANNEL 9 +#define METRONOME_STRONG_NOTE 34 +#define METRONOME_WEAK_NOTE 33 +#define METRONOME_VELOCITY 100 +#define METRONOME_PROGRAM 0 + +static snd_seq_t *seq; +static int client; +static int port_count; +static snd_seq_addr_t *ports; +static int queue; +static int smpte_timing = 0; +static int beats = 120; +static int frames; +static int ticks = 0; +static FILE *file; +static int channel_split; +static int num_tracks; +static struct smf_track *tracks; +static volatile sig_atomic_t stop = 0; +static int use_metronome = 0; +static snd_seq_addr_t metronome_port; +static int metronome_weak_note = METRONOME_WEAK_NOTE; +static int metronome_strong_note = METRONOME_STRONG_NOTE; +static int metronome_velocity = METRONOME_VELOCITY; +static int metronome_program = METRONOME_PROGRAM; +static int metronome_channel = METRONOME_CHANNEL; +static int ts_num = 4; /* time signature: numerator */ +static int ts_div = 4; /* time signature: denominator */ +static int ts_dd = 2; /* time signature: denominator as a power of two */ + + +/* prints an error message to stderr, and dies */ +static void fatal(const char *msg, ...) +{ + va_list ap; + + va_start(ap, msg); + vfprintf(stderr, msg, ap); + va_end(ap); + fputc('\n', stderr); + exit(EXIT_FAILURE); +} + +/* memory allocation error handling */ +static void check_mem(void *p) +{ + if (!p) + fatal("Out of memory"); +} + +/* error handling for ALSA functions */ +static void check_snd(const char *operation, int err) +{ + if (err < 0) + fatal("Cannot %s - %s", operation, snd_strerror(err)); +} + +static void init_seq(void) +{ + int err; + + /* open sequencer */ + err = snd_seq_open(&seq, "default", SND_SEQ_OPEN_DUPLEX, 0); + check_snd("open sequencer", err); + + /* find out our client's id */ + client = snd_seq_client_id(seq); + check_snd("get client id", client); + + /* set our client's name */ + err = snd_seq_set_client_name(seq, "arecordmidi"); + check_snd("set client name", err); +} + +/* parses one or more port addresses from the string */ +static void parse_ports(const char *arg) +{ + char *buf, *s, *port_name; + int err; + + /* make a copy of the string because we're going to modify it */ + buf = strdup(arg); + check_mem(buf); + + for (port_name = s = buf; s; port_name = s + 1) { + /* Assume that ports are separated by commas. We don't use + * spaces because those are valid in client names. */ + s = strchr(port_name, ','); + if (s) + *s = '\0'; + + ++port_count; + ports = realloc(ports, port_count * sizeof(snd_seq_addr_t)); + check_mem(ports); + + err = snd_seq_parse_address(seq, &ports[port_count - 1], port_name); + if (err < 0) + fatal("Invalid port %s - %s", port_name, snd_strerror(err)); + } + + free(buf); +} + +/* parses the metronome port address */ +static void init_metronome(const char *arg) +{ + int err; + + err = snd_seq_parse_address(seq, &metronome_port, arg); + if (err < 0) + fatal("Invalid port %s - %s", arg, snd_strerror(err)); + use_metronome = 1; +} + +/* parses time signature specification */ +static void time_signature(const char *arg) +{ + long x = 0; + char *sep; + + x = strtol(arg, &sep, 10); + if (x < 1 || x > 64 || *sep != ':') + fatal("Invalid time signature (%s)", arg); + ts_num = x; + x = strtol(++sep, NULL, 10); + if (x < 1 || x > 64) + fatal("Invalid time signature (%s)", arg); + ts_div = x; + for (ts_dd = 0; x > 1; x /= 2) + ++ts_dd; +} + +/* + * Metronome implementation + */ +static void metronome_note(unsigned char note, unsigned int tick) +{ + snd_seq_event_t ev; + snd_seq_ev_clear(&ev); + snd_seq_ev_set_note(&ev, metronome_channel, note, metronome_velocity, 1); + snd_seq_ev_schedule_tick(&ev, queue, 0, tick); + snd_seq_ev_set_source(&ev, port_count); + snd_seq_ev_set_subs(&ev); + snd_seq_event_output(seq, &ev); +} + +static void metronome_echo(unsigned int tick) +{ + snd_seq_event_t ev; + snd_seq_ev_clear(&ev); + ev.type = SND_SEQ_EVENT_USR0; + snd_seq_ev_schedule_tick(&ev, queue, 0, tick); + snd_seq_ev_set_source(&ev, port_count); + snd_seq_ev_set_dest(&ev, client, port_count); + snd_seq_event_output(seq, &ev); +} + +static void metronome_pattern(unsigned int tick) +{ + int j, t, duration; + + t = tick; + duration = ticks * 4 / ts_div; + for (j = 0; j < ts_num; j++) { + metronome_note(j ? metronome_weak_note : metronome_strong_note, t); + t += duration; + } + metronome_echo(t); + snd_seq_drain_output(seq); +} + +static void metronome_set_program(void) +{ + snd_seq_event_t ev; + + snd_seq_ev_clear(&ev); + snd_seq_ev_set_pgmchange(&ev, metronome_channel, metronome_program); + snd_seq_ev_set_source(&ev, port_count); + snd_seq_ev_set_subs(&ev); + snd_seq_event_output(seq, &ev); +} + +static void init_tracks(void) +{ + int i; + + /* MIDI RP-019 says we need at least one track per port */ + num_tracks = port_count; + /* Allocate one track for each possible channel. + * Empty tracks won't be written to the file. */ + if (channel_split) + num_tracks *= TRACKS_PER_PORT; + + tracks = calloc(num_tracks, sizeof(struct smf_track)); + check_mem(tracks); + for (i = 0; i < num_tracks; ++i) + tracks[i].cur_buf = &tracks[i].first_buf; +} + +static void create_queue(void) +{ + snd_seq_queue_tempo_t *tempo; + int err; + + queue = snd_seq_alloc_named_queue(seq, "arecordmidi"); + check_snd("create queue", queue); + + snd_seq_queue_tempo_alloca(&tempo); + if (!smpte_timing) { + snd_seq_queue_tempo_set_tempo(tempo, 60000000 / beats); + snd_seq_queue_tempo_set_ppq(tempo, ticks); + } else { + /* + * ALSA doesn't know about the SMPTE time divisions, so + * we pretend to have a musical tempo with the equivalent + * number of ticks/s. + */ + switch (frames) { + case 24: + snd_seq_queue_tempo_set_tempo(tempo, 500000); + snd_seq_queue_tempo_set_ppq(tempo, 12 * ticks); + break; + case 25: + snd_seq_queue_tempo_set_tempo(tempo, 400000); + snd_seq_queue_tempo_set_ppq(tempo, 10 * ticks); + break; + case 29: + snd_seq_queue_tempo_set_tempo(tempo, 100000000); + snd_seq_queue_tempo_set_ppq(tempo, 2997 * ticks); + break; + case 30: + snd_seq_queue_tempo_set_tempo(tempo, 500000); + snd_seq_queue_tempo_set_ppq(tempo, 15 * ticks); + break; + default: + fatal("Invalid SMPTE frames %d", frames); + } + } + err = snd_seq_set_queue_tempo(seq, queue, tempo); + if (err < 0) + fatal("Cannot set queue tempo (%u/%i)", + snd_seq_queue_tempo_get_tempo(tempo), + snd_seq_queue_tempo_get_ppq(tempo)); +} + +static void create_ports(void) +{ + snd_seq_port_info_t *pinfo; + int i, err; + char name[32]; + + snd_seq_port_info_alloca(&pinfo); + + /* common information for all our ports */ + snd_seq_port_info_set_capability(pinfo, + SND_SEQ_PORT_CAP_WRITE | + SND_SEQ_PORT_CAP_SUBS_WRITE); + snd_seq_port_info_set_type(pinfo, + SND_SEQ_PORT_TYPE_MIDI_GENERIC | + SND_SEQ_PORT_TYPE_APPLICATION); + snd_seq_port_info_set_midi_channels(pinfo, 16); + + /* we want to know when the events got delivered to us */ + snd_seq_port_info_set_timestamping(pinfo, 1); + snd_seq_port_info_set_timestamp_queue(pinfo, queue); + + /* our port number is the same as our port index */ + snd_seq_port_info_set_port_specified(pinfo, 1); + for (i = 0; i < port_count; ++i) { + snd_seq_port_info_set_port(pinfo, i); + + sprintf(name, "arecordmidi port %i", i); + snd_seq_port_info_set_name(pinfo, name); + + err = snd_seq_create_port(seq, pinfo); + check_snd("create port", err); + } + + /* create an optional metronome port */ + if (use_metronome) { + snd_seq_port_info_set_port(pinfo, port_count); + snd_seq_port_info_set_name(pinfo, "arecordmidi metronome"); + snd_seq_port_info_set_capability(pinfo, + SND_SEQ_PORT_CAP_READ | + SND_SEQ_PORT_CAP_WRITE); + snd_seq_port_info_set_type(pinfo, SND_SEQ_PORT_TYPE_APPLICATION); + snd_seq_port_info_set_midi_channels(pinfo, 0); + snd_seq_port_info_set_timestamping(pinfo, 0); + err = snd_seq_create_port(seq, pinfo); + check_snd("create metronome port", err); + } +} + +static void connect_ports(void) +{ + int i, err; + + for (i = 0; i < port_count; ++i) { + err = snd_seq_connect_from(seq, i, ports[i].client, ports[i].port); + if (err < 0) + fatal("Cannot connect from port %d:%d - %s", + ports[i].client, ports[i].port, snd_strerror(err)); + } + + /* subscribe the metronome port */ + if (use_metronome) { + err = snd_seq_connect_to(seq, port_count, metronome_port.client, metronome_port.port); + if (err < 0) + fatal("Cannot connect to port %d:%d - %s", + metronome_port.client, metronome_port.port, snd_strerror(err)); + } +} + +/* records a byte to be written to the .mid file */ +static void add_byte(struct smf_track *track, unsigned char byte) +{ + /* make sure we have enough room in the current buffer */ + if (track->cur_buf_size >= BUFFER_SIZE) { + track->cur_buf->next = calloc(1, sizeof(struct buffer)); + if (!track->cur_buf->next) + fatal("out of memory"); + track->cur_buf = track->cur_buf->next; + track->cur_buf_size = 0; + } + + track->cur_buf->buf[track->cur_buf_size++] = byte; + track->size++; +} + +/* record a variable-length quantity */ +static void var_value(struct smf_track *track, int v) +{ + if (v >= (1 << 28)) + add_byte(track, 0x80 | ((v >> 28) & 0x03)); + if (v >= (1 << 21)) + add_byte(track, 0x80 | ((v >> 21) & 0x7f)); + if (v >= (1 << 14)) + add_byte(track, 0x80 | ((v >> 14) & 0x7f)); + if (v >= (1 << 7)) + add_byte(track, 0x80 | ((v >> 7) & 0x7f)); + add_byte(track, v & 0x7f); +} + +/* record the delta time from the last event */ +static void delta_time(struct smf_track *track, const snd_seq_event_t *ev) +{ + int diff = ev->time.tick - track->last_tick; + if (diff < 0) + diff = 0; + var_value(track, diff); + track->last_tick = ev->time.tick; +} + +/* record a status byte (or not if we can use running status) */ +static void command(struct smf_track *track, unsigned char cmd) +{ + if (cmd != track->last_command) + add_byte(track, cmd); + track->last_command = cmd < 0xf0 ? cmd : 0; +} + +/* put port numbers into all tracks */ +static void record_port_numbers(void) +{ + int i; + + for (i = 0; i < num_tracks; ++i) { + var_value(&tracks[i], 0); + add_byte(&tracks[i], 0xff); + add_byte(&tracks[i], 0x21); + var_value(&tracks[i], 1); + if (channel_split) + add_byte(&tracks[i], i / TRACKS_PER_PORT); + else + add_byte(&tracks[i], i); + } +} + +static void record_event(const snd_seq_event_t *ev) +{ + unsigned int i; + struct smf_track *track; + + /* ignore events without proper timestamps */ + if (ev->queue != queue || !snd_seq_ev_is_tick(ev)) + return; + + /* determine which track to record to */ + i = ev->dest.port; + if (i == port_count) { + if (ev->type == SND_SEQ_EVENT_USR0) + metronome_pattern(ev->time.tick); + return; + } + if (channel_split) { + i *= TRACKS_PER_PORT; + if (snd_seq_ev_is_channel_type(ev)) + i += 1 + (ev->data.note.channel & 0xf); + } + if (i >= num_tracks) + return; + track = &tracks[i]; + + switch (ev->type) { + case SND_SEQ_EVENT_NOTEON: + delta_time(track, ev); + command(track, MIDI_CMD_NOTE_ON | (ev->data.note.channel & 0xf)); + add_byte(track, ev->data.note.note & 0x7f); + add_byte(track, ev->data.note.velocity & 0x7f); + break; + case SND_SEQ_EVENT_NOTEOFF: + delta_time(track, ev); + command(track, MIDI_CMD_NOTE_OFF | (ev->data.note.channel & 0xf)); + add_byte(track, ev->data.note.note & 0x7f); + add_byte(track, ev->data.note.velocity & 0x7f); + break; + case SND_SEQ_EVENT_KEYPRESS: + delta_time(track, ev); + command(track, MIDI_CMD_NOTE_PRESSURE | (ev->data.note.channel & 0xf)); + add_byte(track, ev->data.note.note & 0x7f); + add_byte(track, ev->data.note.velocity & 0x7f); + break; + case SND_SEQ_EVENT_CONTROLLER: + delta_time(track, ev); + command(track, MIDI_CMD_CONTROL | (ev->data.control.channel & 0xf)); + add_byte(track, ev->data.control.param & 0x7f); + add_byte(track, ev->data.control.value & 0x7f); + break; + case SND_SEQ_EVENT_PGMCHANGE: + delta_time(track, ev); + command(track, MIDI_CMD_PGM_CHANGE | (ev->data.control.channel & 0xf)); + add_byte(track, ev->data.control.value & 0x7f); + break; + case SND_SEQ_EVENT_CHANPRESS: + delta_time(track, ev); + command(track, MIDI_CMD_CHANNEL_PRESSURE | (ev->data.control.channel & 0xf)); + add_byte(track, ev->data.control.value & 0x7f); + break; + case SND_SEQ_EVENT_PITCHBEND: + delta_time(track, ev); + command(track, MIDI_CMD_BENDER | (ev->data.control.channel & 0xf)); + add_byte(track, (ev->data.control.value + 8192) & 0x7f); + add_byte(track, ((ev->data.control.value + 8192) >> 7) & 0x7f); + break; + case SND_SEQ_EVENT_CONTROL14: + /* create two commands for MSB and LSB */ + delta_time(track, ev); + command(track, MIDI_CMD_CONTROL | (ev->data.control.channel & 0xf)); + add_byte(track, ev->data.control.param & 0x7f); + add_byte(track, (ev->data.control.value >> 7) & 0x7f); + if ((ev->data.control.param & 0x7f) < 0x20) { + delta_time(track, ev); + /* running status */ + add_byte(track, (ev->data.control.param & 0x7f) + 0x20); + add_byte(track, ev->data.control.value & 0x7f); + } + break; + case SND_SEQ_EVENT_NONREGPARAM: + delta_time(track, ev); + command(track, MIDI_CMD_CONTROL | (ev->data.control.channel & 0xf)); + add_byte(track, MIDI_CTL_NONREG_PARM_NUM_LSB); + add_byte(track, ev->data.control.param & 0x7f); + delta_time(track, ev); + add_byte(track, MIDI_CTL_NONREG_PARM_NUM_MSB); + add_byte(track, (ev->data.control.param >> 7) & 0x7f); + delta_time(track, ev); + add_byte(track, MIDI_CTL_MSB_DATA_ENTRY); + add_byte(track, (ev->data.control.value >> 7) & 0x7f); + delta_time(track, ev); + add_byte(track, MIDI_CTL_LSB_DATA_ENTRY); + add_byte(track, ev->data.control.value & 0x7f); + break; + case SND_SEQ_EVENT_REGPARAM: + delta_time(track, ev); + command(track, MIDI_CMD_CONTROL | (ev->data.control.channel & 0xf)); + add_byte(track, MIDI_CTL_REGIST_PARM_NUM_LSB); + add_byte(track, ev->data.control.param & 0x7f); + delta_time(track, ev); + add_byte(track, MIDI_CTL_REGIST_PARM_NUM_MSB); + add_byte(track, (ev->data.control.param >> 7) & 0x7f); + delta_time(track, ev); + add_byte(track, MIDI_CTL_MSB_DATA_ENTRY); + add_byte(track, (ev->data.control.value >> 7) & 0x7f); + delta_time(track, ev); + add_byte(track, MIDI_CTL_LSB_DATA_ENTRY); + add_byte(track, ev->data.control.value & 0x7f); + break; +#if 0 /* ignore */ + case SND_SEQ_EVENT_SONGPOS: + case SND_SEQ_EVENT_SONGSEL: + case SND_SEQ_EVENT_QFRAME: + case SND_SEQ_EVENT_START: + case SND_SEQ_EVENT_CONTINUE: + case SND_SEQ_EVENT_STOP: + case SND_SEQ_EVENT_TUNE_REQUEST: + case SND_SEQ_EVENT_RESET: + case SND_SEQ_EVENT_SENSING: + break; +#endif + case SND_SEQ_EVENT_SYSEX: + if (ev->data.ext.len == 0) + break; + delta_time(track, ev); + if (*(unsigned char*)ev->data.ext.ptr == 0xf0) + command(track, 0xf0), i = 1; + else + command(track, 0xf7), i = 0; + var_value(track, ev->data.ext.len - i); + for (; i < ev->data.ext.len; ++i) + add_byte(track, ((unsigned char*)ev->data.ext.ptr)[i]); + break; + default: + return; + } + track->used = 1; +} + +static void finish_tracks(void) +{ + snd_seq_queue_status_t *queue_status; + int tick, i, err; + + snd_seq_queue_status_alloca(&queue_status); + + err = snd_seq_get_queue_status(seq, queue, queue_status); + check_snd("get queue status", err); + tick = snd_seq_queue_status_get_tick_time(queue_status); + + /* make length of first track the recording length */ + var_value(&tracks[0], tick - tracks[0].last_tick); + add_byte(&tracks[0], 0xff); + add_byte(&tracks[0], 0x2f); + var_value(&tracks[0], 0); + + /* finish other tracks */ + for (i = 1; i < num_tracks; ++i) { + var_value(&tracks[i], 0); + add_byte(&tracks[i], 0xff); + add_byte(&tracks[i], 0x2f); + var_value(&tracks[i], 0); + } +} + +static void write_file(void) +{ + int used_tracks, time_division, i; + struct buffer *buf; + + used_tracks = 0; + for (i = 0; i < num_tracks; ++i) + used_tracks += !!tracks[i].used; + + /* header id and length */ + fwrite("MThd\0\0\0\6", 1, 8, file); + /* type 0 or 1 */ + fputc(0, file); + fputc(used_tracks > 1, file); + /* number of tracks */ + fputc((used_tracks >> 8) & 0xff, file); + fputc(used_tracks & 0xff, file); + /* time division */ + time_division = ticks; + if (smpte_timing) + time_division |= (0x100 - frames) << 8; + fputc(time_division >> 8, file); + fputc(time_division & 0xff, file); + + for (i = 0; i < num_tracks; ++i) { + if (!tracks[i].used) + continue; + /* track id */ + fwrite("MTrk", 1, 4, file); + /* data length */ + fputc((tracks[i].size >> 24) & 0xff, file); + fputc((tracks[i].size >> 16) & 0xff, file); + fputc((tracks[i].size >> 8) & 0xff, file); + fputc(tracks[i].size & 0xff, file); + /* track contents */ + for (buf = &tracks[i].first_buf; buf; buf = buf->next) + fwrite(buf->buf, 1, buf == tracks[i].cur_buf + ? tracks[i].cur_buf_size : BUFFER_SIZE, file); + } +} + +static void list_ports(void) +{ + snd_seq_client_info_t *cinfo; + snd_seq_port_info_t *pinfo; + + snd_seq_client_info_alloca(&cinfo); + snd_seq_port_info_alloca(&pinfo); + + puts(" Port Client name Port name"); + + snd_seq_client_info_set_client(cinfo, -1); + while (snd_seq_query_next_client(seq, cinfo) >= 0) { + int client = snd_seq_client_info_get_client(cinfo); + + if (client == SND_SEQ_CLIENT_SYSTEM) + continue; /* don't show system timer and announce ports */ + snd_seq_port_info_set_client(pinfo, client); + snd_seq_port_info_set_port(pinfo, -1); + while (snd_seq_query_next_port(seq, pinfo) >= 0) { + /* port must understand MIDI messages */ + if (!(snd_seq_port_info_get_type(pinfo) + & SND_SEQ_PORT_TYPE_MIDI_GENERIC)) + continue; + /* we need both READ and SUBS_READ */ + if ((snd_seq_port_info_get_capability(pinfo) + & (SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ)) + != (SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ)) + continue; + printf("%3d:%-3d %-32.32s %s\n", + snd_seq_port_info_get_client(pinfo), + snd_seq_port_info_get_port(pinfo), + snd_seq_client_info_get_name(cinfo), + snd_seq_port_info_get_name(pinfo)); + } + } +} + +static void help(const char *argv0) +{ + fprintf(stderr, "Usage: %s [options] outputfile\n" + "\nAvailable options:\n" + " -h,--help this help\n" + " -V,--version show version\n" + " -l,--list list input ports\n" + " -p,--port=client:port,... source port(s)\n" + " -b,--bpm=beats tempo in beats per minute\n" + " -f,--fps=frames resolution in frames per second (SMPTE)\n" + " -t,--ticks=ticks resolution in ticks per beat or frame\n" + " -s,--split-channels create a track for each channel\n" + " -m,--metronome=client:port play a metronome signal\n" + " -i,--timesig=nn:dd time signature\n", + argv0); +} + +static void version(void) +{ + fputs("arecordmidi version " SND_UTIL_VERSION_STR "\n", stderr); +} + +static void sighandler(int sig) +{ + stop = 1; +} + +int main(int argc, char *argv[]) +{ + static const char short_options[] = "hVlp:b:f:t:sdm:i:"; + static const struct option long_options[] = { + {"help", 0, NULL, 'h'}, + {"version", 0, NULL, 'V'}, + {"list", 0, NULL, 'l'}, + {"port", 1, NULL, 'p'}, + {"bpm", 1, NULL, 'b'}, + {"fps", 1, NULL, 'f'}, + {"ticks", 1, NULL, 't'}, + {"split-channels", 0, NULL, 's'}, + {"dump", 0, NULL, 'd'}, + {"metronome", 1, NULL, 'm'}, + {"timesig", 1, NULL, 'i'}, + { } + }; + + char *filename = NULL; + int do_list = 0; + struct pollfd *pfds; + int npfds; + int c, err; + + init_seq(); + + while ((c = getopt_long(argc, argv, short_options, + long_options, NULL)) != -1) { + switch (c) { + case 'h': + help(argv[0]); + return 0; + case 'V': + version(); + return 0; + case 'l': + do_list = 1; + break; + case 'p': + parse_ports(optarg); + break; + case 'b': + beats = atoi(optarg); + if (beats < 4 || beats > 6000) + fatal("Invalid tempo"); + smpte_timing = 0; + break; + case 'f': + frames = atoi(optarg); + if (frames != 24 && frames != 25 && + frames != 29 && frames != 30) + fatal("Invalid number of frames/s"); + smpte_timing = 1; + break; + case 't': + ticks = atoi(optarg); + if (ticks < 1 || ticks > 0x7fff) + fatal("Invalid number of ticks"); + break; + case 's': + channel_split = 1; + break; + case 'd': + fputs("The --dump option isn't supported anymore, use aseqdump instead.\n", stderr); + break; + case 'm': + init_metronome(optarg); + break; + case 'i': + time_signature(optarg); + break; + default: + help(argv[0]); + return 1; + } + } + + if (do_list) { + list_ports(); + return 0; + } + + if (port_count < 1) { + fputs("Pleast specify a source port with --port.\n", stderr); + return 1; + } + + if (!ticks) + ticks = smpte_timing ? 40 : 384; + if (smpte_timing && ticks > 0xff) + ticks = 0xff; + + if (optind >= argc) { + fputs("Please specify a file to record to.\n", stderr); + return 1; + } + filename = argv[optind]; + + init_tracks(); + create_queue(); + create_ports(); + connect_ports(); + if (port_count > 1) + record_port_numbers(); + + /* record tempo */ + if (!smpte_timing) { + int usecs_per_quarter = 60000000 / beats; + var_value(&tracks[0], 0); /* delta time */ + add_byte(&tracks[0], 0xff); + add_byte(&tracks[0], 0x51); + var_value(&tracks[0], 3); + add_byte(&tracks[0], usecs_per_quarter >> 16); + add_byte(&tracks[0], usecs_per_quarter >> 8); + add_byte(&tracks[0], usecs_per_quarter); + + /* time signature */ + var_value(&tracks[0], 0); /* delta time */ + add_byte(&tracks[0], 0xff); + add_byte(&tracks[0], 0x58); + var_value(&tracks[0], 4); + add_byte(&tracks[0], ts_num); + add_byte(&tracks[0], ts_dd); + add_byte(&tracks[0], 24); /* MIDI clocks per metronome click */ + add_byte(&tracks[0], 8); /* notated 32nd-notes per MIDI quarter note */ + } + + /* always write at least one track */ + tracks[0].used = 1; + + file = fopen(filename, "wb"); + if (!file) + fatal("Cannot open %s - %s", filename, strerror(errno)); + + err = snd_seq_start_queue(seq, queue, NULL); + check_snd("start queue", err); + snd_seq_drain_output(seq); + + err = snd_seq_nonblock(seq, 1); + check_snd("set nonblock mode", err); + + if (use_metronome) { + metronome_set_program(); + metronome_pattern(0); + } + + signal(SIGINT, sighandler); + signal(SIGTERM, sighandler); + + npfds = snd_seq_poll_descriptors_count(seq, POLLIN); + pfds = alloca(sizeof(*pfds) * npfds); + for (;;) { + snd_seq_poll_descriptors(seq, pfds, npfds, POLLIN); + if (poll(pfds, npfds, -1) < 0) + break; + do { + snd_seq_event_t *event; + err = snd_seq_event_input(seq, &event); + if (err < 0) + break; + if (event) + record_event(event); + } while (err > 0); + if (stop) + break; + } + + finish_tracks(); + write_file(); + + fclose(file); + snd_seq_close(seq); + return 0; +} diff --git a/alsa-utils/seq/aseqdump/Makefile.am b/alsa-utils/seq/aseqdump/Makefile.am new file mode 100644 index 0000000..d918d9f --- /dev/null +++ b/alsa-utils/seq/aseqdump/Makefile.am @@ -0,0 +1,5 @@ +INCLUDES = -I$(top_srcdir)/include +EXTRA_DIST = aseqdump.1 + +bin_PROGRAMS = aseqdump +man_MANS = aseqdump.1 diff --git a/alsa-utils/seq/aseqdump/Makefile.in b/alsa-utils/seq/aseqdump/Makefile.in new file mode 100644 index 0000000..f2971a5 --- /dev/null +++ b/alsa-utils/seq/aseqdump/Makefile.in @@ -0,0 +1,498 @@ +# Makefile.in generated by automake 1.9.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005 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@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = ../.. +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +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@ +bin_PROGRAMS = aseqdump$(EXEEXT) +subdir = seq/aseqdump +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/include/aconfig.h +CONFIG_CLEAN_FILES = +am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)" +binPROGRAMS_INSTALL = $(INSTALL_PROGRAM) +PROGRAMS = $(bin_PROGRAMS) +aseqdump_SOURCES = aseqdump.c +aseqdump_OBJECTS = aseqdump.$(OBJEXT) +aseqdump_LDADD = $(LDADD) +DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)/include +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +SOURCES = aseqdump.c +DIST_SOURCES = aseqdump.c +man1dir = $(mandir)/man1 +NROFF = nroff +MANS = $(man_MANS) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALSACONF_FALSE = @ALSACONF_FALSE@ +ALSACONF_TRUE = @ALSACONF_TRUE@ +ALSAMIXER_FALSE = @ALSAMIXER_FALSE@ +ALSAMIXER_TRUE = @ALSAMIXER_TRUE@ +ALSA_CFLAGS = @ALSA_CFLAGS@ +ALSA_LIBS = @ALSA_LIBS@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CURSESINC = @CURSESINC@ +CURSESLIB = @CURSESLIB@ +CURSES_CFLAGS = @CURSES_CFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GREP = @GREP@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LN_S = @LN_S@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +POSUB = @POSUB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SND_UTIL_MAJOR = @SND_UTIL_MAJOR@ +SND_UTIL_MINOR = @SND_UTIL_MINOR@ +SND_UTIL_SUBMINOR = @SND_UTIL_SUBMINOR@ +SND_UTIL_VERSION = @SND_UTIL_VERSION@ +STRIP = @STRIP@ +TESTSOUND = @TESTSOUND@ +USE_NLS = @USE_NLS@ +USE_XMLTO_FALSE = @USE_XMLTO_FALSE@ +USE_XMLTO_TRUE = @USE_XMLTO_TRUE@ +VERSION = @VERSION@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +ac_ct_CC = @ac_ct_CC@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +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@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +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@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +ncurses5_config = @ncurses5_config@ +ncursesw5_config = @ncursesw5_config@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +xmlto = @xmlto@ +INCLUDES = -I$(top_srcdir)/include +EXTRA_DIST = aseqdump.1 +man_MANS = aseqdump.1 +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign seq/aseqdump/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --foreign seq/aseqdump/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 +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + test -z "$(bindir)" || $(mkdir_p) "$(DESTDIR)$(bindir)" + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + if test -f $$p \ + ; then \ + f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \ + $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \ + else :; fi; \ + done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \ + rm -f "$(DESTDIR)$(bindir)/$$f"; \ + done + +clean-binPROGRAMS: + -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) +aseqdump$(EXEEXT): $(aseqdump_OBJECTS) $(aseqdump_DEPENDENCIES) + @rm -f aseqdump$(EXEEXT) + $(LINK) $(aseqdump_LDFLAGS) $(aseqdump_OBJECTS) $(aseqdump_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/aseqdump.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \ +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` +uninstall-info-am: +install-man1: $(man1_MANS) $(man_MANS) + @$(NORMAL_INSTALL) + test -z "$(man1dir)" || $(mkdir_p) "$(DESTDIR)$(man1dir)" + @list='$(man1_MANS) $(dist_man1_MANS) $(nodist_man1_MANS)'; \ + l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ + for i in $$l2; do \ + case "$$i" in \ + *.1*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \ + else file=$$i; fi; \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + case "$$ext" in \ + 1*) ;; \ + *) ext='1' ;; \ + esac; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed -e 's/^.*\///'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \ + $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst"; \ + done +uninstall-man1: + @$(NORMAL_UNINSTALL) + @list='$(man1_MANS) $(dist_man1_MANS) $(nodist_man1_MANS)'; \ + l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ + for i in $$l2; do \ + case "$$i" in \ + *.1*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + case "$$ext" in \ + 1*) ;; \ + *) ext='1' ;; \ + esac; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed -e 's/^.*\///'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " rm -f '$(DESTDIR)$(man1dir)/$$inst'"; \ + rm -f "$(DESTDIR)$(man1dir)/$$inst"; \ + done + +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; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + 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; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + 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; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && 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)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkdir_p) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$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: check-am +all-am: Makefile $(PROGRAMS) $(MANS) +installdirs: + for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)"; do \ + test -z "$$dir" || $(mkdir_p) "$$dir"; \ + done +install: 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: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-binPROGRAMS clean-generic 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 + +info: info-am + +info-am: + +install-data-am: install-man + +install-exec-am: install-binPROGRAMS + +install-info: install-info-am + +install-man: install-man1 + +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 + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-binPROGRAMS uninstall-info-am uninstall-man + +uninstall-man: uninstall-man1 + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ + clean-generic ctags distclean distclean-compile \ + distclean-generic distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-binPROGRAMS \ + install-data install-data-am install-exec install-exec-am \ + install-info install-info-am install-man install-man1 \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-binPROGRAMS \ + uninstall-info-am uninstall-man uninstall-man1 + +# 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/alsa-utils/seq/aseqdump/aseqdump.1 b/alsa-utils/seq/aseqdump/aseqdump.1 new file mode 100644 index 0000000..f6f2aa9 --- /dev/null +++ b/alsa-utils/seq/aseqdump/aseqdump.1 @@ -0,0 +1,39 @@ +.TH ASEQDUMP 1 "19 Feb 2005" + +.SH NAME +aseqdump \- show the events received at an ALSA sequencer port + +.SH SYNOPSIS +.B aseqdump +[\fI\-p client:port,...\fP] + +.SH DESCRIPTION +.B aseqdump +is a command-line utility that prints the sequencer events it receives as text. + +To stop receiving, press Ctrl+C. + +.SH OPTIONS + +.TP +.I \-h,\-\-help +Prints a list of options. + +.TP +.I \-V,\-\-version +Prints the current version. + +.TP +.I \-l,\-\-list +Prints a list of possible input ports. + +.TP +.I \-p,\-\-port=client:port,... +Sets the sequencer port(s) from which events are received. + +A client can be specified by its number, its name, or a prefix of its +name. A port is specified by its number; for port 0 of a client, the +":0" part of the port specification can be omitted. + +.SH AUTHOR +Clemens Ladisch <clemens@ladisch.de> diff --git a/alsa-utils/seq/aseqdump/aseqdump.c b/alsa-utils/seq/aseqdump/aseqdump.c new file mode 100644 index 0000000..24c5d21 --- /dev/null +++ b/alsa-utils/seq/aseqdump/aseqdump.c @@ -0,0 +1,438 @@ +/* + * aseqdump.c - show the events received at an ALSA sequencer port + * + * Copyright (c) 2005 Clemens Ladisch <clemens@ladisch.de> + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <signal.h> +#include <getopt.h> +#include <sys/poll.h> +#include <alsa/asoundlib.h> +#include "aconfig.h" +#include "version.h" + +static snd_seq_t *seq; +static int port_count; +static snd_seq_addr_t *ports; +static volatile sig_atomic_t stop = 0; + + +/* prints an error message to stderr, and dies */ +static void fatal(const char *msg, ...) +{ + va_list ap; + + va_start(ap, msg); + vfprintf(stderr, msg, ap); + va_end(ap); + fputc('\n', stderr); + exit(EXIT_FAILURE); +} + +/* memory allocation error handling */ +static void check_mem(void *p) +{ + if (!p) + fatal("Out of memory"); +} + +/* error handling for ALSA functions */ +static void check_snd(const char *operation, int err) +{ + if (err < 0) + fatal("Cannot %s - %s", operation, snd_strerror(err)); +} + +static void init_seq(void) +{ + int err; + + /* open sequencer */ + err = snd_seq_open(&seq, "default", SND_SEQ_OPEN_DUPLEX, 0); + check_snd("open sequencer", err); + + /* set our client's name */ + err = snd_seq_set_client_name(seq, "aseqdump"); + check_snd("set client name", err); +} + +/* parses one or more port addresses from the string */ +static void parse_ports(const char *arg) +{ + char *buf, *s, *port_name; + int err; + + /* make a copy of the string because we're going to modify it */ + buf = strdup(arg); + check_mem(buf); + + for (port_name = s = buf; s; port_name = s + 1) { + /* Assume that ports are separated by commas. We don't use + * spaces because those are valid in client names. */ + s = strchr(port_name, ','); + if (s) + *s = '\0'; + + ++port_count; + ports = realloc(ports, port_count * sizeof(snd_seq_addr_t)); + check_mem(ports); + + err = snd_seq_parse_address(seq, &ports[port_count - 1], port_name); + if (err < 0) + fatal("Invalid port %s - %s", port_name, snd_strerror(err)); + } + + free(buf); +} + +static void create_port(void) +{ + int err; + + err = snd_seq_create_simple_port(seq, "aseqdump", + SND_SEQ_PORT_CAP_WRITE | + SND_SEQ_PORT_CAP_SUBS_WRITE, + SND_SEQ_PORT_TYPE_MIDI_GENERIC | + SND_SEQ_PORT_TYPE_APPLICATION); + check_snd("create port", err); +} + +static void connect_ports(void) +{ + int i, err; + + for (i = 0; i < port_count; ++i) { + err = snd_seq_connect_from(seq, 0, ports[i].client, ports[i].port); + if (err < 0) + fatal("Cannot connect from port %d:%d - %s", + ports[i].client, ports[i].port, snd_strerror(err)); + } +} + +static void dump_event(const snd_seq_event_t *ev) +{ + printf("%3d:%-3d ", ev->source.client, ev->source.port); + switch (ev->type) { + case SND_SEQ_EVENT_NOTEON: + if (ev->data.note.velocity) + printf("Note on %2d, note %d, velocity %d\n", + ev->data.note.channel, ev->data.note.note, ev->data.note.velocity); + else + printf("Note off %2d, note %d\n", + ev->data.note.channel, ev->data.note.note); + break; + case SND_SEQ_EVENT_NOTEOFF: + printf("Note off %2d, note %d, velocity %d\n", + ev->data.note.channel, ev->data.note.note, ev->data.note.velocity); + break; + case SND_SEQ_EVENT_KEYPRESS: + printf("Polyphonic aftertouch %2d, note %d, value %d\n", + ev->data.note.channel, ev->data.note.note, ev->data.note.velocity); + break; + case SND_SEQ_EVENT_CONTROLLER: + printf("Control change %2d, controller %d, value %d\n", + ev->data.control.channel, ev->data.control.param, ev->data.control.value); + break; + case SND_SEQ_EVENT_PGMCHANGE: + printf("Program change %2d, program %d\n", + ev->data.control.channel, ev->data.control.value); + break; + case SND_SEQ_EVENT_CHANPRESS: + printf("Channel aftertouch %2d, value %d\n", + ev->data.control.channel, ev->data.control.value); + break; + case SND_SEQ_EVENT_PITCHBEND: + printf("Pitch bend %2d, value %d\n", + ev->data.control.channel, ev->data.control.value); + break; + case SND_SEQ_EVENT_CONTROL14: + printf("Control change %2d, controller %d, value %5d\n", + ev->data.control.channel, ev->data.control.param, ev->data.control.value); + break; + case SND_SEQ_EVENT_NONREGPARAM: + printf("Non-reg. parameter %2d, parameter %d, value %d\n", + ev->data.control.channel, ev->data.control.param, ev->data.control.value); + break; + case SND_SEQ_EVENT_REGPARAM: + printf("Reg. parameter %2d, parameter %d, value %d\n", + ev->data.control.channel, ev->data.control.param, ev->data.control.value); + break; + case SND_SEQ_EVENT_SONGPOS: + printf("Song position pointer value %d\n", + ev->data.control.value); + break; + case SND_SEQ_EVENT_SONGSEL: + printf("Song select value %d\n", + ev->data.control.value); + break; + case SND_SEQ_EVENT_QFRAME: + printf("MTC quarter frame %02xh\n", + ev->data.control.value); + break; + case SND_SEQ_EVENT_TIMESIGN: + // XXX how is this encoded? + printf("SMF time signature (%#010x)\n", + ev->data.control.value); + break; + case SND_SEQ_EVENT_KEYSIGN: + // XXX how is this encoded? + printf("SMF key signature (%#010x)\n", + ev->data.control.value); + break; + case SND_SEQ_EVENT_START: + if (ev->source.client == SND_SEQ_CLIENT_SYSTEM && + ev->source.port == SND_SEQ_PORT_SYSTEM_TIMER) + printf("Queue start queue %d\n", + ev->data.queue.queue); + else + printf("Start\n"); + break; + case SND_SEQ_EVENT_CONTINUE: + if (ev->source.client == SND_SEQ_CLIENT_SYSTEM && + ev->source.port == SND_SEQ_PORT_SYSTEM_TIMER) + printf("Queue continue queue %d\n", + ev->data.queue.queue); + else + printf("Continue\n"); + break; + case SND_SEQ_EVENT_STOP: + if (ev->source.client == SND_SEQ_CLIENT_SYSTEM && + ev->source.port == SND_SEQ_PORT_SYSTEM_TIMER) + printf("Queue stop queue %d\n", + ev->data.queue.queue); + else + printf("Stop\n"); + break; + case SND_SEQ_EVENT_SETPOS_TICK: + printf("Set tick queue pos. queue %d\n", ev->data.queue.queue); + break; + case SND_SEQ_EVENT_SETPOS_TIME: + printf("Set rt queue pos. queue %d\n", ev->data.queue.queue); + break; + case SND_SEQ_EVENT_TEMPO: + printf("Set queue tempo queue %d\n", ev->data.queue.queue); + break; + case SND_SEQ_EVENT_CLOCK: + printf("Clock\n"); + break; + case SND_SEQ_EVENT_TICK: + printf("Tick\n"); + break; + case SND_SEQ_EVENT_QUEUE_SKEW: + printf("Queue timer skew queue %d\n", ev->data.queue.queue); + break; + case SND_SEQ_EVENT_TUNE_REQUEST: + printf("Tune request\n"); + break; + case SND_SEQ_EVENT_RESET: + printf("Reset\n"); + break; + case SND_SEQ_EVENT_SENSING: + printf("Active Sensing\n"); + break; + case SND_SEQ_EVENT_CLIENT_START: + printf("Client start client %d\n", + ev->data.addr.client); + break; + case SND_SEQ_EVENT_CLIENT_EXIT: + printf("Client exit client %d\n", + ev->data.addr.client); + break; + case SND_SEQ_EVENT_CLIENT_CHANGE: + printf("Client changed client %d\n", + ev->data.addr.client); + break; + case SND_SEQ_EVENT_PORT_START: + printf("Port start %d:%d\n", + ev->data.addr.client, ev->data.addr.port); + break; + case SND_SEQ_EVENT_PORT_EXIT: + printf("Port exit %d:%d\n", + ev->data.addr.client, ev->data.addr.port); + break; + case SND_SEQ_EVENT_PORT_CHANGE: + printf("Port changed %d:%d\n", + ev->data.addr.client, ev->data.addr.port); + break; + case SND_SEQ_EVENT_PORT_SUBSCRIBED: + printf("Port subscribed %d:%d -> %d:%d\n", + ev->data.connect.sender.client, ev->data.connect.sender.port, + ev->data.connect.dest.client, ev->data.connect.dest.port); + break; + case SND_SEQ_EVENT_PORT_UNSUBSCRIBED: + printf("Port unsubscribed %d:%d -> %d:%d\n", + ev->data.connect.sender.client, ev->data.connect.sender.port, + ev->data.connect.dest.client, ev->data.connect.dest.port); + break; + case SND_SEQ_EVENT_SYSEX: + { + unsigned int i; + printf("System exclusive "); + for (i = 0; i < ev->data.ext.len; ++i) + printf(" %02X", ((unsigned char*)ev->data.ext.ptr)[i]); + printf("\n"); + } + break; + default: + printf("Event type %d\n", ev->type); + } +} + +static void list_ports(void) +{ + snd_seq_client_info_t *cinfo; + snd_seq_port_info_t *pinfo; + + snd_seq_client_info_alloca(&cinfo); + snd_seq_port_info_alloca(&pinfo); + + puts(" Port Client name Port name"); + + snd_seq_client_info_set_client(cinfo, -1); + while (snd_seq_query_next_client(seq, cinfo) >= 0) { + int client = snd_seq_client_info_get_client(cinfo); + + snd_seq_port_info_set_client(pinfo, client); + snd_seq_port_info_set_port(pinfo, -1); + while (snd_seq_query_next_port(seq, pinfo) >= 0) { + /* we need both READ and SUBS_READ */ + if ((snd_seq_port_info_get_capability(pinfo) + & (SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ)) + != (SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ)) + continue; + printf("%3d:%-3d %-32.32s %s\n", + snd_seq_port_info_get_client(pinfo), + snd_seq_port_info_get_port(pinfo), + snd_seq_client_info_get_name(cinfo), + snd_seq_port_info_get_name(pinfo)); + } + } +} + +static void help(const char *argv0) +{ + printf("Usage: %s [options]\n" + "\nAvailable options:\n" + " -h,--help this help\n" + " -V,--version show version\n" + " -l,--list list input ports\n" + " -p,--port=client:port,... source port(s)\n", + argv0); +} + +static void version(void) +{ + puts("aseqdump version " SND_UTIL_VERSION_STR); +} + +static void sighandler(int sig) +{ + stop = 1; +} + +int main(int argc, char *argv[]) +{ + static const char short_options[] = "hVlp:"; + static const struct option long_options[] = { + {"help", 0, NULL, 'h'}, + {"version", 0, NULL, 'V'}, + {"list", 0, NULL, 'l'}, + {"port", 1, NULL, 'p'}, + { } + }; + + int do_list = 0; + struct pollfd *pfds; + int npfds; + int c, err; + + init_seq(); + + while ((c = getopt_long(argc, argv, short_options, + long_options, NULL)) != -1) { + switch (c) { + case 'h': + help(argv[0]); + return 0; + case 'V': + version(); + return 0; + case 'l': + do_list = 1; + break; + case 'p': + parse_ports(optarg); + break; + default: + help(argv[0]); + return 1; + } + } + if (optind < argc) { + help(argv[0]); + return 1; + } + + if (do_list) { + list_ports(); + return 0; + } + + create_port(); + connect_ports(); + + err = snd_seq_nonblock(seq, 1); + check_snd("set nonblock mode", err); + + if (port_count > 0) + printf("Waiting for data."); + else + printf("Waiting for data at port %d:0.", + snd_seq_client_id(seq)); + printf(" Press Ctrl+C to end.\n"); + printf("Source Event Ch Data\n"); + + signal(SIGINT, sighandler); + signal(SIGTERM, sighandler); + + npfds = snd_seq_poll_descriptors_count(seq, POLLIN); + pfds = alloca(sizeof(*pfds) * npfds); + for (;;) { + snd_seq_poll_descriptors(seq, pfds, npfds, POLLIN); + if (poll(pfds, npfds, -1) < 0) + break; + do { + snd_seq_event_t *event; + err = snd_seq_event_input(seq, &event); + if (err < 0) + break; + if (event) + dump_event(event); + } while (err > 0); + fflush(stdout); + if (stop) + break; + } + + snd_seq_close(seq); + return 0; +} diff --git a/alsa-utils/seq/aseqnet/Makefile.am b/alsa-utils/seq/aseqnet/Makefile.am new file mode 100644 index 0000000..2ebc4a5 --- /dev/null +++ b/alsa-utils/seq/aseqnet/Makefile.am @@ -0,0 +1,7 @@ +INCLUDES = -I$(top_srcdir)/include +EXTRA_DIST = README.aseqnet aseqnet.1 + +bin_PROGRAMS = aseqnet +aseqnet_SOURCES = aseqnet.c +aseqnet_LDADD = $(INTLLIBS) +man_MANS = aseqnet.1 diff --git a/alsa-utils/seq/aseqnet/Makefile.in b/alsa-utils/seq/aseqnet/Makefile.in new file mode 100644 index 0000000..9169d65 --- /dev/null +++ b/alsa-utils/seq/aseqnet/Makefile.in @@ -0,0 +1,501 @@ +# Makefile.in generated by automake 1.9.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005 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@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = ../.. +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +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@ +bin_PROGRAMS = aseqnet$(EXEEXT) +subdir = seq/aseqnet +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/include/aconfig.h +CONFIG_CLEAN_FILES = +am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)" +binPROGRAMS_INSTALL = $(INSTALL_PROGRAM) +PROGRAMS = $(bin_PROGRAMS) +am_aseqnet_OBJECTS = aseqnet.$(OBJEXT) +aseqnet_OBJECTS = $(am_aseqnet_OBJECTS) +am__DEPENDENCIES_1 = +aseqnet_DEPENDENCIES = $(am__DEPENDENCIES_1) +DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)/include +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +SOURCES = $(aseqnet_SOURCES) +DIST_SOURCES = $(aseqnet_SOURCES) +man1dir = $(mandir)/man1 +NROFF = nroff +MANS = $(man_MANS) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALSACONF_FALSE = @ALSACONF_FALSE@ +ALSACONF_TRUE = @ALSACONF_TRUE@ +ALSAMIXER_FALSE = @ALSAMIXER_FALSE@ +ALSAMIXER_TRUE = @ALSAMIXER_TRUE@ +ALSA_CFLAGS = @ALSA_CFLAGS@ +ALSA_LIBS = @ALSA_LIBS@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CURSESINC = @CURSESINC@ +CURSESLIB = @CURSESLIB@ +CURSES_CFLAGS = @CURSES_CFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GREP = @GREP@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +LDFLAGS = @LDFLAGS@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LN_S = @LN_S@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +POSUB = @POSUB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SND_UTIL_MAJOR = @SND_UTIL_MAJOR@ +SND_UTIL_MINOR = @SND_UTIL_MINOR@ +SND_UTIL_SUBMINOR = @SND_UTIL_SUBMINOR@ +SND_UTIL_VERSION = @SND_UTIL_VERSION@ +STRIP = @STRIP@ +TESTSOUND = @TESTSOUND@ +USE_NLS = @USE_NLS@ +USE_XMLTO_FALSE = @USE_XMLTO_FALSE@ +USE_XMLTO_TRUE = @USE_XMLTO_TRUE@ +VERSION = @VERSION@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +ac_ct_CC = @ac_ct_CC@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +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@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +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@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +ncurses5_config = @ncurses5_config@ +ncursesw5_config = @ncursesw5_config@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +xmlto = @xmlto@ +INCLUDES = -I$(top_srcdir)/include +EXTRA_DIST = README.aseqnet aseqnet.1 +aseqnet_SOURCES = aseqnet.c +aseqnet_LDADD = $(INTLLIBS) +man_MANS = aseqnet.1 +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign seq/aseqnet/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --foreign seq/aseqnet/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 +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + test -z "$(bindir)" || $(mkdir_p) "$(DESTDIR)$(bindir)" + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + if test -f $$p \ + ; then \ + f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \ + $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \ + else :; fi; \ + done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \ + rm -f "$(DESTDIR)$(bindir)/$$f"; \ + done + +clean-binPROGRAMS: + -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) +aseqnet$(EXEEXT): $(aseqnet_OBJECTS) $(aseqnet_DEPENDENCIES) + @rm -f aseqnet$(EXEEXT) + $(LINK) $(aseqnet_LDFLAGS) $(aseqnet_OBJECTS) $(aseqnet_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/aseqnet.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \ +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` +uninstall-info-am: +install-man1: $(man1_MANS) $(man_MANS) + @$(NORMAL_INSTALL) + test -z "$(man1dir)" || $(mkdir_p) "$(DESTDIR)$(man1dir)" + @list='$(man1_MANS) $(dist_man1_MANS) $(nodist_man1_MANS)'; \ + l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ + for i in $$l2; do \ + case "$$i" in \ + *.1*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \ + else file=$$i; fi; \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + case "$$ext" in \ + 1*) ;; \ + *) ext='1' ;; \ + esac; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed -e 's/^.*\///'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \ + $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst"; \ + done +uninstall-man1: + @$(NORMAL_UNINSTALL) + @list='$(man1_MANS) $(dist_man1_MANS) $(nodist_man1_MANS)'; \ + l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ + for i in $$l2; do \ + case "$$i" in \ + *.1*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + case "$$ext" in \ + 1*) ;; \ + *) ext='1' ;; \ + esac; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed -e 's/^.*\///'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " rm -f '$(DESTDIR)$(man1dir)/$$inst'"; \ + rm -f "$(DESTDIR)$(man1dir)/$$inst"; \ + done + +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; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + 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; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + 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; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && 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)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkdir_p) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$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: check-am +all-am: Makefile $(PROGRAMS) $(MANS) +installdirs: + for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)"; do \ + test -z "$$dir" || $(mkdir_p) "$$dir"; \ + done +install: 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: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-binPROGRAMS clean-generic 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 + +info: info-am + +info-am: + +install-data-am: install-man + +install-exec-am: install-binPROGRAMS + +install-info: install-info-am + +install-man: install-man1 + +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 + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-binPROGRAMS uninstall-info-am uninstall-man + +uninstall-man: uninstall-man1 + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ + clean-generic ctags distclean distclean-compile \ + distclean-generic distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-binPROGRAMS \ + install-data install-data-am install-exec install-exec-am \ + install-info install-info-am install-man install-man1 \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-binPROGRAMS \ + uninstall-info-am uninstall-man uninstall-man1 + +# 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/alsa-utils/seq/aseqnet/README.aseqnet b/alsa-utils/seq/aseqnet/README.aseqnet new file mode 100644 index 0000000..bd0b68e --- /dev/null +++ b/alsa-utils/seq/aseqnet/README.aseqnet @@ -0,0 +1,53 @@ +================================================================ + ALSA sequencer connectors over network + ver.0.1 + Copyright (C) 1999-2000 Takashi Iwai +================================================================ + +* ASEQNET + +aseqnet is a sequencer client which sends/receives events over +network. Suppose two hosts (hostA and hostB) connected by network. +You need to run ALSA system on both hosts. Then, start aseqnet as a +server on hostA: + + hostA% aseqnet + sequencer opened: 128:0 + +A user client 128 with port 0 was opened. (The client number may +vary.) At next, start client on hostB. The argument is the hostname +where server is running. + + hostB% aseqnet hostA + sequencer opened: 132:0 + +Now events sent to hostA:128:0 is transferred to hostB:132:0, and vice +versa. + +You can connect these ports arbitrary to other sequencer ports. +For example, connect hostB:132:0 to a MIDI output device 65:0. The +aconnect utility can be used for this: + + hostB% aconnect 132:0 65:0 + +Events to hostA:128:0 will be delivered indirectly to hostB:65:0. +You'll hear MIDI sounds as following: + + hostA% pmidi -p 128:0 foo.mid + +The multiple clients may exist simultaneously. If hostC is connected +as a client to hostA, events from from hostA are sent to all connected +network clients, hostB and hostC. However, only one connection is +allowed from a client to a server. + +To disconnect network, stop all clients before server by ctrl-C or +sending signal to them. The server will automatically quit. + +The available options are: + + -p port : specify the TCP port number or TCP service name. + Default value is 40002. + -s addr : explicit read-subscription to the given address + (client:addr). + -d addr : explicit write-subscription to the given address. + -v : verbose mode. diff --git a/alsa-utils/seq/aseqnet/aseqnet.1 b/alsa-utils/seq/aseqnet/aseqnet.1 new file mode 100644 index 0000000..a1dc1d3 --- /dev/null +++ b/alsa-utils/seq/aseqnet/aseqnet.1 @@ -0,0 +1,81 @@ +.TH aseqnet 1 "January 1, 2000" +.LO 1 +.SH NAME +aseqnet \- ALSA sequencer connectors over network + +.SH SYNOPSIS +.B aseqnet +[remotehost] + +.SH DESCRIPTION +.B aseqnet +is an ALSA sequencer client which sends and receives event packets +over network. +Suppose two hosts connected by network, +.I hostA +as a server +and +.I hostB +as a client. +The ALSA sequencer system must be running on both hosts. +For creating the server port, run the following on hostA: +.IP "" 4 +hostA% aseqnet +.br +sequencer opened: 128:0 +.PP +Then a user client 128 with port 0 was opened on hostA. +(The client number may vary.) +For creating the (network-)client port, run +.B aseqnet +with the hostname of the server: +.IP "" 4 +hostB% aseqnet hostA +.br +sequencer opened: 132:0 +.PP +Now all events sent to hostA:128:0 are transferred to hostB:132:0, and vice +versa. +.PP +The ports created by +.B aseqnet +can be connected arbitrary to other sequencer ports via +.B aconnect(1). +For example, to connect hostB:132:0 to a MIDI output device 65:0: +.IP "" 4 +hostB% aconnect 132:0 65:0 +.PP +Then events to hostA:128:0 will be delivered to hostB:65:0. +The following command plays MIDI on +.I hostB. +.IP "" 4 +hostA% pmidi \-p 128:0 foo.mid +.PP +The multiple clients may exist simultaneously. If +.I hostC +is connected as a client to hostA, events from from hostA are sent +to all connected network clients, i.e. hostB and hostC. +However, only one connection is allowed from a client to a server. +.PP +To disconnect network, stop all clients before server by ctrl-C or +sending signal to them. The server will automatically quit. + +.SH OPTIONS +.TP +.B \-p port +Specify the TCP port number or TCP service name. +.TP +.B \-s addr +Subscribe to the given address for read automatically. +.TP +.B \-d addr +Subscribe to the given address for write automatically. +.TP +.B \-v +Verbose mode. + +.SH "SEE ALSO" +aconnect(1), pmidi(1) + +.SH AUTHOR +Takashi Iwai <tiwai@suse.de>. diff --git a/alsa-utils/seq/aseqnet/aseqnet.c b/alsa-utils/seq/aseqnet/aseqnet.c new file mode 100644 index 0000000..e071ad9 --- /dev/null +++ b/alsa-utils/seq/aseqnet/aseqnet.c @@ -0,0 +1,609 @@ +/* + * network server/client for ALSA sequencer + * ver.0.1 + * + * Copyright (C) 1999-2000 Takashi Iwai + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> +#include <string.h> +#include <netinet/in.h> +#include <sys/socket.h> +#include <netdb.h> +#include <locale.h> +#include <alsa/asoundlib.h> +#include <getopt.h> +#include <signal.h> +#include <assert.h> +#include "aconfig.h" +#include "gettext.h" + +/* + * prototypes + */ +static void usage(void); +static void init_buf(void); +static void init_pollfds(void); +static void close_files(void); +static void init_seq(char *source, char *dest); +static int get_port(char *service); +static void sigterm_exit(int sig); +static void init_server(int port); +static void init_client(char *server, int port); +static void do_loop(void); +static int copy_local_to_remote(void); +static int copy_remote_to_local(int fd); + +/* + * default TCP port number + */ +#define DEFAULT_PORT 40002 + +/* + * local input buffer + */ +static char *readbuf; +static int max_rdlen; +static char *writebuf; +static int cur_wrlen, max_wrlen; + +#define MAX_BUF_EVENTS 200 +#define MAX_CONNECTION 10 + +static snd_seq_t *handle; +static struct pollfd *seqifds = NULL; +static struct pollfd *seqofds = NULL; +static struct pollfd *pollfds = NULL; +static int seqifds_count = 0; +static int seqofds_count = 0; +static int pollfds_count = 0; +static int sockfd, netfd[MAX_CONNECTION] = {[0 ... MAX_CONNECTION-1] = -1}; +static int max_connection; +static int cur_connected; +static int seq_port; + +static int server_mode; +static int verbose = 0; +static int info = 0; + + +/* + * main routine + */ + +static const struct option long_option[] = { + {"port", 1, NULL, 'p'}, + {"source", 1, NULL, 's'}, + {"dest", 1, NULL, 'd'}, + {"help", 0, NULL, 'h'}, + {"verbose", 0, NULL, 'v'}, + {"info", 0, NULL, 'i'}, + {NULL, 0, NULL, 0}, +}; + +int main(int argc, char **argv) +{ + int c; + int port = DEFAULT_PORT; + char *source = NULL, *dest = NULL; + +#ifdef ENABLE_NLS + setlocale(LC_ALL, ""); + textdomain(PACKAGE); +#endif + + while ((c = getopt_long(argc, argv, "p:s:d:vi", long_option, NULL)) != -1) { + switch (c) { + case 'p': + if (isdigit(*optarg)) + port = atoi(optarg); + else + port = get_port(optarg); + break; + case 's': + source = optarg; + break; + case 'd': + dest = optarg; + break; + case 'v': + verbose++; + break; + case 'i': + info++; + break; + default: + usage(); + exit(1); + } + } + + signal(SIGINT, sigterm_exit); + signal(SIGTERM, sigterm_exit); + + init_buf(); + init_seq(source, dest); + + if (optind >= argc) { + server_mode = 1; + max_connection = MAX_CONNECTION; + init_pollfds(); + init_server(port); + } else { + server_mode = 0; + max_connection = 1; + init_pollfds(); + init_client(argv[optind], port); + } + + do_loop(); + + close_files(); + + return 0; +} + + +/* + * print usage + */ +static void usage(void) +{ + printf(_("aseqnet - network client/server on ALSA sequencer\n")); + printf(_(" Copyright (C) 1999 Takashi Iwai\n")); + printf(_("usage:\n")); + printf(_(" server mode: aseqnet [-options]\n")); + printf(_(" client mode: aseqnet [-options] server_host\n")); + printf(_("options:\n")); + printf(_(" -p,--port # : sepcify TCP port (digit or service name)\n")); + printf(_(" -s,--source addr : read from given addr (client:port)\n")); + printf(_(" -d,--dest addr : write to given addr (client:port)\n")); + printf(_(" -v, --verbose : print verbose messages\n")); + printf(_(" -i, --info : print certain received events\n")); +} + + +/* + * allocate and initialize buffers + */ +static void init_buf(void) +{ + max_wrlen = MAX_BUF_EVENTS * sizeof(snd_seq_event_t); + max_rdlen = MAX_BUF_EVENTS * sizeof(snd_seq_event_t); + writebuf = malloc(max_wrlen); + readbuf = malloc(max_rdlen); + if (writebuf == NULL || readbuf == NULL) { + fprintf(stderr, _("can't malloc\n")); + exit(1); + } + memset(writebuf, 0, max_wrlen); + memset(readbuf, 0, max_rdlen); + cur_wrlen = 0; +} + +/* + * allocate and initialize poll array + */ +static void init_pollfds(void) +{ + pollfds_count = seqifds_count + seqofds_count + 1 + max_connection; + pollfds = (struct pollfd *)calloc(pollfds_count, sizeof(struct pollfd)); + assert(pollfds); +} + +/* + * close all files + */ +static void close_files(void) +{ + int i; + if (verbose) + fprintf(stderr, _("closing files..\n")); + for (i = 0; i < max_connection; i++) { + if (netfd[i] >= 0) + close(netfd[i]); + } + if (sockfd >= 0) + close(sockfd); +} + + +/* + * initialize sequencer + */ +static void init_seq(char *source, char *dest) +{ + snd_seq_addr_t addr; + int err, counti, counto; + + if (snd_seq_open(&handle, "default", SND_SEQ_OPEN_DUPLEX, 0) < 0) { + perror("snd_seq_open"); + exit(1); + } + if (seqifds) + free(seqifds); + if (seqofds) + free(seqofds); + counti = seqifds_count = snd_seq_poll_descriptors_count(handle, POLLIN); + assert(counti > 0); + counto = seqofds_count = snd_seq_poll_descriptors_count(handle, POLLOUT); + assert(counto > 0); + seqifds = (struct pollfd *)calloc(counti, sizeof(struct pollfd)); + assert(seqifds); + seqofds = (struct pollfd *)calloc(counto, sizeof(struct pollfd)); + assert(seqofds); + err = snd_seq_poll_descriptors(handle, seqifds, counti, POLLIN); + assert(err == counti); + err = snd_seq_poll_descriptors(handle, seqofds, counto, POLLOUT); + assert(err == counto); + + snd_seq_nonblock(handle, 1); + + /* set client info */ + if (server_mode) + snd_seq_set_client_name(handle, "Net Server"); + else + snd_seq_set_client_name(handle, "Net Client"); + + /* create a port */ + seq_port = snd_seq_create_simple_port(handle, "Network", + SND_SEQ_PORT_CAP_READ | + SND_SEQ_PORT_CAP_WRITE | + SND_SEQ_PORT_CAP_SUBS_READ | + SND_SEQ_PORT_CAP_SUBS_WRITE, + SND_SEQ_PORT_TYPE_MIDI_GENERIC); + if (seq_port < 0) { + perror("create seq port"); + exit(1); + } + if (verbose) + fprintf(stderr, _("sequencer opened: %d:%d\n"), + snd_seq_client_id(handle), seq_port); + + /* explicit subscriptions */ + if (source) { + /* read subscription */ + if (snd_seq_parse_address(handle, &addr, source) < 0) { + fprintf(stderr, _("invalid source address %s\n"), source); + exit(1); + } + if (snd_seq_connect_from(handle, seq_port, addr.client, addr.port)) { + perror("read subscription"); + exit(1); + } + } + if (dest) { + /* write subscription */ + if (snd_seq_parse_address(handle, &addr, dest) < 0) { + fprintf(stderr, _("invalid destination address %s\n"), dest); + exit(1); + } + if (snd_seq_connect_to(handle, seq_port, addr.client, addr.port)) { + perror("write subscription"); + exit(1); + } + } +} + + +/* + * convert from string to TCP port number + */ +static int get_port(char *service) +{ + struct servent *sp; + + if ((sp = getservbyname(service, "tcp")) == NULL){ + fprintf(stderr, _("service '%s' is not found in /etc/services\n"), service); + return -1; + } + return sp->s_port; +} + +/* + * signal handler + */ +static void sigterm_exit(int sig) +{ + close_files(); + exit(1); +} + + +/* + * initialize network server + */ +static void init_server(int port) +{ + int i; + int curstate = 1; + struct sockaddr_in addr; + + memset(&addr, 0, sizeof(addr)); + + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = INADDR_ANY; + addr.sin_port = htons(port); + + sockfd = socket(AF_INET, SOCK_STREAM, 0); + if (sockfd < 0) { + perror("create socket"); + exit(1); + } + setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &curstate, sizeof(curstate)); + /* the return value is ignored.. */ + + if (bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { + perror("can't bind"); + exit(1); + } + + if (listen(sockfd, 5) < 0) { + perror("can't listen"); + exit(1); + } + + cur_connected = 0; + for (i = 0; i < max_connection; i++) + netfd[i] = -1; +} + +/* + * start connection on server + */ +static void start_connection(void) +{ + struct sockaddr_in addr; + int i; + socklen_t addr_len; + + for (i = 0; i < max_connection; i++) { + if (netfd[i] < 0) + break; + } + if (i >= max_connection) { + fprintf(stderr, _("too many connections!\n")); + exit(1); + } + memset(&addr, 0, sizeof(addr)); + addr_len = sizeof(addr); + netfd[i] = accept(sockfd, (struct sockaddr *)&addr, &addr_len); + if (netfd[i] < 0) { + perror("accept"); + exit(1); + } + if (verbose) + fprintf(stderr, _("accepted[%d]\n"), netfd[i]); + cur_connected++; +} + +/* + * initialize network client + */ +static void init_client(char *server, int port) +{ + struct sockaddr_in addr; + struct hostent *host; + int curstate = 1; + int fd; + + if ((fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0){ + perror("create socket"); + exit(1); + } + if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &curstate, sizeof(curstate)) < 0) { + perror("setsockopt"); + exit(1); + } + if ((host = gethostbyname(server)) == NULL){ + fprintf(stderr, _("can't get address %s\n"), server); + exit(1); + } + addr.sin_port = htons(port); + addr.sin_family = AF_INET; + memcpy(&addr.sin_addr, host->h_addr, host->h_length); + if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { + perror("connect"); + exit(1); + } + if (verbose) + fprintf(stderr, _("ok.. connected\n")); + netfd[0] = fd; + cur_connected = 1; +} + +/* + * event loop + */ +static void do_loop(void) +{ + int i, rc, width; + int seqifd_ptr, sockfd_ptr = -1, netfd_ptr; + + for (;;) { + memset(pollfds, 0, pollfds_count * sizeof(struct pollfd)); + seqifd_ptr = 0; + memcpy(pollfds, seqifds, sizeof(*seqifds)*(width = seqifds_count)); + if (server_mode) { + sockfd_ptr = width; + pollfds[width].fd = sockfd; + pollfds[width].events = POLLIN; + width++; + } + netfd_ptr = width; + for (i = 0; i < max_connection; i++) { + if (netfd[i] >= 0) { + pollfds[width].fd = netfd[i]; + pollfds[width].events = POLLIN; + width++; + } + } + do { + rc = poll(pollfds, width, -1); + } while (rc <= 0 && errno == EINTR); + if (rc <= 0) { + perror("poll"); + exit(1); + } + if (server_mode) { + if (pollfds[sockfd_ptr].revents & (POLLIN|POLLOUT)) + start_connection(); + } + for (i = 0; i < seqifds_count; i++) + if (pollfds[seqifd_ptr + i].revents & (POLLIN|POLLOUT)) { + if (copy_local_to_remote()) + return; + break; + } + for (i = 0; i < max_connection; i++) { + if (netfd[i] < 0) + continue; + if (pollfds[netfd_ptr + i].revents & (POLLIN|POLLOUT)) { + if (copy_remote_to_local(netfd[i])) { + netfd[i] = -1; + cur_connected--; + if (cur_connected <= 0) + return; + } + } + } + } +} + + +/* + * flush write buffer - send data to the socket + */ +static void flush_writebuf(void) +{ + if (cur_wrlen) { + int i; + for (i = 0; i < max_connection; i++) { + if (netfd[i] >= 0) + write(netfd[i], writebuf, cur_wrlen); + } + cur_wrlen = 0; + } +} + +/* + * get space from write buffer + */ +static char *get_writebuf(int len) +{ + char *buf; + if (cur_wrlen + len >= max_wrlen) + flush_writebuf(); + buf = writebuf + cur_wrlen; + cur_wrlen += len; + return buf; +} + +static void print_event(snd_seq_event_t *ev) +{ + switch (ev->type) { + case SND_SEQ_EVENT_CONTROLLER: + printf(_("Channel %2d: Control event : %5d\n"), + ev->data.control.channel, ev->data.control.value); + break; + case SND_SEQ_EVENT_PITCHBEND: + printf(_("Channel %2d: Pitchbender : %5d\n"), + ev->data.control.channel, ev->data.control.value); + break; + case SND_SEQ_EVENT_NOTEON: + printf(_("Channel %2d: Note On event : %5d\n"), + ev->data.control.channel, ev->data.note.note); + break; + case SND_SEQ_EVENT_NOTEOFF: + printf(_("Channel %2d: Note Off event: %5d\n"), + ev->data.control.channel, ev->data.note.note); + break; + } +} + +#define EVENT_PACKET_SIZE 32 + +/* + * copy events from sequencer to port(s) + */ +static int copy_local_to_remote(void) +{ + int rc; + snd_seq_event_t *ev; + char *buf; + + while ((rc = snd_seq_event_input(handle, &ev)) >= 0 && ev) { + if (ev->type >= SND_SEQ_EVENT_CLIENT_START && + ! snd_seq_ev_is_variable_type(ev)) { + snd_seq_free_event(ev); + continue; + } + if (snd_seq_ev_is_variable(ev)) { + int len; + len = EVENT_PACKET_SIZE + ev->data.ext.len; + buf = get_writebuf(len); + memcpy(buf, ev, sizeof(snd_seq_event_t)); + memcpy(buf + EVENT_PACKET_SIZE, ev->data.ext.ptr, ev->data.ext.len); + } else { + buf = get_writebuf(EVENT_PACKET_SIZE); + memcpy(buf, ev, EVENT_PACKET_SIZE); + } + if (info) + print_event(ev); + snd_seq_free_event(ev); + } + flush_writebuf(); + return 0; +} + +/* + * copy events from a port to sequencer + */ +static int copy_remote_to_local(int fd) +{ + int count; + char *buf; + snd_seq_event_t *ev; + + count = read(fd, readbuf, MAX_BUF_EVENTS * sizeof(snd_seq_event_t)); + buf = readbuf; + + if (count == 0) { + if (verbose) + fprintf(stderr, _("disconnected\n")); + return 1; + } + + while (count > 0) { + ev = (snd_seq_event_t*)buf; + buf += EVENT_PACKET_SIZE; + count -= EVENT_PACKET_SIZE; + if (snd_seq_ev_is_variable(ev) && ev->data.ext.len > 0) { + ev->data.ext.ptr = buf; + buf += ev->data.ext.len; + count -= ev->data.ext.len; + } + snd_seq_ev_set_direct(ev); + snd_seq_ev_set_source(ev, seq_port); + snd_seq_ev_set_subs(ev); + if (info) + print_event(ev); + snd_seq_event_output(handle, ev); + } + + snd_seq_drain_output(handle); + return 0; +} + |