diff --git a/.dir-locals.el b/.dir-locals.el new file mode 100644 index 00000000..3c3abd62 --- /dev/null +++ b/.dir-locals.el @@ -0,0 +1,8 @@ +;;; Directory Local Variables +;;; For more information see (info "(emacs) Directory Variables") + +((c++-mode + (c-basic-offset . 2)) + (c-mode + (c-basic-offset . 2))) + diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..f49e8216 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,4 @@ +# make sure that .gitignore, .travis.yml,... are not part of a +# source-package generated via 'git archive' +.git* export-ignore +/.* export-ignore diff --git a/.github/issue_template.md b/.github/issue_template.md new file mode 100644 index 00000000..f95f70d1 --- /dev/null +++ b/.github/issue_template.md @@ -0,0 +1,7 @@ +The maintainers / developers of RtMidi favour pull requests over issues. We generally do not have access to all the supported platforms to attempt to verify a reported problem. It will help the entire RtMidi community if you can debug a problem you are reporting and suggest a way to fix it yourself. + +- Expected behavior and actual behavior. + +- Steps to reproduce the problem. + +- Specifications like the version of the project, operating system, or hardware. diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..1f8c32bd --- /dev/null +++ b/.gitignore @@ -0,0 +1,15 @@ +/config +/configure +/doc/html +Makefile +Makefile.in +/aclocal.m4 +/autom4te.cache +/configure +/m4/libtool.m4 +/m4/ltoptions.m4 +/m4/ltsugar.m4 +/m4/ltversion.m4 +/m4/lt~obsolete.m4 +*.orig +*~ diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..c3318992 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,93 @@ +git: + depth: 1 +branches: + except: + - /(?i:appveyor)/ +sudo: false # docker VM +matrix: + include: + - os: linux + env: HOST="" API="alsa" + compiler: gcc + - os: linux + env: HOST="" API="alsa" + compiler: clang + - os: linux + env: HOST="" API="jack" + compiler: gcc + - os: linux + env: HOST="" API="jack" + compiler: clang + - os: linux + env: HOST="--with-jack" API="alsa" + compiler: gcc + - os: linux + env: HOST="--with-jack" API="alsa" + compiler: clang + # - os: linux + # env: HOST="--host=i686-w64-mingw32" API="winmm" + # compiler: gcc + # - os: linux + # env: HOST="--host=x86_64-w64-mingw32" API="winmm" + # compiler: gcc + # jack and asound not found on ARM gnueabihf + # - os: linux + # env: HOST="--host=arm-linux-gnueabihf" API="alsa" + # compiler: gcc + # - os: linux + # env: HOST="--host=arm-linux-gnueabihf" API="jack" + # compiler: gcc + - os: osx + env: HOST="" API="coremidi" + compiler: gcc + - os: osx + env: HOST="" API="coremidi" + compiler: clang + - os: osx + env: HOST="" API="jack" + compiler: gcc + - os: osx + env: HOST="" API="jack" + compiler: clang + - os: osx + env: HOST="--with-jack" API="coremidi" + compiler: gcc + - os: osx + env: HOST="--with-jack" API="coremidi" + compiler: clang +language: c++ +group: travis_latest + + +addons: + apt: + packages: + - autoconf + - libtool + - autopoint + - automake + - libasound-dev + - libjack-dev + - libcppunit-dev + - doxygen + - g++-mingw-w64-i686 + - g++-mingw-w64-x86-64 + - g++-arm-linux-gnueabihf + + +before_install: + - eval "${MATRIX_EVAL}" + - if test "$TRAVIS_OS_NAME" = osx ; then brew update ; fi + - if test "$TRAVIS_OS_NAME" = osx ; then if brew upgrade boost ; then echo "upgraded" ; else echo "nothing to be done"; fi ; fi + - if test "$TRAVIS_OS_NAME" = osx ; then rm -rf /usr/local/include/c++ ; fi # fix broken gcc installation + - if test "$TRAVIS_OS_NAME" = osx ; then brew install $EXTRA_BREW gettext flex bison libtool autoconf jack doxygen ; fi + - if test "$TRAVIS_OS_NAME" = osx ; then brew link --force $EXTRA_BREW gettext flex bison libtool autoconf jack ; fi + - mkdir -p config + - touch config/config.rpath + +script: + - mkdir -p config + - touch config/config.rpath + - ./autogen.sh --disable-apisearch --with-$API $HOST && make && make -j4 && $TEST_RUNNER make check || (cat test-suite.log ; false) + - make distcheck + - cat tests/errors.log diff --git a/ABOUT-NLS b/ABOUT-NLS new file mode 100644 index 00000000..3cc82865 --- /dev/null +++ b/ABOUT-NLS @@ -0,0 +1,1379 @@ +1 Notes on the Free Translation Project +*************************************** + +Free software is going international! The Free Translation Project is a +way to get maintainers of free software, translators, and users all +together, so that free software will gradually become able to speak many +languages. A few packages already provide translations for their +messages. + + If you found this 'ABOUT-NLS' file inside a distribution, you may +assume that the distributed package does use GNU 'gettext' internally, +itself available at your nearest GNU archive site. But you do _not_ +need to install GNU 'gettext' prior to configuring, installing or using +this package with messages translated. + + Installers will find here some useful hints. These notes also +explain how users should proceed for getting the programs to use the +available translations. They tell how people wanting to contribute and +work on translations can contact the appropriate team. + +1.1 INSTALL Matters +=================== + +Some packages are "localizable" when properly installed; the programs +they contain can be made to speak your own native language. Most such +packages use GNU 'gettext'. Other packages have their own ways to +internationalization, predating GNU 'gettext'. + + By default, this package will be installed to allow translation of +messages. It will automatically detect whether the system already +provides the GNU 'gettext' functions. Installers may use special +options at configuration time for changing the default behaviour. The +command: + + ./configure --disable-nls + +will _totally_ disable translation of messages. + + When you already have GNU 'gettext' installed on your system and run +configure without an option for your new package, 'configure' will +probably detect the previously built and installed 'libintl' library and +will decide to use it. If not, you may have to to use the +'--with-libintl-prefix' option to tell 'configure' where to look for it. + + Internationalized packages usually have many 'po/LL.po' files, where +LL gives an ISO 639 two-letter code identifying the language. Unless +translations have been forbidden at 'configure' time by using the +'--disable-nls' switch, all available translations are installed +together with the package. However, the environment variable 'LINGUAS' +may be set, prior to configuration, to limit the installed set. +'LINGUAS' should then contain a space separated list of two-letter +codes, stating which languages are allowed. + +1.2 Using This Package +====================== + +As a user, if your language has been installed for this package, you +only have to set the 'LANG' environment variable to the appropriate +'LL_CC' combination. If you happen to have the 'LC_ALL' or some other +'LC_xxx' environment variables set, you should unset them before setting +'LANG', otherwise the setting of 'LANG' will not have the desired +effect. Here 'LL' is an ISO 639 two-letter language code, and 'CC' is +an ISO 3166 two-letter country code. For example, let's suppose that +you speak German and live in Germany. At the shell prompt, merely +execute 'setenv LANG de_DE' (in 'csh'), 'export LANG; LANG=de_DE' (in +'sh') or 'export LANG=de_DE' (in 'bash'). This can be done from your +'.login' or '.profile' file, once and for all. + + You might think that the country code specification is redundant. +But in fact, some languages have dialects in different countries. For +example, 'de_AT' is used for Austria, and 'pt_BR' for Brazil. The +country code serves to distinguish the dialects. + + The locale naming convention of 'LL_CC', with 'LL' denoting the +language and 'CC' denoting the country, is the one use on systems based +on GNU libc. On other systems, some variations of this scheme are used, +such as 'LL' or 'LL_CC.ENCODING'. You can get the list of locales +supported by your system for your language by running the command +'locale -a | grep '^LL''. + + Not all programs have translations for all languages. By default, an +English message is shown in place of a nonexistent translation. If you +understand other languages, you can set up a priority list of languages. +This is done through a different environment variable, called +'LANGUAGE'. GNU 'gettext' gives preference to 'LANGUAGE' over 'LANG' +for the purpose of message handling, but you still need to have 'LANG' +set to the primary language; this is required by other parts of the +system libraries. For example, some Swedish users who would rather read +translations in German than English for when Swedish is not available, +set 'LANGUAGE' to 'sv:de' while leaving 'LANG' to 'sv_SE'. + + Special advice for Norwegian users: The language code for Norwegian +bokma*l changed from 'no' to 'nb' recently (in 2003). During the +transition period, while some message catalogs for this language are +installed under 'nb' and some older ones under 'no', it's recommended +for Norwegian users to set 'LANGUAGE' to 'nb:no' so that both newer and +older translations are used. + + In the 'LANGUAGE' environment variable, but not in the 'LANG' +environment variable, 'LL_CC' combinations can be abbreviated as 'LL' to +denote the language's main dialect. For example, 'de' is equivalent to +'de_DE' (German as spoken in Germany), and 'pt' to 'pt_PT' (Portuguese +as spoken in Portugal) in this context. + +1.3 Translating Teams +===================== + +For the Free Translation Project to be a success, we need interested +people who like their own language and write it well, and who are also +able to synergize with other translators speaking the same language. +Each translation team has its own mailing list. The up-to-date list of +teams can be found at the Free Translation Project's homepage, +'http://translationproject.org/', in the "Teams" area. + + If you'd like to volunteer to _work_ at translating messages, you +should become a member of the translating team for your own language. +The subscribing address is _not_ the same as the list itself, it has +'-request' appended. For example, speakers of Swedish can send a +message to 'sv-request@li.org', having this message body: + + subscribe + + Keep in mind that team members are expected to participate _actively_ +in translations, or at solving translational difficulties, rather than +merely lurking around. If your team does not exist yet and you want to +start one, or if you are unsure about what to do or how to get started, +please write to 'coordinator@translationproject.org' to reach the +coordinator for all translator teams. + + The English team is special. It works at improving and uniformizing +the terminology in use. Proven linguistic skills are praised more than +programming skills, here. + +1.4 Available Packages +====================== + +Languages are not equally supported in all packages. The following +matrix shows the current state of internationalization, as of Jun 2014. +The matrix shows, in regard of each package, for which languages PO +files have been submitted to translation coordination, with a +translation percentage of at least 50%. + + Ready PO files af am an ar as ast az be bg bn bn_IN bs ca crh cs + +---------------------------------------------------+ + a2ps | [] [] [] | + aegis | | + anubis | | + aspell | [] [] [] | + bash | [] [] [] | + bfd | | + binutils | [] | + bison | | + bison-runtime | [] | + buzztrax | [] | + ccd2cue | | + ccide | | + cflow | | + clisp | | + coreutils | [] [] | + cpio | | + cppi | | + cpplib | [] | + cryptsetup | [] | + datamash | | + denemo | [] [] | + dfarc | [] | + dialog | [] [] [] | + dico | | + diffutils | [] | + dink | [] | + direvent | | + doodle | [] | + dos2unix | | + dos2unix-man | | + e2fsprogs | [] [] | + enscript | [] | + exif | [] | + fetchmail | [] [] | + findutils | [] | + flex | [] | + freedink | [] [] | + fusionforge | | + gas | | + gawk | [] | + gcal | [] | + gcc | | + gdbm | | + gettext-examples | [] [] [] [] [] | + gettext-runtime | [] [] [] | + gettext-tools | [] [] | + gjay | | + glunarclock | [] [] [] | + gnubiff | [] | + gnubik | [] | + gnucash | () () [] | + gnuchess | | + gnulib | [] | + gnunet | | + gnunet-gtk | | + gold | | + gphoto2 | [] | + gprof | [] | + gramadoir | | + grep | [] [] [] | + grub | [] | + gsasl | | + gss | | + gst-plugins-bad | [] [] | + gst-plugins-base | [] [] [] | + gst-plugins-good | [] [] [] | + gst-plugins-ugly | [] [] [] | + gstreamer | [] [] [] [] | + gtick | [] | + gtkam | [] [] | + gtkspell | [] [] [] [] [] | + guix | | + guix-packages | | + gutenprint | [] | + hello | [] | + help2man | | + help2man-texi | | + hylafax | | + idutils | | + iso_15924 | [] | + iso_3166 | [] [] [] [] [] [] [] [] [] [] | + iso_3166_2 | | + iso_4217 | [] | + iso_639 | [] [] [] [] [] [] [] [] [] | + iso_639_3 | [] [] | + iso_639_5 | | + jwhois | | + kbd | [] | + klavaro | [] [] [] [] [] | + ld | [] | + leafpad | [] [] [] [] | + libc | [] [] [] | + libexif | () | + libextractor | | + libgnutls | [] | + libgphoto2 | [] | + libgphoto2_port | [] | + libgsasl | | + libiconv | [] [] | + libidn | [] | + liferea | [] [] [] [] | + lilypond | [] [] | + lordsawar | [] | + lprng | | + lynx | [] [] | + m4 | [] | + mailfromd | | + mailutils | | + make | [] | + man-db | [] [] | + man-db-manpages | | + midi-instruments | [] [] [] | + minicom | [] | + mkisofs | [] | + myserver | [] | + nano | [] [] [] | + opcodes | | + parted | [] | + pies | | + pnmixer | | + popt | [] | + procps-ng | | + procps-ng-man | | + psmisc | [] | + pspp | [] | + pushover | [] | + pwdutils | | + pyspread | | + radius | [] | + recode | [] [] [] | + recutils | | + rpm | | + rush | | + sarg | | + sed | [] [] [] [] | + sharutils | [] | + shishi | | + skribilo | | + solfege | [] [] | + solfege-manual | | + spotmachine | | + sudo | [] [] | + sudoers | [] [] | + sysstat | [] | + tar | [] [] [] | + texinfo | [] [] | + texinfo_document | [] [] | + tigervnc | [] | + tin | | + tin-man | | + tracgoogleappsa... | | + trader | | + util-linux | [] | + ve | | + vice | | + vmm | | + vorbis-tools | [] | + wastesedge | | + wcd | | + wcd-man | | + wdiff | [] [] | + wget | [] | + wyslij-po | | + xboard | | + xdg-user-dirs | [] [] [] [] [] [] [] [] [] [] | + xkeyboard-config | [] [] [] | + +---------------------------------------------------+ + af am an ar as ast az be bg bn bn_IN bs ca crh cs + 4 0 2 5 3 11 0 8 25 3 3 1 55 4 74 + + da de el en en_GB en_ZA eo es et eu fa fi fr + +--------------------------------------------------+ + a2ps | [] [] [] [] [] [] [] [] [] | + aegis | [] [] [] [] | + anubis | [] [] [] [] [] | + aspell | [] [] [] [] [] [] [] | + bash | [] [] [] | + bfd | [] [] [] [] | + binutils | [] [] [] | + bison | [] [] [] [] [] [] [] [] | + bison-runtime | [] [] [] [] [] [] [] [] | + buzztrax | [] [] [] [] | + ccd2cue | [] [] [] [] | + ccide | [] [] [] [] [] [] | + cflow | [] [] [] [] [] | + clisp | [] [] [] [] [] | + coreutils | [] [] [] [] [] | + cpio | [] [] [] [] [] | + cppi | [] [] [] [] [] | + cpplib | [] [] [] [] [] [] | + cryptsetup | [] [] [] [] [] | + datamash | [] [] [] [] | + denemo | [] | + dfarc | [] [] [] [] [] [] | + dialog | [] [] [] [] [] [] [] [] [] | + dico | [] [] [] [] | + diffutils | [] [] [] [] [] [] | + dink | [] [] [] [] [] [] | + direvent | [] [] [] [] | + doodle | [] [] [] [] | + dos2unix | [] [] [] [] [] | + dos2unix-man | [] [] [] | + e2fsprogs | [] [] [] [] [] | + enscript | [] [] [] [] [] [] | + exif | [] [] [] [] [] [] | + fetchmail | [] () [] [] [] [] [] | + findutils | [] [] [] [] [] [] [] [] | + flex | [] [] [] [] [] [] | + freedink | [] [] [] [] [] [] [] [] | + fusionforge | [] [] [] | + gas | [] [] [] | + gawk | [] [] [] [] [] | + gcal | [] [] [] [] | + gcc | [] | + gdbm | [] [] [] [] [] | + gettext-examples | [] [] [] [] [] [] [] | + gettext-runtime | [] [] [] [] [] [] | + gettext-tools | [] [] [] [] [] | + gjay | [] [] [] [] | + glunarclock | [] [] [] [] [] | + gnubiff | () [] [] () | + gnubik | [] [] [] [] [] | + gnucash | [] () () () () () () | + gnuchess | [] [] [] [] | + gnulib | [] [] [] [] [] [] [] | + gnunet | [] | + gnunet-gtk | [] | + gold | [] [] [] | + gphoto2 | [] () [] [] | + gprof | [] [] [] [] [] [] | + gramadoir | [] [] [] [] [] | + grep | [] [] [] [] [] [] [] | + grub | [] [] [] [] [] | + gsasl | [] [] [] [] [] | + gss | [] [] [] [] [] | + gst-plugins-bad | [] [] [] | + gst-plugins-base | [] [] [] [] [] [] | + gst-plugins-good | [] [] [] [] [] [] [] | + gst-plugins-ugly | [] [] [] [] [] [] [] [] | + gstreamer | [] [] [] [] [] [] [] | + gtick | [] () [] [] [] | + gtkam | [] () [] [] [] [] | + gtkspell | [] [] [] [] [] [] [] [] | + guix | [] [] | + guix-packages | | + gutenprint | [] [] [] [] | + hello | [] [] [] [] [] [] [] [] | + help2man | [] [] [] [] [] [] [] | + help2man-texi | [] [] [] | + hylafax | [] [] | + idutils | [] [] [] [] [] | + iso_15924 | [] () [] [] () [] () | + iso_3166 | [] () [] [] [] [] () [] () | + iso_3166_2 | [] () () () | + iso_4217 | [] () [] [] [] () [] () | + iso_639 | [] () [] [] () [] () | + iso_639_3 | () () () | + iso_639_5 | () () () | + jwhois | [] [] [] [] [] | + kbd | [] [] [] [] [] [] | + klavaro | [] [] [] [] [] [] [] | + ld | [] [] [] [] | + leafpad | [] [] [] [] [] [] [] [] | + libc | [] [] [] [] [] | + libexif | [] [] () [] [] | + libextractor | [] | + libgnutls | [] [] [] [] | + libgphoto2 | [] () [] | + libgphoto2_port | [] () [] [] [] [] | + libgsasl | [] [] [] [] [] | + libiconv | [] [] [] [] [] [] [] | + libidn | [] [] [] [] [] | + liferea | [] () [] [] [] [] [] | + lilypond | [] [] [] [] [] [] | + lordsawar | [] [] | + lprng | | + lynx | [] [] [] [] [] [] | + m4 | [] [] [] [] [] [] | + mailfromd | [] | + mailutils | [] [] [] [] | + make | [] [] [] [] [] | + man-db | [] [] [] [] | + man-db-manpages | [] [] | + midi-instruments | [] [] [] [] [] [] [] [] [] | + minicom | [] [] [] [] [] | + mkisofs | [] [] [] | + myserver | [] [] [] [] | + nano | [] [] [] [] [] [] [] | + opcodes | [] [] [] [] [] | + parted | [] [] [] | + pies | [] | + pnmixer | [] [] | + popt | [] [] [] [] [] [] | + procps-ng | [] [] | + procps-ng-man | [] [] | + psmisc | [] [] [] [] [] [] [] | + pspp | [] [] [] | + pushover | () [] [] [] | + pwdutils | [] [] [] | + pyspread | [] [] [] | + radius | [] [] | + recode | [] [] [] [] [] [] [] | + recutils | [] [] [] [] | + rpm | [] [] [] [] [] | + rush | [] [] [] | + sarg | [] [] | + sed | [] [] [] [] [] [] [] [] | + sharutils | [] [] [] [] | + shishi | [] [] [] | + skribilo | [] [] [] | + solfege | [] [] [] [] [] [] [] [] | + solfege-manual | [] [] [] [] [] | + spotmachine | [] [] [] [] [] | + sudo | [] [] [] [] [] [] | + sudoers | [] [] [] [] [] [] | + sysstat | [] [] [] [] [] [] | + tar | [] [] [] [] [] [] [] | + texinfo | [] [] [] [] [] | + texinfo_document | [] [] [] [] | + tigervnc | [] [] [] [] [] [] | + tin | [] [] [] [] | + tin-man | [] | + tracgoogleappsa... | [] [] [] [] [] | + trader | [] [] [] [] [] [] | + util-linux | [] [] [] [] | + ve | [] [] [] [] [] | + vice | () () () | + vmm | [] [] | + vorbis-tools | [] [] [] [] | + wastesedge | [] | + wcd | [] [] [] [] | + wcd-man | [] | + wdiff | [] [] [] [] [] [] [] | + wget | [] [] [] [] [] [] | + wyslij-po | [] [] [] [] | + xboard | [] [] [] [] | + xdg-user-dirs | [] [] [] [] [] [] [] [] [] [] | + xkeyboard-config | [] [] [] [] [] [] [] | + +--------------------------------------------------+ + da de el en en_GB en_ZA eo es et eu fa fi fr + 119 131 32 1 6 0 94 95 22 13 4 102 139 + + ga gd gl gu he hi hr hu hy ia id is it ja ka kk + +-------------------------------------------------+ + a2ps | [] [] [] [] | + aegis | [] | + anubis | [] [] [] [] | + aspell | [] [] [] [] [] | + bash | [] [] [] [] | + bfd | [] [] | + binutils | [] [] [] | + bison | [] | + bison-runtime | [] [] [] [] [] [] [] [] | + buzztrax | | + ccd2cue | [] | + ccide | [] [] | + cflow | [] [] [] | + clisp | | + coreutils | [] [] | + cpio | [] [] [] [] [] [] | + cppi | [] [] [] [] [] | + cpplib | [] [] | + cryptsetup | [] | + datamash | | + denemo | [] | + dfarc | [] [] [] | + dialog | [] [] [] [] [] [] [] [] [] [] | + dico | | + diffutils | [] [] [] [] | + dink | [] | + direvent | [] | + doodle | [] [] | + dos2unix | [] [] | + dos2unix-man | | + e2fsprogs | [] [] | + enscript | [] [] [] | + exif | [] [] [] [] [] [] | + fetchmail | [] [] [] | + findutils | [] [] [] [] [] [] [] | + flex | [] | + freedink | [] [] [] [] | + fusionforge | | + gas | [] | + gawk | [] () [] | + gcal | | + gcc | | + gdbm | | + gettext-examples | [] [] [] [] [] [] [] | + gettext-runtime | [] [] [] [] [] [] [] | + gettext-tools | [] [] [] | + gjay | [] | + glunarclock | [] [] [] [] [] [] | + gnubiff | [] [] () | + gnubik | [] [] [] | + gnucash | () () () () () | + gnuchess | | + gnulib | [] [] [] [] [] | + gnunet | | + gnunet-gtk | | + gold | [] [] | + gphoto2 | [] [] [] [] | + gprof | [] [] [] [] | + gramadoir | [] [] [] | + grep | [] [] [] [] [] [] [] | + grub | [] [] [] | + gsasl | [] [] [] [] [] | + gss | [] [] [] [] [] | + gst-plugins-bad | [] [] [] | + gst-plugins-base | [] [] [] [] | + gst-plugins-good | [] [] [] [] [] [] | + gst-plugins-ugly | [] [] [] [] [] [] | + gstreamer | [] [] [] [] [] | + gtick | [] [] [] [] [] | + gtkam | [] [] [] [] [] | + gtkspell | [] [] [] [] [] [] [] [] [] [] | + guix | | + guix-packages | | + gutenprint | [] [] [] | + hello | [] [] [] [] [] | + help2man | [] [] [] | + help2man-texi | | + hylafax | [] | + idutils | [] [] | + iso_15924 | [] [] [] [] [] [] | + iso_3166 | [] [] [] [] [] [] [] [] [] [] [] [] [] | + iso_3166_2 | [] [] | + iso_4217 | [] [] [] [] [] [] | + iso_639 | [] [] [] [] [] [] [] [] [] | + iso_639_3 | [] [] | + iso_639_5 | | + jwhois | [] [] [] [] | + kbd | [] [] [] | + klavaro | [] [] [] [] [] | + ld | [] [] [] [] | + leafpad | [] [] [] [] [] [] [] () | + libc | [] [] [] [] [] | + libexif | [] | + libextractor | | + libgnutls | [] | + libgphoto2 | [] [] | + libgphoto2_port | [] [] | + libgsasl | [] [] [] [] | + libiconv | [] [] [] [] [] [] [] | + libidn | [] [] [] [] | + liferea | [] [] [] [] [] | + lilypond | [] | + lordsawar | | + lprng | [] | + lynx | [] [] [] [] | + m4 | [] [] [] [] [] | + mailfromd | | + mailutils | | + make | [] [] [] [] | + man-db | [] [] | + man-db-manpages | [] [] | + midi-instruments | [] [] [] [] [] [] [] [] [] | + minicom | [] [] [] | + mkisofs | [] [] | + myserver | [] | + nano | [] [] [] [] [] [] | + opcodes | [] [] [] | + parted | [] [] [] [] [] | + pies | | + pnmixer | [] [] | + popt | [] [] [] [] [] [] [] [] [] [] | + procps-ng | | + procps-ng-man | | + psmisc | [] [] [] [] | + pspp | [] [] | + pushover | [] | + pwdutils | [] | + pyspread | | + radius | [] | + recode | [] [] [] [] [] [] [] | + recutils | | + rpm | [] | + rush | [] | + sarg | | + sed | [] [] [] [] [] [] [] | + sharutils | | + shishi | | + skribilo | [] | + solfege | [] [] | + solfege-manual | | + spotmachine | | + sudo | [] [] [] [] | + sudoers | [] [] [] | + sysstat | [] [] [] [] | + tar | [] [] [] [] [] [] | + texinfo | [] [] [] | + texinfo_document | [] [] [] | + tigervnc | | + tin | | + tin-man | | + tracgoogleappsa... | [] [] [] [] | + trader | [] [] | + util-linux | [] | + ve | [] | + vice | () () | + vmm | | + vorbis-tools | [] [] | + wastesedge | [] | + wcd | | + wcd-man | | + wdiff | [] [] [] | + wget | [] [] [] [] | + wyslij-po | [] [] [] | + xboard | | + xdg-user-dirs | [] [] [] [] [] [] [] [] [] [] [] [] [] [] | + xkeyboard-config | [] [] [] [] [] [] | + +-------------------------------------------------+ + ga gd gl gu he hi hr hu hy ia id is it ja ka kk + 35 2 47 4 8 2 60 71 2 6 81 11 87 57 0 3 + + kn ko ku ky lg lt lv mk ml mn mr ms mt nb ne nl + +--------------------------------------------------+ + a2ps | [] [] | + aegis | [] | + anubis | [] [] [] | + aspell | [] [] | + bash | [] [] | + bfd | | + binutils | | + bison | [] | + bison-runtime | [] [] [] [] [] [] | + buzztrax | | + ccd2cue | | + ccide | [] [] | + cflow | [] | + clisp | [] | + coreutils | [] [] | + cpio | [] | + cppi | | + cpplib | [] | + cryptsetup | [] | + datamash | [] [] | + denemo | | + dfarc | [] [] | + dialog | [] [] [] [] [] [] | + dico | | + diffutils | [] [] [] | + dink | [] | + direvent | [] | + doodle | [] | + dos2unix | [] [] | + dos2unix-man | [] | + e2fsprogs | [] | + enscript | [] | + exif | [] [] [] | + fetchmail | [] | + findutils | [] [] | + flex | [] | + freedink | [] [] | + fusionforge | | + gas | | + gawk | [] | + gcal | | + gcc | | + gdbm | | + gettext-examples | [] [] [] [] [] [] | + gettext-runtime | [] [] [] | + gettext-tools | [] | + gjay | | + glunarclock | [] [] | + gnubiff | [] | + gnubik | [] [] | + gnucash | () () () () () () () [] | + gnuchess | [] [] | + gnulib | [] | + gnunet | | + gnunet-gtk | | + gold | | + gphoto2 | [] | + gprof | [] [] | + gramadoir | [] | + grep | [] [] | + grub | [] [] [] | + gsasl | [] | + gss | | + gst-plugins-bad | [] [] [] | + gst-plugins-base | [] [] [] | + gst-plugins-good | [] [] [] [] | + gst-plugins-ugly | [] [] [] [] [] | + gstreamer | [] [] [] | + gtick | [] | + gtkam | [] [] | + gtkspell | [] [] [] [] [] [] [] | + guix | | + guix-packages | | + gutenprint | [] | + hello | [] [] [] | + help2man | [] | + help2man-texi | | + hylafax | [] | + idutils | [] | + iso_15924 | () [] [] | + iso_3166 | [] [] [] () [] [] [] [] [] [] | + iso_3166_2 | () [] | + iso_4217 | () [] [] [] | + iso_639 | [] [] () [] [] [] [] | + iso_639_3 | [] () [] | + iso_639_5 | () | + jwhois | [] [] | + kbd | [] | + klavaro | [] [] | + ld | | + leafpad | [] [] [] [] [] | + libc | [] [] | + libexif | [] | + libextractor | [] | + libgnutls | [] [] | + libgphoto2 | [] | + libgphoto2_port | [] | + libgsasl | [] | + libiconv | [] [] | + libidn | [] | + liferea | [] [] [] | + lilypond | [] | + lordsawar | | + lprng | | + lynx | [] | + m4 | [] | + mailfromd | | + mailutils | | + make | [] [] | + man-db | [] | + man-db-manpages | [] | + midi-instruments | [] [] [] [] [] [] [] | + minicom | [] | + mkisofs | [] | + myserver | | + nano | [] [] [] | + opcodes | [] | + parted | [] [] | + pies | | + pnmixer | [] | + popt | [] [] [] [] [] | + procps-ng | | + procps-ng-man | | + psmisc | [] | + pspp | [] [] | + pushover | | + pwdutils | [] | + pyspread | | + radius | [] | + recode | [] [] | + recutils | [] | + rpm | [] | + rush | [] | + sarg | | + sed | [] [] | + sharutils | [] | + shishi | | + skribilo | | + solfege | [] [] | + solfege-manual | [] | + spotmachine | [] | + sudo | [] [] [] | + sudoers | [] [] [] | + sysstat | [] [] | + tar | [] [] [] | + texinfo | [] | + texinfo_document | [] | + tigervnc | [] | + tin | | + tin-man | | + tracgoogleappsa... | [] [] [] | + trader | [] | + util-linux | [] | + ve | [] | + vice | [] | + vmm | [] | + vorbis-tools | [] | + wastesedge | [] | + wcd | [] | + wcd-man | [] | + wdiff | [] | + wget | [] [] | + wyslij-po | [] | + xboard | [] | + xdg-user-dirs | [] [] [] [] [] [] [] [] [] [] [] | + xkeyboard-config | [] [] [] | + +--------------------------------------------------+ + kn ko ku ky lg lt lv mk ml mn mr ms mt nb ne nl + 5 15 4 6 0 13 23 3 3 3 4 11 2 42 1 125 + + nn or pa pl ps pt pt_BR ro ru rw sk sl sq sr + +------------------------------------------------+ + a2ps | [] [] [] [] [] [] [] | + aegis | [] [] | + anubis | [] [] [] | + aspell | [] [] [] [] [] [] [] | + bash | [] [] [] [] [] [] | + bfd | [] [] | + binutils | [] [] | + bison | [] [] [] | + bison-runtime | [] [] [] [] [] [] [] [] | + buzztrax | [] | + ccd2cue | [] [] | + ccide | [] [] [] | + cflow | [] [] [] | + clisp | [] | + coreutils | [] [] [] [] | + cpio | [] [] [] | + cppi | [] [] [] | + cpplib | [] [] [] | + cryptsetup | [] [] [] | + datamash | [] [] | + denemo | | + dfarc | [] [] [] | + dialog | [] [] [] [] [] [] [] | + dico | [] | + diffutils | [] [] [] | + dink | | + direvent | [] [] [] | + doodle | [] [] | + dos2unix | [] [] [] [] | + dos2unix-man | [] [] | + e2fsprogs | [] | + enscript | [] [] [] [] [] [] | + exif | [] [] [] [] [] [] | + fetchmail | [] [] [] | + findutils | [] [] [] [] [] [] | + flex | [] [] [] [] [] | + freedink | [] [] [] [] [] | + fusionforge | | + gas | | + gawk | [] | + gcal | | + gcc | | + gdbm | [] [] [] | + gettext-examples | [] [] [] [] [] [] [] [] | + gettext-runtime | [] [] [] [] [] [] [] [] [] | + gettext-tools | [] [] [] [] [] [] [] | + gjay | [] | + glunarclock | [] [] [] [] [] [] | + gnubiff | [] | + gnubik | [] [] [] [] | + gnucash | () () () () () [] | + gnuchess | [] [] | + gnulib | [] [] [] [] [] | + gnunet | | + gnunet-gtk | | + gold | | + gphoto2 | [] [] [] [] [] | + gprof | [] [] [] [] | + gramadoir | [] [] | + grep | [] [] [] [] [] [] | + grub | [] [] [] [] [] | + gsasl | [] [] [] | + gss | [] [] [] [] | + gst-plugins-bad | [] [] [] [] [] | + gst-plugins-base | [] [] [] [] [] [] | + gst-plugins-good | [] [] [] [] [] [] [] | + gst-plugins-ugly | [] [] [] [] [] [] [] | + gstreamer | [] [] [] [] [] [] [] | + gtick | [] [] [] [] [] | + gtkam | [] [] [] [] [] [] | + gtkspell | [] [] [] [] [] [] [] [] [] | + guix | | + guix-packages | | + gutenprint | [] [] | + hello | [] [] [] [] [] [] | + help2man | [] [] [] [] | + help2man-texi | [] | + hylafax | | + idutils | [] [] [] | + iso_15924 | [] () [] [] [] [] | + iso_3166 | [] [] [] [] () [] [] [] [] [] [] [] [] | + iso_3166_2 | [] () [] | + iso_4217 | [] [] () [] [] [] [] [] | + iso_639 | [] [] [] () [] [] [] [] [] [] | + iso_639_3 | [] () | + iso_639_5 | () [] | + jwhois | [] [] [] [] | + kbd | [] [] | + klavaro | [] [] [] [] [] | + ld | | + leafpad | [] [] [] [] [] [] [] [] | + libc | [] [] [] | + libexif | [] () [] | + libextractor | [] | + libgnutls | [] | + libgphoto2 | [] | + libgphoto2_port | [] [] [] [] [] | + libgsasl | [] [] [] [] | + libiconv | [] [] [] [] [] | + libidn | [] [] [] | + liferea | [] [] [] [] () [] [] | + lilypond | | + lordsawar | | + lprng | [] | + lynx | [] [] | + m4 | [] [] [] [] [] | + mailfromd | [] | + mailutils | [] | + make | [] [] [] | + man-db | [] [] [] | + man-db-manpages | [] [] [] | + midi-instruments | [] [] [] [] [] [] [] [] | + minicom | [] [] [] [] | + mkisofs | [] [] [] | + myserver | [] [] | + nano | [] [] [] [] [] [] | + opcodes | | + parted | [] [] [] [] [] [] | + pies | [] | + pnmixer | [] | + popt | [] [] [] [] [] [] | + procps-ng | [] | + procps-ng-man | [] | + psmisc | [] [] [] [] | + pspp | [] [] | + pushover | | + pwdutils | [] | + pyspread | [] [] | + radius | [] [] | + recode | [] [] [] [] [] [] [] [] | + recutils | [] [] | + rpm | [] | + rush | [] [] [] | + sarg | [] [] | + sed | [] [] [] [] [] [] [] [] | + sharutils | [] [] [] | + shishi | [] [] | + skribilo | [] | + solfege | [] [] [] | + solfege-manual | [] [] | + spotmachine | [] [] | + sudo | [] [] [] [] [] [] | + sudoers | [] [] [] [] | + sysstat | [] [] [] [] [] | + tar | [] [] [] [] [] | + texinfo | [] [] [] | + texinfo_document | [] [] | + tigervnc | [] [] [] | + tin | [] | + tin-man | | + tracgoogleappsa... | [] [] [] [] | + trader | [] [] | + util-linux | [] [] | + ve | [] [] [] | + vice | | + vmm | | + vorbis-tools | [] [] [] | + wastesedge | | + wcd | | + wcd-man | | + wdiff | [] [] [] [] [] | + wget | [] [] [] [] [] | + wyslij-po | [] [] [] [] | + xboard | [] [] [] | + xdg-user-dirs | [] [] [] [] [] [] [] [] [] [] [] [] [] | + xkeyboard-config | [] [] [] [] | + +------------------------------------------------+ + nn or pa pl ps pt pt_BR ro ru rw sk sl sq sr + 7 3 6 114 1 12 88 32 82 3 40 45 7 101 + + sv sw ta te tg th tr uk ur vi wa wo zh_CN + +----------------------------------------------+ + a2ps | [] [] [] [] [] | + aegis | [] | + anubis | [] [] [] [] | + aspell | [] [] [] [] [] | + bash | [] [] [] [] | + bfd | [] [] [] | + binutils | [] [] [] | + bison | [] [] [] [] | + bison-runtime | [] [] [] [] [] [] | + buzztrax | [] [] [] | + ccd2cue | [] [] [] | + ccide | [] [] [] [] | + cflow | [] [] [] [] | + clisp | | + coreutils | [] [] [] | + cpio | [] [] [] [] [] | + cppi | [] [] [] [] | + cpplib | [] [] [] [] [] | + cryptsetup | [] [] [] | + datamash | [] [] [] | + denemo | [] | + dfarc | [] [] | + dialog | [] [] [] [] [] [] | + dico | [] | + diffutils | [] [] [] [] [] | + dink | [] | + direvent | [] [] | + doodle | [] [] | + dos2unix | [] [] [] [] | + dos2unix-man | [] [] [] | + e2fsprogs | [] [] [] [] | + enscript | [] [] [] [] | + exif | [] [] [] [] [] | + fetchmail | [] [] [] [] | + findutils | [] [] [] [] [] | + flex | [] [] [] [] | + freedink | [] [] [] | + fusionforge | | + gas | [] | + gawk | [] [] [] | + gcal | [] [] [] | + gcc | [] | + gdbm | [] [] | + gettext-examples | [] [] [] [] [] | + gettext-runtime | [] [] [] [] [] | + gettext-tools | [] [] [] [] [] | + gjay | [] [] [] | + glunarclock | [] [] [] [] | + gnubiff | [] [] | + gnubik | [] [] [] [] | + gnucash | () () () () [] | + gnuchess | [] [] [] | + gnulib | [] [] [] [] | + gnunet | | + gnunet-gtk | | + gold | [] [] | + gphoto2 | [] [] [] [] | + gprof | [] [] [] [] | + gramadoir | [] [] [] | + grep | [] [] [] [] [] | + grub | [] [] [] [] | + gsasl | [] [] [] [] | + gss | [] [] [] | + gst-plugins-bad | [] [] [] [] [] | + gst-plugins-base | [] [] [] [] [] | + gst-plugins-good | [] [] [] [] [] | + gst-plugins-ugly | [] [] [] [] [] | + gstreamer | [] [] [] [] [] | + gtick | [] [] [] | + gtkam | [] [] [] [] | + gtkspell | [] [] [] [] [] [] [] | + guix | | + guix-packages | | + gutenprint | [] [] [] [] | + hello | [] [] [] [] [] [] | + help2man | [] [] [] | + help2man-texi | [] | + hylafax | [] | + idutils | [] [] [] | + iso_15924 | [] () [] [] () [] | + iso_3166 | [] [] () [] [] () [] [] | + iso_3166_2 | () [] [] () [] | + iso_4217 | [] () [] [] () [] | + iso_639 | [] [] [] () [] [] () [] [] | + iso_639_3 | [] () [] [] () | + iso_639_5 | () [] () | + jwhois | [] [] [] [] | + kbd | [] [] [] [] | + klavaro | [] [] [] [] [] [] | + ld | [] [] [] [] [] | + leafpad | [] [] [] [] [] [] | + libc | [] [] [] [] [] | + libexif | [] [] () | + libextractor | [] [] | + libgnutls | [] [] [] [] | + libgphoto2 | [] [] [] | + libgphoto2_port | [] [] [] [] | + libgsasl | [] [] [] [] | + libiconv | [] [] [] [] [] | + libidn | () [] [] [] | + liferea | [] [] [] [] [] | + lilypond | [] | + lordsawar | | + lprng | [] | + lynx | [] [] [] [] | + m4 | [] [] [] | + mailfromd | [] [] | + mailutils | [] | + make | [] [] [] [] | + man-db | [] [] [] | + man-db-manpages | [] [] | + midi-instruments | [] [] [] [] [] [] | + minicom | [] [] | + mkisofs | [] [] [] | + myserver | [] | + nano | [] [] [] [] | + opcodes | [] [] [] | + parted | [] [] [] [] [] | + pies | [] [] | + pnmixer | [] [] [] | + popt | [] [] [] [] [] [] [] | + procps-ng | [] [] | + procps-ng-man | [] | + psmisc | [] [] [] [] | + pspp | [] [] [] | + pushover | [] | + pwdutils | [] [] | + pyspread | [] | + radius | [] [] | + recode | [] [] [] [] | + recutils | [] [] [] | + rpm | [] [] [] [] | + rush | [] [] | + sarg | | + sed | [] [] [] [] [] | + sharutils | [] [] [] [] | + shishi | [] [] | + skribilo | [] [] | + solfege | [] [] [] [] | + solfege-manual | [] | + spotmachine | [] [] [] | + sudo | [] [] [] [] [] | + sudoers | [] [] [] [] | + sysstat | [] [] [] [] [] | + tar | [] [] [] [] [] | + texinfo | [] [] [] | + texinfo_document | [] | + tigervnc | [] [] [] | + tin | [] | + tin-man | | + tracgoogleappsa... | [] [] [] [] [] | + trader | [] | + util-linux | [] [] [] [] | + ve | [] [] [] [] | + vice | () () | + vmm | | + vorbis-tools | [] [] | + wastesedge | | + wcd | [] [] [] | + wcd-man | [] | + wdiff | [] [] [] [] | + wget | [] [] [] | + wyslij-po | [] [] | + xboard | [] [] | + xdg-user-dirs | [] [] [] [] [] [] [] [] | + xkeyboard-config | [] [] [] [] | + +----------------------------------------------+ + sv sw ta te tg th tr uk ur vi wa wo zh_CN + 106 1 4 3 0 13 51 115 1 125 7 1 100 + + zh_HK zh_TW + +-------------+ + a2ps | | 30 + aegis | | 9 + anubis | | 19 + aspell | | 29 + bash | [] | 23 + bfd | | 11 + binutils | | 12 + bison | [] | 18 + bison-runtime | [] | 38 + buzztrax | | 9 + ccd2cue | | 10 + ccide | | 17 + cflow | | 16 + clisp | | 10 + coreutils | | 18 + cpio | | 20 + cppi | | 17 + cpplib | [] | 19 + cryptsetup | | 14 + datamash | | 11 + denemo | | 5 + dfarc | | 17 + dialog | [] | 42 + dico | | 6 + diffutils | | 22 + dink | | 10 + direvent | | 11 + doodle | | 12 + dos2unix | [] | 18 + dos2unix-man | | 9 + e2fsprogs | | 15 + enscript | | 21 + exif | | 27 + fetchmail | | 19 + findutils | | 29 + flex | [] | 19 + freedink | | 24 + fusionforge | | 3 + gas | | 5 + gawk | | 13 + gcal | | 8 + gcc | | 2 + gdbm | | 10 + gettext-examples | [] [] | 40 + gettext-runtime | [] [] | 35 + gettext-tools | [] | 24 + gjay | | 9 + glunarclock | [] | 27 + gnubiff | | 9 + gnubik | | 19 + gnucash | () | 6 + gnuchess | | 11 + gnulib | | 23 + gnunet | | 1 + gnunet-gtk | | 1 + gold | | 7 + gphoto2 | [] | 19 + gprof | | 21 + gramadoir | | 14 + grep | [] | 31 + grub | | 21 + gsasl | [] | 19 + gss | | 17 + gst-plugins-bad | | 21 + gst-plugins-base | | 27 + gst-plugins-good | | 32 + gst-plugins-ugly | | 34 + gstreamer | [] | 32 + gtick | | 19 + gtkam | | 24 + gtkspell | [] [] | 48 + guix | | 2 + guix-packages | | 0 + gutenprint | | 15 + hello | [] | 30 + help2man | | 18 + help2man-texi | | 5 + hylafax | | 5 + idutils | | 14 + iso_15924 | [] | 23 + iso_3166 | [] [] | 58 + iso_3166_2 | | 9 + iso_4217 | [] [] | 28 + iso_639 | [] [] | 46 + iso_639_3 | | 10 + iso_639_5 | | 2 + jwhois | [] | 20 + kbd | | 17 + klavaro | | 30 + ld | [] | 15 + leafpad | [] | 39 + libc | [] | 24 + libexif | | 10 + libextractor | | 5 + libgnutls | | 13 + libgphoto2 | | 10 + libgphoto2_port | [] | 19 + libgsasl | | 18 + libiconv | [] | 29 + libidn | | 17 + liferea | | 29 + lilypond | | 11 + lordsawar | | 3 + lprng | | 3 + lynx | | 19 + m4 | [] | 22 + mailfromd | | 4 + mailutils | | 6 + make | | 19 + man-db | | 15 + man-db-manpages | | 10 + midi-instruments | [] | 43 + minicom | [] | 17 + mkisofs | | 13 + myserver | | 9 + nano | [] | 30 + opcodes | | 12 + parted | [] | 23 + pies | | 4 + pnmixer | | 9 + popt | [] | 36 + procps-ng | | 5 + procps-ng-man | | 4 + psmisc | [] | 22 + pspp | | 13 + pushover | | 6 + pwdutils | | 8 + pyspread | | 6 + radius | | 9 + recode | | 31 + recutils | | 10 + rpm | [] | 13 + rush | | 10 + sarg | | 4 + sed | [] | 35 + sharutils | | 13 + shishi | | 7 + skribilo | | 7 + solfege | | 21 + solfege-manual | | 9 + spotmachine | | 11 + sudo | | 26 + sudoers | | 22 + sysstat | | 23 + tar | [] | 30 + texinfo | | 17 + texinfo_document | | 13 + tigervnc | | 14 + tin | [] | 7 + tin-man | | 1 + tracgoogleappsa... | [] | 22 + trader | | 12 + util-linux | | 13 + ve | | 14 + vice | | 1 + vmm | | 3 + vorbis-tools | | 13 + wastesedge | | 3 + wcd | | 8 + wcd-man | | 3 + wdiff | [] | 23 + wget | | 21 + wyslij-po | | 14 + xboard | | 10 + xdg-user-dirs | [] [] | 68 + xkeyboard-config | [] | 28 + +-------------+ + 89 teams zh_HK zh_TW + 166 domains 7 42 2809 + + Some counters in the preceding matrix are higher than the number of +visible blocks let us expect. This is because a few extra PO files are +used for implementing regional variants of languages, or language +dialects. + + For a PO file in the matrix above to be effective, the package to +which it applies should also have been internationalized and distributed +as such by its maintainer. There might be an observable lag between the +mere existence a PO file and its wide availability in a distribution. + + If Jun 2014 seems to be old, you may fetch a more recent copy of this +'ABOUT-NLS' file on most GNU archive sites. The most up-to-date matrix +with full percentage details can be found at +'http://translationproject.org/extra/matrix.html'. + +1.5 Using 'gettext' in new packages +=================================== + +If you are writing a freely available program and want to +internationalize it you are welcome to use GNU 'gettext' in your +package. Of course you have to respect the GNU Lesser General Public +License which covers the use of the GNU 'gettext' library. This means +in particular that even non-free programs can use 'libintl' as a shared +library, whereas only free software can use 'libintl' as a static +library or use modified versions of 'libintl'. + + Once the sources are changed appropriately and the setup can handle +the use of 'gettext' the only thing missing are the translations. The +Free Translation Project is also available for packages which are not +developed inside the GNU project. Therefore the information given above +applies also for every other Free Software Project. Contact +'coordinator@translationproject.org' to make the '.pot' files available +to the translation teams. diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000..df2f7661 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,256 @@ +# 2018 (c) Juan G. Victores, Bartek Łukawski, Stephen Sinclair +# CopyPolicy: RtMidi license. + +# Set minimum CMake required version for this project. +cmake_minimum_required(VERSION 3.0 FATAL_ERROR) + +# Define a C++ project. +project(RtMidi LANGUAGES CXX) + +# Check for Jack (any OS) +find_library(JACK_LIB jack) +find_package(PkgConfig) +pkg_check_modules(jack jack) +if(JACK_LIB OR jack_FOUND) + set(HAVE_JACK TRUE) +endif() + +# Necessary for Windows +if(WIN32) + set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) + set(CMAKE_DEBUG_POSTFIX "d") +endif() + +# Build Options +option(BUILD_SHARED_LIBS "Compile library shared lib." TRUE) +option(BUILD_STATIC_LIBS "Compile library static lib." TRUE) +option(BUILD_TESTING "Compile test programs." TRUE) +set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Build type (Release,Debug)") + +# API Options +option(RTMIDI_API_JACK "Compile with JACK support." ${HAVE_JACK}) +if(UNIX AND NOT APPLE) + option(RTMIDI_API_ALSA "Compile with ALSA support." ON) +endif() +option(RTMIDI_API_WINMM "Compile with WINMM support." ${WIN32}) +option(RTMIDI_API_CORE "Compile with CoreMIDI support." ${APPLE}) + +# Add -Wall if possible +if (CMAKE_COMPILER_IS_GNUCXX) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") +endif (CMAKE_COMPILER_IS_GNUCXX) + +# Add debug flags +if (CMAKE_BUILD_TYPE STREQUAL "Debug") + add_definitions(-D__RTMIDI_DEBUG__) + if (CMAKE_COMPILER_IS_GNUCXX) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror") + endif (CMAKE_COMPILER_IS_GNUCXX) +endif () + +# Read libtool version info from configure.ac +set(R "m4_define\\(\\[lt_([a-z]+)\\], ([0-9]+)\\)") +file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/configure.ac" CONFIGAC + REGEX ${R}) +foreach(_S ${CONFIGAC}) + string(REGEX REPLACE ${R} "\\1" k ${_S}) + string(REGEX REPLACE ${R} "\\2" v ${_S}) + set(SO_${k} ${v}) +endforeach() +math(EXPR SO_current_minus_age "${SO_current} - ${SO_age}") +set(SO_VER "${SO_current_minus_age}") +set(FULL_VER "${SO_current_minus_age}.${SO_revision}.${SO_age}") + +# Read package version info from configure.ac +set(R "AC_INIT\\(RtMidi, ([0-9\\.]+),.*\\)") +file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/configure.ac" CONFIGAC + REGEX ${R}) +string(REGEX REPLACE ${R} "\\1" PACKAGE_VERSION ${CONFIGAC}) + +# Init variables +set(rtmidi_SOURCES RtMidi.cpp RtMidi.h rtmidi_c.cpp rtmidi_c.h) +set(LINKLIBS) +set(INCDIRS) +set(PKGCONFIG_REQUIRES) +set(API_DEFS) +set(API_LIST) + +# Tweak API-specific configuration. + +# Jack +if(RTMIDI_API_JACK) + if (NOT HAVE_JACK) + message(FATAL_ERROR "Jack API requested but no Jack dev libraries found") + endif() + set(NEED_PTHREAD ON) + list(APPEND PKGCONFIG_REQUIRES "jack") + list(APPEND API_DEFS "-D__UNIX_JACK__") + list(APPEND API_LIST "jack") + if(jack_FOUND) + list(APPEND LINKLIBS ${jack_LIBRARIES}) + list(APPEND INCDIRS ${jack_INCLUDEDIR}) + else() + list(APPEND LINKLIBS ${JACK_LIB}) + endif() +endif() + +# ALSA +if(RTMIDI_API_ALSA) + set(NEED_PTHREAD ON) + find_package(ALSA) + if (NOT ALSA_FOUND) + message(FATAL_ERROR "ALSA API requested but no ALSA dev libraries found") + endif() + list(APPEND INCDIRS ${ALSA_INCLUDE_DIR}) + list(APPEND LINKLIBS ${ALSA_LIBRARY}) + list(APPEND PKGCONFIG_REQUIRES "alsa") + list(APPEND API_DEFS "-D__LINUX_ALSA__") + list(APPEND API_LIST "alsa") +endif() + +# WinMM +if(RTMIDI_API_WINMM) + list(APPEND API_DEFS "-D__WINDOWS_MM__") + list(APPEND API_LIST "winmm") + list(APPEND LINKLIBS winmm) +endif() + +# CoreMIDI +if(RTMIDI_API_CORE) + list(APPEND API_DEFS "-D__MACOSX_CORE__") + list(APPEND LINKLIBS "-framework CoreServices") + list(APPEND LINKLIBS "-framework CoreAudio") + list(APPEND LINKLIBS "-framework CoreMIDI") + list(APPEND LINKLIBS "-framework CoreFoundation") + list(APPEND LINKFLAGS "-Wl,-F/Library/Frameworks") +endif() + +# pthread +if (NEED_PTHREAD) + find_package(Threads REQUIRED + CMAKE_THREAD_PREFER_PTHREAD + THREADS_PREFER_PTHREAD_FLAG) + list(APPEND LINKLIBS Threads::Threads) +endif() + +# Create library targets. +cmake_policy(SET CMP0042 OLD) +set(LIB_TARGETS) +if(BUILD_SHARED_LIBS) + add_library(rtmidi SHARED ${rtmidi_SOURCES}) + list(APPEND LIB_TARGETS rtmidi) + + # Add headers destination for install rule. + set_target_properties(rtmidi PROPERTIES PUBLIC_HEADER RtMidi.h + SOVERSION ${SO_VER} + VERSION ${FULL_VER}) + + # Set include paths, populate target interface. + target_include_directories(rtmidi PRIVATE + $ + $ + ${INCDIRS}) + + # Set compile-time definitions + target_compile_definitions(rtmidi PRIVATE ${API_DEFS}) + + target_link_libraries(rtmidi ${LINKLIBS}) +endif() + +if(BUILD_STATIC_LIBS) + add_library(rtmidi_static STATIC ${rtmidi_SOURCES}) + list(APPEND LIB_TARGETS rtmidi_static) + + # Add headers destination for install rule. + set_target_properties(rtmidi_static PROPERTIES PUBLIC_HEADER RtMidi.h + SOVERSION ${SO_VER} + VERSION ${FULL_VER}) + + # Set include paths, populate target interface. + target_include_directories(rtmidi_static PRIVATE + $ + $ + ${INCDIRS}) + + # Set compile-time definitions + target_compile_definitions(rtmidi_static PRIVATE ${API_DEFS}) + + target_link_libraries(rtmidi_static ${LINKLIBS}) +endif() + +# Set standard installation directories. +include(GNUInstallDirs) + +# Add tests if requested. +if(BUILD_TESTING) + add_executable(cmidiin tests/cmidiin.cpp) + add_executable(midiclock tests/midiclock.cpp) + add_executable(midiout tests/midiout.cpp) + add_executable(midiprobe tests/midiprobe.cpp) + add_executable(qmidiin tests/qmidiin.cpp) + add_executable(sysextest tests/sysextest.cpp) + list(GET LIB_TARGETS 0 LIBRTMIDI) + set_target_properties(cmidiin midiclock midiout midiprobe qmidiin sysextest + PROPERTIES RUNTIME_OUTPUT_DIRECTORY tests + INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR} + LINK_LIBRARIES ${LIBRTMIDI}) +endif() + +# Set standard installation directories. +include(GNUInstallDirs) + +# Message +string(REPLACE ";" " " apilist "${API_LIST}") +message(STATUS "Compiling with support for: ${apilist}") + +# PkgConfig file +string(REPLACE ";" " " req "${PKGCONFIG_REQUIRES}") +string(REPLACE ";" " " api "${API_DEFS}") +configure_file("rtmidi.pc.in" "rtmidi.pc" @ONLY) + +# Add install rule. +install(TARGETS ${LIB_TARGETS} + EXPORT RtMidiTargets + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) + +# Store the package in the user registry. +export(PACKAGE RtMidi) + +# Set installation path for CMake files. +if(WIN32) + set(RTMIDI_CMAKE_DESTINATION cmake) +else() + set(RTMIDI_CMAKE_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/RtMidi) +endif() + +# Create CMake configuration export file. +file(WRITE ${CMAKE_BINARY_DIR}/RtMidiConfig.cmake "include(\${CMAKE_CURRENT_LIST_DIR}/RtMidiTargets.cmake)") + +# Install CMake configuration export file. +install(FILES ${CMAKE_BINARY_DIR}/RtMidiConfig.cmake + DESTINATION ${RTMIDI_CMAKE_DESTINATION}) + +# Export library target (build-tree). +export(EXPORT RtMidiTargets + NAMESPACE RtMidi::) + +# Export library target (install-tree). +install(EXPORT RtMidiTargets + DESTINATION ${RTMIDI_CMAKE_DESTINATION} + NAMESPACE RtMidi::) + +# Configure uninstall target. +configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/RtMidiConfigUninstall.cmake.in" + "${CMAKE_BINARY_DIR}/RtMidiConfigUninstall.cmake" @ONLY) + +# Create uninstall target. +add_custom_target(uninstall + COMMAND ${CMAKE_COMMAND} -P ${CMAKE_BINARY_DIR}/RtMidiConfigUninstall.cmake) + +install( + FILES ${CMAKE_CURRENT_BINARY_DIR}/rtmidi.pc + DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 00000000..e08af61f --- /dev/null +++ b/Makefile.am @@ -0,0 +1,13 @@ +ACLOCAL_AMFLAGS = -I m4 -I rtmidi-m4 --install +SUBDIRS = po +if MAKE_DOC +SUBDIRS += doc +endif +RTMIDICONFIGRPATH = config/config.rpath +DLLPROGRAMS = $(check_PROGRAMS) +check_PROGRAMS = +TESTS = +CLEANFILES = +DISTCLEANFILES = + +include %D%/Makefile.library diff --git a/Makefile.in b/Makefile.in deleted file mode 100644 index 82ad7ad7..00000000 --- a/Makefile.in +++ /dev/null @@ -1,77 +0,0 @@ -### Do not edit -- Generated by 'configure --with-whatever' from Makefile.in -### RtMidi library Makefile - -RM = /bin/rm -LN = /bin/ln - -OBJECTS = RtMidi.o - -LIBNAME = librtmidi -STATIC = $(LIBNAME).a -SHARED = @sharedlib@ -RELEASE = 2.1.0 -MAJOR = 2 -LIBRARIES = $(STATIC) $(SHARED) - -CC = @CXX@ -AR = @AR@ -RANLIB = @RANLIB@ - -DEFS = @CPPFLAGS@ -CFLAGS = @CXXFLAGS@ -Iinclude -fPIC - -PREFIX = @prefix@ - -all : $(LIBRARIES) - -tests: - cd tests && $(MAKE) all - -$(LIBRARIES): $(OBJECTS) - $(AR) ruv $(STATIC) $(OBJECTS) - ranlib $(STATIC) - $(CC) -fPIC @libflags@ $(OBJECTS) @LIBS@ - $(LN) -sf @sharedname@ $(SHARED) - $(LN) -sf @sharedname@ $(SHARED).$(MAJOR) - -# $(CC) -shared $(OBJECTS) -o $(SHARED) @LIBS@ - -%.o : %.cpp - $(CC) $(CFLAGS) $(DEFS) -c $(<) -o $@ - -%.o : include/%.cpp - $(CC) $(CFLAGS) $(DEFS) -c $(<) -o $@ - -install: all - install --mode=755 $(STATIC) $(PREFIX)/lib/ - install --mode=755 @sharedname@ $(PREFIX)/lib/ - $(LN) -sf @sharedname@ $(PREFIX)/lib/$(SHARED) - $(LN) -sf @sharedname@ $(PREFIX)/lib/$(SHARED).$(MAJOR) - install --mode=644 $(LIBNAME).pc $(PREFIX)/lib/pkgconfig - install --mode=755 rtmidi-config $(PREFIX)/bin/ - install --mode=644 RtMidi.h RtError.h $(PREFIX)/include - -uninstall: - -@rm -vf $(patsubst %,$(PREFIX)/lib/%, $(LIBRARIES) $(SHARED).$(MAJOR) $(SHARED).$(RELEASE)) - -@rm -vf $(PREFIX)/lib/pkgconfig/$(LIBNAME).pc - -@rm -vf $(PREFIX)/bin/rtmidi-config - -clean : - $(RM) -f $(LIBRARIES) @sharedname@ $(SHARED)* - $(RM) -f $(OBJECTS) - $(RM) -f *~ - cd tests && $(MAKE) clean - -distclean: - $(RM) -f $(LIBRARIES) @sharedname@ $(SHARED)* - $(RM) -f $(OBJECTS) - $(RM) -f *~ - $(RM) -rf config.log config.status autom4te.cache Makefile rtmidi-config $(LIBNAME).pc - cd tests && $(MAKE) distclean - -strip : - strip $(LIBRARIES) - ranlib $(LIBRARIES) - cd tests && $(MAKE) strip - -.PHONY: strip distclean clean uninstall diff --git a/Makefile.library b/Makefile.library new file mode 100644 index 00000000..cb1b983e --- /dev/null +++ b/Makefile.library @@ -0,0 +1,59 @@ +# -*- makefile-automake -*- +RTMIDITESTCXXFLAGS = $(EXTRA_RTMIDITESTCXXFLAGS) -I$(top_srcdir)/%D% +RTMIDILIBRARYNAME = %D%/librtmidi@rtmidi_suffix@.la +RTMIDITESTLDFLAGS = $(EXTRA_RTMIDITESTLDFLAGS) $(RTMIDILIBRARYNAME) +lib_LTLIBRARIES += %D%/librtmidi@rtmidi_suffix@.la +DLLPROGRAMS += %D%/librtmidi@rtmidi_suffix@.* +DLLPROGRAMS += %D%/.libs/librtmidi@rtmidi_suffix@.* + +DISTCLEANFILES += \ + %D%/rtmidi@rtmidi_suffix@.pc \ + %D%/rtmidi@rtmidi_suffix@-config + +%C%_librtmidi@rtmidi_suffix@_la_LDFLAGS = \ + $(RTMIDI_LIBS) \ + $(LDADD) \ + -export-dynamic \ + -version-info @RTMIDI_SO_VERSION@ \ + -no-undefined \ + -v +%C%_librtmidi@rtmidi_suffix@_la_CXXFLAGS = \ + $(rtmidi_visibility) \ + $(CXXFLAGS) \ + $(CPPFLAGS) \ + $(RTMIDI_API) \ + $(RTMIDI_LIB_CFLAGS) \ + -DRTMIDI_NO_WARN_DEPRECATED +%C%_librtmidi@rtmidi_suffix@_la_SOURCES = \ + %D%/RtMidi.cpp \ + %D%/RtMidi.h \ + %D%/rtmidi_c.cpp \ + %D%/rtmidi_c.h + +%C%_librtmidi@rtmidi_suffix@_ladir = $(includedir)/rtmidi@rtmidi_suffix@ +%C%_librtmidi@rtmidi_suffix@_la_HEADERS = \ + %D%/RtMidi.h \ + %D%/rtmidi_c.h + + +EXTRA_DIST += \ + $(RTMIDICONFIGRPATH) \ + %D%/m4/ChangeLog \ + %D%/rtmidi-config.in \ + %D%/rtmidi.pc.in \ + %D%/autogen.sh \ + %D%/README.md \ + %D%/msw + +pkgconfigdatadir = $(libdir)/pkgconfig +pkgconfigdata_DATA = %D%/rtmidi@rtmidi_suffix@.pc + +%D%/rtmidi@rtmidi_suffix@.pc: %D%/rtmidi.pc + if cmp "$<" "$@" ; then : ; else cp "$<" "$@" ; fi +%D%/rtmidi@rtmidi_suffix@-config: %D%/rtmidi-config + if cmp "$<" "$@" ; then : ; else cp -a "$<" "$@" ; fi + + + + +include %D%/tests/Makefile.am diff --git a/README.md b/README.md new file mode 100644 index 00000000..1d9a603a --- /dev/null +++ b/README.md @@ -0,0 +1,142 @@ +[![Build Status](https://travis-ci.org/keinstein/rtmidi.svg?branch=master-ts)](https://travis-ci.org/keinstein/rtmidi)[![Build status](https://ci.appveyor.com/api/projects/status/ac98q210qscfjayk/branch/master-ts?svg=true)](https://ci.appveyor.com/project/keinstein/rtmidi/branch/travis-tests) + +Extended RtMidi fork for Mutabor, GUI based Software, and saving MIDI connections +================================================================================= + +A set of C++ classes that provide a common API for realtime MIDI input/output across Linux (ALSA & JACK), Macintosh OS X (CoreMIDI & JACK) and Windows (Multimedia). + +By Gary P. Scavone, 2003-2017. +Forked by Tobias Schlemmer, 2014-2018. + +This fork has been started because the original RtMidi did not work +for Mutabor and ALSA. Mutabor has a two-step activation scheme. The +MIDI configuration is set up while no connections are active. After +compiling the tuning logic all MIDI interfaces are activated at +once. Each MIDI connection that RtMidi makes is reported as MIDI +device again by RtMidi. This leads to a renumbering of all MIDI +endpoints which have a higher ALSA device ID than the current RtMidi +instance. The result is unexpected behaviour. + +As a side effect this library uses a different namespace and is more +C++-ish than the original RtMidi. + +Incompatible changes against upstream +------------------------------------- + +- The old API has been deprecated as there is no way to rely on + consecutive port numbers. It is always the responsibility of the + end user not to change the MIDI configuration between certain points + in the execution path of the library. Obviously they usually lack the + necessary information for that Currently, it is still available, but a + compiler warning is generated if applicable + +- `__MACOSX_CORE__` has been renamed to `__MACOSX_COREMIDI__` + +- The classes of RtMidi now reside in the namespace rtmidi. +- The beginning letters “Rt” are dropped from the names +- For easy adoption of the new interface wrappers for the old API are provided. +- The library uses backend provided port descriptors, now. This provides a more reliable port handling for changing environments (See below). + +- The way MIDI devices are enumerated has changed. The old way, using the ordinal number of MIDI devices works only in cases where MIDI devices are not added or removed during the program session. When a virtual MIDI port or USB MIDI device is added or removed the ordinal number of each of the other devices may change. + + Suppose your computer has the following list of MIDI devices. + 1. MIDI loopback device + 2. Removable USB MIDI device + 3. Another MIDI device + 4. Software MIDI Synth + 5. A virtual MIDI port + + After the software obtained this list, your friend remembers that he + must catch the next bus and unplugs his removable USB MIDI device. + The software does not recognize this removal and keeps the above list, + while the system has a new one: + 1. MIDI loopback device + 2. Another MIDI device + 3. Software MIDI Synth + 4. A virtual MIDI port + + Somehow you told the software to use the Software MIDI Synth. The + program stores the number 4 as it obtained during enumeration of the + MIDI devices. Instead of playing the music using your sound card it + sends the music to a different port. + + While this behaviour is only annoying in interactive environments it + results in unpredictable behaviour if several ports are opened at + once. E.g. in the ALSA backend every opened port results in an + aditional newly created virtual port. + + In order to avoid such problems, most backends identify ports (except + WinMM) by different data structures. + + The current version introduces a new class \ref rtmidi::PortDescriptor + in order to hide this implementation detail from the user code. In + order to avoid the above problems these are retrieved at once using \ref rtmidi::Midi::getPortList. + This new feature also allows to retreive the port descriptor of an open device using + \ref rtmidi::Midi::getDescriptor. The latter can be used to obtain + + +Compilation +----------- + +This distribution of RtMidi contains the following: + +- doc: RtMidi documentation (also online at http://music.mcgill.ca/~gary/rtmidi/) +- tests: example RtMidi programs + +On Unix systems, type `./configure` in the top level directory, then `make` in the tests/ directory to compile the test programs. In Windows, open the Visual C++ workspace file located in the tests/ directory. + +If you checked out the code from git, please run `./autogen.sh` before `./configure`. + +Overview +-------- + +RtMidi is a set of C++ classes (rtmidi::MidiIn, rtmidi::MidiOut, and API specific classes) that provide a common API (Application Programming Interface) for realtime MIDI input/output across Linux (ALSA, JACK), Macintosh OS X (CoreMIDI, JACK), and Windows (Multimedia Library) operating systems. RtMidi significantly simplifies the process of interacting with computer MIDI hardware and software. It was designed with the following goals: + + - object oriented C++ design + - simple, common API across all supported platforms + - only one header and one source file for easy inclusion in programming projects + - MIDI device enumeration + +MIDI input and output functionality are separated into two classes, RtMidiIn and RtMidiOut. Each class instance supports only a single MIDI connection. RtMidi does not provide timing functionality (i.e., output messages are sent immediately). Input messages are timestamped with delta times in seconds (via a double floating point type). MIDI data is passed to the user as raw bytes using an std::vector. + +Windows +------- + +In some cases, for example to use RtMidi with GS Synth, it may be necessary for your program to call CoInitializeEx and CoUninitialize on entry to and exit from the thread that uses RtMidi. + +Further reading +--------------- + +For complete documentation on the original RtMidi, see the doc directory of the distribution or surf to http://music.mcgill.ca/~gary/rtmidi/. + + +Legal and ethical +----------------- + +The RtMidi license is similar to the MIT License, with the added *feature* that modifications be sent to the developer. + + RtMidi: realtime MIDI i/o C++ classes + Copyright (c) 2003-2017 Gary P. Scavone + Forked by Tobias Schlemmer, 2014-2018. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation files + (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, + publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, + subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + Any person wishing to distribute modifications to the Software is asked to send the modifications to the original developer so that they can be incorporated into the canonical version. This is, + however, not a binding provision of this license. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR + ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/RtMidi.cpp b/RtMidi.cpp index 2101c377..b7113ad7 100644 --- a/RtMidi.cpp +++ b/RtMidi.cpp @@ -1,241 +1,726 @@ /**********************************************************************/ -/*! \class RtMidi - \brief An abstract base class for realtime MIDI input/output. +/*! \class Midi + \brief An abstract base class for realtime MIDI input/output. - This class implements some common functionality for the realtime - MIDI input/output subclasses RtMidiIn and RtMidiOut. + This class implements some common functionality for the realtime + MIDI input/output subclasses MidiIn and MidiOut. RtMidi WWW site: http://music.mcgill.ca/~gary/rtmidi/ - RtMidi: realtime MIDI i/o C++ classes - Copyright (c) 2003-2014 Gary P. Scavone - - Permission is hereby granted, free of charge, to any person - obtaining a copy of this software and associated documentation files - (the "Software"), to deal in the Software without restriction, - including without limitation the rights to use, copy, modify, merge, - publish, distribute, sublicense, and/or sell copies of the Software, - and to permit persons to whom the Software is furnished to do so, - subject to the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - Any person wishing to distribute modifications to the Software is - asked to send the modifications to the original developer so that - they can be incorporated into the canonical version. This is, - however, not a binding provision of this license. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR - ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF - CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + Midi: realtime MIDI i/o C++ classes + Copyright (c) 2003-2017 Gary P. Scavone + Forked by Tobias Schlemmer, 2014-2018. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation files + (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, + publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, + subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + Any person wishing to distribute modifications to the Software is + asked to send the modifications to the original developer so that + they can be incorporated into the canonical version. This is, + however, not a binding provision of this license. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR + ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**********************************************************************/ #include "RtMidi.h" #include +#include +#include +#include +#include +#ifndef RTMIDI_FALLTHROUGH +#define RTMIDI_FALLTHROUGH +#endif + +#if defined(__MACOSX_COREMIDI__) +#if TARGET_OS_IPHONE +#define AudioGetCurrentHostTime CAHostTimeBase::GetCurrentTime +#define AudioConvertHostTimeToNanos CAHostTimeBase::ConvertToNanos +#endif +#endif + +// Default for Windows is to add an identifier to the port names; this +// flag can be defined (e.g. in your project file) to disable this behaviour. +//#define RTMIDI_DO_NOT_ENSURE_UNIQUE_PORTNAMES + +// **************************************************************** // +// +// MidiInApi and MidiOutApi subclass prototypes. +// +// **************************************************************** // + +#if !defined(__LINUX_ALSA__) && !defined(__UNIX_JACK__) && !defined(__MACOSX_COREMIDI__) && !defined(__WINDOWS_MM__) + #define __RTMIDI_DUMMY__ +#endif + +RTMIDI_NAMESPACE_START +#if defined(__MACOSX_COREMIDI__) +RTMIDI_NAMESPACE_END +struct MIDIPacketList; +RTMIDI_NAMESPACE_START + +class MidiInCore: public MidiInApi +{ + public: + MidiInCore( const std::string &clientName, unsigned int queueSizeLimit ); + ~MidiInCore( void ); + ApiType getCurrentApi( void ) throw() { return rtmidi::MACOSX_CORE; }; + bool hasVirtualPorts() const { return true; } + void openPort( unsigned int portNumber, const std::string &portName ); + void openVirtualPort( const std::string &portName ); + void openPort( const PortDescriptor & port, const std::string &portName); + Pointer getDescriptor(bool local=false); + PortList getPortList(int capabilities); + void closePort( void ); + void setClientName( const std::string &clientName ); + void setPortName( const std::string &portName ); + unsigned int getPortCount( void ); + std::string getPortName( unsigned int portNumber ); + + protected: + static void midiInputCallback( const MIDIPacketList *list, + void *procRef, + void */*srcRef*/) throw(); + void initialize( const std::string& clientName ); + template + friend class CoreSequencer; +}; + +class MidiOutCore: public MidiOutApi +{ + public: + MidiOutCore( const std::string &clientName ); + ~MidiOutCore( void ); + ApiType getCurrentApi( void ) throw() { return rtmidi::MACOSX_CORE; }; + bool hasVirtualPorts() const { return true; } + void openPort( unsigned int portNumber, const std::string &portName ); + void openVirtualPort( const std::string &portName ); + void openPort( const PortDescriptor & port, const std::string &portName); + Pointer getDescriptor(bool local=false); + PortList getPortList(int capabilities); + void closePort( void ); + void setClientName( const std::string &clientName ); + void setPortName( const std::string &portName ); + unsigned int getPortCount( void ); + std::string getPortName( unsigned int portNumber ); + void sendMessage( const unsigned char *message, size_t size ); + + protected: + void initialize( const std::string& clientName ); +}; + +#endif + +#if defined(__UNIX_JACK__) + +class MidiInJack: public MidiInApi +{ + public: + MidiInJack( const std::string &clientName, unsigned int queueSizeLimit ); + ~MidiInJack( void ); + ApiType getCurrentApi( void ) throw() { return rtmidi::UNIX_JACK; }; + bool hasVirtualPorts() const { return true; } + void openPort( unsigned int portNumber, const std::string &portName ); + void openVirtualPort( const std::string &portName ); + void openPort( const PortDescriptor & port, const std::string &portName); + Pointer getDescriptor(bool local=false); + PortList getPortList(int capabilities); + void closePort( void ); + void setClientName( const std::string &clientName ); + void setPortName( const std::string &portName); + unsigned int getPortCount( void ); + std::string getPortName( unsigned int portNumber ); + + protected: + std::string clientName; + + void connect( void ); + void initialize( const std::string& clientName ); +}; + +class MidiOutJack: public MidiOutApi +{ + public: + MidiOutJack( const std::string &clientName ); + ~MidiOutJack( void ); + ApiType getCurrentApi( void ) throw() { return rtmidi::UNIX_JACK; }; + bool hasVirtualPorts() const { return true; } + void openPort( unsigned int portNumber, const std::string &portName ); + void openVirtualPort( const std::string &portName ); + void openPort( const PortDescriptor & port, const std::string &portName); + Pointer getDescriptor(bool local=false); + PortList getPortList(int capabilities); + void closePort( void ); + void setClientName( const std::string &clientName ); + void setPortName( const std::string &portName); + unsigned int getPortCount( void ); + std::string getPortName( unsigned int portNumber ); + void sendMessage( const unsigned char *message, size_t size ); + + protected: + std::string clientName; + + void connect( void ); + void initialize( const std::string& clientName ); +}; + +#endif + +#if defined(__LINUX_ALSA__) + +class MidiInAlsa: public MidiInApi +{ + public: + MidiInAlsa( const std::string &clientName, unsigned int queueSizeLimit ); + ~MidiInAlsa( void ); + ApiType getCurrentApi( void ) throw() { return rtmidi::LINUX_ALSA; }; + bool hasVirtualPorts() const { return true; } + void openPort( unsigned int portNumber, const std::string &portName ); + void openVirtualPort( const std::string &portName ); + void openPort( const PortDescriptor & port, const std::string &portName); + Pointer getDescriptor(bool local=false); + PortList getPortList(int capabilities); + void closePort( void ); + void setClientName( const std::string &clientName ); + void setPortName( const std::string &portName); + unsigned int getPortCount( void ); + std::string getPortName( unsigned int portNumber ); + + protected: + static void * alsaMidiHandler( void *ptr ) throw(); + void initialize( const std::string &clientName ); + friend struct AlsaMidiData; +}; + +class MidiOutAlsa: public MidiOutApi +{ + public: + MidiOutAlsa( const std::string &clientName ); + ~MidiOutAlsa( void ); + ApiType getCurrentApi( void ) throw() { return rtmidi::LINUX_ALSA; }; + bool hasVirtualPorts() const { return true; } + void openPort( unsigned int portNumber, const std::string &portName ); + void openVirtualPort( const std::string &portName ); + void openPort( const PortDescriptor & port, const std::string &portName); + Pointer getDescriptor(bool local=false); + PortList getPortList(int capabilities); + void closePort( void ); + void setClientName( const std::string &clientName ); + void setPortName( const std::string &portName); + unsigned int getPortCount( void ); + std::string getPortName( unsigned int portNumber ); + void sendMessage( const unsigned char *message, size_t size ); + + protected: + void initialize( const std::string& clientName ); +}; + +#endif + +#if defined(__WINDOWS_MM__) + +class MidiInWinMM: public MidiInApi +{ + public: + MidiInWinMM( const std::string &clientName, unsigned int queueSizeLimit ); + ~MidiInWinMM( void ); + ApiType getCurrentApi( void ) throw() { return rtmidi::WINDOWS_MM; }; + bool hasVirtualPorts() const { return false; } + void openPort( unsigned int portNumber, const std::string &portName ); + void openVirtualPort( const std::string &portName ); + void openPort( const PortDescriptor & port, const std::string &portName); + Pointer getDescriptor(bool local=false); + PortList getPortList(int capabilities); + void closePort( void ); + void setClientName( const std::string &clientName ); + void setPortName( const std::string &portName ); + unsigned int getPortCount( void ); + std::string getPortName( unsigned int portNumber ); + + protected: + void initialize( const std::string& clientName ); + friend struct WinMMCallbacks; +}; + +class MidiOutWinMM: public MidiOutApi +{ + public: + MidiOutWinMM( const std::string &clientName ); + ~MidiOutWinMM( void ); + ApiType getCurrentApi( void ) throw() { return rtmidi::WINDOWS_MM; }; + bool hasVirtualPorts() const { return false; } + void openPort( unsigned int portNumber, const std::string &portName ); + void openVirtualPort( const std::string &portName ); + void openPort( const PortDescriptor & port, const std::string &portName); + Pointer getDescriptor(bool local=false); + PortList getPortList(int capabilities); + void closePort( void ); + void setClientName( const std::string &clientName ); + void setPortName( const std::string &portName ); + unsigned int getPortCount( void ); + std::string getPortName( unsigned int portNumber ); + void sendMessage( const unsigned char *message, size_t size ); + + protected: + void initialize( const std::string& clientName ); +}; + +#endif + +#if defined(__RTMIDI_DUMMY__) + +#define RTMIDI_CLASSNAME "MidiInDummy" +class MidiInDummy: public MidiInApi +{ + public: + MidiInDummy( const std::string &/*clientName*/, unsigned int queueSizeLimit ) + : MidiInApi( queueSizeLimit ) { + error( RTMIDI_ERROR(rtmidi_gettext("No valid MIDI interfaces. I'm using a dummy input interface that never receives anything."), + Error::WARNING) ); + } + ApiType getCurrentApi( void ) throw() { return rtmidi::DUMMY; } + bool hasVirtualPorts() const { return false; } + void openPort( unsigned int /*portNumber*/, const std::string &/*portName*/ ) {} + void openVirtualPort( const std::string &/*portName*/ ) {} + void openPort( const PortDescriptor & /* port */, + const std::string &/* portName */) {} + Pointer getDescriptor(bool /* local=false */) { + return 0; + } + PortList getPortList(int /* capabilities */) { + return PortList(); + } + void closePort( void ) {} + void setClientName( const std::string &/*clientName*/ ) {}; + void setPortName( const std::string &/*portName*/ ) {}; + unsigned int getPortCount( void ) { return 0; } + std::string getPortName( unsigned int /*portNumber*/ ) { return ""; } + + protected: + void initialize( const std::string& /*clientName*/ ) {} +}; + +class MidiOutDummy: public MidiOutApi +{ + public: + MidiOutDummy( const std::string &/*clientName*/ ) { + error( RTMIDI_ERROR(rtmidi_gettext("No valid MIDI interfaces. I'm using a dummy output interface that does nothing."), + Error::WARNING) ); + } + ApiType getCurrentApi( void ) throw() { return rtmidi::DUMMY; } + bool hasVirtualPorts() const { return false; } + void openPort( unsigned int /*portNumber*/, const std::string &/*portName*/ ) {} + void openVirtualPort( const std::string &/*portName*/ ) {} + void openPort( const PortDescriptor & /* port */, + const std::string &/* portName */) {} + Pointer getDescriptor(bool /* local=false */) { + return 0; + } + PortList getPortList(int /* capabilities */) { + return PortList(); + } + void closePort( void ) {} + void setClientName( const std::string &/*clientName*/ ) {}; + void setPortName( const std::string &/*portName*/ ) {}; + unsigned int getPortCount( void ) { return 0; } + std::string getPortName( unsigned int /*portNumber*/ ) { return ""; } + void sendMessage( const unsigned char * /*message*/, size_t /*size*/ ) {} + + protected: + void initialize( const std::string& /*clientName*/ ) {} +}; +#undef RTMIDI_CLASSNAME + +#endif + //*********************************************************************// // RtMidi Definitions //*********************************************************************// -RtMidi :: RtMidi() - : rtapi_(0) -{ +#ifdef RTMIDI_GETTEXT +const char * rtmidi_gettext (const char * s) { + init_rtmidi_gettext(); + return dgettext("rtmidi",s); } -RtMidi :: ~RtMidi() -{ - if ( rtapi_ ) - delete rtapi_; - rtapi_ = 0; +void init_rtmidi_gettext() { + static bool initialized = false; + if (initialized) + return; + bindtextdomain("rtmidi",LOCALEDIR); + initialized = true; +} +#endif + +//! The constructor. +Error::Error( const char * message, + Type type, + const char * class_name, + const char * function_name, + const char * file_name, + int line_number, ...) throw():exception(), + classname(class_name), + function(function_name), + file(file_name), + line(line_number), + type_(type) +{ +#ifdef RTMIDI_GETTEXT + message = rtmidi_gettext(message); +#endif + std::va_list args; + va_start(args,line_number); + size_t length; + length = vsnprintf(NULL,0,message,args); + if (length > 0) { + message_.resize(length+1); + std::vsnprintf(&(message_[0]),length+1,message,args); + message_.resize(length); + } else { + const char * fmt = gettext_noopt("Error formatting the error string:\n'%s'\nFound in %s::%s at \n%s:%d"); +#ifdef RTMIDI_GETTEXT + fmt = rtmidi_gettext(fmt); +#endif + + length = snprintf(NULL,0,fmt,message,class_name,function_name,file_name,line); + if (length > 0) { + message_.resize(length+1); + snprintf(&(message_[0]),length+1,fmt,message,class_name,function_name,file_name,line); + message_.resize(length); + } else { + const char * msg + = gettext_noopt("Error: could not format the error message"); +#ifdef RTMIDI_GETTEXT + msg = rtmidi_gettext(msg); +#endif + message_ = msg; + } + } + va_end(args); + } -std::string RtMidi :: getVersion( void ) throw() +//*********************************************************************// +// Midi Definitions +//*********************************************************************// +std::string Midi :: getVersion( void ) throw() { return std::string( RTMIDI_VERSION ); } -void RtMidi :: getCompiledApi( std::vector &apis ) throw() +void Midi :: getCompiledApi( std::vector &apis, bool preferSystem ) throw() { apis.clear(); // The order here will control the order of RtMidi's API search in // the constructor. -#if defined(__MACOSX_CORE__) - apis.push_back( MACOSX_CORE ); + + if (!preferSystem) { + // first check software and network backends +#if defined(__UNIX_JACK__) + apis.push_back( rtmidi::UNIX_JACK ); #endif -#if defined(__LINUX_ALSA__) - apis.push_back( LINUX_ALSA ); + } + + // check OS provided backends +#if defined(__MACOSX_COREMIDI__) + apis.push_back( rtmidi::MACOSX_CORE ); #endif -#if defined(__UNIX_JACK__) - apis.push_back( UNIX_JACK ); +#if defined(__LINUX_ALSA__) + apis.push_back( rtmidi::LINUX_ALSA ); #endif #if defined(__WINDOWS_MM__) - apis.push_back( WINDOWS_MM ); + apis.push_back( rtmidi::WINDOWS_MM ); #endif -#if defined(__WINDOWS_KS__) - apis.push_back( WINDOWS_KS ); + + if (preferSystem) { + // if we prefer OS provided backends, + // we should add the software backends, here. +#if defined(__UNIX_JACK__) + apis.push_back( rtmidi::UNIX_JACK ); #endif + } + + // DUMMY is a no-backend class so we add it at + // the very end. #if defined(__RTMIDI_DUMMY__) - apis.push_back( RTMIDI_DUMMY ); + apis.push_back( rtmidi::DUMMY ); +#endif +} + + + +void Midi :: error(Error e) +{ + + // use the callback if present. + if (rtapi_) { + rtapi_->error(e); + return; + } + + if ( e.getType() == Error::WARNING ) { + e.printMessage(); + } + else if ( e.getType() == Error::DEBUG_WARNING ) { +#if defined(__RTMIDI_DEBUG__) + e.printMessage(); #endif + } + else { + e.printMessage(); + throw e; + } } + //*********************************************************************// -// RtMidiIn Definitions +// MidiIn Definitions //*********************************************************************// - -void RtMidiIn :: openMidiApi( RtMidi::Api api, const std::string clientName, unsigned int queueSizeLimit ) +#define RTMIDI_CLASSNAME "MidiIn" +void MidiIn :: openMidiApi( ApiType api ) { - if ( rtapi_ ) - delete rtapi_; + delete rtapi_; rtapi_ = 0; + try { + switch (api) { + case rtmidi::UNIX_JACK: #if defined(__UNIX_JACK__) - if ( api == UNIX_JACK ) - rtapi_ = new MidiInJack( clientName, queueSizeLimit ); + rtapi_ = new MidiInJack( clientName, queueSizeLimit ); #endif + break; + case rtmidi::LINUX_ALSA: #if defined(__LINUX_ALSA__) - if ( api == LINUX_ALSA ) - rtapi_ = new MidiInAlsa( clientName, queueSizeLimit ); + rtapi_ = new MidiInAlsa( clientName, queueSizeLimit ); #endif + break; + case rtmidi::WINDOWS_MM: #if defined(__WINDOWS_MM__) - if ( api == WINDOWS_MM ) - rtapi_ = new MidiInWinMM( clientName, queueSizeLimit ); -#endif -#if defined(__WINDOWS_KS__) - if ( api == WINDOWS_KS ) - rtapi_ = new MidiInWinKS( clientName, queueSizeLimit ); + rtapi_ = new MidiInWinMM( clientName, queueSizeLimit ); #endif -#if defined(__MACOSX_CORE__) - if ( api == MACOSX_CORE ) - rtapi_ = new MidiInCore( clientName, queueSizeLimit ); + break; + case rtmidi::MACOSX_CORE: +#if defined(__MACOSX_COREMIDI__) + rtapi_ = new MidiInCore( clientName, queueSizeLimit ); #endif + break; + case rtmidi::DUMMY: #if defined(__RTMIDI_DUMMY__) - if ( api == RTMIDI_DUMMY ) - rtapi_ = new MidiInDummy( clientName, queueSizeLimit ); + rtapi_ = new MidiInDummy( clientName, queueSizeLimit ); #endif + break; + case rtmidi::ALL_API: + case rtmidi::UNSPECIFIED: + default: + break; + } + } catch (const Error & e) { + rtapi_ = 0; + throw; + } } -RtMidiIn :: RtMidiIn( RtMidi::Api api, const std::string clientName, unsigned int queueSizeLimit ) - : RtMidi() +MidiApiList MidiIn::queryApis; + +RTMIDI_DLL_PUBLIC MidiIn :: MidiIn( ApiType api, + const std::string &clientName, + unsigned int queueSize, + bool pfsystem ) + : Midi(&queryApis,pfsystem,clientName), + queueSizeLimit(queueSize) { - if ( api != UNSPECIFIED ) { + if ( api == rtmidi::ALL_API) { + if (!queryApis.empty()) { + rtapi_ = NULL; + return; + } + + std::vector< ApiType > apis; + getCompiledApi( apis ); + for ( unsigned int i=0; i apis; + std::vector< ApiType > apis; getCompiledApi( apis ); for ( unsigned int i=0; igetPortCount() ) break; + openMidiApi( apis[i] ); + if ( rtapi_ && rtapi_->getPortCount() ) break; } if ( rtapi_ ) return; - // It should not be possible to get here because the preprocessor - // definition __RTMIDI_DUMMY__ is automatically defined if no - // API-specific definitions are passed to the compiler. But just in - // case something weird happens, we'll throw an error. - std::string errorText = "RtMidiIn: no compiled API support found ... critical error!!"; - throw( RtMidiError( errorText, RtMidiError::UNSPECIFIED ) ); + // We may reach this point if the only API is JACK, + // but no JACK devices are found. + throw( RTMIDI_ERROR( gettext_noopt("No supported MIDI system has been found."), + Error::NO_DEVICES_FOUND ) ); } -RtMidiIn :: ~RtMidiIn() throw() +MidiIn :: ~MidiIn() throw() { } +#undef RTMIDI_CLASSNAME //*********************************************************************// -// RtMidiOut Definitions +// MidiOut Definitions //*********************************************************************// -void RtMidiOut :: openMidiApi( RtMidi::Api api, const std::string clientName ) +#define RTMIDI_CLASSNAME "MidiOut" +void MidiOut :: openMidiApi( ApiType api ) { - if ( rtapi_ ) - delete rtapi_; + delete rtapi_; rtapi_ = 0; + try { + switch (api) { + case rtmidi::UNIX_JACK: #if defined(__UNIX_JACK__) - if ( api == UNIX_JACK ) - rtapi_ = new MidiOutJack( clientName ); + rtapi_ = new MidiOutJack( clientName ); #endif + break; + case rtmidi::LINUX_ALSA: #if defined(__LINUX_ALSA__) - if ( api == LINUX_ALSA ) - rtapi_ = new MidiOutAlsa( clientName ); + rtapi_ = new MidiOutAlsa( clientName ); #endif + break; + case rtmidi::WINDOWS_MM: #if defined(__WINDOWS_MM__) - if ( api == WINDOWS_MM ) - rtapi_ = new MidiOutWinMM( clientName ); -#endif -#if defined(__WINDOWS_KS__) - if ( api == WINDOWS_KS ) - rtapi_ = new MidiOutWinKS( clientName ); + rtapi_ = new MidiOutWinMM( clientName ); #endif -#if defined(__MACOSX_CORE__) - if ( api == MACOSX_CORE ) - rtapi_ = new MidiOutCore( clientName ); + break; + case rtmidi::MACOSX_CORE: +#if defined(__MACOSX_COREMIDI__) + rtapi_ = new MidiOutCore( clientName ); #endif + break; + case rtmidi::DUMMY: #if defined(__RTMIDI_DUMMY__) - if ( api == RTMIDI_DUMMY ) - rtapi_ = new MidiOutDummy( clientName ); + rtapi_ = new MidiOutDummy( clientName ); #endif + break; + case rtmidi::UNSPECIFIED: + case rtmidi::ALL_API: + default: + break; + } + } catch (const Error & e) { + rtapi_ = 0; + throw; + } + } -RtMidiOut :: RtMidiOut( RtMidi::Api api, const std::string clientName ) + +MidiApiList MidiOut::queryApis; + +RTMIDI_DLL_PUBLIC MidiOut :: MidiOut( ApiType api, const std::string &clientName, bool pfsystem ) + : Midi(&queryApis, pfsystem, clientName) { - if ( api != UNSPECIFIED ) { + if ( api == rtmidi::ALL_API) { + if (!queryApis.empty()) { + rtapi_ = NULL; + return; + } + + std::vector< ApiType > apis; + getCompiledApi( apis ); + for ( unsigned int i=0; i apis; + std::vector< ApiType > apis; getCompiledApi( apis ); for ( unsigned int i=0; igetPortCount() ) break; + openMidiApi( apis[i] ); + if ( rtapi_ && rtapi_->getPortCount() ) break; } if ( rtapi_ ) return; - // It should not be possible to get here because the preprocessor - // definition __RTMIDI_DUMMY__ is automatically defined if no - // API-specific definitions are passed to the compiler. But just in - // case something weird happens, we'll thrown an error. - std::string errorText = "RtMidiOut: no compiled API support found ... critical error!!"; - throw( RtMidiError( errorText, RtMidiError::UNSPECIFIED ) ); + // We may reach this point, e.g. if JACK is the only + // compiled API, but no JACK devices are found. + throw( RTMIDI_ERROR(gettext_noopt("No supported MIDI system has been found."), + Error::NO_DEVICES_FOUND ) ); } -RtMidiOut :: ~RtMidiOut() throw() +MidiOut :: ~MidiOut() throw() { } +#undef RTMIDI_CLASSNAME -//*********************************************************************// -// Common MidiApi Definitions -//*********************************************************************// MidiApi :: MidiApi( void ) - : apiData_( 0 ), connected_( false ), errorCallback_(0) + : apiData_( 0 ), + connected_( false ), + firstErrorOccurred_ (false), + errorCallback_(0) { } @@ -243,38 +728,43 @@ MidiApi :: ~MidiApi( void ) { } -void MidiApi :: setErrorCallback( RtMidiErrorCallback errorCallback ) +void MidiApi :: setErrorCallback( ErrorCallback errorCallback, void *userData ) { - errorCallback_ = errorCallback; + errorCallback_ = new CompatibilityErrorInterface(errorCallback,userData); } -void MidiApi :: error( RtMidiError::Type type, std::string errorString ) +void MidiApi :: setErrorCallback(ErrorInterface * callback) { + errorCallback_ = callback; +} + + +void MidiApi :: error(Error e) { if ( errorCallback_ ) { - static bool firstErrorOccured = false; - if ( firstErrorOccured ) + if ( firstErrorOccurred_ ) return; - firstErrorOccured = true; - const std::string errorMessage = errorString; + firstErrorOccurred_ = true; + std::ostringstream s; + e.printMessage(s); - errorCallback_( type, errorMessage ); - firstErrorOccured = false; + errorCallback_->rtmidi_error(e); + firstErrorOccurred_ = false; return; } - if ( type == RtMidiError::WARNING ) { - std::cerr << '\n' << errorString << "\n\n"; + if ( e.getType() == Error::WARNING ) { + e.printMessage(); } - else if ( type == RtMidiError::DEBUG_WARNING ) { + else if ( e.getType() == Error::DEBUG_WARNING ) { #if defined(__RTMIDI_DEBUG__) - std::cerr << '\n' << errorString << "\n\n"; + e.printMessage(); #endif } else { - std::cerr << '\n' << errorString << "\n\n"; - throw RtMidiError( errorString, type ); + e.printMessage(); + throw e; } } @@ -282,89 +772,160 @@ void MidiApi :: error( RtMidiError::Type type, std::string errorString ) // Common MidiInApi Definitions //*********************************************************************// +#define RTMIDI_CLASSNAME "MidiInApi" MidiInApi :: MidiInApi( unsigned int queueSizeLimit ) - : MidiApi() + : MidiApi(), ignoreFlags(7), doInput(false), firstMessage(true), + userCallback(0), + continueSysex(false) { // Allocate the MIDI queue. - inputData_.queue.ringSize = queueSizeLimit; - if ( inputData_.queue.ringSize > 0 ) - inputData_.queue.ring = new MidiMessage[ inputData_.queue.ringSize ]; + queue.ringSize = queueSizeLimit; + if ( queue.ringSize > 0 ) + queue.ring = new MidiMessage[ queue.ringSize ]; } MidiInApi :: ~MidiInApi( void ) { + if (userCallback) + userCallback->delete_me(); // Delete the MIDI queue. - if ( inputData_.queue.ringSize > 0 ) delete [] inputData_.queue.ring; + if ( queue.ringSize > 0 ) delete [] queue.ring; +} + +void MidiInApi :: setCallback( MidiCallback callback, void *userData ) +{ + if ( userCallback ) { + error(RTMIDI_ERROR(gettext_noopt("A callback function is already set."), + Error::WARNING)); + return; + } + + if ( !callback ) { + error(RTMIDI_ERROR(gettext_noopt("The callback function value is invalid."), + Error::WARNING)); + return; + } + + userCallback = new CompatibilityMidiInterface(callback,userData); } -void MidiInApi :: setCallback( RtMidiIn::RtMidiCallback callback, void *userData ) +void MidiInApi :: setCallback( MidiInterface * callback ) { - if ( inputData_.usingCallback ) { - errorString_ = "MidiInApi::setCallback: a callback function is already set!"; - error( RtMidiError::WARNING, errorString_ ); + if ( userCallback ) { + error(RTMIDI_ERROR(gettext_noopt("A callback function is already set."), + Error::WARNING)); return; } if ( !callback ) { - errorString_ = "RtMidiIn::setCallback: callback function value is invalid!"; - error( RtMidiError::WARNING, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("The callback function value is invalid."), + Error::WARNING)); return; } - inputData_.userCallback = callback; - inputData_.userData = userData; - inputData_.usingCallback = true; + userCallback = callback; } void MidiInApi :: cancelCallback() { - if ( !inputData_.usingCallback ) { - errorString_ = "RtMidiIn::cancelCallback: no callback function was set!"; - error( RtMidiError::WARNING, errorString_ ); + if ( !userCallback ) { + error(RTMIDI_ERROR(gettext_noopt("No callback function was set."), + Error::WARNING)); return; } - inputData_.userCallback = 0; - inputData_.userData = 0; - inputData_.usingCallback = false; + userCallback->delete_me(); + userCallback = 0; } void MidiInApi :: ignoreTypes( bool midiSysex, bool midiTime, bool midiSense ) { - inputData_.ignoreFlags = 0; - if ( midiSysex ) inputData_.ignoreFlags = 0x01; - if ( midiTime ) inputData_.ignoreFlags |= 0x02; - if ( midiSense ) inputData_.ignoreFlags |= 0x04; + ignoreFlags = 0; + if ( midiSysex ) ignoreFlags = 0x01; + if ( midiTime ) ignoreFlags |= 0x02; + if ( midiSense ) ignoreFlags |= 0x04; } -double MidiInApi :: getMessage( std::vector *message ) +double MidiInApi :: getMessage( std::vector &message ) { - message->clear(); + message.clear(); + + if ( userCallback ) { + error(RTMIDI_ERROR(gettext_noopt("Returning an empty MIDI message as all input is handled by a callback function."), + Error::WARNING)); + return 0.0; + } - if ( inputData_.usingCallback ) { - errorString_ = "RtMidiIn::getNextMessage: a user callback is currently set for this port."; - error( RtMidiError::WARNING, errorString_ ); + double timeStamp; + if (!queue.pop(message, timeStamp)) return 0.0; + + return timeStamp; +} + +unsigned int MidiInApi::MidiQueue::size(unsigned int *__back, + unsigned int *__front) +{ + // Access back/front members exactly once and make stack copies for + // size calculation + unsigned int _back = back, _front = front, _size; + if (_back >= _front) + _size = _back - _front; + else + _size = ringSize - _front + _back; + + // Return copies of back/front so no new and unsynchronized accesses + // to member variables are needed. + if (__back) *__back = _back; + if (__front) *__front = _front; + return _size; +} + +// As long as we haven't reached our queue size limit, push the message. +bool MidiInApi::MidiQueue::push(const MidiInApi::MidiMessage& msg) +{ + // Local stack copies of front/back + unsigned int _back, _front, _size; + + // Get back/front indexes exactly once and calculate current size + _size = size(&_back, &_front); + + if ( _size < ringSize-1 ) + { + ring[_back] = msg; + back = (back+1)%ringSize; + return true; } - if ( inputData_.queue.size == 0 ) return 0.0; + return false; +} + +bool MidiInApi::MidiQueue::pop(std::vector &msg, double& timeStamp) +{ + // Local stack copies of front/back + unsigned int _back, _front, _size; + + // Get back/front indexes exactly once and calculate current size + _size = size(&_back, &_front); + + if (_size == 0) + return false; // Copy queued message to the vector pointer argument and then "pop" it. - std::vector *bytes = &(inputData_.queue.ring[inputData_.queue.front].bytes); - message->assign( bytes->begin(), bytes->end() ); - double deltaTime = inputData_.queue.ring[inputData_.queue.front].timeStamp; - inputData_.queue.size--; - inputData_.queue.front++; - if ( inputData_.queue.front == inputData_.queue.ringSize ) - inputData_.queue.front = 0; + msg.assign( ring[_front].bytes.begin(), ring[_front].bytes.end() ); + timeStamp = ring[_front].timeStamp; - return deltaTime; + // Update front + front = (front+1)%ringSize; + return true; } +#undef RTMIDI_CLASSNAME //*********************************************************************// // Common MidiOutApi Definitions //*********************************************************************// +#define RTMIDI_CLASSNAME "MidiOutApi" MidiOutApi :: MidiOutApi( void ) : MidiApi() { @@ -374,13 +935,38 @@ MidiOutApi :: ~MidiOutApi( void ) { } + +// trim from start +static inline std::string <rim(std::string &s) { + s.erase(s.begin(), + std::find_if(s.begin(), s.end(), [](int ch) { + return ! std::isspace(ch); + })); + return s; +} + +// trim from end +static inline std::string &rtrim(std::string &s) { + s.erase(std::find_if(s.rbegin(), s.rend(), [](int ch) { + return ! std::isspace(ch); + }).base(), s.end()); + return s; +} + +// trim from both ends +static inline std::string &trim(std::string &s) { + return ltrim(rtrim(s)); +} +RTMIDI_NAMESPACE_END +#undef RTMIDI_CLASSNAME + // *************************************************** // // // OS/API-specific methods. // // *************************************************** // -#if defined(__MACOSX_CORE__) +#if defined(__MACOSX_COREMIDI__) // The CoreMIDI API is based on the use of a callback function for // MIDI input. We convert the system specific time stamps to delta @@ -391,332 +977,70 @@ MidiOutApi :: ~MidiOutApi( void ) #include #include -// A structure to hold variables related to the CoreMIDI API -// implementation. -struct CoreMidiData { - MIDIClientRef client; - MIDIPortRef port; - MIDIEndpointRef endpoint; - MIDIEndpointRef destinationId; - unsigned long long lastTime; - MIDISysexSendRequest sysexreq; +RTMIDI_NAMESPACE_START +/*! An abstraction layer for the CORE sequencer layer. It provides + the following functionality: + - dynamic allocation of the sequencer + - optionallay avoid concurrent access to the CORE sequencer, + which is not thread proof. This feature is controlled by + the parameter \ref locking. +*/ + +/* A wrapper for temporary CFString objects */ +class CFStringWrapper { +public: + CFStringWrapper(const std::string &s): + cfname(CFStringCreateWithCStringNoCopy( NULL, + s.c_str(), + kCFStringEncodingUTF8, + kCFAllocatorNull)) + {} + CFStringWrapper(const char * s): + cfname(CFStringCreateWithCStringNoCopy( NULL, + s, + kCFStringEncodingUTF8, + kCFAllocatorNull)) + {} + ~CFStringWrapper() { + CFRelease(cfname); + } + + operator CFStringRef&() { return cfname; } +protected: + CFStringRef cfname; }; -//*********************************************************************// -// API: OS-X -// Class Definitions: MidiInCore -//*********************************************************************// +// This function was submitted by Douglas Casey Tucker and apparently +// derived largely from PortMidi. +// or copied from the Apple developer Q&A website +// https://developer.apple.com/library/mac/qa/qa1374/_index.html -static void midiInputCallback( const MIDIPacketList *list, void *procRef, void */*srcRef*/ ) +CFStringRef EndpointName( MIDIEndpointRef endpoint, bool isExternal ) { - MidiInApi::RtMidiInData *data = static_cast (procRef); - CoreMidiData *apiData = static_cast (data->apiData); - - unsigned char status; - unsigned short nBytes, iByte, size; - unsigned long long time; - - bool& continueSysex = data->continueSysex; - MidiInApi::MidiMessage& message = data->message; - - const MIDIPacket *packet = &list->packet[0]; - for ( unsigned int i=0; inumPackets; ++i ) { - - // My interpretation of the CoreMIDI documentation: all message - // types, except sysex, are complete within a packet and there may - // be several of them in a single packet. Sysex messages can be - // broken across multiple packets and PacketLists but are bundled - // alone within each packet (these packets do not contain other - // message types). If sysex messages are split across multiple - // MIDIPacketLists, they must be handled by multiple calls to this - // function. + CFMutableStringRef result = CFStringCreateMutable( NULL, 0 ); + CFStringRef str; - nBytes = packet->length; - if ( nBytes == 0 ) continue; + // Begin with the endpoint's name. + str = NULL; + MIDIObjectGetStringProperty( endpoint, kMIDIPropertyName, &str ); + if ( str != NULL ) { + CFStringAppend( result, str ); + CFRelease( str ); + } - // Calculate time stamp. + MIDIEntityRef entity = 0; + MIDIEndpointGetEntity( endpoint, &entity ); + if ( entity == 0 ) + // probably virtual + return result; - if ( data->firstMessage ) { - message.timeStamp = 0.0; - data->firstMessage = false; - } - else { - time = packet->timeStamp; - if ( time == 0 ) { // this happens when receiving asynchronous sysex messages - time = AudioGetCurrentHostTime(); - } - time -= apiData->lastTime; - time = AudioConvertHostTimeToNanos( time ); - if ( !continueSysex ) - message.timeStamp = time * 0.000000001; - } - apiData->lastTime = packet->timeStamp; - if ( apiData->lastTime == 0 ) { // this happens when receiving asynchronous sysex messages - apiData->lastTime = AudioGetCurrentHostTime(); - } - //std::cout << "TimeStamp = " << packet->timeStamp << std::endl; - - iByte = 0; - if ( continueSysex ) { - // We have a continuing, segmented sysex message. - if ( !( data->ignoreFlags & 0x01 ) ) { - // If we're not ignoring sysex messages, copy the entire packet. - for ( unsigned int j=0; jdata[j] ); - } - continueSysex = packet->data[nBytes-1] != 0xF7; - - if ( !( data->ignoreFlags & 0x01 ) && !continueSysex ) { - // If not a continuing sysex message, invoke the user callback function or queue the message. - if ( data->usingCallback ) { - RtMidiIn::RtMidiCallback callback = (RtMidiIn::RtMidiCallback) data->userCallback; - callback( message.timeStamp, &message.bytes, data->userData ); - } - else { - // As long as we haven't reached our queue size limit, push the message. - if ( data->queue.size < data->queue.ringSize ) { - data->queue.ring[data->queue.back++] = message; - if ( data->queue.back == data->queue.ringSize ) - data->queue.back = 0; - data->queue.size++; - } - else - std::cerr << "\nMidiInCore: message queue limit reached!!\n\n"; - } - message.bytes.clear(); - } - } - else { - while ( iByte < nBytes ) { - size = 0; - // We are expecting that the next byte in the packet is a status byte. - status = packet->data[iByte]; - if ( !(status & 0x80) ) break; - // Determine the number of bytes in the MIDI message. - if ( status < 0xC0 ) size = 3; - else if ( status < 0xE0 ) size = 2; - else if ( status < 0xF0 ) size = 3; - else if ( status == 0xF0 ) { - // A MIDI sysex - if ( data->ignoreFlags & 0x01 ) { - size = 0; - iByte = nBytes; - } - else size = nBytes - iByte; - continueSysex = packet->data[nBytes-1] != 0xF7; - } - else if ( status == 0xF1 ) { - // A MIDI time code message - if ( data->ignoreFlags & 0x02 ) { - size = 0; - iByte += 2; - } - else size = 2; - } - else if ( status == 0xF2 ) size = 3; - else if ( status == 0xF3 ) size = 2; - else if ( status == 0xF8 && ( data->ignoreFlags & 0x02 ) ) { - // A MIDI timing tick message and we're ignoring it. - size = 0; - iByte += 1; - } - else if ( status == 0xFE && ( data->ignoreFlags & 0x04 ) ) { - // A MIDI active sensing message and we're ignoring it. - size = 0; - iByte += 1; - } - else size = 1; - - // Copy the MIDI data to our vector. - if ( size ) { - message.bytes.assign( &packet->data[iByte], &packet->data[iByte+size] ); - if ( !continueSysex ) { - // If not a continuing sysex message, invoke the user callback function or queue the message. - if ( data->usingCallback ) { - RtMidiIn::RtMidiCallback callback = (RtMidiIn::RtMidiCallback) data->userCallback; - callback( message.timeStamp, &message.bytes, data->userData ); - } - else { - // As long as we haven't reached our queue size limit, push the message. - if ( data->queue.size < data->queue.ringSize ) { - data->queue.ring[data->queue.back++] = message; - if ( data->queue.back == data->queue.ringSize ) - data->queue.back = 0; - data->queue.size++; - } - else - std::cerr << "\nMidiInCore: message queue limit reached!!\n\n"; - } - message.bytes.clear(); - } - iByte += size; - } - } - } - packet = MIDIPacketNext(packet); - } -} - -MidiInCore :: MidiInCore( const std::string clientName, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) -{ - initialize( clientName ); -} - -MidiInCore :: ~MidiInCore( void ) -{ - // Close a connection if it exists. - closePort(); - - // Cleanup. - CoreMidiData *data = static_cast (apiData_); - MIDIClientDispose( data->client ); - if ( data->endpoint ) MIDIEndpointDispose( data->endpoint ); - delete data; -} - -void MidiInCore :: initialize( const std::string& clientName ) -{ - // Set up our client. - MIDIClientRef client; - OSStatus result = MIDIClientCreate( CFStringCreateWithCString( NULL, clientName.c_str(), kCFStringEncodingASCII ), NULL, NULL, &client ); - if ( result != noErr ) { - errorString_ = "MidiInCore::initialize: error creating OS-X MIDI client object."; - error( RtMidiError::DRIVER_ERROR, errorString_ ); - return; - } - - // Save our api-specific connection information. - CoreMidiData *data = (CoreMidiData *) new CoreMidiData; - data->client = client; - data->endpoint = 0; - apiData_ = (void *) data; - inputData_.apiData = (void *) data; -} - -void MidiInCore :: openPort( unsigned int portNumber, const std::string portName ) -{ - if ( connected_ ) { - errorString_ = "MidiInCore::openPort: a valid connection already exists!"; - error( RtMidiError::WARNING, errorString_ ); - return; - } - - CFRunLoopRunInMode( kCFRunLoopDefaultMode, 0, false ); - unsigned int nSrc = MIDIGetNumberOfSources(); - if (nSrc < 1) { - errorString_ = "MidiInCore::openPort: no MIDI input sources found!"; - error( RtMidiError::NO_DEVICES_FOUND, errorString_ ); - return; - } - - if ( portNumber >= nSrc ) { - std::ostringstream ost; - ost << "MidiInCore::openPort: the 'portNumber' argument (" << portNumber << ") is invalid."; - errorString_ = ost.str(); - error( RtMidiError::INVALID_PARAMETER, errorString_ ); - return; - } - - MIDIPortRef port; - CoreMidiData *data = static_cast (apiData_); - OSStatus result = MIDIInputPortCreate( data->client, - CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII ), - midiInputCallback, (void *)&inputData_, &port ); - if ( result != noErr ) { - MIDIClientDispose( data->client ); - errorString_ = "MidiInCore::openPort: error creating OS-X MIDI input port."; - error( RtMidiError::DRIVER_ERROR, errorString_ ); - return; - } - - // Get the desired input source identifier. - MIDIEndpointRef endpoint = MIDIGetSource( portNumber ); - if ( endpoint == 0 ) { - MIDIPortDispose( port ); - MIDIClientDispose( data->client ); - errorString_ = "MidiInCore::openPort: error getting MIDI input source reference."; - error( RtMidiError::DRIVER_ERROR, errorString_ ); - return; - } - - // Make the connection. - result = MIDIPortConnectSource( port, endpoint, NULL ); - if ( result != noErr ) { - MIDIPortDispose( port ); - MIDIClientDispose( data->client ); - errorString_ = "MidiInCore::openPort: error connecting OS-X MIDI input port."; - error( RtMidiError::DRIVER_ERROR, errorString_ ); - return; - } - - // Save our api-specific port information. - data->port = port; - - connected_ = true; -} - -void MidiInCore :: openVirtualPort( const std::string portName ) -{ - CoreMidiData *data = static_cast (apiData_); - - // Create a virtual MIDI input destination. - MIDIEndpointRef endpoint; - OSStatus result = MIDIDestinationCreate( data->client, - CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII ), - midiInputCallback, (void *)&inputData_, &endpoint ); - if ( result != noErr ) { - errorString_ = "MidiInCore::openVirtualPort: error creating virtual OS-X MIDI destination."; - error( RtMidiError::DRIVER_ERROR, errorString_ ); - return; - } - - // Save our api-specific connection information. - data->endpoint = endpoint; -} - -void MidiInCore :: closePort( void ) -{ - if ( connected_ ) { - CoreMidiData *data = static_cast (apiData_); - MIDIPortDispose( data->port ); - connected_ = false; - } -} - -unsigned int MidiInCore :: getPortCount() -{ - CFRunLoopRunInMode( kCFRunLoopDefaultMode, 0, false ); - return MIDIGetNumberOfSources(); -} - -// This function was submitted by Douglas Casey Tucker and apparently -// derived largely from PortMidi. -CFStringRef EndpointName( MIDIEndpointRef endpoint, bool isExternal ) -{ - CFMutableStringRef result = CFStringCreateMutable( NULL, 0 ); - CFStringRef str; - - // Begin with the endpoint's name. - str = NULL; - MIDIObjectGetStringProperty( endpoint, kMIDIPropertyName, &str ); - if ( str != NULL ) { - CFStringAppend( result, str ); - CFRelease( str ); - } - - MIDIEntityRef entity = 0; - MIDIEndpointGetEntity( endpoint, &entity ); - if ( entity == 0 ) - // probably virtual - return result; - - if ( CFStringGetLength( result ) == 0 ) { - // endpoint name has zero length -- try the entity - str = NULL; - MIDIObjectGetStringProperty( entity, kMIDIPropertyName, &str ); - if ( str != NULL ) { - CFStringAppend( result, str ); - CFRelease( str ); + if ( CFStringGetLength( result ) == 0 ) { + // endpoint name has zero length -- try the entity + str = NULL; + MIDIObjectGetStringProperty( entity, kMIDIPropertyName, &str ); + if ( str != NULL ) { + CFStringAppend( result, str ); + CFRelease( str ); } } // now consider the device's name @@ -728,8 +1052,8 @@ CFStringRef EndpointName( MIDIEndpointRef endpoint, bool isExternal ) str = NULL; MIDIObjectGetStringProperty( device, kMIDIPropertyName, &str ); if ( CFStringGetLength( result ) == 0 ) { - CFRelease( result ); - return str; + CFRelease( result ); + return str; } if ( str != NULL ) { // if an external device has only one entity, throw away @@ -739,19 +1063,19 @@ CFStringRef EndpointName( MIDIEndpointRef endpoint, bool isExternal ) return str; } else { if ( CFStringGetLength( str ) == 0 ) { - CFRelease( str ); - return result; + CFRelease( str ); + return result; } // does the entity name already start with the device name? // (some drivers do this though they shouldn't) // if so, do not prepend - if ( CFStringCompareWithOptions( result, /* endpoint name */ - str /* device name */, - CFRangeMake(0, CFStringGetLength( str ) ), 0 ) != kCFCompareEqualTo ) { - // prepend the device name to the entity name - if ( CFStringGetLength( result ) > 0 ) - CFStringInsert( result, 0, CFSTR(" ") ); - CFStringInsert( result, 0, str ); + if ( CFStringCompareWithOptions( result, /* endpoint name */ + str /* device name */, + CFRangeMake(0, CFStringGetLength( str ) ), 0 ) != kCFCompareEqualTo ) { + // prepend the device name to the entity name + if ( CFStringGetLength( result ) > 0 ) + CFStringInsert( result, 0, CFSTR(" ") ); + CFStringInsert( result, 0, str ); } CFRelease( str ); } @@ -761,6 +1085,8 @@ CFStringRef EndpointName( MIDIEndpointRef endpoint, bool isExternal ) // This function was submitted by Douglas Casey Tucker and apparently // derived largely from PortMidi. +// Nearly the same text can be found in the Apple Q&A qa1374: +// https://developer.apple.com/library/mac/qa/qa1374/_index.html static CFStringRef ConnectedEndpointName( MIDIEndpointRef endpoint ) { CFMutableStringRef result = CFStringCreateMutable( NULL, 0 ); @@ -780,28 +1106,28 @@ static CFStringRef ConnectedEndpointName( MIDIEndpointRef endpoint ) if ( nConnected ) { const SInt32 *pid = (const SInt32 *)(CFDataGetBytePtr(connections)); for ( i=0; i= MIDIGetNumberOfSources() ) { - std::ostringstream ost; - ost << "MidiInCore::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid."; - errorString_ = ost.str(); - error( RtMidiError::WARNING, errorString_ ); - return stringName; +#define RTMIDI_CLASSNAME "CoreSequencer" +template +class CoreSequencer { +public: + CoreSequencer():seq(0) + { + if (locking) { + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL); + pthread_mutex_init(&mutex, &attr); + } } - portRef = MIDIGetSource( portNumber ); - nameRef = ConnectedEndpointName(portRef); - CFStringGetCString( nameRef, name, sizeof(name), CFStringGetSystemEncoding()); - CFRelease( nameRef ); - - return stringName = name; -} - -//*********************************************************************// -// API: OS-X -// Class Definitions: MidiOutCore -//*********************************************************************// + CoreSequencer(const std::string &n):seq(0),name(n) + { + if (locking) { + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL); + pthread_mutex_init(&mutex, &attr); + } + init(); + } -MidiOutCore :: MidiOutCore( const std::string clientName ) : MidiOutApi() -{ - initialize( clientName ); -} + ~CoreSequencer() + { + if (seq) { + scoped_lock lock(mutex); + MIDIClientDispose(seq); + seq = 0; + } + if (locking) { + pthread_mutex_destroy(&mutex); + } + } -MidiOutCore :: ~MidiOutCore( void ) -{ - // Close a connection if it exists. - closePort(); + bool setName(const std::string &n) { + /* we don't want to rename the client after opening it. */ + if (seq) return false; + name = n; + return true; + } - // Cleanup. - CoreMidiData *data = static_cast (apiData_); - MIDIClientDispose( data->client ); - if ( data->endpoint ) MIDIEndpointDispose( data->endpoint ); - delete data; -} + static std::string str(CFStringRef s) { + const char * cstr = + CFStringGetCStringPtr(s,kCFStringEncodingUTF8); + if (cstr) return cstr; -void MidiOutCore :: initialize( const std::string& clientName ) -{ - // Set up our client. - MIDIClientRef client; - OSStatus result = MIDIClientCreate( CFStringCreateWithCString( NULL, clientName.c_str(), kCFStringEncodingASCII ), NULL, NULL, &client ); - if ( result != noErr ) { - errorString_ = "MidiOutCore::initialize: error creating OS-X MIDI client object."; - error( RtMidiError::DRIVER_ERROR, errorString_ ); - return; + CFIndex len = CFStringGetLength(s); + std::string retval; + retval.resize(CFStringGetMaximumSizeForEncoding(len, + kCFStringEncodingUTF8)+1); + CFStringGetBytes(s, + CFRangeMake(0, len), + kCFStringEncodingUTF8, + 0, + false, + reinterpret_cast(&retval[0]), + retval.size()-1, + &len); + retval.resize(len); + return trim(retval); } - // Save our api-specific connection information. - CoreMidiData *data = (CoreMidiData *) new CoreMidiData; - data->client = client; - data->endpoint = 0; - apiData_ = (void *) data; -} -unsigned int MidiOutCore :: getPortCount() -{ - CFRunLoopRunInMode( kCFRunLoopDefaultMode, 0, false ); - return MIDIGetNumberOfDestinations(); -} +#if 0 + // Obtain the name of an endpoint, following connections. -std::string MidiOutCore :: getPortName( unsigned int portNumber ) -{ - CFStringRef nameRef; - MIDIEndpointRef portRef; - char name[128]; + // The result should be released by the caller. - std::string stringName; - CFRunLoopRunInMode( kCFRunLoopDefaultMode, 0, false ); - if ( portNumber >= MIDIGetNumberOfDestinations() ) { - std::ostringstream ost; - ost << "MidiOutCore::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid."; - errorString_ = ost.str(); - error( RtMidiError::WARNING, errorString_ ); - return stringName; - } + static CFStringRef CreateConnectedEndpointName(MIDIEndpointRef endpoint) + { + CFMutableStringRef result = CFStringCreateMutable(NULL, 0); + CFStringRef str; + OSStatus err; + + + // Does the endpoint have connections? + CFDataRef connections = NULL; + int nConnected = 0; + bool anyStrings = false; + err = MIDIObjectGetDataProperty(endpoint, kMIDIPropertyConnectionUniqueID, &connections); + if (connections != NULL) { + // It has connections, follow them + // Concatenate the names of all connected devices + nConnected = CFDataGetLength(connections) / sizeof(MIDIUniqueID); + + if (nConnected) { + const SInt32 *pid = reinterpret_cast(CFDataGetBytePtr(connections)); + for (int i = 0; i < nConnected; ++i, ++pid) { + MIDIUniqueID id = EndianS32_BtoN(*pid); + MIDIObjectRef connObject; + MIDIObjectType connObjectType; + err = MIDIObjectFindByUniqueID(id, &connObject, &connObjectType); + if (err == noErr) { + if (connObjectType == kMIDIObjectType_ExternalSource || + connObjectType == kMIDIObjectType_ExternalDestination) { + // Connected to an external device's endpoint (10.3 and later). + str = EndpointName(static_cast(connObject), true); + } else { + // Connected to an external device (10.2) (or something else, catch-all) + str = NULL; + MIDIObjectGetStringProperty(connObject, kMIDIPropertyName, &str); + } + + if (str != NULL) { + if (anyStrings) + CFStringAppend(result, CFSTR(", ")); + else anyStrings = true; + CFStringAppend(result, str); + CFRelease(str); + } + } + } + } + CFRelease(connections); + } - portRef = MIDIGetDestination( portNumber ); - nameRef = ConnectedEndpointName(portRef); - CFStringGetCString( nameRef, name, sizeof(name), CFStringGetSystemEncoding()); - CFRelease( nameRef ); - - return stringName = name; -} -void MidiOutCore :: openPort( unsigned int portNumber, const std::string portName ) -{ - if ( connected_ ) { - errorString_ = "MidiOutCore::openPort: a valid connection already exists!"; - error( RtMidiError::WARNING, errorString_ ); - return; - } + if (anyStrings) + return result; + else + CFRelease(result); - CFRunLoopRunInMode( kCFRunLoopDefaultMode, 0, false ); - unsigned int nDest = MIDIGetNumberOfDestinations(); - if (nDest < 1) { - errorString_ = "MidiOutCore::openPort: no MIDI output destinations found!"; - error( RtMidiError::NO_DEVICES_FOUND, errorString_ ); - return; + // Here, either the endpoint had no connections, or we failed to obtain names for any of them. + return CreateEndpointName(endpoint, false); } - if ( portNumber >= nDest ) { - std::ostringstream ost; - ost << "MidiOutCore::openPort: the 'portNumber' argument (" << portNumber << ") is invalid."; - errorString_ = ost.str(); - error( RtMidiError::INVALID_PARAMETER, errorString_ ); - return; - } - MIDIPortRef port; - CoreMidiData *data = static_cast (apiData_); - OSStatus result = MIDIOutputPortCreate( data->client, - CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII ), - &port ); - if ( result != noErr ) { - MIDIClientDispose( data->client ); - errorString_ = "MidiOutCore::openPort: error creating OS-X MIDI output port."; - error( RtMidiError::DRIVER_ERROR, errorString_ ); - return; - } - // Get the desired output port identifier. - MIDIEndpointRef destination = MIDIGetDestination( portNumber ); - if ( destination == 0 ) { - MIDIPortDispose( port ); - MIDIClientDispose( data->client ); - errorString_ = "MidiOutCore::openPort: error getting MIDI output destination reference."; - error( RtMidiError::DRIVER_ERROR, errorString_ ); - return; - } + ////////////////////////////////////// + // Obtain the name of an endpoint without regard for whether it has connections. + // The result should be released by the caller. - // Save our api-specific connection information. - data->port = port; - data->destinationId = destination; - connected_ = true; -} + static CFStringRef CreateEndpointName(MIDIEndpointRef endpoint, bool isExternal) + { + CFMutableStringRef result = CFStringCreateMutable(NULL, 0); + CFStringRef str; + + // begin with the endpoint's name + str = NULL; + MIDIObjectGetStringProperty(endpoint, kMIDIPropertyName, &str); + if (str != NULL) { + CFStringAppend(result, str); + CFRelease(str); + } + + MIDIEntityRef entity = NULL; + MIDIEndpointGetEntity(endpoint, &entity); + if (entity == NULL) + // probably virtual + return result; + + if (CFStringGetLength(result) == 0) { + // endpoint name has zero length -- try the entity + str = NULL; + MIDIObjectGetStringProperty(entity, kMIDIPropertyName, &str); + if (str != NULL) { + CFStringAppend(result, str); + CFRelease(str); + } + } + + + + // now consider the device's name + MIDIDeviceRef device = NULL; + MIDIEntityGetDevice(entity, &device); + if (device == NULL) return result; + + str = NULL; + MIDIObjectGetStringProperty(device, kMIDIPropertyName, &str); + if (str != NULL) { + // if an external device has only one entity, throw away + // the endpoint name and just use the device name + if (isExternal && MIDIDeviceGetNumberOfEntities(device) < 2) { + CFRelease(result); + return str; + } else { + // does the entity name already start with the device name? + // (some drivers do this though they shouldn't) + // if so, do not prepend + + if (CFStringCompareWithOptions(str /* device name */, + result /* endpoint name */, + CFRangeMake(0, + CFStringGetLength(str)), + 0) + != kCFCompareEqualTo) { + // prepend the device name to the entity name + if (CFStringGetLength(result) > 0) + CFStringInsert(result, 0, CFSTR(" ")); + CFStringInsert(result, 0, str); + } + CFRelease(str); + } + } + + return result; + } +#endif + + static std::string getConnectionsString(MIDIEndpointRef port) + { + /* This function is derived from + CreateConnectedEndpointName at Apple Q&A */ + std::ostringstream result; + CFDataRef connections = NULL; + OSStatus err = MIDIObjectGetDataProperty(port, + kMIDIPropertyConnectionUniqueID, + &connections); + if (err != noErr) + return result.str(); + + if (!connections) + return result.str(); + CFIndex size = CFDataGetLength( connections ) / sizeof(MIDIUniqueID); + if (!size) { + CFRelease(connections); + return result.str(); + } + + CFStringRef strRef; + const SInt32 *pid + = reinterpret_cast(CFDataGetBytePtr(connections)); + bool anyStrings = false; + for (int i = 0; i < size; ++i, ++pid) { + MIDIUniqueID id = EndianS32_BtoN(*pid); + MIDIObjectRef connObject; + MIDIObjectType connObjectType; + err = MIDIObjectFindByUniqueID(id, &connObject, &connObjectType); + if (err != noErr) + continue; + + if (connObjectType == kMIDIObjectType_ExternalSource || + connObjectType == kMIDIObjectType_ExternalDestination) { + // Connected to an external + // device's endpoint + // (10.3 and later). + strRef = EndpointName(static_cast(connObject), + true); + } else { + // Connected to an external device + // (10.2) (or something else, catch-all) + strRef = NULL; + MIDIObjectGetStringProperty(connObject, + kMIDIPropertyName, &strRef); + } + + if (strRef != NULL) { + if (anyStrings) + result << ", "; + else anyStrings = true; + result << str(strRef); + CFRelease(strRef); + } + } + CFRelease(connections); + return result.str(); + } + + static std::string getPortName(MIDIEndpointRef port, int flags) { + // std::string clientname; + std::string devicename; + std::string portname; + std::string entityname; + // std::string externaldevicename; + std::string connections; + std::string recommendedname; + // bool isVirtual; + bool hasManyEntities = false; + bool hasManyEndpoints = false; + CFStringRef nameRef; + MIDIObjectGetStringProperty(port, + kMIDIPropertyDisplayName, + &nameRef); + recommendedname = str(nameRef); + connections = getConnectionsString(port); + + MIDIObjectGetStringProperty(port, + kMIDIPropertyName, + &nameRef); + portname = str(nameRef); + CFRelease( nameRef ); + + MIDIEntityRef entity = 0; + MIDIEndpointGetEntity(port, &entity); + // entity == NULL: probably virtual + if (entity != 0) { + nameRef = NULL; + MIDIObjectGetStringProperty(entity, kMIDIPropertyName, &nameRef); + if (nameRef != NULL) { + entityname = str(nameRef); + CFRelease(nameRef); + } + hasManyEndpoints = + MIDIEntityGetNumberOfSources(entity) >= 2 || + MIDIEntityGetNumberOfDestinations(entity) + >= 2; + + // now consider the device's name + MIDIDeviceRef device = 0; + MIDIEntityGetDevice(entity, &device); + if (device != 0) { + hasManyEntities = MIDIDeviceGetNumberOfEntities(device) >= 2; + MIDIObjectGetStringProperty(device, + kMIDIPropertyName, + &nameRef); + devicename = str(nameRef); + CFRelease(nameRef); + } + // does the entity name already start with the device name? + // (some drivers do this though they shouldn't) + if (entityname.substr(0,devicename.length()) + == devicename) { + int start = devicename.length(); + while (isspace(entityname[start])) + start++; + entityname = entityname.substr(start); + } + } + + int naming = flags & PortDescriptor::NAMING_MASK; + + std::ostringstream os; + bool needcolon; + switch (naming) { + case PortDescriptor::SESSION_PATH: + if (flags & PortDescriptor::INCLUDE_API) + os << "CORE:"; + os << port; + break; + case PortDescriptor::STORAGE_PATH: + if (flags & PortDescriptor::INCLUDE_API) + os << "CORE:"; + // os << clientname; + os << devicename; + os << ":" << portname; + os << ":" << entityname; + // os << ":" << externaldevicename; + os << ":" << connections; + // os << ":" << recommendedname; + if (flags & PortDescriptor::UNIQUE_PORT_NAME) + os << ";" << port; + break; + case PortDescriptor::LONG_NAME: + needcolon = !devicename.empty(); + os << devicename; + if (hasManyEndpoints || + hasManyEntities || + devicename.empty()) { + if (!entityname.empty()) { + if (needcolon) + os << ": "; + os << entityname; + needcolon = true; + } + if ((hasManyEndpoints + || entityname.empty()) + && !portname.empty()) { + if (needcolon) + os << ": "; + os << portname; + } + } + if (!connections.empty()) { + os << " ⇒ "; + os << connections; + } + if (flags & + (PortDescriptor::INCLUDE_API + | PortDescriptor::UNIQUE_PORT_NAME)) { + os << " ("; + if (flags & + PortDescriptor::INCLUDE_API) { + os << "CORE"; + if (flags & PortDescriptor::UNIQUE_PORT_NAME) + os << ":"; + } + if (flags & PortDescriptor::UNIQUE_PORT_NAME) { + os << port; + } + os << ")"; + } + break; + case PortDescriptor::SHORT_NAME: + default: + if (!recommendedname.empty()) { + os << recommendedname; + } else + if (!connections.empty()) { + os << connections; + } else { + os << devicename; + if (hasManyEntities || + hasManyEndpoints || + devicename.empty()) { + if (!devicename.empty()) + os << " "; + if (!portname.empty()) { + os << portname; + } else if (!entityname.empty()) { + os << entityname; + } else + os << "???"; + } + } + if (flags & + (PortDescriptor::INCLUDE_API + | PortDescriptor::UNIQUE_PORT_NAME)) { + os << " ("; + if (flags & + PortDescriptor::INCLUDE_API) { + os << "CORE"; + if (flags & PortDescriptor::UNIQUE_PORT_NAME) + os << ":"; + } + if (flags & PortDescriptor::UNIQUE_PORT_NAME) { + os << port; + } + os << ")"; + } + break; + } + return os.str(); + } + + int getPortCapabilities(MIDIEndpointRef port) { + int retval = 0; + MIDIEntityRef entity = 0; + OSStatus stat = + MIDIEndpointGetEntity(port,&entity); + if (stat == kMIDIObjectNotFound) { + // plan B for virtual ports + MIDIUniqueID uid; + stat = MIDIObjectGetIntegerProperty (port, + kMIDIPropertyUniqueID, + &uid); + if (stat != noErr) { + throw RTMIDI_ERROR(gettext_noopt("Could not get the unique identifier of a midi endpoint."), + Error::WARNING); + return 0; + } + MIDIObjectRef obj; + MIDIObjectType type; + stat = MIDIObjectFindByUniqueID (uid, + &obj, + &type); + if (stat != noErr || obj != port) { + throw RTMIDI_ERROR(gettext_noopt("Could not get the endpoint back from the unique identifier of a midi endpoint."), + Error::WARNING); + return 0; + } + if (type == kMIDIObjectType_Source + || type == kMIDIObjectType_ExternalSource) + return PortDescriptor::INPUT; + else if (type == kMIDIObjectType_Destination + || type == kMIDIObjectType_ExternalDestination) + return PortDescriptor::OUTPUT; + else { + return 0; + } + + } else if (stat != noErr) { + throw RTMIDI_ERROR(gettext_noopt("Could not get the entity of a midi endpoint."), + Error::WARNING); + return 0; + } + /* Theoretically Mac OS X could silently use + the same endpoint reference for input and + output. We might benefit from this + behaviour. + \todo: Find a way to query the object + whether it can act as source or destination. + */ + ItemCount count = + MIDIEntityGetNumberOfDestinations(entity); + for (ItemCount i = 0; i < count ; i++) { + MIDIEndpointRef dest= + MIDIEntityGetDestination(entity,i); + if (dest == port) { + retval |= + PortDescriptor::OUTPUT; + break; + } + } + count = + MIDIEntityGetNumberOfSources(entity); + for (ItemCount i = 0; i < count ; i++) { + MIDIEndpointRef src= + MIDIEntityGetSource(entity,i); + if (src == port) { + retval |= + PortDescriptor::INPUT; + } + } + return retval; + } + + + MIDIPortRef createPort (const std::string &portName, + int flags, + MidiInCore * data = NULL) + { + init(); + scoped_lock lock (mutex); + MIDIPortRef port = 0; + OSStatus result; + switch (flags) { + case PortDescriptor::INPUT: { + result = MIDIInputPortCreate(seq, + CFStringWrapper(portName), + MidiInCore::midiInputCallback, + (void *)data, + &port); + } + break; + case PortDescriptor::OUTPUT: { + result + = MIDIOutputPortCreate(seq, + CFStringWrapper(portName), + &port); + } + break; + default: + throw RTMIDI_ERROR(gettext_noopt("Error creating OS X MIDI port because of invalid port flags."), + Error::INVALID_PARAMETER); + } + if ( result != noErr ) { + throw RTMIDI_ERROR(gettext_noopt("Error creating OS-X MIDI port."), + Error::DRIVER_ERROR); + } + return port; + } + + MIDIEndpointRef createVirtualPort (const std::string &portName, + int flags, + MidiInCore * data = NULL) + { + init(); + scoped_lock lock (mutex); + MIDIEndpointRef port = 0; + OSStatus result; + switch (flags) { + case PortDescriptor::INPUT: { + result + = MIDIDestinationCreate(seq, + CFStringWrapper(portName), + MidiInCore::midiInputCallback, + (void *)data, + &port); + } + break; + case PortDescriptor::OUTPUT: { + result + = MIDISourceCreate(seq, + CFStringWrapper(portName), + &port); + } + break; + default: + throw RTMIDI_ERROR(gettext_noopt("Error creating OS X MIDI port because of invalid port flags."), + Error::INVALID_PARAMETER); + } + if ( result != noErr ) { + throw RTMIDI_ERROR(gettext_noopt("Error creating OS-X MIDI port."), + Error::DRIVER_ERROR); + } + return port; + } + + + /*! Use CoreSequencer like a C pointer. + \note This function breaks the design to control thread safety + by the selection of the \ref locking parameter to the class. + It should be removed as soon as possible in order ensure the + thread policy that has been intended by creating this class. + */ + operator MIDIClientRef () + { + return seq; + } +protected: + struct scoped_lock { + pthread_mutex_t * mutex; + scoped_lock(pthread_mutex_t & m): mutex(&m) + { + if (locking) + pthread_mutex_lock(mutex); + } + ~scoped_lock() + { + if (locking) + pthread_mutex_unlock(mutex); + } + }; + pthread_mutex_t mutex; + MIDIClientRef seq; + std::string name; + + + void init() + { + init (seq); + } + + void init(MIDIClientRef &client) + { + if (client) return; + { + scoped_lock lock(mutex); + + OSStatus result = MIDIClientCreate(CFStringWrapper(name), NULL, NULL, &client ); + if ( result != noErr ) { + throw RTMIDI_ERROR1(gettext_noopt("Error creating OS-X MIDI client object (Error no: %d)."), + Error::DRIVER_ERROR, + result); + return; + } + } + } +}; +#undef RTMIDI_CLASSNAME + +typedef CoreSequencer<1> LockingCoreSequencer; +typedef CoreSequencer<0> NonLockingCoreSequencer; + +#define RTMIDI_CLASSNAME "CorePortDescriptor" +struct CorePortDescriptor:public PortDescriptor { + CorePortDescriptor(const std::string &name):api(0), + clientName(name), + endpoint(0) + { + } + CorePortDescriptor(MIDIEndpointRef p, + const std::string &name):api(0), + clientName(name), + endpoint(p) + { + seq.setName(name); + } + CorePortDescriptor(CorePortDescriptor & + other):PortDescriptor(other), + api(other.api), + clientName(other.clientName), + endpoint(other.endpoint) + { + seq.setName(clientName); + } + ~CorePortDescriptor() {} + + MidiInApi * getInputApi(unsigned int queueSizeLimit = 100) const { + if (getCapabilities() & INPUT) + return new MidiInCore(clientName,queueSizeLimit); + else + return 0; + } + + MidiOutApi * getOutputApi() const { + if (getCapabilities() & OUTPUT) + return new MidiOutCore(clientName); + else + return 0; + } + + void setEndpoint(MIDIEndpointRef e) + { + endpoint = e; + } + MIDIEndpointRef getEndpoint() const + { + return endpoint; + } + + std::string getName(int flags = SHORT_NAME | UNIQUE_PORT_NAME) { + return seq.getPortName(endpoint,flags); + } + + const std::string &getClientName() { + return clientName; + } + int getCapabilities() const { + if (!endpoint) return 0; + return seq.getPortCapabilities(endpoint); + } + static PortList getPortList(int capabilities, const std::string &clientName); +protected: + MidiApi * api; + static LockingCoreSequencer seq; + + std::string clientName; + MIDIEndpointRef endpoint; +}; + +LockingCoreSequencer CorePortDescriptor::seq; + + + +PortList CorePortDescriptor :: getPortList(int capabilities, const std::string &clientName) +{ + PortList list; + + CFRunLoopRunInMode( kCFRunLoopDefaultMode, 0, false ); + int caps = capabilities & PortDescriptor::INOUTPUT; + // bool unlimited = capabilities & PortDescriptor::UNLIMITED; + bool forceInput = PortDescriptor::INPUT & caps; + bool forceOutput = PortDescriptor::OUTPUT & caps; + bool allowOutput = forceOutput || !forceInput; + bool allowInput = forceInput || !forceOutput; + if (allowOutput) { + ItemCount count = + MIDIGetNumberOfDestinations(); + for (ItemCount i = 0 ; i < count; i++) { + MIDIEndpointRef destination = + MIDIGetDestination(i); + try { + if ((seq.getPortCapabilities(destination) + & caps) == caps) + list.push_back(Pointer( + new CorePortDescriptor(destination, clientName))); + } catch (Error & e) { + if (e.getType() == Error::WARNING || + e.getType() == Error::DEBUG_WARNING) + e.printMessage(); + else throw; + } + } + // Combined sources and destinations + // should be both occur as destinations and as + // sources. So we have finished the search, here. + } else if (allowInput) { + ItemCount count = + MIDIGetNumberOfSources(); + for (ItemCount i = 0 ; i < count; i++) { + MIDIEndpointRef src = + MIDIGetSource(i); + try { + if ((seq.getPortCapabilities(src) + & caps) == caps) + list.push_back(Pointer( + new CorePortDescriptor(src, clientName))); + } catch (Error & e) { + if (e.getType() == Error::WARNING || + e.getType() == Error::DEBUG_WARNING) + e.printMessage(); + else throw; + } + } + } + return list; +} +#undef RTMIDI_CLASSNAME + + +#define RTMIDI_CLASSNAME "CoreMidiData" +// A structure to hold variables related to the CoreMIDI API +// implementation. +struct CoreMidiData:public CorePortDescriptor { + CoreMidiData(const std::string &clientname):CorePortDescriptor(clientname), + client(clientname), + localEndpoint(0), + localPort(0) {} + ~CoreMidiData() { + if (localEndpoint) + MIDIEndpointDispose(localEndpoint); + localEndpoint = 0; + } + + void openPort(const std::string &name, + int flags, + MidiInCore * data = NULL) { + localPort = client.createPort(name, flags, data); + } + + void setRemote(const CorePortDescriptor & remote) + { + setEndpoint(remote.getEndpoint()); + } + + NonLockingCoreSequencer client; + MIDIEndpointRef localEndpoint; + MIDIPortRef localPort; + unsigned long long lastTime; + MIDISysexSendRequest sysexreq; +}; +#undef RTMIDI_CLASSNAME + + +//*********************************************************************// +// API: OS-X +// Class Definitions: MidiInCore +//*********************************************************************// + +#define RTMIDI_CLASSNAME "MidiInCore" +void MidiInCore::midiInputCallback( const MIDIPacketList *list, + void *procRef, + void */*srcRef*/ ) throw() +{ + MidiInCore *data = static_cast (procRef); + CoreMidiData *apiData = static_cast (data->apiData_); + + unsigned char status; + unsigned short nBytes, iByte, size; + unsigned long long time; + + bool& continueSysex = data->continueSysex; + MidiInApi::MidiMessage& message = data->message; + + const MIDIPacket *packet = &list->packet[0]; + for ( unsigned int i=0; inumPackets; ++i ) { + + // My interpretation of the CoreMIDI documentation: all message + // types, except sysex, are complete within a packet and there may + // be several of them in a single packet. Sysex messages can be + // broken across multiple packets and PacketLists but are bundled + // alone within each packet (these packets do not contain other + // message types). If sysex messages are split across multiple + // MIDIPacketLists, they must be handled by multiple calls to this + // function. + + nBytes = packet->length; + if ( nBytes == 0 ) { + packet = MIDIPacketNext(packet); + continue; + } + + // Calculate time stamp. + + if ( data->firstMessage ) { + message.timeStamp = 0.0; + data->firstMessage = false; + } + else { + time = packet->timeStamp; + if ( time == 0 ) { // this happens when receiving asynchronous sysex messages + time = AudioGetCurrentHostTime(); + } + time -= apiData->lastTime; + time = AudioConvertHostTimeToNanos( time ); + if ( !continueSysex ) + message.timeStamp = time * 0.000000001; + } + // Track whether any non-filtered messages were found in this + // packet for timestamp calculation + bool foundNonFiltered = false; + //std::cout << "TimeStamp = " << packet->timeStamp << std::endl; + + iByte = 0; + if ( continueSysex ) { + // We have a continuing, segmented sysex message. + if ( !( data->ignoreFlags & 0x01 ) ) { + // If we're not ignoring sysex messages, copy the entire packet. + for ( unsigned int j=0; jdata[j] ); + } + continueSysex = packet->data[nBytes-1] != 0xF7; + + if ( !( data->ignoreFlags & 0x01 ) ) { + if ( !continueSysex ) { + // If not a continuing sysex message, invoke the user callback function or queue the message. + if ( data->userCallback ) { + data->userCallback->rtmidi_midi_in( message.timeStamp, + message.bytes); + } + else { + // As long as we haven't reached our queue size limit, push the message. + if (!data->queue.push(message)) { + try { + data->error(RTMIDI_ERROR(rtmidi_gettext("Error: Message queue limit reached."), + Error::WARNING)); + } catch (Error & e) { + // don't bother ALSA with an unhandled exception + } + } + } + message.bytes.clear(); + } + } + } + else { + while ( iByte < nBytes ) { + size = 0; + // We are expecting that the next byte in the packet is a status byte. + status = packet->data[iByte]; + if ( !(status & 0x80) ) break; + // Determine the number of bytes in the MIDI message. + if ( status < 0xC0 ) size = 3; + else if ( status < 0xE0 ) size = 2; + else if ( status < 0xF0 ) size = 3; + else if ( status == 0xF0 ) { + // A MIDI sysex + if ( data->ignoreFlags & 0x01 ) { + size = 0; + iByte = nBytes; + } + else size = nBytes - iByte; + continueSysex = packet->data[nBytes-1] != 0xF7; + } + else if ( status == 0xF1 ) { + // A MIDI time code message + if ( data->ignoreFlags & 0x02 ) { + size = 0; + iByte += 2; + } + else size = 2; + } + else if ( status == 0xF2 ) size = 3; + else if ( status == 0xF3 ) size = 2; + else if ( status == 0xF8 && ( data->ignoreFlags & 0x02 ) ) { + // A MIDI timing tick message and we're ignoring it. + size = 0; + iByte += 1; + } + else if ( status == 0xFE && ( data->ignoreFlags & 0x04 ) ) { + // A MIDI active sensing message and we're ignoring it. + size = 0; + iByte += 1; + } + else size = 1; + + // Copy the MIDI data to our vector. + if ( size ) { + foundNonFiltered = true; + message.bytes.assign( &packet->data[iByte], &packet->data[iByte+size] ); + if ( !continueSysex ) { + // If not a continuing sysex message, invoke the user callback function or queue the message. + if ( data->userCallback ) { + data->userCallback->rtmidi_midi_in( message.timeStamp, + message.bytes); + } + else { + // As long as we haven't reached our queue size limit, push the message. + if (!data->queue.push(message)) { + try { + data->error(RTMIDI_ERROR(rtmidi_gettext("Error: Message queue limit reached."), + Error::WARNING)); + } catch (Error & e) { + // don't bother WinMM with an unhandled exception + } + } + } + message.bytes.clear(); + } + iByte += size; + } + } + } + packet = MIDIPacketNext(packet); + + // Save the time of the last non-filtered message + if (foundNonFiltered) + { + apiData->lastTime = packet->timeStamp; + if ( apiData->lastTime == 0 ) { // this happens when receiving asynchronous sysex messages + apiData->lastTime = AudioGetCurrentHostTime(); + } + } + + } +} + +MidiInCore :: MidiInCore( const std::string &clientName, + unsigned int queueSizeLimit ) : + MidiInApi( queueSizeLimit ) +{ + MidiInCore::initialize( clientName ); +} + +MidiInCore :: ~MidiInCore( void ) +{ + // Cleanup. + CoreMidiData *data = static_cast (apiData_); + try { + // Close a connection if it exists. + MidiInCore::closePort(); + + } catch (Error & e) { + delete data; + throw; + } + delete data; + +} + +void MidiInCore :: initialize( const std::string &clientName ) +{ + // Save our api-specific connection information. + CoreMidiData *data = (CoreMidiData *) new CoreMidiData(clientName); + apiData_ = (void *) data; +} + +void MidiInCore :: openPort( unsigned int portNumber, + const std::string &portName ) +{ + if ( connected_ ) { + error(RTMIDI_ERROR(gettext_noopt("A valid connection already exists."), + Error::WARNING)); + return; + } + + CFRunLoopRunInMode( kCFRunLoopDefaultMode, 0, false ); + unsigned int nSrc = MIDIGetNumberOfSources(); + if (nSrc < 1) { + error(RTMIDI_ERROR(gettext_noopt("No MIDI input sources found."), + Error::NO_DEVICES_FOUND)); + return; + } + + if ( portNumber >= nSrc ) { + std::ostringstream ost; + ost << ""; + errorString_ = ost.str(); + error(RTMIDI_ERROR1(gettext_noopt("The 'portNumber' argument (%d) is invalid."), + Error::INVALID_PARAMETER, portNumber) ); + return; + } + + MIDIPortRef port; + CoreMidiData *data = static_cast (apiData_); + OSStatus result = MIDIInputPortCreate( data->client, + CFStringWrapper(portName), + midiInputCallback, (void *)this, &port ); + if ( result != noErr ) { + MIDIClientDispose( data->client ); + error(RTMIDI_ERROR(gettext_noopt("Error creating OS-X MIDI input port."), + Error::DRIVER_ERROR)); + return; + } + + // Get the desired input source identifier. + MIDIEndpointRef endpoint = MIDIGetSource( portNumber ); + if ( endpoint == 0 ) { + MIDIPortDispose( port ); + port = 0; + MIDIClientDispose( data->client ); + error(RTMIDI_ERROR(gettext_noopt("Error getting MIDI input source reference."), + Error::DRIVER_ERROR) ); + return; + } + + // Make the connection. + result = MIDIPortConnectSource( port, endpoint, NULL ); + if ( result != noErr ) { + MIDIPortDispose( port ); + port = 0; + MIDIClientDispose( data->client ); + error(RTMIDI_ERROR(gettext_noopt("Error connecting OS-X MIDI input port."), + Error::DRIVER_ERROR) ); + return; + } + + // Save our api-specific port information. + data->localPort = port; + data->setEndpoint(endpoint); + + connected_ = true; +} + +void MidiInCore :: openVirtualPort( const std::string &portName ) +{ + CoreMidiData *data = static_cast (apiData_); + + // Create a virtual MIDI input destination. + MIDIEndpointRef endpoint; + OSStatus result = MIDIDestinationCreate( data->client, + CFStringWrapper(portName), + midiInputCallback, (void *)this, &endpoint ); + if ( result != noErr ) { + error(RTMIDI_ERROR(gettext_noopt("Error creating virtual OS-X MIDI destination."), + Error::DRIVER_ERROR) ); + return; + } + + // Save our api-specific connection information. + data->localEndpoint = endpoint; +} + +void MidiInCore :: openPort( const PortDescriptor & port, + const std::string &portName) +{ + CoreMidiData *data = static_cast (apiData_); + const CorePortDescriptor * remote = dynamic_cast(&port); + + if ( !data ) { + error(RTMIDI_ERROR(gettext_noopt("Data has not been allocated."), + Error::SYSTEM_ERROR) ); + return; + } + if ( connected_ || data -> localEndpoint) { + error(RTMIDI_ERROR(gettext_noopt("A valid connection already exists."), + Error::WARNING) ); + return; + } + if (!remote) { + error(RTMIDI_ERROR(gettext_noopt("Core MIDI has been instructed to open a non-Core MIDI port. This doesn't work."), + Error::INVALID_DEVICE) ); + return; + } + + data->openPort (portName, + PortDescriptor::INPUT, + this); + data->setRemote(*remote); + OSStatus result = + MIDIPortConnectSource(data->localPort, + data->getEndpoint(), + NULL); + if ( result != noErr ) { + error(RTMIDI_ERROR(gettext_noopt("Error creating OS-X MIDI port."), + Error::DRIVER_ERROR)); + } + + connected_ = true; +} + +Pointer MidiInCore :: getDescriptor(bool local) +{ + CoreMidiData *data = static_cast + (apiData_); + if (!data) { + return NULL; + } + if (local) { + if (data && data->localEndpoint) { + return Pointer(new + CorePortDescriptor(data->localEndpoint, data->getClientName())); + } + } else { + if (data->getEndpoint()) { + return Pointer(new CorePortDescriptor(*data)); + } + } + return NULL; +} + +PortList MidiInCore :: getPortList(int capabilities) +{ + CoreMidiData *data = static_cast (apiData_); + try { + return CorePortDescriptor::getPortList(capabilities | PortDescriptor::INPUT, + data->getClientName()); + } catch (Error & e) { + error(e); + return PortList(); + } +} + +void MidiInCore :: closePort( void ) +{ + CoreMidiData *data = static_cast (apiData_); + + if ( data->localPort ) { + MIDIPortDispose( data->localPort ); + data->localPort = 0; + } + + if (data->localEndpoint) { + MIDIEndpointDispose( data->localEndpoint ); + data->localEndpoint = 0; + } + + connected_ = false; +} + +void MidiInCore :: setClientName ( const std::string& ) +{ + error(RTMIDI_ERROR(gettext_noopt("Setting client names is not implemented for Mac OS X CoreMIDI."), + Error::WARNING)); +} + +void MidiInCore :: setPortName ( const std::string& ) +{ + error(RTMIDI_ERROR(gettext_noopt("Setting port names is not implemented for Mac OS X CoreMIDI."), + Error::WARNING)); +} + +unsigned int MidiInCore :: getPortCount() +{ + CFRunLoopRunInMode( kCFRunLoopDefaultMode, 0, false ); + return MIDIGetNumberOfSources(); +} + +std::string MidiInCore :: getPortName( unsigned int portNumber ) +{ + CFStringRef nameRef; + MIDIEndpointRef portRef; + char name[128]; + + std::string stringName; + CFRunLoopRunInMode( kCFRunLoopDefaultMode, 0, false ); + if ( portNumber >= MIDIGetNumberOfSources() ) { + error(RTMIDI_ERROR1(gettext_noopt("The 'portNumber' argument (%d) is invalid."), + Error::WARNING, portNumber)); + return stringName; + } + + portRef = MIDIGetSource( portNumber ); + nameRef = ConnectedEndpointName(portRef); + CFStringGetCString( nameRef, name, sizeof(name), kCFStringEncodingUTF8); + CFRelease( nameRef ); + + return stringName = name; +} +#undef RTMIDI_CLASSNAME + + +//*********************************************************************// +// API: OS-X +// Class Definitions: MidiOutCore +//*********************************************************************// + +#define RTMIDI_CLASSNAME "MidiOutCore" +MidiOutCore :: MidiOutCore( const std::string &clientName ) : MidiOutApi() +{ + MidiOutCore::initialize( clientName ); +} + +MidiOutCore :: ~MidiOutCore( void ) +{ + // Close a connection if it exists. + MidiOutCore::closePort(); + + // Cleanup. + CoreMidiData *data = static_cast (apiData_); + delete data; +} + +void MidiOutCore :: initialize( const std::string &clientName ) +{ + // Save our api-specific connection information. + CoreMidiData *data = (CoreMidiData *) new CoreMidiData(clientName); + apiData_ = (void *) data; +} + +unsigned int MidiOutCore :: getPortCount() +{ + CFRunLoopRunInMode( kCFRunLoopDefaultMode, 0, false ); + return MIDIGetNumberOfDestinations(); +} + +std::string MidiOutCore :: getPortName( unsigned int portNumber ) +{ + CFStringRef nameRef; + MIDIEndpointRef portRef; + char name[128]; + + std::string stringName; + CFRunLoopRunInMode( kCFRunLoopDefaultMode, 0, false ); + if ( portNumber >= MIDIGetNumberOfDestinations() ) { + error(RTMIDI_ERROR1(gettext_noopt("The 'portNumber' argument (%d) is invalid."), + Error::WARNING, portNumber) ); + return stringName; + } + + portRef = MIDIGetDestination( portNumber ); + nameRef = ConnectedEndpointName(portRef); + CFStringGetCString( nameRef, name, sizeof(name), kCFStringEncodingUTF8 ); + CFRelease( nameRef ); + + return stringName = name; +} + +void MidiOutCore :: openPort( unsigned int portNumber, + const std::string &portName ) +{ + if ( connected_ ) { + error(RTMIDI_ERROR(gettext_noopt("A valid connection already exists."), + Error::WARNING) ); + return; + } + + CFRunLoopRunInMode( kCFRunLoopDefaultMode, 0, false ); + unsigned int nDest = MIDIGetNumberOfDestinations(); + if (nDest < 1) { + error(RTMIDI_ERROR(gettext_noopt("No MIDI output destinations found."), + Error::NO_DEVICES_FOUND) ); + return; + } + + if ( portNumber >= nDest ) { + error(RTMIDI_ERROR1(gettext_noopt("The 'portNumber' argument (%d) is invalid."), + Error::INVALID_PARAMETER, portNumber) ); + return; + } + + MIDIPortRef port; + CoreMidiData *data = static_cast (apiData_); + OSStatus result = MIDIOutputPortCreate( data->client, + CFStringWrapper( portName ), + &port ); + if ( result != noErr ) { + MIDIClientDispose( data->client ); + error(RTMIDI_ERROR(gettext_noopt("Error creating OS-X MIDI output port."), + Error::DRIVER_ERROR) ); + return; + } + + // Get the desired output port identifier. + MIDIEndpointRef destination = MIDIGetDestination( portNumber ); + if ( destination == 0 ) { + MIDIPortDispose( port ); + port = 0; + MIDIClientDispose( data->client ); + error(RTMIDI_ERROR(gettext_noopt("Error getting MIDI output destination reference."), + Error::DRIVER_ERROR) ); + return; + } + + // Save our api-specific connection information. + data->localPort = port; + data->setEndpoint(destination); + connected_ = true; +} void MidiOutCore :: closePort( void ) { - if ( connected_ ) { - CoreMidiData *data = static_cast (apiData_); - MIDIPortDispose( data->port ); - connected_ = false; + CoreMidiData *data = static_cast (apiData_); + + if ( data->localPort ) { + MIDIPortDispose( data->localPort ); + data->localPort = 0; + } + + if (data->localEndpoint) { + MIDIEndpointDispose( data->localEndpoint ); + data->localEndpoint = 0; } + + connected_ = false; +} + +void MidiOutCore :: setClientName ( const std::string& ) +{ + error(RTMIDI_ERROR(gettext_noopt("Setting client names is not implemented for Mac OS X CoreMIDI."), + Error::WARNING)); +} + +void MidiOutCore :: setPortName ( const std::string& ) +{ + error(RTMIDI_ERROR(gettext_noopt("Setting port names is not implemented for Mac OS X CoreMIDI."), + Error::WARNING)); } -void MidiOutCore :: openVirtualPort( std::string portName ) +void MidiOutCore :: openVirtualPort( const std::string &portName ) { CoreMidiData *data = static_cast (apiData_); - if ( data->endpoint ) { - errorString_ = "MidiOutCore::openVirtualPort: a virtual output port already exists!"; - error( RtMidiError::WARNING, errorString_ ); + if ( data->localEndpoint ) { + error(RTMIDI_ERROR(gettext_noopt("A virtual output port already exists."), + Error::WARNING) ); return; } // Create a virtual MIDI output source. MIDIEndpointRef endpoint; OSStatus result = MIDISourceCreate( data->client, - CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII ), - &endpoint ); + CFStringWrapper( portName ), + &endpoint ); if ( result != noErr ) { - errorString_ = "MidiOutCore::initialize: error creating OS-X virtual MIDI source."; - error( RtMidiError::DRIVER_ERROR, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("Error creating OS-X virtual MIDI source."), + Error::DRIVER_ERROR) ); return; } // Save our api-specific connection information. - data->endpoint = endpoint; + data->localEndpoint = endpoint; } +void MidiOutCore :: openPort( const PortDescriptor & port, + const std::string &portName) +{ + CoreMidiData *data = static_cast (apiData_); + const CorePortDescriptor * remote = dynamic_cast(&port); + + if ( !data ) { + error(RTMIDI_ERROR(gettext_noopt("Data has not been allocated."), + Error::SYSTEM_ERROR) ); + return; + } + if ( connected_ || data -> localEndpoint) { + error(RTMIDI_ERROR(gettext_noopt("A valid connection already exists."), + Error::WARNING) ); + return; + } + if (!remote) { + error(RTMIDI_ERROR(gettext_noopt("Core MIDI has been instructed to open a non-Core MIDI port. This doesn't work."), + Error::INVALID_DEVICE) ); + return; + } + + try { + data->openPort (portName, + PortDescriptor::OUTPUT); + data->setRemote(*remote); + connected_ = true; + } catch (Error & e) { + error(e); + } +} + +Pointer MidiOutCore :: getDescriptor(bool local) +{ + CoreMidiData *data = static_cast + (apiData_); + if (!data) { + return NULL; + } + try { + if (local) { + if (data && data->localEndpoint) { + return Pointer( + new CorePortDescriptor(data->localEndpoint, data->getClientName())); + } + } else { + if (data->getEndpoint()) { + return Pointer( + new CorePortDescriptor(*data)); + } + } + } catch (Error & e) { + error(e); + } + return NULL; +} + +PortList MidiOutCore :: getPortList(int capabilities) +{ + CoreMidiData *data = static_cast (apiData_); + try { + return CorePortDescriptor::getPortList(capabilities | PortDescriptor::OUTPUT, + data->getClientName()); + } catch (Error & e) { + error(e); + return PortList(); + } +} + + // Not necessary if we don't treat sysex messages any differently than // normal messages ... see below. //static void sysexCompletionProc( MIDISysexSendRequest *sreq ) @@ -1000,95 +2588,68 @@ void MidiOutCore :: openVirtualPort( std::string portName ) // free( sreq ); //} -void MidiOutCore :: sendMessage( std::vector *message ) +void MidiOutCore :: sendMessage( const unsigned char *message, size_t size ) { // We use the MIDISendSysex() function to asynchronously send sysex - // messages. Otherwise, we use a single CoreMidi MIDIPacket. - unsigned int nBytes = message->size(); - if ( nBytes == 0 ) { - errorString_ = "MidiOutCore::sendMessage: no data in message argument!"; - error( RtMidiError::WARNING, errorString_ ); + // messages. Otherwise, we use a single CoreMIDI MIDIPacket. + if ( size == 0 ) { + error(RTMIDI_ERROR(gettext_noopt("No data in message argument."), + Error::WARNING)); return; } - // unsigned int packetBytes, bytesLeft = nBytes; + // unsigned int packetBytes, bytesLeft = size; // unsigned int messageIndex = 0; MIDITimeStamp timeStamp = AudioGetCurrentHostTime(); CoreMidiData *data = static_cast (apiData_); OSStatus result; - /* - // I don't think this code is necessary. We can send sysex - // messages through the normal mechanism. In addition, this avoids - // the problem of virtual ports not receiving sysex messages. - - if ( message->at(0) == 0xF0 ) { - - // Apple's fantastic API requires us to free the allocated data in - // the completion callback but trashes the pointer and size before - // we get a chance to free it!! This is a somewhat ugly hack - // submitted by ptarabbia that puts the sysex buffer data right at - // the end of the MIDISysexSendRequest structure. This solution - // does not require that we wait for a previous sysex buffer to be - // sent before sending a new one, which was the old way we did it. - MIDISysexSendRequest *newRequest = (MIDISysexSendRequest *) malloc(sizeof(struct MIDISysexSendRequest) + nBytes); - char * sysexBuffer = ((char *) newRequest) + sizeof(struct MIDISysexSendRequest); - - // Copy data to buffer. - for ( unsigned int i=0; iat(i); - - newRequest->destination = data->destinationId; - newRequest->data = (Byte *)sysexBuffer; - newRequest->bytesToSend = nBytes; - newRequest->complete = 0; - newRequest->completionProc = sysexCompletionProc; - newRequest->completionRefCon = newRequest; - - result = MIDISendSysex(newRequest); - if ( result != noErr ) { - free( newRequest ); - errorString_ = "MidiOutCore::sendMessage: error sending MIDI to virtual destinations."; - error( RtMidiError::WARNING, errorString_ ); - return; - } + if ( message[0] != 0xF0 && size > 3 ) { + error(RTMIDI_ERROR(gettext_noopt("message format problem ... not sysex but > 3 bytes?"), + Error::WARNING )); return; } - else if ( nBytes > 3 ) { - errorString_ = "MidiOutCore::sendMessage: message format problem ... not sysex but > 3 bytes?"; - error( RtMidiError::WARNING, errorString_ ); - return; + + Byte buffer[size+(sizeof(MIDIPacketList))]; + ByteCount listSize = sizeof(buffer); + MIDIPacketList *packetList = (MIDIPacketList*)buffer; + MIDIPacket *packet = MIDIPacketListInit( packetList ); + + ByteCount remainingBytes = size; + while (remainingBytes && packet) { + ByteCount bytesForPacket = remainingBytes > 65535 ? 65535 : remainingBytes; // 65535 = maximum size of a MIDIPacket + const Byte* dataStartPtr = (const Byte *) &message[size - remainingBytes]; + packet = MIDIPacketListAdd( packetList, listSize, packet, timeStamp, bytesForPacket, dataStartPtr); + remainingBytes -= bytesForPacket; } - */ - MIDIPacketList packetList; - MIDIPacket *packet = MIDIPacketListInit( &packetList ); - packet = MIDIPacketListAdd( &packetList, sizeof(packetList), packet, timeStamp, nBytes, (const Byte *) &message->at( 0 ) ); if ( !packet ) { - errorString_ = "MidiOutCore::sendMessage: could not allocate packet list"; - error( RtMidiError::DRIVER_ERROR, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("Could not allocate packet list."), + Error::DRIVER_ERROR) ); return; } // Send to any destinations that may have connected to us. - if ( data->endpoint ) { - result = MIDIReceived( data->endpoint, &packetList ); + if ( data->localEndpoint ) { + result = MIDIReceived( data->localEndpoint, packetList ); if ( result != noErr ) { - errorString_ = "MidiOutCore::sendMessage: error sending MIDI to virtual destinations."; - error( RtMidiError::WARNING, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("Error sending MIDI to virtual destinations."), + Error::WARNING) ); } } // And send to an explicit destination port if we're connected. if ( connected_ ) { - result = MIDISend( data->port, data->destinationId, &packetList ); + result = MIDISend( data->localPort, data->getEndpoint(), packetList ); if ( result != noErr ) { - errorString_ = "MidiOutCore::sendMessage: error sending MIDI message to port."; - error( RtMidiError::WARNING, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("Error sending MIDI message to port."), + Error::WARNING) ); } } } - -#endif // __MACOSX_CORE__ +#undef RTMIDI_CLASSNAME +RTMIDI_NAMESPACE_END +#endif // __MACOSX_COREMIDI__ //*********************************************************************// @@ -1116,22 +2677,553 @@ void MidiOutCore :: sendMessage( std::vector *message ) // ALSA header file. #include -// A structure to hold variables related to the ALSA API -// implementation. -struct AlsaMidiData { - snd_seq_t *seq; - unsigned int portNum; - int vport; +RTMIDI_NAMESPACE_START +struct AlsaMidiData; + +/*! An abstraction layer for the ALSA sequencer layer. It provides + the following functionality: + - dynamic allocation of the sequencer + - optionallay avoid concurrent access to the ALSA sequencer, + which is not thread proof. This feature is controlled by + the parameter \ref locking. +*/ + +#define RTMIDI_CLASSNAME "AlsaSequencer" +template +class AlsaSequencer { +public: + AlsaSequencer():seq(0) + { + if (locking) { + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL); + pthread_mutex_init(&mutex, &attr); + } + } + + AlsaSequencer(const std::string &n):seq(0),name(n) + { + if (locking) { + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL); + pthread_mutex_init(&mutex, &attr); + } + init(); + { + scoped_lock lock(mutex); + snd_seq_set_client_name( seq, name.c_str() ); + } + } + + ~AlsaSequencer() + { + if (seq) { + scoped_lock lock(mutex); + snd_seq_close(seq); + seq = 0; + } + if (locking) { + pthread_mutex_destroy(&mutex); + } + } + + int setName(const std::string &n) { + /* we don't want to rename the client after opening it. */ + name = n; + if (seq) { + return snd_seq_set_client_name( seq, name.c_str() ); + } + return 0; + } + + std::string GetPortName(int client, int port, int flags) { + init(); + snd_seq_client_info_t *cinfo; + snd_seq_client_info_alloca( &cinfo ); + { + scoped_lock lock (mutex); + snd_seq_get_any_client_info(seq,client,cinfo); + } + + snd_seq_port_info_t *pinfo; + snd_seq_port_info_alloca( &pinfo ); + { + scoped_lock lock (mutex); + snd_seq_get_any_port_info(seq,client,port,pinfo); + } + + int naming = flags & PortDescriptor::NAMING_MASK; + + std::ostringstream os; + switch (naming) { + case PortDescriptor::SESSION_PATH: + if (flags & PortDescriptor::INCLUDE_API) + os << "ALSA:"; + os << client << ":" << port; + break; + case PortDescriptor::STORAGE_PATH: + if (flags & PortDescriptor::INCLUDE_API) + os << "ALSA:"; + os << snd_seq_client_info_get_name(cinfo); + os << ":"; + os << snd_seq_port_info_get_name(pinfo); + if (flags & PortDescriptor::UNIQUE_PORT_NAME) + os << ";" << client << ":" << port; + break; + case PortDescriptor::LONG_NAME: + os << snd_seq_client_info_get_name( cinfo ); + if (flags & PortDescriptor::UNIQUE_PORT_NAME) { + os << " " << client; + } + os << ":"; + if (flags & PortDescriptor::UNIQUE_PORT_NAME) { + os << port; + } + + os << " " << snd_seq_port_info_get_name(pinfo); + if (flags & PortDescriptor::INCLUDE_API) + os << " (ALSA)"; + break; + case PortDescriptor::SHORT_NAME: + default: + os << snd_seq_client_info_get_name( cinfo ); + if (flags & PortDescriptor::UNIQUE_PORT_NAME) { + os << " "; + os << client; + } + os << ":" << port; + if (flags & PortDescriptor::INCLUDE_API) + os << " (ALSA)"; + + break; + } + return os.str(); + } + + void setPortName(const std::string &name, int port) { + snd_seq_port_info_t *pinfo = NULL; + int error; + snd_seq_port_info_alloca( &pinfo ); + if (pinfo == NULL) { + throw RTMIDI_ERROR(gettext_noopt("Could not allocate ALSA port info structure."), + Error::MEMORY_ERROR); + } + if ((error = snd_seq_get_port_info( seq, port, pinfo ))<0) { + throw RTMIDI_ERROR1(gettext_noopt("Could not get ALSA port information: %s"), + Error::DRIVER_ERROR, + snd_strerror(error)); + } + snd_seq_port_info_set_name( pinfo, name.c_str() ); + if ((error = snd_seq_set_port_info( seq, port, pinfo ) )) { + throw RTMIDI_ERROR1(gettext_noopt("Could not set ALSA port information: %s"), + Error::DRIVER_ERROR, + snd_strerror(error)); + } + } + + int getPortCapabilities(int client, int port) { + init(); + snd_seq_port_info_t *pinfo; + snd_seq_port_info_alloca( &pinfo ); + { + scoped_lock lock (mutex); + snd_seq_get_any_port_info(seq,client,port,pinfo); + } + unsigned int caps = snd_seq_port_info_get_capability(pinfo); + int retval = (caps & (SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ))? + PortDescriptor::INPUT:0; + if (caps & (SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE)) + retval |= PortDescriptor::OUTPUT; + return retval; + } + + int getNextClient(snd_seq_client_info_t * cinfo ) { + init(); + scoped_lock lock (mutex); + return snd_seq_query_next_client (seq, cinfo); + } + + int getNextPort(snd_seq_port_info_t * pinfo ) { + init(); + scoped_lock lock (mutex); + return snd_seq_query_next_port (seq, pinfo); + } + + int createPort (snd_seq_port_info_t *pinfo) { + init(); + scoped_lock lock (mutex); + return snd_seq_create_port(seq, pinfo); + } + + void deletePort(int port) { + init(); + scoped_lock lock (mutex); + snd_seq_delete_port( seq, port ); + } + + snd_seq_port_subscribe_t * connectPorts(const snd_seq_addr_t & from, + const snd_seq_addr_t & to, + bool real_time) { + init(); + snd_seq_port_subscribe_t *subscription; + + if (snd_seq_port_subscribe_malloc( &subscription ) < 0) { + throw RTMIDI_ERROR(gettext_noopt("Could not allocate ALSA port subscription."), + Error::DRIVER_ERROR ); + return 0; + } + snd_seq_port_subscribe_set_sender(subscription, &from); + snd_seq_port_subscribe_set_dest(subscription, &to); + if (real_time) { + snd_seq_port_subscribe_set_time_update(subscription, 1); + snd_seq_port_subscribe_set_time_real(subscription, 1); + } + { + scoped_lock lock (mutex); + if ( snd_seq_subscribe_port(seq, subscription) ) { + snd_seq_port_subscribe_free( subscription ); + subscription = 0; + throw RTMIDI_ERROR(gettext_noopt("Error making ALSA port connection."), + Error::DRIVER_ERROR); + return 0; + } + } + return subscription; + } + + void closePort(snd_seq_port_subscribe_t * subscription ) { + init(); + scoped_lock lock(mutex); + snd_seq_unsubscribe_port( seq, subscription ); + } + + void startQueue(int queue_id) { + init(); + scoped_lock lock(mutex); + snd_seq_start_queue( seq, queue_id, NULL ); + snd_seq_drain_output( seq ); + } + + /*! Use AlsaSequencer like a C pointer. + \note This function breaks the design to control thread safety + by the selection of the \ref locking parameter to the class. + It should be removed as soon as possible in order ensure the + thread policy that has been intended by creating this class. + */ + operator snd_seq_t * () + { + return seq; + } +protected: + struct scoped_lock { + pthread_mutex_t * mutex; + scoped_lock(pthread_mutex_t & m): mutex(&m) + { + if (locking) + pthread_mutex_lock(mutex); + } + ~scoped_lock() + { + if (locking) + pthread_mutex_unlock(mutex); + } + }; + pthread_mutex_t mutex; + snd_seq_t * seq; + std::string name; + + + snd_seq_client_info_t * GetClient(int id) { + init(); + snd_seq_client_info_t * cinfo; + scoped_lock lock(mutex); + snd_seq_get_any_client_info(seq,id,cinfo); + return cinfo; + } + + void init() + { + init (seq); + } + + void init(snd_seq_t * &s) + { + if (s) return; + { + scoped_lock lock(mutex); + int result = snd_seq_open(&s, "default", SND_SEQ_OPEN_DUPLEX, SND_SEQ_NONBLOCK); + if ( result < 0 ) { + switch (result) { + case -ENOENT: // /dev/snd/seq does not exist + // Error numbers are defined to be positive + case ENOENT: // just in case ... + throw RTMIDI_ERROR(snd_strerror(result), + Error::NO_DEVICES_FOUND); + return; + default: + std::cerr << __FILE__ << ":" << __LINE__ + << "Got unhandled error number " << result << std::endl; + throw RTMIDI_ERROR(snd_strerror(result), + Error::DRIVER_ERROR ); + return; + } + } + snd_seq_set_client_name( seq, name.c_str() ); + } + } +}; +#undef RTMIDI_CLASSNAME +typedef AlsaSequencer<1> LockingAlsaSequencer; +typedef AlsaSequencer<0> NonLockingAlsaSequencer; + +#define RTMIDI_CLASSNAME "AlsaPortDescriptor" +struct AlsaPortDescriptor:public PortDescriptor, + public snd_seq_addr_t +{ + MidiApi * api; + static LockingAlsaSequencer seq; + AlsaPortDescriptor(const std::string &name):api(0),clientName(name) + { + client = 0; + port = 0; + } + AlsaPortDescriptor(int c, int p, const std::string &name):api(0),clientName(name) + { + client = c; + port = p; + seq.setName(name); + } + AlsaPortDescriptor(snd_seq_addr_t & other, + const std::string &name):snd_seq_addr_t(other), + clientName(name) { + seq.setName(name); + } + ~AlsaPortDescriptor() {} + MidiInApi * getInputApi(unsigned int queueSizeLimit = 100) const { + if (getCapabilities() & INPUT) + return new MidiInAlsa(clientName,queueSizeLimit); + else + return 0; + } + MidiOutApi * getOutputApi() const { + if (getCapabilities() & OUTPUT) + return new MidiOutAlsa(clientName); + else + return 0; + } + std::string getName(int flags = SHORT_NAME | UNIQUE_PORT_NAME) { + return seq.GetPortName(client,port,flags); + } + + const std::string &getClientName() { + return clientName; + } + + int getCapabilities() const { + if (!client) return 0; + return seq.getPortCapabilities(client,port); + } + static PortList getPortList(int capabilities, const std::string &clientName); +protected: + std::string clientName; +}; + +LockingAlsaSequencer AlsaPortDescriptor::seq; + + + +PortList AlsaPortDescriptor :: getPortList(int capabilities, const std::string &clientName) +{ + PortList list; + snd_seq_client_info_t *cinfo; + snd_seq_port_info_t *pinfo; + int client; + snd_seq_client_info_alloca( &cinfo ); + snd_seq_port_info_alloca( &pinfo ); + + snd_seq_client_info_set_client( cinfo, -1 ); + while ( seq.getNextClient(cinfo ) >= 0 ) { + client = snd_seq_client_info_get_client( cinfo ); + // ignore default device (it is included in the following results again) + if ( client == 0 ) continue; + // Reset query info + snd_seq_port_info_set_client( pinfo, client ); + snd_seq_port_info_set_port( pinfo, -1 ); + while ( seq.getNextPort( pinfo ) >= 0 ) { + unsigned int atyp = snd_seq_port_info_get_type( pinfo ); + // otherwise we get ports without any + if ( !(capabilities & UNLIMITED) && + !( atyp & SND_SEQ_PORT_TYPE_MIDI_GENERIC ) && + !( atyp & SND_SEQ_PORT_TYPE_SYNTH ) + ) continue; + unsigned int caps = snd_seq_port_info_get_capability( pinfo ); + if (capabilities & INPUT) { + /* we need both READ and SUBS_READ */ + if ((caps & (SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ)) + != (SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ)) + continue; + } + if (capabilities & OUTPUT) { + /* we need both WRITE and SUBS_WRITE */ + if ((caps & (SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE)) + != (SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE)) + continue; + } + list.push_back(Pointer( + new AlsaPortDescriptor(client,snd_seq_port_info_get_port(pinfo),clientName))); + } + } + return list; +} +#undef RTMIDI_CLASSNAME + + +/*! A structure to hold variables related to the ALSA API + implementation. + + \note After all sequencer handling is covered by the \ref + AlsaSequencer class, we should make seq to be a pointer in order + to allow a common client implementation. +*/ +#define RTMIDI_CLASSNAME "AlsaMidiData" + +struct AlsaMidiData:public AlsaPortDescriptor { + /* + AlsaMidiData():seq() + { + init(); + } + */ + AlsaMidiData(const std::string &clientName):AlsaPortDescriptor(clientName), + seq(clientName) + { + init(); + } + ~AlsaMidiData() + { + if (local.client) + deletePort(); + } + void init () { + local.port = 0; + local.client = 0; + port = -1; + subscription = 0; + coder = 0; + bufferSize = 32; + buffer = 0; + dummy_thread_id = pthread_self(); + thread = dummy_thread_id; + queue_id = -1; + trigger_fds[0] = -1; + trigger_fds[1] = -1; + } + snd_seq_addr_t local; /*!< Our port and client id. If client = 0 (default) this means we didn't aquire a port so far. */ + NonLockingAlsaSequencer seq; + // unsigned int portNum; snd_seq_port_subscribe_t *subscription; snd_midi_event_t *coder; unsigned int bufferSize; unsigned char *buffer; pthread_t thread; pthread_t dummy_thread_id; - unsigned long long lastTime; + snd_seq_real_time_t lastTime; int queue_id; // an input queue is needed to get timestamped events int trigger_fds[2]; + + void setRemote(const AlsaPortDescriptor * remote) { + port = remote->port; + client = remote->client; + } + void connectPorts(const snd_seq_addr_t &from, + const snd_seq_addr_t &to, + bool real_time) { + subscription = seq.connectPorts(from, to, real_time); + } + + int openPort(int alsaCapabilities, + const std::string &portName) { + if (subscription) { + api->error( RTMIDI_ERROR(gettext_noopt("Could not allocate ALSA port subscription."), + Error::DRIVER_ERROR )); + return -99; + } + + snd_seq_port_info_t *pinfo; + snd_seq_port_info_alloca( &pinfo ); + + snd_seq_port_info_set_client( pinfo, 0 ); + snd_seq_port_info_set_port( pinfo, 0 ); + snd_seq_port_info_set_capability( pinfo, + alsaCapabilities); + 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); +#ifndef AVOID_TIMESTAMPING + snd_seq_port_info_set_timestamping(pinfo, 1); + snd_seq_port_info_set_timestamp_real(pinfo, 1); + snd_seq_port_info_set_timestamp_queue(pinfo, queue_id); +#endif + snd_seq_port_info_set_name(pinfo, portName.c_str() ); + int createok = seq.createPort(pinfo); + + if ( createok < 0 ) { + api->error(RTMIDI_ERROR("ALSA error while creating input port.", + Error::DRIVER_ERROR)); + return createok; + } + + local.client = snd_seq_port_info_get_client( pinfo ); + local.port = snd_seq_port_info_get_port(pinfo); + return 0; + } + + void deletePort() { + seq.deletePort(local.port); + local.client = 0; + local.port = 0; + } + + void closePort() { + seq.closePort(subscription ); + snd_seq_port_subscribe_free( subscription ); + subscription = 0; + } + + void setName(const std::string &name) { + seq.setPortName(name, local.port); + } + + void setClientName(const std::string &name) { + seq.setName(name); + } + + bool startQueue(void * userdata) { + // Start the input queue +#ifndef AVOID_TIMESTAMPING + seq.startQueue(queue_id); +#endif + // Start our MIDI input thread. + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); + pthread_attr_setschedpolicy(&attr, SCHED_OTHER); + + int err = pthread_create(&thread, &attr, MidiInAlsa::alsaMidiHandler, userdata); + pthread_attr_destroy(&attr); + if ( err ) { + closePort(); + api->error(RTMIDI_ERROR(gettext_noopt("Error starting MIDI input thread!"), + Error::THREAD_ERROR)); + return false; + } + return true; + } }; +#undef RTMIDI_CLASSNAME #define PORT_TYPE( pinfo, bits ) ((snd_seq_port_info_get_capability(pinfo) & (bits)) == (bits)) @@ -1140,13 +3232,15 @@ struct AlsaMidiData { // Class Definitions: MidiInAlsa //*********************************************************************// -static void *alsaMidiHandler( void *ptr ) +#define RTMIDI_CLASSNAME "MidiInAlsa" +// static function: +void * MidiInAlsa::alsaMidiHandler( void *ptr ) throw() { - MidiInApi::RtMidiInData *data = static_cast (ptr); - AlsaMidiData *apiData = static_cast (data->apiData); + MidiInAlsa *data = static_cast (ptr); + AlsaMidiData *apiData = static_cast (data->apiData_); long nBytes; - unsigned long long time, lastTime; + double time; bool continueSysex = false; bool doDecode = false; MidiInApi::MidiMessage message; @@ -1159,7 +3253,12 @@ static void *alsaMidiHandler( void *ptr ) result = snd_midi_event_new( 0, &apiData->coder ); if ( result < 0 ) { data->doInput = false; - std::cerr << "\nMidiInAlsa::alsaMidiHandler: error initializing MIDI event parser!\n\n"; + try { + data->error(RTMIDI_ERROR(rtmidi_gettext("Error initializing MIDI event parser."), + Error::WARNING)); + } catch (Error & e) { + // don't bother ALSA with an unhandled exception + } return 0; } unsigned char *buffer = (unsigned char *) malloc( apiData->bufferSize ); @@ -1167,7 +3266,12 @@ static void *alsaMidiHandler( void *ptr ) data->doInput = false; snd_midi_event_free( apiData->coder ); apiData->coder = 0; - std::cerr << "\nMidiInAlsa::alsaMidiHandler: error initializing buffer memory!\n\n"; + try { + data->error(RTMIDI_ERROR(rtmidi_gettext("Error initializing buffer memory."), + Error::WARNING)); + } catch (Error & e) { + // don't bother ALSA with an unhandled exception + } return 0; } snd_midi_event_init( apiData->coder ); @@ -1184,11 +3288,11 @@ static void *alsaMidiHandler( void *ptr ) if ( snd_seq_event_input_pending( apiData->seq, 1 ) == 0 ) { // No data pending if ( poll( poll_fds, poll_fd_count, -1) >= 0 ) { - if ( poll_fds[0].revents & POLLIN ) { - bool dummy; - int res = read( poll_fds[0].fd, &dummy, sizeof(dummy) ); - (void) res; - } + if ( poll_fds[0].revents & POLLIN ) { + bool dummy; + int res = read( poll_fds[0].fd, &dummy, sizeof(dummy) ); + (void) res; + } } continue; } @@ -1196,12 +3300,33 @@ static void *alsaMidiHandler( void *ptr ) // If here, there should be data. result = snd_seq_event_input( apiData->seq, &ev ); if ( result == -ENOSPC ) { - std::cerr << "\nMidiInAlsa::alsaMidiHandler: MIDI input buffer overrun!\n\n"; + try { + data->error(RTMIDI_ERROR(rtmidi_gettext("MIDI input buffer overrun."), + Error::WARNING)); + } catch (Error & e) { + // don't bother ALSA with an unhandled exception + } + + continue; + } + else if ( result == -EAGAIN ) { + try { + data->error(RTMIDI_ERROR(rtmidi_gettext("ALSA returned without providing a MIDI event."), + Error::WARNING)); + } catch (Error & e) { + // don't bother ALSA with an unhandled exception + } + continue; } else if ( result <= 0 ) { - std::cerr << "\nMidiInAlsa::alsaMidiHandler: unknown MIDI input error!\n"; - perror("System reports"); + try { + data->error(RTMIDI_ERROR1(rtmidi_gettext("Unknown MIDI input error.\nThe system reports:\n%s"), + Error::WARNING, + strerror(-result))); + } catch (Error & e) { + // don't bother ALSA with an unhandled exception + } continue; } @@ -1222,10 +3347,10 @@ static void *alsaMidiHandler( void *ptr ) #if defined(__RTMIDI_DEBUG__) std::cerr << "MidiInAlsa::alsaMidiHandler: port connection has closed!\n"; std::cout << "sender = " << (int) ev->data.connect.sender.client << ":" - << (int) ev->data.connect.sender.port - << ", dest = " << (int) ev->data.connect.dest.client << ":" - << (int) ev->data.connect.dest.port - << std::endl; + << (int) ev->data.connect.sender.port + << ", dest = " << (int) ev->data.connect.dest.client << ":" + << (int) ev->data.connect.dest.port + << std::endl; #endif break; @@ -1245,19 +3370,24 @@ static void *alsaMidiHandler( void *ptr ) if ( !( data->ignoreFlags & 0x04 ) ) doDecode = true; break; - case SND_SEQ_EVENT_SYSEX: + case SND_SEQ_EVENT_SYSEX: if ( (data->ignoreFlags & 0x01) ) break; if ( ev->data.ext.len > apiData->bufferSize ) { - apiData->bufferSize = ev->data.ext.len; - free( buffer ); - buffer = (unsigned char *) malloc( apiData->bufferSize ); - if ( buffer == NULL ) { - data->doInput = false; - std::cerr << "\nMidiInAlsa::alsaMidiHandler: error resizing buffer memory!\n\n"; - break; - } + apiData->bufferSize = ev->data.ext.len; + free( buffer ); + buffer = (unsigned char *) malloc( apiData->bufferSize ); + if ( buffer == NULL ) { + data->doInput = false; + try { + data->error(RTMIDI_ERROR(rtmidi_gettext("Error resizing buffer memory."), + Error::WARNING)); + } catch (Error & e) { + // don't bother ALSA with an unhandled exception + } + break; + } } - + RTMIDI_FALLTHROUGH; default: doDecode = true; } @@ -1266,62 +3396,89 @@ static void *alsaMidiHandler( void *ptr ) nBytes = snd_midi_event_decode( apiData->coder, buffer, apiData->bufferSize, ev ); if ( nBytes > 0 ) { - // The ALSA sequencer has a maximum buffer size for MIDI sysex - // events of 256 bytes. If a device sends sysex messages larger - // than this, they are segmented into 256 byte chunks. So, - // we'll watch for this and concatenate sysex chunks into a - // single sysex message if necessary. - if ( !continueSysex ) - message.bytes.assign( buffer, &buffer[nBytes] ); - else - message.bytes.insert( message.bytes.end(), buffer, &buffer[nBytes] ); - - continueSysex = ( ( ev->type == SND_SEQ_EVENT_SYSEX ) && ( message.bytes.back() != 0xF7 ) ); - if ( !continueSysex ) { - - // Calculate the time stamp: - message.timeStamp = 0.0; - - // Method 1: Use the system time. - //(void)gettimeofday(&tv, (struct timezone *)NULL); - //time = (tv.tv_sec * 1000000) + tv.tv_usec; - - // Method 2: Use the ALSA sequencer event time data. - // (thanks to Pedro Lopez-Cabanillas!). - time = ( ev->time.time.tv_sec * 1000000 ) + ( ev->time.time.tv_nsec/1000 ); - lastTime = time; - time -= apiData->lastTime; - apiData->lastTime = lastTime; - if ( data->firstMessage == true ) - data->firstMessage = false; - else - message.timeStamp = time * 0.000001; - } - else { + // The ALSA sequencer has a maximum buffer size for MIDI sysex + // events of 256 bytes. If a device sends sysex messages larger + // than this, they are segmented into 256 byte chunks. So, + // we'll watch for this and concatenate sysex chunks into a + // single sysex message if necessary. + if ( !continueSysex ) + message.bytes.assign( buffer, &buffer[nBytes] ); + else + message.bytes.insert( message.bytes.end(), buffer, &buffer[nBytes] ); + + continueSysex = ( ( ev->type == SND_SEQ_EVENT_SYSEX ) && ( message.bytes.back() != 0xF7 ) ); + if ( !continueSysex ) { + + // Calculate the time stamp: + message.timeStamp = 0.0; + + // Method 1: Use the system time. + //(void)gettimeofday(&tv, (struct timezone *)NULL); + //time = (tv.tv_sec * 1000000) + tv.tv_usec; + + // Method 2: Use the ALSA sequencer event time data. + // (thanks to Pedro Lopez-Cabanillas!). + // time = ( ev->time.time.tv_sec * 1000000 ) + ( ev->time.time.tv_nsec/1000 ); + // lastTime = time; + // time -= apiData->lastTime; + // apiData->lastTime = lastTime; + // Using method from: + // https://www.gnu.org/software/libc/manual/html_node/Elapsed-Time.html + + // Perform the carry for the later subtraction by updating y. + snd_seq_real_time_t &x(ev->time.time); + snd_seq_real_time_t &y(apiData->lastTime); + if (x.tv_nsec < y.tv_nsec) { + int nsec = (y.tv_nsec - x.tv_nsec) / 1000000000 + 1; + y.tv_nsec -= 1000000000 * nsec; + y.tv_sec += nsec; + } + if (x.tv_nsec - y.tv_nsec > 1000000000) { + int nsec = (x.tv_nsec - y.tv_nsec) / 1000000000; + y.tv_nsec += 1000000000 * nsec; + y.tv_sec -= nsec; + } + + // Compute the time difference. + time = x.tv_sec - y.tv_sec + (x.tv_nsec - y.tv_nsec)*1e-9; + + apiData->lastTime = ev->time.time; + + if ( data->firstMessage == true ) + data->firstMessage = false; + else + message.timeStamp = time * 0.000001; + } + else { #if defined(__RTMIDI_DEBUG__) - std::cerr << "\nMidiInAlsa::alsaMidiHandler: event parsing error or not a MIDI event!\n\n"; + try { + data->error(RTMIDI_ERROR(rtmidi_gettext("Event parsing error or not a MIDI event."), + Error::WARNING)); + } catch (Error & e) { + // don't bother ALSA with an unhandled exception + } #endif - } + } } } snd_seq_free_event( ev ); + ev = 0; if ( message.bytes.size() == 0 || continueSysex ) continue; - if ( data->usingCallback ) { - RtMidiIn::RtMidiCallback callback = (RtMidiIn::RtMidiCallback) data->userCallback; - callback( message.timeStamp, &message.bytes, data->userData ); + if ( data->userCallback ) { + data->userCallback->rtmidi_midi_in( message.timeStamp, message.bytes); } else { // As long as we haven't reached our queue size limit, push the message. - if ( data->queue.size < data->queue.ringSize ) { - data->queue.ring[data->queue.back++] = message; - if ( data->queue.back == data->queue.ringSize ) - data->queue.back = 0; - data->queue.size++; + if (!data->queue.push(message)) { + try { + data->error(RTMIDI_ERROR(rtmidi_gettext("Error: Message queue limit reached."), + Error::WARNING)); + } catch (Error & e) { + // don't bother ALSA with an unhandled exception + } } - else - std::cerr << "\nMidiInAlsa: message queue limit reached!!\n\n"; } } @@ -1332,21 +3489,22 @@ static void *alsaMidiHandler( void *ptr ) return 0; } -MidiInAlsa :: MidiInAlsa( const std::string clientName, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) +MidiInAlsa :: MidiInAlsa( const std::string &clientName, + unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) { - initialize( clientName ); + MidiInAlsa::initialize( clientName ); } MidiInAlsa :: ~MidiInAlsa() { // Close a connection if it exists. - closePort(); + MidiInAlsa::closePort(); // Shutdown the input thread. AlsaMidiData *data = static_cast (apiData_); - if ( inputData_.doInput ) { - inputData_.doInput = false; - int res = write( data->trigger_fds[1], &inputData_.doInput, sizeof(inputData_.doInput) ); + if ( doInput ) { + doInput = false; + int res = write( data->trigger_fds[1], &doInput, sizeof(doInput) ); (void) res; if ( !pthread_equal(data->thread, data->dummy_thread_id) ) pthread_join( data->thread, NULL ); @@ -1355,50 +3513,30 @@ MidiInAlsa :: ~MidiInAlsa() // Cleanup. close ( data->trigger_fds[0] ); close ( data->trigger_fds[1] ); - if ( data->vport >= 0 ) snd_seq_delete_port( data->seq, data->vport ); + if ( data->local.client ) data->deletePort(); #ifndef AVOID_TIMESTAMPING snd_seq_free_queue( data->seq, data->queue_id ); + data->queue_id = -1; #endif - snd_seq_close( data->seq ); delete data; } -void MidiInAlsa :: initialize( const std::string& clientName ) +void MidiInAlsa :: initialize( const std::string &clientName ) { - // Set up the ALSA sequencer client. - snd_seq_t *seq; - int result = snd_seq_open(&seq, "default", SND_SEQ_OPEN_DUPLEX, SND_SEQ_NONBLOCK); - if ( result < 0 ) { - errorString_ = "MidiInAlsa::initialize: error creating ALSA sequencer client object."; - error( RtMidiError::DRIVER_ERROR, errorString_ ); - return; - } - - // Set client name. - snd_seq_set_client_name( seq, clientName.c_str() ); // Save our api-specific connection information. - AlsaMidiData *data = (AlsaMidiData *) new AlsaMidiData; - data->seq = seq; - data->portNum = -1; - data->vport = -1; - data->subscription = 0; - data->dummy_thread_id = pthread_self(); - data->thread = data->dummy_thread_id; - data->trigger_fds[0] = -1; - data->trigger_fds[1] = -1; + AlsaMidiData *data = new AlsaMidiData (clientName); apiData_ = (void *) data; - inputData_.apiData = (void *) data; - if ( pipe(data->trigger_fds) == -1 ) { - errorString_ = "MidiInAlsa::initialize: error creating pipe objects."; - error( RtMidiError::DRIVER_ERROR, errorString_ ); + if ( pipe(data->trigger_fds) == -1 ) { + error(RTMIDI_ERROR(gettext_noopt("Error creating pipe objects."), + Error::DRIVER_ERROR) ); return; } // Create the input queue #ifndef AVOID_TIMESTAMPING - data->queue_id = snd_seq_alloc_named_queue(seq, "RtMidi Queue"); + data->queue_id = snd_seq_alloc_named_queue(data->seq, "Midi Queue"); // Set arbitrary tempo (mm=100) and resolution (240) snd_seq_queue_tempo_t *qtempo; snd_seq_queue_tempo_alloca(&qtempo); @@ -1426,7 +3564,8 @@ unsigned int portInfo( snd_seq_t *seq, snd_seq_port_info_t *pinfo, unsigned int snd_seq_port_info_set_port( pinfo, -1 ); while ( snd_seq_query_next_port( seq, pinfo ) >= 0 ) { unsigned int atyp = snd_seq_port_info_get_type( pinfo ); - if ( ( atyp & SND_SEQ_PORT_TYPE_MIDI_GENERIC ) == 0 ) continue; + if ( ( ( atyp & SND_SEQ_PORT_TYPE_MIDI_GENERIC ) == 0 ) && + ( ( atyp & SND_SEQ_PORT_TYPE_SYNTH ) == 0 ) ) continue; unsigned int caps = snd_seq_port_info_get_capability( pinfo ); if ( ( caps & type ) != type ) continue; if ( count == portNumber ) return 1; @@ -1462,6 +3601,8 @@ std::string MidiInAlsa :: getPortName( unsigned int portNumber ) snd_seq_get_any_client_info( data->seq, cnum, cinfo ); std::ostringstream os; os << snd_seq_client_info_get_name( cinfo ); + os << ":"; + os << snd_seq_port_info_get_name( pinfo ); os << " "; // These lines added to make sure devices are listed os << snd_seq_port_info_get_client( pinfo ); // with full portnames added to ensure individual device names os << ":"; @@ -1471,23 +3612,23 @@ std::string MidiInAlsa :: getPortName( unsigned int portNumber ) } // If we get here, we didn't find a match. - errorString_ = "MidiInAlsa::getPortName: error looking for port name!"; - error( RtMidiError::WARNING, errorString_ ); + error( RTMIDI_ERROR(gettext_noopt("Error looking for port name."), + Error::WARNING) ); return stringName; } -void MidiInAlsa :: openPort( unsigned int portNumber, const std::string portName ) +void MidiInAlsa :: openPort( unsigned int portNumber, const std::string &portName ) { if ( connected_ ) { - errorString_ = "MidiInAlsa::openPort: a valid connection already exists!"; - error( RtMidiError::WARNING, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("A valid connection already exists."), + Error::WARNING) ); return; } unsigned int nSrc = this->getPortCount(); if ( nSrc < 1 ) { - errorString_ = "MidiInAlsa::openPort: no MIDI input sources found!"; - error( RtMidiError::NO_DEVICES_FOUND, errorString_ ); + error( RTMIDI_ERROR(gettext_noopt("No MIDI input sources found."), + Error::NO_DEVICES_FOUND )); return; } @@ -1496,9 +3637,9 @@ void MidiInAlsa :: openPort( unsigned int portNumber, const std::string portName AlsaMidiData *data = static_cast (apiData_); if ( portInfo( data->seq, src_pinfo, SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, (int) portNumber ) == 0 ) { std::ostringstream ost; - ost << "MidiInAlsa::openPort: the 'portNumber' argument (" << portNumber << ") is invalid."; - errorString_ = ost.str(); - error( RtMidiError::INVALID_PARAMETER, errorString_ ); + error( RTMIDI_ERROR1(gettext_noopt("The 'portNumber' argument (%d) is invalid."), + Error::INVALID_PARAMETER, + portNumber) ); return; } @@ -1508,40 +3649,40 @@ void MidiInAlsa :: openPort( unsigned int portNumber, const std::string portName snd_seq_port_info_t *pinfo; snd_seq_port_info_alloca( &pinfo ); - if ( data->vport < 0 ) { + if ( !data->local.client ) { snd_seq_port_info_set_client( pinfo, 0 ); snd_seq_port_info_set_port( pinfo, 0 ); snd_seq_port_info_set_capability( pinfo, - SND_SEQ_PORT_CAP_WRITE | - SND_SEQ_PORT_CAP_SUBS_WRITE ); + 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_TYPE_MIDI_GENERIC | + SND_SEQ_PORT_TYPE_APPLICATION ); snd_seq_port_info_set_midi_channels(pinfo, 16); #ifndef AVOID_TIMESTAMPING snd_seq_port_info_set_timestamping(pinfo, 1); - snd_seq_port_info_set_timestamp_real(pinfo, 1); + snd_seq_port_info_set_timestamp_real(pinfo, 1); snd_seq_port_info_set_timestamp_queue(pinfo, data->queue_id); #endif snd_seq_port_info_set_name(pinfo, portName.c_str() ); - data->vport = snd_seq_create_port(data->seq, pinfo); - - if ( data->vport < 0 ) { - errorString_ = "MidiInAlsa::openPort: ALSA error creating input port."; - error( RtMidiError::DRIVER_ERROR, errorString_ ); + int createok = snd_seq_create_port(data->seq, pinfo); + + if ( createok < 0 ) { + error( RTMIDI_ERROR(gettext_noopt("Error creating ALSA input port."), + Error::DRIVER_ERROR)); return; } - data->vport = snd_seq_port_info_get_port(pinfo); + data->local.port = snd_seq_port_info_get_port(pinfo); + data->local.client = snd_seq_port_info_get_client(pinfo); } - receiver.client = snd_seq_port_info_get_client( pinfo ); - receiver.port = data->vport; + receiver = data->local; if ( !data->subscription ) { // Make subscription if (snd_seq_port_subscribe_malloc( &data->subscription ) < 0) { - errorString_ = "MidiInAlsa::openPort: ALSA error allocation port subscription."; - error( RtMidiError::DRIVER_ERROR, errorString_ ); + error( RTMIDI_ERROR(gettext_noopt("Could not allocate ALSA port subscription."), + Error::DRIVER_ERROR) ); return; } snd_seq_port_subscribe_set_sender(data->subscription, &sender); @@ -1549,13 +3690,13 @@ void MidiInAlsa :: openPort( unsigned int portNumber, const std::string portName if ( snd_seq_subscribe_port(data->seq, data->subscription) ) { snd_seq_port_subscribe_free( data->subscription ); data->subscription = 0; - errorString_ = "MidiInAlsa::openPort: ALSA error making port connection."; - error( RtMidiError::DRIVER_ERROR, errorString_ ); + error( RTMIDI_ERROR(gettext_noopt("Error making ALSA port connection."), + Error::DRIVER_ERROR) ); return; } } - if ( inputData_.doInput == false ) { + if ( doInput == false ) { // Start the input queue #ifndef AVOID_TIMESTAMPING snd_seq_start_queue( data->seq, data->queue_id, NULL ); @@ -1567,16 +3708,16 @@ void MidiInAlsa :: openPort( unsigned int portNumber, const std::string portName pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); pthread_attr_setschedpolicy(&attr, SCHED_OTHER); - inputData_.doInput = true; - int err = pthread_create(&data->thread, &attr, alsaMidiHandler, &inputData_); + doInput = true; + int err = pthread_create(&data->thread, &attr, alsaMidiHandler, this); pthread_attr_destroy(&attr); if ( err ) { snd_seq_unsubscribe_port( data->seq, data->subscription ); snd_seq_port_subscribe_free( data->subscription ); data->subscription = 0; - inputData_.doInput = false; - errorString_ = "MidiInAlsa::openPort: error starting MIDI input thread!"; - error( RtMidiError::THREAD_ERROR, errorString_ ); + doInput = false; + error( RTMIDI_ERROR(gettext_noopt("Error starting MIDI input thread!"), + Error::THREAD_ERROR) ); return; } } @@ -1584,10 +3725,93 @@ void MidiInAlsa :: openPort( unsigned int portNumber, const std::string portName connected_ = true; } -void MidiInAlsa :: openVirtualPort( std::string portName ) +void MidiInAlsa :: openPort( const PortDescriptor & port, + const std::string &portName) +{ + AlsaMidiData *data = static_cast (apiData_); + const AlsaPortDescriptor * remote = dynamic_cast(&port); + + if ( !data ) { + error( RTMIDI_ERROR(gettext_noopt("Data has not been allocated."), + Error::SYSTEM_ERROR) ); + return; + } + if ( connected_ ) { + error( RTMIDI_ERROR(gettext_noopt("A valid connection already exists."), + Error::WARNING) ); + return; + } + if (data->subscription) { + error( RTMIDI_ERROR(gettext_noopt("Could not allocate ALSA port subscription."), + Error::DRIVER_ERROR)); + return; + } + if (!remote) { + error( RTMIDI_ERROR(gettext_noopt("ALSA has been instructed to open a non-ALSA MIDI port. This doesn't work."), + Error::INVALID_DEVICE) ); + return; + } + + try { + if (!data->local.client) + data->openPort (SND_SEQ_PORT_CAP_WRITE + | SND_SEQ_PORT_CAP_SUBS_WRITE, + portName); + data->setRemote(remote); + data->connectPorts(*remote, + data->local, + false); + + + if ( doInput == false ) { + doInput + = data->startQueue(this); + } + + connected_ = true; + } catch (Error & e) { + error(e); + } +} + +Pointer MidiInAlsa :: getDescriptor(bool local) +{ + AlsaMidiData *data = static_cast (apiData_); + try { + if (local) { + if (data && data->local.client) { + return Pointer( + new AlsaPortDescriptor(data->local,data->getClientName())); + } + } else { + if (data && data->client) { + return Pointer( + new AlsaPortDescriptor(*data,data->getClientName())); + } + } + } catch (Error & e) { + error (e); + } + return NULL; +} +PortList MidiInAlsa :: getPortList(int capabilities) +{ + AlsaMidiData *data = static_cast (apiData_); + try { + return AlsaPortDescriptor::getPortList(capabilities | PortDescriptor::INPUT, + data->getClientName()); + } catch (Error & e) { + error (e); + return PortList(); + } +} + + + +void MidiInAlsa :: openVirtualPort(const std::string &portName ) { AlsaMidiData *data = static_cast (apiData_); - if ( data->vport < 0 ) { + if ( !data->local.client ) { snd_seq_port_info_t *pinfo; snd_seq_port_info_alloca( &pinfo ); snd_seq_port_info_set_capability( pinfo, @@ -1599,21 +3823,23 @@ void MidiInAlsa :: openVirtualPort( std::string portName ) snd_seq_port_info_set_midi_channels(pinfo, 16); #ifndef AVOID_TIMESTAMPING snd_seq_port_info_set_timestamping(pinfo, 1); - snd_seq_port_info_set_timestamp_real(pinfo, 1); + snd_seq_port_info_set_timestamp_real(pinfo, 1); snd_seq_port_info_set_timestamp_queue(pinfo, data->queue_id); #endif snd_seq_port_info_set_name(pinfo, portName.c_str()); - data->vport = snd_seq_create_port(data->seq, pinfo); + int createok = snd_seq_create_port(data->seq, pinfo); - if ( data->vport < 0 ) { - errorString_ = "MidiInAlsa::openVirtualPort: ALSA error creating virtual port."; - error( RtMidiError::DRIVER_ERROR, errorString_ ); + if ( createok < 0 ) { + errorString_ = "MidiInAlsa::openVirtualPort: "; + error( RTMIDI_ERROR(gettext_noopt("Error creating ALSA virtual port."), + Error::DRIVER_ERROR) ); return; } - data->vport = snd_seq_port_info_get_port(pinfo); + data->local.port = snd_seq_port_info_get_port(pinfo); + data->local.client = snd_seq_port_info_get_client(pinfo); } - if ( inputData_.doInput == false ) { + if ( doInput == false ) { // Wait for old thread to stop, if still running if ( !pthread_equal(data->thread, data->dummy_thread_id) ) pthread_join( data->thread, NULL ); @@ -1629,18 +3855,18 @@ void MidiInAlsa :: openVirtualPort( std::string portName ) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); pthread_attr_setschedpolicy(&attr, SCHED_OTHER); - inputData_.doInput = true; - int err = pthread_create(&data->thread, &attr, alsaMidiHandler, &inputData_); + doInput = true; + int err = pthread_create(&data->thread, &attr, alsaMidiHandler, this); pthread_attr_destroy(&attr); if ( err ) { if ( data->subscription ) { - snd_seq_unsubscribe_port( data->seq, data->subscription ); - snd_seq_port_subscribe_free( data->subscription ); - data->subscription = 0; + snd_seq_unsubscribe_port( data->seq, data->subscription ); + snd_seq_port_subscribe_free( data->subscription ); + data->subscription = 0; } - inputData_.doInput = false; - errorString_ = "MidiInAlsa::openPort: error starting MIDI input thread!"; - error( RtMidiError::THREAD_ERROR, errorString_ ); + doInput = false; + error( RTMIDI_ERROR(gettext_noopt("Error starting MIDI input thread!"), + Error::THREAD_ERROR) ); return; } } @@ -1665,73 +3891,95 @@ void MidiInAlsa :: closePort( void ) } // Stop thread to avoid triggering the callback, while the port is intended to be closed - if ( inputData_.doInput ) { - inputData_.doInput = false; - int res = write( data->trigger_fds[1], &inputData_.doInput, sizeof(inputData_.doInput) ); + if ( doInput ) { + doInput = false; + int res = write( data->trigger_fds[1], &doInput, sizeof(doInput) ); (void) res; if ( !pthread_equal(data->thread, data->dummy_thread_id) ) pthread_join( data->thread, NULL ); } } +void MidiInAlsa :: setClientName( const std::string &clientName ) +{ + AlsaMidiData *data = static_cast ( apiData_ ); + data->setClientName(clientName); +} + +void MidiInAlsa :: setPortName( const std::string &portName ) +{ + AlsaMidiData *data = static_cast (apiData_); + data->setName(portName); +} + +#undef RTMIDI_CLASSNAME + //*********************************************************************// // API: LINUX ALSA // Class Definitions: MidiOutAlsa //*********************************************************************// -MidiOutAlsa :: MidiOutAlsa( const std::string clientName ) : MidiOutApi() +#define RTMIDI_CLASSNAME "MidiOutAlsa" +MidiOutAlsa :: MidiOutAlsa( const std::string &clientName ) : MidiOutApi() { - initialize( clientName ); + MidiOutAlsa::initialize( clientName ); } MidiOutAlsa :: ~MidiOutAlsa() { // Close a connection if it exists. - closePort(); + MidiOutAlsa::closePort(); // Cleanup. AlsaMidiData *data = static_cast (apiData_); - if ( data->vport >= 0 ) snd_seq_delete_port( data->seq, data->vport ); - if ( data->coder ) snd_midi_event_free( data->coder ); - if ( data->buffer ) free( data->buffer ); - snd_seq_close( data->seq ); + if ( data->local.client > 0 ) { + snd_seq_delete_port( data->seq, data->local.port ); + data->local.port = -1; + } + if ( data->coder ) { + snd_midi_event_free( data->coder ); + data->coder = 0; + } + if ( data->buffer ) { + free( data->buffer ); + data->buffer = 0; + } delete data; } -void MidiOutAlsa :: initialize( const std::string& clientName ) +void MidiOutAlsa :: initialize( const std::string &clientName ) { +#if 0 // Set up the ALSA sequencer client. snd_seq_t *seq; int result1 = snd_seq_open( &seq, "default", SND_SEQ_OPEN_OUTPUT, SND_SEQ_NONBLOCK ); if ( result1 < 0 ) { - errorString_ = "MidiOutAlsa::initialize: error creating ALSA sequencer client object."; - error( RtMidiError::DRIVER_ERROR, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("Error creating ALSA sequencer client object."), + Error::DRIVER_ERROR, errorString_ )); return; - } + } // Set client name. snd_seq_set_client_name( seq, clientName.c_str() ); +#endif // Save our api-specific connection information. - AlsaMidiData *data = (AlsaMidiData *) new AlsaMidiData; - data->seq = seq; - data->portNum = -1; - data->vport = -1; - data->bufferSize = 32; - data->coder = 0; - data->buffer = 0; + AlsaMidiData *data = new AlsaMidiData(clientName); + // data->seq = seq; + // data->portNum = -1; + int result = snd_midi_event_new( data->bufferSize, &data->coder ); if ( result < 0 ) { delete data; - errorString_ = "MidiOutAlsa::initialize: error initializing MIDI event parser!\n\n"; - error( RtMidiError::DRIVER_ERROR, errorString_ ); + error( RTMIDI_ERROR(gettext_noopt("Error initializing MIDI event parser."), + Error::DRIVER_ERROR) ); return; } data->buffer = (unsigned char *) malloc( data->bufferSize ); if ( data->buffer == NULL ) { delete data; - errorString_ = "MidiOutAlsa::initialize: error allocating buffer memory!\n\n"; - error( RtMidiError::MEMORY_ERROR, errorString_ ); + error( RTMIDI_ERROR(gettext_noopt("Error while allocating buffer memory."), + Error::MEMORY_ERROR) ); return; } snd_midi_event_init( data->coder ); @@ -1740,8 +3988,8 @@ void MidiOutAlsa :: initialize( const std::string& clientName ) unsigned int MidiOutAlsa :: getPortCount() { - snd_seq_port_info_t *pinfo; - snd_seq_port_info_alloca( &pinfo ); + snd_seq_port_info_t *pinfo; + snd_seq_port_info_alloca( &pinfo ); AlsaMidiData *data = static_cast (apiData_); return portInfo( data->seq, pinfo, SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE, -1 ); @@ -1761,6 +4009,8 @@ std::string MidiOutAlsa :: getPortName( unsigned int portNumber ) snd_seq_get_any_client_info( data->seq, cnum, cinfo ); std::ostringstream os; os << snd_seq_client_info_get_name(cinfo); + os << ":"; + os << snd_seq_port_info_get_name( pinfo ); os << " "; // These lines added to make sure devices are listed os << snd_seq_port_info_get_client( pinfo ); // with full portnames added to ensure individual device names os << ":"; @@ -1770,70 +4020,75 @@ std::string MidiOutAlsa :: getPortName( unsigned int portNumber ) } // If we get here, we didn't find a match. - errorString_ = "MidiOutAlsa::getPortName: error looking for port name!"; - error( RtMidiError::WARNING, errorString_ ); + errorString_ = "MidiOutAlsa::getPortName: "; + error( RTMIDI_ERROR(gettext_noopt("Error looking for port name."), + Error::WARNING) ); return stringName; } -void MidiOutAlsa :: openPort( unsigned int portNumber, const std::string portName ) +void MidiOutAlsa :: openPort( unsigned int portNumber, const std::string &portName ) { if ( connected_ ) { - errorString_ = "MidiOutAlsa::openPort: a valid connection already exists!"; - error( RtMidiError::WARNING, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("A valid connection already exists."), + Error::WARNING) ); return; } unsigned int nSrc = this->getPortCount(); if (nSrc < 1) { - errorString_ = "MidiOutAlsa::openPort: no MIDI output sources found!"; - error( RtMidiError::NO_DEVICES_FOUND, errorString_ ); + errorString_ = "MidiOutAlsa::openPort: !"; + error(RTMIDI_ERROR(gettext_noopt("No MIDI output sinks found."), + Error::NO_DEVICES_FOUND) ); return; } - snd_seq_port_info_t *pinfo; - snd_seq_port_info_alloca( &pinfo ); + snd_seq_port_info_t *pinfo; + snd_seq_port_info_alloca( &pinfo ); AlsaMidiData *data = static_cast (apiData_); if ( portInfo( data->seq, pinfo, SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE, (int) portNumber ) == 0 ) { std::ostringstream ost; - ost << "MidiOutAlsa::openPort: the 'portNumber' argument (" << portNumber << ") is invalid."; + ost << "MidiOutAlsa::openPort: "; errorString_ = ost.str(); - error( RtMidiError::INVALID_PARAMETER, errorString_ ); + error(RTMIDI_ERROR1(gettext_noopt("The 'portNumber' argument (%d) is invalid."), + Error::INVALID_PARAMETER, portNumber) ); return; } - snd_seq_addr_t sender, receiver; - receiver.client = snd_seq_port_info_get_client( pinfo ); - receiver.port = snd_seq_port_info_get_port( pinfo ); - sender.client = snd_seq_client_id( data->seq ); - - if ( data->vport < 0 ) { - data->vport = snd_seq_create_simple_port( data->seq, portName.c_str(), - SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, - SND_SEQ_PORT_TYPE_MIDI_GENERIC|SND_SEQ_PORT_TYPE_APPLICATION ); - if ( data->vport < 0 ) { - errorString_ = "MidiOutAlsa::openPort: ALSA error creating output port."; - error( RtMidiError::DRIVER_ERROR, errorString_ ); + data->client = snd_seq_port_info_get_client( pinfo ); + data->port = snd_seq_port_info_get_port( pinfo ); + data->local.client = snd_seq_client_id( data->seq ); + + if ( !data->local.client ) { + int port = snd_seq_create_simple_port( data->seq, portName.c_str(), + SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, + SND_SEQ_PORT_TYPE_MIDI_GENERIC|SND_SEQ_PORT_TYPE_APPLICATION ); + if ( port < 0 ) { + errorString_ = "MidiOutAlsa::openPort: "; + error(RTMIDI_ERROR(gettext_noopt("Error creating ALSA output port."), + Error::DRIVER_ERROR)); return; } - } - sender.port = data->vport; + data->local.port = port; + } // Make subscription if (snd_seq_port_subscribe_malloc( &data->subscription ) < 0) { snd_seq_port_subscribe_free( data->subscription ); - errorString_ = "MidiOutAlsa::openPort: error allocating port subscription."; - error( RtMidiError::DRIVER_ERROR, errorString_ ); + data->subscription = 0; + error(RTMIDI_ERROR(gettext_noopt("Could not allocate ALSA port subscription."), + Error::DRIVER_ERROR) ); return; } - snd_seq_port_subscribe_set_sender(data->subscription, &sender); - snd_seq_port_subscribe_set_dest(data->subscription, &receiver); + snd_seq_port_subscribe_set_sender(data->subscription, data); + snd_seq_port_subscribe_set_dest(data->subscription, &data->local); snd_seq_port_subscribe_set_time_update(data->subscription, 1); snd_seq_port_subscribe_set_time_real(data->subscription, 1); if ( snd_seq_subscribe_port(data->seq, data->subscription) ) { snd_seq_port_subscribe_free( data->subscription ); - errorString_ = "MidiOutAlsa::openPort: ALSA error making port connection."; - error( RtMidiError::DRIVER_ERROR, errorString_ ); + data->subscription = 0; + error(RTMIDI_ERROR(gettext_noopt("Error making ALSA port connection."), + Error::DRIVER_ERROR) ); return; } @@ -1846,1670 +4101,1804 @@ void MidiOutAlsa :: closePort( void ) AlsaMidiData *data = static_cast (apiData_); snd_seq_unsubscribe_port( data->seq, data->subscription ); snd_seq_port_subscribe_free( data->subscription ); + data->subscription = 0; connected_ = false; } } -void MidiOutAlsa :: openVirtualPort( std::string portName ) +void MidiOutAlsa :: setClientName( const std::string &clientName ) { - AlsaMidiData *data = static_cast (apiData_); - if ( data->vport < 0 ) { - data->vport = snd_seq_create_simple_port( data->seq, portName.c_str(), - SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, - SND_SEQ_PORT_TYPE_MIDI_GENERIC|SND_SEQ_PORT_TYPE_APPLICATION ); - - if ( data->vport < 0 ) { - errorString_ = "MidiOutAlsa::openVirtualPort: ALSA error creating virtual port."; - error( RtMidiError::DRIVER_ERROR, errorString_ ); - } - } + AlsaMidiData *data = static_cast ( apiData_ ); + data->setClientName(clientName); } -void MidiOutAlsa :: sendMessage( std::vector *message ) +void MidiOutAlsa :: setPortName( const std::string &portName ) { - int result; AlsaMidiData *data = static_cast (apiData_); - unsigned int nBytes = message->size(); - if ( nBytes > data->bufferSize ) { - data->bufferSize = nBytes; - result = snd_midi_event_resize_buffer ( data->coder, nBytes); - if ( result != 0 ) { - errorString_ = "MidiOutAlsa::sendMessage: ALSA error resizing MIDI event buffer."; - error( RtMidiError::DRIVER_ERROR, errorString_ ); - return; - } - free (data->buffer); - data->buffer = (unsigned char *) malloc( data->bufferSize ); - if ( data->buffer == NULL ) { - errorString_ = "MidiOutAlsa::initialize: error allocating buffer memory!\n\n"; - error( RtMidiError::MEMORY_ERROR, errorString_ ); - return; - } - } - - snd_seq_event_t ev; - snd_seq_ev_clear(&ev); - snd_seq_ev_set_source(&ev, data->vport); - snd_seq_ev_set_subs(&ev); - snd_seq_ev_set_direct(&ev); - for ( unsigned int i=0; ibuffer[i] = message->at(i); - result = snd_midi_event_encode( data->coder, data->buffer, (long)nBytes, &ev ); - if ( result < (int)nBytes ) { - errorString_ = "MidiOutAlsa::sendMessage: event parsing error!"; - error( RtMidiError::WARNING, errorString_ ); - return; - } - - // Send the event. - result = snd_seq_event_output(data->seq, &ev); - if ( result < 0 ) { - errorString_ = "MidiOutAlsa::sendMessage: error sending MIDI message to port."; - error( RtMidiError::WARNING, errorString_ ); - return; - } - snd_seq_drain_output(data->seq); -} - -#endif // __LINUX_ALSA__ - - -//*********************************************************************// -// API: Windows Multimedia Library (MM) -//*********************************************************************// - -// API information deciphered from: -// - http://msdn.microsoft.com/library/default.asp?url=/library/en-us/multimed/htm/_win32_midi_reference.asp - -// Thanks to Jean-Baptiste Berruchon for the sysex code. - -#if defined(__WINDOWS_MM__) - -// The Windows MM API is based on the use of a callback function for -// MIDI input. We convert the system specific time stamps to delta -// time values. - -// Windows MM MIDI header files. -#include -#include - -#define RT_SYSEX_BUFFER_SIZE 1024 -#define RT_SYSEX_BUFFER_COUNT 4 - -// A structure to hold variables related to the CoreMIDI API -// implementation. -struct WinMidiData { - HMIDIIN inHandle; // Handle to Midi Input Device - HMIDIOUT outHandle; // Handle to Midi Output Device - DWORD lastTime; - MidiInApi::MidiMessage message; - LPMIDIHDR sysexBuffer[RT_SYSEX_BUFFER_COUNT]; - CRITICAL_SECTION _mutex; // [Patrice] see https://groups.google.com/forum/#!topic/mididev/6OUjHutMpEo -}; - -//*********************************************************************// -// API: Windows MM -// Class Definitions: MidiInWinMM -//*********************************************************************// - -static void CALLBACK midiInputCallback( HMIDIIN /*hmin*/, - UINT inputStatus, - DWORD_PTR instancePtr, - DWORD_PTR midiMessage, - DWORD timestamp ) -{ - if ( inputStatus != MIM_DATA && inputStatus != MIM_LONGDATA && inputStatus != MIM_LONGERROR ) return; - - //MidiInApi::RtMidiInData *data = static_cast (instancePtr); - MidiInApi::RtMidiInData *data = (MidiInApi::RtMidiInData *)instancePtr; - WinMidiData *apiData = static_cast (data->apiData); - - // Calculate time stamp. - if ( data->firstMessage == true ) { - apiData->message.timeStamp = 0.0; - data->firstMessage = false; - } - else apiData->message.timeStamp = (double) ( timestamp - apiData->lastTime ) * 0.001; - apiData->lastTime = timestamp; - - if ( inputStatus == MIM_DATA ) { // Channel or system message - - // Make sure the first byte is a status byte. - unsigned char status = (unsigned char) (midiMessage & 0x000000FF); - if ( !(status & 0x80) ) return; - - // Determine the number of bytes in the MIDI message. - unsigned short nBytes = 1; - if ( status < 0xC0 ) nBytes = 3; - else if ( status < 0xE0 ) nBytes = 2; - else if ( status < 0xF0 ) nBytes = 3; - else if ( status == 0xF1 ) { - if ( data->ignoreFlags & 0x02 ) return; - else nBytes = 2; - } - else if ( status == 0xF2 ) nBytes = 3; - else if ( status == 0xF3 ) nBytes = 2; - else if ( status == 0xF8 && (data->ignoreFlags & 0x02) ) { - // A MIDI timing tick message and we're ignoring it. - return; - } - else if ( status == 0xFE && (data->ignoreFlags & 0x04) ) { - // A MIDI active sensing message and we're ignoring it. - return; - } - - // Copy bytes to our MIDI message. - unsigned char *ptr = (unsigned char *) &midiMessage; - for ( int i=0; imessage.bytes.push_back( *ptr++ ); - } - else { // Sysex message ( MIM_LONGDATA or MIM_LONGERROR ) - MIDIHDR *sysex = ( MIDIHDR *) midiMessage; - if ( !( data->ignoreFlags & 0x01 ) && inputStatus != MIM_LONGERROR ) { - // Sysex message and we're not ignoring it - for ( int i=0; i<(int)sysex->dwBytesRecorded; ++i ) - apiData->message.bytes.push_back( sysex->lpData[i] ); - } - - // The WinMM API requires that the sysex buffer be requeued after - // input of each sysex message. Even if we are ignoring sysex - // messages, we still need to requeue the buffer in case the user - // decides to not ignore sysex messages in the future. However, - // it seems that WinMM calls this function with an empty sysex - // buffer when an application closes and in this case, we should - // avoid requeueing it, else the computer suddenly reboots after - // one or two minutes. - if ( apiData->sysexBuffer[sysex->dwUser]->dwBytesRecorded > 0 ) { - //if ( sysex->dwBytesRecorded > 0 ) { - EnterCriticalSection( &(apiData->_mutex) ); - MMRESULT result = midiInAddBuffer( apiData->inHandle, apiData->sysexBuffer[sysex->dwUser], sizeof(MIDIHDR) ); - LeaveCriticalSection( &(apiData->_mutex) ); - if ( result != MMSYSERR_NOERROR ) - std::cerr << "\nRtMidiIn::midiInputCallback: error sending sysex to Midi device!!\n\n"; - - if ( data->ignoreFlags & 0x01 ) return; - } - else return; - } - - if ( data->usingCallback ) { - RtMidiIn::RtMidiCallback callback = (RtMidiIn::RtMidiCallback) data->userCallback; - callback( apiData->message.timeStamp, &apiData->message.bytes, data->userData ); - } - else { - // As long as we haven't reached our queue size limit, push the message. - if ( data->queue.size < data->queue.ringSize ) { - data->queue.ring[data->queue.back++] = apiData->message; - if ( data->queue.back == data->queue.ringSize ) - data->queue.back = 0; - data->queue.size++; - } - else - std::cerr << "\nRtMidiIn: message queue limit reached!!\n\n"; - } - - // Clear the vector for the next input message. - apiData->message.bytes.clear(); -} - -MidiInWinMM :: MidiInWinMM( const std::string clientName, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) -{ - initialize( clientName ); -} - -MidiInWinMM :: ~MidiInWinMM() -{ - // Close a connection if it exists. - closePort(); - - WinMidiData *data = static_cast (apiData_); - DeleteCriticalSection( &(data->_mutex) ); - - // Cleanup. - delete data; + data->setName(portName); } -void MidiInWinMM :: initialize( const std::string& /*clientName*/ ) +void MidiOutAlsa :: openVirtualPort(const std::string &portName ) { - // We'll issue a warning here if no devices are available but not - // throw an error since the user can plugin something later. - unsigned int nDevices = midiInGetNumDevs(); - if ( nDevices == 0 ) { - errorString_ = "MidiInWinMM::initialize: no MIDI input devices currently available."; - error( RtMidiError::WARNING, errorString_ ); - } - - // Save our api-specific connection information. - WinMidiData *data = (WinMidiData *) new WinMidiData; - apiData_ = (void *) data; - inputData_.apiData = (void *) data; - data->message.bytes.clear(); // needs to be empty for first input message - - if ( !InitializeCriticalSectionAndSpinCount(&(data->_mutex), 0x00000400) ) { - errorString_ = "MidiInWinMM::initialize: InitializeCriticalSectionAndSpinCount failed."; - error( RtMidiError::WARNING, errorString_ ); + AlsaMidiData *data = static_cast (apiData_); + if ( !data->local.client ) { + int port = snd_seq_create_simple_port( data->seq, portName.c_str(), + SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, + SND_SEQ_PORT_TYPE_MIDI_GENERIC|SND_SEQ_PORT_TYPE_APPLICATION ); + + if ( port < 0 ) { + error(RTMIDI_ERROR(gettext_noopt("Error creating ALSA virtual port."), + Error::DRIVER_ERROR) ); + } + data->local.port = port; + data->local.client = snd_seq_client_id(data->seq); } } -void MidiInWinMM :: openPort( unsigned int portNumber, const std::string /*portName*/ ) -{ - if ( connected_ ) { - errorString_ = "MidiInWinMM::openPort: a valid connection already exists!"; - error( RtMidiError::WARNING, errorString_ ); - return; - } - - unsigned int nDevices = midiInGetNumDevs(); - if (nDevices == 0) { - errorString_ = "MidiInWinMM::openPort: no MIDI input sources found!"; - error( RtMidiError::NO_DEVICES_FOUND, errorString_ ); - return; - } - - if ( portNumber >= nDevices ) { - std::ostringstream ost; - ost << "MidiInWinMM::openPort: the 'portNumber' argument (" << portNumber << ") is invalid."; - errorString_ = ost.str(); - error( RtMidiError::INVALID_PARAMETER, errorString_ ); - return; - } - - WinMidiData *data = static_cast (apiData_); - MMRESULT result = midiInOpen( &data->inHandle, - portNumber, - (DWORD_PTR)&midiInputCallback, - (DWORD_PTR)&inputData_, - CALLBACK_FUNCTION ); - if ( result != MMSYSERR_NOERROR ) { - errorString_ = "MidiInWinMM::openPort: error creating Windows MM MIDI input port."; - error( RtMidiError::DRIVER_ERROR, errorString_ ); - return; - } - - // Allocate and init the sysex buffers. - for ( int i=0; isysexBuffer[i] = (MIDIHDR*) new char[ sizeof(MIDIHDR) ]; - data->sysexBuffer[i]->lpData = new char[ RT_SYSEX_BUFFER_SIZE ]; - data->sysexBuffer[i]->dwBufferLength = RT_SYSEX_BUFFER_SIZE; - data->sysexBuffer[i]->dwUser = i; // We use the dwUser parameter as buffer indicator - data->sysexBuffer[i]->dwFlags = 0; - - result = midiInPrepareHeader( data->inHandle, data->sysexBuffer[i], sizeof(MIDIHDR) ); - if ( result != MMSYSERR_NOERROR ) { - midiInClose( data->inHandle ); - errorString_ = "MidiInWinMM::openPort: error starting Windows MM MIDI input port (PrepareHeader)."; - error( RtMidiError::DRIVER_ERROR, errorString_ ); +void MidiOutAlsa :: sendMessage( const unsigned char *message, size_t size ) +{ + int result; + AlsaMidiData *data = static_cast (apiData_); + if ( size > data->bufferSize ) { + data->bufferSize = size; + result = snd_midi_event_resize_buffer ( data->coder, size); + if ( result != 0 ) { + error(RTMIDI_ERROR(gettext_noopt("ALSA error resizing MIDI event buffer."), + Error::DRIVER_ERROR) ); return; } - - // Register the buffer. - result = midiInAddBuffer( data->inHandle, data->sysexBuffer[i], sizeof(MIDIHDR) ); - if ( result != MMSYSERR_NOERROR ) { - midiInClose( data->inHandle ); - errorString_ = "MidiInWinMM::openPort: error starting Windows MM MIDI input port (AddBuffer)."; - error( RtMidiError::DRIVER_ERROR, errorString_ ); + free (data->buffer); + data->buffer = (unsigned char *) malloc( data->bufferSize ); + if ( data->buffer == NULL ) { + error(RTMIDI_ERROR(gettext_noopt("Error while allocating buffer memory."), + Error::MEMORY_ERROR) ); return; } } - result = midiInStart( data->inHandle ); - if ( result != MMSYSERR_NOERROR ) { - midiInClose( data->inHandle ); - errorString_ = "MidiInWinMM::openPort: error starting Windows MM MIDI input port."; - error( RtMidiError::DRIVER_ERROR, errorString_ ); + snd_seq_event_t ev; + snd_seq_ev_clear(&ev); + snd_seq_ev_set_source(&ev, data->local.port); + snd_seq_ev_set_subs(&ev); + snd_seq_ev_set_direct(&ev); + for ( unsigned int i=0; ibuffer[i] = message[i]; + result = snd_midi_event_encode( data->coder, data->buffer, (long)size, &ev ); + if ( result < (int)size ) { + error(RTMIDI_ERROR(gettext_noopt("Event parsing error."), + Error::WARNING) ); return; } - connected_ = true; + // Send the event. + result = snd_seq_event_output(data->seq, &ev); + if ( result < 0 ) { + error(RTMIDI_ERROR(gettext_noopt("Error sending MIDI message to port."), + Error::WARNING) ); + return; + } + snd_seq_drain_output(data->seq); } -void MidiInWinMM :: openVirtualPort( std::string /*portName*/ ) +void MidiOutAlsa :: openPort( const PortDescriptor & port, + const std::string &portName) { - // This function cannot be implemented for the Windows MM MIDI API. - errorString_ = "MidiInWinMM::openVirtualPort: cannot be implemented in Windows MM MIDI API!"; - error( RtMidiError::WARNING, errorString_ ); -} + AlsaMidiData *data = static_cast (apiData_); + const AlsaPortDescriptor * remote = dynamic_cast(&port); -void MidiInWinMM :: closePort( void ) -{ + if ( !data ) { + error(RTMIDI_ERROR(gettext_noopt("Data has not been allocated."), + Error::SYSTEM_ERROR) ); + return; + } if ( connected_ ) { - WinMidiData *data = static_cast (apiData_); - EnterCriticalSection( &(data->_mutex) ); - midiInReset( data->inHandle ); - midiInStop( data->inHandle ); + error(RTMIDI_ERROR(gettext_noopt("A valid connection already exists."), + Error::WARNING) ); + return; + } + if (data->subscription) { + error(RTMIDI_ERROR(gettext_noopt("Error allocating ALSA port subscription."), + Error::DRIVER_ERROR) ); + return; + } + if (!remote) { + error(RTMIDI_ERROR(gettext_noopt("ALSA has been instructed to open a non-ALSA MIDI port. This doesn't work."), + Error::INVALID_DEVICE) ); + return; + } - for ( int i=0; iinHandle, data->sysexBuffer[i], sizeof(MIDIHDR)); - delete [] data->sysexBuffer[i]->lpData; - delete [] data->sysexBuffer[i]; - if ( result != MMSYSERR_NOERROR ) { - midiInClose( data->inHandle ); - errorString_ = "MidiInWinMM::openPort: error closing Windows MM MIDI input port (midiInUnprepareHeader)."; - error( RtMidiError::DRIVER_ERROR, errorString_ ); - return; - } - } + try { + if (!data->local.client) + data->openPort (SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ, + portName); + data->setRemote(remote); + data->connectPorts(data->local,*remote,true); - midiInClose( data->inHandle ); - connected_ = false; - LeaveCriticalSection( &(data->_mutex) ); + connected_ = true; + } catch (Error & e) { + error (e); } } - -unsigned int MidiInWinMM :: getPortCount() +Pointer MidiOutAlsa :: getDescriptor(bool local) { - return midiInGetNumDevs(); + AlsaMidiData *data = static_cast (apiData_); + try { + if (local) { + if (data && data->local.client) { + return Pointer( + new AlsaPortDescriptor(data->local, data->getClientName())); + } + } else { + if (data && data->client) { + return Pointer( + new AlsaPortDescriptor(*data, data->getClientName())); + } + } + } catch (Error & e) { + error(e); + } + return NULL; } - -std::string MidiInWinMM :: getPortName( unsigned int portNumber ) +PortList MidiOutAlsa :: getPortList(int capabilities) { - std::string stringName; - unsigned int nDevices = midiInGetNumDevs(); - if ( portNumber >= nDevices ) { - std::ostringstream ost; - ost << "MidiInWinMM::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid."; - errorString_ = ost.str(); - error( RtMidiError::WARNING, errorString_ ); - return stringName; + AlsaMidiData *data = static_cast (apiData_); + try { + return AlsaPortDescriptor::getPortList(capabilities | PortDescriptor::OUTPUT, + data->getClientName()); + } catch (Error & e) { + return PortList(); } - - MIDIINCAPS deviceCaps; - midiInGetDevCaps( portNumber, &deviceCaps, sizeof(MIDIINCAPS)); - -#if defined( UNICODE ) || defined( _UNICODE ) - int length = WideCharToMultiByte(CP_UTF8, 0, deviceCaps.szPname, -1, NULL, 0, NULL, NULL) - 1; - stringName.assign( length, 0 ); - length = WideCharToMultiByte(CP_UTF8, 0, deviceCaps.szPname, static_cast(wcslen(deviceCaps.szPname)), &stringName[0], length, NULL, NULL); -#else - stringName = std::string( deviceCaps.szPname ); -#endif - - // Next lines added to add the portNumber to the name so that - // the device's names are sure to be listed with individual names - // even when they have the same brand name - std::ostringstream os; - os << " "; - os << portNumber; - stringName += os.str(); - - return stringName; } +RTMIDI_NAMESPACE_END +#undef RTMIDI_CLASSNAME +#endif // __LINUX_ALSA__ + //*********************************************************************// -// API: Windows MM -// Class Definitions: MidiOutWinMM +// API: Windows Multimedia Library (MM) //*********************************************************************// -MidiOutWinMM :: MidiOutWinMM( const std::string clientName ) : MidiOutApi() -{ - initialize( clientName ); -} - -MidiOutWinMM :: ~MidiOutWinMM() -{ - // Close a connection if it exists. - closePort(); +// API information deciphered from: +// - http://msdn.microsoft.com/library/default.asp?url=/library/en-us/multimed/htm/_win32_midi_reference.asp - // Cleanup. - WinMidiData *data = static_cast (apiData_); - delete data; -} +// Thanks to Jean-Baptiste Berruchon for the sysex code. -void MidiOutWinMM :: initialize( const std::string& /*clientName*/ ) -{ - // We'll issue a warning here if no devices are available but not - // throw an error since the user can plug something in later. - unsigned int nDevices = midiOutGetNumDevs(); - if ( nDevices == 0 ) { - errorString_ = "MidiOutWinMM::initialize: no MIDI output devices currently available."; - error( RtMidiError::WARNING, errorString_ ); - } +#if defined(__WINDOWS_MM__) - // Save our api-specific connection information. - WinMidiData *data = (WinMidiData *) new WinMidiData; - apiData_ = (void *) data; -} +// The Windows MM API is based on the use of a callback function for +// MIDI input. We convert the system specific time stamps to delta +// time values. -unsigned int MidiOutWinMM :: getPortCount() -{ - return midiOutGetNumDevs(); -} +// Windows MM MIDI header files. +#include +#include -std::string MidiOutWinMM :: getPortName( unsigned int portNumber ) +// Convert a null-terminated wide string or ANSI-encoded string to UTF-8. +static std::string ConvertToUTF8(const TCHAR *str) { - std::string stringName; - unsigned int nDevices = midiOutGetNumDevs(); - if ( portNumber >= nDevices ) { - std::ostringstream ost; - ost << "MidiOutWinMM::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid."; - errorString_ = ost.str(); - error( RtMidiError::WARNING, errorString_ ); - return stringName; - } - - MIDIOUTCAPS deviceCaps; - midiOutGetDevCaps( portNumber, &deviceCaps, sizeof(MIDIOUTCAPS)); - + std::string u8str; + const WCHAR *wstr = L""; #if defined( UNICODE ) || defined( _UNICODE ) - int length = WideCharToMultiByte(CP_UTF8, 0, deviceCaps.szPname, -1, NULL, 0, NULL, NULL) - 1; - stringName.assign( length, 0 ); - length = WideCharToMultiByte(CP_UTF8, 0, deviceCaps.szPname, static_cast(wcslen(deviceCaps.szPname)), &stringName[0], length, NULL, NULL); + wstr = str; #else - stringName = std::string( deviceCaps.szPname ); + // Convert from ANSI encoding to wide string + int wlength = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 ); + std::wstring wstrtemp; + if ( wlength ) + { + wstrtemp.assign( wlength - 1, 0 ); + MultiByteToWideChar( CP_ACP, 0, str, -1, &wstrtemp[0], wlength ); + wstr = &wstrtemp[0]; + } #endif - - return stringName; + // Convert from wide string to UTF-8 + int length = WideCharToMultiByte( CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL ); + if ( length ) + { + u8str.assign( length - 1, 0 ); + length = WideCharToMultiByte( CP_UTF8, 0, wstr, -1, &u8str[0], length, NULL, NULL ); + } + return u8str; } -void MidiOutWinMM :: openPort( unsigned int portNumber, const std::string /*portName*/ ) -{ - if ( connected_ ) { - errorString_ = "MidiOutWinMM::openPort: a valid connection already exists!"; - error( RtMidiError::WARNING, errorString_ ); - return; - } +#define RT_SYSEX_BUFFER_SIZE 1024 +#define RT_SYSEX_BUFFER_COUNT 4 - unsigned int nDevices = midiOutGetNumDevs(); - if (nDevices < 1) { - errorString_ = "MidiOutWinMM::openPort: no MIDI output destinations found!"; - error( RtMidiError::NO_DEVICES_FOUND, errorString_ ); - return; - } +/* some header defines UNIQUE_PORT_NAME as a macro */ +#ifdef UNIQUE_PORT_NAME +#undef UNIQUE_PORT_NAME +#endif +RTMIDI_NAMESPACE_START +/*! An abstraction layer for the ALSA sequencer layer. It provides + the following functionality: + - dynamic allocation of the sequencer + - optionallay avoid concurrent access to the ALSA sequencer, + which is not thread proof. This feature is controlled by + the parameter \ref locking. +*/ - if ( portNumber >= nDevices ) { - std::ostringstream ost; - ost << "MidiOutWinMM::openPort: the 'portNumber' argument (" << portNumber << ") is invalid."; - errorString_ = ost.str(); - error( RtMidiError::INVALID_PARAMETER, errorString_ ); - return; +#define RTMIDI_CLASSNAME "WinMMSequencer" +template +class WinMMSequencer { +public: + WinMMSequencer():mutex(0),name() + { + if (locking) { +#if 0 + // use mthreads instead + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL); + pthread_mutex_init(&mutex, &attr); +#endif + } } - WinMidiData *data = static_cast (apiData_); - MMRESULT result = midiOutOpen( &data->outHandle, - portNumber, - (DWORD)NULL, - (DWORD)NULL, - CALLBACK_NULL ); - if ( result != MMSYSERR_NOERROR ) { - errorString_ = "MidiOutWinMM::openPort: error creating Windows MM MIDI output port."; - error( RtMidiError::DRIVER_ERROR, errorString_ ); - return; + WinMMSequencer(const std::string &n):name(n) + { + if (locking) { +#if 0 + // use mthreads instead + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL); + pthread_mutex_init(&mutex, &attr); +#endif + } + init(); + { + scoped_lock lock(mutex); + } } - connected_ = true; -} + ~WinMMSequencer() + { + if (locking) { +#if 0 + // use mthreads instead + pthread_mutex_destroy(&mutex); +#endif + } + } -void MidiOutWinMM :: closePort( void ) -{ - if ( connected_ ) { - WinMidiData *data = static_cast (apiData_); - midiOutReset( data->outHandle ); - midiOutClose( data->outHandle ); - connected_ = false; + bool setName(const std::string &n) { + /* we don't want to rename the client after opening it. */ + name = n; + return true; } -} -void MidiOutWinMM :: openVirtualPort( std::string /*portName*/ ) -{ - // This function cannot be implemented for the Windows MM MIDI API. - errorString_ = "MidiOutWinMM::openVirtualPort: cannot be implemented in Windows MM MIDI API!"; - error( RtMidiError::WARNING, errorString_ ); -} + std::string getPortName(int port, bool is_input, int flags) { + init(); + int naming = flags & PortDescriptor::NAMING_MASK; + std::string name; -void MidiOutWinMM :: sendMessage( std::vector *message ) -{ - if ( !connected_ ) return; + unsigned int nDevices = is_input?midiInGetNumDevs() + : midiOutGetNumDevs(); + if ( port < 0 || (unsigned int)port >= nDevices ) { + throw Error(RTMIDI_ERROR1(gettext_noopt("The port argument %d is invalid."), + Error::INVALID_PARAMETER,port)); + } - unsigned int nBytes = static_cast(message->size()); - if ( nBytes == 0 ) { - errorString_ = "MidiOutWinMM::sendMessage: message argument is empty!"; - error( RtMidiError::WARNING, errorString_ ); - return; - } + if (is_input) { + MIDIINCAPS deviceCaps; + midiInGetDevCaps( port, &deviceCaps, sizeof(MIDIINCAPS)); - MMRESULT result; - WinMidiData *data = static_cast (apiData_); - if ( message->at(0) == 0xF0 ) { // Sysex message +#if defined( UNICODE ) || defined( _UNICODE ) + int length = WideCharToMultiByte(CP_UTF8, 0, deviceCaps.szPname, -1, NULL, 0, NULL, NULL) - 1; + name.assign( length, 0 ); + length = WideCharToMultiByte(CP_UTF8, + 0, + deviceCaps.szPname, + static_cast(wcslen(deviceCaps.szPname)), + &name[0], + length, + NULL, + NULL); +#else + name = deviceCaps.szPname; +#endif + } else { + MIDIOUTCAPS deviceCaps; + midiOutGetDevCaps( port, &deviceCaps, sizeof(MIDIOUTCAPS)); + +#if defined( UNICODE ) || defined( _UNICODE ) + int length = WideCharToMultiByte(CP_UTF8, 0, deviceCaps.szPname, -1, NULL, 0, NULL, NULL) - 1; + name.assign( length, 0 ); + length = WideCharToMultiByte(CP_UTF8, + 0, + deviceCaps.szPname, + static_cast(wcslen(deviceCaps.szPname)), + &name[0], + length, + NULL, + NULL); +#else + name = deviceCaps.szPname; +#endif - // Allocate buffer for sysex data. - char *buffer = (char *) malloc( nBytes ); - if ( buffer == NULL ) { - errorString_ = "MidiOutWinMM::sendMessage: error allocating sysex message memory!"; - error( RtMidiError::MEMORY_ERROR, errorString_ ); - return; } - // Copy data to buffer. - for ( unsigned int i=0; iat(i); - // Create and prepare MIDIHDR structure. - MIDIHDR sysex; - sysex.lpData = (LPSTR) buffer; - sysex.dwBufferLength = nBytes; - sysex.dwFlags = 0; - result = midiOutPrepareHeader( data->outHandle, &sysex, sizeof(MIDIHDR) ); - if ( result != MMSYSERR_NOERROR ) { - free( buffer ); - errorString_ = "MidiOutWinMM::sendMessage: error preparing sysex header."; - error( RtMidiError::DRIVER_ERROR, errorString_ ); - return; + std::ostringstream os; + switch (naming) { + case PortDescriptor::SESSION_PATH: + if (flags & PortDescriptor::INCLUDE_API) + os << "WinMM:"; + os << port << ":" << name.c_str(); + break; + case PortDescriptor::STORAGE_PATH: + if (flags & PortDescriptor::INCLUDE_API) + os << "WinMM:"; + os << name.c_str(); + if (flags & PortDescriptor::UNIQUE_PORT_NAME) + os << ";" << port; + break; + case PortDescriptor::LONG_NAME: + case PortDescriptor::SHORT_NAME: + default: + os << name.c_str(); + if (flags & PortDescriptor::UNIQUE_PORT_NAME) { + os << " "; + os << port; + } + if (flags & PortDescriptor::INCLUDE_API) + os << " (WinMM)"; + + break; } + return os.str(); + } - // Send the message. - result = midiOutLongMsg( data->outHandle, &sysex, sizeof(MIDIHDR) ); - if ( result != MMSYSERR_NOERROR ) { - free( buffer ); - errorString_ = "MidiOutWinMM::sendMessage: error sending sysex message."; - error( RtMidiError::DRIVER_ERROR, errorString_ ); - return; +protected: + struct scoped_lock { + // pthread_mutex_t * mutex; + scoped_lock(unsigned int &) + { +#if 0 + if (locking) + pthread_mutex_lock(mutex); +#endif } + ~scoped_lock() + { +#if 0 + if (locking) + pthread_mutex_unlock(mutex); +#endif + } + }; + // to keep the API simple + int mutex; + std::string name; - // Unprepare the buffer and MIDIHDR. - while ( MIDIERR_STILLPLAYING == midiOutUnprepareHeader( data->outHandle, &sysex, sizeof (MIDIHDR) ) ) Sleep( 1 ); - free( buffer ); + + void init() + { + // init (seq); + } + +}; +// typedef WinMMSequencer<1> LockingWinMMSequencer; +typedef WinMMSequencer<0> NonLockingWinMMSequencer; +#undef RTMIDI_CLASSNAME + +struct WinMMPortDescriptor:public PortDescriptor +{ + static NonLockingWinMMSequencer seq; + WinMMPortDescriptor(const std::string &/*cname*/):name(),port(0),clientName(name) + { + } + WinMMPortDescriptor(unsigned int p, const std::string &pn, bool i_o, const std::string &n): + name(pn), + port(p), + is_input(i_o), + clientName(n) + { + } + ~WinMMPortDescriptor() {} + MidiInApi * getInputApi(unsigned int queueSizeLimit = 100) const { + if (is_input) + return new MidiInWinMM(clientName,queueSizeLimit); + else + return 0; + } + MidiOutApi * getOutputApi() const { + if (!is_input) + return new MidiOutWinMM(clientName); + else + return 0; + } + std::string getName(int flags = SHORT_NAME | UNIQUE_PORT_NAME) { + return seq.getPortName(port,is_input,flags); } - else { // Channel or system message. - // Make sure the message size isn't too big. - if ( nBytes > 3 ) { - errorString_ = "MidiOutWinMM::sendMessage: message size is greater than 3 bytes (and not sysex)!"; - error( RtMidiError::WARNING, errorString_ ); - return; - } + const std::string &getClientName() const { + return clientName; + } + int getCapabilities() const { + return is_input ? INPUT : OUTPUT; + } - // Pack MIDI bytes into double word. - DWORD packet; - unsigned char *ptr = (unsigned char *) &packet; - for ( unsigned int i=0; iat(i); - ++ptr; - } + int getCapabilities() { + const WinMMPortDescriptor * self = this; + return self->getCapabilities(); + } - // Send the message immediately. - result = midiOutShortMsg( data->outHandle, packet ); - if ( result != MMSYSERR_NOERROR ) { - errorString_ = "MidiOutWinMM::sendMessage: error sending MIDI message."; - error( RtMidiError::DRIVER_ERROR, errorString_ ); + bool is_valid() const { + if (is_input) { + if (midiInGetNumDevs() <= port) { + return false; + } + } else { + if (midiOutGetNumDevs() <= port) { + return false; + } } + return seq.getPortName(port,is_input,PortDescriptor::STORAGE_PATH) + == name; } -} -#endif // __WINDOWS_MM__ + void setRemote(const WinMMPortDescriptor * remote) { + port = remote->port; + name = remote->name; + is_input = remote->is_input; + } -// *********************************************************************// -// API: WINDOWS Kernel Streaming -// -// Written by Sebastien Alaiwan, 2012. -// -// NOTE BY GARY: much of the KS-specific code below probably should go in a separate file. -// -// *********************************************************************// -#if defined(__WINDOWS_KS__) + unsigned int getPortNumber() const { return port; } -#include -#include -#include -#include -#include -#include -#include -#include + static PortList getPortList(int capabilities, const std::string &clientName); +protected: + /* There is no perfect port descriptor available in this API. + We use the port number and issue an error if the port name has changed + between the creation of the port descriptor and opening the port. */ + std::string name; + unsigned int port; + bool is_input; + std::string clientName; +}; -#include "ks.h" -#include "ksmedia.h" +NonLockingWinMMSequencer WinMMPortDescriptor::seq; -#define INSTANTIATE_GUID(a) GUID const a = { STATIC_ ## a } -INSTANTIATE_GUID(GUID_NULL); -INSTANTIATE_GUID(KSPROPSETID_Pin); -INSTANTIATE_GUID(KSPROPSETID_Connection); -INSTANTIATE_GUID(KSPROPSETID_Topology); -INSTANTIATE_GUID(KSINTERFACESETID_Standard); -INSTANTIATE_GUID(KSMEDIUMSETID_Standard); -INSTANTIATE_GUID(KSDATAFORMAT_TYPE_MUSIC); -INSTANTIATE_GUID(KSDATAFORMAT_SUBTYPE_MIDI); -INSTANTIATE_GUID(KSDATAFORMAT_SPECIFIER_NONE); -#undef INSTANTIATE_GUID +PortList WinMMPortDescriptor :: getPortList(int capabilities, const std::string &clientName) +{ + PortList list; -typedef std::basic_string tstring; + if (capabilities & INPUT && capabilities & OUTPUT) return list; -inline bool IsValid(HANDLE handle) -{ - return handle != NULL && handle != INVALID_HANDLE_VALUE; + if (capabilities & INPUT) { + size_t n = midiInGetNumDevs(); + for (size_t i = 0 ; i < n ; i++) { + std::string name = seq.getPortName(i,true,PortDescriptor::STORAGE_PATH); + list.push_back(Pointer( + new WinMMPortDescriptor(i,name,true,clientName))); + } + } else { + size_t n = midiOutGetNumDevs(); + for (size_t i = 0 ; i < n ; i++) { + std::string name = seq.getPortName(i,false,PortDescriptor::STORAGE_PATH); + list.push_back(Pointer( + new WinMMPortDescriptor(i,name,false,clientName))); + } + } + return list; } -class ComException : public std::runtime_error -{ -private: - static std::string MakeString(std::string const& s, HRESULT hr) - { - std::stringstream ss; - ss << "(error 0x" << std::hex << hr << ")"; - return s + ss.str(); - } -public: - ComException(std::string const& s, HRESULT hr) : - std::runtime_error(MakeString(s, hr)) - { - } +/*! A structure to hold variables related to the WINMM API + implementation. + + \note After all sequencer handling is covered by the \ref + WinMMSequencer class, we should make seq to be a pointer in order + to allow a common client implementation. +*/ + +struct WinMidiData:public WinMMPortDescriptor { + /* + WinMMMidiData():seq() + { + init(); + } + */ + WinMidiData(const std::string &clientName):WinMMPortDescriptor(clientName) {} + ~WinMidiData() {} + + HMIDIIN inHandle; // Handle to Midi Input Device + HMIDIOUT outHandle; // Handle to Midi Output Device + DWORD lastTime; + MidiInApi::MidiMessage message; + LPMIDIHDR sysexBuffer[RT_SYSEX_BUFFER_COUNT]; + CRITICAL_SECTION _mutex; // [Patrice] see https://groups.google.com/forum/#!topic/mididev/6OUjHutMpEo }; -template -class CKsEnumFilters -{ -public: - ~CKsEnumFilters() - { - DestroyLists(); - } - void EnumFilters(GUID const* categories, size_t numCategories) +//*********************************************************************// +// API: Windows MM +// Class Definitions: MidiInWinMM +//*********************************************************************// +#define RTMIDI_CLASSNAME "WinMMCallbacks" +//! Windows callbacks +/*! In order to avoid including too many header files in RtMidi.h, we use this + * class to callect all friend functions of Midi*WinMM. + */ +struct WinMMCallbacks { + static void CALLBACK midiInputCallback( HMIDIIN /*hmin*/, + UINT inputStatus, + DWORD_PTR instancePtr, + DWORD_PTR midiMessage, + DWORD timestamp ) { - DestroyLists(); + if ( inputStatus != MIM_DATA && inputStatus != MIM_LONGDATA && inputStatus != MIM_LONGERROR ) return; - if (categories == 0) - throw std::runtime_error("CKsEnumFilters: invalid argument"); + //MidiInApi::MidiInData *data = static_cast (instancePtr); + MidiInWinMM *data = (MidiInWinMM *)instancePtr; + WinMidiData *apiData = static_cast (data->apiData_); - // Get a handle to the device set specified by the guid - HDEVINFO hDevInfo = ::SetupDiGetClassDevs(&categories[0], NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); - if (!IsValid(hDevInfo)) - throw std::runtime_error("CKsEnumFilters: no devices found"); - - // Loop through members of the set and get details for each - for ( int iClassMember=0; iClassMember++ ) { - try { - SP_DEVICE_INTERFACE_DATA DID; - DID.cbSize = sizeof(DID); - DID.Reserved = 0; + // Calculate time stamp. + if ( data->firstMessage == true ) { + apiData->message.timeStamp = 0.0; + data->firstMessage = false; + } + else apiData->message.timeStamp = (double) ( timestamp - apiData->lastTime ) * 0.001; + + if ( inputStatus == MIM_DATA ) { // Channel or system message + + // Make sure the first byte is a status byte. + unsigned char status = (unsigned char) (midiMessage & 0x000000FF); + if ( !(status & 0x80) ) return; + + // Determine the number of bytes in the MIDI message. + unsigned short nBytes = 1; + if ( status < 0xC0 ) nBytes = 3; + else if ( status < 0xE0 ) nBytes = 2; + else if ( status < 0xF0 ) nBytes = 3; + else if ( status == 0xF1 ) { + if ( data->ignoreFlags & 0x02 ) return; + else nBytes = 2; + } + else if ( status == 0xF2 ) nBytes = 3; + else if ( status == 0xF3 ) nBytes = 2; + else if ( status == 0xF8 && (data->ignoreFlags & 0x02) ) { + // A MIDI timing tick message and we're ignoring it. + return; + } + else if ( status == 0xFE && (data->ignoreFlags & 0x04) ) { + // A MIDI active sensing message and we're ignoring it. + return; + } - bool fRes = ::SetupDiEnumDeviceInterfaces(hDevInfo, NULL, &categories[0], iClassMember, &DID); - if (!fRes) - break; + // Copy bytes to our MIDI message. + unsigned char *ptr = (unsigned char *) &midiMessage; + for ( int i=0; imessage.bytes.push_back( *ptr++ ); + } + else { // Sysex message ( MIM_LONGDATA or MIM_LONGERROR ) + MIDIHDR *sysex = ( MIDIHDR *) midiMessage; + if ( !( data->ignoreFlags & 0x01 ) && inputStatus != MIM_LONGERROR ) { + // Sysex message and we're not ignoring it + for ( int i=0; i<(int)sysex->dwBytesRecorded; ++i ) + apiData->message.bytes.push_back( sysex->lpData[i] ); + } - // Get filter friendly name - HKEY hRegKey = ::SetupDiOpenDeviceInterfaceRegKey(hDevInfo, &DID, 0, KEY_READ); - if (hRegKey == INVALID_HANDLE_VALUE) - throw std::runtime_error("CKsEnumFilters: interface has no registry"); + // The WinMM API requires that the sysex buffer be requeued after + // input of each sysex message. Even if we are ignoring sysex + // messages, we still need to requeue the buffer in case the user + // decides to not ignore sysex messages in the future. However, + // it seems that WinMM calls this function with an empty sysex + // buffer when an application closes and in this case, we should + // avoid requeueing it, else the computer suddenly reboots after + // one or two minutes. + if ( apiData->sysexBuffer[sysex->dwUser]->dwBytesRecorded > 0 ) { + //if ( sysex->dwBytesRecorded > 0 ) { + EnterCriticalSection( &(apiData->_mutex) ); + MMRESULT result = midiInAddBuffer( apiData->inHandle, apiData->sysexBuffer[sysex->dwUser], sizeof(MIDIHDR) ); + LeaveCriticalSection( &(apiData->_mutex) ); + if ( result != MMSYSERR_NOERROR ){ + try { + data->error(RTMIDI_ERROR(rtmidi_gettext("Error sending sysex to Midi device."), + Error::WARNING)); + } catch (Error & e) { + // don't bother WinMM with an unhandled exception + } + } - char friendlyName[256]; - DWORD dwSize = sizeof friendlyName; - LONG lval = ::RegQueryValueEx(hRegKey, TEXT("FriendlyName"), NULL, NULL, (LPBYTE)friendlyName, &dwSize); - ::RegCloseKey(hRegKey); - if (lval != ERROR_SUCCESS) - throw std::runtime_error("CKsEnumFilters: interface has no friendly name"); + if ( data->ignoreFlags & 0x01 ) return; + } + else return; + } - // Get details for the device registered in this class - DWORD const cbItfDetails = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA) + MAX_PATH * sizeof(WCHAR); - std::vector buffer(cbItfDetails); + // Save the time of the last non-filtered message + apiData->lastTime = timestamp; - SP_DEVICE_INTERFACE_DETAIL_DATA* pDevInterfaceDetails = reinterpret_cast(&buffer[0]); - pDevInterfaceDetails->cbSize = sizeof(*pDevInterfaceDetails); + if ( data->userCallback ) { + data->userCallback->rtmidi_midi_in( apiData->message.timeStamp, apiData->message.bytes ); + } + else { + // As long as we haven't reached our queue size limit, push the message. + if (!data->queue.push(apiData->message)) { + try { + data->error(RTMIDI_ERROR(rtmidi_gettext("Error: Message queue limit reached."), + Error::WARNING)); + } catch (Error & e) { + // don't bother WinMM with an unhandled exception + } + } + } - SP_DEVINFO_DATA DevInfoData; - DevInfoData.cbSize = sizeof(DevInfoData); - DevInfoData.Reserved = 0; + // Clear the vector for the next input message. + apiData->message.bytes.clear(); + } +}; +#undef RTMIDI_CLASSNAME - fRes = ::SetupDiGetDeviceInterfaceDetail(hDevInfo, &DID, pDevInterfaceDetails, cbItfDetails, NULL, &DevInfoData); - if (!fRes) - throw std::runtime_error("CKsEnumFilters: could not get interface details"); +#define RTMIDI_CLASSNAME "MidiInWinMM" +MidiInWinMM :: MidiInWinMM( const std::string &clientName, + unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) +{ + MidiInWinMM::initialize( clientName ); +} - // check additional category guids which may (or may not) have been supplied - for (size_t i=1; i < numCategories; ++i) { - SP_DEVICE_INTERFACE_DATA DIDAlias; - DIDAlias.cbSize = sizeof(DIDAlias); - DIDAlias.Reserved = 0; +MidiInWinMM :: ~MidiInWinMM() +{ + // Close a connection if it exists. + MidiInWinMM::closePort(); - fRes = ::SetupDiGetDeviceInterfaceAlias(hDevInfo, &DID, &categories[i], &DIDAlias); - if (!fRes) - throw std::runtime_error("CKsEnumFilters: could not get interface alias"); + WinMidiData *data = static_cast (apiData_); + DeleteCriticalSection( &(data->_mutex) ); - // Check if the this interface alias is enabled. - if (!DIDAlias.Flags || (DIDAlias.Flags & SPINT_REMOVED)) - throw std::runtime_error("CKsEnumFilters: interface alias is not enabled"); - } + // Cleanup. + delete data; +} - std::auto_ptr pFilter(new TFilterType(pDevInterfaceDetails->DevicePath, friendlyName)); +void MidiInWinMM :: initialize( const std::string &clientName ) +{ + // We'll issue a warning here if no devices are available but not + // throw an error since the user can plugin something later. + unsigned int nDevices = midiInGetNumDevs(); + if ( nDevices == 0 ) { + error(RTMIDI_ERROR(gettext_noopt("No MIDI input devices currently available."), + Error::WARNING) ); + } - pFilter->Instantiate(); - pFilter->FindMidiPins(); - pFilter->Validate(); + // Save our api-specific connection information. + WinMidiData *data = (WinMidiData *) new WinMidiData(clientName); + apiData_ = (void *) data; + data->message.bytes.clear(); // needs to be empty for first input message - m_Filters.push_back(pFilter.release()); - } - catch (std::runtime_error const& e) { - } - } + if ( !InitializeCriticalSectionAndSpinCount(&(data->_mutex), 0x00000400) ) { + error(RTMIDI_ERROR(gettext_noopt("Failed to initialize a critical section."), + Error::WARNING) ); + } +} - ::SetupDiDestroyDeviceInfoList(hDevInfo); +void MidiInWinMM :: openPort( unsigned int portNumber, const std::string &/*portName*/ ) +{ + if ( connected_ ) { + error(RTMIDI_ERROR(gettext_noopt("A valid connection already exists."), + Error::WARNING) ); + return; } -private: - void DestroyLists() - { - for (size_t i=0;i < m_Filters.size();++i) - delete m_Filters[i]; - m_Filters.clear(); + unsigned int nDevices = midiInGetNumDevs(); + if (nDevices == 0) { + error(RTMIDI_ERROR(gettext_noopt("No MIDI input sources found."), + Error::NO_DEVICES_FOUND) ); + return; } -public: - // TODO: make this private. - std::vector m_Filters; -}; + if ( portNumber >= nDevices ) { + std::ostringstream ost; + ost << "MidiInWinMM::openPort: "; + errorString_ = ost.str(); + error(RTMIDI_ERROR1(gettext_noopt("the 'portNumber' argument (%d) is invalid."), + Error::INVALID_PARAMETER, portNumber) ); + return; + } -class CKsObject -{ -public: - CKsObject(HANDLE handle) : m_handle(handle) - { + WinMidiData *data = static_cast (apiData_); + MMRESULT result = midiInOpen( &data->inHandle, + portNumber, + (DWORD_PTR)&WinMMCallbacks::midiInputCallback, + (DWORD_PTR)this, + CALLBACK_FUNCTION ); + if ( result != MMSYSERR_NOERROR ) { + error(RTMIDI_ERROR(gettext_noopt("Error creating Windows MM MIDI input port."), + Error::DRIVER_ERROR) ); + return; } -protected: - HANDLE m_handle; + // Allocate and init the sysex buffers. + for ( int i=0; isysexBuffer[i] = (MIDIHDR*) new char[ sizeof(MIDIHDR) ]; + data->sysexBuffer[i]->lpData = new char[ RT_SYSEX_BUFFER_SIZE ]; + data->sysexBuffer[i]->dwBufferLength = RT_SYSEX_BUFFER_SIZE; + data->sysexBuffer[i]->dwUser = i; // We use the dwUser parameter as buffer indicator + data->sysexBuffer[i]->dwFlags = 0; - void SetProperty(REFGUID guidPropertySet, ULONG nProperty, void* pvValue, ULONG cbValue) - { - KSPROPERTY ksProperty; - memset(&ksProperty, 0, sizeof ksProperty); - ksProperty.Set = guidPropertySet; - ksProperty.Id = nProperty; - ksProperty.Flags = KSPROPERTY_TYPE_SET; + result = midiInPrepareHeader( data->inHandle, data->sysexBuffer[i], sizeof(MIDIHDR) ); + if ( result != MMSYSERR_NOERROR ) { + midiInClose( data->inHandle ); + data->inHandle = 0; + error(RTMIDI_ERROR(gettext_noopt("Error initializing data for Windows MM MIDI input port."), + Error::DRIVER_ERROR )); + return; + } - HRESULT hr = DeviceIoControlKsProperty(ksProperty, pvValue, cbValue); - if (FAILED(hr)) - throw ComException("CKsObject::SetProperty: could not set property", hr); + // Register the buffer. + result = midiInAddBuffer( data->inHandle, data->sysexBuffer[i], sizeof(MIDIHDR) ); + if ( result != MMSYSERR_NOERROR ) { + midiInClose( data->inHandle ); + data->inHandle = 0; + error(RTMIDI_ERROR(gettext_noopt("Could not register the input buffer for Windows MM MIDI input port."), + Error::DRIVER_ERROR) ); + return; + } } -private: - - HRESULT DeviceIoControlKsProperty(KSPROPERTY& ksProperty, void* pvValue, ULONG cbValue) - { - ULONG ulReturned; - return ::DeviceIoControl( - m_handle, - IOCTL_KS_PROPERTY, - &ksProperty, - sizeof(ksProperty), - pvValue, - cbValue, - &ulReturned, - NULL); + result = midiInStart( data->inHandle ); + if ( result != MMSYSERR_NOERROR ) { + midiInClose( data->inHandle ); + data->inHandle = 0; + error(RTMIDI_ERROR(gettext_noopt("Error starting Windows MM MIDI input port."), + Error::DRIVER_ERROR) ); + return; } -}; -class CKsPin; + connected_ = true; +} -class CKsFilter : public CKsObject +void MidiInWinMM :: openVirtualPort(const std::string &/*portName*/ ) { - friend class CKsPin; - -public: - CKsFilter(tstring const& name, std::string const& sFriendlyName); - virtual ~CKsFilter(); + // This function cannot be implemented for the Windows MM MIDI API. + error(RTMIDI_ERROR(gettext_noopt("Virtual ports are not available Windows Multimedia MIDI API."), + Error::WARNING )); +} - virtual void Instantiate(); +void MidiInWinMM :: openPort(const PortDescriptor & p, const std::string &portName) { + const WinMMPortDescriptor * port = dynamic_cast (&p); + if ( !port) { + error( RTMIDI_ERROR(gettext_noopt("Windows Multimedia (WinMM) has been instructed to open a non-WinMM MIDI port. This doesn't work."), + Error::INVALID_DEVICE)); + return; + } + if ( connected_ ) { + error( RTMIDI_ERROR(gettext_noopt("We are overwriting an existing connection. This is probably a programming error."), + Error::WARNING) ); + return; + } + if (port->getCapabilities() != PortDescriptor::INPUT) { + error(RTMIDI_ERROR(gettext_noopt("Trying to open a non-input port as input MIDI port. This doesn't work."), + Error::INVALID_DEVICE)); + return; + } - template - T GetPinProperty(ULONG nPinId, ULONG nProperty) - { - ULONG ulReturned = 0; - T value; - - KSP_PIN ksPProp; - ksPProp.Property.Set = KSPROPSETID_Pin; - ksPProp.Property.Id = nProperty; - ksPProp.Property.Flags = KSPROPERTY_TYPE_GET; - ksPProp.PinId = nPinId; - ksPProp.Reserved = 0; - - HRESULT hr = ::DeviceIoControl( - m_handle, - IOCTL_KS_PROPERTY, - &ksPProp, - sizeof(KSP_PIN), - &value, - sizeof(value), - &ulReturned, - NULL); - if (FAILED(hr)) - throw ComException("CKsFilter::GetPinProperty: failed to retrieve property", hr); - - return value; - } - - void GetPinPropertyMulti(ULONG nPinId, REFGUID guidPropertySet, ULONG nProperty, PKSMULTIPLE_ITEM* ppKsMultipleItem) - { - HRESULT hr; - - KSP_PIN ksPProp; - ksPProp.Property.Set = guidPropertySet; - ksPProp.Property.Id = nProperty; - ksPProp.Property.Flags = KSPROPERTY_TYPE_GET; - ksPProp.PinId = nPinId; - ksPProp.Reserved = 0; - - ULONG cbMultipleItem = 0; - hr = ::DeviceIoControl(m_handle, - IOCTL_KS_PROPERTY, - &ksPProp.Property, - sizeof(KSP_PIN), - NULL, - 0, - &cbMultipleItem, - NULL); - if (FAILED(hr)) - throw ComException("CKsFilter::GetPinPropertyMulti: cannot get property", hr); - - *ppKsMultipleItem = (PKSMULTIPLE_ITEM) new BYTE[cbMultipleItem]; - - ULONG ulReturned = 0; - hr = ::DeviceIoControl( - m_handle, - IOCTL_KS_PROPERTY, - &ksPProp, - sizeof(KSP_PIN), - (PVOID)*ppKsMultipleItem, - cbMultipleItem, - &ulReturned, - NULL); - if (FAILED(hr)) - throw ComException("CKsFilter::GetPinPropertyMulti: cannot get property", hr); - } - - std::string const& GetFriendlyName() const - { - return m_sFriendlyName; + // there is a possible race condition between opening the port and + // reordering of ports so we must check whether we opened the right port. + try { + openPort(port->getPortNumber(),portName); + } catch (Error & e) { + error(e); + } + if (!port->is_valid()) { + closePort(); + error (RTMIDI_ERROR(gettext_noopt("Some change in the arrangement of MIDI input ports invalidated the port descriptor."), + Error::DRIVER_ERROR)); + return; } + connected_ = true; +} -protected: +Pointer MidiInWinMM :: getDescriptor(bool local) +{ + if (local || !connected_) return 0; + WinMidiData *data = static_cast (apiData_); + if (!data) return 0; + UINT devid; + switch (midiInGetID(data->inHandle,&devid)) { + case MMSYSERR_INVALHANDLE: + error (RTMIDI_ERROR(gettext_noopt("The handle is invalid. Did you disconnect the device?"), + Error::DRIVER_ERROR)); + return 0; + case MMSYSERR_NODRIVER: + error (RTMIDI_ERROR(gettext_noopt("The system has no driver for our handle :-(. Did you disconnect the device?"), + Error::DRIVER_ERROR)); + return 0; + case MMSYSERR_NOMEM: + error (RTMIDI_ERROR(gettext_noopt("Out of memory."), + Error::DRIVER_ERROR)); + return 0; + } + WinMMPortDescriptor * retval = NULL; + try { + retval = new WinMMPortDescriptor(devid, getPortName(devid), true, data->getClientName()); + } catch (Error & e) { + try { + error(e); + } catch (...) { + if (retval) delete retval; + throw; + } + } + return Pointer(retval); - std::vector m_Pins; // this list owns the pins. +} - std::vector m_RenderPins; - std::vector m_CapturePins; +PortList MidiInWinMM :: getPortList(int capabilities) +{ + WinMidiData *data = static_cast (apiData_); + if (!data || capabilities != PortDescriptor::INPUT) return PortList(); + try { + return WinMMPortDescriptor::getPortList(PortDescriptor::INPUT,data->getClientName()); + } catch (Error & e) { + error(e); + return PortList(); + } +} -private: - std::string const m_sFriendlyName; // friendly name eg "Virus TI Synth" - tstring const m_sName; // Filter path, eg "\\?\usb#vid_133e&pid_0815...\vtimidi02" -}; -class CKsPin : public CKsObject +void MidiInWinMM :: closePort( void ) { -public: - CKsPin(CKsFilter* pFilter, ULONG nId); - virtual ~CKsPin(); + if ( connected_ ) { + WinMidiData *data = static_cast (apiData_); + EnterCriticalSection( &(data->_mutex) ); + midiInReset( data->inHandle ); + midiInStop( data->inHandle ); - virtual void Instantiate(); + for ( int i=0; iinHandle, data->sysexBuffer[i], sizeof(MIDIHDR)); + delete [] data->sysexBuffer[i]->lpData; + delete [] data->sysexBuffer[i]; + if ( result != MMSYSERR_NOERROR ) { + midiInClose( data->inHandle ); + data->inHandle = 0; + error(RTMIDI_ERROR(gettext_noopt("Error closing Windows MM MIDI input port."), + Error::DRIVER_ERROR) ); + return; + } + } - void ClosePin(); + midiInClose( data->inHandle ); + data->inHandle = 0; + connected_ = false; + LeaveCriticalSection( &(data->_mutex) ); + } +} - void SetState(KSSTATE ksState); +void MidiInWinMM :: setClientName ( const std::string& ) +{ + error(RTMIDI_ERROR(gettext_noopt("Setting the client name is not supported by Windows MM."), + Error::WARNING )); +} - void WriteData(KSSTREAM_HEADER* pKSSTREAM_HEADER, OVERLAPPED* pOVERLAPPED); - void ReadData(KSSTREAM_HEADER* pKSSTREAM_HEADER, OVERLAPPED* pOVERLAPPED); +void MidiInWinMM :: setPortName ( const std::string& ) +{ + error(RTMIDI_ERROR(gettext_noopt("Setting the port name is not supported by Windows MM."), + Error::WARNING )); +} - KSPIN_DATAFLOW GetDataFlow() const - { - return m_DataFlow; - } +unsigned int MidiInWinMM :: getPortCount() +{ + return midiInGetNumDevs(); +} - bool IsSink() const - { - return m_Communication == KSPIN_COMMUNICATION_SINK - || m_Communication == KSPIN_COMMUNICATION_BOTH; +std::string MidiInWinMM :: getPortName( unsigned int portNumber ) +{ + std::string stringName; + unsigned int nDevices = midiInGetNumDevs(); + if ( portNumber >= nDevices ) { + error(RTMIDI_ERROR1(gettext_noopt("The 'portNumber' argument (%d) is invalid."), + Error::WARNING,portNumber)); + return stringName; } + MIDIINCAPS deviceCaps; + midiInGetDevCaps( portNumber, &deviceCaps, sizeof(MIDIINCAPS)); + stringName = ConvertToUTF8( deviceCaps.szPname ); -protected: - PKSPIN_CONNECT m_pKsPinConnect; // creation parameters of pin - CKsFilter* const m_pFilter; + // Next lines added to add the portNumber to the name so that + // the device's names are sure to be listed with individual names + // even when they have the same brand name +#ifndef RTMIDI_DO_NOT_ENSURE_UNIQUE_PORTNAMES + std::ostringstream os; + os << " "; + os << portNumber; + stringName += os.str(); +#endif - ULONG m_cInterfaces; - PKSIDENTIFIER m_pInterfaces; - PKSMULTIPLE_ITEM m_pmiInterfaces; + return stringName; +} +#undef RTMIDI_CLASSNAME - ULONG m_cMediums; - PKSIDENTIFIER m_pMediums; - PKSMULTIPLE_ITEM m_pmiMediums; - ULONG m_cDataRanges; - PKSDATARANGE m_pDataRanges; - PKSMULTIPLE_ITEM m_pmiDataRanges; - KSPIN_DATAFLOW m_DataFlow; - KSPIN_COMMUNICATION m_Communication; -}; +//*********************************************************************// +// API: Windows MM +// Class Definitions: MidiOutWinMM +//*********************************************************************// -CKsFilter::CKsFilter(tstring const& sName, std::string const& sFriendlyName) : - CKsObject(INVALID_HANDLE_VALUE), - m_sFriendlyName(sFriendlyName), - m_sName(sName) +#define RTMIDI_CLASSNAME "MidiOutWinMM" +MidiOutWinMM :: MidiOutWinMM( const std::string &clientName ) : MidiOutApi() { - if (sName.empty()) - throw std::runtime_error("CKsFilter::CKsFilter: name can't be empty"); + MidiOutWinMM::initialize( clientName ); +} + +MidiOutWinMM :: ~MidiOutWinMM() +{ + // Close a connection if it exists. + MidiOutWinMM::closePort(); + + // Cleanup. + WinMidiData *data = static_cast (apiData_); + delete data; } -CKsFilter::~CKsFilter() +void MidiOutWinMM :: initialize( const std::string &clientName ) { - for (size_t i=0;i < m_Pins.size();++i) - delete m_Pins[i]; + // We'll issue a warning here if no devices are available but not + // throw an error since the user can plug something in later. + unsigned int nDevices = midiOutGetNumDevs(); + if ( nDevices == 0 ) { + error(RTMIDI_ERROR(gettext_noopt("No MIDI output devices currently available."), + Error::WARNING)); + } - if (IsValid(m_handle)) - ::CloseHandle(m_handle); + // Save our api-specific connection information. + WinMidiData *data = (WinMidiData *) new WinMidiData(clientName); + apiData_ = (void *) data; } -void CKsFilter::Instantiate() +unsigned int MidiOutWinMM :: getPortCount() { - m_handle = CreateFile( - m_sName.c_str(), - GENERIC_READ | GENERIC_WRITE, - 0, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, - NULL); - - if (!IsValid(m_handle)) - { - DWORD const dwError = GetLastError(); - throw ComException("CKsFilter::Instantiate: can't open driver", HRESULT_FROM_WIN32(dwError)); - } + return midiOutGetNumDevs(); } -CKsPin::CKsPin(CKsFilter* pFilter, ULONG PinId) : - CKsObject(INVALID_HANDLE_VALUE), - m_pKsPinConnect(NULL), - m_pFilter(pFilter) +std::string MidiOutWinMM :: getPortName( unsigned int portNumber ) { - m_Communication = m_pFilter->GetPinProperty(PinId, KSPROPERTY_PIN_COMMUNICATION); - m_DataFlow = m_pFilter->GetPinProperty(PinId, KSPROPERTY_PIN_DATAFLOW); + std::string stringName; + unsigned int nDevices = midiOutGetNumDevs(); + if ( portNumber >= nDevices ) { + std::ostringstream ost; + ost << "MidiOutWinMM::getPortName: "; + errorString_ = ost.str(); + error(RTMIDI_ERROR(gettext_noopt("The 'portNumber' argument (%d) is invalid."), + Error::WARNING)); + return stringName; + } + + MIDIOUTCAPS deviceCaps; + midiOutGetDevCaps( portNumber, &deviceCaps, sizeof(MIDIOUTCAPS)); + stringName = ConvertToUTF8( deviceCaps.szPname ); - // Interfaces - m_pFilter->GetPinPropertyMulti( - PinId, - KSPROPSETID_Pin, - KSPROPERTY_PIN_INTERFACES, - &m_pmiInterfaces); + // Next lines added to add the portNumber to the name so that + // the device's names are sure to be listed with individual names + // even when they have the same brand name + std::ostringstream os; +#ifndef RTMIDI_DO_NOT_ENSURE_UNIQUE_PORTNAMES + os << " "; + os << portNumber; + stringName += os.str(); +#endif - m_cInterfaces = m_pmiInterfaces->Count; - m_pInterfaces = (PKSPIN_INTERFACE)(m_pmiInterfaces + 1); + return stringName; +} - // Mediums - m_pFilter->GetPinPropertyMulti( - PinId, - KSPROPSETID_Pin, - KSPROPERTY_PIN_MEDIUMS, - &m_pmiMediums); - m_cMediums = m_pmiMediums->Count; - m_pMediums = (PKSPIN_MEDIUM)(m_pmiMediums + 1); +void MidiOutWinMM :: openPort( unsigned int portNumber, const std::string &/*portName*/ ) +{ + if ( connected_ ) { + error(RTMIDI_ERROR(gettext_noopt("A valid connection already exists."), + Error::WARNING) ); + return; + } - // Data ranges - m_pFilter->GetPinPropertyMulti( - PinId, - KSPROPSETID_Pin, - KSPROPERTY_PIN_DATARANGES, - &m_pmiDataRanges); + unsigned int nDevices = midiOutGetNumDevs(); + if (nDevices < 1) { + error(RTMIDI_ERROR(gettext_noopt("No MIDI output destinations found!"), + Error::NO_DEVICES_FOUND) ); + return; + } - m_cDataRanges = m_pmiDataRanges->Count; - m_pDataRanges = (PKSDATARANGE)(m_pmiDataRanges + 1); -} + if ( portNumber >= nDevices ) { + error(RTMIDI_ERROR1(gettext_noopt("The 'portNumber' argument (%d) is invalid."), + Error::INVALID_PARAMETER, portNumber) ); + return; + } -CKsPin::~CKsPin() -{ - ClosePin(); + WinMidiData *data = static_cast (apiData_); + MMRESULT result = midiOutOpen( &data->outHandle, + portNumber, + (DWORD)NULL, + (DWORD)NULL, + CALLBACK_NULL ); + if ( result != MMSYSERR_NOERROR ) { + error(RTMIDI_ERROR(gettext_noopt("Error creating Windows MM MIDI output port."), + Error::DRIVER_ERROR) ); + return; + } - delete[] (BYTE*)m_pKsPinConnect; - delete[] (BYTE*)m_pmiDataRanges; - delete[] (BYTE*)m_pmiInterfaces; - delete[] (BYTE*)m_pmiMediums; + connected_ = true; } -void CKsPin::ClosePin() +void MidiOutWinMM :: closePort( void ) { - if (IsValid(m_handle)) { - SetState(KSSTATE_STOP); - ::CloseHandle(m_handle); + if ( connected_ ) { + WinMidiData *data = static_cast (apiData_); + midiOutReset( data->outHandle ); + midiOutClose( data->outHandle ); + data->outHandle = 0; + connected_ = false; } - m_handle = INVALID_HANDLE_VALUE; } -void CKsPin::SetState(KSSTATE ksState) +void MidiOutWinMM :: setClientName ( const std::string& ) { - SetProperty(KSPROPSETID_Connection, KSPROPERTY_CONNECTION_STATE, &ksState, sizeof(ksState)); + error(RTMIDI_ERROR(gettext_noopt("Setting the client name is not supported by Windows MM."), + Error::WARNING )); } -void CKsPin::Instantiate() +void MidiOutWinMM :: setPortName ( const std::string& ) { - if (!m_pKsPinConnect) - throw std::runtime_error("CKsPin::Instanciate: abstract pin"); - - DWORD const dwResult = KsCreatePin(m_pFilter->m_handle, m_pKsPinConnect, GENERIC_WRITE | GENERIC_READ, &m_handle); - if (dwResult != ERROR_SUCCESS) - throw ComException("CKsMidiCapFilter::CreateRenderPin: Pin instanciation failed", HRESULT_FROM_WIN32(dwResult)); + error(RTMIDI_ERROR(gettext_noopt("Setting the port name is not supported by Windows MM."), + Error::WARNING )); } -void CKsPin::WriteData(KSSTREAM_HEADER* pKSSTREAM_HEADER, OVERLAPPED* pOVERLAPPED) +void MidiOutWinMM :: openVirtualPort(const std::string &/*portName*/ ) { - DWORD cbWritten; - BOOL fRes = ::DeviceIoControl( - m_handle, - IOCTL_KS_WRITE_STREAM, - NULL, - 0, - pKSSTREAM_HEADER, - pKSSTREAM_HEADER->Size, - &cbWritten, - pOVERLAPPED); - if (!fRes) { - DWORD const dwError = GetLastError(); - if (dwError != ERROR_IO_PENDING) - throw ComException("CKsPin::WriteData: DeviceIoControl failed", HRESULT_FROM_WIN32(dwError)); - } + // This function cannot be implemented for the Windows MM MIDI API. + error(RTMIDI_ERROR(gettext_noopt("Virtual ports are not available Windows Multimedia MIDI API."), + Error::WARNING) ); } -void CKsPin::ReadData(KSSTREAM_HEADER* pKSSTREAM_HEADER, OVERLAPPED* pOVERLAPPED) -{ - DWORD cbReturned; - BOOL fRes = ::DeviceIoControl( - m_handle, - IOCTL_KS_READ_STREAM, - NULL, - 0, - pKSSTREAM_HEADER, - pKSSTREAM_HEADER->Size, - &cbReturned, - pOVERLAPPED); - if (!fRes) { - DWORD const dwError = GetLastError(); - if (dwError != ERROR_IO_PENDING) - throw ComException("CKsPin::ReadData: DeviceIoControl failed", HRESULT_FROM_WIN32(dwError)); + +void MidiOutWinMM :: openPort(const PortDescriptor & p, const std::string &portName) { + const WinMMPortDescriptor * port = dynamic_cast (&p); + if ( !port) { + error( RTMIDI_ERROR(gettext_noopt("Windows Multimedia (WinMM) has been instructed to open a non-WinMM MIDI port. This doesn't work."), + Error::INVALID_DEVICE)); + return; } + if ( connected_ ) { + error( RTMIDI_ERROR(gettext_noopt("A valid connection already exists." ), + Error::WARNING) ); + return; + } + if (port->getCapabilities() != PortDescriptor::OUTPUT) { + error( RTMIDI_ERROR(gettext_noopt("The port descriptor cannot be used to open an output port."), + Error::DRIVER_ERROR)); + return; + } + + // there is a possible race condition between opening the port and + // reordering of ports so we must check whether we opened the right port. + try { + openPort(port->getPortNumber(),portName); + } catch (Error & e) { + error(e); + } + if (!port->is_valid()) { + closePort(); + error (RTMIDI_ERROR(gettext_noopt("Some change in the arrangement of MIDI input ports invalidated the port descriptor."), + Error::DRIVER_ERROR)); + return; + } + connected_ = true; } -class CKsMidiFilter : public CKsFilter +Pointer MidiOutWinMM :: getDescriptor(bool local) { -public: - void FindMidiPins(); - -protected: - CKsMidiFilter(tstring const& sPath, std::string const& sFriendlyName); -}; + if (local || !connected_) return 0; + WinMidiData *data = static_cast (apiData_); + if (!data) return 0; + UINT devid; + switch (midiOutGetID(data->outHandle,&devid)) { + case MMSYSERR_INVALHANDLE: + error (RTMIDI_ERROR(gettext_noopt("The internal handle is invalid. Did you disconnect the device?"), + Error::DRIVER_ERROR)); + return 0; + case MMSYSERR_NODRIVER: + error (RTMIDI_ERROR(gettext_noopt("The system has no driver for our handle :-(. Did you disconnect the device?"), + Error::DRIVER_ERROR)); + return 0; + case MMSYSERR_NOMEM: + error (RTMIDI_ERROR(gettext_noopt("Out of memory."), + Error::DRIVER_ERROR)); + return 0; + } + return Pointer( + new WinMMPortDescriptor(devid, getPortName(devid), true, data->getClientName())); -class CKsMidiPin : public CKsPin -{ -public: - CKsMidiPin(CKsFilter* pFilter, ULONG nId); -}; +} -class CKsMidiRenFilter : public CKsMidiFilter +PortList MidiOutWinMM :: getPortList(int capabilities) { -public: - CKsMidiRenFilter(tstring const& sPath, std::string const& sFriendlyName); - CKsMidiPin* CreateRenderPin(); - - void Validate() - { - if (m_RenderPins.empty()) - throw std::runtime_error("Could not find a MIDI render pin"); + WinMidiData *data = static_cast (apiData_); + if (!data || capabilities != PortDescriptor::OUTPUT) return PortList(); + try { + return WinMMPortDescriptor::getPortList(PortDescriptor::OUTPUT,data->getClientName()); + } catch (Error & e) { + error(e); + return PortList(); } -}; +} -class CKsMidiCapFilter : public CKsMidiFilter + +void MidiOutWinMM :: sendMessage( const unsigned char *message, size_t size ) { -public: - CKsMidiCapFilter(tstring const& sPath, std::string const& sFriendlyName); - CKsMidiPin* CreateCapturePin(); + if ( !connected_ ) return; - void Validate() - { - if (m_CapturePins.empty()) - throw std::runtime_error("Could not find a MIDI capture pin"); + if ( size == 0 ) { + error(RTMIDI_ERROR(gettext_noopt("Message argument is empty."), + Error::WARNING)); + return; } -}; -CKsMidiFilter::CKsMidiFilter(tstring const& sPath, std::string const& sFriendlyName) : - CKsFilter(sPath, sFriendlyName) -{ -} + MMRESULT result; + WinMidiData *data = static_cast (apiData_); + if ( message[0] == 0xF0 ) { // Sysex message -void CKsMidiFilter::FindMidiPins() -{ - ULONG numPins = GetPinProperty(0, KSPROPERTY_PIN_CTYPES); + // Allocate buffer for sysex data. + char *buffer = (char *) malloc( size ); + if ( buffer == NULL ) { + error(RTMIDI_ERROR(gettext_noopt("Error while allocating sysex message memory."), + Error::MEMORY_ERROR) ); + return; + } - for (ULONG iPin = 0; iPin < numPins; ++iPin) { - try { - KSPIN_COMMUNICATION com = GetPinProperty(iPin, KSPROPERTY_PIN_COMMUNICATION); - if (com != KSPIN_COMMUNICATION_SINK && com != KSPIN_COMMUNICATION_BOTH) - throw std::runtime_error("Unknown pin communication value"); + // Copy data to buffer. + for ( unsigned int i=0; ioutHandle, &sysex, sizeof(MIDIHDR) ); + if ( result != MMSYSERR_NOERROR ) { + free( buffer ); + error(RTMIDI_ERROR(gettext_noopt("Error preparing sysex header."), + Error::DRIVER_ERROR)); + return; } - catch (std::runtime_error const&) { - // pin instanciation has failed, continue to the next pin. + + // Send the message. + result = midiOutLongMsg( data->outHandle, &sysex, sizeof(MIDIHDR) ); + if ( result != MMSYSERR_NOERROR ) { + free( buffer ); + error(RTMIDI_ERROR(gettext_noopt("Error sending sysex message."), + Error::DRIVER_ERROR) ); + return; } + + // Unprepare the buffer and MIDIHDR. + while ( MIDIERR_STILLPLAYING == midiOutUnprepareHeader( data->outHandle, &sysex, sizeof (MIDIHDR) ) ) Sleep( 1 ); + free( buffer ); } + else { // Channel or system message. - m_RenderPins.clear(); - m_CapturePins.clear(); + // Make sure the message size isn't too big. + if ( size > 3 ) { + error(RTMIDI_ERROR(gettext_noopt("Message size is greater than 3 bytes (and not sysex)."), + Error::WARNING) ); + return; + } - for (size_t i = 0; i < m_Pins.size(); ++i) { - CKsPin* const pPin = m_Pins[i]; + // Pack MIDI bytes into double word. + DWORD packet; + unsigned char *ptr = (unsigned char *) &packet; + for ( unsigned int i=0; iIsSink()) { - if (pPin->GetDataFlow() == KSPIN_DATAFLOW_IN) - m_RenderPins.push_back(pPin); - else - m_CapturePins.push_back(pPin); + // Send the message immediately. + result = midiOutShortMsg( data->outHandle, packet ); + if ( result != MMSYSERR_NOERROR ) { + error(RTMIDI_ERROR(gettext_noopt("Error sending MIDI message."), + Error::DRIVER_ERROR )); } } - - if (m_RenderPins.empty() && m_CapturePins.empty()) - throw std::runtime_error("No valid pins found on the filter."); -} - -CKsMidiRenFilter::CKsMidiRenFilter(tstring const& sPath, std::string const& sFriendlyName) : - CKsMidiFilter(sPath, sFriendlyName) -{ } +#undef RTMIDI_CLASSNAME +RTMIDI_NAMESPACE_END +#endif // __WINDOWS_MM__ -CKsMidiPin* CKsMidiRenFilter::CreateRenderPin() -{ - if (m_RenderPins.empty()) - throw std::runtime_error("Could not find a MIDI render pin"); - CKsMidiPin* pPin = (CKsMidiPin*)m_RenderPins[0]; - pPin->Instantiate(); - return pPin; -} +//*********************************************************************// +// API: UNIX JACK +// +// Written primarily by Alexander Svetalkin, with updates for delta +// time by Gary Scavone, April 2011. +// +// *********************************************************************// -CKsMidiCapFilter::CKsMidiCapFilter(tstring const& sPath, std::string const& sFriendlyName) : - CKsMidiFilter(sPath, sFriendlyName) -{ -} +#if defined(__UNIX_JACK__) -CKsMidiPin* CKsMidiCapFilter::CreateCapturePin() -{ - if (m_CapturePins.empty()) - throw std::runtime_error("Could not find a MIDI capture pin"); +// JACK header files +#include +#include +#include +#ifdef HAVE_SEMAPHORE + #include +#endif - CKsMidiPin* pPin = (CKsMidiPin*)m_CapturePins[0]; - pPin->Instantiate(); - return pPin; -} +#define JACK_RINGBUFFER_SIZE 16384 // Default size for ringbuffer -CKsMidiPin::CKsMidiPin(CKsFilter* pFilter, ULONG nId) : - CKsPin(pFilter, nId) -{ - DWORD const cbPinCreateSize = sizeof(KSPIN_CONNECT) + sizeof(KSDATAFORMAT); - m_pKsPinConnect = (PKSPIN_CONNECT) new BYTE[cbPinCreateSize]; +RTMIDI_NAMESPACE_START - m_pKsPinConnect->Interface.Set = KSINTERFACESETID_Standard; - m_pKsPinConnect->Interface.Id = KSINTERFACE_STANDARD_STREAMING; - m_pKsPinConnect->Interface.Flags = 0; - m_pKsPinConnect->Medium.Set = KSMEDIUMSETID_Standard; - m_pKsPinConnect->Medium.Id = KSMEDIUM_TYPE_ANYINSTANCE; - m_pKsPinConnect->Medium.Flags = 0; - m_pKsPinConnect->PinId = nId; - m_pKsPinConnect->PinToHandle = NULL; - m_pKsPinConnect->Priority.PriorityClass = KSPRIORITY_NORMAL; - m_pKsPinConnect->Priority.PrioritySubClass = 1; +struct JackMidiData; +struct JackBackendCallbacks { + static int jackProcessIn( jack_nframes_t nframes, void *arg ); + static int jackProcessOut( jack_nframes_t nframes, void *arg ); +}; - // point m_pDataFormat to just after the pConnect struct - KSDATAFORMAT* m_pDataFormat = (KSDATAFORMAT*)(m_pKsPinConnect + 1); - m_pDataFormat->FormatSize = sizeof(KSDATAFORMAT); - m_pDataFormat->Flags = 0; - m_pDataFormat->SampleSize = 0; - m_pDataFormat->Reserved = 0; - m_pDataFormat->MajorFormat = GUID(KSDATAFORMAT_TYPE_MUSIC); - m_pDataFormat->SubFormat = GUID(KSDATAFORMAT_SUBTYPE_MIDI); - m_pDataFormat->Specifier = GUID(KSDATAFORMAT_SPECIFIER_NONE); - bool hasStdStreamingInterface = false; - bool hasStdStreamingMedium = false; +#define RTMIDI_CLASSNAME "JackSequencer" +template +class JackSequencer { +public: + JackSequencer():client(0),name(),data(0) + { + if (locking) { + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL); + pthread_mutex_init(&mutex, &attr); + } + } - for ( ULONG i = 0; i < m_cInterfaces; i++ ) { - if (m_pInterfaces[i].Set == KSINTERFACESETID_Standard - && m_pInterfaces[i].Id == KSINTERFACE_STANDARD_STREAMING) - hasStdStreamingInterface = true; + JackSequencer(const std::string &n, JackMidiData * d):client(0),name(n),data(d) + { + if (locking) { + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL); + pthread_mutex_init(&mutex, &attr); + } } - for (ULONG i = 0; i < m_cMediums; i++) { - if (m_pMediums[i].Set == KSMEDIUMSETID_Standard - && m_pMediums[i].Id == KSMEDIUM_STANDARD_DEVIO) - hasStdStreamingMedium = true; + ~JackSequencer() + { + { + scoped_lock lock (mutex); + if (client) { + jack_deactivate (client); + // the latter doesn't flush the queue + jack_client_close (client); + client = 0; + } + } + if (locking) { + pthread_mutex_destroy(&mutex); + } } - if (!hasStdStreamingInterface) // No standard streaming interfaces on the pin - throw std::runtime_error("CKsMidiPin::CKsMidiPin: no standard streaming interface"); + void init(bool startqueue) { + init(client,startqueue); + } - if (!hasStdStreamingMedium) // No standard streaming mediums on the pin - throw std::runtime_error("CKsMidiPin::CKsMidiPin: no standard streaming medium"); + bool setName(const std::string &n) { + /* we don't want to rename the client after opening it. */ + if (client) return false; + name = n; + return true; + } - bool hasMidiDataRange = false; + const char ** getPortList(unsigned long flags) { + init(); + return jack_get_ports(client, + NULL, + "midi", + flags); + } - BYTE const* pDataRangePtr = reinterpret_cast(m_pDataRanges); + jack_port_t * getPort(const char * name) { + init(); + return jack_port_by_name(client,name); + } - for (ULONG i = 0; i < m_cDataRanges; ++i) { - KSDATARANGE const* pDataRange = reinterpret_cast(pDataRangePtr); + std::string getPortName(jack_port_t * port, int flags) { + init(); + int naming = flags & PortDescriptor::NAMING_MASK; - if (pDataRange->SubFormat == KSDATAFORMAT_SUBTYPE_MIDI) { - hasMidiDataRange = true; + std::ostringstream os; + switch (naming) { + case PortDescriptor::SESSION_PATH: + if (flags & PortDescriptor::INCLUDE_API) + os << "JACK:"; +#if __UNIX_JACK_HAS_UUID__ + os << "UUID:" << std::hex << jack_port_uuid(port); +#else + os << jack_port_name(port); +#endif + break; + case PortDescriptor::STORAGE_PATH: + if (flags & PortDescriptor::INCLUDE_API) + os << "JACK:"; + os << jack_port_name(port); + break; + case PortDescriptor::LONG_NAME: + os << jack_port_name(port); + if (flags & PortDescriptor::INCLUDE_API) + os << " (JACK)"; + break; + case PortDescriptor::SHORT_NAME: + default: + os << jack_port_short_name(port); + if (flags & PortDescriptor::INCLUDE_API) + os << " (JACK)"; break; } + return os.str(); + } + + int getPortCapabilities(jack_port_t * port) { + if (!port) return 0; + const char * type = jack_port_type(port); + if (strcmp(type,JACK_DEFAULT_MIDI_TYPE)) return 0; + int flags = jack_port_flags(port); + int retval = 0; + /* a JACK input port is capable of handling output to it and vice versa */ + if (flags & JackPortIsInput) + retval |= PortDescriptor::OUTPUT; + if (flags & JackPortIsOutput) + retval |= PortDescriptor::INPUT; - pDataRangePtr += pDataRange->FormatSize; + return retval; } - if (!hasMidiDataRange) // No MIDI dataranges on the pin - throw std::runtime_error("CKsMidiPin::CKsMidiPin: no MIDI datarange"); -} + jack_port_t * createPort (const std::string &portName, unsigned long portOptions) { + init(); + scoped_lock lock (mutex); + return jack_port_register(client, + portName.c_str(), + JACK_DEFAULT_MIDI_TYPE, + portOptions, + 0); + } + + int renamePort(jack_port_t * port, const std::string &portName) { +#ifdef JACK_HAS_PORT_RENAME + return jack_port_rename( client, port, portName.c_str() ); +#else + return jack_port_set_name( port, portName.c_str() ); +#endif + } + + void deletePort(jack_port_t * port) { + init(); + scoped_lock lock (mutex); + jack_port_unregister( client, port ); + } -struct WindowsKsData -{ - WindowsKsData() : m_pPin(NULL), m_Buffer(1024), m_hInputThread(NULL) + void connectPorts(jack_port_t * from, + jack_port_t * to) { - memset(&overlapped, 0, sizeof(OVERLAPPED)); - m_hExitEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL); - overlapped.hEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL); - m_hInputThread = NULL; + init(); + jack_connect( client, + jack_port_name( from ), + jack_port_name( to ) ); } - ~WindowsKsData() + void closePort(jack_port_t * port) { - ::CloseHandle(overlapped.hEvent); - ::CloseHandle(m_hExitEvent); + init(); + jack_port_disconnect( client, port); } - OVERLAPPED overlapped; - CKsPin* m_pPin; - std::vector m_Buffer; - std::auto_ptr > m_pCaptureEnum; - std::auto_ptr > m_pRenderEnum; - HANDLE m_hInputThread; - HANDLE m_hExitEvent; -}; -// *********************************************************************// -// API: WINDOWS Kernel Streaming -// Class Definitions: MidiInWinKS -// *********************************************************************// - -static DWORD WINAPI midiKsInputThread(VOID* pUser) -{ - MidiInApi::RtMidiInData* data = static_cast(pUser); - WindowsKsData* apiData = static_cast(data->apiData); - - HANDLE hEvents[] = { apiData->overlapped.hEvent, apiData->m_hExitEvent }; - - while ( true ) { - KSSTREAM_HEADER packet; - memset(&packet, 0, sizeof packet); - packet.Size = sizeof(KSSTREAM_HEADER); - packet.PresentationTime.Time = 0; - packet.PresentationTime.Numerator = 1; - packet.PresentationTime.Denominator = 1; - packet.Data = &apiData->m_Buffer[0]; - packet.DataUsed = 0; - packet.FrameExtent = apiData->m_Buffer.size(); - apiData->m_pPin->ReadData(&packet, &apiData->overlapped); - - DWORD dwRet = ::WaitForMultipleObjects(2, hEvents, FALSE, INFINITE); - - if ( dwRet == WAIT_OBJECT_0 ) { - // parse packet - unsigned char* pData = (unsigned char*)packet.Data; - unsigned int iOffset = 0; - - while ( iOffset < packet.DataUsed ) { - KSMUSICFORMAT* pMusic = (KSMUSICFORMAT*)&pData[iOffset]; - iOffset += sizeof(KSMUSICFORMAT); - - MidiInApi::MidiMessage message; - message.timeStamp = 0; - for(size_t i=0;i < pMusic->ByteCount;++i) - message.bytes.push_back(pData[iOffset+i]); - - if ( data->usingCallback ) { - RtMidiIn::RtMidiCallback callback = (RtMidiIn::RtMidiCallback)data->userCallback; - callback(message.timeStamp, &message.bytes, data->userData); - } - else { - // As long as we haven't reached our queue size limit, push the message. - if ( data->queue.size < data->queue.ringSize ) { - data->queue.ring[data->queue.back++] = message; - if(data->queue.back == data->queue.ringSize) - data->queue.back = 0; - data->queue.size++; - } - else - std::cerr << "\nRtMidiIn: message queue limit reached!!\n\n"; - } - - iOffset += pMusic->ByteCount; - - // re-align on 32 bits - if ( iOffset % 4 != 0 ) - iOffset += (4 - iOffset % 4); - } - } - else - break; + /*! Use JackSequencer like a C pointer. + \note This function breaks the design to control thread safety + by the selection of the \ref locking parameter to the class. + It should be removed as soon as possible in order ensure the + thread policy that has been intended by creating this class. + */ + operator jack_client_t * () + { + return client; } - return 0; -} -MidiInWinKS :: MidiInWinKS( const std::string clientName, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) -{ - initialize( clientName ); -} +protected: + struct scoped_lock { + pthread_mutex_t * mutex; + scoped_lock(pthread_mutex_t & m): mutex(&m) + { + if (locking) + pthread_mutex_lock(mutex); + } + ~scoped_lock() + { + if (locking) + pthread_mutex_unlock(mutex); + } + }; + pthread_mutex_t mutex; + jack_client_t * client; + std::string name; + JackMidiData * data; -void MidiInWinKS :: initialize( const std::string& clientName ) -{ - WindowsKsData* data = new WindowsKsData; - apiData_ = (void*)data; - inputData_.apiData = data; - GUID const aguidEnumCats[] = + void init() { - { STATIC_KSCATEGORY_AUDIO }, { STATIC_KSCATEGORY_CAPTURE } - }; - data->m_pCaptureEnum.reset(new CKsEnumFilters ); - data->m_pCaptureEnum->EnumFilters(aguidEnumCats, 2); -} - -MidiInWinKS :: ~MidiInWinKS() -{ - WindowsKsData* data = static_cast(apiData_); - try { - if ( data->m_pPin ) - closePort(); - } - catch(...) { + init (client,false); } - delete data; -} + void init(jack_client_t * &c, bool isoutput) + { + if (c) return; + { + scoped_lock lock(mutex); + if (( c = jack_client_open( name.c_str(), + JackNoStartServer, + NULL )) == 0) { + c = NULL; + throw RTMIDI_ERROR(gettext_noopt("Could not connect to JACK server. Is it runnig?"), + Error::NO_DEVICES_FOUND); + return; + } -void MidiInWinKS :: openPort( unsigned int portNumber, const std::string portName ) -{ - WindowsKsData* data = static_cast(apiData_); + if (isoutput && data) { + jack_set_process_callback( c, JackBackendCallbacks::jackProcessOut, data ); + } else if (data) + jack_set_process_callback( c, JackBackendCallbacks::jackProcessIn, data ); + jack_activate( c ); + } + } +}; +typedef JackSequencer<1> LockingJackSequencer; +typedef JackSequencer<0> NonLockingJackSequencer; +#undef RTMIDI_CLASSNAME - if ( portNumber < 0 || portNumber >= data->m_pCaptureEnum->m_Filters.size() ) { - std::stringstream ost; - ost << "MidiInWinKS::openPort: the 'portNumber' argument (" << portNumber << ") is invalid."; - errorString_ = ost.str(); - error( RtMidiError::WARNING, errorString_ ); - return; +#define RTMIDI_CLASSNAME "JackPortDescriptor" +struct JackPortDescriptor:public PortDescriptor +{ + MidiApi * api; + static LockingJackSequencer seq; + JackPortDescriptor(const std::string &name):api(0),clientName(name) + { + port = 0; + } + JackPortDescriptor(const char * portname, const std::string &name):api(0),clientName(name) + { + seq.setName(name); + port = seq.getPort(portname); + } + JackPortDescriptor(jack_port_t * other, + const std::string &name):api(0), + clientName(name) + { + port = other; + seq.setName(name); + } + JackPortDescriptor(JackPortDescriptor & other, + const std::string &name):api(0), + clientName(name) + { + port = other.port; + seq.setName(name); + } + ~JackPortDescriptor() + { + } + MidiInApi * getInputApi(unsigned int queueSizeLimit = 100) const { + if (getCapabilities() & INPUT) + return new MidiInJack(clientName,queueSizeLimit); + else + return 0; + } + MidiOutApi * getOutputApi() const { + if (getCapabilities() & OUTPUT) + return new MidiOutJack(clientName); + else + return 0; } - CKsMidiCapFilter* pFilter = data->m_pCaptureEnum->m_Filters[portNumber]; - data->m_pPin = pFilter->CreateCapturePin(); - if ( data->m_pPin == NULL ) { - std::stringstream ost; - ost << "MidiInWinKS::openPort: KS error opening port (could not create pin)"; - errorString_ = ost.str(); - error( RtMidiError::WARNING, errorString_ ); - return; + std::string getName(int flags = SHORT_NAME | UNIQUE_PORT_NAME) { + return seq.getPortName(port,flags); } - data->m_pPin->SetState(KSSTATE_RUN); - - DWORD threadId; - data->m_hInputThread = ::CreateThread(NULL, 0, &midiKsInputThread, &inputData_, 0, &threadId); - if ( data->m_hInputThread == NULL ) { - std::stringstream ost; - ost << "MidiInWinKS::openPort: Could not create input thread : Windows error " << GetLastError() << std::endl;; - errorString_ = ost.str(); - error( RtMidiError::WARNING, errorString_ ); - return; + const std::string &getClientName() { + return clientName; + } + int getCapabilities() const { + return seq.getPortCapabilities(port); } + static PortList getPortList(int capabilities, const std::string &clientName); - connected_ = true; -} + operator jack_port_t * () const { return port; } -void MidiInWinKS :: openVirtualPort( const std::string portName ) -{ - // This function cannot be implemented for the Windows KS MIDI API. - errorString_ = "MidiInWinKS::openVirtualPort: cannot be implemented in Windows KS MIDI API!"; - error( RtMidiError::WARNING, errorString_ ); -} +protected: + std::string clientName; + jack_port_t * port; -unsigned int MidiInWinKS :: getPortCount() -{ - WindowsKsData* data = static_cast(apiData_); - return (unsigned int)data->m_pCaptureEnum->m_Filters.size(); -} + friend struct JackMidiData; +}; -std::string MidiInWinKS :: getPortName(unsigned int portNumber) -{ - WindowsKsData* data = static_cast(apiData_); +LockingJackSequencer JackPortDescriptor::seq; - if (portNumber < 0 || portNumber >= data->m_pCaptureEnum->m_Filters.size()) { - std::stringstream ost; - ost << "MidiInWinKS::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid."; - errorString_ = ost.str(); - error( RtMidiError::WARNING, errorString_ ); - return; - } - CKsMidiCapFilter* pFilter = data->m_pCaptureEnum->m_Filters[portNumber]; - return pFilter->GetFriendlyName(); -} -void MidiInWinKS :: closePort() +PortList JackPortDescriptor :: getPortList(int capabilities, const std::string &clientName) { - WindowsKsData* data = static_cast(apiData_); - connected_ = false; + PortList list; + unsigned long flags = 0; - if (data->m_hInputThread) { - ::SignalObjectAndWait(data->m_hExitEvent, data->m_hInputThread, INFINITE, FALSE); - ::CloseHandle(data->m_hInputThread); + if (capabilities & INPUT) { + flags |= JackPortIsOutput; } - - if (data->m_pPin) { - data->m_pPin->SetState(KSSTATE_PAUSE); - data->m_pPin->SetState(KSSTATE_STOP); - data->m_pPin->ClosePin(); - data->m_pPin = NULL; + if (capabilities & OUTPUT) { + flags |= JackPortIsInput; + } + const char ** ports = seq.getPortList(flags); + if (!ports) return list; + for (const char ** port = ports; *port; port++) { + list.push_back(Pointer( + new JackPortDescriptor(*port, clientName))); } + jack_free(ports); + return list; } +#undef RTMIDI_CLASSNAME -// *********************************************************************// -// API: WINDOWS Kernel Streaming -// Class Definitions: MidiOutWinKS -// *********************************************************************// +/*! A structure to hold variables related to the JACK API + implementation. -MidiOutWinKS :: MidiOutWinKS( const std::string clientName ) : MidiOutApi() -{ - initialize( clientName ); -} + \note After all sequencer handling is covered by the \ref + JackSequencer class, we should make seq to be a pointer in order + to allow a common client implementation. +*/ -void MidiOutWinKS :: initialize( const std::string& clientName ) -{ - WindowsKsData* data = new WindowsKsData; +#define RTMIDI_CLASSNAME "JackMidiData" +struct JackMidiData:public JackPortDescriptor { + /* signal the JACK process what to do next */ + volatile enum { + RUNNING, /*!< keep the client open, flag is owned by the controlling process */ + CLOSING, /*!< close the current port */ + DELETING /*!< Delete the client after delivering the contents of the ring buffer */ + } stateflags; + /*! response/state from the JACK thread. See \ref jackProcessOut for details */ + volatile enum { + OPEN, + CLOSING2, + CLOSED, + DELETING2, + DELETING3 + /* DELETED is useless as this doesn't exist anymore */ + } state_response; + + jack_port_t * local; + jack_ringbuffer_t *buffSize; + jack_ringbuffer_t *buffMessage; + jack_time_t lastTime; +#ifdef HAVE_SEMAPHORE + sem_t sem_cleanup; + sem_t sem_needpost; +#endif + MidiInJack *rtMidiIn; + /*! Sequencer object: This must be deleted _before_ the MIDI data to avoid + segmentation faults while queued data is still in the ring buffer. */ + NonLockingJackSequencer * seq; - data->m_pPin = NULL; - data->m_pRenderEnum.reset(new CKsEnumFilters ); - GUID const aguidEnumCats[] = + /* + JackMidiData():seq() + { + init(); + } + */ + JackMidiData(const std::string &clientName, + MidiInJack * inputData_):JackPortDescriptor(clientName), + stateflags(RUNNING), + local(0), + buffSize(0), + buffMessage(0), + lastTime(0), + rtMidiIn(inputData_), + seq(new NonLockingJackSequencer(clientName,this)) { - { STATIC_KSCATEGORY_AUDIO }, { STATIC_KSCATEGORY_RENDER } - }; - data->m_pRenderEnum->EnumFilters(aguidEnumCats, 2); - - apiData_ = (void*)data; -} +#ifdef HAVE_SEMAPHORE + sem_init(&sem_cleanup, 0, 0); + sem_init(&sem_needpost, 0, 0); +#endif + } -MidiOutWinKS :: ~MidiOutWinKS() -{ - // Close a connection if it exists. - closePort(); + /** + * Create output midi data. + * + * \param clientName + * + * \return + */ + JackMidiData(const std::string &clientName):JackPortDescriptor(clientName), + stateflags(RUNNING), + local(0), + buffSize(jack_ringbuffer_create( JACK_RINGBUFFER_SIZE )), + buffMessage(jack_ringbuffer_create( JACK_RINGBUFFER_SIZE )), + lastTime(0), + rtMidiIn(), + seq(new NonLockingJackSequencer(clientName,this)) + { +#ifdef HAVE_SEMAPHORE + sem_init(&sem_cleanup, 0, 0); + sem_init(&sem_needpost, 0, 0); +#endif + } - // Cleanup. - WindowsKsData* data = static_cast(apiData_); - delete data; -} -void MidiOutWinKS :: openPort( unsigned int portNumber, const std::string portName ) -{ - WindowsKsData* data = static_cast(apiData_); + ~JackMidiData() + { + if (local) + deletePort(); + if (seq) + delete seq; +#ifdef HAVE_SEMAPHORE + sem_destroy(&sem_cleanup); + sem_destroy(&sem_needpost); +#endif - if (portNumber < 0 || portNumber >= data->m_pRenderEnum->m_Filters.size()) { - std::stringstream ost; - ost << "MidiOutWinKS::openPort: the 'portNumber' argument (" << portNumber << ") is invalid."; - errorString_ = ost.str(); - error( RtMidiError::WARNING, errorString_ ); - return; + if (buffSize) { + jack_ringbuffer_free( buffSize ); + buffSize = 0; + } + if (buffMessage) { + jack_ringbuffer_free( buffMessage ); + buffMessage = 0; + } } - CKsMidiRenFilter* pFilter = data->m_pRenderEnum->m_Filters[portNumber]; - data->m_pPin = pFilter->CreateRenderPin(); - - if (data->m_pPin == NULL) { - std::stringstream ost; - ost << "MidiOutWinKS::openPort: KS error opening port (could not create pin)"; - errorString_ = ost.str(); - error( RtMidiError::WARNING, errorString_ ); - return; + void init(bool isinput) { + seq->init(!isinput); } - data->m_pPin->SetState(KSSTATE_RUN); - connected_ = true; -} -void MidiOutWinKS :: openVirtualPort( const std::string portName ) -{ - // This function cannot be implemented for the Windows KS MIDI API. - errorString_ = "MidiOutWinKS::openVirtualPort: cannot be implemented in Windows KS MIDI API!"; - error( RtMidiError::WARNING, errorString_ ); -} + void setRemote(jack_port_t * remote) { + port = remote; + } -unsigned int MidiOutWinKS :: getPortCount() -{ - WindowsKsData* data = static_cast(apiData_); - return (unsigned int)data->m_pRenderEnum->m_Filters.size(); -} + void connectPorts(jack_port_t * from, + jack_port_t * to) { + seq->connectPorts(from, to); + } -std::string MidiOutWinKS :: getPortName( unsigned int portNumber ) -{ - WindowsKsData* data = static_cast(apiData_); + int openPort(unsigned long jackCapabilities, + const std::string &portName) { + local = seq->createPort(portName, jackCapabilities); + if (!local) { + api->error(RTMIDI_ERROR(gettext_noopt("Error opening JACK port subscription."), + Error::DRIVER_ERROR) ); + return -99; + } + return 0; + } - if ( portNumber < 0 || portNumber >= data->m_pRenderEnum->m_Filters.size() ) { - std::stringstream ost; - ost << "MidiOutWinKS::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid."; - errorString_ = ost.str(); - error( RtMidiError::WARNING, errorString_ ); - return; + int rename(const std::string &portName) { + return seq->renamePort(local,portName); } - CKsMidiRenFilter* pFilter = data->m_pRenderEnum->m_Filters[portNumber]; - return pFilter->GetFriendlyName(); -} + void delayedDeletePort() { + /* Closing the port can be twofold to ensure all data is sent: + - Use a semaphore to wait for this state + - Close the port from within jackProcessOut + */ + if (local == NULL) return; -void MidiOutWinKS :: closePort() -{ - WindowsKsData* data = static_cast(apiData_); - connected_ = false; +#ifdef HAVE_SEMAPHORE + struct timespec ts; + if (clock_gettime(CLOCK_REALTIME, &ts) != -1) + { + ts.tv_sec += 1; // wait max one second + sem_post(&sem_needpost); + sem_timedwait(&sem_cleanup, &ts); + } - if ( data->m_pPin ) { - data->m_pPin->SetState(KSSTATE_PAUSE); - data->m_pPin->SetState(KSSTATE_STOP); - data->m_pPin->ClosePin(); - data->m_pPin = NULL; + deletePort(); +#else + if ( local == NULL || state_response == JackMidiData::CLOSED ) return; + stateflags = JackMidiData::CLOSING; +#endif +#if defined(__RTMIDI_DEBUG__) + std::cerr << "Closed Port" << std::endl; +#endif } -} - -void MidiOutWinKS :: sendMessage(std::vector* pMessage) -{ - std::vector const& msg = *pMessage; - WindowsKsData* data = static_cast(apiData_); - size_t iNumMidiBytes = msg.size(); - size_t pos = 0; - // write header - KSMUSICFORMAT* pKsMusicFormat = reinterpret_cast(&data->m_Buffer[pos]); - pKsMusicFormat->TimeDeltaMs = 0; - pKsMusicFormat->ByteCount = iNumMidiBytes; - pos += sizeof(KSMUSICFORMAT); + void request_delete() { + // signal the output callback to delete the data + // after finishing its job. + // this can be done twofold: + // - via signal in jackProcessOut + // - using a semaphore +#ifdef HAVE_SEMAPHORE + closePort(); - // write MIDI bytes - if ( pos + iNumMidiBytes > data->m_Buffer.size() ) { - std::stringstream ost; - ost << "KsMidiInput::Write: MIDI buffer too small. Required " << pos + iNumMidiBytes << " bytes, only has " << data->m_Buffer.size(); - errorString_ = ost.str(); - error( RtMidiError::WARNING, errorString_ ); + // Cleanup + delete this; return; +#else + stateflags = JackMidiData::DELETING; +#endif } - if ( data->m_pPin == NULL ) { - std::stringstream ost; - ost << "MidiOutWinKS::sendMessage: port is not open"; - errorString_ = ost.str(); - error( RtMidiError::WARNING, errorString_ ); - return; - } + void deletePortIfRequested() { +#ifdef HAVE_SEMAPHORE + if (!sem_trywait(&sem_needpost)) + sem_post(&sem_cleanup); +#else + switch (stateflags) { + case JackMidiData::RUNNING: break; + case JackMidiData::CLOSING: + if (state_response != JackMidiData::CLOSING2) { + /* output the transferred data */ + state_response = JackMidiData::CLOSING2; + return; + } + deletePort(); + state_response = JackMidiData::CLOSED; + break; - memcpy(&data->m_Buffer[pos], &msg[0], iNumMidiBytes); - pos += iNumMidiBytes; + case JackMidiData::DELETING: +#if defined(__RTMIDI_DEBUG__) + std::cerr << "deleting port" << std::endl; +#endif + if (state_response != JackMidiData::DELETING2) { + state_response = JackMidiData::DELETING2; + /* output the transferred data */ + return; + } - KSSTREAM_HEADER packet; - memset(&packet, 0, sizeof packet); - packet.Size = sizeof(packet); - packet.PresentationTime.Time = 0; - packet.PresentationTime.Numerator = 1; - packet.PresentationTime.Denominator = 1; - packet.Data = const_cast(&data->m_Buffer[0]); - packet.DataUsed = ((pos+3)/4)*4; - packet.FrameExtent = data->m_Buffer.size(); + delete this; + return; +#if defined(__RTMIDI_DEBUG__) + std::cerr << "deleted port" << std::endl; +#endif + break; + } +#endif + } - data->m_pPin->WriteData(&packet, NULL); -} + void deletePort() { + if (local == NULL) + return; -#endif // __WINDOWS_KS__ +#ifdef HAVE_SEMAPHORE + struct timespec ts; + if (clock_gettime(CLOCK_REALTIME, &ts) != -1) { + ts.tv_sec += 2; // wait max two seconds + sem_post(&sem_needpost); + sem_timedwait(&sem_cleanup, &ts); + } +#endif -//*********************************************************************// -// API: UNIX JACK -// -// Written primarily by Alexander Svetalkin, with updates for delta -// time by Gary Scavone, April 2011. -// -// *********************************************************************// + seq->deletePort(local); + local = NULL; + } -#if defined(__UNIX_JACK__) + void closePort() { + seq->closePort( local ); + local = NULL; + } -// JACK header files -#include -#include -#include + operator jack_port_t * () const { return port; } +}; +#undef RTMIDI_CLASSNAME -#define JACK_RINGBUFFER_SIZE 16384 // Default size for ringbuffer -struct JackMidiData { - jack_client_t *client; - jack_port_t *port; - jack_ringbuffer_t *buffSize; - jack_ringbuffer_t *buffMessage; - jack_time_t lastTime; - MidiInApi :: RtMidiInData *rtMidiIn; - }; //*********************************************************************// // API: JACK // Class Definitions: MidiInJack //*********************************************************************// -static int jackProcessIn( jack_nframes_t nframes, void *arg ) +#define RTMIDI_CLASSNAME "JackBackendCallbacks" +int JackBackendCallbacks::jackProcessIn( jack_nframes_t nframes, void *arg ) { JackMidiData *jData = (JackMidiData *) arg; - MidiInApi :: RtMidiInData *rtData = jData->rtMidiIn; + MidiInJack *rtData = jData->rtMidiIn; jack_midi_event_t event; jack_time_t time; // Is port created? - if ( jData->port == NULL ) return 0; - void *buff = jack_port_get_buffer( jData->port, nframes ); + if ( jData->local == NULL ) return 0; + void *buff = jack_port_get_buffer( jData->local, nframes ); // We have midi events in buffer int evCount = jack_midi_get_event_count( buff ); @@ -3532,20 +5921,19 @@ static int jackProcessIn( jack_nframes_t nframes, void *arg ) jData->lastTime = time; if ( !rtData->continueSysex ) { - if ( rtData->usingCallback ) { - RtMidiIn::RtMidiCallback callback = (RtMidiIn::RtMidiCallback) rtData->userCallback; - callback( message.timeStamp, &message.bytes, rtData->userData ); + if ( rtData->userCallback ) { + rtData->userCallback->rtmidi_midi_in( message.timeStamp, message.bytes); } else { - // As long as we haven't reached our queue size limit, push the message. - if ( rtData->queue.size < rtData->queue.ringSize ) { - rtData->queue.ring[rtData->queue.back++] = message; - if ( rtData->queue.back == rtData->queue.ringSize ) - rtData->queue.back = 0; - rtData->queue.size++; - } - else - std::cerr << "\nMidiInJack: message queue limit reached!!\n\n"; + // As long as we haven't reached our queue size limit, push the message. + if (!rtData->queue.push(message)) { + try { + rtData->error(RTMIDI_ERROR(rtmidi_gettext("Error: Message queue limit reached."), + Error::WARNING)); + } catch (Error & e) { + // don't bother JACK with an unhandled exception + } + } } } } @@ -3553,98 +5941,212 @@ static int jackProcessIn( jack_nframes_t nframes, void *arg ) return 0; } -MidiInJack :: MidiInJack( const std::string clientName, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) +// Jack process callback +int JackBackendCallbacks::jackProcessOut( jack_nframes_t nframes, void *arg ) +{ + JackMidiData *data = (JackMidiData *) arg; + jack_midi_data_t *midiData; + int space; + + // Is port created? + if ( data->local == NULL ) return 0; + + void *buff = jack_port_get_buffer( data->local, nframes ); + if (buff != NULL) { + jack_midi_clear_buffer( buff ); + + while ( jack_ringbuffer_read_space( data->buffSize ) > 0 ) { + jack_ringbuffer_read( data->buffSize, (char *) &space, (size_t) sizeof(space) ); + midiData = jack_midi_event_reserve( buff, 0, space ); + + jack_ringbuffer_read( data->buffMessage, (char *) midiData, (size_t) space ); + } + } + + data->deletePortIfRequested(); + return 0; +} +#undef RTMIDI_CLASSNAME + +#define RTMIDI_CLASSNAME "MidiInJack" +MidiInJack :: MidiInJack( const std::string &clientName, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) { - initialize( clientName ); + MidiInJack::initialize( clientName ); } -void MidiInJack :: initialize( const std::string& clientName ) +void MidiInJack :: initialize( const std::string &clientName ) { - JackMidiData *data = new JackMidiData; + JackMidiData *data = new JackMidiData(clientName,this); apiData_ = (void *) data; - - data->rtMidiIn = &inputData_; - data->port = NULL; - data->client = NULL; this->clientName = clientName; - - connect(); + try { + data->init(true); + } catch (const Error & e) { + delete data; + apiData_ = 0; + throw; + } } +#if 0 void MidiInJack :: connect() { + abort(); + // this should be unnecessary JackMidiData *data = static_cast (apiData_); - if ( data->client ) + if ( data->local ) return; // Initialize JACK client - if (( data->client = jack_client_open( clientName.c_str(), JackNoStartServer, NULL )) == 0) { - errorString_ = "MidiInJack::initialize: JACK server not running?"; - error( RtMidiError::WARNING, errorString_ ); + if (( data->local = jack_client_open( clientName.c_str(), JackNoStartServer, NULL )) == 0) { + error(RTMIDI_ERROR(gettext_noopt("JACK server not running?"), + Error::WARNING) ); return; } jack_set_process_callback( data->client, jackProcessIn, data ); jack_activate( data->client ); } +#endif MidiInJack :: ~MidiInJack() { JackMidiData *data = static_cast (apiData_); - closePort(); + try { + MidiInJack::closePort(); + } catch (Error & e) { + try { + delete data; + } catch (...) { + } + error(e); + return; + } +#if 0 if ( data->client ) jack_client_close( data->client ); +#endif + /* immediately shut down the JACK client */ delete data; } -void MidiInJack :: openPort( unsigned int portNumber, const std::string portName ) +void MidiInJack :: openPort( unsigned int portNumber, const std::string &portName ) { JackMidiData *data = static_cast (apiData_); - connect(); + // connect(); // Creating new port - if ( data->port == NULL) - data->port = jack_port_register( data->client, portName.c_str(), - JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0 ); + if ( data->local == NULL) + data->local = jack_port_register( *(data->seq), portName.c_str(), + JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0 ); - if ( data->port == NULL) { - errorString_ = "MidiInJack::openPort: JACK error creating port"; - error( RtMidiError::DRIVER_ERROR, errorString_ ); + if ( data->local == NULL) { + error(RTMIDI_ERROR(gettext_noopt("Error creating JACK port."), + Error::DRIVER_ERROR) ); return; } // Connecting to the output std::string name = getPortName( portNumber ); - jack_connect( data->client, name.c_str(), jack_port_name( data->port ) ); + jack_connect( *(data->seq), name.c_str(), jack_port_name( data->local ) ); +} + +void MidiInJack :: openVirtualPort( const std::string &portName ) +{ + JackMidiData *data = static_cast (apiData_); + + // connect(); + if ( data->local == NULL ) + data->local = jack_port_register( *(data->seq), portName.c_str(), + JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0 ); + + if ( data->local == NULL ) { + error(RTMIDI_ERROR(gettext_noopt("Error creating JACK virtual port."), + Error::DRIVER_ERROR) ); + } } -void MidiInJack :: openVirtualPort( const std::string portName ) +void MidiInJack :: openPort( const PortDescriptor & p, + const std::string &portName ) { JackMidiData *data = static_cast (apiData_); + const JackPortDescriptor * port = dynamic_cast(&p); + + if ( !data ) { + error(RTMIDI_ERROR(gettext_noopt("Data has not been allocated."), + Error::SYSTEM_ERROR) ); + return; + } +#if 0 + if ( connected_ ) { + error(RTMIDI_ERROR(gettext_noopt("A valid connection already exists."), + Error::WARNING) ); + return; + } +#endif + if (!port) { + error(RTMIDI_ERROR(gettext_noopt("JACK has been instructed to open a non-JACK MIDI port. This doesn't work."), + Error::INVALID_DEVICE) ); + return; + } + + try { + if (!data->local) + data->openPort (JackPortIsInput, + portName); + data->setRemote(*port); + data->connectPorts(*port,data->local); + } catch (Error & e) { + error (e); + } - connect(); - if ( data->port == NULL ) - data->port = jack_port_register( data->client, portName.c_str(), - JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0 ); +} + +Pointer MidiInJack :: getDescriptor(bool local) +{ + JackMidiData *data = static_cast (apiData_); + try { + if (local) { + if (data && data->local) { + return Pointer( + new JackPortDescriptor(data->local,data->getClientName())); + } + } else { + if (data && *data) { + return Pointer( + new JackPortDescriptor(*data,data->getClientName())); + } + } + } catch (Error & e) { + error(e); + } + return NULL; +} - if ( data->port == NULL ) { - errorString_ = "MidiInJack::openVirtualPort: JACK error creating virtual port"; - error( RtMidiError::DRIVER_ERROR, errorString_ ); +PortList MidiInJack :: getPortList(int capabilities) +{ + JackMidiData *data = static_cast (apiData_); + try { + return JackPortDescriptor::getPortList(capabilities | PortDescriptor::INPUT, + data->getClientName()); + } catch (Error & e) { + error(e); } + return PortList(); } unsigned int MidiInJack :: getPortCount() { int count = 0; + // connect(); JackMidiData *data = static_cast (apiData_); - connect(); - if ( !data->client ) + if ( !(*(data->seq)) ) return 0; // List of available ports - const char **ports = jack_get_ports( data->client, NULL, JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput ); + const char **ports = jack_get_ports( *(data->seq), NULL, JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput ); if ( ports == NULL ) return 0; while ( ports[count] != NULL ) @@ -3660,95 +6162,91 @@ std::string MidiInJack :: getPortName( unsigned int portNumber ) JackMidiData *data = static_cast (apiData_); std::string retStr(""); - connect(); + // connect(); // List of available ports - const char **ports = jack_get_ports( data->client, NULL, - JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput ); + const char **ports = jack_get_ports(* (data->seq), NULL, + JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput ); // Check port validity if ( ports == NULL ) { - errorString_ = "MidiInJack::getPortName: no ports available!"; - error( RtMidiError::WARNING, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("No ports available."), + Error::WARNING) ); return retStr; } - if ( ports[portNumber] == NULL ) { + unsigned int i; + for (i=0; i (apiData_); + if (!data) return; + + data->deletePort(); +} + +void MidiInJack :: setClientName( const std::string& ) +{ + error(RTMIDI_ERROR(gettext_noopt("Setting the client name is not supported by JACK."), + Error::WARNING )); +} - if ( data->port == NULL ) return; - jack_port_unregister( data->client, data->port ); - data->port = NULL; +void MidiInJack :: setPortName( const std::string &portName ) +{ + JackMidiData *data = static_cast (apiData_); + data->rename(portName); } +#undef RTMIDI_CLASSNAME //*********************************************************************// // API: JACK // Class Definitions: MidiOutJack //*********************************************************************// -// Jack process callback -static int jackProcessOut( jack_nframes_t nframes, void *arg ) -{ - JackMidiData *data = (JackMidiData *) arg; - jack_midi_data_t *midiData; - int space; - - // Is port created? - if ( data->port == NULL ) return 0; - - void *buff = jack_port_get_buffer( data->port, nframes ); - jack_midi_clear_buffer( buff ); - - while ( jack_ringbuffer_read_space( data->buffSize ) > 0 ) { - jack_ringbuffer_read( data->buffSize, (char *) &space, (size_t) sizeof(space) ); - midiData = jack_midi_event_reserve( buff, 0, space ); - - jack_ringbuffer_read( data->buffMessage, (char *) midiData, (size_t) space ); - } - - return 0; -} -MidiOutJack :: MidiOutJack( const std::string clientName ) : MidiOutApi() +#define RTMIDI_CLASSNAME "MidiOutJack" +MidiOutJack :: MidiOutJack( const std::string &clientName ) : MidiOutApi() { - initialize( clientName ); + MidiOutJack::initialize( clientName ); } -void MidiOutJack :: initialize( const std::string& clientName ) +void MidiOutJack :: initialize( const std::string &clientName ) { - JackMidiData *data = new JackMidiData; + JackMidiData *data = new JackMidiData(clientName); apiData_ = (void *) data; - - data->port = NULL; - data->client = NULL; this->clientName = clientName; - - connect(); + // init is the last as it may throw an exception + try { + data->init(false); + } catch (const Error & e) { + delete data; + apiData_ = 0; + throw; + } } void MidiOutJack :: connect() { +#if 0 JackMidiData *data = static_cast (apiData_); - if ( data->client ) + if ( *(data->seq) ) return; // Initialize JACK client - if (( data->client = jack_client_open( clientName.c_str(), JackNoStartServer, NULL )) == 0) { - errorString_ = "MidiOutJack::initialize: JACK server not running?"; - error( RtMidiError::WARNING, errorString_ ); + if (( *(data->seq) = jack_client_open( clientName.c_str(), JackNoStartServer, NULL )) == 0) { + error(RTMIDI_ERROR(gettext_noopt("JACK server not running?"), + Error::WARNING) ); return; } @@ -3756,71 +6254,127 @@ void MidiOutJack :: connect() data->buffSize = jack_ringbuffer_create( JACK_RINGBUFFER_SIZE ); data->buffMessage = jack_ringbuffer_create( JACK_RINGBUFFER_SIZE ); jack_activate( data->client ); +#endif } MidiOutJack :: ~MidiOutJack() { JackMidiData *data = static_cast (apiData_); - closePort(); - - if ( data->client ) { - // Cleanup - jack_client_close( data->client ); - jack_ringbuffer_free( data->buffSize ); - jack_ringbuffer_free( data->buffMessage ); - } - - delete data; + // closePort(); + data -> request_delete(); } -void MidiOutJack :: openPort( unsigned int portNumber, const std::string portName ) +void MidiOutJack :: openPort( unsigned int portNumber, const std::string &portName ) { JackMidiData *data = static_cast (apiData_); - connect(); + // connect(); // Creating new port - if ( data->port == NULL ) - data->port = jack_port_register( data->client, portName.c_str(), - JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0 ); + if ( data->local == NULL ) + data->local = jack_port_register( *(data->seq), portName.c_str(), + JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0 ); - if ( data->port == NULL ) { - errorString_ = "MidiOutJack::openPort: JACK error creating port"; - error( RtMidiError::DRIVER_ERROR, errorString_ ); + if ( data->local == NULL ) { + error(RTMIDI_ERROR(gettext_noopt("Error creating JACK port."), + Error::DRIVER_ERROR) ); return; } // Connecting to the output std::string name = getPortName( portNumber ); - jack_connect( data->client, jack_port_name( data->port ), name.c_str() ); + jack_connect( *(data->seq), jack_port_name( data->local ), name.c_str() ); +} + +void MidiOutJack :: openVirtualPort( const std::string &portName ) +{ + JackMidiData *data = static_cast (apiData_); + + // connect(); + if ( data->local == NULL ) + data->local = jack_port_register( *(data->seq), portName.c_str(), + JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0 ); + + if ( data->local == NULL ) { + error(RTMIDI_ERROR(gettext_noopt("Error creating JACK virtual port."), + Error::DRIVER_ERROR) ); + } } -void MidiOutJack :: openVirtualPort( const std::string portName ) +void MidiOutJack :: openPort( const PortDescriptor & p, + const std::string &portName ) { JackMidiData *data = static_cast (apiData_); + const JackPortDescriptor * port = dynamic_cast(&p); + + if ( !data ) { + error(RTMIDI_ERROR(gettext_noopt("Data has not been allocated."), + Error::SYSTEM_ERROR) ); + return; + } +#if 0 + if ( connected_ ) { + error(RTMIDI_ERROR(gettext_noopt("A valid connection already exists."), + Error::WARNING) ); + return; + } +#endif + if (!port) { + error(RTMIDI_ERROR(gettext_noopt("JACK has been instructed to open a non-JACK MIDI port. This doesn't work."), + Error::INVALID_DEVICE) ); + return; + } - connect(); - if ( data->port == NULL ) - data->port = jack_port_register( data->client, portName.c_str(), - JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0 ); + try { + if (!data->local) + data->openPort (JackPortIsOutput, + portName); + data->setRemote(*port); + data->connectPorts(data->local,*port); + } catch (Error & e) { + error(e); + } +} - if ( data->port == NULL ) { - errorString_ = "MidiOutJack::openVirtualPort: JACK error creating virtual port"; - error( RtMidiError::DRIVER_ERROR, errorString_ ); +Pointer MidiOutJack :: getDescriptor(bool local) +{ + JackMidiData *data = static_cast (apiData_); + try { + if (local) { + if (data && data->local) { + return Pointer( + new JackPortDescriptor(data->local,data->getClientName())); + } + } else { + if (data && *data) { + return Pointer( + new JackPortDescriptor(*data,data->getClientName())); + } + } + } catch (Error & e) { + error(e); } + return NULL; +} + +PortList MidiOutJack :: getPortList(int capabilities) +{ + JackMidiData *data = static_cast (apiData_); + return JackPortDescriptor::getPortList(capabilities | PortDescriptor::OUTPUT, + data->getClientName()); } unsigned int MidiOutJack :: getPortCount() { int count = 0; JackMidiData *data = static_cast (apiData_); - connect(); - if ( !data->client ) + // connect(); + if ( !*(data->seq) ) return 0; // List of available ports - const char **ports = jack_get_ports( data->client, NULL, - JACK_DEFAULT_MIDI_TYPE, JackPortIsInput ); + const char **ports = jack_get_ports(* (data->seq), NULL, + JACK_DEFAULT_MIDI_TYPE, JackPortIsInput ); if ( ports == NULL ) return 0; while ( ports[count] != NULL ) @@ -3836,24 +6390,23 @@ std::string MidiOutJack :: getPortName( unsigned int portNumber ) JackMidiData *data = static_cast (apiData_); std::string retStr(""); - connect(); + // connect(); // List of available ports - const char **ports = jack_get_ports( data->client, NULL, - JACK_DEFAULT_MIDI_TYPE, JackPortIsInput ); + const char **ports = jack_get_ports(*(data->seq), NULL, + JACK_DEFAULT_MIDI_TYPE, JackPortIsInput ); // Check port validity if ( ports == NULL) { - errorString_ = "MidiOutJack::getPortName: no ports available!"; - error( RtMidiError::WARNING, errorString_ ); + error(RTMIDI_ERROR(gettext_noopt("No ports available."), + Error::WARNING) ); return retStr; } if ( ports[portNumber] == NULL) { std::ostringstream ost; - ost << "MidiOutJack::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid."; - errorString_ = ost.str(); - error( RtMidiError::WARNING, errorString_ ); + error(RTMIDI_ERROR1(gettext_noopt("The 'portNumber' argument (%d) is invalid."), + Error::WARNING, portNumber) ); } else retStr.assign( ports[portNumber] ); @@ -3863,22 +6416,37 @@ std::string MidiOutJack :: getPortName( unsigned int portNumber ) void MidiOutJack :: closePort() { +#if defined(__RTMIDI_DEBUG__) + std::cerr << "Closing Port" << std::endl; +#endif JackMidiData *data = static_cast (apiData_); - if ( data->port == NULL ) return; - jack_port_unregister( data->client, data->port ); - data->port = NULL; + data->delayedDeletePort(); +} + +void MidiOutJack:: setClientName( const std::string& ) +{ + error(RTMIDI_ERROR(gettext_noopt("Setting the client name is not supported by JACK."), + Error::WARNING )); +} + +void MidiOutJack :: setPortName( const std::string &portName ) +{ + JackMidiData *data = static_cast (apiData_); + data->rename(portName); } -void MidiOutJack :: sendMessage( std::vector *message ) +void MidiOutJack :: sendMessage( const unsigned char *message, size_t size ) { - int nBytes = message->size(); + int nBytes = size; JackMidiData *data = static_cast (apiData_); // Write full message to buffer - jack_ringbuffer_write( data->buffMessage, ( const char * ) &( *message )[0], - message->size() ); + jack_ringbuffer_write( data->buffMessage, ( const char * ) message, + nBytes ); jack_ringbuffer_write( data->buffSize, ( char * ) &nBytes, sizeof( nBytes ) ); } - +#undef RTMIDI_CLASSNAME +RTMIDI_NAMESPACE_END #endif // __UNIX_JACK__ + diff --git a/RtMidi.h b/RtMidi.h index 99dc38c1..51f9a3d8 100644 --- a/RtMidi.h +++ b/RtMidi.h @@ -1,69 +1,194 @@ -/**********************************************************************/ +/********************* -*- C++ -*- ****************************************/ /*! \class RtMidi - \brief An abstract base class for realtime MIDI input/output. - - This class implements some common functionality for the realtime - MIDI input/output subclasses RtMidiIn and RtMidiOut. - - RtMidi WWW site: http://music.mcgill.ca/~gary/rtmidi/ - - RtMidi: realtime MIDI i/o C++ classes - Copyright (c) 2003-2014 Gary P. Scavone - - Permission is hereby granted, free of charge, to any person - obtaining a copy of this software and associated documentation files - (the "Software"), to deal in the Software without restriction, - including without limitation the rights to use, copy, modify, merge, - publish, distribute, sublicense, and/or sell copies of the Software, - and to permit persons to whom the Software is furnished to do so, - subject to the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - Any person wishing to distribute modifications to the Software is - asked to send the modifications to the original developer so that - they can be incorporated into the canonical version. This is, - however, not a binding provision of this license. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR - ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF - CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + \brief An abstract base class for realtime MIDI input/output. + + This class implements some common functionality for the realtime + MIDI input/output subclasses RtMidiIn and RtMidiOut. + + RtMidi WWW site: http://music.mcgill.ca/~gary/rtmidi/ + + RtMidi: realtime MIDI i/o C++ classes + Copyright (c) 2003-2017 Gary P. Scavone + Forked by Tobias Schlemmer, 2014-2018. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation files + (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, + publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, + subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + Any person wishing to distribute modifications to the Software is + asked to send the modifications to the original developer so that + they can be incorporated into the canonical version. This is, + however, not a binding provision of this license. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR + ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**********************************************************************/ /*! \file RtMidi.h - */ +*/ #ifndef RTMIDI_H #define RTMIDI_H -#define RTMIDI_VERSION "2.1.0" +#define RTMIDI_VERSION "4.0.0" + +#ifdef RTMIDI_NO_WARN_DEPRECATED +#define RTMIDI_DEPRECATED(func,message) func +#else +#ifdef __GNUC__ +#define RTMIDI_DEPRECATED(func,message) func __attribute__ ((deprecated(message))) +#elif defined(_MSC_VER) +#define RTMIDI_DEPRECATED(func,message) __declspec(deprecated(message)) func +#else +#pragma message("WARNING: You need to implement the macro RTMIDI_DEPRECATED for this compiler if this code doesn't compile") +#define RTMIDI_DEPRECATED(func,message) func [[deprecated(message)]] +#endif +#endif + +#define rtmidiUnused(x) do { (void)x; } while (0) + +// Check for C++11 support +#if defined(_MSC_VER) && _MSC_VER >= 1800 +// At least Visual Studio 2013 +#define RTMIDI_SUPPORTS_CPP11 1 +#elif __cplusplus >= 201103L +#define RTMIDI_SUPPORTS_CPP11 1 +#else +#define RTMIDI_SUPPORTS_CPP11 0 +#endif + +#if defined _WIN32 || defined __CYGWIN__ + #define RTMIDI_DLL_PUBLIC +#else + #if __GNUC__ >= 4 + #define RTMIDI_DLL_PUBLIC __attribute__( (visibility( "default" )) ) + #else + #define RTMIDI_DLL_PUBLIC + #endif +#endif + #include #include #include #include +#include +#include +#include +// the following are used in the error constructor +#include +#include +#include + +#ifdef RTMIDI_GETTEXT +#include "libintl.h" +#endif +#define gettext_noopt(str) (str) + +#define RTMIDI_NAMESPACE_START namespace rtmidi { +#define RTMIDI_NAMESPACE_END } + +RTMIDI_NAMESPACE_START + +#ifdef RTMIDI_GETTEXT +const char * rtmidi_gettext(const char * s); +void init_rtmidi_gettext(); +#else +#define rtmidi_gettext(arg) (arg) +#endif + +//! MIDI API specifier arguments. +enum ApiType { + UNSPECIFIED, /*!< Search for a working compiled API. */ + MACOSX_CORE, /*!< Macintosh OS-X Core Midi API. */ + LINUX_ALSA, /*!< The Advanced Linux Sound Architecture API. */ + UNIX_JACK, /*!< The JACK Low-Latency MIDI Server API. */ + WINDOWS_MM, /*!< The Microsoft Multimedia MIDI API. */ + WINDOWS_KS, /*!< The Microsoft Kernel Streaming MIDI API. */ + DUMMY, /*!< A compilable but non-functional API. */ + ALL_API /*!< Use all available APIs for port selection. */ +}; + +//! Return the name on a MIDI API +inline std::string getApiName(ApiType type) { + switch (type) { + case UNSPECIFIED: return rtmidi_gettext("Automatic selection"); + case MACOSX_CORE: return rtmidi_gettext("Core MIDI"); + case LINUX_ALSA: return rtmidi_gettext("ALSA"); + case UNIX_JACK: return rtmidi_gettext("JACK"); + case WINDOWS_MM: return rtmidi_gettext("Windows Multimedia"); + case WINDOWS_KS: return rtmidi_gettext("DirectX/Kernel Streaming"); + case DUMMY: return rtmidi_gettext("NULL device"); + case ALL_API: return rtmidi_gettext("All available MIDI systems"); + } + return ""; +} + +//! C++ style user callback interface. +/*! + This interface class can be used to implement type safe MIDI callbacks. + Every time a MIDI message is received the function \ref MidiInterface::rtmidi_midi_in of the + currently set callback object is called. +*/ +struct MidiInterface { + //! Virtual destructor to avoid unexpected behaviour. + virtual ~MidiInterface() {} + + //! The MIDI callback function. + /*! This function is called whenever a MIDI packet is received by a + MIDI backend that uses the corresponding callback object. + \param timestamp the timestamp when the MIDI message has been received + \param message the message itself. + */ + virtual void rtmidi_midi_in(double timestamp, std::vector &message) = 0; + + //! Delete the object if necessary. + /*! This function allows the user to delete the Midi callback object, + when MIDI backend drops its reference to it. By default it does nothing. + But, callback objects are owned by the MIDI backend. These must be deleted + after the reference to them has been dropped. + + \sa CompatibilityMidiInterface + */ + virtual void delete_me() {} +}; /************************************************************************/ -/*! \class RtMidiError - \brief Exception handling class for RtMidi. +/*! \class Error + \brief Exception handling class for RtMidi. - The RtMidiError class is quite simple but it does allow errors to be - "caught" by RtMidiError::Type. See the RtMidi documentation to know - which methods can throw an RtMidiError. + The Error class is quite simple but it does allow errors to be + "caught" by Error::Type. See the RtMidi documentation to know + which methods can throw an Error. */ /************************************************************************/ -class RtMidiError : public std::exception +#define RTMIDI_ERROR(message, type) \ + rtmidi::Error(message, type, \ + RTMIDI_CLASSNAME, __FUNCTION__, \ + __FILE__, __LINE__) +#define RTMIDI_ERROR1(message, type, arg1) \ + rtmidi::Error(message, type, \ + RTMIDI_CLASSNAME, __FUNCTION__, \ + __FILE__, __LINE__, arg1) +class RTMIDI_DLL_PUBLIC Error : public std::exception { - public: - //! Defined RtMidiError types. +public: + //! Defined Error types. enum Type { WARNING, /*!< A non-critical error. */ DEBUG_WARNING, /*!< A non-critical error which might be useful for debugging. */ @@ -79,55 +204,305 @@ class RtMidiError : public std::exception }; //! The constructor. - RtMidiError( const std::string& message, Type type = RtMidiError::UNSPECIFIED ) throw() : message_(message), type_(type) {} - + Error( const char * message, + Type type, + const char * class_name, + const char * function_name, + const char * file_name, + int line_number, ...) throw(); + //! The destructor. - virtual ~RtMidiError( void ) throw() {} + virtual ~Error( void ) throw() {} //! Prints thrown error message to stderr. - virtual void printMessage( void ) const throw() { std::cerr << '\n' << message_ << "\n\n"; } + virtual void printMessage( std::ostream &s = std::cerr ) const throw() { + s << std::endl + << file << ":" << line << ": in function " + << classname << "::" << function << std::endl + << message_ << std::endl << std::endl; + } //! Returns the thrown error message type. virtual const Type& getType(void) const throw() { return type_; } //! Returns the thrown error message string. - virtual const std::string& getMessage(void) const throw() { return message_; } + virtual const std::string &getMessage(void) const throw() { return message_; } //! Returns the thrown error message as a c-style string. virtual const char* what( void ) const throw() { return message_.c_str(); } - protected: +protected: + const char * classname; + const char * function; + const char * file; + int line; std::string message_; Type type_; }; -//! RtMidi error callback function prototype. -/*! - \param type Type of error. - \param errorText Error description. - Note that class behaviour is undefined after a critical error (not - a warning) is reported. - */ -typedef void (*RtMidiErrorCallback)( RtMidiError::Type type, const std::string &errorText ); +struct ErrorInterface { + virtual ~ErrorInterface() {} + virtual void rtmidi_error (Error e) = 0; + virtual void delete_me() {}; +}; + +#if !RTMIDI_SUPPORTS_CPP11 +class PortDescriptor; + +template +class Pointer { +public: + typedef T datatype; +protected: + struct countPointer { + int count; + datatype * descriptor; + }; +public: + Pointer():ptr(0) {} + Pointer(datatype * p):ptr(new countPointer) { + ptr->count = 1; + ptr->descriptor = p; + } + Pointer(const Pointer & other): + ptr(other.ptr) { + if (ptr) + ptr->count++; + } + Pointer(const Pointer && other): + ptr(other.ptr) { + } + + ~Pointer() { + if (!ptr) return; + if (!(--(ptr->count))) { + delete ptr->descriptor; + delete ptr; + } + } + + datatype * operator -> () { + if (!ptr) return 0; + // this should throw an exception + + return ptr->descriptor; + } + + datatype & operator * () { + if (!ptr || !ptr->descriptor) { + throw std::invalid_argument("rtmidi::Pointer: trying to dereference a NULL pointer."); + } + else return (*ptr->descriptor); + } + + const datatype & operator * () const { + if (!ptr || !ptr->descriptor) { + throw std::invalid_argument("rtmidi::Pointer: trying to dereference a NULL pointer."); + } + else return (*ptr->descriptor); + } + + bool operator ! () { + return (!ptr || !ptr->descriptor); + } + + operator bool () { + return (ptr && ptr->descriptor); + } + + Pointer & operator = (const Pointer & other) { + if (ptr) { + if (!(--ptr->count)) { + delete ptr->descriptor; + delete ptr; + } + } + if ((ptr = other.ptr)) + ptr->count++; + return *this; + } +protected: + countPointer * ptr; +}; + +template +bool operator==(const Pointer& lhs, const Pointer& rhs) { + return (&(*lhs)) == (&(*rhs)); +} + +template +bool operator!=(const Pointer& lhs, const Pointer& rhs) { + return (&(*lhs)) != (&(*rhs)); +} + +#else +template +using Pointer = std::shared_ptr; +#endif class MidiApi; +class MidiInApi; +class MidiOutApi; +typedef Pointer MidiApiPtr; +typedef std::list MidiApiList; + +class PortDescriptor { +public: + //! Flags for formatting a string description of the port. + /*! These flags just mark the requirements that the string + should fulfil. An API may return the same string for + different requirements e.g. the same short and long + name. */ + enum NamingType { + SHORT_NAME =0, /*!< A short human readable name + depending on the API + e.g. “Ensoniq AudioPCI” */ + LONG_NAME, /*!< A complete human readable + name depending on the API + e.g. "Ensoniq AudioPCI: ES1371" */ + SESSION_PATH, /*!< A unique description that can + be used to identify the port + during runtime. It may be a + cryptic string. */ + STORAGE_PATH, /*!< A unique description that is + optimised for storage in + configuration files. This is a + more textual representation that + is more robust to small changes in + the surrounding environment than + \ref SESSION_PATH */ + NAMING_MASK = 0x0F, /*!< part of the flags + that is concerned with + naming. + */ + UNIQUE_PORT_NAME = 0x10, /*!< Make all names uniqe. This + is usually done by adding + numbers to the end of the + string \note: use #undef UNIQUE_PORT_NAME + on windows in case of any errors */ + INCLUDE_API = 0x20 /*!< Add a string describing the + API at the beginning of the + string. */ + }; -class RtMidi -{ - public: - - //! MIDI API specifier arguments. - enum Api { - UNSPECIFIED, /*!< Search for a working compiled API. */ - MACOSX_CORE, /*!< Macintosh OS-X Core Midi API. */ - LINUX_ALSA, /*!< The Advanced Linux Sound Architecture API. */ - UNIX_JACK, /*!< The JACK Low-Latency MIDI Server API. */ - WINDOWS_MM, /*!< The Microsoft Multimedia MIDI API. */ - WINDOWS_KS, /*!< The Microsoft Kernel Streaming MIDI API. */ - RTMIDI_DUMMY /*!< A compilable but non-functional API. */ + //! Flags describing the capabilities of a given port. + enum PortCapabilities { + INPUT = 1, /*!< Ports that can be read from. */ + OUTPUT = 2, /*!< Ports that can be written to. */ + INOUTPUT = 3, /*!< Ports that allow reading and writing (INPUT | OUTPUT) */ + UNLIMITED = 0x10 /*!< Some APIs can filter out certain ports which they consider + not to be useful. This flags supresses this behaviour and + selects all ports that are useable. */ }; + //! Default constructor. + /*! + * Derived classes should have a constructor. + */ + PortDescriptor() {}; + + //! A virtual destructor + /*! As we might have to destruct the object from the application code + * each port id must have a virtual destructor. + */ + virtual ~PortDescriptor() {}; + + //! Get the MIDI input api for the current port. + /*! This is the only information RtMidi needs to know: Which + * API should handle this object. This can be used to get + * an API which can send data to the given port. + * + * \param queueSizeLimit The limit of the midi queue. This parameter is handled by + * the constructor of the backend API. + * + * \return API that can use this object to connect to an input port or 0 + * if no input API can be created. + */ + virtual MidiInApi * getInputApi(unsigned int queueSizeLimit = 100) const = 0; + + //! Get the MIDI output api for the current port. + /*! This is the only information RtMidi needs to know: Which + * API should handle this object. This can be used to get + * an API which can receive data from the given port. + * + * \return API that can use this object to connect to an output port. + */ + virtual MidiOutApi * getOutputApi() const = 0; + + //! Return the port name + /*! + * \param flags A description of the requirements of the returned name. + * \return A name that is formatted according to \ref flags. + * \sa NamingTypes + */ + virtual std::string getName(int flags = SHORT_NAME | UNIQUE_PORT_NAME) = 0; + + //! Get capabilities + /*! \return a capabilities flag describing the capabilities of the port. + * \sa PortCapabilities + */ + virtual int getCapabilities() const = 0; +}; + +//! A list of port descriptors. +/*! Port descriptors are stored as shared pointers. This avoids + unnecessary duplication of the data structure and handles automatic + deletion if all references have been removed. */ +typedef Pointer PortPointer; +typedef std::list > PortList; + +/* A deprecated type. See below for the documentation. We + split the definiton into several pieces to work around some + intended warnings. */ +typedef void (*ErrorCallback_t)( Error::Type type, const std::string &errorText, void * userdata ); +//! RtMidi error callback function prototype. +/*! + \param type Type of error. + \param errorText Error description. + + Note that class behaviour is undefined after a critical error (not + a warning) is reported. + \sa ErrorInterface + \deprecated +*/ +RTMIDI_DEPRECATED(typedef ErrorCallback_t ErrorCallback,"RtMidi now provides a class MidiInterface for error callbacks"); + +/* A deprecated type. See below for the documentation. We + split the definiton into several pieces to work around some + intended warnings. */ +#define ErrorCallback ErrorCallback_t + +typedef void (*MidiCallback_t)( double timeStamp, std::vector *message, void *userData); +//! C style user callback function type definition. +/*! + This interface type has been replaced by a MidiInterface class. + + \param timeStamp timestamp indicating when the event has been received + \param message a pointer to the binary MIDI message + \param userData a pointer that can be set using setUserdata + \sa MidiIn + \sa MidiInApi + \sa MidiInterface + \deprecated +*/ +RTMIDI_DEPRECATED(typedef MidiCallback_t MidiCallback,"RtMidi now provides a class MidiInterface for MIDI callbacks"); +#define MidiCallback MidiCallback_t + + +/*! \class Midi + \brief A global class that implements basic backend API handling. + + This class enhances \ref MidiApi by some functionality to handle + backend API objects. It serves as base class for the public RtMidi + API. + + by Gary P. Scavone, 2003-2014. +*/ +/**********************************************************************/ +#define RTMIDI_CLASSNAME "Midi" +class RTMIDI_DLL_PUBLIC Midi { +public: //! A static function to determine the current RtMidi version. static std::string getVersion( void ) throw(); @@ -136,80 +511,212 @@ class RtMidi The values returned in the std::vector can be compared against the enumerated list values. Note that there can be more than one API compiled for certain operating systems. + + \param apis A vector apis must be provided for the + return value. All data in this vector will be + deleted prior to filling in the API data. + + \param preferSystem An opitonal boolean parameter + may be provided that tells wheter system or software + APIs shall be prefered. Passing \c true will prefer OS provided APIs */ - static void getCompiledApi( std::vector &apis ) throw(); + static void getCompiledApi( std::vector &apis, bool preferSystem = true ) throw(); - //! Pure virtual openPort() function. - virtual void openPort( unsigned int portNumber = 0, const std::string portName = std::string( "RtMidi" ) ) = 0; + //! A static function to determine the available compiled MIDI APIs. + /*! + The values returned in the std::vector can be compared against + the enumerated list values. Note that there can be more than one + API compiled for certain operating systems. + */ + static std::vector getCompiledApi( ) throw(); - //! Pure virtual openVirtualPort() function. - virtual void openVirtualPort( const std::string portName = std::string( "RtMidi" ) ) = 0; + //! Returns the MIDI API specifier for the current instance of rtmidi::MidiIn. + ApiType getCurrentApi( void ) throw(); - //! Pure virtual getPortCount() function. - virtual unsigned int getPortCount() = 0; - //! Pure virtual getPortName() function. - virtual std::string getPortName( unsigned int portNumber = 0 ) = 0; + //! Pure virtual function to return a port descirptor if the port is open + Pointer getDescriptor(bool local=false); - //! Pure virtual closePort() function. - virtual void closePort( void ) = 0; + //! Return a list of all available ports of the current API. + /*! + \param capabilities an optional parameter that + describes which capabilities the returned devices + must support. The returned devices may have + additional capabilities to those which have been + requested, but not less. + + \return This function returns a list of port descriptors. + + \note Each API will request additonal + capabilites. An output API will set always add \ref + PortDescriptor::OUTPUT to the mask while an input + device will always add \ref PortDescriptor::OUTPUT. + + \note An input API may but need not necessarily + report output devices which cannot be used as input + if \ref PortDescriptor::OUTPUT is passed as \ref + capabilities parameter. + */ + PortList getPortList(int capabilities = 0); + + //! Close an open MIDI connection (if one exists). + void closePort( void ); + + void setClientName( const std::string &clientName ); + void setPortName( const std::string &portName ); //! Returns true if a port is open and false if not. - virtual bool isPortOpen( void ) const = 0; + /*! + Note that this only applies to connections made with the openPort() + function, not to virtual ports. - //! Set an error callback function to be invoked when an error has occured. + \retval true if a port is open and + \retval false if the port is not open (e.g. not opend or closed). + */ + bool isPortOpen( void ) const; + + //! Pure virtual function to set an error callback function to be invoked when an error has occured. /*! The callback function will be called whenever an error has occured. It is best to set the error callback function before opening a port. */ - virtual void setErrorCallback( RtMidiErrorCallback errorCallback = NULL ) = 0; + void setErrorCallback( ErrorInterface * callback); + + //! A basic error reporting function for RtMidi classes. + void error( Error e ); + + enum Api_t { + UNSPECIFIED = rtmidi::UNSPECIFIED, + MACOSX_CORE = rtmidi::MACOSX_CORE, + LINUX_ALSA = rtmidi::LINUX_ALSA, + UNIX_JACK = rtmidi::UNIX_JACK, + WINDOWS_MM = rtmidi::WINDOWS_MM, + RTMIDI_DUMMY = rtmidi::DUMMY + }; + + /* old functions */ + RTMIDI_DEPRECATED(typedef Api_t Api, + "enum RtMidi::Api has been replaced by enum rtmidi::ApiType"); +#define Api Api_t + RTMIDI_DEPRECATED(static void getCompiledApi( std::vector &apis, bool + preferSystem + = true ) throw(), "enum RtMidi::Api has been replaced by enum rtmidi::ApiType" ); + //! Compatibilty function for older code + virtual + RTMIDI_DEPRECATED(void openVirtualPort( const std::string &portName + = std::string( "RtMidi virtual port" ) ), + "For better usability you should call this function from a derived class") = 0; + + //! Pure virtual function to open a MIDI connection given by enumeration number. + /*! \param portNumber An optional port number greater than 0 + can be specified. Otherwise, the default or first port + found is opened. + + \param portName An optional name for the applicaction port + that will be generated to connect to portId can be + specified. + + \deprecated + */ + RTMIDI_DEPRECATED(void openPort( unsigned int portNumber = 0, + const std::string &portName = std::string( "RtMidi" ) + ),"Port numbers are unreliable. Use port descriptors instead (see examples for a demonstration)"); + + //! Pure virtual to return the number of available MIDI ports of the current API. + /*! + \return This function returns the number of MIDI ports of + the selected API. + + \note Only ports are counted that can be used with the + current API so an input API does ignore all output devices + and vice versa. + + \sa getPortName + \deprecated + */ + RTMIDI_DEPRECATED(unsigned int getPortCount(),"Port numbers are unreliable. Use port descriptors instead (see examples for a demonstration)"); + + //! Pure virtual function to return a string identifier for the specified MIDI port number. + /*! + \param portNumber Number of the device to be referred to. + \return The name of the port with the given Id is returned. + \retval An empty string is returned if an invalid port specifier is provided. - protected: + \note Only ports are counted that can be used with the + current API so an input API does ignore all output devices + and vice versa. - RtMidi(); - virtual ~RtMidi(); + \sa getPortCount() + \deprecated + */ + RTMIDI_DEPRECATED(std::string getPortName( unsigned int portNumber = 0 ),"Port numbers are unreliable. Use port descriptors instead (see examples for a demonstration)"); + //! Pure virtual function to set an error callback function to be invoked when an error has occured. + /*! + The callback function will be called whenever an error has occured. It is best + to set the error callback function before opening a port. + */ + RTMIDI_DEPRECATED(void setErrorCallback( ErrorCallback errorCallback = NULL, void * userData = 0 ), "setErrorCallback now expects an object of type ErrorInterface"); + + +protected: MidiApi *rtapi_; + MidiApiList * list; + bool preferSystem; + std::string clientName; + + Midi(MidiApiList * l, + bool pfsystem, + const std::string &name); + + virtual ~Midi(); }; +inline RTMIDI_DEPRECATED(std::string getApiName(Midi::Api type),"Use rtmidi::ApiType instead of RtMidi::Api"); +inline std::string getApiName(Midi::Api type) +{ + return getApiName((ApiType)type); +} + +#undef RTMIDI_CLASSNAME + /**********************************************************************/ -/*! \class RtMidiIn - \brief A realtime MIDI input class. - - This class provides a common, platform-independent API for - realtime MIDI input. It allows access to a single MIDI input - port. Incoming MIDI messages are either saved to a queue for - retrieval using the getMessage() function or immediately passed to - a user-specified callback function. Create multiple instances of - this class to connect to more than one MIDI device at the same - time. With the OS-X, Linux ALSA, and JACK MIDI APIs, it is also - possible to open a virtual input port to which other MIDI software - clients can connect. - - by Gary P. Scavone, 2003-2014. +/*! \class MidiIn + \brief A realtime MIDI input class. + + This class provides a common, platform-independent API for + realtime MIDI input. It allows access to a single MIDI input + port. Incoming MIDI messages are either saved to a queue for + retrieval using the getMessage() function or immediately passed to + a user-specified callback function. Create multiple instances of + this class to connect to more than one MIDI device at the same + time. With the OS-X, Linux ALSA, and JACK MIDI APIs, it is also + possible to open a virtual input port to which other MIDI software + clients can connect. + + by Gary P. Scavone, 2003-2017. */ /**********************************************************************/ // **************************************************************** // // -// RtMidiIn and RtMidiOut class declarations. +// MidiIn and MidiOut class declarations. // -// RtMidiIn / RtMidiOut are "controllers" used to select an available +// MidiIn / MidiOut are "controllers" used to select an available // MIDI input or output interface. They present common APIs for the // user to call but all functionality is implemented by the classes -// MidiInApi, MidiOutApi and their subclasses. RtMidiIn and RtMidiOut +// MidiInApi, MidiOutApi and their subclasses. MidiIn and MidiOut // each create an instance of a MidiInApi or MidiOutApi subclass based // on the user's API choice. If no choice is made, they attempt to // make a "logical" API selection. // // **************************************************************** // -class RtMidiIn : public RtMidi +#define RTMIDI_CLASSNAME "MidiIn" +class RTMIDI_DLL_PUBLIC MidiIn : public Midi { - public: +public: - //! User callback function type definition. - typedef void (*RtMidiCallback)( double timeStamp, std::vector *message, void *userData); //! Default constructor that allows an optional api, client name and queue size. /*! @@ -220,44 +727,89 @@ class RtMidiIn : public RtMidi incoming messages will be ignored. If no API argument is specified and multiple API support has been - compiled, the default order of use is JACK, ALSA (Linux) and JACK, - CORE (OS-X). + compiled, the default order of use is JACK, ALSA (Linux) and CORE, + JACK (OS-X). \param api An optional API id can be specified. - \param clientName An optional client name can be specified. This - will be used to group the ports that are created - by the application. + \param clientName An optional Client name can be specified. This + will be used to group the ports that are created + by the application. \param queueSizeLimit An optional size of the MIDI input queue can be specified. + + \param pfsystem An optional boolean parameter can be + provided to indicate the API preferences of the user + code. If RtMidi is requested to autoselect a backend + this parameter tells which backend should be tried + first. If it is \c true the backend will prefer OS + provieded APIs (WinMM, ALSA, Core MIDI) over other + APIs (JACK). If \c false, the order will be vice + versa. */ - RtMidiIn( RtMidi::Api api=UNSPECIFIED, - const std::string clientName = std::string( "RtMidi Input Client"), - unsigned int queueSizeLimit = 100 ); + MidiIn( ApiType api=rtmidi::UNSPECIFIED, + const std::string &clientName = std::string( "RtMidi Input Client"), + unsigned int queueSizeLimit = 100, + bool pfsystem = true); //! If a MIDI connection is still open, it will be closed by the destructor. - ~RtMidiIn ( void ) throw(); + ~MidiIn ( void ) throw(); - //! Returns the MIDI API specifier for the current instance of RtMidiIn. - RtMidi::Api getCurrentApi( void ) throw(); + using Midi::openPort; - //! Open a MIDI input connection given by enumeration number. + //! Open a MIDI connection given by a port descriptor. /*! - \param portNumber An optional port number greater than 0 can be specified. - Otherwise, the default or first port found is opened. - \param portName An optional name for the application port that is used to connect to portId can be specified. + \param port A port descriptor of the port must be specified. + \param portName An optional name for the applicaction port that is used to connect to portId can be specified. */ - void openPort( unsigned int portNumber = 0, const std::string portName = std::string( "RtMidi Input" ) ); + void openPort( const PortDescriptor & port, + const std::string &portName = std::string( "RtMidi" ) ); + - //! Create a virtual input port, with optional name, to allow software connections (OS X, JACK and ALSA only). + //! Open a MIDI connection given by a port descriptor pointer. /*! - This function creates a virtual MIDI input port to which other - software applications can connect. This type of functionality + \param port A pointer to a port descriptor of the port must be specified. + \param portName An optional name for the applicaction port that is used to connect to portId can be specified. + \sa openPort(const PortDescriptor &,const std::string &); + */ + void openPort( Pointer p, + const std::string &portName = std::string( "RtMidi" ) ); + + //! Function to create a virtual port, with optional name. + /*! + This function creates a virtual MIDI port to which other + software applications can connect. This type of functionality is currently only supported by the Macintosh OS-X, any JACK, and Linux ALSA APIs (the function returns an error for the other APIs). \param portName An optional name for the application port that is - used to connect to portId can be specified. + used to connect to portId can be specified. + */ + void openVirtualPort( const std::string &portName = std::string( "RtMidi virtual input port" ) ); + + //! Return a list of all available ports of the current API. + /*! + \param capabilities an optional parameter that + describes which capabilities the returned devices + must support. The returned devices may have + additional capabilities to those which have been + requested, but not less. + + \return This function returns a list of port descriptors. + + \note Each API will request additonal + capabilites. An output API will set always add \ref + PortDescriptor::OUTPUT to the mask while an input + device will always add \ref PortDescriptor::OUTPUT. + + \note An input API may but need not necessarily + report output devices which cannot be used as input + if \ref PortDescriptor::OUTPUT is passed as \ref + capabilities parameter. */ - void openVirtualPort( const std::string portName = std::string( "RtMidi Input" ) ); + PortList getPortList(int capabilities = PortDescriptor::INPUT) { + return Midi::getPortList(capabilities); + } + + //! Set a callback function to be invoked for incoming MIDI messages. /*! @@ -267,10 +819,10 @@ class RtMidiIn : public RtMidi leaving some messages in the queue. \param callback A callback function must be given. - \param userData Optionally, a pointer to additional data can be - passed to the callback function whenever it is called. + \param userData Opitionally, a pointer to additional data can be + passed to the callback function whenever it is called. */ - void setCallback( RtMidiCallback callback, void *userData = 0 ); + void setCallback( MidiInterface * callback ); //! Cancel use of the current callback function (if one exists). /*! @@ -279,25 +831,6 @@ class RtMidiIn : public RtMidi */ void cancelCallback(); - //! Close an open MIDI connection (if one exists). - void closePort( void ); - - //! Returns true if a port is open and false if not. - virtual bool isPortOpen() const; - - //! Return the number of available MIDI input ports. - /*! - \return This function returns the number of MIDI ports of the selected API. - */ - unsigned int getPortCount(); - - //! Return a string identifier for the specified MIDI input port number. - /*! - \return The name of the port with the given Id is returned. - \retval An empty string is returned if an invalid port specifier is provided. - */ - std::string getPortName( unsigned int portNumber = 0 ); - //! Specify whether certain MIDI message types should be queued or ignored during input. /*! By default, MIDI timing and active sensing messages are ignored @@ -306,7 +839,9 @@ class RtMidiIn : public RtMidi values of "true" imply that the respective message type will be ignored. */ - void ignoreTypes( bool midiSysex = true, bool midiTime = true, bool midiSense = true ); + void ignoreTypes( bool midiSysex = true, + bool midiTime = true, + bool midiSense = true ); //! Fill the user-provided vector with the data bytes for the next available MIDI message in the input queue and return the event delta-time in seconds. /*! @@ -316,109 +851,187 @@ class RtMidiIn : public RtMidi message retrieval or an input connection was not previously established. */ - double getMessage( std::vector *message ); + double getMessage( std::vector &message ); - //! Set an error callback function to be invoked when an error has occured. + + //! Set a callback function to be invoked for incoming MIDI messages. /*! - The callback function will be called whenever an error has occured. It is best - to set the error callback function before opening a port. + The callback function will be called whenever an incoming MIDI + message is received. While not absolutely necessary, it is best + to set the callback function before opening a MIDI port to avoid + leaving some messages in the queue. + + \param callback A callback function must be given. + \param userData Opitionally, a pointer to additional data can be + passed to the callback function whenever it is called. */ - virtual void setErrorCallback( RtMidiErrorCallback errorCallback = NULL ); + RTMIDI_DEPRECATED(void setCallback( MidiCallback callback, void *userData = 0 ), + "RtMidi now provides a type-safe MidiInterface class."); - protected: - void openMidiApi( RtMidi::Api api, const std::string clientName, unsigned int queueSizeLimit ); + //! Fill the user-provided vector with the data bytes for the next available MIDI message in the input queue and return the event delta-time in seconds. + /*! + This function returns immediately whether a new message is + available or not. A valid message is indicated by a non-zero + vector size. An exception is thrown if an error occurs during + message retrieval or an input connection was not previously + established. + + \deprecated + */ + RTMIDI_DEPRECATED(double getMessage( std::vector *message ), + "Please, use a C++ style reference to pass the message vector."); +protected: + static MidiApiList queryApis; + int queueSizeLimit; + void openMidiApi( ApiType api ); }; +#undef RTMIDI_CLASSNAME /**********************************************************************/ -/*! \class RtMidiOut - \brief A realtime MIDI output class. - - This class provides a common, platform-independent API for MIDI - output. It allows one to probe available MIDI output ports, to - connect to one such port, and to send MIDI bytes immediately over - the connection. Create multiple instances of this class to - connect to more than one MIDI device at the same time. With the - OS-X, Linux ALSA and JACK MIDI APIs, it is also possible to open a - virtual port to which other MIDI software clients can connect. - - by Gary P. Scavone, 2003-2014. +/*! \class MidiOut + \brief A realtime MIDI output class. + + This class provides a common, platform-independent API for MIDI + output. It allows one to probe available MIDI output ports, to + connect to one such port, and to send MIDI bytes immediately over + the connection. Create multiple instances of this class to + connect to more than one MIDI device at the same time. With the + OS-X, Linux ALSA and JACK MIDI APIs, it is also possible to open a + virtual port to which other MIDI software clients can connect. + + by Gary P. Scavone, 2003-2017. */ /**********************************************************************/ -class RtMidiOut : public RtMidi +#define RTMIDI_CLASSNAME "MidiOut" +class RTMIDI_DLL_PUBLIC MidiOut : public Midi { - public: +public: //! Default constructor that allows an optional client name. /*! An exception will be thrown if a MIDI system initialization error occurs. If no API argument is specified and multiple API support has been - compiled, the default order of use is JACK, ALSA (Linux) and JACK, - CORE (OS-X). + compiled, the default order of use is JACK, ALSA (Linux) and CORE, + JACK (OS-X). + + \param api An optional API id can be specified. + \param clientName An optional Client name can be specified. This + will be used to group the ports that are created + by the application. + \param queueSizeLimit An optional size of the MIDI input queue can be specified. + + \param pfsystem An optional boolean parameter can be + provided to indicate the API preferences of the user + code. If RtMidi is requested to autoselect a backend + this parameter tells which backend should be tried + first. If it is \c true the backend will prefer OS + provieded APIs (WinMM, ALSA, Core MIDI) over other + APIs (JACK). If \c false, the order will be vice + versa. */ - RtMidiOut( RtMidi::Api api=UNSPECIFIED, - const std::string clientName = std::string( "RtMidi Output Client") ); + MidiOut( ApiType api=rtmidi::UNSPECIFIED, + const std::string &clientName = std::string( "RtMidi Output Client"), + bool pfsystem = true); //! The destructor closes any open MIDI connections. - ~RtMidiOut( void ) throw(); + ~MidiOut( void ) throw(); - //! Returns the MIDI API specifier for the current instance of RtMidiOut. - RtMidi::Api getCurrentApi( void ) throw(); + using Midi::openPort; - //! Open a MIDI output connection. + //! Open a MIDI connection given by a port descriptor. + /*! + \param port A port descriptor of the port must be specified. + \param portName An optional name for the applicaction port that is used to connect to portId can be specified. + */ + void openPort( const PortDescriptor & port, + const std::string &portName = std::string( "RtMidi" ) ); + //! Open a MIDI connection given by a port descriptor pointer. /*! - An optional port number greater than 0 can be specified. - Otherwise, the default or first port found is opened. An - exception is thrown if an error occurs while attempting to make - the port connection. + \param port A pointer to a port descriptor of the port must be specified. + \param portName An optional name for the applicaction port that is used to connect to portId can be specified. + \sa openPort(const PortDescriptor &,const std::string &); */ - void openPort( unsigned int portNumber = 0, const std::string portName = std::string( "RtMidi Output" ) ); + void openPort( Pointer p, + const std::string &portName = std::string( "RtMidi" ) ); - //! Close an open MIDI connection (if one exists). - void closePort( void ); + //! Function to create a virtual port, with optional name. + /*! + This function creates a virtual MIDI port to which other + software applications can connect. This type of functionality + is currently only supported by the Macintosh OS-X, any JACK, + and Linux ALSA APIs (the function returns an error for the other APIs). - //! Returns true if a port is open and false if not. - virtual bool isPortOpen() const; + \param portName An optional name for the applicaction port that is + used to connect to portId can be specified. + */ + void openVirtualPort( const std::string &portName = std::string( "RtMidi virtual output port" ) ); - //! Create a virtual output port, with optional name, to allow software connections (OS X, JACK and ALSA only). + //! Return a list of all available ports of the current API. /*! - This function creates a virtual MIDI output port to which other - software applications can connect. This type of functionality - is currently only supported by the Macintosh OS-X, Linux ALSA - and JACK APIs (the function does nothing with the other APIs). - An exception is thrown if an error occurs while attempting to - create the virtual port. + \param capabilities an optional parameter that + describes which capabilities the returned devices + must support. The returned devices may have + additional capabilities to those which have been + requested, but not less. + + \return This function returns a list of port descriptors. + + \note Each API will request additonal + capabilites. An output API will set always add \ref + PortDescriptor::OUTPUT to the mask while an input + device will always add \ref PortDescriptor::OUTPUT. + + \note An input API may but need not necessarily + report output devices which cannot be used as input + if \ref PortDescriptor::OUTPUT is passed as \ref + capabilities parameter. */ - void openVirtualPort( const std::string portName = std::string( "RtMidi Output" ) ); + PortList getPortList(int capabilities = PortDescriptor::OUTPUT) { + return Midi::getPortList(capabilities); + } - //! Return the number of available MIDI output ports. - unsigned int getPortCount( void ); - - //! Return a string identifier for the specified MIDI port type and number. + //! Immediately send a single message out an open MIDI output port. /*! - An empty string is returned if an invalid port specifier is provided. + An exception is thrown if an error occurs during output or an + output connection was not previously established. + + \deprecated */ - std::string getPortName( unsigned int portNumber = 0 ); + RTMIDI_DEPRECATED(void sendMessage( const std::vector *message ), + "Please, use a C++ style reference to pass the message vector.") + { + sendMessage(*message); + } + //! Immediately send a single message out an open MIDI output port. /*! - An exception is thrown if an error occurs during output or an - output connection was not previously established. + An exception is thrown if an error occurs during output or an + output connection was not previously established. */ - void sendMessage( std::vector *message ); - //! Set an error callback function to be invoked when an error has occured. + void sendMessage(const std::vector &message ) { + sendMessage(message.data(), message.size()); + } + //! Immediately send a single message out an open MIDI output port. /*! - The callback function will be called whenever an error has occured. It is best - to set the error callback function before opening a port. + An exception is thrown if an error occurs during output or an + output connection was not previously established. + + \param message A pointer to the MIDI message as raw bytes + \param size Length of the MIDI message in bytes */ - virtual void setErrorCallback( RtMidiErrorCallback errorCallback = NULL ); + void sendMessage( const unsigned char *message, size_t size ); - protected: - void openMidiApi( RtMidi::Api api, const std::string clientName ); +protected: + static MidiApiList queryApis; + void openMidiApi( ApiType api ); + bool firstErrorOccurred_; }; +#undef RTMIDI_CLASSNAME // **************************************************************** // @@ -429,371 +1042,563 @@ class RtMidiOut : public RtMidi // OS-specific code necessary to fully implement the RtMidi API. // // Note that MidiInApi and MidiOutApi are abstract base classes and -// cannot be explicitly instantiated. RtMidiIn and RtMidiOut will +// cannot be explicitly instantiated. MidiIn and MidiOut will // create instances of a MidiInApi or MidiOutApi subclass. // // **************************************************************** // -class MidiApi +#define RTMIDI_CLASSNAME "MidiApi" +class RTMIDI_DLL_PUBLIC MidiApi { - public: +public: MidiApi(); virtual ~MidiApi(); - virtual RtMidi::Api getCurrentApi( void ) = 0; - virtual void openPort( unsigned int portNumber, const std::string portName ) = 0; - virtual void openVirtualPort( const std::string portName ) = 0; + + //! Return whether the API supports virtual ports + /*! + \retval true The funcion returns true if the API supports virtual ports. + \retval false The funcion returns false if the API doesn't support virtual ports. + \sa openVirtualPort + */ + virtual bool hasVirtualPorts() const = 0; + + //! Pure virtal function to create a virtual port, with optional name. + /*! + This function creates a virtual MIDI port to which other + software applications can connect. This type of functionality + is currently only supported by the Macintosh OS-X, any JACK, + and Linux ALSA APIs (the function returns an error for the other APIs). + + \param portName An optional name for the applicaction port that is + used to connect to portId can be specified. + + \sa hasVirtualPorts + */ + virtual void openVirtualPort( const std::string &portName = std::string( "RtMidi virtual port" ) ) = 0; + + //! Pure virtual function to open a MIDI connection given by enumeration number. + /*! \param portNumber An optional port number greater than 0 + can be specified. Otherwise, the default or first port + found is opened. + + \param portName An optional name for the applicaction port + that will be generated to connect to portId can be + specified. + */ + virtual void openPort( unsigned int portNumber = 0, const std::string &portName = std::string( "RtMidi" ) ) = 0; + + //! Pure virtual function to open a MIDI connection given by a port descriptor. + /*! + \param port A port descriptor of the port must be specified. + \param portName An optional name for the applicaction port that is used to connect to portId can be specified. + */ + virtual void openPort( const PortDescriptor & port, const std::string &portName = std::string( "RtMidi" ) ) = 0; + + //! Open a MIDI connection given by a port descriptor pointer. + /*! + \param port A pointer to a port descriptor of the port must be specified. + \param portName An optional name for the applicaction port that is used to connect to portId can be specified. + \sa openPort(const PortDescriptor &,const std::string &); + */ + void openPort( Pointer p, const std::string &portName = std::string( "RtMidi" ) ) { + if (!p) { + error(RTMIDI_ERROR( gettext_noopt("Passed NULL pointer."), + Error::INVALID_PARAMETER)); + return; + } + openPort(*p, portName); + } + + //! Pure virtual function to return a port descriptor if the port is open + /*! This function returns a port descriptor that can be used to open another port + either to the connected port or – if the backend supports it – the connecting port. + \param local The parameter local defines whether the function returns a descriptor to + the virtual port (true) or the remote port (false). The function returns 0 if the + port cannot be determined (e.g. if the port is not connected or the backend dosen't support it). + */ + virtual Pointer getDescriptor(bool local=false) = 0; + + //! Pure virtual function to return a list of all available ports of the current API. + /*! + \param capabilities an optional parameter that describes which + capabilities the device typu + + \return This function returns a list of port descriptors. + + \note An input API may but need not necessarily report + output devices which cannot be used as input if + \ref 0 is passed as \ref capabilities parameter. + \sa PortDescriptor::PortCapabilitiers + */ + virtual PortList getPortList(int capabilities = 0) = 0; + + //! Pure virtual to return the number of available MIDI ports of the current API. + /*! + \return This function returns the number of MIDI ports of + the selected API. + + \note Only ports are counted that can be used with the + current API so an input API does ignore all output devices + and vice versa. + + \sa getPortName + */ + virtual unsigned int getPortCount() = 0; + + //! Pure virtual function to return a string identifier for the specified MIDI port number. + /*! + \param portNumber Number of the device to be referred to. + \return The name of the port with the given Id is returned. + \retval An empty string is returned if an invalid port specifier is provided. + + \note Only ports are counted that can be used with the + current API so an input API does ignore all output devices + and vice versa. + + \sa getPortCount() + */ + virtual std::string getPortName( unsigned int portNumber = 0 ) = 0; + + //! Pure virtual function to close an open MIDI connection (if one exists). virtual void closePort( void ) = 0; + virtual void setClientName( const std::string &clientName ) = 0; + virtual void setPortName( const std::string &portName ) = 0; + + // ! A basic error reporting function for RtMidi classes. + // static void error( Error::Type type, std::string &errorString ); + + //! Pure virtual function to return whether a port is open or not. + /*! \retval true if a port is open and + \retval false if the port is not open (e.g. not opend or closed). + */ + bool isPortOpen() const { return connected_; } + - virtual unsigned int getPortCount( void ) = 0; - virtual std::string getPortName( unsigned int portNumber ) = 0; + //! Virtual function to set the error callback object + /*! + Everytime an error is detected or a warning is issued the function + \r ErrorInterface::rtmidi_error of the callback object is called with an error object + that describes the situation. + + \param callback An objact that provides an ErrorInterface. + */ + virtual void setErrorCallback(ErrorInterface * callback); - inline bool isPortOpen() const { return connected_; } - void setErrorCallback( RtMidiErrorCallback errorCallback ); + + //! Returns the MIDI API specifier for the current instance of RtMidiIn. + virtual ApiType getCurrentApi( void ) throw() = 0; //! A basic error reporting function for RtMidi classes. - void error( RtMidiError::Type type, std::string errorString ); + /*! This function hanles errors end warnings that + occur during runtime of RtMidi. If an error callback + has been set the function calls the callback and + returns quietly assuming the callback handled the + case correctly. + + Otherwise it depends on the type of the error. If it + is a warning, a message is displayed to + std::cerr. If it is an error the object is thrown as + an exception. + + \param e Error/Warning object describing the current + situation. + + \throw Error + */ + void error( Error e ); + + + //! Virtual function to set an error callback function to be invoked when an error has occured. + /*! + The callback function will be called whenever an error has occured. It is best + to set the error callback function before opening a port. + */ + RTMIDI_DEPRECATED(virtual void setErrorCallback( ErrorCallback errorCallback = NULL, void * userData = 0 ), "RtMidi now provides a typesafe ErrorInterface class"); protected: - virtual void initialize( const std::string& clientName ) = 0; + virtual void initialize( const std::string &clientName ) = 0; void *apiData_; bool connected_; + bool firstErrorOccurred_; std::string errorString_; - RtMidiErrorCallback errorCallback_; + ErrorInterface * errorCallback_; }; +#undef RTMIDI_CLASSNAME -class MidiInApi : public MidiApi +#define RTMIDI_CLASSNAME "MidiInApi" +class RTMIDI_DLL_PUBLIC MidiInApi : public MidiApi { - public: +public: MidiInApi( unsigned int queueSizeLimit ); virtual ~MidiInApi( void ); - void setCallback( RtMidiIn::RtMidiCallback callback, void *userData ); + void setCallback( MidiInterface * callback); void cancelCallback( void ); virtual void ignoreTypes( bool midiSysex, bool midiTime, bool midiSense ); - double getMessage( std::vector *message ); + double getMessage( std::vector &message ); // A MIDI structure used internally by the class to store incoming // messages. Each message represents one and only one MIDI message. - struct MidiMessage { - std::vector bytes; + struct MidiMessage { + std::vector bytes; + //! Time in seconds elapsed since the previous message double timeStamp; // Default constructor. - MidiMessage() - :bytes(0), timeStamp(0.0) {} + MidiMessage() + :bytes(0), timeStamp(0.0) {} }; struct MidiQueue { unsigned int front; unsigned int back; - unsigned int size; unsigned int ringSize; MidiMessage *ring; // Default constructor. - MidiQueue() - :front(0), back(0), size(0), ringSize(0) {} + MidiQueue() + :front(0), back(0), ringSize(0), ring(0) {} + bool push(const MidiMessage&); + bool pop(std::vector& message, double& timestamp); + unsigned int size(unsigned int *back=0, + unsigned int *front=0); }; - // The RtMidiInData structure is used to pass private class data to - // the MIDI input handling function or thread. - struct RtMidiInData { - MidiQueue queue; - MidiMessage message; - unsigned char ignoreFlags; - bool doInput; - bool firstMessage; - void *apiData; - bool usingCallback; - RtMidiIn::RtMidiCallback userCallback; - void *userData; - bool continueSysex; - // Default constructor. - RtMidiInData() - : ignoreFlags(7), doInput(false), firstMessage(true), - apiData(0), usingCallback(false), userCallback(0), userData(0), - continueSysex(false) {} - }; - protected: - RtMidiInData inputData_; + RTMIDI_DEPRECATED(void setCallback( MidiCallback callback, void *userData = 0 ), + "RtMidi now provides a type-safe MidiInterface class."); + RTMIDI_DEPRECATED(double getMessage( std::vector *message ), + "Please, use a C++ style reference to pass the message vector.") + { + if (!message) { + error( RTMIDI_ERROR(gettext_noopt("Passed NULL pointer."), + Error::WARNING )); + } + return getMessage(*message); + } + +protected: + // The RtMidiInData structure is used to pass private class data to + // the MIDI input handling function or thread. + MidiQueue queue; + MidiMessage message; + unsigned char ignoreFlags; + bool doInput; + bool firstMessage; + MidiInterface * userCallback; + bool continueSysex; + friend struct JackBackendCallbacks; }; +#undef RTMIDI_CLASSNAME -class MidiOutApi : public MidiApi +#define RTMIDI_CLASSNAME "MidiOutApi" +class RTMIDI_DLL_PUBLIC MidiOutApi : public MidiApi { - public: +public: MidiOutApi( void ); virtual ~MidiOutApi( void ); - virtual void sendMessage( std::vector *message ) = 0; + virtual void sendMessage( const unsigned char *message, size_t size ) = 0; + void sendMessage( const std::vector &message ) + { + if (message.empty()) { + error( RTMIDI_ERROR(gettext_noopt("No data in message argument."), + Error::WARNING)); + } + sendMessage(message.data(),message.size()); + } + RTMIDI_DEPRECATED(void sendMessage( const std::vector *message ), + "Please, use a C++ style reference to pass the message vector.") + { + if (!message) { + error( RTMIDI_ERROR(gettext_noopt("No data in message argument."), + Error::WARNING)); + } + sendMessage(*message); + } }; +#undef RTMIDI_CLASSNAME -// **************************************************************** // -// -// Inline RtMidiIn and RtMidiOut definitions. -// -// **************************************************************** // - -inline RtMidi::Api RtMidiIn :: getCurrentApi( void ) throw() { return rtapi_->getCurrentApi(); } -inline void RtMidiIn :: openPort( unsigned int portNumber, const std::string portName ) { rtapi_->openPort( portNumber, portName ); } -inline void RtMidiIn :: openVirtualPort( const std::string portName ) { rtapi_->openVirtualPort( portName ); } -inline void RtMidiIn :: closePort( void ) { rtapi_->closePort(); } -inline bool RtMidiIn :: isPortOpen() const { return rtapi_->isPortOpen(); } -inline void RtMidiIn :: setCallback( RtMidiCallback callback, void *userData ) { ((MidiInApi *)rtapi_)->setCallback( callback, userData ); } -inline void RtMidiIn :: cancelCallback( void ) { ((MidiInApi *)rtapi_)->cancelCallback(); } -inline unsigned int RtMidiIn :: getPortCount( void ) { return rtapi_->getPortCount(); } -inline std::string RtMidiIn :: getPortName( unsigned int portNumber ) { return rtapi_->getPortName( portNumber ); } -inline void RtMidiIn :: ignoreTypes( bool midiSysex, bool midiTime, bool midiSense ) { ((MidiInApi *)rtapi_)->ignoreTypes( midiSysex, midiTime, midiSense ); } -inline double RtMidiIn :: getMessage( std::vector *message ) { return ((MidiInApi *)rtapi_)->getMessage( message ); } -inline void RtMidiIn :: setErrorCallback( RtMidiErrorCallback errorCallback ) { rtapi_->setErrorCallback(errorCallback); } - -inline RtMidi::Api RtMidiOut :: getCurrentApi( void ) throw() { return rtapi_->getCurrentApi(); } -inline void RtMidiOut :: openPort( unsigned int portNumber, const std::string portName ) { rtapi_->openPort( portNumber, portName ); } -inline void RtMidiOut :: openVirtualPort( const std::string portName ) { rtapi_->openVirtualPort( portName ); } -inline void RtMidiOut :: closePort( void ) { rtapi_->closePort(); } -inline bool RtMidiOut :: isPortOpen() const { return rtapi_->isPortOpen(); } -inline unsigned int RtMidiOut :: getPortCount( void ) { return rtapi_->getPortCount(); } -inline std::string RtMidiOut :: getPortName( unsigned int portNumber ) { return rtapi_->getPortName( portNumber ); } -inline void RtMidiOut :: sendMessage( std::vector *message ) { ((MidiOutApi *)rtapi_)->sendMessage( message ); } -inline void RtMidiOut :: setErrorCallback( RtMidiErrorCallback errorCallback ) { rtapi_->setErrorCallback(errorCallback); } // **************************************************************** // // -// MidiInApi and MidiOutApi subclass prototypes. +// Inline rtmidi::Midi, rtmidi::MidiIn and rtmidid:MidiOut definitions. // // **************************************************************** // - -#if !defined(__LINUX_ALSA__) && !defined(__UNIX_JACK__) && !defined(__MACOSX_CORE__) && !defined(__WINDOWS_MM__) && !defined(__WINDOWS_KS__) - #define __RTMIDI_DUMMY__ -#endif - -#if defined(__MACOSX_CORE__) - -class MidiInCore: public MidiInApi +// rtmidi::Midi +#define RTMIDI_CLASSNAME "Midi" +inline std::vector Midi :: getCompiledApi( ) throw() { + std::vector apis; + getCompiledApi(apis); + return apis; +} +inline ApiType Midi :: getCurrentApi( void ) throw() { + if (rtapi_) return rtapi_->getCurrentApi(); + else return rtmidi::UNSPECIFIED; +} +inline Pointer Midi :: getDescriptor( bool local ) { + if (rtapi_) return rtapi_->getDescriptor(local); + return 0; +} +inline PortList Midi :: getPortList(int capabilities ) { + if (rtapi_) return rtapi_->getPortList(capabilities); + if (list && !list->empty()) { + PortList retval; + for (MidiApiList::iterator i = list->begin(); + i != list->end(); + ++i) { + PortList tmp = (*i)->getPortList(capabilities); + retval.splice(retval.end(), tmp); + } + return retval; + } + return PortList(); +} +inline void Midi :: closePort( void ) { + if (rtapi_) rtapi_->closePort(); +} +inline void Midi :: setClientName( const std::string &clientName ) { - public: - MidiInCore( const std::string clientName, unsigned int queueSizeLimit ); - ~MidiInCore( void ); - RtMidi::Api getCurrentApi( void ) { return RtMidi::MACOSX_CORE; }; - void openPort( unsigned int portNumber, const std::string portName ); - void openVirtualPort( const std::string portName ); - void closePort( void ); - unsigned int getPortCount( void ); - std::string getPortName( unsigned int portNumber ); - - protected: - void initialize( const std::string& clientName ); -}; - -class MidiOutCore: public MidiOutApi + if (rtapi_) rtapi_->setClientName(clientName); +} +inline void Midi :: setPortName( const std::string &portName ) { - public: - MidiOutCore( const std::string clientName ); - ~MidiOutCore( void ); - RtMidi::Api getCurrentApi( void ) { return RtMidi::MACOSX_CORE; }; - void openPort( unsigned int portNumber, const std::string portName ); - void openVirtualPort( const std::string portName ); - void closePort( void ); - unsigned int getPortCount( void ); - std::string getPortName( unsigned int portNumber ); - void sendMessage( std::vector *message ); - - protected: - void initialize( const std::string& clientName ); -}; - + if (rtapi_) rtapi_->setPortName(portName); +} +inline bool Midi :: isPortOpen( void ) const { + if (rtapi_) return rtapi_->isPortOpen(); + return false; +} +inline void Midi :: setErrorCallback( ErrorInterface * callback) { + if (rtapi_) rtapi_->setErrorCallback(callback); +} +inline void Midi :: getCompiledApi( std::vector &apis, bool + preferSystem ) throw() { + std::vector api2; + Midi::getCompiledApi(api2,preferSystem); + apis.reserve(api2.size()); + size_t s = api2.size(); + for (size_t i = 0; i < s; i++) { + apis.push_back((Api)api2[i]); + } +} +inline void Midi :: openPort( unsigned int portNumber, + const std::string &portName) { + if (rtapi_) rtapi_->openPort(portNumber,portName); +} +inline unsigned int Midi :: getPortCount() { + if (rtapi_) return rtapi_->getPortCount(); + return 0; +} +inline std::string Midi :: getPortName( unsigned int portNumber ) { + if (rtapi_) return rtapi_->getPortName(portNumber); + return ""; +} +inline void Midi :: setErrorCallback( ErrorCallback errorCallback , void * userData ) { +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" #endif - -#if defined(__UNIX_JACK__) - -class MidiInJack: public MidiInApi -{ - public: - MidiInJack( const std::string clientName, unsigned int queueSizeLimit ); - ~MidiInJack( void ); - RtMidi::Api getCurrentApi( void ) { return RtMidi::UNIX_JACK; }; - void openPort( unsigned int portNumber, const std::string portName ); - void openVirtualPort( const std::string portName ); - void closePort( void ); - unsigned int getPortCount( void ); - std::string getPortName( unsigned int portNumber ); - - protected: - std::string clientName; - - void connect( void ); - void initialize( const std::string& clientName ); -}; - -class MidiOutJack: public MidiOutApi -{ - public: - MidiOutJack( const std::string clientName ); - ~MidiOutJack( void ); - RtMidi::Api getCurrentApi( void ) { return RtMidi::UNIX_JACK; }; - void openPort( unsigned int portNumber, const std::string portName ); - void openVirtualPort( const std::string portName ); - void closePort( void ); - unsigned int getPortCount( void ); - std::string getPortName( unsigned int portNumber ); - void sendMessage( std::vector *message ); - - protected: - std::string clientName; - - void connect( void ); - void initialize( const std::string& clientName ); -}; - + if (rtapi_) rtapi_->setErrorCallback(errorCallback, userData); +#ifdef __GNUC__ +#pragma GCC diagnostic pop #endif - -#if defined(__LINUX_ALSA__) - -class MidiInAlsa: public MidiInApi -{ - public: - MidiInAlsa( const std::string clientName, unsigned int queueSizeLimit ); - ~MidiInAlsa( void ); - RtMidi::Api getCurrentApi( void ) { return RtMidi::LINUX_ALSA; }; - void openPort( unsigned int portNumber, const std::string portName ); - void openVirtualPort( const std::string portName ); - void closePort( void ); - unsigned int getPortCount( void ); - std::string getPortName( unsigned int portNumber ); - - protected: - void initialize( const std::string& clientName ); -}; - -class MidiOutAlsa: public MidiOutApi -{ - public: - MidiOutAlsa( const std::string clientName ); - ~MidiOutAlsa( void ); - RtMidi::Api getCurrentApi( void ) { return RtMidi::LINUX_ALSA; }; - void openPort( unsigned int portNumber, const std::string portName ); - void openVirtualPort( const std::string portName ); - void closePort( void ); - unsigned int getPortCount( void ); - std::string getPortName( unsigned int portNumber ); - void sendMessage( std::vector *message ); - - protected: - void initialize( const std::string& clientName ); -}; - +} +inline Midi :: Midi(MidiApiList * l, + bool pfsystem, + const std::string &name):rtapi_(0), + list(l), + preferSystem(pfsystem), + clientName(name) { } +inline Midi :: ~Midi() { + delete rtapi_; + rtapi_ = 0; +} +#undef RTMIDI_CLASSNAME + +#define RTMIDI_CLASSNAME "MidiIn" +// rtmidi::MidiIn +inline void MidiIn :: openPort( const PortDescriptor & port, + const std::string &portName ) { + if (!rtapi_) rtapi_ = port.getInputApi(); + if (rtapi_) rtapi_->openPort(port,portName); +} +inline void MidiIn :: openPort( Pointer p, + const std::string &portName ) { + if (!p) { + error(RTMIDI_ERROR(gettext_noopt("A NULL pointer has been passed as port descriptor"), + Error::INVALID_PARAMETER)); + return; + } + openPort(*p, portName); +} +inline void MidiIn :: openVirtualPort( const std::string &portName ) { + if (!rtapi_ && list && !list->empty()) { + Pointer api = list->front(); + + std::vector< ApiType > apis; + getCompiledApi( apis ); + for (size_t i = 0 ; i < apis.size() ; i++) { + openMidiApi( apis[0] ); + if (rtapi_ && rtapi_->hasVirtualPorts()) break; + } + } + + if (rtapi_) rtapi_->openVirtualPort(portName); + else { + error(RTMIDI_ERROR(gettext_noopt("No valid MIDI system has been selected."), + Error::INVALID_DEVICE)); + } +} +inline void MidiIn :: setCallback( MidiInterface * callback ) { + if (rtapi_) + static_cast(rtapi_)->setCallback(callback); +} +inline void MidiIn :: cancelCallback() { + if (rtapi_) + static_cast(rtapi_)->cancelCallback(); +} +inline void MidiIn :: ignoreTypes( bool midiSysex, + bool midiTime, + bool midiSense ) { + if (rtapi_) + static_cast(rtapi_)->ignoreTypes(midiSysex, midiTime, midiSense); +} +inline double MidiIn :: getMessage( std::vector &message ) { + if (rtapi_) + return static_cast(rtapi_)->getMessage(message); + error( RTMIDI_ERROR(gettext_noopt("Could not find any valid MIDI system."), + Error::WARNING)); + return 0.0; +} +inline void MidiIn :: setCallback( MidiCallback callback, void *userData) { +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" #endif - -#if defined(__WINDOWS_MM__) - -class MidiInWinMM: public MidiInApi -{ - public: - MidiInWinMM( const std::string clientName, unsigned int queueSizeLimit ); - ~MidiInWinMM( void ); - RtMidi::Api getCurrentApi( void ) { return RtMidi::WINDOWS_MM; }; - void openPort( unsigned int portNumber, const std::string portName ); - void openVirtualPort( const std::string portName ); - void closePort( void ); - unsigned int getPortCount( void ); - std::string getPortName( unsigned int portNumber ); - - protected: - void initialize( const std::string& clientName ); -}; - -class MidiOutWinMM: public MidiOutApi -{ - public: - MidiOutWinMM( const std::string clientName ); - ~MidiOutWinMM( void ); - RtMidi::Api getCurrentApi( void ) { return RtMidi::WINDOWS_MM; }; - void openPort( unsigned int portNumber, const std::string portName ); - void openVirtualPort( const std::string portName ); - void closePort( void ); - unsigned int getPortCount( void ); - std::string getPortName( unsigned int portNumber ); - void sendMessage( std::vector *message ); - - protected: - void initialize( const std::string& clientName ); + if (rtapi_) + static_cast(rtapi_)->setCallback(callback,userData); +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif +} +inline double MidiIn :: getMessage( std::vector *message ) { + if (!message) { + error( RTMIDI_ERROR(gettext_noopt("Passed NULL pointer."), + Error::WARNING)); + } + if (rtapi_) + return static_cast(rtapi_)->getMessage(*message); + error( RTMIDI_ERROR(gettext_noopt("No valid MIDI system has been found."), + Error::WARNING)); + return 0.0; +} +#undef RTMIDI_CLASSNAME + +// rtmidi::MidiOut +#define RTMIDI_CLASSNAME "MidiOut" +inline void MidiOut :: openPort( const PortDescriptor & port, + const std::string &portName ) { + if (!rtapi_) rtapi_ = port.getOutputApi(); + if (rtapi_) rtapi_->openPort(port,portName); +} +inline void MidiOut :: openPort( Pointer p, + const std::string &portName ) { + if (!p) { + error(RTMIDI_ERROR(gettext_noopt("Passed NULL pointer."), + Error::INVALID_PARAMETER)); + return; + } + openPort(*p, portName); +} +inline void MidiOut :: openVirtualPort( const std::string &portName ) { + if (!rtapi_ && list && !list->empty()) { + Pointer api = list->front(); + + std::vector< ApiType > apis; + getCompiledApi( apis ); + for (size_t i = 0 ; i < apis.size() ; i++) { + openMidiApi( apis[0] ); + if (rtapi_ && rtapi_->hasVirtualPorts()) break; + } + } + + if (rtapi_) rtapi_->openVirtualPort(portName); + else { + error(RTMIDI_ERROR(gettext_noopt("No valid MIDI system has been selected."), + Error::INVALID_DEVICE)); + } +} +inline void MidiOut :: sendMessage( const unsigned char *message, size_t size ) { + if (!message) { + error( RTMIDI_ERROR(gettext_noopt("No data in MIDI message."), + Error::WARNING)); + } + if (rtapi_) + static_cast(rtapi_)->sendMessage(message,size); + else + error( RTMIDI_ERROR(gettext_noopt("No valid MIDI system has been selected."), + Error::WARNING)); +} +#undef RTMIDI_CLASSNAME + + +// old API + + +//! Compatibility interface to hold a C style callback function +struct CompatibilityMidiInterface: MidiInterface { + CompatibilityMidiInterface(MidiCallback cb, void * ud): + callback(cb), + userData(ud) {} + void rtmidi_midi_in(double timestamp, std::vector &message) { + callback (timestamp, &message, userData); + } + void delete_me() { delete this; } + MidiCallback callback; + void * userData; }; -#endif -#if defined(__WINDOWS_KS__) +struct CompatibilityErrorInterface: ErrorInterface { + CompatibilityErrorInterface(ErrorCallback cb, void * ud): callback(cb), + userdata(ud) {} + void rtmidi_error(Error e) { + callback(e.getType(),e.getMessage(),userdata); + } -class MidiInWinKS: public MidiInApi -{ - public: - MidiInWinKS( const std::string clientName, unsigned int queueSizeLimit ); - ~MidiInWinKS( void ); - RtMidi::Api getCurrentApi( void ) { return RtMidi::WINDOWS_KS; }; - void openPort( unsigned int portNumber, const std::string portName ); - void openVirtualPort( const std::string portName ); - void closePort( void ); - unsigned int getPortCount( void ); - std::string getPortName( unsigned int portNumber ); - - protected: - void initialize( const std::string& clientName ); + void delete_me() { delete this; } +private: + ErrorCallback callback; + void * userdata; }; -class MidiOutWinKS: public MidiOutApi -{ - public: - MidiOutWinKS( const std::string clientName ); - ~MidiOutWinKS( void ); - RtMidi::Api getCurrentApi( void ) { return RtMidi::WINDOWS_KS; }; - void openPort( unsigned int portNumber, const std::string portName ); - void openVirtualPort( const std::string portName ); - void closePort( void ); - unsigned int getPortCount( void ); - std::string getPortName( unsigned int portNumber ); - void sendMessage( std::vector *message ); - protected: - void initialize( const std::string& clientName ); -}; -#endif +RTMIDI_NAMESPACE_END -#if defined(__RTMIDI_DUMMY__) +typedef rtmidi::Midi RTMIDI_DEPRECATED(RtMidi,"RtMidi has been replaced by rtmidi::Midi"); -class MidiInDummy: public MidiInApi -{ - public: - MidiInDummy( const std::string /*clientName*/, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) { errorString_ = "MidiInDummy: This class provides no functionality."; error( RtMidiError::WARNING, errorString_ ); } - RtMidi::Api getCurrentApi( void ) { return RtMidi::RTMIDI_DUMMY; } - void openPort( unsigned int /*portNumber*/, const std::string /*portName*/ ) {} - void openVirtualPort( const std::string /*portName*/ ) {} - void closePort( void ) {} - unsigned int getPortCount( void ) { return 0; } - std::string getPortName( unsigned int portNumber ) { return ""; } - - protected: - void initialize( const std::string& /*clientName*/ ) {} +class RtMidiIn: public rtmidi::MidiIn { +public: + RTMIDI_DEPRECATED(RtMidiIn( RtMidi::Api api = (Api_t)rtmidi::UNSPECIFIED, + const std::string &clientName = std::string( "RtMidi Input Client")), + "Class RtMidiIn has been replaced by rtmidi::MidiIn"): + MidiIn((rtmidi::ApiType)api, + clientName) {} }; - -class MidiOutDummy: public MidiOutApi -{ - public: - MidiOutDummy( const std::string /*clientName*/ ) { errorString_ = "MidiOutDummy: This class provides no functionality."; error( RtMidiError::WARNING, errorString_ ); } - RtMidi::Api getCurrentApi( void ) { return RtMidi::RTMIDI_DUMMY; } - void openPort( unsigned int /*portNumber*/, const std::string /*portName*/ ) {} - void openVirtualPort( const std::string /*portName*/ ) {} - void closePort( void ) {} - unsigned int getPortCount( void ) { return 0; } - std::string getPortName( unsigned int /*portNumber*/ ) { return ""; } - void sendMessage( std::vector * /*message*/ ) {} - - protected: - void initialize( const std::string& /*clientName*/ ) {} +class RtMidiOut: public rtmidi::MidiOut { +public: + RTMIDI_DEPRECATED(RtMidiOut( RtMidi::Api api = (Api_t)rtmidi::UNSPECIFIED, + const std::string &clientName = std::string( "RtMidi Output Client")), + "Class RtMidiOut has been replaced by rtmidi::MidiOut"): + MidiOut((rtmidi::ApiType)api, + clientName) {} }; +typedef rtmidi::Error RtMidiError; -#endif #endif diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 00000000..35505301 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,65 @@ +environment: + matrix: + ### + - TOOLCHAIN: "default" + CONFIG: Release + _CC: MINGW + + - TOOLCHAIN: "default" + CONFIG: Debug + _CC: MINGW + +# example see: https://github.com/wang-bin/avbuild/blob/master/appveyor.yml +init: + - echo NUMBER_OF_PROCESSORS=%NUMBER_OF_PROCESSORS% + - echo PROCESSOR_IDENTIFIER=%PROCESSOR_IDENTIFIER% + - set MSYS2_PATH_TYPE=inherit + - set MSYS2_DIR=C:\msys64 + +install: +# can not starts with % +# - git submodule update --init + - if /i %_CC%==MinGW ( + C:\msys64\usr\bin\pacman -Syyuu --noconfirm && + C:\msys64\usr\bin\pacman -Suu --noconfirm && + C:\msys64\usr\bin\pacman -S --noconfirm --needed mingw-w64-i686-gcc mingw-w64-x86_64-gcc && + C:\msys64\usr\bin\pacman -Sc --noconfirm + ) + - C:\msys64\usr\bin\pacman -Ss --noconfirm boost + - C:\msys64\usr\bin\pacman -Ss --noconfirm autoconf + - C:\msys64\usr\bin\pacman -Ss --noconfirm automake + - C:\msys64\usr\bin\pacman -Ss --noconfirm libtool + - C:\msys64\usr\bin\pacman -Ss --noconfirm gettext + - C:\msys64\usr\bin\pacman -S --noconfirm --needed + mingw-w64-x86_64-boost autoconf mingw-w64-x86_64-libtool automake1.15 mingw-w64-x86_64-gettext + +build_script: + - dir C:\ + - dir C:\msys64 + - dir C:\msys64\usr\bin + - dir C:\msys64\opt + - dir C:\msys64\mingw64 + - dir c:\msys64\mingw64\bin + - dir C:\msys64\mingw64\x86_64-w64-mingw32 + - dir C:\msys64\mingw64\x86_64-w64-mingw32\bin + - dir C:\mingw-w64 + - dir C:\mingw-w64\x86_64-7.2.0-posix-seh-rt_v5-rev1\mingw64\bin + - dir C:\mingw-w64\x86_64-7.2.0-posix-seh-rt_v5-rev1\mingw64\opt\bin + - SET PATH=C:\mingw-w64\bin;C:\msys64\mingw64\bin;C:\msys64\usr\bin;%PATH% + - echo "%PATH%" + - path + - bash -c "env" + - bash -c pwd + - bash -c ls + - bash -c "#aclocal -I m4 --install" + - bash -c "#automake --add-missing -f" + - bash -c "#autopoint -f" + - bash -c "#libtoolize -i -f" + - bash -c "#autoconf --add-missing" + - bash -c "mkdir -p config" + - bash -c "touch config/config.rpath" + - bash -c "autoreconf -i -f" + - bash -c "./configure" + - bash -c make + - bash -c "make check" + - bash -c "make distcheck" diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 00000000..8bd52e88 --- /dev/null +++ b/autogen.sh @@ -0,0 +1,107 @@ +#!/bin/sh +# Run this to generate all the initial makefiles, etc. + +srcdir=`dirname $0` +test -z "$srcdir" && srcdir=. + +DIE=0 + +if test -z "$*"; then + echo "**Warning**: I am going to run \`configure' with arguments for" + echo "developer/maintainer mode. If you wish to pass extra arguments," + echo "(such as --prefix), please specify them on the \`$0'" + echo "command line." + echo "If you wish to run configure yourself, please specify --no-configure." + echo +fi + +(test -f $srcdir/configure.ac) || { + echo -n "**Error**: Directory "\`$srcdir\'" does not look like the" + echo " top-level package directory" + exit 1 +} + +# Make some directories required by automake, if they don't exist +if ! [ -d config ]; then mkdir -v config; fi +if ! [ -d m4 ]; then mkdir -v m4; fi + +if ! autoreconf --version /dev/null 2>&1 +then + +(autoconf --version) < /dev/null > /dev/null 2>&1 || { + echo + echo "**Error**: You must have \`autoconf' installed." + echo "Download the appropriate package for your distribution," + echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/" + DIE=1 +} + +(grep "^LT_INIT" $srcdir/configure.ac >/dev/null) && { + (libtoolize --version) < /dev/null > /dev/null 2>&1 \ + && LIBTOOLIZE=libtoolize || { + (glibtoolize --version) < /dev/null > /dev/null 2>&1 \ + && LIBTOOLIZE=glibtoolize || { + echo + echo "**Error**: You must have \`libtool' installed." + echo "You can get it from: ftp://ftp.gnu.org/pub/gnu/" + DIE=1 + } + } +} + +(automake --version) < /dev/null > /dev/null 2>&1 || { + echo + echo "**Error**: You must have \`automake' installed." + echo "You can get it from: ftp://ftp.gnu.org/pub/gnu/" + DIE=1 + NO_AUTOMAKE=yes +} + + +# if no automake, don't bother testing for aclocal +test -n "$NO_AUTOMAKE" || (aclocal --version) < /dev/null > /dev/null 2>&1 || { + echo + echo "**Error**: Missing \`aclocal'. The version of \`automake'" + echo "installed doesn't appear recent enough." + echo "You can get automake from ftp://ftp.gnu.org/pub/gnu/" + DIE=1 +} + +if test "$DIE" -eq 1; then + exit 1 +fi + +case $CC in +xlc ) + am_opt=--include-deps;; +esac + +echo "Running aclocal $aclocalinclude ..." +aclocal $ACLOCAL_FLAGS || exit 1 +echo "Running $LIBTOOLIZE ..." +$LIBTOOLIZE || exit 1 +echo "Running automake --gnu $am_opt ..." +automake --add-missing --gnu $am_opt || exit 1 +echo "Running autoconf ..." +autoconf || exit 1 + +else # autoreconf instead + + echo "Running autoreconf --verbose --install ..." + autoreconf --verbose --install || exit 1 + +fi + +if ( echo "$@" | grep -q -e "--no-configure" ); then + NOCONFIGURE=1 +fi + +conf_flags="--enable-maintainer-mode --enable-debug --disable-silent-rules" + +if test x$NOCONFIGURE = x; then + echo Running $srcdir/configure $conf_flags "$@" ... + $srcdir/configure $conf_flags "$@" \ + && echo Now type \`make\' to compile. || exit 1 +else + echo Skipping configure process. +fi diff --git a/cmake/RtMidiConfigUninstall.cmake.in b/cmake/RtMidiConfigUninstall.cmake.in new file mode 100644 index 00000000..db894b3f --- /dev/null +++ b/cmake/RtMidiConfigUninstall.cmake.in @@ -0,0 +1,21 @@ +if(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") + message(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"") +endif(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") + +file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files) +string(REGEX REPLACE "\n" ";" files "${files}") +foreach(file ${files}) + message(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"") + if(EXISTS "$ENV{DESTDIR}${file}") + exec_program( + "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" + OUTPUT_VARIABLE rm_out + RETURN_VALUE rm_retval + ) + if(NOT "${rm_retval}" STREQUAL 0) + message(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"") + endif(NOT "${rm_retval}" STREQUAL 0) + else(EXISTS "$ENV{DESTDIR}${file}") + message(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.") + endif(EXISTS "$ENV{DESTDIR}${file}") +endforeach(file) diff --git a/config/config.guess b/config/config.guess deleted file mode 100755 index 313be34b..00000000 --- a/config/config.guess +++ /dev/null @@ -1,1371 +0,0 @@ -#! /bin/sh -# Attempt to guess a canonical system name. -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 -# Free Software Foundation, Inc. - -timestamp='2004-02-26' - -# This file 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. -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -# Written by Per Bothner . -# Please send patches to . -# -# This script attempts to guess a canonical system name similar to -# config.sub. If it succeeds, it prints the system name on stdout, and -# exits with 0. Otherwise, it exits with 1. -# -# The plan is that this can be called by configure scripts if you -# don't specify an explicit build system type. - -me=`echo "$0" | sed -e 's,.*/,,'` - -usage="\ -Usage: $0 [OPTION] - -Output the configuration name of the system \`$me' is run on. - -Operation modes: - -h, --help print this help, then exit - -t, --time-stamp print date of last modification, then exit - -v, --version print version number, then exit - -Report bugs and patches to ." - -version="\ -GNU config.guess ($timestamp) - -Originally written by Per Bothner. -Copyright (C) 1992, 93, 94, 95, 96, 97, 98, 99, 2000 -Free Software Foundation, Inc. - -This is free software; see the source for copying conditions. There is NO -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." - -help=" -Try \`$me --help' for more information." - -# Parse command line -while test $# -gt 0 ; do - case $1 in - --time-stamp | --time* | -t ) - echo "$timestamp" ; exit 0 ;; - --version | -v ) - echo "$version" ; exit 0 ;; - --help | --h* | -h ) - echo "$usage"; exit 0 ;; - -- ) # Stop option processing - shift; break ;; - - ) # Use stdin as input. - break ;; - -* ) - echo "$me: invalid option $1$help" >&2 - exit 1 ;; - * ) - break ;; - esac -done - -if test $# != 0; then - echo "$me: too many arguments$help" >&2 - exit 1 -fi - - -dummy=dummy-$$ -trap 'rm -f $dummy.c $dummy.o $dummy.rel $dummy; exit 1' 1 2 15 - -# CC_FOR_BUILD -- compiler used by this script. -# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still -# use `HOST_CC' if defined, but it is deprecated. - -case $CC_FOR_BUILD,$HOST_CC,$CC in - ,,) echo "int dummy(){}" > $dummy.c - for c in cc gcc c89 ; do - ($c $dummy.c -c -o $dummy.o) >/dev/null 2>&1 - if test $? = 0 ; then - CC_FOR_BUILD="$c"; break - fi - done - rm -f $dummy.c $dummy.o $dummy.rel - if test x"$CC_FOR_BUILD" = x ; then - CC_FOR_BUILD=no_compiler_found - fi - ;; - ,,*) CC_FOR_BUILD=$CC ;; - ,*,*) CC_FOR_BUILD=$HOST_CC ;; -esac - -# This is needed to find uname on a Pyramid OSx when run in the BSD universe. -# (ghazi@noc.rutgers.edu 8/24/94.) -if (test -f /.attbin/uname) >/dev/null 2>&1 ; then - PATH=$PATH:/.attbin ; export PATH -fi - -UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown -UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown -UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown -UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown - -# Note: order is significant - the case branches are not exclusive. - -case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in - *:NetBSD:*:*) - # Netbsd (nbsd) targets should (where applicable) match one or - # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, - # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently - # switched to ELF, *-*-netbsd* would select the old - # object file format. This provides both forward - # compatibility and a consistent mechanism for selecting the - # object file format. - # Determine the machine/vendor (is the vendor relevant). - case "${UNAME_MACHINE}" in - amiga) machine=m68k-unknown ;; - arm32) machine=arm-unknown ;; - atari*) machine=m68k-atari ;; - sun3*) machine=m68k-sun ;; - mac68k) machine=m68k-apple ;; - macppc) machine=powerpc-apple ;; - hp3[0-9][05]) machine=m68k-hp ;; - ibmrt|romp-ibm) machine=romp-ibm ;; - *) machine=${UNAME_MACHINE}-unknown ;; - esac - # The Operating System including object format, if it has switched - # to ELF recently, or will in the future. - case "${UNAME_MACHINE}" in - i386|sparc|amiga|arm*|hp300|mvme68k|vax|atari|luna68k|mac68k|news68k|next68k|pc532|sun3*|x68k) - if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep __ELF__ >/dev/null - then - # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). - # Return netbsd for either. FIX? - os=netbsd - else - os=netbsdelf - fi - ;; - *) - os=netbsd - ;; - esac - # The OS release - release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` - # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: - # contains redundant information, the shorter form: - # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. - echo "${machine}-${os}${release}" - exit 0 ;; - alpha:OSF1:*:*) - if test $UNAME_RELEASE = "V4.0"; then - UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` - fi - # A Vn.n version is a released version. - # A Tn.n version is a released field test version. - # A Xn.n version is an unreleased experimental baselevel. - # 1.2 uses "1.2" for uname -r. - cat <$dummy.s - .data -\$Lformat: - .byte 37,100,45,37,120,10,0 # "%d-%x\n" - - .text - .globl main - .align 4 - .ent main -main: - .frame \$30,16,\$26,0 - ldgp \$29,0(\$27) - .prologue 1 - .long 0x47e03d80 # implver \$0 - lda \$2,-1 - .long 0x47e20c21 # amask \$2,\$1 - lda \$16,\$Lformat - mov \$0,\$17 - not \$1,\$18 - jsr \$26,printf - ldgp \$29,0(\$26) - mov 0,\$16 - jsr \$26,exit - .end main -EOF - $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null - if test "$?" = 0 ; then - case `./$dummy` in - 0-0) - UNAME_MACHINE="alpha" - ;; - 1-0) - UNAME_MACHINE="alphaev5" - ;; - 1-1) - UNAME_MACHINE="alphaev56" - ;; - 1-101) - UNAME_MACHINE="alphapca56" - ;; - 2-303) - UNAME_MACHINE="alphaev6" - ;; - 2-307) - UNAME_MACHINE="alphaev67" - ;; - esac - fi - rm -f $dummy.s $dummy - echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - exit 0 ;; - Alpha\ *:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # Should we change UNAME_MACHINE based on the output of uname instead - # of the specific Alpha model? - echo alpha-pc-interix - exit 0 ;; - 21064:Windows_NT:50:3) - echo alpha-dec-winnt3.5 - exit 0 ;; - Amiga*:UNIX_System_V:4.0:*) - echo m68k-unknown-sysv4 - exit 0;; - amiga:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - *:[Aa]miga[Oo][Ss]:*:*) - echo ${UNAME_MACHINE}-unknown-amigaos - exit 0 ;; - arc64:OpenBSD:*:*) - echo mips64el-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - arc:OpenBSD:*:*) - echo mipsel-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - hkmips:OpenBSD:*:*) - echo mips-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - pmax:OpenBSD:*:*) - echo mipsel-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - sgi:OpenBSD:*:*) - echo mips-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - wgrisc:OpenBSD:*:*) - echo mipsel-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - *:OS/390:*:*) - echo i370-ibm-openedition - exit 0 ;; - arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) - echo arm-acorn-riscix${UNAME_RELEASE} - exit 0;; - SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) - echo hppa1.1-hitachi-hiuxmpp - exit 0;; - Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) - # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. - if test "`(/bin/universe) 2>/dev/null`" = att ; then - echo pyramid-pyramid-sysv3 - else - echo pyramid-pyramid-bsd - fi - exit 0 ;; - NILE*:*:*:dcosx) - echo pyramid-pyramid-svr4 - exit 0 ;; - sun4H:SunOS:5.*:*) - echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit 0 ;; - sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) - echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit 0 ;; - i86pc:SunOS:5.*:*) - echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit 0 ;; - sun4*:SunOS:6*:*) - # According to config.sub, this is the proper way to canonicalize - # SunOS6. Hard to guess exactly what SunOS6 will be like, but - # it's likely to be more like Solaris than SunOS4. - echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit 0 ;; - sun4*:SunOS:*:*) - case "`/usr/bin/arch -k`" in - Series*|S4*) - UNAME_RELEASE=`uname -v` - ;; - esac - # Japanese Language versions have a version number like `4.1.3-JL'. - echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` - exit 0 ;; - sun3*:SunOS:*:*) - echo m68k-sun-sunos${UNAME_RELEASE} - exit 0 ;; - sun*:*:4.2BSD:*) - UNAME_RELEASE=`(head -1 /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` - test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 - case "`/bin/arch`" in - sun3) - echo m68k-sun-sunos${UNAME_RELEASE} - ;; - sun4) - echo sparc-sun-sunos${UNAME_RELEASE} - ;; - esac - exit 0 ;; - aushp:SunOS:*:*) - echo sparc-auspex-sunos${UNAME_RELEASE} - exit 0 ;; - atari*:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - # The situation for MiNT is a little confusing. The machine name - # can be virtually everything (everything which is not - # "atarist" or "atariste" at least should have a processor - # > m68000). The system name ranges from "MiNT" over "FreeMiNT" - # to the lowercase version "mint" (or "freemint"). Finally - # the system name "TOS" denotes a system which is actually not - # MiNT. But MiNT is downward compatible to TOS, so this should - # be no problem. - atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit 0 ;; - atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit 0 ;; - *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit 0 ;; - milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) - echo m68k-milan-mint${UNAME_RELEASE} - exit 0 ;; - hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) - echo m68k-hades-mint${UNAME_RELEASE} - exit 0 ;; - *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) - echo m68k-unknown-mint${UNAME_RELEASE} - exit 0 ;; - sun3*:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - mac68k:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - mvme68k:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - mvme88k:OpenBSD:*:*) - echo m88k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - powerpc:machten:*:*) - echo powerpc-apple-machten${UNAME_RELEASE} - exit 0 ;; - RISC*:Mach:*:*) - echo mips-dec-mach_bsd4.3 - exit 0 ;; - RISC*:ULTRIX:*:*) - echo mips-dec-ultrix${UNAME_RELEASE} - exit 0 ;; - VAX*:ULTRIX*:*:*) - echo vax-dec-ultrix${UNAME_RELEASE} - exit 0 ;; - 2020:CLIX:*:* | 2430:CLIX:*:*) - echo clipper-intergraph-clix${UNAME_RELEASE} - exit 0 ;; - mips:*:*:UMIPS | mips:*:*:RISCos) - sed 's/^ //' << EOF >$dummy.c -#ifdef __cplusplus -#include /* for printf() prototype */ - int main (int argc, char *argv[]) { -#else - int main (argc, argv) int argc; char *argv[]; { -#endif - #if defined (host_mips) && defined (MIPSEB) - #if defined (SYSTYPE_SYSV) - printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); - #endif - #if defined (SYSTYPE_SVR4) - printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); - #endif - #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) - printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); - #endif - #endif - exit (-1); - } -EOF - $CC_FOR_BUILD $dummy.c -o $dummy \ - && ./$dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ - && rm -f $dummy.c $dummy && exit 0 - rm -f $dummy.c $dummy - echo mips-mips-riscos${UNAME_RELEASE} - exit 0 ;; - Motorola:PowerMAX_OS:*:*) - echo powerpc-motorola-powermax - exit 0 ;; - Night_Hawk:Power_UNIX:*:*) - echo powerpc-harris-powerunix - exit 0 ;; - m88k:CX/UX:7*:*) - echo m88k-harris-cxux7 - exit 0 ;; - m88k:*:4*:R4*) - echo m88k-motorola-sysv4 - exit 0 ;; - m88k:*:3*:R3*) - echo m88k-motorola-sysv3 - exit 0 ;; - AViiON:dgux:*:*) - # DG/UX returns AViiON for all architectures - UNAME_PROCESSOR=`/usr/bin/uname -p` - if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] - then - if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ - [ ${TARGET_BINARY_INTERFACE}x = x ] - then - echo m88k-dg-dgux${UNAME_RELEASE} - else - echo m88k-dg-dguxbcs${UNAME_RELEASE} - fi - else - echo i586-dg-dgux${UNAME_RELEASE} - fi - exit 0 ;; - M88*:DolphinOS:*:*) # DolphinOS (SVR3) - echo m88k-dolphin-sysv3 - exit 0 ;; - M88*:*:R3*:*) - # Delta 88k system running SVR3 - echo m88k-motorola-sysv3 - exit 0 ;; - XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) - echo m88k-tektronix-sysv3 - exit 0 ;; - Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) - echo m68k-tektronix-bsd - exit 0 ;; - *:IRIX*:*:*) - echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` - exit 0 ;; - ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. - echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id - exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX ' - i*86:AIX:*:*) - echo i386-ibm-aix - exit 0 ;; - ia64:AIX:*:*) - if [ -x /usr/bin/oslevel ] ; then - IBM_REV=`/usr/bin/oslevel` - else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} - fi - echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} - exit 0 ;; - *:AIX:2:3) - if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then - sed 's/^ //' << EOF >$dummy.c - #include - - main() - { - if (!__power_pc()) - exit(1); - puts("powerpc-ibm-aix3.2.5"); - exit(0); - } -EOF - $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0 - rm -f $dummy.c $dummy - echo rs6000-ibm-aix3.2.5 - elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then - echo rs6000-ibm-aix3.2.4 - else - echo rs6000-ibm-aix3.2 - fi - exit 0 ;; - *:AIX:*:[45]) - IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | head -1 | awk '{ print $1 }'` - if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then - IBM_ARCH=rs6000 - else - IBM_ARCH=powerpc - fi - if [ -x /usr/bin/oslevel ] ; then - IBM_REV=`/usr/bin/oslevel` - else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} - fi - echo ${IBM_ARCH}-ibm-aix${IBM_REV} - exit 0 ;; - *:AIX:*:*) - echo rs6000-ibm-aix - exit 0 ;; - ibmrt:4.4BSD:*|romp-ibm:BSD:*) - echo romp-ibm-bsd4.4 - exit 0 ;; - ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and - echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to - exit 0 ;; # report: romp-ibm BSD 4.3 - *:BOSX:*:*) - echo rs6000-bull-bosx - exit 0 ;; - DPX/2?00:B.O.S.:*:*) - echo m68k-bull-sysv3 - exit 0 ;; - 9000/[34]??:4.3bsd:1.*:*) - echo m68k-hp-bsd - exit 0 ;; - hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) - echo m68k-hp-bsd4.4 - exit 0 ;; - 9000/[34678]??:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - case "${UNAME_MACHINE}" in - 9000/31? ) HP_ARCH=m68000 ;; - 9000/[34]?? ) HP_ARCH=m68k ;; - 9000/[678][0-9][0-9]) - case "${HPUX_REV}" in - 11.[0-9][0-9]) - if [ -x /usr/bin/getconf ]; then - sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` - sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` - case "${sc_cpu_version}" in - 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 - 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 - 532) # CPU_PA_RISC2_0 - case "${sc_kernel_bits}" in - 32) HP_ARCH="hppa2.0n" ;; - 64) HP_ARCH="hppa2.0w" ;; - esac ;; - esac - fi ;; - esac - if [ "${HP_ARCH}" = "" ]; then - sed 's/^ //' << EOF >$dummy.c - - #define _HPUX_SOURCE - #include - #include - - int main () - { - #if defined(_SC_KERNEL_BITS) - long bits = sysconf(_SC_KERNEL_BITS); - #endif - long cpu = sysconf (_SC_CPU_VERSION); - - switch (cpu) - { - case CPU_PA_RISC1_0: puts ("hppa1.0"); break; - case CPU_PA_RISC1_1: puts ("hppa1.1"); break; - case CPU_PA_RISC2_0: - #if defined(_SC_KERNEL_BITS) - switch (bits) - { - case 64: puts ("hppa2.0w"); break; - case 32: puts ("hppa2.0n"); break; - default: puts ("hppa2.0"); break; - } break; - #else /* !defined(_SC_KERNEL_BITS) */ - puts ("hppa2.0"); break; - #endif - default: puts ("hppa1.0"); break; - } - exit (0); - } -EOF - (CCOPTS= $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null ) && HP_ARCH=`./$dummy` - if test -z "$HP_ARCH"; then HP_ARCH=hppa; fi - rm -f $dummy.c $dummy - fi ;; - esac - echo ${HP_ARCH}-hp-hpux${HPUX_REV} - exit 0 ;; - ia64:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - echo ia64-hp-hpux${HPUX_REV} - exit 0 ;; - 3050*:HI-UX:*:*) - sed 's/^ //' << EOF >$dummy.c - #include - int - main () - { - long cpu = sysconf (_SC_CPU_VERSION); - /* The order matters, because CPU_IS_HP_MC68K erroneously returns - true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct - results, however. */ - if (CPU_IS_PA_RISC (cpu)) - { - switch (cpu) - { - case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; - case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; - case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; - default: puts ("hppa-hitachi-hiuxwe2"); break; - } - } - else if (CPU_IS_HP_MC68K (cpu)) - puts ("m68k-hitachi-hiuxwe2"); - else puts ("unknown-hitachi-hiuxwe2"); - exit (0); - } -EOF - $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0 - rm -f $dummy.c $dummy - echo unknown-hitachi-hiuxwe2 - exit 0 ;; - 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) - echo hppa1.1-hp-bsd - exit 0 ;; - 9000/8??:4.3bsd:*:*) - echo hppa1.0-hp-bsd - exit 0 ;; - *9??*:MPE/iX:*:*) - echo hppa1.0-hp-mpeix - exit 0 ;; - hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) - echo hppa1.1-hp-osf - exit 0 ;; - hp8??:OSF1:*:*) - echo hppa1.0-hp-osf - exit 0 ;; - i*86:OSF1:*:*) - if [ -x /usr/sbin/sysversion ] ; then - echo ${UNAME_MACHINE}-unknown-osf1mk - else - echo ${UNAME_MACHINE}-unknown-osf1 - fi - exit 0 ;; - parisc*:Lites*:*:*) - echo hppa1.1-hp-lites - exit 0 ;; - hppa*:OpenBSD:*:*) - echo hppa-unknown-openbsd - exit 0 ;; - C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) - echo c1-convex-bsd - exit 0 ;; - C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) - if getsysinfo -f scalar_acc - then echo c32-convex-bsd - else echo c2-convex-bsd - fi - exit 0 ;; - C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) - echo c34-convex-bsd - exit 0 ;; - C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) - echo c38-convex-bsd - exit 0 ;; - C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) - echo c4-convex-bsd - exit 0 ;; - CRAY*X-MP:*:*:*) - echo xmp-cray-unicos - exit 0 ;; - CRAY*Y-MP:*:*:*) - echo ymp-cray-unicos${UNAME_RELEASE} - exit 0 ;; - CRAY*[A-Z]90:*:*:*) - echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ - | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ - -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ - exit 0 ;; - CRAY*TS:*:*:*) - echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit 0 ;; - CRAY*T3D:*:*:*) - echo alpha-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit 0 ;; - CRAY*T3E:*:*:*) - echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit 0 ;; - CRAY*SV1:*:*:*) - echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit 0 ;; - CRAY-2:*:*:*) - echo cray2-cray-unicos - exit 0 ;; - F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) - FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` - echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" - exit 0 ;; - hp300:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) - echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} - exit 0 ;; - sparc*:BSD/OS:*:*) - echo sparc-unknown-bsdi${UNAME_RELEASE} - exit 0 ;; - *:BSD/OS:*:*) - echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} - exit 0 ;; - *:FreeBSD:*:*) - echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` - exit 0 ;; - *:OpenBSD:*:*) - echo ${UNAME_MACHINE}-unknown-openbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` - exit 0 ;; - i*:CYGWIN*:*) - echo ${UNAME_MACHINE}-pc-cygwin - exit 0 ;; - i*:MINGW*:*) - echo ${UNAME_MACHINE}-pc-mingw32 - exit 0 ;; - i*:PW*:*) - echo ${UNAME_MACHINE}-pc-pw32 - exit 0 ;; - i*:Windows_NT*:* | Pentium*:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we - # UNAME_MACHINE based on the output of uname instead of i386? - echo i386-pc-interix - exit 0 ;; - i*:UWIN*:*) - echo ${UNAME_MACHINE}-pc-uwin - exit 0 ;; - p*:CYGWIN*:*) - echo powerpcle-unknown-cygwin - exit 0 ;; - prep*:SunOS:5.*:*) - echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit 0 ;; - *:GNU:*:*) - echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` - exit 0 ;; - i*86:Minix:*:*) - echo ${UNAME_MACHINE}-pc-minix - exit 0 ;; - arm*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit 0 ;; - ia64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux - exit 0 ;; - m68*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit 0 ;; - mips:Linux:*:*) - cat >$dummy.c < /* for printf() prototype */ -int main (int argc, char *argv[]) { -#else -int main (argc, argv) int argc; char *argv[]; { -#endif -#ifdef __MIPSEB__ - printf ("%s-unknown-linux-gnu\n", argv[1]); -#endif -#ifdef __MIPSEL__ - printf ("%sel-unknown-linux-gnu\n", argv[1]); -#endif - return 0; -} -EOF - $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm -f $dummy.c $dummy && exit 0 - rm -f $dummy.c $dummy - ;; - ppc:Linux:*:*) - # Determine Lib Version - cat >$dummy.c < -#if defined(__GLIBC__) -extern char __libc_version[]; -extern char __libc_release[]; -#endif -main(argc, argv) - int argc; - char *argv[]; -{ -#if defined(__GLIBC__) - printf("%s %s\n", __libc_version, __libc_release); -#else - printf("unknown\n"); -#endif - return 0; -} -EOF - LIBC="" - $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null - if test "$?" = 0 ; then - ./$dummy | grep 1\.99 > /dev/null - if test "$?" = 0 ; then LIBC="libc1" ; fi - fi - rm -f $dummy.c $dummy - echo powerpc-unknown-linux-gnu${LIBC} - exit 0 ;; - alpha:Linux:*:*) - cat <$dummy.s - .data - \$Lformat: - .byte 37,100,45,37,120,10,0 # "%d-%x\n" - .text - .globl main - .align 4 - .ent main - main: - .frame \$30,16,\$26,0 - ldgp \$29,0(\$27) - .prologue 1 - .long 0x47e03d80 # implver \$0 - lda \$2,-1 - .long 0x47e20c21 # amask \$2,\$1 - lda \$16,\$Lformat - mov \$0,\$17 - not \$1,\$18 - jsr \$26,printf - ldgp \$29,0(\$26) - mov 0,\$16 - jsr \$26,exit - .end main -EOF - LIBC="" - $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null - if test "$?" = 0 ; then - case `./$dummy` in - 0-0) UNAME_MACHINE="alpha" ;; - 1-0) UNAME_MACHINE="alphaev5" ;; - 1-1) UNAME_MACHINE="alphaev56" ;; - 1-101) UNAME_MACHINE="alphapca56" ;; - 2-303) UNAME_MACHINE="alphaev6" ;; - 2-307) UNAME_MACHINE="alphaev67" ;; - esac - objdump --private-headers $dummy | \ - grep ld.so.1 > /dev/null - if test "$?" = 0 ; then - LIBC="libc1" - fi - fi - rm -f $dummy.s $dummy - echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} - exit 0 ;; - parisc:Linux:*:* | hppa:Linux:*:*) - # Look for CPU level - case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in - PA7*) echo hppa1.1-unknown-linux-gnu ;; - PA8*) echo hppa2.0-unknown-linux-gnu ;; - *) echo hppa-unknown-linux-gnu ;; - esac - exit 0 ;; - parisc64:Linux:*:* | hppa64:Linux:*:*) - echo hppa64-unknown-linux-gnu - exit 0 ;; - s390:Linux:*:* | s390x:Linux:*:*) - echo ${UNAME_MACHINE}-ibm-linux - exit 0 ;; - sh*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit 0 ;; - sparc:Linux:*:* | sparc64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit 0 ;; - x86_64:Linux:*:*) - echo x86_64-unknown-linux-gnu - exit 0 ;; - i*86:Linux:*:*) - # The BFD linker knows what the default object file format is, so - # first see if it will tell us. cd to the root directory to prevent - # problems with other programs or directories called `ld' in the path. - ld_supported_emulations=`cd /; ld --help 2>&1 \ - | sed -ne '/supported emulations:/!d - s/[ ][ ]*/ /g - s/.*supported emulations: *// - s/ .*// - p'` - case "$ld_supported_emulations" in - i*86linux) - echo "${UNAME_MACHINE}-pc-linux-gnuaout" - exit 0 - ;; - elf_i*86) - TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" - ;; - i*86coff) - echo "${UNAME_MACHINE}-pc-linux-gnucoff" - exit 0 - ;; - esac - # Either a pre-BFD a.out linker (linux-gnuoldld) - # or one that does not give us useful --help. - # GCC wants to distinguish between linux-gnuoldld and linux-gnuaout. - # If ld does not provide *any* "supported emulations:" - # that means it is gnuoldld. - test -z "$ld_supported_emulations" && echo "${UNAME_MACHINE}-pc-linux-gnuoldld" && exit 0 - case "${UNAME_MACHINE}" in - i*86) - VENDOR=pc; - ;; - *) - VENDOR=unknown; - ;; - esac - # Determine whether the default compiler is a.out or elf - cat >$dummy.c < -#ifdef __cplusplus -#include /* for printf() prototype */ - int main (int argc, char *argv[]) { -#else - int main (argc, argv) int argc; char *argv[]; { -#endif -#ifdef __ELF__ -# ifdef __GLIBC__ -# if __GLIBC__ >= 2 - printf ("%s-${VENDOR}-linux-gnu\n", argv[1]); -# else - printf ("%s-${VENDOR}-linux-gnulibc1\n", argv[1]); -# endif -# else - printf ("%s-${VENDOR}-linux-gnulibc1\n", argv[1]); -# endif -#else - printf ("%s-${VENDOR}-linux-gnuaout\n", argv[1]); -#endif - return 0; -} -EOF - $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm -f $dummy.c $dummy && exit 0 - rm -f $dummy.c $dummy - test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0 - ;; -# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. earlier versions -# are messed up and put the nodename in both sysname and nodename. - i*86:DYNIX/ptx:4*:*) - echo i386-sequent-sysv4 - exit 0 ;; - i*86:UNIX_SV:4.2MP:2.*) - # Unixware is an offshoot of SVR4, but it has its own version - # number series starting with 2... - # I am not positive that other SVR4 systems won't match this, - # I just have to hope. -- rms. - # Use sysv4.2uw... so that sysv4* matches it. - echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} - exit 0 ;; - i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) - UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` - if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then - echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} - else - echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} - fi - exit 0 ;; - i*86:*:5:7*) - # Fixed at (any) Pentium or better - UNAME_MACHINE=i586 - if [ ${UNAME_SYSTEM} = "UnixWare" ] ; then - echo ${UNAME_MACHINE}-sco-sysv${UNAME_RELEASE}uw${UNAME_VERSION} - else - echo ${UNAME_MACHINE}-pc-sysv${UNAME_RELEASE} - fi - exit 0 ;; - i*86:*:3.2:*) - if test -f /usr/options/cb.name; then - UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then - UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')` - (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486 - (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \ - && UNAME_MACHINE=i586 - (/bin/uname -X|egrep '^Machine.*Pent ?II' >/dev/null) \ - && UNAME_MACHINE=i686 - (/bin/uname -X|egrep '^Machine.*Pentium Pro' >/dev/null) \ - && UNAME_MACHINE=i686 - echo ${UNAME_MACHINE}-pc-sco$UNAME_REL - else - echo ${UNAME_MACHINE}-pc-sysv32 - fi - exit 0 ;; - i*86:*DOS:*:*) - echo ${UNAME_MACHINE}-pc-msdosdjgpp - exit 0 ;; - pc:*:*:*) - # Left here for compatibility: - # uname -m prints for DJGPP always 'pc', but it prints nothing about - # the processor, so we play safe by assuming i386. - echo i386-pc-msdosdjgpp - exit 0 ;; - Intel:Mach:3*:*) - echo i386-pc-mach3 - exit 0 ;; - paragon:*:*:*) - echo i860-intel-osf1 - exit 0 ;; - i860:*:4.*:*) # i860-SVR4 - if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then - echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 - else # Add other i860-SVR4 vendors below as they are discovered. - echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 - fi - exit 0 ;; - mini*:CTIX:SYS*5:*) - # "miniframe" - echo m68010-convergent-sysv - exit 0 ;; - M68*:*:R3V[567]*:*) - test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;; - 3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 4850:*:4.0:3.0) - OS_REL='' - test -r /etc/.relid \ - && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && echo i486-ncr-sysv4.3${OS_REL} && exit 0 - /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;; - 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && echo i486-ncr-sysv4 && exit 0 ;; - m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) - echo m68k-unknown-lynxos${UNAME_RELEASE} - exit 0 ;; - mc68030:UNIX_System_V:4.*:*) - echo m68k-atari-sysv4 - exit 0 ;; - i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) - echo i386-unknown-lynxos${UNAME_RELEASE} - exit 0 ;; - TSUNAMI:LynxOS:2.*:*) - echo sparc-unknown-lynxos${UNAME_RELEASE} - exit 0 ;; - rs6000:LynxOS:2.*:*) - echo rs6000-unknown-lynxos${UNAME_RELEASE} - exit 0 ;; - PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) - echo powerpc-unknown-lynxos${UNAME_RELEASE} - exit 0 ;; - SM[BE]S:UNIX_SV:*:*) - echo mips-dde-sysv${UNAME_RELEASE} - exit 0 ;; - RM*:ReliantUNIX-*:*:*) - echo mips-sni-sysv4 - exit 0 ;; - RM*:SINIX-*:*:*) - echo mips-sni-sysv4 - exit 0 ;; - *:SINIX-*:*:*) - if uname -p 2>/dev/null >/dev/null ; then - UNAME_MACHINE=`(uname -p) 2>/dev/null` - echo ${UNAME_MACHINE}-sni-sysv4 - else - echo ns32k-sni-sysv - fi - exit 0 ;; - PENTIUM:CPunix:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort - # says - echo i586-unisys-sysv4 - exit 0 ;; - *:UNIX_System_V:4*:FTX*) - # From Gerald Hewes . - # How about differentiating between stratus architectures? -djm - echo hppa1.1-stratus-sysv4 - exit 0 ;; - *:*:*:FTX*) - # From seanf@swdc.stratus.com. - echo i860-stratus-sysv4 - exit 0 ;; - mc68*:A/UX:*:*) - echo m68k-apple-aux${UNAME_RELEASE} - exit 0 ;; - news*:NEWS-OS:6*:*) - echo mips-sony-newsos6 - exit 0 ;; - R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) - if [ -d /usr/nec ]; then - echo mips-nec-sysv${UNAME_RELEASE} - else - echo mips-unknown-sysv${UNAME_RELEASE} - fi - exit 0 ;; - BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. - echo powerpc-be-beos - exit 0 ;; - BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. - echo powerpc-apple-beos - exit 0 ;; - BePC:BeOS:*:*) # BeOS running on Intel PC compatible. - echo i586-pc-beos - exit 0 ;; - SX-4:SUPER-UX:*:*) - echo sx4-nec-superux${UNAME_RELEASE} - exit 0 ;; - SX-5:SUPER-UX:*:*) - echo sx5-nec-superux${UNAME_RELEASE} - exit 0 ;; - Power*:Rhapsody:*:*) - echo powerpc-apple-rhapsody${UNAME_RELEASE} - exit 0 ;; - *:Rhapsody:*:*) - echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} - exit 0 ;; - *:Darwin:*:*) - echo `uname -p`-apple-darwin${UNAME_RELEASE} - exit 0 ;; - *:procnto*:*:* | *:QNX:[0123456789]*:*) - if test "${UNAME_MACHINE}" = "x86pc"; then - UNAME_MACHINE=pc - fi - echo `uname -p`-${UNAME_MACHINE}-nto-qnx - exit 0 ;; - *:QNX:*:4*) - echo i386-pc-qnx - exit 0 ;; - NSR-[KW]:NONSTOP_KERNEL:*:*) - echo nsr-tandem-nsk${UNAME_RELEASE} - exit 0 ;; - *:NonStop-UX:*:*) - echo mips-compaq-nonstopux - exit 0 ;; - BS2000:POSIX*:*:*) - echo bs2000-siemens-sysv - exit 0 ;; - DS/*:UNIX_System_V:*:*) - echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} - exit 0 ;; - *:Plan9:*:*) - # "uname -m" is not consistent, so use $cputype instead. 386 - # is converted to i386 for consistency with other x86 - # operating systems. - if test "$cputype" = "386"; then - UNAME_MACHINE=i386 - else - UNAME_MACHINE="$cputype" - fi - echo ${UNAME_MACHINE}-unknown-plan9 - exit 0 ;; - i*86:OS/2:*:*) - # If we were able to find `uname', then EMX Unix compatibility - # is probably installed. - echo ${UNAME_MACHINE}-pc-os2-emx - exit 0 ;; - *:TOPS-10:*:*) - echo pdp10-unknown-tops10 - exit 0 ;; - *:TENEX:*:*) - echo pdp10-unknown-tenex - exit 0 ;; - KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) - echo pdp10-dec-tops20 - exit 0 ;; - XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) - echo pdp10-xkl-tops20 - exit 0 ;; - *:TOPS-20:*:*) - echo pdp10-unknown-tops20 - exit 0 ;; - *:ITS:*:*) - echo pdp10-unknown-its - exit 0 ;; -esac - -#echo '(No uname command or uname output not recognized.)' 1>&2 -#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 - -cat >$dummy.c < -# include -#endif -main () -{ -#if defined (sony) -#if defined (MIPSEB) - /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, - I don't know.... */ - printf ("mips-sony-bsd\n"); exit (0); -#else -#include - printf ("m68k-sony-newsos%s\n", -#ifdef NEWSOS4 - "4" -#else - "" -#endif - ); exit (0); -#endif -#endif - -#if defined (__arm) && defined (__acorn) && defined (__unix) - printf ("arm-acorn-riscix"); exit (0); -#endif - -#if defined (hp300) && !defined (hpux) - printf ("m68k-hp-bsd\n"); exit (0); -#endif - -#if defined (NeXT) -#if !defined (__ARCHITECTURE__) -#define __ARCHITECTURE__ "m68k" -#endif - int version; - version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; - if (version < 4) - printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); - else - printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); - exit (0); -#endif - -#if defined (MULTIMAX) || defined (n16) -#if defined (UMAXV) - printf ("ns32k-encore-sysv\n"); exit (0); -#else -#if defined (CMU) - printf ("ns32k-encore-mach\n"); exit (0); -#else - printf ("ns32k-encore-bsd\n"); exit (0); -#endif -#endif -#endif - -#if defined (__386BSD__) - printf ("i386-pc-bsd\n"); exit (0); -#endif - -#if defined (sequent) -#if defined (i386) - printf ("i386-sequent-dynix\n"); exit (0); -#endif -#if defined (ns32000) - printf ("ns32k-sequent-dynix\n"); exit (0); -#endif -#endif - -#if defined (_SEQUENT_) - struct utsname un; - - uname(&un); - - if (strncmp(un.version, "V2", 2) == 0) { - printf ("i386-sequent-ptx2\n"); exit (0); - } - if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ - printf ("i386-sequent-ptx1\n"); exit (0); - } - printf ("i386-sequent-ptx\n"); exit (0); - -#endif - -#if defined (vax) -# if !defined (ultrix) -# include -# if defined (BSD) -# if BSD == 43 - printf ("vax-dec-bsd4.3\n"); exit (0); -# else -# if BSD == 199006 - printf ("vax-dec-bsd4.3reno\n"); exit (0); -# else - printf ("vax-dec-bsd\n"); exit (0); -# endif -# endif -# else - printf ("vax-dec-bsd\n"); exit (0); -# endif -# else - printf ("vax-dec-ultrix\n"); exit (0); -# endif -#endif - -#if defined (alliant) && defined (i860) - printf ("i860-alliant-bsd\n"); exit (0); -#endif - - exit (1); -} -EOF - -$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy && rm -f $dummy.c $dummy && exit 0 -rm -f $dummy.c $dummy - -# Apollos put the system type in the environment. - -test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; } - -# Convex versions that predate uname can use getsysinfo(1) - -if [ -x /usr/convex/getsysinfo ] -then - case `getsysinfo -f cpu_type` in - c1*) - echo c1-convex-bsd - exit 0 ;; - c2*) - if getsysinfo -f scalar_acc - then echo c32-convex-bsd - else echo c2-convex-bsd - fi - exit 0 ;; - c34*) - echo c34-convex-bsd - exit 0 ;; - c38*) - echo c38-convex-bsd - exit 0 ;; - c4*) - echo c4-convex-bsd - exit 0 ;; - esac -fi - -cat >&2 < in order to provide the needed -information to handle your system. - -config.guess timestamp = $timestamp - -uname -m = `(uname -m) 2>/dev/null || echo unknown` -uname -r = `(uname -r) 2>/dev/null || echo unknown` -uname -s = `(uname -s) 2>/dev/null || echo unknown` -uname -v = `(uname -v) 2>/dev/null || echo unknown` - -/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` -/bin/uname -X = `(/bin/uname -X) 2>/dev/null` - -hostinfo = `(hostinfo) 2>/dev/null` -/bin/universe = `(/bin/universe) 2>/dev/null` -/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` -/bin/arch = `(/bin/arch) 2>/dev/null` -/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` -/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` - -UNAME_MACHINE = ${UNAME_MACHINE} -UNAME_RELEASE = ${UNAME_RELEASE} -UNAME_SYSTEM = ${UNAME_SYSTEM} -UNAME_VERSION = ${UNAME_VERSION} -EOF - -exit 1 - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "timestamp='" -# time-stamp-format: "%:y-%02m-%02d" -# time-stamp-end: "'" -# End: diff --git a/config/config.sub b/config/config.sub deleted file mode 100755 index 7d3f49f0..00000000 --- a/config/config.sub +++ /dev/null @@ -1,1362 +0,0 @@ -#! /bin/sh -# Configuration validation subroutine script. -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 -# Free Software Foundation, Inc. - -timestamp='2004-02-26' - -# This file is (in principle) common to ALL GNU software. -# The presence of a machine in this file suggests that SOME GNU software -# can handle that machine. It does not imply ALL GNU software can. -# -# This file 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. - -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -# Please send patches to . -# -# Configuration subroutine to validate and canonicalize a configuration type. -# Supply the specified configuration type as an argument. -# If it is invalid, we print an error message on stderr and exit with code 1. -# Otherwise, we print the canonical config type on stdout and succeed. - -# This file is supposed to be the same for all GNU packages -# and recognize all the CPU types, system types and aliases -# that are meaningful with *any* GNU software. -# Each package is responsible for reporting which valid configurations -# it does not support. The user should be able to distinguish -# a failure to support a valid configuration from a meaningless -# configuration. - -# The goal of this file is to map all the various variations of a given -# machine specification into a single specification in the form: -# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM -# or in some cases, the newer four-part form: -# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM -# It is wrong to echo any other type of specification. - -me=`echo "$0" | sed -e 's,.*/,,'` - -usage="\ -Usage: $0 [OPTION] CPU-MFR-OPSYS - $0 [OPTION] ALIAS - -Canonicalize a configuration name. - -Operation modes: - -h, --help print this help, then exit - -t, --time-stamp print date of last modification, then exit - -v, --version print version number, then exit - -Report bugs and patches to ." - -version="\ -GNU config.sub ($timestamp) - -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 -Free Software Foundation, Inc. - -This is free software; see the source for copying conditions. There is NO -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." - -help=" -Try \`$me --help' for more information." - -# Parse command line -while test $# -gt 0 ; do - case $1 in - --time-stamp | --time* | -t ) - echo "$timestamp" ; exit 0 ;; - --version | -v ) - echo "$version" ; exit 0 ;; - --help | --h* | -h ) - echo "$usage"; exit 0 ;; - -- ) # Stop option processing - shift; break ;; - - ) # Use stdin as input. - break ;; - -* ) - echo "$me: invalid option $1$help" - exit 1 ;; - - *local*) - # First pass through any local machine types. - echo $1 - exit 0;; - - * ) - break ;; - esac -done - -case $# in - 0) echo "$me: missing argument$help" >&2 - exit 1;; - 1) ;; - *) echo "$me: too many arguments$help" >&2 - exit 1;; -esac - -# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). -# Here we must recognize all the valid KERNEL-OS combinations. -maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` -case $maybe_os in - nto-qnx* | linux-gnu* | storm-chaos* | os2-emx*) - os=-$maybe_os - basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` - ;; - *) - basic_machine=`echo $1 | sed 's/-[^-]*$//'` - if [ $basic_machine != $1 ] - then os=`echo $1 | sed 's/.*-/-/'` - else os=; fi - ;; -esac - -### Let's recognize common machines as not being operating systems so -### that things like config.sub decstation-3100 work. We also -### recognize some manufacturers as not being operating systems, so we -### can provide default operating systems below. -case $os in - -sun*os*) - # Prevent following clause from handling this invalid input. - ;; - -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ - -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ - -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ - -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ - -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ - -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ - -apple | -axis) - os= - basic_machine=$1 - ;; - -sim | -cisco | -oki | -wec | -winbond) - os= - basic_machine=$1 - ;; - -scout) - ;; - -wrs) - os=-vxworks - basic_machine=$1 - ;; - -hiux*) - os=-hiuxwe2 - ;; - -sco5) - os=-sco3.2v5 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco4) - os=-sco3.2v4 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco3.2.[4-9]*) - os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco3.2v[4-9]*) - # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco*) - os=-sco3.2v2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -udk*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -isc) - os=-isc2.2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -clix*) - basic_machine=clipper-intergraph - ;; - -isc*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -lynx*) - os=-lynxos - ;; - -ptx*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` - ;; - -windowsnt*) - os=`echo $os | sed -e 's/windowsnt/winnt/'` - ;; - -psos*) - os=-psos - ;; - -mint | -mint[0-9]*) - basic_machine=m68k-atari - os=-mint - ;; -esac - -# Decode aliases for certain CPU-COMPANY combinations. -case $basic_machine in - # Recognize the basic CPU types without company name. - # Some are omitted here because they have special meanings below. - tahoe | i860 | ia64 | m32r | m68k | m68000 | m88k | ns32k | arc \ - | arm | arme[lb] | arm[bl]e | armv[2345] | armv[345][lb] | strongarm | xscale \ - | pyramid | mn10200 | mn10300 | tron | a29k \ - | 580 | i960 | h8300 \ - | x86 | ppcbe | mipsbe | mipsle | shbe | shle \ - | hppa | hppa1.0 | hppa1.1 | hppa2.0 | hppa2.0w | hppa2.0n \ - | hppa64 \ - | alpha | alphaev[4-8] | alphaev56 | alphapca5[67] \ - | alphaev6[78] \ - | we32k | ns16k | clipper | i370 | sh | sh[34] \ - | powerpc | powerpcle \ - | 1750a | dsp16xx | pdp10 | pdp11 \ - | mips16 | mips64 | mipsel | mips64el \ - | mips64orion | mips64orionel | mipstx39 | mipstx39el \ - | mips64vr4300 | mips64vr4300el | mips64vr4100 | mips64vr4100el \ - | mips64vr5000 | miprs64vr5000el | mcore | s390 | s390x \ - | sparc | sparclet | sparclite | sparc64 | sparcv9 | sparcv9b \ - | v850 | c4x \ - | thumb | d10v | d30v | fr30 | avr | openrisc | tic80 \ - | pj | pjl | h8500) - basic_machine=$basic_machine-unknown - ;; - m6811 | m68hc11 | m6812 | m68hc12) - # Motorola 68HC11/12. - basic_machine=$basic_machine-unknown - os=-none - ;; - m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | z8k | v70 | w65) - ;; - - # We use `pc' rather than `unknown' - # because (1) that's what they normally are, and - # (2) the word "unknown" tends to confuse beginning users. - i*86 | x86_64) - basic_machine=$basic_machine-pc - ;; - # Object if more than one company name word. - *-*-*) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 - exit 1 - ;; - # Recognize the basic CPU types with company name. - # FIXME: clean up the formatting here. - vax-* | tahoe-* | i*86-* | i860-* | ia64-* | m32r-* | m68k-* | m68000-* \ - | m88k-* | sparc-* | ns32k-* | fx80-* | arc-* | c[123]* \ - | arm-* | armbe-* | armle-* | armv*-* | strongarm-* | xscale-* \ - | mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* \ - | power-* | none-* | 580-* | cray2-* | h8300-* | h8500-* | i960-* \ - | xmp-* | ymp-* \ - | x86-* | ppcbe-* | mipsbe-* | mipsle-* | shbe-* | shle-* \ - | hppa-* | hppa1.0-* | hppa1.1-* | hppa2.0-* | hppa2.0w-* \ - | hppa2.0n-* | hppa64-* \ - | alpha-* | alphaev[4-8]-* | alphaev56-* | alphapca5[67]-* \ - | alphaev6[78]-* \ - | we32k-* | cydra-* | ns16k-* | pn-* | np1-* | xps100-* \ - | clipper-* | orion-* \ - | sparclite-* | pdp10-* | pdp11-* | sh-* | powerpc-* | powerpcle-* \ - | sparc64-* | sparcv9-* | sparcv9b-* | sparc86x-* \ - | mips16-* | mips64-* | mipsel-* \ - | mips64el-* | mips64orion-* | mips64orionel-* \ - | mips64vr4100-* | mips64vr4100el-* | mips64vr4300-* | mips64vr4300el-* \ - | mipstx39-* | mipstx39el-* | mcore-* \ - | f30[01]-* | f700-* | s390-* | s390x-* | sv1-* | t3e-* \ - | [cjt]90-* \ - | m88110-* | m680[01234]0-* | m683?2-* | m68360-* | z8k-* | d10v-* \ - | thumb-* | v850-* | d30v-* | tic30-* | tic80-* | c30-* | fr30-* \ - | bs2000-* | tic54x-* | c54x-* | x86_64-* | pj-* | pjl-*) - ;; - # Recognize the various machine names and aliases which stand - # for a CPU type and a company and sometimes even an OS. - 386bsd) - basic_machine=i386-unknown - os=-bsd - ;; - 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) - basic_machine=m68000-att - ;; - 3b*) - basic_machine=we32k-att - ;; - a29khif) - basic_machine=a29k-amd - os=-udi - ;; - adobe68k) - basic_machine=m68010-adobe - os=-scout - ;; - alliant | fx80) - basic_machine=fx80-alliant - ;; - altos | altos3068) - basic_machine=m68k-altos - ;; - am29k) - basic_machine=a29k-none - os=-bsd - ;; - amdahl) - basic_machine=580-amdahl - os=-sysv - ;; - amiga | amiga-*) - basic_machine=m68k-unknown - ;; - amigaos | amigados) - basic_machine=m68k-unknown - os=-amigaos - ;; - amigaunix | amix) - basic_machine=m68k-unknown - os=-sysv4 - ;; - apollo68) - basic_machine=m68k-apollo - os=-sysv - ;; - apollo68bsd) - basic_machine=m68k-apollo - os=-bsd - ;; - aux) - basic_machine=m68k-apple - os=-aux - ;; - balance) - basic_machine=ns32k-sequent - os=-dynix - ;; - convex-c1) - basic_machine=c1-convex - os=-bsd - ;; - convex-c2) - basic_machine=c2-convex - os=-bsd - ;; - convex-c32) - basic_machine=c32-convex - os=-bsd - ;; - convex-c34) - basic_machine=c34-convex - os=-bsd - ;; - convex-c38) - basic_machine=c38-convex - os=-bsd - ;; - cray | ymp) - basic_machine=ymp-cray - os=-unicos - ;; - cray2) - basic_machine=cray2-cray - os=-unicos - ;; - [cjt]90) - basic_machine=${basic_machine}-cray - os=-unicos - ;; - crds | unos) - basic_machine=m68k-crds - ;; - cris | cris-* | etrax*) - basic_machine=cris-axis - ;; - da30 | da30-*) - basic_machine=m68k-da30 - ;; - decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) - basic_machine=mips-dec - ;; - delta | 3300 | motorola-3300 | motorola-delta \ - | 3300-motorola | delta-motorola) - basic_machine=m68k-motorola - ;; - delta88) - basic_machine=m88k-motorola - os=-sysv3 - ;; - dpx20 | dpx20-*) - basic_machine=rs6000-bull - os=-bosx - ;; - dpx2* | dpx2*-bull) - basic_machine=m68k-bull - os=-sysv3 - ;; - ebmon29k) - basic_machine=a29k-amd - os=-ebmon - ;; - elxsi) - basic_machine=elxsi-elxsi - os=-bsd - ;; - encore | umax | mmax) - basic_machine=ns32k-encore - ;; - es1800 | OSE68k | ose68k | ose | OSE) - basic_machine=m68k-ericsson - os=-ose - ;; - fx2800) - basic_machine=i860-alliant - ;; - genix) - basic_machine=ns32k-ns - ;; - gmicro) - basic_machine=tron-gmicro - os=-sysv - ;; - go32) - basic_machine=i386-pc - os=-go32 - ;; - h3050r* | hiux*) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - h8300hms) - basic_machine=h8300-hitachi - os=-hms - ;; - h8300xray) - basic_machine=h8300-hitachi - os=-xray - ;; - h8500hms) - basic_machine=h8500-hitachi - os=-hms - ;; - harris) - basic_machine=m88k-harris - os=-sysv3 - ;; - hp300-*) - basic_machine=m68k-hp - ;; - hp300bsd) - basic_machine=m68k-hp - os=-bsd - ;; - hp300hpux) - basic_machine=m68k-hp - os=-hpux - ;; - hp3k9[0-9][0-9] | hp9[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hp9k2[0-9][0-9] | hp9k31[0-9]) - basic_machine=m68000-hp - ;; - hp9k3[2-9][0-9]) - basic_machine=m68k-hp - ;; - hp9k6[0-9][0-9] | hp6[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hp9k7[0-79][0-9] | hp7[0-79][0-9]) - basic_machine=hppa1.1-hp - ;; - hp9k78[0-9] | hp78[0-9]) - # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp - ;; - hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) - # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp - ;; - hp9k8[0-9][13679] | hp8[0-9][13679]) - basic_machine=hppa1.1-hp - ;; - hp9k8[0-9][0-9] | hp8[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hppa-next) - os=-nextstep3 - ;; - hppaosf) - basic_machine=hppa1.1-hp - os=-osf - ;; - hppro) - basic_machine=hppa1.1-hp - os=-proelf - ;; - i370-ibm* | ibm*) - basic_machine=i370-ibm - ;; -# I'm not sure what "Sysv32" means. Should this be sysv3.2? - i*86v32) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv32 - ;; - i*86v4*) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv4 - ;; - i*86v) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv - ;; - i*86sol2) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-solaris2 - ;; - i386mach) - basic_machine=i386-mach - os=-mach - ;; - i386-vsta | vsta) - basic_machine=i386-unknown - os=-vsta - ;; - iris | iris4d) - basic_machine=mips-sgi - case $os in - -irix*) - ;; - *) - os=-irix4 - ;; - esac - ;; - isi68 | isi) - basic_machine=m68k-isi - os=-sysv - ;; - m88k-omron*) - basic_machine=m88k-omron - ;; - magnum | m3230) - basic_machine=mips-mips - os=-sysv - ;; - merlin) - basic_machine=ns32k-utek - os=-sysv - ;; - mingw32) - basic_machine=i386-pc - os=-mingw32 - ;; - miniframe) - basic_machine=m68000-convergent - ;; - *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) - basic_machine=m68k-atari - os=-mint - ;; - mipsel*-linux*) - basic_machine=mipsel-unknown - os=-linux-gnu - ;; - mips*-linux*) - basic_machine=mips-unknown - os=-linux-gnu - ;; - mips3*-*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` - ;; - mips3*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown - ;; - mmix*) - basic_machine=mmix-knuth - os=-mmixware - ;; - monitor) - basic_machine=m68k-rom68k - os=-coff - ;; - msdos) - basic_machine=i386-pc - os=-msdos - ;; - mvs) - basic_machine=i370-ibm - os=-mvs - ;; - ncr3000) - basic_machine=i486-ncr - os=-sysv4 - ;; - netbsd386) - basic_machine=i386-unknown - os=-netbsd - ;; - netwinder) - basic_machine=armv4l-rebel - os=-linux - ;; - news | news700 | news800 | news900) - basic_machine=m68k-sony - os=-newsos - ;; - news1000) - basic_machine=m68030-sony - os=-newsos - ;; - news-3600 | risc-news) - basic_machine=mips-sony - os=-newsos - ;; - necv70) - basic_machine=v70-nec - os=-sysv - ;; - next | m*-next ) - basic_machine=m68k-next - case $os in - -nextstep* ) - ;; - -ns2*) - os=-nextstep2 - ;; - *) - os=-nextstep3 - ;; - esac - ;; - nh3000) - basic_machine=m68k-harris - os=-cxux - ;; - nh[45]000) - basic_machine=m88k-harris - os=-cxux - ;; - nindy960) - basic_machine=i960-intel - os=-nindy - ;; - mon960) - basic_machine=i960-intel - os=-mon960 - ;; - nonstopux) - basic_machine=mips-compaq - os=-nonstopux - ;; - np1) - basic_machine=np1-gould - ;; - nsr-tandem) - basic_machine=nsr-tandem - ;; - op50n-* | op60c-*) - basic_machine=hppa1.1-oki - os=-proelf - ;; - OSE68000 | ose68000) - basic_machine=m68000-ericsson - os=-ose - ;; - os68k) - basic_machine=m68k-none - os=-os68k - ;; - pa-hitachi) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - paragon) - basic_machine=i860-intel - os=-osf - ;; - pbd) - basic_machine=sparc-tti - ;; - pbb) - basic_machine=m68k-tti - ;; - pc532 | pc532-*) - basic_machine=ns32k-pc532 - ;; - pentium | p5 | k5 | k6 | nexgen) - basic_machine=i586-pc - ;; - pentiumpro | p6 | 6x86 | athlon) - basic_machine=i686-pc - ;; - pentiumii | pentium2) - basic_machine=i686-pc - ;; - pentium-* | p5-* | k5-* | k6-* | nexgen-*) - basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentiumpro-* | p6-* | 6x86-* | athlon-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentiumii-* | pentium2-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pn) - basic_machine=pn-gould - ;; - power) basic_machine=power-ibm - ;; - ppc) basic_machine=powerpc-unknown - ;; - ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppcle | powerpclittle | ppc-le | powerpc-little) - basic_machine=powerpcle-unknown - ;; - ppcle-* | powerpclittle-*) - basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ps2) - basic_machine=i386-ibm - ;; - pw32) - basic_machine=i586-unknown - os=-pw32 - ;; - rom68k) - basic_machine=m68k-rom68k - os=-coff - ;; - rm[46]00) - basic_machine=mips-siemens - ;; - rtpc | rtpc-*) - basic_machine=romp-ibm - ;; - sa29200) - basic_machine=a29k-amd - os=-udi - ;; - sequent) - basic_machine=i386-sequent - ;; - sh) - basic_machine=sh-hitachi - os=-hms - ;; - sparclite-wrs) - basic_machine=sparclite-wrs - os=-vxworks - ;; - sps7) - basic_machine=m68k-bull - os=-sysv2 - ;; - spur) - basic_machine=spur-unknown - ;; - st2000) - basic_machine=m68k-tandem - ;; - stratus) - basic_machine=i860-stratus - os=-sysv4 - ;; - sun2) - basic_machine=m68000-sun - ;; - sun2os3) - basic_machine=m68000-sun - os=-sunos3 - ;; - sun2os4) - basic_machine=m68000-sun - os=-sunos4 - ;; - sun3os3) - basic_machine=m68k-sun - os=-sunos3 - ;; - sun3os4) - basic_machine=m68k-sun - os=-sunos4 - ;; - sun4os3) - basic_machine=sparc-sun - os=-sunos3 - ;; - sun4os4) - basic_machine=sparc-sun - os=-sunos4 - ;; - sun4sol2) - basic_machine=sparc-sun - os=-solaris2 - ;; - sun3 | sun3-*) - basic_machine=m68k-sun - ;; - sun4) - basic_machine=sparc-sun - ;; - sun386 | sun386i | roadrunner) - basic_machine=i386-sun - ;; - sv1) - basic_machine=sv1-cray - os=-unicos - ;; - symmetry) - basic_machine=i386-sequent - os=-dynix - ;; - t3e) - basic_machine=t3e-cray - os=-unicos - ;; - tic54x | c54x*) - basic_machine=tic54x-unknown - os=-coff - ;; - tx39) - basic_machine=mipstx39-unknown - ;; - tx39el) - basic_machine=mipstx39el-unknown - ;; - tower | tower-32) - basic_machine=m68k-ncr - ;; - udi29k) - basic_machine=a29k-amd - os=-udi - ;; - ultra3) - basic_machine=a29k-nyu - os=-sym1 - ;; - v810 | necv810) - basic_machine=v810-nec - os=-none - ;; - vaxv) - basic_machine=vax-dec - os=-sysv - ;; - vms) - basic_machine=vax-dec - os=-vms - ;; - vpp*|vx|vx-*) - basic_machine=f301-fujitsu - ;; - vxworks960) - basic_machine=i960-wrs - os=-vxworks - ;; - vxworks68) - basic_machine=m68k-wrs - os=-vxworks - ;; - vxworks29k) - basic_machine=a29k-wrs - os=-vxworks - ;; - w65*) - basic_machine=w65-wdc - os=-none - ;; - w89k-*) - basic_machine=hppa1.1-winbond - os=-proelf - ;; - xmp) - basic_machine=xmp-cray - os=-unicos - ;; - xps | xps100) - basic_machine=xps100-honeywell - ;; - z8k-*-coff) - basic_machine=z8k-unknown - os=-sim - ;; - none) - basic_machine=none-none - os=-none - ;; - -# Here we handle the default manufacturer of certain CPU types. It is in -# some cases the only manufacturer, in others, it is the most popular. - w89k) - basic_machine=hppa1.1-winbond - ;; - op50n) - basic_machine=hppa1.1-oki - ;; - op60c) - basic_machine=hppa1.1-oki - ;; - mips) - if [ x$os = x-linux-gnu ]; then - basic_machine=mips-unknown - else - basic_machine=mips-mips - fi - ;; - romp) - basic_machine=romp-ibm - ;; - rs6000) - basic_machine=rs6000-ibm - ;; - vax) - basic_machine=vax-dec - ;; - pdp10) - # there are many clones, so DEC is not a safe bet - basic_machine=pdp10-unknown - ;; - pdp11) - basic_machine=pdp11-dec - ;; - we32k) - basic_machine=we32k-att - ;; - sh3 | sh4) - basic_machine=sh-unknown - ;; - sparc | sparcv9 | sparcv9b) - basic_machine=sparc-sun - ;; - cydra) - basic_machine=cydra-cydrome - ;; - orion) - basic_machine=orion-highlevel - ;; - orion105) - basic_machine=clipper-highlevel - ;; - mac | mpw | mac-mpw) - basic_machine=m68k-apple - ;; - pmac | pmac-mpw) - basic_machine=powerpc-apple - ;; - c4x*) - basic_machine=c4x-none - os=-coff - ;; - *-unknown) - # Make sure to match an already-canonicalized machine name. - ;; - *) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 - exit 1 - ;; -esac - -# Here we canonicalize certain aliases for manufacturers. -case $basic_machine in - *-digital*) - basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` - ;; - *-commodore*) - basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` - ;; - *) - ;; -esac - -# Decode manufacturer-specific aliases for certain operating systems. - -if [ x"$os" != x"" ] -then -case $os in - # First match some system type aliases - # that might get confused with valid system types. - # -solaris* is a basic system type, with this one exception. - -solaris1 | -solaris1.*) - os=`echo $os | sed -e 's|solaris1|sunos4|'` - ;; - -solaris) - os=-solaris2 - ;; - -svr4*) - os=-sysv4 - ;; - -unixware*) - os=-sysv4.2uw - ;; - -gnu/linux*) - os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` - ;; - # First accept the basic system types. - # The portable systems comes first. - # Each alternative MUST END IN A *, to match a version number. - # -sysv* is not here because it comes later, after sysvr4. - -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ - | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ - | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ - | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ - | -aos* \ - | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ - | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ - | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \ - | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ - | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ - | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ - | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ - | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \ - | -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \ - | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ - | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* | -os2*) - # Remember, each alternative MUST END IN *, to match a version number. - ;; - -qnx*) - case $basic_machine in - x86-* | i*86-*) - ;; - *) - os=-nto$os - ;; - esac - ;; - -nto*) - os=-nto-qnx - ;; - -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ - | -windows* | -osx | -abug | -netware* | -os9* | -beos* \ - | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) - ;; - -mac*) - os=`echo $os | sed -e 's|mac|macos|'` - ;; - -linux*) - os=`echo $os | sed -e 's|linux|linux-gnu|'` - ;; - -sunos5*) - os=`echo $os | sed -e 's|sunos5|solaris2|'` - ;; - -sunos6*) - os=`echo $os | sed -e 's|sunos6|solaris3|'` - ;; - -opened*) - os=-openedition - ;; - -wince*) - os=-wince - ;; - -osfrose*) - os=-osfrose - ;; - -osf*) - os=-osf - ;; - -utek*) - os=-bsd - ;; - -dynix*) - os=-bsd - ;; - -acis*) - os=-aos - ;; - -386bsd) - os=-bsd - ;; - -ctix* | -uts*) - os=-sysv - ;; - -ns2 ) - os=-nextstep2 - ;; - -nsk*) - os=-nsk - ;; - # Preserve the version number of sinix5. - -sinix5.*) - os=`echo $os | sed -e 's|sinix|sysv|'` - ;; - -sinix*) - os=-sysv4 - ;; - -triton*) - os=-sysv3 - ;; - -oss*) - os=-sysv3 - ;; - -svr4) - os=-sysv4 - ;; - -svr3) - os=-sysv3 - ;; - -sysvr4) - os=-sysv4 - ;; - # This must come after -sysvr4. - -sysv*) - ;; - -ose*) - os=-ose - ;; - -es1800*) - os=-ose - ;; - -xenix) - os=-xenix - ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) - os=-mint - ;; - -none) - ;; - *) - # Get rid of the `-' at the beginning of $os. - os=`echo $os | sed 's/[^-]*-//'` - echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 - exit 1 - ;; -esac -else - -# Here we handle the default operating systems that come with various machines. -# The value should be what the vendor currently ships out the door with their -# machine or put another way, the most popular os provided with the machine. - -# Note that if you're going to try to match "-MANUFACTURER" here (say, -# "-sun"), then you have to tell the case statement up towards the top -# that MANUFACTURER isn't an operating system. Otherwise, code above -# will signal an error saying that MANUFACTURER isn't an operating -# system, and we'll never get to this point. - -case $basic_machine in - *-acorn) - os=-riscix1.2 - ;; - arm*-rebel) - os=-linux - ;; - arm*-semi) - os=-aout - ;; - pdp10-*) - os=-tops20 - ;; - pdp11-*) - os=-none - ;; - *-dec | vax-*) - os=-ultrix4.2 - ;; - m68*-apollo) - os=-domain - ;; - i386-sun) - os=-sunos4.0.2 - ;; - m68000-sun) - os=-sunos3 - # This also exists in the configure program, but was not the - # default. - # os=-sunos4 - ;; - m68*-cisco) - os=-aout - ;; - mips*-cisco) - os=-elf - ;; - mips*-*) - os=-elf - ;; - *-tti) # must be before sparc entry or we get the wrong os. - os=-sysv3 - ;; - sparc-* | *-sun) - os=-sunos4.1.1 - ;; - *-be) - os=-beos - ;; - *-ibm) - os=-aix - ;; - *-wec) - os=-proelf - ;; - *-winbond) - os=-proelf - ;; - *-oki) - os=-proelf - ;; - *-hp) - os=-hpux - ;; - *-hitachi) - os=-hiux - ;; - i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) - os=-sysv - ;; - *-cbm) - os=-amigaos - ;; - *-dg) - os=-dgux - ;; - *-dolphin) - os=-sysv3 - ;; - m68k-ccur) - os=-rtu - ;; - m88k-omron*) - os=-luna - ;; - *-next ) - os=-nextstep - ;; - *-sequent) - os=-ptx - ;; - *-crds) - os=-unos - ;; - *-ns) - os=-genix - ;; - i370-*) - os=-mvs - ;; - *-next) - os=-nextstep3 - ;; - *-gould) - os=-sysv - ;; - *-highlevel) - os=-bsd - ;; - *-encore) - os=-bsd - ;; - *-sgi) - os=-irix - ;; - *-siemens) - os=-sysv4 - ;; - *-masscomp) - os=-rtu - ;; - f30[01]-fujitsu | f700-fujitsu) - os=-uxpv - ;; - *-rom68k) - os=-coff - ;; - *-*bug) - os=-coff - ;; - *-apple) - os=-macos - ;; - *-atari*) - os=-mint - ;; - *) - os=-none - ;; -esac -fi - -# Here we handle the case where we know the os, and the CPU type, but not the -# manufacturer. We pick the logical manufacturer. -vendor=unknown -case $basic_machine in - *-unknown) - case $os in - -riscix*) - vendor=acorn - ;; - -sunos*) - vendor=sun - ;; - -aix*) - vendor=ibm - ;; - -beos*) - vendor=be - ;; - -hpux*) - vendor=hp - ;; - -mpeix*) - vendor=hp - ;; - -hiux*) - vendor=hitachi - ;; - -unos*) - vendor=crds - ;; - -dgux*) - vendor=dg - ;; - -luna*) - vendor=omron - ;; - -genix*) - vendor=ns - ;; - -mvs* | -opened*) - vendor=ibm - ;; - -ptx*) - vendor=sequent - ;; - -vxsim* | -vxworks*) - vendor=wrs - ;; - -aux*) - vendor=apple - ;; - -hms*) - vendor=hitachi - ;; - -mpw* | -macos*) - vendor=apple - ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) - vendor=atari - ;; - esac - basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` - ;; -esac - -echo $basic_machine$os -exit 0 - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "timestamp='" -# time-stamp-format: "%:y-%02m-%02d" -# time-stamp-end: "'" -# End: diff --git a/config/install.sh b/config/install.sh deleted file mode 100755 index e69de29b..00000000 diff --git a/configure.ac b/configure.ac index f4f497aa..586fa831 100644 --- a/configure.ac +++ b/configure.ac @@ -1,148 +1,34 @@ # Process this file with autoconf to produce a configure script. -AC_INIT(RtMidi, 2.1.0, gary@music.mcgill.ca, rtmidi) -AC_CONFIG_AUX_DIR(config) -AC_CONFIG_SRCDIR(RtMidi.cpp) -AC_CONFIG_FILES([rtmidi-config librtmidi.pc Makefile tests/Makefile]) - -# Fill GXX with something before test. -AC_SUBST( GXX, ["no"] ) - -# Checks for programs. -AC_PROG_CXX(g++ CC c++ cxx) -AC_PROG_RANLIB -AC_PATH_PROG(AR, ar, no) -if [[ $AR = "no" ]] ; then - AC_MSG_ERROR("Could not find ar - needed to create a library"); -fi - -# Checks for header files. -AC_HEADER_STDC -#AC_CHECK_HEADERS(sys/ioctl.h unistd.h) - -# Check for debug -AC_MSG_CHECKING(whether to compile debug version) -AC_ARG_ENABLE(debug, - [ --enable-debug = enable various debug output], - [AC_SUBST( cppflag, [-D__RTMIDI_DEBUG__] ) AC_SUBST( cxxflag, [-g] ) AC_SUBST( object_path, [Debug] ) AC_MSG_RESULT(yes)], - [AC_SUBST( cppflag, [] ) AC_SUBST( cxxflag, [-O3] ) AC_SUBST( object_path, [Release] ) AC_MSG_RESULT(no)]) - -# Set paths if prefix is defined -if test "x$prefix" != "x" && test "x$prefix" != "xNONE"; then - LIBS="$LIBS -L$prefix/lib" - CPPFLAGS="$CPPFLAGS -I$prefix/include" -fi - -# For -I and -D flags -CPPFLAGS="$CPPFLAGS $cppflag" - -# For debugging and optimization ... overwrite default because it has both -g and -O2 -#CXXFLAGS="$CXXFLAGS $cxxflag" -CXXFLAGS="$cxxflag" +#AC_INIT(RtMidi, 2.1.0, gary@music.mcgill.ca, rtmidi) -# Check compiler and use -Wall if gnu. -if [test $GXX = "yes" ;] then - AC_SUBST( cxxflag, ["-Wall -Wextra"] ) -fi +m4_include(configure.version) -CXXFLAGS="$CXXFLAGS $cxxflag" +m4_define([ac_rtmidi_version],[lt_current.lt_revision.lt_age]) -# Checks for package options and external software -AC_CANONICAL_HOST -AC_SUBST( sharedlib, ["librtmidi.so"] ) -AC_SUBST( sharedname, ["librtmidi.so.\$(RELEASE)"] ) -AC_SUBST( libflags, ["-shared -Wl,-soname,\$(SHARED).\$(MAJOR) -o \$(SHARED).\$(RELEASE)"] ) -case $host in - *-apple*) - AC_SUBST( sharedlib, ["librtmidi.dylib"] ) - AC_SUBST( sharedname, ["librtmidi.\$(RELEASE).dylib"] ) - AC_SUBST( libflags, ["-dynamiclib -o librtmidi.\$(RELEASE).dylib"] ) -esac - -AC_SUBST( api, [""] ) -AC_SUBST( req, [""] ) -AC_MSG_CHECKING(for MIDI API) -case $host in - *-*-linux*) - AC_ARG_WITH(jack, [ --with-jack = choose JACK server support (mac and linux only)], [ - api="$api -D__UNIX_JACK__" - AC_MSG_RESULT(using JACK) - AC_CHECK_LIB(jack, jack_client_open, , AC_MSG_ERROR(JACK support requires the jack library!))], ) - - # Look for ALSA flag - AC_ARG_WITH(alsa, [ --with-alsa = choose native ALSA sequencer API support (linux only)], [ - api="$api -D__LINUX_ALSA__" - req="$req alsa" - AC_MSG_RESULT(using ALSA) - AC_CHECK_LIB(asound, snd_seq_open, , AC_MSG_ERROR(ALSA support requires the asound library!))], ) - - if [test "$api" == "";] then - AC_MSG_RESULT(using ALSA) - AC_SUBST( api, [-D__LINUX_ALSA__] ) - req="$req alsa" - AC_CHECK_LIB(asound, snd_seq_open, , AC_MSG_ERROR(ALSA sequencer support requires the asound library!)) - fi - - # Checks for pthread library. - AC_CHECK_LIB(pthread, pthread_create, , AC_MSG_ERROR(RtMidi requires the pthread library!)) - ;; - - *-apple*) - AC_ARG_WITH(jack, [ --with-jack = choose JACK server support (mac and linux only)], [ - api="$api -D__UNIX_JACK__" - AC_MSG_RESULT(using JACK) - AC_CHECK_LIB(jack, jack_client_open, , AC_MSG_ERROR(JACK support requires the jack library!))], ) - - # Look for Core flag - AC_ARG_WITH(core, [ --with-core = choose CoreMidi API support (mac only)], [ - api="$api -D__MACOSX_CORE__" - AC_MSG_RESULT(using CoreMidi) - AC_CHECK_HEADER(CoreMIDI/CoreMIDI.h, [], [AC_MSG_ERROR(CoreMIDI header files not found!)] ) - LIBS="$LIBS -framework CoreMIDI -framework CoreFoundation -framework CoreAudio" ], ) +AC_INIT(RtMidi-ts, ac_rtmidi_version, keinstein_junior@gmx.net, rtmidi-ts) +AC_CONFIG_AUX_DIR(config) +AC_CONFIG_SRCDIR(RtMidi.cpp) +AC_CONFIG_FILES([Makefile doc/Makefile po/Makefile.in rtmidi-config rtmidi.pc doc/doxygen/Doxyfile],[chmod oug+x rtmidi-config]) +AM_INIT_AUTOMAKE([1.14 -Wall -Werror foreign subdir-objects]) - # If no api flags specified, use CoreMidi - if [test "$api" == ""; ] then - AC_SUBST( api, [-D__MACOSX_CORE__] ) - AC_MSG_RESULT(using CoreMidi) - AC_CHECK_HEADER(CoreMIDI/CoreMIDI.h, - [], - [AC_MSG_ERROR(CoreMIDI header files not found!)] ) - AC_SUBST( LIBS, ["-framework CoreMIDI -framework CoreFoundation -framework CoreAudio"] ) - fi - ;; - *-mingw32*) - # Look for WinMM flag - AC_ARG_WITH(winmm, [ --with-winmm = choose Windows MultiMedia (MM) API support (windoze only)], [ - api="$api -D__WINDOWS_MM__" - AC_MSG_RESULT(using WinMM) - AC_SUBST( LIBS, [-lwinmm] )], ) - AC_ARG_WITH(winks, [ --with-winks = choose kernel streaming support (windoze only)], [ - api="$api -D__WINDOWS_KS__" - AC_SUBST( LIBS, ["-lsetupapi -lksuser"] ) - AC_MSG_RESULT(using kernel streaming) ], ) +# Fill GXX with something before test. +GXX="no" - # I can't get the following check to work so just manually add the library - # or could try the following? AC_LIB_WINMM([midiOutGetNumDevs]) - # AC_CHECK_LIB(winmm, midiInGetNumDevs, , AC_MSG_ERROR(Windows MIDI support requires the winmm library!) )],) +# Enable some nice automake features if they are available +m4_ifdef([AM_MAINTAINER_MODE], [AM_MAINTAINER_MODE]) +m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) - # If no api flags specified, use WinMM - if [test "$api" == "";] then - AC_SUBST( api, [-D__WINDOWS_MM__] ) - AC_MSG_RESULT(using WinMM) - AC_SUBST( LIBS, [-lwinmm] ) - fi - ;; - *) - # Default case for unknown realtime systems. - AC_MSG_ERROR(Unknown system type for MIDI support!) - ;; -esac +AC_CONFIG_MACRO_DIR([m4]) -CPPFLAGS="$CPPFLAGS $api" +rtmidi_suffix="-ts" +rtmidi_standalone="yes" +SUBDIRS="$SUBDIRS %D%/po" +rtmidi_subdir="$srcdir" +m4_include(configure.library) AC_OUTPUT -chmod oug+x rtmidi-config diff --git a/configure.library b/configure.library new file mode 100644 index 00000000..b84b5393 --- /dev/null +++ b/configure.library @@ -0,0 +1,383 @@ +# -*- Autoconf -*- +# Process this file with autoconf to produce a configure script. +ifdef([lt_current],,[m4_include(configure.version)]) + +m4_define([lt_version_info], [lt_current:lt_revision:lt_age]) +m4_define([lt_current_minus_age], [m4_eval(lt_current - lt_age)]) + +RTMIDI_SO_VERSION=lt_version_info +AC_SUBST(RTMIDI_SO_VERSION) + +# Checks for package options and external software +AC_CANONICAL_HOST + +# initialize the variables for the makefile +AC_SUBST(noinst_LIBRARIES) +AC_SUBST(noinst_PROGRAMS) +AC_SUBST(TESTS) +dnl AC_SUBST(SUBDIRS) +AC_SUBST(lib_LTLIBRARIES) +AC_SUBST(EXTRA_DIST) +AC_SUBST(RTMIDI_TS_SUFFIX,[ts]) +AC_SUBST(rtmidi_visibility) +AC_SUBST(rtmidi_pkconfig_requirements) +AM_CONDITIONAL(RTMIDI_STANDALONE,test "$rtmidi_standalone" = "yes") +# Checks for programs. +AC_PROG_CXX +AM_PROG_AR +dnl AC_PATH_PROG(AR, ar, no) +dnl if [[ $AR = "no" ]] ; then +dnl AC_MSG_ERROR("Could not find ar - needed to create a library"); +dnl fi + + + +LT_INIT([win32-dll]) + +AC_LANG_PUSH(C++) +AX_CXX_COMPILE_STDCXX(11) + +rtmidi_test_flags="-Wall -Wextra" +rtmidi_visibility="-fvisibility=hidden" + +# Checks for header files. +AC_HEADER_STDC +#AC_CHECK_HEADERS(sys/ioctl.h unistd.h) + +# Check version number coherency between RtMidi.h and configure.ac +AC_MSG_CHECKING([that version numbers are coherent]) +RTMIDI_VERSION=`sed -n 's/#define RTMIDI_VERSION "\(.*\)"/\1/p' "$rtmidi_subdir/RtMidi.h"` +AS_IF( + [test "x$RTMIDI_VERSION" != "x$PACKAGE_VERSION"], + [AC_MSG_FAILURE([testing RTMIDI_VERSION==PACKAGE_VERSION failed, check that RtMidi.h defines RTMIDI_VERSION as "$PACKAGE_VERSION" or that the first line of configure.ac has been updated.])]) + + + + +AC_ARG_WITH(suffix, +AS_HELP_STRING([--with-suffix],[add a suffix to the library. Default is $rtmidi_suffix]), +[AS_IF(test "x$with_suffix" = "xno", + [ rtmidi_suffix=""], + [ rtmidi_suffix="$with_suffix"])]) +AC_SUBST(rtmidi_suffix) + + + +# Check for debug +AC_MSG_CHECKING(whether to compile debug version) +AC_ARG_ENABLE(debug, +AS_HELP_STRING([--enable-debug],[enable various debug output]), + [ + AC_SUBST( RTMIDI_CPPFLAGS, [-D__RTMIDI_DEBUG__] ) + AC_SUBST( RTMIDI_CXXFLAGS, [-g] ) + AC_SUBST( object_path, [Debug] ) + AC_MSG_RESULT(yes)], + [AC_SUBST( RTMIDI_CPPFLAGS, [] ) + AC_SUBST( RTMIDI_CXXFLAGS, [-O3] ) + AC_SUBST( object_path, [Release] ) + rtmidi_visibility="${rtmidi_visibility} -fvisibility=hidden" + AC_MSG_RESULT(no)]) + + +# Checks for doxygen +AC_CHECK_PROG( DOXYGEN, [doxygen], [doxygen] ) +AM_CONDITIONAL( MAKE_DOC, [test "x${DOXYGEN}" != x] ) + +# Copy doc files to build dir if necessary +AC_CONFIG_LINKS( [doc/doxygen/footer.html:doc/doxygen/footer.html] ) +AC_CONFIG_LINKS( [doc/doxygen/header.html:doc/doxygen/header.html] ) +AC_CONFIG_LINKS( [doc/doxygen/tutorial.txt:doc/doxygen/tutorial.txt] ) +AC_CONFIG_LINKS( [doc/images/ccrma.gif:doc/images/ccrma.gif] ) +AC_CONFIG_LINKS( [doc/images/mcgill.gif:doc/images/mcgill.gif] ) + + +dnl # Set paths if prefix is defined +dnl if test "x$prefix" != "x" && test "x$prefix" != "xNONE"; then +dnl LIBS="$LIBS -L$prefix/lib" +dnl CPPFLAGS="$CPPFLAGS -I$prefix/include" +dnl fi + +# Check compiler and use -Wall if supported. +for flag in $rtmidi_test_flags +do + tmpcxxflags="$CXXFLAGS" + CXXFLAGS="$CXXFLAGS $flag" + AC_MSG_CHECKING([whether $CXX supports $flag]) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]],[[]])], + [AC_MSG_RESULT([yes])], + [CXXFLAGS="$tmpcxxflags" + AC_MSG_RESULT([no])]) + AC_LANG_PUSH(C) + tmpcflags="$CFLAGS" + CFLAGS="$CFLAGS $flag" + AC_MSG_CHECKING([whether $CC supports $flag]) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]],[[]])], + [AC_MSG_RESULT([yes])], + [CFLAGS="$tmpcflags" + AC_MSG_RESULT([no])]) + AC_LANG_POP(C) +done + +# Check compiler and use -Wall if supported. +tmpcflags="$CFLAGS" +tmpcxxflags="$CXXFLAGS" +rtmidi_visibility_result="" +for flag in $rtmidi_visibility +do + CXXFLAGS="$tmpcxxflags $rtmidi_visibility_result $flag" + AC_MSG_CHECKING([whether $CXX supports $flag]) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]],[[]])], + [ + rtmidi_visibility_result="$rtmidi_visibility_result $flag" + AC_MSG_RESULT([yes]) + ],[AC_MSG_RESULT([no])]) +done +rtmidi_visibility="$rtmidi_visibility_result" + + +dnl mudflap is not possible with g++ 4.7.1 and wxWidgets 2.8 +dnl tmpcxxflags="$CXXFLAGS" +dnl tmplibs="$LIBS" +dnl CXXFLAGS="$CXXFLAGS -fmudflapth" +dnl LIBS="-lmudflapth" +dnl AC_MSG_CHECKING([whether $CXX supports -fmudflapth -lmudflapth]) +dnl AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]],[[]])], +dnl [AC_MSG_RESULT([yes])], +dnl [CXXFLAGS="$tmpcxxflags" +dnl LIBS="$tmplibs"] +dnl [AC_MSG_RESULT([no])]) +dnl + +AC_ARG_ENABLE(address-sanitizer, + AS_HELP_STRING([--enable-address-sanitizer],[Enable gcc/clang address santizer]), + [AS_IF(test "$enableval" = yes, + + AC_LANG_PUSH(C++) + for flag in -fsanitize=address -fno-omit-frame-pointer -fno-common + do + tmpcxxflags="$CXXFLAGS" + CXXFLAGS="$CXXFLAGS $flag" + AC_MSG_CHECKING([whether $CXX supports $flag]) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]],[[]])], + [AC_MSG_RESULT([yes])], + [CXXFLAGS="$tmpcxxflags" + AC_MSG_RESULT([no])]) + AC_LANG_PUSH(C) + tmpcflags="$CFLAGS" + CFLAGS="$CFLAGS $flag" + AC_MSG_CHECKING([whether $CC supports $flag]) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]],[[]])], + [AC_MSG_RESULT([yes])], + [CFLAGS="$tmpcflags" + AC_MSG_RESULT([no])]) + AC_LANG_POP(C) + done + AC_LANG_POP(C++) + ) + ] +) + +AC_ARG_ENABLE(thread-sanitizer, + AS_HELP_STRING([--enable-thread-sanitizer],[Enable gcc/clang thread santizer]), + [AS_IF(test "$enableval" = yes, + AC_LANG_PUSH(C++) + for flag in -fsanitize=thread -fno-omit-frame-pointer -fno-common -fPIC + do + tmpcxxflags="$CXXFLAGS" + CXXFLAGS="$CXXFLAGS $flag" + AC_MSG_CHECKING([whether $CXX supports $flag]) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]],[[]])], + [AC_MSG_RESULT([yes])], + [CXXFLAGS="$tmpcxxflags" + AC_MSG_RESULT([no])]) + AC_LANG_PUSH(C) + tmpcflags="$CFLAGS" + CFLAGS="$CFLAGS $flag" + AC_MSG_CHECKING([whether $CC supports $flag]) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]],[[]])], + [AC_MSG_RESULT([yes])], + [CFLAGS="$tmpcflags" + AC_MSG_RESULT([no])]) + AC_LANG_POP(C) + done + for flag in -pie + do + tmpldflags="$LDFLAGS" + LDFLAGS="$LDFLAGS $flag" + AC_MSG_CHECKING([whether $LD supports $flag]) + AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])], + [AC_MSG_RESULT([yes])], + [LDFLAGS="$tmpldflags" + AC_MSG_RESULT([no])]) + done + AC_LANG_POP(C++) + ) + ] +) + +dnl AC_SUBST( sharedlib, ["librtmidi.so"] ) +dnl AC_SUBST( sharedname, ["librtmidi.so.\$(RELEASE)"] ) +dnl AC_SUBST( libflags, ["-shared -Wl,-soname,\$(SHARED).\$(MAJOR) -o \$(SHARED).\$(RELEASE)"] ) +dnl case $host in +dnl *-apple*) +dnl AC_SUBST( sharedlib, ["librtmidi.dylib"] ) +dnl AC_SUBST( sharedname, ["librtmidi.\$(RELEASE).dylib"] ) +dnl AC_SUBST( libflags, ["-dynamiclib -o librtmidi.\$(RELEASE).dylib"] ) +dnl esac + + + +dnl sem_timedwait may not be availlable on Mac OS X +# Check for POSIX semaphore support +AC_CHECK_HEADER([semaphore.h], [ + AC_CHECK_LIB(pthread, sem_timedwait, + AC_DEFINE([HAVE_SEMAPHORE],[1],[Define to 1 if you have POSIX semaphore support on your system.]), + AC_MSG_WARN([POSIX semaphore support not found; data may be lost on closePort])) +]) + +AC_MSG_CHECKING(whether to check all apis) +AC_ARG_ENABLE(apisearch, + AS_HELP_STRING([--disable-apisearch],[disable all unrequested apis]), + [ + AS_IF([test "x$enableval" = "xno"],[ + AC_MSG_RESULT(no) + AS_IF([test "x$with_alsa" = "x"],[with_alsa=no]) + AS_IF([test "x$with_jack" = "x"],[with_jack=no]) + AS_IF([test "x$with_winmm" = "x"],[with_winmm=no]) + AS_IF([test "x$with_winks" = "x"],[with_winks=no]) + AS_IF([test "x$with_coremidi" = "x"],[with_coremidi=no]) + ],[AC_MSG_RESULT(yes)]) + ],[AC_MSG_RESULT(yes)]) + +AC_SUBST( RTMIDI_API, [""] ) +AC_SUBST( RTMIDI_LIB_CFLAGS, [""] ) +AC_SUBST( RTMIDI_LIBS, [""] ) +AC_MSG_CHECKING(for MIDI API) +RTMIDI_HAVE_VIRTUAL_DEVICES=no +rtmidi_check_jack=auto +case $host in +*linux*) + PLATFORM=linux +dnl with_winmm=no +dnl with_winks=no +dnl with_coremidi=no + + # Checks for pthread library. + ;; + +darwin*|*apple*) + PLATFORM=macosx + # Check for CoreAudio framework +dnl with_winmm=no +dnl with_winks=no +dnl with_alsa=no + + ;; + +*winnt*|*interix*|cygwin*|*mingw*|uwin*) + PLATFORM=windows +dnl with_alsa=no +dnl with_coremidi=no + + # I can't get the following check to work so just manually add the library + # or could try the following? AC_LIB_WINMM([midiOutGetNumDevs]) + # AC_CHECK_LIB(winmm, midiInGetNumDevs, , AC_MSG_ERROR(Windows MIDI support requires the winmm library!) )],) + AC_CACHE_CHECK([where to find support dlls], [ac_cv_rtmidi_ts_mingw_dll_dirs], + [ + gccsearchdirs=`$CXX $CXXFLAGS -print-search-dirs|\ + sed -e '/^libraries:/ { s/^libraries: *=\?//; /;\([0-9a-zA-Z]\):/ { s,;\([0-9a-zA-Z]\):,:/\1/,g;s,^\([0-9a-zA-Z]\):,/\1/,g; s,\\\\,/,g } ; p } ; d'` ; \ + gccsearchdirs="$WINEDLLPATH:$gccsearchdirs:\ +/usr/share/doc/mingw32-runtime:\ +/usr/$host/bin:\ +/usr/$host/lib:\ +/usr/bin/$host/:\ +/usr/lib/$host/:\ +/usr/lib/$host/lib:\ +/usr/lib/$host/bin:\ +/usr/bin/$host/lib:\ +/usr/bin/$host/bin:\ +/mingw/lib:\ +/mingw/bin:\ +/usr/lib:\ +/lib:\ +/usr/bin:\ +/bin" + SEARCHDIRS="$PWD:$PWD/.libs" + old_FS="$IFS" + IFS=: + for d in $gccsearchdirs ; + do + AS_IF(test -d "$d",[ SEARCHDIRS="$SEARCHDIRS:$d" ]) + done + IFS="$old_FS" + ac_cv_rtmidi_ts_mingw_dll_dirs="$SEARCHDIRS" + ]) + + AC_SUBST(DLLSEARCHPATH,"$ac_cv_rtmidi_ts_mingw_dll_dirs") + rtmidicopydlls=true + ;; + +*) + # Default case for unknown realtime systems. + AC_MSG_WARN([ + Your target system could not be recognized. $PACKAGE depends on + a working MIDI configuration for your System. We are trying all + supported APIs. The result may be varying. + + Please contact the development team at + + $PACKAGE_BUGREPORT + + and provide the following information: + + * The output of configure + * The description of your System. + + ]) + ;; +esac + +AC_ARG_WITH(jack, + AS_HELP_STRING([--with-jack],[choose JACK server support (needs libjack to be installed)]),[ + echo running jack: + AS_IF([test "x$with_jack" = "xno"],,[RTMIDI_LIB_JACK ]) + ],[ echo runnning jack 2 ; RTMIDI_LIB_JACK(,[true]) ]) + +AC_ARG_WITH(alsa, AS_HELP_STRING([--with-alsa],[choose native ALSA sequencer API support]),[ + AS_IF([test "x$with_alsa" = "xno"],,[ RTMIDI_LIB_ALSA ]) + ],[ RTMIDI_LIB_ALSA(,[true]) ]) + +AC_ARG_WITH(winmm, AS_HELP_STRING([--with-winmm],[choose native Windows Multimedia API support]),[ + AS_IF([test "x$with_winmm" = "xno"],,[RTMIDI_LIB_WINMM ]) + ],[ RTMIDI_LIB_WINMM(,[true]) ]) + +AC_ARG_WITH(winks, AS_HELP_STRING([--with-winks],[choose native Windows kernel streaming API support]),[ + AS_IF([test "x$with_winks" = "xno"],,[ RTMIDI_LIB_WINKS ]) + ],[ RTMIDI_LIB_WINKS(,[true]) ]) + +AC_ARG_WITH(coremidi, AS_HELP_STRING([--with-coremidi],[choose native CoreAudio API support]),[ + AS_IF([test "x$with_coremidi" = "xno"],,[RTMIDI_LIB_COREMIDI ]) + ],[ RTMIDI_LIB_COREMIDI(,[true]) ]) + +AS_IF([test "x$RTMIDI_API" = "x"],[ + AC_MSG_WARN("No suitable MIDI interface found. Using dummy driver") + RTMIDI_API="-D__RTMIDI_DUMMY__" +]) + +AM_CONDITIONAL(RTMIDI_HAVE_VIRTUAL_DEVICES,test "$RTMIDI_HAVE_VIRTUAL_DEVICES" == yes) +AM_GNU_GETTEXT([external]) +AM_GNU_GETTEXT_VERSION([0.18.3]) + +if test "x$rtmidicopydlls" = "x" +then + rtmidicopydlls=false +fi + +AM_CONDITIONAL(RTMIDICOPYDLLS,$rtmidicopydlls && test -n "$DLLSEARCHPATH") + + +AX_CHECK_FALLTHROUGH_SYNTAX +AC_DEFINE_UNQUOTED(RTMIDI_FALLTHROUGH, + [$ax_cv_check_cxx_fallthrough_syntax_], + [syntax for switch case fallthrough attributes in C++]) +AC_LANG_POP(C++) diff --git a/configure.version b/configure.version new file mode 100644 index 00000000..015bd7f5 --- /dev/null +++ b/configure.version @@ -0,0 +1,16 @@ +# libtool version: current:revision:age +# +# If the library source code has changed at all since the last update, then +# increment revision (`c:r:a' becomes `c:r+1:a'). +# +# If any interfaces have been added, removed, or changed since the last update, +# increment current, and set revision to 0. +# +# If any interfaces have been added since the last public release, then +# increment age. +# +# If any interfaces have been removed since the last public release, then set +# age to 0. +m4_define([lt_current], 4) +m4_define([lt_revision], 0) +m4_define([lt_age], 0) diff --git a/contrib/go/rtmidi/rtmidi.go b/contrib/go/rtmidi/rtmidi.go new file mode 100644 index 00000000..0ac7decb --- /dev/null +++ b/contrib/go/rtmidi/rtmidi.go @@ -0,0 +1,355 @@ +package rtmidi + +/* +#cgo CXXFLAGS: -g +#cgo LDFLAGS: -g + +#cgo linux CXXFLAGS: -D__LINUX_ALSA__ +#cgo linux LDFLAGS: -lasound -pthread +#cgo windows CXXFLAGS: -D__WINDOWS_MM__ +#cgo windows LDFLAGS: -luuid -lksuser -lwinmm -lole32 +#cgo darwin CXXFLAGS: -D__MACOSX_CORE__ +#cgo darwin LDFLAGS: -framework CoreServices -framework CoreAudio -framework CoreMIDI -framework CoreFoundation + +#include +#include +#include "rtmidi_stub.h" + +extern void goMIDIInCallback(double ts, unsigned char *msg, size_t msgsz, void *arg); + +static inline void midiInCallback(double ts, const unsigned char *msg, size_t msgsz, void *arg) { + goMIDIInCallback(ts, (unsigned char*) msg, msgsz, arg); +} + +static inline void cgoSetCallback(RtMidiPtr in, int cb_id) { + rtmidi_in_set_callback(in, midiInCallback, (void*)(uintptr_t) cb_id); +} +*/ +import "C" +import ( + "errors" + "sync" + "unsafe" +) + +// API is an enumeration of possible MIDI API specifiers. +type API C.enum_RtMidiApi + +const ( + // APIUnspecified searches for a working compiled API. + APIUnspecified API = C.RT_MIDI_API_UNSPECIFIED + // APIMacOSXCore uses Macintosh OS-X CoreMIDI API. + APIMacOSXCore = C.RT_MIDI_API_MACOSX_CORE + // APILinuxALSA uses the Advanced Linux Sound Architecture API. + APILinuxALSA = C.RT_MIDI_API_LINUX_ALSA + // APIUnixJack uses the JACK Low-Latency MIDI Server API. + APIUnixJack = C.RT_MIDI_API_UNIX_JACK + // APIWindowsMM uses the Microsoft Multimedia MIDI API. + APIWindowsMM = C.RT_MIDI_API_WINDOWS_MM + // APIDummy is a compilable but non-functional API. + APIDummy = C.RT_MIDI_API_RTMIDI_DUMMY +) + +func (api API) String() string { + switch api { + case APIUnspecified: + return "unspecified" + case APILinuxALSA: + return "alsa" + case APIUnixJack: + return "jack" + case APIMacOSXCore: + return "coreaudio" + case APIWindowsMM: + return "winmm" + case APIDummy: + return "dummy" + } + return "?" +} + +// CompiledAPI determines the available compiled MIDI APIs. +func CompiledAPI() (apis []API) { + n := C.rtmidi_get_compiled_api(nil, 0) + capis := make([]C.enum_RtMidiApi, n, n) + C.rtmidi_get_compiled_api(&capis[0], _Ctype_uint(n)) + for _, capi := range capis { + apis = append(apis, API(capi)) + } + return apis +} + +// MIDI interface provides a common, platform-independent API for realtime MIDI +// device enumeration and handling MIDI ports. +type MIDI interface { + OpenPort(port int, name string) error + OpenVirtualPort(name string) error + Close() error + PortCount() (int, error) + PortName(port int) (string, error) +} + +// MIDIIn interface provides a common, platform-independent API for realtime +// MIDI input. It allows access to a single MIDI input port. Incoming MIDI +// messages are either saved to a queue for retrieval using the Message() +// method or immediately passed to a user-specified callback function. Create +// multiple instances of this class to connect to more than one MIDI device at +// the same time. +type MIDIIn interface { + MIDI + API() (API, error) + IgnoreTypes(midiSysex bool, midiTime bool, midiSense bool) error + SetCallback(func(MIDIIn, []byte, float64)) error + CancelCallback() error + Message() ([]byte, float64, error) + Destroy() +} + +// MIDIOut interface provides a common, platform-independent API for MIDI +// output. It allows one to probe available MIDI output ports, to connect to +// one such port, and to send MIDI bytes immediately over the connection. +// Create multiple instances of this class to connect to more than one MIDI +// device at the same time. +type MIDIOut interface { + MIDI + API() (API, error) + SendMessage([]byte) error + Destroy() +} + +type midi struct { + midi C.RtMidiPtr +} + +func (m *midi) OpenPort(port int, name string) error { + p := C.CString(name) + defer C.free(unsafe.Pointer(p)) + C.rtmidi_open_port(m.midi, C.uint(port), p) + if !m.midi.ok { + return errors.New(C.GoString(m.midi.msg)) + } + return nil +} + +func (m *midi) OpenVirtualPort(name string) error { + p := C.CString(name) + defer C.free(unsafe.Pointer(p)) + C.rtmidi_open_virtual_port(m.midi, p) + if !m.midi.ok { + return errors.New(C.GoString(m.midi.msg)) + } + return nil +} + +func (m *midi) PortName(port int) (string, error) { + p := C.rtmidi_get_port_name(m.midi, C.uint(port)) + if !m.midi.ok { + return "", errors.New(C.GoString(m.midi.msg)) + } + defer C.free(unsafe.Pointer(p)) + return C.GoString(p), nil +} + +func (m *midi) PortCount() (int, error) { + n := C.rtmidi_get_port_count(m.midi) + if !m.midi.ok { + return 0, errors.New(C.GoString(m.midi.msg)) + } + return int(n), nil +} + +func (m *midi) Close() error { + C.rtmidi_close_port(C.RtMidiPtr(m.midi)) + if !m.midi.ok { + return errors.New(C.GoString(m.midi.msg)) + } + return nil +} + +type midiIn struct { + midi + in C.RtMidiInPtr + cb func(MIDIIn, []byte, float64) +} + +type midiOut struct { + midi + out C.RtMidiOutPtr +} + +// NewMIDIInDefault opens a default MIDIIn port. +func NewMIDIInDefault() (MIDIIn, error) { + in := C.rtmidi_in_create_default() + if !in.ok { + defer C.rtmidi_in_free(in) + return nil, errors.New(C.GoString(in.msg)) + } + return &midiIn{in: in, midi: midi{midi: C.RtMidiPtr(in)}}, nil +} + +// NewMIDIIn opens a single MIDIIn port using the given API. One can provide a +// custom port name and a desired queue size for the incomming MIDI messages. +func NewMIDIIn(api API, name string, queueSize int) (MIDIIn, error) { + p := C.CString(name) + defer C.free(unsafe.Pointer(p)) + in := C.rtmidi_in_create(C.enum_RtMidiApi(api), p, C.uint(queueSize)) + if !in.ok { + defer C.rtmidi_in_free(in) + return nil, errors.New(C.GoString(in.msg)) + } + return &midiIn{in: in, midi: midi{midi: C.RtMidiPtr(in)}}, nil +} + +func (m *midiIn) API() (API, error) { + api := C.rtmidi_in_get_current_api(m.in) + if !m.in.ok { + return APIUnspecified, errors.New(C.GoString(m.in.msg)) + } + return API(api), nil +} + +func (m *midiIn) Close() error { + unregisterMIDIIn(m) + if err := m.midi.Close(); err != nil { + return err + } + C.rtmidi_in_free(m.in) + return nil +} + +func (m *midiIn) IgnoreTypes(midiSysex bool, midiTime bool, midiSense bool) error { + C.rtmidi_in_ignore_types(m.in, C._Bool(midiSysex), C._Bool(midiTime), C._Bool(midiSense)) + if !m.in.ok { + return errors.New(C.GoString(m.in.msg)) + } + return nil +} + +var ( + mu sync.Mutex + inputs = map[int]*midiIn{} +) + +func registerMIDIIn(m *midiIn) int { + mu.Lock() + defer mu.Unlock() + for i := 0; ; i++ { + if _, ok := inputs[i]; !ok { + inputs[i] = m + return i + } + } +} + +func unregisterMIDIIn(m *midiIn) { + mu.Lock() + defer mu.Unlock() + for i := 0; i < len(inputs); i++ { + if inputs[i] == m { + delete(inputs, i) + return + } + } +} + +func findMIDIIn(k int) *midiIn { + mu.Lock() + defer mu.Unlock() + return inputs[k] +} + +//export goMIDIInCallback +func goMIDIInCallback(ts C.double, msg *C.uchar, msgsz C.size_t, arg unsafe.Pointer) { + k := int(uintptr(arg)) + m := findMIDIIn(k) + m.cb(m, C.GoBytes(unsafe.Pointer(msg), C.int(msgsz)), float64(ts)) +} + +func (m *midiIn) SetCallback(cb func(MIDIIn, []byte, float64)) error { + k := registerMIDIIn(m) + m.cb = cb + C.cgoSetCallback(m.in, C.int(k)) + if !m.in.ok { + return errors.New(C.GoString(m.in.msg)) + } + return nil +} + +func (m *midiIn) CancelCallback() error { + unregisterMIDIIn(m) + C.rtmidi_in_cancel_callback(m.in) + if !m.in.ok { + return errors.New(C.GoString(m.in.msg)) + } + return nil +} + +func (m *midiIn) Message() ([]byte, float64, error) { + msg := make([]C.uchar, 64*1024, 64*1024) + sz := C.size_t(len(msg)) + r := C.rtmidi_in_get_message(m.in, &msg[0], &sz) + if !m.in.ok { + return nil, 0, errors.New(C.GoString(m.in.msg)) + } + b := make([]byte, int(sz), int(sz)) + for i, c := range msg[:sz] { + b[i] = byte(c) + } + return b, float64(r), nil +} + +func (m *midiIn) Destroy() { + C.rtmidi_in_free(m.in) +} + +// NewMIDIOutDefault opens a default MIDIOut port. +func NewMIDIOutDefault() (MIDIOut, error) { + out := C.rtmidi_out_create_default() + if !out.ok { + defer C.rtmidi_out_free(out) + return nil, errors.New(C.GoString(out.msg)) + } + return &midiOut{out: out, midi: midi{midi: C.RtMidiPtr(out)}}, nil +} + +// NewMIDIOut opens a single MIDIIn port using the given API with the given port name. +func NewMIDIOut(api API, name string) (MIDIOut, error) { + p := C.CString(name) + defer C.free(unsafe.Pointer(p)) + out := C.rtmidi_out_create(C.enum_RtMidiApi(api), p) + if !out.ok { + defer C.rtmidi_out_free(out) + return nil, errors.New(C.GoString(out.msg)) + } + return &midiOut{out: out, midi: midi{midi: C.RtMidiPtr(out)}}, nil +} + +func (m *midiOut) API() (API, error) { + api := C.rtmidi_out_get_current_api(m.out) + if !m.out.ok { + return APIUnspecified, errors.New(C.GoString(m.out.msg)) + } + return API(api), nil +} + +func (m *midiOut) Close() error { + if err := m.midi.Close(); err != nil { + return err + } + C.rtmidi_out_free(m.out) + return nil +} + +func (m *midiOut) SendMessage(b []byte) error { + p := C.CBytes(b) + defer C.free(unsafe.Pointer(p)) + C.rtmidi_out_send_message(m.out, (*C.uchar)(p), C.int(len(b))) + if !m.out.ok { + return errors.New(C.GoString(m.out.msg)) + } + return nil +} + +func (m *midiOut) Destroy() { + C.rtmidi_out_free(m.out) +} diff --git a/contrib/go/rtmidi/rtmidi_stub.cpp b/contrib/go/rtmidi/rtmidi_stub.cpp new file mode 100644 index 00000000..7a5b6924 --- /dev/null +++ b/contrib/go/rtmidi/rtmidi_stub.cpp @@ -0,0 +1,4 @@ +#include "../../../RtMidi.h" + +#include "../../../RtMidi.cpp" +#include "../../../rtmidi_c.cpp" diff --git a/contrib/go/rtmidi/rtmidi_stub.h b/contrib/go/rtmidi/rtmidi_stub.h new file mode 100644 index 00000000..8a53d4c0 --- /dev/null +++ b/contrib/go/rtmidi/rtmidi_stub.h @@ -0,0 +1 @@ +#include "../../../rtmidi_c.h" diff --git a/contrib/go/rtmidi/rtmidi_test.go b/contrib/go/rtmidi/rtmidi_test.go new file mode 100644 index 00000000..8079fb4f --- /dev/null +++ b/contrib/go/rtmidi/rtmidi_test.go @@ -0,0 +1,46 @@ +package rtmidi + +import ( + "log" +) + +func ExampleCompiledAPI() { + for _, api := range CompiledAPI() { + log.Println("Compiled API: ", api) + } +} + +func ExampleMIDIIn_Message() { + in, err := NewMIDIInDefault() + if err != nil { + log.Fatal(err) + } + defer in.Destroy() + if err := in.OpenPort(0, "RtMidi"); err != nil { + log.Fatal(err) + } + defer in.Close() + + for { + m, t, err := in.Message() + if len(m) > 0 { + log.Println(m, t, err) + } + } +} + +func ExampleMIDIIn_SetCallback() { + in, err := NewMIDIInDefault() + if err != nil { + log.Fatal(err) + } + defer in.Destroy() + if err := in.OpenPort(0, "RtMidi"); err != nil { + log.Fatal(err) + } + defer in.Close() + in.SetCallback(func(m MIDIIn, msg []byte, t float64) { + log.Println(msg, t) + }) + <-make(chan struct{}) +} diff --git a/doc/Makefile.am b/doc/Makefile.am new file mode 100644 index 00000000..92b337f1 --- /dev/null +++ b/doc/Makefile.am @@ -0,0 +1,39 @@ + +MAINTAINERCLEANFILES=Makefile.in + +CLEANFILES=doxygen-build.stamp + +DOX=Doxyfile + +EXTRA_DIST=html release.txt + +INSTIMAGES=html/doxygen.png + +DOC_STAMPS=doxygen-build.stamp + +DOC_DIR=$(HTML_DIR) + +all-local: doxygen-build.stamp + +if MAKE_DOC +doxygen-build.stamp: doxygen/$(DOX) $(top_srcdir)/RtMidi.h $(top_srcdir)/rtmidi_c.h + @echo '*** Running doxygen ***' + cd doxygen; $(DOXYGEN) $(DOX) + touch doxygen-build.stamp +else +doxygen-build.stamp: + touch "$@" + mkdir html +endif + +clean-local: + rm -f *~ *.bak $(DOC_STAMPS) || true + if test -d html; then rm -fr html; fi + if test -d latex; then rm -fr latex; fi + if test -d man; then rm -fr man; fi + +distclean-local: clean + rm -f *.stamp || true + if test -d html; then rm -rf html; fi + +html-local: $(DOC_STAMPS) diff --git a/doc/doxygen/Doxyfile b/doc/doxygen/Doxyfile.in similarity index 99% rename from doc/doxygen/Doxyfile rename to doc/doxygen/Doxyfile.in index 29cc59a3..8864d73a 100644 --- a/doc/doxygen/Doxyfile +++ b/doc/doxygen/Doxyfile.in @@ -32,7 +32,7 @@ PROJECT_NAME = RtMidi # This could be handy for archiving the generated documentation or # if some version control system is used. -PROJECT_NUMBER = 2.1.0 +PROJECT_NUMBER = @PACKAGE_VERSION@ # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer @@ -669,7 +669,7 @@ WARN_LOGFILE = INPUT = tutorial.txt \ ../../RtMidi.h \ - ../../RtError.h + ../../tests # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is @@ -729,7 +729,7 @@ EXCLUDE_SYMBOLS = # directories that contain example code fragments that are included (see # the \include command). -EXAMPLE_PATH = +EXAMPLE_PATH = ../../tests samples # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp @@ -1580,7 +1580,7 @@ INCLUDE_FILE_PATTERNS = # undefined via #undef or recursively expanded use the := operator # instead of the = operator. -PREDEFINED = __MACOSX_CORE__ \ +PREDEFINED = __MACOSX_COREMIDI__ \ __WINDOWS_MM__ \ __UNIX_JACK__ \ __LINUX_ALSA__ \ diff --git a/doc/doxygen/footer.html b/doc/doxygen/footer.html index 82ae6c69..684f5cf5 100644 --- a/doc/doxygen/footer.html +++ b/doc/doxygen/footer.html @@ -1,7 +1,7 @@
-
©2003-2014 Gary P. Scavone, McGill University. All Rights Reserved.
+
©2003-2017 Gary P. Scavone, McGill University. All Rights Reserved.
Maintained by Gary P. Scavone, gary at music.mcgill.ca
diff --git a/doc/doxygen/header.html b/doc/doxygen/header.html index 3b6d60ba..62a1f347 100644 --- a/doc/doxygen/header.html +++ b/doc/doxygen/header.html @@ -5,5 +5,5 @@
-Tutorial   Class/Enum List   File List   Compound Members  
+Tutorial   Examples   Class/Enum List   File List   Compound Members  
diff --git a/doc/doxygen/samples/getting_started.cpp b/doc/doxygen/samples/getting_started.cpp new file mode 100644 index 00000000..cc0cf0e1 --- /dev/null +++ b/doc/doxygen/samples/getting_started.cpp @@ -0,0 +1,13 @@ +#include "RtMidi.h" + +int main() { + try { + rtmidi::MidiIn midiin; + } catch (const rtmidi::Error &error) { + // Handle the exception here + error.printMessage(); + // opitionally rethrow: + // throw; + } + return 0; +} diff --git a/doc/doxygen/tutorial.txt b/doc/doxygen/tutorial.txt index d6dc8266..c1ce51b8 100644 --- a/doc/doxygen/tutorial.txt +++ b/doc/doxygen/tutorial.txt @@ -2,143 +2,182 @@
\ref intro    \ref download    \ref start    \ref error    \ref probing    \ref output    \ref input    \ref virtual    \ref compiling    \ref debug    \ref multi    \ref apinotes    \ref acknowledge    \ref license
-\section intro Introduction +\section warning Warning: + +This documentation refers to an API suggested to RtMidi (and available at GitHub). So far it is not officially accepted in the RtMidi distribution. -RtMidi is a set of C++ classes (RtMidiIn, RtMidiOut and API-specific classes) that provides a common API (Application Programming Interface) for realtime MIDI input/output across Linux (ALSA & JACK), Macintosh OS X (CoreMIDI & JACK), and Windows (Multimedia Library & Kernel Streaming) operating systems. RtMidi significantly simplifies the process of interacting with computer MIDI hardware and software. It was designed with the following goals: +\section intro Introduction -
    -
  • object oriented C++ design
  • -
  • simple, common API across all supported platforms
  • -
  • only one header and one source file for easy inclusion in programming projects
  • -
  • MIDI device enumeration
  • -
+RtMidi is a set of C++ classes (rtmidi::MidiIn, rtmidi::MidiOut and API-specific classes) that provides a common API (Application Programming Interface) for realtime MIDI input/output across Linux (ALSA & JACK), Macintosh OS X (CoreMIDI & JACK), and Windows (Multimedia Library) operating systems. RtMidi significantly simplifies the process of interacting with computer MIDI hardware and software. It was designed with the following goals: + - object oriented C++ design + - simple, common API across all supported platforms + - only one header and one source file for easy inclusion in programming projects + - query availlable MIDI devices Where applicable, multiple API support can be compiled and a particular API specified when creating an RtAudio instance. -MIDI input and output functionality are separated into two classes, RtMidiIn and RtMidiOut. Each class instance supports only a single MIDI connection. RtMidi does not provide timing functionality (i.e., output messages are sent immediately). Input messages are timestamped with delta times in seconds (via a \c double floating point type). MIDI data is passed to the user as raw bytes using an std::vector. +MIDI input and output functionality are separated into two classes, rtmidi::MidiIn and rtmidi::MidiOut. Each class instance supports only a single MIDI connection. RtMidi does not provide timing functionality (i.e., output messages are sent immediately). Input messages are timestamped with delta times in seconds (via a \c double floating point type). MIDI data is passed to the user as raw bytes using an std::vector. -\section whatsnew What's New (Version 2.1) +\section whatsnewts What's New in the Fork (Version 5.0) -A minor API change was made. The RtError class was renamed RtMidiError and embedded directly in RtMidi.h. Thus, all references to RtError should be renamed to RtMidiError and the RtError.h file should be deleted. + - The classes of RtMidi now reside in the namespace rtmidi. + - The beginning letters “Rt” are dropped from the names + - For easy adoption of the new interface wrappers for the old API are provided. + - The library uses backend provided port descriptors, now. This provides a more reliable port handling for changing environments (See below). + - Allow to use all supported backends in parallel -\section download Download +The way MIDI devices are enumerated has changed. The old way, using the ordinal number of MIDI devices works only in cases where MIDI devices are not added or removed during the program session. When a virtual MIDI port or USB MIDI device is added or removed the ordinal number of each of the other devices may change. -Latest Release (30 March 2014): Version 2.1.0 +Suppose your computer has the following list of MIDI devices. + 1. MIDI loopback device + 2. Removable USB MIDI device + 3. Another MIDI device + 4. Software MIDI Synth + 5. A virtual MIDI port -\section start Getting Started +After the software obtained this list, your friend remembers that he +must catch the next bus and unplugs his removable USB MIDI device. +The software does not recognize this removal and keeps the above list, +while the system has a new one: + 1. MIDI loopback device + 2. Another MIDI device + 3. Software MIDI Synth + 4. A virtual MIDI port -The first thing that must be done when using RtMidi is to create an instance of the RtMidiIn or RtMidiOut subclasses. RtMidi is an abstract base class, which itself cannot be instantiated. Each default constructor attempts to establish any necessary "connections" with the underlying MIDI system. RtMidi uses C++ exceptions to report errors, necessitating try/catch blocks around many member functions. An RtMidiError can be thrown during instantiation in some circumstances. A warning message may also be reported if no MIDI devices are found during instantiation. The RtMidi classes have been designed to work with "hot pluggable" or virtual (software) MIDI devices, making it possible to connect to MIDI devices that may not have been present when the classes were instantiated. The following code example demonstrates default object construction and destruction: +Somehow you told the software to use the Software MIDI Synth. The +program stores the number 4 as it obtained during enumeration of the +MIDI devices. Instead of playing the music using your sound card it +sends the music to a different port. -\code +While this behaviour is only annoying in interactive environments it +results in unpredictable behaviour if several ports are opened at +once. E.g. in the ALSA backend every opened port results in an +aditional newly created virtual port. -#include "RtMidi.h" +In order to avoid such problems, most backends identify ports (except +WinMM) by different data structures. -int main() -{ - RtMidiIn *midiin = 0; +The current version introduces a new class \ref rtmidi::PortDescriptor +in order to hide this implementation detail from the user code. In +order to avoid the above problems these are retrieved at once using \ref rtmidi::Midi::getPortList. +This new feature also allows to retreive the port descriptor of an open device using +\ref rtmidi::Midi::getDescriptor. The latter can be used to obtain - // RtMidiIn constructor - try { - midiin = new RtMidiIn(); - } - catch (RtMidiError &error) { - // Handle the exception here - error.printMessage(); - } - // Clean up - delete midiin; -} -\endcode + +\section whatsnew What's New (Version 3.0.0) + +The version number has been bumped to 3.0.0 because of the past API change concerning the renaming of the RtError class to RtMidiError. Changes in this release include: + +- see git history for complete list of changes +- new sendMessage() function that does not use std::vector +- various std::string updates, including use of UTF8 for port names +- fixes for the MIDI queue +- various build system updates and code efficiencies + +\section download Download + +Latest Release (31 August 2017): Version 3.0.0 + +\section start Getting Started + +The first thing that must be done when using RtMidi is to create an instance of the rtmidi::MidiIn or rtmidi::MidiOut subclasses. rtmidi::Midi is an abstract base class, which itself cannot be instantiated. Each default constructor attempts to establish any necessary "connections" with the underlying MIDI system. RtMidi uses C++ exceptions to report errors, necessitating try/catch blocks around many member functions. An rtmidi::Error can be thrown during instantiation in some circumstances. A warning message may also be reported if no MIDI devices are found during instantiation. The RtMidi classes have been designed to work with "hot pluggable" or virtual (software) MIDI devices, making it possible to connect to MIDI devices that may not have been present when the classes were instantiated. The following code example demonstrates default object construction and destruction: + +\include getting_started.cpp Obviously, this example doesn't demonstrate any of the real functionality of RtMidi. However, all uses of RtMidi must begin with construction and must end with class destruction. Further, it is necessary that all class methods that can throw a C++ exception be called within a try/catch block. +\note The outer try/catch block can be simplyfied if you create the MidiIn object on the stack as it is done in the following examples. + + + \section error Error Handling -RtMidi uses a C++ exception handler called RtMidiError, which is -declared and defined in RtMidi.h. The RtMidiError class is quite -simple but it does allow errors to be "caught" by RtMidiError::Type. -Many RtMidi methods can "throw" an RtMidiError, most typically if a +RtMidi uses a C++ exception handler called rtmidi::Error, which is +declared and defined in RtMidi.h. The rtmidi::Error class is quite +simple but it does allow errors to be "caught" by rtmidi::Error::Type. +Many RtMidi methods can "throw" an rtmidi::Error, most typically if a driver error occurs or an invalid function argument is specified. There are a number of cases within RtMidi where warning messages may be displayed but an exception is not thrown. A client error callback -function can be specified (via the RtMidi::setErrorCallback function) +function can be specified (via the rtmidi::Midi::setErrorCallback function) that is invoked when an error occurs. By default, error messages are not automatically displayed in RtMidi unless the preprocessor definition __RTMIDI_DEBUG__ is defined during compilation. Messages associated with caught exceptions can be displayed with, for example, -the RtMidiError::printMessage() function. +the rtmidi::Error::printMessage() function. \section probing Probing Ports -A client generally must query the available MIDI ports before deciding which to use. The following example outlines how this can be done. +A client generally must query the available MIDI ports before deciding which to use. The following example outlines how this can be done. A more sophisticated example demonstrating the API detection and the different naming schemes can be found in the \c tests subdirectory in the file \link midiprobe2.cpp \c midiprobe2.cpp \endlink. \code // midiprobe.cpp #include #include +#include #include "RtMidi.h" int main() { - RtMidiIn *midiin = 0; - RtMidiOut *midiout = 0; + // Create an api map. + std::map apiMap; + apiMap[RtMidi::MACOSX_CORE] = "OS-X CoreMidi"; + apiMap[RtMidi::WINDOWS_MM] = "Windows MultiMedia"; + apiMap[RtMidi::WINDOWS_KS] = "Windows Kernel Straming"; + apiMap[RtMidi::UNIX_JACK] = "Jack Client"; + apiMap[RtMidi::LINUX_ALSA] = "Linux ALSA"; + apiMap[RtMidi::RTMIDI_DUMMY] = "RtMidi Dummy"; - // RtMidiIn constructor - try { - midiin = new RtMidiIn(); - } - catch ( RtMidiError &error ) { - error.printMessage(); - exit( EXIT_FAILURE ); - } + std::vector< rtmidi::ApiType > apis; + rtmidi::Midi :: getCompiledApi( apis ); + + std::cout << "\nCompiled APIs:\n"; + for ( unsigned int i=0; igetPortCount(); - std::cout << "\nThere are " << nPorts << " MIDI input sources available.\n"; - std::string portName; - for ( unsigned int i=0; igetPortName(i); - } - catch ( RtMidiError &error ) { - error.printMessage(); - goto cleanup; - } - std::cout << " Input Port #" << i+1 << ": " << portName << '\n'; - } - // RtMidiOut constructor try { - midiout = new RtMidiOut(); - } - catch ( RtMidiError &error ) { - error.printMessage(); - exit( EXIT_FAILURE ); - } - // Check outputs. - nPorts = midiout->getPortCount(); - std::cout << "\nThere are " << nPorts << " MIDI output ports available.\n"; - for ( unsigned int i=0; igetPortName(i); + // rtmidi::MidiIn constructor ... exception possible + rtmidi::MidiIn midiin; + + std::cout << "\nCurrent input API: " << apiMap[ midiin.getCurrentApi() ] << std::endl; + + + rtmidi::PortList list = midiin.getPortList(); + // Check inputs. + std::cout << "\nThere are " << list.size() << " MIDI input sources available.\n"; + for (rtmidi::PortList::iterator i = list.begin(); + i != list.end(); + i++) { + std::cout << " Input Port: " << (*i)->getName() << std::endl; } - catch (RtMidiError &error) { - error.printMessage(); - goto cleanup; + + std::cout << "**********************************************************************" << std::endl; + + // rtmidi::MidiOut constructor ... exception possible + rtmidi::MidiOut midiout; + + std::cout << "\nCurrent output API: " << apiMap[ midiout.getCurrentApi() ] << std::endl; + + list = midiout.getPortList(); + + // Check inputs. + std::cout << "\nThere are " << list.size() << " MIDI output sinks available.\n"; + + for (rtmidi::PortList::iterator i = list.begin(); + i != list.end(); + i++) { + std::cout << " Output Port: " << (*i)->getName() << std::endl; } - std::cout << " Output Port #" << i+1 << ": " << portName << '\n'; - } - std::cout << '\n'; - // Clean up - cleanup: - delete midiin; - delete midiout; + } catch ( rtmidi::Error &error ) { + error.printMessage(); + } return 0; } @@ -146,9 +185,9 @@ int main() \section output MIDI Output -The RtMidiOut class provides simple functionality to immediately send messages over a MIDI connection. No timing functionality is provided. +The rtmidi::MidiOut class provides simple functionality to immediately send messages over a MIDI connection. No timing functionality is provided. Note that there is are overloaded \ref rtmidi::MidiOut::sendMessage() functions for C arrays as well as std::vectors. -In the following example, we omit necessary error checking and details regarding OS-dependent sleep functions. For a complete example, see the \c midiout.cpp program in the \c tests directory. +In the following example, we omit necessary error checking and details regarding OS-dependent sleep functions. For a complete example, see the \link midiout2.cpp \c midiout2.cpp \endlink program in the \c tests directory. \code // midiout.cpp @@ -159,50 +198,51 @@ In the following example, we omit necessary error checking and details regarding int main() { - RtMidiOut *midiout = new RtMidiOut(); - std::vector message; - - // Check available ports. - unsigned int nPorts = midiout->getPortCount(); - if ( nPorts == 0 ) { - std::cout << "No ports available!\n"; - goto cleanup; - } - - // Open first available port. - midiout->openPort( 0 ); + try { + rtmidi::MidiOut midiout; + std::vector message; + + // Check available ports. + rtmidi::PortList list = midiout.getPortList(); + if (list.empty()) { + std::cerr << "No devices found." << std::endl; + exit(EXIT_FAILURE); + } - // Send out a series of MIDI messages. + // Open first available port. + midiout.openPort( list.front ); - // Program change: 192, 5 - message.push_back( 192 ); - message.push_back( 5 ); - midiout->sendMessage( &message ); + // Send out a series of MIDI messages. - // Control Change: 176, 7, 100 (volume) - message[0] = 176; - message[1] = 7; - message.push_back( 100 ); - midiout->sendMessage( &message ); + // Program change: 192, 5 + message.push_back( 192 ); + message.push_back( 5 ); + midiout.sendMessage( &message ); - // Note On: 144, 64, 90 - message[0] = 144; - message[1] = 64; - message[2] = 90; - midiout->sendMessage( &message ); + // Control Change: 176, 7, 100 (volume) + message[0] = 176; + message[1] = 7; + message.push_back( 100 ); + midiout.sendMessage( &message ); - SLEEP( 500 ); // Platform-dependent ... see example in tests directory. + // Note On: 144, 64, 90 + message[0] = 144; + message[1] = 64; + message[2] = 90; + midiout.sendMessage( &message ); - // Note Off: 128, 64, 40 - message[0] = 128; - message[1] = 64; - message[2] = 40; - midiout->sendMessage( &message ); + SLEEP( 500 ); // Platform-dependent ... see example in tests directory. - // Clean up - cleanup: - delete midiout; + // Note Off: 128, 64, 40 + message[0] = 128; + message[1] = 64; + message[2] = 40; + midiout.sendMessage( &message ); + } catch (rtmidi::Error & error) { + error.printMessage(); + exit(EXIT_FAILURE); + } return 0; } \endcode @@ -210,15 +250,15 @@ int main() \section input MIDI Input -The RtMidiIn class uses an internal callback function or thread to receive incoming MIDI messages from a port or device. These messages are then either queued and read by the user via calls to the RtMidiIn::getMessage() function or immediately passed to a user-specified callback function (which must be "registered" using the RtMidiIn::setCallback() function). We'll provide examples of both usages. +The rtmidi::MidiIn class uses an internal callback function or thread to receive incoming MIDI messages from a port or device. These messages are then either queued and read by the user via calls to the rtmidi::MidiIn::getMessage() function or immediately passed to a user-specified callback function (which must be "registered" using the rtmidi::MidiIn::setCallback() function). We'll provide examples of both usages. -The RtMidiIn class provides the RtMidiIn::ignoreTypes() function to specify that certain MIDI message types be ignored. By default, system exclusive, timing, and active sensing messages are ignored. +The rtmidi::MidiIn class provides the rtmidi::MidiIn::ignoreTypes() function to specify that certain MIDI message types be ignored. By default, system exclusive, timing, and active sensing messages are ignored. \subsection qmidiin Queued MIDI Input -The RtMidiIn::getMessage() function does not block. If a MIDI message is available in the queue, it is copied to the user-provided \c std::vector container. When no MIDI message is available, the function returns an empty container. The default maximum MIDI queue size is 1024 messages. This value may be modified with the RtMidiIn::setQueueSizeLimit() function. If the maximum queue size limit is reached, subsequent incoming MIDI messages are discarded until the queue size is reduced. +The rtmidi::MidiIn::getMessage() function does not block. If a MIDI message is available in the queue, it is copied to the user-provided \c std::vector container. When no MIDI message is available, the function returns an empty container. The default maximum MIDI queue size is 1024 messages. This value may be modified with the rtmidi::MidiIn::setQueueSizeLimit() function. If the maximum queue size limit is reached, subsequent incoming MIDI messages are discarded until the queue size is reduced. -In the following example, we omit some necessary error checking and details regarding OS-dependent sleep functions. For a more complete example, see the \c qmidiin.cpp program in the \c tests directory. +In the following example, we omit some necessary error checking and details regarding OS-dependent sleep functions. For a more complete example, see the \link qmidiin2.cpp \c qmidiin2.cpp \endlink program in the \c tests directory. \code // qmidiin.cpp @@ -233,51 +273,54 @@ static void finish(int ignore){ done = true; } int main() { - RtMidiIn *midiin = new RtMidiIn(); - std::vector message; - int nBytes, i; - double stamp; - - // Check available ports. - unsigned int nPorts = midiin->getPortCount(); - if ( nPorts == 0 ) { - std::cout << "No ports available!\n"; - goto cleanup; - } - midiin->openPort( 0 ); - - // Don't ignore sysex, timing, or active sensing messages. - midiin->ignoreTypes( false, false, false ); - - // Install an interrupt handler function. - done = false; - (void) signal(SIGINT, finish); - - // Periodically check input queue. - std::cout << "Reading MIDI from port ... quit with Ctrl-C.\n"; - while ( !done ) { - stamp = midiin->getMessage( &message ); - nBytes = message.size(); - for ( i=0; i 0 ) - std::cout << "stamp = " << stamp << std::endl; - - // Sleep for 10 milliseconds ... platform-dependent. - SLEEP( 10 ); - } + try { + rtmidi::MidiIn midiin; + std::vector message; + int nBytes, i; + double stamp; + + // Check available ports. + rtmidi::PortList list = midiin.getPortList(); + if (list.empty()) { + std::cerr << "No devices found." << std::endl; + exit(EXIT_FAILURE); + } + + // Open first available port. + midiin.openPort( list.front ); + + // Don't ignore sysex, timing, or active sensing messages. + midiin.ignoreTypes( false, false, false ); - // Clean up - cleanup: - delete midiin; + // Install an interrupt handler function. + done = false; + (void) signal(SIGINT, finish); + // Periodically check input queue. + std::cout << "Reading MIDI from port ... quit with Ctrl-C.\n"; + while ( !done ) { + stamp = midiin.getMessage( &message ); + nBytes = message.size(); + for ( i=0; i 0 ) + std::cout << "stamp = " << stamp << std::endl; + + // Sleep for 10 milliseconds ... platform-dependent. + SLEEP( 10 ); + } + + } catch (rtmidi::Error & error) { + error.printMessage(); + exit(EXIT_FAILURE); + } return 0; } \endcode \subsection cmidiin MIDI Input with User Callback -When set, a user-provided callback function will be invoked after the input of a complete MIDI message. It is possible to provide a pointer to user data that can be accessed in the callback function (not shown here). It is necessary to set the callback function immediately after opening the port to avoid having incoming messages written to the queue (which is not emptied when a callback function is set). If you are worried about this happening, you can check the queue using the RtMidi::getMessage() function to verify it is empty (after the callback function is set). +When set, a user-provided callback function will be invoked after the input of a complete MIDI message. It is possible to provide a pointer to user data that can be accessed in the callback function (not shown here). It is necessary to set the callback function immediately after opening the port to avoid having incoming messages written to the queue (which is not emptied when a callback function is set). If you are worried about this happening, you can check the queue using the rtmidi::Midi::getMessage() function to verify it is empty (after the callback function is set). In the following example, we omit some necessary error checking. For a more complete example, see the \c cmidiin.cpp program in the \c tests directory. @@ -299,40 +342,42 @@ void mycallback( double deltatime, std::vector< unsigned char > *message, void * int main() { - RtMidiIn *midiin = new RtMidiIn(); - - // Check available ports. - unsigned int nPorts = midiin->getPortCount(); - if ( nPorts == 0 ) { - std::cout << "No ports available!\n"; - goto cleanup; - } + try { + rtmidi::MidiIn midiin; - midiin->openPort( 0 ); + // Check available ports. + rtmidi::PortList list = midiin.getPortList(); + if (list.empty()) { + std::cerr << "No ports available." << std::endl; + exit(EXIT_FAILURE); + } - // Set our callback function. This should be done immediately after - // opening the port to avoid having incoming messages written to the - // queue. - midiin->setCallback( &mycallback ); + // Open first available port. + midiin.openPort( list.front ); - // Don't ignore sysex, timing, or active sensing messages. - midiin->ignoreTypes( false, false, false ); + // Set our callback function. This should be done immediately after + // opening the port to avoid having incoming messages written to the + // queue. + midiin.setCallback( &mycallback ); - std::cout << "\nReading MIDI input ... press to quit.\n"; - char input; - std::cin.get(input); + // Don't ignore sysex, timing, or active sensing messages. + midiin.ignoreTypes( false, false, false ); - // Clean up - cleanup: - delete midiin; + std::cout << "\nReading MIDI input ... press to quit.\n"; + char input; + std::cin.get(input); + } catch (rtmidi::Error & error) { + error.printMessage(); + exit(EXIT_FAILURE); + } return 0; } \endcode \section virtual Virtual Ports -The Linux ALSA, Macintosh CoreMIDI and JACK APIs allow for the establishment of virtual input and output MIDI ports to which other software clients can connect. RtMidi incorporates this functionality with the RtMidiIn::openVirtualPort() and RtMidiOut::openVirtualPort() functions. Any messages sent with the RtMidiOut::sendMessage() function will also be transmitted through an open virtual output port. If a virtual input port is open and a user callback function is set, the callback function will be invoked when messages arrive via that port. If a callback function is not set, the user must poll the input queue to check whether messages have arrived. No notification is provided for the establishment of a client connection via a virtual port. +The Linux ALSA, Macintosh CoreMIDI and JACK APIs allow for the establishment of virtual input and output MIDI ports to which other software clients can connect. RtMidi incorporates this functionality with the rtmidi::MidiIn::openVirtualPort() and rtmidi::MidiOut::openVirtualPort() functions. Any messages sent with the rtmidi::MidiOut::sendMessage() function will also be transmitted through an open virtual output port. If a virtual input port is open and a user callback function is set, the callback function will be invoked when messages arrive via that port. If a callback function is not set, the user must poll the input queue to check whether messages have arrived. No notification is provided for the establishment of a client connection via a virtual port. The RtMidi::isPortOpen() function does not report the status of ports created with the RtMidi::openVirtualPort() function. \section compiling Compiling @@ -352,21 +397,21 @@ In order to compile RtMidi for a specific OS and API, it is necessary to supply ALSA Sequencer __LINUX_ALSA__ asound, pthread - g++ -Wall -D__LINUX_ALSA__ -o midiprobe midiprobe.cpp RtMidi.cpp -lasound -lpthread + g++ -Wall -D__LINUX_ALSA__ -o midiprobe midiprobe2.cpp RtMidi.cpp -lasound -lpthread Linux or Mac JACK MIDI __UNIX_JACK__ jack - g++ -Wall -D__UNIX_JACK__ -o midiprobe midiprobe.cpp RtMidi.cpp -ljack + g++ -Wall -D__UNIX_JACK__ -o midiprobe midiprobe2.cpp RtMidi.cpp -ljack Macintosh OS X CoreMIDI - __MACOSX_CORE__ + __MACOSX_COREMIDI__ CoreMIDI, CoreAudio, CoreFoundation - g++ -Wall -D__MACOSX_CORE__ -o midiprobe midiprobe.cpp RtMidi.cpp -framework CoreMIDI -framework CoreAudio -framework CoreFoundation + g++ -Wall -D__MACOSX_COREMIDI__ -o midiprobe midiprobe2.cpp RtMidi.cpp -framework CoreMIDI -framework CoreAudio -framework CoreFoundation Windows @@ -375,17 +420,10 @@ In order to compile RtMidi for a specific OS and API, it is necessary to supply winmm.lib, multithreaded compiler specific - - Windows - Kernel Streaming - __WINDOWS_KS__ - ks.h, ksmedia.h, setupapi.lib, ksuser.lib, multithreaded - compiler specific -

-The example compiler statements above could be used to compile the midiprobe.cpp example file, assuming that midiprobe.cpp, RtMidi.h and RtMidi.cpp all exist in the same directory. +The example compiler statements above could be used to compile the midiprobe2.cpp example file, assuming that midiprobe2.cpp, RtMidi.h and RtMidi.cpp all exist in the same directory. \section debug Debugging @@ -393,9 +431,13 @@ If you are having problems getting RtMidi to run on your system, try passing the \section multi Using Simultaneous Multiple APIs -Support for each MIDI API is encapsulated in specific MidiInApi or MidiOutApi subclasses, making it possible to compile and instantiate multiple API-specific subclasses on a given operating system. For example, one can compile both CoreMIDI and JACK support on the OS-X operating system by providing the appropriate preprocessor definitions for each. In a run-time situation, one might first attempt to determine whether any JACK ports are available. This can be done by specifying the api argument RtMidi::UNIX_JACK when attempting to create an instance of RtMidiIn or RtMidiOut. If no available ports are found, then an instance of RtMidi with the api argument RtMidi::MACOSX_CORE can be created. Alternately, if no api argument is specified, RtMidi will first look for JACK ports and if none are found, then CoreMIDI ports (in linux, the search order is JACK and then ALSA; in Windows, the search order is WinMM and then WinKS). In theory, it should also be possible to have separate instances of RtMidi open at the same time with different underlying API support, though this has not been tested. +Support for each MIDI API is encapsulated in specific \ref rtmidi::MidiInApi or \ref rtmidi::MidiOutApi subclasses, making it possible to compile and instantiate multiple API-specific subclasses on a given operating system. For example, one can compile both CoreMIDI and JACK support on the OS-X operating system by providing the appropriate preprocessor definitions for each. In a run-time situation, one might first attempt to determine whether any JACK ports are available. This can be done by specifying the api argument rtmidi::UNIX_JACK when attempting to create an instance of rtmidi::MidiIn or rtmidi::MidiOut. If no available ports are found, then an instance of rtmidi::Midi with the api argument rtmidi::MACOSX_CORE can be created. Alternately, if no api argument is specified, RtMidi will first look for OS provided ports and if none are found, then software demons (currently JACK) ports (in linux, the search order is ALSA and then JACK). + +It is also possible to use all compiled backends simultaneously by passing the special api argument rtmidi::ALL_API to the constructor. In that case rtmidi::midi::getPortList will return a list of all port descriptors from all backends that are available. On the other hand rtmidi::midi::openVirtualPort will open only one port on the first API that is tested in the automatic port selecton as described above. -The static function RtMidi::getCompiledApi() is provided to determine the available compiled API support. The function RtMidi::getCurrentApi() indicates the API selected for a given RtMidi instance. +The static function rtmidi::Midi::getCompiledApi() is provided to determine the available compiled API support. The function rtmidi::Midi::getCurrentApi() indicates the API selected for a given RtMidi instance. + +\note It is recommended to avoid the atomatic API selection for virtual ports. In most cases it is a better option to let the end user choose the API for this port or simply generate an array of ports, each with a different backend API. \section apinotes API Notes @@ -403,7 +445,7 @@ RtMidi is designed to provide a common API across the various supported operatin \subsection linux Linux: -RtMidi for Linux was developed using the Fedora distribution. Two different MIDI APIs are supported on Linux platforms: ALSA and JACK. A decision was made to not include support for the OSS API because the OSS API provides very limited functionality and because ALSA support is now incorporated in the Linux kernel. The ALSA sequencer and JACK APIs allows for virtual software input and output ports. +Two different MIDI APIs are supported on Linux platforms: ALSA and JACK. A decision was made to not include support for the OSS API because the OSS API provides very limited functionality and because ALSA support is incorporated in the Linux kernel. The ALSA sequencer and JACK APIs allows for virtual software input and output ports. \subsection macosx Macintosh OS X (CoreAudio): @@ -415,41 +457,41 @@ The RtMidi JACK support can be compiled on Macintosh OS-X systems, as well as in The \c configure script provides support for the MinGW compiler. -The Windows Multimedia library MIDI calls used in RtMidi do not make use of streaming functionality. Incoming system exclusive messages read by RtMidiIn are limited to a length as defined by the preprocessor definition RT_SYSEX_BUFFER_SIZE (set in RtMidi.cpp). The default value is 1024. There is no such limit for outgoing sysex messages via RtMidiOut. +The Windows Multimedia library MIDI calls used in RtMidi do not make use of streaming functionality. Incoming system exclusive messages read by rtimidi::MidiIn are limited to a length as defined by the preprocessor definition RT_SYSEX_BUFFER_SIZE (set in RtMidi.cpp). The default value is 1024. There is no such limit for outgoing sysex messages via rtmidi::MidiOut. RtMidi was originally developed with Visual C++ version 6.0 but has been tested with Virtual Studio 2010. -The \c configure script provides support for the MinGW compiler. - \section acknowledge Development & Acknowledgements RtMidi is on github (https://github.com/thestk/rtmidi). Many thanks to the developers that are helping to maintain and improve RtMidi. In years past, the following people provided bug fixes and improvements: -

    -
  • Sebastien Alaiwan (JACK memory leaks, Windows kernel streaming)
  • -
  • Jean-Baptiste Berruchon (Windows sysex code)
  • -
  • Pedro Lopez-Cabanillas (ALSA sequencer API, client naming)
  • -
  • Jason Champion (MSW project file for library build)
  • -
  • Eduardo Coutinho (Windows device names)
  • -
  • Paul Dean (increment optimization)
  • -
  • Luc Deschenaux (sysex issues)
  • -
  • John Dey (OS-X timestamps)
  • -
  • Christoph Eckert (ALSA sysex fixes)
  • -
  • Martin Koegler (various fixes)
  • -
  • Immanuel Litzroth (OS-X sysex fix)
  • -
  • Jon McCormack (Snow Leopard updates)
  • -
  • Axel Schmidt (client naming)
  • -
  • Alexander Svetalkin (JACK MIDI)
  • -
  • Casey Tucker (OS-X driver information, sysex sending)
  • -
  • Bastiaan Verreijt (Windows sysex multi-buffer code)
  • -
  • Dan Wilcox
  • -
+ +- Stephen Sinclair (Git repo, code and build system) +- Atsushi Eno (C API) +- Sebastien Alaiwan (JACK memory leaks, Windows kernel streaming) +- Jean-Baptiste Berruchon (Windows sysex code) +- Pedro Lopez-Cabanillas (ALSA sequencer API, client naming) +- Jason Champion (MSW project file for library build) +- Eduardo Coutinho (Windows device names) +- Paul Dean (increment optimization) +- Luc Deschenaux (sysex issues) +- John Dey (OS-X timestamps) +- Christoph Eckert (ALSA sysex fixes) +- Martin Koegler (various fixes) +- Immanuel Litzroth (OS-X sysex fix) +- Jon McCormack (Snow Leopard updates) +- Axel Schmidt (client naming) +- Alexander Svetalkin (JACK MIDI) +- Casey Tucker (OS-X driver information, sysex sending) +- Bastiaan Verreijt (Windows sysex multi-buffer code) +- Dan Wilcox \section license License RtMidi: realtime MIDI i/o C++ classes
- Copyright (c) 2003-2014 Gary P. Scavone + Copyright (c) 2003-2017 Gary P. Scavone + Forked by Tobias Schlemmer, 2014-2018. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files @@ -476,3 +518,4 @@ In years past, the following people provided bug fixes and improvements: WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + diff --git a/doc/release.txt b/doc/release.txt index 83debcc9..4bd52f96 100644 --- a/doc/release.txt +++ b/doc/release.txt @@ -1,14 +1,41 @@ -RtMidi - a set of C++ classes that provides a common API for realtime MIDI input/output across Linux (ALSA & JACK), Macintosh OS X (CoreMidi & JACK), and Windows (Multimedia, Kernel Streaming). - -By Gary P. Scavone, 2003-2014 +RtMidi - a set of C++ classes that provides a common API for realtime MIDI input/output across Linux (ALSA & JACK), Macintosh OS X (CoreMIDI & JACK), and Windows (Multimedia Library). + +By Gary P. Scavone, 2003-2017 (with help from many others!) + +Fork by Tobias Schlemmer: (August 2018) +- see git history for complete list of changes +- The old API has been deprecated as there is no way to rely on + consecutive port numbers. Currently, it is still available, but a + compiler warning is generated if applicable +- `__MACOSX_CORE__` has been renamed to `__MACOSX_COREMIDI__` +- The classes of RtMidi now reside in the namespace rtmidi. +- The beginning letters “Rt” are dropped from the names +- For easy adoption of the new interface wrappers for the old API are provided. +- The library uses backend provided port descriptors, now. This provides a more reliable port handling for changing environments. + +v.3.0.0: (31 August 2017) +- see git history for complete list of changes +- new sendMessage() function that does not use std::vector +- various std::string updates, including use of UTF8 for port names +- fixes for the MIDI queue +- various build system updates and code efficiencies + +v2.1.1: (11 February 2016) +- updates to automake routines +- added C API (thanks to Atsushi Eno!) +- JACK ringbuffer allocation change +- OSX virtual port closing fix +- OSX sysex sending fix +- moved Windows kernel streaming code to other branch because it is incomplete +- miscellaneous small fixes v2.1.0: (30 March 2014) - renamed RtError class to RtMidiError and embedded it in RtMidi.h (and deleted RtError.h) -- fix to CoreMidi implementation to support dynamic port changes +- fix to CoreMIDI implementation to support dynamic port changes - removed global ALSA sequencer objects because they were not thread safe (Martin Koegler) - fix for ALSA timing ignore flag (Devin Anderson) - fix for ALSA incorrect use of snd_seq_create_port() function (Tobias Schlemmer) -- fix for international character support in CoreMidi (Martin Finke) +- fix for international character support in CoreMIDI (Martin Finke) - fix for unicode conversion in WinMM (Dan Wilcox) - added custom error hook that allows the client to capture an RtMidi error outside of the RtMidi code (Pavel Mogilevskiy) - added RtMidi::isPortOpen function (Pavel Mogilevskiy) @@ -16,6 +43,7 @@ v2.1.0: (30 March 2014) - Windows update to avoid lockups when shutting down while sending/receiving sysex messages (ptarabbia) - OS-X fix to avoid empty messages in callbacks when ignoring sysex messages and split sysexes are received (codepainters) - ALSA openPort fix to better distinguish sender and receiver (Russell Smyth) +- Windows Kernel Streaming support removed because it was uncompilable and incomplete v2.0.1: (26 July 2012) - small fixes for problems reported by Chris Arndt (scoping, preprocessor, and include) diff --git a/include/ks.h b/include/ks.h deleted file mode 100644 index 1f8b8b45..00000000 --- a/include/ks.h +++ /dev/null @@ -1,3577 +0,0 @@ -/** - * This file has no copyright assigned and is placed in the Public Domain. - * This file is part of the w64 mingw-runtime package. - * No warranty is given. - */ -#ifndef _KS_ -#define _KS_ - -#include - -#if __GNUC__ >= 3 - # pragma GCC system_header -#endif - -#ifndef __MINGW_EXTENSION - # if defined(__GNUC__) || defined(__GNUG__) - # define __MINGW_EXTENSION __extension__ - # else - # define __MINGW_EXTENSION - # endif -#endif - -#ifdef __TCS__ - # define _KS_NO_ANONYMOUS_STRUCTURES_ 1 -#endif - -#ifdef _KS_NO_ANONYMOUS_STRUCTURES_ - # define _KS_ANON_STRUCT(X) struct X -#else - # define _KS_ANON_STRUCT(X) __MINGW_EXTENSION struct -#endif - -#ifndef _NTRTL_ - # ifndef DEFINE_GUIDEX - # define DEFINE_GUIDEX(name) EXTERN_C const GUID name - # endif - # ifndef STATICGUIDOF - # define STATICGUIDOF(guid) STATIC_ ## guid - # endif -#endif /* _NTRTL_ */ - -#ifndef SIZEOF_ARRAY - # define SIZEOF_ARRAY(ar) (sizeof(ar) / sizeof((ar)[0])) -#endif - -#define DEFINE_GUIDSTRUCT(g, n) DEFINE_GUIDEX(n) -#define DEFINE_GUIDNAMED(n) n - -#define STATIC_GUID_NULL \ - 0x00000000L, 0x0000, 0x0000, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } - -DEFINE_GUIDSTRUCT("00000000-0000-0000-0000-000000000000", GUID_NULL); -#define GUID_NULL DEFINE_GUIDNAMED(GUID_NULL) - -#define IOCTL_KS_PROPERTY CTL_CODE(FILE_DEVICE_KS, 0x000, METHOD_NEITHER, FILE_ANY_ACCESS) -#define IOCTL_KS_ENABLE_EVENT CTL_CODE(FILE_DEVICE_KS, 0x001, METHOD_NEITHER, FILE_ANY_ACCESS) -#define IOCTL_KS_DISABLE_EVENT CTL_CODE(FILE_DEVICE_KS, 0x002, METHOD_NEITHER, FILE_ANY_ACCESS) -#define IOCTL_KS_METHOD CTL_CODE(FILE_DEVICE_KS, 0x003, METHOD_NEITHER, FILE_ANY_ACCESS) -#define IOCTL_KS_WRITE_STREAM CTL_CODE(FILE_DEVICE_KS, 0x004, METHOD_NEITHER, FILE_WRITE_ACCESS) -#define IOCTL_KS_READ_STREAM CTL_CODE(FILE_DEVICE_KS, 0x005, METHOD_NEITHER, FILE_READ_ACCESS) -#define IOCTL_KS_RESET_STATE CTL_CODE(FILE_DEVICE_KS, 0x006, METHOD_NEITHER, FILE_ANY_ACCESS) - -typedef enum -{ - KSRESET_BEGIN, - KSRESET_END -}KSRESET; - -typedef enum -{ - KSSTATE_STOP, - KSSTATE_ACQUIRE, - KSSTATE_PAUSE, - KSSTATE_RUN -}KSSTATE, * PKSSTATE; - -#define KSPRIORITY_LOW 0x00000001 -#define KSPRIORITY_NORMAL 0x40000000 -#define KSPRIORITY_HIGH 0x80000000 -#define KSPRIORITY_EXCLUSIVE 0xFFFFFFFF - -typedef struct -{ - ULONG PriorityClass; - ULONG PrioritySubClass; -}KSPRIORITY, * PKSPRIORITY; - -typedef struct -{ - __MINGW_EXTENSION union - { - _KS_ANON_STRUCT(_IDENTIFIER) - { - GUID Set; - ULONG Id; - ULONG Flags; - }; - LONGLONG Alignment; - }; -}KSIDENTIFIER, * PKSIDENTIFIER; - -typedef KSIDENTIFIER KSPROPERTY, * PKSPROPERTY, KSMETHOD, * PKSMETHOD, KSEVENT, * PKSEVENT; - -#define KSMETHOD_TYPE_NONE 0x00000000 -#define KSMETHOD_TYPE_READ 0x00000001 -#define KSMETHOD_TYPE_WRITE 0x00000002 -#define KSMETHOD_TYPE_MODIFY 0x00000003 -#define KSMETHOD_TYPE_SOURCE 0x00000004 - -#define KSMETHOD_TYPE_SEND 0x00000001 -#define KSMETHOD_TYPE_SETSUPPORT 0x00000100 -#define KSMETHOD_TYPE_BASICSUPPORT 0x00000200 - -#define KSMETHOD_TYPE_TOPOLOGY 0x10000000 - -#define KSPROPERTY_TYPE_GET 0x00000001 -#define KSPROPERTY_TYPE_SET 0x00000002 -#define KSPROPERTY_TYPE_SETSUPPORT 0x00000100 -#define KSPROPERTY_TYPE_BASICSUPPORT 0x00000200 -#define KSPROPERTY_TYPE_RELATIONS 0x00000400 -#define KSPROPERTY_TYPE_SERIALIZESET 0x00000800 -#define KSPROPERTY_TYPE_UNSERIALIZESET 0x00001000 -#define KSPROPERTY_TYPE_SERIALIZERAW 0x00002000 -#define KSPROPERTY_TYPE_UNSERIALIZERAW 0x00004000 -#define KSPROPERTY_TYPE_SERIALIZESIZE 0x00008000 -#define KSPROPERTY_TYPE_DEFAULTVALUES 0x00010000 - -#define KSPROPERTY_TYPE_TOPOLOGY 0x10000000 - -typedef struct -{ - KSPROPERTY Property; - ULONG NodeId; - ULONG Reserved; -}KSP_NODE, * PKSP_NODE; - -typedef struct -{ - KSMETHOD Method; - ULONG NodeId; - ULONG Reserved; -}KSM_NODE, * PKSM_NODE; - -typedef struct -{ - KSEVENT Event; - ULONG NodeId; - ULONG Reserved; -}KSE_NODE, * PKSE_NODE; - -#define STATIC_KSPROPTYPESETID_General \ - 0x97E99BA0L, 0xBDEA, 0x11CF, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 -DEFINE_GUIDSTRUCT("97E99BA0-BDEA-11CF-A5D6-28DB04C10000", KSPROPTYPESETID_General); -#define KSPROPTYPESETID_General DEFINE_GUIDNAMED(KSPROPTYPESETID_General) - -typedef struct -{ - ULONG Size; - ULONG Count; -}KSMULTIPLE_ITEM, * PKSMULTIPLE_ITEM; - -typedef struct -{ - ULONG AccessFlags; - ULONG DescriptionSize; - KSIDENTIFIER PropTypeSet; - ULONG MembersListCount; - ULONG Reserved; -}KSPROPERTY_DESCRIPTION, * PKSPROPERTY_DESCRIPTION; - -#define KSPROPERTY_MEMBER_RANGES 0x00000001 -#define KSPROPERTY_MEMBER_STEPPEDRANGES 0x00000002 -#define KSPROPERTY_MEMBER_VALUES 0x00000003 - -#define KSPROPERTY_MEMBER_FLAG_DEFAULT 0x00000001 -#define KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_MULTICHANNEL 0x00000002 -#define KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_UNIFORM 0x00000004 - -typedef struct -{ - ULONG MembersFlags; - ULONG MembersSize; - ULONG MembersCount; - ULONG Flags; -}KSPROPERTY_MEMBERSHEADER, * PKSPROPERTY_MEMBERSHEADER; - -typedef union -{ - _KS_ANON_STRUCT(_SIGNED) - { - LONG SignedMinimum; - LONG SignedMaximum; - }; - _KS_ANON_STRUCT(_UNSIGNED) - { - ULONG UnsignedMinimum; - ULONG UnsignedMaximum; - }; -}KSPROPERTY_BOUNDS_LONG, * PKSPROPERTY_BOUNDS_LONG; - -typedef union -{ - _KS_ANON_STRUCT(_SIGNED64) - { - LONGLONG SignedMinimum; - LONGLONG SignedMaximum; - }; - _KS_ANON_STRUCT(_UNSIGNED64) - { - DWORDLONG UnsignedMinimum; - DWORDLONG UnsignedMaximum; - }; -}KSPROPERTY_BOUNDS_LONGLONG, * PKSPROPERTY_BOUNDS_LONGLONG; - -typedef struct -{ - ULONG SteppingDelta; - ULONG Reserved; - KSPROPERTY_BOUNDS_LONG Bounds; -}KSPROPERTY_STEPPING_LONG, * PKSPROPERTY_STEPPING_LONG; - -typedef struct -{ - DWORDLONG SteppingDelta; - KSPROPERTY_BOUNDS_LONGLONG Bounds; -}KSPROPERTY_STEPPING_LONGLONG, * PKSPROPERTY_STEPPING_LONGLONG; - -#if defined(_NTDDK_) -typedef struct _KSDEVICE_DESCRIPTOR KSDEVICE_DESCRIPTOR, * PKSDEVICE_DESCRIPTOR; -typedef struct _KSDEVICE_DISPATCH KSDEVICE_DISPATCH, * PKSDEVICE_DISPATCH; -typedef struct _KSDEVICE KSDEVICE, * PKSDEVICE; -typedef struct _KSFILTERFACTORY KSFILTERFACTORY, * PKSFILTERFACTORY; -typedef struct _KSFILTER_DESCRIPTOR KSFILTER_DESCRIPTOR, * PKSFILTER_DESCRIPTOR; -typedef struct _KSFILTER_DISPATCH KSFILTER_DISPATCH, * PKSFILTER_DISPATCH; -typedef struct _KSFILTER KSFILTER, * PKSFILTER; -typedef struct _KSPIN_DESCRIPTOR_EX KSPIN_DESCRIPTOR_EX, * PKSPIN_DESCRIPTOR_EX; -typedef struct _KSPIN_DISPATCH KSPIN_DISPATCH, * PKSPIN_DISPATCH; -typedef struct _KSCLOCK_DISPATCH KSCLOCK_DISPATCH, * PKSCLOCK_DISPATCH; -typedef struct _KSALLOCATOR_DISPATCH KSALLOCATOR_DISPATCH, * PKSALLOCATOR_DISPATCH; -typedef struct _KSPIN KSPIN, * PKSPIN; -typedef struct _KSNODE_DESCRIPTOR KSNODE_DESCRIPTOR, * PKSNODE_DESCRIPTOR; -typedef struct _KSSTREAM_POINTER_OFFSET KSSTREAM_POINTER_OFFSET, * PKSSTREAM_POINTER_OFFSET; -typedef struct _KSSTREAM_POINTER KSSTREAM_POINTER, * PKSSTREAM_POINTER; -typedef struct _KSMAPPING KSMAPPING, * PKSMAPPING; -typedef struct _KSPROCESSPIN KSPROCESSPIN, * PKSPROCESSPIN; -typedef struct _KSPROCESSPIN_INDEXENTRY KSPROCESSPIN_INDEXENTRY, * PKSPROCESSPIN_INDEXENTRY; -#endif /* _NTDDK_ */ - -typedef PVOID PKSWORKER; - -typedef struct -{ - ULONG NotificationType; - __MINGW_EXTENSION union - { - struct - { - HANDLE Event; - ULONG_PTR Reserved[2]; - }EventHandle; - struct - { - HANDLE Semaphore; - ULONG Reserved; - LONG Adjustment; - }SemaphoreHandle; -#if defined(_NTDDK_) - struct - { - PVOID Event; - KPRIORITY Increment; - ULONG_PTR Reserved; - }EventObject; - struct - { - PVOID Semaphore; - KPRIORITY Increment; - LONG Adjustment; - }SemaphoreObject; - struct - { - PKDPC Dpc; - ULONG ReferenceCount; - ULONG_PTR Reserved; - }Dpc; - struct - { - PWORK_QUEUE_ITEM WorkQueueItem; - WORK_QUEUE_TYPE WorkQueueType; - ULONG_PTR Reserved; - }WorkItem; - struct - { - PWORK_QUEUE_ITEM WorkQueueItem; - PKSWORKER KsWorkerObject; - ULONG_PTR Reserved; - }KsWorkItem; -#endif /* _NTDDK_ */ - struct - { - PVOID Unused; - LONG_PTR Alignment[2]; - }Alignment; - }; -}KSEVENTDATA, * PKSEVENTDATA; - -#define KSEVENTF_EVENT_HANDLE 0x00000001 -#define KSEVENTF_SEMAPHORE_HANDLE 0x00000002 -#if defined(_NTDDK_) - # define KSEVENTF_EVENT_OBJECT 0x00000004 - # define KSEVENTF_SEMAPHORE_OBJECT 0x00000008 - # define KSEVENTF_DPC 0x00000010 - # define KSEVENTF_WORKITEM 0x00000020 - # define KSEVENTF_KSWORKITEM 0x00000080 -#endif /* _NTDDK_ */ - -#define KSEVENT_TYPE_ENABLE 0x00000001 -#define KSEVENT_TYPE_ONESHOT 0x00000002 -#define KSEVENT_TYPE_ENABLEBUFFERED 0x00000004 -#define KSEVENT_TYPE_SETSUPPORT 0x00000100 -#define KSEVENT_TYPE_BASICSUPPORT 0x00000200 -#define KSEVENT_TYPE_QUERYBUFFER 0x00000400 - -#define KSEVENT_TYPE_TOPOLOGY 0x10000000 - -typedef struct -{ - KSEVENT Event; - PKSEVENTDATA EventData; - PVOID Reserved; -}KSQUERYBUFFER, * PKSQUERYBUFFER; - -typedef struct -{ - ULONG Size; - ULONG Flags; - __MINGW_EXTENSION union - { - HANDLE ObjectHandle; - PVOID ObjectPointer; - }; - PVOID Reserved; - KSEVENT Event; - KSEVENTDATA EventData; -}KSRELATIVEEVENT; - -#define KSRELATIVEEVENT_FLAG_HANDLE 0x00000001 -#define KSRELATIVEEVENT_FLAG_POINTER 0x00000002 - -typedef struct -{ - KSEVENTDATA EventData; - LONGLONG MarkTime; -}KSEVENT_TIME_MARK, * PKSEVENT_TIME_MARK; - -typedef struct -{ - KSEVENTDATA EventData; - LONGLONG TimeBase; - LONGLONG Interval; -}KSEVENT_TIME_INTERVAL, * PKSEVENT_TIME_INTERVAL; - -typedef struct -{ - LONGLONG TimeBase; - LONGLONG Interval; -}KSINTERVAL, * PKSINTERVAL; - -#define STATIC_KSPROPSETID_General \ - 0x1464EDA5L, 0x6A8F, 0x11D1, 0x9A, 0xA7, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 -DEFINE_GUIDSTRUCT("1464EDA5-6A8F-11D1-9AA7-00A0C9223196", KSPROPSETID_General); -#define KSPROPSETID_General DEFINE_GUIDNAMED(KSPROPSETID_General) - -typedef enum -{ - KSPROPERTY_GENERAL_COMPONENTID -}KSPROPERTY_GENERAL; - -typedef struct -{ - GUID Manufacturer; - GUID Product; - GUID Component; - GUID Name; - ULONG Version; - ULONG Revision; -}KSCOMPONENTID, * PKSCOMPONENTID; - -#define DEFINE_KSPROPERTY_ITEM_GENERAL_COMPONENTID(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_GENERAL_COMPONENTID, \ - (Handler), \ - sizeof(KSPROPERTY), \ - sizeof(KSCOMPONENTID), \ - NULL, NULL, 0, NULL, NULL, 0) - -#define STATIC_KSMETHODSETID_StreamIo \ - 0x65D003CAL, 0x1523, 0x11D2, 0xB2, 0x7A, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 -DEFINE_GUIDSTRUCT("65D003CA-1523-11D2-B27A-00A0C9223196", KSMETHODSETID_StreamIo); -#define KSMETHODSETID_StreamIo DEFINE_GUIDNAMED(KSMETHODSETID_StreamIo) - -typedef enum -{ - KSMETHOD_STREAMIO_READ, - KSMETHOD_STREAMIO_WRITE -}KSMETHOD_STREAMIO; - -#define DEFINE_KSMETHOD_ITEM_STREAMIO_READ(Handler) \ - DEFINE_KSMETHOD_ITEM( \ - KSMETHOD_STREAMIO_READ, \ - KSMETHOD_TYPE_WRITE, \ - (Handler), \ - sizeof(KSMETHOD), \ - 0, \ - NULL) - -#define DEFINE_KSMETHOD_ITEM_STREAMIO_WRITE(Handler) \ - DEFINE_KSMETHOD_ITEM( \ - KSMETHOD_STREAMIO_WRITE, \ - KSMETHOD_TYPE_READ, \ - (Handler), \ - sizeof(KSMETHOD), \ - 0, \ - NULL) - -#define STATIC_KSPROPSETID_MediaSeeking \ - 0xEE904F0CL, 0xD09B, 0x11D0, 0xAB, 0xE9, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 -DEFINE_GUIDSTRUCT("EE904F0C-D09B-11D0-ABE9-00A0C9223196", KSPROPSETID_MediaSeeking); -#define KSPROPSETID_MediaSeeking DEFINE_GUIDNAMED(KSPROPSETID_MediaSeeking) - -typedef enum -{ - KSPROPERTY_MEDIASEEKING_CAPABILITIES, - KSPROPERTY_MEDIASEEKING_FORMATS, - KSPROPERTY_MEDIASEEKING_TIMEFORMAT, - KSPROPERTY_MEDIASEEKING_POSITION, - KSPROPERTY_MEDIASEEKING_STOPPOSITION, - KSPROPERTY_MEDIASEEKING_POSITIONS, - KSPROPERTY_MEDIASEEKING_DURATION, - KSPROPERTY_MEDIASEEKING_AVAILABLE, - KSPROPERTY_MEDIASEEKING_PREROLL, - KSPROPERTY_MEDIASEEKING_CONVERTTIMEFORMAT -}KSPROPERTY_MEDIASEEKING; - -typedef enum -{ - KS_SEEKING_NoPositioning, - KS_SEEKING_AbsolutePositioning, - KS_SEEKING_RelativePositioning, - KS_SEEKING_IncrementalPositioning, - KS_SEEKING_PositioningBitsMask = 0x3, - KS_SEEKING_SeekToKeyFrame, - KS_SEEKING_ReturnTime = 0x8 -}KS_SEEKING_FLAGS; - -typedef enum -{ - KS_SEEKING_CanSeekAbsolute = 0x1, - KS_SEEKING_CanSeekForwards = 0x2, - KS_SEEKING_CanSeekBackwards = 0x4, - KS_SEEKING_CanGetCurrentPos = 0x8, - KS_SEEKING_CanGetStopPos = 0x10, - KS_SEEKING_CanGetDuration = 0x20, - KS_SEEKING_CanPlayBackwards = 0x40 -}KS_SEEKING_CAPABILITIES; - -typedef struct -{ - LONGLONG Current; - LONGLONG Stop; - KS_SEEKING_FLAGS CurrentFlags; - KS_SEEKING_FLAGS StopFlags; -}KSPROPERTY_POSITIONS, * PKSPROPERTY_POSITIONS; - -typedef struct -{ - LONGLONG Earliest; - LONGLONG Latest; -}KSPROPERTY_MEDIAAVAILABLE, * PKSPROPERTY_MEDIAAVAILABLE; - -typedef struct -{ - KSPROPERTY Property; - GUID SourceFormat; - GUID TargetFormat; - LONGLONG Time; -}KSP_TIMEFORMAT, * PKSP_TIMEFORMAT; - -#define DEFINE_KSPROPERTY_ITEM_MEDIASEEKING_CAPABILITIES(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_MEDIASEEKING_CAPABILITIES, \ - (Handler), \ - sizeof(KSPROPERTY), \ - sizeof(KS_SEEKING_CAPABILITIES), \ - NULL, NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_MEDIASEEKING_FORMATS(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_MEDIASEEKING_FORMATS, \ - (Handler), \ - sizeof(KSPROPERTY), \ - 0, \ - NULL, NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_MEDIASEEKING_TIMEFORMAT(GetHandler, SetHandler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_MEDIASEEKING_TIMEFORMAT, \ - (GetHandler), \ - sizeof(KSPROPERTY), \ - sizeof(GUID), \ - (SetHandler), \ - NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_MEDIASEEKING_POSITION(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_MEDIASEEKING_POSITION, \ - (Handler), \ - sizeof(KSPROPERTY), \ - sizeof(LONGLONG), \ - NULL, NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_MEDIASEEKING_STOPPOSITION(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_MEDIASEEKING_STOPPOSITION, \ - (Handler), \ - sizeof(KSPROPERTY), \ - sizeof(LONGLONG), \ - NULL, NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_MEDIASEEKING_POSITIONS(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_MEDIASEEKING_POSITIONS, \ - NULL, \ - sizeof(KSPROPERTY), \ - sizeof(KSPROPERTY_POSITIONS), \ - (Handler), \ - NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_MEDIASEEKING_DURATION(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_MEDIASEEKING_DURATION, \ - (Handler), \ - sizeof(KSPROPERTY), \ - sizeof(LONGLONG), \ - NULL, NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_MEDIASEEKING_AVAILABLE(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_MEDIASEEKING_AVAILABLE, \ - (Handler), \ - sizeof(KSPROPERTY), \ - sizeof(KSPROPERTY_MEDIAAVAILABLE), \ - NULL, NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_MEDIASEEKING_PREROLL(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_MEDIASEEKING_PREROLL, \ - (Handler), \ - sizeof(KSPROPERTY), \ - sizeof(LONGLONG), \ - NULL, NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_MEDIASEEKING_CONVERTTIMEFORMAT(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_MEDIASEEKING_CONVERTTIMEFORMAT, \ - (Handler), \ - sizeof(KSP_TIMEFORMAT), \ - sizeof(LONGLONG), \ - NULL, NULL, 0, NULL, NULL, 0) - -#define STATIC_KSPROPSETID_Topology \ - 0x720D4AC0L, 0x7533, 0x11D0, { 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 } -DEFINE_GUIDSTRUCT("720D4AC0-7533-11D0-A5D6-28DB04C10000", KSPROPSETID_Topology); -#define KSPROPSETID_Topology DEFINE_GUIDNAMED(KSPROPSETID_Topology) - -typedef enum -{ - KSPROPERTY_TOPOLOGY_CATEGORIES, - KSPROPERTY_TOPOLOGY_NODES, - KSPROPERTY_TOPOLOGY_CONNECTIONS, - KSPROPERTY_TOPOLOGY_NAME -}KSPROPERTY_TOPOLOGY; - -#define DEFINE_KSPROPERTY_ITEM_TOPOLOGY_CATEGORIES(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_TOPOLOGY_CATEGORIES, \ - (Handler), \ - sizeof(KSPROPERTY), \ - 0, \ - NULL, NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_TOPOLOGY_NODES(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_TOPOLOGY_NODES, \ - (Handler), \ - sizeof(KSPROPERTY), \ - 0, \ - NULL, NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_TOPOLOGY_CONNECTIONS(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_TOPOLOGY_CONNECTIONS, \ - (Handler), \ - sizeof(KSPROPERTY), \ - 0, \ - NULL, NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_TOPOLOGY_NAME(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_TOPOLOGY_NAME, \ - (Handler), \ - sizeof(KSP_NODE), \ - 0, \ - NULL, NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_TOPOLOGYSET(TopologySet, Handler) \ - DEFINE_KSPROPERTY_TABLE(TopologySet) { \ - DEFINE_KSPROPERTY_ITEM_TOPOLOGY_CATEGORIES(Handler), \ - DEFINE_KSPROPERTY_ITEM_TOPOLOGY_NODES(Handler), \ - DEFINE_KSPROPERTY_ITEM_TOPOLOGY_CONNECTIONS(Handler), \ - DEFINE_KSPROPERTY_ITEM_TOPOLOGY_NAME(Handler) \ - } - -#define STATIC_KSCATEGORY_BRIDGE \ - 0x085AFF00L, 0x62CE, 0x11CF, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 -DEFINE_GUIDSTRUCT("085AFF00-62CE-11CF-A5D6-28DB04C10000", KSCATEGORY_BRIDGE); -#define KSCATEGORY_BRIDGE DEFINE_GUIDNAMED(KSCATEGORY_BRIDGE) - -#define STATIC_KSCATEGORY_CAPTURE \ - 0x65E8773DL, 0x8F56, 0x11D0, { 0xA3, 0xB9, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 } -DEFINE_GUIDSTRUCT("65E8773D-8F56-11D0-A3B9-00A0C9223196", KSCATEGORY_CAPTURE); -#define KSCATEGORY_CAPTURE DEFINE_GUIDNAMED(KSCATEGORY_CAPTURE) - -#define STATIC_KSCATEGORY_RENDER \ - 0x65E8773EL, 0x8F56, 0x11D0, { 0xA3, 0xB9, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 } -DEFINE_GUIDSTRUCT("65E8773E-8F56-11D0-A3B9-00A0C9223196", KSCATEGORY_RENDER); -#define KSCATEGORY_RENDER DEFINE_GUIDNAMED(KSCATEGORY_RENDER) - -#define STATIC_KSCATEGORY_MIXER \ - 0xAD809C00L, 0x7B88, 0x11D0, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 -DEFINE_GUIDSTRUCT("AD809C00-7B88-11D0-A5D6-28DB04C10000", KSCATEGORY_MIXER); -#define KSCATEGORY_MIXER DEFINE_GUIDNAMED(KSCATEGORY_MIXER) - -#define STATIC_KSCATEGORY_SPLITTER \ - 0x0A4252A0L, 0x7E70, 0x11D0, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 -DEFINE_GUIDSTRUCT("0A4252A0-7E70-11D0-A5D6-28DB04C10000", KSCATEGORY_SPLITTER); -#define KSCATEGORY_SPLITTER DEFINE_GUIDNAMED(KSCATEGORY_SPLITTER) - -#define STATIC_KSCATEGORY_DATACOMPRESSOR \ - 0x1E84C900L, 0x7E70, 0x11D0, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 -DEFINE_GUIDSTRUCT("1E84C900-7E70-11D0-A5D6-28DB04C10000", KSCATEGORY_DATACOMPRESSOR); -#define KSCATEGORY_DATACOMPRESSOR DEFINE_GUIDNAMED(KSCATEGORY_DATACOMPRESSOR) - -#define STATIC_KSCATEGORY_DATADECOMPRESSOR \ - 0x2721AE20L, 0x7E70, 0x11D0, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 -DEFINE_GUIDSTRUCT("2721AE20-7E70-11D0-A5D6-28DB04C10000", KSCATEGORY_DATADECOMPRESSOR); -#define KSCATEGORY_DATADECOMPRESSOR DEFINE_GUIDNAMED(KSCATEGORY_DATADECOMPRESSOR) - -#define STATIC_KSCATEGORY_DATATRANSFORM \ - 0x2EB07EA0L, 0x7E70, 0x11D0, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 -DEFINE_GUIDSTRUCT("2EB07EA0-7E70-11D0-A5D6-28DB04C10000", KSCATEGORY_DATATRANSFORM); -#define KSCATEGORY_DATATRANSFORM DEFINE_GUIDNAMED(KSCATEGORY_DATATRANSFORM) - -#define STATIC_KSCATEGORY_COMMUNICATIONSTRANSFORM \ - 0xCF1DDA2CL, 0x9743, 0x11D0, 0xA3, 0xEE, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 -DEFINE_GUIDSTRUCT("CF1DDA2C-9743-11D0-A3EE-00A0C9223196", KSCATEGORY_COMMUNICATIONSTRANSFORM); -#define KSCATEGORY_COMMUNICATIONSTRANSFORM DEFINE_GUIDNAMED(KSCATEGORY_COMMUNICATIONSTRANSFORM) - -#define STATIC_KSCATEGORY_INTERFACETRANSFORM \ - 0xCF1DDA2DL, 0x9743, 0x11D0, 0xA3, 0xEE, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 -DEFINE_GUIDSTRUCT("CF1DDA2D-9743-11D0-A3EE-00A0C9223196", KSCATEGORY_INTERFACETRANSFORM); -#define KSCATEGORY_INTERFACETRANSFORM DEFINE_GUIDNAMED(KSCATEGORY_INTERFACETRANSFORM) - -#define STATIC_KSCATEGORY_MEDIUMTRANSFORM \ - 0xCF1DDA2EL, 0x9743, 0x11D0, 0xA3, 0xEE, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 -DEFINE_GUIDSTRUCT("CF1DDA2E-9743-11D0-A3EE-00A0C9223196", KSCATEGORY_MEDIUMTRANSFORM); -#define KSCATEGORY_MEDIUMTRANSFORM DEFINE_GUIDNAMED(KSCATEGORY_MEDIUMTRANSFORM) - -#define STATIC_KSCATEGORY_FILESYSTEM \ - 0x760FED5EL, 0x9357, 0x11D0, 0xA3, 0xCC, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 -DEFINE_GUIDSTRUCT("760FED5E-9357-11D0-A3CC-00A0C9223196", KSCATEGORY_FILESYSTEM); -#define KSCATEGORY_FILESYSTEM DEFINE_GUIDNAMED(KSCATEGORY_FILESYSTEM) - -#define STATIC_KSCATEGORY_CLOCK \ - 0x53172480L, 0x4791, 0x11D0, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 -DEFINE_GUIDSTRUCT("53172480-4791-11D0-A5D6-28DB04C10000", KSCATEGORY_CLOCK); -#define KSCATEGORY_CLOCK DEFINE_GUIDNAMED(KSCATEGORY_CLOCK) - -#define STATIC_KSCATEGORY_PROXY \ - 0x97EBAACAL, 0x95BD, 0x11D0, 0xA3, 0xEA, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 -DEFINE_GUIDSTRUCT("97EBAACA-95BD-11D0-A3EA-00A0C9223196", KSCATEGORY_PROXY); -#define KSCATEGORY_PROXY DEFINE_GUIDNAMED(KSCATEGORY_PROXY) - -#define STATIC_KSCATEGORY_QUALITY \ - 0x97EBAACBL, 0x95BD, 0x11D0, 0xA3, 0xEA, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 -DEFINE_GUIDSTRUCT("97EBAACB-95BD-11D0-A3EA-00A0C9223196", KSCATEGORY_QUALITY); -#define KSCATEGORY_QUALITY DEFINE_GUIDNAMED(KSCATEGORY_QUALITY) - -typedef struct -{ - ULONG FromNode; - ULONG FromNodePin; - ULONG ToNode; - ULONG ToNodePin; -}KSTOPOLOGY_CONNECTION, * PKSTOPOLOGY_CONNECTION; - -typedef struct -{ - ULONG CategoriesCount; - const GUID* Categories; - ULONG TopologyNodesCount; - const GUID* TopologyNodes; - ULONG TopologyConnectionsCount; - const KSTOPOLOGY_CONNECTION* TopologyConnections; - const GUID* TopologyNodesNames; - ULONG Reserved; -}KSTOPOLOGY, * PKSTOPOLOGY; - -#define KSFILTER_NODE ((ULONG)-1) -#define KSALL_NODES ((ULONG)-1) - -typedef struct -{ - ULONG CreateFlags; - ULONG Node; -}KSNODE_CREATE, * PKSNODE_CREATE; - -#define STATIC_KSTIME_FORMAT_NONE STATIC_GUID_NULL -#define KSTIME_FORMAT_NONE GUID_NULL - -#define STATIC_KSTIME_FORMAT_FRAME \ - 0x7b785570L, 0x8c82, 0x11cf, 0xbc, 0x0c, 0x00, 0xaa, 0x00, 0xac, 0x74, 0xf6 -DEFINE_GUIDSTRUCT("7b785570-8c82-11cf-bc0c-00aa00ac74f6", KSTIME_FORMAT_FRAME); -#define KSTIME_FORMAT_FRAME DEFINE_GUIDNAMED(KSTIME_FORMAT_FRAME) - -#define STATIC_KSTIME_FORMAT_BYTE \ - 0x7b785571L, 0x8c82, 0x11cf, 0xbc, 0x0c, 0x00, 0xaa, 0x00, 0xac, 0x74, 0xf6 -DEFINE_GUIDSTRUCT("7b785571-8c82-11cf-bc0c-00aa00ac74f6", KSTIME_FORMAT_BYTE); -#define KSTIME_FORMAT_BYTE DEFINE_GUIDNAMED(KSTIME_FORMAT_BYTE) - -#define STATIC_KSTIME_FORMAT_SAMPLE \ - 0x7b785572L, 0x8c82, 0x11cf, 0xbc, 0x0c, 0x00, 0xaa, 0x00, 0xac, 0x74, 0xf6 -DEFINE_GUIDSTRUCT("7b785572-8c82-11cf-bc0c-00aa00ac74f6", KSTIME_FORMAT_SAMPLE); -#define KSTIME_FORMAT_SAMPLE DEFINE_GUIDNAMED(KSTIME_FORMAT_SAMPLE) - -#define STATIC_KSTIME_FORMAT_FIELD \ - 0x7b785573L, 0x8c82, 0x11cf, 0xbc, 0x0c, 0x00, 0xaa, 0x00, 0xac, 0x74, 0xf6 -DEFINE_GUIDSTRUCT("7b785573-8c82-11cf-bc0c-00aa00ac74f6", KSTIME_FORMAT_FIELD); -#define KSTIME_FORMAT_FIELD DEFINE_GUIDNAMED(KSTIME_FORMAT_FIELD) - -#define STATIC_KSTIME_FORMAT_MEDIA_TIME \ - 0x7b785574L, 0x8c82, 0x11cf, 0xbc, 0x0c, 0x00, 0xaa, 0x00, 0xac, 0x74, 0xf6 -DEFINE_GUIDSTRUCT("7b785574-8c82-11cf-bc0c-00aa00ac74f6", KSTIME_FORMAT_MEDIA_TIME); -#define KSTIME_FORMAT_MEDIA_TIME DEFINE_GUIDNAMED(KSTIME_FORMAT_MEDIA_TIME) - -typedef KSIDENTIFIER KSPIN_INTERFACE, * PKSPIN_INTERFACE; - -#define STATIC_KSINTERFACESETID_Standard \ - 0x1A8766A0L, 0x62CE, 0x11CF, { 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 } -DEFINE_GUIDSTRUCT("1A8766A0-62CE-11CF-A5D6-28DB04C10000", KSINTERFACESETID_Standard); -#define KSINTERFACESETID_Standard DEFINE_GUIDNAMED(KSINTERFACESETID_Standard) - -typedef enum -{ - KSINTERFACE_STANDARD_STREAMING, - KSINTERFACE_STANDARD_LOOPED_STREAMING, - KSINTERFACE_STANDARD_CONTROL -}KSINTERFACE_STANDARD; - -#define STATIC_KSINTERFACESETID_FileIo \ - 0x8C6F932CL, 0xE771, 0x11D0, 0xB8, 0xFF, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 -DEFINE_GUIDSTRUCT("8C6F932C-E771-11D0-B8FF-00A0C9223196", KSINTERFACESETID_FileIo); -#define KSINTERFACESETID_FileIo DEFINE_GUIDNAMED(KSINTERFACESETID_FileIo) - -typedef enum -{ - KSINTERFACE_FILEIO_STREAMING -}KSINTERFACE_FILEIO; - -#define KSMEDIUM_TYPE_ANYINSTANCE 0 - -#define STATIC_KSMEDIUMSETID_Standard \ - 0x4747B320L, 0x62CE, 0x11CF, { 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 } -DEFINE_GUIDSTRUCT("4747B320-62CE-11CF-A5D6-28DB04C10000", KSMEDIUMSETID_Standard); -#define KSMEDIUMSETID_Standard DEFINE_GUIDNAMED(KSMEDIUMSETID_Standard) - -#define KSMEDIUM_STANDARD_DEVIO KSMEDIUM_TYPE_ANYINSTANCE - -#define STATIC_KSPROPSETID_Pin \ - 0x8C134960L, 0x51AD, 0x11CF, { 0x87, 0x8A, 0x94, 0xF8, 0x01, 0xC1, 0x00, 0x00 } -DEFINE_GUIDSTRUCT("8C134960-51AD-11CF-878A-94F801C10000", KSPROPSETID_Pin); -#define KSPROPSETID_Pin DEFINE_GUIDNAMED(KSPROPSETID_Pin) - -typedef enum -{ - KSPROPERTY_PIN_CINSTANCES, - KSPROPERTY_PIN_CTYPES, - KSPROPERTY_PIN_DATAFLOW, - KSPROPERTY_PIN_DATARANGES, - KSPROPERTY_PIN_DATAINTERSECTION, - KSPROPERTY_PIN_INTERFACES, - KSPROPERTY_PIN_MEDIUMS, - KSPROPERTY_PIN_COMMUNICATION, - KSPROPERTY_PIN_GLOBALCINSTANCES, - KSPROPERTY_PIN_NECESSARYINSTANCES, - KSPROPERTY_PIN_PHYSICALCONNECTION, - KSPROPERTY_PIN_CATEGORY, - KSPROPERTY_PIN_NAME, - KSPROPERTY_PIN_CONSTRAINEDDATARANGES, - KSPROPERTY_PIN_PROPOSEDATAFORMAT -}KSPROPERTY_PIN; - -typedef struct -{ - KSPROPERTY Property; - ULONG PinId; - ULONG Reserved; -}KSP_PIN, * PKSP_PIN; - -#define KSINSTANCE_INDETERMINATE ((ULONG)-1) - -typedef struct -{ - ULONG PossibleCount; - ULONG CurrentCount; -}KSPIN_CINSTANCES, * PKSPIN_CINSTANCES; - -typedef enum -{ - KSPIN_DATAFLOW_IN = 1, - KSPIN_DATAFLOW_OUT -}KSPIN_DATAFLOW, * PKSPIN_DATAFLOW; - -#define KSDATAFORMAT_BIT_TEMPORAL_COMPRESSION 0 -#define KSDATAFORMAT_TEMPORAL_COMPRESSION (1 << KSDATAFORMAT_BIT_TEMPORAL_COMPRESSION) -#define KSDATAFORMAT_BIT_ATTRIBUTES 1 -#define KSDATAFORMAT_ATTRIBUTES (1 << KSDATAFORMAT_BIT_ATTRIBUTES) - -#define KSDATARANGE_BIT_ATTRIBUTES 1 -#define KSDATARANGE_ATTRIBUTES (1 << KSDATARANGE_BIT_ATTRIBUTES) -#define KSDATARANGE_BIT_REQUIRED_ATTRIBUTES 2 -#define KSDATARANGE_REQUIRED_ATTRIBUTES (1 << KSDATARANGE_BIT_REQUIRED_ATTRIBUTES) - -typedef union -{ - __MINGW_EXTENSION struct - { - ULONG FormatSize; - ULONG Flags; - ULONG SampleSize; - ULONG Reserved; - GUID MajorFormat; - GUID SubFormat; - GUID Specifier; - }; - LONGLONG Alignment; -}KSDATAFORMAT, * PKSDATAFORMAT, KSDATARANGE, * PKSDATARANGE; - -#define KSATTRIBUTE_REQUIRED 0x00000001 - -typedef struct -{ - ULONG Size; - ULONG Flags; - GUID Attribute; -}KSATTRIBUTE, * PKSATTRIBUTE; - -#if defined(_NTDDK_) -typedef struct -{ - ULONG Count; - PKSATTRIBUTE* Attributes; -}KSATTRIBUTE_LIST, * PKSATTRIBUTE_LIST; -#endif /* _NTDDK_ */ - -typedef enum -{ - KSPIN_COMMUNICATION_NONE, - KSPIN_COMMUNICATION_SINK, - KSPIN_COMMUNICATION_SOURCE, - KSPIN_COMMUNICATION_BOTH, - KSPIN_COMMUNICATION_BRIDGE -}KSPIN_COMMUNICATION, * PKSPIN_COMMUNICATION; - -typedef KSIDENTIFIER KSPIN_MEDIUM, * PKSPIN_MEDIUM; - -typedef struct -{ - KSPIN_INTERFACE Interface; - KSPIN_MEDIUM Medium; - ULONG PinId; - HANDLE PinToHandle; - KSPRIORITY Priority; -}KSPIN_CONNECT, * PKSPIN_CONNECT; - -typedef struct -{ - ULONG Size; - ULONG Pin; - WCHAR SymbolicLinkName[1]; -}KSPIN_PHYSICALCONNECTION, * PKSPIN_PHYSICALCONNECTION; - -#if defined(_NTDDK_) -typedef NTSTATUS (*PFNKSINTERSECTHANDLER)(PIRP Irp, PKSP_PIN Pin, - PKSDATARANGE DataRange, - PVOID Data); -typedef NTSTATUS (*PFNKSINTERSECTHANDLEREX)(PVOID Context, PIRP Irp, - PKSP_PIN Pin, - PKSDATARANGE DataRange, - PKSDATARANGE MatchingDataRange, - ULONG DataBufferSize, - PVOID Data, - PULONG DataSize); -#endif /* _NTDDK_ */ - -#define DEFINE_KSPIN_INTERFACE_TABLE(tablename) \ - const KSPIN_INTERFACE tablename[] = - -#define DEFINE_KSPIN_INTERFACE_ITEM(guid, _interFace) \ - { \ - STATICGUIDOF(guid), \ - (_interFace), \ - 0 \ - } - -#define DEFINE_KSPIN_MEDIUM_TABLE(tablename) \ - const KSPIN_MEDIUM tablename[] = - -#define DEFINE_KSPIN_MEDIUM_ITEM(guid, medium) \ - DEFINE_KSPIN_INTERFACE_ITEM(guid, medium) - -#define DEFINE_KSPROPERTY_ITEM_PIN_CINSTANCES(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_PIN_CINSTANCES, \ - (Handler), \ - sizeof(KSP_PIN), \ - sizeof(KSPIN_CINSTANCES), \ - NULL, NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_PIN_CTYPES(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_PIN_CTYPES, \ - (Handler), \ - sizeof(KSPROPERTY), \ - sizeof(ULONG), \ - NULL, NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_PIN_DATAFLOW(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_PIN_DATAFLOW, \ - (Handler), \ - sizeof(KSP_PIN), \ - sizeof(KSPIN_DATAFLOW), \ - NULL, NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_PIN_DATARANGES(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_PIN_DATARANGES, \ - (Handler), \ - sizeof(KSP_PIN), \ - 0, \ - NULL, NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_PIN_DATAINTERSECTION(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_PIN_DATAINTERSECTION, \ - (Handler), \ - sizeof(KSP_PIN) + sizeof(KSMULTIPLE_ITEM), \ - 0, \ - NULL, NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_PIN_INTERFACES(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_PIN_INTERFACES, \ - (Handler), \ - sizeof(KSP_PIN), \ - 0, \ - NULL, NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_PIN_MEDIUMS(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_PIN_MEDIUMS, \ - (Handler), \ - sizeof(KSP_PIN), \ - 0, \ - NULL, NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_PIN_COMMUNICATION(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_PIN_COMMUNICATION, \ - (Handler), \ - sizeof(KSP_PIN), \ - sizeof(KSPIN_COMMUNICATION), \ - NULL, NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_PIN_GLOBALCINSTANCES(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_PIN_GLOBALCINSTANCES, \ - (Handler), \ - sizeof(KSP_PIN), \ - sizeof(KSPIN_CINSTANCES), \ - NULL, NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_PIN_NECESSARYINSTANCES(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_PIN_NECESSARYINSTANCES, \ - (Handler), \ - sizeof(KSP_PIN), \ - sizeof(ULONG), \ - NULL, NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_PIN_PHYSICALCONNECTION(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_PIN_PHYSICALCONNECTION, \ - (Handler), \ - sizeof(KSP_PIN), \ - 0, \ - NULL, NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_PIN_CATEGORY(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_PIN_CATEGORY, \ - (Handler), \ - sizeof(KSP_PIN), \ - sizeof(GUID), \ - NULL, NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_PIN_NAME(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_PIN_NAME, \ - (Handler), \ - sizeof(KSP_PIN), \ - 0, \ - NULL, NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_PIN_CONSTRAINEDDATARANGES(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_PIN_CONSTRAINEDDATARANGES, \ - (Handler), \ - sizeof(KSP_PIN), \ - 0, \ - NULL, NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_PIN_PROPOSEDATAFORMAT(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_PIN_PROPOSEDATAFORMAT, \ - NULL, \ - sizeof(KSP_PIN), \ - sizeof(KSDATAFORMAT), \ - (Handler), NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_PINSET(PinSet, PropGeneral, PropInstances, PropIntersection) \ - DEFINE_KSPROPERTY_TABLE(PinSet) { \ - DEFINE_KSPROPERTY_ITEM_PIN_CINSTANCES(PropInstances), \ - DEFINE_KSPROPERTY_ITEM_PIN_CTYPES(PropGeneral), \ - DEFINE_KSPROPERTY_ITEM_PIN_DATAFLOW(PropGeneral), \ - DEFINE_KSPROPERTY_ITEM_PIN_DATARANGES(PropGeneral), \ - DEFINE_KSPROPERTY_ITEM_PIN_DATAINTERSECTION(PropIntersection), \ - DEFINE_KSPROPERTY_ITEM_PIN_INTERFACES(PropGeneral), \ - DEFINE_KSPROPERTY_ITEM_PIN_MEDIUMS(PropGeneral), \ - DEFINE_KSPROPERTY_ITEM_PIN_COMMUNICATION(PropGeneral), \ - DEFINE_KSPROPERTY_ITEM_PIN_CATEGORY(PropGeneral), \ - DEFINE_KSPROPERTY_ITEM_PIN_NAME(PropGeneral) \ - } - -#define DEFINE_KSPROPERTY_PINSETCONSTRAINED(PinSet, PropGeneral, PropInstances, PropIntersection) \ - DEFINE_KSPROPERTY_TABLE(PinSet) { \ - DEFINE_KSPROPERTY_ITEM_PIN_CINSTANCES(PropInstances), \ - DEFINE_KSPROPERTY_ITEM_PIN_CTYPES(PropGeneral), \ - DEFINE_KSPROPERTY_ITEM_PIN_DATAFLOW(PropGeneral), \ - DEFINE_KSPROPERTY_ITEM_PIN_DATARANGES(PropGeneral), \ - DEFINE_KSPROPERTY_ITEM_PIN_DATAINTERSECTION(PropIntersection), \ - DEFINE_KSPROPERTY_ITEM_PIN_INTERFACES(PropGeneral), \ - DEFINE_KSPROPERTY_ITEM_PIN_MEDIUMS(PropGeneral), \ - DEFINE_KSPROPERTY_ITEM_PIN_COMMUNICATION(PropGeneral), \ - DEFINE_KSPROPERTY_ITEM_PIN_CATEGORY(PropGeneral), \ - DEFINE_KSPROPERTY_ITEM_PIN_NAME(PropGeneral), \ - DEFINE_KSPROPERTY_ITEM_PIN_CONSTRAINEDDATARANGES(PropGeneral) \ - } - -#define STATIC_KSNAME_Filter \ - 0x9b365890L, 0x165f, 0x11d0, 0xa1, 0x95, 0x00, 0x20, 0xaf, 0xd1, 0x56, 0xe4 -DEFINE_GUIDSTRUCT("9b365890-165f-11d0-a195-0020afd156e4", KSNAME_Filter); -#define KSNAME_Filter DEFINE_GUIDNAMED(KSNAME_Filter) - -#define KSSTRING_Filter L"{9B365890-165F-11D0-A195-0020AFD156E4}" - -#define STATIC_KSNAME_Pin \ - 0x146F1A80L, 0x4791, 0x11D0, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 -DEFINE_GUIDSTRUCT("146F1A80-4791-11D0-A5D6-28DB04C10000", KSNAME_Pin); -#define KSNAME_Pin DEFINE_GUIDNAMED(KSNAME_Pin) - -#define KSSTRING_Pin L"{146F1A80-4791-11D0-A5D6-28DB04C10000}" - -#define STATIC_KSNAME_Clock \ - 0x53172480L, 0x4791, 0x11D0, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 -DEFINE_GUIDSTRUCT("53172480-4791-11D0-A5D6-28DB04C10000", KSNAME_Clock); -#define KSNAME_Clock DEFINE_GUIDNAMED(KSNAME_Clock) - -#define KSSTRING_Clock L"{53172480-4791-11D0-A5D6-28DB04C10000}" - -#define STATIC_KSNAME_Allocator \ - 0x642F5D00L, 0x4791, 0x11D0, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 -DEFINE_GUIDSTRUCT("642F5D00-4791-11D0-A5D6-28DB04C10000", KSNAME_Allocator); -#define KSNAME_Allocator DEFINE_GUIDNAMED(KSNAME_Allocator) - -#define KSSTRING_Allocator L"{642F5D00-4791-11D0-A5D6-28DB04C10000}" - -#define KSSTRING_AllocatorEx L"{091BB63B-603F-11D1-B067-00A0C9062802}" - -#define STATIC_KSNAME_TopologyNode \ - 0x0621061AL, 0xEE75, 0x11D0, 0xB9, 0x15, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 -DEFINE_GUIDSTRUCT("0621061A-EE75-11D0-B915-00A0C9223196", KSNAME_TopologyNode); -#define KSNAME_TopologyNode DEFINE_GUIDNAMED(KSNAME_TopologyNode) - -#define KSSTRING_TopologyNode L"{0621061A-EE75-11D0-B915-00A0C9223196}" - -#if defined(_NTDDK_) -typedef struct -{ - ULONG InterfacesCount; - const KSPIN_INTERFACE* Interfaces; - ULONG MediumsCount; - const KSPIN_MEDIUM* Mediums; - ULONG DataRangesCount; - const PKSDATARANGE* DataRanges; - KSPIN_DATAFLOW DataFlow; - KSPIN_COMMUNICATION Communication; - const GUID* Category; - const GUID* Name; - __MINGW_EXTENSION union - { - LONGLONG Reserved; - __MINGW_EXTENSION struct - { - ULONG ConstrainedDataRangesCount; - PKSDATARANGE* ConstrainedDataRanges; - }; - }; -}KSPIN_DESCRIPTOR, * PKSPIN_DESCRIPTOR; -typedef const KSPIN_DESCRIPTOR* PCKSPIN_DESCRIPTOR; - - # define DEFINE_KSPIN_DESCRIPTOR_TABLE(tablename) \ - const KSPIN_DESCRIPTOR tablename[] = - - # define DEFINE_KSPIN_DESCRIPTOR_ITEM(InterfacesCount, Interfaces, MediumsCount, Mediums, DataRangesCount, DataRanges, DataFlow, Communication) \ - { \ - InterfacesCount, Interfaces, MediumsCount, Mediums, \ - DataRangesCount, DataRanges, DataFlow, Communication, \ - NULL, NULL, 0 \ - } - - # define DEFINE_KSPIN_DESCRIPTOR_ITEMEX(InterfacesCount, Interfaces, MediumsCount, Mediums, DataRangesCount, DataRanges, DataFlow, Communication, Category, Name) \ - { \ - InterfacesCount, Interfaces, MediumsCount, Mediums, \ - DataRangesCount, DataRanges, DataFlow, Communication, \ - Category, Name, 0 \ - } -#endif /* _NTDDK_ */ - -#define STATIC_KSDATAFORMAT_TYPE_WILDCARD STATIC_GUID_NULL -#define KSDATAFORMAT_TYPE_WILDCARD GUID_NULL - -#define STATIC_KSDATAFORMAT_SUBTYPE_WILDCARD STATIC_GUID_NULL -#define KSDATAFORMAT_SUBTYPE_WILDCARD GUID_NULL - -#define STATIC_KSDATAFORMAT_TYPE_STREAM \ - 0xE436EB83L, 0x524F, 0x11CE, 0x9F, 0x53, 0x00, 0x20, 0xAF, 0x0B, 0xA7, 0x70 -DEFINE_GUIDSTRUCT("E436EB83-524F-11CE-9F53-0020AF0BA770", KSDATAFORMAT_TYPE_STREAM); -#define KSDATAFORMAT_TYPE_STREAM DEFINE_GUIDNAMED(KSDATAFORMAT_TYPE_STREAM) - -#define STATIC_KSDATAFORMAT_SUBTYPE_NONE \ - 0xE436EB8EL, 0x524F, 0x11CE, 0x9F, 0x53, 0x00, 0x20, 0xAF, 0x0B, 0xA7, 0x70 -DEFINE_GUIDSTRUCT("E436EB8E-524F-11CE-9F53-0020AF0BA770", KSDATAFORMAT_SUBTYPE_NONE); -#define KSDATAFORMAT_SUBTYPE_NONE DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_NONE) - -#define STATIC_KSDATAFORMAT_SPECIFIER_WILDCARD STATIC_GUID_NULL -#define KSDATAFORMAT_SPECIFIER_WILDCARD GUID_NULL - -#define STATIC_KSDATAFORMAT_SPECIFIER_FILENAME \ - 0xAA797B40L, 0xE974, 0x11CF, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 -DEFINE_GUIDSTRUCT("AA797B40-E974-11CF-A5D6-28DB04C10000", KSDATAFORMAT_SPECIFIER_FILENAME); -#define KSDATAFORMAT_SPECIFIER_FILENAME DEFINE_GUIDNAMED(KSDATAFORMAT_SPECIFIER_FILENAME) - -#define STATIC_KSDATAFORMAT_SPECIFIER_FILEHANDLE \ - 0x65E8773CL, 0x8F56, 0x11D0, 0xA3, 0xB9, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 -DEFINE_GUIDSTRUCT("65E8773C-8F56-11D0-A3B9-00A0C9223196", KSDATAFORMAT_SPECIFIER_FILEHANDLE); -#define KSDATAFORMAT_SPECIFIER_FILEHANDLE DEFINE_GUIDNAMED(KSDATAFORMAT_SPECIFIER_FILEHANDLE) - -#define STATIC_KSDATAFORMAT_SPECIFIER_NONE \ - 0x0F6417D6L, 0xC318, 0x11D0, { 0xA4, 0x3F, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 } -DEFINE_GUIDSTRUCT("0F6417D6-C318-11D0-A43F-00A0C9223196", KSDATAFORMAT_SPECIFIER_NONE); -#define KSDATAFORMAT_SPECIFIER_NONE DEFINE_GUIDNAMED(KSDATAFORMAT_SPECIFIER_NONE) - -#define STATIC_KSPROPSETID_Quality \ - 0xD16AD380L, 0xAC1A, 0x11CF, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 -DEFINE_GUIDSTRUCT("D16AD380-AC1A-11CF-A5D6-28DB04C10000", KSPROPSETID_Quality); -#define KSPROPSETID_Quality DEFINE_GUIDNAMED(KSPROPSETID_Quality) - -typedef enum -{ - KSPROPERTY_QUALITY_REPORT, - KSPROPERTY_QUALITY_ERROR -}KSPROPERTY_QUALITY; - -#define DEFINE_KSPROPERTY_ITEM_QUALITY_REPORT(GetHandler, SetHandler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_QUALITY_REPORT, \ - (GetHandler), \ - sizeof(KSPROPERTY), \ - sizeof(KSQUALITY), \ - (SetHandler), \ - NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_QUALITY_ERROR(GetHandler, SetHandler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_QUALITY_ERROR, \ - (GetHandler), \ - sizeof(KSPROPERTY), \ - sizeof(KSERROR), \ - (SetHandler), \ - NULL, 0, NULL, NULL, 0) - -#define STATIC_KSPROPSETID_Connection \ - 0x1D58C920L, 0xAC9B, 0x11CF, { 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 } -DEFINE_GUIDSTRUCT("1D58C920-AC9B-11CF-A5D6-28DB04C10000", KSPROPSETID_Connection); -#define KSPROPSETID_Connection DEFINE_GUIDNAMED(KSPROPSETID_Connection) - -typedef enum -{ - KSPROPERTY_CONNECTION_STATE, - KSPROPERTY_CONNECTION_PRIORITY, - KSPROPERTY_CONNECTION_DATAFORMAT, - KSPROPERTY_CONNECTION_ALLOCATORFRAMING, - KSPROPERTY_CONNECTION_PROPOSEDATAFORMAT, - KSPROPERTY_CONNECTION_ACQUIREORDERING, - KSPROPERTY_CONNECTION_ALLOCATORFRAMING_EX, - KSPROPERTY_CONNECTION_STARTAT -}KSPROPERTY_CONNECTION; - -#define DEFINE_KSPROPERTY_ITEM_CONNECTION_STATE(GetHandler, SetHandler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_CONNECTION_STATE, \ - (GetHandler), \ - sizeof(KSPROPERTY), \ - sizeof(KSSTATE), \ - (SetHandler), \ - NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_CONNECTION_PRIORITY(GetHandler, SetHandler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_CONNECTION_PRIORITY, \ - (GetHandler), \ - sizeof(KSPROPERTY), \ - sizeof(KSPRIORITY), \ - (SetHandler), \ - NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_CONNECTION_DATAFORMAT(GetHandler, SetHandler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_CONNECTION_DATAFORMAT, \ - (GetHandler), \ - sizeof(KSPROPERTY), \ - 0, \ - (SetHandler), \ - NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_CONNECTION_ALLOCATORFRAMING(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_CONNECTION_ALLOCATORFRAMING, \ - (Handler), \ - sizeof(KSPROPERTY), \ - sizeof(KSALLOCATOR_FRAMING), \ - NULL, NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_CONNECTION_ALLOCATORFRAMING_EX(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_CONNECTION_ALLOCATORFRAMING_EX, \ - (Handler), \ - sizeof(KSPROPERTY), \ - 0, \ - NULL, NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_CONNECTION_PROPOSEDATAFORMAT(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_CONNECTION_PROPOSEDATAFORMAT, \ - NULL, \ - sizeof(KSPROPERTY), \ - sizeof(KSDATAFORMAT), \ - (Handler), \ - NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_CONNECTION_ACQUIREORDERING(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_CONNECTION_ACQUIREORDERING, \ - (Handler), \ - sizeof(KSPROPERTY), \ - sizeof(int), \ - NULL, NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_CONNECTION_STARTAT(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_CONNECTION_STARTAT, \ - NULL, \ - sizeof(KSPROPERTY), \ - sizeof(KSRELATIVEEVENT), \ - (Handler), \ - NULL, 0, NULL, NULL, 0) - -#define KSALLOCATOR_REQUIREMENTF_INPLACE_MODIFIER 0x00000001 -#define KSALLOCATOR_REQUIREMENTF_SYSTEM_MEMORY 0x00000002 -#define KSALLOCATOR_REQUIREMENTF_FRAME_INTEGRITY 0x00000004 -#define KSALLOCATOR_REQUIREMENTF_MUST_ALLOCATE 0x00000008 -#define KSALLOCATOR_REQUIREMENTF_PREFERENCES_ONLY 0x80000000 - -#define KSALLOCATOR_OPTIONF_COMPATIBLE 0x00000001 -#define KSALLOCATOR_OPTIONF_SYSTEM_MEMORY 0x00000002 -#define KSALLOCATOR_OPTIONF_VALID 0x00000003 - -#define KSALLOCATOR_FLAG_PARTIAL_READ_SUPPORT 0x00000010 -#define KSALLOCATOR_FLAG_DEVICE_SPECIFIC 0x00000020 -#define KSALLOCATOR_FLAG_CAN_ALLOCATE 0x00000040 -#define KSALLOCATOR_FLAG_INSIST_ON_FRAMESIZE_RATIO 0x00000080 -#define KSALLOCATOR_FLAG_NO_FRAME_INTEGRITY 0x00000100 -#define KSALLOCATOR_FLAG_MULTIPLE_OUTPUT 0x00000200 -#define KSALLOCATOR_FLAG_CYCLE 0x00000400 -#define KSALLOCATOR_FLAG_ALLOCATOR_EXISTS 0x00000800 -#define KSALLOCATOR_FLAG_INDEPENDENT_RANGES 0x00001000 -#define KSALLOCATOR_FLAG_ATTENTION_STEPPING 0x00002000 - -typedef struct -{ - __MINGW_EXTENSION union - { - ULONG OptionsFlags; - ULONG RequirementsFlags; - }; -#if defined(_NTDDK_) - POOL_TYPE PoolType; -#else - ULONG PoolType; -#endif /* _NTDDK_ */ - ULONG Frames; - ULONG FrameSize; - ULONG FileAlignment; - ULONG Reserved; -}KSALLOCATOR_FRAMING, * PKSALLOCATOR_FRAMING; - -#if defined(_NTDDK_) -typedef PVOID (*PFNKSDEFAULTALLOCATE)(PVOID Context); -typedef VOID (*PFNKSDEFAULTFREE)(PVOID Context, PVOID Buffer); -typedef NTSTATUS (*PFNKSINITIALIZEALLOCATOR)(PVOID InitialContext, - PKSALLOCATOR_FRAMING AllocatorFraming, - PVOID* Context); -typedef VOID (*PFNKSDELETEALLOCATOR)(PVOID Context); -#endif /* _NTDDK_ */ - -typedef struct -{ - ULONG MinFrameSize; - ULONG MaxFrameSize; - ULONG Stepping; -}KS_FRAMING_RANGE, * PKS_FRAMING_RANGE; - -typedef struct -{ - KS_FRAMING_RANGE Range; - ULONG InPlaceWeight; - ULONG NotInPlaceWeight; -}KS_FRAMING_RANGE_WEIGHTED, * PKS_FRAMING_RANGE_WEIGHTED; - -typedef struct -{ - ULONG RatioNumerator; - ULONG RatioDenominator; - ULONG RatioConstantMargin; -}KS_COMPRESSION, * PKS_COMPRESSION; - -typedef struct -{ - GUID MemoryType; - GUID BusType; - ULONG MemoryFlags; - ULONG BusFlags; - ULONG Flags; - ULONG Frames; - ULONG FileAlignment; - ULONG MemoryTypeWeight; - KS_FRAMING_RANGE PhysicalRange; - KS_FRAMING_RANGE_WEIGHTED FramingRange; -}KS_FRAMING_ITEM, * PKS_FRAMING_ITEM; - -typedef struct -{ - ULONG CountItems; - ULONG PinFlags; - KS_COMPRESSION OutputCompression; - ULONG PinWeight; - KS_FRAMING_ITEM FramingItem[1]; -}KSALLOCATOR_FRAMING_EX, * PKSALLOCATOR_FRAMING_EX; - -#define KSMEMORY_TYPE_WILDCARD GUID_NULL -#define STATIC_KSMEMORY_TYPE_WILDCARD STATIC_GUID_NULL - -#define KSMEMORY_TYPE_DONT_CARE GUID_NULL -#define STATIC_KSMEMORY_TYPE_DONT_CARE STATIC_GUID_NULL - -#define KS_TYPE_DONT_CARE GUID_NULL -#define STATIC_KS_TYPE_DONT_CARE STATIC_GUID_NULL - -#define STATIC_KSMEMORY_TYPE_SYSTEM \ - 0x091bb638L, 0x603f, 0x11d1, 0xb0, 0x67, 0x00, 0xa0, 0xc9, 0x06, 0x28, 0x02 -DEFINE_GUIDSTRUCT("091bb638-603f-11d1-b067-00a0c9062802", KSMEMORY_TYPE_SYSTEM); -#define KSMEMORY_TYPE_SYSTEM DEFINE_GUIDNAMED(KSMEMORY_TYPE_SYSTEM) - -#define STATIC_KSMEMORY_TYPE_USER \ - 0x8cb0fc28L, 0x7893, 0x11d1, 0xb0, 0x69, 0x00, 0xa0, 0xc9, 0x06, 0x28, 0x02 -DEFINE_GUIDSTRUCT("8cb0fc28-7893-11d1-b069-00a0c9062802", KSMEMORY_TYPE_USER); -#define KSMEMORY_TYPE_USER DEFINE_GUIDNAMED(KSMEMORY_TYPE_USER) - -#define STATIC_KSMEMORY_TYPE_KERNEL_PAGED \ - 0xd833f8f8L, 0x7894, 0x11d1, 0xb0, 0x69, 0x00, 0xa0, 0xc9, 0x06, 0x28, 0x02 -DEFINE_GUIDSTRUCT("d833f8f8-7894-11d1-b069-00a0c9062802", KSMEMORY_TYPE_KERNEL_PAGED); -#define KSMEMORY_TYPE_KERNEL_PAGED DEFINE_GUIDNAMED(KSMEMORY_TYPE_KERNEL_PAGED) - -#define STATIC_KSMEMORY_TYPE_KERNEL_NONPAGED \ - 0x4a6d5fc4L, 0x7895, 0x11d1, 0xb0, 0x69, 0x00, 0xa0, 0xc9, 0x06, 0x28, 0x02 -DEFINE_GUIDSTRUCT("4a6d5fc4-7895-11d1-b069-00a0c9062802", KSMEMORY_TYPE_KERNEL_NONPAGED); -#define KSMEMORY_TYPE_KERNEL_NONPAGED DEFINE_GUIDNAMED(KSMEMORY_TYPE_KERNEL_NONPAGED) - -#define STATIC_KSMEMORY_TYPE_DEVICE_UNKNOWN \ - 0x091bb639L, 0x603f, 0x11d1, 0xb0, 0x67, 0x00, 0xa0, 0xc9, 0x06, 0x28, 0x02 -DEFINE_GUIDSTRUCT("091bb639-603f-11d1-b067-00a0c9062802", KSMEMORY_TYPE_DEVICE_UNKNOWN); -#define KSMEMORY_TYPE_DEVICE_UNKNOWN DEFINE_GUIDNAMED(KSMEMORY_TYPE_DEVICE_UNKNOWN) - -#define DECLARE_SIMPLE_FRAMING_EX(FramingExName, MemoryType, Flags, Frames, Alignment, MinFrameSize, MaxFrameSize) \ - const KSALLOCATOR_FRAMING_EX FramingExName = \ - { \ - 1, \ - 0, \ - { \ - 1, \ - 1, \ - 0 \ - }, \ - 0, \ - { \ - { \ - MemoryType, \ - STATIC_KS_TYPE_DONT_CARE, \ - 0, \ - 0, \ - Flags, \ - Frames, \ - Alignment, \ - 0, \ - { \ - 0, \ - (ULONG)-1, \ - 1 \ - }, \ - { \ - { \ - MinFrameSize, \ - MaxFrameSize, \ - 1 \ - }, \ - 0, \ - 0 \ - } \ - } \ - } \ - } - -#define SetDefaultKsCompression(KsCompressionPointer) \ - { \ - KsCompressionPointer->RatioNumerator = 1; \ - KsCompressionPointer->RatioDenominator = 1; \ - KsCompressionPointer->RatioConstantMargin = 0; \ - } - -#define SetDontCareKsFramingRange(KsFramingRangePointer) \ - { \ - KsFramingRangePointer->MinFrameSize = 0; \ - KsFramingRangePointer->MaxFrameSize = (ULONG)-1; \ - KsFramingRangePointer->Stepping = 1; \ - } - -#define SetKsFramingRange(KsFramingRangePointer, P_MinFrameSize, P_MaxFrameSize) \ - { \ - KsFramingRangePointer->MinFrameSize = P_MinFrameSize; \ - KsFramingRangePointer->MaxFrameSize = P_MaxFrameSize; \ - KsFramingRangePointer->Stepping = 1; \ - } - -#define SetKsFramingRangeWeighted(KsFramingRangeWeightedPointer, P_MinFrameSize, P_MaxFrameSize) \ - { \ - KS_FRAMING_RANGE* KsFramingRange = \ - &KsFramingRangeWeightedPointer->Range; \ - SetKsFramingRange(KsFramingRange, P_MinFrameSize, P_MaxFrameSize); \ - KsFramingRangeWeightedPointer->InPlaceWeight = 0; \ - KsFramingRangeWeightedPointer->NotInPlaceWeight = 0; \ - } - -#define INITIALIZE_SIMPLE_FRAMING_EX(FramingExPointer, P_MemoryType, P_Flags, P_Frames, P_Alignment, P_MinFrameSize, P_MaxFrameSize) \ - { \ - KS_COMPRESSION* KsCompression = \ - &FramingExPointer->OutputCompression; \ - KS_FRAMING_RANGE* KsFramingRange = \ - &FramingExPointer->FramingItem[0].PhysicalRange; \ - KS_FRAMING_RANGE_WEIGHTED* KsFramingRangeWeighted = \ - &FramingExPointer->FramingItem[0].FramingRange; \ - FramingExPointer->CountItems = 1; \ - FramingExPointer->PinFlags = 0; \ - SetDefaultKsCompression(KsCompression); \ - FramingExPointer->PinWeight = 0; \ - FramingExPointer->FramingItem[0].MemoryType = P_MemoryType; \ - FramingExPointer->FramingItem[0].BusType = KS_TYPE_DONT_CARE; \ - FramingExPointer->FramingItem[0].MemoryFlags = 0; \ - FramingExPointer->FramingItem[0].BusFlags = 0; \ - FramingExPointer->FramingItem[0].Flags = P_Flags; \ - FramingExPointer->FramingItem[0].Frames = P_Frames; \ - FramingExPointer->FramingItem[0].FileAlignment = P_Alignment; \ - FramingExPointer->FramingItem[0].MemoryTypeWeight = 0; \ - SetDontCareKsFramingRange(KsFramingRange); \ - SetKsFramingRangeWeighted(KsFramingRangeWeighted, \ - P_MinFrameSize, P_MaxFrameSize); \ - } - -#define STATIC_KSEVENTSETID_StreamAllocator \ - 0x75d95571L, 0x073c, 0x11d0, 0xa1, 0x61, 0x00, 0x20, 0xaf, 0xd1, 0x56, 0xe4 -DEFINE_GUIDSTRUCT("75d95571-073c-11d0-a161-0020afd156e4", KSEVENTSETID_StreamAllocator); -#define KSEVENTSETID_StreamAllocator DEFINE_GUIDNAMED(KSEVENTSETID_StreamAllocator) - -typedef enum -{ - KSEVENT_STREAMALLOCATOR_INTERNAL_FREEFRAME, - KSEVENT_STREAMALLOCATOR_FREEFRAME -}KSEVENT_STREAMALLOCATOR; - -#define STATIC_KSMETHODSETID_StreamAllocator \ - 0xcf6e4341L, 0xec87, 0x11cf, 0xa1, 0x30, 0x00, 0x20, 0xaf, 0xd1, 0x56, 0xe4 -DEFINE_GUIDSTRUCT("cf6e4341-ec87-11cf-a130-0020afd156e4", KSMETHODSETID_StreamAllocator); -#define KSMETHODSETID_StreamAllocator DEFINE_GUIDNAMED(KSMETHODSETID_StreamAllocator) - -typedef enum -{ - KSMETHOD_STREAMALLOCATOR_ALLOC, - KSMETHOD_STREAMALLOCATOR_FREE -}KSMETHOD_STREAMALLOCATOR; - -#define DEFINE_KSMETHOD_ITEM_STREAMALLOCATOR_ALLOC(Handler) \ - DEFINE_KSMETHOD_ITEM( \ - KSMETHOD_STREAMALLOCATOR_ALLOC, \ - KSMETHOD_TYPE_WRITE, \ - (Handler), \ - sizeof(KSMETHOD), \ - sizeof(PVOID), \ - NULL) - -#define DEFINE_KSMETHOD_ITEM_STREAMALLOCATOR_FREE(Handler) \ - DEFINE_KSMETHOD_ITEM( \ - KSMETHOD_STREAMALLOCATOR_FREE, \ - KSMETHOD_TYPE_READ, \ - (Handler), \ - sizeof(KSMETHOD), \ - sizeof(PVOID), \ - NULL) - -#define DEFINE_KSMETHOD_ALLOCATORSET(AllocatorSet, MethodAlloc, MethodFree) \ - DEFINE_KSMETHOD_TABLE(AllocatorSet) { \ - DEFINE_KSMETHOD_ITEM_STREAMALLOCATOR_ALLOC(MethodAlloc), \ - DEFINE_KSMETHOD_ITEM_STREAMALLOCATOR_FREE(MethodFree) \ - } - -#define STATIC_KSPROPSETID_StreamAllocator \ - 0xcf6e4342L, 0xec87, 0x11cf, 0xa1, 0x30, 0x00, 0x20, 0xaf, 0xd1, 0x56, 0xe4 -DEFINE_GUIDSTRUCT("cf6e4342-ec87-11cf-a130-0020afd156e4", KSPROPSETID_StreamAllocator); -#define KSPROPSETID_StreamAllocator DEFINE_GUIDNAMED(KSPROPSETID_StreamAllocator) - -#if defined(_NTDDK_) -typedef enum -{ - KSPROPERTY_STREAMALLOCATOR_FUNCTIONTABLE, - KSPROPERTY_STREAMALLOCATOR_STATUS -}KSPROPERTY_STREAMALLOCATOR; - - # define DEFINE_KSPROPERTY_ITEM_STREAMALLOCATOR_FUNCTIONTABLE(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_STREAMALLOCATOR_FUNCTIONTABLE, \ - (Handler), \ - sizeof(KSPROPERTY), \ - sizeof(KSSTREAMALLOCATOR_FUNCTIONTABLE), \ - NULL, NULL, 0, NULL, NULL, 0) - - # define DEFINE_KSPROPERTY_ITEM_STREAMALLOCATOR_STATUS(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_STREAMALLOCATOR_STATUS, \ - (Handler), \ - sizeof(KSPROPERTY), \ - sizeof(KSSTREAMALLOCATOR_STATUS), \ - NULL, NULL, 0, NULL, NULL, 0) - - # define DEFINE_KSPROPERTY_ALLOCATORSET(AllocatorSet, PropFunctionTable, PropStatus) \ - DEFINE_KSPROPERTY_TABLE(AllocatorSet) { \ - DEFINE_KSPROPERTY_ITEM_STREAMALLOCATOR_STATUS(PropStatus), \ - DEFINE_KSPROPERTY_ITEM_STREAMALLOCATOR_FUNCTIONTABLE(PropFunctionTable) \ - } - -typedef NTSTATUS (*PFNALLOCATOR_ALLOCATEFRAME)(PFILE_OBJECT FileObject, - PVOID* Frame); -typedef VOID (*PFNALLOCATOR_FREEFRAME)(PFILE_OBJECT FileObject, PVOID Frame); - -typedef struct -{ - PFNALLOCATOR_ALLOCATEFRAME AllocateFrame; - PFNALLOCATOR_FREEFRAME FreeFrame; -}KSSTREAMALLOCATOR_FUNCTIONTABLE, * PKSSTREAMALLOCATOR_FUNCTIONTABLE; -#endif /* _NTDDK_ */ - -typedef struct -{ - KSALLOCATOR_FRAMING Framing; - ULONG AllocatedFrames; - ULONG Reserved; -}KSSTREAMALLOCATOR_STATUS, * PKSSTREAMALLOCATOR_STATUS; - -typedef struct -{ - KSALLOCATOR_FRAMING_EX Framing; - ULONG AllocatedFrames; - ULONG Reserved; -}KSSTREAMALLOCATOR_STATUS_EX, * PKSSTREAMALLOCATOR_STATUS_EX; - -#define KSSTREAM_HEADER_OPTIONSF_SPLICEPOINT 0x00000001 -#define KSSTREAM_HEADER_OPTIONSF_PREROLL 0x00000002 -#define KSSTREAM_HEADER_OPTIONSF_DATADISCONTINUITY 0x00000004 -#define KSSTREAM_HEADER_OPTIONSF_TYPECHANGED 0x00000008 -#define KSSTREAM_HEADER_OPTIONSF_TIMEVALID 0x00000010 -#define KSSTREAM_HEADER_OPTIONSF_TIMEDISCONTINUITY 0x00000040 -#define KSSTREAM_HEADER_OPTIONSF_FLUSHONPAUSE 0x00000080 -#define KSSTREAM_HEADER_OPTIONSF_DURATIONVALID 0x00000100 -#define KSSTREAM_HEADER_OPTIONSF_ENDOFSTREAM 0x00000200 -#define KSSTREAM_HEADER_OPTIONSF_LOOPEDDATA 0x80000000 - -typedef struct -{ - LONGLONG Time; - ULONG Numerator; - ULONG Denominator; -}KSTIME, * PKSTIME; - -typedef struct -{ - ULONG Size; - ULONG TypeSpecificFlags; - KSTIME PresentationTime; - LONGLONG Duration; - ULONG FrameExtent; - ULONG DataUsed; - PVOID Data; - ULONG OptionsFlags; -#ifdef _WIN64 - ULONG Reserved; -#endif -}KSSTREAM_HEADER, * PKSSTREAM_HEADER; - -#define STATIC_KSPROPSETID_StreamInterface \ - 0x1fdd8ee1L, 0x9cd3, 0x11d0, 0x82, 0xaa, 0x00, 0x00, 0xf8, 0x22, 0xfe, 0x8a -DEFINE_GUIDSTRUCT("1fdd8ee1-9cd3-11d0-82aa-0000f822fe8a", KSPROPSETID_StreamInterface); -#define KSPROPSETID_StreamInterface DEFINE_GUIDNAMED(KSPROPSETID_StreamInterface) - -typedef enum -{ - KSPROPERTY_STREAMINTERFACE_HEADERSIZE -}KSPROPERTY_STREAMINTERFACE; - -#define DEFINE_KSPROPERTY_ITEM_STREAMINTERFACE_HEADERSIZE(GetHandler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_STREAMINTERFACE_HEADERSIZE, \ - (GetHandler), \ - sizeof(KSPROPERTY), \ - sizeof(ULONG), \ - NULL, NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_STREAMINTERFACESET(StreamInterfaceSet, HeaderSizeHandler) \ - DEFINE_KSPROPERTY_TABLE(StreamInterfaceSet) { \ - DEFINE_KSPROPERTY_ITEM_STREAMINTERFACE_HEADERSIZE(HeaderSizeHandler) \ - } - -#define STATIC_KSPROPSETID_Stream \ - 0x65aaba60L, 0x98ae, 0x11cf, 0xa1, 0x0d, 0x00, 0x20, 0xaf, 0xd1, 0x56, 0xe4 -DEFINE_GUIDSTRUCT("65aaba60-98ae-11cf-a10d-0020afd156e4", KSPROPSETID_Stream); -#define KSPROPSETID_Stream DEFINE_GUIDNAMED(KSPROPSETID_Stream) - -typedef enum -{ - KSPROPERTY_STREAM_ALLOCATOR, - KSPROPERTY_STREAM_QUALITY, - KSPROPERTY_STREAM_DEGRADATION, - KSPROPERTY_STREAM_MASTERCLOCK, - KSPROPERTY_STREAM_TIMEFORMAT, - KSPROPERTY_STREAM_PRESENTATIONTIME, - KSPROPERTY_STREAM_PRESENTATIONEXTENT, - KSPROPERTY_STREAM_FRAMETIME, - KSPROPERTY_STREAM_RATECAPABILITY, - KSPROPERTY_STREAM_RATE, - KSPROPERTY_STREAM_PIPE_ID -}KSPROPERTY_STREAM; - -#define DEFINE_KSPROPERTY_ITEM_STREAM_ALLOCATOR(GetHandler, SetHandler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_STREAM_ALLOCATOR, \ - (GetHandler), \ - sizeof(KSPROPERTY), \ - sizeof(HANDLE), \ - (SetHandler), \ - NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_STREAM_QUALITY(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_STREAM_QUALITY, \ - (Handler), \ - sizeof(KSPROPERTY), \ - sizeof(KSQUALITY_MANAGER), \ - NULL, NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_STREAM_DEGRADATION(GetHandler, SetHandler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_STREAM_DEGRADATION, \ - (GetHandler), \ - sizeof(KSPROPERTY), \ - 0, \ - (SetHandler), \ - NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_STREAM_MASTERCLOCK(GetHandler, SetHandler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_STREAM_MASTERCLOCK, \ - (GetHandler), \ - sizeof(KSPROPERTY), \ - sizeof(HANDLE), \ - (SetHandler), \ - NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_STREAM_TIMEFORMAT(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_STREAM_TIMEFORMAT, \ - (Handler), \ - sizeof(KSPROPERTY), \ - sizeof(GUID), \ - NULL, NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_STREAM_PRESENTATIONTIME(GetHandler, SetHandler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_STREAM_PRESENTATIONTIME, \ - (GetHandler), \ - sizeof(KSPROPERTY), \ - sizeof(KSTIME), \ - (SetHandler), \ - NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_STREAM_PRESENTATIONEXTENT(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_STREAM_PRESENTATIONEXTENT, \ - (Handler), \ - sizeof(KSPROPERTY), \ - sizeof(LONGLONG), \ - NULL, NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_STREAM_FRAMETIME(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_STREAM_FRAMETIME, \ - (Handler), \ - sizeof(KSPROPERTY), \ - sizeof(KSFRAMETIME), \ - NULL, NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_STREAM_RATECAPABILITY(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_STREAM_RATECAPABILITY, \ - (Handler), \ - sizeof(KSRATE_CAPABILITY), \ - sizeof(KSRATE), \ - NULL, NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_STREAM_RATE(GetHandler, SetHandler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_STREAM_RATE, \ - (GetHandler), \ - sizeof(KSPROPERTY), \ - sizeof(KSRATE), \ - (SetHandler), \ - NULL, 0, NULL, NULL, 0) - -#define DEFINE_KSPROPERTY_ITEM_STREAM_PIPE_ID(GetHandler, SetHandler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_STREAM_PIPE_ID, \ - (GetHandler), \ - sizeof(KSPROPERTY), \ - sizeof(HANDLE), \ - (SetHandler), \ - NULL, 0, NULL, NULL, 0) - -typedef struct -{ - HANDLE QualityManager; - PVOID Context; -}KSQUALITY_MANAGER, * PKSQUALITY_MANAGER; - -typedef struct -{ - LONGLONG Duration; - ULONG FrameFlags; - ULONG Reserved; -}KSFRAMETIME, * PKSFRAMETIME; - -#define KSFRAMETIME_VARIABLESIZE 0x00000001 - -typedef struct -{ - LONGLONG PresentationStart; - LONGLONG Duration; - KSPIN_INTERFACE Interface; - LONG Rate; - ULONG Flags; -}KSRATE, * PKSRATE; - -#define KSRATE_NOPRESENTATIONSTART 0x00000001 -#define KSRATE_NOPRESENTATIONDURATION 0x00000002 - -typedef struct -{ - KSPROPERTY Property; - KSRATE Rate; -}KSRATE_CAPABILITY, * PKSRATE_CAPABILITY; - -#define STATIC_KSPROPSETID_Clock \ - 0xDF12A4C0L, 0xAC17, 0x11CF, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 -DEFINE_GUIDSTRUCT("DF12A4C0-AC17-11CF-A5D6-28DB04C10000", KSPROPSETID_Clock); -#define KSPROPSETID_Clock DEFINE_GUIDNAMED(KSPROPSETID_Clock) - -#define NANOSECONDS 10000000 -#define KSCONVERT_PERFORMANCE_TIME(Frequency, PerformanceTime) \ - ((((ULONGLONG)(ULONG)(PerformanceTime).HighPart * NANOSECONDS / (Frequency)) << 32) + \ - ((((((ULONGLONG)(ULONG)(PerformanceTime).HighPart * NANOSECONDS) % (Frequency)) << 32) + \ - ((ULONGLONG)(PerformanceTime).LowPart * NANOSECONDS)) / (Frequency))) - -typedef struct -{ - ULONG CreateFlags; -}KSCLOCK_CREATE, * PKSCLOCK_CREATE; - -typedef struct -{ - LONGLONG Time; - LONGLONG SystemTime; -}KSCORRELATED_TIME, * PKSCORRELATED_TIME; - -typedef struct -{ - LONGLONG Granularity; - LONGLONG Error; -}KSRESOLUTION, * PKSRESOLUTION; - -typedef enum -{ - KSPROPERTY_CLOCK_TIME, - KSPROPERTY_CLOCK_PHYSICALTIME, - KSPROPERTY_CLOCK_CORRELATEDTIME, - KSPROPERTY_CLOCK_CORRELATEDPHYSICALTIME, - KSPROPERTY_CLOCK_RESOLUTION, - KSPROPERTY_CLOCK_STATE, -#if defined(_NTDDK_) - KSPROPERTY_CLOCK_FUNCTIONTABLE -#endif /* _NTDDK_ */ -}KSPROPERTY_CLOCK; - -#if defined(_NTDDK_) -typedef LONGLONG (FASTCALL * PFNKSCLOCK_GETTIME)(PFILE_OBJECT FileObject); -typedef LONGLONG (FASTCALL * PFNKSCLOCK_CORRELATEDTIME)(PFILE_OBJECT FileObject, - PLONGLONG SystemTime); - -typedef struct -{ - PFNKSCLOCK_GETTIME GetTime; - PFNKSCLOCK_GETTIME GetPhysicalTime; - PFNKSCLOCK_CORRELATEDTIME GetCorrelatedTime; - PFNKSCLOCK_CORRELATEDTIME GetCorrelatedPhysicalTime; -}KSCLOCK_FUNCTIONTABLE, * PKSCLOCK_FUNCTIONTABLE; - -typedef BOOLEAN (*PFNKSSETTIMER)(PVOID Context, PKTIMER Timer, - LARGE_INTEGER DueTime, PKDPC Dpc); -typedef BOOLEAN (*PFNKSCANCELTIMER)(PVOID Context, PKTIMER Timer); -typedef LONGLONG (FASTCALL * PFNKSCORRELATEDTIME)(PVOID Context, - PLONGLONG SystemTime); - -typedef PVOID PKSDEFAULTCLOCK; - - # define DEFINE_KSPROPERTY_ITEM_CLOCK_TIME(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_CLOCK_TIME, \ - (Handler), \ - sizeof(KSPROPERTY), sizeof(LONGLONG), \ - NULL, NULL, 0, NULL, NULL, 0) - - # define DEFINE_KSPROPERTY_ITEM_CLOCK_PHYSICALTIME(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_CLOCK_PHYSICALTIME, \ - (Handler), \ - sizeof(KSPROPERTY), sizeof(LONGLONG), \ - NULL, NULL, 0, NULL, NULL, 0) - - # define DEFINE_KSPROPERTY_ITEM_CLOCK_CORRELATEDTIME(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_CLOCK_CORRELATEDTIME, \ - (Handler), \ - sizeof(KSPROPERTY), \ - sizeof(KSCORRELATED_TIME), \ - NULL, NULL, 0, NULL, NULL, 0) - - # define DEFINE_KSPROPERTY_ITEM_CLOCK_CORRELATEDPHYSICALTIME(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_CLOCK_CORRELATEDPHYSICALTIME, \ - (Handler), \ - sizeof(KSPROPERTY), \ - sizeof(KSCORRELATED_TIME), \ - NULL, NULL, 0, NULL, NULL, 0) - - # define DEFINE_KSPROPERTY_ITEM_CLOCK_RESOLUTION(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_CLOCK_RESOLUTION, \ - (Handler), \ - sizeof(KSPROPERTY), sizeof(KSRESOLUTION), \ - NULL, NULL, 0, NULL, NULL, 0) - - # define DEFINE_KSPROPERTY_ITEM_CLOCK_STATE(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_CLOCK_STATE, \ - (Handler), \ - sizeof(KSPROPERTY), sizeof(KSSTATE), \ - NULL, NULL, 0, NULL, NULL, 0) - - # define DEFINE_KSPROPERTY_ITEM_CLOCK_FUNCTIONTABLE(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_CLOCK_FUNCTIONTABLE, \ - (Handler), \ - sizeof(KSPROPERTY), \ - sizeof(KSCLOCK_FUNCTIONTABLE), \ - NULL, NULL, 0, NULL, NULL, 0) - - # define DEFINE_KSPROPERTY_CLOCKSET(ClockSet, PropTime, PropPhysicalTime, PropCorrelatedTime, PropCorrelatedPhysicalTime, PropResolution, PropState, PropFunctionTable) \ - DEFINE_KSPROPERTY_TABLE(ClockSet) { \ - DEFINE_KSPROPERTY_ITEM_CLOCK_TIME(PropTime), \ - DEFINE_KSPROPERTY_ITEM_CLOCK_PHYSICALTIME(PropPhysicalTime), \ - DEFINE_KSPROPERTY_ITEM_CLOCK_CORRELATEDTIME(PropCorrelatedTime), \ - DEFINE_KSPROPERTY_ITEM_CLOCK_CORRELATEDPHYSICALTIME(PropCorrelatedPhysicalTime), \ - DEFINE_KSPROPERTY_ITEM_CLOCK_RESOLUTION(PropResolution), \ - DEFINE_KSPROPERTY_ITEM_CLOCK_STATE(PropState), \ - DEFINE_KSPROPERTY_ITEM_CLOCK_FUNCTIONTABLE(PropFunctionTable), \ - } -#endif /* _NTDDK_ */ - -#define STATIC_KSEVENTSETID_Clock \ - 0x364D8E20L, 0x62C7, 0x11CF, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 -DEFINE_GUIDSTRUCT("364D8E20-62C7-11CF-A5D6-28DB04C10000", KSEVENTSETID_Clock); -#define KSEVENTSETID_Clock DEFINE_GUIDNAMED(KSEVENTSETID_Clock) - -typedef enum -{ - KSEVENT_CLOCK_INTERVAL_MARK, - KSEVENT_CLOCK_POSITION_MARK -}KSEVENT_CLOCK_POSITION; - -#define STATIC_KSEVENTSETID_Connection \ - 0x7f4bcbe0L, 0x9ea5, 0x11cf, 0xa5, 0xd6, 0x28, 0xdb, 0x04, 0xc1, 0x00, 0x00 -DEFINE_GUIDSTRUCT("7f4bcbe0-9ea5-11cf-a5d6-28db04c10000", KSEVENTSETID_Connection); -#define KSEVENTSETID_Connection DEFINE_GUIDNAMED(KSEVENTSETID_Connection) - -typedef enum -{ - KSEVENT_CONNECTION_POSITIONUPDATE, - KSEVENT_CONNECTION_DATADISCONTINUITY, - KSEVENT_CONNECTION_TIMEDISCONTINUITY, - KSEVENT_CONNECTION_PRIORITY, - KSEVENT_CONNECTION_ENDOFSTREAM -}KSEVENT_CONNECTION; - -typedef struct -{ - PVOID Context; - ULONG Proportion; - LONGLONG DeltaTime; -}KSQUALITY, * PKSQUALITY; - -typedef struct -{ - PVOID Context; - ULONG Status; -}KSERROR, * PKSERROR; - -typedef KSIDENTIFIER KSDEGRADE, * PKSDEGRADE; - -#define STATIC_KSDEGRADESETID_Standard \ - 0x9F564180L, 0x704C, 0x11D0, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 -DEFINE_GUIDSTRUCT("9F564180-704C-11D0-A5D6-28DB04C10000", KSDEGRADESETID_Standard); -#define KSDEGRADESETID_Standard DEFINE_GUIDNAMED(KSDEGRADESETID_Standard) - -typedef enum -{ - KSDEGRADE_STANDARD_SAMPLE, - KSDEGRADE_STANDARD_QUALITY, - KSDEGRADE_STANDARD_COMPUTATION, - KSDEGRADE_STANDARD_SKIP -}KSDEGRADE_STANDARD; - -#if defined(_NTDDK_) - - # define KSPROBE_STREAMREAD 0x00000000 - # define KSPROBE_STREAMWRITE 0x00000001 - # define KSPROBE_ALLOCATEMDL 0x00000010 - # define KSPROBE_PROBEANDLOCK 0x00000020 - # define KSPROBE_SYSTEMADDRESS 0x00000040 - # define KSPROBE_MODIFY 0x00000200 - # define KSPROBE_STREAMWRITEMODIFY (KSPROBE_MODIFY | KSPROBE_STREAMWRITE) - # define KSPROBE_ALLOWFORMATCHANGE 0x00000080 - # define KSSTREAM_READ KSPROBE_STREAMREAD - # define KSSTREAM_WRITE KSPROBE_STREAMWRITE - # define KSSTREAM_PAGED_DATA 0x00000000 - # define KSSTREAM_NONPAGED_DATA 0x00000100 - # define KSSTREAM_SYNCHRONOUS 0x00001000 - # define KSSTREAM_FAILUREEXCEPTION 0x00002000 - -typedef NTSTATUS (*PFNKSCONTEXT_DISPATCH)(PVOID Context, PIRP Irp); -typedef NTSTATUS (*PFNKSHANDLER)(PIRP Irp, PKSIDENTIFIER Request, PVOID Data); -typedef BOOLEAN (*PFNKSFASTHANDLER)(PFILE_OBJECT FileObject, - PKSIDENTIFIER Request, - ULONG RequestLength, PVOID Data, - ULONG DataLength, - PIO_STATUS_BLOCK IoStatus); -typedef NTSTATUS (*PFNKSALLOCATOR)(PIRP Irp, ULONG BufferSize, - BOOLEAN InputOperation); - -typedef struct -{ - KSPROPERTY_MEMBERSHEADER MembersHeader; - const VOID* Members; -}KSPROPERTY_MEMBERSLIST, * PKSPROPERTY_MEMBERSLIST; - -typedef struct -{ - KSIDENTIFIER PropTypeSet; - ULONG MembersListCount; - const KSPROPERTY_MEMBERSLIST* MembersList; -}KSPROPERTY_VALUES, * PKSPROPERTY_VALUES; - - # define DEFINE_KSPROPERTY_TABLE(tablename) \ - const KSPROPERTY_ITEM tablename[] = - - # define DEFINE_KSPROPERTY_ITEM(PropertyId, GetHandler, MinProperty, MinData, SetHandler, Values, RelationsCount, Relations, SupportHandler, SerializedSize) \ - { \ - PropertyId, (PFNKSHANDLER)GetHandler, \ - MinProperty, MinData, \ - (PFNKSHANDLER)SetHandler, \ - (PKSPROPERTY_VALUES)Values, RelationsCount, \ - (PKSPROPERTY)Relations, \ - (PFNKSHANDLER)SupportHandler, \ - (ULONG)SerializedSize \ - } - -typedef struct -{ - ULONG PropertyId; - __MINGW_EXTENSION union - { - PFNKSHANDLER GetPropertyHandler; - BOOLEAN GetSupported; - }; - ULONG MinProperty; - ULONG MinData; - __MINGW_EXTENSION union - { - PFNKSHANDLER SetPropertyHandler; - BOOLEAN SetSupported; - }; - const KSPROPERTY_VALUES* Values; - ULONG RelationsCount; - const KSPROPERTY* Relations; - PFNKSHANDLER SupportHandler; - ULONG SerializedSize; -}KSPROPERTY_ITEM, * PKSPROPERTY_ITEM; - - # define DEFINE_KSFASTPROPERTY_ITEM(PropertyId, GetHandler, SetHandler) \ - { \ - PropertyId, (PFNKSFASTHANDLER)GetHandler, \ - (PFNKSFASTHANDLER)SetHandler, 0 \ - } - -typedef struct -{ - ULONG PropertyId; - __MINGW_EXTENSION union - { - PFNKSFASTHANDLER GetPropertyHandler; - BOOLEAN GetSupported; - }; - __MINGW_EXTENSION union - { - PFNKSFASTHANDLER SetPropertyHandler; - BOOLEAN SetSupported; - }; - ULONG Reserved; -}KSFASTPROPERTY_ITEM, * PKSFASTPROPERTY_ITEM; - - # define DEFINE_KSPROPERTY_SET(Set, PropertiesCount, PropertyItem, FastIoCount, FastIoTable) \ - { \ - Set, \ - PropertiesCount, PropertyItem, \ - FastIoCount, FastIoTable \ - } - - # define DEFINE_KSPROPERTY_SET_TABLE(tablename) \ - const KSPROPERTY_SET tablename[] = - -typedef struct -{ - const GUID* Set; - ULONG PropertiesCount; - const KSPROPERTY_ITEM* PropertyItem; - ULONG FastIoCount; - const KSFASTPROPERTY_ITEM* FastIoTable; -}KSPROPERTY_SET, * PKSPROPERTY_SET; - - # define DEFINE_KSMETHOD_TABLE(tablename) \ - const KSMETHOD_ITEM tablename[] = - - # define DEFINE_KSMETHOD_ITEM(MethodId, Flags, MethodHandler, MinMethod, MinData, SupportHandler) \ - { \ - MethodId, (PFNKSHANDLER)MethodHandler, \ - MinMethod, MinData, \ - SupportHandler, Flags \ - } - -typedef struct -{ - ULONG MethodId; - __MINGW_EXTENSION union - { - PFNKSHANDLER MethodHandler; - BOOLEAN MethodSupported; - }; - ULONG MinMethod; - ULONG MinData; - PFNKSHANDLER SupportHandler; - ULONG Flags; -}KSMETHOD_ITEM, * PKSMETHOD_ITEM; - - # define DEFINE_KSFASTMETHOD_ITEM(MethodId, MethodHandler) \ - { \ - MethodId, (PFNKSFASTHANDLER)MethodHandler \ - } - -typedef struct -{ - ULONG MethodId; - __MINGW_EXTENSION union - { - PFNKSFASTHANDLER MethodHandler; - BOOLEAN MethodSupported; - }; -}KSFASTMETHOD_ITEM, * PKSFASTMETHOD_ITEM; - - # define DEFINE_KSMETHOD_SET(Set, MethodsCount, MethodItem, FastIoCount, FastIoTable) \ - { \ - Set, \ - MethodsCount, MethodItem, \ - FastIoCount, FastIoTable \ - } - - # define DEFINE_KSMETHOD_SET_TABLE(tablename) \ - const KSMETHOD_SET tablename[] = - -typedef struct -{ - const GUID* Set; - ULONG MethodsCount; - const KSMETHOD_ITEM* MethodItem; - ULONG FastIoCount; - const KSFASTMETHOD_ITEM* FastIoTable; -}KSMETHOD_SET, * PKSMETHOD_SET; - -typedef struct _KSEVENT_ENTRY KSEVENT_ENTRY, * PKSEVENT_ENTRY; -typedef NTSTATUS (*PFNKSADDEVENT)(PIRP Irp, PKSEVENTDATA EventData, - struct _KSEVENT_ENTRY* EventEntry); -typedef VOID (*PFNKSREMOVEEVENT)(PFILE_OBJECT FileObject, - struct _KSEVENT_ENTRY* EventEntry); - - # define DEFINE_KSEVENT_TABLE(tablename) \ - const KSEVENT_ITEM tablename[] = - - # define DEFINE_KSEVENT_ITEM(EventId, DataInput, ExtraEntryData, AddHandler, RemoveHandler, SupportHandler) \ - { \ - EventId, DataInput, ExtraEntryData, \ - AddHandler, RemoveHandler, SupportHandler \ - } - -typedef struct -{ - ULONG EventId; - ULONG DataInput; - ULONG ExtraEntryData; - PFNKSADDEVENT AddHandler; - PFNKSREMOVEEVENT RemoveHandler; - PFNKSHANDLER SupportHandler; -}KSEVENT_ITEM, * PKSEVENT_ITEM; - - # define DEFINE_KSEVENT_SET(Set, EventsCount, EventItem) \ - { \ - Set, EventsCount, EventItem \ - } - - # define DEFINE_KSEVENT_SET_TABLE(tablename) \ - const KSEVENT_SET tablename[] = - -typedef struct -{ - const GUID* Set; - ULONG EventsCount; - const KSEVENT_ITEM* EventItem; -}KSEVENT_SET, * PKSEVENT_SET; - -typedef struct -{ - KDPC Dpc; - ULONG ReferenceCount; - KSPIN_LOCK AccessLock; -}KSDPC_ITEM, * PKSDPC_ITEM; - -typedef struct -{ - KSDPC_ITEM DpcItem; - LIST_ENTRY BufferList; -}KSBUFFER_ITEM, * PKSBUFFER_ITEM; - - # define KSEVENT_ENTRY_DELETED 1 - # define KSEVENT_ENTRY_ONESHOT 2 - # define KSEVENT_ENTRY_BUFFERED 4 - -struct _KSEVENT_ENTRY -{ - LIST_ENTRY ListEntry; - PVOID Object; - __MINGW_EXTENSION union - { - PKSDPC_ITEM DpcItem; - PKSBUFFER_ITEM BufferItem; - }; - PKSEVENTDATA EventData; - ULONG NotificationType; - const KSEVENT_SET* EventSet; - const KSEVENT_ITEM* EventItem; - PFILE_OBJECT FileObject; - ULONG SemaphoreAdjustment; - ULONG Reserved; - ULONG Flags; -}; - -typedef enum -{ - KSEVENTS_NONE, - KSEVENTS_SPINLOCK, - KSEVENTS_MUTEX, - KSEVENTS_FMUTEX, - KSEVENTS_FMUTEXUNSAFE, - KSEVENTS_INTERRUPT, - KSEVENTS_ERESOURCE -}KSEVENTS_LOCKTYPE; - - # define KSDISPATCH_FASTIO 0x80000000 - -typedef struct -{ - PDRIVER_DISPATCH Create; - PVOID Context; - UNICODE_STRING ObjectClass; - PSECURITY_DESCRIPTOR SecurityDescriptor; - ULONG Flags; -}KSOBJECT_CREATE_ITEM, * PKSOBJECT_CREATE_ITEM; - -typedef VOID (*PFNKSITEMFREECALLBACK)(PKSOBJECT_CREATE_ITEM CreateItem); - - # define KSCREATE_ITEM_SECURITYCHANGED 0x00000001 - # define KSCREATE_ITEM_WILDCARD 0x00000002 - # define KSCREATE_ITEM_NOPARAMETERS 0x00000004 - # define KSCREATE_ITEM_FREEONSTOP 0x00000008 - - # define DEFINE_KSCREATE_DISPATCH_TABLE(tablename) \ - KSOBJECT_CREATE_ITEM tablename[] = - - # define DEFINE_KSCREATE_ITEM(DispatchCreate, TypeName, Context) \ - { \ - (DispatchCreate), (PVOID)(Context), \ - { \ - sizeof(TypeName) - sizeof(UNICODE_NULL), \ - sizeof(TypeName), \ - (PWCHAR)(TypeName) \ - }, \ - NULL, 0 \ - } - - # define DEFINE_KSCREATE_ITEMEX(DispatchCreate, TypeName, Context, Flags) \ - { \ - (DispatchCreate), \ - (PVOID)(Context), \ - { \ - sizeof(TypeName) - sizeof(UNICODE_NULL), \ - sizeof(TypeName), \ - (PWCHAR)(TypeName) \ - }, \ - NULL, (Flags) \ - } - - # define DEFINE_KSCREATE_ITEMNULL(DispatchCreate, Context) \ - { \ - DispatchCreate, Context, \ - { \ - 0, 0, NULL, \ - }, \ - NULL, 0 \ - } - -typedef struct -{ - ULONG CreateItemsCount; - PKSOBJECT_CREATE_ITEM CreateItemsList; -}KSOBJECT_CREATE, * PKSOBJECT_CREATE; - -typedef struct -{ - PDRIVER_DISPATCH DeviceIoControl; - PDRIVER_DISPATCH Read; - PDRIVER_DISPATCH Write; - PDRIVER_DISPATCH Flush; - PDRIVER_DISPATCH Close; - PDRIVER_DISPATCH QuerySecurity; - PDRIVER_DISPATCH SetSecurity; - PFAST_IO_DEVICE_CONTROL FastDeviceIoControl; - PFAST_IO_READ FastRead; - PFAST_IO_WRITE FastWrite; -}KSDISPATCH_TABLE, * PKSDISPATCH_TABLE; - - # define DEFINE_KSDISPATCH_TABLE(tablename, DeviceIoControl, Read, Write, Flush, Close, QuerySecurity, SetSecurity, FastDeviceIoControl, FastRead, FastWrite) \ - const KSDISPATCH_TABLE tablename = \ - { \ - DeviceIoControl, \ - Read, \ - Write, \ - Flush, \ - Close, \ - QuerySecurity, \ - SetSecurity, \ - FastDeviceIoControl, \ - FastRead, \ - FastWrite, \ - } - - # define KSCREATE_ITEM_IRP_STORAGE(Irp) \ - (*(PKSOBJECT_CREATE_ITEM*)&(Irp)->Tail.Overlay.DriverContext[0]) - # define KSEVENT_SET_IRP_STORAGE(Irp) \ - (*(const KSEVENT_SET**)&(Irp)->Tail.Overlay.DriverContext[0]) - # define KSEVENT_ITEM_IRP_STORAGE(Irp) \ - (*(const KSEVENT_ITEM**)&(Irp)->Tail.Overlay.DriverContext[3]) - # define KSEVENT_ENTRY_IRP_STORAGE(Irp) \ - (*(PKSEVENT_ENTRY*)&(Irp)->Tail.Overlay.DriverContext[0]) - # define KSMETHOD_SET_IRP_STORAGE(Irp) \ - (*(const KSMETHOD_SET**)&(Irp)->Tail.Overlay.DriverContext[0]) - # define KSMETHOD_ITEM_IRP_STORAGE(Irp) \ - (*(const KSMETHOD_ITEM**)&(Irp)->Tail.Overlay.DriverContext[3]) - # define KSMETHOD_TYPE_IRP_STORAGE(Irp) \ - (*(ULONG_PTR*)(&(Irp)->Tail.Overlay.DriverContext[2])) - # define KSQUEUE_SPINLOCK_IRP_STORAGE(Irp) \ - (*(PKSPIN_LOCK*)&(Irp)->Tail.Overlay.DriverContext[1]) - # define KSPROPERTY_SET_IRP_STORAGE(Irp) \ - (*(const KSPROPERTY_SET**)&(Irp)->Tail.Overlay.DriverContext[0]) - # define KSPROPERTY_ITEM_IRP_STORAGE(Irp) \ - (*(const KSPROPERTY_ITEM**)&(Irp)->Tail.Overlay.DriverContext[3]) - # define KSPROPERTY_ATTRIBUTES_IRP_STORAGE(Irp) \ - (*(PKSATTRIBUTE_LIST*)&(Irp)->Tail.Overlay.DriverContext[2]) - -typedef PVOID KSDEVICE_HEADER, KSOBJECT_HEADER; - -typedef enum -{ - KsInvokeOnSuccess = 1, - KsInvokeOnError = 2, - KsInvokeOnCancel = 4 -}KSCOMPLETION_INVOCATION; - -typedef enum -{ - KsListEntryTail, - KsListEntryHead -}KSLIST_ENTRY_LOCATION; - -typedef enum -{ - KsAcquireOnly, - KsAcquireAndRemove, - KsAcquireOnlySingleItem, - KsAcquireAndRemoveOnlySingleItem -}KSIRP_REMOVAL_OPERATION; - -typedef enum -{ - KsStackCopyToNewLocation, - KsStackReuseCurrentLocation, - KsStackUseNewLocation -}KSSTACK_USE; - -typedef enum -{ - KSTARGET_STATE_DISABLED, - KSTARGET_STATE_ENABLED -}KSTARGET_STATE; - -typedef NTSTATUS (*PFNKSIRPLISTCALLBACK)(PIRP Irp, PVOID Context); -typedef VOID (*PFNREFERENCEDEVICEOBJECT)(PVOID Context); -typedef VOID (*PFNDEREFERENCEDEVICEOBJECT)(PVOID Context); -typedef NTSTATUS (*PFNQUERYREFERENCESTRING)(PVOID Context, PWCHAR* String); - - # define BUS_INTERFACE_REFERENCE_VERSION 0x100 - -typedef struct -{ - INTERFACE Interface; - - PFNREFERENCEDEVICEOBJECT ReferenceDeviceObject; - PFNDEREFERENCEDEVICEOBJECT DereferenceDeviceObject; - PFNQUERYREFERENCESTRING QueryReferenceString; -}BUS_INTERFACE_REFERENCE, * PBUS_INTERFACE_REFERENCE; - - # define STATIC_REFERENCE_BUS_INTERFACE STATIC_KSMEDIUMSETID_Standard - # define REFERENCE_BUS_INTERFACE KSMEDIUMSETID_Standard - -#endif /* _NTDDK_ */ - -#ifndef PACK_PRAGMAS_NOT_SUPPORTED - # include -#endif - -typedef struct -{ - GUID PropertySet; - ULONG Count; -}KSPROPERTY_SERIALHDR, * PKSPROPERTY_SERIALHDR; - -#ifndef PACK_PRAGMAS_NOT_SUPPORTED - # include -#endif - -typedef struct -{ - KSIDENTIFIER PropTypeSet; - ULONG Id; - ULONG PropertyLength; -}KSPROPERTY_SERIAL, * PKSPROPERTY_SERIAL; - -#if defined(_NTDDK_) - - # define IOCTL_KS_HANDSHAKE \ - CTL_CODE(FILE_DEVICE_KS, 0x007, METHOD_NEITHER, FILE_ANY_ACCESS) - -typedef struct -{ - GUID ProtocolId; - PVOID Argument1; - PVOID Argument2; -}KSHANDSHAKE, * PKSHANDSHAKE; - -typedef struct _KSGATE KSGATE, * PKSGATE; - -struct _KSGATE -{ - LONG Count; - PKSGATE NextGate; -}; - -typedef PVOID KSOBJECT_BAG; - -typedef BOOLEAN (*PFNKSGENERATEEVENTCALLBACK)(PVOID Context, - PKSEVENT_ENTRY EventEntry); - -typedef NTSTATUS (*PFNKSDEVICECREATE)(PKSDEVICE Device); - -typedef NTSTATUS (*PFNKSDEVICEPNPSTART)(PKSDEVICE Device, PIRP Irp, - PCM_RESOURCE_LIST TranslatedResourceList, - PCM_RESOURCE_LIST UntranslatedResourceList); - -typedef NTSTATUS (*PFNKSDEVICE)(PKSDEVICE Device); - -typedef NTSTATUS (*PFNKSDEVICEIRP)(PKSDEVICE Device, PIRP Irp); - -typedef void (*PFNKSDEVICEIRPVOID)(PKSDEVICE Device, PIRP Irp); - -typedef NTSTATUS (*PFNKSDEVICEQUERYCAPABILITIES)(PKSDEVICE Device, PIRP Irp, - PDEVICE_CAPABILITIES Capabilities); - -typedef NTSTATUS (*PFNKSDEVICEQUERYPOWER)(PKSDEVICE Device, PIRP Irp, - DEVICE_POWER_STATE DeviceTo, - DEVICE_POWER_STATE DeviceFrom, - SYSTEM_POWER_STATE SystemTo, - SYSTEM_POWER_STATE SystemFrom, - POWER_ACTION Action); - -typedef void (*PFNKSDEVICESETPOWER)(PKSDEVICE Device, PIRP Irp, - DEVICE_POWER_STATE To, - DEVICE_POWER_STATE From); - -typedef NTSTATUS (*PFNKSFILTERFACTORYVOID)(PKSFILTERFACTORY FilterFactory); - -typedef void (*PFNKSFILTERFACTORYPOWER)(PKSFILTERFACTORY FilterFactory, - DEVICE_POWER_STATE State); - -typedef NTSTATUS (*PFNKSFILTERIRP)(PKSFILTER Filter, PIRP Irp); - -typedef NTSTATUS (*PFNKSFILTERPROCESS)(PKSFILTER Filter, - PKSPROCESSPIN_INDEXENTRY Index); - -typedef NTSTATUS (*PFNKSFILTERVOID)(PKSFILTER Filter); - -typedef void (*PFNKSFILTERPOWER)(PKSFILTER Filter, DEVICE_POWER_STATE State); - -typedef NTSTATUS (*PFNKSPINIRP)(PKSPIN Pin, PIRP Irp); - -typedef NTSTATUS (*PFNKSPINSETDEVICESTATE)(PKSPIN Pin, KSSTATE ToState, - KSSTATE FromState); - -typedef NTSTATUS (*PFNKSPINSETDATAFORMAT)(PKSPIN Pin, PKSDATAFORMAT OldFormat, - PKSMULTIPLE_ITEM OldAttributeList, - const KSDATARANGE* DataRange, - const KSATTRIBUTE_LIST* AttributeRange); - -typedef NTSTATUS (*PFNKSPINHANDSHAKE)(PKSPIN Pin, PKSHANDSHAKE In, - PKSHANDSHAKE Out); - -typedef NTSTATUS (*PFNKSPIN)(PKSPIN Pin); - -typedef void (*PFNKSPINVOID)(PKSPIN Pin); - -typedef void (*PFNKSPINPOWER)(PKSPIN Pin, DEVICE_POWER_STATE State); - -typedef BOOLEAN (*PFNKSPINSETTIMER)(PKSPIN Pin, PKTIMER Timer, - LARGE_INTEGER DueTime, PKDPC Dpc); - -typedef BOOLEAN (*PFNKSPINCANCELTIMER)(PKSPIN Pin, PKTIMER Timer); - -typedef LONGLONG (FASTCALL * PFNKSPINCORRELATEDTIME)(PKSPIN Pin, - PLONGLONG SystemTime); - -typedef void (*PFNKSPINRESOLUTION)(PKSPIN Pin, PKSRESOLUTION Resolution); - -typedef NTSTATUS (*PFNKSPININITIALIZEALLOCATOR)(PKSPIN Pin, - PKSALLOCATOR_FRAMING AllocatorFraming, - PVOID* Context); - -typedef void (*PFNKSSTREAMPOINTER)(PKSSTREAM_POINTER StreamPointer); - -typedef struct KSAUTOMATION_TABLE_ KSAUTOMATION_TABLE, * PKSAUTOMATION_TABLE; - -struct KSAUTOMATION_TABLE_ -{ - ULONG PropertySetsCount; - ULONG PropertyItemSize; - const KSPROPERTY_SET* PropertySets; - ULONG MethodSetsCount; - ULONG MethodItemSize; - const KSMETHOD_SET* MethodSets; - ULONG EventSetsCount; - ULONG EventItemSize; - const KSEVENT_SET* EventSets; - # ifndef _WIN64 - PVOID Alignment; - # endif -}; - - # define DEFINE_KSAUTOMATION_TABLE(table) \ - const KSAUTOMATION_TABLE table = - - # define DEFINE_KSAUTOMATION_PROPERTIES(table) \ - SIZEOF_ARRAY(table), \ - sizeof(KSPROPERTY_ITEM), \ - table - - # define DEFINE_KSAUTOMATION_METHODS(table) \ - SIZEOF_ARRAY(table), \ - sizeof(KSMETHOD_ITEM), \ - table - - # define DEFINE_KSAUTOMATION_EVENTS(table) \ - SIZEOF_ARRAY(table), \ - sizeof(KSEVENT_ITEM), \ - table - - # define DEFINE_KSAUTOMATION_PROPERTIES_NULL \ - 0, \ - sizeof(KSPROPERTY_ITEM), \ - NULL - - # define DEFINE_KSAUTOMATION_METHODS_NULL \ - 0, \ - sizeof(KSMETHOD_ITEM), \ - NULL - - # define DEFINE_KSAUTOMATION_EVENTS_NULL \ - 0, \ - sizeof(KSEVENT_ITEM), \ - NULL - - # define MIN_DEV_VER_FOR_QI (0x100) - -struct _KSDEVICE_DISPATCH -{ - PFNKSDEVICECREATE Add; - PFNKSDEVICEPNPSTART Start; - PFNKSDEVICE PostStart; - PFNKSDEVICEIRP QueryStop; - PFNKSDEVICEIRPVOID CancelStop; - PFNKSDEVICEIRPVOID Stop; - PFNKSDEVICEIRP QueryRemove; - PFNKSDEVICEIRPVOID CancelRemove; - PFNKSDEVICEIRPVOID Remove; - PFNKSDEVICEQUERYCAPABILITIES QueryCapabilities; - PFNKSDEVICEIRPVOID SurpriseRemoval; - PFNKSDEVICEQUERYPOWER QueryPower; - PFNKSDEVICESETPOWER SetPower; - PFNKSDEVICEIRP QueryInterface; -}; - -struct _KSFILTER_DISPATCH -{ - PFNKSFILTERIRP Create; - PFNKSFILTERIRP Close; - PFNKSFILTERPROCESS Process; - PFNKSFILTERVOID Reset; -}; - -struct _KSPIN_DISPATCH -{ - PFNKSPINIRP Create; - PFNKSPINIRP Close; - PFNKSPIN Process; - PFNKSPINVOID Reset; - PFNKSPINSETDATAFORMAT SetDataFormat; - PFNKSPINSETDEVICESTATE SetDeviceState; - PFNKSPIN Connect; - PFNKSPINVOID Disconnect; - const KSCLOCK_DISPATCH* Clock; - const KSALLOCATOR_DISPATCH* Allocator; -}; - -struct _KSCLOCK_DISPATCH -{ - PFNKSPINSETTIMER SetTimer; - PFNKSPINCANCELTIMER CancelTimer; - PFNKSPINCORRELATEDTIME CorrelatedTime; - PFNKSPINRESOLUTION Resolution; -}; - -struct _KSALLOCATOR_DISPATCH -{ - PFNKSPININITIALIZEALLOCATOR InitializeAllocator; - PFNKSDELETEALLOCATOR DeleteAllocator; - PFNKSDEFAULTALLOCATE Allocate; - PFNKSDEFAULTFREE Free; -}; - - # define KSDEVICE_DESCRIPTOR_VERSION (0x100) - -struct _KSDEVICE_DESCRIPTOR -{ - const KSDEVICE_DISPATCH* Dispatch; - ULONG FilterDescriptorsCount; - const KSFILTER_DESCRIPTOR* const* FilterDescriptors; - ULONG Version; -}; - -struct _KSFILTER_DESCRIPTOR -{ - const KSFILTER_DISPATCH* Dispatch; - const KSAUTOMATION_TABLE* AutomationTable; - ULONG Version; - # define KSFILTER_DESCRIPTOR_VERSION ((ULONG)-1) - ULONG Flags; - # define KSFILTER_FLAG_DISPATCH_LEVEL_PROCESSING 0x00000001 - # define KSFILTER_FLAG_CRITICAL_PROCESSING 0x00000002 - # define KSFILTER_FLAG_HYPERCRITICAL_PROCESSING 0x00000004 - # define KSFILTER_FLAG_RECEIVE_ZERO_LENGTH_SAMPLES 0x00000008 - # define KSFILTER_FLAG_DENY_USERMODE_ACCESS 0x80000000 - const GUID* ReferenceGuid; - ULONG PinDescriptorsCount; - ULONG PinDescriptorSize; - const KSPIN_DESCRIPTOR_EX* PinDescriptors; - ULONG CategoriesCount; - const GUID* Categories; - ULONG NodeDescriptorsCount; - ULONG NodeDescriptorSize; - const KSNODE_DESCRIPTOR* NodeDescriptors; - ULONG ConnectionsCount; - const KSTOPOLOGY_CONNECTION* Connections; - const KSCOMPONENTID* ComponentId; -}; - - # define DEFINE_KSFILTER_DESCRIPTOR(descriptor) \ - const KSFILTER_DESCRIPTOR descriptor = - - # define DEFINE_KSFILTER_PIN_DESCRIPTORS(table) \ - SIZEOF_ARRAY(table), \ - sizeof(table[0]), \ - table - - # define DEFINE_KSFILTER_CATEGORIES(table) \ - SIZEOF_ARRAY(table), \ - table - - # define DEFINE_KSFILTER_CATEGORY(category) \ - 1, \ - &(category) - - # define DEFINE_KSFILTER_CATEGORIES_NULL \ - 0, \ - NULL - - # define DEFINE_KSFILTER_NODE_DESCRIPTORS(table) \ - SIZEOF_ARRAY(table), \ - sizeof(table[0]), \ - table - - # define DEFINE_KSFILTER_NODE_DESCRIPTORS_NULL \ - 0, \ - sizeof(KSNODE_DESCRIPTOR), \ - NULL - - # define DEFINE_KSFILTER_CONNECTIONS(table) \ - SIZEOF_ARRAY(table), \ - table - - # define DEFINE_KSFILTER_DEFAULT_CONNECTIONS \ - 0, \ - NULL - - # define DEFINE_KSFILTER_DESCRIPTOR_TABLE(table) \ - const KSFILTER_DESCRIPTOR * const table[] = - -struct _KSPIN_DESCRIPTOR_EX -{ - const KSPIN_DISPATCH* Dispatch; - const KSAUTOMATION_TABLE* AutomationTable; - KSPIN_DESCRIPTOR PinDescriptor; - ULONG Flags; - # define KSPIN_FLAG_DISPATCH_LEVEL_PROCESSING KSFILTER_FLAG_DISPATCH_LEVEL_PROCESSING - # define KSPIN_FLAG_CRITICAL_PROCESSING KSFILTER_FLAG_CRITICAL_PROCESSING - # define KSPIN_FLAG_HYPERCRITICAL_PROCESSING KSFILTER_FLAG_HYPERCRITICAL_PROCESSING - # define KSPIN_FLAG_ASYNCHRONOUS_PROCESSING 0x00000008 - # define KSPIN_FLAG_DO_NOT_INITIATE_PROCESSING 0x00000010 - # define KSPIN_FLAG_INITIATE_PROCESSING_ON_EVERY_ARRIVAL 0x00000020 - # define KSPIN_FLAG_FRAMES_NOT_REQUIRED_FOR_PROCESSING 0x00000040 - # define KSPIN_FLAG_ENFORCE_FIFO 0x00000080 - # define KSPIN_FLAG_GENERATE_MAPPINGS 0x00000100 - # define KSPIN_FLAG_DISTINCT_TRAILING_EDGE 0x00000200 - # define KSPIN_FLAG_PROCESS_IN_RUN_STATE_ONLY 0x00010000 - # define KSPIN_FLAG_SPLITTER 0x00020000 - # define KSPIN_FLAG_USE_STANDARD_TRANSPORT 0x00040000 - # define KSPIN_FLAG_DO_NOT_USE_STANDARD_TRANSPORT 0x00080000 - # define KSPIN_FLAG_FIXED_FORMAT 0x00100000 - # define KSPIN_FLAG_GENERATE_EOS_EVENTS 0x00200000 - # define KSPIN_FLAG_RENDERER (KSPIN_FLAG_PROCESS_IN_RUN_STATE_ONLY | KSPIN_FLAG_GENERATE_EOS_EVENTS) - # define KSPIN_FLAG_IMPLEMENT_CLOCK 0x00400000 - # define KSPIN_FLAG_SOME_FRAMES_REQUIRED_FOR_PROCESSING 0x00800000 - # define KSPIN_FLAG_PROCESS_IF_ANY_IN_RUN_STATE 0x01000000 - # define KSPIN_FLAG_DENY_USERMODE_ACCESS 0x80000000 - ULONG InstancesPossible; - ULONG InstancesNecessary; - const KSALLOCATOR_FRAMING_EX* AllocatorFraming; - PFNKSINTERSECTHANDLEREX IntersectHandler; -}; - - # define DEFINE_KSPIN_DEFAULT_INTERFACES \ - 0, \ - NULL - - # define DEFINE_KSPIN_DEFAULT_MEDIUMS \ - 0, \ - NULL - -struct _KSNODE_DESCRIPTOR -{ - const KSAUTOMATION_TABLE* AutomationTable; - const GUID* Type; - const GUID* Name; - # ifndef _WIN64 - PVOID Alignment; - # endif -}; - - # ifndef _WIN64 - # define DEFINE_NODE_DESCRIPTOR(automation, type, name) \ - { (automation), (type), (name), NULL } - # else - # define DEFINE_NODE_DESCRIPTOR(automation, type, name) \ - { (automation), (type), (name) } - # endif - -struct _KSDEVICE -{ - const KSDEVICE_DESCRIPTOR* Descriptor; - KSOBJECT_BAG Bag; - PVOID Context; - PDEVICE_OBJECT FunctionalDeviceObject; - PDEVICE_OBJECT PhysicalDeviceObject; - PDEVICE_OBJECT NextDeviceObject; - BOOLEAN Started; - SYSTEM_POWER_STATE SystemPowerState; - DEVICE_POWER_STATE DevicePowerState; -}; - -struct _KSFILTERFACTORY -{ - const KSFILTER_DESCRIPTOR* FilterDescriptor; - KSOBJECT_BAG Bag; - PVOID Context; -}; - -struct _KSFILTER -{ - const KSFILTER_DESCRIPTOR* Descriptor; - KSOBJECT_BAG Bag; - PVOID Context; -}; - -struct _KSPIN -{ - const KSPIN_DESCRIPTOR_EX* Descriptor; - KSOBJECT_BAG Bag; - PVOID Context; - ULONG Id; - KSPIN_COMMUNICATION Communication; - BOOLEAN ConnectionIsExternal; - KSPIN_INTERFACE ConnectionInterface; - KSPIN_MEDIUM ConnectionMedium; - KSPRIORITY ConnectionPriority; - PKSDATAFORMAT ConnectionFormat; - PKSMULTIPLE_ITEM AttributeList; - ULONG StreamHeaderSize; - KSPIN_DATAFLOW DataFlow; - KSSTATE DeviceState; - KSRESET ResetState; - KSSTATE ClientState; -}; - -struct _KSMAPPING -{ - PHYSICAL_ADDRESS PhysicalAddress; - ULONG ByteCount; - ULONG Alignment; -}; - -struct _KSSTREAM_POINTER_OFFSET -{ - # if defined(_NTDDK_) - __MINGW_EXTENSION union - { - PUCHAR Data; - PKSMAPPING Mappings; - }; - # else - PUCHAR Data; - # endif /* _NTDDK_ */ - # ifndef _WIN64 - PVOID Alignment; - # endif - ULONG Count; - ULONG Remaining; -}; - -struct _KSSTREAM_POINTER -{ - PVOID Context; - PKSPIN Pin; - PKSSTREAM_HEADER StreamHeader; - PKSSTREAM_POINTER_OFFSET Offset; - KSSTREAM_POINTER_OFFSET OffsetIn; - KSSTREAM_POINTER_OFFSET OffsetOut; -}; - -struct _KSPROCESSPIN -{ - PKSPIN Pin; - PKSSTREAM_POINTER StreamPointer; - PKSPROCESSPIN InPlaceCounterpart; - PKSPROCESSPIN DelegateBranch; - PKSPROCESSPIN CopySource; - PVOID Data; - ULONG BytesAvailable; - ULONG BytesUsed; - ULONG Flags; - BOOLEAN Terminate; -}; - -struct _KSPROCESSPIN_INDEXENTRY -{ - PKSPROCESSPIN* Pins; - ULONG Count; -}; - -typedef enum -{ - KsObjectTypeDevice, - KsObjectTypeFilterFactory, - KsObjectTypeFilter, - KsObjectTypePin -}KSOBJECTTYPE; - -typedef void (*PFNKSFREE)(PVOID Data); - -typedef void (*PFNKSPINFRAMERETURN)(PKSPIN Pin, PVOID Data, ULONG Size, PMDL Mdl, - PVOID Context, NTSTATUS Status); - -typedef void (*PFNKSPINIRPCOMPLETION)(PKSPIN Pin, PIRP Irp); - - # if defined(_UNKNOWN_H_) || defined(__IUnknown_INTERFACE_DEFINED__) - # ifndef _IKsControl_ - # define _IKsControl_ - -typedef struct IKsControl* PIKSCONTROL; - - # ifndef DEFINE_ABSTRACT_UNKNOWN - # define DEFINE_ABSTRACT_UNKNOWN() \ - STDMETHOD_(NTSTATUS, QueryInterface) (THIS_ \ - REFIID InterfaceId, \ - PVOID * Interface \ - )PURE; \ - STDMETHOD_(ULONG, AddRef) (THIS)PURE; \ - STDMETHOD_(ULONG, Release) (THIS)PURE; - # endif - - # undef INTERFACE - # define INTERFACE IKsControl -DECLARE_INTERFACE_(IKsControl, IUnknown) -{ - DEFINE_ABSTRACT_UNKNOWN() - STDMETHOD_(NTSTATUS, KsProperty) (THIS_ - PKSPROPERTY Property, - ULONG PropertyLength, - PVOID PropertyData, - ULONG DataLength, - ULONG * BytesReturned - ) PURE; - STDMETHOD_(NTSTATUS, KsMethod) (THIS_ - PKSMETHOD Method, - ULONG MethodLength, - PVOID MethodData, - ULONG DataLength, - ULONG * BytesReturned - ) PURE; - STDMETHOD_(NTSTATUS, KsEvent) (THIS_ - PKSEVENT Event, - ULONG EventLength, - PVOID EventData, - ULONG DataLength, - ULONG * BytesReturned - ) PURE; -}; -typedef struct IKsReferenceClock* PIKSREFERENCECLOCK; - - # undef INTERFACE - # define INTERFACE IKsReferenceClock -DECLARE_INTERFACE_(IKsReferenceClock, IUnknown) -{ - DEFINE_ABSTRACT_UNKNOWN() - STDMETHOD_(LONGLONG, GetTime) (THIS) PURE; - STDMETHOD_(LONGLONG, GetPhysicalTime) (THIS) PURE; - STDMETHOD_(LONGLONG, GetCorrelatedTime) (THIS_ - PLONGLONG SystemTime - ) PURE; - STDMETHOD_(LONGLONG, GetCorrelatedPhysicalTime) (THIS_ - PLONGLONG SystemTime - ) PURE; - STDMETHOD_(NTSTATUS, GetResolution) (THIS_ - PKSRESOLUTION Resolution - ) PURE; - STDMETHOD_(NTSTATUS, GetState) (THIS_ - PKSSTATE State - ) PURE; -}; - # undef INTERFACE - - # define INTERFACE IKsDeviceFunctions -DECLARE_INTERFACE_(IKsDeviceFunctions, IUnknown) -{ - DEFINE_ABSTRACT_UNKNOWN() - STDMETHOD_(NTSTATUS, RegisterAdapterObjectEx) (THIS_ - PADAPTER_OBJECT AdapterObject, - PDEVICE_DESCRIPTION DeviceDescription, - ULONG NumberOfMapRegisters, - ULONG MaxMappingsByteCount, - ULONG MappingTableStride - ) PURE; -}; - - # undef INTERFACE - # define STATIC_IID_IKsControl \ - 0x28F54685L, 0x06FD, 0x11D2, 0xB2, 0x7A, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 -DEFINE_GUID(IID_IKsControl, - 0x28F54685L, 0x06FD, 0x11D2, 0xB2, 0x7A, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96); - # define STATIC_IID_IKsFastClock \ - 0xc9902485, 0xc180, 0x11d2, 0x84, 0x73, 0xd4, 0x23, 0x94, 0x45, 0x9e, 0x5e -DEFINE_GUID(IID_IKsFastClock, - 0xc9902485, 0xc180, 0x11d2, 0x84, 0x73, 0xd4, 0x23, 0x94, 0x45, 0x9e, 0x5e); - # define STATIC_IID_IKsDeviceFunctions \ - 0xe234f2e2, 0xbd69, 0x4f8c, 0xb3, 0xf2, 0x7c, 0xd7, 0x9e, 0xd4, 0x66, 0xbd -DEFINE_GUID(IID_IKsDeviceFunctions, - 0xe234f2e2, 0xbd69, 0x4f8c, 0xb3, 0xf2, 0x7c, 0xd7, 0x9e, 0xd4, 0x66, 0xbd); - # endif /* _IKsControl_ */ - # endif /* defined(_UNKNOWN_H_) || defined(__IUnknown_INTERFACE_DEFINED__) */ - -#endif /* _NTDDK_ */ - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef _KSDDK_ - # define KSDDKAPI -#else - # define KSDDKAPI DECLSPEC_IMPORT -#endif - -#if defined(_NTDDK_) - -KSDDKAPI NTSTATUS NTAPI KsEnableEvent(PIRP Irp, ULONG EventSetsCount, const KSEVENT_SET* EventSet, PLIST_ENTRY EventsList, KSEVENTS_LOCKTYPE EventsFlags, PVOID EventsLock); - -KSDDKAPI NTSTATUS NTAPI KsEnableEventWithAllocator(PIRP Irp, ULONG EventSetsCount, const KSEVENT_SET* EventSet, PLIST_ENTRY EventsList, KSEVENTS_LOCKTYPE EventsFlags, PVOID EventsLock, PFNKSALLOCATOR Allocator, ULONG EventItemSize); - -KSDDKAPI NTSTATUS NTAPI KsDisableEvent(PIRP Irp, PLIST_ENTRY EventsList, KSEVENTS_LOCKTYPE EventsFlags, PVOID EventsLock); - -KSDDKAPI VOID NTAPI KsDiscardEvent(PKSEVENT_ENTRY EventEntry); - -KSDDKAPI VOID NTAPI KsFreeEventList(PFILE_OBJECT FileObject, PLIST_ENTRY EventsList, KSEVENTS_LOCKTYPE EventsFlags, PVOID EventsLock); - -KSDDKAPI NTSTATUS NTAPI KsGenerateEvent(PKSEVENT_ENTRY EventEntry); - -KSDDKAPI NTSTATUS NTAPI KsGenerateDataEvent(PKSEVENT_ENTRY EventEntry, ULONG DataSize, PVOID Data); - -KSDDKAPI VOID NTAPI KsGenerateEventList(GUID* Set, ULONG EventId, PLIST_ENTRY EventsList, KSEVENTS_LOCKTYPE EventsFlags, PVOID EventsLock); - -KSDDKAPI NTSTATUS NTAPI KsPropertyHandler(PIRP Irp, ULONG PropertySetsCount, const KSPROPERTY_SET* PropertySet); - -KSDDKAPI NTSTATUS NTAPI KsPropertyHandlerWithAllocator(PIRP Irp, ULONG PropertySetsCount, const KSPROPERTY_SET* PropertySet, PFNKSALLOCATOR Allocator, ULONG PropertyItemSize); - -KSDDKAPI BOOLEAN NTAPI KsFastPropertyHandler(PFILE_OBJECT FileObject, PKSPROPERTY Property, ULONG PropertyLength, PVOID Data, ULONG DataLength, PIO_STATUS_BLOCK IoStatus, ULONG PropertySetsCount, const KSPROPERTY_SET* PropertySet); - -KSDDKAPI NTSTATUS NTAPI KsMethodHandler(PIRP Irp, ULONG MethodSetsCount, const KSMETHOD_SET* MethodSet); - -KSDDKAPI NTSTATUS NTAPI KsMethodHandlerWithAllocator(PIRP Irp, ULONG MethodSetsCount, const KSMETHOD_SET* MethodSet, PFNKSALLOCATOR Allocator, ULONG MethodItemSize); - -KSDDKAPI BOOLEAN NTAPI KsFastMethodHandler(PFILE_OBJECT FileObject, PKSMETHOD Method, ULONG MethodLength, PVOID Data, ULONG DataLength, PIO_STATUS_BLOCK IoStatus, ULONG MethodSetsCount, const KSMETHOD_SET* MethodSet); - -KSDDKAPI NTSTATUS NTAPI KsCreateDefaultAllocator(PIRP Irp); - -KSDDKAPI NTSTATUS NTAPI KsCreateDefaultAllocatorEx(PIRP Irp, PVOID InitializeContext, PFNKSDEFAULTALLOCATE DefaultAllocate, PFNKSDEFAULTFREE DefaultFree, PFNKSINITIALIZEALLOCATOR InitializeAllocator, PFNKSDELETEALLOCATOR DeleteAllocator); - -KSDDKAPI NTSTATUS NTAPI KsCreateAllocator(HANDLE ConnectionHandle, PKSALLOCATOR_FRAMING AllocatorFraming, PHANDLE AllocatorHandle); - -KSDDKAPI NTSTATUS NTAPI KsValidateAllocatorCreateRequest(PIRP Irp, PKSALLOCATOR_FRAMING* AllocatorFraming); - -KSDDKAPI NTSTATUS NTAPI KsValidateAllocatorFramingEx(PKSALLOCATOR_FRAMING_EX Framing, ULONG BufferSize, const KSALLOCATOR_FRAMING_EX* PinFraming); - -KSDDKAPI NTSTATUS NTAPI KsAllocateDefaultClock(PKSDEFAULTCLOCK* DefaultClock); - -KSDDKAPI NTSTATUS NTAPI KsAllocateDefaultClockEx(PKSDEFAULTCLOCK* DefaultClock, PVOID Context, PFNKSSETTIMER SetTimer, PFNKSCANCELTIMER CancelTimer, PFNKSCORRELATEDTIME CorrelatedTime, const KSRESOLUTION* Resolution, ULONG Flags); - -KSDDKAPI VOID NTAPI KsFreeDefaultClock(PKSDEFAULTCLOCK DefaultClock); -KSDDKAPI NTSTATUS NTAPI KsCreateDefaultClock(PIRP Irp, PKSDEFAULTCLOCK DefaultClock); - -KSDDKAPI NTSTATUS NTAPI KsCreateClock(HANDLE ConnectionHandle, PKSCLOCK_CREATE ClockCreate, PHANDLE ClockHandle); - -KSDDKAPI NTSTATUS NTAPI KsValidateClockCreateRequest(PIRP Irp, PKSCLOCK_CREATE* ClockCreate); - -KSDDKAPI KSSTATE NTAPI KsGetDefaultClockState(PKSDEFAULTCLOCK DefaultClock); -KSDDKAPI VOID NTAPI KsSetDefaultClockState(PKSDEFAULTCLOCK DefaultClock, KSSTATE State); -KSDDKAPI LONGLONG NTAPI KsGetDefaultClockTime(PKSDEFAULTCLOCK DefaultClock); -KSDDKAPI VOID NTAPI KsSetDefaultClockTime(PKSDEFAULTCLOCK DefaultClock, LONGLONG Time); - -KSDDKAPI NTSTATUS NTAPI KsCreatePin(HANDLE FilterHandle, PKSPIN_CONNECT Connect, ACCESS_MASK DesiredAccess, PHANDLE ConnectionHandle); - -KSDDKAPI NTSTATUS NTAPI KsValidateConnectRequest(PIRP Irp, ULONG DescriptorsCount, const KSPIN_DESCRIPTOR* Descriptor, PKSPIN_CONNECT* Connect); - -KSDDKAPI NTSTATUS NTAPI KsPinPropertyHandler(PIRP Irp, PKSPROPERTY Property, PVOID Data, ULONG DescriptorsCount, const KSPIN_DESCRIPTOR* Descriptor); - -KSDDKAPI NTSTATUS NTAPI KsPinDataIntersection(PIRP Irp, PKSP_PIN Pin, PVOID Data, ULONG DescriptorsCount, const KSPIN_DESCRIPTOR* Descriptor, PFNKSINTERSECTHANDLER IntersectHandler); - -KSDDKAPI NTSTATUS NTAPI KsPinDataIntersectionEx(PIRP Irp, PKSP_PIN Pin, PVOID Data, ULONG DescriptorsCount, const KSPIN_DESCRIPTOR* Descriptor, ULONG DescriptorSize, PFNKSINTERSECTHANDLEREX IntersectHandler, PVOID HandlerContext); - -KSDDKAPI NTSTATUS NTAPI KsHandleSizedListQuery(PIRP Irp, ULONG DataItemsCount, ULONG DataItemSize, const VOID* DataItems); - - # ifndef MAKEINTRESOURCE - # define MAKEINTRESOURCE(r) ((ULONG_PTR)(USHORT)r) - # endif - # ifndef RT_STRING - # define RT_STRING MAKEINTRESOURCE(6) - # define RT_RCDATA MAKEINTRESOURCE(10) - # endif - -KSDDKAPI NTSTATUS NTAPI KsLoadResource(PVOID ImageBase, POOL_TYPE PoolType, ULONG_PTR ResourceName, ULONG ResourceType, PVOID* Resource, PULONG ResourceSize); - -KSDDKAPI NTSTATUS NTAPI KsGetImageNameAndResourceId(HANDLE RegKey, PUNICODE_STRING ImageName, PULONG_PTR ResourceId, PULONG ValueType); - -KSDDKAPI NTSTATUS NTAPI KsMapModuleName(PDEVICE_OBJECT PhysicalDeviceObject, PUNICODE_STRING ModuleName, PUNICODE_STRING ImageName, PULONG_PTR ResourceId, PULONG ValueType); - -KSDDKAPI NTSTATUS NTAPI KsReferenceBusObject(KSDEVICE_HEADER Header); -KSDDKAPI VOID NTAPI KsDereferenceBusObject(KSDEVICE_HEADER Header); -KSDDKAPI NTSTATUS NTAPI KsDispatchQuerySecurity(PDEVICE_OBJECT DeviceObject, PIRP Irp); -KSDDKAPI NTSTATUS NTAPI KsDispatchSetSecurity(PDEVICE_OBJECT DeviceObject, PIRP Irp); -KSDDKAPI NTSTATUS NTAPI KsDispatchSpecificProperty(PIRP Irp, PFNKSHANDLER Handler); -KSDDKAPI NTSTATUS NTAPI KsDispatchSpecificMethod(PIRP Irp, PFNKSHANDLER Handler); - -KSDDKAPI NTSTATUS NTAPI KsReadFile(PFILE_OBJECT FileObject, PKEVENT Event, PVOID PortContext, PIO_STATUS_BLOCK IoStatusBlock, PVOID Buffer, ULONG Length, ULONG Key, KPROCESSOR_MODE RequestorMode); - -KSDDKAPI NTSTATUS NTAPI KsWriteFile(PFILE_OBJECT FileObject, PKEVENT Event, PVOID PortContext, PIO_STATUS_BLOCK IoStatusBlock, PVOID Buffer, ULONG Length, ULONG Key, KPROCESSOR_MODE RequestorMode); - -KSDDKAPI NTSTATUS NTAPI KsQueryInformationFile(PFILE_OBJECT FileObject, PVOID FileInformation, ULONG Length, FILE_INFORMATION_CLASS FileInformationClass); - -KSDDKAPI NTSTATUS NTAPI KsSetInformationFile(PFILE_OBJECT FileObject, PVOID FileInformation, ULONG Length, FILE_INFORMATION_CLASS FileInformationClass); - -KSDDKAPI NTSTATUS NTAPI KsStreamIo(PFILE_OBJECT FileObject, PKEVENT Event, PVOID PortContext, PIO_COMPLETION_ROUTINE CompletionRoutine, PVOID CompletionContext, KSCOMPLETION_INVOCATION CompletionInvocationFlags, PIO_STATUS_BLOCK IoStatusBlock, PVOID StreamHeaders, ULONG Length, ULONG Flags, KPROCESSOR_MODE RequestorMode); - -KSDDKAPI NTSTATUS NTAPI KsProbeStreamIrp(PIRP Irp, ULONG ProbeFlags, ULONG HeaderSize); -KSDDKAPI NTSTATUS NTAPI KsAllocateExtraData(PIRP Irp, ULONG ExtraSize, PVOID* ExtraBuffer); -KSDDKAPI VOID NTAPI KsNullDriverUnload(PDRIVER_OBJECT DriverObject); - -KSDDKAPI NTSTATUS NTAPI KsSetMajorFunctionHandler(PDRIVER_OBJECT DriverObject, ULONG MajorFunction); - -KSDDKAPI NTSTATUS NTAPI KsDispatchInvalidDeviceRequest(PDEVICE_OBJECT DeviceObject, PIRP Irp); - -KSDDKAPI NTSTATUS NTAPI KsDefaultDeviceIoCompletion(PDEVICE_OBJECT DeviceObject, PIRP Irp); - -KSDDKAPI NTSTATUS NTAPI KsDispatchIrp(PDEVICE_OBJECT DeviceObject, PIRP Irp); - -KSDDKAPI BOOLEAN NTAPI KsDispatchFastIoDeviceControlFailure(PFILE_OBJECT FileObject, BOOLEAN Wait, PVOID InputBuffer, ULONG InputBufferLength, PVOID OutputBuffer, ULONG OutputBufferLength, ULONG IoControlCode, PIO_STATUS_BLOCK IoStatus, PDEVICE_OBJECT DeviceObject); - -KSDDKAPI BOOLEAN NTAPI KsDispatchFastReadFailure(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, ULONG Length, BOOLEAN Wait, ULONG LockKey, PVOID Buffer, PIO_STATUS_BLOCK IoStatus, PDEVICE_OBJECT DeviceObject); - - # define KsDispatchFastWriteFailure KsDispatchFastReadFailure - -KSDDKAPI VOID NTAPI KsCancelRoutine(PDEVICE_OBJECT DeviceObject, PIRP Irp); -KSDDKAPI VOID NTAPI KsCancelIo(PLIST_ENTRY QueueHead, PKSPIN_LOCK SpinLock); -KSDDKAPI VOID NTAPI KsReleaseIrpOnCancelableQueue(PIRP Irp, PDRIVER_CANCEL DriverCancel); - -KSDDKAPI PIRP NTAPI KsRemoveIrpFromCancelableQueue(PLIST_ENTRY QueueHead, PKSPIN_LOCK SpinLock, KSLIST_ENTRY_LOCATION ListLocation, KSIRP_REMOVAL_OPERATION RemovalOperation); - -KSDDKAPI NTSTATUS NTAPI KsMoveIrpsOnCancelableQueue(PLIST_ENTRY SourceList, PKSPIN_LOCK SourceLock, PLIST_ENTRY DestinationList, PKSPIN_LOCK DestinationLock, KSLIST_ENTRY_LOCATION ListLocation, PFNKSIRPLISTCALLBACK ListCallback, PVOID Context); - -KSDDKAPI VOID NTAPI KsRemoveSpecificIrpFromCancelableQueue(PIRP Irp); - -KSDDKAPI VOID NTAPI KsAddIrpToCancelableQueue(PLIST_ENTRY QueueHead, PKSPIN_LOCK SpinLock, PIRP Irp, KSLIST_ENTRY_LOCATION ListLocation, PDRIVER_CANCEL DriverCancel); - -KSDDKAPI NTSTATUS NTAPI KsAcquireResetValue(PIRP Irp, KSRESET* ResetValue); - -KSDDKAPI NTSTATUS NTAPI KsTopologyPropertyHandler(PIRP Irp, PKSPROPERTY Property, PVOID Data, const KSTOPOLOGY* Topology); - -KSDDKAPI VOID NTAPI KsAcquireDeviceSecurityLock(KSDEVICE_HEADER Header, BOOLEAN Exclusive); -KSDDKAPI VOID NTAPI KsReleaseDeviceSecurityLock(KSDEVICE_HEADER Header); -KSDDKAPI NTSTATUS NTAPI KsDefaultDispatchPnp(PDEVICE_OBJECT DeviceObject, PIRP Irp); -KSDDKAPI NTSTATUS NTAPI KsDefaultDispatchPower(PDEVICE_OBJECT DeviceObject, PIRP Irp); -KSDDKAPI NTSTATUS NTAPI KsDefaultForwardIrp(PDEVICE_OBJECT DeviceObject, PIRP Irp); - -KSDDKAPI VOID NTAPI KsSetDevicePnpAndBaseObject(KSDEVICE_HEADER Header, PDEVICE_OBJECT PnpDeviceObject, PDEVICE_OBJECT BaseObject); - -KSDDKAPI PDEVICE_OBJECT NTAPI KsQueryDevicePnpObject(KSDEVICE_HEADER Header); -KSDDKAPI ACCESS_MASK NTAPI KsQueryObjectAccessMask(KSOBJECT_HEADER Header); - -KSDDKAPI VOID NTAPI KsRecalculateStackDepth(KSDEVICE_HEADER Header, BOOLEAN ReuseStackLocation); - -KSDDKAPI VOID NTAPI KsSetTargetState(KSOBJECT_HEADER Header, KSTARGET_STATE TargetState); - -KSDDKAPI VOID NTAPI KsSetTargetDeviceObject(KSOBJECT_HEADER Header, PDEVICE_OBJECT TargetDevice); - -KSDDKAPI VOID NTAPI KsSetPowerDispatch(KSOBJECT_HEADER Header, PFNKSCONTEXT_DISPATCH PowerDispatch, PVOID PowerContext); - -KSDDKAPI PKSOBJECT_CREATE_ITEM NTAPI KsQueryObjectCreateItem(KSOBJECT_HEADER Header); - -KSDDKAPI NTSTATUS NTAPI KsAllocateDeviceHeader(KSDEVICE_HEADER* Header, ULONG ItemsCount, PKSOBJECT_CREATE_ITEM ItemsList); - -KSDDKAPI VOID NTAPI KsFreeDeviceHeader(KSDEVICE_HEADER Header); - -KSDDKAPI NTSTATUS NTAPI KsAllocateObjectHeader(KSOBJECT_HEADER* Header, ULONG ItemsCount, PKSOBJECT_CREATE_ITEM ItemsList, PIRP Irp, const KSDISPATCH_TABLE* Table); - -KSDDKAPI VOID NTAPI KsFreeObjectHeader(KSOBJECT_HEADER Header); - -KSDDKAPI NTSTATUS NTAPI KsAddObjectCreateItemToDeviceHeader(KSDEVICE_HEADER Header, PDRIVER_DISPATCH Create, PVOID Context, PWSTR ObjectClass, PSECURITY_DESCRIPTOR SecurityDescriptor); - -KSDDKAPI NTSTATUS NTAPI KsAddObjectCreateItemToObjectHeader(KSOBJECT_HEADER Header, PDRIVER_DISPATCH Create, PVOID Context, PWSTR ObjectClass, PSECURITY_DESCRIPTOR SecurityDescriptor); - -KSDDKAPI NTSTATUS NTAPI KsAllocateObjectCreateItem(KSDEVICE_HEADER Header, PKSOBJECT_CREATE_ITEM CreateItem, BOOLEAN AllocateEntry, PFNKSITEMFREECALLBACK ItemFreeCallback); - -KSDDKAPI NTSTATUS NTAPI KsFreeObjectCreateItem(KSDEVICE_HEADER Header, PUNICODE_STRING CreateItem); - -KSDDKAPI NTSTATUS NTAPI KsFreeObjectCreateItemsByContext(KSDEVICE_HEADER Header, PVOID Context); - -KSDDKAPI NTSTATUS NTAPI KsCreateDefaultSecurity(PSECURITY_DESCRIPTOR ParentSecurity, PSECURITY_DESCRIPTOR* DefaultSecurity); - -KSDDKAPI NTSTATUS NTAPI KsForwardIrp(PIRP Irp, PFILE_OBJECT FileObject, BOOLEAN ReuseStackLocation); - -KSDDKAPI NTSTATUS NTAPI KsForwardAndCatchIrp(PDEVICE_OBJECT DeviceObject, PIRP Irp, PFILE_OBJECT FileObject, KSSTACK_USE StackUse); - -KSDDKAPI NTSTATUS NTAPI KsSynchronousIoControlDevice(PFILE_OBJECT FileObject, KPROCESSOR_MODE RequestorMode, ULONG IoControl, PVOID InBuffer, ULONG InSize, PVOID OutBuffer, ULONG OutSize, PULONG BytesReturned); - -KSDDKAPI NTSTATUS NTAPI KsUnserializeObjectPropertiesFromRegistry(PFILE_OBJECT FileObject, HANDLE ParentKey, PUNICODE_STRING RegistryPath); - -KSDDKAPI NTSTATUS NTAPI KsCacheMedium(PUNICODE_STRING SymbolicLink, PKSPIN_MEDIUM Medium, ULONG PinDirection); - -KSDDKAPI NTSTATUS NTAPI KsRegisterWorker(WORK_QUEUE_TYPE WorkQueueType, PKSWORKER* Worker); - -KSDDKAPI NTSTATUS NTAPI KsRegisterCountedWorker(WORK_QUEUE_TYPE WorkQueueType, PWORK_QUEUE_ITEM CountedWorkItem, PKSWORKER* Worker); - -KSDDKAPI VOID NTAPI KsUnregisterWorker(PKSWORKER Worker); -KSDDKAPI NTSTATUS NTAPI KsQueueWorkItem(PKSWORKER Worker, PWORK_QUEUE_ITEM WorkItem); -KSDDKAPI ULONG NTAPI KsIncrementCountedWorker(PKSWORKER Worker); -KSDDKAPI ULONG NTAPI KsDecrementCountedWorker(PKSWORKER Worker); - -KSDDKAPI NTSTATUS NTAPI KsCreateTopologyNode(HANDLE ParentHandle, PKSNODE_CREATE NodeCreate, ACCESS_MASK DesiredAccess, PHANDLE NodeHandle); - -KSDDKAPI NTSTATUS NTAPI KsValidateTopologyNodeCreateRequest(PIRP Irp, PKSTOPOLOGY Topology, PKSNODE_CREATE* NodeCreate); - -KSDDKAPI NTSTATUS NTAPI KsMergeAutomationTables(PKSAUTOMATION_TABLE* AutomationTableAB, PKSAUTOMATION_TABLE AutomationTableA, PKSAUTOMATION_TABLE AutomationTableB, KSOBJECT_BAG Bag); - -KSDDKAPI NTSTATUS NTAPI KsInitializeDriver(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPathName, const KSDEVICE_DESCRIPTOR* Descriptor); - -KSDDKAPI NTSTATUS NTAPI KsAddDevice(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT PhysicalDeviceObject); - -KSDDKAPI NTSTATUS NTAPI KsCreateDevice(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT PhysicalDeviceObject, const KSDEVICE_DESCRIPTOR* Descriptor, ULONG ExtensionSize, PKSDEVICE* Device); - -KSDDKAPI NTSTATUS NTAPI KsInitializeDevice(PDEVICE_OBJECT FunctionalDeviceObject, PDEVICE_OBJECT PhysicalDeviceObject, PDEVICE_OBJECT NextDeviceObject, const KSDEVICE_DESCRIPTOR* Descriptor); - -KSDDKAPI void NTAPI KsTerminateDevice(PDEVICE_OBJECT DeviceObject); -KSDDKAPI PKSDEVICE NTAPI KsGetDeviceForDeviceObject(PDEVICE_OBJECT FunctionalDeviceObject); -KSDDKAPI void NTAPI KsAcquireDevice(PKSDEVICE Device); -KSDDKAPI void NTAPI KsReleaseDevice(PKSDEVICE Device); - -KSDDKAPI void NTAPI KsDeviceRegisterAdapterObject(PKSDEVICE Device, PADAPTER_OBJECT AdapterObject, ULONG MaxMappingsByteCount, ULONG MappingTableStride); - -KSDDKAPI ULONG NTAPI KsDeviceGetBusData(PKSDEVICE Device, ULONG DataType, PVOID Buffer, ULONG Offset, ULONG Length); - -KSDDKAPI ULONG NTAPI KsDeviceSetBusData(PKSDEVICE Device, ULONG DataType, PVOID Buffer, ULONG Offset, ULONG Length); - -KSDDKAPI NTSTATUS NTAPI KsCreateFilterFactory(PDEVICE_OBJECT DeviceObject, const KSFILTER_DESCRIPTOR* Descriptor, PWSTR RefString, PSECURITY_DESCRIPTOR SecurityDescriptor, ULONG CreateItemFlags, PFNKSFILTERFACTORYPOWER SleepCallback, PFNKSFILTERFACTORYPOWER WakeCallback, PKSFILTERFACTORY* FilterFactory); - - # define KsDeleteFilterFactory(FilterFactory) \ - KsFreeObjectCreateItemsByContext(*(KSDEVICE_HEADER*)( \ - KsFilterFactoryGetParentDevice(FilterFactory)->FunctionalDeviceObject->DeviceExtension), \ - FilterFactory) - -KSDDKAPI NTSTATUS NTAPI KsFilterFactoryUpdateCacheData(PKSFILTERFACTORY FilterFactory, const KSFILTER_DESCRIPTOR* FilterDescriptor); - -KSDDKAPI NTSTATUS NTAPI KsFilterFactoryAddCreateItem(PKSFILTERFACTORY FilterFactory, PWSTR RefString, PSECURITY_DESCRIPTOR SecurityDescriptor, ULONG CreateItemFlags); - -KSDDKAPI NTSTATUS NTAPI KsFilterFactorySetDeviceClassesState(PKSFILTERFACTORY FilterFactory, BOOLEAN NewState); - -KSDDKAPI PUNICODE_STRING NTAPI KsFilterFactoryGetSymbolicLink(PKSFILTERFACTORY FilterFactory); - -KSDDKAPI void NTAPI KsAddEvent(PVOID Object, PKSEVENT_ENTRY EventEntry); - -void __forceinline KsFilterAddEvent(PKSFILTER Filter, PKSEVENT_ENTRY EventEntry) -{ - KsAddEvent(Filter, EventEntry); -} - -void __forceinline KsPinAddEvent(PKSPIN Pin, PKSEVENT_ENTRY EventEntry) -{ - KsAddEvent(Pin, EventEntry); -} - -KSDDKAPI NTSTATUS NTAPI KsDefaultAddEventHandler(PIRP Irp, PKSEVENTDATA EventData, PKSEVENT_ENTRY EventEntry); - -KSDDKAPI void NTAPI KsGenerateEvents(PVOID Object, const GUID* EventSet, ULONG EventId, ULONG DataSize, PVOID Data, PFNKSGENERATEEVENTCALLBACK CallBack, PVOID CallBackContext); - -void __forceinline KsFilterGenerateEvents(PKSFILTER Filter, const GUID* EventSet, ULONG EventId, ULONG DataSize, PVOID Data, PFNKSGENERATEEVENTCALLBACK CallBack, PVOID CallBackContext) -{ - KsGenerateEvents(Filter, EventSet, EventId, DataSize, Data, CallBack, - CallBackContext); -} - -void __forceinline KsPinGenerateEvents(PKSPIN Pin, const GUID* EventSet, ULONG EventId, ULONG DataSize, PVOID Data, PFNKSGENERATEEVENTCALLBACK CallBack, PVOID CallBackContext) -{ - KsGenerateEvents(Pin, EventSet, EventId, DataSize, Data, CallBack, - CallBackContext); -} - -typedef enum -{ - KSSTREAM_POINTER_STATE_UNLOCKED = 0, - KSSTREAM_POINTER_STATE_LOCKED -}KSSTREAM_POINTER_STATE; - -KSDDKAPI NTSTATUS NTAPI KsPinGetAvailableByteCount(PKSPIN Pin, PLONG InputDataBytes, PLONG OutputBufferBytes); - -KSDDKAPI PKSSTREAM_POINTER NTAPI KsPinGetLeadingEdgeStreamPointer(PKSPIN Pin, KSSTREAM_POINTER_STATE State); - -KSDDKAPI PKSSTREAM_POINTER NTAPI KsPinGetTrailingEdgeStreamPointer(PKSPIN Pin, KSSTREAM_POINTER_STATE State); - -KSDDKAPI NTSTATUS NTAPI KsStreamPointerSetStatusCode(PKSSTREAM_POINTER StreamPointer, NTSTATUS Status); - -KSDDKAPI NTSTATUS NTAPI KsStreamPointerLock(PKSSTREAM_POINTER StreamPointer); -KSDDKAPI void NTAPI KsStreamPointerUnlock(PKSSTREAM_POINTER StreamPointer, BOOLEAN Eject); - -KSDDKAPI void NTAPI KsStreamPointerAdvanceOffsetsAndUnlock(PKSSTREAM_POINTER StreamPointer, ULONG InUsed, ULONG OutUsed, BOOLEAN Eject); - -KSDDKAPI void NTAPI KsStreamPointerDelete(PKSSTREAM_POINTER StreamPointer); - -KSDDKAPI NTSTATUS NTAPI KsStreamPointerClone(PKSSTREAM_POINTER StreamPointer, PFNKSSTREAMPOINTER CancelCallback, ULONG ContextSize, PKSSTREAM_POINTER* CloneStreamPointer); - -KSDDKAPI NTSTATUS NTAPI KsStreamPointerAdvanceOffsets(PKSSTREAM_POINTER StreamPointer, ULONG InUsed, ULONG OutUsed, BOOLEAN Eject); - -KSDDKAPI NTSTATUS NTAPI KsStreamPointerAdvance(PKSSTREAM_POINTER StreamPointer); -KSDDKAPI PMDL NTAPI KsStreamPointerGetMdl(PKSSTREAM_POINTER StreamPointer); - -KSDDKAPI PIRP NTAPI KsStreamPointerGetIrp(PKSSTREAM_POINTER StreamPointer, PBOOLEAN FirstFrameInIrp, PBOOLEAN LastFrameInIrp); - -KSDDKAPI void NTAPI KsStreamPointerScheduleTimeout(PKSSTREAM_POINTER StreamPointer, PFNKSSTREAMPOINTER Callback, ULONGLONG Interval); - -KSDDKAPI void NTAPI KsStreamPointerCancelTimeout(PKSSTREAM_POINTER StreamPointer); -KSDDKAPI PKSSTREAM_POINTER NTAPI KsPinGetFirstCloneStreamPointer(PKSPIN Pin); - -KSDDKAPI PKSSTREAM_POINTER NTAPI KsStreamPointerGetNextClone(PKSSTREAM_POINTER StreamPointer); - -KSDDKAPI NTSTATUS NTAPI KsPinHandshake(PKSPIN Pin, PKSHANDSHAKE In, PKSHANDSHAKE Out); -KSDDKAPI void NTAPI KsCompletePendingRequest(PIRP Irp); -KSDDKAPI KSOBJECTTYPE NTAPI KsGetObjectTypeFromIrp(PIRP Irp); -KSDDKAPI PVOID NTAPI KsGetObjectFromFileObject(PFILE_OBJECT FileObject); -KSDDKAPI KSOBJECTTYPE NTAPI KsGetObjectTypeFromFileObject(PFILE_OBJECT FileObject); - -PKSFILTER __forceinline KsGetFilterFromFileObject(PFILE_OBJECT FileObject) -{ - return (PKSFILTER)KsGetObjectFromFileObject(FileObject); -} - -PKSPIN __forceinline KsGetPinFromFileObject(PFILE_OBJECT FileObject) -{ - return (PKSPIN)KsGetObjectFromFileObject(FileObject); -} - -KSDDKAPI PKSGATE NTAPI KsFilterGetAndGate(PKSFILTER Filter); -KSDDKAPI void NTAPI KsFilterAcquireProcessingMutex(PKSFILTER Filter); -KSDDKAPI void NTAPI KsFilterReleaseProcessingMutex(PKSFILTER Filter); -KSDDKAPI void NTAPI KsFilterAttemptProcessing(PKSFILTER Filter, BOOLEAN Asynchronous); -KSDDKAPI PKSGATE NTAPI KsPinGetAndGate(PKSPIN Pin); -KSDDKAPI void NTAPI KsPinAttachAndGate(PKSPIN Pin, PKSGATE AndGate); -KSDDKAPI void NTAPI KsPinAttachOrGate(PKSPIN Pin, PKSGATE OrGate); -KSDDKAPI void NTAPI KsPinAcquireProcessingMutex(PKSPIN Pin); -KSDDKAPI void NTAPI KsPinReleaseProcessingMutex(PKSPIN Pin); -KSDDKAPI BOOLEAN NTAPI KsProcessPinUpdate(PKSPROCESSPIN ProcessPin); - -KSDDKAPI void NTAPI KsPinGetCopyRelationships(PKSPIN Pin, PKSPIN* CopySource, PKSPIN* DelegateBranch); - -KSDDKAPI void NTAPI KsPinAttemptProcessing(PKSPIN Pin, BOOLEAN Asynchronous); -KSDDKAPI PVOID NTAPI KsGetParent(PVOID Object); - -PKSDEVICE __forceinline KsFilterFactoryGetParentDevice(PKSFILTERFACTORY FilterFactory) -{ - return (PKSDEVICE)KsGetParent((PVOID)FilterFactory); -} - -PKSFILTERFACTORY __forceinline KsFilterGetParentFilterFactory(PKSFILTER Filter) -{ - return (PKSFILTERFACTORY)KsGetParent((PVOID)Filter); -} - -KSDDKAPI PKSFILTER NTAPI KsPinGetParentFilter(PKSPIN Pin); -KSDDKAPI PVOID NTAPI KsGetFirstChild(PVOID Object); - -PKSFILTERFACTORY __forceinline KsDeviceGetFirstChildFilterFactory(PKSDEVICE Device) -{ - return (PKSFILTERFACTORY)KsGetFirstChild((PVOID)Device); -} - -PKSFILTER __forceinline KsFilterFactoryGetFirstChildFilter(PKSFILTERFACTORY FilterFactory) -{ - return (PKSFILTER)KsGetFirstChild((PVOID)FilterFactory); -} - -KSDDKAPI ULONG NTAPI KsFilterGetChildPinCount(PKSFILTER Filter, ULONG PinId); -KSDDKAPI PKSPIN NTAPI KsFilterGetFirstChildPin(PKSFILTER Filter, ULONG PinId); -KSDDKAPI PVOID NTAPI KsGetNextSibling(PVOID Object); -KSDDKAPI PKSPIN NTAPI KsPinGetNextSiblingPin(PKSPIN Pin); - -PKSFILTERFACTORY __forceinline KsFilterFactoryGetNextSiblingFilterFactory(PKSFILTERFACTORY FilterFactory) -{ - return (PKSFILTERFACTORY)KsGetNextSibling((PVOID)FilterFactory); -} - -PKSFILTER __forceinline KsFilterGetNextSiblingFilter(PKSFILTER Filter) -{ - return (PKSFILTER)KsGetNextSibling((PVOID)Filter); -} - -KSDDKAPI PKSDEVICE NTAPI KsGetDevice(PVOID Object); - -PKSDEVICE __forceinline KsFilterFactoryGetDevice(PKSFILTERFACTORY FilterFactory) -{ - return KsGetDevice((PVOID)FilterFactory); -} - -PKSDEVICE __forceinline KsFilterGetDevice(PKSFILTER Filter) -{ - return KsGetDevice((PVOID)Filter); -} - -PKSDEVICE __forceinline KsPinGetDevice(PKSPIN Pin) -{ - return KsGetDevice((PVOID)Pin); -} - -KSDDKAPI PKSFILTER NTAPI KsGetFilterFromIrp(PIRP Irp); -KSDDKAPI PKSPIN NTAPI KsGetPinFromIrp(PIRP Irp); -KSDDKAPI ULONG NTAPI KsGetNodeIdFromIrp(PIRP Irp); -KSDDKAPI void NTAPI KsAcquireControl(PVOID Object); -KSDDKAPI void NTAPI KsReleaseControl(PVOID Object); - -void __forceinline KsFilterAcquireControl(PKSFILTER Filter) -{ - KsAcquireControl((PVOID)Filter); -} - -void __forceinline KsFilterReleaseControl(PKSFILTER Filter) -{ - KsReleaseControl((PVOID)Filter); -} - -void __forceinline KsPinAcquireControl(PKSPIN Pin) -{ - KsAcquireControl((PVOID)Pin); -} - -void __forceinline KsPinReleaseControl(PKSPIN Pin) -{ - KsReleaseControl((PVOID)Pin); -} - -KSDDKAPI NTSTATUS NTAPI KsAddItemToObjectBag(KSOBJECT_BAG ObjectBag, PVOID Item, PFNKSFREE Free); - -KSDDKAPI ULONG NTAPI KsRemoveItemFromObjectBag(KSOBJECT_BAG ObjectBag, PVOID Item, BOOLEAN Free); - - # define KsDiscard(Object, Pointer) \ - KsRemoveItemFromObjectBag((Object)->Bag, (PVOID)(Pointer), TRUE) - -KSDDKAPI NTSTATUS NTAPI KsAllocateObjectBag(PKSDEVICE Device, KSOBJECT_BAG* ObjectBag); -KSDDKAPI void NTAPI KsFreeObjectBag(KSOBJECT_BAG ObjectBag); - -KSDDKAPI NTSTATUS NTAPI KsCopyObjectBagItems(KSOBJECT_BAG ObjectBagDestination, KSOBJECT_BAG ObjectBagSource); - -KSDDKAPI NTSTATUS NTAPI _KsEdit(KSOBJECT_BAG ObjectBag, PVOID* PointerToPointerToItem, ULONG NewSize, ULONG OldSize, ULONG Tag); - - # define KsEdit(Object, PointerToPointer, Tag) \ - _KsEdit((Object)->Bag, (PVOID*)(PointerToPointer), \ - sizeof(**(PointerToPointer)), sizeof(**(PointerToPointer)), (Tag)) - - # define KsEditSized(Object, PointerToPointer, NewSize, OldSize, Tag) \ - _KsEdit((Object)->Bag, (PVOID*)(PointerToPointer), (NewSize), (OldSize), (Tag)) - -KSDDKAPI NTSTATUS NTAPI KsRegisterFilterWithNoKSPins(PDEVICE_OBJECT DeviceObject, const GUID* InterfaceClassGUID, ULONG PinCount, WINBOOL* PinDirection, KSPIN_MEDIUM* MediumList, GUID* CategoryList); - -KSDDKAPI NTSTATUS NTAPI KsFilterCreatePinFactory(PKSFILTER Filter, const KSPIN_DESCRIPTOR_EX* const PinDescriptor, PULONG PinID); - -KSDDKAPI NTSTATUS NTAPI KsFilterCreateNode(PKSFILTER Filter, const KSNODE_DESCRIPTOR* const NodeDescriptor, PULONG NodeID); - -KSDDKAPI NTSTATUS NTAPI KsFilterAddTopologyConnections(PKSFILTER Filter, ULONG NewConnectionsCount, const KSTOPOLOGY_CONNECTION* const NewTopologyConnections); - -KSDDKAPI NTSTATUS NTAPI KsPinGetConnectedPinInterface(PKSPIN Pin, const GUID* InterfaceId, PVOID* Interface); - -KSDDKAPI PFILE_OBJECT NTAPI KsPinGetConnectedPinFileObject(PKSPIN Pin); -KSDDKAPI PDEVICE_OBJECT NTAPI KsPinGetConnectedPinDeviceObject(PKSPIN Pin); - -KSDDKAPI NTSTATUS NTAPI KsPinGetConnectedFilterInterface(PKSPIN Pin, const GUID* InterfaceId, PVOID* Interface); - - # if defined(_UNKNOWN_H_) || defined(__IUnknown_INTERFACE_DEFINED__) -KSDDKAPI NTSTATUS NTAPI KsPinGetReferenceClockInterface(PKSPIN Pin, PIKSREFERENCECLOCK* Interface); - # endif /* defined(_UNKNOWN_H_) || defined(__IUnknown_INTERFACE_DEFINED__) */ - -KSDDKAPI VOID NTAPI KsPinSetPinClockTime(PKSPIN Pin, LONGLONG Time); - -KSDDKAPI NTSTATUS NTAPI KsPinSubmitFrame(PKSPIN Pin, PVOID Data, ULONG Size, PKSSTREAM_HEADER StreamHeader, PVOID Context); - -KSDDKAPI NTSTATUS NTAPI KsPinSubmitFrameMdl(PKSPIN Pin, PMDL Mdl, PKSSTREAM_HEADER StreamHeader, PVOID Context); - -KSDDKAPI void NTAPI KsPinRegisterFrameReturnCallback(PKSPIN Pin, PFNKSPINFRAMERETURN FrameReturn); - -KSDDKAPI void NTAPI KsPinRegisterIrpCompletionCallback(PKSPIN Pin, PFNKSPINIRPCOMPLETION IrpCompletion); - -KSDDKAPI void NTAPI KsPinRegisterHandshakeCallback(PKSPIN Pin, PFNKSPINHANDSHAKE Handshake); - -KSDDKAPI void NTAPI KsFilterRegisterPowerCallbacks(PKSFILTER Filter, PFNKSFILTERPOWER Sleep, PFNKSFILTERPOWER Wake); - -KSDDKAPI void NTAPI KsPinRegisterPowerCallbacks(PKSPIN Pin, PFNKSPINPOWER Sleep, PFNKSPINPOWER Wake); - - # if defined(_UNKNOWN_H_) || defined(__IUnknown_INTERFACE_DEFINED__) -KSDDKAPI PUNKNOWN NTAPI KsRegisterAggregatedClientUnknown(PVOID Object, PUNKNOWN ClientUnknown); - -KSDDKAPI PUNKNOWN NTAPI KsGetOuterUnknown(PVOID Object); - -PUNKNOWN __forceinline KsDeviceRegisterAggregatedClientUnknown(PKSDEVICE Device, PUNKNOWN ClientUnknown) -{ - return KsRegisterAggregatedClientUnknown((PVOID)Device, ClientUnknown); -} - -PUNKNOWN __forceinline KsDeviceGetOuterUnknown(PKSDEVICE Device) -{ - return KsGetOuterUnknown((PVOID)Device); -} - -PUNKNOWN __forceinline KsFilterFactoryRegisterAggregatedClientUnknown(PKSFILTERFACTORY FilterFactory, PUNKNOWN ClientUnknown) -{ - return KsRegisterAggregatedClientUnknown((PVOID)FilterFactory, ClientUnknown); -} - -PUNKNOWN __forceinline KsFilterFactoryGetOuterUnknown(PKSFILTERFACTORY FilterFactory) -{ - return KsGetOuterUnknown((PVOID)FilterFactory); -} - -PUNKNOWN __forceinline KsFilterRegisterAggregatedClientUnknown(PKSFILTER Filter, PUNKNOWN ClientUnknown) -{ - return KsRegisterAggregatedClientUnknown((PVOID)Filter, ClientUnknown); -} - -PUNKNOWN __forceinline KsFilterGetOuterUnknown(PKSFILTER Filter) -{ - return KsGetOuterUnknown((PVOID)Filter); -} - -PUNKNOWN __forceinline KsPinRegisterAggregatedClientUnknown(PKSPIN Pin, PUNKNOWN ClientUnknown) -{ - return KsRegisterAggregatedClientUnknown((PVOID)Pin, ClientUnknown); -} - -PUNKNOWN __forceinline KsPinGetOuterUnknown(PKSPIN Pin) -{ - return KsGetOuterUnknown((PVOID)Pin); -} - - # endif /* defined(_UNKNOWN_H_) || defined(__IUnknown_INTERFACE_DEFINED__) */ - -#else /* _NTDDK_ */ - - # ifndef KS_NO_CREATE_FUNCTIONS -KSDDKAPI DWORD WINAPI KsCreateAllocator(HANDLE ConnectionHandle, PKSALLOCATOR_FRAMING AllocatorFraming, PHANDLE AllocatorHandle); -KSDDKAPI DWORD NTAPI KsCreateClock(HANDLE ConnectionHandle, PKSCLOCK_CREATE ClockCreate, PHANDLE ClockHandle); -KSDDKAPI DWORD WINAPI KsCreatePin(HANDLE FilterHandle, PKSPIN_CONNECT Connect, ACCESS_MASK DesiredAccess, PHANDLE ConnectionHandle); -KSDDKAPI DWORD WINAPI KsCreateTopologyNode(HANDLE ParentHandle, PKSNODE_CREATE NodeCreate, ACCESS_MASK DesiredAccess, PHANDLE NodeHandle); - # endif - -#endif /* _NTDDK_ */ - -#ifdef __cplusplus -} -#endif - -#define DENY_USERMODE_ACCESS(pIrp, CompleteRequest) \ - if(pIrp->RequestorMode != KernelMode){ \ - pIrp->IoStatus.Information = 0; \ - pIrp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; \ - if(CompleteRequest){ \ - IoCompleteRequest(pIrp, IO_NO_INCREMENT); } \ - return STATUS_INVALID_DEVICE_REQUEST; \ - } - -#endif /* _KS_ */ - diff --git a/include/ksmedia.h b/include/ksmedia.h deleted file mode 100644 index a01823b9..00000000 --- a/include/ksmedia.h +++ /dev/null @@ -1,4824 +0,0 @@ -/** - * This file has no copyright assigned and is placed in the Public Domain. - * This file is part of the w64 mingw-runtime package. - */ -#if !defined(_KS_) - # warning ks.h must be included before ksmedia.h - # include "ks.h" -#endif - -#if __GNUC__ >= 3 - # pragma GCC system_header -#endif - -#if !defined(_KSMEDIA_) - # define _KSMEDIA_ - -typedef struct -{ - KSPROPERTY Property; - KSMULTIPLE_ITEM MultipleItem; -}KSMULTIPLE_DATA_PROP, * PKSMULTIPLE_DATA_PROP; - - # define STATIC_KSMEDIUMSETID_MidiBus \ - 0x05908040L, 0x3246, 0x11D0, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 -DEFINE_GUIDSTRUCT("05908040-3246-11D0-A5D6-28DB04C10000", KSMEDIUMSETID_MidiBus); - # define KSMEDIUMSETID_MidiBus DEFINE_GUIDNAMED(KSMEDIUMSETID_MidiBus) - - # define STATIC_KSMEDIUMSETID_VPBus \ - 0xA18C15ECL, 0xCE43, 0x11D0, 0xAB, 0xE7, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 -DEFINE_GUIDSTRUCT("A18C15EC-CE43-11D0-ABE7-00A0C9223196", KSMEDIUMSETID_VPBus); - # define KSMEDIUMSETID_VPBus DEFINE_GUIDNAMED(KSMEDIUMSETID_VPBus) - - # define STATIC_KSINTERFACESETID_Media \ - 0x3A13EB40L, 0x30A7, 0x11D0, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 -DEFINE_GUIDSTRUCT("3A13EB40-30A7-11D0-A5D6-28DB04C10000", KSINTERFACESETID_Media); - # define KSINTERFACESETID_Media DEFINE_GUIDNAMED(KSINTERFACESETID_Media) - -typedef enum -{ - KSINTERFACE_MEDIA_MUSIC, - KSINTERFACE_MEDIA_WAVE_BUFFERED, - KSINTERFACE_MEDIA_WAVE_QUEUED -}KSINTERFACE_MEDIA; - - # ifndef INIT_USBAUDIO_MID - # define INIT_USBAUDIO_MID(guid, id) \ - { \ - (guid)->Data1 = 0x4e1cecd2 + (USHORT)(id); \ - (guid)->Data2 = 0x1679; \ - (guid)->Data3 = 0x463b; \ - (guid)->Data4[0] = 0xa7; \ - (guid)->Data4[1] = 0x2f; \ - (guid)->Data4[2] = 0xa5; \ - (guid)->Data4[3] = 0xbf; \ - (guid)->Data4[4] = 0x64; \ - (guid)->Data4[5] = 0xc8; \ - (guid)->Data4[6] = 0x6e; \ - (guid)->Data4[7] = 0xba; \ - } - # define EXTRACT_USBAUDIO_MID(guid) \ - (USHORT)((guid)->Data1 - 0x4e1cecd2) - # define DEFINE_USBAUDIO_MID_GUID(id) \ - 0x4e1cecd2 + (USHORT)(id), 0x1679, 0x463b, 0xa7, 0x2f, 0xa5, 0xbf, 0x64, 0xc8, 0x6e, 0xba - # define IS_COMPATIBLE_USBAUDIO_MID(guid) \ - (((guid)->Data1 >= 0x4e1cecd2) && \ - ((guid)->Data1 < 0x4e1cecd2 + 0xffff) && \ - ((guid)->Data2 == 0x1679) && \ - ((guid)->Data3 == 0x463b) && \ - ((guid)->Data4[0] == 0xa7) && \ - ((guid)->Data4[1] == 0x2f) && \ - ((guid)->Data4[2] == 0xa5) && \ - ((guid)->Data4[3] == 0xbf) && \ - ((guid)->Data4[4] == 0x64) && \ - ((guid)->Data4[5] == 0xc8) && \ - ((guid)->Data4[6] == 0x6e) && \ - ((guid)->Data4[7] == 0xba)) - # endif /* INIT_USBAUDIO_MID */ - - # ifndef INIT_USBAUDIO_PID - # define INIT_USBAUDIO_PID(guid, id) \ - { \ - (guid)->Data1 = 0xabcc5a5e + (USHORT)(id); \ - (guid)->Data2 = 0xc263; \ - (guid)->Data3 = 0x463b; \ - (guid)->Data4[0] = 0xa7; \ - (guid)->Data4[1] = 0x2f; \ - (guid)->Data4[2] = 0xa5; \ - (guid)->Data4[3] = 0xbf; \ - (guid)->Data4[4] = 0x64; \ - (guid)->Data4[5] = 0xc8; \ - (guid)->Data4[6] = 0x6e; \ - (guid)->Data4[7] = 0xba; \ - } - # define EXTRACT_USBAUDIO_PID(guid) \ - (USHORT)((guid)->Data1 - 0xabcc5a5e) - # define DEFINE_USBAUDIO_PID_GUID(id) \ - 0xabcc5a5e + (USHORT)(id), 0xc263, 0x463b, 0xa7, 0x2f, 0xa5, 0xbf, 0x64, 0xc8, 0x6e, 0xba - # define IS_COMPATIBLE_USBAUDIO_PID(guid) \ - (((guid)->Data1 >= 0xabcc5a5e) && \ - ((guid)->Data1 < 0xabcc5a5e + 0xffff) && \ - ((guid)->Data2 == 0xc263) && \ - ((guid)->Data3 == 0x463b) && \ - ((guid)->Data4[0] == 0xa7) && \ - ((guid)->Data4[1] == 0x2f) && \ - ((guid)->Data4[2] == 0xa5) && \ - ((guid)->Data4[3] == 0xbf) && \ - ((guid)->Data4[4] == 0x64) && \ - ((guid)->Data4[5] == 0xc8) && \ - ((guid)->Data4[6] == 0x6e) && \ - ((guid)->Data4[7] == 0xba)) - # endif /* INIT_USBAUDIO_PID */ - - # ifndef INIT_USBAUDIO_PRODUCT_NAME - # define INIT_USBAUDIO_PRODUCT_NAME(guid, vid, pid, strIndex) \ - { \ - (guid)->Data1 = 0XFC575048 + (USHORT)(vid); \ - (guid)->Data2 = 0x2E08 + (USHORT)(pid); \ - (guid)->Data3 = 0x463B + (USHORT)(strIndex); \ - (guid)->Data4[0] = 0xA7; \ - (guid)->Data4[1] = 0x2F; \ - (guid)->Data4[2] = 0xA5; \ - (guid)->Data4[3] = 0xBF; \ - (guid)->Data4[4] = 0x64; \ - (guid)->Data4[5] = 0xC8; \ - (guid)->Data4[6] = 0x6E; \ - (guid)->Data4[7] = 0xBA; \ - } - # define DEFINE_USBAUDIO_PRODUCT_NAME(vid, pid, strIndex) \ - 0xFC575048 + (USHORT)(vid), 0x2E08 + (USHORT)(pid), 0x463B + (USHORT)(strIndex), 0xA7, 0x2F, 0xA5, 0xBF, 0x64, 0xC8, 0x6E, 0xBA - # endif /* INIT_USBAUDIO_PRODUCT_NAME */ - - # define STATIC_KSCOMPONENTID_USBAUDIO \ - 0x8F1275F0, 0x26E9, 0x4264, 0xBA, 0x4D, 0x39, 0xFF, 0xF0, 0x1D, 0x94, 0xAA -DEFINE_GUIDSTRUCT("8F1275F0-26E9-4264-BA4D-39FFF01D94AA", KSCOMPONENTID_USBAUDIO); - # define KSCOMPONENTID_USBAUDIO DEFINE_GUIDNAMED(KSCOMPONENTID_USBAUDIO) - - # define INIT_USB_TERMINAL(guid, id) \ - { \ - (guid)->Data1 = 0xDFF219E0 + (USHORT)(id); \ - (guid)->Data2 = 0xF70F; \ - (guid)->Data3 = 0x11D0; \ - (guid)->Data4[0] = 0xb9; \ - (guid)->Data4[1] = 0x17; \ - (guid)->Data4[2] = 0x00; \ - (guid)->Data4[3] = 0xa0; \ - (guid)->Data4[4] = 0xc9; \ - (guid)->Data4[5] = 0x22; \ - (guid)->Data4[6] = 0x31; \ - (guid)->Data4[7] = 0x96; \ - } - # define EXTRACT_USB_TERMINAL(guid) \ - (USHORT)((guid)->Data1 - 0xDFF219E0) - # define DEFINE_USB_TERMINAL_GUID(id) \ - 0xDFF219E0 + (USHORT)(id), 0xF70F, 0x11D0, 0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 - - # define STATIC_KSNODETYPE_MICROPHONE \ - DEFINE_USB_TERMINAL_GUID(0x0201) -DEFINE_GUIDSTRUCT("DFF21BE1-F70F-11D0-B917-00A0C9223196", KSNODETYPE_MICROPHONE); - # define KSNODETYPE_MICROPHONE DEFINE_GUIDNAMED(KSNODETYPE_MICROPHONE) - - # define STATIC_KSNODETYPE_DESKTOP_MICROPHONE \ - DEFINE_USB_TERMINAL_GUID(0x0202) -DEFINE_GUIDSTRUCT("DFF21BE2-F70F-11D0-B917-00A0C9223196", KSNODETYPE_DESKTOP_MICROPHONE); - # define KSNODETYPE_DESKTOP_MICROPHONE DEFINE_GUIDNAMED(KSNODETYPE_DESKTOP_MICROPHONE) - - # define STATIC_KSNODETYPE_PERSONAL_MICROPHONE \ - DEFINE_USB_TERMINAL_GUID(0x0203) -DEFINE_GUIDSTRUCT("DFF21BE3-F70F-11D0-B917-00A0C9223196", KSNODETYPE_PERSONAL_MICROPHONE); - # define KSNODETYPE_PERSONAL_MICROPHONE DEFINE_GUIDNAMED(KSNODETYPE_PERSONAL_MICROPHONE) - - # define STATIC_KSNODETYPE_OMNI_DIRECTIONAL_MICROPHONE \ - DEFINE_USB_TERMINAL_GUID(0x0204) -DEFINE_GUIDSTRUCT("DFF21BE4-F70F-11D0-B917-00A0C9223196", KSNODETYPE_OMNI_DIRECTIONAL_MICROPHONE); - # define KSNODETYPE_OMNI_DIRECTIONAL_MICROPHONE DEFINE_GUIDNAMED(KSNODETYPE_OMNI_DIRECTIONAL_MICROPHONE) - - # define STATIC_KSNODETYPE_MICROPHONE_ARRAY \ - DEFINE_USB_TERMINAL_GUID(0x0205) -DEFINE_GUIDSTRUCT("DFF21BE5-F70F-11D0-B917-00A0C9223196", KSNODETYPE_MICROPHONE_ARRAY); - # define KSNODETYPE_MICROPHONE_ARRAY DEFINE_GUIDNAMED(KSNODETYPE_MICROPHONE_ARRAY) - - # define STATIC_KSNODETYPE_PROCESSING_MICROPHONE_ARRAY \ - DEFINE_USB_TERMINAL_GUID(0x0206) -DEFINE_GUIDSTRUCT("DFF21BE6-F70F-11D0-B917-00A0C9223196", KSNODETYPE_PROCESSING_MICROPHONE_ARRAY); - # define KSNODETYPE_PROCESSING_MICROPHONE_ARRAY DEFINE_GUIDNAMED(KSNODETYPE_PROCESSING_MICROPHONE_ARRAY) - - # define STATIC_KSCATEGORY_MICROPHONE_ARRAY_PROCESSOR \ - 0x830a44f2, 0xa32d, 0x476b, 0xbe, 0x97, 0x42, 0x84, 0x56, 0x73, 0xb3, 0x5a -DEFINE_GUIDSTRUCT("830a44f2-a32d-476b-be97-42845673b35a", KSCATEGORY_MICROPHONE_ARRAY_PROCESSOR); - # define KSCATEGORY_MICROPHONE_ARRAY_PROCESSOR DEFINE_GUIDNAMED(KSCATEGORY_MICROPHONE_ARRAY_PROCESSOR) - - # define STATIC_KSNODETYPE_SPEAKER \ - DEFINE_USB_TERMINAL_GUID(0x0301) -DEFINE_GUIDSTRUCT("DFF21CE1-F70F-11D0-B917-00A0C9223196", KSNODETYPE_SPEAKER); - # define KSNODETYPE_SPEAKER DEFINE_GUIDNAMED(KSNODETYPE_SPEAKER) - - # define STATIC_KSNODETYPE_HEADPHONES \ - DEFINE_USB_TERMINAL_GUID(0x0302) -DEFINE_GUIDSTRUCT("DFF21CE2-F70F-11D0-B917-00A0C9223196", KSNODETYPE_HEADPHONES); - # define KSNODETYPE_HEADPHONES DEFINE_GUIDNAMED(KSNODETYPE_HEADPHONES) - - # define STATIC_KSNODETYPE_HEAD_MOUNTED_DISPLAY_AUDIO \ - DEFINE_USB_TERMINAL_GUID(0x0303) -DEFINE_GUIDSTRUCT("DFF21CE3-F70F-11D0-B917-00A0C9223196", KSNODETYPE_HEAD_MOUNTED_DISPLAY_AUDIO); - # define KSNODETYPE_HEAD_MOUNTED_DISPLAY_AUDIO DEFINE_GUIDNAMED(KSNODETYPE_HEAD_MOUNTED_DISPLAY_AUDIO) - - # define STATIC_KSNODETYPE_DESKTOP_SPEAKER \ - DEFINE_USB_TERMINAL_GUID(0x0304) -DEFINE_GUIDSTRUCT("DFF21CE4-F70F-11D0-B917-00A0C9223196", KSNODETYPE_DESKTOP_SPEAKER); - # define KSNODETYPE_DESKTOP_SPEAKER DEFINE_GUIDNAMED(KSNODETYPE_DESKTOP_SPEAKER) - - # define STATIC_KSNODETYPE_ROOM_SPEAKER \ - DEFINE_USB_TERMINAL_GUID(0x0305) -DEFINE_GUIDSTRUCT("DFF21CE5-F70F-11D0-B917-00A0C9223196", KSNODETYPE_ROOM_SPEAKER); - # define KSNODETYPE_ROOM_SPEAKER DEFINE_GUIDNAMED(KSNODETYPE_ROOM_SPEAKER) - - # define STATIC_KSNODETYPE_COMMUNICATION_SPEAKER \ - DEFINE_USB_TERMINAL_GUID(0x0306) -DEFINE_GUIDSTRUCT("DFF21CE6-F70F-11D0-B917-00A0C9223196", KSNODETYPE_COMMUNICATION_SPEAKER); - # define KSNODETYPE_COMMUNICATION_SPEAKER DEFINE_GUIDNAMED(KSNODETYPE_COMMUNICATION_SPEAKER) - - # define STATIC_KSNODETYPE_LOW_FREQUENCY_EFFECTS_SPEAKER \ - DEFINE_USB_TERMINAL_GUID(0x0307) -DEFINE_GUIDSTRUCT("DFF21CE7-F70F-11D0-B917-00A0C9223196", KSNODETYPE_LOW_FREQUENCY_EFFECTS_SPEAKER); - # define KSNODETYPE_LOW_FREQUENCY_EFFECTS_SPEAKER DEFINE_GUIDNAMED(KSNODETYPE_LOW_FREQUENCY_EFFECTS_SPEAKER) - - # define STATIC_KSNODETYPE_HANDSET \ - DEFINE_USB_TERMINAL_GUID(0x0401) -DEFINE_GUIDSTRUCT("DFF21DE1-F70F-11D0-B917-00A0C9223196", KSNODETYPE_HANDSET); - # define KSNODETYPE_HANDSET DEFINE_GUIDNAMED(KSNODETYPE_HANDSET) - - # define STATIC_KSNODETYPE_HEADSET \ - DEFINE_USB_TERMINAL_GUID(0x0402) -DEFINE_GUIDSTRUCT("DFF21DE2-F70F-11D0-B917-00A0C9223196", KSNODETYPE_HEADSET); - # define KSNODETYPE_HEADSET DEFINE_GUIDNAMED(KSNODETYPE_HEADSET) - - # define STATIC_KSNODETYPE_SPEAKERPHONE_NO_ECHO_REDUCTION \ - DEFINE_USB_TERMINAL_GUID(0x0403) -DEFINE_GUIDSTRUCT("DFF21DE3-F70F-11D0-B917-00A0C9223196", KSNODETYPE_SPEAKERPHONE_NO_ECHO_REDUCTION); - # define KSNODETYPE_SPEAKERPHONE_NO_ECHO_REDUCTION DEFINE_GUIDNAMED(KSNODETYPE_SPEAKERPHONE_NO_ECHO_REDUCTION) - - # define STATIC_KSNODETYPE_ECHO_SUPPRESSING_SPEAKERPHONE \ - DEFINE_USB_TERMINAL_GUID(0x0404) -DEFINE_GUIDSTRUCT("DFF21DE4-F70F-11D0-B917-00A0C9223196", KSNODETYPE_ECHO_SUPPRESSING_SPEAKERPHONE); - # define KSNODETYPE_ECHO_SUPPRESSING_SPEAKERPHONE DEFINE_GUIDNAMED(KSNODETYPE_ECHO_SUPPRESSING_SPEAKERPHONE) - - # define STATIC_KSNODETYPE_ECHO_CANCELING_SPEAKERPHONE \ - DEFINE_USB_TERMINAL_GUID(0x0405) -DEFINE_GUIDSTRUCT("DFF21DE5-F70F-11D0-B917-00A0C9223196", KSNODETYPE_ECHO_CANCELING_SPEAKERPHONE); - # define KSNODETYPE_ECHO_CANCELING_SPEAKERPHONE DEFINE_GUIDNAMED(KSNODETYPE_ECHO_CANCELING_SPEAKERPHONE) - - # define STATIC_KSNODETYPE_PHONE_LINE \ - DEFINE_USB_TERMINAL_GUID(0x0501) -DEFINE_GUIDSTRUCT("DFF21EE1-F70F-11D0-B917-00A0C9223196", KSNODETYPE_PHONE_LINE); - # define KSNODETYPE_PHONE_LINE DEFINE_GUIDNAMED(KSNODETYPE_PHONE_LINE) - - # define STATIC_KSNODETYPE_TELEPHONE \ - DEFINE_USB_TERMINAL_GUID(0x0502) -DEFINE_GUIDSTRUCT("DFF21EE2-F70F-11D0-B917-00A0C9223196", KSNODETYPE_TELEPHONE); - # define KSNODETYPE_TELEPHONE DEFINE_GUIDNAMED(KSNODETYPE_TELEPHONE) - - # define STATIC_KSNODETYPE_DOWN_LINE_PHONE \ - DEFINE_USB_TERMINAL_GUID(0x0503) -DEFINE_GUIDSTRUCT("DFF21EE3-F70F-11D0-B917-00A0C9223196", KSNODETYPE_DOWN_LINE_PHONE); - # define KSNODETYPE_DOWN_LINE_PHONE DEFINE_GUIDNAMED(KSNODETYPE_DOWN_LINE_PHONE) - - # define STATIC_KSNODETYPE_ANALOG_CONNECTOR \ - DEFINE_USB_TERMINAL_GUID(0x601) -DEFINE_GUIDSTRUCT("DFF21FE1-F70F-11D0-B917-00A0C9223196", KSNODETYPE_ANALOG_CONNECTOR); - # define KSNODETYPE_ANALOG_CONNECTOR DEFINE_GUIDNAMED(KSNODETYPE_ANALOG_CONNECTOR) - - # define STATIC_KSNODETYPE_DIGITAL_AUDIO_INTERFACE \ - DEFINE_USB_TERMINAL_GUID(0x0602) -DEFINE_GUIDSTRUCT("DFF21FE2-F70F-11D0-B917-00A0C9223196", KSNODETYPE_DIGITAL_AUDIO_INTERFACE); - # define KSNODETYPE_DIGITAL_AUDIO_INTERFACE DEFINE_GUIDNAMED(KSNODETYPE_DIGITAL_AUDIO_INTERFACE) - - # define STATIC_KSNODETYPE_LINE_CONNECTOR \ - DEFINE_USB_TERMINAL_GUID(0x0603) -DEFINE_GUIDSTRUCT("DFF21FE3-F70F-11D0-B917-00A0C9223196", KSNODETYPE_LINE_CONNECTOR); - # define KSNODETYPE_LINE_CONNECTOR DEFINE_GUIDNAMED(KSNODETYPE_LINE_CONNECTOR) - - # define STATIC_KSNODETYPE_LEGACY_AUDIO_CONNECTOR \ - DEFINE_USB_TERMINAL_GUID(0x0604) -DEFINE_GUIDSTRUCT("DFF21FE4-F70F-11D0-B917-00A0C9223196", KSNODETYPE_LEGACY_AUDIO_CONNECTOR); - # define KSNODETYPE_LEGACY_AUDIO_CONNECTOR DEFINE_GUIDNAMED(KSNODETYPE_LEGACY_AUDIO_CONNECTOR) - - # define STATIC_KSNODETYPE_SPDIF_INTERFACE \ - DEFINE_USB_TERMINAL_GUID(0x0605) -DEFINE_GUIDSTRUCT("DFF21FE5-F70F-11D0-B917-00A0C9223196", KSNODETYPE_SPDIF_INTERFACE); - # define KSNODETYPE_SPDIF_INTERFACE DEFINE_GUIDNAMED(KSNODETYPE_SPDIF_INTERFACE) - - # define STATIC_KSNODETYPE_1394_DA_STREAM \ - DEFINE_USB_TERMINAL_GUID(0x0606) -DEFINE_GUIDSTRUCT("DFF21FE6-F70F-11D0-B917-00A0C9223196", KSNODETYPE_1394_DA_STREAM); - # define KSNODETYPE_1394_DA_STREAM DEFINE_GUIDNAMED(KSNODETYPE_1394_DA_STREAM) - - # define STATIC_KSNODETYPE_1394_DV_STREAM_SOUNDTRACK \ - DEFINE_USB_TERMINAL_GUID(0x0607) -DEFINE_GUIDSTRUCT("DFF21FE7-F70F-11D0-B917-00A0C9223196", KSNODETYPE_1394_DV_STREAM_SOUNDTRACK); - # define KSNODETYPE_1394_DV_STREAM_SOUNDTRACK DEFINE_GUIDNAMED(KSNODETYPE_1394_DV_STREAM_SOUNDTRACK) - - # define STATIC_KSNODETYPE_LEVEL_CALIBRATION_NOISE_SOURCE \ - DEFINE_USB_TERMINAL_GUID(0x0701) -DEFINE_GUIDSTRUCT("DFF220E1-F70F-11D0-B917-00A0C9223196", KSNODETYPE_LEVEL_CALIBRATION_NOISE_SOURCE); - # define KSNODETYPE_LEVEL_CALIBRATION_NOISE_SOURCE DEFINE_GUIDNAMED(KSNODETYPE_LEVEL_CALIBRATION_NOISE_SOURCE) - - # define STATIC_KSNODETYPE_EQUALIZATION_NOISE \ - DEFINE_USB_TERMINAL_GUID(0x0702) -DEFINE_GUIDSTRUCT("DFF220E2-F70F-11D0-B917-00A0C9223196", KSNODETYPE_EQUALIZATION_NOISE); - # define KSNODETYPE_EQUALIZATION_NOISE DEFINE_GUIDNAMED(KSNODETYPE_EQUALIZATION_NOISE) - - # define STATIC_KSNODETYPE_CD_PLAYER \ - DEFINE_USB_TERMINAL_GUID(0x0703) -DEFINE_GUIDSTRUCT("DFF220E3-F70F-11D0-B917-00A0C9223196", KSNODETYPE_CD_PLAYER); - # define KSNODETYPE_CD_PLAYER DEFINE_GUIDNAMED(KSNODETYPE_CD_PLAYER) - - # define STATIC_KSNODETYPE_DAT_IO_DIGITAL_AUDIO_TAPE \ - DEFINE_USB_TERMINAL_GUID(0x0704) -DEFINE_GUIDSTRUCT("DFF220E4-F70F-11D0-B917-00A0C9223196", KSNODETYPE_DAT_IO_DIGITAL_AUDIO_TAPE); - # define KSNODETYPE_DAT_IO_DIGITAL_AUDIO_TAPE DEFINE_GUIDNAMED(KSNODETYPE_DAT_IO_DIGITAL_AUDIO_TAPE) - - # define STATIC_KSNODETYPE_DCC_IO_DIGITAL_COMPACT_CASSETTE \ - DEFINE_USB_TERMINAL_GUID(0x0705) -DEFINE_GUIDSTRUCT("DFF220E5-F70F-11D0-B917-00A0C9223196", KSNODETYPE_DCC_IO_DIGITAL_COMPACT_CASSETTE); - # define KSNODETYPE_DCC_IO_DIGITAL_COMPACT_CASSETTE DEFINE_GUIDNAMED(KSNODETYPE_DCC_IO_DIGITAL_COMPACT_CASSETTE) - - # define STATIC_KSNODETYPE_MINIDISK \ - DEFINE_USB_TERMINAL_GUID(0x0706) -DEFINE_GUIDSTRUCT("DFF220E6-F70F-11D0-B917-00A0C9223196", KSNODETYPE_MINIDISK); - # define KSNODETYPE_MINIDISK DEFINE_GUIDNAMED(KSNODETYPE_MINIDISK) - - # define STATIC_KSNODETYPE_ANALOG_TAPE \ - DEFINE_USB_TERMINAL_GUID(0x0707) -DEFINE_GUIDSTRUCT("DFF220E7-F70F-11D0-B917-00A0C9223196", KSNODETYPE_ANALOG_TAPE); - # define KSNODETYPE_ANALOG_TAPE DEFINE_GUIDNAMED(KSNODETYPE_ANALOG_TAPE) - - # define STATIC_KSNODETYPE_PHONOGRAPH \ - DEFINE_USB_TERMINAL_GUID(0x0708) -DEFINE_GUIDSTRUCT("DFF220E8-F70F-11D0-B917-00A0C9223196", KSNODETYPE_PHONOGRAPH); - # define KSNODETYPE_PHONOGRAPH DEFINE_GUIDNAMED(KSNODETYPE_PHONOGRAPH) - - # define STATIC_KSNODETYPE_VCR_AUDIO \ - DEFINE_USB_TERMINAL_GUID(0x0708) -DEFINE_GUIDSTRUCT("DFF220E9-F70F-11D0-B917-00A0C9223196", KSNODETYPE_VCR_AUDIO); - # define KSNODETYPE_VCR_AUDIO DEFINE_GUIDNAMED(KSNODETYPE_VCR_AUDIO) - - # define STATIC_KSNODETYPE_VIDEO_DISC_AUDIO \ - DEFINE_USB_TERMINAL_GUID(0x070A) -DEFINE_GUIDSTRUCT("DFF220EA-F70F-11D0-B917-00A0C9223196", KSNODETYPE_VIDEO_DISC_AUDIO); - # define KSNODETYPE_VIDEO_DISC_AUDIO DEFINE_GUIDNAMED(KSNODETYPE_VIDEO_DISC_AUDIO) - - # define STATIC_KSNODETYPE_DVD_AUDIO \ - DEFINE_USB_TERMINAL_GUID(0x070B) -DEFINE_GUIDSTRUCT("DFF220EB-F70F-11D0-B917-00A0C9223196", KSNODETYPE_DVD_AUDIO); - # define KSNODETYPE_DVD_AUDIO DEFINE_GUIDNAMED(KSNODETYPE_DVD_AUDIO) - - # define STATIC_KSNODETYPE_TV_TUNER_AUDIO \ - DEFINE_USB_TERMINAL_GUID(0x070C) -DEFINE_GUIDSTRUCT("DFF220EC-F70F-11D0-B917-00A0C9223196", KSNODETYPE_TV_TUNER_AUDIO); - # define KSNODETYPE_TV_TUNER_AUDIO DEFINE_GUIDNAMED(KSNODETYPE_TV_TUNER_AUDIO) - - # define STATIC_KSNODETYPE_SATELLITE_RECEIVER_AUDIO \ - DEFINE_USB_TERMINAL_GUID(0x070D) -DEFINE_GUIDSTRUCT("DFF220ED-F70F-11D0-B917-00A0C9223196", KSNODETYPE_SATELLITE_RECEIVER_AUDIO); - # define KSNODETYPE_SATELLITE_RECEIVER_AUDIO DEFINE_GUIDNAMED(KSNODETYPE_SATELLITE_RECEIVER_AUDIO) - - # define STATIC_KSNODETYPE_CABLE_TUNER_AUDIO \ - DEFINE_USB_TERMINAL_GUID(0x070E) -DEFINE_GUIDSTRUCT("DFF220EE-F70F-11D0-B917-00A0C9223196", KSNODETYPE_CABLE_TUNER_AUDIO); - # define KSNODETYPE_CABLE_TUNER_AUDIO DEFINE_GUIDNAMED(KSNODETYPE_CABLE_TUNER_AUDIO) - - # define STATIC_KSNODETYPE_DSS_AUDIO \ - DEFINE_USB_TERMINAL_GUID(0x070F) -DEFINE_GUIDSTRUCT("DFF220EF-F70F-11D0-B917-00A0C9223196", KSNODETYPE_DSS_AUDIO); - # define KSNODETYPE_DSS_AUDIO DEFINE_GUIDNAMED(KSNODETYPE_DSS_AUDIO) - - # define STATIC_KSNODETYPE_RADIO_RECEIVER \ - DEFINE_USB_TERMINAL_GUID(0x0710) -DEFINE_GUIDSTRUCT("DFF220F0-F70F-11D0-B917-00A0C9223196", KSNODETYPE_RADIO_RECEIVER); - # define KSNODETYPE_RADIO_RECEIVER DEFINE_GUIDNAMED(KSNODETYPE_RADIO_RECEIVER) - - # define STATIC_KSNODETYPE_RADIO_TRANSMITTER \ - DEFINE_USB_TERMINAL_GUID(0x0711) -DEFINE_GUIDSTRUCT("DFF220F1-F70F-11D0-B917-00A0C9223196", KSNODETYPE_RADIO_TRANSMITTER); - # define KSNODETYPE_RADIO_TRANSMITTER DEFINE_GUIDNAMED(KSNODETYPE_RADIO_TRANSMITTER) - - # define STATIC_KSNODETYPE_MULTITRACK_RECORDER \ - DEFINE_USB_TERMINAL_GUID(0x0712) -DEFINE_GUIDSTRUCT("DFF220F2-F70F-11D0-B917-00A0C9223196", KSNODETYPE_MULTITRACK_RECORDER); - # define KSNODETYPE_MULTITRACK_RECORDER DEFINE_GUIDNAMED(KSNODETYPE_MULTITRACK_RECORDER) - - # define STATIC_KSNODETYPE_SYNTHESIZER \ - DEFINE_USB_TERMINAL_GUID(0x0713) -DEFINE_GUIDSTRUCT("DFF220F3-F70F-11D0-B917-00A0C9223196", KSNODETYPE_SYNTHESIZER); - # define KSNODETYPE_SYNTHESIZER DEFINE_GUIDNAMED(KSNODETYPE_SYNTHESIZER) - - # define STATIC_KSNODETYPE_SWSYNTH \ - 0x423274A0L, 0x8B81, 0x11D1, 0xA0, 0x50, 0x00, 0x00, 0xF8, 0x00, 0x47, 0x88 -DEFINE_GUIDSTRUCT("423274A0-8B81-11D1-A050-0000F8004788", KSNODETYPE_SWSYNTH); - # define KSNODETYPE_SWSYNTH DEFINE_GUIDNAMED(KSNODETYPE_SWSYNTH) - - # define STATIC_KSNODETYPE_SWMIDI \ - 0xCB9BEFA0L, 0xA251, 0x11D1, 0xA0, 0x50, 0x00, 0x00, 0xF8, 0x00, 0x47, 0x88 -DEFINE_GUIDSTRUCT("CB9BEFA0-A251-11D1-A050-0000F8004788", KSNODETYPE_SWMIDI); - # define KSNODETYPE_SWMIDI DEFINE_GUIDNAMED(KSNODETYPE_SWMIDI) - - # define STATIC_KSNODETYPE_DRM_DESCRAMBLE \ - 0xFFBB6E3FL, 0xCCFE, 0x4D84, 0x90, 0xD9, 0x42, 0x14, 0x18, 0xB0, 0x3A, 0x8E -DEFINE_GUIDSTRUCT("FFBB6E3F-CCFE-4D84-90D9-421418B03A8E", KSNODETYPE_DRM_DESCRAMBLE); - # define KSNODETYPE_DRM_DESCRAMBLE DEFINE_GUIDNAMED(KSNODETYPE_DRM_DESCRAMBLE) - - # define STATIC_KSCATEGORY_AUDIO \ - 0x6994AD04L, 0x93EF, 0x11D0, { 0xA3, 0xCC, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 } -DEFINE_GUIDSTRUCT("6994AD04-93EF-11D0-A3CC-00A0C9223196", KSCATEGORY_AUDIO); - # define KSCATEGORY_AUDIO DEFINE_GUIDNAMED(KSCATEGORY_AUDIO) - - # define STATIC_KSCATEGORY_VIDEO \ - 0x6994AD05L, 0x93EF, 0x11D0, 0xA3, 0xCC, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 -DEFINE_GUIDSTRUCT("6994AD05-93EF-11D0-A3CC-00A0C9223196", KSCATEGORY_VIDEO); - # define KSCATEGORY_VIDEO DEFINE_GUIDNAMED(KSCATEGORY_VIDEO) - - # define STATIC_KSCATEGORY_TEXT \ - 0x6994AD06L, 0x93EF, 0x11D0, 0xA3, 0xCC, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 -DEFINE_GUIDSTRUCT("6994AD06-93EF-11D0-A3CC-00A0C9223196", KSCATEGORY_TEXT); - # define KSCATEGORY_TEXT DEFINE_GUIDNAMED(KSCATEGORY_TEXT) - - # define STATIC_KSCATEGORY_NETWORK \ - 0x67C9CC3CL, 0x69C4, 0x11D2, 0x87, 0x59, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 -DEFINE_GUIDSTRUCT("67C9CC3C-69C4-11D2-8759-00A0C9223196", KSCATEGORY_NETWORK); - # define KSCATEGORY_NETWORK DEFINE_GUIDNAMED(KSCATEGORY_NETWORK) - - # define STATIC_KSCATEGORY_TOPOLOGY \ - 0xDDA54A40L, 0x1E4C, 0x11D1, 0xA0, 0x50, 0x40, 0x57, 0x05, 0xC1, 0x00, 0x00 -DEFINE_GUIDSTRUCT("DDA54A40-1E4C-11D1-A050-405705C10000", KSCATEGORY_TOPOLOGY); - # define KSCATEGORY_TOPOLOGY DEFINE_GUIDNAMED(KSCATEGORY_TOPOLOGY) - - # define STATIC_KSCATEGORY_VIRTUAL \ - 0x3503EAC4L, 0x1F26, 0x11D1, 0x8A, 0xB0, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 -DEFINE_GUIDSTRUCT("3503EAC4-1F26-11D1-8AB0-00A0C9223196", KSCATEGORY_VIRTUAL); - # define KSCATEGORY_VIRTUAL DEFINE_GUIDNAMED(KSCATEGORY_VIRTUAL) - - # define STATIC_KSCATEGORY_ACOUSTIC_ECHO_CANCEL \ - 0xBF963D80L, 0xC559, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1 -DEFINE_GUIDSTRUCT("BF963D80-C559-11D0-8A2B-00A0C9255AC1", KSCATEGORY_ACOUSTIC_ECHO_CANCEL); - # define KSCATEGORY_ACOUSTIC_ECHO_CANCEL DEFINE_GUIDNAMED(KSCATEGORY_ACOUSTIC_ECHO_CANCEL) - - # define STATIC_KSCATEGORY_SYSAUDIO \ - 0xA7C7A5B1L, 0x5AF3, 0x11D1, 0x9C, 0xED, 0x00, 0xA0, 0x24, 0xBF, 0x04, 0x07 -DEFINE_GUIDSTRUCT("A7C7A5B1-5AF3-11D1-9CED-00A024BF0407", KSCATEGORY_SYSAUDIO); - # define KSCATEGORY_SYSAUDIO DEFINE_GUIDNAMED(KSCATEGORY_SYSAUDIO) - - # define STATIC_KSCATEGORY_WDMAUD \ - 0x3E227E76L, 0x690D, 0x11D2, 0x81, 0x61, 0x00, 0x00, 0xF8, 0x77, 0x5B, 0xF1 -DEFINE_GUIDSTRUCT("3E227E76-690D-11D2-8161-0000F8775BF1", KSCATEGORY_WDMAUD); - # define KSCATEGORY_WDMAUD DEFINE_GUIDNAMED(KSCATEGORY_WDMAUD) - - # define STATIC_KSCATEGORY_AUDIO_GFX \ - 0x9BAF9572L, 0x340C, 0x11D3, 0xAB, 0xDC, 0x00, 0xA0, 0xC9, 0x0A, 0xB1, 0x6F -DEFINE_GUIDSTRUCT("9BAF9572-340C-11D3-ABDC-00A0C90AB16F", KSCATEGORY_AUDIO_GFX); - # define KSCATEGORY_AUDIO_GFX DEFINE_GUIDNAMED(KSCATEGORY_AUDIO_GFX) - - # define STATIC_KSCATEGORY_AUDIO_SPLITTER \ - 0x9EA331FAL, 0xB91B, 0x45F8, 0x92, 0x85, 0xBD, 0x2B, 0xC7, 0x7A, 0xFC, 0xDE -DEFINE_GUIDSTRUCT("9EA331FA-B91B-45F8-9285-BD2BC77AFCDE", KSCATEGORY_AUDIO_SPLITTER); - # define KSCATEGORY_AUDIO_SPLITTER DEFINE_GUIDNAMED(KSCATEGORY_AUDIO_SPLITTER) - - # define STATIC_KSCATEGORY_SYNTHESIZER STATIC_KSNODETYPE_SYNTHESIZER - # define KSCATEGORY_SYNTHESIZER KSNODETYPE_SYNTHESIZER - - # define STATIC_KSCATEGORY_DRM_DESCRAMBLE STATIC_KSNODETYPE_DRM_DESCRAMBLE - # define KSCATEGORY_DRM_DESCRAMBLE KSNODETYPE_DRM_DESCRAMBLE - - # define STATIC_KSCATEGORY_AUDIO_DEVICE \ - 0xFBF6F530L, 0x07B9, 0x11D2, 0xA7, 0x1E, 0x00, 0x00, 0xF8, 0x00, 0x47, 0x88 -DEFINE_GUIDSTRUCT("FBF6F530-07B9-11D2-A71E-0000F8004788", KSCATEGORY_AUDIO_DEVICE); - # define KSCATEGORY_AUDIO_DEVICE DEFINE_GUIDNAMED(KSCATEGORY_AUDIO_DEVICE) - - # define STATIC_KSCATEGORY_PREFERRED_WAVEOUT_DEVICE \ - 0xD6C5066EL, 0x72C1, 0x11D2, 0x97, 0x55, 0x00, 0x00, 0xF8, 0x00, 0x47, 0x88 -DEFINE_GUIDSTRUCT("D6C5066E-72C1-11D2-9755-0000F8004788", KSCATEGORY_PREFERRED_WAVEOUT_DEVICE); - # define KSCATEGORY_PREFERRED_WAVEOUT_DEVICE DEFINE_GUIDNAMED(KSCATEGORY_PREFERRED_WAVEOUT_DEVICE) - - # define STATIC_KSCATEGORY_PREFERRED_WAVEIN_DEVICE \ - 0xD6C50671L, 0x72C1, 0x11D2, 0x97, 0x55, 0x00, 0x00, 0xF8, 0x00, 0x47, 0x88 -DEFINE_GUIDSTRUCT("D6C50671-72C1-11D2-9755-0000F8004788", KSCATEGORY_PREFERRED_WAVEIN_DEVICE); - # define KSCATEGORY_PREFERRED_WAVEIN_DEVICE DEFINE_GUIDNAMED(KSCATEGORY_PREFERRED_WAVEIN_DEVICE) - - # define STATIC_KSCATEGORY_PREFERRED_MIDIOUT_DEVICE \ - 0xD6C50674L, 0x72C1, 0x11D2, 0x97, 0x55, 0x00, 0x00, 0xF8, 0x00, 0x47, 0x88 -DEFINE_GUIDSTRUCT("D6C50674-72C1-11D2-9755-0000F8004788", KSCATEGORY_PREFERRED_MIDIOUT_DEVICE); - # define KSCATEGORY_PREFERRED_MIDIOUT_DEVICE DEFINE_GUIDNAMED(KSCATEGORY_PREFERRED_MIDIOUT_DEVICE) - - # define STATIC_KSCATEGORY_WDMAUD_USE_PIN_NAME \ - 0x47A4FA20L, 0xA251, 0x11D1, 0xA0, 0x50, 0x00, 0x00, 0xF8, 0x00, 0x47, 0x88 -DEFINE_GUIDSTRUCT("47A4FA20-A251-11D1-A050-0000F8004788", KSCATEGORY_WDMAUD_USE_PIN_NAME); - # define KSCATEGORY_WDMAUD_USE_PIN_NAME DEFINE_GUIDNAMED(KSCATEGORY_WDMAUD_USE_PIN_NAME) - - # define STATIC_KSCATEGORY_ESCALANTE_PLATFORM_DRIVER \ - 0x74f3aea8L, 0x9768, 0x11d1, 0x8e, 0x07, 0x00, 0xa0, 0xc9, 0x5e, 0xc2, 0x2e -DEFINE_GUIDSTRUCT("74f3aea8-9768-11d1-8e07-00a0c95ec22e", KSCATEGORY_ESCALANTE_PLATFORM_DRIVER); - # define KSCATEGORY_ESCALANTE_PLATFORM_DRIVER DEFINE_GUIDNAMED(KSCATEGORY_ESCALANTE_PLATFORM_DRIVER) - - # define STATIC_KSDATAFORMAT_TYPE_VIDEO \ - 0x73646976L, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 -DEFINE_GUIDSTRUCT("73646976-0000-0010-8000-00aa00389b71", KSDATAFORMAT_TYPE_VIDEO); - # define KSDATAFORMAT_TYPE_VIDEO DEFINE_GUIDNAMED(KSDATAFORMAT_TYPE_VIDEO) - - # define STATIC_KSDATAFORMAT_TYPE_AUDIO \ - 0x73647561L, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 -DEFINE_GUIDSTRUCT("73647561-0000-0010-8000-00aa00389b71", KSDATAFORMAT_TYPE_AUDIO); - # define KSDATAFORMAT_TYPE_AUDIO DEFINE_GUIDNAMED(KSDATAFORMAT_TYPE_AUDIO) - - # define STATIC_KSDATAFORMAT_TYPE_TEXT \ - 0x73747874L, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 -DEFINE_GUIDSTRUCT("73747874-0000-0010-8000-00aa00389b71", KSDATAFORMAT_TYPE_TEXT); - # define KSDATAFORMAT_TYPE_TEXT DEFINE_GUIDNAMED(KSDATAFORMAT_TYPE_TEXT) - - # if !defined(DEFINE_WAVEFORMATEX_GUID) - # define DEFINE_WAVEFORMATEX_GUID(x) \ - (USHORT)(x), 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 } - # endif - - # define STATIC_KSDATAFORMAT_SUBTYPE_WAVEFORMATEX \ - 0x00000000L, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 -DEFINE_GUIDSTRUCT("00000000-0000-0010-8000-00aa00389b71", KSDATAFORMAT_SUBTYPE_WAVEFORMATEX); - # define KSDATAFORMAT_SUBTYPE_WAVEFORMATEX DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_WAVEFORMATEX) - - # define INIT_WAVEFORMATEX_GUID(Guid, x) \ - { \ - *(Guid) = KSDATAFORMAT_SUBTYPE_WAVEFORMATEX; \ - (Guid)->Data1 = (USHORT)(x); \ - } - - # define EXTRACT_WAVEFORMATEX_ID(Guid) \ - (USHORT)((Guid)->Data1) - - # define IS_VALID_WAVEFORMATEX_GUID(Guid) \ - (!memcmp(((PUSHORT)&KSDATAFORMAT_SUBTYPE_WAVEFORMATEX) + 1, ((PUSHORT)(Guid)) + 1, sizeof(GUID) - sizeof(USHORT))) - - # ifndef INIT_MMREG_MID - # define INIT_MMREG_MID(guid, id) \ - { \ - (guid)->Data1 = 0xd5a47fa7 + (USHORT)(id); \ - (guid)->Data2 = 0x6d98; \ - (guid)->Data3 = 0x11d1; \ - (guid)->Data4[0] = 0xa2; \ - (guid)->Data4[1] = 0x1a; \ - (guid)->Data4[2] = 0x00; \ - (guid)->Data4[3] = 0xa0; \ - (guid)->Data4[4] = 0xc9; \ - (guid)->Data4[5] = 0x22; \ - (guid)->Data4[6] = 0x31; \ - (guid)->Data4[7] = 0x96; \ - } - # define EXTRACT_MMREG_MID(guid) \ - (USHORT)((guid)->Data1 - 0xd5a47fa7) - # define DEFINE_MMREG_MID_GUID(id) \ - 0xd5a47fa7 + (USHORT)(id), 0x6d98, 0x11d1, 0xa2, 0x1a, 0x00, 0xa0, 0xc9, 0x22, 0x31, 0x96 - - # define IS_COMPATIBLE_MMREG_MID(guid) \ - (((guid)->Data1 >= 0xd5a47fa7) && \ - ((guid)->Data1 < 0xd5a47fa7 + 0xffff) && \ - ((guid)->Data2 == 0x6d98) && \ - ((guid)->Data3 == 0x11d1) && \ - ((guid)->Data4[0] == 0xa2) && \ - ((guid)->Data4[1] == 0x1a) && \ - ((guid)->Data4[2] == 0x00) && \ - ((guid)->Data4[3] == 0xa0) && \ - ((guid)->Data4[4] == 0xc9) && \ - ((guid)->Data4[5] == 0x22) && \ - ((guid)->Data4[6] == 0x31) && \ - ((guid)->Data4[7] == 0x96)) - # endif /* INIT_MMREG_MID */ - - # ifndef INIT_MMREG_PID - # define INIT_MMREG_PID(guid, id) \ - { \ - (guid)->Data1 = 0xe36dc2ac + (USHORT)(id); \ - (guid)->Data2 = 0x6d9a; \ - (guid)->Data3 = 0x11d1; \ - (guid)->Data4[0] = 0xa2; \ - (guid)->Data4[1] = 0x1a; \ - (guid)->Data4[2] = 0x00; \ - (guid)->Data4[3] = 0xa0; \ - (guid)->Data4[4] = 0xc9; \ - (guid)->Data4[5] = 0x22; \ - (guid)->Data4[6] = 0x31; \ - (guid)->Data4[7] = 0x96; \ - } - # define EXTRACT_MMREG_PID(guid) \ - (USHORT)((guid)->Data1 - 0xe36dc2ac) - # define DEFINE_MMREG_PID_GUID(id) \ - 0xe36dc2ac + (USHORT)(id), 0x6d9a, 0x11d1, 0xa2, 0x1a, 0x00, 0xa0, 0xc9, 0x22, 0x31, 0x96 - - # define IS_COMPATIBLE_MMREG_PID(guid) \ - (((guid)->Data1 >= 0xe36dc2ac) && \ - ((guid)->Data1 < 0xe36dc2ac + 0xffff) && \ - ((guid)->Data2 == 0x6d9a) && \ - ((guid)->Data3 == 0x11d1) && \ - ((guid)->Data4[0] == 0xa2) && \ - ((guid)->Data4[1] == 0x1a) && \ - ((guid)->Data4[2] == 0x00) && \ - ((guid)->Data4[3] == 0xa0) && \ - ((guid)->Data4[4] == 0xc9) && \ - ((guid)->Data4[5] == 0x22) && \ - ((guid)->Data4[6] == 0x31) && \ - ((guid)->Data4[7] == 0x96)) - # endif /* INIT_MMREG_PID */ - - # define STATIC_KSDATAFORMAT_SUBTYPE_ANALOG \ - 0x6dba3190L, 0x67bd, 0x11cf, 0xa0, 0xf7, 0x00, 0x20, 0xaf, 0xd1, 0x56, 0xe4 -DEFINE_GUIDSTRUCT("6dba3190-67bd-11cf-a0f7-0020afd156e4", KSDATAFORMAT_SUBTYPE_ANALOG); - # define KSDATAFORMAT_SUBTYPE_ANALOG DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_ANALOG) - - # define STATIC_KSDATAFORMAT_SUBTYPE_PCM \ - DEFINE_WAVEFORMATEX_GUID(WAVE_FORMAT_PCM) -DEFINE_GUIDSTRUCT("00000001-0000-0010-8000-00aa00389b71", KSDATAFORMAT_SUBTYPE_PCM); - # define KSDATAFORMAT_SUBTYPE_PCM DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_PCM) - - # ifdef _INC_MMREG - # define STATIC_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT \ - DEFINE_WAVEFORMATEX_GUID(WAVE_FORMAT_IEEE_FLOAT) -DEFINE_GUIDSTRUCT("00000003-0000-0010-8000-00aa00389b71", KSDATAFORMAT_SUBTYPE_IEEE_FLOAT); - # define KSDATAFORMAT_SUBTYPE_IEEE_FLOAT DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT) - - # define STATIC_KSDATAFORMAT_SUBTYPE_DRM \ - DEFINE_WAVEFORMATEX_GUID(WAVE_FORMAT_DRM) -DEFINE_GUIDSTRUCT("00000009-0000-0010-8000-00aa00389b71", KSDATAFORMAT_SUBTYPE_DRM); - # define KSDATAFORMAT_SUBTYPE_DRM DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_DRM) - - # define STATIC_KSDATAFORMAT_SUBTYPE_ALAW \ - DEFINE_WAVEFORMATEX_GUID(WAVE_FORMAT_ALAW) -DEFINE_GUIDSTRUCT("00000006-0000-0010-8000-00aa00389b71", KSDATAFORMAT_SUBTYPE_ALAW); - # define KSDATAFORMAT_SUBTYPE_ALAW DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_ALAW) - - # define STATIC_KSDATAFORMAT_SUBTYPE_MULAW \ - DEFINE_WAVEFORMATEX_GUID(WAVE_FORMAT_MULAW) -DEFINE_GUIDSTRUCT("00000007-0000-0010-8000-00aa00389b71", KSDATAFORMAT_SUBTYPE_MULAW); - # define KSDATAFORMAT_SUBTYPE_MULAW DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_MULAW) - - # define STATIC_KSDATAFORMAT_SUBTYPE_ADPCM \ - DEFINE_WAVEFORMATEX_GUID(WAVE_FORMAT_ADPCM) -DEFINE_GUIDSTRUCT("00000002-0000-0010-8000-00aa00389b71", KSDATAFORMAT_SUBTYPE_ADPCM); - # define KSDATAFORMAT_SUBTYPE_ADPCM DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_ADPCM) - - # define STATIC_KSDATAFORMAT_SUBTYPE_MPEG \ - DEFINE_WAVEFORMATEX_GUID(WAVE_FORMAT_MPEG) -DEFINE_GUIDSTRUCT("00000050-0000-0010-8000-00aa00389b71", KSDATAFORMAT_SUBTYPE_MPEG); - # define KSDATAFORMAT_SUBTYPE_MPEG DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_MPEG) - # endif /* _INC_MMREG */ - - # define STATIC_KSDATAFORMAT_SPECIFIER_VC_ID \ - 0xAD98D184L, 0xAAC3, 0x11D0, 0xA4, 0x1C, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 -DEFINE_GUIDSTRUCT("AD98D184-AAC3-11D0-A41C-00A0C9223196", KSDATAFORMAT_SPECIFIER_VC_ID); - # define KSDATAFORMAT_SPECIFIER_VC_ID DEFINE_GUIDNAMED(KSDATAFORMAT_SPECIFIER_VC_ID) - - # define STATIC_KSDATAFORMAT_SPECIFIER_WAVEFORMATEX \ - 0x05589f81L, 0xc356, 0x11ce, 0xbf, 0x01, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a -DEFINE_GUIDSTRUCT("05589f81-c356-11ce-bf01-00aa0055595a", KSDATAFORMAT_SPECIFIER_WAVEFORMATEX); - # define KSDATAFORMAT_SPECIFIER_WAVEFORMATEX DEFINE_GUIDNAMED(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) - - # define STATIC_KSDATAFORMAT_SPECIFIER_DSOUND \ - 0x518590a2L, 0xa184, 0x11d0, 0x85, 0x22, 0x00, 0xc0, 0x4f, 0xd9, 0xba, 0xf3 -DEFINE_GUIDSTRUCT("518590a2-a184-11d0-8522-00c04fd9baf3", KSDATAFORMAT_SPECIFIER_DSOUND); - # define KSDATAFORMAT_SPECIFIER_DSOUND DEFINE_GUIDNAMED(KSDATAFORMAT_SPECIFIER_DSOUND) - - # if defined(_INC_MMSYSTEM) || defined(_INC_MMREG) || 1 - # if !defined(PACK_PRAGMAS_NOT_SUPPORTED) - # include - # endif -typedef struct -{ - KSDATAFORMAT DataFormat; - WAVEFORMATEX WaveFormatEx; -}KSDATAFORMAT_WAVEFORMATEX, * PKSDATAFORMAT_WAVEFORMATEX; - - # ifndef _WAVEFORMATEXTENSIBLE_ - # define _WAVEFORMATEXTENSIBLE_ -typedef struct -{ - WAVEFORMATEX Format; - union - { - WORD wValidBitsPerSample; - WORD wSamplesPerBlock; - WORD wReserved; - }Samples; - DWORD dwChannelMask; - - GUID SubFormat; -}WAVEFORMATEXTENSIBLE, * PWAVEFORMATEXTENSIBLE; - # endif /* _WAVEFORMATEXTENSIBLE_ */ - - # if !defined(WAVE_FORMAT_EXTENSIBLE) - # define WAVE_FORMAT_EXTENSIBLE 0xFFFE - # endif - -typedef struct -{ - ULONG Flags; - ULONG Control; - WAVEFORMATEX WaveFormatEx; -}KSDSOUND_BUFFERDESC, * PKSDSOUND_BUFFERDESC; - -typedef struct -{ - KSDATAFORMAT DataFormat; - KSDSOUND_BUFFERDESC BufferDesc; -}KSDATAFORMAT_DSOUND, * PKSDATAFORMAT_DSOUND; - - # if !defined(PACK_PRAGMAS_NOT_SUPPORTED) - # include - # endif - # endif /* defined(_INC_MMSYSTEM) || defined(_INC_MMREG) */ - - # define KSDSOUND_BUFFER_PRIMARY 0x00000001 - # define KSDSOUND_BUFFER_STATIC 0x00000002 - # define KSDSOUND_BUFFER_LOCHARDWARE 0x00000004 - # define KSDSOUND_BUFFER_LOCSOFTWARE 0x00000008 - - # define KSDSOUND_BUFFER_CTRL_3D 0x00000001 - # define KSDSOUND_BUFFER_CTRL_FREQUENCY 0x00000002 - # define KSDSOUND_BUFFER_CTRL_PAN 0x00000004 - # define KSDSOUND_BUFFER_CTRL_VOLUME 0x00000008 - # define KSDSOUND_BUFFER_CTRL_POSITIONNOTIFY 0x00000010 - -typedef struct -{ - DWORDLONG PlayOffset; - DWORDLONG WriteOffset; -}KSAUDIO_POSITION, * PKSAUDIO_POSITION; - -typedef struct _DS3DVECTOR -{ - __MINGW_EXTENSION union - { - FLOAT x; - FLOAT dvX; - }; - __MINGW_EXTENSION union - { - FLOAT y; - FLOAT dvY; - }; - __MINGW_EXTENSION union - { - FLOAT z; - FLOAT dvZ; - }; -}DS3DVECTOR, * PDS3DVECTOR; - - # define STATIC_KSPROPSETID_DirectSound3DListener \ - 0x437b3414L, 0xd060, 0x11d0, 0x85, 0x83, 0x00, 0xc0, 0x4f, 0xd9, 0xba, 0xf3 -DEFINE_GUIDSTRUCT("437b3414-d060-11d0-8583-00c04fd9baf3", KSPROPSETID_DirectSound3DListener); - # define KSPROPSETID_DirectSound3DListener DEFINE_GUIDNAMED(KSPROPSETID_DirectSound3DListener) - -typedef enum -{ - KSPROPERTY_DIRECTSOUND3DLISTENER_ALL, - KSPROPERTY_DIRECTSOUND3DLISTENER_POSITION, - KSPROPERTY_DIRECTSOUND3DLISTENER_VELOCITY, - KSPROPERTY_DIRECTSOUND3DLISTENER_ORIENTATION, - KSPROPERTY_DIRECTSOUND3DLISTENER_DISTANCEFACTOR, - KSPROPERTY_DIRECTSOUND3DLISTENER_ROLLOFFFACTOR, - KSPROPERTY_DIRECTSOUND3DLISTENER_DOPPLERFACTOR, - KSPROPERTY_DIRECTSOUND3DLISTENER_BATCH, - KSPROPERTY_DIRECTSOUND3DLISTENER_ALLOCATION -}KSPROPERTY_DIRECTSOUND3DLISTENER; - -typedef struct -{ - DS3DVECTOR Position; - DS3DVECTOR Velocity; - DS3DVECTOR OrientFront; - DS3DVECTOR OrientTop; - FLOAT DistanceFactor; - FLOAT RolloffFactor; - FLOAT DopplerFactor; -}KSDS3D_LISTENER_ALL, * PKSDS3D_LISTENER_ALL; - -typedef struct -{ - DS3DVECTOR Front; - DS3DVECTOR Top; -}KSDS3D_LISTENER_ORIENTATION, * PKSDS3D_LISTENER_ORIENTATION; - - # define STATIC_KSPROPSETID_DirectSound3DBuffer \ - 0x437b3411L, 0xd060, 0x11d0, 0x85, 0x83, 0x00, 0xc0, 0x4f, 0xd9, 0xba, 0xf3 -DEFINE_GUIDSTRUCT("437b3411-d060-11d0-8583-00c04fd9baf3", KSPROPSETID_DirectSound3DBuffer); - # define KSPROPSETID_DirectSound3DBuffer DEFINE_GUIDNAMED(KSPROPSETID_DirectSound3DBuffer) - -typedef enum -{ - KSPROPERTY_DIRECTSOUND3DBUFFER_ALL, - KSPROPERTY_DIRECTSOUND3DBUFFER_POSITION, - KSPROPERTY_DIRECTSOUND3DBUFFER_VELOCITY, - KSPROPERTY_DIRECTSOUND3DBUFFER_CONEANGLES, - KSPROPERTY_DIRECTSOUND3DBUFFER_CONEORIENTATION, - KSPROPERTY_DIRECTSOUND3DBUFFER_CONEOUTSIDEVOLUME, - KSPROPERTY_DIRECTSOUND3DBUFFER_MINDISTANCE, - KSPROPERTY_DIRECTSOUND3DBUFFER_MAXDISTANCE, - KSPROPERTY_DIRECTSOUND3DBUFFER_MODE -}KSPROPERTY_DIRECTSOUND3DBUFFER; - -typedef struct -{ - DS3DVECTOR Position; - DS3DVECTOR Velocity; - ULONG InsideConeAngle; - ULONG OutsideConeAngle; - DS3DVECTOR ConeOrientation; - LONG ConeOutsideVolume; - FLOAT MinDistance; - FLOAT MaxDistance; - ULONG Mode; -}KSDS3D_BUFFER_ALL, * PKSDS3D_BUFFER_ALL; - -typedef struct -{ - ULONG InsideConeAngle; - ULONG OutsideConeAngle; -}KSDS3D_BUFFER_CONE_ANGLES, * PKSDS3D_BUFFER_CONE_ANGLES; - - # define KSAUDIO_STEREO_SPEAKER_GEOMETRY_HEADPHONE (-1) - # define KSAUDIO_STEREO_SPEAKER_GEOMETRY_MIN 5 - # define KSAUDIO_STEREO_SPEAKER_GEOMETRY_NARROW 10 - # define KSAUDIO_STEREO_SPEAKER_GEOMETRY_WIDE 20 - # define KSAUDIO_STEREO_SPEAKER_GEOMETRY_MAX 180 - - # define KSDSOUND_3D_MODE_NORMAL 0x00000000 - # define KSDSOUND_3D_MODE_HEADRELATIVE 0x00000001 - # define KSDSOUND_3D_MODE_DISABLE 0x00000002 - - # define KSDSOUND_BUFFER_CTRL_HRTF_3D 0x40000000 - -typedef struct -{ - ULONG Size; - ULONG Enabled; - WINBOOL SwapChannels; - WINBOOL ZeroAzimuth; - WINBOOL CrossFadeOutput; - ULONG FilterSize; -}KSDS3D_HRTF_PARAMS_MSG, * PKSDS3D_HRTF_PARAMS_MSG; - -typedef enum -{ - FULL_FILTER, - LIGHT_FILTER, - KSDS3D_FILTER_QUALITY_COUNT -}KSDS3D_HRTF_FILTER_QUALITY; - -typedef struct -{ - ULONG Size; - KSDS3D_HRTF_FILTER_QUALITY Quality; - FLOAT SampleRate; - ULONG MaxFilterSize; - ULONG FilterTransientMuteLength; - ULONG FilterOverlapBufferLength; - ULONG OutputOverlapBufferLength; - ULONG Reserved; -}KSDS3D_HRTF_INIT_MSG, * PKSDS3D_HRTF_INIT_MSG; - -typedef enum -{ - FLOAT_COEFF, - SHORT_COEFF, - KSDS3D_COEFF_COUNT -}KSDS3D_HRTF_COEFF_FORMAT; - -typedef enum -{ - DIRECT_FORM, - CASCADE_FORM, - KSDS3D_FILTER_METHOD_COUNT -}KSDS3D_HRTF_FILTER_METHOD; - -typedef enum -{ - DS3D_HRTF_VERSION_1 -}KSDS3D_HRTF_FILTER_VERSION; - -typedef struct -{ - KSDS3D_HRTF_FILTER_METHOD FilterMethod; - KSDS3D_HRTF_COEFF_FORMAT CoeffFormat; - KSDS3D_HRTF_FILTER_VERSION Version; - ULONG Reserved; -}KSDS3D_HRTF_FILTER_FORMAT_MSG, * PKSDS3D_HRTF_FILTER_FORMAT_MSG; - - # define STATIC_KSPROPSETID_Hrtf3d \ - 0xb66decb0L, 0xa083, 0x11d0, 0x85, 0x1e, 0x00, 0xc0, 0x4f, 0xd9, 0xba, 0xf3 -DEFINE_GUIDSTRUCT("b66decb0-a083-11d0-851e-00c04fd9baf3", KSPROPSETID_Hrtf3d); - # define KSPROPSETID_Hrtf3d DEFINE_GUIDNAMED(KSPROPSETID_Hrtf3d) - -typedef enum -{ - KSPROPERTY_HRTF3D_PARAMS = 0, - KSPROPERTY_HRTF3D_INITIALIZE, - KSPROPERTY_HRTF3D_FILTER_FORMAT -}KSPROPERTY_HRTF3D; - -typedef struct -{ - LONG Channel; - FLOAT VolSmoothScale; - FLOAT TotalDryAttenuation; - FLOAT TotalWetAttenuation; - LONG SmoothFrequency; - LONG Delay; -}KSDS3D_ITD_PARAMS, * PKSDS3D_ITD_PARAMS; - -typedef struct -{ - ULONG Enabled; - KSDS3D_ITD_PARAMS LeftParams; - KSDS3D_ITD_PARAMS RightParams; - ULONG Reserved; -}KSDS3D_ITD_PARAMS_MSG, * PKSDS3D_ITD_PARAMS_MSG; - - # define STATIC_KSPROPSETID_Itd3d \ - 0x6429f090L, 0x9fd9, 0x11d0, 0xa7, 0x5b, 0x00, 0xa0, 0xc9, 0x03, 0x65, 0xe3 -DEFINE_GUIDSTRUCT("6429f090-9fd9-11d0-a75b-00a0c90365e3", KSPROPSETID_Itd3d); - # define KSPROPSETID_Itd3d DEFINE_GUIDNAMED(KSPROPSETID_Itd3d) - -typedef enum -{ - KSPROPERTY_ITD3D_PARAMS = 0 -}KSPROPERTY_ITD3D; - -typedef struct -{ - KSDATARANGE DataRange; - ULONG MaximumChannels; - ULONG MinimumBitsPerSample; - ULONG MaximumBitsPerSample; - ULONG MinimumSampleFrequency; - ULONG MaximumSampleFrequency; -}KSDATARANGE_AUDIO, * PKSDATARANGE_AUDIO; - - # define STATIC_KSDATAFORMAT_SUBTYPE_RIFF \ - 0x4995DAEEL, 0x9EE6, 0x11D0, 0xA4, 0x0E, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 -DEFINE_GUIDSTRUCT("4995DAEE-9EE6-11D0-A40E-00A0C9223196", KSDATAFORMAT_SUBTYPE_RIFF); - # define KSDATAFORMAT_SUBTYPE_RIFF DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_RIFF) - - # define STATIC_KSDATAFORMAT_SUBTYPE_RIFFWAVE \ - 0xe436eb8bL, 0x524f, 0x11ce, 0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70 -DEFINE_GUIDSTRUCT("e436eb8b-524f-11ce-9f53-0020af0ba770", KSDATAFORMAT_SUBTYPE_RIFFWAVE); - # define KSDATAFORMAT_SUBTYPE_RIFFWAVE DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_RIFFWAVE) - - # define STATIC_KSPROPSETID_Bibliographic \ - 0x07BA150EL, 0xE2B1, 0x11D0, 0xAC, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 -DEFINE_GUIDSTRUCT("07BA150E-E2B1-11D0-AC17-00A0C9223196", KSPROPSETID_Bibliographic); - # define KSPROPSETID_Bibliographic DEFINE_GUIDNAMED(KSPROPSETID_Bibliographic) - - # define SEB_MK_FOURCC(a, b, c, d) ((a << 24) | (b << 16) | (c << 8) | (d << 0)) - -typedef enum -{ - KSPROPERTY_BIBLIOGRAPHIC_LEADER = SEB_MK_FOURCC('R', 'D', 'L', ' '), - KSPROPERTY_BIBLIOGRAPHIC_LCCN = SEB_MK_FOURCC('0', '1', '0', ' '), - KSPROPERTY_BIBLIOGRAPHIC_ISBN = SEB_MK_FOURCC('0', '2', '0', ' '), - KSPROPERTY_BIBLIOGRAPHIC_ISSN = SEB_MK_FOURCC('2', '2', '0', ' '), - KSPROPERTY_BIBLIOGRAPHIC_CATALOGINGSOURCE = SEB_MK_FOURCC('0', '4', '0', ' '), - KSPROPERTY_BIBLIOGRAPHIC_MAINPERSONALNAME = SEB_MK_FOURCC('0', '0', '1', ' '), - KSPROPERTY_BIBLIOGRAPHIC_MAINCORPORATEBODY = SEB_MK_FOURCC('0', '1', '1', ' '), - KSPROPERTY_BIBLIOGRAPHIC_MAINMEETINGNAME = SEB_MK_FOURCC('1', '1', '1', ' '), - KSPROPERTY_BIBLIOGRAPHIC_MAINUNIFORMTITLE = SEB_MK_FOURCC('0', '3', '1', ' '), - KSPROPERTY_BIBLIOGRAPHIC_UNIFORMTITLE = SEB_MK_FOURCC('0', '4', '2', ' '), - KSPROPERTY_BIBLIOGRAPHIC_TITLESTATEMENT = SEB_MK_FOURCC('5', '4', '2', ' '), - KSPROPERTY_BIBLIOGRAPHIC_VARYINGFORMTITLE = SEB_MK_FOURCC('6', '4', '2', ' '), - KSPROPERTY_BIBLIOGRAPHIC_PUBLICATION = SEB_MK_FOURCC('0', '6', '2', ' '), - KSPROPERTY_BIBLIOGRAPHIC_PHYSICALDESCRIPTION = SEB_MK_FOURCC('0', '0', '3', ' '), - KSPROPERTY_BIBLIOGRAPHIC_ADDEDENTRYTITLE = SEB_MK_FOURCC('0', '4', '4', ' '), - KSPROPERTY_BIBLIOGRAPHIC_SERIESSTATEMENT = SEB_MK_FOURCC('0', '9', '4', ' '), - KSPROPERTY_BIBLIOGRAPHIC_GENERALNOTE = SEB_MK_FOURCC('0', '0', '5', ' '), - KSPROPERTY_BIBLIOGRAPHIC_BIBLIOGRAPHYNOTE = SEB_MK_FOURCC('4', '0', '5', ' '), - KSPROPERTY_BIBLIOGRAPHIC_CONTENTSNOTE = SEB_MK_FOURCC('5', '0', '5', ' '), - KSPROPERTY_BIBLIOGRAPHIC_CREATIONCREDIT = SEB_MK_FOURCC('8', '0', '5', ' '), - KSPROPERTY_BIBLIOGRAPHIC_CITATION = SEB_MK_FOURCC('0', '1', '5', ' '), - KSPROPERTY_BIBLIOGRAPHIC_PARTICIPANT = SEB_MK_FOURCC('1', '1', '5', ' '), - KSPROPERTY_BIBLIOGRAPHIC_SUMMARY = SEB_MK_FOURCC('0', '2', '5', ' '), - KSPROPERTY_BIBLIOGRAPHIC_TARGETAUDIENCE = SEB_MK_FOURCC('1', '2', '5', ' '), - KSPROPERTY_BIBLIOGRAPHIC_ADDEDFORMAVAILABLE = SEB_MK_FOURCC('0', '3', '5', ' '), - KSPROPERTY_BIBLIOGRAPHIC_SYSTEMDETAILS = SEB_MK_FOURCC('8', '3', '5', ' '), - KSPROPERTY_BIBLIOGRAPHIC_AWARDS = SEB_MK_FOURCC('6', '8', '5', ' '), - KSPROPERTY_BIBLIOGRAPHIC_ADDEDENTRYPERSONALNAME = SEB_MK_FOURCC('0', '0', '6', ' '), - KSPROPERTY_BIBLIOGRAPHIC_ADDEDENTRYTOPICALTERM = SEB_MK_FOURCC('0', '5', '6', ' '), - KSPROPERTY_BIBLIOGRAPHIC_ADDEDENTRYGEOGRAPHIC = SEB_MK_FOURCC('1', '5', '6', ' '), - KSPROPERTY_BIBLIOGRAPHIC_INDEXTERMGENRE = SEB_MK_FOURCC('5', '5', '6', ' '), - KSPROPERTY_BIBLIOGRAPHIC_INDEXTERMCURRICULUM = SEB_MK_FOURCC('8', '5', '6', ' '), - KSPROPERTY_BIBLIOGRAPHIC_ADDEDENTRYUNIFORMTITLE = SEB_MK_FOURCC('0', '3', '7', ' '), - KSPROPERTY_BIBLIOGRAPHIC_ADDEDENTRYRELATED = SEB_MK_FOURCC('0', '4', '7', ' '), - KSPROPERTY_BIBLIOGRAPHIC_SERIESSTATEMENTPERSONALNAME = SEB_MK_FOURCC('0', '0', '8', ' '), - KSPROPERTY_BIBLIOGRAPHIC_SERIESSTATEMENTUNIFORMTITLE = SEB_MK_FOURCC('0', '3', '8', ' ') -}KSPROPERTY_BIBLIOGRAPHIC; - - # undef SEB_MK_FOURCC - - # define STATIC_KSPROPSETID_TopologyNode \ - 0x45FFAAA1L, 0x6E1B, 0x11D0, 0xBC, 0xF2, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00 -DEFINE_GUIDSTRUCT("45FFAAA1-6E1B-11D0-BCF2-444553540000", KSPROPSETID_TopologyNode); - # define KSPROPSETID_TopologyNode DEFINE_GUIDNAMED(KSPROPSETID_TopologyNode) - -typedef enum -{ - KSPROPERTY_TOPOLOGYNODE_ENABLE = 1, - KSPROPERTY_TOPOLOGYNODE_RESET -}KSPROPERTY_TOPOLOGYNODE; - - # define STATIC_KSPROPSETID_RtAudio \ - 0xa855a48c, 0x2f78, 0x4729, 0x90, 0x51, 0x19, 0x68, 0x74, 0x6b, 0x9e, 0xef -DEFINE_GUIDSTRUCT("A855A48C-2F78-4729-9051-1968746B9EEF", KSPROPSETID_RtAudio); - # define KSPROPSETID_RtAudio DEFINE_GUIDNAMED(KSPROPSETID_RtAudio) - -typedef enum -{ - KSPROPERTY_RTAUDIO_GETPOSITIONFUNCTION -}KSPROPERTY_RTAUDIO; - - # define STATIC_KSPROPSETID_DrmAudioStream \ - 0x2f2c8ddd, 0x4198, 0x4fac, 0xba, 0x29, 0x61, 0xbb, 0x5, 0xb7, 0xde, 0x6 -DEFINE_GUIDSTRUCT("2F2C8DDD-4198-4fac-BA29-61BB05B7DE06", KSPROPSETID_DrmAudioStream); - # define KSPROPSETID_DrmAudioStream DEFINE_GUIDNAMED(KSPROPSETID_DrmAudioStream) - -typedef enum -{ - KSPROPERTY_DRMAUDIOSTREAM_CONTENTID -}KSPROPERTY_DRMAUDIOSTREAM; - - # define STATIC_KSPROPSETID_Audio \ - 0x45FFAAA0L, 0x6E1B, 0x11D0, 0xBC, 0xF2, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00 -DEFINE_GUIDSTRUCT("45FFAAA0-6E1B-11D0-BCF2-444553540000", KSPROPSETID_Audio); - # define KSPROPSETID_Audio DEFINE_GUIDNAMED(KSPROPSETID_Audio) - -typedef enum -{ - KSPROPERTY_AUDIO_LATENCY = 1, - KSPROPERTY_AUDIO_COPY_PROTECTION, - KSPROPERTY_AUDIO_CHANNEL_CONFIG, - KSPROPERTY_AUDIO_VOLUMELEVEL, - KSPROPERTY_AUDIO_POSITION, - KSPROPERTY_AUDIO_DYNAMIC_RANGE, - KSPROPERTY_AUDIO_QUALITY, - KSPROPERTY_AUDIO_SAMPLING_RATE, - KSPROPERTY_AUDIO_DYNAMIC_SAMPLING_RATE, - KSPROPERTY_AUDIO_MIX_LEVEL_TABLE, - KSPROPERTY_AUDIO_MIX_LEVEL_CAPS, - KSPROPERTY_AUDIO_MUX_SOURCE, - KSPROPERTY_AUDIO_MUTE, - KSPROPERTY_AUDIO_BASS, - KSPROPERTY_AUDIO_MID, - KSPROPERTY_AUDIO_TREBLE, - KSPROPERTY_AUDIO_BASS_BOOST, - KSPROPERTY_AUDIO_EQ_LEVEL, - KSPROPERTY_AUDIO_NUM_EQ_BANDS, - KSPROPERTY_AUDIO_EQ_BANDS, - KSPROPERTY_AUDIO_AGC, - KSPROPERTY_AUDIO_DELAY, - KSPROPERTY_AUDIO_LOUDNESS, - KSPROPERTY_AUDIO_WIDE_MODE, - KSPROPERTY_AUDIO_WIDENESS, - KSPROPERTY_AUDIO_REVERB_LEVEL, - KSPROPERTY_AUDIO_CHORUS_LEVEL, - KSPROPERTY_AUDIO_DEV_SPECIFIC, - KSPROPERTY_AUDIO_DEMUX_DEST, - KSPROPERTY_AUDIO_STEREO_ENHANCE, - KSPROPERTY_AUDIO_MANUFACTURE_GUID, - KSPROPERTY_AUDIO_PRODUCT_GUID, - KSPROPERTY_AUDIO_CPU_RESOURCES, - KSPROPERTY_AUDIO_STEREO_SPEAKER_GEOMETRY, - KSPROPERTY_AUDIO_SURROUND_ENCODE, - KSPROPERTY_AUDIO_3D_INTERFACE, - KSPROPERTY_AUDIO_PEAKMETER, - KSPROPERTY_AUDIO_ALGORITHM_INSTANCE, - KSPROPERTY_AUDIO_FILTER_STATE, - KSPROPERTY_AUDIO_PREFERRED_STATUS -}KSPROPERTY_AUDIO; - - # define KSAUDIO_QUALITY_WORST 0x0 - # define KSAUDIO_QUALITY_PC 0x1 - # define KSAUDIO_QUALITY_BASIC 0x2 - # define KSAUDIO_QUALITY_ADVANCED 0x3 - - # define KSAUDIO_CPU_RESOURCES_NOT_HOST_CPU 0x00000000 - # define KSAUDIO_CPU_RESOURCES_HOST_CPU 0x7FFFFFFF - -typedef struct -{ - WINBOOL fCopyrighted; - WINBOOL fOriginal; -}KSAUDIO_COPY_PROTECTION, * PKSAUDIO_COPY_PROTECTION; - -typedef struct -{ - LONG ActiveSpeakerPositions; -}KSAUDIO_CHANNEL_CONFIG, * PKSAUDIO_CHANNEL_CONFIG; - - # define SPEAKER_FRONT_LEFT 0x1 - # define SPEAKER_FRONT_RIGHT 0x2 - # define SPEAKER_FRONT_CENTER 0x4 - # define SPEAKER_LOW_FREQUENCY 0x8 - # define SPEAKER_BACK_LEFT 0x10 - # define SPEAKER_BACK_RIGHT 0x20 - # define SPEAKER_FRONT_LEFT_OF_CENTER 0x40 - # define SPEAKER_FRONT_RIGHT_OF_CENTER 0x80 - # define SPEAKER_BACK_CENTER 0x100 - # define SPEAKER_SIDE_LEFT 0x200 - # define SPEAKER_SIDE_RIGHT 0x400 - # define SPEAKER_TOP_CENTER 0x800 - # define SPEAKER_TOP_FRONT_LEFT 0x1000 - # define SPEAKER_TOP_FRONT_CENTER 0x2000 - # define SPEAKER_TOP_FRONT_RIGHT 0x4000 - # define SPEAKER_TOP_BACK_LEFT 0x8000 - # define SPEAKER_TOP_BACK_CENTER 0x10000 - # define SPEAKER_TOP_BACK_RIGHT 0x20000 - - # define SPEAKER_RESERVED 0x7FFC0000 - - # define SPEAKER_ALL 0x80000000 - - # define KSAUDIO_SPEAKER_DIRECTOUT 0 - # define KSAUDIO_SPEAKER_MONO (SPEAKER_FRONT_CENTER) - # define KSAUDIO_SPEAKER_STEREO (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT) - # define KSAUDIO_SPEAKER_QUAD (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | \ - SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT) - # define KSAUDIO_SPEAKER_SURROUND (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | \ - SPEAKER_FRONT_CENTER | SPEAKER_BACK_CENTER) - # define KSAUDIO_SPEAKER_5POINT1 (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | \ - SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | \ - SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT) - # define KSAUDIO_SPEAKER_7POINT1 (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | \ - SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | \ - SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | \ - SPEAKER_FRONT_LEFT_OF_CENTER | SPEAKER_FRONT_RIGHT_OF_CENTER) - # define KSAUDIO_SPEAKER_5POINT1_SURROUND (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | \ - SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | \ - SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT) - # define KSAUDIO_SPEAKER_7POINT1_SURROUND (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | \ - SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | \ - SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | \ - SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT) - - # define KSAUDIO_SPEAKER_5POINT1_BACK KSAUDIO_SPEAKER_5POINT1 - # define KSAUDIO_SPEAKER_7POINT1_WIDE KSAUDIO_SPEAKER_7POINT1 - - # define KSAUDIO_SPEAKER_GROUND_FRONT_LEFT SPEAKER_FRONT_LEFT - # define KSAUDIO_SPEAKER_GROUND_FRONT_CENTER SPEAKER_FRONT_CENTER - # define KSAUDIO_SPEAKER_GROUND_FRONT_RIGHT SPEAKER_FRONT_RIGHT - # define KSAUDIO_SPEAKER_GROUND_REAR_LEFT SPEAKER_BACK_LEFT - # define KSAUDIO_SPEAKER_GROUND_REAR_RIGHT SPEAKER_BACK_RIGHT - # define KSAUDIO_SPEAKER_TOP_MIDDLE SPEAKER_TOP_CENTER - # define KSAUDIO_SPEAKER_SUPER_WOOFER SPEAKER_LOW_FREQUENCY - -typedef struct -{ - ULONG QuietCompression; - ULONG LoudCompression; -}KSAUDIO_DYNAMIC_RANGE, * PKSAUDIO_DYNAMIC_RANGE; - -typedef struct -{ - WINBOOL Mute; - LONG Level; -}KSAUDIO_MIXLEVEL, * PKSAUDIO_MIXLEVEL; - -typedef struct -{ - WINBOOL Mute; - LONG Minimum; - LONG Maximum; - LONG Reset; -}KSAUDIO_MIX_CAPS, * PKSAUDIO_MIX_CAPS; - -typedef struct -{ - ULONG InputChannels; - ULONG OutputChannels; - KSAUDIO_MIX_CAPS Capabilities[1]; -}KSAUDIO_MIXCAP_TABLE, * PKSAUDIO_MIXCAP_TABLE; - -typedef enum -{ - SE_TECH_NONE, - SE_TECH_ANALOG_DEVICES_PHAT, - SE_TECH_CREATIVE, - SE_TECH_NATIONAL_SEMI, - SE_TECH_YAMAHA_YMERSION, - SE_TECH_BBE, - SE_TECH_CRYSTAL_SEMI, - SE_TECH_QSOUND_QXPANDER, - SE_TECH_SPATIALIZER, - SE_TECH_SRS, - SE_TECH_PLATFORM_TECH, - SE_TECH_AKM, - SE_TECH_AUREAL, - SE_TECH_AZTECH, - SE_TECH_BINAURA, - SE_TECH_ESS_TECH, - SE_TECH_HARMAN_VMAX, - SE_TECH_NVIDEA, - SE_TECH_PHILIPS_INCREDIBLE, - SE_TECH_TEXAS_INST, - SE_TECH_VLSI_TECH -}SE_TECHNIQUE; - -typedef struct -{ - SE_TECHNIQUE Technique; - ULONG Center; - ULONG Depth; - ULONG Reserved; -}KSAUDIO_STEREO_ENHANCE, * PKSAUDIO_STEREO_ENHANCE; - -typedef enum -{ - KSPROPERTY_SYSAUDIO_NORMAL_DEFAULT = 0, - KSPROPERTY_SYSAUDIO_PLAYBACK_DEFAULT, - KSPROPERTY_SYSAUDIO_RECORD_DEFAULT, - KSPROPERTY_SYSAUDIO_MIDI_DEFAULT, - KSPROPERTY_SYSAUDIO_MIXER_DEFAULT -}KSPROPERTY_SYSAUDIO_DEFAULT_TYPE; - -typedef struct -{ - WINBOOL Enable; - KSPROPERTY_SYSAUDIO_DEFAULT_TYPE DeviceType; - ULONG Flags; - ULONG Reserved; -}KSAUDIO_PREFERRED_STATUS, * PKSAUDIO_PREFERRED_STATUS; - - # define STATIC_KSNODETYPE_DAC \ - 0x507AE360L, 0xC554, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1 -DEFINE_GUIDSTRUCT("507AE360-C554-11D0-8A2B-00A0C9255AC1", KSNODETYPE_DAC); - # define KSNODETYPE_DAC DEFINE_GUIDNAMED(KSNODETYPE_DAC) - - # define STATIC_KSNODETYPE_ADC \ - 0x4D837FE0L, 0xC555, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1 -DEFINE_GUIDSTRUCT("4D837FE0-C555-11D0-8A2B-00A0C9255AC1", KSNODETYPE_ADC); - # define KSNODETYPE_ADC DEFINE_GUIDNAMED(KSNODETYPE_ADC) - - # define STATIC_KSNODETYPE_SRC \ - 0x9DB7B9E0L, 0xC555, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1 -DEFINE_GUIDSTRUCT("9DB7B9E0-C555-11D0-8A2B-00A0C9255AC1", KSNODETYPE_SRC); - # define KSNODETYPE_SRC DEFINE_GUIDNAMED(KSNODETYPE_SRC) - - # define STATIC_KSNODETYPE_SUPERMIX \ - 0xE573ADC0L, 0xC555, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1 -DEFINE_GUIDSTRUCT("E573ADC0-C555-11D0-8A2B-00A0C9255AC1", KSNODETYPE_SUPERMIX); - # define KSNODETYPE_SUPERMIX DEFINE_GUIDNAMED(KSNODETYPE_SUPERMIX) - - # define STATIC_KSNODETYPE_MUX \ - 0x2CEAF780L, 0xC556, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1 -DEFINE_GUIDSTRUCT("2CEAF780-C556-11D0-8A2B-00A0C9255AC1", KSNODETYPE_MUX); - # define KSNODETYPE_MUX DEFINE_GUIDNAMED(KSNODETYPE_MUX) - - # define STATIC_KSNODETYPE_DEMUX \ - 0xC0EB67D4L, 0xE807, 0x11D0, 0x95, 0x8A, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("C0EB67D4-E807-11D0-958A-00C04FB925D3", KSNODETYPE_DEMUX); - # define KSNODETYPE_DEMUX DEFINE_GUIDNAMED(KSNODETYPE_DEMUX) - - # define STATIC_KSNODETYPE_SUM \ - 0xDA441A60L, 0xC556, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1 -DEFINE_GUIDSTRUCT("DA441A60-C556-11D0-8A2B-00A0C9255AC1", KSNODETYPE_SUM); - # define KSNODETYPE_SUM DEFINE_GUIDNAMED(KSNODETYPE_SUM) - - # define STATIC_KSNODETYPE_MUTE \ - 0x02B223C0L, 0xC557, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1 -DEFINE_GUIDSTRUCT("02B223C0-C557-11D0-8A2B-00A0C9255AC1", KSNODETYPE_MUTE); - # define KSNODETYPE_MUTE DEFINE_GUIDNAMED(KSNODETYPE_MUTE) - - # define STATIC_KSNODETYPE_VOLUME \ - 0x3A5ACC00L, 0xC557, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1 -DEFINE_GUIDSTRUCT("3A5ACC00-C557-11D0-8A2B-00A0C9255AC1", KSNODETYPE_VOLUME); - # define KSNODETYPE_VOLUME DEFINE_GUIDNAMED(KSNODETYPE_VOLUME) - - # define STATIC_KSNODETYPE_TONE \ - 0x7607E580L, 0xC557, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1 -DEFINE_GUIDSTRUCT("7607E580-C557-11D0-8A2B-00A0C9255AC1", KSNODETYPE_TONE); - # define KSNODETYPE_TONE DEFINE_GUIDNAMED(KSNODETYPE_TONE) - - # define STATIC_KSNODETYPE_EQUALIZER \ - 0x9D41B4A0L, 0xC557, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1 -DEFINE_GUIDSTRUCT("9D41B4A0-C557-11D0-8A2B-00A0C9255AC1", KSNODETYPE_EQUALIZER); - # define KSNODETYPE_EQUALIZER DEFINE_GUIDNAMED(KSNODETYPE_EQUALIZER) - - # define STATIC_KSNODETYPE_AGC \ - 0xE88C9BA0L, 0xC557, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1 -DEFINE_GUIDSTRUCT("E88C9BA0-C557-11D0-8A2B-00A0C9255AC1", KSNODETYPE_AGC); - # define KSNODETYPE_AGC DEFINE_GUIDNAMED(KSNODETYPE_AGC) - - # define STATIC_KSNODETYPE_NOISE_SUPPRESS \ - 0xe07f903f, 0x62fd, 0x4e60, 0x8c, 0xdd, 0xde, 0xa7, 0x23, 0x66, 0x65, 0xb5 -DEFINE_GUIDSTRUCT("E07F903F-62FD-4e60-8CDD-DEA7236665B5", KSNODETYPE_NOISE_SUPPRESS); - # define KSNODETYPE_NOISE_SUPPRESS DEFINE_GUIDNAMED(KSNODETYPE_NOISE_SUPPRESS) - - # define STATIC_KSNODETYPE_DELAY \ - 0x144981E0L, 0xC558, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1 -DEFINE_GUIDSTRUCT("144981E0-C558-11D0-8A2B-00A0C9255AC1", KSNODETYPE_DELAY); - # define KSNODETYPE_DELAY DEFINE_GUIDNAMED(KSNODETYPE_DELAY) - - # define STATIC_KSNODETYPE_LOUDNESS \ - 0x41887440L, 0xC558, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1 -DEFINE_GUIDSTRUCT("41887440-C558-11D0-8A2B-00A0C9255AC1", KSNODETYPE_LOUDNESS); - # define KSNODETYPE_LOUDNESS DEFINE_GUIDNAMED(KSNODETYPE_LOUDNESS) - - # define STATIC_KSNODETYPE_PROLOGIC_DECODER \ - 0x831C2C80L, 0xC558, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1 -DEFINE_GUIDSTRUCT("831C2C80-C558-11D0-8A2B-00A0C9255AC1", KSNODETYPE_PROLOGIC_DECODER); - # define KSNODETYPE_PROLOGIC_DECODER DEFINE_GUIDNAMED(KSNODETYPE_PROLOGIC_DECODER) - - # define STATIC_KSNODETYPE_STEREO_WIDE \ - 0xA9E69800L, 0xC558, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1 -DEFINE_GUIDSTRUCT("A9E69800-C558-11D0-8A2B-00A0C9255AC1", KSNODETYPE_STEREO_WIDE); - # define KSNODETYPE_STEREO_WIDE DEFINE_GUIDNAMED(KSNODETYPE_STEREO_WIDE) - - # define STATIC_KSNODETYPE_STEREO_ENHANCE \ - 0xAF6878ACL, 0xE83F, 0x11D0, 0x95, 0x8A, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("AF6878AC-E83F-11D0-958A-00C04FB925D3", KSNODETYPE_STEREO_ENHANCE); - # define KSNODETYPE_STEREO_ENHANCE DEFINE_GUIDNAMED(KSNODETYPE_STEREO_ENHANCE) - - # define STATIC_KSNODETYPE_REVERB \ - 0xEF0328E0L, 0xC558, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1 -DEFINE_GUIDSTRUCT("EF0328E0-C558-11D0-8A2B-00A0C9255AC1", KSNODETYPE_REVERB); - # define KSNODETYPE_REVERB DEFINE_GUIDNAMED(KSNODETYPE_REVERB) - - # define STATIC_KSNODETYPE_CHORUS \ - 0x20173F20L, 0xC559, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1 -DEFINE_GUIDSTRUCT("20173F20-C559-11D0-8A2B-00A0C9255AC1", KSNODETYPE_CHORUS); - # define KSNODETYPE_CHORUS DEFINE_GUIDNAMED(KSNODETYPE_CHORUS) - - # define STATIC_KSNODETYPE_3D_EFFECTS \ - 0x55515860L, 0xC559, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1 -DEFINE_GUIDSTRUCT("55515860-C559-11D0-8A2B-00A0C9255AC1", KSNODETYPE_3D_EFFECTS); - # define KSNODETYPE_3D_EFFECTS DEFINE_GUIDNAMED(KSNODETYPE_3D_EFFECTS) - - # define STATIC_KSNODETYPE_ACOUSTIC_ECHO_CANCEL STATIC_KSCATEGORY_ACOUSTIC_ECHO_CANCEL - # define KSNODETYPE_ACOUSTIC_ECHO_CANCEL KSCATEGORY_ACOUSTIC_ECHO_CANCEL - - # define STATIC_KSALGORITHMINSTANCE_SYSTEM_ACOUSTIC_ECHO_CANCEL \ - 0x1c22c56dL, 0x9879, 0x4f5b, 0xa3, 0x89, 0x27, 0x99, 0x6d, 0xdc, 0x28, 0x10 -DEFINE_GUIDSTRUCT("1C22C56D-9879-4f5b-A389-27996DDC2810", KSALGORITHMINSTANCE_SYSTEM_ACOUSTIC_ECHO_CANCEL); - # define KSALGORITHMINSTANCE_SYSTEM_ACOUSTIC_ECHO_CANCEL DEFINE_GUIDNAMED(KSALGORITHMINSTANCE_SYSTEM_ACOUSTIC_ECHO_CANCEL) - - # define STATIC_KSALGORITHMINSTANCE_SYSTEM_NOISE_SUPPRESS \ - 0x5ab0882eL, 0x7274, 0x4516, 0x87, 0x7d, 0x4e, 0xee, 0x99, 0xba, 0x4f, 0xd0 -DEFINE_GUIDSTRUCT("5AB0882E-7274-4516-877D-4EEE99BA4FD0", KSALGORITHMINSTANCE_SYSTEM_NOISE_SUPPRESS); - # define KSALGORITHMINSTANCE_SYSTEM_NOISE_SUPPRESS DEFINE_GUIDNAMED(KSALGORITHMINSTANCE_SYSTEM_NOISE_SUPPRESS) - - # define STATIC_KSALGORITHMINSTANCE_SYSTEM_AGC \ - 0x950e55b9L, 0x877c, 0x4c67, 0xbe, 0x8, 0xe4, 0x7b, 0x56, 0x11, 0x13, 0xa -DEFINE_GUIDSTRUCT("950E55B9-877C-4c67-BE08-E47B5611130A", KSALGORITHMINSTANCE_SYSTEM_AGC); - # define KSALGORITHMINSTANCE_SYSTEM_AGC DEFINE_GUIDNAMED(KSALGORITHMINSTANCE_SYSTEM_AGC) - - # define STATIC_KSALGORITHMINSTANCE_SYSTEM_MICROPHONE_ARRAY_PROCESSOR \ - 0xB6F5A0A0L, 0x9E61, 0x4F8C, 0x91, 0xE3, 0x76, 0xCF, 0xF, 0x3C, 0x47, 0x1F -DEFINE_GUIDSTRUCT("B6F5A0A0-9E61-4f8c-91E3-76CF0F3C471F", KSALGORITHMINSTANCE_SYSTEM_MICROPHONE_ARRAY_PROCESSOR); - # define KSALGORITHMINSTANCE_SYSTEM_MICROPHONE_ARRAY_PROCESSOR DEFINE_GUIDNAMED(KSALGORITHMINSTANCE_SYSTEM_MICROPHONE_ARRAY_PROCESSOR) - - # define STATIC_KSNODETYPE_MICROPHONE_ARRAY_PROCESSOR STATIC_KSCATEGORY_MICROPHONE_ARRAY_PROCESSOR - # define KSNODETYPE_MICROPHONE_ARRAY_PROCESSOR KSCATEGORY_MICROPHONE_ARRAY_PROCESSOR - - # define STATIC_KSNODETYPE_DEV_SPECIFIC \ - 0x941C7AC0L, 0xC559, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1 -DEFINE_GUIDSTRUCT("941C7AC0-C559-11D0-8A2B-00A0C9255AC1", KSNODETYPE_DEV_SPECIFIC); - # define KSNODETYPE_DEV_SPECIFIC DEFINE_GUIDNAMED(KSNODETYPE_DEV_SPECIFIC) - - # define STATIC_KSNODETYPE_PROLOGIC_ENCODER \ - 0x8074C5B2L, 0x3C66, 0x11D2, 0xB4, 0x5A, 0x30, 0x78, 0x30, 0x2C, 0x20, 0x30 -DEFINE_GUIDSTRUCT("8074C5B2-3C66-11D2-B45A-3078302C2030", KSNODETYPE_PROLOGIC_ENCODER); - # define KSNODETYPE_PROLOGIC_ENCODER DEFINE_GUIDNAMED(KSNODETYPE_PROLOGIC_ENCODER) - # define KSNODETYPE_SURROUND_ENCODER KSNODETYPE_PROLOGIC_ENCODER - - # define STATIC_KSNODETYPE_PEAKMETER \ - 0xa085651eL, 0x5f0d, 0x4b36, 0xa8, 0x69, 0xd1, 0x95, 0xd6, 0xab, 0x4b, 0x9e -DEFINE_GUIDSTRUCT("A085651E-5F0D-4b36-A869-D195D6AB4B9E", KSNODETYPE_PEAKMETER); - # define KSNODETYPE_PEAKMETER DEFINE_GUIDNAMED(KSNODETYPE_PEAKMETER) - - # define STATIC_KSAUDFNAME_BASS \ - 0x185FEDE0L, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("185FEDE0-9905-11D1-95A9-00C04FB925D3", KSAUDFNAME_BASS); - # define KSAUDFNAME_BASS DEFINE_GUIDNAMED(KSAUDFNAME_BASS) - - # define STATIC_KSAUDFNAME_TREBLE \ - 0x185FEDE1L, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("185FEDE1-9905-11D1-95A9-00C04FB925D3", KSAUDFNAME_TREBLE); - # define KSAUDFNAME_TREBLE DEFINE_GUIDNAMED(KSAUDFNAME_TREBLE) - - # define STATIC_KSAUDFNAME_3D_STEREO \ - 0x185FEDE2L, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("185FEDE2-9905-11D1-95A9-00C04FB925D3", KSAUDFNAME_3D_STEREO); - # define KSAUDFNAME_3D_STEREO DEFINE_GUIDNAMED(KSAUDFNAME_3D_STEREO) - - # define STATIC_KSAUDFNAME_MASTER_VOLUME \ - 0x185FEDE3L, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("185FEDE3-9905-11D1-95A9-00C04FB925D3", KSAUDFNAME_MASTER_VOLUME); - # define KSAUDFNAME_MASTER_VOLUME DEFINE_GUIDNAMED(KSAUDFNAME_MASTER_VOLUME) - - # define STATIC_KSAUDFNAME_MASTER_MUTE \ - 0x185FEDE4L, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("185FEDE4-9905-11D1-95A9-00C04FB925D3", KSAUDFNAME_MASTER_MUTE); - # define KSAUDFNAME_MASTER_MUTE DEFINE_GUIDNAMED(KSAUDFNAME_MASTER_MUTE) - - # define STATIC_KSAUDFNAME_WAVE_VOLUME \ - 0x185FEDE5L, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("185FEDE5-9905-11D1-95A9-00C04FB925D3", KSAUDFNAME_WAVE_VOLUME); - # define KSAUDFNAME_WAVE_VOLUME DEFINE_GUIDNAMED(KSAUDFNAME_WAVE_VOLUME) - - # define STATIC_KSAUDFNAME_WAVE_MUTE \ - 0x185FEDE6L, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("185FEDE6-9905-11D1-95A9-00C04FB925D3", KSAUDFNAME_WAVE_MUTE); - # define KSAUDFNAME_WAVE_MUTE DEFINE_GUIDNAMED(KSAUDFNAME_WAVE_MUTE) - - # define STATIC_KSAUDFNAME_MIDI_VOLUME \ - 0x185FEDE7L, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("185FEDE7-9905-11D1-95A9-00C04FB925D3", KSAUDFNAME_MIDI_VOLUME); - # define KSAUDFNAME_MIDI_VOLUME DEFINE_GUIDNAMED(KSAUDFNAME_MIDI_VOLUME) - - # define STATIC_KSAUDFNAME_MIDI_MUTE \ - 0x185FEDE8L, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("185FEDE8-9905-11D1-95A9-00C04FB925D3", KSAUDFNAME_MIDI_MUTE); - # define KSAUDFNAME_MIDI_MUTE DEFINE_GUIDNAMED(KSAUDFNAME_MIDI_MUTE) - - # define STATIC_KSAUDFNAME_CD_VOLUME \ - 0x185FEDE9L, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("185FEDE9-9905-11D1-95A9-00C04FB925D3", KSAUDFNAME_CD_VOLUME); - # define KSAUDFNAME_CD_VOLUME DEFINE_GUIDNAMED(KSAUDFNAME_CD_VOLUME) - - # define STATIC_KSAUDFNAME_CD_MUTE \ - 0x185FEDEAL, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("185FEDEA-9905-11D1-95A9-00C04FB925D3", KSAUDFNAME_CD_MUTE); - # define KSAUDFNAME_CD_MUTE DEFINE_GUIDNAMED(KSAUDFNAME_CD_MUTE) - - # define STATIC_KSAUDFNAME_LINE_VOLUME \ - 0x185FEDEBL, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("185FEDEB-9905-11D1-95A9-00C04FB925D3", KSAUDFNAME_LINE_VOLUME); - # define KSAUDFNAME_LINE_VOLUME DEFINE_GUIDNAMED(KSAUDFNAME_LINE_VOLUME) - - # define STATIC_KSAUDFNAME_LINE_MUTE \ - 0x185FEDECL, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("185FEDEC-9905-11D1-95A9-00C04FB925D3", KSAUDFNAME_LINE_MUTE); - # define KSAUDFNAME_LINE_MUTE DEFINE_GUIDNAMED(KSAUDFNAME_LINE_MUTE) - - # define STATIC_KSAUDFNAME_MIC_VOLUME \ - 0x185FEDEDL, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("185FEDED-9905-11D1-95A9-00C04FB925D3", KSAUDFNAME_MIC_VOLUME); - # define KSAUDFNAME_MIC_VOLUME DEFINE_GUIDNAMED(KSAUDFNAME_MIC_VOLUME) - - # define STATIC_KSAUDFNAME_MIC_MUTE \ - 0x185FEDEEL, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("185FEDEE-9905-11D1-95A9-00C04FB925D3", KSAUDFNAME_MIC_MUTE); - # define KSAUDFNAME_MIC_MUTE DEFINE_GUIDNAMED(KSAUDFNAME_MIC_MUTE) - - # define STATIC_KSAUDFNAME_RECORDING_SOURCE \ - 0x185FEDEFL, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("185FEDEF-9905-11D1-95A9-00C04FB925D3", KSAUDFNAME_RECORDING_SOURCE); - # define KSAUDFNAME_RECORDING_SOURCE DEFINE_GUIDNAMED(KSAUDFNAME_RECORDING_SOURCE) - - # define STATIC_KSAUDFNAME_PC_SPEAKER_VOLUME \ - 0x185FEDF0L, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("185FEDF0-9905-11D1-95A9-00C04FB925D3", KSAUDFNAME_PC_SPEAKER_VOLUME); - # define KSAUDFNAME_PC_SPEAKER_VOLUME DEFINE_GUIDNAMED(KSAUDFNAME_PC_SPEAKER_VOLUME) - - # define STATIC_KSAUDFNAME_PC_SPEAKER_MUTE \ - 0x185FEDF1L, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("185FEDF1-9905-11D1-95A9-00C04FB925D3", KSAUDFNAME_PC_SPEAKER_MUTE); - # define KSAUDFNAME_PC_SPEAKER_MUTE DEFINE_GUIDNAMED(KSAUDFNAME_PC_SPEAKER_MUTE) - - # define STATIC_KSAUDFNAME_MIDI_IN_VOLUME \ - 0x185FEDF2L, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("185FEDF2-9905-11D1-95A9-00C04FB925D3", KSAUDFNAME_MIDI_IN_VOLUME); - # define KSAUDFNAME_MIDI_IN_VOLUME DEFINE_GUIDNAMED(KSAUDFNAME_MIDI_IN_VOLUME) - - # define STATIC_KSAUDFNAME_CD_IN_VOLUME \ - 0x185FEDF3L, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("185FEDF3-9905-11D1-95A9-00C04FB925D3", KSAUDFNAME_CD_IN_VOLUME); - # define KSAUDFNAME_CD_IN_VOLUME DEFINE_GUIDNAMED(KSAUDFNAME_CD_IN_VOLUME) - - # define STATIC_KSAUDFNAME_LINE_IN_VOLUME \ - 0x185FEDF4L, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("185FEDF4-9905-11D1-95A9-00C04FB925D3", KSAUDFNAME_LINE_IN_VOLUME); - # define KSAUDFNAME_LINE_IN_VOLUME DEFINE_GUIDNAMED(KSAUDFNAME_LINE_IN_VOLUME) - - # define STATIC_KSAUDFNAME_MIC_IN_VOLUME \ - 0x185FEDF5L, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("185FEDF5-9905-11D1-95A9-00C04FB925D3", KSAUDFNAME_MIC_IN_VOLUME); - # define KSAUDFNAME_MIC_IN_VOLUME DEFINE_GUIDNAMED(KSAUDFNAME_MIC_IN_VOLUME) - - # define STATIC_KSAUDFNAME_WAVE_IN_VOLUME \ - 0x185FEDF6L, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("185FEDF6-9905-11D1-95A9-00C04FB925D3", KSAUDFNAME_WAVE_IN_VOLUME); - # define KSAUDFNAME_WAVE_IN_VOLUME DEFINE_GUIDNAMED(KSAUDFNAME_WAVE_IN_VOLUME) - - # define STATIC_KSAUDFNAME_VOLUME_CONTROL \ - 0x185FEDF7L, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("185FEDF7-9905-11D1-95A9-00C04FB925D3", KSAUDFNAME_VOLUME_CONTROL); - # define KSAUDFNAME_VOLUME_CONTROL DEFINE_GUIDNAMED(KSAUDFNAME_VOLUME_CONTROL) - - # define STATIC_KSAUDFNAME_MIDI \ - 0x185FEDF8L, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("185FEDF8-9905-11D1-95A9-00C04FB925D3", KSAUDFNAME_MIDI); - # define KSAUDFNAME_MIDI DEFINE_GUIDNAMED(KSAUDFNAME_MIDI) - - # define STATIC_KSAUDFNAME_LINE_IN \ - 0x185FEDF9L, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("185FEDF9-9905-11D1-95A9-00C04FB925D3", KSAUDFNAME_LINE_IN); - # define KSAUDFNAME_LINE_IN DEFINE_GUIDNAMED(KSAUDFNAME_LINE_IN) - - # define STATIC_KSAUDFNAME_RECORDING_CONTROL \ - 0x185FEDFAL, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("185FEDFA-9905-11D1-95A9-00C04FB925D3", KSAUDFNAME_RECORDING_CONTROL); - # define KSAUDFNAME_RECORDING_CONTROL DEFINE_GUIDNAMED(KSAUDFNAME_RECORDING_CONTROL) - - # define STATIC_KSAUDFNAME_CD_AUDIO \ - 0x185FEDFBL, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("185FEDFB-9905-11D1-95A9-00C04FB925D3", KSAUDFNAME_CD_AUDIO); - # define KSAUDFNAME_CD_AUDIO DEFINE_GUIDNAMED(KSAUDFNAME_CD_AUDIO) - - # define STATIC_KSAUDFNAME_AUX_VOLUME \ - 0x185FEDFCL, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("185FEDFC-9905-11D1-95A9-00C04FB925D3", KSAUDFNAME_AUX_VOLUME); - # define KSAUDFNAME_AUX_VOLUME DEFINE_GUIDNAMED(KSAUDFNAME_AUX_VOLUME) - - # define STATIC_KSAUDFNAME_AUX_MUTE \ - 0x185FEDFDL, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("185FEDFD-9905-11D1-95A9-00C04FB925D3", KSAUDFNAME_AUX_MUTE); - # define KSAUDFNAME_AUX_MUTE DEFINE_GUIDNAMED(KSAUDFNAME_AUX_MUTE) - - # define STATIC_KSAUDFNAME_AUX \ - 0x185FEDFEL, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("185FEDFE-9905-11D1-95A9-00C04FB925D3", KSAUDFNAME_AUX); - # define KSAUDFNAME_AUX DEFINE_GUIDNAMED(KSAUDFNAME_AUX) - - # define STATIC_KSAUDFNAME_PC_SPEAKER \ - 0x185FEDFFL, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("185FEDFF-9905-11D1-95A9-00C04FB925D3", KSAUDFNAME_PC_SPEAKER); - # define KSAUDFNAME_PC_SPEAKER DEFINE_GUIDNAMED(KSAUDFNAME_PC_SPEAKER) - - # define STATIC_KSAUDFNAME_WAVE_OUT_MIX \ - 0x185FEE00L, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("185FEE00-9905-11D1-95A9-00C04FB925D3", KSAUDFNAME_WAVE_OUT_MIX); - # define KSAUDFNAME_WAVE_OUT_MIX DEFINE_GUIDNAMED(KSAUDFNAME_WAVE_OUT_MIX) - - # define STATIC_KSAUDFNAME_MONO_OUT \ - 0xf9b41dc3L, 0x96e2, 0x11d2, 0xac, 0x4c, 0x0, 0xc0, 0x4f, 0x8e, 0xfb, 0x68 -DEFINE_GUIDSTRUCT("F9B41DC3-96E2-11d2-AC4C-00C04F8EFB68", KSAUDFNAME_MONO_OUT); - # define KSAUDFNAME_MONO_OUT DEFINE_GUIDNAMED(KSAUDFNAME_MONO_OUT) - - # define STATIC_KSAUDFNAME_STEREO_MIX \ - 0xdff077L, 0x96e3, 0x11d2, 0xac, 0x4c, 0x0, 0xc0, 0x4f, 0x8e, 0xfb, 0x68 -DEFINE_GUIDSTRUCT("00DFF077-96E3-11d2-AC4C-00C04F8EFB68", KSAUDFNAME_STEREO_MIX); - # define KSAUDFNAME_STEREO_MIX DEFINE_GUIDNAMED(KSAUDFNAME_STEREO_MIX) - - # define STATIC_KSAUDFNAME_MONO_MIX \ - 0xdff078L, 0x96e3, 0x11d2, 0xac, 0x4c, 0x0, 0xc0, 0x4f, 0x8e, 0xfb, 0x68 -DEFINE_GUIDSTRUCT("00DFF078-96E3-11d2-AC4C-00C04F8EFB68", KSAUDFNAME_MONO_MIX); - # define KSAUDFNAME_MONO_MIX DEFINE_GUIDNAMED(KSAUDFNAME_MONO_MIX) - - # define STATIC_KSAUDFNAME_MONO_OUT_VOLUME \ - 0x1ad247ebL, 0x96e3, 0x11d2, 0xac, 0x4c, 0x0, 0xc0, 0x4f, 0x8e, 0xfb, 0x68 -DEFINE_GUIDSTRUCT("1AD247EB-96E3-11d2-AC4C-00C04F8EFB68", KSAUDFNAME_MONO_OUT_VOLUME); - # define KSAUDFNAME_MONO_OUT_VOLUME DEFINE_GUIDNAMED(KSAUDFNAME_MONO_OUT_VOLUME) - - # define STATIC_KSAUDFNAME_MONO_OUT_MUTE \ - 0x1ad247ecL, 0x96e3, 0x11d2, 0xac, 0x4c, 0x0, 0xc0, 0x4f, 0x8e, 0xfb, 0x68 -DEFINE_GUIDSTRUCT("1AD247EC-96E3-11d2-AC4C-00C04F8EFB68", KSAUDFNAME_MONO_OUT_MUTE); - # define KSAUDFNAME_MONO_OUT_MUTE DEFINE_GUIDNAMED(KSAUDFNAME_MONO_OUT_MUTE) - - # define STATIC_KSAUDFNAME_STEREO_MIX_VOLUME \ - 0x1ad247edL, 0x96e3, 0x11d2, 0xac, 0x4c, 0x0, 0xc0, 0x4f, 0x8e, 0xfb, 0x68 -DEFINE_GUIDSTRUCT("1AD247ED-96E3-11d2-AC4C-00C04F8EFB68", KSAUDFNAME_STEREO_MIX_VOLUME); - # define KSAUDFNAME_STEREO_MIX_VOLUME DEFINE_GUIDNAMED(KSAUDFNAME_STEREO_MIX_VOLUME) - - # define STATIC_KSAUDFNAME_STEREO_MIX_MUTE \ - 0x22b0eafdL, 0x96e3, 0x11d2, 0xac, 0x4c, 0x0, 0xc0, 0x4f, 0x8e, 0xfb, 0x68 -DEFINE_GUIDSTRUCT("22B0EAFD-96E3-11d2-AC4C-00C04F8EFB68", KSAUDFNAME_STEREO_MIX_MUTE); - # define KSAUDFNAME_STEREO_MIX_MUTE DEFINE_GUIDNAMED(KSAUDFNAME_STEREO_MIX_MUTE) - - # define STATIC_KSAUDFNAME_MONO_MIX_VOLUME \ - 0x22b0eafeL, 0x96e3, 0x11d2, 0xac, 0x4c, 0x0, 0xc0, 0x4f, 0x8e, 0xfb, 0x68 -DEFINE_GUIDSTRUCT("22B0EAFE-96E3-11d2-AC4C-00C04F8EFB68", KSAUDFNAME_MONO_MIX_VOLUME); - # define KSAUDFNAME_MONO_MIX_VOLUME DEFINE_GUIDNAMED(KSAUDFNAME_MONO_MIX_VOLUME) - - # define STATIC_KSAUDFNAME_MONO_MIX_MUTE \ - 0x2bc31d69L, 0x96e3, 0x11d2, 0xac, 0x4c, 0x0, 0xc0, 0x4f, 0x8e, 0xfb, 0x68 -DEFINE_GUIDSTRUCT("2BC31D69-96E3-11d2-AC4C-00C04F8EFB68", KSAUDFNAME_MONO_MIX_MUTE); - # define KSAUDFNAME_MONO_MIX_MUTE DEFINE_GUIDNAMED(KSAUDFNAME_MONO_MIX_MUTE) - - # define STATIC_KSAUDFNAME_MICROPHONE_BOOST \ - 0x2bc31d6aL, 0x96e3, 0x11d2, 0xac, 0x4c, 0x0, 0xc0, 0x4f, 0x8e, 0xfb, 0x68 -DEFINE_GUIDSTRUCT("2BC31D6A-96E3-11d2-AC4C-00C04F8EFB68", KSAUDFNAME_MICROPHONE_BOOST); - # define KSAUDFNAME_MICROPHONE_BOOST DEFINE_GUIDNAMED(KSAUDFNAME_MICROPHONE_BOOST) - - # define STATIC_KSAUDFNAME_ALTERNATE_MICROPHONE \ - 0x2bc31d6bL, 0x96e3, 0x11d2, 0xac, 0x4c, 0x0, 0xc0, 0x4f, 0x8e, 0xfb, 0x68 -DEFINE_GUIDSTRUCT("2BC31D6B-96E3-11d2-AC4C-00C04F8EFB68", KSAUDFNAME_ALTERNATE_MICROPHONE); - # define KSAUDFNAME_ALTERNATE_MICROPHONE DEFINE_GUIDNAMED(KSAUDFNAME_ALTERNATE_MICROPHONE) - - # define STATIC_KSAUDFNAME_3D_DEPTH \ - 0x63ff5747L, 0x991f, 0x11d2, 0xac, 0x4d, 0x0, 0xc0, 0x4f, 0x8e, 0xfb, 0x68 -DEFINE_GUIDSTRUCT("63FF5747-991F-11d2-AC4D-00C04F8EFB68", KSAUDFNAME_3D_DEPTH); - # define KSAUDFNAME_3D_DEPTH DEFINE_GUIDNAMED(KSAUDFNAME_3D_DEPTH) - - # define STATIC_KSAUDFNAME_3D_CENTER \ - 0x9f0670b4L, 0x991f, 0x11d2, 0xac, 0x4d, 0x0, 0xc0, 0x4f, 0x8e, 0xfb, 0x68 -DEFINE_GUIDSTRUCT("9F0670B4-991F-11d2-AC4D-00C04F8EFB68", KSAUDFNAME_3D_CENTER); - # define KSAUDFNAME_3D_CENTER DEFINE_GUIDNAMED(KSAUDFNAME_3D_CENTER) - - # define STATIC_KSAUDFNAME_VIDEO_VOLUME \ - 0x9b46e708L, 0x992a, 0x11d2, 0xac, 0x4d, 0x0, 0xc0, 0x4f, 0x8e, 0xfb, 0x68 -DEFINE_GUIDSTRUCT("9B46E708-992A-11d2-AC4D-00C04F8EFB68", KSAUDFNAME_VIDEO_VOLUME); - # define KSAUDFNAME_VIDEO_VOLUME DEFINE_GUIDNAMED(KSAUDFNAME_VIDEO_VOLUME) - - # define STATIC_KSAUDFNAME_VIDEO_MUTE \ - 0x9b46e709L, 0x992a, 0x11d2, 0xac, 0x4d, 0x0, 0xc0, 0x4f, 0x8e, 0xfb, 0x68 -DEFINE_GUIDSTRUCT("9B46E709-992A-11d2-AC4D-00C04F8EFB68", KSAUDFNAME_VIDEO_MUTE); - # define KSAUDFNAME_VIDEO_MUTE DEFINE_GUIDNAMED(KSAUDFNAME_VIDEO_MUTE) - - # define STATIC_KSAUDFNAME_VIDEO \ - 0x915daec4L, 0xa434, 0x11d2, 0xac, 0x52, 0x0, 0xc0, 0x4f, 0x8e, 0xfb, 0x68 -DEFINE_GUIDSTRUCT("915DAEC4-A434-11d2-AC52-00C04F8EFB68", KSAUDFNAME_VIDEO); - # define KSAUDFNAME_VIDEO DEFINE_GUIDNAMED(KSAUDFNAME_VIDEO) - - # define STATIC_KSAUDFNAME_PEAKMETER \ - 0x57e24340L, 0xfc5b, 0x4612, 0xa5, 0x62, 0x72, 0xb1, 0x1a, 0x29, 0xdf, 0xae -DEFINE_GUIDSTRUCT("57E24340-FC5B-4612-A562-72B11A29DFAE", KSAUDFNAME_PEAKMETER); - # define KSAUDFNAME_PEAKMETER DEFINE_GUIDNAMED(KSAUDFNAME_PEAKMETER) - - # define KSNODEPIN_STANDARD_IN 1 - # define KSNODEPIN_STANDARD_OUT 0 - - # define KSNODEPIN_SUM_MUX_IN 1 - # define KSNODEPIN_SUM_MUX_OUT 0 - - # define KSNODEPIN_DEMUX_IN 0 - # define KSNODEPIN_DEMUX_OUT 1 - - # define KSNODEPIN_AEC_RENDER_IN 1 - # define KSNODEPIN_AEC_RENDER_OUT 0 - # define KSNODEPIN_AEC_CAPTURE_IN 2 - # define KSNODEPIN_AEC_CAPTURE_OUT 3 - - # define STATIC_KSMETHODSETID_Wavetable \ - 0xDCEF31EBL, 0xD907, 0x11D0, 0x95, 0x83, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("DCEF31EB-D907-11D0-9583-00C04FB925D3", KSMETHODSETID_Wavetable); - # define KSMETHODSETID_Wavetable DEFINE_GUIDNAMED(KSMETHODSETID_Wavetable) - -typedef enum -{ - KSMETHOD_WAVETABLE_WAVE_ALLOC, - KSMETHOD_WAVETABLE_WAVE_FREE, - KSMETHOD_WAVETABLE_WAVE_FIND, - KSMETHOD_WAVETABLE_WAVE_WRITE -}KSMETHOD_WAVETABLE; - -typedef struct -{ - KSIDENTIFIER Identifier; - ULONG Size; - WINBOOL Looped; - ULONG LoopPoint; - WINBOOL InROM; - KSDATAFORMAT Format; -}KSWAVETABLE_WAVE_DESC, * PKSWAVETABLE_WAVE_DESC; - - # define STATIC_KSPROPSETID_Acoustic_Echo_Cancel \ - 0xd7a4af8bL, 0x3dc1, 0x4902, 0x91, 0xea, 0x8a, 0x15, 0xc9, 0x0e, 0x05, 0xb2 -DEFINE_GUIDSTRUCT("D7A4AF8B-3DC1-4902-91EA-8A15C90E05B2", KSPROPSETID_Acoustic_Echo_Cancel); - # define KSPROPSETID_Acoustic_Echo_Cancel DEFINE_GUIDNAMED(KSPROPSETID_Acoustic_Echo_Cancel) - -typedef enum -{ - KSPROPERTY_AEC_NOISE_FILL_ENABLE = 0, - KSPROPERTY_AEC_STATUS, - KSPROPERTY_AEC_MODE -}KSPROPERTY_AEC; - - # define AEC_STATUS_FD_HISTORY_UNINITIALIZED 0x0 - # define AEC_STATUS_FD_HISTORY_CONTINUOUSLY_CONVERGED 0x1 - # define AEC_STATUS_FD_HISTORY_PREVIOUSLY_DIVERGED 0x2 - # define AEC_STATUS_FD_CURRENTLY_CONVERGED 0x8 - - # define AEC_MODE_PASS_THROUGH 0x0 - # define AEC_MODE_HALF_DUPLEX 0x1 - # define AEC_MODE_FULL_DUPLEX 0x2 - - # define STATIC_KSPROPSETID_Wave \ - 0x924e54b0L, 0x630f, 0x11cf, 0xad, 0xa7, 0x08, 0x00, 0x3e, 0x30, 0x49, 0x4a -DEFINE_GUIDSTRUCT("924e54b0-630f-11cf-ada7-08003e30494a", KSPROPSETID_Wave); - # define KSPROPSETID_Wave DEFINE_GUIDNAMED(KSPROPSETID_Wave) - -typedef enum -{ - KSPROPERTY_WAVE_COMPATIBLE_CAPABILITIES, - KSPROPERTY_WAVE_INPUT_CAPABILITIES, - KSPROPERTY_WAVE_OUTPUT_CAPABILITIES, - KSPROPERTY_WAVE_BUFFER, - KSPROPERTY_WAVE_FREQUENCY, - KSPROPERTY_WAVE_VOLUME, - KSPROPERTY_WAVE_PAN -}KSPROPERTY_WAVE; - -typedef struct -{ - ULONG ulDeviceType; -}KSWAVE_COMPATCAPS, * PKSWAVE_COMPATCAPS; - - # define KSWAVE_COMPATCAPS_INPUT 0x00000000 - # define KSWAVE_COMPATCAPS_OUTPUT 0x00000001 - -typedef struct -{ - ULONG MaximumChannelsPerConnection; - ULONG MinimumBitsPerSample; - ULONG MaximumBitsPerSample; - ULONG MinimumSampleFrequency; - ULONG MaximumSampleFrequency; - ULONG TotalConnections; - ULONG ActiveConnections; -}KSWAVE_INPUT_CAPABILITIES, * PKSWAVE_INPUT_CAPABILITIES; - -typedef struct -{ - ULONG MaximumChannelsPerConnection; - ULONG MinimumBitsPerSample; - ULONG MaximumBitsPerSample; - ULONG MinimumSampleFrequency; - ULONG MaximumSampleFrequency; - ULONG TotalConnections; - ULONG StaticConnections; - ULONG StreamingConnections; - ULONG ActiveConnections; - ULONG ActiveStaticConnections; - ULONG ActiveStreamingConnections; - ULONG Total3DConnections; - ULONG Static3DConnections; - ULONG Streaming3DConnections; - ULONG Active3DConnections; - ULONG ActiveStatic3DConnections; - ULONG ActiveStreaming3DConnections; - ULONG TotalSampleMemory; - ULONG FreeSampleMemory; - ULONG LargestFreeContiguousSampleMemory; -}KSWAVE_OUTPUT_CAPABILITIES, * PKSWAVE_OUTPUT_CAPABILITIES; - -typedef struct -{ - LONG LeftAttenuation; - LONG RightAttenuation; -}KSWAVE_VOLUME, * PKSWAVE_VOLUME; - - # define KSWAVE_BUFFER_ATTRIBUTEF_LOOPING 0x00000001 - # define KSWAVE_BUFFER_ATTRIBUTEF_STATIC 0x00000002 - -typedef struct -{ - ULONG Attributes; - ULONG BufferSize; - PVOID BufferAddress; -}KSWAVE_BUFFER, * PKSWAVE_BUFFER; - - # define STATIC_KSMUSIC_TECHNOLOGY_PORT \ - 0x86C92E60L, 0x62E8, 0x11CF, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 -DEFINE_GUIDSTRUCT("86C92E60-62E8-11CF-A5D6-28DB04C10000", KSMUSIC_TECHNOLOGY_PORT); - # define KSMUSIC_TECHNOLOGY_PORT DEFINE_GUIDNAMED(KSMUSIC_TECHNOLOGY_PORT) - - # define STATIC_KSMUSIC_TECHNOLOGY_SQSYNTH \ - 0x0ECF4380L, 0x62E9, 0x11CF, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 -DEFINE_GUIDSTRUCT("0ECF4380-62E9-11CF-A5D6-28DB04C10000", KSMUSIC_TECHNOLOGY_SQSYNTH); - # define KSMUSIC_TECHNOLOGY_SQSYNTH DEFINE_GUIDNAMED(KSMUSIC_TECHNOLOGY_SQSYNTH) - - # define STATIC_KSMUSIC_TECHNOLOGY_FMSYNTH \ - 0x252C5C80L, 0x62E9, 0x11CF, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 -DEFINE_GUIDSTRUCT("252C5C80-62E9-11CF-A5D6-28DB04C10000", KSMUSIC_TECHNOLOGY_FMSYNTH); - # define KSMUSIC_TECHNOLOGY_FMSYNTH DEFINE_GUIDNAMED(KSMUSIC_TECHNOLOGY_FMSYNTH) - - # define STATIC_KSMUSIC_TECHNOLOGY_WAVETABLE \ - 0x394EC7C0L, 0x62E9, 0x11CF, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 -DEFINE_GUIDSTRUCT("394EC7C0-62E9-11CF-A5D6-28DB04C10000", KSMUSIC_TECHNOLOGY_WAVETABLE); - # define KSMUSIC_TECHNOLOGY_WAVETABLE DEFINE_GUIDNAMED(KSMUSIC_TECHNOLOGY_WAVETABLE) - - # define STATIC_KSMUSIC_TECHNOLOGY_SWSYNTH \ - 0x37407736L, 0x3620, 0x11D1, 0x85, 0xD3, 0x00, 0x00, 0xF8, 0x75, 0x43, 0x80 -DEFINE_GUIDSTRUCT("37407736-3620-11D1-85D3-0000F8754380", KSMUSIC_TECHNOLOGY_SWSYNTH); - # define KSMUSIC_TECHNOLOGY_SWSYNTH DEFINE_GUIDNAMED(KSMUSIC_TECHNOLOGY_SWSYNTH) - - # define STATIC_KSPROPSETID_WaveTable \ - 0x8539E660L, 0x62E9, 0x11CF, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 -DEFINE_GUIDSTRUCT("8539E660-62E9-11CF-A5D6-28DB04C10000", KSPROPSETID_WaveTable); - # define KSPROPSETID_WaveTable DEFINE_GUIDNAMED(KSPROPSETID_WaveTable) - -typedef enum -{ - KSPROPERTY_WAVETABLE_LOAD_SAMPLE, - KSPROPERTY_WAVETABLE_UNLOAD_SAMPLE, - KSPROPERTY_WAVETABLE_MEMORY, - KSPROPERTY_WAVETABLE_VERSION -}KSPROPERTY_WAVETABLE; - -typedef struct -{ - KSDATARANGE DataRange; - GUID Technology; - ULONG Channels; - ULONG Notes; - ULONG ChannelMask; -}KSDATARANGE_MUSIC, * PKSDATARANGE_MUSIC; - - # define STATIC_KSEVENTSETID_Cyclic \ - 0x142C1AC0L, 0x072A, 0x11D0, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 -DEFINE_GUIDSTRUCT("142C1AC0-072A-11D0-A5D6-28DB04C10000", KSEVENTSETID_Cyclic); - # define KSEVENTSETID_Cyclic DEFINE_GUIDNAMED(KSEVENTSETID_Cyclic) - -typedef enum -{ - KSEVENT_CYCLIC_TIME_INTERVAL -}KSEVENT_CYCLIC_TIME; - - # define STATIC_KSPROPSETID_Cyclic \ - 0x3FFEAEA0L, 0x2BEE, 0x11CF, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 -DEFINE_GUIDSTRUCT("3FFEAEA0-2BEE-11CF-A5D6-28DB04C10000", KSPROPSETID_Cyclic); - # define KSPROPSETID_Cyclic DEFINE_GUIDNAMED(KSPROPSETID_Cyclic) - -typedef enum -{ - KSPROPERTY_CYCLIC_POSITION -}KSPROPERTY_CYCLIC; - - # define STATIC_KSEVENTSETID_AudioControlChange \ - 0xE85E9698L, 0xFA2F, 0x11D1, 0x95, 0xBD, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3 -DEFINE_GUIDSTRUCT("E85E9698-FA2F-11D1-95BD-00C04FB925D3", KSEVENTSETID_AudioControlChange); - # define KSEVENTSETID_AudioControlChange DEFINE_GUIDNAMED(KSEVENTSETID_AudioControlChange) - -typedef enum -{ - KSEVENT_CONTROL_CHANGE -}KSEVENT_AUDIO_CONTROL_CHANGE; - - # define STATIC_KSEVENTSETID_LoopedStreaming \ - 0x4682B940L, 0xC6EF, 0x11D0, 0x96, 0xD8, 0x00, 0xAA, 0x00, 0x51, 0xE5, 0x1D -DEFINE_GUIDSTRUCT("4682B940-C6EF-11D0-96D8-00AA0051E51D", KSEVENTSETID_LoopedStreaming); - # define KSEVENTSETID_LoopedStreaming DEFINE_GUIDNAMED(KSEVENTSETID_LoopedStreaming) - -typedef enum -{ - KSEVENT_LOOPEDSTREAMING_POSITION -}KSEVENT_LOOPEDSTREAMING; - -typedef struct -{ - KSEVENTDATA KsEventData; - DWORDLONG Position; -}LOOPEDSTREAMING_POSITION_EVENT_DATA, * PLOOPEDSTREAMING_POSITION_EVENT_DATA; - - # define STATIC_KSPROPSETID_Sysaudio \ - 0xCBE3FAA0L, 0xCC75, 0x11D0, 0xB4, 0x65, 0x00, 0x00, 0x1A, 0x18, 0x18, 0xE6 -DEFINE_GUIDSTRUCT("CBE3FAA0-CC75-11D0-B465-00001A1818E6", KSPROPSETID_Sysaudio); - # define KSPROPSETID_Sysaudio DEFINE_GUIDNAMED(KSPROPSETID_Sysaudio) - -typedef enum -{ - KSPROPERTY_SYSAUDIO_DEVICE_COUNT = 1, - KSPROPERTY_SYSAUDIO_DEVICE_FRIENDLY_NAME = 2, - KSPROPERTY_SYSAUDIO_DEVICE_INSTANCE = 3, - KSPROPERTY_SYSAUDIO_DEVICE_INTERFACE_NAME = 4, - KSPROPERTY_SYSAUDIO_SELECT_GRAPH = 5, - KSPROPERTY_SYSAUDIO_CREATE_VIRTUAL_SOURCE = 6, - KSPROPERTY_SYSAUDIO_DEVICE_DEFAULT = 7, - KSPROPERTY_SYSAUDIO_INSTANCE_INFO = 14, - KSPROPERTY_SYSAUDIO_COMPONENT_ID = 16 -}KSPROPERTY_SYSAUDIO; - -typedef struct -{ - KSPROPERTY Property; - GUID PinCategory; - GUID PinName; -}SYSAUDIO_CREATE_VIRTUAL_SOURCE, * PSYSAUDIO_CREATE_VIRTUAL_SOURCE; - -typedef struct -{ - KSPROPERTY Property; - ULONG PinId; - ULONG NodeId; - ULONG Flags; - ULONG Reserved; -}SYSAUDIO_SELECT_GRAPH, * PSYSAUDIO_SELECT_GRAPH; - -typedef struct -{ - KSPROPERTY Property; - ULONG Flags; - ULONG DeviceNumber; -}SYSAUDIO_INSTANCE_INFO, * PSYSAUDIO_INSTANCE_INFO; - - # define SYSAUDIO_FLAGS_DONT_COMBINE_PINS 0x00000001 - - # define STATIC_KSPROPSETID_Sysaudio_Pin \ - 0xA3A53220L, 0xC6E4, 0x11D0, 0xB4, 0x65, 0x00, 0x00, 0x1A, 0x18, 0x18, 0xE6 -DEFINE_GUIDSTRUCT("A3A53220-C6E4-11D0-B465-00001A1818E6", KSPROPSETID_Sysaudio_Pin); - # define KSPROPSETID_Sysaudio_Pin DEFINE_GUIDNAMED(KSPROPSETID_Sysaudio_Pin) - -typedef enum -{ - KSPROPERTY_SYSAUDIO_ATTACH_VIRTUAL_SOURCE = 1 -}KSPROPERTY_SYSAUDIO_PIN; - -typedef struct -{ - KSPROPERTY Property; - ULONG MixerPinId; - ULONG Reserved; -}SYSAUDIO_ATTACH_VIRTUAL_SOURCE, * PSYSAUDIO_ATTACH_VIRTUAL_SOURCE; - -typedef struct -{ - KSPROPERTY Property; - ULONG NodeId; - ULONG Reserved; -}KSNODEPROPERTY, * PKSNODEPROPERTY; - -typedef struct -{ - KSNODEPROPERTY NodeProperty; - LONG Channel; - ULONG Reserved; -}KSNODEPROPERTY_AUDIO_CHANNEL, * PKSNODEPROPERTY_AUDIO_CHANNEL; - -typedef struct -{ - KSNODEPROPERTY NodeProperty; - ULONG DevSpecificId; - ULONG DeviceInfo; - ULONG Length; -}KSNODEPROPERTY_AUDIO_DEV_SPECIFIC, * PKSNODEPROPERTY_AUDIO_DEV_SPECIFIC; - -typedef struct -{ - KSNODEPROPERTY NodeProperty; - PVOID ListenerId; - # ifndef _WIN64 - ULONG Reserved; - # endif -}KSNODEPROPERTY_AUDIO_3D_LISTENER, * PKSNODEPROPERTY_AUDIO_3D_LISTENER; - -typedef struct -{ - KSNODEPROPERTY NodeProperty; - PVOID AppContext; - ULONG Length; - # ifndef _WIN64 - ULONG Reserved; - # endif -}KSNODEPROPERTY_AUDIO_PROPERTY, * PKSNODEPROPERTY_AUDIO_PROPERTY; - - # define STATIC_KSPROPSETID_AudioGfx \ - 0x79a9312eL, 0x59ae, 0x43b0, 0xa3, 0x50, 0x8b, 0x5, 0x28, 0x4c, 0xab, 0x24 -DEFINE_GUIDSTRUCT("79A9312E-59AE-43b0-A350-8B05284CAB24", KSPROPSETID_AudioGfx); - # define KSPROPSETID_AudioGfx DEFINE_GUIDNAMED(KSPROPSETID_AudioGfx) - -typedef enum -{ - KSPROPERTY_AUDIOGFX_RENDERTARGETDEVICEID, - KSPROPERTY_AUDIOGFX_CAPTURETARGETDEVICEID -}KSPROPERTY_AUDIOGFX; - - # define STATIC_KSPROPSETID_Linear \ - 0x5A2FFE80L, 0x16B9, 0x11D0, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 -DEFINE_GUIDSTRUCT("5A2FFE80-16B9-11D0-A5D6-28DB04C10000", KSPROPSETID_Linear); - # define KSPROPSETID_Linear DEFINE_GUIDNAMED(KSPROPSETID_Linear) - -typedef enum -{ - KSPROPERTY_LINEAR_POSITION -}KSPROPERTY_LINEAR; - - # define STATIC_KSDATAFORMAT_TYPE_MUSIC \ - 0xE725D360L, 0x62CC, 0x11CF, { 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 } -DEFINE_GUIDSTRUCT("E725D360-62CC-11CF-A5D6-28DB04C10000", KSDATAFORMAT_TYPE_MUSIC); - # define KSDATAFORMAT_TYPE_MUSIC DEFINE_GUIDNAMED(KSDATAFORMAT_TYPE_MUSIC) - - # define STATIC_KSDATAFORMAT_TYPE_MIDI \ - 0x7364696DL, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 -DEFINE_GUIDSTRUCT("7364696D-0000-0010-8000-00aa00389b71", KSDATAFORMAT_TYPE_MIDI); - # define KSDATAFORMAT_TYPE_MIDI DEFINE_GUIDNAMED(KSDATAFORMAT_TYPE_MIDI) - - # define STATIC_KSDATAFORMAT_SUBTYPE_MIDI \ - 0x1D262760L, 0xE957, 0x11CF, { 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 } -DEFINE_GUIDSTRUCT("1D262760-E957-11CF-A5D6-28DB04C10000", KSDATAFORMAT_SUBTYPE_MIDI); - # define KSDATAFORMAT_SUBTYPE_MIDI DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_MIDI) - - # define STATIC_KSDATAFORMAT_SUBTYPE_MIDI_BUS \ - 0x2CA15FA0L, 0x6CFE, 0x11CF, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 -DEFINE_GUIDSTRUCT("2CA15FA0-6CFE-11CF-A5D6-28DB04C10000", KSDATAFORMAT_SUBTYPE_MIDI_BUS); - # define KSDATAFORMAT_SUBTYPE_MIDI_BUS DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_MIDI_BUS) - - # define STATIC_KSDATAFORMAT_SUBTYPE_RIFFMIDI \ - 0x4995DAF0L, 0x9EE6, 0x11D0, 0xA4, 0x0E, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 -DEFINE_GUIDSTRUCT("4995DAF0-9EE6-11D0-A40E-00A0C9223196", KSDATAFORMAT_SUBTYPE_RIFFMIDI); - # define KSDATAFORMAT_SUBTYPE_RIFFMIDI DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_RIFFMIDI) - -typedef struct -{ - ULONG TimeDeltaMs; - - ULONG ByteCount; -}KSMUSICFORMAT, * PKSMUSICFORMAT; - - # define STATIC_KSDATAFORMAT_TYPE_STANDARD_ELEMENTARY_STREAM \ - 0x36523b11L, 0x8ee5, 0x11d1, 0x8c, 0xa3, 0x00, 0x60, 0xb0, 0x57, 0x66, 0x4a -DEFINE_GUIDSTRUCT("36523B11-8EE5-11d1-8CA3-0060B057664A", KSDATAFORMAT_TYPE_STANDARD_ELEMENTARY_STREAM); - # define KSDATAFORMAT_TYPE_STANDARD_ELEMENTARY_STREAM DEFINE_GUIDNAMED(KSDATAFORMAT_TYPE_STANDARD_ELEMENTARY_STREAM) - - # define STATIC_KSDATAFORMAT_TYPE_STANDARD_PES_PACKET \ - 0x36523b12L, 0x8ee5, 0x11d1, 0x8c, 0xa3, 0x00, 0x60, 0xb0, 0x57, 0x66, 0x4a -DEFINE_GUIDSTRUCT("36523B12-8EE5-11d1-8CA3-0060B057664A", KSDATAFORMAT_TYPE_STANDARD_PES_PACKET); - # define KSDATAFORMAT_TYPE_STANDARD_PES_PACKET DEFINE_GUIDNAMED(KSDATAFORMAT_TYPE_STANDARD_PES_PACKET) - - # define STATIC_KSDATAFORMAT_TYPE_STANDARD_PACK_HEADER \ - 0x36523b13L, 0x8ee5, 0x11d1, 0x8c, 0xa3, 0x00, 0x60, 0xb0, 0x57, 0x66, 0x4a -DEFINE_GUIDSTRUCT("36523B13-8EE5-11d1-8CA3-0060B057664A", KSDATAFORMAT_TYPE_STANDARD_PACK_HEADER); - # define KSDATAFORMAT_TYPE_STANDARD_PACK_HEADER DEFINE_GUIDNAMED(KSDATAFORMAT_TYPE_STANDARD_PACK_HEADER) - - # define STATIC_KSDATAFORMAT_SUBTYPE_STANDARD_MPEG1_VIDEO \ - 0x36523b21L, 0x8ee5, 0x11d1, 0x8c, 0xa3, 0x00, 0x60, 0xb0, 0x57, 0x66, 0x4a -DEFINE_GUIDSTRUCT("36523B21-8EE5-11d1-8CA3-0060B057664A", KSDATAFORMAT_SUBTYPE_STANDARD_MPEG1_VIDEO); - # define KSDATAFORMAT_SUBTYPE_STANDARD_MPEG1_VIDEO DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_STANDARD_MPEG1_VIDEO) - - # define STATIC_KSDATAFORMAT_SUBTYPE_STANDARD_MPEG1_AUDIO \ - 0x36523b22L, 0x8ee5, 0x11d1, 0x8c, 0xa3, 0x00, 0x60, 0xb0, 0x57, 0x66, 0x4a -DEFINE_GUIDSTRUCT("36523B22-8EE5-11d1-8CA3-0060B057664A", KSDATAFORMAT_SUBTYPE_STANDARD_MPEG1_AUDIO); - # define KSDATAFORMAT_SUBTYPE_STANDARD_MPEG1_AUDIO DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_STANDARD_MPEG1_AUDIO) - - # define STATIC_KSDATAFORMAT_SUBTYPE_STANDARD_MPEG2_VIDEO \ - 0x36523b23L, 0x8ee5, 0x11d1, 0x8c, 0xa3, 0x00, 0x60, 0xb0, 0x57, 0x66, 0x4a -DEFINE_GUIDSTRUCT("36523B23-8EE5-11d1-8CA3-0060B057664A", KSDATAFORMAT_SUBTYPE_STANDARD_MPEG2_VIDEO); - # define KSDATAFORMAT_SUBTYPE_STANDARD_MPEG2_VIDEO DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_STANDARD_MPEG2_VIDEO) - - # define STATIC_KSDATAFORMAT_SUBTYPE_STANDARD_MPEG2_AUDIO \ - 0x36523b24L, 0x8ee5, 0x11d1, 0x8c, 0xa3, 0x00, 0x60, 0xb0, 0x57, 0x66, 0x4a -DEFINE_GUIDSTRUCT("36523B24-8EE5-11d1-8CA3-0060B057664A", KSDATAFORMAT_SUBTYPE_STANDARD_MPEG2_AUDIO); - # define KSDATAFORMAT_SUBTYPE_STANDARD_MPEG2_AUDIO DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_STANDARD_MPEG2_AUDIO) - - # define STATIC_KSDATAFORMAT_SUBTYPE_STANDARD_AC3_AUDIO \ - 0x36523b25L, 0x8ee5, 0x11d1, 0x8c, 0xa3, 0x00, 0x60, 0xb0, 0x57, 0x66, 0x4a -DEFINE_GUIDSTRUCT("36523B25-8EE5-11d1-8CA3-0060B057664A", KSDATAFORMAT_SUBTYPE_STANDARD_AC3_AUDIO); - # define KSDATAFORMAT_SUBTYPE_STANDARD_AC3_AUDIO DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_STANDARD_AC3_AUDIO) - - # define STATIC_KSDATAFORMAT_SPECIFIER_DIALECT_MPEG1_VIDEO \ - 0x36523b31L, 0x8ee5, 0x11d1, 0x8c, 0xa3, 0x00, 0x60, 0xb0, 0x57, 0x66, 0x4a -DEFINE_GUIDSTRUCT("36523B31-8EE5-11d1-8CA3-0060B057664A", KSDATAFORMAT_SPECIFIER_DIALECT_MPEG1_VIDEO); - # define KSDATAFORMAT_SPECIFIER_DIALECT_MPEG1_VIDEO DEFINE_GUIDNAMED(KSDATAFORMAT_SPECIFIER_DIALECT_MPEG1_VIDEO) - - # define STATIC_KSDATAFORMAT_SPECIFIER_DIALECT_MPEG1_AUDIO \ - 0x36523b32L, 0x8ee5, 0x11d1, 0x8c, 0xa3, 0x00, 0x60, 0xb0, 0x57, 0x66, 0x4a -DEFINE_GUIDSTRUCT("36523B32-8EE5-11d1-8CA3-0060B057664A", KSDATAFORMAT_SPECIFIER_DIALECT_MPEG1_AUDIO); - # define KSDATAFORMAT_SPECIFIER_DIALECT_MPEG1_AUDIO DEFINE_GUIDNAMED(KSDATAFORMAT_SPECIFIER_DIALECT_MPEG1_AUDIO) - - # define STATIC_KSDATAFORMAT_SPECIFIER_DIALECT_MPEG2_VIDEO \ - 0x36523b33L, 0x8ee5, 0x11d1, 0x8c, 0xa3, 0x00, 0x60, 0xb0, 0x57, 0x66, 0x4a -DEFINE_GUIDSTRUCT("36523B33-8EE5-11d1-8CA3-0060B057664A", KSDATAFORMAT_SPECIFIER_DIALECT_MPEG2_VIDEO); - # define KSDATAFORMAT_SPECIFIER_DIALECT_MPEG2_VIDEO DEFINE_GUIDNAMED(KSDATAFORMAT_SPECIFIER_DIALECT_MPEG2_VIDEO) - - # define STATIC_KSDATAFORMAT_SPECIFIER_DIALECT_MPEG2_AUDIO \ - 0x36523b34L, 0x8ee5, 0x11d1, 0x8c, 0xa3, 0x00, 0x60, 0xb0, 0x57, 0x66, 0x4a -DEFINE_GUIDSTRUCT("36523B34-8EE5-11d1-8CA3-0060B057664A", KSDATAFORMAT_SPECIFIER_DIALECT_MPEG2_AUDIO); - # define KSDATAFORMAT_SPECIFIER_DIALECT_MPEG2_AUDIO DEFINE_GUIDNAMED(KSDATAFORMAT_SPECIFIER_DIALECT_MPEG2_AUDIO) - - # define STATIC_KSDATAFORMAT_SPECIFIER_DIALECT_AC3_AUDIO \ - 0x36523b35L, 0x8ee5, 0x11d1, 0x8c, 0xa3, 0x00, 0x60, 0xb0, 0x57, 0x66, 0x4a -DEFINE_GUIDSTRUCT("36523B35-8EE5-11d1-8CA3-0060B057664A", KSDATAFORMAT_SPECIFIER_DIALECT_AC3_AUDIO); - # define KSDATAFORMAT_SPECIFIER_DIALECT_AC3_AUDIO DEFINE_GUIDNAMED(KSDATAFORMAT_SPECIFIER_DIALECT_AC3_AUDIO) - - # define STATIC_KSDATAFORMAT_SUBTYPE_DSS_VIDEO \ - 0xa0af4f81L, 0xe163, 0x11d0, 0xba, 0xd9, 0x00, 0x60, 0x97, 0x44, 0x11, 0x1a -DEFINE_GUIDSTRUCT("a0af4f81-e163-11d0-bad9-00609744111a", KSDATAFORMAT_SUBTYPE_DSS_VIDEO); - # define KSDATAFORMAT_SUBTYPE_DSS_VIDEO DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_DSS_VIDEO) - - # define STATIC_KSDATAFORMAT_SUBTYPE_DSS_AUDIO \ - 0xa0af4f82L, 0xe163, 0x11d0, 0xba, 0xd9, 0x00, 0x60, 0x97, 0x44, 0x11, 0x1a -DEFINE_GUIDSTRUCT("a0af4f82-e163-11d0-bad9-00609744111a", KSDATAFORMAT_SUBTYPE_DSS_AUDIO); - # define KSDATAFORMAT_SUBTYPE_DSS_AUDIO DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_DSS_AUDIO) - - # define STATIC_KSDATAFORMAT_SUBTYPE_MPEG1Packet \ - 0xe436eb80, 0x524f, 0x11ce, 0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70 -DEFINE_GUIDSTRUCT("e436eb80-524f-11ce-9F53-0020af0ba770", KSDATAFORMAT_SUBTYPE_MPEG1Packet); - # define KSDATAFORMAT_SUBTYPE_MPEG1Packet DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_MPEG1Packet) - - # define STATIC_KSDATAFORMAT_SUBTYPE_MPEG1Payload \ - 0xe436eb81, 0x524f, 0x11ce, 0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70 -DEFINE_GUIDSTRUCT("e436eb81-524f-11ce-9F53-0020af0ba770", KSDATAFORMAT_SUBTYPE_MPEG1Payload); - # define KSDATAFORMAT_SUBTYPE_MPEG1Payload DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_MPEG1Payload) - - # define STATIC_KSDATAFORMAT_SUBTYPE_MPEG1Video \ - 0xe436eb86, 0x524f, 0x11ce, 0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70 -DEFINE_GUIDSTRUCT("e436eb86-524f-11ce-9f53-0020af0ba770", KSDATAFORMAT_SUBTYPE_MPEG1Video); - # define KSDATAFORMAT_SUBTYPE_MPEG1Video DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_MPEG1Video) - - # define STATIC_KSDATAFORMAT_SPECIFIER_MPEG1_VIDEO \ - 0x05589f82L, 0xc356, 0x11ce, 0xbf, 0x01, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a -DEFINE_GUIDSTRUCT("05589f82-c356-11ce-bf01-00aa0055595a", KSDATAFORMAT_SPECIFIER_MPEG1_VIDEO); - # define KSDATAFORMAT_SPECIFIER_MPEG1_VIDEO DEFINE_GUIDNAMED(KSDATAFORMAT_SPECIFIER_MPEG1_VIDEO) - - # define STATIC_KSDATAFORMAT_TYPE_MPEG2_PES \ - 0xe06d8020L, 0xdb46, 0x11cf, 0xb4, 0xd1, 0x00, 0x80, 0x5f, 0x6c, 0xbb, 0xea -DEFINE_GUIDSTRUCT("e06d8020-db46-11cf-b4d1-00805f6cbbea", KSDATAFORMAT_TYPE_MPEG2_PES); - # define KSDATAFORMAT_TYPE_MPEG2_PES DEFINE_GUIDNAMED(KSDATAFORMAT_TYPE_MPEG2_PES) - - # define STATIC_KSDATAFORMAT_TYPE_MPEG2_PROGRAM \ - 0xe06d8022L, 0xdb46, 0x11cf, 0xb4, 0xd1, 0x00, 0x80, 0x5f, 0x6c, 0xbb, 0xea -DEFINE_GUIDSTRUCT("e06d8022-db46-11cf-b4d1-00805f6cbbea", KSDATAFORMAT_TYPE_MPEG2_PROGRAM); - # define KSDATAFORMAT_TYPE_MPEG2_PROGRAM DEFINE_GUIDNAMED(KSDATAFORMAT_TYPE_MPEG2_PROGRAM) - - # define STATIC_KSDATAFORMAT_TYPE_MPEG2_TRANSPORT \ - 0xe06d8023L, 0xdb46, 0x11cf, 0xb4, 0xd1, 0x00, 0x80, 0x5f, 0x6c, 0xbb, 0xea -DEFINE_GUIDSTRUCT("e06d8023-db46-11cf-b4d1-00805f6cbbea", KSDATAFORMAT_TYPE_MPEG2_TRANSPORT); - # define KSDATAFORMAT_TYPE_MPEG2_TRANSPORT DEFINE_GUIDNAMED(KSDATAFORMAT_TYPE_MPEG2_TRANSPORT) - - # define STATIC_KSDATAFORMAT_SUBTYPE_MPEG2_VIDEO \ - 0xe06d8026L, 0xdb46, 0x11cf, 0xb4, 0xd1, 0x00, 0x80, 0x5f, 0x6c, 0xbb, 0xea -DEFINE_GUIDSTRUCT("e06d8026-db46-11cf-b4d1-00805f6cbbea", KSDATAFORMAT_SUBTYPE_MPEG2_VIDEO); - # define KSDATAFORMAT_SUBTYPE_MPEG2_VIDEO DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_MPEG2_VIDEO) - - # define STATIC_KSDATAFORMAT_SPECIFIER_MPEG2_VIDEO \ - 0xe06d80e3L, 0xdb46, 0x11cf, 0xb4, 0xd1, 0x00, 0x80, 0x5f, 0x6c, 0xbb, 0xea -DEFINE_GUIDSTRUCT("e06d80e3-db46-11cf-b4d1-00805f6cbbea", KSDATAFORMAT_SPECIFIER_MPEG2_VIDEO); - # define KSDATAFORMAT_SPECIFIER_MPEG2_VIDEO DEFINE_GUIDNAMED(KSDATAFORMAT_SPECIFIER_MPEG2_VIDEO) - - # define STATIC_KSPROPSETID_Mpeg2Vid \ - 0xC8E11B60L, 0x0CC9, 0x11D0, 0xBD, 0x69, 0x00, 0x35, 0x05, 0xC1, 0x03, 0xA9 -DEFINE_GUIDSTRUCT("C8E11B60-0CC9-11D0-BD69-003505C103A9", KSPROPSETID_Mpeg2Vid); - # define KSPROPSETID_Mpeg2Vid DEFINE_GUIDNAMED(KSPROPSETID_Mpeg2Vid) - -typedef enum -{ - KSPROPERTY_MPEG2VID_MODES, - KSPROPERTY_MPEG2VID_CUR_MODE, - KSPROPERTY_MPEG2VID_4_3_RECT, - KSPROPERTY_MPEG2VID_16_9_RECT, - KSPROPERTY_MPEG2VID_16_9_PANSCAN -}KSPROPERTY_MPEG2VID; - - # define KSMPEGVIDMODE_PANSCAN 0x0001 - # define KSMPEGVIDMODE_LTRBOX 0x0002 - # define KSMPEGVIDMODE_SCALE 0x0004 - -typedef struct _KSMPEGVID_RECT -{ - ULONG StartX; - ULONG StartY; - ULONG EndX; - ULONG EndY; -}KSMPEGVID_RECT, * PKSMPEGVID_RECT; - - # define STATIC_KSDATAFORMAT_SUBTYPE_MPEG2_AUDIO \ - 0xe06d802bL, 0xdb46, 0x11cf, 0xb4, 0xd1, 0x00, 0x80, 0x5f, 0x6c, 0xbb, 0xea -DEFINE_GUIDSTRUCT("e06d802b-db46-11cf-b4d1-00805f6cbbea", KSDATAFORMAT_SUBTYPE_MPEG2_AUDIO); - # define KSDATAFORMAT_SUBTYPE_MPEG2_AUDIO DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_MPEG2_AUDIO) - - # define STATIC_KSDATAFORMAT_SPECIFIER_MPEG2_AUDIO \ - 0xe06d80e5L, 0xdb46, 0x11cf, 0xb4, 0xd1, 0x00, 0x80, 0x5f, 0x6c, 0xbb, 0xea -DEFINE_GUIDSTRUCT("e06d80e5-db46-11cf-b4d1-00805f6cbbea", KSDATAFORMAT_SPECIFIER_MPEG2_AUDIO); - # define KSDATAFORMAT_SPECIFIER_MPEG2_AUDIO DEFINE_GUIDNAMED(KSDATAFORMAT_SPECIFIER_MPEG2_AUDIO) - - # define STATIC_KSDATAFORMAT_SUBTYPE_LPCM_AUDIO \ - 0xe06d8032L, 0xdb46, 0x11cf, 0xb4, 0xd1, 0x00, 0x80, 0x5f, 0x6c, 0xbb, 0xea -DEFINE_GUIDSTRUCT("e06d8032-db46-11cf-b4d1-00805f6cbbea", KSDATAFORMAT_SUBTYPE_LPCM_AUDIO); - # define KSDATAFORMAT_SUBTYPE_LPCM_AUDIO DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_LPCM_AUDIO) - - # define STATIC_KSDATAFORMAT_SPECIFIER_LPCM_AUDIO \ - 0xe06d80e6L, 0xdb46, 0x11cf, 0xb4, 0xd1, 0x00, 0x80, 0x5f, 0x6c, 0xbb, 0xea -DEFINE_GUIDSTRUCT("e06d80e6-db46-11cf-b4d1-00805f6cbbea", KSDATAFORMAT_SPECIFIER_LPCM_AUDIO); - # define KSDATAFORMAT_SPECIFIER_LPCM_AUDIO DEFINE_GUIDNAMED(KSDATAFORMAT_SPECIFIER_LPCM_AUDIO) - - # define STATIC_KSDATAFORMAT_SUBTYPE_AC3_AUDIO \ - 0xe06d802cL, 0xdb46, 0x11cf, 0xb4, 0xd1, 0x00, 0x80, 0x5f, 0x6c, 0xbb, 0xea -DEFINE_GUIDSTRUCT("e06d802c-db46-11cf-b4d1-00805f6cbbea", KSDATAFORMAT_SUBTYPE_AC3_AUDIO); - # define KSDATAFORMAT_SUBTYPE_AC3_AUDIO DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_AC3_AUDIO) - - # define STATIC_KSDATAFORMAT_SPECIFIER_AC3_AUDIO \ - 0xe06d80e4L, 0xdb46, 0x11cf, 0xb4, 0xd1, 0x00, 0x80, 0x5f, 0x6c, 0xbb, 0xea -DEFINE_GUIDSTRUCT("e06d80e4-db46-11cf-b4d1-00805f6cbbea", KSDATAFORMAT_SPECIFIER_AC3_AUDIO); - # define KSDATAFORMAT_SPECIFIER_AC3_AUDIO DEFINE_GUIDNAMED(KSDATAFORMAT_SPECIFIER_AC3_AUDIO) - - # define STATIC_KSPROPSETID_AC3 \ - 0xBFABE720L, 0x6E1F, 0x11D0, 0xBC, 0xF2, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00 -DEFINE_GUIDSTRUCT("BFABE720-6E1F-11D0-BCF2-444553540000", KSPROPSETID_AC3); - # define KSPROPSETID_AC3 DEFINE_GUIDNAMED(KSPROPSETID_AC3) - -typedef enum -{ - KSPROPERTY_AC3_ERROR_CONCEALMENT = 1, - KSPROPERTY_AC3_ALTERNATE_AUDIO, - KSPROPERTY_AC3_DOWNMIX, - KSPROPERTY_AC3_BIT_STREAM_MODE, - KSPROPERTY_AC3_DIALOGUE_LEVEL, - KSPROPERTY_AC3_LANGUAGE_CODE, - KSPROPERTY_AC3_ROOM_TYPE -}KSPROPERTY_AC3; - -typedef struct -{ - WINBOOL fRepeatPreviousBlock; - WINBOOL fErrorInCurrentBlock; -}KSAC3_ERROR_CONCEALMENT, * PKSAC3_ERROR_CONCEALMENT; - -typedef struct -{ - WINBOOL fStereo; - ULONG DualMode; -}KSAC3_ALTERNATE_AUDIO, * PKSAC3_ALTERNATE_AUDIO; - - # define KSAC3_ALTERNATE_AUDIO_1 1 - # define KSAC3_ALTERNATE_AUDIO_2 2 - # define KSAC3_ALTERNATE_AUDIO_BOTH 3 - -typedef struct -{ - WINBOOL fDownMix; - WINBOOL fDolbySurround; -}KSAC3_DOWNMIX, * PKSAC3_DOWNMIX; - -typedef struct -{ - LONG BitStreamMode; -}KSAC3_BIT_STREAM_MODE, * PKSAC3_BIT_STREAM_MODE; - - # define KSAC3_SERVICE_MAIN_AUDIO 0 - # define KSAC3_SERVICE_NO_DIALOG 1 - # define KSAC3_SERVICE_VISUALLY_IMPAIRED 2 - # define KSAC3_SERVICE_HEARING_IMPAIRED 3 - # define KSAC3_SERVICE_DIALOG_ONLY 4 - # define KSAC3_SERVICE_COMMENTARY 5 - # define KSAC3_SERVICE_EMERGENCY_FLASH 6 - # define KSAC3_SERVICE_VOICE_OVER 7 - -typedef struct -{ - ULONG DialogueLevel; -}KSAC3_DIALOGUE_LEVEL, * PKSAC3_DIALOGUE_LEVEL; - -typedef struct -{ - WINBOOL fLargeRoom; -}KSAC3_ROOM_TYPE, * PKSAC3_ROOM_TYPE; - - # define STATIC_KSDATAFORMAT_SUBTYPE_DTS_AUDIO \ - 0xe06d8033L, 0xdb46, 0x11cf, 0xb4, 0xd1, 0x00, 0x80, 0x5f, 0x6c, 0xbb, 0xea -DEFINE_GUIDSTRUCT("e06d8033-db46-11cf-b4d1-00805f6cbbea", KSDATAFORMAT_SUBTYPE_DTS_AUDIO); - # define KSDATAFORMAT_SUBTYPE_DTS_AUDIO DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_DTS_AUDIO) - - # define STATIC_KSDATAFORMAT_SUBTYPE_SDDS_AUDIO \ - 0xe06d8034L, 0xdb46, 0x11cf, 0xb4, 0xd1, 0x00, 0x80, 0x5f, 0x6c, 0xbb, 0xea -DEFINE_GUIDSTRUCT("e06d8034-db46-11cf-b4d1-00805f6cbbea", KSDATAFORMAT_SUBTYPE_SDDS_AUDIO); - # define KSDATAFORMAT_SUBTYPE_SDDS_AUDIO DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_SDDS_AUDIO) - - # define STATIC_KSPROPSETID_AudioDecoderOut \ - 0x6ca6e020L, 0x43bd, 0x11d0, 0xbd, 0x6a, 0x00, 0x35, 0x05, 0xc1, 0x03, 0xa9 -DEFINE_GUIDSTRUCT("6ca6e020-43bd-11d0-bd6a-003505c103a9", KSPROPSETID_AudioDecoderOut); - # define KSPROPSETID_AudioDecoderOut DEFINE_GUIDNAMED(KSPROPSETID_AudioDecoderOut) - -typedef enum -{ - KSPROPERTY_AUDDECOUT_MODES, - KSPROPERTY_AUDDECOUT_CUR_MODE -}KSPROPERTY_AUDDECOUT; - - # define KSAUDDECOUTMODE_STEREO_ANALOG 0x0001 - # define KSAUDDECOUTMODE_PCM_51 0x0002 - # define KSAUDDECOUTMODE_SPDIFF 0x0004 - - # define STATIC_KSDATAFORMAT_SUBTYPE_SUBPICTURE \ - 0xe06d802dL, 0xdb46, 0x11cf, 0xb4, 0xd1, 0x00, 0x80, 0x5f, 0x6c, 0xbb, 0xea -DEFINE_GUIDSTRUCT("e06d802d-db46-11cf-b4d1-00805f6cbbea", KSDATAFORMAT_SUBTYPE_SUBPICTURE); - # define KSDATAFORMAT_SUBTYPE_SUBPICTURE DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_SUBPICTURE) - - # define STATIC_KSPROPSETID_DvdSubPic \ - 0xac390460L, 0x43af, 0x11d0, 0xbd, 0x6a, 0x00, 0x35, 0x05, 0xc1, 0x03, 0xa9 -DEFINE_GUIDSTRUCT("ac390460-43af-11d0-bd6a-003505c103a9", KSPROPSETID_DvdSubPic); - # define KSPROPSETID_DvdSubPic DEFINE_GUIDNAMED(KSPROPSETID_DvdSubPic) - -typedef enum -{ - KSPROPERTY_DVDSUBPIC_PALETTE, - KSPROPERTY_DVDSUBPIC_HLI, - KSPROPERTY_DVDSUBPIC_COMPOSIT_ON -}KSPROPERTY_DVDSUBPIC; - -typedef struct _KS_DVD_YCrCb -{ - UCHAR Reserved; - UCHAR Y; - UCHAR Cr; - UCHAR Cb; -}KS_DVD_YCrCb, * PKS_DVD_YCrCb; - -typedef struct _KS_DVD_YUV -{ - UCHAR Reserved; - UCHAR Y; - UCHAR V; - UCHAR U; -}KS_DVD_YUV, * PKS_DVD_YUV; - -typedef struct _KSPROPERTY_SPPAL -{ - KS_DVD_YUV sppal[16]; -}KSPROPERTY_SPPAL, * PKSPROPERTY_SPPAL; - -typedef struct _KS_COLCON -{ - UCHAR emph1col : 4; - UCHAR emph2col : 4; - UCHAR backcol : 4; - UCHAR patcol : 4; - UCHAR emph1con : 4; - UCHAR emph2con : 4; - UCHAR backcon : 4; - UCHAR patcon : 4; -}KS_COLCON, * PKS_COLCON; - -typedef struct _KSPROPERTY_SPHLI -{ - USHORT HLISS; - USHORT Reserved; - ULONG StartPTM; - ULONG EndPTM; - USHORT StartX; - USHORT StartY; - USHORT StopX; - USHORT StopY; - KS_COLCON ColCon; -}KSPROPERTY_SPHLI, * PKSPROPERTY_SPHLI; - -typedef WINBOOL KSPROPERTY_COMPOSIT_ON, * PKSPROPERTY_COMPOSIT_ON; - - # define STATIC_KSPROPSETID_CopyProt \ - 0x0E8A0A40L, 0x6AEF, 0x11D0, 0x9E, 0xD0, 0x00, 0xA0, 0x24, 0xCA, 0x19, 0xB3 -DEFINE_GUIDSTRUCT("0E8A0A40-6AEF-11D0-9ED0-00A024CA19B3", KSPROPSETID_CopyProt); - # define KSPROPSETID_CopyProt DEFINE_GUIDNAMED(KSPROPSETID_CopyProt) - -typedef enum -{ - KSPROPERTY_DVDCOPY_CHLG_KEY = 0x01, - KSPROPERTY_DVDCOPY_DVD_KEY1, - KSPROPERTY_DVDCOPY_DEC_KEY2, - KSPROPERTY_DVDCOPY_TITLE_KEY, - KSPROPERTY_COPY_MACROVISION, - KSPROPERTY_DVDCOPY_REGION, - KSPROPERTY_DVDCOPY_SET_COPY_STATE, - KSPROPERTY_DVDCOPY_DISC_KEY = 0x80 -}KSPROPERTY_COPYPROT; - -typedef struct _KS_DVDCOPY_CHLGKEY -{ - BYTE ChlgKey[10]; - BYTE Reserved[2]; -}KS_DVDCOPY_CHLGKEY, * PKS_DVDCOPY_CHLGKEY; - -typedef struct _KS_DVDCOPY_BUSKEY -{ - BYTE BusKey[5]; - BYTE Reserved[1]; -}KS_DVDCOPY_BUSKEY, * PKS_DVDCOPY_BUSKEY; - -typedef struct _KS_DVDCOPY_DISCKEY -{ - BYTE DiscKey[2048]; -}KS_DVDCOPY_DISCKEY, * PKS_DVDCOPY_DISCKEY; - -typedef struct _KS_DVDCOPY_REGION -{ - UCHAR Reserved; - UCHAR RegionData; - UCHAR Reserved2[2]; -}KS_DVDCOPY_REGION, * PKS_DVDCOPY_REGION; - -typedef struct _KS_DVDCOPY_TITLEKEY -{ - ULONG KeyFlags; - ULONG ReservedNT[2]; - UCHAR TitleKey[6]; - UCHAR Reserved[2]; -}KS_DVDCOPY_TITLEKEY, * PKS_DVDCOPY_TITLEKEY; - -typedef struct _KS_COPY_MACROVISION -{ - ULONG MACROVISIONLevel; -}KS_COPY_MACROVISION, * PKS_COPY_MACROVISION; - -typedef struct _KS_DVDCOPY_SET_COPY_STATE -{ - ULONG DVDCopyState; -}KS_DVDCOPY_SET_COPY_STATE, * PKS_DVDCOPY_SET_COPY_STATE; - -typedef enum -{ - KS_DVDCOPYSTATE_INITIALIZE, - KS_DVDCOPYSTATE_INITIALIZE_TITLE, - KS_DVDCOPYSTATE_AUTHENTICATION_NOT_REQUIRED, - KS_DVDCOPYSTATE_AUTHENTICATION_REQUIRED, - KS_DVDCOPYSTATE_DONE -}KS_DVDCOPYSTATE; - -typedef enum -{ - KS_MACROVISION_DISABLED, - KS_MACROVISION_LEVEL1, - KS_MACROVISION_LEVEL2, - KS_MACROVISION_LEVEL3 -}KS_COPY_MACROVISION_LEVEL, * PKS_COPY_MACROVISION_LEVEL; - - # define KS_DVD_CGMS_RESERVED_MASK 0x00000078 - - # define KS_DVD_CGMS_COPY_PROTECT_MASK 0x00000018 - # define KS_DVD_CGMS_COPY_PERMITTED 0x00000000 - # define KS_DVD_CGMS_COPY_ONCE 0x00000010 - # define KS_DVD_CGMS_NO_COPY 0x00000018 - - # define KS_DVD_COPYRIGHT_MASK 0x00000040 - # define KS_DVD_NOT_COPYRIGHTED 0x00000000 - # define KS_DVD_COPYRIGHTED 0x00000040 - - # define KS_DVD_SECTOR_PROTECT_MASK 0x00000020 - # define KS_DVD_SECTOR_NOT_PROTECTED 0x00000000 - # define KS_DVD_SECTOR_PROTECTED 0x00000020 - - # define STATIC_KSCATEGORY_TVTUNER \ - 0xa799a800L, 0xa46d, 0x11d0, 0xa1, 0x8c, 0x00, 0xa0, 0x24, 0x01, 0xdc, 0xd4 -DEFINE_GUIDSTRUCT("a799a800-a46d-11d0-a18c-00a02401dcd4", KSCATEGORY_TVTUNER); - # define KSCATEGORY_TVTUNER DEFINE_GUIDNAMED(KSCATEGORY_TVTUNER) - - # define STATIC_KSCATEGORY_CROSSBAR \ - 0xa799a801L, 0xa46d, 0x11d0, 0xa1, 0x8c, 0x00, 0xa0, 0x24, 0x01, 0xdc, 0xd4 -DEFINE_GUIDSTRUCT("a799a801-a46d-11d0-a18c-00a02401dcd4", KSCATEGORY_CROSSBAR); - # define KSCATEGORY_CROSSBAR DEFINE_GUIDNAMED(KSCATEGORY_CROSSBAR) - - # define STATIC_KSCATEGORY_TVAUDIO \ - 0xa799a802L, 0xa46d, 0x11d0, 0xa1, 0x8c, 0x00, 0xa0, 0x24, 0x01, 0xdc, 0xd4 -DEFINE_GUIDSTRUCT("a799a802-a46d-11d0-a18c-00a02401dcd4", KSCATEGORY_TVAUDIO); - # define KSCATEGORY_TVAUDIO DEFINE_GUIDNAMED(KSCATEGORY_TVAUDIO) - - # define STATIC_KSCATEGORY_VPMUX \ - 0xa799a803L, 0xa46d, 0x11d0, 0xa1, 0x8c, 0x00, 0xa0, 0x24, 0x01, 0xdc, 0xd4 -DEFINE_GUIDSTRUCT("a799a803-a46d-11d0-a18c-00a02401dcd4", KSCATEGORY_VPMUX); - # define KSCATEGORY_VPMUX DEFINE_GUIDNAMED(KSCATEGORY_VPMUX) - - # define STATIC_KSCATEGORY_VBICODEC \ - 0x07dad660L, 0x22f1, 0x11d1, 0xa9, 0xf4, 0x00, 0xc0, 0x4f, 0xbb, 0xde, 0x8f -DEFINE_GUIDSTRUCT("07dad660-22f1-11d1-a9f4-00c04fbbde8f", KSCATEGORY_VBICODEC); - # define KSCATEGORY_VBICODEC DEFINE_GUIDNAMED(KSCATEGORY_VBICODEC) - - # define STATIC_KSDATAFORMAT_SUBTYPE_VPVideo \ - 0x5a9b6a40L, 0x1a22, 0x11d1, 0xba, 0xd9, 0x0, 0x60, 0x97, 0x44, 0x11, 0x1a -DEFINE_GUIDSTRUCT("5a9b6a40-1a22-11d1-bad9-00609744111a", KSDATAFORMAT_SUBTYPE_VPVideo); - # define KSDATAFORMAT_SUBTYPE_VPVideo DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_VPVideo) - - # define STATIC_KSDATAFORMAT_SUBTYPE_VPVBI \ - 0x5a9b6a41L, 0x1a22, 0x11d1, 0xba, 0xd9, 0x0, 0x60, 0x97, 0x44, 0x11, 0x1a -DEFINE_GUIDSTRUCT("5a9b6a41-1a22-11d1-bad9-00609744111a", KSDATAFORMAT_SUBTYPE_VPVBI); - # define KSDATAFORMAT_SUBTYPE_VPVBI DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_VPVBI) - - # define STATIC_KSDATAFORMAT_SPECIFIER_VIDEOINFO \ - 0x05589f80L, 0xc356, 0x11ce, 0xbf, 0x01, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a -DEFINE_GUIDSTRUCT("05589f80-c356-11ce-bf01-00aa0055595a", KSDATAFORMAT_SPECIFIER_VIDEOINFO); - # define KSDATAFORMAT_SPECIFIER_VIDEOINFO DEFINE_GUIDNAMED(KSDATAFORMAT_SPECIFIER_VIDEOINFO) - - # define STATIC_KSDATAFORMAT_SPECIFIER_VIDEOINFO2 \ - 0xf72a76A0L, 0xeb0a, 0x11d0, 0xac, 0xe4, 0x00, 0x00, 0xc0, 0xcc, 0x16, 0xba -DEFINE_GUIDSTRUCT("f72a76A0-eb0a-11d0-ace4-0000c0cc16ba", KSDATAFORMAT_SPECIFIER_VIDEOINFO2); - # define KSDATAFORMAT_SPECIFIER_VIDEOINFO2 DEFINE_GUIDNAMED(KSDATAFORMAT_SPECIFIER_VIDEOINFO2) - - # define STATIC_KSDATAFORMAT_TYPE_ANALOGVIDEO \ - 0x0482dde1L, 0x7817, 0x11cf, 0x8a, 0x03, 0x00, 0xaa, 0x00, 0x6e, 0xcb, 0x65 -DEFINE_GUIDSTRUCT("0482dde1-7817-11cf-8a03-00aa006ecb65", KSDATAFORMAT_TYPE_ANALOGVIDEO); - # define KSDATAFORMAT_TYPE_ANALOGVIDEO DEFINE_GUIDNAMED(KSDATAFORMAT_TYPE_ANALOGVIDEO) - - # define STATIC_KSDATAFORMAT_SPECIFIER_ANALOGVIDEO \ - 0x0482dde0L, 0x7817, 0x11cf, 0x8a, 0x03, 0x00, 0xaa, 0x00, 0x6e, 0xcb, 0x65 -DEFINE_GUIDSTRUCT("0482dde0-7817-11cf-8a03-00aa006ecb65", KSDATAFORMAT_SPECIFIER_ANALOGVIDEO); - # define KSDATAFORMAT_SPECIFIER_ANALOGVIDEO DEFINE_GUIDNAMED(KSDATAFORMAT_SPECIFIER_ANALOGVIDEO) - - # define STATIC_KSDATAFORMAT_TYPE_ANALOGAUDIO \ - 0x0482dee1L, 0x7817, 0x11cf, 0x8a, 0x03, 0x00, 0xaa, 0x00, 0x6e, 0xcb, 0x65 -DEFINE_GUIDSTRUCT("0482DEE1-7817-11cf-8a03-00aa006ecb65", KSDATAFORMAT_TYPE_ANALOGAUDIO); - # define KSDATAFORMAT_TYPE_ANALOGAUDIO DEFINE_GUIDNAMED(KSDATAFORMAT_TYPE_ANALOGAUDIO) - - # define STATIC_KSDATAFORMAT_SPECIFIER_VBI \ - 0xf72a76e0L, 0xeb0a, 0x11d0, 0xac, 0xe4, 0x00, 0x00, 0xc0, 0xcc, 0x16, 0xba -DEFINE_GUIDSTRUCT("f72a76e0-eb0a-11d0-ace4-0000c0cc16ba", KSDATAFORMAT_SPECIFIER_VBI); - # define KSDATAFORMAT_SPECIFIER_VBI DEFINE_GUIDNAMED(KSDATAFORMAT_SPECIFIER_VBI) - - # define STATIC_KSDATAFORMAT_TYPE_VBI \ - 0xf72a76e1L, 0xeb0a, 0x11d0, 0xac, 0xe4, 0x00, 0x00, 0xc0, 0xcc, 0x16, 0xba -DEFINE_GUIDSTRUCT("f72a76e1-eb0a-11d0-ace4-0000c0cc16ba", KSDATAFORMAT_TYPE_VBI); - # define KSDATAFORMAT_TYPE_VBI DEFINE_GUIDNAMED(KSDATAFORMAT_TYPE_VBI) - - # define STATIC_KSDATAFORMAT_SUBTYPE_RAW8 \ - 0xca20d9a0, 0x3e3e, 0x11d1, 0x9b, 0xf9, 0x0, 0xc0, 0x4f, 0xbb, 0xde, 0xbf -DEFINE_GUIDSTRUCT("ca20d9a0-3e3e-11d1-9bf9-00c04fbbdebf", KSDATAFORMAT_SUBTYPE_RAW8); - # define KSDATAFORMAT_SUBTYPE_RAW8 DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_RAW8) - - # define STATIC_KSDATAFORMAT_SUBTYPE_CC \ - 0x33214cc1, 0x11f, 0x11d2, 0xb4, 0xb1, 0x0, 0xa0, 0xd1, 0x2, 0xcf, 0xbe -DEFINE_GUIDSTRUCT("33214CC1-011F-11D2-B4B1-00A0D102CFBE", KSDATAFORMAT_SUBTYPE_CC); - # define KSDATAFORMAT_SUBTYPE_CC DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_CC) - - # define STATIC_KSDATAFORMAT_SUBTYPE_NABTS \ - 0xf72a76e2L, 0xeb0a, 0x11d0, 0xac, 0xe4, 0x00, 0x00, 0xc0, 0xcc, 0x16, 0xba -DEFINE_GUIDSTRUCT("f72a76e2-eb0a-11d0-ace4-0000c0cc16ba", KSDATAFORMAT_SUBTYPE_NABTS); - # define KSDATAFORMAT_SUBTYPE_NABTS DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_NABTS) - - # define STATIC_KSDATAFORMAT_SUBTYPE_TELETEXT \ - 0xf72a76e3L, 0xeb0a, 0x11d0, 0xac, 0xe4, 0x00, 0x00, 0xc0, 0xcc, 0x16, 0xba -DEFINE_GUIDSTRUCT("f72a76e3-eb0a-11d0-ace4-0000c0cc16ba", KSDATAFORMAT_SUBTYPE_TELETEXT); - # define KSDATAFORMAT_SUBTYPE_TELETEXT DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_TELETEXT) - - # define KS_BI_RGB 0L - # define KS_BI_RLE8 1L - # define KS_BI_RLE4 2L - # define KS_BI_BITFIELDS 3L - -typedef struct tagKS_RGBQUAD -{ - BYTE rgbBlue; - BYTE rgbGreen; - BYTE rgbRed; - BYTE rgbReserved; -}KS_RGBQUAD, * PKS_RGBQUAD; - - # define KS_iPALETTE_COLORS 256 - # define KS_iEGA_COLORS 16 - # define KS_iMASK_COLORS 3 - # define KS_iTRUECOLOR 16 - # define KS_iRED 0 - # define KS_iGREEN 1 - # define KS_iBLUE 2 - # define KS_iPALETTE 8 - # define KS_iMAXBITS 8 - # define KS_SIZE_EGA_PALETTE (KS_iEGA_COLORS * sizeof(KS_RGBQUAD)) - # define KS_SIZE_PALETTE (KS_iPALETTE_COLORS * sizeof(KS_RGBQUAD)) - -typedef struct tagKS_BITMAPINFOHEADER -{ - DWORD biSize; - LONG biWidth; - LONG biHeight; - WORD biPlanes; - WORD biBitCount; - DWORD biCompression; - DWORD biSizeImage; - LONG biXPelsPerMeter; - LONG biYPelsPerMeter; - DWORD biClrUsed; - DWORD biClrImportant; -}KS_BITMAPINFOHEADER, * PKS_BITMAPINFOHEADER; - -typedef struct tag_KS_TRUECOLORINFO -{ - DWORD dwBitMasks[KS_iMASK_COLORS]; - KS_RGBQUAD bmiColors[KS_iPALETTE_COLORS]; -}KS_TRUECOLORINFO, * PKS_TRUECOLORINFO; - - # define KS_WIDTHBYTES(bits) ((DWORD)(((bits) + 31) & (~31)) / 8) - # define KS_DIBWIDTHBYTES(bi) (DWORD)KS_WIDTHBYTES((DWORD)(bi).biWidth * (DWORD)(bi).biBitCount) - # define KS__DIBSIZE(bi) (KS_DIBWIDTHBYTES(bi) * (DWORD)(bi).biHeight) - # define KS_DIBSIZE(bi) ((bi).biHeight < 0 ? (-1) * (KS__DIBSIZE(bi)) : KS__DIBSIZE(bi)) - -typedef LONGLONG REFERENCE_TIME; - -typedef struct tagKS_VIDEOINFOHEADER -{ - RECT rcSource; - RECT rcTarget; - DWORD dwBitRate; - DWORD dwBitErrorRate; - REFERENCE_TIME AvgTimePerFrame; - KS_BITMAPINFOHEADER bmiHeader; -}KS_VIDEOINFOHEADER, * PKS_VIDEOINFOHEADER; - -typedef struct tagKS_VIDEOINFO -{ - RECT rcSource; - RECT rcTarget; - DWORD dwBitRate; - DWORD dwBitErrorRate; - REFERENCE_TIME AvgTimePerFrame; - KS_BITMAPINFOHEADER bmiHeader; - __MINGW_EXTENSION union - { - KS_RGBQUAD bmiColors[KS_iPALETTE_COLORS]; - DWORD dwBitMasks[KS_iMASK_COLORS]; - KS_TRUECOLORINFO TrueColorInfo; - }; -}KS_VIDEOINFO, * PKS_VIDEOINFO; - - # define KS_SIZE_MASKS (KS_iMASK_COLORS * sizeof(DWORD)) - # define KS_SIZE_PREHEADER (FIELD_OFFSET(KS_VIDEOINFOHEADER, bmiHeader)) - - # define KS_SIZE_VIDEOHEADER(pbmi) ((pbmi)->bmiHeader.biSize + KS_SIZE_PREHEADER) - -typedef struct tagKS_VBIINFOHEADER -{ - ULONG StartLine; - ULONG EndLine; - ULONG SamplingFrequency; - ULONG MinLineStartTime; - ULONG MaxLineStartTime; - ULONG ActualLineStartTime; - ULONG ActualLineEndTime; - ULONG VideoStandard; - ULONG SamplesPerLine; - ULONG StrideInBytes; - ULONG BufferSize; -}KS_VBIINFOHEADER, * PKS_VBIINFOHEADER; - - # define KS_VBIDATARATE_NABTS (5727272L) - # define KS_VBIDATARATE_CC (503493L) - # define KS_VBISAMPLINGRATE_4X_NABTS ((long)(4 * KS_VBIDATARATE_NABTS)) - # define KS_VBISAMPLINGRATE_47X_NABTS ((long)(27000000)) - # define KS_VBISAMPLINGRATE_5X_NABTS ((long)(5 * KS_VBIDATARATE_NABTS)) - - # define KS_47NABTS_SCALER (KS_VBISAMPLINGRATE_47X_NABTS / (double)KS_VBIDATARATE_NABTS) - -typedef struct tagKS_AnalogVideoInfo -{ - RECT rcSource; - RECT rcTarget; - DWORD dwActiveWidth; - DWORD dwActiveHeight; - REFERENCE_TIME AvgTimePerFrame; -}KS_ANALOGVIDEOINFO, * PKS_ANALOGVIDEOINFO; - - # define KS_TVTUNER_CHANGE_BEGIN_TUNE 0x0001L - # define KS_TVTUNER_CHANGE_END_TUNE 0x0002L - -typedef struct tagKS_TVTUNER_CHANGE_INFO -{ - DWORD dwFlags; - DWORD dwCountryCode; - DWORD dwAnalogVideoStandard; - DWORD dwChannel; -}KS_TVTUNER_CHANGE_INFO, * PKS_TVTUNER_CHANGE_INFO; - -typedef enum -{ - KS_MPEG2Level_Low, - KS_MPEG2Level_Main, - KS_MPEG2Level_High1440, - KS_MPEG2Level_High -}KS_MPEG2Level; - -typedef enum -{ - KS_MPEG2Profile_Simple, - KS_MPEG2Profile_Main, - KS_MPEG2Profile_SNRScalable, - KS_MPEG2Profile_SpatiallyScalable, - KS_MPEG2Profile_High -}KS_MPEG2Profile; - - # define KS_INTERLACE_IsInterlaced 0x00000001 - # define KS_INTERLACE_1FieldPerSample 0x00000002 - # define KS_INTERLACE_Field1First 0x00000004 - # define KS_INTERLACE_UNUSED 0x00000008 - # define KS_INTERLACE_FieldPatternMask 0x00000030 - # define KS_INTERLACE_FieldPatField1Only 0x00000000 - # define KS_INTERLACE_FieldPatField2Only 0x00000010 - # define KS_INTERLACE_FieldPatBothRegular 0x00000020 - # define KS_INTERLACE_FieldPatBothIrregular 0x00000030 - # define KS_INTERLACE_DisplayModeMask 0x000000c0 - # define KS_INTERLACE_DisplayModeBobOnly 0x00000000 - # define KS_INTERLACE_DisplayModeWeaveOnly 0x00000040 - # define KS_INTERLACE_DisplayModeBobOrWeave 0x00000080 - - # define KS_MPEG2_DoPanScan 0x00000001 - # define KS_MPEG2_DVDLine21Field1 0x00000002 - # define KS_MPEG2_DVDLine21Field2 0x00000004 - # define KS_MPEG2_SourceIsLetterboxed 0x00000008 - # define KS_MPEG2_FilmCameraMode 0x00000010 - # define KS_MPEG2_LetterboxAnalogOut 0x00000020 - # define KS_MPEG2_DSS_UserData 0x00000040 - # define KS_MPEG2_DVB_UserData 0x00000080 - # define KS_MPEG2_27MhzTimebase 0x00000100 - -typedef struct tagKS_VIDEOINFOHEADER2 -{ - RECT rcSource; - RECT rcTarget; - DWORD dwBitRate; - DWORD dwBitErrorRate; - REFERENCE_TIME AvgTimePerFrame; - DWORD dwInterlaceFlags; - DWORD dwCopyProtectFlags; - DWORD dwPictAspectRatioX; - DWORD dwPictAspectRatioY; - DWORD dwReserved1; - DWORD dwReserved2; - KS_BITMAPINFOHEADER bmiHeader; -}KS_VIDEOINFOHEADER2, * PKS_VIDEOINFOHEADER2; - -typedef struct tagKS_MPEG1VIDEOINFO -{ - KS_VIDEOINFOHEADER hdr; - DWORD dwStartTimeCode; - DWORD cbSequenceHeader; - BYTE bSequenceHeader[1]; -}KS_MPEG1VIDEOINFO, * PKS_MPEG1VIDEOINFO; - - # define KS_MAX_SIZE_MPEG1_SEQUENCE_INFO 140 - # define KS_SIZE_MPEG1VIDEOINFO(pv) (FIELD_OFFSET(KS_MPEG1VIDEOINFO, bSequenceHeader[0]) + (pv)->cbSequenceHeader) - # define KS_MPEG1_SEQUENCE_INFO(pv) ((const BYTE*)(pv)->bSequenceHeader) - -typedef struct tagKS_MPEGVIDEOINFO2 -{ - KS_VIDEOINFOHEADER2 hdr; - DWORD dwStartTimeCode; - DWORD cbSequenceHeader; - DWORD dwProfile; - DWORD dwLevel; - DWORD dwFlags; - DWORD bSequenceHeader[1]; -}KS_MPEGVIDEOINFO2, * PKS_MPEGVIDEOINFO2; - - # define KS_SIZE_MPEGVIDEOINFO2(pv) (FIELD_OFFSET(KS_MPEGVIDEOINFO2, bSequenceHeader[0]) + (pv)->cbSequenceHeader) - # define KS_MPEG1_SEQUENCE_INFO(pv) ((const BYTE*)(pv)->bSequenceHeader) - - # define KS_MPEGAUDIOINFO_27MhzTimebase 0x00000001 - -typedef struct tagKS_MPEAUDIOINFO -{ - DWORD dwFlags; - DWORD dwReserved1; - DWORD dwReserved2; - DWORD dwReserved3; -}KS_MPEGAUDIOINFO, * PKS_MPEGAUDIOINFO; - -typedef struct tagKS_DATAFORMAT_VIDEOINFOHEADER -{ - KSDATAFORMAT DataFormat; - KS_VIDEOINFOHEADER VideoInfoHeader; -}KS_DATAFORMAT_VIDEOINFOHEADER, * PKS_DATAFORMAT_VIDEOINFOHEADER; - -typedef struct tagKS_DATAFORMAT_VIDEOINFOHEADER2 -{ - KSDATAFORMAT DataFormat; - KS_VIDEOINFOHEADER2 VideoInfoHeader2; -}KS_DATAFORMAT_VIDEOINFOHEADER2, * PKS_DATAFORMAT_VIDEOINFOHEADER2; - -typedef struct tagKS_DATAFORMAT_VIDEOINFO_PALETTE -{ - KSDATAFORMAT DataFormat; - KS_VIDEOINFO VideoInfo; -}KS_DATAFORMAT_VIDEOINFO_PALETTE, * PKS_DATAFORMAT_VIDEOINFO_PALETTE; - -typedef struct tagKS_DATAFORMAT_VBIINFOHEADER -{ - KSDATAFORMAT DataFormat; - KS_VBIINFOHEADER VBIInfoHeader; -}KS_DATAFORMAT_VBIINFOHEADER, * PKS_DATAFORMAT_VBIINFOHEADER; - -typedef struct _KS_VIDEO_STREAM_CONFIG_CAPS -{ - GUID guid; - ULONG VideoStandard; - SIZE InputSize; - SIZE MinCroppingSize; - SIZE MaxCroppingSize; - int CropGranularityX; - int CropGranularityY; - int CropAlignX; - int CropAlignY; - SIZE MinOutputSize; - SIZE MaxOutputSize; - int OutputGranularityX; - int OutputGranularityY; - int StretchTapsX; - int StretchTapsY; - int ShrinkTapsX; - int ShrinkTapsY; - LONGLONG MinFrameInterval; - LONGLONG MaxFrameInterval; - LONG MinBitsPerSecond; - LONG MaxBitsPerSecond; -}KS_VIDEO_STREAM_CONFIG_CAPS, * PKS_VIDEO_STREAM_CONFIG_CAPS; - -typedef struct tagKS_DATARANGE_VIDEO -{ - KSDATARANGE DataRange; - WINBOOL bFixedSizeSamples; - WINBOOL bTemporalCompression; - DWORD StreamDescriptionFlags; - DWORD MemoryAllocationFlags; - KS_VIDEO_STREAM_CONFIG_CAPS ConfigCaps; - KS_VIDEOINFOHEADER VideoInfoHeader; -}KS_DATARANGE_VIDEO, * PKS_DATARANGE_VIDEO; - -typedef struct tagKS_DATARANGE_VIDEO2 -{ - KSDATARANGE DataRange; - WINBOOL bFixedSizeSamples; - WINBOOL bTemporalCompression; - DWORD StreamDescriptionFlags; - DWORD MemoryAllocationFlags; - KS_VIDEO_STREAM_CONFIG_CAPS ConfigCaps; - KS_VIDEOINFOHEADER2 VideoInfoHeader; -}KS_DATARANGE_VIDEO2, * PKS_DATARANGE_VIDEO2; - -typedef struct tagKS_DATARANGE_MPEG1_VIDEO -{ - KSDATARANGE DataRange; - WINBOOL bFixedSizeSamples; - WINBOOL bTemporalCompression; - DWORD StreamDescriptionFlags; - DWORD MemoryAllocationFlags; - KS_VIDEO_STREAM_CONFIG_CAPS ConfigCaps; - KS_MPEG1VIDEOINFO VideoInfoHeader; -}KS_DATARANGE_MPEG1_VIDEO, * PKS_DATARANGE_MPEG1_VIDEO; - -typedef struct tagKS_DATARANGE_MPEG2_VIDEO -{ - KSDATARANGE DataRange; - WINBOOL bFixedSizeSamples; - WINBOOL bTemporalCompression; - DWORD StreamDescriptionFlags; - DWORD MemoryAllocationFlags; - KS_VIDEO_STREAM_CONFIG_CAPS ConfigCaps; - KS_MPEGVIDEOINFO2 VideoInfoHeader; -}KS_DATARANGE_MPEG2_VIDEO, * PKS_DATARANGE_MPEG2_VIDEO; - -typedef struct tagKS_DATARANGE_VIDEO_PALETTE -{ - KSDATARANGE DataRange; - WINBOOL bFixedSizeSamples; - WINBOOL bTemporalCompression; - DWORD StreamDescriptionFlags; - DWORD MemoryAllocationFlags; - KS_VIDEO_STREAM_CONFIG_CAPS ConfigCaps; - KS_VIDEOINFO VideoInfo; -}KS_DATARANGE_VIDEO_PALETTE, * PKS_DATARANGE_VIDEO_PALETTE; - -typedef struct tagKS_DATARANGE_VIDEO_VBI -{ - KSDATARANGE DataRange; - WINBOOL bFixedSizeSamples; - WINBOOL bTemporalCompression; - DWORD StreamDescriptionFlags; - DWORD MemoryAllocationFlags; - KS_VIDEO_STREAM_CONFIG_CAPS ConfigCaps; - KS_VBIINFOHEADER VBIInfoHeader; -}KS_DATARANGE_VIDEO_VBI, * PKS_DATARANGE_VIDEO_VBI; - -typedef struct tagKS_DATARANGE_ANALOGVIDEO -{ - KSDATARANGE DataRange; - KS_ANALOGVIDEOINFO AnalogVideoInfo; -}KS_DATARANGE_ANALOGVIDEO, * PKS_DATARANGE_ANALOGVIDEO; - - # define KS_VIDEOSTREAM_PREVIEW 0x0001 - # define KS_VIDEOSTREAM_CAPTURE 0x0002 - # define KS_VIDEOSTREAM_VBI 0x0010 - # define KS_VIDEOSTREAM_NABTS 0x0020 - # define KS_VIDEOSTREAM_CC 0x0100 - # define KS_VIDEOSTREAM_EDS 0x0200 - # define KS_VIDEOSTREAM_TELETEXT 0x0400 - # define KS_VIDEOSTREAM_STILL 0x1000 - # define KS_VIDEOSTREAM_IS_VPE 0x8000 - - # define KS_VIDEO_ALLOC_VPE_SYSTEM 0x0001 - # define KS_VIDEO_ALLOC_VPE_DISPLAY 0x0002 - # define KS_VIDEO_ALLOC_VPE_AGP 0x0004 - - # define STATIC_KSPROPSETID_VBICAP_PROPERTIES \ - 0xf162c607, 0x7b35, 0x496f, 0xad, 0x7f, 0x2d, 0xca, 0x3b, 0x46, 0xb7, 0x18 -DEFINE_GUIDSTRUCT("F162C607-7B35-496f-AD7F-2DCA3B46B718", KSPROPSETID_VBICAP_PROPERTIES); - # define KSPROPSETID_VBICAP_PROPERTIES DEFINE_GUIDNAMED(KSPROPSETID_VBICAP_PROPERTIES) - -typedef enum -{ - KSPROPERTY_VBICAP_PROPERTIES_PROTECTION = 0x01 -}KSPROPERTY_VBICAP; - -typedef struct _VBICAP_PROPERTIES_PROTECTION_S -{ - KSPROPERTY Property; - ULONG StreamIndex; - ULONG Status; -}VBICAP_PROPERTIES_PROTECTION_S, * PVBICAP_PROPERTIES_PROTECTION_S; - - # define KS_VBICAP_PROTECTION_MV_PRESENT 0x0001L - # define KS_VBICAP_PROTECTION_MV_HARDWARE 0x0002L - # define KS_VBICAP_PROTECTION_MV_DETECTED 0x0004L - - # define KS_NABTS_GROUPID_ORIGINAL_CONTENT_BASE 0x800 - # define KS_NABTS_GROUPID_ORIGINAL_CONTENT_ADVERTISER_BASE 0x810 - - # define KS_NABTS_GROUPID_PRODUCTION_COMPANY_CONTENT_BASE 0x820 - # define KS_NABTS_GROUPID_PRODUCTION_COMPANY_ADVERTISER_BASE 0x830 - - # define KS_NABTS_GROUPID_SYNDICATED_SHOW_CONTENT_BASE 0x840 - # define KS_NABTS_GROUPID_SYNDICATED_SHOW_ADVERTISER_BASE 0x850 - - # define KS_NABTS_GROUPID_NETWORK_WIDE_CONTENT_BASE 0x860 - # define KS_NABTS_GROUPID_NETWORK_WIDE_ADVERTISER_BASE 0x870 - - # define KS_NABTS_GROUPID_TELEVISION_STATION_CONTENT_BASE 0x880 - # define KS_NABTS_GROUPID_TELEVISION_STATION_ADVERTISER_BASE 0x890 - - # define KS_NABTS_GROUPID_LOCAL_CABLE_SYSTEM_CONTENT_BASE 0x8A0 - # define KS_NABTS_GROUPID_LOCAL_CABLE_SYSTEM_ADVERTISER_BASE 0x8B0 - - # define KS_NABTS_GROUPID_MICROSOFT_RESERVED_TEST_DATA_BASE 0x8F0 - - # define STATIC_KSDATAFORMAT_TYPE_NABTS \ - 0xe757bca0, 0x39ac, 0x11d1, 0xa9, 0xf5, 0x0, 0xc0, 0x4f, 0xbb, 0xde, 0x8f -DEFINE_GUIDSTRUCT("E757BCA0-39AC-11d1-A9F5-00C04FBBDE8F", KSDATAFORMAT_TYPE_NABTS); - # define KSDATAFORMAT_TYPE_NABTS DEFINE_GUIDNAMED(KSDATAFORMAT_TYPE_NABTS) - - # define STATIC_KSDATAFORMAT_SUBTYPE_NABTS_FEC \ - 0xe757bca1, 0x39ac, 0x11d1, 0xa9, 0xf5, 0x0, 0xc0, 0x4f, 0xbb, 0xde, 0x8f -DEFINE_GUIDSTRUCT("E757BCA1-39AC-11d1-A9F5-00C04FBBDE8F", KSDATAFORMAT_SUBTYPE_NABTS_FEC); - # define KSDATAFORMAT_SUBTYPE_NABTS_FEC DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_NABTS_FEC) - - # define MAX_NABTS_VBI_LINES_PER_FIELD 11 - # define NABTS_LINES_PER_BUNDLE 16 - # define NABTS_PAYLOAD_PER_LINE 28 - # define NABTS_BYTES_PER_LINE 36 - -typedef struct _NABTSFEC_BUFFER -{ - ULONG dataSize; - USHORT groupID; - USHORT Reserved; - UCHAR data[NABTS_LINES_PER_BUNDLE * NABTS_PAYLOAD_PER_LINE]; -}NABTSFEC_BUFFER, * PNABTSFEC_BUFFER; - - # define STATIC_KSPROPSETID_VBICodecFiltering \ - 0xcafeb0caL, 0x8715, 0x11d0, 0xbd, 0x6a, 0x00, 0x35, 0xc0, 0xed, 0xba, 0xbe -DEFINE_GUIDSTRUCT("cafeb0ca-8715-11d0-bd6a-0035c0edbabe", KSPROPSETID_VBICodecFiltering); - # define KSPROPSETID_VBICodecFiltering DEFINE_GUIDNAMED(KSPROPSETID_VBICodecFiltering) - -typedef enum -{ - KSPROPERTY_VBICODECFILTERING_SCANLINES_REQUESTED_BIT_ARRAY = 0x01, - KSPROPERTY_VBICODECFILTERING_SCANLINES_DISCOVERED_BIT_ARRAY, - KSPROPERTY_VBICODECFILTERING_SUBSTREAMS_REQUESTED_BIT_ARRAY, - KSPROPERTY_VBICODECFILTERING_SUBSTREAMS_DISCOVERED_BIT_ARRAY, - KSPROPERTY_VBICODECFILTERING_STATISTICS -}KSPROPERTY_VBICODECFILTERING; - -typedef struct _VBICODECFILTERING_SCANLINES -{ - DWORD DwordBitArray[32]; -}VBICODECFILTERING_SCANLINES, * PVBICODECFILTERING_SCANLINES; - -typedef struct _VBICODECFILTERING_NABTS_SUBSTREAMS -{ - DWORD SubstreamMask[128]; -}VBICODECFILTERING_NABTS_SUBSTREAMS, * PVBICODECFILTERING_NABTS_SUBSTREAMS; - -typedef struct _VBICODECFILTERING_CC_SUBSTREAMS -{ - DWORD SubstreamMask; -}VBICODECFILTERING_CC_SUBSTREAMS, * PVBICODECFILTERING_CC_SUBSTREAMS; - - # define KS_CC_SUBSTREAM_ODD 0x0001L - # define KS_CC_SUBSTREAM_EVEN 0x0002L - - # define KS_CC_SUBSTREAM_FIELD1_MASK 0x00F0L - # define KS_CC_SUBSTREAM_SERVICE_CC1 0x0010L - # define KS_CC_SUBSTREAM_SERVICE_CC2 0x0020L - # define KS_CC_SUBSTREAM_SERVICE_T1 0x0040L - # define KS_CC_SUBSTREAM_SERVICE_T2 0x0080L - - # define KS_CC_SUBSTREAM_FIELD2_MASK 0x1F00L - # define KS_CC_SUBSTREAM_SERVICE_CC3 0x0100L - # define KS_CC_SUBSTREAM_SERVICE_CC4 0x0200L - # define KS_CC_SUBSTREAM_SERVICE_T3 0x0400L - # define KS_CC_SUBSTREAM_SERVICE_T4 0x0800L - # define KS_CC_SUBSTREAM_SERVICE_XDS 0x1000L - - # define CC_MAX_HW_DECODE_LINES 12 -typedef struct _CC_BYTE_PAIR -{ - BYTE Decoded[2]; - USHORT Reserved; -}CC_BYTE_PAIR, * PCC_BYTE_PAIR; - -typedef struct _CC_HW_FIELD -{ - VBICODECFILTERING_SCANLINES ScanlinesRequested; - ULONG fieldFlags; - LONGLONG PictureNumber; - CC_BYTE_PAIR Lines[CC_MAX_HW_DECODE_LINES]; -}CC_HW_FIELD, * PCC_HW_FIELD; - - # ifndef PACK_PRAGMAS_NOT_SUPPORTED - # include - # endif -typedef struct _NABTS_BUFFER_LINE -{ - BYTE Confidence; - BYTE Bytes[NABTS_BYTES_PER_LINE]; -}NABTS_BUFFER_LINE, * PNABTS_BUFFER_LINE; - - # define NABTS_BUFFER_PICTURENUMBER_SUPPORT 1 -typedef struct _NABTS_BUFFER -{ - VBICODECFILTERING_SCANLINES ScanlinesRequested; - LONGLONG PictureNumber; - NABTS_BUFFER_LINE NabtsLines[MAX_NABTS_VBI_LINES_PER_FIELD]; -}NABTS_BUFFER, * PNABTS_BUFFER; - # ifndef PACK_PRAGMAS_NOT_SUPPORTED - # include - # endif - - # define WST_TVTUNER_CHANGE_BEGIN_TUNE 0x1000L - # define WST_TVTUNER_CHANGE_END_TUNE 0x2000L - - # define MAX_WST_VBI_LINES_PER_FIELD 17 - # define WST_BYTES_PER_LINE 42 - -typedef struct _WST_BUFFER_LINE -{ - BYTE Confidence; - BYTE Bytes[WST_BYTES_PER_LINE]; -}WST_BUFFER_LINE, * PWST_BUFFER_LINE; - -typedef struct _WST_BUFFER -{ - VBICODECFILTERING_SCANLINES ScanlinesRequested; - WST_BUFFER_LINE WstLines[MAX_WST_VBI_LINES_PER_FIELD]; -}WST_BUFFER, * PWST_BUFFER; - -typedef struct _VBICODECFILTERING_STATISTICS_COMMON -{ - DWORD InputSRBsProcessed; - DWORD OutputSRBsProcessed; - DWORD SRBsIgnored; - DWORD InputSRBsMissing; - DWORD OutputSRBsMissing; - DWORD OutputFailures; - DWORD InternalErrors; - DWORD ExternalErrors; - DWORD InputDiscontinuities; - DWORD DSPFailures; - DWORD TvTunerChanges; - DWORD VBIHeaderChanges; - DWORD LineConfidenceAvg; - DWORD BytesOutput; -}VBICODECFILTERING_STATISTICS_COMMON, * PVBICODECFILTERING_STATISTICS_COMMON; - -typedef struct _VBICODECFILTERING_STATISTICS_COMMON_PIN -{ - DWORD SRBsProcessed; - DWORD SRBsIgnored; - DWORD SRBsMissing; - DWORD InternalErrors; - DWORD ExternalErrors; - DWORD Discontinuities; - DWORD LineConfidenceAvg; - DWORD BytesOutput; -}VBICODECFILTERING_STATISTICS_COMMON_PIN, * PVBICODECFILTERING_STATISTICS_COMMON_PIN; - -typedef struct _VBICODECFILTERING_STATISTICS_NABTS -{ - VBICODECFILTERING_STATISTICS_COMMON Common; - DWORD FECBundleBadLines; - DWORD FECQueueOverflows; - DWORD FECCorrectedLines; - DWORD FECUncorrectableLines; - DWORD BundlesProcessed; - DWORD BundlesSent2IP; - DWORD FilteredLines; -}VBICODECFILTERING_STATISTICS_NABTS, * PVBICODECFILTERING_STATISTICS_NABTS; - -typedef struct _VBICODECFILTERING_STATISTICS_NABTS_PIN -{ - VBICODECFILTERING_STATISTICS_COMMON_PIN Common; -}VBICODECFILTERING_STATISTICS_NABTS_PIN, * PVBICODECFILTERING_STATISTICS_NABTS_PIN; - -typedef struct _VBICODECFILTERING_STATISTICS_CC -{ - VBICODECFILTERING_STATISTICS_COMMON Common; -}VBICODECFILTERING_STATISTICS_CC, * PVBICODECFILTERING_STATISTICS_CC; - -typedef struct _VBICODECFILTERING_STATISTICS_CC_PIN -{ - VBICODECFILTERING_STATISTICS_COMMON_PIN Common; -}VBICODECFILTERING_STATISTICS_CC_PIN, * PVBICODECFILTERING_STATISTICS_CC_PIN; - -typedef struct _VBICODECFILTERING_STATISTICS_TELETEXT -{ - VBICODECFILTERING_STATISTICS_COMMON Common; -}VBICODECFILTERING_STATISTICS_TELETEXT, * PVBICODECFILTERING_STATISTICS_TELETEXT; - -typedef struct _VBICODECFILTERING_STATISTICS_TELETEXT_PIN -{ - VBICODECFILTERING_STATISTICS_COMMON_PIN Common; -}VBICODECFILTERING_STATISTICS_TELETEXT_PIN, * PVBICODECFILTERING_STATISTICS_TELETEXT_PIN; - -typedef struct -{ - KSPROPERTY Property; - VBICODECFILTERING_SCANLINES Scanlines; -}KSPROPERTY_VBICODECFILTERING_SCANLINES_S, * PKSPROPERTY_VBICODECFILTERING_SCANLINES_S; - -typedef struct -{ - KSPROPERTY Property; - VBICODECFILTERING_NABTS_SUBSTREAMS Substreams; -}KSPROPERTY_VBICODECFILTERING_NABTS_SUBSTREAMS_S, * PKSPROPERTY_VBICODECFILTERING_NABTS_SUBSTREAMS_S; - -typedef struct -{ - KSPROPERTY Property; - VBICODECFILTERING_CC_SUBSTREAMS Substreams; -}KSPROPERTY_VBICODECFILTERING_CC_SUBSTREAMS_S, * PKSPROPERTY_VBICODECFILTERING_CC_SUBSTREAMS_S; - -typedef struct -{ - KSPROPERTY Property; - VBICODECFILTERING_STATISTICS_COMMON Statistics; -}KSPROPERTY_VBICODECFILTERING_STATISTICS_COMMON_S, * PKSPROPERTY_VBICODECFILTERING_STATISTICS_COMMON_S; - -typedef struct -{ - KSPROPERTY Property; - VBICODECFILTERING_STATISTICS_COMMON_PIN Statistics; -}KSPROPERTY_VBICODECFILTERING_STATISTICS_COMMON_PIN_S, * PKSPROPERTY_VBICODECFILTERING_STATISTICS_COMMON_PIN_S; - -typedef struct -{ - KSPROPERTY Property; - VBICODECFILTERING_STATISTICS_NABTS Statistics; -}KSPROPERTY_VBICODECFILTERING_STATISTICS_NABTS_S, * PKSPROPERTY_VBICODECFILTERING_STATISTICS_NABTS_S; - -typedef struct -{ - KSPROPERTY Property; - VBICODECFILTERING_STATISTICS_NABTS_PIN Statistics; -}KSPROPERTY_VBICODECFILTERING_STATISTICS_NABTS_PIN_S, * PKSPROPERTY_VBICODECFILTERING_STATISTICS_NABTS_PIN_S; - -typedef struct -{ - KSPROPERTY Property; - VBICODECFILTERING_STATISTICS_CC Statistics; -}KSPROPERTY_VBICODECFILTERING_STATISTICS_CC_S, * PKSPROPERTY_VBICODECFILTERING_STATISTICS_CC_S; - -typedef struct -{ - KSPROPERTY Property; - VBICODECFILTERING_STATISTICS_CC_PIN Statistics; -}KSPROPERTY_VBICODECFILTERING_STATISTICS_CC_PIN_S, * PKSPROPERTY_VBICODECFILTERING_STATISTICS_CC_PIN_S; - - # define STATIC_PINNAME_VIDEO_CAPTURE \ - 0xfb6c4281, 0x353, 0x11d1, 0x90, 0x5f, 0x0, 0x0, 0xc0, 0xcc, 0x16, 0xba - # define STATIC_PINNAME_CAPTURE STATIC_PINNAME_VIDEO_CAPTURE -DEFINE_GUIDSTRUCT("FB6C4281-0353-11d1-905F-0000C0CC16BA", PINNAME_VIDEO_CAPTURE); - # define PINNAME_VIDEO_CAPTURE DEFINE_GUIDNAMED(PINNAME_VIDEO_CAPTURE) - # define PINNAME_CAPTURE PINNAME_VIDEO_CAPTURE - - # define STATIC_PINNAME_VIDEO_CC_CAPTURE \ - 0x1aad8061, 0x12d, 0x11d2, 0xb4, 0xb1, 0x0, 0xa0, 0xd1, 0x2, 0xcf, 0xbe - # define STATIC_PINNAME_CC_CAPTURE STATIC_PINNAME_VIDEO_CC_CAPTURE -DEFINE_GUIDSTRUCT("1AAD8061-012D-11d2-B4B1-00A0D102CFBE", PINNAME_VIDEO_CC_CAPTURE); - # define PINNAME_VIDEO_CC_CAPTURE DEFINE_GUIDNAMED(PINNAME_VIDEO_CC_CAPTURE) - - # define STATIC_PINNAME_VIDEO_NABTS_CAPTURE \ - 0x29703660, 0x498a, 0x11d2, 0xb4, 0xb1, 0x0, 0xa0, 0xd1, 0x2, 0xcf, 0xbe - # define STATIC_PINNAME_NABTS_CAPTURE STATIC_PINNAME_VIDEO_NABTS_CAPTURE -DEFINE_GUIDSTRUCT("29703660-498A-11d2-B4B1-00A0D102CFBE", PINNAME_VIDEO_NABTS_CAPTURE); - # define PINNAME_VIDEO_NABTS_CAPTURE DEFINE_GUIDNAMED(PINNAME_VIDEO_NABTS_CAPTURE) - - # define STATIC_PINNAME_VIDEO_PREVIEW \ - 0xfb6c4282, 0x353, 0x11d1, 0x90, 0x5f, 0x0, 0x0, 0xc0, 0xcc, 0x16, 0xba - # define STATIC_PINNAME_PREVIEW STATIC_PINNAME_VIDEO_PREVIEW -DEFINE_GUIDSTRUCT("FB6C4282-0353-11d1-905F-0000C0CC16BA", PINNAME_VIDEO_PREVIEW); - # define PINNAME_VIDEO_PREVIEW DEFINE_GUIDNAMED(PINNAME_VIDEO_PREVIEW) - # define PINNAME_PREVIEW PINNAME_VIDEO_PREVIEW - - # define STATIC_PINNAME_VIDEO_ANALOGVIDEOIN \ - 0xfb6c4283, 0x353, 0x11d1, 0x90, 0x5f, 0x0, 0x0, 0xc0, 0xcc, 0x16, 0xba -DEFINE_GUIDSTRUCT("FB6C4283-0353-11d1-905F-0000C0CC16BA", PINNAME_VIDEO_ANALOGVIDEOIN); - # define PINNAME_VIDEO_ANALOGVIDEOIN DEFINE_GUIDNAMED(PINNAME_VIDEO_ANALOGVIDEOIN) - - # define STATIC_PINNAME_VIDEO_VBI \ - 0xfb6c4284, 0x353, 0x11d1, 0x90, 0x5f, 0x0, 0x0, 0xc0, 0xcc, 0x16, 0xba -DEFINE_GUIDSTRUCT("FB6C4284-0353-11d1-905F-0000C0CC16BA", PINNAME_VIDEO_VBI); - # define PINNAME_VIDEO_VBI DEFINE_GUIDNAMED(PINNAME_VIDEO_VBI) - - # define STATIC_PINNAME_VIDEO_VIDEOPORT \ - 0xfb6c4285, 0x353, 0x11d1, 0x90, 0x5f, 0x0, 0x0, 0xc0, 0xcc, 0x16, 0xba -DEFINE_GUIDSTRUCT("FB6C4285-0353-11d1-905F-0000C0CC16BA", PINNAME_VIDEO_VIDEOPORT); - # define PINNAME_VIDEO_VIDEOPORT DEFINE_GUIDNAMED(PINNAME_VIDEO_VIDEOPORT) - - # define STATIC_PINNAME_VIDEO_NABTS \ - 0xfb6c4286, 0x353, 0x11d1, 0x90, 0x5f, 0x0, 0x0, 0xc0, 0xcc, 0x16, 0xba -DEFINE_GUIDSTRUCT("FB6C4286-0353-11d1-905F-0000C0CC16BA", PINNAME_VIDEO_NABTS); - # define PINNAME_VIDEO_NABTS DEFINE_GUIDNAMED(PINNAME_VIDEO_NABTS) - - # define STATIC_PINNAME_VIDEO_EDS \ - 0xfb6c4287, 0x353, 0x11d1, 0x90, 0x5f, 0x0, 0x0, 0xc0, 0xcc, 0x16, 0xba -DEFINE_GUIDSTRUCT("FB6C4287-0353-11d1-905F-0000C0CC16BA", PINNAME_VIDEO_EDS); - # define PINNAME_VIDEO_EDS DEFINE_GUIDNAMED(PINNAME_VIDEO_EDS) - - # define STATIC_PINNAME_VIDEO_TELETEXT \ - 0xfb6c4288, 0x353, 0x11d1, 0x90, 0x5f, 0x0, 0x0, 0xc0, 0xcc, 0x16, 0xba -DEFINE_GUIDSTRUCT("FB6C4288-0353-11d1-905F-0000C0CC16BA", PINNAME_VIDEO_TELETEXT); - # define PINNAME_VIDEO_TELETEXT DEFINE_GUIDNAMED(PINNAME_VIDEO_TELETEXT) - - # define STATIC_PINNAME_VIDEO_CC \ - 0xfb6c4289, 0x353, 0x11d1, 0x90, 0x5f, 0x0, 0x0, 0xc0, 0xcc, 0x16, 0xba -DEFINE_GUIDSTRUCT("FB6C4289-0353-11d1-905F-0000C0CC16BA", PINNAME_VIDEO_CC); - # define PINNAME_VIDEO_CC DEFINE_GUIDNAMED(PINNAME_VIDEO_CC) - - # define STATIC_PINNAME_VIDEO_STILL \ - 0xfb6c428A, 0x353, 0x11d1, 0x90, 0x5f, 0x0, 0x0, 0xc0, 0xcc, 0x16, 0xba -DEFINE_GUIDSTRUCT("FB6C428A-0353-11d1-905F-0000C0CC16BA", PINNAME_VIDEO_STILL); - # define PINNAME_VIDEO_STILL DEFINE_GUIDNAMED(PINNAME_VIDEO_STILL) - - # define STATIC_PINNAME_VIDEO_TIMECODE \ - 0xfb6c428B, 0x353, 0x11d1, 0x90, 0x5f, 0x0, 0x0, 0xc0, 0xcc, 0x16, 0xba -DEFINE_GUIDSTRUCT("FB6C428B-0353-11d1-905F-0000C0CC16BA", PINNAME_VIDEO_TIMECODE); - # define PINNAME_VIDEO_TIMECODE DEFINE_GUIDNAMED(PINNAME_VIDEO_TIMECODE) - - # define STATIC_PINNAME_VIDEO_VIDEOPORT_VBI \ - 0xfb6c428C, 0x353, 0x11d1, 0x90, 0x5f, 0x0, 0x0, 0xc0, 0xcc, 0x16, 0xba -DEFINE_GUIDSTRUCT("FB6C428C-0353-11d1-905F-0000C0CC16BA", PINNAME_VIDEO_VIDEOPORT_VBI); - # define PINNAME_VIDEO_VIDEOPORT_VBI DEFINE_GUIDNAMED(PINNAME_VIDEO_VIDEOPORT_VBI) - - # define KS_VIDEO_FLAG_FRAME 0x0000L - # define KS_VIDEO_FLAG_FIELD1 0x0001L - # define KS_VIDEO_FLAG_FIELD2 0x0002L - - # define KS_VIDEO_FLAG_I_FRAME 0x0000L - # define KS_VIDEO_FLAG_P_FRAME 0x0010L - # define KS_VIDEO_FLAG_B_FRAME 0x0020L - -typedef struct tagKS_FRAME_INFO -{ - ULONG ExtendedHeaderSize; - DWORD dwFrameFlags; - LONGLONG PictureNumber; - LONGLONG DropCount; - HANDLE hDirectDraw; - HANDLE hSurfaceHandle; - RECT DirectDrawRect; - - DWORD Reserved1; - DWORD Reserved2; - DWORD Reserved3; - DWORD Reserved4; -}KS_FRAME_INFO, * PKS_FRAME_INFO; - - # define KS_VBI_FLAG_FIELD1 0x0001L - # define KS_VBI_FLAG_FIELD2 0x0002L - - # define KS_VBI_FLAG_MV_PRESENT 0x0100L - # define KS_VBI_FLAG_MV_HARDWARE 0x0200L - # define KS_VBI_FLAG_MV_DETECTED 0x0400L - - # define KS_VBI_FLAG_TVTUNER_CHANGE 0x0010L - # define KS_VBI_FLAG_VBIINFOHEADER_CHANGE 0x0020L - -typedef struct tagKS_VBI_FRAME_INFO -{ - ULONG ExtendedHeaderSize; - DWORD dwFrameFlags; - LONGLONG PictureNumber; - LONGLONG DropCount; - DWORD dwSamplingFrequency; - KS_TVTUNER_CHANGE_INFO TvTunerChangeInfo; - KS_VBIINFOHEADER VBIInfoHeader; -}KS_VBI_FRAME_INFO, * PKS_VBI_FRAME_INFO; - -typedef enum -{ - KS_AnalogVideo_None = 0x00000000, - KS_AnalogVideo_NTSC_M = 0x00000001, - KS_AnalogVideo_NTSC_M_J = 0x00000002, - KS_AnalogVideo_NTSC_433 = 0x00000004, - KS_AnalogVideo_PAL_B = 0x00000010, - KS_AnalogVideo_PAL_D = 0x00000020, - KS_AnalogVideo_PAL_G = 0x00000040, - KS_AnalogVideo_PAL_H = 0x00000080, - KS_AnalogVideo_PAL_I = 0x00000100, - KS_AnalogVideo_PAL_M = 0x00000200, - KS_AnalogVideo_PAL_N = 0x00000400, - KS_AnalogVideo_PAL_60 = 0x00000800, - KS_AnalogVideo_SECAM_B = 0x00001000, - KS_AnalogVideo_SECAM_D = 0x00002000, - KS_AnalogVideo_SECAM_G = 0x00004000, - KS_AnalogVideo_SECAM_H = 0x00008000, - KS_AnalogVideo_SECAM_K = 0x00010000, - KS_AnalogVideo_SECAM_K1 = 0x00020000, - KS_AnalogVideo_SECAM_L = 0x00040000, - KS_AnalogVideo_SECAM_L1 = 0x00080000, - KS_AnalogVideo_PAL_N_COMBO = 0x00100000 -}KS_AnalogVideoStandard; - - # define KS_AnalogVideo_NTSC_Mask 0x00000007 - # define KS_AnalogVideo_PAL_Mask 0x00100FF0 - # define KS_AnalogVideo_SECAM_Mask 0x000FF000 - - # define STATIC_PROPSETID_ALLOCATOR_CONTROL \ - 0x53171960, 0x148e, 0x11d2, 0x99, 0x79, 0x0, 0x0, 0xc0, 0xcc, 0x16, 0xba -DEFINE_GUIDSTRUCT("53171960-148E-11d2-9979-0000C0CC16BA", PROPSETID_ALLOCATOR_CONTROL); - # define PROPSETID_ALLOCATOR_CONTROL DEFINE_GUIDNAMED(PROPSETID_ALLOCATOR_CONTROL) - -typedef enum -{ - KSPROPERTY_ALLOCATOR_CONTROL_HONOR_COUNT, - KSPROPERTY_ALLOCATOR_CONTROL_SURFACE_SIZE, - KSPROPERTY_ALLOCATOR_CONTROL_CAPTURE_CAPS, - KSPROPERTY_ALLOCATOR_CONTROL_CAPTURE_INTERLEAVE -}KSPROPERTY_ALLOCATOR_CONTROL; - -typedef struct -{ - ULONG CX; - ULONG CY; -}KSPROPERTY_ALLOCATOR_CONTROL_SURFACE_SIZE_S, * PKSPROPERTY_ALLOCATOR_CONTROL_SURFACE_SIZE_S; - -typedef struct -{ - ULONG InterleavedCapSupported; -}KSPROPERTY_ALLOCATOR_CONTROL_CAPTURE_CAPS_S, * PKSPROPERTY_ALLOCATOR_CONTROL_CAPTURE_CAPS_S; - -typedef struct -{ - ULONG InterleavedCapPossible; -}KSPROPERTY_ALLOCATOR_CONTROL_CAPTURE_INTERLEAVE_S, * PKSPROPERTY_ALLOCATOR_CONTROL_CAPTURE_INTERLEAVE_S; - - # define STATIC_PROPSETID_VIDCAP_VIDEOPROCAMP \ - 0xC6E13360L, 0x30AC, 0x11d0, 0xa1, 0x8c, 0x00, 0xA0, 0xC9, 0x11, 0x89, 0x56 -DEFINE_GUIDSTRUCT("C6E13360-30AC-11d0-A18C-00A0C9118956", PROPSETID_VIDCAP_VIDEOPROCAMP); - # define PROPSETID_VIDCAP_VIDEOPROCAMP DEFINE_GUIDNAMED(PROPSETID_VIDCAP_VIDEOPROCAMP) - -typedef enum -{ - KSPROPERTY_VIDEOPROCAMP_BRIGHTNESS, - KSPROPERTY_VIDEOPROCAMP_CONTRAST, - KSPROPERTY_VIDEOPROCAMP_HUE, - KSPROPERTY_VIDEOPROCAMP_SATURATION, - KSPROPERTY_VIDEOPROCAMP_SHARPNESS, - KSPROPERTY_VIDEOPROCAMP_GAMMA, - KSPROPERTY_VIDEOPROCAMP_COLORENABLE, - KSPROPERTY_VIDEOPROCAMP_WHITEBALANCE, - KSPROPERTY_VIDEOPROCAMP_BACKLIGHT_COMPENSATION, - KSPROPERTY_VIDEOPROCAMP_GAIN, - KSPROPERTY_VIDEOPROCAMP_DIGITAL_MULTIPLIER, - KSPROPERTY_VIDEOPROCAMP_DIGITAL_MULTIPLIER_LIMIT, - KSPROPERTY_VIDEOPROCAMP_WHITEBALANCE_COMPONENT, - KSPROPERTY_VIDEOPROCAMP_POWERLINE_FREQUENCY -}KSPROPERTY_VIDCAP_VIDEOPROCAMP; - -typedef struct -{ - KSPROPERTY Property; - LONG Value; - ULONG Flags; - ULONG Capabilities; -}KSPROPERTY_VIDEOPROCAMP_S, * PKSPROPERTY_VIDEOPROCAMP_S; - -typedef struct -{ - KSP_NODE NodeProperty; - LONG Value; - ULONG Flags; - ULONG Capabilities; -}KSPROPERTY_VIDEOPROCAMP_NODE_S, * PKSPROPERTY_VIDEOPROCAMP_NODE_S; - -typedef struct -{ - KSPROPERTY Property; - LONG Value1; - ULONG Flags; - ULONG Capabilities; - LONG Value2; -}KSPROPERTY_VIDEOPROCAMP_S2, * PKSPROPERTY_VIDEOPROCAMP_S2; - -typedef struct -{ - KSP_NODE NodeProperty; - LONG Value1; - ULONG Flags; - ULONG Capabilities; - LONG Value2; -}KSPROPERTY_VIDEOPROCAMP_NODE_S2, * PKSPROPERTY_VIDEOPROCAMP_NODE_S2; - - # define KSPROPERTY_VIDEOPROCAMP_FLAGS_AUTO 0X0001L - # define KSPROPERTY_VIDEOPROCAMP_FLAGS_MANUAL 0X0002L - - # define STATIC_PROPSETID_VIDCAP_SELECTOR \ - 0x1ABDAECA, 0x68B6, 0x4F83, 0x93, 0x71, 0xB4, 0x13, 0x90, 0x7C, 0x7B, 0x9F -DEFINE_GUIDSTRUCT("1ABDAECA-68B6-4F83-9371-B413907C7B9F", PROPSETID_VIDCAP_SELECTOR); - # define PROPSETID_VIDCAP_SELECTOR DEFINE_GUIDNAMED(PROPSETID_VIDCAP_SELECTOR) - -typedef enum -{ - KSPROPERTY_SELECTOR_SOURCE_NODE_ID, - KSPROPERTY_SELECTOR_NUM_SOURCES -}KSPROPERTY_VIDCAP_SELECTOR, * PKSPROPERTY_VIDCAP_SELECTOR; - -typedef struct -{ - KSPROPERTY Property; - LONG Value; - ULONG Flags; - ULONG Capabilities; -}KSPROPERTY_SELECTOR_S, * PKSPROPERTY_SELECTOR_S; - -typedef struct -{ - KSP_NODE NodeProperty; - LONG Value; - ULONG Flags; - ULONG Capabilities; -}KSPROPERTY_SELECTOR_NODE_S, * PKSPROPERTY_SELECTOR_NODE_S; - - # define STATIC_PROPSETID_TUNER \ - 0x6a2e0605L, 0x28e4, 0x11d0, 0xa1, 0x8c, 0x00, 0xa0, 0xc9, 0x11, 0x89, 0x56 -DEFINE_GUIDSTRUCT("6a2e0605-28e4-11d0-a18c-00a0c9118956", PROPSETID_TUNER); - # define PROPSETID_TUNER DEFINE_GUIDNAMED(PROPSETID_TUNER) - -typedef enum -{ - KSPROPERTY_TUNER_CAPS, - KSPROPERTY_TUNER_MODE_CAPS, - KSPROPERTY_TUNER_MODE, - KSPROPERTY_TUNER_STANDARD, - KSPROPERTY_TUNER_FREQUENCY, - KSPROPERTY_TUNER_INPUT, - KSPROPERTY_TUNER_STATUS, - KSPROPERTY_TUNER_IF_MEDIUM -}KSPROPERTY_TUNER; - -typedef enum -{ - KSPROPERTY_TUNER_MODE_TV = 0X0001, - KSPROPERTY_TUNER_MODE_FM_RADIO = 0X0002, - KSPROPERTY_TUNER_MODE_AM_RADIO = 0X0004, - KSPROPERTY_TUNER_MODE_DSS = 0X0008, - KSPROPERTY_TUNER_MODE_ATSC = 0X0010 -}KSPROPERTY_TUNER_MODES; - -typedef enum -{ - KS_TUNER_TUNING_EXACT = 1, - KS_TUNER_TUNING_FINE, - KS_TUNER_TUNING_COARSE -}KS_TUNER_TUNING_FLAGS; - -typedef enum -{ - KS_TUNER_STRATEGY_PLL = 0X01, - KS_TUNER_STRATEGY_SIGNAL_STRENGTH = 0X02, - KS_TUNER_STRATEGY_DRIVER_TUNES = 0X04 -}KS_TUNER_STRATEGY; - -typedef struct -{ - KSPROPERTY Property; - ULONG ModesSupported; - KSPIN_MEDIUM VideoMedium; - KSPIN_MEDIUM TVAudioMedium; - KSPIN_MEDIUM RadioAudioMedium; -}KSPROPERTY_TUNER_CAPS_S, * PKSPROPERTY_TUNER_CAPS_S; - -typedef struct -{ - KSPROPERTY Property; - KSPIN_MEDIUM IFMedium; -}KSPROPERTY_TUNER_IF_MEDIUM_S, * PKSPROPERTY_TUNER_IF_MEDIUM_S; - -typedef struct -{ - KSPROPERTY Property; - ULONG Mode; - ULONG StandardsSupported; - ULONG MinFrequency; - ULONG MaxFrequency; - ULONG TuningGranularity; - ULONG NumberOfInputs; - ULONG SettlingTime; - ULONG Strategy; -}KSPROPERTY_TUNER_MODE_CAPS_S, * PKSPROPERTY_TUNER_MODE_CAPS_S; - -typedef struct -{ - KSPROPERTY Property; - ULONG Mode; -}KSPROPERTY_TUNER_MODE_S, * PKSPROPERTY_TUNER_MODE_S; - -typedef struct -{ - KSPROPERTY Property; - ULONG Frequency; - ULONG LastFrequency; - ULONG TuningFlags; - ULONG VideoSubChannel; - ULONG AudioSubChannel; - ULONG Channel; - ULONG Country; -}KSPROPERTY_TUNER_FREQUENCY_S, * PKSPROPERTY_TUNER_FREQUENCY_S; - -typedef struct -{ - KSPROPERTY Property; - ULONG Standard; -}KSPROPERTY_TUNER_STANDARD_S, * PKSPROPERTY_TUNER_STANDARD_S; - -typedef struct -{ - KSPROPERTY Property; - ULONG InputIndex; -}KSPROPERTY_TUNER_INPUT_S, * PKSPROPERTY_TUNER_INPUT_S; - -typedef struct -{ - KSPROPERTY Property; - ULONG CurrentFrequency; - ULONG PLLOffset; - ULONG SignalStrength; - ULONG Busy; -}KSPROPERTY_TUNER_STATUS_S, * PKSPROPERTY_TUNER_STATUS_S; - - # define STATIC_EVENTSETID_TUNER \ - 0x6a2e0606L, 0x28e4, 0x11d0, 0xa1, 0x8c, 0x00, 0xa0, 0xc9, 0x11, 0x89, 0x56 -DEFINE_GUIDSTRUCT("6a2e0606-28e4-11d0-a18c-00a0c9118956", EVENTSETID_TUNER); - # define EVENTSETID_TUNER DEFINE_GUIDNAMED(EVENTSETID_TUNER) - -typedef enum -{ - KSEVENT_TUNER_CHANGED -}KSEVENT_TUNER; - - # define STATIC_KSNODETYPE_VIDEO_STREAMING \ - 0xDFF229E1L, 0xF70F, 0x11D0, 0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 -DEFINE_GUIDSTRUCT("DFF229E1-F70F-11D0-B917-00A0C9223196", KSNODETYPE_VIDEO_STREAMING); - # define KSNODETYPE_VIDEO_STREAMING DEFINE_GUIDNAMED(KSNODETYPE_VIDEO_STREAMING) - - # define STATIC_KSNODETYPE_VIDEO_INPUT_TERMINAL \ - 0xDFF229E2L, 0xF70F, 0x11D0, 0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 -DEFINE_GUIDSTRUCT("DFF229E2-F70F-11D0-B917-00A0C9223196", KSNODETYPE_VIDEO_INPUT_TERMINAL); - # define KSNODETYPE_VIDEO_INPUT_TERMINAL DEFINE_GUIDNAMED(KSNODETYPE_VIDEO_INPUT_TERMINAL) - - # define STATIC_KSNODETYPE_VIDEO_OUTPUT_TERMINAL \ - 0xDFF229E3L, 0xF70F, 0x11D0, 0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 -DEFINE_GUIDSTRUCT("DFF229E3-F70F-11D0-B917-00A0C9223196", KSNODETYPE_VIDEO_OUTPUT_TERMINAL); - # define KSNODETYPE_VIDEO_OUTPUT_TERMINAL DEFINE_GUIDNAMED(KSNODETYPE_VIDEO_OUTPUT_TERMINAL) - - # define STATIC_KSNODETYPE_VIDEO_SELECTOR \ - 0xDFF229E4L, 0xF70F, 0x11D0, 0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 -DEFINE_GUIDSTRUCT("DFF229E4-F70F-11D0-B917-00A0C9223196", KSNODETYPE_VIDEO_SELECTOR); - # define KSNODETYPE_VIDEO_SELECTOR DEFINE_GUIDNAMED(KSNODETYPE_VIDEO_SELECTOR) - - # define STATIC_KSNODETYPE_VIDEO_PROCESSING \ - 0xDFF229E5L, 0xF70F, 0x11D0, 0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 -DEFINE_GUIDSTRUCT("DFF229E5-F70F-11D0-B917-00A0C9223196", KSNODETYPE_VIDEO_PROCESSING); - # define KSNODETYPE_VIDEO_PROCESSING DEFINE_GUIDNAMED(KSNODETYPE_VIDEO_PROCESSING) - - # define STATIC_KSNODETYPE_VIDEO_CAMERA_TERMINAL \ - 0xDFF229E6L, 0xF70F, 0x11D0, 0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 -DEFINE_GUIDSTRUCT("DFF229E6-F70F-11D0-B917-00A0C9223196", KSNODETYPE_VIDEO_CAMERA_TERMINAL); - # define KSNODETYPE_VIDEO_CAMERA_TERMINAL DEFINE_GUIDNAMED(KSNODETYPE_VIDEO_CAMERA_TERMINAL) - - # define STATIC_KSNODETYPE_VIDEO_INPUT_MTT \ - 0xDFF229E7L, 0xF70F, 0x11D0, 0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 -DEFINE_GUIDSTRUCT("DFF229E7-F70F-11D0-B917-00A0C9223196", KSNODETYPE_VIDEO_INPUT_MTT); - # define KSNODETYPE_VIDEO_INPUT_MTT DEFINE_GUIDNAMED(KSNODETYPE_VIDEO_INPUT_MTT) - - # define STATIC_KSNODETYPE_VIDEO_OUTPUT_MTT \ - 0xDFF229E8L, 0xF70F, 0x11D0, 0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 -DEFINE_GUIDSTRUCT("DFF229E8-F70F-11D0-B917-00A0C9223196", KSNODETYPE_VIDEO_OUTPUT_MTT); - # define KSNODETYPE_VIDEO_OUTPUT_MTT DEFINE_GUIDNAMED(KSNODETYPE_VIDEO_OUTPUT_MTT) - - # define STATIC_PROPSETID_VIDCAP_VIDEOENCODER \ - 0x6a2e0610L, 0x28e4, 0x11d0, 0xa1, 0x8c, 0x00, 0xa0, 0xc9, 0x11, 0x89, 0x56 -DEFINE_GUIDSTRUCT("6a2e0610-28e4-11d0-a18c-00a0c9118956", PROPSETID_VIDCAP_VIDEOENCODER); - # define PROPSETID_VIDCAP_VIDEOENCODER DEFINE_GUIDNAMED(PROPSETID_VIDCAP_VIDEOENCODER) - -typedef enum -{ - KSPROPERTY_VIDEOENCODER_CAPS, - KSPROPERTY_VIDEOENCODER_STANDARD, - KSPROPERTY_VIDEOENCODER_COPYPROTECTION, - KSPROPERTY_VIDEOENCODER_CC_ENABLE -}KSPROPERTY_VIDCAP_VIDEOENCODER; - -typedef struct -{ - KSPROPERTY Property; - LONG Value; - ULONG Flags; - ULONG Capabilities; -}KSPROPERTY_VIDEOENCODER_S, * PKSPROPERTY_VIDEOENCODER_S; - - # define STATIC_PROPSETID_VIDCAP_VIDEODECODER \ - 0xC6E13350L, 0x30AC, 0x11d0, 0xA1, 0x8C, 0x00, 0xA0, 0xC9, 0x11, 0x89, 0x56 -DEFINE_GUIDSTRUCT("C6E13350-30AC-11d0-A18C-00A0C9118956", PROPSETID_VIDCAP_VIDEODECODER); - # define PROPSETID_VIDCAP_VIDEODECODER DEFINE_GUIDNAMED(PROPSETID_VIDCAP_VIDEODECODER) - -typedef enum -{ - KSPROPERTY_VIDEODECODER_CAPS, - KSPROPERTY_VIDEODECODER_STANDARD, - KSPROPERTY_VIDEODECODER_STATUS, - KSPROPERTY_VIDEODECODER_OUTPUT_ENABLE, - KSPROPERTY_VIDEODECODER_VCR_TIMING -}KSPROPERTY_VIDCAP_VIDEODECODER; - -typedef enum -{ - KS_VIDEODECODER_FLAGS_CAN_DISABLE_OUTPUT = 0X0001, - KS_VIDEODECODER_FLAGS_CAN_USE_VCR_LOCKING = 0X0002, - KS_VIDEODECODER_FLAGS_CAN_INDICATE_LOCKED = 0X0004 -}KS_VIDEODECODER_FLAGS; - -typedef struct -{ - KSPROPERTY Property; - ULONG StandardsSupported; - ULONG Capabilities; - ULONG SettlingTime; - ULONG HSyncPerVSync; -}KSPROPERTY_VIDEODECODER_CAPS_S, * PKSPROPERTY_VIDEODECODER_CAPS_S; - -typedef struct -{ - KSPROPERTY Property; - ULONG NumberOfLines; - ULONG SignalLocked; -}KSPROPERTY_VIDEODECODER_STATUS_S, * PKSPROPERTY_VIDEODECODER_STATUS_S; - -typedef struct -{ - KSPROPERTY Property; - ULONG Value; -}KSPROPERTY_VIDEODECODER_S, * PKSPROPERTY_VIDEODECODER_S; - - # define STATIC_EVENTSETID_VIDEODECODER \ - 0x6a2e0621L, 0x28e4, 0x11d0, 0xa1, 0x8c, 0x00, 0xa0, 0xc9, 0x11, 0x89, 0x56 -DEFINE_GUIDSTRUCT("6a2e0621-28e4-11d0-a18c-00a0c9118956", EVENTSETID_VIDEODECODER); - # define EVENTSETID_VIDEODECODER DEFINE_GUIDNAMED(EVENTSETID_VIDEODECODER) - -typedef enum -{ - KSEVENT_VIDEODECODER_CHANGED -}KSEVENT_VIDEODECODER; - - # define STATIC_PROPSETID_VIDCAP_CAMERACONTROL \ - 0xC6E13370L, 0x30AC, 0x11d0, 0xa1, 0x8C, 0x00, 0xA0, 0xC9, 0x11, 0x89, 0x56 -DEFINE_GUIDSTRUCT("C6E13370-30AC-11d0-A18C-00A0C9118956", PROPSETID_VIDCAP_CAMERACONTROL); - # define PROPSETID_VIDCAP_CAMERACONTROL DEFINE_GUIDNAMED(PROPSETID_VIDCAP_CAMERACONTROL) - -typedef enum -{ - KSPROPERTY_CAMERACONTROL_PAN, - KSPROPERTY_CAMERACONTROL_TILT, - KSPROPERTY_CAMERACONTROL_ROLL, - KSPROPERTY_CAMERACONTROL_ZOOM, - KSPROPERTY_CAMERACONTROL_EXPOSURE, - KSPROPERTY_CAMERACONTROL_IRIS, - KSPROPERTY_CAMERACONTROL_FOCUS, - KSPROPERTY_CAMERACONTROL_SCANMODE, - KSPROPERTY_CAMERACONTROL_PRIVACY, - KSPROPERTY_CAMERACONTROL_PANTILT, - KSPROPERTY_CAMERACONTROL_PAN_RELATIVE, - KSPROPERTY_CAMERACONTROL_TILT_RELATIVE, - KSPROPERTY_CAMERACONTROL_ROLL_RELATIVE, - KSPROPERTY_CAMERACONTROL_ZOOM_RELATIVE, - KSPROPERTY_CAMERACONTROL_EXPOSURE_RELATIVE, - KSPROPERTY_CAMERACONTROL_IRIS_RELATIVE, - KSPROPERTY_CAMERACONTROL_FOCUS_RELATIVE, - KSPROPERTY_CAMERACONTROL_PANTILT_RELATIVE, - KSPROPERTY_CAMERACONTROL_FOCAL_LENGTH -}KSPROPERTY_VIDCAP_CAMERACONTROL; - -typedef struct -{ - KSPROPERTY Property; - LONG Value; - ULONG Flags; - ULONG Capabilities; -}KSPROPERTY_CAMERACONTROL_S, * PKSPROPERTY_CAMERACONTROL_S; - -typedef struct -{ - KSP_NODE NodeProperty; - LONG Value; - ULONG Flags; - ULONG Capabilities; -}KSPROPERTY_CAMERACONTROL_NODE_S, PKSPROPERTY_CAMERACONTROL_NODE_S; - -typedef struct -{ - KSPROPERTY Property; - LONG Value1; - ULONG Flags; - ULONG Capabilities; - LONG Value2; -}KSPROPERTY_CAMERACONTROL_S2, * PKSPROPERTY_CAMERACONTROL_S2; - -typedef struct -{ - KSP_NODE NodeProperty; - LONG Value1; - ULONG Flags; - ULONG Capabilities; - LONG Value2; -}KSPROPERTY_CAMERACONTROL_NODE_S2, * PKSPROPERTY_CAMERACONTROL_NODE_S2; - -typedef struct -{ - KSPROPERTY Property; - LONG lOcularFocalLength; - LONG lObjectiveFocalLengthMin; - LONG lObjectiveFocalLengthMax; -}KSPROPERTY_CAMERACONTROL_FOCAL_LENGTH_S, * PKSPROPERTY_CAMERACONTROL_FOCAL_LENGTH_S; - -typedef struct -{ - KSNODEPROPERTY NodeProperty; - LONG lOcularFocalLength; - LONG lObjectiveFocalLengthMin; - LONG lObjectiveFocalLengthMax; -}KSPROPERTY_CAMERACONTROL_NODE_FOCAL_LENGTH_S, * PKSPROPERTY_CAMERACONTROL_NODE_FOCAL_LENGTH_S; - - # define KSPROPERTY_CAMERACONTROL_FLAGS_AUTO 0X0001L - # define KSPROPERTY_CAMERACONTROL_FLAGS_MANUAL 0X0002L - - # define KSPROPERTY_CAMERACONTROL_FLAGS_ABSOLUTE 0X0000L - # define KSPROPERTY_CAMERACONTROL_FLAGS_RELATIVE 0X0010L - - # ifndef __EDevCtrl__ - # define __EDevCtrl__ - - # define STATIC_PROPSETID_EXT_DEVICE \ - 0xB5730A90L, 0x1A2C, 0x11cf, 0x8c, 0x23, 0x00, 0xAA, 0x00, 0x6B, 0x68, 0x14 -DEFINE_GUIDSTRUCT("B5730A90-1A2C-11cf-8C23-00AA006B6814", PROPSETID_EXT_DEVICE); - # define PROPSETID_EXT_DEVICE DEFINE_GUIDNAMED(PROPSETID_EXT_DEVICE) - -typedef enum -{ - KSPROPERTY_EXTDEVICE_ID, - KSPROPERTY_EXTDEVICE_VERSION, - KSPROPERTY_EXTDEVICE_POWER_STATE, - KSPROPERTY_EXTDEVICE_PORT, - KSPROPERTY_EXTDEVICE_CAPABILITIES -}KSPROPERTY_EXTDEVICE; - -typedef struct tagDEVCAPS -{ - LONG CanRecord; - LONG CanRecordStrobe; - LONG HasAudio; - LONG HasVideo; - LONG UsesFiles; - LONG CanSave; - LONG DeviceType; - LONG TCRead; - LONG TCWrite; - LONG CTLRead; - LONG IndexRead; - LONG Preroll; - LONG Postroll; - LONG SyncAcc; - LONG NormRate; - LONG CanPreview; - LONG CanMonitorSrc; - LONG CanTest; - LONG VideoIn; - LONG AudioIn; - LONG Calibrate; - LONG SeekType; - LONG SimulatedHardware; -}DEVCAPS, * PDEVCAPS; - -typedef struct -{ - KSPROPERTY Property; - union - { - DEVCAPS Capabilities; - ULONG DevPort; - ULONG PowerState; - WCHAR pawchString[MAX_PATH]; - DWORD NodeUniqueID[2]; - }u; -}KSPROPERTY_EXTDEVICE_S, * PKSPROPERTY_EXTDEVICE_S; - - # define STATIC_PROPSETID_EXT_TRANSPORT \ - 0xA03CD5F0L, 0x3045, 0x11cf, 0x8c, 0x44, 0x00, 0xAA, 0x00, 0x6B, 0x68, 0x14 -DEFINE_GUIDSTRUCT("A03CD5F0-3045-11cf-8C44-00AA006B6814", PROPSETID_EXT_TRANSPORT); - # define PROPSETID_EXT_TRANSPORT DEFINE_GUIDNAMED(PROPSETID_EXT_TRANSPORT) - -typedef enum -{ - KSPROPERTY_EXTXPORT_CAPABILITIES, - KSPROPERTY_EXTXPORT_INPUT_SIGNAL_MODE, - KSPROPERTY_EXTXPORT_OUTPUT_SIGNAL_MODE, - KSPROPERTY_EXTXPORT_LOAD_MEDIUM, - KSPROPERTY_EXTXPORT_MEDIUM_INFO, - KSPROPERTY_EXTXPORT_STATE, - KSPROPERTY_EXTXPORT_STATE_NOTIFY, - KSPROPERTY_EXTXPORT_TIMECODE_SEARCH, - KSPROPERTY_EXTXPORT_ATN_SEARCH, - KSPROPERTY_EXTXPORT_RTC_SEARCH, - KSPROPERTY_RAW_AVC_CMD -}KSPROPERTY_EXTXPORT; - -typedef struct tagTRANSPORTSTATUS -{ - LONG Mode; - LONG LastError; - LONG RecordInhibit; - LONG ServoLock; - LONG MediaPresent; - LONG MediaLength; - LONG MediaSize; - LONG MediaTrackCount; - LONG MediaTrackLength; - LONG MediaTrackSide; - LONG MediaType; - LONG LinkMode; - LONG NotifyOn; -}TRANSPORTSTATUS, * PTRANSPORTSTATUS; - -typedef struct tagTRANSPORTBASICPARMS -{ - LONG TimeFormat; - LONG TimeReference; - LONG Superimpose; - LONG EndStopAction; - LONG RecordFormat; - LONG StepFrames; - LONG SetpField; - LONG Preroll; - LONG RecPreroll; - LONG Postroll; - LONG EditDelay; - LONG PlayTCDelay; - LONG RecTCDelay; - LONG EditField; - LONG FrameServo; - LONG ColorFrameServo; - LONG ServoRef; - LONG WarnGenlock; - LONG SetTracking; - TCHAR VolumeName[40]; - LONG Ballistic[20]; - LONG Speed; - LONG CounterFormat; - LONG TunerChannel; - LONG TunerNumber; - LONG TimerEvent; - LONG TimerStartDay; - LONG TimerStartTime; - LONG TimerStopDay; - LONG TimerStopTime; -}TRANSPORTBASICPARMS, * PTRANSPORTBASICPARMS; - -typedef struct tagTRANSPORTVIDEOPARMS -{ - LONG OutputMode; - LONG Input; -}TRANSPORTVIDEOPARMS, * PTRANSPORTVIDEOPARMS; - -typedef struct tagTRANSPORTAUDIOPARMS -{ - LONG EnableOutput; - LONG EnableRecord; - LONG EnableSelsync; - LONG Input; - LONG MonitorSource; -}TRANSPORTAUDIOPARMS, * PTRANSPORTAUDIOPARMS; - -typedef struct -{ - WINBOOL MediaPresent; - ULONG MediaType; - WINBOOL RecordInhibit; -}MEDIUM_INFO, * PMEDIUM_INFO; - -typedef struct -{ - ULONG Mode; - ULONG State; -}TRANSPORT_STATE, * PTRANSPORT_STATE; - -typedef struct -{ - KSPROPERTY Property; - union - { - ULONG Capabilities; - ULONG SignalMode; - ULONG LoadMedium; - MEDIUM_INFO MediumInfo; - TRANSPORT_STATE XPrtState; - struct - { - BYTE frame; - BYTE second; - BYTE minute; - BYTE hour; - }Timecode; - DWORD dwTimecode; - DWORD dwAbsTrackNumber; - struct - { - ULONG PayloadSize; - BYTE Payload[512]; - }RawAVC; - }u; -}KSPROPERTY_EXTXPORT_S, * PKSPROPERTY_EXTXPORT_S; - -typedef struct -{ - KSP_NODE NodeProperty; - union - { - ULONG Capabilities; - ULONG SignalMode; - ULONG LoadMedium; - MEDIUM_INFO MediumInfo; - TRANSPORT_STATE XPrtState; - struct - { - BYTE frame; - BYTE second; - BYTE minute; - BYTE hour; - }Timecode; - DWORD dwTimecode; - DWORD dwAbsTrackNumber; - struct - { - ULONG PayloadSize; - BYTE Payload[512]; - }RawAVC; - }u; -}KSPROPERTY_EXTXPORT_NODE_S, * PKSPROPERTY_EXTXPORT_NODE_S; - - # define STATIC_PROPSETID_TIMECODE_READER \ - 0x9B496CE1L, 0x811B, 0x11cf, 0x8C, 0x77, 0x00, 0xAA, 0x00, 0x6B, 0x68, 0x14 -DEFINE_GUIDSTRUCT("9B496CE1-811B-11cf-8C77-00AA006B6814", PROPSETID_TIMECODE_READER); - # define PROPSETID_TIMECODE_READER DEFINE_GUIDNAMED(PROPSETID_TIMECODE_READER) - -typedef enum -{ - KSPROPERTY_TIMECODE_READER, - KSPROPERTY_ATN_READER, - KSPROPERTY_RTC_READER -}KSPROPERTY_TIMECODE; - - # ifndef TIMECODE_DEFINED - # define TIMECODE_DEFINED -typedef union _timecode -{ - struct - { - WORD wFrameRate; - WORD wFrameFract; - DWORD dwFrames; - }; - DWORDLONG qw; -}TIMECODE; -typedef TIMECODE* PTIMECODE; - -typedef struct tagTIMECODE_SAMPLE -{ - LONGLONG qwTick; - TIMECODE timecode; - DWORD dwUser; - DWORD dwFlags; -}TIMECODE_SAMPLE; - -typedef TIMECODE_SAMPLE* PTIMECODE_SAMPLE; - # endif /* TIMECODE_DEFINED */ - -typedef struct -{ - KSPROPERTY Property; - TIMECODE_SAMPLE TimecodeSamp; -}KSPROPERTY_TIMECODE_S, * PKSPROPERTY_TIMECODE_S; - -typedef struct -{ - KSP_NODE NodeProperty; - TIMECODE_SAMPLE TimecodeSamp; -}KSPROPERTY_TIMECODE_NODE_S, * PKSPROPERTY_TIMECODE_NODE_S; - - # define STATIC_KSEVENTSETID_EXTDEV_Command \ - 0x109c7988L, 0xb3cb, 0x11d2, 0xb4, 0x8e, 0x00, 0x60, 0x97, 0xb3, 0x39, 0x1b -DEFINE_GUIDSTRUCT("109c7988-b3cb-11d2-b48e-006097b3391b", KSEVENTSETID_EXTDEV_Command); - # define KSEVENTSETID_EXTDEV_Command DEFINE_GUIDNAMED(KSEVENTSETID_EXTDEV_Command) - -typedef enum -{ - KSEVENT_EXTDEV_COMMAND_NOTIFY_INTERIM_READY, - KSEVENT_EXTDEV_COMMAND_CONTROL_INTERIM_READY, - KSEVENT_EXTDEV_COMMAND_BUSRESET, - KSEVENT_EXTDEV_TIMECODE_UPDATE, - KSEVENT_EXTDEV_OPERATION_MODE_UPDATE, - KSEVENT_EXTDEV_TRANSPORT_STATE_UPDATE, - KSEVENT_EXTDEV_NOTIFY_REMOVAL, - KSEVENT_EXTDEV_NOTIFY_MEDIUM_CHANGE -}KSEVENT_DEVCMD; - # endif /* __EDevCtrl__ */ - - # define STATIC_PROPSETID_VIDCAP_CROSSBAR \ - 0x6a2e0640L, 0x28e4, 0x11d0, 0xa1, 0x8c, 0x00, 0xa0, 0xc9, 0x11, 0x89, 0x56 -DEFINE_GUIDSTRUCT("6a2e0640-28e4-11d0-a18c-00a0c9118956", PROPSETID_VIDCAP_CROSSBAR); - # define PROPSETID_VIDCAP_CROSSBAR DEFINE_GUIDNAMED(PROPSETID_VIDCAP_CROSSBAR) - -typedef enum -{ - KSPROPERTY_CROSSBAR_CAPS, - KSPROPERTY_CROSSBAR_PININFO, - KSPROPERTY_CROSSBAR_CAN_ROUTE, - KSPROPERTY_CROSSBAR_ROUTE -}KSPROPERTY_VIDCAP_CROSSBAR; - -typedef struct -{ - KSPROPERTY Property; - ULONG NumberOfInputs; - ULONG NumberOfOutputs; -}KSPROPERTY_CROSSBAR_CAPS_S, * PKSPROPERTY_CROSSBAR_CAPS_S; - -typedef struct -{ - KSPROPERTY Property; - KSPIN_DATAFLOW Direction; - ULONG Index; - ULONG PinType; - ULONG RelatedPinIndex; - KSPIN_MEDIUM Medium; -}KSPROPERTY_CROSSBAR_PININFO_S, * PKSPROPERTY_CROSSBAR_PININFO_S; - -typedef struct -{ - KSPROPERTY Property; - ULONG IndexInputPin; - ULONG IndexOutputPin; - ULONG CanRoute; -}KSPROPERTY_CROSSBAR_ROUTE_S, * PKSPROPERTY_CROSSBAR_ROUTE_S; - - # define STATIC_EVENTSETID_CROSSBAR \ - 0x6a2e0641L, 0x28e4, 0x11d0, 0xa1, 0x8c, 0x00, 0xa0, 0xc9, 0x11, 0x89, 0x56 -DEFINE_GUIDSTRUCT("6a2e0641-28e4-11d0-a18c-00a0c9118956", EVENTSETID_CROSSBAR); - # define EVENTSETID_CROSSBAR DEFINE_GUIDNAMED(EVENTSETID_CROSSBAR) - -typedef enum -{ - KSEVENT_CROSSBAR_CHANGED -}KSEVENT_CROSSBAR; - -typedef enum -{ - KS_PhysConn_Video_Tuner = 1, - KS_PhysConn_Video_Composite, - KS_PhysConn_Video_SVideo, - KS_PhysConn_Video_RGB, - KS_PhysConn_Video_YRYBY, - KS_PhysConn_Video_SerialDigital, - KS_PhysConn_Video_ParallelDigital, - KS_PhysConn_Video_SCSI, - KS_PhysConn_Video_AUX, - KS_PhysConn_Video_1394, - KS_PhysConn_Video_USB, - KS_PhysConn_Video_VideoDecoder, - KS_PhysConn_Video_VideoEncoder, - KS_PhysConn_Video_SCART, - KS_PhysConn_Audio_Tuner = 4096, - KS_PhysConn_Audio_Line, - KS_PhysConn_Audio_Mic, - KS_PhysConn_Audio_AESDigital, - KS_PhysConn_Audio_SPDIFDigital, - KS_PhysConn_Audio_SCSI, - KS_PhysConn_Audio_AUX, - KS_PhysConn_Audio_1394, - KS_PhysConn_Audio_USB, - KS_PhysConn_Audio_AudioDecoder -}KS_PhysicalConnectorType; - - # define STATIC_PROPSETID_VIDCAP_TVAUDIO \ - 0x6a2e0650L, 0x28e4, 0x11d0, 0xa1, 0x8c, 0x00, 0xa0, 0xc9, 0x11, 0x89, 0x56 -DEFINE_GUIDSTRUCT("6a2e0650-28e4-11d0-a18c-00a0c9118956", PROPSETID_VIDCAP_TVAUDIO); - # define PROPSETID_VIDCAP_TVAUDIO DEFINE_GUIDNAMED(PROPSETID_VIDCAP_TVAUDIO) - -typedef enum -{ - KSPROPERTY_TVAUDIO_CAPS, - KSPROPERTY_TVAUDIO_MODE, - KSPROPERTY_TVAUDIO_CURRENTLY_AVAILABLE_MODES -}KSPROPERTY_VIDCAP_TVAUDIO; - - # define KS_TVAUDIO_MODE_MONO 0x0001 - # define KS_TVAUDIO_MODE_STEREO 0x0002 - # define KS_TVAUDIO_MODE_LANG_A 0x0010 - # define KS_TVAUDIO_MODE_LANG_B 0x0020 - # define KS_TVAUDIO_MODE_LANG_C 0x0040 - -typedef struct -{ - KSPROPERTY Property; - ULONG Capabilities; - KSPIN_MEDIUM InputMedium; - KSPIN_MEDIUM OutputMedium; -}KSPROPERTY_TVAUDIO_CAPS_S, * PKSPROPERTY_TVAUDIO_CAPS_S; - -typedef struct -{ - KSPROPERTY Property; - ULONG Mode; -}KSPROPERTY_TVAUDIO_S, * PKSPROPERTY_TVAUDIO_S; - - # define STATIC_KSEVENTSETID_VIDCAP_TVAUDIO \ - 0x6a2e0651L, 0x28e4, 0x11d0, 0xa1, 0x8c, 0x00, 0xa0, 0xc9, 0x11, 0x89, 0x56 -DEFINE_GUIDSTRUCT("6a2e0651-28e4-11d0-a18c-00a0c9118956", KSEVENTSETID_VIDCAP_TVAUDIO); - # define KSEVENTSETID_VIDCAP_TVAUDIO DEFINE_GUIDNAMED(KSEVENTSETID_VIDCAP_TVAUDIO) - -typedef enum -{ - KSEVENT_TVAUDIO_CHANGED -}KSEVENT_TVAUDIO; - - # define STATIC_PROPSETID_VIDCAP_VIDEOCOMPRESSION \ - 0xC6E13343L, 0x30AC, 0x11d0, 0xA1, 0x8C, 0x00, 0xA0, 0xC9, 0x11, 0x89, 0x56 -DEFINE_GUIDSTRUCT("C6E13343-30AC-11d0-A18C-00A0C9118956", PROPSETID_VIDCAP_VIDEOCOMPRESSION); - # define PROPSETID_VIDCAP_VIDEOCOMPRESSION DEFINE_GUIDNAMED(PROPSETID_VIDCAP_VIDEOCOMPRESSION) - -typedef enum -{ - KSPROPERTY_VIDEOCOMPRESSION_GETINFO, - KSPROPERTY_VIDEOCOMPRESSION_KEYFRAME_RATE, - KSPROPERTY_VIDEOCOMPRESSION_PFRAMES_PER_KEYFRAME, - KSPROPERTY_VIDEOCOMPRESSION_QUALITY, - KSPROPERTY_VIDEOCOMPRESSION_OVERRIDE_KEYFRAME, - KSPROPERTY_VIDEOCOMPRESSION_OVERRIDE_FRAME_SIZE, - KSPROPERTY_VIDEOCOMPRESSION_WINDOWSIZE -}KSPROPERTY_VIDCAP_VIDEOCOMPRESSION; - -typedef enum -{ - KS_CompressionCaps_CanQuality = 1, - KS_CompressionCaps_CanCrunch = 2, - KS_CompressionCaps_CanKeyFrame = 4, - KS_CompressionCaps_CanBFrame = 8, - KS_CompressionCaps_CanWindow = 0x10 -}KS_CompressionCaps; - -typedef enum -{ - KS_StreamingHint_FrameInterval = 0x0100, - KS_StreamingHint_KeyFrameRate = 0x0200, - KS_StreamingHint_PFrameRate = 0x0400, - KS_StreamingHint_CompQuality = 0x0800, - KS_StreamingHint_CompWindowSize = 0x1000 -}KS_VideoStreamingHints; - -typedef struct -{ - KSPROPERTY Property; - ULONG StreamIndex; - LONG DefaultKeyFrameRate; - LONG DefaultPFrameRate; - LONG DefaultQuality; - LONG NumberOfQualitySettings; - LONG Capabilities; -}KSPROPERTY_VIDEOCOMPRESSION_GETINFO_S, * PKSPROPERTY_VIDEOCOMPRESSION_GETINFO_S; - -typedef struct -{ - KSPROPERTY Property; - ULONG StreamIndex; - LONG Value; -}KSPROPERTY_VIDEOCOMPRESSION_S, * PKSPROPERTY_VIDEOCOMPRESSION_S; - -typedef struct -{ - KSPROPERTY Property; - ULONG StreamIndex; - LONG Value; - ULONG Flags; -}KSPROPERTY_VIDEOCOMPRESSION_S1, * PKSPROPERTY_VIDEOCOMPRESSION_S1; - - # define STATIC_KSDATAFORMAT_SUBTYPE_OVERLAY \ - 0xe436eb7fL, 0x524f, 0x11ce, 0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70 -DEFINE_GUIDSTRUCT("e436eb7f-524f-11ce-9f53-0020af0ba770", KSDATAFORMAT_SUBTYPE_OVERLAY); - # define KSDATAFORMAT_SUBTYPE_OVERLAY DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_OVERLAY) - - # define STATIC_KSPROPSETID_OverlayUpdate \ - 0x490EA5CFL, 0x7681, 0x11D1, 0xA2, 0x1C, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 -DEFINE_GUIDSTRUCT("490EA5CF-7681-11D1-A21C-00A0C9223196", KSPROPSETID_OverlayUpdate); - # define KSPROPSETID_OverlayUpdate DEFINE_GUIDNAMED(KSPROPSETID_OverlayUpdate) - -typedef enum -{ - KSPROPERTY_OVERLAYUPDATE_INTERESTS, - KSPROPERTY_OVERLAYUPDATE_CLIPLIST = 0x1, - KSPROPERTY_OVERLAYUPDATE_PALETTE = 0x2, - KSPROPERTY_OVERLAYUPDATE_COLORKEY = 0x4, - KSPROPERTY_OVERLAYUPDATE_VIDEOPOSITION = 0x8, - KSPROPERTY_OVERLAYUPDATE_DISPLAYCHANGE = 0x10, - KSPROPERTY_OVERLAYUPDATE_COLORREF = 0x10000000 -}KSPROPERTY_OVERLAYUPDATE; - -typedef struct -{ - ULONG PelsWidth; - ULONG PelsHeight; - ULONG BitsPerPel; - WCHAR DeviceID[1]; -}KSDISPLAYCHANGE, * PKSDISPLAYCHANGE; - - # define DEFINE_KSPROPERTY_ITEM_OVERLAYUPDATE_INTERESTS(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_OVERLAYUPDATE_INTERESTS, \ - (Handler), \ - sizeof(KSPROPERTY), \ - sizeof(ULONG), \ - NULL, NULL, 0, NULL, NULL, 0) - - # define DEFINE_KSPROPERTY_ITEM_OVERLAYUPDATE_PALETTE(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_OVERLAYUPDATE_PALETTE, \ - NULL, \ - sizeof(KSPROPERTY), \ - 0, \ - (Handler), \ - NULL, 0, NULL, NULL, 0) - - # define DEFINE_KSPROPERTY_ITEM_OVERLAYUPDATE_COLORKEY(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_OVERLAYUPDATE_COLORKEY, \ - NULL, \ - sizeof(KSPROPERTY), \ - sizeof(COLORKEY), \ - (Handler), \ - NULL, 0, NULL, NULL, 0) - - # define DEFINE_KSPROPERTY_ITEM_OVERLAYUPDATE_CLIPLIST(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_OVERLAYUPDATE_CLIPLIST, \ - NULL, \ - sizeof(KSPROPERTY), \ - 2 * sizeof(RECT) + sizeof(RGNDATAHEADER), \ - (Handler), \ - NULL, 0, NULL, NULL, 0) - - # define DEFINE_KSPROPERTY_ITEM_OVERLAYUPDATE_VIDEOPOSITION(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_OVERLAYUPDATE_VIDEOPOSITION, \ - NULL, \ - sizeof(KSPROPERTY), \ - 2 * sizeof(RECT), \ - (Handler), \ - NULL, 0, NULL, NULL, 0) - - # define DEFINE_KSPROPERTY_ITEM_OVERLAYUPDATE_DISPLAYCHANGE(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_OVERLAYUPDATE_DISPLAYCHANGE, \ - NULL, \ - sizeof(KSPROPERTY), \ - sizeof(KSDISPLAYCHANGE), \ - (Handler), \ - NULL, 0, NULL, NULL, 0) - - # define DEFINE_KSPROPERTY_ITEM_OVERLAYUPDATE_COLORREF(Handler) \ - DEFINE_KSPROPERTY_ITEM( \ - KSPROPERTY_OVERLAYUPDATE_COLORREF, \ - (Handler), \ - sizeof(KSPROPERTY), \ - sizeof(COLORREF), \ - NULL, \ - NULL, 0, NULL, NULL, 0) - - # define STATIC_PROPSETID_VIDCAP_VIDEOCONTROL \ - 0x6a2e0670L, 0x28e4, 0x11d0, 0xa1, 0x8c, 0x00, 0xa0, 0xc9, 0x11, 0x89, 0x56 -DEFINE_GUIDSTRUCT("6a2e0670-28e4-11d0-a18c-00a0c9118956", PROPSETID_VIDCAP_VIDEOCONTROL); - # define PROPSETID_VIDCAP_VIDEOCONTROL DEFINE_GUIDNAMED(PROPSETID_VIDCAP_VIDEOCONTROL) - -typedef enum -{ - KSPROPERTY_VIDEOCONTROL_CAPS, - KSPROPERTY_VIDEOCONTROL_ACTUAL_FRAME_RATE, - KSPROPERTY_VIDEOCONTROL_FRAME_RATES, - KSPROPERTY_VIDEOCONTROL_MODE -}KSPROPERTY_VIDCAP_VIDEOCONTROL; - -typedef enum -{ - KS_VideoControlFlag_FlipHorizontal = 0x0001, - KS_VideoControlFlag_FlipVertical = 0x0002, - KS_Obsolete_VideoControlFlag_ExternalTriggerEnable = 0x0010, - KS_Obsolete_VideoControlFlag_Trigger = 0x0020, - KS_VideoControlFlag_ExternalTriggerEnable = 0x0004, - KS_VideoControlFlag_Trigger = 0x0008 -}KS_VideoControlFlags; - -typedef struct -{ - KSPROPERTY Property; - ULONG StreamIndex; - ULONG VideoControlCaps; -}KSPROPERTY_VIDEOCONTROL_CAPS_S, * PKSPROPERTY_VIDEOCONTROL_CAPS_S; - -typedef struct -{ - KSPROPERTY Property; - ULONG StreamIndex; - LONG Mode; -}KSPROPERTY_VIDEOCONTROL_MODE_S, * PKSPROPERTY_VIDEOCONTROL_MODE_S; - -typedef struct -{ - KSPROPERTY Property; - ULONG StreamIndex; - ULONG RangeIndex; - SIZE Dimensions; - LONGLONG CurrentActualFrameRate; - LONGLONG CurrentMaxAvailableFrameRate; -}KSPROPERTY_VIDEOCONTROL_ACTUAL_FRAME_RATE_S, * PKSPROPERTY_VIDEOCONTROL_ACTUAL_FRAME_RATE_S; - -typedef struct -{ - KSPROPERTY Property; - ULONG StreamIndex; - ULONG RangeIndex; - SIZE Dimensions; -}KSPROPERTY_VIDEOCONTROL_FRAME_RATES_S, * PKSPROPERTY_VIDEOCONTROL_FRAME_RATES_S; - - # define STATIC_PROPSETID_VIDCAP_DROPPEDFRAMES \ - 0xC6E13344L, 0x30AC, 0x11d0, 0xa1, 0x8c, 0x00, 0xa0, 0xc9, 0x11, 0x89, 0x56 -DEFINE_GUIDSTRUCT("C6E13344-30AC-11d0-A18C-00A0C9118956", PROPSETID_VIDCAP_DROPPEDFRAMES); - # define PROPSETID_VIDCAP_DROPPEDFRAMES DEFINE_GUIDNAMED(PROPSETID_VIDCAP_DROPPEDFRAMES) - -typedef enum -{ - KSPROPERTY_DROPPEDFRAMES_CURRENT -}KSPROPERTY_VIDCAP_DROPPEDFRAMES; - -typedef struct -{ - KSPROPERTY Property; - LONGLONG PictureNumber; - LONGLONG DropCount; - ULONG AverageFrameSize; -}KSPROPERTY_DROPPEDFRAMES_CURRENT_S, * PKSPROPERTY_DROPPEDFRAMES_CURRENT_S; - - # define STATIC_KSPROPSETID_VPConfig \ - 0xbc29a660L, 0x30e3, 0x11d0, 0x9e, 0x69, 0x00, 0xc0, 0x4f, 0xd7, 0xc1, 0x5b -DEFINE_GUIDSTRUCT("bc29a660-30e3-11d0-9e69-00c04fd7c15b", KSPROPSETID_VPConfig); - # define KSPROPSETID_VPConfig DEFINE_GUIDNAMED(KSPROPSETID_VPConfig) - - # define STATIC_KSPROPSETID_VPVBIConfig \ - 0xec529b00L, 0x1a1f, 0x11d1, 0xba, 0xd9, 0x0, 0x60, 0x97, 0x44, 0x11, 0x1a -DEFINE_GUIDSTRUCT("ec529b00-1a1f-11d1-bad9-00609744111a", KSPROPSETID_VPVBIConfig); - # define KSPROPSETID_VPVBIConfig DEFINE_GUIDNAMED(KSPROPSETID_VPVBIConfig) - -typedef enum -{ - KSPROPERTY_VPCONFIG_NUMCONNECTINFO, - KSPROPERTY_VPCONFIG_GETCONNECTINFO, - KSPROPERTY_VPCONFIG_SETCONNECTINFO, - KSPROPERTY_VPCONFIG_VPDATAINFO, - KSPROPERTY_VPCONFIG_MAXPIXELRATE, - KSPROPERTY_VPCONFIG_INFORMVPINPUT, - KSPROPERTY_VPCONFIG_NUMVIDEOFORMAT, - KSPROPERTY_VPCONFIG_GETVIDEOFORMAT, - KSPROPERTY_VPCONFIG_SETVIDEOFORMAT, - KSPROPERTY_VPCONFIG_INVERTPOLARITY, - KSPROPERTY_VPCONFIG_DECIMATIONCAPABILITY, - KSPROPERTY_VPCONFIG_SCALEFACTOR, - KSPROPERTY_VPCONFIG_DDRAWHANDLE, - KSPROPERTY_VPCONFIG_VIDEOPORTID, - KSPROPERTY_VPCONFIG_DDRAWSURFACEHANDLE, - KSPROPERTY_VPCONFIG_SURFACEPARAMS -}KSPROPERTY_VPCONFIG; - - # define STATIC_CLSID_KsIBasicAudioInterfaceHandler \ - 0xb9f8ac3e, 0x0f71, 0x11d2, 0xb7, 0x2c, 0x00, 0xc0, 0x4f, 0xb6, 0xbd, 0x3d -DEFINE_GUIDSTRUCT("b9f8ac3e-0f71-11d2-b72c-00c04fb6bd3d", CLSID_KsIBasicAudioInterfaceHandler); - # define CLSID_KsIBasicAudioInterfaceHandler DEFINE_GUIDNAMED(CLSID_KsIBasicAudioInterfaceHandler) - - # ifdef __IVPType__ -typedef struct -{ - AMVPSIZE Size; - DWORD MaxPixelsPerSecond; - DWORD Reserved; -}KSVPMAXPIXELRATE, * PKSVPMAXPIXELRATE; - -typedef struct -{ - KSPROPERTY Property; - AMVPSIZE Size; -}KSVPSIZE_PROP, * PKSVPSIZE_PROP; - -typedef struct -{ - DWORD dwPitch; - DWORD dwXOrigin; - DWORD dwYOrigin; -}KSVPSURFACEPARAMS, * PKSVPSURFACEPARAMS; - # else /* __IVPType__ */ - - # ifndef __DDRAW_INCLUDED__ - # define DDPF_FOURCC 0x00000004l - -typedef struct _DDPIXELFORMAT -{ - DWORD dwSize; - DWORD dwFlags; - DWORD dwFourCC; - __MINGW_EXTENSION union - { - DWORD dwRGBBitCount; - DWORD dwYUVBitCount; - DWORD dwZBufferBitDepth; - DWORD dwAlphaBitDepth; - }; - __MINGW_EXTENSION union - { - DWORD dwRBitMask; - DWORD dwYBitMask; - }; - __MINGW_EXTENSION union - { - DWORD dwGBitMask; - DWORD dwUBitMask; - }; - __MINGW_EXTENSION union - { - DWORD dwBBitMask; - DWORD dwVBitMask; - }; - __MINGW_EXTENSION union - { - DWORD dwRGBAlphaBitMask; - DWORD dwYUVAlphaBitMask; - DWORD dwRGBZBitMask; - DWORD dwYUVZBitMask; - }; -}DDPIXELFORMAT, * LPDDPIXELFORMAT; - # endif /* __DDRAW_INCLUDED__ */ - - # ifndef __DVP_INCLUDED__ -typedef struct _DDVIDEOPORTCONNECT -{ - DWORD dwSize; - DWORD dwPortWidth; - GUID guidTypeID; - DWORD dwFlags; - ULONG_PTR dwReserved1; -}DDVIDEOPORTCONNECT, * LPDDVIDEOPORTCONNECT; - - # define DDVPTYPE_E_HREFH_VREFH \ - 0x54F39980L, 0xDA60, 0x11CF, 0x9B, 0x06, 0x00, 0xA0, 0xC9, 0x03, 0xA3, 0xB8 - - # define DDVPTYPE_E_HREFL_VREFL \ - 0xE09C77E0L, 0xDA60, 0x11CF, 0x9B, 0x06, 0x00, 0xA0, 0xC9, 0x03, 0xA3, 0xB8 - # endif /* __DVP_INCLUDED__ */ - -typedef enum -{ - KS_PixAspectRatio_NTSC4x3, - KS_PixAspectRatio_NTSC16x9, - KS_PixAspectRatio_PAL4x3, - KS_PixAspectRatio_PAL16x9 -}KS_AMPixAspectRatio; - -typedef enum -{ - KS_AMVP_DO_NOT_CARE, - KS_AMVP_BEST_BANDWIDTH, - KS_AMVP_INPUT_SAME_AS_OUTPUT -}KS_AMVP_SELECTFORMATBY; - -typedef enum -{ - KS_AMVP_MODE_WEAVE, - KS_AMVP_MODE_BOBINTERLEAVED, - KS_AMVP_MODE_BOBNONINTERLEAVED, - KS_AMVP_MODE_SKIPEVEN, - KS_AMVP_MODE_SKIPODD -}KS_AMVP_MODE; - -typedef struct tagKS_AMVPDIMINFO -{ - DWORD dwFieldWidth; - DWORD dwFieldHeight; - DWORD dwVBIWidth; - DWORD dwVBIHeight; - RECT rcValidRegion; -}KS_AMVPDIMINFO, * PKS_AMVPDIMINFO; - -typedef struct tagKS_AMVPDATAINFO -{ - DWORD dwSize; - DWORD dwMicrosecondsPerField; - KS_AMVPDIMINFO amvpDimInfo; - DWORD dwPictAspectRatioX; - DWORD dwPictAspectRatioY; - WINBOOL bEnableDoubleClock; - WINBOOL bEnableVACT; - WINBOOL bDataIsInterlaced; - LONG lHalfLinesOdd; - WINBOOL bFieldPolarityInverted; - DWORD dwNumLinesInVREF; - LONG lHalfLinesEven; - DWORD dwReserved1; -}KS_AMVPDATAINFO, * PKS_AMVPDATAINFO; - -typedef struct tagKS_AMVPSIZE -{ - DWORD dwWidth; - DWORD dwHeight; -}KS_AMVPSIZE, * PKS_AMVPSIZE; - -typedef struct -{ - KS_AMVPSIZE Size; - DWORD MaxPixelsPerSecond; - DWORD Reserved; -}KSVPMAXPIXELRATE, * PKSVPMAXPIXELRATE; - -typedef struct -{ - KSPROPERTY Property; - KS_AMVPSIZE Size; -}KSVPSIZE_PROP, * PKSVPSIZE_PROP; - -typedef struct -{ - DWORD dwPitch; - DWORD dwXOrigin; - DWORD dwYOrigin; -}KSVPSURFACEPARAMS, * PKSVPSURFACEPARAMS; - # endif /* __IVPType__ */ - - # define STATIC_KSEVENTSETID_VPNotify \ - 0x20c5598eL, 0xd3c8, 0x11d0, 0x8d, 0xfc, 0x00, 0xc0, 0x4f, 0xd7, 0xc0, 0x8b -DEFINE_GUIDSTRUCT("20c5598e-d3c8-11d0-8dfc-00c04fd7c08b", KSEVENTSETID_VPNotify); - # define KSEVENTSETID_VPNotify DEFINE_GUIDNAMED(KSEVENTSETID_VPNotify) - -typedef enum -{ - KSEVENT_VPNOTIFY_FORMATCHANGE -}KSEVENT_VPNOTIFY; - - # define STATIC_KSEVENTSETID_VIDCAPTOSTI \ - 0xdb47de20, 0xf628, 0x11d1, 0xba, 0x41, 0x0, 0xa0, 0xc9, 0xd, 0x2b, 0x5 -DEFINE_GUIDSTRUCT("DB47DE20-F628-11d1-BA41-00A0C90D2B05", KSEVENTSETID_VIDCAPTOSTI); - # define KSEVENTSETID_VIDCAPNotify DEFINE_GUIDNAMED(KSEVENTSETID_VIDCAPTOSTI) - -typedef enum -{ - KSEVENT_VIDCAPTOSTI_EXT_TRIGGER, - KSEVENT_VIDCAP_AUTO_UPDATE, - KSEVENT_VIDCAP_SEARCH -}KSEVENT_VIDCAPTOSTI; - -typedef enum -{ - KSPROPERTY_EXTENSION_UNIT_INFO, - KSPROPERTY_EXTENSION_UNIT_CONTROL, - KSPROPERTY_EXTENSION_UNIT_PASS_THROUGH = 0xffff -}KSPROPERTY_EXTENSION_UNIT, * PKSPROPERTY_EXTENSION_UNIT; - - # define STATIC_KSEVENTSETID_VPVBINotify \ - 0xec529b01L, 0x1a1f, 0x11d1, 0xba, 0xd9, 0x0, 0x60, 0x97, 0x44, 0x11, 0x1a -DEFINE_GUIDSTRUCT("ec529b01-1a1f-11d1-bad9-00609744111a", KSEVENTSETID_VPVBINotify); - # define KSEVENTSETID_VPVBINotify DEFINE_GUIDNAMED(KSEVENTSETID_VPVBINotify) - -typedef enum -{ - KSEVENT_VPVBINOTIFY_FORMATCHANGE -}KSEVENT_VPVBINOTIFY; - - # define STATIC_KSDATAFORMAT_TYPE_AUXLine21Data \ - 0x670aea80L, 0x3a82, 0x11d0, 0xb7, 0x9b, 0x00, 0xaa, 0x00, 0x37, 0x67, 0xa7 -DEFINE_GUIDSTRUCT("670aea80-3a82-11d0-b79b-00aa003767a7", KSDATAFORMAT_TYPE_AUXLine21Data); - # define KSDATAFORMAT_TYPE_AUXLine21Data DEFINE_GUIDNAMED(KSDATAFORMAT_TYPE_AUXLine21Data) - - # define STATIC_KSDATAFORMAT_SUBTYPE_Line21_BytePair \ - 0x6e8d4a22L, 0x310c, 0x11d0, 0xb7, 0x9a, 0x00, 0xaa, 0x00, 0x37, 0x67, 0xa7 -DEFINE_GUIDSTRUCT("6e8d4a22-310c-11d0-b79a-00aa003767a7", KSDATAFORMAT_SUBTYPE_Line21_BytePair); - # define KSDATAFORMAT_SUBTYPE_Line21_BytePair DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_Line21_BytePair) - - # define STATIC_KSDATAFORMAT_SUBTYPE_Line21_GOPPacket \ - 0x6e8d4a23L, 0x310c, 0x11d0, 0xb7, 0x9a, 0x00, 0xaa, 0x00, 0x37, 0x67, 0xa7 -DEFINE_GUIDSTRUCT("6e8d4a23-310c-11d0-b79a-00aa003767a7", KSDATAFORMAT_SUBTYPE_Line21_GOPPacket); - # define KSDATAFORMAT_SUBTYPE_Line21_GOPPacket DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_Line21_GOPPacket) - -typedef struct _KSGOP_USERDATA -{ - ULONG sc; - ULONG reserved1; - BYTE cFields; - CHAR l21Data[3]; -}KSGOP_USERDATA, * PKSGOP_USERDATA; - - # define STATIC_KSDATAFORMAT_TYPE_DVD_ENCRYPTED_PACK \ - 0xed0b916a, 0x044d, 0x11d1, 0xaa, 0x78, 0x00, 0xc0, 0x4f, 0xc3, 0x1d, 0x60 -DEFINE_GUIDSTRUCT("ed0b916a-044d-11d1-aa78-00c04fc31d60", KSDATAFORMAT_TYPE_DVD_ENCRYPTED_PACK); - # define KSDATAFORMAT_TYPE_DVD_ENCRYPTED_PACK DEFINE_GUIDNAMED(KSDATAFORMAT_TYPE_DVD_ENCRYPTED_PACK) - - # define KS_AM_UseNewCSSKey 0x1 - - # define STATIC_KSPROPSETID_TSRateChange \ - 0xa503c5c0, 0x1d1d, 0x11d1, 0xad, 0x80, 0x44, 0x45, 0x53, 0x54, 0x0, 0x0 -DEFINE_GUIDSTRUCT("A503C5C0-1D1D-11D1-AD80-444553540000", KSPROPSETID_TSRateChange); - # define KSPROPSETID_TSRateChange DEFINE_GUIDNAMED(KSPROPSETID_TSRateChange) - -typedef enum -{ - KS_AM_RATE_SimpleRateChange = 1, - KS_AM_RATE_ExactRateChange = 2, - KS_AM_RATE_MaxFullDataRate = 3, - KS_AM_RATE_Step = 4 -}KS_AM_PROPERTY_TS_RATE_CHANGE; - -typedef struct -{ - REFERENCE_TIME StartTime; - LONG Rate; -}KS_AM_SimpleRateChange, * PKS_AM_SimpleRateChange; - -typedef struct -{ - REFERENCE_TIME OutputZeroTime; - LONG Rate; -}KS_AM_ExactRateChange, * PKS_AM_ExactRateChange; - -typedef LONG KS_AM_MaxFullDataRate; -typedef DWORD KS_AM_Step; - - # define STATIC_KSCATEGORY_ENCODER \ - 0x19689bf6, 0xc384, 0x48fd, 0xad, 0x51, 0x90, 0xe5, 0x8c, 0x79, 0xf7, 0xb -DEFINE_GUIDSTRUCT("19689BF6-C384-48fd-AD51-90E58C79F70B", KSCATEGORY_ENCODER); - # define KSCATEGORY_ENCODER DEFINE_GUIDNAMED(KSCATEGORY_ENCODER) - - # define STATIC_KSCATEGORY_MULTIPLEXER \ - 0x7a5de1d3, 0x1a1, 0x452c, 0xb4, 0x81, 0x4f, 0xa2, 0xb9, 0x62, 0x71, 0xe8 -DEFINE_GUIDSTRUCT("7A5DE1D3-01A1-452c-B481-4FA2B96271E8", KSCATEGORY_MULTIPLEXER); - # define KSCATEGORY_MULTIPLEXER DEFINE_GUIDNAMED(KSCATEGORY_MULTIPLEXER) - - # ifndef __ENCODER_API_GUIDS__ - # define __ENCODER_API_GUIDS__ - - # define STATIC_ENCAPIPARAM_BITRATE \ - 0x49cc4c43, 0xca83, 0x4ad4, 0xa9, 0xaf, 0xf3, 0x69, 0x6a, 0xf6, 0x66, 0xdf -DEFINE_GUIDSTRUCT("49CC4C43-CA83-4ad4-A9AF-F3696AF666DF", ENCAPIPARAM_BITRATE); - # define ENCAPIPARAM_BITRATE DEFINE_GUIDNAMED(ENCAPIPARAM_BITRATE) - - # define STATIC_ENCAPIPARAM_PEAK_BITRATE \ - 0x703f16a9, 0x3d48, 0x44a1, 0xb0, 0x77, 0x1, 0x8d, 0xff, 0x91, 0x5d, 0x19 -DEFINE_GUIDSTRUCT("703F16A9-3D48-44a1-B077-018DFF915D19", ENCAPIPARAM_PEAK_BITRATE); - # define ENCAPIPARAM_PEAK_BITRATE DEFINE_GUIDNAMED(ENCAPIPARAM_PEAK_BITRATE) - - # define STATIC_ENCAPIPARAM_BITRATE_MODE \ - 0xee5fb25c, 0xc713, 0x40d1, 0x9d, 0x58, 0xc0, 0xd7, 0x24, 0x1e, 0x25, 0xf -DEFINE_GUIDSTRUCT("EE5FB25C-C713-40d1-9D58-C0D7241E250F", ENCAPIPARAM_BITRATE_MODE); - # define ENCAPIPARAM_BITRATE_MODE DEFINE_GUIDNAMED(ENCAPIPARAM_BITRATE_MODE) - - # define STATIC_CODECAPI_CHANGELISTS \ - 0x62b12acf, 0xf6b0, 0x47d9, 0x94, 0x56, 0x96, 0xf2, 0x2c, 0x4e, 0x0b, 0x9d -DEFINE_GUIDSTRUCT("62B12ACF-F6B0-47D9-9456-96F22C4E0B9D", CODECAPI_CHANGELISTS); - # define CODECAPI_CHANGELISTS DEFINE_GUIDNAMED(CODECAPI_CHANGELISTS) - - # define STATIC_CODECAPI_VIDEO_ENCODER \ - 0x7112e8e1, 0x3d03, 0x47ef, 0x8e, 0x60, 0x03, 0xf1, 0xcf, 0x53, 0x73, 0x01 -DEFINE_GUIDSTRUCT("7112E8E1-3D03-47EF-8E60-03F1CF537301", CODECAPI_VIDEO_ENCODER); - # define CODECAPI_VIDEO_ENCODER DEFINE_GUIDNAMED(CODECAPI_VIDEO_ENCODER) - - # define STATIC_CODECAPI_AUDIO_ENCODER \ - 0xb9d19a3e, 0xf897, 0x429c, 0xbc, 0x46, 0x81, 0x38, 0xb7, 0x27, 0x2b, 0x2d -DEFINE_GUIDSTRUCT("B9D19A3E-F897-429C-BC46-8138B7272B2D", CODECAPI_AUDIO_ENCODER); - # define CODECAPI_AUDIO_ENCODER DEFINE_GUIDNAMED(CODECAPI_AUDIO_ENCODER) - - # define STATIC_CODECAPI_SETALLDEFAULTS \ - 0x6c5e6a7c, 0xacf8, 0x4f55, 0xa9, 0x99, 0x1a, 0x62, 0x81, 0x09, 0x05, 0x1b -DEFINE_GUIDSTRUCT("6C5E6A7C-ACF8-4F55-A999-1A628109051B", CODECAPI_SETALLDEFAULTS); - # define CODECAPI_SETALLDEFAULTS DEFINE_GUIDNAMED(CODECAPI_SETALLDEFAULTS) - - # define STATIC_CODECAPI_ALLSETTINGS \ - 0x6a577e92, 0x83e1, 0x4113, 0xad, 0xc2, 0x4f, 0xce, 0xc3, 0x2f, 0x83, 0xa1 -DEFINE_GUIDSTRUCT("6A577E92-83E1-4113-ADC2-4FCEC32F83A1", CODECAPI_ALLSETTINGS); - # define CODECAPI_ALLSETTINGS DEFINE_GUIDNAMED(CODECAPI_ALLSETTINGS) - - # define STATIC_CODECAPI_SUPPORTSEVENTS \ - 0x0581af97, 0x7693, 0x4dbd, 0x9d, 0xca, 0x3f, 0x9e, 0xbd, 0x65, 0x85, 0xa1 -DEFINE_GUIDSTRUCT("0581AF97-7693-4DBD-9DCA-3F9EBD6585A1", CODECAPI_SUPPORTSEVENTS); - # define CODECAPI_SUPPORTSEVENTS DEFINE_GUIDNAMED(CODECAPI_SUPPORTSEVENTS) - - # define STATIC_CODECAPI_CURRENTCHANGELIST \ - 0x1cb14e83, 0x7d72, 0x4657, 0x83, 0xfd, 0x47, 0xa2, 0xc5, 0xb9, 0xd1, 0x3d -DEFINE_GUIDSTRUCT("1CB14E83-7D72-4657-83FD-47A2C5B9D13D", CODECAPI_CURRENTCHANGELIST); - # define CODECAPI_CURRENTCHANGELIST DEFINE_GUIDNAMED(CODECAPI_CURRENTCHANGELIST) - # endif /* __ENCODER_API_GUIDS__ */ - - # ifndef __ENCODER_API_DEFINES__ - # define __ENCODER_API_DEFINES__ -typedef enum -{ - ConstantBitRate = 0, - VariableBitRateAverage, - VariableBitRatePeak -}VIDEOENCODER_BITRATE_MODE; - # endif /* __ENCODER_API_DEFINES__ */ - - # define STATIC_KSPROPSETID_Jack \ - 0x4509f757, 0x2d46, 0x4637, 0x8e, 0x62, 0xce, 0x7d, 0xb9, 0x44, 0xf5, 0x7b -DEFINE_GUIDSTRUCT("4509F757-2D46-4637-8E62-CE7DB944F57B", KSPROPSETID_Jack); - # define KSPROPSETID_Jack DEFINE_GUIDNAMED(KSPROPSETID_Jack) - -typedef enum -{ - KSPROPERTY_JACK_DESCRIPTION = 1, - KSPROPERTY_JACK_DESCRIPTION2, - KSPROPERTY_JACK_SINK_INFO -}KSPROPERTY_JACK; - -typedef enum -{ - eConnTypeUnknown, - eConnType3Point5mm, - eConnTypeQuarter, - eConnTypeAtapiInternal, - eConnTypeRCA, - eConnTypeOptical, - eConnTypeOtherDigital, - eConnTypeOtherAnalog, - eConnTypeMultichannelAnalogDIN, - eConnTypeXlrProfessional, - eConnTypeRJ11Modem, - eConnTypeCombination -}EPcxConnectionType; - -typedef enum -{ - eGeoLocRear = 0x1, - eGeoLocFront, - eGeoLocLeft, - eGeoLocRight, - eGeoLocTop, - eGeoLocBottom, - eGeoLocRearPanel, - eGeoLocRiser, - eGeoLocInsideMobileLid, - eGeoLocDrivebay, - eGeoLocHDMI, - eGeoLocOutsideMobileLid, - eGeoLocATAPI, - eGeoLocReserved5, - eGeoLocReserved6, - EPcxGeoLocation_enum_count -}EPcxGeoLocation; - -typedef enum -{ - eGenLocPrimaryBox = 0, - eGenLocInternal, - eGenLocSeparate, - eGenLocOther, - EPcxGenLocation_enum_count -}EPcxGenLocation; - -typedef enum -{ - ePortConnJack = 0, - ePortConnIntegratedDevice, - ePortConnBothIntegratedAndJack, - ePortConnUnknown -}EPxcPortConnection; - -typedef struct -{ - DWORD ChannelMapping; - COLORREF Color; - EPcxConnectionType ConnectionType; - EPcxGeoLocation GeoLocation; - EPcxGenLocation GenLocation; - EPxcPortConnection PortConnection; - BOOL IsConnected; -}KSJACK_DESCRIPTION, * PKSJACK_DESCRIPTION; - -typedef enum -{ - KSJACK_SINK_CONNECTIONTYPE_HDMI = 0, - KSJACK_SINK_CONNECTIONTYPE_DISPLAYPORT, -}KSJACK_SINK_CONNECTIONTYPE; - - # define MAX_SINK_DESCRIPTION_NAME_LENGTH 32 -typedef struct _tagKSJACK_SINK_INFORMATION -{ - KSJACK_SINK_CONNECTIONTYPE ConnType; - WORD ManufacturerId; - WORD ProductId; - WORD AudioLatency; - BOOL HDCPCapable; - BOOL AICapable; - UCHAR SinkDescriptionLength; - WCHAR SinkDescription[MAX_SINK_DESCRIPTION_NAME_LENGTH]; - LUID PortId; -}KSJACK_SINK_INFORMATION, * PKSJACK_SINK_INFORMATION; - - # define JACKDESC2_PRESENCE_DETECT_CAPABILITY 0x00000001 - # define JACKDESC2_DYNAMIC_FORMAT_CHANGE_CAPABILITY 0x00000002 - -typedef struct _tagKSJACK_DESCRIPTION2 -{ - DWORD DeviceStateInfo; - DWORD JackCapabilities; -}KSJACK_DESCRIPTION2, * PKSJACK_DESCRIPTION2; - -#endif /* _KSMEDIA_ */ - diff --git a/librtmidi.pc.in b/librtmidi.pc.in deleted file mode 100644 index d3099065..00000000 --- a/librtmidi.pc.in +++ /dev/null @@ -1,12 +0,0 @@ -prefix=@prefix@ -exec_prefix=${prefix} -libdir=${exec_prefix}/lib -includedir=${prefix}/include - -Name: librtmidi -Description: RtMidi - a set of C++ classes that provide a common API for realtime MIDI input/output -Version: 2.1.0 -Requires: @req@ -Libs: -L${libdir} -lrtmidi -Libs.private: -lpthread -Cflags: -pthread -I${includedir} @CPPFLAGS@ \ No newline at end of file diff --git a/m4/ChangeLog b/m4/ChangeLog new file mode 100644 index 00000000..33ccb9bb --- /dev/null +++ b/m4/ChangeLog @@ -0,0 +1,11 @@ +2018-01-07 gettextize + + * gettext.m4: Upgrade to gettext-0.19.8.1. + * iconv.m4: Upgrade to gettext-0.19.8.1. + * lib-ld.m4: Upgrade to gettext-0.19.8.1. + * lib-link.m4: Upgrade to gettext-0.19.8.1. + * lib-prefix.m4: Upgrade to gettext-0.19.8.1. + * nls.m4: Upgrade to gettext-0.19.8.1. + * po.m4: Upgrade to gettext-0.19.8.1. + * progtest.m4: Upgrade to gettext-0.19.8.1. + diff --git a/m4/alsa.m4 b/m4/alsa.m4 new file mode 100644 index 00000000..e12310df --- /dev/null +++ b/m4/alsa.m4 @@ -0,0 +1,143 @@ +dnl Configure Paths for Alsa +dnl Some modifications by Richard Boulton +dnl Christopher Lansdown +dnl Jaroslav Kysela +dnl Last modification: $Id: alsa.m4,v 1.24 2004/09/15 18:48:07 tiwai Exp $ +dnl AM_PATH_ALSA([MINIMUM-VERSION [, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]]) +dnl Test for libasound, and define ALSA_CFLAGS and ALSA_LIBS as appropriate. +dnl enables arguments --with-alsa-prefix= +dnl --with-alsa-enc-prefix= +dnl --disable-alsatest +dnl +dnl For backwards compatibility, if ACTION_IF_NOT_FOUND is not specified, +dnl and the alsa libraries are not found, a fatal AC_MSG_ERROR() will result. +dnl +AC_DEFUN([AM_PATH_ALSA], +[dnl Save the original CFLAGS, LDFLAGS, and LIBS +alsa_save_CFLAGS="$CFLAGS" +alsa_save_LDFLAGS="$LDFLAGS" +alsa_save_LIBS="$LIBS" +alsa_found=yes + +dnl +dnl Get the cflags and libraries for alsa +dnl +AC_ARG_WITH(alsa-prefix, +[ --with-alsa-prefix=PFX Prefix where Alsa library is installed(optional)], +[alsa_prefix="$withval"], [alsa_prefix=""]) + +AC_ARG_WITH(alsa-inc-prefix, +[ --with-alsa-inc-prefix=PFX Prefix where include libraries are (optional)], +[alsa_inc_prefix="$withval"], [alsa_inc_prefix=""]) + +dnl FIXME: this is not yet implemented +AC_ARG_ENABLE(alsatest, +[ --disable-alsatest Do not try to compile and run a test Alsa program], +[enable_alsatest="$enableval"], +[enable_alsatest=yes]) + +dnl Add any special include directories +AC_MSG_CHECKING(for ALSA CFLAGS) +if test "$alsa_inc_prefix" != "" ; then + ALSA_CFLAGS="$ALSA_CFLAGS -I$alsa_inc_prefix" + CFLAGS="$CFLAGS -I$alsa_inc_prefix" +fi +AC_MSG_RESULT($ALSA_CFLAGS) + +dnl add any special lib dirs +AC_MSG_CHECKING(for ALSA LDFLAGS) +if test "$alsa_prefix" != "" ; then + ALSA_LIBS="$ALSA_LIBS -L$alsa_prefix" + LDFLAGS="$LDFLAGS $ALSA_LIBS" +fi + +dnl add the alsa library +ALSA_LIBS="$ALSA_LIBS -lasound -lm -ldl -lpthread" +LIBS="$ALSA_LIBS $LIBS" +AC_MSG_RESULT($ALSA_LIBS) + +dnl Check for a working version of libasound that is of the right version. +if test "x$enable_alsatest" = "xyes"; then +min_alsa_version=ifelse([$1], ,0.1.1,$1) +AC_MSG_CHECKING(for libasound headers version >= $min_alsa_version) +no_alsa="" + alsa_min_major_version=`echo $min_alsa_version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` + alsa_min_minor_version=`echo $min_alsa_version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` + alsa_min_micro_version=`echo $min_alsa_version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` + +AC_LANG_SAVE +AC_LANG_C +AC_TRY_COMPILE([ +#include +], [ +/* ensure backward compatibility */ +#if !defined(SND_LIB_MAJOR) && defined(SOUNDLIB_VERSION_MAJOR) +#define SND_LIB_MAJOR SOUNDLIB_VERSION_MAJOR +#endif +#if !defined(SND_LIB_MINOR) && defined(SOUNDLIB_VERSION_MINOR) +#define SND_LIB_MINOR SOUNDLIB_VERSION_MINOR +#endif +#if !defined(SND_LIB_SUBMINOR) && defined(SOUNDLIB_VERSION_SUBMINOR) +#define SND_LIB_SUBMINOR SOUNDLIB_VERSION_SUBMINOR +#endif + +# if(SND_LIB_MAJOR > $alsa_min_major_version) + exit(0); +# else +# if(SND_LIB_MAJOR < $alsa_min_major_version) +# error not present +# endif + +# if(SND_LIB_MINOR > $alsa_min_minor_version) + exit(0); +# else +# if(SND_LIB_MINOR < $alsa_min_minor_version) +# error not present +# endif + +# if(SND_LIB_SUBMINOR < $alsa_min_micro_version) +# error not present +# endif +# endif +# endif +exit(0); +], + [AC_MSG_RESULT(found.)], + [AC_MSG_RESULT(not present.) + ifelse([$3], , [AC_MSG_ERROR(Sufficiently new version of libasound not found.)]) + alsa_found=no] +) +AC_LANG_RESTORE +fi + +dnl Now that we know that we have the right version, let's see if we have the library and not just the headers. +if test "x$enable_alsatest" = "xyes"; then +AC_CHECK_LIB([asound], [snd_ctl_open],, + [ifelse([$3], , [AC_MSG_ERROR(No linkable libasound was found.)]) + alsa_found=no] +) +fi + +if test "x$alsa_found" = "xyes" ; then + ifelse([$2], , :, [$2]) + LIBS=`echo $LIBS | sed 's/-lasound//g'` + LIBS=`echo $LIBS | sed 's/ //'` + LIBS="-lasound $LIBS" +fi +if test "x$alsa_found" = "xno" ; then + ifelse([$3], , :, [$3]) + CFLAGS="$alsa_save_CFLAGS" + LDFLAGS="$alsa_save_LDFLAGS" + LIBS="$alsa_save_LIBS" + ALSA_CFLAGS="" + ALSA_LIBS="" +fi + +dnl That should be it. Now just export out symbols: +AC_SUBST(ALSA_CFLAGS) +AC_SUBST(ALSA_LIBS) +]) + diff --git a/m4/ax_check_compile_flag.m4 b/m4/ax_check_compile_flag.m4 new file mode 100644 index 00000000..dcabb92a --- /dev/null +++ b/m4/ax_check_compile_flag.m4 @@ -0,0 +1,74 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT]) +# +# DESCRIPTION +# +# Check whether the given FLAG works with the current language's compiler +# or gives an error. (Warnings, however, are ignored) +# +# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on +# success/failure. +# +# If EXTRA-FLAGS is defined, it is added to the current language's default +# flags (e.g. CFLAGS) when the check is done. The check is thus made with +# the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to +# force the compiler to issue an error when a bad flag is given. +# +# INPUT gives an alternative input source to AC_COMPILE_IFELSE. +# +# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this +# macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG. +# +# LICENSE +# +# Copyright (c) 2008 Guido U. Draheim +# Copyright (c) 2011 Maarten Bosmans +# +# 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 3 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, see . +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +#serial 5 + +AC_DEFUN([AX_CHECK_COMPILE_FLAG], +[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF +AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl +AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [ + ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS + _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1" + AC_COMPILE_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])], + [AS_VAR_SET(CACHEVAR,[yes])], + [AS_VAR_SET(CACHEVAR,[no])]) + _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags]) +AS_VAR_IF(CACHEVAR,yes, + [m4_default([$2], :)], + [m4_default([$3], :)]) +AS_VAR_POPDEF([CACHEVAR])dnl +])dnl AX_CHECK_COMPILE_FLAGS diff --git a/m4/ax_cxx_compile_stdcxx.m4 b/m4/ax_cxx_compile_stdcxx.m4 new file mode 100644 index 00000000..5032bba8 --- /dev/null +++ b/m4/ax_cxx_compile_stdcxx.m4 @@ -0,0 +1,982 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_CXX_COMPILE_STDCXX(VERSION, [ext|noext], [mandatory|optional]) +# +# DESCRIPTION +# +# Check for baseline language coverage in the compiler for the specified +# version of the C++ standard. If necessary, add switches to CXX and +# CXXCPP to enable support. VERSION may be '11' (for the C++11 standard) +# or '14' (for the C++14 standard). +# +# The second argument, if specified, indicates whether you insist on an +# extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g. +# -std=c++11). If neither is specified, you get whatever works, with +# preference for an extended mode. +# +# The third argument, if specified 'mandatory' or if left unspecified, +# indicates that baseline support for the specified C++ standard is +# required and that the macro should error out if no mode with that +# support is found. If specified 'optional', then configuration proceeds +# regardless, after defining HAVE_CXX${VERSION} if and only if a +# supporting mode is found. +# +# LICENSE +# +# Copyright (c) 2008 Benjamin Kosnik +# Copyright (c) 2012 Zack Weinberg +# Copyright (c) 2013 Roy Stogner +# Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov +# Copyright (c) 2015 Paul Norman +# Copyright (c) 2015 Moritz Klammler +# Copyright (c) 2016 Krzesimir Nowak +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 7 + +dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro +dnl (serial version number 13). + +AX_REQUIRE_DEFINED([AC_MSG_WARN]) +AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl + m4_if([$1], [11], [ax_cxx_compile_alternatives="11 0x"], + [$1], [14], [ax_cxx_compile_alternatives="14 1y"], + [$1], [17], [ax_cxx_compile_alternatives="17 1z"], + [m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl + m4_if([$2], [], [], + [$2], [ext], [], + [$2], [noext], [], + [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX])])dnl + m4_if([$3], [], [ax_cxx_compile_cxx$1_required=true], + [$3], [mandatory], [ax_cxx_compile_cxx$1_required=true], + [$3], [optional], [ax_cxx_compile_cxx$1_required=false], + [m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])]) + AC_LANG_PUSH([C++])dnl + ac_success=no + AC_CACHE_CHECK(whether $CXX supports C++$1 features by default, + ax_cv_cxx_compile_cxx$1, + [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], + [ax_cv_cxx_compile_cxx$1=yes], + [ax_cv_cxx_compile_cxx$1=no])]) + if test x$ax_cv_cxx_compile_cxx$1 = xyes; then + ac_success=yes + fi + + m4_if([$2], [noext], [], [dnl + if test x$ac_success = xno; then + for alternative in ${ax_cxx_compile_alternatives}; do + switch="-std=gnu++${alternative}" + cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) + AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, + $cachevar, + [ac_save_CXX="$CXX" + CXX="$CXX $switch" + AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], + [eval $cachevar=yes], + [eval $cachevar=no]) + CXX="$ac_save_CXX"]) + if eval test x\$$cachevar = xyes; then + CXX="$CXX $switch" + if test -n "$CXXCPP" ; then + CXXCPP="$CXXCPP $switch" + fi + ac_success=yes + break + fi + done + fi]) + + m4_if([$2], [ext], [], [dnl + if test x$ac_success = xno; then + dnl HP's aCC needs +std=c++11 according to: + dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf + dnl Cray's crayCC needs "-h std=c++11" + for alternative in ${ax_cxx_compile_alternatives}; do + for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}"; do + cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) + AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, + $cachevar, + [ac_save_CXX="$CXX" + CXX="$CXX $switch" + AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], + [eval $cachevar=yes], + [eval $cachevar=no]) + CXX="$ac_save_CXX"]) + if eval test x\$$cachevar = xyes; then + CXX="$CXX $switch" + if test -n "$CXXCPP" ; then + CXXCPP="$CXXCPP $switch" + fi + ac_success=yes + break + fi + done + if test x$ac_success = xyes; then + break + fi + done + fi]) + AC_LANG_POP([C++]) + if test x$ax_cxx_compile_cxx$1_required = xtrue; then + if test x$ac_success = xno; then + AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.]) + fi + fi + if test x$ac_success = xno; then + HAVE_CXX$1=0 + AC_MSG_NOTICE([No compiler with C++$1 support was found]) + else + HAVE_CXX$1=1 + AC_DEFINE(HAVE_CXX$1,1, + [define if the compiler supports basic C++$1 syntax]) + fi + AC_SUBST(HAVE_CXX$1) + m4_if([$1], [17], [AC_MSG_WARN([C++17 is not yet standardized, so the checks may change in incompatible ways anytime])]) +]) + + +dnl Test body for checking C++11 support + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11], + _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 +) + + +dnl Test body for checking C++14 support + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14], + _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 +) + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_17], + _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_17 +) + +dnl Tests for new features in C++11 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[ + +// If the compiler admits that it is not ready for C++11, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 201103L + +#error "This is not a C++11 compiler" + +#else + +namespace cxx11 +{ + + namespace test_static_assert + { + + template + struct check + { + static_assert(sizeof(int) <= sizeof(T), "not big enough"); + }; + + } + + namespace test_final_override + { + + struct Base + { + virtual void f() {} + }; + + struct Derived : public Base + { + virtual void f() override {} + }; + + } + + namespace test_double_right_angle_brackets + { + + template < typename T > + struct check {}; + + typedef check single_type; + typedef check> double_type; + typedef check>> triple_type; + typedef check>>> quadruple_type; + + } + + namespace test_decltype + { + + int + f() + { + int a = 1; + decltype(a) b = 2; + return a + b; + } + + } + + namespace test_type_deduction + { + + template < typename T1, typename T2 > + struct is_same + { + static const bool value = false; + }; + + template < typename T > + struct is_same + { + static const bool value = true; + }; + + template < typename T1, typename T2 > + auto + add(T1 a1, T2 a2) -> decltype(a1 + a2) + { + return a1 + a2; + } + + int + test(const int c, volatile int v) + { + static_assert(is_same::value == true, ""); + static_assert(is_same::value == false, ""); + static_assert(is_same::value == false, ""); + auto ac = c; + auto av = v; + auto sumi = ac + av + 'x'; + auto sumf = ac + av + 1.0; + static_assert(is_same::value == true, ""); + static_assert(is_same::value == true, ""); + static_assert(is_same::value == true, ""); + static_assert(is_same::value == false, ""); + static_assert(is_same::value == true, ""); + return (sumf > 0.0) ? sumi : add(c, v); + } + + } + + namespace test_noexcept + { + + int f() { return 0; } + int g() noexcept { return 0; } + + static_assert(noexcept(f()) == false, ""); + static_assert(noexcept(g()) == true, ""); + + } + + namespace test_constexpr + { + + template < typename CharT > + unsigned long constexpr + strlen_c_r(const CharT *const s, const unsigned long acc) noexcept + { + return *s ? strlen_c_r(s + 1, acc + 1) : acc; + } + + template < typename CharT > + unsigned long constexpr + strlen_c(const CharT *const s) noexcept + { + return strlen_c_r(s, 0UL); + } + + static_assert(strlen_c("") == 0UL, ""); + static_assert(strlen_c("1") == 1UL, ""); + static_assert(strlen_c("example") == 7UL, ""); + static_assert(strlen_c("another\0example") == 7UL, ""); + + } + + namespace test_rvalue_references + { + + template < int N > + struct answer + { + static constexpr int value = N; + }; + + answer<1> f(int&) { return answer<1>(); } + answer<2> f(const int&) { return answer<2>(); } + answer<3> f(int&&) { return answer<3>(); } + + void + test() + { + int i = 0; + const int c = 0; + static_assert(decltype(f(i))::value == 1, ""); + static_assert(decltype(f(c))::value == 2, ""); + static_assert(decltype(f(0))::value == 3, ""); + } + + } + + namespace test_uniform_initialization + { + + struct test + { + static const int zero {}; + static const int one {1}; + }; + + static_assert(test::zero == 0, ""); + static_assert(test::one == 1, ""); + + } + + namespace test_lambdas + { + + void + test1() + { + auto lambda1 = [](){}; + auto lambda2 = lambda1; + lambda1(); + lambda2(); + } + + int + test2() + { + auto a = [](int i, int j){ return i + j; }(1, 2); + auto b = []() -> int { return '0'; }(); + auto c = [=](){ return a + b; }(); + auto d = [&](){ return c; }(); + auto e = [a, &b](int x) mutable { + const auto identity = [](int y){ return y; }; + for (auto i = 0; i < a; ++i) + a += b--; + return x + identity(a + b); + }(0); + return a + b + c + d + e; + } + + int + test3() + { + const auto nullary = [](){ return 0; }; + const auto unary = [](int x){ return x; }; + using nullary_t = decltype(nullary); + using unary_t = decltype(unary); + const auto higher1st = [](nullary_t f){ return f(); }; + const auto higher2nd = [unary](nullary_t f1){ + return [unary, f1](unary_t f2){ return f2(unary(f1())); }; + }; + return higher1st(nullary) + higher2nd(nullary)(unary); + } + + } + + namespace test_variadic_templates + { + + template + struct sum; + + template + struct sum + { + static constexpr auto value = N0 + sum::value; + }; + + template <> + struct sum<> + { + static constexpr auto value = 0; + }; + + static_assert(sum<>::value == 0, ""); + static_assert(sum<1>::value == 1, ""); + static_assert(sum<23>::value == 23, ""); + static_assert(sum<1, 2>::value == 3, ""); + static_assert(sum<5, 5, 11>::value == 21, ""); + static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, ""); + + } + + // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae + // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function + // because of this. + namespace test_template_alias_sfinae + { + + struct foo {}; + + template + using member = typename T::member_type; + + template + void func(...) {} + + template + void func(member*) {} + + void test(); + + void test() { func(0); } + + } + +} // namespace cxx11 + +#endif // __cplusplus >= 201103L + +]]) + + +dnl Tests for new features in C++14 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[ + +// If the compiler admits that it is not ready for C++14, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 201402L + +#error "This is not a C++14 compiler" + +#else + +namespace cxx14 +{ + + namespace test_polymorphic_lambdas + { + + int + test() + { + const auto lambda = [](auto&&... args){ + const auto istiny = [](auto x){ + return (sizeof(x) == 1UL) ? 1 : 0; + }; + const int aretiny[] = { istiny(args)... }; + return aretiny[0]; + }; + return lambda(1, 1L, 1.0f, '1'); + } + + } + + namespace test_binary_literals + { + + constexpr auto ivii = 0b0000000000101010; + static_assert(ivii == 42, "wrong value"); + + } + + namespace test_generalized_constexpr + { + + template < typename CharT > + constexpr unsigned long + strlen_c(const CharT *const s) noexcept + { + auto length = 0UL; + for (auto p = s; *p; ++p) + ++length; + return length; + } + + static_assert(strlen_c("") == 0UL, ""); + static_assert(strlen_c("x") == 1UL, ""); + static_assert(strlen_c("test") == 4UL, ""); + static_assert(strlen_c("another\0test") == 7UL, ""); + + } + + namespace test_lambda_init_capture + { + + int + test() + { + auto x = 0; + const auto lambda1 = [a = x](int b){ return a + b; }; + const auto lambda2 = [a = lambda1(x)](){ return a; }; + return lambda2(); + } + + } + + namespace test_digit_separators + { + + constexpr auto ten_million = 100'000'000; + static_assert(ten_million == 100000000, ""); + + } + + namespace test_return_type_deduction + { + + auto f(int& x) { return x; } + decltype(auto) g(int& x) { return x; } + + template < typename T1, typename T2 > + struct is_same + { + static constexpr auto value = false; + }; + + template < typename T > + struct is_same + { + static constexpr auto value = true; + }; + + int + test() + { + auto x = 0; + static_assert(is_same::value, ""); + static_assert(is_same::value, ""); + return x; + } + + } + +} // namespace cxx14 + +#endif // __cplusplus >= 201402L + +]]) + + +dnl Tests for new features in C++17 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_17], [[ + +// If the compiler admits that it is not ready for C++17, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus <= 201402L + +#error "This is not a C++17 compiler" + +#else + +#if defined(__clang__) + #define REALLY_CLANG +#else + #if defined(__GNUC__) + #define REALLY_GCC + #endif +#endif + +#include +#include +#include + +namespace cxx17 +{ + +#if !defined(REALLY_CLANG) + namespace test_constexpr_lambdas + { + + // TODO: test it with clang++ from git + + constexpr int foo = [](){return 42;}(); + + } +#endif // !defined(REALLY_CLANG) + + namespace test::nested_namespace::definitions + { + + } + + namespace test_fold_expression + { + + template + int multiply(Args... args) + { + return (args * ... * 1); + } + + template + bool all(Args... args) + { + return (args && ...); + } + + } + + namespace test_extended_static_assert + { + + static_assert (true); + + } + + namespace test_auto_brace_init_list + { + + auto foo = {5}; + auto bar {5}; + + static_assert(std::is_same, decltype(foo)>::value); + static_assert(std::is_same::value); + } + + namespace test_typename_in_template_template_parameter + { + + template typename X> struct D; + + } + + namespace test_fallthrough_nodiscard_maybe_unused_attributes + { + + int f1() + { + return 42; + } + + [[nodiscard]] int f2() + { + [[maybe_unused]] auto unused = f1(); + + switch (f1()) + { + case 17: + f1(); + [[fallthrough]]; + case 42: + f1(); + } + return f1(); + } + + } + + namespace test_extended_aggregate_initialization + { + + struct base1 + { + int b1, b2 = 42; + }; + + struct base2 + { + base2() { + b3 = 42; + } + int b3; + }; + + struct derived : base1, base2 + { + int d; + }; + + derived d1 {{1, 2}, {}, 4}; // full initialization + derived d2 {{}, {}, 4}; // value-initialized bases + + } + + namespace test_general_range_based_for_loop + { + + struct iter + { + int i; + + int& operator* () + { + return i; + } + + const int& operator* () const + { + return i; + } + + iter& operator++() + { + ++i; + return *this; + } + }; + + struct sentinel + { + int i; + }; + + bool operator== (const iter& i, const sentinel& s) + { + return i.i == s.i; + } + + bool operator!= (const iter& i, const sentinel& s) + { + return !(i == s); + } + + struct range + { + iter begin() const + { + return {0}; + } + + sentinel end() const + { + return {5}; + } + }; + + void f() + { + range r {}; + + for (auto i : r) + { + [[maybe_unused]] auto v = i; + } + } + + } + + namespace test_lambda_capture_asterisk_this_by_value + { + + struct t + { + int i; + int foo() + { + return [*this]() + { + return i; + }(); + } + }; + + } + + namespace test_enum_class_construction + { + + enum class byte : unsigned char + {}; + + byte foo {42}; + + } + + namespace test_constexpr_if + { + + template + int f () + { + if constexpr(cond) + { + return 13; + } + else + { + return 42; + } + } + + } + + namespace test_selection_statement_with_initializer + { + + int f() + { + return 13; + } + + int f2() + { + if (auto i = f(); i > 0) + { + return 3; + } + + switch (auto i = f(); i + 4) + { + case 17: + return 2; + + default: + return 1; + } + } + + } + +#if !defined(REALLY_CLANG) + namespace test_template_argument_deduction_for_class_templates + { + + // TODO: test it with clang++ from git + + template + struct pair + { + pair (T1 p1, T2 p2) + : m1 {p1}, + m2 {p2} + {} + + T1 m1; + T2 m2; + }; + + void f() + { + [[maybe_unused]] auto p = pair{13, 42u}; + } + + } +#endif // !defined(REALLY_CLANG) + + namespace test_non_type_auto_template_parameters + { + + template + struct B + {}; + + B<5> b1; + B<'a'> b2; + + } + +#if !defined(REALLY_CLANG) + namespace test_structured_bindings + { + + // TODO: test it with clang++ from git + + int arr[2] = { 1, 2 }; + std::pair pr = { 1, 2 }; + + auto f1() -> int(&)[2] + { + return arr; + } + + auto f2() -> std::pair& + { + return pr; + } + + struct S + { + int x1 : 2; + volatile double y1; + }; + + S f3() + { + return {}; + } + + auto [ x1, y1 ] = f1(); + auto& [ xr1, yr1 ] = f1(); + auto [ x2, y2 ] = f2(); + auto& [ xr2, yr2 ] = f2(); + const auto [ x3, y3 ] = f3(); + + } +#endif // !defined(REALLY_CLANG) + +#if !defined(REALLY_CLANG) + namespace test_exception_spec_type_system + { + + // TODO: test it with clang++ from git + + struct Good {}; + struct Bad {}; + + void g1() noexcept; + void g2(); + + template + Bad + f(T*, T*); + + template + Good + f(T1*, T2*); + + static_assert (std::is_same_v); + + } +#endif // !defined(REALLY_CLANG) + + namespace test_inline_variables + { + + template void f(T) + {} + + template inline T g(T) + { + return T{}; + } + + template<> inline void f<>(int) + {} + + template<> int g<>(int) + { + return 5; + } + + } + +} // namespace cxx17 + +#endif // __cplusplus <= 201402L + +]]) diff --git a/m4/ax_require_defined.m4 b/m4/ax_require_defined.m4 new file mode 100644 index 00000000..17c3eab7 --- /dev/null +++ b/m4/ax_require_defined.m4 @@ -0,0 +1,37 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_require_defined.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_REQUIRE_DEFINED(MACRO) +# +# DESCRIPTION +# +# AX_REQUIRE_DEFINED is a simple helper for making sure other macros have +# been defined and thus are available for use. This avoids random issues +# where a macro isn't expanded. Instead the configure script emits a +# non-fatal: +# +# ./configure: line 1673: AX_CFLAGS_WARN_ALL: command not found +# +# It's like AC_REQUIRE except it doesn't expand the required macro. +# +# Here's an example: +# +# AX_REQUIRE_DEFINED([AX_CHECK_LINK_FLAG]) +# +# LICENSE +# +# Copyright (c) 2014 Mike Frysinger +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 2 + +AC_DEFUN([AX_REQUIRE_DEFINED], [dnl + m4_ifndef([$1], [m4_fatal([macro ]$1[ is not defined; is a m4 file missing?])]) +])dnl AX_REQUIRE_DEFINED diff --git a/m4/codeset.m4 b/m4/codeset.m4 new file mode 100644 index 00000000..a53c0426 --- /dev/null +++ b/m4/codeset.m4 @@ -0,0 +1,21 @@ +# codeset.m4 serial 4 (gettext-0.18) +dnl Copyright (C) 2000-2002, 2006, 2008-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +AC_DEFUN([AM_LANGINFO_CODESET], +[ + AC_CACHE_CHECK([for nl_langinfo and CODESET], [am_cv_langinfo_codeset], + [AC_TRY_LINK([#include ], + [char* cs = nl_langinfo(CODESET); return !cs;], + [am_cv_langinfo_codeset=yes], + [am_cv_langinfo_codeset=no]) + ]) + if test $am_cv_langinfo_codeset = yes; then + AC_DEFINE([HAVE_LANGINFO_CODESET], [1], + [Define if you have and nl_langinfo(CODESET).]) + fi +]) diff --git a/m4/fcntl-o.m4 b/m4/fcntl-o.m4 new file mode 100644 index 00000000..d416a61c --- /dev/null +++ b/m4/fcntl-o.m4 @@ -0,0 +1,81 @@ +# fcntl-o.m4 serial 1 +dnl Copyright (C) 2006, 2009-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl Written by Paul Eggert. + +# Test whether the flags O_NOATIME and O_NOFOLLOW actually work. +# Define HAVE_WORKING_O_NOATIME to 1 if O_NOATIME works, or to 0 otherwise. +# Define HAVE_WORKING_O_NOFOLLOW to 1 if O_NOFOLLOW works, or to 0 otherwise. +AC_DEFUN([gl_FCNTL_O_FLAGS], +[ + dnl Persuade glibc to define O_NOATIME and O_NOFOLLOW. + AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS]) + AC_CACHE_CHECK([for working fcntl.h], [gl_cv_header_working_fcntl_h], + [AC_RUN_IFELSE( + [AC_LANG_PROGRAM( + [[#include + #include + #include + #include + #ifndef O_NOATIME + #define O_NOATIME 0 + #endif + #ifndef O_NOFOLLOW + #define O_NOFOLLOW 0 + #endif + static int const constants[] = + { + O_CREAT, O_EXCL, O_NOCTTY, O_TRUNC, O_APPEND, + O_NONBLOCK, O_SYNC, O_ACCMODE, O_RDONLY, O_RDWR, O_WRONLY + }; + ]], + [[ + int status = !constants; + { + static char const sym[] = "conftest.sym"; + if (symlink (".", sym) != 0 + || close (open (sym, O_RDONLY | O_NOFOLLOW)) == 0) + status |= 32; + unlink (sym); + } + { + static char const file[] = "confdefs.h"; + int fd = open (file, O_RDONLY | O_NOATIME); + char c; + struct stat st0, st1; + if (fd < 0 + || fstat (fd, &st0) != 0 + || sleep (1) != 0 + || read (fd, &c, 1) != 1 + || close (fd) != 0 + || stat (file, &st1) != 0 + || st0.st_atime != st1.st_atime) + status |= 64; + } + return status;]])], + [gl_cv_header_working_fcntl_h=yes], + [case $? in #( + 32) gl_cv_header_working_fcntl_h='no (bad O_NOFOLLOW)';; #( + 64) gl_cv_header_working_fcntl_h='no (bad O_NOATIME)';; #( + 96) gl_cv_header_working_fcntl_h='no (bad O_NOATIME, O_NOFOLLOW)';; #( + *) gl_cv_header_working_fcntl_h='no';; + esac], + [gl_cv_header_working_fcntl_h=cross-compiling])]) + + case $gl_cv_header_working_fcntl_h in #( + *O_NOATIME* | no | cross-compiling) ac_val=0;; #( + *) ac_val=1;; + esac + AC_DEFINE_UNQUOTED([HAVE_WORKING_O_NOATIME], [$ac_val], + [Define to 1 if O_NOATIME works.]) + + case $gl_cv_header_working_fcntl_h in #( + *O_NOFOLLOW* | no | cross-compiling) ac_val=0;; #( + *) ac_val=1;; + esac + AC_DEFINE_UNQUOTED([HAVE_WORKING_O_NOFOLLOW], [$ac_val], + [Define to 1 if O_NOFOLLOW works.]) +]) diff --git a/m4/gettext.m4 b/m4/gettext.m4 new file mode 100644 index 00000000..eef5073b --- /dev/null +++ b/m4/gettext.m4 @@ -0,0 +1,420 @@ +# gettext.m4 serial 68 (gettext-0.19.8) +dnl Copyright (C) 1995-2014, 2016 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl +dnl This file can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Authors: +dnl Ulrich Drepper , 1995-2000. +dnl Bruno Haible , 2000-2006, 2008-2010. + +dnl Macro to add for using GNU gettext. + +dnl Usage: AM_GNU_GETTEXT([INTLSYMBOL], [NEEDSYMBOL], [INTLDIR]). +dnl INTLSYMBOL can be one of 'external', 'no-libtool', 'use-libtool'. The +dnl default (if it is not specified or empty) is 'no-libtool'. +dnl INTLSYMBOL should be 'external' for packages with no intl directory, +dnl and 'no-libtool' or 'use-libtool' for packages with an intl directory. +dnl If INTLSYMBOL is 'use-libtool', then a libtool library +dnl $(top_builddir)/intl/libintl.la will be created (shared and/or static, +dnl depending on --{enable,disable}-{shared,static} and on the presence of +dnl AM-DISABLE-SHARED). If INTLSYMBOL is 'no-libtool', a static library +dnl $(top_builddir)/intl/libintl.a will be created. +dnl If NEEDSYMBOL is specified and is 'need-ngettext', then GNU gettext +dnl implementations (in libc or libintl) without the ngettext() function +dnl will be ignored. If NEEDSYMBOL is specified and is +dnl 'need-formatstring-macros', then GNU gettext implementations that don't +dnl support the ISO C 99 formatstring macros will be ignored. +dnl INTLDIR is used to find the intl libraries. If empty, +dnl the value '$(top_builddir)/intl/' is used. +dnl +dnl The result of the configuration is one of three cases: +dnl 1) GNU gettext, as included in the intl subdirectory, will be compiled +dnl and used. +dnl Catalog format: GNU --> install in $(datadir) +dnl Catalog extension: .mo after installation, .gmo in source tree +dnl 2) GNU gettext has been found in the system's C library. +dnl Catalog format: GNU --> install in $(datadir) +dnl Catalog extension: .mo after installation, .gmo in source tree +dnl 3) No internationalization, always use English msgid. +dnl Catalog format: none +dnl Catalog extension: none +dnl If INTLSYMBOL is 'external', only cases 2 and 3 can occur. +dnl The use of .gmo is historical (it was needed to avoid overwriting the +dnl GNU format catalogs when building on a platform with an X/Open gettext), +dnl but we keep it in order not to force irrelevant filename changes on the +dnl maintainers. +dnl +AC_DEFUN([AM_GNU_GETTEXT], +[ + dnl Argument checking. + ifelse([$1], [], , [ifelse([$1], [external], , [ifelse([$1], [no-libtool], , [ifelse([$1], [use-libtool], , + [errprint([ERROR: invalid first argument to AM_GNU_GETTEXT +])])])])]) + ifelse(ifelse([$1], [], [old])[]ifelse([$1], [no-libtool], [old]), [old], + [AC_DIAGNOSE([obsolete], [Use of AM_GNU_GETTEXT without [external] argument is deprecated.])]) + ifelse([$2], [], , [ifelse([$2], [need-ngettext], , [ifelse([$2], [need-formatstring-macros], , + [errprint([ERROR: invalid second argument to AM_GNU_GETTEXT +])])])]) + define([gt_included_intl], + ifelse([$1], [external], + ifdef([AM_GNU_GETTEXT_][INTL_SUBDIR], [yes], [no]), + [yes])) + define([gt_libtool_suffix_prefix], ifelse([$1], [use-libtool], [l], [])) + gt_NEEDS_INIT + AM_GNU_GETTEXT_NEED([$2]) + + AC_REQUIRE([AM_PO_SUBDIRS])dnl + ifelse(gt_included_intl, yes, [ + AC_REQUIRE([AM_INTL_SUBDIR])dnl + ]) + + dnl Prerequisites of AC_LIB_LINKFLAGS_BODY. + AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) + AC_REQUIRE([AC_LIB_RPATH]) + + dnl Sometimes libintl requires libiconv, so first search for libiconv. + dnl Ideally we would do this search only after the + dnl if test "$USE_NLS" = "yes"; then + dnl if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" != "yes"; }; then + dnl tests. But if configure.in invokes AM_ICONV after AM_GNU_GETTEXT + dnl the configure script would need to contain the same shell code + dnl again, outside any 'if'. There are two solutions: + dnl - Invoke AM_ICONV_LINKFLAGS_BODY here, outside any 'if'. + dnl - Control the expansions in more detail using AC_PROVIDE_IFELSE. + dnl Since AC_PROVIDE_IFELSE is only in autoconf >= 2.52 and not + dnl documented, we avoid it. + ifelse(gt_included_intl, yes, , [ + AC_REQUIRE([AM_ICONV_LINKFLAGS_BODY]) + ]) + + dnl Sometimes, on Mac OS X, libintl requires linking with CoreFoundation. + gt_INTL_MACOSX + + dnl Set USE_NLS. + AC_REQUIRE([AM_NLS]) + + ifelse(gt_included_intl, yes, [ + BUILD_INCLUDED_LIBINTL=no + USE_INCLUDED_LIBINTL=no + ]) + LIBINTL= + LTLIBINTL= + POSUB= + + dnl Add a version number to the cache macros. + case " $gt_needs " in + *" need-formatstring-macros "*) gt_api_version=3 ;; + *" need-ngettext "*) gt_api_version=2 ;; + *) gt_api_version=1 ;; + esac + gt_func_gnugettext_libc="gt_cv_func_gnugettext${gt_api_version}_libc" + gt_func_gnugettext_libintl="gt_cv_func_gnugettext${gt_api_version}_libintl" + + dnl If we use NLS figure out what method + if test "$USE_NLS" = "yes"; then + gt_use_preinstalled_gnugettext=no + ifelse(gt_included_intl, yes, [ + AC_MSG_CHECKING([whether included gettext is requested]) + AC_ARG_WITH([included-gettext], + [ --with-included-gettext use the GNU gettext library included here], + nls_cv_force_use_gnu_gettext=$withval, + nls_cv_force_use_gnu_gettext=no) + AC_MSG_RESULT([$nls_cv_force_use_gnu_gettext]) + + nls_cv_use_gnu_gettext="$nls_cv_force_use_gnu_gettext" + if test "$nls_cv_force_use_gnu_gettext" != "yes"; then + ]) + dnl User does not insist on using GNU NLS library. Figure out what + dnl to use. If GNU gettext is available we use this. Else we have + dnl to fall back to GNU NLS library. + + if test $gt_api_version -ge 3; then + gt_revision_test_code=' +#ifndef __GNU_GETTEXT_SUPPORTED_REVISION +#define __GNU_GETTEXT_SUPPORTED_REVISION(major) ((major) == 0 ? 0 : -1) +#endif +changequote(,)dnl +typedef int array [2 * (__GNU_GETTEXT_SUPPORTED_REVISION(0) >= 1) - 1]; +changequote([,])dnl +' + else + gt_revision_test_code= + fi + if test $gt_api_version -ge 2; then + gt_expression_test_code=' + * ngettext ("", "", 0)' + else + gt_expression_test_code= + fi + + AC_CACHE_CHECK([for GNU gettext in libc], [$gt_func_gnugettext_libc], + [AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include +#ifndef __GNU_GETTEXT_SUPPORTED_REVISION +extern int _nl_msg_cat_cntr; +extern int *_nl_domain_bindings; +#define __GNU_GETTEXT_SYMBOL_EXPRESSION (_nl_msg_cat_cntr + *_nl_domain_bindings) +#else +#define __GNU_GETTEXT_SYMBOL_EXPRESSION 0 +#endif +$gt_revision_test_code + ]], + [[ +bindtextdomain ("", ""); +return * gettext ("")$gt_expression_test_code + __GNU_GETTEXT_SYMBOL_EXPRESSION + ]])], + [eval "$gt_func_gnugettext_libc=yes"], + [eval "$gt_func_gnugettext_libc=no"])]) + + if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" != "yes"; }; then + dnl Sometimes libintl requires libiconv, so first search for libiconv. + ifelse(gt_included_intl, yes, , [ + AM_ICONV_LINK + ]) + dnl Search for libintl and define LIBINTL, LTLIBINTL and INCINTL + dnl accordingly. Don't use AC_LIB_LINKFLAGS_BODY([intl],[iconv]) + dnl because that would add "-liconv" to LIBINTL and LTLIBINTL + dnl even if libiconv doesn't exist. + AC_LIB_LINKFLAGS_BODY([intl]) + AC_CACHE_CHECK([for GNU gettext in libintl], + [$gt_func_gnugettext_libintl], + [gt_save_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $INCINTL" + gt_save_LIBS="$LIBS" + LIBS="$LIBS $LIBINTL" + dnl Now see whether libintl exists and does not depend on libiconv. + AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include +#ifndef __GNU_GETTEXT_SUPPORTED_REVISION +extern int _nl_msg_cat_cntr; +extern +#ifdef __cplusplus +"C" +#endif +const char *_nl_expand_alias (const char *); +#define __GNU_GETTEXT_SYMBOL_EXPRESSION (_nl_msg_cat_cntr + *_nl_expand_alias ("")) +#else +#define __GNU_GETTEXT_SYMBOL_EXPRESSION 0 +#endif +$gt_revision_test_code + ]], + [[ +bindtextdomain ("", ""); +return * gettext ("")$gt_expression_test_code + __GNU_GETTEXT_SYMBOL_EXPRESSION + ]])], + [eval "$gt_func_gnugettext_libintl=yes"], + [eval "$gt_func_gnugettext_libintl=no"]) + dnl Now see whether libintl exists and depends on libiconv. + if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" != yes; } && test -n "$LIBICONV"; then + LIBS="$LIBS $LIBICONV" + AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include +#ifndef __GNU_GETTEXT_SUPPORTED_REVISION +extern int _nl_msg_cat_cntr; +extern +#ifdef __cplusplus +"C" +#endif +const char *_nl_expand_alias (const char *); +#define __GNU_GETTEXT_SYMBOL_EXPRESSION (_nl_msg_cat_cntr + *_nl_expand_alias ("")) +#else +#define __GNU_GETTEXT_SYMBOL_EXPRESSION 0 +#endif +$gt_revision_test_code + ]], + [[ +bindtextdomain ("", ""); +return * gettext ("")$gt_expression_test_code + __GNU_GETTEXT_SYMBOL_EXPRESSION + ]])], + [LIBINTL="$LIBINTL $LIBICONV" + LTLIBINTL="$LTLIBINTL $LTLIBICONV" + eval "$gt_func_gnugettext_libintl=yes" + ]) + fi + CPPFLAGS="$gt_save_CPPFLAGS" + LIBS="$gt_save_LIBS"]) + fi + + dnl If an already present or preinstalled GNU gettext() is found, + dnl use it. But if this macro is used in GNU gettext, and GNU + dnl gettext is already preinstalled in libintl, we update this + dnl libintl. (Cf. the install rule in intl/Makefile.in.) + if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" = "yes"; } \ + || { { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; } \ + && test "$PACKAGE" != gettext-runtime \ + && test "$PACKAGE" != gettext-tools; }; then + gt_use_preinstalled_gnugettext=yes + else + dnl Reset the values set by searching for libintl. + LIBINTL= + LTLIBINTL= + INCINTL= + fi + + ifelse(gt_included_intl, yes, [ + if test "$gt_use_preinstalled_gnugettext" != "yes"; then + dnl GNU gettext is not found in the C library. + dnl Fall back on included GNU gettext library. + nls_cv_use_gnu_gettext=yes + fi + fi + + if test "$nls_cv_use_gnu_gettext" = "yes"; then + dnl Mark actions used to generate GNU NLS library. + BUILD_INCLUDED_LIBINTL=yes + USE_INCLUDED_LIBINTL=yes + LIBINTL="ifelse([$3],[],\${top_builddir}/intl,[$3])/libintl.[]gt_libtool_suffix_prefix[]a $LIBICONV $LIBTHREAD" + LTLIBINTL="ifelse([$3],[],\${top_builddir}/intl,[$3])/libintl.[]gt_libtool_suffix_prefix[]a $LTLIBICONV $LTLIBTHREAD" + LIBS=`echo " $LIBS " | sed -e 's/ -lintl / /' -e 's/^ //' -e 's/ $//'` + fi + + CATOBJEXT= + if test "$gt_use_preinstalled_gnugettext" = "yes" \ + || test "$nls_cv_use_gnu_gettext" = "yes"; then + dnl Mark actions to use GNU gettext tools. + CATOBJEXT=.gmo + fi + ]) + + if test -n "$INTL_MACOSX_LIBS"; then + if test "$gt_use_preinstalled_gnugettext" = "yes" \ + || test "$nls_cv_use_gnu_gettext" = "yes"; then + dnl Some extra flags are needed during linking. + LIBINTL="$LIBINTL $INTL_MACOSX_LIBS" + LTLIBINTL="$LTLIBINTL $INTL_MACOSX_LIBS" + fi + fi + + if test "$gt_use_preinstalled_gnugettext" = "yes" \ + || test "$nls_cv_use_gnu_gettext" = "yes"; then + AC_DEFINE([ENABLE_NLS], [1], + [Define to 1 if translation of program messages to the user's native language + is requested.]) + else + USE_NLS=no + fi + fi + + AC_MSG_CHECKING([whether to use NLS]) + AC_MSG_RESULT([$USE_NLS]) + if test "$USE_NLS" = "yes"; then + AC_MSG_CHECKING([where the gettext function comes from]) + if test "$gt_use_preinstalled_gnugettext" = "yes"; then + if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; }; then + gt_source="external libintl" + else + gt_source="libc" + fi + else + gt_source="included intl directory" + fi + AC_MSG_RESULT([$gt_source]) + fi + + if test "$USE_NLS" = "yes"; then + + if test "$gt_use_preinstalled_gnugettext" = "yes"; then + if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; }; then + AC_MSG_CHECKING([how to link with libintl]) + AC_MSG_RESULT([$LIBINTL]) + AC_LIB_APPENDTOVAR([CPPFLAGS], [$INCINTL]) + fi + + dnl For backward compatibility. Some packages may be using this. + AC_DEFINE([HAVE_GETTEXT], [1], + [Define if the GNU gettext() function is already present or preinstalled.]) + AC_DEFINE([HAVE_DCGETTEXT], [1], + [Define if the GNU dcgettext() function is already present or preinstalled.]) + fi + + dnl We need to process the po/ directory. + POSUB=po + fi + + ifelse(gt_included_intl, yes, [ + dnl If this is used in GNU gettext we have to set BUILD_INCLUDED_LIBINTL + dnl to 'yes' because some of the testsuite requires it. + if test "$PACKAGE" = gettext-runtime || test "$PACKAGE" = gettext-tools; then + BUILD_INCLUDED_LIBINTL=yes + fi + + dnl Make all variables we use known to autoconf. + AC_SUBST([BUILD_INCLUDED_LIBINTL]) + AC_SUBST([USE_INCLUDED_LIBINTL]) + AC_SUBST([CATOBJEXT]) + + dnl For backward compatibility. Some configure.ins may be using this. + nls_cv_header_intl= + nls_cv_header_libgt= + + dnl For backward compatibility. Some Makefiles may be using this. + DATADIRNAME=share + AC_SUBST([DATADIRNAME]) + + dnl For backward compatibility. Some Makefiles may be using this. + INSTOBJEXT=.mo + AC_SUBST([INSTOBJEXT]) + + dnl For backward compatibility. Some Makefiles may be using this. + GENCAT=gencat + AC_SUBST([GENCAT]) + + dnl For backward compatibility. Some Makefiles may be using this. + INTLOBJS= + if test "$USE_INCLUDED_LIBINTL" = yes; then + INTLOBJS="\$(GETTOBJS)" + fi + AC_SUBST([INTLOBJS]) + + dnl Enable libtool support if the surrounding package wishes it. + INTL_LIBTOOL_SUFFIX_PREFIX=gt_libtool_suffix_prefix + AC_SUBST([INTL_LIBTOOL_SUFFIX_PREFIX]) + ]) + + dnl For backward compatibility. Some Makefiles may be using this. + INTLLIBS="$LIBINTL" + AC_SUBST([INTLLIBS]) + + dnl Make all documented variables known to autoconf. + AC_SUBST([LIBINTL]) + AC_SUBST([LTLIBINTL]) + AC_SUBST([POSUB]) +]) + + +dnl gt_NEEDS_INIT ensures that the gt_needs variable is initialized. +m4_define([gt_NEEDS_INIT], +[ + m4_divert_text([DEFAULTS], [gt_needs=]) + m4_define([gt_NEEDS_INIT], []) +]) + + +dnl Usage: AM_GNU_GETTEXT_NEED([NEEDSYMBOL]) +AC_DEFUN([AM_GNU_GETTEXT_NEED], +[ + m4_divert_text([INIT_PREPARE], [gt_needs="$gt_needs $1"]) +]) + + +dnl Usage: AM_GNU_GETTEXT_VERSION([gettext-version]) +AC_DEFUN([AM_GNU_GETTEXT_VERSION], []) + + +dnl Usage: AM_GNU_GETTEXT_REQUIRE_VERSION([gettext-version]) +AC_DEFUN([AM_GNU_GETTEXT_REQUIRE_VERSION], []) diff --git a/m4/glibc2.m4 b/m4/glibc2.m4 new file mode 100644 index 00000000..f148c12c --- /dev/null +++ b/m4/glibc2.m4 @@ -0,0 +1,30 @@ +# glibc2.m4 serial 2 +dnl Copyright (C) 2000-2002, 2004, 2008-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +# Test for the GNU C Library, version 2.0 or newer. +# From Bruno Haible. + +AC_DEFUN([gt_GLIBC2], + [ + AC_CACHE_CHECK([whether we are using the GNU C Library 2 or newer], + [ac_cv_gnu_library_2], + [AC_EGREP_CPP([Lucky GNU user], + [ +#include +#ifdef __GNU_LIBRARY__ + #if (__GLIBC__ >= 2) + Lucky GNU user + #endif +#endif + ], + [ac_cv_gnu_library_2=yes], + [ac_cv_gnu_library_2=no]) + ] + ) + AC_SUBST([GLIBC2]) + GLIBC2="$ac_cv_gnu_library_2" + ] +) diff --git a/m4/glibc21.m4 b/m4/glibc21.m4 new file mode 100644 index 00000000..68ada9d4 --- /dev/null +++ b/m4/glibc21.m4 @@ -0,0 +1,30 @@ +# glibc21.m4 serial 4 +dnl Copyright (C) 2000-2002, 2004, 2008-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +# Test for the GNU C Library, version 2.1 or newer. +# From Bruno Haible. + +AC_DEFUN([gl_GLIBC21], + [ + AC_CACHE_CHECK([whether we are using the GNU C Library 2.1 or newer], + [ac_cv_gnu_library_2_1], + [AC_EGREP_CPP([Lucky GNU user], + [ +#include +#ifdef __GNU_LIBRARY__ + #if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1) || (__GLIBC__ > 2) + Lucky GNU user + #endif +#endif + ], + [ac_cv_gnu_library_2_1=yes], + [ac_cv_gnu_library_2_1=no]) + ] + ) + AC_SUBST([GLIBC21]) + GLIBC21="$ac_cv_gnu_library_2_1" + ] +) diff --git a/m4/iconv.m4 b/m4/iconv.m4 new file mode 100644 index 00000000..aa159c53 --- /dev/null +++ b/m4/iconv.m4 @@ -0,0 +1,271 @@ +# iconv.m4 serial 19 (gettext-0.18.2) +dnl Copyright (C) 2000-2002, 2007-2014, 2016 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +AC_DEFUN([AM_ICONV_LINKFLAGS_BODY], +[ + dnl Prerequisites of AC_LIB_LINKFLAGS_BODY. + AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) + AC_REQUIRE([AC_LIB_RPATH]) + + dnl Search for libiconv and define LIBICONV, LTLIBICONV and INCICONV + dnl accordingly. + AC_LIB_LINKFLAGS_BODY([iconv]) +]) + +AC_DEFUN([AM_ICONV_LINK], +[ + dnl Some systems have iconv in libc, some have it in libiconv (OSF/1 and + dnl those with the standalone portable GNU libiconv installed). + AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles + + dnl Search for libiconv and define LIBICONV, LTLIBICONV and INCICONV + dnl accordingly. + AC_REQUIRE([AM_ICONV_LINKFLAGS_BODY]) + + dnl Add $INCICONV to CPPFLAGS before performing the following checks, + dnl because if the user has installed libiconv and not disabled its use + dnl via --without-libiconv-prefix, he wants to use it. The first + dnl AC_LINK_IFELSE will then fail, the second AC_LINK_IFELSE will succeed. + am_save_CPPFLAGS="$CPPFLAGS" + AC_LIB_APPENDTOVAR([CPPFLAGS], [$INCICONV]) + + AC_CACHE_CHECK([for iconv], [am_cv_func_iconv], [ + am_cv_func_iconv="no, consider installing GNU libiconv" + am_cv_lib_iconv=no + AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include +#include + ]], + [[iconv_t cd = iconv_open("",""); + iconv(cd,NULL,NULL,NULL,NULL); + iconv_close(cd);]])], + [am_cv_func_iconv=yes]) + if test "$am_cv_func_iconv" != yes; then + am_save_LIBS="$LIBS" + LIBS="$LIBS $LIBICONV" + AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include +#include + ]], + [[iconv_t cd = iconv_open("",""); + iconv(cd,NULL,NULL,NULL,NULL); + iconv_close(cd);]])], + [am_cv_lib_iconv=yes] + [am_cv_func_iconv=yes]) + LIBS="$am_save_LIBS" + fi + ]) + if test "$am_cv_func_iconv" = yes; then + AC_CACHE_CHECK([for working iconv], [am_cv_func_iconv_works], [ + dnl This tests against bugs in AIX 5.1, AIX 6.1..7.1, HP-UX 11.11, + dnl Solaris 10. + am_save_LIBS="$LIBS" + if test $am_cv_lib_iconv = yes; then + LIBS="$LIBS $LIBICONV" + fi + am_cv_func_iconv_works=no + for ac_iconv_const in '' 'const'; do + AC_RUN_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include +#include + +#ifndef ICONV_CONST +# define ICONV_CONST $ac_iconv_const +#endif + ]], + [[int result = 0; + /* Test against AIX 5.1 bug: Failures are not distinguishable from successful + returns. */ + { + iconv_t cd_utf8_to_88591 = iconv_open ("ISO8859-1", "UTF-8"); + if (cd_utf8_to_88591 != (iconv_t)(-1)) + { + static ICONV_CONST char input[] = "\342\202\254"; /* EURO SIGN */ + char buf[10]; + ICONV_CONST char *inptr = input; + size_t inbytesleft = strlen (input); + char *outptr = buf; + size_t outbytesleft = sizeof (buf); + size_t res = iconv (cd_utf8_to_88591, + &inptr, &inbytesleft, + &outptr, &outbytesleft); + if (res == 0) + result |= 1; + iconv_close (cd_utf8_to_88591); + } + } + /* Test against Solaris 10 bug: Failures are not distinguishable from + successful returns. */ + { + iconv_t cd_ascii_to_88591 = iconv_open ("ISO8859-1", "646"); + if (cd_ascii_to_88591 != (iconv_t)(-1)) + { + static ICONV_CONST char input[] = "\263"; + char buf[10]; + ICONV_CONST char *inptr = input; + size_t inbytesleft = strlen (input); + char *outptr = buf; + size_t outbytesleft = sizeof (buf); + size_t res = iconv (cd_ascii_to_88591, + &inptr, &inbytesleft, + &outptr, &outbytesleft); + if (res == 0) + result |= 2; + iconv_close (cd_ascii_to_88591); + } + } + /* Test against AIX 6.1..7.1 bug: Buffer overrun. */ + { + iconv_t cd_88591_to_utf8 = iconv_open ("UTF-8", "ISO-8859-1"); + if (cd_88591_to_utf8 != (iconv_t)(-1)) + { + static ICONV_CONST char input[] = "\304"; + static char buf[2] = { (char)0xDE, (char)0xAD }; + ICONV_CONST char *inptr = input; + size_t inbytesleft = 1; + char *outptr = buf; + size_t outbytesleft = 1; + size_t res = iconv (cd_88591_to_utf8, + &inptr, &inbytesleft, + &outptr, &outbytesleft); + if (res != (size_t)(-1) || outptr - buf > 1 || buf[1] != (char)0xAD) + result |= 4; + iconv_close (cd_88591_to_utf8); + } + } +#if 0 /* This bug could be worked around by the caller. */ + /* Test against HP-UX 11.11 bug: Positive return value instead of 0. */ + { + iconv_t cd_88591_to_utf8 = iconv_open ("utf8", "iso88591"); + if (cd_88591_to_utf8 != (iconv_t)(-1)) + { + static ICONV_CONST char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337"; + char buf[50]; + ICONV_CONST char *inptr = input; + size_t inbytesleft = strlen (input); + char *outptr = buf; + size_t outbytesleft = sizeof (buf); + size_t res = iconv (cd_88591_to_utf8, + &inptr, &inbytesleft, + &outptr, &outbytesleft); + if ((int)res > 0) + result |= 8; + iconv_close (cd_88591_to_utf8); + } + } +#endif + /* Test against HP-UX 11.11 bug: No converter from EUC-JP to UTF-8 is + provided. */ + if (/* Try standardized names. */ + iconv_open ("UTF-8", "EUC-JP") == (iconv_t)(-1) + /* Try IRIX, OSF/1 names. */ + && iconv_open ("UTF-8", "eucJP") == (iconv_t)(-1) + /* Try AIX names. */ + && iconv_open ("UTF-8", "IBM-eucJP") == (iconv_t)(-1) + /* Try HP-UX names. */ + && iconv_open ("utf8", "eucJP") == (iconv_t)(-1)) + result |= 16; + return result; +]])], + [am_cv_func_iconv_works=yes], , + [case "$host_os" in + aix* | hpux*) am_cv_func_iconv_works="guessing no" ;; + *) am_cv_func_iconv_works="guessing yes" ;; + esac]) + test "$am_cv_func_iconv_works" = no || break + done + LIBS="$am_save_LIBS" + ]) + case "$am_cv_func_iconv_works" in + *no) am_func_iconv=no am_cv_lib_iconv=no ;; + *) am_func_iconv=yes ;; + esac + else + am_func_iconv=no am_cv_lib_iconv=no + fi + if test "$am_func_iconv" = yes; then + AC_DEFINE([HAVE_ICONV], [1], + [Define if you have the iconv() function and it works.]) + fi + if test "$am_cv_lib_iconv" = yes; then + AC_MSG_CHECKING([how to link with libiconv]) + AC_MSG_RESULT([$LIBICONV]) + else + dnl If $LIBICONV didn't lead to a usable library, we don't need $INCICONV + dnl either. + CPPFLAGS="$am_save_CPPFLAGS" + LIBICONV= + LTLIBICONV= + fi + AC_SUBST([LIBICONV]) + AC_SUBST([LTLIBICONV]) +]) + +dnl Define AM_ICONV using AC_DEFUN_ONCE for Autoconf >= 2.64, in order to +dnl avoid warnings like +dnl "warning: AC_REQUIRE: `AM_ICONV' was expanded before it was required". +dnl This is tricky because of the way 'aclocal' is implemented: +dnl - It requires defining an auxiliary macro whose name ends in AC_DEFUN. +dnl Otherwise aclocal's initial scan pass would miss the macro definition. +dnl - It requires a line break inside the AC_DEFUN_ONCE and AC_DEFUN expansions. +dnl Otherwise aclocal would emit many "Use of uninitialized value $1" +dnl warnings. +m4_define([gl_iconv_AC_DEFUN], + m4_version_prereq([2.64], + [[AC_DEFUN_ONCE( + [$1], [$2])]], + [m4_ifdef([gl_00GNULIB], + [[AC_DEFUN_ONCE( + [$1], [$2])]], + [[AC_DEFUN( + [$1], [$2])]])])) +gl_iconv_AC_DEFUN([AM_ICONV], +[ + AM_ICONV_LINK + if test "$am_cv_func_iconv" = yes; then + AC_MSG_CHECKING([for iconv declaration]) + AC_CACHE_VAL([am_cv_proto_iconv], [ + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include +#include +extern +#ifdef __cplusplus +"C" +#endif +#if defined(__STDC__) || defined(_MSC_VER) || defined(__cplusplus) +size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft); +#else +size_t iconv(); +#endif + ]], + [[]])], + [am_cv_proto_iconv_arg1=""], + [am_cv_proto_iconv_arg1="const"]) + am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);"]) + am_cv_proto_iconv=`echo "[$]am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'` + AC_MSG_RESULT([ + $am_cv_proto_iconv]) + AC_DEFINE_UNQUOTED([ICONV_CONST], [$am_cv_proto_iconv_arg1], + [Define as const if the declaration of iconv() needs const.]) + dnl Also substitute ICONV_CONST in the gnulib generated . + m4_ifdef([gl_ICONV_H_DEFAULTS], + [AC_REQUIRE([gl_ICONV_H_DEFAULTS]) + if test -n "$am_cv_proto_iconv_arg1"; then + ICONV_CONST="const" + fi + ]) + fi +]) diff --git a/m4/intdiv0.m4 b/m4/intdiv0.m4 new file mode 100644 index 00000000..289c4df5 --- /dev/null +++ b/m4/intdiv0.m4 @@ -0,0 +1,84 @@ +# intdiv0.m4 serial 3 (gettext-0.18) +dnl Copyright (C) 2002, 2007-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +AC_DEFUN([gt_INTDIV0], +[ + AC_REQUIRE([AC_PROG_CC])dnl + AC_REQUIRE([AC_CANONICAL_HOST])dnl + + AC_CACHE_CHECK([whether integer division by zero raises SIGFPE], + gt_cv_int_divbyzero_sigfpe, + [ + gt_cv_int_divbyzero_sigfpe= +changequote(,)dnl + case "$host_os" in + macos* | darwin[6-9]* | darwin[1-9][0-9]*) + # On MacOS X 10.2 or newer, just assume the same as when cross- + # compiling. If we were to perform the real test, 1 Crash Report + # dialog window would pop up. + case "$host_cpu" in + i[34567]86 | x86_64) + gt_cv_int_divbyzero_sigfpe="guessing yes" ;; + esac + ;; + esac +changequote([,])dnl + if test -z "$gt_cv_int_divbyzero_sigfpe"; then + AC_TRY_RUN([ +#include +#include + +static void +sigfpe_handler (int sig) +{ + /* Exit with code 0 if SIGFPE, with code 1 if any other signal. */ + exit (sig != SIGFPE); +} + +int x = 1; +int y = 0; +int z; +int nan; + +int main () +{ + signal (SIGFPE, sigfpe_handler); +/* IRIX and AIX (when "xlc -qcheck" is used) yield signal SIGTRAP. */ +#if (defined (__sgi) || defined (_AIX)) && defined (SIGTRAP) + signal (SIGTRAP, sigfpe_handler); +#endif +/* Linux/SPARC yields signal SIGILL. */ +#if defined (__sparc__) && defined (__linux__) + signal (SIGILL, sigfpe_handler); +#endif + + z = x / y; + nan = y / y; + exit (1); +} +], [gt_cv_int_divbyzero_sigfpe=yes], [gt_cv_int_divbyzero_sigfpe=no], + [ + # Guess based on the CPU. +changequote(,)dnl + case "$host_cpu" in + alpha* | i[34567]86 | x86_64 | m68k | s390*) + gt_cv_int_divbyzero_sigfpe="guessing yes";; + *) + gt_cv_int_divbyzero_sigfpe="guessing no";; + esac +changequote([,])dnl + ]) + fi + ]) + case "$gt_cv_int_divbyzero_sigfpe" in + *yes) value=1;; + *) value=0;; + esac + AC_DEFINE_UNQUOTED([INTDIV0_RAISES_SIGFPE], [$value], + [Define if integer division by zero raises signal SIGFPE.]) +]) diff --git a/m4/intl.m4 b/m4/intl.m4 new file mode 100644 index 00000000..335b23c2 --- /dev/null +++ b/m4/intl.m4 @@ -0,0 +1,294 @@ +# intl.m4 serial 17 (gettext-0.18) +dnl Copyright (C) 1995-2009 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl +dnl This file can can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Authors: +dnl Ulrich Drepper , 1995-2000. +dnl Bruno Haible , 2000-2009. + +AC_PREREQ([2.52]) + +dnl Checks for all prerequisites of the intl subdirectory, +dnl except for INTL_LIBTOOL_SUFFIX_PREFIX (and possibly LIBTOOL), INTLOBJS, +dnl USE_INCLUDED_LIBINTL, BUILD_INCLUDED_LIBINTL. +AC_DEFUN([AM_INTL_SUBDIR], +[ + AC_REQUIRE([AC_PROG_INSTALL])dnl + AC_REQUIRE([AM_PROG_MKDIR_P])dnl defined by automake + AC_REQUIRE([AC_PROG_CC])dnl + AC_REQUIRE([AC_CANONICAL_HOST])dnl + AC_REQUIRE([gt_GLIBC2])dnl + AC_REQUIRE([AC_PROG_RANLIB])dnl + AC_REQUIRE([gl_VISIBILITY])dnl + AC_REQUIRE([gt_INTL_SUBDIR_CORE])dnl + AC_REQUIRE([AC_TYPE_LONG_LONG_INT])dnl + AC_REQUIRE([gt_TYPE_WCHAR_T])dnl + AC_REQUIRE([gt_TYPE_WINT_T])dnl + AC_REQUIRE([gl_AC_HEADER_INTTYPES_H]) + AC_REQUIRE([gt_TYPE_INTMAX_T]) + AC_REQUIRE([gt_PRINTF_POSIX]) + AC_REQUIRE([gl_GLIBC21])dnl + AC_REQUIRE([gl_XSIZE])dnl + AC_REQUIRE([gl_FCNTL_O_FLAGS])dnl + AC_REQUIRE([gt_INTL_MACOSX])dnl + + dnl Support for automake's --enable-silent-rules. + case "$enable_silent_rules" in + yes) INTL_DEFAULT_VERBOSITY=0;; + no) INTL_DEFAULT_VERBOSITY=1;; + *) INTL_DEFAULT_VERBOSITY=1;; + esac + AC_SUBST([INTL_DEFAULT_VERBOSITY]) + + AC_CHECK_TYPE([ptrdiff_t], , + [AC_DEFINE([ptrdiff_t], [long], + [Define as the type of the result of subtracting two pointers, if the system doesn't define it.]) + ]) + AC_CHECK_HEADERS([stddef.h stdlib.h string.h]) + AC_CHECK_FUNCS([asprintf fwprintf newlocale putenv setenv setlocale \ + snprintf strnlen wcslen wcsnlen mbrtowc wcrtomb]) + + dnl Use the _snprintf function only if it is declared (because on NetBSD it + dnl is defined as a weak alias of snprintf; we prefer to use the latter). + gt_CHECK_DECL(_snprintf, [#include ]) + gt_CHECK_DECL(_snwprintf, [#include ]) + + dnl Use the *_unlocked functions only if they are declared. + dnl (because some of them were defined without being declared in Solaris + dnl 2.5.1 but were removed in Solaris 2.6, whereas we want binaries built + dnl on Solaris 2.5.1 to run on Solaris 2.6). + dnl Don't use AC_CHECK_DECLS because it isn't supported in autoconf-2.13. + gt_CHECK_DECL(getc_unlocked, [#include ]) + + case $gt_cv_func_printf_posix in + *yes) HAVE_POSIX_PRINTF=1 ;; + *) HAVE_POSIX_PRINTF=0 ;; + esac + AC_SUBST([HAVE_POSIX_PRINTF]) + if test "$ac_cv_func_asprintf" = yes; then + HAVE_ASPRINTF=1 + else + HAVE_ASPRINTF=0 + fi + AC_SUBST([HAVE_ASPRINTF]) + if test "$ac_cv_func_snprintf" = yes; then + HAVE_SNPRINTF=1 + else + HAVE_SNPRINTF=0 + fi + AC_SUBST([HAVE_SNPRINTF]) + if test "$ac_cv_func_newlocale" = yes; then + HAVE_NEWLOCALE=1 + else + HAVE_NEWLOCALE=0 + fi + AC_SUBST([HAVE_NEWLOCALE]) + if test "$ac_cv_func_wprintf" = yes; then + HAVE_WPRINTF=1 + else + HAVE_WPRINTF=0 + fi + AC_SUBST([HAVE_WPRINTF]) + + AM_LANGINFO_CODESET + gt_LC_MESSAGES + + dnl Compilation on mingw and Cygwin needs special Makefile rules, because + dnl 1. when we install a shared library, we must arrange to export + dnl auxiliary pointer variables for every exported variable, + dnl 2. when we install a shared library and a static library simultaneously, + dnl the include file specifies __declspec(dllimport) and therefore we + dnl must arrange to define the auxiliary pointer variables for the + dnl exported variables _also_ in the static library. + if test "$enable_shared" = yes; then + case "$host_os" in + mingw* | cygwin*) is_woe32dll=yes ;; + *) is_woe32dll=no ;; + esac + else + is_woe32dll=no + fi + WOE32DLL=$is_woe32dll + AC_SUBST([WOE32DLL]) + + dnl On mingw and Cygwin, we can activate special Makefile rules which add + dnl version information to the shared libraries and executables. + case "$host_os" in + mingw* | cygwin*) is_woe32=yes ;; + *) is_woe32=no ;; + esac + WOE32=$is_woe32 + AC_SUBST([WOE32]) + if test $WOE32 = yes; then + dnl Check for a program that compiles Windows resource files. + AC_CHECK_TOOL([WINDRES], [windres]) + fi + + dnl Determine whether when creating a library, "-lc" should be passed to + dnl libtool or not. On many platforms, it is required for the libtool option + dnl -no-undefined to work. On HP-UX, however, the -lc - stored by libtool + dnl in the *.la files - makes it impossible to create multithreaded programs, + dnl because libtool also reorders the -lc to come before the -pthread, and + dnl this disables pthread_create() . + case "$host_os" in + hpux*) LTLIBC="" ;; + *) LTLIBC="-lc" ;; + esac + AC_SUBST([LTLIBC]) + + dnl Rename some macros and functions used for locking. + AH_BOTTOM([ +#define __libc_lock_t gl_lock_t +#define __libc_lock_define gl_lock_define +#define __libc_lock_define_initialized gl_lock_define_initialized +#define __libc_lock_init gl_lock_init +#define __libc_lock_lock gl_lock_lock +#define __libc_lock_unlock gl_lock_unlock +#define __libc_lock_recursive_t gl_recursive_lock_t +#define __libc_lock_define_recursive gl_recursive_lock_define +#define __libc_lock_define_initialized_recursive gl_recursive_lock_define_initialized +#define __libc_lock_init_recursive gl_recursive_lock_init +#define __libc_lock_lock_recursive gl_recursive_lock_lock +#define __libc_lock_unlock_recursive gl_recursive_lock_unlock +#define glthread_in_use libintl_thread_in_use +#define glthread_lock_init_func libintl_lock_init_func +#define glthread_lock_lock_func libintl_lock_lock_func +#define glthread_lock_unlock_func libintl_lock_unlock_func +#define glthread_lock_destroy_func libintl_lock_destroy_func +#define glthread_rwlock_init_multithreaded libintl_rwlock_init_multithreaded +#define glthread_rwlock_init_func libintl_rwlock_init_func +#define glthread_rwlock_rdlock_multithreaded libintl_rwlock_rdlock_multithreaded +#define glthread_rwlock_rdlock_func libintl_rwlock_rdlock_func +#define glthread_rwlock_wrlock_multithreaded libintl_rwlock_wrlock_multithreaded +#define glthread_rwlock_wrlock_func libintl_rwlock_wrlock_func +#define glthread_rwlock_unlock_multithreaded libintl_rwlock_unlock_multithreaded +#define glthread_rwlock_unlock_func libintl_rwlock_unlock_func +#define glthread_rwlock_destroy_multithreaded libintl_rwlock_destroy_multithreaded +#define glthread_rwlock_destroy_func libintl_rwlock_destroy_func +#define glthread_recursive_lock_init_multithreaded libintl_recursive_lock_init_multithreaded +#define glthread_recursive_lock_init_func libintl_recursive_lock_init_func +#define glthread_recursive_lock_lock_multithreaded libintl_recursive_lock_lock_multithreaded +#define glthread_recursive_lock_lock_func libintl_recursive_lock_lock_func +#define glthread_recursive_lock_unlock_multithreaded libintl_recursive_lock_unlock_multithreaded +#define glthread_recursive_lock_unlock_func libintl_recursive_lock_unlock_func +#define glthread_recursive_lock_destroy_multithreaded libintl_recursive_lock_destroy_multithreaded +#define glthread_recursive_lock_destroy_func libintl_recursive_lock_destroy_func +#define glthread_once_func libintl_once_func +#define glthread_once_singlethreaded libintl_once_singlethreaded +#define glthread_once_multithreaded libintl_once_multithreaded +]) +]) + + +dnl Checks for the core files of the intl subdirectory: +dnl dcigettext.c +dnl eval-plural.h +dnl explodename.c +dnl finddomain.c +dnl gettextP.h +dnl gmo.h +dnl hash-string.h hash-string.c +dnl l10nflist.c +dnl libgnuintl.h.in (except the *printf stuff) +dnl loadinfo.h +dnl loadmsgcat.c +dnl localealias.c +dnl log.c +dnl plural-exp.h plural-exp.c +dnl plural.y +dnl Used by libglocale. +AC_DEFUN([gt_INTL_SUBDIR_CORE], +[ + AC_REQUIRE([AC_C_INLINE])dnl + AC_REQUIRE([AC_TYPE_SIZE_T])dnl + AC_REQUIRE([gl_AC_HEADER_STDINT_H]) + AC_REQUIRE([AC_FUNC_ALLOCA])dnl + AC_REQUIRE([AC_FUNC_MMAP])dnl + AC_REQUIRE([gt_INTDIV0])dnl + AC_REQUIRE([gl_AC_TYPE_UINTMAX_T])dnl + AC_REQUIRE([gt_INTTYPES_PRI])dnl + AC_REQUIRE([gl_LOCK])dnl + + AC_TRY_LINK( + [int foo (int a) { a = __builtin_expect (a, 10); return a == 10 ? 0 : 1; }], + [], + [AC_DEFINE([HAVE_BUILTIN_EXPECT], [1], + [Define to 1 if the compiler understands __builtin_expect.])]) + + AC_CHECK_HEADERS([argz.h inttypes.h limits.h unistd.h sys/param.h]) + AC_CHECK_FUNCS([getcwd getegid geteuid getgid getuid mempcpy munmap \ + stpcpy strcasecmp strdup strtoul tsearch uselocale argz_count \ + argz_stringify argz_next __fsetlocking]) + + dnl Use the *_unlocked functions only if they are declared. + dnl (because some of them were defined without being declared in Solaris + dnl 2.5.1 but were removed in Solaris 2.6, whereas we want binaries built + dnl on Solaris 2.5.1 to run on Solaris 2.6). + dnl Don't use AC_CHECK_DECLS because it isn't supported in autoconf-2.13. + gt_CHECK_DECL([feof_unlocked], [#include ]) + gt_CHECK_DECL([fgets_unlocked], [#include ]) + + AM_ICONV + + dnl intl/plural.c is generated from intl/plural.y. It requires bison, + dnl because plural.y uses bison specific features. It requires at least + dnl bison-1.26 because earlier versions generate a plural.c that doesn't + dnl compile. + dnl bison is only needed for the maintainer (who touches plural.y). But in + dnl order to avoid separate Makefiles or --enable-maintainer-mode, we put + dnl the rule in general Makefile. Now, some people carelessly touch the + dnl files or have a broken "make" program, hence the plural.c rule will + dnl sometimes fire. To avoid an error, defines BISON to ":" if it is not + dnl present or too old. + AC_CHECK_PROGS([INTLBISON], [bison]) + if test -z "$INTLBISON"; then + ac_verc_fail=yes + else + dnl Found it, now check the version. + AC_MSG_CHECKING([version of bison]) +changequote(<<,>>)dnl + ac_prog_version=`$INTLBISON --version 2>&1 | sed -n 's/^.*GNU Bison.* \([0-9]*\.[0-9.]*\).*$/\1/p'` + case $ac_prog_version in + '') ac_prog_version="v. ?.??, bad"; ac_verc_fail=yes;; + 1.2[6-9]* | 1.[3-9][0-9]* | [2-9].*) +changequote([,])dnl + ac_prog_version="$ac_prog_version, ok"; ac_verc_fail=no;; + *) ac_prog_version="$ac_prog_version, bad"; ac_verc_fail=yes;; + esac + AC_MSG_RESULT([$ac_prog_version]) + fi + if test $ac_verc_fail = yes; then + INTLBISON=: + fi +]) + + +dnl gt_CHECK_DECL(FUNC, INCLUDES) +dnl Check whether a function is declared. +AC_DEFUN([gt_CHECK_DECL], +[ + AC_CACHE_CHECK([whether $1 is declared], [ac_cv_have_decl_$1], + [AC_TRY_COMPILE([$2], [ +#ifndef $1 + char *p = (char *) $1; +#endif +], ac_cv_have_decl_$1=yes, ac_cv_have_decl_$1=no)]) + if test $ac_cv_have_decl_$1 = yes; then + gt_value=1 + else + gt_value=0 + fi + AC_DEFINE_UNQUOTED([HAVE_DECL_]translit($1, [a-z], [A-Z]), [$gt_value], + [Define to 1 if you have the declaration of `$1', and to 0 if you don't.]) +]) diff --git a/m4/intldir.m4 b/m4/intldir.m4 new file mode 100644 index 00000000..ebae76d3 --- /dev/null +++ b/m4/intldir.m4 @@ -0,0 +1,19 @@ +# intldir.m4 serial 2 (gettext-0.18) +dnl Copyright (C) 2006, 2009-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl +dnl This file can can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +AC_PREREQ([2.52]) + +dnl Tells the AM_GNU_GETTEXT macro to consider an intl/ directory. +AC_DEFUN([AM_GNU_GETTEXT_INTL_SUBDIR], []) diff --git a/m4/intlmacosx.m4 b/m4/intlmacosx.m4 new file mode 100644 index 00000000..dd910259 --- /dev/null +++ b/m4/intlmacosx.m4 @@ -0,0 +1,51 @@ +# intlmacosx.m4 serial 3 (gettext-0.18) +dnl Copyright (C) 2004-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl +dnl This file can can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Checks for special options needed on MacOS X. +dnl Defines INTL_MACOSX_LIBS. +AC_DEFUN([gt_INTL_MACOSX], +[ + dnl Check for API introduced in MacOS X 10.2. + AC_CACHE_CHECK([for CFPreferencesCopyAppValue], + [gt_cv_func_CFPreferencesCopyAppValue], + [gt_save_LIBS="$LIBS" + LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation" + AC_TRY_LINK([#include ], + [CFPreferencesCopyAppValue(NULL, NULL)], + [gt_cv_func_CFPreferencesCopyAppValue=yes], + [gt_cv_func_CFPreferencesCopyAppValue=no]) + LIBS="$gt_save_LIBS"]) + if test $gt_cv_func_CFPreferencesCopyAppValue = yes; then + AC_DEFINE([HAVE_CFPREFERENCESCOPYAPPVALUE], [1], + [Define to 1 if you have the MacOS X function CFPreferencesCopyAppValue in the CoreFoundation framework.]) + fi + dnl Check for API introduced in MacOS X 10.3. + AC_CACHE_CHECK([for CFLocaleCopyCurrent], [gt_cv_func_CFLocaleCopyCurrent], + [gt_save_LIBS="$LIBS" + LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation" + AC_TRY_LINK([#include ], [CFLocaleCopyCurrent();], + [gt_cv_func_CFLocaleCopyCurrent=yes], + [gt_cv_func_CFLocaleCopyCurrent=no]) + LIBS="$gt_save_LIBS"]) + if test $gt_cv_func_CFLocaleCopyCurrent = yes; then + AC_DEFINE([HAVE_CFLOCALECOPYCURRENT], [1], + [Define to 1 if you have the MacOS X function CFLocaleCopyCurrent in the CoreFoundation framework.]) + fi + INTL_MACOSX_LIBS= + if test $gt_cv_func_CFPreferencesCopyAppValue = yes || test $gt_cv_func_CFLocaleCopyCurrent = yes; then + INTL_MACOSX_LIBS="-Wl,-framework -Wl,CoreFoundation" + fi + AC_SUBST([INTL_MACOSX_LIBS]) +]) diff --git a/m4/intmax.m4 b/m4/intmax.m4 new file mode 100644 index 00000000..74aaaf5e --- /dev/null +++ b/m4/intmax.m4 @@ -0,0 +1,33 @@ +# intmax.m4 serial 5 (gettext-0.18) +dnl Copyright (C) 2002-2005, 2008-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. +dnl Test whether the system has the 'intmax_t' type, but don't attempt to +dnl find a replacement if it is lacking. + +AC_DEFUN([gt_TYPE_INTMAX_T], +[ + AC_REQUIRE([gl_AC_HEADER_INTTYPES_H]) + AC_REQUIRE([gl_AC_HEADER_STDINT_H]) + AC_CACHE_CHECK([for intmax_t], [gt_cv_c_intmax_t], + [AC_TRY_COMPILE([ +#include +#include +#if HAVE_STDINT_H_WITH_UINTMAX +#include +#endif +#if HAVE_INTTYPES_H_WITH_UINTMAX +#include +#endif +], [intmax_t x = -1; + return !x;], + [gt_cv_c_intmax_t=yes], + [gt_cv_c_intmax_t=no])]) + if test $gt_cv_c_intmax_t = yes; then + AC_DEFINE([HAVE_INTMAX_T], [1], + [Define if you have the 'intmax_t' type in or .]) + fi +]) diff --git a/m4/inttypes-pri.m4 b/m4/inttypes-pri.m4 new file mode 100644 index 00000000..718a4f4e --- /dev/null +++ b/m4/inttypes-pri.m4 @@ -0,0 +1,36 @@ +# inttypes-pri.m4 serial 6 (gettext-0.18) +dnl Copyright (C) 1997-2002, 2006, 2008-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +AC_PREREQ([2.52]) + +# Define PRI_MACROS_BROKEN if exists and defines the PRI* +# macros to non-string values. This is the case on AIX 4.3.3. + +AC_DEFUN([gt_INTTYPES_PRI], +[ + AC_CHECK_HEADERS([inttypes.h]) + if test $ac_cv_header_inttypes_h = yes; then + AC_CACHE_CHECK([whether the inttypes.h PRIxNN macros are broken], + [gt_cv_inttypes_pri_broken], + [ + AC_TRY_COMPILE([#include +#ifdef PRId32 +char *p = PRId32; +#endif +], [], [gt_cv_inttypes_pri_broken=no], [gt_cv_inttypes_pri_broken=yes]) + ]) + fi + if test "$gt_cv_inttypes_pri_broken" = yes; then + AC_DEFINE_UNQUOTED([PRI_MACROS_BROKEN], [1], + [Define if exists and defines unusable PRI* macros.]) + PRI_MACROS_BROKEN=1 + else + PRI_MACROS_BROKEN=0 + fi + AC_SUBST([PRI_MACROS_BROKEN]) +]) diff --git a/m4/inttypes_h.m4 b/m4/inttypes_h.m4 new file mode 100644 index 00000000..782d77ed --- /dev/null +++ b/m4/inttypes_h.m4 @@ -0,0 +1,26 @@ +# inttypes_h.m4 serial 9 +dnl Copyright (C) 1997-2004, 2006, 2008-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Paul Eggert. + +# Define HAVE_INTTYPES_H_WITH_UINTMAX if exists, +# doesn't clash with , and declares uintmax_t. + +AC_DEFUN([gl_AC_HEADER_INTTYPES_H], +[ + AC_CACHE_CHECK([for inttypes.h], [gl_cv_header_inttypes_h], + [AC_TRY_COMPILE( + [#include +#include ], + [uintmax_t i = (uintmax_t) -1; return !i;], + [gl_cv_header_inttypes_h=yes], + [gl_cv_header_inttypes_h=no])]) + if test $gl_cv_header_inttypes_h = yes; then + AC_DEFINE_UNQUOTED([HAVE_INTTYPES_H_WITH_UINTMAX], [1], + [Define if exists, doesn't clash with , + and declares uintmax_t. ]) + fi +]) diff --git a/m4/lcmessage.m4 b/m4/lcmessage.m4 new file mode 100644 index 00000000..1a705431 --- /dev/null +++ b/m4/lcmessage.m4 @@ -0,0 +1,31 @@ +# lcmessage.m4 serial 6 (gettext-0.18) +dnl Copyright (C) 1995-2002, 2004-2005, 2008-2010 Free Software Foundation, +dnl Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl +dnl This file can can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Authors: +dnl Ulrich Drepper , 1995. + +# Check whether LC_MESSAGES is available in . + +AC_DEFUN([gt_LC_MESSAGES], +[ + AC_CACHE_CHECK([for LC_MESSAGES], [gt_cv_val_LC_MESSAGES], + [AC_TRY_LINK([#include ], [return LC_MESSAGES], + [gt_cv_val_LC_MESSAGES=yes], [gt_cv_val_LC_MESSAGES=no])]) + if test $gt_cv_val_LC_MESSAGES = yes; then + AC_DEFINE([HAVE_LC_MESSAGES], [1], + [Define if your file defines LC_MESSAGES.]) + fi +]) diff --git a/m4/lib-ld.m4 b/m4/lib-ld.m4 new file mode 100644 index 00000000..6209de65 --- /dev/null +++ b/m4/lib-ld.m4 @@ -0,0 +1,119 @@ +# lib-ld.m4 serial 6 +dnl Copyright (C) 1996-2003, 2009-2016 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl Subroutines of libtool.m4, +dnl with replacements s/_*LT_PATH/AC_LIB_PROG/ and s/lt_/acl_/ to avoid +dnl collision with libtool.m4. + +dnl From libtool-2.4. Sets the variable with_gnu_ld to yes or no. +AC_DEFUN([AC_LIB_PROG_LD_GNU], +[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], [acl_cv_prog_gnu_ld], +[# I'd rather use --version here, but apparently some GNU lds only accept -v. +case `$LD -v 2>&1 /dev/null 2>&1 \ + && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 \ + || PATH_SEPARATOR=';' + } +fi + +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + AC_MSG_CHECKING([for ld used by $CC]) + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [[\\/]]* | ?:[[\\/]]*) + re_direlt='/[[^/]][[^/]]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`echo "$ac_prog"| sed 's%\\\\%/%g'` + while echo "$ac_prog" | grep "$re_direlt" > /dev/null 2>&1; do + ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + AC_MSG_CHECKING([for GNU ld]) +else + AC_MSG_CHECKING([for non-GNU ld]) +fi +AC_CACHE_VAL([acl_cv_path_LD], +[if test -z "$LD"; then + acl_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$acl_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + acl_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$acl_cv_path_LD" -v 2>&1 = 1.10 to complain if config.rpath is missing. + m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([config.rpath])]) + AC_REQUIRE([AC_PROG_CC]) dnl we use $CC, $GCC, $LDFLAGS + AC_REQUIRE([AC_LIB_PROG_LD]) dnl we use $LD, $with_gnu_ld + AC_REQUIRE([AC_CANONICAL_HOST]) dnl we use $host + AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT]) dnl we use $ac_aux_dir + AC_CACHE_CHECK([for shared library run path origin], [acl_cv_rpath], [ + CC="$CC" GCC="$GCC" LDFLAGS="$LDFLAGS" LD="$LD" with_gnu_ld="$with_gnu_ld" \ + ${CONFIG_SHELL-/bin/sh} "$ac_aux_dir/config.rpath" "$host" > conftest.sh + . ./conftest.sh + rm -f ./conftest.sh + acl_cv_rpath=done + ]) + wl="$acl_cv_wl" + acl_libext="$acl_cv_libext" + acl_shlibext="$acl_cv_shlibext" + acl_libname_spec="$acl_cv_libname_spec" + acl_library_names_spec="$acl_cv_library_names_spec" + acl_hardcode_libdir_flag_spec="$acl_cv_hardcode_libdir_flag_spec" + acl_hardcode_libdir_separator="$acl_cv_hardcode_libdir_separator" + acl_hardcode_direct="$acl_cv_hardcode_direct" + acl_hardcode_minus_L="$acl_cv_hardcode_minus_L" + dnl Determine whether the user wants rpath handling at all. + AC_ARG_ENABLE([rpath], + [ --disable-rpath do not hardcode runtime library paths], + :, enable_rpath=yes) +]) + +dnl AC_LIB_FROMPACKAGE(name, package) +dnl declares that libname comes from the given package. The configure file +dnl will then not have a --with-libname-prefix option but a +dnl --with-package-prefix option. Several libraries can come from the same +dnl package. This declaration must occur before an AC_LIB_LINKFLAGS or similar +dnl macro call that searches for libname. +AC_DEFUN([AC_LIB_FROMPACKAGE], +[ + pushdef([NAME],[m4_translit([$1],[abcdefghijklmnopqrstuvwxyz./+-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ____])]) + define([acl_frompackage_]NAME, [$2]) + popdef([NAME]) + pushdef([PACK],[$2]) + pushdef([PACKUP],[m4_translit(PACK,[abcdefghijklmnopqrstuvwxyz./+-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ____])]) + define([acl_libsinpackage_]PACKUP, + m4_ifdef([acl_libsinpackage_]PACKUP, [m4_defn([acl_libsinpackage_]PACKUP)[, ]],)[lib$1]) + popdef([PACKUP]) + popdef([PACK]) +]) + +dnl AC_LIB_LINKFLAGS_BODY(name [, dependencies]) searches for libname and +dnl the libraries corresponding to explicit and implicit dependencies. +dnl Sets the LIB${NAME}, LTLIB${NAME} and INC${NAME} variables. +dnl Also, sets the LIB${NAME}_PREFIX variable to nonempty if libname was found +dnl in ${LIB${NAME}_PREFIX}/$acl_libdirstem. +AC_DEFUN([AC_LIB_LINKFLAGS_BODY], +[ + AC_REQUIRE([AC_LIB_PREPARE_MULTILIB]) + pushdef([NAME],[m4_translit([$1],[abcdefghijklmnopqrstuvwxyz./+-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ____])]) + pushdef([PACK],[m4_ifdef([acl_frompackage_]NAME, [acl_frompackage_]NAME, lib[$1])]) + pushdef([PACKUP],[m4_translit(PACK,[abcdefghijklmnopqrstuvwxyz./+-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ____])]) + pushdef([PACKLIBS],[m4_ifdef([acl_frompackage_]NAME, [acl_libsinpackage_]PACKUP, lib[$1])]) + dnl Autoconf >= 2.61 supports dots in --with options. + pushdef([P_A_C_K],[m4_if(m4_version_compare(m4_defn([m4_PACKAGE_VERSION]),[2.61]),[-1],[m4_translit(PACK,[.],[_])],PACK)]) + dnl By default, look in $includedir and $libdir. + use_additional=yes + AC_LIB_WITH_FINAL_PREFIX([ + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + ]) + AC_ARG_WITH(P_A_C_K[-prefix], +[[ --with-]]P_A_C_K[[-prefix[=DIR] search for ]PACKLIBS[ in DIR/include and DIR/lib + --without-]]P_A_C_K[[-prefix don't search for ]PACKLIBS[ in includedir and libdir]], +[ + if test "X$withval" = "Xno"; then + use_additional=no + else + if test "X$withval" = "X"; then + AC_LIB_WITH_FINAL_PREFIX([ + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + ]) + else + additional_includedir="$withval/include" + additional_libdir="$withval/$acl_libdirstem" + if test "$acl_libdirstem2" != "$acl_libdirstem" \ + && ! test -d "$withval/$acl_libdirstem"; then + additional_libdir="$withval/$acl_libdirstem2" + fi + fi + fi +]) + dnl Search the library and its dependencies in $additional_libdir and + dnl $LDFLAGS. Using breadth-first-seach. + LIB[]NAME= + LTLIB[]NAME= + INC[]NAME= + LIB[]NAME[]_PREFIX= + dnl HAVE_LIB${NAME} is an indicator that LIB${NAME}, LTLIB${NAME} have been + dnl computed. So it has to be reset here. + HAVE_LIB[]NAME= + rpathdirs= + ltrpathdirs= + names_already_handled= + names_next_round='$1 $2' + while test -n "$names_next_round"; do + names_this_round="$names_next_round" + names_next_round= + for name in $names_this_round; do + already_handled= + for n in $names_already_handled; do + if test "$n" = "$name"; then + already_handled=yes + break + fi + done + if test -z "$already_handled"; then + names_already_handled="$names_already_handled $name" + dnl See if it was already located by an earlier AC_LIB_LINKFLAGS + dnl or AC_LIB_HAVE_LINKFLAGS call. + uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./+-|ABCDEFGHIJKLMNOPQRSTUVWXYZ____|'` + eval value=\"\$HAVE_LIB$uppername\" + if test -n "$value"; then + if test "$value" = yes; then + eval value=\"\$LIB$uppername\" + test -z "$value" || LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$value" + eval value=\"\$LTLIB$uppername\" + test -z "$value" || LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$value" + else + dnl An earlier call to AC_LIB_HAVE_LINKFLAGS has determined + dnl that this library doesn't exist. So just drop it. + : + fi + else + dnl Search the library lib$name in $additional_libdir and $LDFLAGS + dnl and the already constructed $LIBNAME/$LTLIBNAME. + found_dir= + found_la= + found_so= + found_a= + eval libname=\"$acl_libname_spec\" # typically: libname=lib$name + if test -n "$acl_shlibext"; then + shrext=".$acl_shlibext" # typically: shrext=.so + else + shrext= + fi + if test $use_additional = yes; then + dir="$additional_libdir" + dnl The same code as in the loop below: + dnl First look for a shared library. + if test -n "$acl_shlibext"; then + if test -f "$dir/$libname$shrext"; then + found_dir="$dir" + found_so="$dir/$libname$shrext" + else + if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then + ver=`(cd "$dir" && \ + for f in "$libname$shrext".*; do echo "$f"; done \ + | sed -e "s,^$libname$shrext\\\\.,," \ + | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ + | sed 1q ) 2>/dev/null` + if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then + found_dir="$dir" + found_so="$dir/$libname$shrext.$ver" + fi + else + eval library_names=\"$acl_library_names_spec\" + for f in $library_names; do + if test -f "$dir/$f"; then + found_dir="$dir" + found_so="$dir/$f" + break + fi + done + fi + fi + fi + dnl Then look for a static library. + if test "X$found_dir" = "X"; then + if test -f "$dir/$libname.$acl_libext"; then + found_dir="$dir" + found_a="$dir/$libname.$acl_libext" + fi + fi + if test "X$found_dir" != "X"; then + if test -f "$dir/$libname.la"; then + found_la="$dir/$libname.la" + fi + fi + fi + if test "X$found_dir" = "X"; then + for x in $LDFLAGS $LTLIB[]NAME; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + case "$x" in + -L*) + dir=`echo "X$x" | sed -e 's/^X-L//'` + dnl First look for a shared library. + if test -n "$acl_shlibext"; then + if test -f "$dir/$libname$shrext"; then + found_dir="$dir" + found_so="$dir/$libname$shrext" + else + if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then + ver=`(cd "$dir" && \ + for f in "$libname$shrext".*; do echo "$f"; done \ + | sed -e "s,^$libname$shrext\\\\.,," \ + | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ + | sed 1q ) 2>/dev/null` + if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then + found_dir="$dir" + found_so="$dir/$libname$shrext.$ver" + fi + else + eval library_names=\"$acl_library_names_spec\" + for f in $library_names; do + if test -f "$dir/$f"; then + found_dir="$dir" + found_so="$dir/$f" + break + fi + done + fi + fi + fi + dnl Then look for a static library. + if test "X$found_dir" = "X"; then + if test -f "$dir/$libname.$acl_libext"; then + found_dir="$dir" + found_a="$dir/$libname.$acl_libext" + fi + fi + if test "X$found_dir" != "X"; then + if test -f "$dir/$libname.la"; then + found_la="$dir/$libname.la" + fi + fi + ;; + esac + if test "X$found_dir" != "X"; then + break + fi + done + fi + if test "X$found_dir" != "X"; then + dnl Found the library. + LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$found_dir -l$name" + if test "X$found_so" != "X"; then + dnl Linking with a shared library. We attempt to hardcode its + dnl directory into the executable's runpath, unless it's the + dnl standard /usr/lib. + if test "$enable_rpath" = no \ + || test "X$found_dir" = "X/usr/$acl_libdirstem" \ + || test "X$found_dir" = "X/usr/$acl_libdirstem2"; then + dnl No hardcoding is needed. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" + else + dnl Use an explicit option to hardcode DIR into the resulting + dnl binary. + dnl Potentially add DIR to ltrpathdirs. + dnl The ltrpathdirs will be appended to $LTLIBNAME at the end. + haveit= + for x in $ltrpathdirs; do + if test "X$x" = "X$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + ltrpathdirs="$ltrpathdirs $found_dir" + fi + dnl The hardcoding into $LIBNAME is system dependent. + if test "$acl_hardcode_direct" = yes; then + dnl Using DIR/libNAME.so during linking hardcodes DIR into the + dnl resulting binary. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" + else + if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then + dnl Use an explicit option to hardcode DIR into the resulting + dnl binary. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" + dnl Potentially add DIR to rpathdirs. + dnl The rpathdirs will be appended to $LIBNAME at the end. + haveit= + for x in $rpathdirs; do + if test "X$x" = "X$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + rpathdirs="$rpathdirs $found_dir" + fi + else + dnl Rely on "-L$found_dir". + dnl But don't add it if it's already contained in the LDFLAGS + dnl or the already constructed $LIBNAME + haveit= + for x in $LDFLAGS $LIB[]NAME; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-L$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir" + fi + if test "$acl_hardcode_minus_L" != no; then + dnl FIXME: Not sure whether we should use + dnl "-L$found_dir -l$name" or "-L$found_dir $found_so" + dnl here. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" + else + dnl We cannot use $acl_hardcode_runpath_var and LD_RUN_PATH + dnl here, because this doesn't fit in flags passed to the + dnl compiler. So give up. No hardcoding. This affects only + dnl very old systems. + dnl FIXME: Not sure whether we should use + dnl "-L$found_dir -l$name" or "-L$found_dir $found_so" + dnl here. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name" + fi + fi + fi + fi + else + if test "X$found_a" != "X"; then + dnl Linking with a static library. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_a" + else + dnl We shouldn't come here, but anyway it's good to have a + dnl fallback. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir -l$name" + fi + fi + dnl Assume the include files are nearby. + additional_includedir= + case "$found_dir" in + */$acl_libdirstem | */$acl_libdirstem/) + basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem/"'*$,,'` + if test "$name" = '$1'; then + LIB[]NAME[]_PREFIX="$basedir" + fi + additional_includedir="$basedir/include" + ;; + */$acl_libdirstem2 | */$acl_libdirstem2/) + basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem2/"'*$,,'` + if test "$name" = '$1'; then + LIB[]NAME[]_PREFIX="$basedir" + fi + additional_includedir="$basedir/include" + ;; + esac + if test "X$additional_includedir" != "X"; then + dnl Potentially add $additional_includedir to $INCNAME. + dnl But don't add it + dnl 1. if it's the standard /usr/include, + dnl 2. if it's /usr/local/include and we are using GCC on Linux, + dnl 3. if it's already present in $CPPFLAGS or the already + dnl constructed $INCNAME, + dnl 4. if it doesn't exist as a directory. + if test "X$additional_includedir" != "X/usr/include"; then + haveit= + if test "X$additional_includedir" = "X/usr/local/include"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + for x in $CPPFLAGS $INC[]NAME; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-I$additional_includedir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_includedir"; then + dnl Really add $additional_includedir to $INCNAME. + INC[]NAME="${INC[]NAME}${INC[]NAME:+ }-I$additional_includedir" + fi + fi + fi + fi + fi + dnl Look for dependencies. + if test -n "$found_la"; then + dnl Read the .la file. It defines the variables + dnl dlname, library_names, old_library, dependency_libs, current, + dnl age, revision, installed, dlopen, dlpreopen, libdir. + save_libdir="$libdir" + case "$found_la" in + */* | *\\*) . "$found_la" ;; + *) . "./$found_la" ;; + esac + libdir="$save_libdir" + dnl We use only dependency_libs. + for dep in $dependency_libs; do + case "$dep" in + -L*) + additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'` + dnl Potentially add $additional_libdir to $LIBNAME and $LTLIBNAME. + dnl But don't add it + dnl 1. if it's the standard /usr/lib, + dnl 2. if it's /usr/local/lib and we are using GCC on Linux, + dnl 3. if it's already present in $LDFLAGS or the already + dnl constructed $LIBNAME, + dnl 4. if it doesn't exist as a directory. + if test "X$additional_libdir" != "X/usr/$acl_libdirstem" \ + && test "X$additional_libdir" != "X/usr/$acl_libdirstem2"; then + haveit= + if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem" \ + || test "X$additional_libdir" = "X/usr/local/$acl_libdirstem2"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + haveit= + for x in $LDFLAGS $LIB[]NAME; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + dnl Really add $additional_libdir to $LIBNAME. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$additional_libdir" + fi + fi + haveit= + for x in $LDFLAGS $LTLIB[]NAME; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + dnl Really add $additional_libdir to $LTLIBNAME. + LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$additional_libdir" + fi + fi + fi + fi + ;; + -R*) + dir=`echo "X$dep" | sed -e 's/^X-R//'` + if test "$enable_rpath" != no; then + dnl Potentially add DIR to rpathdirs. + dnl The rpathdirs will be appended to $LIBNAME at the end. + haveit= + for x in $rpathdirs; do + if test "X$x" = "X$dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + rpathdirs="$rpathdirs $dir" + fi + dnl Potentially add DIR to ltrpathdirs. + dnl The ltrpathdirs will be appended to $LTLIBNAME at the end. + haveit= + for x in $ltrpathdirs; do + if test "X$x" = "X$dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + ltrpathdirs="$ltrpathdirs $dir" + fi + fi + ;; + -l*) + dnl Handle this in the next round. + names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'` + ;; + *.la) + dnl Handle this in the next round. Throw away the .la's + dnl directory; it is already contained in a preceding -L + dnl option. + names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'` + ;; + *) + dnl Most likely an immediate library name. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$dep" + LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$dep" + ;; + esac + done + fi + else + dnl Didn't find the library; assume it is in the system directories + dnl known to the linker and runtime loader. (All the system + dnl directories known to the linker should also be known to the + dnl runtime loader, otherwise the system is severely misconfigured.) + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name" + LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-l$name" + fi + fi + fi + done + done + if test "X$rpathdirs" != "X"; then + if test -n "$acl_hardcode_libdir_separator"; then + dnl Weird platform: only the last -rpath option counts, the user must + dnl pass all path elements in one option. We can arrange that for a + dnl single library, but not when more than one $LIBNAMEs are used. + alldirs= + for found_dir in $rpathdirs; do + alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$found_dir" + done + dnl Note: acl_hardcode_libdir_flag_spec uses $libdir and $wl. + acl_save_libdir="$libdir" + libdir="$alldirs" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag" + else + dnl The -rpath options are cumulative. + for found_dir in $rpathdirs; do + acl_save_libdir="$libdir" + libdir="$found_dir" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag" + done + fi + fi + if test "X$ltrpathdirs" != "X"; then + dnl When using libtool, the option that works for both libraries and + dnl executables is -R. The -R options are cumulative. + for found_dir in $ltrpathdirs; do + LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-R$found_dir" + done + fi + popdef([P_A_C_K]) + popdef([PACKLIBS]) + popdef([PACKUP]) + popdef([PACK]) + popdef([NAME]) +]) + +dnl AC_LIB_APPENDTOVAR(VAR, CONTENTS) appends the elements of CONTENTS to VAR, +dnl unless already present in VAR. +dnl Works only for CPPFLAGS, not for LIB* variables because that sometimes +dnl contains two or three consecutive elements that belong together. +AC_DEFUN([AC_LIB_APPENDTOVAR], +[ + for element in [$2]; do + haveit= + for x in $[$1]; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X$element"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + [$1]="${[$1]}${[$1]:+ }$element" + fi + done +]) + +dnl For those cases where a variable contains several -L and -l options +dnl referring to unknown libraries and directories, this macro determines the +dnl necessary additional linker options for the runtime path. +dnl AC_LIB_LINKFLAGS_FROM_LIBS([LDADDVAR], [LIBSVALUE], [USE-LIBTOOL]) +dnl sets LDADDVAR to linker options needed together with LIBSVALUE. +dnl If USE-LIBTOOL evaluates to non-empty, linking with libtool is assumed, +dnl otherwise linking without libtool is assumed. +AC_DEFUN([AC_LIB_LINKFLAGS_FROM_LIBS], +[ + AC_REQUIRE([AC_LIB_RPATH]) + AC_REQUIRE([AC_LIB_PREPARE_MULTILIB]) + $1= + if test "$enable_rpath" != no; then + if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then + dnl Use an explicit option to hardcode directories into the resulting + dnl binary. + rpathdirs= + next= + for opt in $2; do + if test -n "$next"; then + dir="$next" + dnl No need to hardcode the standard /usr/lib. + if test "X$dir" != "X/usr/$acl_libdirstem" \ + && test "X$dir" != "X/usr/$acl_libdirstem2"; then + rpathdirs="$rpathdirs $dir" + fi + next= + else + case $opt in + -L) next=yes ;; + -L*) dir=`echo "X$opt" | sed -e 's,^X-L,,'` + dnl No need to hardcode the standard /usr/lib. + if test "X$dir" != "X/usr/$acl_libdirstem" \ + && test "X$dir" != "X/usr/$acl_libdirstem2"; then + rpathdirs="$rpathdirs $dir" + fi + next= ;; + *) next= ;; + esac + fi + done + if test "X$rpathdirs" != "X"; then + if test -n ""$3""; then + dnl libtool is used for linking. Use -R options. + for dir in $rpathdirs; do + $1="${$1}${$1:+ }-R$dir" + done + else + dnl The linker is used for linking directly. + if test -n "$acl_hardcode_libdir_separator"; then + dnl Weird platform: only the last -rpath option counts, the user + dnl must pass all path elements in one option. + alldirs= + for dir in $rpathdirs; do + alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$dir" + done + acl_save_libdir="$libdir" + libdir="$alldirs" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + $1="$flag" + else + dnl The -rpath options are cumulative. + for dir in $rpathdirs; do + acl_save_libdir="$libdir" + libdir="$dir" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + $1="${$1}${$1:+ }$flag" + done + fi + fi + fi + fi + fi + AC_SUBST([$1]) +]) diff --git a/m4/lib-prefix.m4 b/m4/lib-prefix.m4 new file mode 100644 index 00000000..6851031d --- /dev/null +++ b/m4/lib-prefix.m4 @@ -0,0 +1,224 @@ +# lib-prefix.m4 serial 7 (gettext-0.18) +dnl Copyright (C) 2001-2005, 2008-2016 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +dnl AC_LIB_ARG_WITH is synonymous to AC_ARG_WITH in autoconf-2.13, and +dnl similar to AC_ARG_WITH in autoconf 2.52...2.57 except that is doesn't +dnl require excessive bracketing. +ifdef([AC_HELP_STRING], +[AC_DEFUN([AC_LIB_ARG_WITH], [AC_ARG_WITH([$1],[[$2]],[$3],[$4])])], +[AC_DEFUN([AC_][LIB_ARG_WITH], [AC_ARG_WITH([$1],[$2],[$3],[$4])])]) + +dnl AC_LIB_PREFIX adds to the CPPFLAGS and LDFLAGS the flags that are needed +dnl to access previously installed libraries. The basic assumption is that +dnl a user will want packages to use other packages he previously installed +dnl with the same --prefix option. +dnl This macro is not needed if only AC_LIB_LINKFLAGS is used to locate +dnl libraries, but is otherwise very convenient. +AC_DEFUN([AC_LIB_PREFIX], +[ + AC_BEFORE([$0], [AC_LIB_LINKFLAGS]) + AC_REQUIRE([AC_PROG_CC]) + AC_REQUIRE([AC_CANONICAL_HOST]) + AC_REQUIRE([AC_LIB_PREPARE_MULTILIB]) + AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) + dnl By default, look in $includedir and $libdir. + use_additional=yes + AC_LIB_WITH_FINAL_PREFIX([ + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + ]) + AC_LIB_ARG_WITH([lib-prefix], +[ --with-lib-prefix[=DIR] search for libraries in DIR/include and DIR/lib + --without-lib-prefix don't search for libraries in includedir and libdir], +[ + if test "X$withval" = "Xno"; then + use_additional=no + else + if test "X$withval" = "X"; then + AC_LIB_WITH_FINAL_PREFIX([ + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + ]) + else + additional_includedir="$withval/include" + additional_libdir="$withval/$acl_libdirstem" + fi + fi +]) + if test $use_additional = yes; then + dnl Potentially add $additional_includedir to $CPPFLAGS. + dnl But don't add it + dnl 1. if it's the standard /usr/include, + dnl 2. if it's already present in $CPPFLAGS, + dnl 3. if it's /usr/local/include and we are using GCC on Linux, + dnl 4. if it doesn't exist as a directory. + if test "X$additional_includedir" != "X/usr/include"; then + haveit= + for x in $CPPFLAGS; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-I$additional_includedir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test "X$additional_includedir" = "X/usr/local/include"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + if test -d "$additional_includedir"; then + dnl Really add $additional_includedir to $CPPFLAGS. + CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }-I$additional_includedir" + fi + fi + fi + fi + dnl Potentially add $additional_libdir to $LDFLAGS. + dnl But don't add it + dnl 1. if it's the standard /usr/lib, + dnl 2. if it's already present in $LDFLAGS, + dnl 3. if it's /usr/local/lib and we are using GCC on Linux, + dnl 4. if it doesn't exist as a directory. + if test "X$additional_libdir" != "X/usr/$acl_libdirstem"; then + haveit= + for x in $LDFLAGS; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem"; then + if test -n "$GCC"; then + case $host_os in + linux*) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + dnl Really add $additional_libdir to $LDFLAGS. + LDFLAGS="${LDFLAGS}${LDFLAGS:+ }-L$additional_libdir" + fi + fi + fi + fi + fi +]) + +dnl AC_LIB_PREPARE_PREFIX creates variables acl_final_prefix, +dnl acl_final_exec_prefix, containing the values to which $prefix and +dnl $exec_prefix will expand at the end of the configure script. +AC_DEFUN([AC_LIB_PREPARE_PREFIX], +[ + dnl Unfortunately, prefix and exec_prefix get only finally determined + dnl at the end of configure. + if test "X$prefix" = "XNONE"; then + acl_final_prefix="$ac_default_prefix" + else + acl_final_prefix="$prefix" + fi + if test "X$exec_prefix" = "XNONE"; then + acl_final_exec_prefix='${prefix}' + else + acl_final_exec_prefix="$exec_prefix" + fi + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + eval acl_final_exec_prefix=\"$acl_final_exec_prefix\" + prefix="$acl_save_prefix" +]) + +dnl AC_LIB_WITH_FINAL_PREFIX([statement]) evaluates statement, with the +dnl variables prefix and exec_prefix bound to the values they will have +dnl at the end of the configure script. +AC_DEFUN([AC_LIB_WITH_FINAL_PREFIX], +[ + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + $1 + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" +]) + +dnl AC_LIB_PREPARE_MULTILIB creates +dnl - a variable acl_libdirstem, containing the basename of the libdir, either +dnl "lib" or "lib64" or "lib/64", +dnl - a variable acl_libdirstem2, as a secondary possible value for +dnl acl_libdirstem, either the same as acl_libdirstem or "lib/sparcv9" or +dnl "lib/amd64". +AC_DEFUN([AC_LIB_PREPARE_MULTILIB], +[ + dnl There is no formal standard regarding lib and lib64. + dnl On glibc systems, the current practice is that on a system supporting + dnl 32-bit and 64-bit instruction sets or ABIs, 64-bit libraries go under + dnl $prefix/lib64 and 32-bit libraries go under $prefix/lib. We determine + dnl the compiler's default mode by looking at the compiler's library search + dnl path. If at least one of its elements ends in /lib64 or points to a + dnl directory whose absolute pathname ends in /lib64, we assume a 64-bit ABI. + dnl Otherwise we use the default, namely "lib". + dnl On Solaris systems, the current practice is that on a system supporting + dnl 32-bit and 64-bit instruction sets or ABIs, 64-bit libraries go under + dnl $prefix/lib/64 (which is a symlink to either $prefix/lib/sparcv9 or + dnl $prefix/lib/amd64) and 32-bit libraries go under $prefix/lib. + AC_REQUIRE([AC_CANONICAL_HOST]) + acl_libdirstem=lib + acl_libdirstem2= + case "$host_os" in + solaris*) + dnl See Solaris 10 Software Developer Collection > Solaris 64-bit Developer's Guide > The Development Environment + dnl . + dnl "Portable Makefiles should refer to any library directories using the 64 symbolic link." + dnl But we want to recognize the sparcv9 or amd64 subdirectory also if the + dnl symlink is missing, so we set acl_libdirstem2 too. + AC_CACHE_CHECK([for 64-bit host], [gl_cv_solaris_64bit], + [AC_EGREP_CPP([sixtyfour bits], [ +#ifdef _LP64 +sixtyfour bits +#endif + ], [gl_cv_solaris_64bit=yes], [gl_cv_solaris_64bit=no]) + ]) + if test $gl_cv_solaris_64bit = yes; then + acl_libdirstem=lib/64 + case "$host_cpu" in + sparc*) acl_libdirstem2=lib/sparcv9 ;; + i*86 | x86_64) acl_libdirstem2=lib/amd64 ;; + esac + fi + ;; + *) + searchpath=`(LC_ALL=C $CC -print-search-dirs) 2>/dev/null | sed -n -e 's,^libraries: ,,p' | sed -e 's,^=,,'` + if test -n "$searchpath"; then + acl_save_IFS="${IFS= }"; IFS=":" + for searchdir in $searchpath; do + if test -d "$searchdir"; then + case "$searchdir" in + */lib64/ | */lib64 ) acl_libdirstem=lib64 ;; + */../ | */.. ) + # Better ignore directories of this form. They are misleading. + ;; + *) searchdir=`cd "$searchdir" && pwd` + case "$searchdir" in + */lib64 ) acl_libdirstem=lib64 ;; + esac ;; + esac + fi + done + IFS="$acl_save_IFS" + fi + ;; + esac + test -n "$acl_libdirstem2" || acl_libdirstem2="$acl_libdirstem" +]) diff --git a/m4/lock.m4 b/m4/lock.m4 new file mode 100644 index 00000000..9da8465e --- /dev/null +++ b/m4/lock.m4 @@ -0,0 +1,37 @@ +# lock.m4 serial 10 (gettext-0.18) +dnl Copyright (C) 2005-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +AC_DEFUN([gl_LOCK], +[ + AC_REQUIRE([gl_THREADLIB]) + if test "$gl_threads_api" = posix; then + # OSF/1 4.0 and MacOS X 10.1 lack the pthread_rwlock_t type and the + # pthread_rwlock_* functions. + AC_CHECK_TYPE([pthread_rwlock_t], + [AC_DEFINE([HAVE_PTHREAD_RWLOCK], [1], + [Define if the POSIX multithreading library has read/write locks.])], + [], + [#include ]) + # glibc defines PTHREAD_MUTEX_RECURSIVE as enum, not as a macro. + AC_TRY_COMPILE([#include ], + [#if __FreeBSD__ == 4 +error "No, in FreeBSD 4.0 recursive mutexes actually don't work." +#else +int x = (int)PTHREAD_MUTEX_RECURSIVE; +return !x; +#endif], + [AC_DEFINE([HAVE_PTHREAD_MUTEX_RECURSIVE], [1], + [Define if the defines PTHREAD_MUTEX_RECURSIVE.])]) + fi + gl_PREREQ_LOCK +]) + +# Prerequisites of lib/lock.c. +AC_DEFUN([gl_PREREQ_LOCK], [ + AC_REQUIRE([AC_C_INLINE]) +]) diff --git a/m4/longlong.m4 b/m4/longlong.m4 new file mode 100644 index 00000000..cca3c1a9 --- /dev/null +++ b/m4/longlong.m4 @@ -0,0 +1,106 @@ +# longlong.m4 serial 14 +dnl Copyright (C) 1999-2007, 2009-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Paul Eggert. + +# Define HAVE_LONG_LONG_INT if 'long long int' works. +# This fixes a bug in Autoconf 2.61, but can be removed once we +# assume 2.62 everywhere. + +# Note: If the type 'long long int' exists but is only 32 bits large +# (as on some very old compilers), HAVE_LONG_LONG_INT will not be +# defined. In this case you can treat 'long long int' like 'long int'. + +AC_DEFUN([AC_TYPE_LONG_LONG_INT], +[ + AC_CACHE_CHECK([for long long int], [ac_cv_type_long_long_int], + [AC_LINK_IFELSE( + [_AC_TYPE_LONG_LONG_SNIPPET], + [dnl This catches a bug in Tandem NonStop Kernel (OSS) cc -O circa 2004. + dnl If cross compiling, assume the bug isn't important, since + dnl nobody cross compiles for this platform as far as we know. + AC_RUN_IFELSE( + [AC_LANG_PROGRAM( + [[@%:@include + @%:@ifndef LLONG_MAX + @%:@ define HALF \ + (1LL << (sizeof (long long int) * CHAR_BIT - 2)) + @%:@ define LLONG_MAX (HALF - 1 + HALF) + @%:@endif]], + [[long long int n = 1; + int i; + for (i = 0; ; i++) + { + long long int m = n << i; + if (m >> i != n) + return 1; + if (LLONG_MAX / 2 < m) + break; + } + return 0;]])], + [ac_cv_type_long_long_int=yes], + [ac_cv_type_long_long_int=no], + [ac_cv_type_long_long_int=yes])], + [ac_cv_type_long_long_int=no])]) + if test $ac_cv_type_long_long_int = yes; then + AC_DEFINE([HAVE_LONG_LONG_INT], [1], + [Define to 1 if the system has the type `long long int'.]) + fi +]) + +# Define HAVE_UNSIGNED_LONG_LONG_INT if 'unsigned long long int' works. +# This fixes a bug in Autoconf 2.61, but can be removed once we +# assume 2.62 everywhere. + +# Note: If the type 'unsigned long long int' exists but is only 32 bits +# large (as on some very old compilers), AC_TYPE_UNSIGNED_LONG_LONG_INT +# will not be defined. In this case you can treat 'unsigned long long int' +# like 'unsigned long int'. + +AC_DEFUN([AC_TYPE_UNSIGNED_LONG_LONG_INT], +[ + AC_CACHE_CHECK([for unsigned long long int], + [ac_cv_type_unsigned_long_long_int], + [AC_LINK_IFELSE( + [_AC_TYPE_LONG_LONG_SNIPPET], + [ac_cv_type_unsigned_long_long_int=yes], + [ac_cv_type_unsigned_long_long_int=no])]) + if test $ac_cv_type_unsigned_long_long_int = yes; then + AC_DEFINE([HAVE_UNSIGNED_LONG_LONG_INT], [1], + [Define to 1 if the system has the type `unsigned long long int'.]) + fi +]) + +# Expands to a C program that can be used to test for simultaneous support +# of 'long long' and 'unsigned long long'. We don't want to say that +# 'long long' is available if 'unsigned long long' is not, or vice versa, +# because too many programs rely on the symmetry between signed and unsigned +# integer types (excluding 'bool'). +AC_DEFUN([_AC_TYPE_LONG_LONG_SNIPPET], +[ + AC_LANG_PROGRAM( + [[/* For now, do not test the preprocessor; as of 2007 there are too many + implementations with broken preprocessors. Perhaps this can + be revisited in 2012. In the meantime, code should not expect + #if to work with literals wider than 32 bits. */ + /* Test literals. */ + long long int ll = 9223372036854775807ll; + long long int nll = -9223372036854775807LL; + unsigned long long int ull = 18446744073709551615ULL; + /* Test constant expressions. */ + typedef int a[((-9223372036854775807LL < 0 && 0 < 9223372036854775807ll) + ? 1 : -1)]; + typedef int b[(18446744073709551615ULL <= (unsigned long long int) -1 + ? 1 : -1)]; + int i = 63;]], + [[/* Test availability of runtime routines for shift and division. */ + long long int llmax = 9223372036854775807ll; + unsigned long long int ullmax = 18446744073709551615ull; + return ((ll << 63) | (ll >> 63) | (ll < i) | (ll > i) + | (llmax / ll) | (llmax % ll) + | (ull << 63) | (ull >> 63) | (ull << i) | (ull >> i) + | (ullmax / ull) | (ullmax % ull));]]) +]) diff --git a/m4/nls.m4 b/m4/nls.m4 new file mode 100644 index 00000000..afdb9cac --- /dev/null +++ b/m4/nls.m4 @@ -0,0 +1,32 @@ +# nls.m4 serial 5 (gettext-0.18) +dnl Copyright (C) 1995-2003, 2005-2006, 2008-2014, 2016 Free Software +dnl Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl +dnl This file can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Authors: +dnl Ulrich Drepper , 1995-2000. +dnl Bruno Haible , 2000-2003. + +AC_PREREQ([2.50]) + +AC_DEFUN([AM_NLS], +[ + AC_MSG_CHECKING([whether NLS is requested]) + dnl Default is enabled NLS + AC_ARG_ENABLE([nls], + [ --disable-nls do not use Native Language Support], + USE_NLS=$enableval, USE_NLS=yes) + AC_MSG_RESULT([$USE_NLS]) + AC_SUBST([USE_NLS]) +]) diff --git a/m4/pkg.m4 b/m4/pkg.m4 new file mode 100644 index 00000000..4688002e --- /dev/null +++ b/m4/pkg.m4 @@ -0,0 +1,275 @@ +dnl pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- +dnl serial 11 (pkg-config-0.29) +dnl +dnl Copyright © 2004 Scott James Remnant . +dnl Copyright © 2012-2015 Dan Nicholson +dnl +dnl This program is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2 of the License, or +dnl (at your option) any later version. +dnl +dnl This program is distributed in the hope that it will be useful, but +dnl WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +dnl General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with this program; if not, write to the Free Software +dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +dnl 02111-1307, USA. +dnl +dnl As a special exception to the GNU General Public License, if you +dnl distribute this file as part of a program that contains a +dnl configuration script generated by Autoconf, you may include it under +dnl the same distribution terms that you use for the rest of that +dnl program. + +dnl PKG_PREREQ(MIN-VERSION) +dnl ----------------------- +dnl Since: 0.29 +dnl +dnl Verify that the version of the pkg-config macros are at least +dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's +dnl installed version of pkg-config, this checks the developer's version +dnl of pkg.m4 when generating configure. +dnl +dnl To ensure that this macro is defined, also add: +dnl m4_ifndef([PKG_PREREQ], +dnl [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])]) +dnl +dnl See the "Since" comment for each macro you use to see what version +dnl of the macros you require. +m4_defun([PKG_PREREQ], +[m4_define([PKG_MACROS_VERSION], [0.29]) +m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1, + [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])]) +])dnl PKG_PREREQ + +dnl PKG_PROG_PKG_CONFIG([MIN-VERSION]) +dnl ---------------------------------- +dnl Since: 0.16 +dnl +dnl Search for the pkg-config tool and set the PKG_CONFIG variable to +dnl first found in the path. Checks that the version of pkg-config found +dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is +dnl used since that's the first version where most current features of +dnl pkg-config existed. +AC_DEFUN([PKG_PROG_PKG_CONFIG], +[m4_pattern_forbid([^_?PKG_[A-Z_]+$]) +m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) +m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$]) +AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility]) +AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path]) +AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path]) + +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=m4_default([$1], [0.9.0]) + AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + PKG_CONFIG="" + fi +fi[]dnl +])dnl PKG_PROG_PKG_CONFIG + +dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +dnl ------------------------------------------------------------------- +dnl Since: 0.18 +dnl +dnl Check to see whether a particular set of modules exists. Similar to +dnl PKG_CHECK_MODULES(), but does not set variables or print errors. +dnl +dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +dnl only at the first occurence in configure.ac, so if the first place +dnl it's called might be skipped (such as if it is within an "if", you +dnl have to call PKG_CHECK_EXISTS manually +AC_DEFUN([PKG_CHECK_EXISTS], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +if test -n "$PKG_CONFIG" && \ + AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then + m4_default([$2], [:]) +m4_ifvaln([$3], [else + $3])dnl +fi]) + +dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) +dnl --------------------------------------------- +dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting +dnl pkg_failed based on the result. +m4_define([_PKG_CONFIG], +[if test -n "$$1"; then + pkg_cv_[]$1="$$1" + elif test -n "$PKG_CONFIG"; then + PKG_CHECK_EXISTS([$3], + [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes ], + [pkg_failed=yes]) + else + pkg_failed=untried +fi[]dnl +])dnl _PKG_CONFIG + +dnl _PKG_SHORT_ERRORS_SUPPORTED +dnl --------------------------- +dnl Internal check to see if pkg-config supports short errors. +AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi[]dnl +])dnl _PKG_SHORT_ERRORS_SUPPORTED + + +dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +dnl [ACTION-IF-NOT-FOUND]) +dnl -------------------------------------------------------------- +dnl Since: 0.4.0 +dnl +dnl Note that if there is a possibility the first call to +dnl PKG_CHECK_MODULES might not happen, you should be sure to include an +dnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac +AC_DEFUN([PKG_CHECK_MODULES], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl +AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl + +pkg_failed=no +AC_MSG_CHECKING([for $1]) + +_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) +_PKG_CONFIG([$1][_LIBS], [libs], [$2]) + +m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS +and $1[]_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details.]) + +if test $pkg_failed = yes; then + AC_MSG_RESULT([no]) + _PKG_SHORT_ERRORS_SUPPORTED + if test $_pkg_short_errors_supported = yes; then + $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1` + else + $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD + + m4_default([$4], [AC_MSG_ERROR( +[Package requirements ($2) were not met: + +$$1_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +_PKG_TEXT])[]dnl + ]) +elif test $pkg_failed = untried; then + AC_MSG_RESULT([no]) + m4_default([$4], [AC_MSG_FAILURE( +[The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +_PKG_TEXT + +To get pkg-config, see .])[]dnl + ]) +else + $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS + $1[]_LIBS=$pkg_cv_[]$1[]_LIBS + AC_MSG_RESULT([yes]) + $3 +fi[]dnl +])dnl PKG_CHECK_MODULES + + +dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +dnl [ACTION-IF-NOT-FOUND]) +dnl --------------------------------------------------------------------- +dnl Since: 0.29 +dnl +dnl Checks for existence of MODULES and gathers its build flags with +dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags +dnl and VARIABLE-PREFIX_LIBS from --libs. +dnl +dnl Note that if there is a possibility the first call to +dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to +dnl include an explicit call to PKG_PROG_PKG_CONFIG in your +dnl configure.ac. +AC_DEFUN([PKG_CHECK_MODULES_STATIC], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +_save_PKG_CONFIG=$PKG_CONFIG +PKG_CONFIG="$PKG_CONFIG --static" +PKG_CHECK_MODULES($@) +PKG_CONFIG=$_save_PKG_CONFIG[]dnl +])dnl PKG_CHECK_MODULES_STATIC + + +dnl PKG_INSTALLDIR([DIRECTORY]) +dnl ------------------------- +dnl Since: 0.27 +dnl +dnl Substitutes the variable pkgconfigdir as the location where a module +dnl should install pkg-config .pc files. By default the directory is +dnl $libdir/pkgconfig, but the default can be changed by passing +dnl DIRECTORY. The user can override through the --with-pkgconfigdir +dnl parameter. +AC_DEFUN([PKG_INSTALLDIR], +[m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])]) +m4_pushdef([pkg_description], + [pkg-config installation directory @<:@]pkg_default[@:>@]) +AC_ARG_WITH([pkgconfigdir], + [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],, + [with_pkgconfigdir=]pkg_default) +AC_SUBST([pkgconfigdir], [$with_pkgconfigdir]) +m4_popdef([pkg_default]) +m4_popdef([pkg_description]) +])dnl PKG_INSTALLDIR + + +dnl PKG_NOARCH_INSTALLDIR([DIRECTORY]) +dnl -------------------------------- +dnl Since: 0.27 +dnl +dnl Substitutes the variable noarch_pkgconfigdir as the location where a +dnl module should install arch-independent pkg-config .pc files. By +dnl default the directory is $datadir/pkgconfig, but the default can be +dnl changed by passing DIRECTORY. The user can override through the +dnl --with-noarch-pkgconfigdir parameter. +AC_DEFUN([PKG_NOARCH_INSTALLDIR], +[m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])]) +m4_pushdef([pkg_description], + [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@]) +AC_ARG_WITH([noarch-pkgconfigdir], + [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],, + [with_noarch_pkgconfigdir=]pkg_default) +AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir]) +m4_popdef([pkg_default]) +m4_popdef([pkg_description]) +])dnl PKG_NOARCH_INSTALLDIR + + +dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, +dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +dnl ------------------------------------------- +dnl Since: 0.28 +dnl +dnl Retrieves the value of the pkg-config variable for the given module. +AC_DEFUN([PKG_CHECK_VAR], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl + +_PKG_CONFIG([$1], [variable="][$3]["], [$2]) +AS_VAR_COPY([$1], [pkg_cv_][$1]) + +AS_VAR_IF([$1], [""], [$5], [$4])dnl +])dnl PKG_CHECK_VAR diff --git a/m4/po.m4 b/m4/po.m4 new file mode 100644 index 00000000..c5a2f6bf --- /dev/null +++ b/m4/po.m4 @@ -0,0 +1,453 @@ +# po.m4 serial 24 (gettext-0.19) +dnl Copyright (C) 1995-2014, 2016 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl +dnl This file can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Authors: +dnl Ulrich Drepper , 1995-2000. +dnl Bruno Haible , 2000-2003. + +AC_PREREQ([2.60]) + +dnl Checks for all prerequisites of the po subdirectory. +AC_DEFUN([AM_PO_SUBDIRS], +[ + AC_REQUIRE([AC_PROG_MAKE_SET])dnl + AC_REQUIRE([AC_PROG_INSTALL])dnl + AC_REQUIRE([AC_PROG_MKDIR_P])dnl + AC_REQUIRE([AC_PROG_SED])dnl + AC_REQUIRE([AM_NLS])dnl + + dnl Release version of the gettext macros. This is used to ensure that + dnl the gettext macros and po/Makefile.in.in are in sync. + AC_SUBST([GETTEXT_MACRO_VERSION], [0.19]) + + dnl Perform the following tests also if --disable-nls has been given, + dnl because they are needed for "make dist" to work. + + dnl Search for GNU msgfmt in the PATH. + dnl The first test excludes Solaris msgfmt and early GNU msgfmt versions. + dnl The second test excludes FreeBSD msgfmt. + AM_PATH_PROG_WITH_TEST(MSGFMT, msgfmt, + [$ac_dir/$ac_word --statistics /dev/null >&]AS_MESSAGE_LOG_FD[ 2>&1 && + (if $ac_dir/$ac_word --statistics /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi)], + :) + AC_PATH_PROG([GMSGFMT], [gmsgfmt], [$MSGFMT]) + + dnl Test whether it is GNU msgfmt >= 0.15. +changequote(,)dnl + case `$MSGFMT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) MSGFMT_015=: ;; + *) MSGFMT_015=$MSGFMT ;; + esac +changequote([,])dnl + AC_SUBST([MSGFMT_015]) +changequote(,)dnl + case `$GMSGFMT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) GMSGFMT_015=: ;; + *) GMSGFMT_015=$GMSGFMT ;; + esac +changequote([,])dnl + AC_SUBST([GMSGFMT_015]) + + dnl Search for GNU xgettext 0.12 or newer in the PATH. + dnl The first test excludes Solaris xgettext and early GNU xgettext versions. + dnl The second test excludes FreeBSD xgettext. + AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext, + [$ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null >&]AS_MESSAGE_LOG_FD[ 2>&1 && + (if $ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi)], + :) + dnl Remove leftover from FreeBSD xgettext call. + rm -f messages.po + + dnl Test whether it is GNU xgettext >= 0.15. +changequote(,)dnl + case `$XGETTEXT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) XGETTEXT_015=: ;; + *) XGETTEXT_015=$XGETTEXT ;; + esac +changequote([,])dnl + AC_SUBST([XGETTEXT_015]) + + dnl Search for GNU msgmerge 0.11 or newer in the PATH. + AM_PATH_PROG_WITH_TEST(MSGMERGE, msgmerge, + [$ac_dir/$ac_word --update -q /dev/null /dev/null >&]AS_MESSAGE_LOG_FD[ 2>&1], :) + + dnl Installation directories. + dnl Autoconf >= 2.60 defines localedir. For older versions of autoconf, we + dnl have to define it here, so that it can be used in po/Makefile. + test -n "$localedir" || localedir='${datadir}/locale' + AC_SUBST([localedir]) + + dnl Support for AM_XGETTEXT_OPTION. + test -n "${XGETTEXT_EXTRA_OPTIONS+set}" || XGETTEXT_EXTRA_OPTIONS= + AC_SUBST([XGETTEXT_EXTRA_OPTIONS]) + + AC_CONFIG_COMMANDS([po-directories], [[ + for ac_file in $CONFIG_FILES; do + # Support "outfile[:infile[:infile...]]" + case "$ac_file" in + *:*) ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + esac + # PO directories have a Makefile.in generated from Makefile.in.in. + case "$ac_file" in */Makefile.in) + # Adjust a relative srcdir. + ac_dir=`echo "$ac_file"|sed 's%/[^/][^/]*$%%'` + ac_dir_suffix=/`echo "$ac_dir"|sed 's%^\./%%'` + ac_dots=`echo "$ac_dir_suffix"|sed 's%/[^/]*%../%g'` + # In autoconf-2.13 it is called $ac_given_srcdir. + # In autoconf-2.50 it is called $srcdir. + test -n "$ac_given_srcdir" || ac_given_srcdir="$srcdir" + case "$ac_given_srcdir" in + .) top_srcdir=`echo $ac_dots|sed 's%/$%%'` ;; + /*) top_srcdir="$ac_given_srcdir" ;; + *) top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + # Treat a directory as a PO directory if and only if it has a + # POTFILES.in file. This allows packages to have multiple PO + # directories under different names or in different locations. + if test -f "$ac_given_srcdir/$ac_dir/POTFILES.in"; then + rm -f "$ac_dir/POTFILES" + test -n "$as_me" && echo "$as_me: creating $ac_dir/POTFILES" || echo "creating $ac_dir/POTFILES" + gt_tab=`printf '\t'` + cat "$ac_given_srcdir/$ac_dir/POTFILES.in" | sed -e "/^#/d" -e "/^[ ${gt_tab}]*\$/d" -e "s,.*, $top_srcdir/& \\\\," | sed -e "\$s/\(.*\) \\\\/\1/" > "$ac_dir/POTFILES" + POMAKEFILEDEPS="POTFILES.in" + # ALL_LINGUAS, POFILES, UPDATEPOFILES, DUMMYPOFILES, GMOFILES depend + # on $ac_dir but don't depend on user-specified configuration + # parameters. + if test -f "$ac_given_srcdir/$ac_dir/LINGUAS"; then + # The LINGUAS file contains the set of available languages. + if test -n "$OBSOLETE_ALL_LINGUAS"; then + test -n "$as_me" && echo "$as_me: setting ALL_LINGUAS in configure.in is obsolete" || echo "setting ALL_LINGUAS in configure.in is obsolete" + fi + ALL_LINGUAS_=`sed -e "/^#/d" -e "s/#.*//" "$ac_given_srcdir/$ac_dir/LINGUAS"` + # Hide the ALL_LINGUAS assignment from automake < 1.5. + eval 'ALL_LINGUAS''=$ALL_LINGUAS_' + POMAKEFILEDEPS="$POMAKEFILEDEPS LINGUAS" + else + # The set of available languages was given in configure.in. + # Hide the ALL_LINGUAS assignment from automake < 1.5. + eval 'ALL_LINGUAS''=$OBSOLETE_ALL_LINGUAS' + fi + # Compute POFILES + # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).po) + # Compute UPDATEPOFILES + # as $(foreach lang, $(ALL_LINGUAS), $(lang).po-update) + # Compute DUMMYPOFILES + # as $(foreach lang, $(ALL_LINGUAS), $(lang).nop) + # Compute GMOFILES + # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).gmo) + case "$ac_given_srcdir" in + .) srcdirpre= ;; + *) srcdirpre='$(srcdir)/' ;; + esac + POFILES= + UPDATEPOFILES= + DUMMYPOFILES= + GMOFILES= + for lang in $ALL_LINGUAS; do + POFILES="$POFILES $srcdirpre$lang.po" + UPDATEPOFILES="$UPDATEPOFILES $lang.po-update" + DUMMYPOFILES="$DUMMYPOFILES $lang.nop" + GMOFILES="$GMOFILES $srcdirpre$lang.gmo" + done + # CATALOGS depends on both $ac_dir and the user's LINGUAS + # environment variable. + INST_LINGUAS= + if test -n "$ALL_LINGUAS"; then + for presentlang in $ALL_LINGUAS; do + useit=no + if test "%UNSET%" != "$LINGUAS"; then + desiredlanguages="$LINGUAS" + else + desiredlanguages="$ALL_LINGUAS" + fi + for desiredlang in $desiredlanguages; do + # Use the presentlang catalog if desiredlang is + # a. equal to presentlang, or + # b. a variant of presentlang (because in this case, + # presentlang can be used as a fallback for messages + # which are not translated in the desiredlang catalog). + case "$desiredlang" in + "$presentlang"*) useit=yes;; + esac + done + if test $useit = yes; then + INST_LINGUAS="$INST_LINGUAS $presentlang" + fi + done + fi + CATALOGS= + if test -n "$INST_LINGUAS"; then + for lang in $INST_LINGUAS; do + CATALOGS="$CATALOGS $lang.gmo" + done + fi + test -n "$as_me" && echo "$as_me: creating $ac_dir/Makefile" || echo "creating $ac_dir/Makefile" + sed -e "/^POTFILES =/r $ac_dir/POTFILES" -e "/^# Makevars/r $ac_given_srcdir/$ac_dir/Makevars" -e "s|@POFILES@|$POFILES|g" -e "s|@UPDATEPOFILES@|$UPDATEPOFILES|g" -e "s|@DUMMYPOFILES@|$DUMMYPOFILES|g" -e "s|@GMOFILES@|$GMOFILES|g" -e "s|@CATALOGS@|$CATALOGS|g" -e "s|@POMAKEFILEDEPS@|$POMAKEFILEDEPS|g" "$ac_dir/Makefile.in" > "$ac_dir/Makefile" + for f in "$ac_given_srcdir/$ac_dir"/Rules-*; do + if test -f "$f"; then + case "$f" in + *.orig | *.bak | *~) ;; + *) cat "$f" >> "$ac_dir/Makefile" ;; + esac + fi + done + fi + ;; + esac + done]], + [# Capture the value of obsolete ALL_LINGUAS because we need it to compute + # POFILES, UPDATEPOFILES, DUMMYPOFILES, GMOFILES, CATALOGS. But hide it + # from automake < 1.5. + eval 'OBSOLETE_ALL_LINGUAS''="$ALL_LINGUAS"' + # Capture the value of LINGUAS because we need it to compute CATALOGS. + LINGUAS="${LINGUAS-%UNSET%}" + ]) +]) + +dnl Postprocesses a Makefile in a directory containing PO files. +AC_DEFUN([AM_POSTPROCESS_PO_MAKEFILE], +[ + # When this code is run, in config.status, two variables have already been + # set: + # - OBSOLETE_ALL_LINGUAS is the value of LINGUAS set in configure.in, + # - LINGUAS is the value of the environment variable LINGUAS at configure + # time. + +changequote(,)dnl + # Adjust a relative srcdir. + ac_dir=`echo "$ac_file"|sed 's%/[^/][^/]*$%%'` + ac_dir_suffix=/`echo "$ac_dir"|sed 's%^\./%%'` + ac_dots=`echo "$ac_dir_suffix"|sed 's%/[^/]*%../%g'` + # In autoconf-2.13 it is called $ac_given_srcdir. + # In autoconf-2.50 it is called $srcdir. + test -n "$ac_given_srcdir" || ac_given_srcdir="$srcdir" + case "$ac_given_srcdir" in + .) top_srcdir=`echo $ac_dots|sed 's%/$%%'` ;; + /*) top_srcdir="$ac_given_srcdir" ;; + *) top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + + # Find a way to echo strings without interpreting backslash. + if test "X`(echo '\t') 2>/dev/null`" = 'X\t'; then + gt_echo='echo' + else + if test "X`(printf '%s\n' '\t') 2>/dev/null`" = 'X\t'; then + gt_echo='printf %s\n' + else + echo_func () { + cat < "$ac_file.tmp" + tab=`printf '\t'` + if grep -l '@TCLCATALOGS@' "$ac_file" > /dev/null; then + # Add dependencies that cannot be formulated as a simple suffix rule. + for lang in $ALL_LINGUAS; do + frobbedlang=`echo $lang | sed -e 's/\..*$//' -e 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/'` + cat >> "$ac_file.tmp" < /dev/null; then + # Add dependencies that cannot be formulated as a simple suffix rule. + for lang in $ALL_LINGUAS; do + frobbedlang=`echo $lang | sed -e 's/_/-/g' -e 's/^sr-CS/sr-SP/' -e 's/@latin$/-Latn/' -e 's/@cyrillic$/-Cyrl/' -e 's/^sr-SP$/sr-SP-Latn/' -e 's/^uz-UZ$/uz-UZ-Latn/'` + cat >> "$ac_file.tmp" <> "$ac_file.tmp" < +#include +/* The string "%2$d %1$d", with dollar characters protected from the shell's + dollar expansion (possibly an autoconf bug). */ +static char format[] = { '%', '2', '$', 'd', ' ', '%', '1', '$', 'd', '\0' }; +static char buf[100]; +int main () +{ + sprintf (buf, format, 33, 55); + return (strcmp (buf, "55 33") != 0); +}], gt_cv_func_printf_posix=yes, gt_cv_func_printf_posix=no, + [ + AC_EGREP_CPP([notposix], [ +#if defined __NetBSD__ || defined __BEOS__ || defined _MSC_VER || defined __MINGW32__ || defined __CYGWIN__ + notposix +#endif + ], + [gt_cv_func_printf_posix="guessing no"], + [gt_cv_func_printf_posix="guessing yes"]) + ]) + ]) + case $gt_cv_func_printf_posix in + *yes) + AC_DEFINE([HAVE_POSIX_PRINTF], [1], + [Define if your printf() function supports format strings with positions.]) + ;; + esac +]) diff --git a/m4/progtest.m4 b/m4/progtest.m4 new file mode 100644 index 00000000..9ace7c34 --- /dev/null +++ b/m4/progtest.m4 @@ -0,0 +1,91 @@ +# progtest.m4 serial 7 (gettext-0.18.2) +dnl Copyright (C) 1996-2003, 2005, 2008-2016 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl +dnl This file can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Authors: +dnl Ulrich Drepper , 1996. + +AC_PREREQ([2.50]) + +# Search path for a program which passes the given test. + +dnl AM_PATH_PROG_WITH_TEST(VARIABLE, PROG-TO-CHECK-FOR, +dnl TEST-PERFORMED-ON-FOUND_PROGRAM [, VALUE-IF-NOT-FOUND [, PATH]]) +AC_DEFUN([AM_PATH_PROG_WITH_TEST], +[ +# Prepare PATH_SEPARATOR. +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + # Determine PATH_SEPARATOR by trying to find /bin/sh in a PATH which + # contains only /bin. Note that ksh looks also at the FPATH variable, + # so we have to set that as well for the test. + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 \ + && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 \ + || PATH_SEPARATOR=';' + } +fi + +# Find out how to test for executable files. Don't use a zero-byte file, +# as systems may use methods other than mode bits to determine executability. +cat >conf$$.file <<_ASEOF +#! /bin/sh +exit 0 +_ASEOF +chmod +x conf$$.file +if test -x conf$$.file >/dev/null 2>&1; then + ac_executable_p="test -x" +else + ac_executable_p="test -f" +fi +rm -f conf$$.file + +# Extract the first word of "$2", so it can be a program name with args. +set dummy $2; ac_word=[$]2 +AC_MSG_CHECKING([for $ac_word]) +AC_CACHE_VAL([ac_cv_path_$1], +[case "[$]$1" in + [[\\/]]* | ?:[[\\/]]*) + ac_cv_path_$1="[$]$1" # Let the user override the test with a path. + ;; + *) + ac_save_IFS="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in ifelse([$5], , $PATH, [$5]); do + IFS="$ac_save_IFS" + test -z "$ac_dir" && ac_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $ac_executable_p "$ac_dir/$ac_word$ac_exec_ext"; then + echo "$as_me: trying $ac_dir/$ac_word..." >&AS_MESSAGE_LOG_FD + if [$3]; then + ac_cv_path_$1="$ac_dir/$ac_word$ac_exec_ext" + break 2 + fi + fi + done + done + IFS="$ac_save_IFS" +dnl If no 4th arg is given, leave the cache variable unset, +dnl so AC_PATH_PROGS will keep looking. +ifelse([$4], , , [ test -z "[$]ac_cv_path_$1" && ac_cv_path_$1="$4" +])dnl + ;; +esac])dnl +$1="$ac_cv_path_$1" +if test ifelse([$4], , [-n "[$]$1"], ["[$]$1" != "$4"]); then + AC_MSG_RESULT([$][$1]) +else + AC_MSG_RESULT([no]) +fi +AC_SUBST([$1])dnl +]) diff --git a/m4/size_max.m4 b/m4/size_max.m4 new file mode 100644 index 00000000..ce992db1 --- /dev/null +++ b/m4/size_max.m4 @@ -0,0 +1,75 @@ +# size_max.m4 serial 9 +dnl Copyright (C) 2003, 2005-2006, 2008-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +AC_DEFUN([gl_SIZE_MAX], +[ + AC_CHECK_HEADERS([stdint.h]) + dnl First test whether the system already has SIZE_MAX. + AC_CACHE_CHECK([for SIZE_MAX], [gl_cv_size_max], [ + gl_cv_size_max= + AC_EGREP_CPP([Found it], [ +#include +#if HAVE_STDINT_H +#include +#endif +#ifdef SIZE_MAX +Found it +#endif +], [gl_cv_size_max=yes]) + if test -z "$gl_cv_size_max"; then + dnl Define it ourselves. Here we assume that the type 'size_t' is not wider + dnl than the type 'unsigned long'. Try hard to find a definition that can + dnl be used in a preprocessor #if, i.e. doesn't contain a cast. + AC_COMPUTE_INT([size_t_bits_minus_1], [sizeof (size_t) * CHAR_BIT - 1], + [#include +#include ], [size_t_bits_minus_1=]) + AC_COMPUTE_INT([fits_in_uint], [sizeof (size_t) <= sizeof (unsigned int)], + [#include ], [fits_in_uint=]) + if test -n "$size_t_bits_minus_1" && test -n "$fits_in_uint"; then + if test $fits_in_uint = 1; then + dnl Even though SIZE_MAX fits in an unsigned int, it must be of type + dnl 'unsigned long' if the type 'size_t' is the same as 'unsigned long'. + AC_TRY_COMPILE([#include + extern size_t foo; + extern unsigned long foo; + ], [], [fits_in_uint=0]) + fi + dnl We cannot use 'expr' to simplify this expression, because 'expr' + dnl works only with 'long' integers in the host environment, while we + dnl might be cross-compiling from a 32-bit platform to a 64-bit platform. + if test $fits_in_uint = 1; then + gl_cv_size_max="(((1U << $size_t_bits_minus_1) - 1) * 2 + 1)" + else + gl_cv_size_max="(((1UL << $size_t_bits_minus_1) - 1) * 2 + 1)" + fi + else + dnl Shouldn't happen, but who knows... + gl_cv_size_max='((size_t)~(size_t)0)' + fi + fi + ]) + if test "$gl_cv_size_max" != yes; then + AC_DEFINE_UNQUOTED([SIZE_MAX], [$gl_cv_size_max], + [Define as the maximum value of type 'size_t', if the system doesn't define it.]) + fi + dnl Don't redefine SIZE_MAX in config.h if config.h is re-included after + dnl . Remember that the #undef in AH_VERBATIM gets replaced with + dnl #define by AC_DEFINE_UNQUOTED. + AH_VERBATIM([SIZE_MAX], +[/* Define as the maximum value of type 'size_t', if the system doesn't define + it. */ +#ifndef SIZE_MAX +# undef SIZE_MAX +#endif]) +]) + +dnl Autoconf >= 2.61 has AC_COMPUTE_INT built-in. +dnl Remove this when we can assume autoconf >= 2.61. +m4_ifdef([AC_COMPUTE_INT], [], [ + AC_DEFUN([AC_COMPUTE_INT], [_AC_COMPUTE_INT([$2],[$1],[$3],[$4])]) +]) diff --git a/m4/stdint_h.m4 b/m4/stdint_h.m4 new file mode 100644 index 00000000..b8e3c6cc --- /dev/null +++ b/m4/stdint_h.m4 @@ -0,0 +1,26 @@ +# stdint_h.m4 serial 8 +dnl Copyright (C) 1997-2004, 2006, 2008-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Paul Eggert. + +# Define HAVE_STDINT_H_WITH_UINTMAX if exists, +# doesn't clash with , and declares uintmax_t. + +AC_DEFUN([gl_AC_HEADER_STDINT_H], +[ + AC_CACHE_CHECK([for stdint.h], [gl_cv_header_stdint_h], + [AC_TRY_COMPILE( + [#include +#include ], + [uintmax_t i = (uintmax_t) -1; return !i;], + [gl_cv_header_stdint_h=yes], + [gl_cv_header_stdint_h=no])]) + if test $gl_cv_header_stdint_h = yes; then + AC_DEFINE_UNQUOTED([HAVE_STDINT_H_WITH_UINTMAX], [1], + [Define if exists, doesn't clash with , + and declares uintmax_t. ]) + fi +]) diff --git a/m4/threadlib.m4 b/m4/threadlib.m4 new file mode 100644 index 00000000..05cc4ffa --- /dev/null +++ b/m4/threadlib.m4 @@ -0,0 +1,347 @@ +# threadlib.m4 serial 5 (gettext-0.18) +dnl Copyright (C) 2005-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +dnl gl_THREADLIB +dnl ------------ +dnl Tests for a multithreading library to be used. +dnl Defines at most one of the macros USE_POSIX_THREADS, USE_SOLARIS_THREADS, +dnl USE_PTH_THREADS, USE_WIN32_THREADS +dnl Sets the variables LIBTHREAD and LTLIBTHREAD to the linker options for use +dnl in a Makefile (LIBTHREAD for use without libtool, LTLIBTHREAD for use with +dnl libtool). +dnl Sets the variables LIBMULTITHREAD and LTLIBMULTITHREAD similarly, for +dnl programs that really need multithread functionality. The difference +dnl between LIBTHREAD and LIBMULTITHREAD is that on platforms supporting weak +dnl symbols, typically LIBTHREAD="" whereas LIBMULTITHREAD="-lpthread". +dnl Adds to CPPFLAGS the flag -D_REENTRANT or -D_THREAD_SAFE if needed for +dnl multithread-safe programs. + +AC_DEFUN([gl_THREADLIB_EARLY], +[ + AC_REQUIRE([gl_THREADLIB_EARLY_BODY]) +]) + +dnl The guts of gl_THREADLIB_EARLY. Needs to be expanded only once. + +AC_DEFUN([gl_THREADLIB_EARLY_BODY], +[ + dnl Ordering constraints: This macro modifies CPPFLAGS in a way that + dnl influences the result of the autoconf tests that test for *_unlocked + dnl declarations, on AIX 5 at least. Therefore it must come early. + AC_BEFORE([$0], [gl_FUNC_GLIBC_UNLOCKED_IO])dnl + AC_BEFORE([$0], [gl_ARGP])dnl + + AC_REQUIRE([AC_CANONICAL_HOST]) + dnl _GNU_SOURCE is needed for pthread_rwlock_t on glibc systems. + dnl AC_USE_SYSTEM_EXTENSIONS was introduced in autoconf 2.60 and obsoletes + dnl AC_GNU_SOURCE. + m4_ifdef([AC_USE_SYSTEM_EXTENSIONS], + [AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS])], + [AC_REQUIRE([AC_GNU_SOURCE])]) + dnl Check for multithreading. + m4_divert_text([DEFAULTS], [gl_use_threads_default=]) + AC_ARG_ENABLE([threads], +AC_HELP_STRING([--enable-threads={posix|solaris|pth|win32}], [specify multithreading API]) +AC_HELP_STRING([--disable-threads], [build without multithread safety]), + [gl_use_threads=$enableval], + [if test -n "$gl_use_threads_default"; then + gl_use_threads="$gl_use_threads_default" + else +changequote(,)dnl + case "$host_os" in + dnl Disable multithreading by default on OSF/1, because it interferes + dnl with fork()/exec(): When msgexec is linked with -lpthread, its + dnl child process gets an endless segmentation fault inside execvp(). + dnl Disable multithreading by default on Cygwin 1.5.x, because it has + dnl bugs that lead to endless loops or crashes. See + dnl . + osf*) gl_use_threads=no ;; + cygwin*) + case `uname -r` in + 1.[0-5].*) gl_use_threads=no ;; + *) gl_use_threads=yes ;; + esac + ;; + *) gl_use_threads=yes ;; + esac +changequote([,])dnl + fi + ]) + if test "$gl_use_threads" = yes || test "$gl_use_threads" = posix; then + # For using : + case "$host_os" in + osf*) + # On OSF/1, the compiler needs the flag -D_REENTRANT so that it + # groks . cc also understands the flag -pthread, but + # we don't use it because 1. gcc-2.95 doesn't understand -pthread, + # 2. putting a flag into CPPFLAGS that has an effect on the linker + # causes the AC_TRY_LINK test below to succeed unexpectedly, + # leading to wrong values of LIBTHREAD and LTLIBTHREAD. + CPPFLAGS="$CPPFLAGS -D_REENTRANT" + ;; + esac + # Some systems optimize for single-threaded programs by default, and + # need special flags to disable these optimizations. For example, the + # definition of 'errno' in . + case "$host_os" in + aix* | freebsd*) CPPFLAGS="$CPPFLAGS -D_THREAD_SAFE" ;; + solaris*) CPPFLAGS="$CPPFLAGS -D_REENTRANT" ;; + esac + fi +]) + +dnl The guts of gl_THREADLIB. Needs to be expanded only once. + +AC_DEFUN([gl_THREADLIB_BODY], +[ + AC_REQUIRE([gl_THREADLIB_EARLY_BODY]) + gl_threads_api=none + LIBTHREAD= + LTLIBTHREAD= + LIBMULTITHREAD= + LTLIBMULTITHREAD= + if test "$gl_use_threads" != no; then + dnl Check whether the compiler and linker support weak declarations. + AC_CACHE_CHECK([whether imported symbols can be declared weak], + [gl_cv_have_weak], + [gl_cv_have_weak=no + dnl First, test whether the compiler accepts it syntactically. + AC_TRY_LINK([extern void xyzzy (); +#pragma weak xyzzy], [xyzzy();], [gl_cv_have_weak=maybe]) + if test $gl_cv_have_weak = maybe; then + dnl Second, test whether it actually works. On Cygwin 1.7.2, with + dnl gcc 4.3, symbols declared weak always evaluate to the address 0. + AC_TRY_RUN([ +#include +#pragma weak fputs +int main () +{ + return (fputs == NULL); +}], [gl_cv_have_weak=yes], [gl_cv_have_weak=no], + [dnl When cross-compiling, assume that only ELF platforms support + dnl weak symbols. + AC_EGREP_CPP([Extensible Linking Format], + [#ifdef __ELF__ + Extensible Linking Format + #endif + ], + [gl_cv_have_weak="guessing yes"], + [gl_cv_have_weak="guessing no"]) + ]) + fi + ]) + if test "$gl_use_threads" = yes || test "$gl_use_threads" = posix; then + # On OSF/1, the compiler needs the flag -pthread or -D_REENTRANT so that + # it groks . It's added above, in gl_THREADLIB_EARLY_BODY. + AC_CHECK_HEADER([pthread.h], + [gl_have_pthread_h=yes], [gl_have_pthread_h=no]) + if test "$gl_have_pthread_h" = yes; then + # Other possible tests: + # -lpthreads (FSU threads, PCthreads) + # -lgthreads + gl_have_pthread= + # Test whether both pthread_mutex_lock and pthread_mutexattr_init exist + # in libc. IRIX 6.5 has the first one in both libc and libpthread, but + # the second one only in libpthread, and lock.c needs it. + AC_TRY_LINK([#include ], + [pthread_mutex_lock((pthread_mutex_t*)0); + pthread_mutexattr_init((pthread_mutexattr_t*)0);], + [gl_have_pthread=yes]) + # Test for libpthread by looking for pthread_kill. (Not pthread_self, + # since it is defined as a macro on OSF/1.) + if test -n "$gl_have_pthread"; then + # The program links fine without libpthread. But it may actually + # need to link with libpthread in order to create multiple threads. + AC_CHECK_LIB([pthread], [pthread_kill], + [LIBMULTITHREAD=-lpthread LTLIBMULTITHREAD=-lpthread + # On Solaris and HP-UX, most pthread functions exist also in libc. + # Therefore pthread_in_use() needs to actually try to create a + # thread: pthread_create from libc will fail, whereas + # pthread_create will actually create a thread. + case "$host_os" in + solaris* | hpux*) + AC_DEFINE([PTHREAD_IN_USE_DETECTION_HARD], [1], + [Define if the pthread_in_use() detection is hard.]) + esac + ]) + else + # Some library is needed. Try libpthread and libc_r. + AC_CHECK_LIB([pthread], [pthread_kill], + [gl_have_pthread=yes + LIBTHREAD=-lpthread LTLIBTHREAD=-lpthread + LIBMULTITHREAD=-lpthread LTLIBMULTITHREAD=-lpthread]) + if test -z "$gl_have_pthread"; then + # For FreeBSD 4. + AC_CHECK_LIB([c_r], [pthread_kill], + [gl_have_pthread=yes + LIBTHREAD=-lc_r LTLIBTHREAD=-lc_r + LIBMULTITHREAD=-lc_r LTLIBMULTITHREAD=-lc_r]) + fi + fi + if test -n "$gl_have_pthread"; then + gl_threads_api=posix + AC_DEFINE([USE_POSIX_THREADS], [1], + [Define if the POSIX multithreading library can be used.]) + if test -n "$LIBMULTITHREAD" || test -n "$LTLIBMULTITHREAD"; then + if case "$gl_cv_have_weak" in *yes) true;; *) false;; esac; then + AC_DEFINE([USE_POSIX_THREADS_WEAK], [1], + [Define if references to the POSIX multithreading library should be made weak.]) + LIBTHREAD= + LTLIBTHREAD= + fi + fi + fi + fi + fi + if test -z "$gl_have_pthread"; then + if test "$gl_use_threads" = yes || test "$gl_use_threads" = solaris; then + gl_have_solaristhread= + gl_save_LIBS="$LIBS" + LIBS="$LIBS -lthread" + AC_TRY_LINK([#include +#include ], + [thr_self();], + [gl_have_solaristhread=yes]) + LIBS="$gl_save_LIBS" + if test -n "$gl_have_solaristhread"; then + gl_threads_api=solaris + LIBTHREAD=-lthread + LTLIBTHREAD=-lthread + LIBMULTITHREAD="$LIBTHREAD" + LTLIBMULTITHREAD="$LTLIBTHREAD" + AC_DEFINE([USE_SOLARIS_THREADS], [1], + [Define if the old Solaris multithreading library can be used.]) + if case "$gl_cv_have_weak" in *yes) true;; *) false;; esac; then + AC_DEFINE([USE_SOLARIS_THREADS_WEAK], [1], + [Define if references to the old Solaris multithreading library should be made weak.]) + LIBTHREAD= + LTLIBTHREAD= + fi + fi + fi + fi + if test "$gl_use_threads" = pth; then + gl_save_CPPFLAGS="$CPPFLAGS" + AC_LIB_LINKFLAGS([pth]) + gl_have_pth= + gl_save_LIBS="$LIBS" + LIBS="$LIBS -lpth" + AC_TRY_LINK([#include ], [pth_self();], [gl_have_pth=yes]) + LIBS="$gl_save_LIBS" + if test -n "$gl_have_pth"; then + gl_threads_api=pth + LIBTHREAD="$LIBPTH" + LTLIBTHREAD="$LTLIBPTH" + LIBMULTITHREAD="$LIBTHREAD" + LTLIBMULTITHREAD="$LTLIBTHREAD" + AC_DEFINE([USE_PTH_THREADS], [1], + [Define if the GNU Pth multithreading library can be used.]) + if test -n "$LIBMULTITHREAD" || test -n "$LTLIBMULTITHREAD"; then + if case "$gl_cv_have_weak" in *yes) true;; *) false;; esac; then + AC_DEFINE([USE_PTH_THREADS_WEAK], [1], + [Define if references to the GNU Pth multithreading library should be made weak.]) + LIBTHREAD= + LTLIBTHREAD= + fi + fi + else + CPPFLAGS="$gl_save_CPPFLAGS" + fi + fi + if test -z "$gl_have_pthread"; then + if test "$gl_use_threads" = yes || test "$gl_use_threads" = win32; then + if { case "$host_os" in + mingw*) true;; + *) false;; + esac + }; then + gl_threads_api=win32 + AC_DEFINE([USE_WIN32_THREADS], [1], + [Define if the Win32 multithreading API can be used.]) + fi + fi + fi + fi + AC_MSG_CHECKING([for multithread API to use]) + AC_MSG_RESULT([$gl_threads_api]) + AC_SUBST([LIBTHREAD]) + AC_SUBST([LTLIBTHREAD]) + AC_SUBST([LIBMULTITHREAD]) + AC_SUBST([LTLIBMULTITHREAD]) +]) + +AC_DEFUN([gl_THREADLIB], +[ + AC_REQUIRE([gl_THREADLIB_EARLY]) + AC_REQUIRE([gl_THREADLIB_BODY]) +]) + + +dnl gl_DISABLE_THREADS +dnl ------------------ +dnl Sets the gl_THREADLIB default so that threads are not used by default. +dnl The user can still override it at installation time, by using the +dnl configure option '--enable-threads'. + +AC_DEFUN([gl_DISABLE_THREADS], [ + m4_divert_text([INIT_PREPARE], [gl_use_threads_default=no]) +]) + + +dnl Survey of platforms: +dnl +dnl Platform Available Compiler Supports test-lock +dnl flavours option weak result +dnl --------------- --------- --------- -------- --------- +dnl Linux 2.4/glibc posix -lpthread Y OK +dnl +dnl GNU Hurd/glibc posix +dnl +dnl FreeBSD 5.3 posix -lc_r Y +dnl posix -lkse ? Y +dnl posix -lpthread ? Y +dnl posix -lthr Y +dnl +dnl FreeBSD 5.2 posix -lc_r Y +dnl posix -lkse Y +dnl posix -lthr Y +dnl +dnl FreeBSD 4.0,4.10 posix -lc_r Y OK +dnl +dnl NetBSD 1.6 -- +dnl +dnl OpenBSD 3.4 posix -lpthread Y OK +dnl +dnl MacOS X 10.[123] posix -lpthread Y OK +dnl +dnl Solaris 7,8,9 posix -lpthread Y Sol 7,8: 0.0; Sol 9: OK +dnl solaris -lthread Y Sol 7,8: 0.0; Sol 9: OK +dnl +dnl HP-UX 11 posix -lpthread N (cc) OK +dnl Y (gcc) +dnl +dnl IRIX 6.5 posix -lpthread Y 0.5 +dnl +dnl AIX 4.3,5.1 posix -lpthread N AIX 4: 0.5; AIX 5: OK +dnl +dnl OSF/1 4.0,5.1 posix -pthread (cc) N OK +dnl -lpthread (gcc) Y +dnl +dnl Cygwin posix -lpthread Y OK +dnl +dnl Any of the above pth -lpth 0.0 +dnl +dnl Mingw win32 N OK +dnl +dnl BeOS 5 -- +dnl +dnl The test-lock result shows what happens if in test-lock.c EXPLICIT_YIELD is +dnl turned off: +dnl OK if all three tests terminate OK, +dnl 0.5 if the first test terminates OK but the second one loops endlessly, +dnl 0.0 if the first test already loops endlessly. diff --git a/m4/uintmax_t.m4 b/m4/uintmax_t.m4 new file mode 100644 index 00000000..03b51bcf --- /dev/null +++ b/m4/uintmax_t.m4 @@ -0,0 +1,30 @@ +# uintmax_t.m4 serial 12 +dnl Copyright (C) 1997-2004, 2007-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Paul Eggert. + +AC_PREREQ([2.13]) + +# Define uintmax_t to 'unsigned long' or 'unsigned long long' +# if it is not already defined in or . + +AC_DEFUN([gl_AC_TYPE_UINTMAX_T], +[ + AC_REQUIRE([gl_AC_HEADER_INTTYPES_H]) + AC_REQUIRE([gl_AC_HEADER_STDINT_H]) + if test $gl_cv_header_inttypes_h = no && test $gl_cv_header_stdint_h = no; then + AC_REQUIRE([AC_TYPE_UNSIGNED_LONG_LONG_INT]) + test $ac_cv_type_unsigned_long_long_int = yes \ + && ac_type='unsigned long long' \ + || ac_type='unsigned long' + AC_DEFINE_UNQUOTED([uintmax_t], [$ac_type], + [Define to unsigned long or unsigned long long + if and don't define.]) + else + AC_DEFINE([HAVE_UINTMAX_T], [1], + [Define if you have the 'uintmax_t' type in or .]) + fi +]) diff --git a/m4/visibility.m4 b/m4/visibility.m4 new file mode 100644 index 00000000..077c4765 --- /dev/null +++ b/m4/visibility.m4 @@ -0,0 +1,74 @@ +# visibility.m4 serial 3 (gettext-0.18) +dnl Copyright (C) 2005, 2008-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +dnl Tests whether the compiler supports the command-line option +dnl -fvisibility=hidden and the function and variable attributes +dnl __attribute__((__visibility__("hidden"))) and +dnl __attribute__((__visibility__("default"))). +dnl Does *not* test for __visibility__("protected") - which has tricky +dnl semantics (see the 'vismain' test in glibc) and does not exist e.g. on +dnl MacOS X. +dnl Does *not* test for __visibility__("internal") - which has processor +dnl dependent semantics. +dnl Does *not* test for #pragma GCC visibility push(hidden) - which is +dnl "really only recommended for legacy code". +dnl Set the variable CFLAG_VISIBILITY. +dnl Defines and sets the variable HAVE_VISIBILITY. + +AC_DEFUN([gl_VISIBILITY], +[ + AC_REQUIRE([AC_PROG_CC]) + CFLAG_VISIBILITY= + HAVE_VISIBILITY=0 + if test -n "$GCC"; then + dnl First, check whether -Werror can be added to the command line, or + dnl whether it leads to an error because of some other option that the + dnl user has put into $CC $CFLAGS $CPPFLAGS. + AC_MSG_CHECKING([whether the -Werror option is usable]) + AC_CACHE_VAL([gl_cv_cc_vis_werror], [ + gl_save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -Werror" + AC_TRY_COMPILE([], [], + [gl_cv_cc_vis_werror=yes], + [gl_cv_cc_vis_werror=no]) + CFLAGS="$gl_save_CFLAGS"]) + AC_MSG_RESULT([$gl_cv_cc_vis_werror]) + dnl Now check whether visibility declarations are supported. + AC_MSG_CHECKING([for simple visibility declarations]) + AC_CACHE_VAL([gl_cv_cc_visibility], [ + gl_save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -fvisibility=hidden" + dnl We use the option -Werror and a function dummyfunc, because on some + dnl platforms (Cygwin 1.7) the use of -fvisibility triggers a warning + dnl "visibility attribute not supported in this configuration; ignored" + dnl at the first function definition in every compilation unit, and we + dnl don't want to use the option in this case. + if test $gl_cv_cc_vis_werror = yes; then + CFLAGS="$CFLAGS -Werror" + fi + AC_TRY_COMPILE( + [extern __attribute__((__visibility__("hidden"))) int hiddenvar; + extern __attribute__((__visibility__("default"))) int exportedvar; + extern __attribute__((__visibility__("hidden"))) int hiddenfunc (void); + extern __attribute__((__visibility__("default"))) int exportedfunc (void); + void dummyfunc (void) {}], + [], + [gl_cv_cc_visibility=yes], + [gl_cv_cc_visibility=no]) + CFLAGS="$gl_save_CFLAGS"]) + AC_MSG_RESULT([$gl_cv_cc_visibility]) + if test $gl_cv_cc_visibility = yes; then + CFLAG_VISIBILITY="-fvisibility=hidden" + HAVE_VISIBILITY=1 + fi + fi + AC_SUBST([CFLAG_VISIBILITY]) + AC_SUBST([HAVE_VISIBILITY]) + AC_DEFINE_UNQUOTED([HAVE_VISIBILITY], [$HAVE_VISIBILITY], + [Define to 1 or 0, depending whether the compiler supports simple visibility declarations.]) +]) diff --git a/m4/wchar_t.m4 b/m4/wchar_t.m4 new file mode 100644 index 00000000..ed804e66 --- /dev/null +++ b/m4/wchar_t.m4 @@ -0,0 +1,20 @@ +# wchar_t.m4 serial 3 (gettext-0.18) +dnl Copyright (C) 2002-2003, 2008-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. +dnl Test whether has the 'wchar_t' type. +dnl Prerequisite: AC_PROG_CC + +AC_DEFUN([gt_TYPE_WCHAR_T], +[ + AC_CACHE_CHECK([for wchar_t], [gt_cv_c_wchar_t], + [AC_TRY_COMPILE([#include + wchar_t foo = (wchar_t)'\0';], , + [gt_cv_c_wchar_t=yes], [gt_cv_c_wchar_t=no])]) + if test $gt_cv_c_wchar_t = yes; then + AC_DEFINE([HAVE_WCHAR_T], [1], [Define if you have the 'wchar_t' type.]) + fi +]) diff --git a/m4/wint_t.m4 b/m4/wint_t.m4 new file mode 100644 index 00000000..a6c7d15c --- /dev/null +++ b/m4/wint_t.m4 @@ -0,0 +1,28 @@ +# wint_t.m4 serial 4 (gettext-0.18) +dnl Copyright (C) 2003, 2007-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. +dnl Test whether has the 'wint_t' type. +dnl Prerequisite: AC_PROG_CC + +AC_DEFUN([gt_TYPE_WINT_T], +[ + AC_CACHE_CHECK([for wint_t], [gt_cv_c_wint_t], + [AC_TRY_COMPILE([ +/* Tru64 with Desktop Toolkit C has a bug: must be included before + . + BSD/OS 4.0.1 has a bug: , and must be included + before . */ +#include +#include +#include +#include + wint_t foo = (wchar_t)'\0';], , + [gt_cv_c_wint_t=yes], [gt_cv_c_wint_t=no])]) + if test $gt_cv_c_wint_t = yes; then + AC_DEFINE([HAVE_WINT_T], [1], [Define if you have the 'wint_t' type.]) + fi +]) diff --git a/m4/xsize.m4 b/m4/xsize.m4 new file mode 100644 index 00000000..b653693a --- /dev/null +++ b/m4/xsize.m4 @@ -0,0 +1,13 @@ +# xsize.m4 serial 4 +dnl Copyright (C) 2003-2004, 2008-2010 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_XSIZE], +[ + dnl Prerequisites of lib/xsize.h. + AC_REQUIRE([gl_SIZE_MAX]) + AC_REQUIRE([AC_C_INLINE]) + AC_CHECK_HEADERS([stdint.h]) +]) diff --git a/msw/rtmidilib.vcproj b/msw/rtmidilib.vcproj index af1f75c2..20a458f0 100755 --- a/msw/rtmidilib.vcproj +++ b/msw/rtmidilib.vcproj @@ -151,6 +151,10 @@ RelativePath="..\RtMidi.cpp" > + + + + + + * Makefile.in.in: Upgrade to gettext-0.19.8.1. + * Rules-quot: Upgrade to gettext-0.19.8.1. + +2014-06-08 gettextize + + * Makefile.in.in: New file, from gettext-0.18.3. + * Rules-quot: New file, from gettext-0.18.3. + * boldquot.sed: New file, from gettext-0.18.3. + * en@boldquot.header: New file, from gettext-0.18.3. + * en@quot.header: New file, from gettext-0.18.3. + * insert-header.sin: New file, from gettext-0.18.3. + * quot.sed: New file, from gettext-0.18.3. + * remove-potcdate.sin: New file, from gettext-0.18.3. + * POTFILES.in: New file. + diff --git a/po/LINGUAS b/po/LINGUAS new file mode 100644 index 00000000..c42e816f --- /dev/null +++ b/po/LINGUAS @@ -0,0 +1 @@ +de \ No newline at end of file diff --git a/po/Makefile.in.in b/po/Makefile.in.in new file mode 100644 index 00000000..38c293d2 --- /dev/null +++ b/po/Makefile.in.in @@ -0,0 +1,483 @@ +# Makefile for PO directory in any package using GNU gettext. +# Copyright (C) 1995-1997, 2000-2007, 2009-2010 by Ulrich Drepper +# +# Copying and distribution of this file, with or without modification, +# are permitted in any medium without royalty provided the copyright +# notice and this notice are preserved. This file is offered as-is, +# without any warranty. +# +# Origin: gettext-0.19.8 +GETTEXT_MACRO_VERSION = 0.19 + +PACKAGE = @PACKAGE@ +VERSION = @VERSION@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ + +SED = @SED@ +SHELL = /bin/sh +@SET_MAKE@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ + +prefix = @prefix@ +exec_prefix = @exec_prefix@ +datarootdir = @datarootdir@ +datadir = @datadir@ +localedir = @localedir@ +gettextsrcdir = $(datadir)/gettext/po + +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ + +# We use $(mkdir_p). +# In automake <= 1.9.x, $(mkdir_p) is defined either as "mkdir -p --" or as +# "$(mkinstalldirs)" or as "$(install_sh) -d". For these automake versions, +# @install_sh@ does not start with $(SHELL), so we add it. +# In automake >= 1.10, @mkdir_p@ is derived from ${MKDIR_P}, which is defined +# either as "/path/to/mkdir -p" or ".../install-sh -c -d". For these automake +# versions, $(mkinstalldirs) and $(install_sh) are unused. +mkinstalldirs = $(SHELL) @install_sh@ -d +install_sh = $(SHELL) @install_sh@ +MKDIR_P = @MKDIR_P@ +mkdir_p = @mkdir_p@ + +# When building gettext-tools, we prefer to use the built programs +# rather than installed programs. However, we can't do that when we +# are cross compiling. +CROSS_COMPILING = @CROSS_COMPILING@ + +GMSGFMT_ = @GMSGFMT@ +GMSGFMT_no = @GMSGFMT@ +GMSGFMT_yes = @GMSGFMT_015@ +GMSGFMT = $(GMSGFMT_$(USE_MSGCTXT)) +MSGFMT_ = @MSGFMT@ +MSGFMT_no = @MSGFMT@ +MSGFMT_yes = @MSGFMT_015@ +MSGFMT = $(MSGFMT_$(USE_MSGCTXT)) +XGETTEXT_ = @XGETTEXT@ +XGETTEXT_no = @XGETTEXT@ +XGETTEXT_yes = @XGETTEXT_015@ +XGETTEXT = $(XGETTEXT_$(USE_MSGCTXT)) +MSGMERGE = msgmerge +MSGMERGE_UPDATE = @MSGMERGE@ --update +MSGINIT = msginit +MSGCONV = msgconv +MSGFILTER = msgfilter + +POFILES = @POFILES@ +GMOFILES = @GMOFILES@ +UPDATEPOFILES = @UPDATEPOFILES@ +DUMMYPOFILES = @DUMMYPOFILES@ +DISTFILES.common = Makefile.in.in remove-potcdate.sin \ +$(DISTFILES.common.extra1) $(DISTFILES.common.extra2) $(DISTFILES.common.extra3) +DISTFILES = $(DISTFILES.common) Makevars POTFILES.in \ +$(POFILES) $(GMOFILES) \ +$(DISTFILES.extra1) $(DISTFILES.extra2) $(DISTFILES.extra3) + +POTFILES = \ + +CATALOGS = @CATALOGS@ + +POFILESDEPS_ = $(srcdir)/$(DOMAIN).pot +POFILESDEPS_yes = $(POFILESDEPS_) +POFILESDEPS_no = +POFILESDEPS = $(POFILESDEPS_$(PO_DEPENDS_ON_POT)) + +DISTFILESDEPS_ = update-po +DISTFILESDEPS_yes = $(DISTFILESDEPS_) +DISTFILESDEPS_no = +DISTFILESDEPS = $(DISTFILESDEPS_$(DIST_DEPENDS_ON_UPDATE_PO)) + +# Makevars gets inserted here. (Don't remove this line!) + +.SUFFIXES: +.SUFFIXES: .po .gmo .mo .sed .sin .nop .po-create .po-update + +.po.mo: + @echo "$(MSGFMT) -c -o $@ $<"; \ + $(MSGFMT) -c -o t-$@ $< && mv t-$@ $@ + +.po.gmo: + @lang=`echo $* | sed -e 's,.*/,,'`; \ + test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \ + echo "$${cdcmd}rm -f $${lang}.gmo && $(GMSGFMT) -c --statistics --verbose -o $${lang}.gmo $${lang}.po"; \ + cd $(srcdir) && rm -f $${lang}.gmo && $(GMSGFMT) -c --statistics --verbose -o t-$${lang}.gmo $${lang}.po && mv t-$${lang}.gmo $${lang}.gmo + +.sin.sed: + sed -e '/^#/d' $< > t-$@ + mv t-$@ $@ + + +all: all-@USE_NLS@ + +all-yes: stamp-po +all-no: + +# Ensure that the gettext macros and this Makefile.in.in are in sync. +CHECK_MACRO_VERSION = \ + test "$(GETTEXT_MACRO_VERSION)" = "@GETTEXT_MACRO_VERSION@" \ + || { echo "*** error: gettext infrastructure mismatch: using a Makefile.in.in from gettext version $(GETTEXT_MACRO_VERSION) but the autoconf macros are from gettext version @GETTEXT_MACRO_VERSION@" 1>&2; \ + exit 1; \ + } + +# $(srcdir)/$(DOMAIN).pot is only created when needed. When xgettext finds no +# internationalized messages, no $(srcdir)/$(DOMAIN).pot is created (because +# we don't want to bother translators with empty POT files). We assume that +# LINGUAS is empty in this case, i.e. $(POFILES) and $(GMOFILES) are empty. +# In this case, stamp-po is a nop (i.e. a phony target). + +# stamp-po is a timestamp denoting the last time at which the CATALOGS have +# been loosely updated. Its purpose is that when a developer or translator +# checks out the package via CVS, and the $(DOMAIN).pot file is not in CVS, +# "make" will update the $(DOMAIN).pot and the $(CATALOGS), but subsequent +# invocations of "make" will do nothing. This timestamp would not be necessary +# if updating the $(CATALOGS) would always touch them; however, the rule for +# $(POFILES) has been designed to not touch files that don't need to be +# changed. +stamp-po: $(srcdir)/$(DOMAIN).pot + @$(CHECK_MACRO_VERSION) + test ! -f $(srcdir)/$(DOMAIN).pot || \ + test -z "$(GMOFILES)" || $(MAKE) $(GMOFILES) + @test ! -f $(srcdir)/$(DOMAIN).pot || { \ + echo "touch stamp-po" && \ + echo timestamp > stamp-poT && \ + mv stamp-poT stamp-po; \ + } + +# Note: Target 'all' must not depend on target '$(DOMAIN).pot-update', +# otherwise packages like GCC can not be built if only parts of the source +# have been downloaded. + +# This target rebuilds $(DOMAIN).pot; it is an expensive operation. +# Note that $(DOMAIN).pot is not touched if it doesn't need to be changed. +# The determination of whether the package xyz is a GNU one is based on the +# heuristic whether some file in the top level directory mentions "GNU xyz". +# If GNU 'find' is available, we avoid grepping through monster files. +$(DOMAIN).pot-update: $(POTFILES) $(srcdir)/POTFILES.in remove-potcdate.sed + package_gnu="$(PACKAGE_GNU)"; \ + test -n "$$package_gnu" || { \ + if { if (LC_ALL=C find --version) 2>/dev/null | grep GNU >/dev/null; then \ + LC_ALL=C find -L $(top_srcdir) -maxdepth 1 -type f \ + -size -10000000c -exec grep 'GNU @PACKAGE@' \ + /dev/null '{}' ';' 2>/dev/null; \ + else \ + LC_ALL=C grep 'GNU @PACKAGE@' $(top_srcdir)/* 2>/dev/null; \ + fi; \ + } | grep -v 'libtool:' >/dev/null; then \ + package_gnu=yes; \ + else \ + package_gnu=no; \ + fi; \ + }; \ + if test "$$package_gnu" = "yes"; then \ + package_prefix='GNU '; \ + else \ + package_prefix=''; \ + fi; \ + if test -n '$(MSGID_BUGS_ADDRESS)' || test '$(PACKAGE_BUGREPORT)' = '@'PACKAGE_BUGREPORT'@'; then \ + msgid_bugs_address='$(MSGID_BUGS_ADDRESS)'; \ + else \ + msgid_bugs_address='$(PACKAGE_BUGREPORT)'; \ + fi; \ + case `$(XGETTEXT) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \ + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-5] | 0.1[0-5].* | 0.16 | 0.16.[0-1]*) \ + $(XGETTEXT) --default-domain=$(DOMAIN) --directory=$(top_srcdir) \ + --add-comments=TRANSLATORS: $(XGETTEXT_OPTIONS) @XGETTEXT_EXTRA_OPTIONS@ \ + --files-from=$(srcdir)/POTFILES.in \ + --copyright-holder='$(COPYRIGHT_HOLDER)' \ + --msgid-bugs-address="$$msgid_bugs_address" \ + ;; \ + *) \ + $(XGETTEXT) --default-domain=$(DOMAIN) --directory=$(top_srcdir) \ + --add-comments=TRANSLATORS: $(XGETTEXT_OPTIONS) @XGETTEXT_EXTRA_OPTIONS@ \ + --files-from=$(srcdir)/POTFILES.in \ + --copyright-holder='$(COPYRIGHT_HOLDER)' \ + --package-name="$${package_prefix}@PACKAGE@" \ + --package-version='@VERSION@' \ + --msgid-bugs-address="$$msgid_bugs_address" \ + ;; \ + esac + test ! -f $(DOMAIN).po || { \ + if test -f $(srcdir)/$(DOMAIN).pot-header; then \ + sed -e '1,/^#$$/d' < $(DOMAIN).po > $(DOMAIN).1po && \ + cat $(srcdir)/$(DOMAIN).pot-header $(DOMAIN).1po > $(DOMAIN).po; \ + rm -f $(DOMAIN).1po; \ + fi; \ + if test -f $(srcdir)/$(DOMAIN).pot; then \ + sed -f remove-potcdate.sed < $(srcdir)/$(DOMAIN).pot > $(DOMAIN).1po && \ + sed -f remove-potcdate.sed < $(DOMAIN).po > $(DOMAIN).2po && \ + if cmp $(DOMAIN).1po $(DOMAIN).2po >/dev/null 2>&1; then \ + rm -f $(DOMAIN).1po $(DOMAIN).2po $(DOMAIN).po; \ + else \ + rm -f $(DOMAIN).1po $(DOMAIN).2po $(srcdir)/$(DOMAIN).pot && \ + mv $(DOMAIN).po $(srcdir)/$(DOMAIN).pot; \ + fi; \ + else \ + mv $(DOMAIN).po $(srcdir)/$(DOMAIN).pot; \ + fi; \ + } + +# This rule has no dependencies: we don't need to update $(DOMAIN).pot at +# every "make" invocation, only create it when it is missing. +# Only "make $(DOMAIN).pot-update" or "make dist" will force an update. +$(srcdir)/$(DOMAIN).pot: + $(MAKE) $(DOMAIN).pot-update + +# This target rebuilds a PO file if $(DOMAIN).pot has changed. +# Note that a PO file is not touched if it doesn't need to be changed. +$(POFILES): $(POFILESDEPS) + @lang=`echo $@ | sed -e 's,.*/,,' -e 's/\.po$$//'`; \ + if test -f "$(srcdir)/$${lang}.po"; then \ + test -f $(srcdir)/$(DOMAIN).pot || $(MAKE) $(srcdir)/$(DOMAIN).pot; \ + test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \ + echo "$${cdcmd}$(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) --lang=$${lang} $${lang}.po $(DOMAIN).pot"; \ + cd $(srcdir) \ + && { case `$(MSGMERGE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \ + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-7] | 0.1[0-7].*) \ + $(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \ + *) \ + $(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) --lang=$${lang} $${lang}.po $(DOMAIN).pot;; \ + esac; \ + }; \ + else \ + $(MAKE) $${lang}.po-create; \ + fi + + +install: install-exec install-data +install-exec: +install-data: install-data-@USE_NLS@ + if test "$(PACKAGE)" = "gettext-tools"; then \ + $(mkdir_p) $(DESTDIR)$(gettextsrcdir); \ + for file in $(DISTFILES.common) Makevars.template; do \ + $(INSTALL_DATA) $(srcdir)/$$file \ + $(DESTDIR)$(gettextsrcdir)/$$file; \ + done; \ + for file in Makevars; do \ + rm -f $(DESTDIR)$(gettextsrcdir)/$$file; \ + done; \ + else \ + : ; \ + fi +install-data-no: all +install-data-yes: all + @catalogs='$(CATALOGS)'; \ + for cat in $$catalogs; do \ + cat=`basename $$cat`; \ + lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \ + dir=$(localedir)/$$lang/LC_MESSAGES; \ + $(mkdir_p) $(DESTDIR)$$dir; \ + if test -r $$cat; then realcat=$$cat; else realcat=$(srcdir)/$$cat; fi; \ + $(INSTALL_DATA) $$realcat $(DESTDIR)$$dir/$(DOMAIN).mo; \ + echo "installing $$realcat as $(DESTDIR)$$dir/$(DOMAIN).mo"; \ + for lc in '' $(EXTRA_LOCALE_CATEGORIES); do \ + if test -n "$$lc"; then \ + if (cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc 2>/dev/null) | grep ' -> ' >/dev/null; then \ + link=`cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc | sed -e 's/^.* -> //'`; \ + mv $(DESTDIR)$(localedir)/$$lang/$$lc $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ + mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ + (cd $(DESTDIR)$(localedir)/$$lang/$$lc.old && \ + for file in *; do \ + if test -f $$file; then \ + ln -s ../$$link/$$file $(DESTDIR)$(localedir)/$$lang/$$lc/$$file; \ + fi; \ + done); \ + rm -f $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ + else \ + if test -d $(DESTDIR)$(localedir)/$$lang/$$lc; then \ + :; \ + else \ + rm -f $(DESTDIR)$(localedir)/$$lang/$$lc; \ + mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ + fi; \ + fi; \ + rm -f $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \ + ln -s ../LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo 2>/dev/null || \ + ln $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo 2>/dev/null || \ + cp -p $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \ + echo "installing $$realcat link as $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo"; \ + fi; \ + done; \ + done + +install-strip: install + +installdirs: installdirs-exec installdirs-data +installdirs-exec: +installdirs-data: installdirs-data-@USE_NLS@ + if test "$(PACKAGE)" = "gettext-tools"; then \ + $(mkdir_p) $(DESTDIR)$(gettextsrcdir); \ + else \ + : ; \ + fi +installdirs-data-no: +installdirs-data-yes: + @catalogs='$(CATALOGS)'; \ + for cat in $$catalogs; do \ + cat=`basename $$cat`; \ + lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \ + dir=$(localedir)/$$lang/LC_MESSAGES; \ + $(mkdir_p) $(DESTDIR)$$dir; \ + for lc in '' $(EXTRA_LOCALE_CATEGORIES); do \ + if test -n "$$lc"; then \ + if (cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc 2>/dev/null) | grep ' -> ' >/dev/null; then \ + link=`cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc | sed -e 's/^.* -> //'`; \ + mv $(DESTDIR)$(localedir)/$$lang/$$lc $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ + mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ + (cd $(DESTDIR)$(localedir)/$$lang/$$lc.old && \ + for file in *; do \ + if test -f $$file; then \ + ln -s ../$$link/$$file $(DESTDIR)$(localedir)/$$lang/$$lc/$$file; \ + fi; \ + done); \ + rm -f $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ + else \ + if test -d $(DESTDIR)$(localedir)/$$lang/$$lc; then \ + :; \ + else \ + rm -f $(DESTDIR)$(localedir)/$$lang/$$lc; \ + mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ + fi; \ + fi; \ + fi; \ + done; \ + done + +# Define this as empty until I found a useful application. +installcheck: + +uninstall: uninstall-exec uninstall-data +uninstall-exec: +uninstall-data: uninstall-data-@USE_NLS@ + if test "$(PACKAGE)" = "gettext-tools"; then \ + for file in $(DISTFILES.common) Makevars.template; do \ + rm -f $(DESTDIR)$(gettextsrcdir)/$$file; \ + done; \ + else \ + : ; \ + fi +uninstall-data-no: +uninstall-data-yes: + catalogs='$(CATALOGS)'; \ + for cat in $$catalogs; do \ + cat=`basename $$cat`; \ + lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \ + for lc in LC_MESSAGES $(EXTRA_LOCALE_CATEGORIES); do \ + rm -f $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \ + done; \ + done + +check: all + +info dvi ps pdf html tags TAGS ctags CTAGS ID: + +mostlyclean: + rm -f remove-potcdate.sed + rm -f stamp-poT + rm -f core core.* $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.new.po + rm -fr *.o + +clean: mostlyclean + +distclean: clean + rm -f Makefile Makefile.in POTFILES *.mo + +maintainer-clean: distclean + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + rm -f stamp-po $(GMOFILES) + +distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) +dist distdir: + test -z "$(DISTFILESDEPS)" || $(MAKE) $(DISTFILESDEPS) + @$(MAKE) dist2 +# This is a separate target because 'update-po' must be executed before. +dist2: stamp-po $(DISTFILES) + dists="$(DISTFILES)"; \ + if test "$(PACKAGE)" = "gettext-tools"; then \ + dists="$$dists Makevars.template"; \ + fi; \ + if test -f $(srcdir)/$(DOMAIN).pot; then \ + dists="$$dists $(DOMAIN).pot stamp-po"; \ + fi; \ + if test -f $(srcdir)/ChangeLog; then \ + dists="$$dists ChangeLog"; \ + fi; \ + for i in 0 1 2 3 4 5 6 7 8 9; do \ + if test -f $(srcdir)/ChangeLog.$$i; then \ + dists="$$dists ChangeLog.$$i"; \ + fi; \ + done; \ + if test -f $(srcdir)/LINGUAS; then dists="$$dists LINGUAS"; fi; \ + for file in $$dists; do \ + if test -f $$file; then \ + cp -p $$file $(distdir) || exit 1; \ + else \ + cp -p $(srcdir)/$$file $(distdir) || exit 1; \ + fi; \ + done + +update-po: Makefile + $(MAKE) $(DOMAIN).pot-update + test -z "$(UPDATEPOFILES)" || $(MAKE) $(UPDATEPOFILES) + $(MAKE) update-gmo + +# General rule for creating PO files. + +.nop.po-create: + @lang=`echo $@ | sed -e 's/\.po-create$$//'`; \ + echo "File $$lang.po does not exist. If you are a translator, you can create it through 'msginit'." 1>&2; \ + exit 1 + +# General rule for updating PO files. + +.nop.po-update: + @lang=`echo $@ | sed -e 's/\.po-update$$//'`; \ + if test "$(PACKAGE)" = "gettext-tools" && test "$(CROSS_COMPILING)" != "yes"; then PATH=`pwd`/../src:$$PATH; fi; \ + tmpdir=`pwd`; \ + echo "$$lang:"; \ + test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \ + echo "$${cdcmd}$(MSGMERGE) $(MSGMERGE_OPTIONS) --lang=$$lang $$lang.po $(DOMAIN).pot -o $$lang.new.po"; \ + cd $(srcdir); \ + if { case `$(MSGMERGE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \ + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-7] | 0.1[0-7].*) \ + $(MSGMERGE) $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \ + *) \ + $(MSGMERGE) $(MSGMERGE_OPTIONS) --lang=$$lang -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \ + esac; \ + }; then \ + if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \ + rm -f $$tmpdir/$$lang.new.po; \ + else \ + if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \ + :; \ + else \ + echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \ + exit 1; \ + fi; \ + fi; \ + else \ + echo "msgmerge for $$lang.po failed!" 1>&2; \ + rm -f $$tmpdir/$$lang.new.po; \ + fi + +$(DUMMYPOFILES): + +update-gmo: Makefile $(GMOFILES) + @: + +# Recreate Makefile by invoking config.status. Explicitly invoke the shell, +# because execution permission bits may not work on the current file system. +# Use @SHELL@, which is the shell determined by autoconf for the use by its +# scripts, not $(SHELL) which is hardwired to /bin/sh and may be deficient. +Makefile: Makefile.in.in Makevars $(top_builddir)/config.status @POMAKEFILEDEPS@ + cd $(top_builddir) \ + && @SHELL@ ./config.status $(subdir)/$@.in po-directories + +force: + +# Tell versions [3.59,3.63) of GNU make not to export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/po/Makevars b/po/Makevars new file mode 100644 index 00000000..57406079 --- /dev/null +++ b/po/Makevars @@ -0,0 +1,85 @@ +# Makefile variables for PO directory in any package using GNU gettext. + +# Usually the message domain is the same as the package name. +DOMAIN = $(PACKAGE) + +# These two variables depend on the location of this directory. +subdir = po +top_builddir = .. + +# These options get passed to xgettext. +XGETTEXT_OPTIONS = --keyword=_ --keyword=N_ --keyword=gettext_noopt --keyword=rtmidi_gettext + +# This is the copyright holder that gets inserted into the header of the +# $(DOMAIN).pot file. Set this to the copyright holder of the surrounding +# package. (Note that the msgstr strings, extracted from the package's +# sources, belong to the copyright holder of the package.) Translators are +# expected to transfer the copyright for their translations to this person +# or entity, or to disclaim their copyright. The empty string stands for +# the public domain; in this case the translators are expected to disclaim +# their copyright. +COPYRIGHT_HOLDER = Gary P. Scavone, Tobias Schlemmer + +# This tells whether or not to prepend "GNU " prefix to the package +# name that gets inserted into the header of the $(DOMAIN).pot file. +# Possible values are "yes", "no", or empty. If it is empty, try to +# detect it automatically by scanning the files in $(top_srcdir) for +# "GNU packagename" string. +PACKAGE_GNU = no + +# This is the email address or URL to which the translators shall report +# bugs in the untranslated strings: +# - Strings which are not entire sentences, see the maintainer guidelines +# in the GNU gettext documentation, section 'Preparing Strings'. +# - Strings which use unclear terms or require additional context to be +# understood. +# - Strings which make invalid assumptions about notation of date, time or +# money. +# - Pluralisation problems. +# - Incorrect English spelling. +# - Incorrect formatting. +# It can be your email address, or a mailing list address where translators +# can write to without being subscribed, or the URL of a web page through +# which the translators can contact you. +MSGID_BUGS_ADDRESS = https://github.com/keinstein/rtmidi + +# This is the list of locale categories, beyond LC_MESSAGES, for which the +# message catalogs shall be used. It is usually empty. +EXTRA_LOCALE_CATEGORIES = + +# This tells whether the $(DOMAIN).pot file contains messages with an 'msgctxt' +# context. Possible values are "yes" and "no". Set this to yes if the +# package uses functions taking also a message context, like pgettext(), or +# if in $(XGETTEXT_OPTIONS) you define keywords with a context argument. +USE_MSGCTXT = no + +# These options get passed to msgmerge. +# Useful options are in particular: +# --previous to keep previous msgids of translated messages, +# --quiet to reduce the verbosity. +MSGMERGE_OPTIONS = + +# These options get passed to msginit. +# If you want to disable line wrapping when writing PO files, add +# --no-wrap to MSGMERGE_OPTIONS, XGETTEXT_OPTIONS, and +# MSGINIT_OPTIONS. +MSGINIT_OPTIONS = + +# This tells whether or not to regenerate a PO file when $(DOMAIN).pot +# has changed. Possible values are "yes" and "no". Set this to no if +# the POT file is checked in the repository and the version control +# program ignores timestamps. +PO_DEPENDS_ON_POT = yes + +# This tells whether or not to forcibly update $(DOMAIN).pot and +# regenerate PO files on "make dist". Possible values are "yes" and +# "no". Set this to no if the POT file and PO files are maintained +# externally. +DIST_DEPENDS_ON_UPDATE_PO = yes + + +# Extra rules + +all: + +tags: diff --git a/po/Makevars.template b/po/Makevars.template new file mode 100644 index 00000000..0648ec75 --- /dev/null +++ b/po/Makevars.template @@ -0,0 +1,78 @@ +# Makefile variables for PO directory in any package using GNU gettext. + +# Usually the message domain is the same as the package name. +DOMAIN = $(PACKAGE) + +# These two variables depend on the location of this directory. +subdir = po +top_builddir = .. + +# These options get passed to xgettext. +XGETTEXT_OPTIONS = --keyword=_ --keyword=N_ + +# This is the copyright holder that gets inserted into the header of the +# $(DOMAIN).pot file. Set this to the copyright holder of the surrounding +# package. (Note that the msgstr strings, extracted from the package's +# sources, belong to the copyright holder of the package.) Translators are +# expected to transfer the copyright for their translations to this person +# or entity, or to disclaim their copyright. The empty string stands for +# the public domain; in this case the translators are expected to disclaim +# their copyright. +COPYRIGHT_HOLDER = Free Software Foundation, Inc. + +# This tells whether or not to prepend "GNU " prefix to the package +# name that gets inserted into the header of the $(DOMAIN).pot file. +# Possible values are "yes", "no", or empty. If it is empty, try to +# detect it automatically by scanning the files in $(top_srcdir) for +# "GNU packagename" string. +PACKAGE_GNU = + +# This is the email address or URL to which the translators shall report +# bugs in the untranslated strings: +# - Strings which are not entire sentences, see the maintainer guidelines +# in the GNU gettext documentation, section 'Preparing Strings'. +# - Strings which use unclear terms or require additional context to be +# understood. +# - Strings which make invalid assumptions about notation of date, time or +# money. +# - Pluralisation problems. +# - Incorrect English spelling. +# - Incorrect formatting. +# It can be your email address, or a mailing list address where translators +# can write to without being subscribed, or the URL of a web page through +# which the translators can contact you. +MSGID_BUGS_ADDRESS = + +# This is the list of locale categories, beyond LC_MESSAGES, for which the +# message catalogs shall be used. It is usually empty. +EXTRA_LOCALE_CATEGORIES = + +# This tells whether the $(DOMAIN).pot file contains messages with an 'msgctxt' +# context. Possible values are "yes" and "no". Set this to yes if the +# package uses functions taking also a message context, like pgettext(), or +# if in $(XGETTEXT_OPTIONS) you define keywords with a context argument. +USE_MSGCTXT = no + +# These options get passed to msgmerge. +# Useful options are in particular: +# --previous to keep previous msgids of translated messages, +# --quiet to reduce the verbosity. +MSGMERGE_OPTIONS = + +# These options get passed to msginit. +# If you want to disable line wrapping when writing PO files, add +# --no-wrap to MSGMERGE_OPTIONS, XGETTEXT_OPTIONS, and +# MSGINIT_OPTIONS. +MSGINIT_OPTIONS = + +# This tells whether or not to regenerate a PO file when $(DOMAIN).pot +# has changed. Possible values are "yes" and "no". Set this to no if +# the POT file is checked in the repository and the version control +# program ignores timestamps. +PO_DEPENDS_ON_POT = yes + +# This tells whether or not to forcibly update $(DOMAIN).pot and +# regenerate PO files on "make dist". Possible values are "yes" and +# "no". Set this to no if the POT file and PO files are maintained +# externally. +DIST_DEPENDS_ON_UPDATE_PO = yes diff --git a/po/POTFILES.in b/po/POTFILES.in new file mode 100644 index 00000000..b4596b4b --- /dev/null +++ b/po/POTFILES.in @@ -0,0 +1,3 @@ +# List of source files which contain translatable strings. +RtMidi.h +RtMidi.cpp \ No newline at end of file diff --git a/po/Rules-quot b/po/Rules-quot new file mode 100644 index 00000000..baf65285 --- /dev/null +++ b/po/Rules-quot @@ -0,0 +1,58 @@ +# This file, Rules-quot, can be copied and used freely without restrictions. +# Special Makefile rules for English message catalogs with quotation marks. + +DISTFILES.common.extra1 = quot.sed boldquot.sed en@quot.header en@boldquot.header insert-header.sin Rules-quot + +.SUFFIXES: .insert-header .po-update-en + +en@quot.po-create: + $(MAKE) en@quot.po-update +en@boldquot.po-create: + $(MAKE) en@boldquot.po-update + +en@quot.po-update: en@quot.po-update-en +en@boldquot.po-update: en@boldquot.po-update-en + +.insert-header.po-update-en: + @lang=`echo $@ | sed -e 's/\.po-update-en$$//'`; \ + if test "$(PACKAGE)" = "gettext-tools" && test "$(CROSS_COMPILING)" != "yes"; then PATH=`pwd`/../src:$$PATH; GETTEXTLIBDIR=`cd $(top_srcdir)/src && pwd`; export GETTEXTLIBDIR; fi; \ + tmpdir=`pwd`; \ + echo "$$lang:"; \ + ll=`echo $$lang | sed -e 's/@.*//'`; \ + LC_ALL=C; export LC_ALL; \ + cd $(srcdir); \ + if $(MSGINIT) $(MSGINIT_OPTIONS) -i $(DOMAIN).pot --no-translator -l $$lang -o - 2>/dev/null \ + | $(SED) -f $$tmpdir/$$lang.insert-header | $(MSGCONV) -t UTF-8 | \ + { case `$(MSGFILTER) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \ + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-8] | 0.1[0-8].*) \ + $(MSGFILTER) $(SED) -f `echo $$lang | sed -e 's/.*@//'`.sed \ + ;; \ + *) \ + $(MSGFILTER) `echo $$lang | sed -e 's/.*@//'` \ + ;; \ + esac } 2>/dev/null > $$tmpdir/$$lang.new.po \ + ; then \ + if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \ + rm -f $$tmpdir/$$lang.new.po; \ + else \ + if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \ + :; \ + else \ + echo "creation of $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \ + exit 1; \ + fi; \ + fi; \ + else \ + echo "creation of $$lang.po failed!" 1>&2; \ + rm -f $$tmpdir/$$lang.new.po; \ + fi + +en@quot.insert-header: insert-header.sin + sed -e '/^#/d' -e 's/HEADER/en@quot.header/g' $(srcdir)/insert-header.sin > en@quot.insert-header + +en@boldquot.insert-header: insert-header.sin + sed -e '/^#/d' -e 's/HEADER/en@boldquot.header/g' $(srcdir)/insert-header.sin > en@boldquot.insert-header + +mostlyclean: mostlyclean-quot +mostlyclean-quot: + rm -f *.insert-header diff --git a/po/boldquot.sed b/po/boldquot.sed new file mode 100644 index 00000000..4b937aa5 --- /dev/null +++ b/po/boldquot.sed @@ -0,0 +1,10 @@ +s/"\([^"]*\)"/“\1”/g +s/`\([^`']*\)'/‘\1’/g +s/ '\([^`']*\)' / ‘\1’ /g +s/ '\([^`']*\)'$/ ‘\1’/g +s/^'\([^`']*\)' /‘\1’ /g +s/“”/""/g +s/“/“/g +s/”/”/g +s/‘/‘/g +s/’/’/g diff --git a/po/de.gmo b/po/de.gmo new file mode 100644 index 00000000..ba5cfe20 Binary files /dev/null and b/po/de.gmo differ diff --git a/po/de.mo b/po/de.mo new file mode 100644 index 00000000..ba5cfe20 Binary files /dev/null and b/po/de.mo differ diff --git a/po/de.po b/po/de.po new file mode 100644 index 00000000..8a4f2fed --- /dev/null +++ b/po/de.po @@ -0,0 +1,628 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR Gary P. Scavone +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: rtmidi 2.1.0\n" +"Report-Msgid-Bugs-To: https://github.com/keinstein/rtmidi\n" +"POT-Creation-Date: 2018-08-13 18:56+0200\n" +"PO-Revision-Date: 2018-08-13 19:04+0200\n" +"Last-Translator: Tobias Schlemmer \n" +"Language-Team: German translation team \n" +"Language: de\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Poedit 2.1.1\n" +"X-Poedit-SourceCharset: UTF-8\n" +"X-Poedit-Basepath: .\n" +"X-Poedit-KeywordsList: gettext_noopt\n" +"X-Poedit-SearchPath-0: /home/tobias/macbookbackup/Entwicklung/rtmidi-beides\n" + +#: RtMidi.h:129 +msgid "Automatic selection" +msgstr "Automatische Auswahl" + +#: RtMidi.h:130 +msgid "Core MIDI" +msgstr "Core MIDI" + +#: RtMidi.h:131 +msgid "ALSA" +msgstr "ALSA" + +#: RtMidi.h:132 +msgid "JACK" +msgstr "JACK" + +#: RtMidi.h:133 +msgid "Windows Multimedia" +msgstr "Windows Multimedia" + +#: RtMidi.h:134 +msgid "DirectX/Kernel Streaming" +msgstr "DirectX/Kernel Streaming" + +#: RtMidi.h:135 +msgid "NULL device" +msgstr "Keine Funktion." + +#: RtMidi.h:136 +msgid "All available MIDI systems" +msgstr "Alle verfügbaren MIDI-Systeme." + +#: RtMidi.h:1106 RtMidi.h:1277 RtMidi.h:1490 RtMidi.h:1511 +msgid "Passed NULL pointer." +msgstr "Nullzeiger übergeben." + +#: RtMidi.h:1308 RtMidi.h:1317 RtMidi.cpp:2596 +msgid "No data in message argument." +msgstr "Keine Daten in der MIDI-Nachricht." + +#: RtMidi.h:1432 +msgid "A NULL pointer has been passed as port descriptor" +msgstr "Ein leerer Zeiger wurde als Schnittstellenbeschreibung übergeben." + +#: RtMidi.h:1452 RtMidi.h:1531 RtMidi.h:1543 +msgid "No valid MIDI system has been selected." +msgstr "Es wurde kein benutzbares MIDI-System ausgewählt." + +#: RtMidi.h:1473 +msgid "Could not find any valid MIDI system." +msgstr "Es konnte kein benutzbares MIDI-System gefunden werden." + +#: RtMidi.h:1495 +msgid "No valid MIDI system has been found." +msgstr "Es konnte kein benutzbares MIDI-System gefunden werden." + +#: RtMidi.h:1537 +msgid "No data in MIDI message." +msgstr "Keine Daten in der MIDI-Nachricht." + +#: RtMidi.cpp:293 +msgid "" +"No valid MIDI interfaces. I'm using a dummy input interface that never " +"receives anything." +msgstr "" +"Keine gültige MIDI-Schnittstelle gefunden. Ich imitiere ein Eingabegerät, " +"das niemals etwas empfängt." + +#: RtMidi.cpp:322 +msgid "" +"No valid MIDI interfaces. I'm using a dummy output interface that does " +"nothing." +msgstr "" +"Keine gültige MIDI-Schnittstelle gefunden. Ich imitiere ein Ausgabegerät, " +"das nichts tut." + +#: RtMidi.cpp:396 +#, c-format +msgid "" +"Error formatting the error string:\n" +"'%s'\n" +"Found in %s::%s at \n" +"%s:%d" +msgstr "" +"Fehler bei der Formatierung der Fehlermeldung:\n" +"'%s'\n" +"gefunden in %s::%s bei \n" +"%s:%d" + +#: RtMidi.cpp:408 +msgid "Error: could not format the error message" +msgstr "Fehler: Ich konnte eine Fehlermeldung nicht formatieren." + +#: RtMidi.cpp:579 RtMidi.cpp:692 +#, c-format +msgid "" +"Support for the selected MIDI system %d has not been compiled into the " +"RtMidi library." +msgstr "" +"Die Unterstützung für das gewählte MIDI-System %d wurde nicht in die RtMidi-" +"Bibliothek eingebaut." + +#: RtMidi.cpp:597 RtMidi.cpp:709 +msgid "No supported MIDI system has been found." +msgstr "Es konnte kein benutzbares MIDI-System gefunden werden." + +#: RtMidi.cpp:798 RtMidi.cpp:815 +msgid "A callback function is already set." +msgstr "Es wurde schon eine Rückruffunktion gesetzt." + +#: RtMidi.cpp:804 RtMidi.cpp:821 +msgid "The callback function value is invalid." +msgstr "Der Funktionswert einer aufgerufenen Rückruffunktion ist ungültig." + +#: RtMidi.cpp:832 +msgid "No callback function was set." +msgstr "Es wurde keine Rückruffunktion gesetzt." + +#: RtMidi.cpp:854 +msgid "" +"Returning an empty MIDI message as all input is handled by a callback " +"function." +msgstr "" +"Es wird eine leere MIDI-Nachricht generiert, weil alle Eingaben durch eine " +"Rückruf-Funktion (engl. callback) abgefangen werden." + +#: RtMidi.cpp:1585 +msgid "Could not get the unique identifier of a midi endpoint." +msgstr "" +"Konnte die eindeutige Identifikation (UUID) eines MIDI-Endpunktes nicht " +"bekommen." + +#: RtMidi.cpp:1595 +msgid "" +"Could not get the endpoint back from the unique identifier of a midi " +"endpoint." +msgstr "" +"Konnte den MIDI-Endpunkt einer eindeutige Identifikation (UUID) nicht " +"bekommen." + +#: RtMidi.cpp:1610 +msgid "Could not get the entity of a midi endpoint." +msgstr "Konnte die Geräteeinheit eines MIDI-Endpunktes nicht bekommen." + +#: RtMidi.cpp:1671 RtMidi.cpp:1707 +msgid "Error creating OS X MIDI port because of invalid port flags." +msgstr "" +"Konnte die OS X-MIDI-Schnittstelle nicht anlegen, da ungültige Eigenschaften " +"angegeben wurden." + +#: RtMidi.cpp:1675 RtMidi.cpp:1711 RtMidi.cpp:2254 +msgid "Error creating OS-X MIDI port." +msgstr "Es gab einen Fehler beim Erzeugen der MIDI-Schnittstelle." + +#: RtMidi.cpp:1760 +#, c-format +msgid "Error creating OS-X MIDI client object (Error no: %d)." +msgstr "Fehler beim erzeugen des OS-X-MIDI-Klienten (Fehlernummer: %d)." + +#: RtMidi.cpp:2014 RtMidi.cpp:2080 RtMidi.cpp:3476 RtMidi.cpp:4720 +#: RtMidi.cpp:5931 +msgid "Error: Message queue limit reached." +msgstr "Fehler: Die Nachrichten-Warteschlange ist überlang." + +#: RtMidi.cpp:2141 RtMidi.cpp:2235 RtMidi.cpp:2412 RtMidi.cpp:2526 +#: RtMidi.cpp:3623 RtMidi.cpp:3740 RtMidi.cpp:4032 RtMidi.cpp:4194 +#: RtMidi.cpp:4777 RtMidi.cpp:5089 RtMidi.cpp:5161 RtMidi.cpp:6084 +#: RtMidi.cpp:6317 +msgid "A valid connection already exists." +msgstr "Es existiert schon eine gültige Verbindung." + +#: RtMidi.cpp:2149 RtMidi.cpp:3630 RtMidi.cpp:4784 +msgid "No MIDI input sources found." +msgstr "Keine MIDI-Eingabe-Geräte gefunden." + +#: RtMidi.cpp:2158 RtMidi.cpp:2337 RtMidi.cpp:2395 RtMidi.cpp:2426 +#: RtMidi.cpp:3640 RtMidi.cpp:4052 RtMidi.cpp:4989 RtMidi.cpp:5063 +#: RtMidi.cpp:5102 RtMidi.cpp:6182 RtMidi.cpp:6408 +#, c-format +msgid "The 'portNumber' argument (%d) is invalid." +msgstr "Die Portnummer %d ist ungültig." + +#: RtMidi.cpp:2170 +msgid "Error creating OS-X MIDI input port." +msgstr "Fehler beim Erzeugen der OS-X-MIDI-Eingabe-Schnittstelle." + +#: RtMidi.cpp:2181 +msgid "Error getting MIDI input source reference." +msgstr "Konnte keine Referenz zum MIDI-Eingang bekommen." + +#: RtMidi.cpp:2192 +msgid "Error connecting OS-X MIDI input port." +msgstr "Fehler beim verbinden mit dem OS-X-MIDI-Eingang." + +#: RtMidi.cpp:2214 +msgid "Error creating virtual OS-X MIDI destination." +msgstr "Konnte den virtuellen OS-X-MIDI-Ausgang nicht erzeugen." + +#: RtMidi.cpp:2230 RtMidi.cpp:2521 RtMidi.cpp:3735 RtMidi.cpp:4189 +#: RtMidi.cpp:6078 RtMidi.cpp:6311 +msgid "Data has not been allocated." +msgstr "Daten konnten nicht angelegt werden." + +#: RtMidi.cpp:2240 RtMidi.cpp:2531 +msgid "" +"Core MIDI has been instructed to open a non-Core MIDI port. This doesn't " +"work." +msgstr "" +"Core-MIDI wurde angewiesen, eine nicht-Core-MIDI-Schnittstelle zu öffnen. " +"Das geht nicht." + +#: RtMidi.cpp:2312 RtMidi.cpp:2479 +msgid "Setting client names is not implemented for Mac OS X CoreMIDI." +msgstr "" +"Das Ändern des Namens des MIDI-Klienten ist für Mac OS X CoreMIDI nicht " +"implementiert." + +#: RtMidi.cpp:2318 RtMidi.cpp:2485 +msgid "Setting port names is not implemented for Mac OS X CoreMIDI." +msgstr "" +"Das Ändern des Namens einer MIDI-Schnittstelle ist für Mac OS X CoreMIDI " +"nicht implementiert." + +#: RtMidi.cpp:2420 +msgid "No MIDI output destinations found." +msgstr "Es wurden keine MIDI-Ausgabegeräte gefunden." + +#: RtMidi.cpp:2438 +msgid "Error creating OS-X MIDI output port." +msgstr "Fehler beim Erzeugen der OS-X-MIDI-Ausgabe-Schnittstelle." + +#: RtMidi.cpp:2449 +msgid "Error getting MIDI output destination reference." +msgstr "Konnte keine Referenz zum MIDI-Ausgang bekommen." + +#: RtMidi.cpp:2494 +msgid "A virtual output port already exists." +msgstr "Es gibt schon einen virtuellen MIDI-Ausgang." + +#: RtMidi.cpp:2505 +msgid "Error creating OS-X virtual MIDI source." +msgstr "Konnte den virtuellen OS-X-MIDI-Eingang nicht erzeugen." + +#: RtMidi.cpp:2608 +msgid "message format problem ... not sysex but > 3 bytes?" +msgstr "" +"Nachrichtenformatproblem: Eine MIDI-Nachricht ist größer als 3 Bytes (und " +"keine SysEx-Nachricht)." + +#: RtMidi.cpp:2627 +msgid "Could not allocate packet list." +msgstr "Konnte die Paketliste nicht anlegen." + +#: RtMidi.cpp:2636 +msgid "Error sending MIDI to virtual destinations." +msgstr "Konnte MIDI-Daten nicht zu virtuellen Ausgängen senden." + +#: RtMidi.cpp:2645 RtMidi.cpp:4175 +msgid "Error sending MIDI message to port." +msgstr "Fehler beim Senden der MIDI-Nachricht zum Ausgang." + +#: RtMidi.cpp:2810 +msgid "Could not allocate ALSA port info structure." +msgstr "" +"Konnte keinen Speicher für die ALSA-MIDI-Schnittstelleninformation bekommen." + +#: RtMidi.cpp:2814 +#, c-format +msgid "Could not get ALSA port information: %s" +msgstr "Konnte keine ALSA-Schnittstelleninformation bekommen: %s" + +#: RtMidi.cpp:2820 +#, c-format +msgid "Could not set ALSA port information: %s" +msgstr "Konnte ALSA-Schnittstelleninformation nicht ändern: %s" + +#: RtMidi.cpp:2873 RtMidi.cpp:3149 RtMidi.cpp:3684 RtMidi.cpp:3745 +#: RtMidi.cpp:4079 +msgid "Could not allocate ALSA port subscription." +msgstr "" +"Konnte keinen Speicher für das Abonnoment der ALSA-MIDI-Schnittstelle " +"bekommen." + +#: RtMidi.cpp:2888 RtMidi.cpp:3693 RtMidi.cpp:4090 +msgid "Error making ALSA port connection." +msgstr "Konnte zwei ALSA-Schnittstellen nicht miteinander verbinden." + +#: RtMidi.cpp:3219 RtMidi.cpp:3719 RtMidi.cpp:3868 +msgid "Error starting MIDI input thread!" +msgstr "Konnte den MIDI-Eingabe-Prozess nicht starten." + +#: RtMidi.cpp:3257 RtMidi.cpp:3974 +msgid "Error initializing MIDI event parser." +msgstr "Fehler bei der Initialisierung des MIDI-Ereeignisparsers." + +#: RtMidi.cpp:3270 +msgid "Error initializing buffer memory." +msgstr "Fehler beim Anlegen des Pufferspeichers." + +#: RtMidi.cpp:3304 +msgid "MIDI input buffer overrun." +msgstr "MIDI-Eingabepuffer übergelaufen." + +#: RtMidi.cpp:3314 +msgid "ALSA returned without providing a MIDI event." +msgstr "ALSA kam zurück ohne ein MIDI-Ereignis mitzubringen." + +#: RtMidi.cpp:3324 +#, c-format +msgid "" +"Unknown MIDI input error.\n" +"The system reports:\n" +"%s" +msgstr "" +"Unbekannter MIDI-Eingabefehler.\n" +"Das System meldet:\n" +"%s" + +#: RtMidi.cpp:3382 +msgid "Error resizing buffer memory." +msgstr "Fehler beim Ändern der Grüße des Pufferspeichers." + +#: RtMidi.cpp:3455 +msgid "Event parsing error or not a MIDI event." +msgstr "" +"Analyse eines Ereignisses fehlgeschlagen oder es war kein MIDI-Ereignis." + +#: RtMidi.cpp:3532 +msgid "Error creating pipe objects." +msgstr "Fehler beim anlegen einer Pipe." + +#: RtMidi.cpp:3615 RtMidi.cpp:4024 +msgid "Error looking for port name." +msgstr "Fehler beim Suchen nach einem Schnittstellennamen." + +#: RtMidi.cpp:3671 +msgid "Error creating ALSA input port." +msgstr "Fehler beim Erzeugen der ALSA-Eingabe-Schnittstelle." + +#: RtMidi.cpp:3750 RtMidi.cpp:4204 +msgid "" +"ALSA has been instructed to open a non-ALSA MIDI port. This doesn't work." +msgstr "" +"ALSA wurde angewiesen, eine nicht-ALSA-MIDI-Schnittstelle zu öffnen. Das " +"geht nicht." + +#: RtMidi.cpp:3834 RtMidi.cpp:4130 +msgid "Error creating ALSA virtual port." +msgstr "Fehler beim Erzeugen einer virtuellen ALSA-Schnittstelle." + +#: RtMidi.cpp:3957 +msgid "Error creating ALSA sequencer client object." +msgstr "Fehler beim erzeugen des ALSA-Klienten." + +#: RtMidi.cpp:3981 RtMidi.cpp:4153 +msgid "Error while allocating buffer memory." +msgstr "Fehler beim Anlegen des Pufferspeichers." + +#: RtMidi.cpp:4040 +msgid "No MIDI output sinks found." +msgstr "Es wurden kiene Midi-Ausgabegeräte gefunden." + +#: RtMidi.cpp:4067 +msgid "Error creating ALSA output port." +msgstr "Fehler beim Erzeugen der ALSA-Ausgangs." + +#: RtMidi.cpp:4146 +msgid "ALSA error resizing MIDI event buffer." +msgstr "ALSA-Fehler beim Verändern der Größe des MIDI-Nachrichten-Puffers." + +#: RtMidi.cpp:4167 +msgid "Event parsing error." +msgstr "Fehler bei der Analyse eines Ereignisses." + +#: RtMidi.cpp:4199 +msgid "Error allocating ALSA port subscription." +msgstr "" +"Konnte keinen Speicher für das Abonnoment der ALSA-MIDI-Schnittstelle " +"bekommen." + +#: RtMidi.cpp:4377 +#, c-format +msgid "The port argument %d is invalid." +msgstr "Das Schnittstellenargument %d ist ungültig." + +#: RtMidi.cpp:4698 +msgid "Error sending sysex to Midi device." +msgstr "Fehler beim Senden der SysEx-Nachricht zum MIDI-Gerät." + +#: RtMidi.cpp:4759 +msgid "No MIDI input devices currently available." +msgstr "Es gibt momentan keine MIDI-Eingabegeräte." + +#: RtMidi.cpp:4769 +msgid "Failed to initialize a critical section." +msgstr "Konnte kritischen Bereich nicht initialisieren." + +#: RtMidi.cpp:4793 +#, c-format +msgid "the 'portNumber' argument (%d) is invalid." +msgstr "Die Portnummer %d ist ungültig." + +#: RtMidi.cpp:4805 +msgid "Error creating Windows MM MIDI input port." +msgstr "Konnte den Windows-Multimedia-MIDI-Eingang nicht erzeugen." + +#: RtMidi.cpp:4822 +msgid "Error initializing data for Windows MM MIDI input port." +msgstr "" +"Fehler beim Erzeugen der daten für einen Windows Multimedia MIDI-Eingang." + +#: RtMidi.cpp:4832 +msgid "Could not register the input buffer for Windows MM MIDI input port." +msgstr "" +"Konnte den Eingabe-Puffer eines Windows-Multimedia-MIDI-Eingangs nicht " +"erzeugen." + +#: RtMidi.cpp:4842 +msgid "Error starting Windows MM MIDI input port." +msgstr "Konnte einen Windows-Multimedia-MIDI-Eingang nicht aktivieren." + +#: RtMidi.cpp:4853 RtMidi.cpp:5148 +msgid "Virtual ports are not available Windows Multimedia MIDI API." +msgstr "" +"Windows Multimedia unterstützt keine virtuellen MIDI-Ein- und -Ausgänge." + +#: RtMidi.cpp:4860 RtMidi.cpp:5156 +msgid "" +"Windows Multimedia (WinMM) has been instructed to open a non-WinMM MIDI " +"port. This doesn't work." +msgstr "" +"Windows Multimedia (WinMM) wurde angewiesen, eine nicht-WinMM-MIDI-" +"Schnittstelle zu öffnen. Das geht nicht." + +#: RtMidi.cpp:4865 +msgid "" +"We are overwriting an existing connection. This is probably a programming " +"error." +msgstr "" +"Wir überschreiben eine vorhandene MIDI-Verbindung. Das ist vermutlich ein " +"Programmierfehler." + +#: RtMidi.cpp:4870 +msgid "Trying to open a non-input port as input MIDI port. This doesn't work." +msgstr "" +"Versuche eine Nicht-Eingang als MIDI-Eingang zu öffnen. Das geht nicht." + +#: RtMidi.cpp:4884 RtMidi.cpp:5180 +msgid "" +"Some change in the arrangement of MIDI input ports invalidated the port " +"descriptor." +msgstr "" +"Eine Veränderung bei den MIDI-Schnittstellen hat die interne " +"Schnittstellenbeschreibung ungültig gemacht." + +#: RtMidi.cpp:4899 +msgid "The handle is invalid. Did you disconnect the device?" +msgstr "" +"Ein Schnittstellenverweis ist ungültig. Haben Sie das zugehörige Gerät " +"entfernt?" + +#: RtMidi.cpp:4903 RtMidi.cpp:5199 +msgid "" +"The system has no driver for our handle :-(. Did you disconnect the device?" +msgstr "" +"Das System hat keinen Treiber für unseren Schnittstellenverweis (mehr) :-(. " +"Haben Sie das zugehörige Gerät entfernt?" + +#: RtMidi.cpp:4907 RtMidi.cpp:5203 +msgid "Out of memory." +msgstr "Hauptspeicher erschöpft." + +#: RtMidi.cpp:4954 +msgid "Error closing Windows MM MIDI input port." +msgstr "" +"Konnte den Windows Multimedia MIDI-Eingang nicht ordnungsgemäß schließen." + +#: RtMidi.cpp:4969 RtMidi.cpp:5135 +msgid "Setting the client name is not supported by Windows MM." +msgstr "" +"Das Ändern des Namens des MIDI-Klienten wird vom Windows MIDI Mapper nicht " +"unterstützt." + +#: RtMidi.cpp:4975 RtMidi.cpp:5141 +msgid "Setting the port name is not supported by Windows MM." +msgstr "" +"Das Ändern des Namens der MIDI-Schnittstelle wird vom Windows MIDI Mapper " +"nicht unterstützt." + +#: RtMidi.cpp:5041 +msgid "No MIDI output devices currently available." +msgstr "Es gibt momentan keine MIDI-Ausgabegeräte." + +#: RtMidi.cpp:5096 +msgid "No MIDI output destinations found!" +msgstr "Es wurden keine MIDI-Ausgabegeräte gefunden." + +#: RtMidi.cpp:5114 +msgid "Error creating Windows MM MIDI output port." +msgstr "Konnte den Windows Multimedia MIDI-Ausgang nicht erzeugen." + +#: RtMidi.cpp:5166 +msgid "The port descriptor cannot be used to open an output port." +msgstr "" +"Eine Schnittstellenbeschreibung kann nicht benutzt werden, um einen MIDI-" +"Ausgang zu erzeugen." + +#: RtMidi.cpp:5195 +msgid "The internal handle is invalid. Did you disconnect the device?" +msgstr "" +"Ein interner Schnittstellenverweis ist ungültig. Haben sie das zugehörige " +"Gerät entfernt?" + +#: RtMidi.cpp:5230 +msgid "Message argument is empty." +msgstr "Das Nachrichtenargument ist leer." + +#: RtMidi.cpp:5242 +msgid "Error while allocating sysex message memory." +msgstr "Fehler beim Anlegen des Speichers für SysEx-Nachrichten." + +#: RtMidi.cpp:5258 +msgid "Error preparing sysex header." +msgstr "Fehler beim Erstellen des SysEx-Kopfes." + +#: RtMidi.cpp:5267 +msgid "Error sending sysex message." +msgstr "Fehler beim Senden der SysEx-Nachricht." + +#: RtMidi.cpp:5280 +msgid "Message size is greater than 3 bytes (and not sysex)." +msgstr "" +"Eine MIDI-Nachricht ist größer als 3 Bytes (und keine SysEx-Nachricht)." + +#: RtMidi.cpp:5296 +msgid "Error sending MIDI message." +msgstr "Fehler beim Senden der MIDI-Nachricht." + +#: RtMidi.cpp:5535 +msgid "Could not connect to JACK server. Is it runnig?" +msgstr "Ich konnte mich nicht mit dem JACK-Server verbinden. Läuft er?" + +#: RtMidi.cpp:5767 +msgid "Error opening JACK port subscription." +msgstr "Fehler beim abonnieren einer JACK-Schnittstelle." + +#: RtMidi.cpp:6002 RtMidi.cpp:6248 +msgid "JACK server not running?" +msgstr "Läuft der JACK-Server?" + +#: RtMidi.cpp:6046 RtMidi.cpp:6279 +msgid "Error creating JACK port." +msgstr "Es gab einen Fehler beim Erzeugen der JACK-Schnittstelle." + +#: RtMidi.cpp:6066 RtMidi.cpp:6299 +msgid "Error creating JACK virtual port." +msgstr "Fehler beim Erzeugen einer virtuellen JACK-Schnittstelle." + +#: RtMidi.cpp:6090 RtMidi.cpp:6323 +msgid "" +"JACK has been instructed to open a non-JACK MIDI port. This doesn't work." +msgstr "" +"JACK wurde angewiesen, eine nicht-JACK-Schnittstelle zu öffnen. Das geht " +"nicht." + +#: RtMidi.cpp:6173 RtMidi.cpp:6401 +msgid "No ports available." +msgstr "Keine Schnittstellen verfügbar." + +#: RtMidi.cpp:6201 RtMidi.cpp:6429 +msgid "Setting the client name is not supported by JACK." +msgstr "" +"Das Ändern des Namens des MIDI-Klienten wird von JACK nicht unterstützt." + +#~ msgid "MidiInDummy: This class provides no functionality." +#~ msgstr "MidiInDummy: Diese Klasse stellt keine Funktionen zur verfügung." + +#, fuzzy +#~ msgid "InitializeCriticalSectionAndSpinCount failed." +#~ msgstr "%s: malloc ist fehlgeschlagen: %s\n" + +#, fuzzy +#~ msgid "ALSA error allocation port subscription." +#~ msgstr "" +#~ "Konnte keinen Speicher für das Abonnoments der MIDI-Schnittstelle " +#~ "bekommen." + +#, fuzzy +#~ msgid "A valid connection already exists" +#~ msgstr "Es existiert schon eine gültige Verbindung." + +#, fuzzy +#~ msgid "No ports available" +#~ msgstr "Keine Adresse verfügbar" + +#~ msgid "" +#~ "An invalid (i.e. non-CORE) port descriptor has been passed to openPort." +#~ msgstr "Es wurde eine ungültige Schnittstellenbeschreibung (" + +#~ msgid "Internal error: data has not been allocated." +#~ msgstr " " + +#~ msgid "No data in message argument!" +#~ msgstr "Keine Daten in der MIDI-Nachricht." diff --git a/po/en@boldquot.header b/po/en@boldquot.header new file mode 100644 index 00000000..fedb6a06 --- /dev/null +++ b/po/en@boldquot.header @@ -0,0 +1,25 @@ +# All this catalog "translates" are quotation characters. +# The msgids must be ASCII and therefore cannot contain real quotation +# characters, only substitutes like grave accent (0x60), apostrophe (0x27) +# and double quote (0x22). These substitutes look strange; see +# http://www.cl.cam.ac.uk/~mgk25/ucs/quotes.html +# +# This catalog translates grave accent (0x60) and apostrophe (0x27) to +# left single quotation mark (U+2018) and right single quotation mark (U+2019). +# It also translates pairs of apostrophe (0x27) to +# left single quotation mark (U+2018) and right single quotation mark (U+2019) +# and pairs of quotation mark (0x22) to +# left double quotation mark (U+201C) and right double quotation mark (U+201D). +# +# When output to an UTF-8 terminal, the quotation characters appear perfectly. +# When output to an ISO-8859-1 terminal, the single quotation marks are +# transliterated to apostrophes (by iconv in glibc 2.2 or newer) or to +# grave/acute accent (by libiconv), and the double quotation marks are +# transliterated to 0x22. +# When output to an ASCII terminal, the single quotation marks are +# transliterated to apostrophes, and the double quotation marks are +# transliterated to 0x22. +# +# This catalog furthermore displays the text between the quotation marks in +# bold face, assuming the VT100/XTerm escape sequences. +# diff --git a/po/en@quot.header b/po/en@quot.header new file mode 100644 index 00000000..a9647fc3 --- /dev/null +++ b/po/en@quot.header @@ -0,0 +1,22 @@ +# All this catalog "translates" are quotation characters. +# The msgids must be ASCII and therefore cannot contain real quotation +# characters, only substitutes like grave accent (0x60), apostrophe (0x27) +# and double quote (0x22). These substitutes look strange; see +# http://www.cl.cam.ac.uk/~mgk25/ucs/quotes.html +# +# This catalog translates grave accent (0x60) and apostrophe (0x27) to +# left single quotation mark (U+2018) and right single quotation mark (U+2019). +# It also translates pairs of apostrophe (0x27) to +# left single quotation mark (U+2018) and right single quotation mark (U+2019) +# and pairs of quotation mark (0x22) to +# left double quotation mark (U+201C) and right double quotation mark (U+201D). +# +# When output to an UTF-8 terminal, the quotation characters appear perfectly. +# When output to an ISO-8859-1 terminal, the single quotation marks are +# transliterated to apostrophes (by iconv in glibc 2.2 or newer) or to +# grave/acute accent (by libiconv), and the double quotation marks are +# transliterated to 0x22. +# When output to an ASCII terminal, the single quotation marks are +# transliterated to apostrophes, and the double quotation marks are +# transliterated to 0x22. +# diff --git a/po/insert-header.sin b/po/insert-header.sin new file mode 100644 index 00000000..b26de01f --- /dev/null +++ b/po/insert-header.sin @@ -0,0 +1,23 @@ +# Sed script that inserts the file called HEADER before the header entry. +# +# At each occurrence of a line starting with "msgid ", we execute the following +# commands. At the first occurrence, insert the file. At the following +# occurrences, do nothing. The distinction between the first and the following +# occurrences is achieved by looking at the hold space. +/^msgid /{ +x +# Test if the hold space is empty. +s/m/m/ +ta +# Yes it was empty. First occurrence. Read the file. +r HEADER +# Output the file's contents by reading the next line. But don't lose the +# current line while doing this. +g +N +bb +:a +# The hold space was nonempty. Following occurrences. Do nothing. +x +:b +} diff --git a/po/quot.sed b/po/quot.sed new file mode 100644 index 00000000..0122c463 --- /dev/null +++ b/po/quot.sed @@ -0,0 +1,6 @@ +s/"\([^"]*\)"/“\1”/g +s/`\([^`']*\)'/‘\1’/g +s/ '\([^`']*\)' / ‘\1’ /g +s/ '\([^`']*\)'$/ ‘\1’/g +s/^'\([^`']*\)' /‘\1’ /g +s/“”/""/g diff --git a/po/remove-potcdate.sin b/po/remove-potcdate.sin new file mode 100644 index 00000000..2436c49e --- /dev/null +++ b/po/remove-potcdate.sin @@ -0,0 +1,19 @@ +# Sed script that remove the POT-Creation-Date line in the header entry +# from a POT file. +# +# The distinction between the first and the following occurrences of the +# pattern is achieved by looking at the hold space. +/^"POT-Creation-Date: .*"$/{ +x +# Test if the hold space is empty. +s/P/P/ +ta +# Yes it was empty. First occurrence. Remove the line. +g +d +bb +:a +# The hold space was nonempty. Following occurrences. Do nothing. +x +:b +} diff --git a/po/rtmidi-ts.pot b/po/rtmidi-ts.pot new file mode 100644 index 00000000..ff848fa5 --- /dev/null +++ b/po/rtmidi-ts.pot @@ -0,0 +1,527 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR Gary P. Scavone, Tobias Schlemmer +# This file is distributed under the same license as the rtmidi-ts package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: rtmidi-ts 5.0.0\n" +"Report-Msgid-Bugs-To: https://github.com/keinstein/rtmidi\n" +"POT-Creation-Date: 2018-08-13 18:56+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: 8bit\n" + +#: RtMidi.h:129 +msgid "Automatic selection" +msgstr "" + +#: RtMidi.h:130 +msgid "Core MIDI" +msgstr "" + +#: RtMidi.h:131 +msgid "ALSA" +msgstr "" + +#: RtMidi.h:132 +msgid "JACK" +msgstr "" + +#: RtMidi.h:133 +msgid "Windows Multimedia" +msgstr "" + +#: RtMidi.h:134 +msgid "DirectX/Kernel Streaming" +msgstr "" + +#: RtMidi.h:135 +msgid "NULL device" +msgstr "" + +#: RtMidi.h:136 +msgid "All available MIDI systems" +msgstr "" + +#: RtMidi.h:1106 RtMidi.h:1277 RtMidi.h:1490 RtMidi.h:1511 +msgid "Passed NULL pointer." +msgstr "" + +#: RtMidi.h:1308 RtMidi.h:1317 RtMidi.cpp:2596 +msgid "No data in message argument." +msgstr "" + +#: RtMidi.h:1432 +msgid "A NULL pointer has been passed as port descriptor" +msgstr "" + +#: RtMidi.h:1452 RtMidi.h:1531 RtMidi.h:1543 +msgid "No valid MIDI system has been selected." +msgstr "" + +#: RtMidi.h:1473 +msgid "Could not find any valid MIDI system." +msgstr "" + +#: RtMidi.h:1495 +msgid "No valid MIDI system has been found." +msgstr "" + +#: RtMidi.h:1537 +msgid "No data in MIDI message." +msgstr "" + +#: RtMidi.cpp:293 +msgid "" +"No valid MIDI interfaces. I'm using a dummy input interface that never " +"receives anything." +msgstr "" + +#: RtMidi.cpp:322 +msgid "" +"No valid MIDI interfaces. I'm using a dummy output interface that does " +"nothing." +msgstr "" + +#: RtMidi.cpp:396 +#, c-format +msgid "" +"Error formatting the error string:\n" +"'%s'\n" +"Found in %s::%s at \n" +"%s:%d" +msgstr "" + +#: RtMidi.cpp:408 +msgid "Error: could not format the error message" +msgstr "" + +#: RtMidi.cpp:579 RtMidi.cpp:692 +#, c-format +msgid "" +"Support for the selected MIDI system %d has not been compiled into the " +"RtMidi library." +msgstr "" + +#: RtMidi.cpp:597 RtMidi.cpp:709 +msgid "No supported MIDI system has been found." +msgstr "" + +#: RtMidi.cpp:798 RtMidi.cpp:815 +msgid "A callback function is already set." +msgstr "" + +#: RtMidi.cpp:804 RtMidi.cpp:821 +msgid "The callback function value is invalid." +msgstr "" + +#: RtMidi.cpp:832 +msgid "No callback function was set." +msgstr "" + +#: RtMidi.cpp:854 +msgid "" +"Returning an empty MIDI message as all input is handled by a callback " +"function." +msgstr "" + +#: RtMidi.cpp:1585 +msgid "Could not get the unique identifier of a midi endpoint." +msgstr "" + +#: RtMidi.cpp:1595 +msgid "" +"Could not get the endpoint back from the unique identifier of a midi " +"endpoint." +msgstr "" + +#: RtMidi.cpp:1610 +msgid "Could not get the entity of a midi endpoint." +msgstr "" + +#: RtMidi.cpp:1671 RtMidi.cpp:1707 +msgid "Error creating OS X MIDI port because of invalid port flags." +msgstr "" + +#: RtMidi.cpp:1675 RtMidi.cpp:1711 RtMidi.cpp:2254 +msgid "Error creating OS-X MIDI port." +msgstr "" + +#: RtMidi.cpp:1760 +#, c-format +msgid "Error creating OS-X MIDI client object (Error no: %d)." +msgstr "" + +#: RtMidi.cpp:2014 RtMidi.cpp:2080 RtMidi.cpp:3476 RtMidi.cpp:4720 +#: RtMidi.cpp:5931 +msgid "Error: Message queue limit reached." +msgstr "" + +#: RtMidi.cpp:2141 RtMidi.cpp:2235 RtMidi.cpp:2412 RtMidi.cpp:2526 +#: RtMidi.cpp:3623 RtMidi.cpp:3740 RtMidi.cpp:4032 RtMidi.cpp:4194 +#: RtMidi.cpp:4777 RtMidi.cpp:5089 RtMidi.cpp:5161 RtMidi.cpp:6084 +#: RtMidi.cpp:6317 +msgid "A valid connection already exists." +msgstr "" + +#: RtMidi.cpp:2149 RtMidi.cpp:3630 RtMidi.cpp:4784 +msgid "No MIDI input sources found." +msgstr "" + +#: RtMidi.cpp:2158 RtMidi.cpp:2337 RtMidi.cpp:2395 RtMidi.cpp:2426 +#: RtMidi.cpp:3640 RtMidi.cpp:4052 RtMidi.cpp:4989 RtMidi.cpp:5063 +#: RtMidi.cpp:5102 RtMidi.cpp:6182 RtMidi.cpp:6408 +#, c-format +msgid "The 'portNumber' argument (%d) is invalid." +msgstr "" + +#: RtMidi.cpp:2170 +msgid "Error creating OS-X MIDI input port." +msgstr "" + +#: RtMidi.cpp:2181 +msgid "Error getting MIDI input source reference." +msgstr "" + +#: RtMidi.cpp:2192 +msgid "Error connecting OS-X MIDI input port." +msgstr "" + +#: RtMidi.cpp:2214 +msgid "Error creating virtual OS-X MIDI destination." +msgstr "" + +#: RtMidi.cpp:2230 RtMidi.cpp:2521 RtMidi.cpp:3735 RtMidi.cpp:4189 +#: RtMidi.cpp:6078 RtMidi.cpp:6311 +msgid "Data has not been allocated." +msgstr "" + +#: RtMidi.cpp:2240 RtMidi.cpp:2531 +msgid "" +"Core MIDI has been instructed to open a non-Core MIDI port. This doesn't " +"work." +msgstr "" + +#: RtMidi.cpp:2312 RtMidi.cpp:2479 +msgid "Setting client names is not implemented for Mac OS X CoreMIDI." +msgstr "" + +#: RtMidi.cpp:2318 RtMidi.cpp:2485 +msgid "Setting port names is not implemented for Mac OS X CoreMIDI." +msgstr "" + +#: RtMidi.cpp:2420 +msgid "No MIDI output destinations found." +msgstr "" + +#: RtMidi.cpp:2438 +msgid "Error creating OS-X MIDI output port." +msgstr "" + +#: RtMidi.cpp:2449 +msgid "Error getting MIDI output destination reference." +msgstr "" + +#: RtMidi.cpp:2494 +msgid "A virtual output port already exists." +msgstr "" + +#: RtMidi.cpp:2505 +msgid "Error creating OS-X virtual MIDI source." +msgstr "" + +#: RtMidi.cpp:2608 +msgid "message format problem ... not sysex but > 3 bytes?" +msgstr "" + +#: RtMidi.cpp:2627 +msgid "Could not allocate packet list." +msgstr "" + +#: RtMidi.cpp:2636 +msgid "Error sending MIDI to virtual destinations." +msgstr "" + +#: RtMidi.cpp:2645 RtMidi.cpp:4175 +msgid "Error sending MIDI message to port." +msgstr "" + +#: RtMidi.cpp:2810 +msgid "Could not allocate ALSA port info structure." +msgstr "" + +#: RtMidi.cpp:2814 +#, c-format +msgid "Could not get ALSA port information: %s" +msgstr "" + +#: RtMidi.cpp:2820 +#, c-format +msgid "Could not set ALSA port information: %s" +msgstr "" + +#: RtMidi.cpp:2873 RtMidi.cpp:3149 RtMidi.cpp:3684 RtMidi.cpp:3745 +#: RtMidi.cpp:4079 +msgid "Could not allocate ALSA port subscription." +msgstr "" + +#: RtMidi.cpp:2888 RtMidi.cpp:3693 RtMidi.cpp:4090 +msgid "Error making ALSA port connection." +msgstr "" + +#: RtMidi.cpp:3219 RtMidi.cpp:3719 RtMidi.cpp:3868 +msgid "Error starting MIDI input thread!" +msgstr "" + +#: RtMidi.cpp:3257 RtMidi.cpp:3974 +msgid "Error initializing MIDI event parser." +msgstr "" + +#: RtMidi.cpp:3270 +msgid "Error initializing buffer memory." +msgstr "" + +#: RtMidi.cpp:3304 +msgid "MIDI input buffer overrun." +msgstr "" + +#: RtMidi.cpp:3314 +msgid "ALSA returned without providing a MIDI event." +msgstr "" + +#: RtMidi.cpp:3324 +#, c-format +msgid "" +"Unknown MIDI input error.\n" +"The system reports:\n" +"%s" +msgstr "" + +#: RtMidi.cpp:3382 +msgid "Error resizing buffer memory." +msgstr "" + +#: RtMidi.cpp:3455 +msgid "Event parsing error or not a MIDI event." +msgstr "" + +#: RtMidi.cpp:3532 +msgid "Error creating pipe objects." +msgstr "" + +#: RtMidi.cpp:3615 RtMidi.cpp:4024 +msgid "Error looking for port name." +msgstr "" + +#: RtMidi.cpp:3671 +msgid "Error creating ALSA input port." +msgstr "" + +#: RtMidi.cpp:3750 RtMidi.cpp:4204 +msgid "" +"ALSA has been instructed to open a non-ALSA MIDI port. This doesn't work." +msgstr "" + +#: RtMidi.cpp:3834 RtMidi.cpp:4130 +msgid "Error creating ALSA virtual port." +msgstr "" + +#: RtMidi.cpp:3957 +msgid "Error creating ALSA sequencer client object." +msgstr "" + +#: RtMidi.cpp:3981 RtMidi.cpp:4153 +msgid "Error while allocating buffer memory." +msgstr "" + +#: RtMidi.cpp:4040 +msgid "No MIDI output sinks found." +msgstr "" + +#: RtMidi.cpp:4067 +msgid "Error creating ALSA output port." +msgstr "" + +#: RtMidi.cpp:4146 +msgid "ALSA error resizing MIDI event buffer." +msgstr "" + +#: RtMidi.cpp:4167 +msgid "Event parsing error." +msgstr "" + +#: RtMidi.cpp:4199 +msgid "Error allocating ALSA port subscription." +msgstr "" + +#: RtMidi.cpp:4377 +#, c-format +msgid "The port argument %d is invalid." +msgstr "" + +#: RtMidi.cpp:4698 +msgid "Error sending sysex to Midi device." +msgstr "" + +#: RtMidi.cpp:4759 +msgid "No MIDI input devices currently available." +msgstr "" + +#: RtMidi.cpp:4769 +msgid "Failed to initialize a critical section." +msgstr "" + +#: RtMidi.cpp:4793 +#, c-format +msgid "the 'portNumber' argument (%d) is invalid." +msgstr "" + +#: RtMidi.cpp:4805 +msgid "Error creating Windows MM MIDI input port." +msgstr "" + +#: RtMidi.cpp:4822 +msgid "Error initializing data for Windows MM MIDI input port." +msgstr "" + +#: RtMidi.cpp:4832 +msgid "Could not register the input buffer for Windows MM MIDI input port." +msgstr "" + +#: RtMidi.cpp:4842 +msgid "Error starting Windows MM MIDI input port." +msgstr "" + +#: RtMidi.cpp:4853 RtMidi.cpp:5148 +msgid "Virtual ports are not available Windows Multimedia MIDI API." +msgstr "" + +#: RtMidi.cpp:4860 RtMidi.cpp:5156 +msgid "" +"Windows Multimedia (WinMM) has been instructed to open a non-WinMM MIDI " +"port. This doesn't work." +msgstr "" + +#: RtMidi.cpp:4865 +msgid "" +"We are overwriting an existing connection. This is probably a programming " +"error." +msgstr "" + +#: RtMidi.cpp:4870 +msgid "Trying to open a non-input port as input MIDI port. This doesn't work." +msgstr "" + +#: RtMidi.cpp:4884 RtMidi.cpp:5180 +msgid "" +"Some change in the arrangement of MIDI input ports invalidated the port " +"descriptor." +msgstr "" + +#: RtMidi.cpp:4899 +msgid "The handle is invalid. Did you disconnect the device?" +msgstr "" + +#: RtMidi.cpp:4903 RtMidi.cpp:5199 +msgid "" +"The system has no driver for our handle :-(. Did you disconnect the device?" +msgstr "" + +#: RtMidi.cpp:4907 RtMidi.cpp:5203 +msgid "Out of memory." +msgstr "" + +#: RtMidi.cpp:4954 +msgid "Error closing Windows MM MIDI input port." +msgstr "" + +#: RtMidi.cpp:4969 RtMidi.cpp:5135 +msgid "Setting the client name is not supported by Windows MM." +msgstr "" + +#: RtMidi.cpp:4975 RtMidi.cpp:5141 +msgid "Setting the port name is not supported by Windows MM." +msgstr "" + +#: RtMidi.cpp:5041 +msgid "No MIDI output devices currently available." +msgstr "" + +#: RtMidi.cpp:5096 +msgid "No MIDI output destinations found!" +msgstr "" + +#: RtMidi.cpp:5114 +msgid "Error creating Windows MM MIDI output port." +msgstr "" + +#: RtMidi.cpp:5166 +msgid "The port descriptor cannot be used to open an output port." +msgstr "" + +#: RtMidi.cpp:5195 +msgid "The internal handle is invalid. Did you disconnect the device?" +msgstr "" + +#: RtMidi.cpp:5230 +msgid "Message argument is empty." +msgstr "" + +#: RtMidi.cpp:5242 +msgid "Error while allocating sysex message memory." +msgstr "" + +#: RtMidi.cpp:5258 +msgid "Error preparing sysex header." +msgstr "" + +#: RtMidi.cpp:5267 +msgid "Error sending sysex message." +msgstr "" + +#: RtMidi.cpp:5280 +msgid "Message size is greater than 3 bytes (and not sysex)." +msgstr "" + +#: RtMidi.cpp:5296 +msgid "Error sending MIDI message." +msgstr "" + +#: RtMidi.cpp:5535 +msgid "Could not connect to JACK server. Is it runnig?" +msgstr "" + +#: RtMidi.cpp:5767 +msgid "Error opening JACK port subscription." +msgstr "" + +#: RtMidi.cpp:6002 RtMidi.cpp:6248 +msgid "JACK server not running?" +msgstr "" + +#: RtMidi.cpp:6046 RtMidi.cpp:6279 +msgid "Error creating JACK port." +msgstr "" + +#: RtMidi.cpp:6066 RtMidi.cpp:6299 +msgid "Error creating JACK virtual port." +msgstr "" + +#: RtMidi.cpp:6090 RtMidi.cpp:6323 +msgid "" +"JACK has been instructed to open a non-JACK MIDI port. This doesn't work." +msgstr "" + +#: RtMidi.cpp:6173 RtMidi.cpp:6401 +msgid "No ports available." +msgstr "" + +#: RtMidi.cpp:6201 RtMidi.cpp:6429 +msgid "Setting the client name is not supported by JACK." +msgstr "" diff --git a/po/rtmidi.pot b/po/rtmidi.pot new file mode 100644 index 00000000..60eb9ba2 --- /dev/null +++ b/po/rtmidi.pot @@ -0,0 +1,484 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR Gary P. Scavone +# This file is distributed under the same license as the rtmidi package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: rtmidi 2.1.0\n" +"Report-Msgid-Bugs-To: https://github.com/thestk/rtmidi\n" +"POT-Creation-Date: 2016-02-28 19:22+0100\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: 8bit\n" + +#: RtMidi.h:107 +msgid "Automatic selection" +msgstr "" + +#: RtMidi.h:108 +msgid "Core MIDI" +msgstr "" + +#: RtMidi.h:109 +msgid "ALSA" +msgstr "" + +#: RtMidi.h:110 +msgid "JACK" +msgstr "" + +#: RtMidi.h:111 +msgid "Windows Multimedia" +msgstr "" + +#: RtMidi.h:112 +msgid "DirectX/Kernel Streaming" +msgstr "" + +#: RtMidi.h:113 +msgid "NULL device" +msgstr "" + +#: RtMidi.h:114 +msgid "All available MIDI systems" +msgstr "" + +#: RtMidi.h:530 RtMidi.h:692 RtMidi.h:1221 RtMidi.h:1313 +msgid "Passed NULL pointer." +msgstr "" + +#: RtMidi.h:724 RtMidi.cpp:2165 +msgid "No data in message argument." +msgstr "" + +#: RtMidi.h:1083 +msgid "A NULL pointer has been passed as port descriptor" +msgstr "" + +#: RtMidi.h:1115 RtMidi.h:1346 RtMidi.h:1370 RtMidi.h:1383 +msgid "No valid MIDI system has been selected." +msgstr "" + +#: RtMidi.h:1185 +msgid "Could not find any valid MIDI system." +msgstr "" + +#: RtMidi.h:1226 +msgid "No valid MIDI system has been found." +msgstr "" + +#: RtMidi.h:1364 +msgid "No data in MIDI message." +msgstr "" + +#: RtMidi.h:1610 RtMidi.h:1632 +msgid "MidiInDummy: This class provides no functionality." +msgstr "" + +#: RtMidi.cpp:87 +#, c-format +msgid "" +"Error formatting the error string:\n" +"'%s'\n" +"Found in %s::%s at \n" +"%s:%d" +msgstr "" + +#: RtMidi.cpp:99 +msgid "Error: could not format the error message" +msgstr "" + +#: RtMidi.cpp:267 RtMidi.cpp:370 +#, c-format +msgid "" +"Support for the selected MIDI system %d has not been compiled into the " +"RtMidi library." +msgstr "" + +#: RtMidi.cpp:285 RtMidi.cpp:387 +msgid "No supported MIDI system has been found." +msgstr "" + +#: RtMidi.cpp:476 RtMidi.cpp:493 +msgid "A callback function is already set." +msgstr "" + +#: RtMidi.cpp:482 RtMidi.cpp:499 +msgid "The callback function value is invalid." +msgstr "" + +#: RtMidi.cpp:510 +msgid "No callback function was set." +msgstr "" + +#: RtMidi.cpp:532 +msgid "" +"Returning an empty MIDI message as all input is handled by a callback " +"function." +msgstr "" + +#: RtMidi.cpp:1187 +msgid "Could not get the unique identifier of a midi endpoint." +msgstr "" + +#: RtMidi.cpp:1197 +msgid "" +"Could not get the endpoint back from the unique identifier of a midi " +"endpoint." +msgstr "" + +#: RtMidi.cpp:1212 +msgid "Could not get the entity of a midi endpoint." +msgstr "" + +#: RtMidi.cpp:1277 RtMidi.cpp:1317 +msgid "Error creating OS X MIDI port because of invalid port flags." +msgstr "" + +#: RtMidi.cpp:1281 RtMidi.cpp:1321 RtMidi.cpp:1862 +msgid "Error creating OS-X MIDI port." +msgstr "" + +#: RtMidi.cpp:1374 +msgid "Error creating OS-X MIDI client object." +msgstr "" + +#: RtMidi.cpp:1630 RtMidi.cpp:1700 RtMidi.cpp:2983 RtMidi.cpp:4162 +#: RtMidi.cpp:5236 +msgid "Error: Message queue limit reached." +msgstr "" + +#: RtMidi.cpp:1751 RtMidi.cpp:1843 RtMidi.cpp:2001 RtMidi.cpp:2094 +#: RtMidi.cpp:3127 RtMidi.cpp:3244 RtMidi.cpp:3512 RtMidi.cpp:3660 +#: RtMidi.cpp:4218 RtMidi.cpp:4521 RtMidi.cpp:4580 RtMidi.cpp:5424 +#: RtMidi.cpp:5641 +msgid "A valid connection already exists." +msgstr "" + +#: RtMidi.cpp:1759 RtMidi.cpp:3134 RtMidi.cpp:4225 +msgid "No MIDI input sources found." +msgstr "" + +#: RtMidi.cpp:1768 RtMidi.cpp:1926 RtMidi.cpp:1984 RtMidi.cpp:2015 +#: RtMidi.cpp:3144 RtMidi.cpp:3532 RtMidi.cpp:4413 RtMidi.cpp:4491 +#: RtMidi.cpp:4534 RtMidi.cpp:5520 RtMidi.cpp:5732 +#, c-format +msgid "The 'portNumber' argument (%d) is invalid." +msgstr "" + +#: RtMidi.cpp:1780 +msgid "Error creating OS-X MIDI input port." +msgstr "" + +#: RtMidi.cpp:1790 +msgid "Error getting MIDI input source reference." +msgstr "" + +#: RtMidi.cpp:1800 +msgid "Error connecting OS-X MIDI input port." +msgstr "" + +#: RtMidi.cpp:1822 +msgid "Error creating virtual OS-X MIDI destination." +msgstr "" + +#: RtMidi.cpp:1838 RtMidi.cpp:2089 RtMidi.cpp:3239 RtMidi.cpp:3655 +#: RtMidi.cpp:5418 RtMidi.cpp:5635 +msgid "Data has not been allocated." +msgstr "" + +#: RtMidi.cpp:1848 RtMidi.cpp:2099 +msgid "" +"Core MIDI has been instructed to open a non-Core MIDI port. This doesn't " +"work." +msgstr "" + +#: RtMidi.cpp:2009 +msgid "No MIDI output destinations found." +msgstr "" + +#: RtMidi.cpp:2027 +msgid "Error creating OS-X MIDI output port." +msgstr "" + +#: RtMidi.cpp:2037 +msgid "Error getting MIDI output destination reference." +msgstr "" + +#: RtMidi.cpp:2062 +msgid "A virtual output port already exists." +msgstr "" + +#: RtMidi.cpp:2073 +msgid "Error creating OS-X virtual MIDI source." +msgstr "" + +#: RtMidi.cpp:2177 +msgid "message format problem ... not sysex but > 3 bytes?" +msgstr "" + +#: RtMidi.cpp:2196 +msgid "Could not allocate packet list." +msgstr "" + +#: RtMidi.cpp:2205 +msgid "Error sending MIDI to virtual destinations." +msgstr "" + +#: RtMidi.cpp:2214 RtMidi.cpp:3641 +msgid "Error sending MIDI message to port." +msgstr "" + +#: RtMidi.cpp:2418 RtMidi.cpp:2681 RtMidi.cpp:3188 RtMidi.cpp:3249 +#: RtMidi.cpp:3558 +msgid "Could not allocate ALSA port subscription." +msgstr "" + +#: RtMidi.cpp:2433 RtMidi.cpp:3197 RtMidi.cpp:3568 +msgid "Error making ALSA port connection." +msgstr "" + +#: RtMidi.cpp:2503 RtMidi.cpp:3439 +msgid "Error creating ALSA sequencer client object." +msgstr "" + +#: RtMidi.cpp:2743 RtMidi.cpp:3223 RtMidi.cpp:3372 +msgid "Error starting MIDI input thread!" +msgstr "" + +#: RtMidi.cpp:2781 RtMidi.cpp:3456 +msgid "Error initializing MIDI event parser." +msgstr "" + +#: RtMidi.cpp:2794 +msgid "Error initializing buffer memory." +msgstr "" + +#: RtMidi.cpp:2828 +msgid "MIDI input buffer overrun." +msgstr "" + +#: RtMidi.cpp:2838 +msgid "ALSA returned without providing a MIDI event." +msgstr "" + +#: RtMidi.cpp:2848 +#, c-format +msgid "" +"Unknown MIDI input error.\n" +"The system reports:\n" +"%s" +msgstr "" + +#: RtMidi.cpp:2906 +msgid "Error resizing buffer memory." +msgstr "" + +#: RtMidi.cpp:2957 +msgid "Event parsing error or not a MIDI event." +msgstr "" + +#: RtMidi.cpp:3038 +msgid "Error creating pipe objects." +msgstr "" + +#: RtMidi.cpp:3119 RtMidi.cpp:3504 +msgid "Error looking for port name." +msgstr "" + +#: RtMidi.cpp:3175 +msgid "Error creating ALSA input port." +msgstr "" + +#: RtMidi.cpp:3254 RtMidi.cpp:3670 +msgid "" +"ALSA has been instructed to open a non-ALSA MIDI port. This doesn't work." +msgstr "" + +#: RtMidi.cpp:3338 RtMidi.cpp:3595 +msgid "Error creating ALSA virtual port." +msgstr "" + +#: RtMidi.cpp:3463 RtMidi.cpp:3619 +msgid "Error while allocating buffer memory." +msgstr "" + +#: RtMidi.cpp:3520 +msgid "No MIDI output sinks found." +msgstr "" + +#: RtMidi.cpp:3547 +msgid "Error creating ALSA output port." +msgstr "" + +#: RtMidi.cpp:3612 +msgid "ALSA error resizing MIDI event buffer." +msgstr "" + +#: RtMidi.cpp:3633 +msgid "Event parsing error." +msgstr "" + +#: RtMidi.cpp:3665 +msgid "Error allocating ALSA port subscription." +msgstr "" + +#: RtMidi.cpp:3815 +#, c-format +msgid "The port argument %d is invalid." +msgstr "" + +#: RtMidi.cpp:4137 +msgid "Error sending sysex to Midi device." +msgstr "" + +#: RtMidi.cpp:4200 +msgid "No MIDI input devices currently available." +msgstr "" + +#: RtMidi.cpp:4210 +msgid "Failed to initialize a critical section." +msgstr "" + +#: RtMidi.cpp:4234 +#, c-format +msgid "the 'portNumber' argument (%d) is invalid." +msgstr "" + +#: RtMidi.cpp:4246 +msgid "Error creating Windows MM MIDI input port." +msgstr "" + +#: RtMidi.cpp:4262 +msgid "Error initializing data for Windows MM MIDI input port." +msgstr "" + +#: RtMidi.cpp:4271 +msgid "Could not register the input buffer for Windows MM MIDI input port." +msgstr "" + +#: RtMidi.cpp:4280 +msgid "Error starting Windows MM MIDI input port." +msgstr "" + +#: RtMidi.cpp:4291 RtMidi.cpp:4567 +msgid "Virtual ports are not available Windows Multimedia MIDI API." +msgstr "" + +#: RtMidi.cpp:4298 RtMidi.cpp:4575 +msgid "" +"Windows Multimedia (WinMM) has been instructed to open a non-WinMM MIDI " +"port. This doesn't work." +msgstr "" + +#: RtMidi.cpp:4303 +msgid "" +"We are overwriting an existing connection. This is probably a programming " +"error." +msgstr "" + +#: RtMidi.cpp:4308 +msgid "Trying to open a non-input port as input MIDI port. This doesn't work." +msgstr "" + +#: RtMidi.cpp:4322 RtMidi.cpp:4599 +msgid "" +"Some change in the arrangement of MIDI input ports invalidated the port " +"descriptor." +msgstr "" + +#: RtMidi.cpp:4337 +msgid "The handle is invalid. Did you disconnect the device?" +msgstr "" + +#: RtMidi.cpp:4341 RtMidi.cpp:4618 +msgid "" +"The system has no driver for our handle :-(. Did you disconnect the device?" +msgstr "" + +#: RtMidi.cpp:4345 RtMidi.cpp:4622 +msgid "Out of memory." +msgstr "" + +#: RtMidi.cpp:4391 +msgid "Error closing Windows MM MIDI input port." +msgstr "" + +#: RtMidi.cpp:4469 +msgid "No MIDI output devices currently available." +msgstr "" + +#: RtMidi.cpp:4528 +msgid "No MIDI output destinations found!" +msgstr "" + +#: RtMidi.cpp:4546 +msgid "Error creating Windows MM MIDI output port." +msgstr "" + +#: RtMidi.cpp:4585 +msgid "The port descriptor cannot be used to open an output port." +msgstr "" + +#: RtMidi.cpp:4614 +msgid "The internal handle is invalid. Did you disconnect the device?" +msgstr "" + +#: RtMidi.cpp:4650 +msgid "Message argument is empty." +msgstr "" + +#: RtMidi.cpp:4662 +msgid "Error while allocating sysex message memory." +msgstr "" + +#: RtMidi.cpp:4678 +msgid "Error preparing sysex header." +msgstr "" + +#: RtMidi.cpp:4687 +msgid "Error sending sysex message." +msgstr "" + +#: RtMidi.cpp:4700 +msgid "Message size is greater than 3 bytes (and not sysex)." +msgstr "" + +#: RtMidi.cpp:4716 +msgid "Error sending MIDI message." +msgstr "" + +#: RtMidi.cpp:4947 +msgid "Could not connect to JACK server. Is it runnig?" +msgstr "" + +#: RtMidi.cpp:5158 +msgid "Error opening JACK port subscription." +msgstr "" + +#: RtMidi.cpp:5342 RtMidi.cpp:5570 +msgid "JACK server not running?" +msgstr "" + +#: RtMidi.cpp:5386 RtMidi.cpp:5603 +msgid "Error creating JACK port." +msgstr "" + +#: RtMidi.cpp:5406 RtMidi.cpp:5623 +msgid "Error creating JACK virtual port." +msgstr "" + +#: RtMidi.cpp:5430 RtMidi.cpp:5647 +msgid "" +"JACK has been instructed to open a non-JACK MIDI port. This doesn't work." +msgstr "" + +#: RtMidi.cpp:5513 RtMidi.cpp:5725 +msgid "No ports available." +msgstr "" diff --git a/readme b/readme deleted file mode 100644 index 69f095b0..00000000 --- a/readme +++ /dev/null @@ -1,59 +0,0 @@ -RtMidi - a set of C++ classes that provide a common API for realtime MIDI input/output across Linux (ALSA & JACK), Macintosh OS X (CoreMidi & JACK) and Windows (Multimedia & Kernel Streaming). - -By Gary P. Scavone, 2003-2014. - -This distribution of RtMidi contains the following: - -doc: RtMidi documentation (see doc/html/index.html) -tests: example RtMidi programs - -On unix systems, type "./configure" in the top level directory, then "make" in the tests/ directory to compile the test programs. In Windows, open the Visual C++ workspace file located in the tests/ directory. - -If you checked out the code from git, please run "autoconf" before "./configure". - -OVERVIEW: - -RtMidi is a set of C++ classes (RtMidiIn, RtMidiOut, and API specific classes) that provide a common API (Application Programming Interface) for realtime MIDI input/output across Linux (ALSA, JACK), Macintosh OS X (CoreMidi, JACK), and Windows (Multimedia Library, Kernel Streming) operating systems. RtMidi significantly simplifies the process of interacting with computer MIDI hardware and software. It was designed with the following goals: - - - object oriented C++ design - - simple, common API across all supported platforms - - only one header and one source file for easy inclusion in programming projects - - MIDI device enumeration - -MIDI input and output functionality are separated into two classes, RtMidiIn and RtMidiOut. Each class instance supports only a single MIDI connection. RtMidi does not provide timing functionality (i.e., output messages are sent immediately). Input messages are timestamped with delta times in seconds (via a double floating point type). MIDI data is passed to the user as raw bytes using an std::vector. - -FURTHER READING: - -For complete documentation on RtMidi, see the doc directory of the distribution or surf to http://music.mcgill.ca/~gary/rtmidi/. - - -LEGAL AND ETHICAL: - -The RtMidi license is similar to the the MIT License, with the added "feature" that modifications be sent to the developer. - - RtMidi: realtime MIDI i/o C++ classes - Copyright (c) 2003-2014 Gary P. Scavone - - Permission is hereby granted, free of charge, to any person - obtaining a copy of this software and associated documentation files - (the "Software"), to deal in the Software without restriction, - including without limitation the rights to use, copy, modify, merge, - publish, distribute, sublicense, and/or sell copies of the Software, - and to permit persons to whom the Software is furnished to do so, - subject to the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - Any person wishing to distribute modifications to the Software is - asked to send the modifications to the original developer so that - they can be incorporated into the canonical version. This is, - however, not a binding provision of this license. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR - ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF - CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/rtmidi-config.in b/rtmidi-config.in index 34d2a25d..0cff7f37 100644 --- a/rtmidi-config.in +++ b/rtmidi-config.in @@ -5,15 +5,20 @@ if (test "x$#" != "x1") ; then fi LIBRARY="@LIBS@" -CXXFLAGS="@CXXFLAGS@" -CPPFLAGS="@CPPFLAGS@" +CXXFLAGS="@CXXFLAGS@ @RTMIDI_API@ @RTMIDI_API_CFLAGS@" +CPPFLAGS="@CPPFLAGS@ @RTMIDI_API@ @RTMIDI_API_CFLAGS@" + +prefix=@prefix@ +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include/rtmidi@rtmidi_suffix@ if (test "x$1" = "x--libs") ; then - echo "$LIBRARY -lrtmidi" + echo "$LIBRARY -L${libdir} -lrtmidi@rtmidi_suffix@" elif (test "x$1" = "x--cxxflags") ; then - echo "$CXXFLAGS" + echo "$CXXFLAGS -I${includedir}" elif (test "x$1" = "x--cppflags") ; then - echo "$CPPFLAGS" + echo "$CPPFLAGS -I${includedir}" else echo "Unknown option: $1" fi diff --git a/rtmidi-m4/ac_lib_winmm.m4 b/rtmidi-m4/ac_lib_winmm.m4 new file mode 100644 index 00000000..8d7089a1 --- /dev/null +++ b/rtmidi-m4/ac_lib_winmm.m4 @@ -0,0 +1,43 @@ +# AC_LIB_WINMM(FUNCTION, +# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND], +# [OTHER-LIBRARIES]) +# ------------------------------------------------------ +# +# Use a cache variable name containing both the library and function name, +# because the test really is for library $1 defining function $2, not +# just for library $1. Separate tests with the same $1 and different $2s +# may have different results. +# +# Note that using directly AS_VAR_PUSHDEF([ac_Lib], [ac_cv_lib_$1_$2]) +# is asking for troubles, since AC_CHECK_LIB($lib, fun) would give +# ac_cv_lib_$lib_fun, which is definitely not what was meant. Hence +# the AS_LITERAL_IF indirection. +# +# FIXME: This macro is extremely suspicious. It DEFINEs unconditionally, +# whatever the FUNCTION, in addition to not being a *S macro. Note +# that the cache does depend upon the function we are looking for. +# +# It is on purpose we used `ac_check_lib_save_LIBS' and not just +# `ac_save_LIBS': there are many macros which don't want to see `LIBS' +# changed but still want to use AC_CHECK_LIB, so they save `LIBS'. +# And ``ac_save_LIBS' is too tempting a name, so let's leave them some +# freedom. +AC_DEFUN([AC_LIB_WINMM],[ + m4_ifval([$2], , [AH_CHECK_LIB([winmm])])dnl + AC_CACHE_CHECK([for $1 in -lwinmm], [ac_cv_lib_winmm_$1],[ + ac_check_lib_save_LIBS="$LIBS" + LIBS="-lwinmm $4 $LIBS" + AC_LINK_IFELSE([AC_LANG_PROGRAM([ +#include "windows.h" +#include "mmsystem.h" + ],[[void * x= &$1;]])], + [ac_cv_lib_winmm_$1=yes], + [ac_cv_lib_winmm_$1=no]) + LIBS=$ac_check_lib_save_LIBS]) + AS_IF([test "${ac_cv_lib_winmm_$1}" = yes], + [m4_default([$2], + [AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_LIBWINMM)) + LIBS="-lwinmm $LIBS" + ])],[$3] + )dnl +])# AC_CHECK_LIB diff --git a/rtmidi-m4/ax_check_fallthrough_syntax.m4 b/rtmidi-m4/ax_check_fallthrough_syntax.m4 new file mode 100644 index 00000000..583ad827 --- /dev/null +++ b/rtmidi-m4/ax_check_fallthrough_syntax.m4 @@ -0,0 +1,90 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_check_fallthrough_syntax.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_CHECK_FALLTHROUGH_SYNTAX([ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT]) +# +# DESCRIPTION +# +# Check whether the given FLAG works with the current language's compiler +# or gives an error. (Warnings, however, are ignored) +# +# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on +# success/failure. +# +# If EXTRA-FLAGS is defined, it is added to the current language's default +# flags (e.g. CFLAGS) when the check is done. The check is thus made with +# the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to +# force the compiler to issue an error when a bad flag is given. +# +# INPUT gives an alternative input source to AC_COMPILE_IFELSE. +# +# LICENSE +# +# Copyright (c) 2008 Guido U. Draheim +# Copyright (c) 2011 Maarten Bosmans +# +# 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 3 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, see . +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +#serial 1 +AC_DEFUN([_AX_CHECK_FALLTHROUGH_SYNTAX_COMPILE], +[ + AC_COMPILE_IFELSE([ + AC_LANG_PROGRAM([ +int j; +void test(int i) { + switch (i) { + case 1: j = 3; + $1 ; + case 2: j++; + } +} + ],[])],$2,$3) +]) + +AC_DEFUN([AX_CHECK_FALLTHROUGH_SYNTAX], +[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF +AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]_fallthrough_syntax_$1])dnl +AC_CACHE_CHECK([syntax of _AC_LANG fallthrough attribute ], CACHEVAR, [ + ax_check_save_flags_fallthrough="$[]_AC_LANG_PREFIX[]FLAGS" + _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $1" + AS_UNSET([ax_cv_check_[]_AC_LANG_ABBREV[]flags___Werror]) + AX_CHECK_COMPILE_FLAG([-Werror],[_AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS -Werror"]) + AS_VAR_SET(CACHEVAR,[]) + for flag in "[[[fallthrough]]]" "[[[gnu::fallthrough]]]" "__attribute__((fallthrough))" + do + _AX_CHECK_FALLTHROUGH_SYNTAX_COMPILE([$flag],[ + AS_VAR_SET(CACHEVAR,[$flag]) + break; + ],[:]) + done + _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags_fallthrough + ]) +AS_VAR_POPDEF([CACHEVAR])dnl +])dnl AX_CHECK_FALLTHROUGH_SYNTAX diff --git a/rtmidi-m4/rtmidi_lib_alsa.m4 b/rtmidi-m4/rtmidi_lib_alsa.m4 new file mode 100644 index 00000000..5d4ee1eb --- /dev/null +++ b/rtmidi-m4/rtmidi_lib_alsa.m4 @@ -0,0 +1,46 @@ +# AC_LIB_ALSA(FUNCTION, +# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND], +# [OTHER-LIBRARIES]) +# ------------------------------------------------------ +# +# Use a cache variable name containing both the library and function name, +# because the test really is for library $1 defining function $2, not +# just for library $1. Separate tests with the same $1 and different $2s +# may have different results. +# +# Note that using directly AS_VAR_PUSHDEF([ac_Lib], [ac_cv_lib_$1_$2]) +# is asking for troubles, since AC_CHECK_LIB($lib, fun) would give +# ac_cv_lib_$lib_fun, which is definitely not what was meant. Hence +# the AS_LITERAL_IF indirection. +# +# FIXME: This macro is extremely suspicious. It DEFINEs unconditionally, +# whatever the FUNCTION, in addition to not being a *S macro. Note +# that the cache does depend upon the function we are looking for. +# +# It is on purpose we used `ac_check_lib_save_LIBS' and not just +# `ac_save_LIBS': there are many macros which don't want to see `LIBS' +# changed but still want to use AC_CHECK_LIB, so they save `LIBS'. +# And ``ac_save_LIBS' is too tempting a name, so let's leave them some +# freedom. +AC_DEFUN([RTMIDI_LIB_ALSA],[ + AC_LANG_PUSH(C++) + rtmidi_have_alsa=no + AM_PATH_ALSA(1.0.27,[rtmidi_have_alsa=yes],[rtmidi_have_alsa=no]) + AS_IF(test "x$rtmidi_have_alsa" = "xyes",,[ + AC_CHECK_LIB(pthread, pthread_create,[ + AC_MSG_WARN([RtMidi requires the pthread library! Disabling Alsa!]) + rtmidi_have_alsa=no + ]) + ]) + AS_IF(test "x$rtmidi_have_alsa" = "xyes",[ + RTMIDI_API="$RTMIDI_API -D__LINUX_ALSA__" + RTMIDI_LIB_CFLAGS="$RTMIDI_LIB_CFLAGS $ALSA_CFLAGS" + RTMIDI_LIBS="$RTMIDI_LIBS $ALSA_LIBS" + rtmidi_pkconfig_requirements="$rtmidi_pkconfig_requirements alsa" + RTMIDI_HAVE_VIRTUAL_DEVICES=yes + $1 + ],[ + m4_default([$2],[AC_MSG_WARN(ALSA support requires the asound and pthread libraries!)]) + ]) + AC_LANG_POP(C++) +])dnl RTMIDI_LIB_ALSA diff --git a/rtmidi-m4/rtmidi_lib_coremidi.m4 b/rtmidi-m4/rtmidi_lib_coremidi.m4 new file mode 100644 index 00000000..d4eb29e5 --- /dev/null +++ b/rtmidi-m4/rtmidi_lib_coremidi.m4 @@ -0,0 +1,46 @@ +# AC_LIB_COREMIDI(FUNCTION, +# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND], +# [OTHER-LIBRARIES]) +# ------------------------------------------------------ +# +# Use a cache variable name containing both the library and function name, +# because the test really is for library $1 defining function $2, not +# just for library $1. Separate tests with the same $1 and different $2s +# may have different results. +# +# Note that using directly AS_VAR_PUSHDEF([ac_Lib], [ac_cv_lib_$1_$2]) +# is asking for troubles, since AC_CHECK_LIB($lib, fun) would give +# ac_cv_lib_$lib_fun, which is definitely not what was meant. Hence +# the AS_LITERAL_IF indirection. +# +# FIXME: This macro is extremely suspicious. It DEFINEs unconditionally, +# whatever the FUNCTION, in addition to not being a *S macro. Note +# that the cache does depend upon the function we are looking for. +# +# It is on purpose we used `ac_check_lib_save_LIBS' and not just +# `ac_save_LIBS': there are many macros which don't want to see `LIBS' +# changed but still want to use AC_CHECK_LIB, so they save `LIBS'. +# And ``ac_save_LIBS' is too tempting a name, so let's leave them some +# freedom. +AC_DEFUN([RTMIDI_LIB_COREMIDI],[ + AC_LANG_PUSH(C++) + ac_cv_rtmidi_lib_coremidi="$LIBS" + LIBS="$LIBS -framework CoreMIDI -framework CoreFoundation -framework CoreAudio" + rtmidi_have_coremidi=no + AC_CHECK_HEADER(CoreMIDI/CoreMIDI.h, [rtmidi_have_coremidi=yes]) + AS_IF(test "x$rtmidi_have_coremidi" = "xyes",[ + AC_CHECK_LIB(pthread, pthread_create, ,[ + rtmidi_have_coremidi=no + AC_MSG_WARN([RtMidi requires the pthread library!]) + ]) + ]) + AS_IF(test "x$rtmidi_have_coremidi" = "xyes",[ + RTMIDI_API="$RTMIDI_API -D__MACOSX_COREMIDI__" + RTMIDI_LIBS="$RTMIDI_LIBS -framework CoreMIDI -framework CoreFoundation -framework CoreAudio" + $1 + ], [ + m4_default([$2],[AC_MSG_ERROR(CoreMIDI header files not found!)] ) + ]) + LIBS="$ac_cv_rtmidi_lib_coremidi" + AC_LANG_POP(C++) +])dnl RTMIDI_LIB_COREMIDI diff --git a/rtmidi-m4/rtmidi_lib_jack.m4 b/rtmidi-m4/rtmidi_lib_jack.m4 new file mode 100644 index 00000000..2523f2bc --- /dev/null +++ b/rtmidi-m4/rtmidi_lib_jack.m4 @@ -0,0 +1,69 @@ +# AC_LIB_JACK(FUNCTION, +# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND], +# [OTHER-LIBRARIES]) +# ------------------------------------------------------ +# +# Use a cache variable name containing both the library and function name, +# because the test really is for library $1 defining function $2, not +# just for library $1. Separate tests with the same $1 and different $2s +# may have different results. +# +# Note that using directly AS_VAR_PUSHDEF([ac_Lib], [ac_cv_lib_$1_$2]) +# is asking for troubles, since AC_CHECK_LIB($lib, fun) would give +# ac_cv_lib_$lib_fun, which is definitely not what was meant. Hence +# the AS_LITERAL_IF indirection. +# +# FIXME: This macro is extremely suspicious. It DEFINEs unconditionally, +# whatever the FUNCTION, in addition to not being a *S macro. Note +# that the cache does depend upon the function we are looking for. +# +# It is on purpose we used `ac_check_lib_save_LIBS' and not just +# `ac_save_LIBS': there are many macros which don't want to see `LIBS' +# changed but still want to use AC_CHECK_LIB, so they save `LIBS'. +# And ``ac_save_LIBS' is too tempting a name, so let's leave them some +# freedom. +AC_DEFUN([RTMIDI_LIB_JACK],[ + AC_REQUIRE([PKG_PROG_PKG_CONFIG]) + AC_LANG_PUSH(C++) + rtmidi_have_jack=no + PKG_CHECK_MODULES(JACK,[jack],[rtmidi_have_jack=yes],[rtmidi_have_jack=no]) + AS_IF(test "x$rtmidi_have_jack" = "xyes",[ + rtmidi_save_libs="$LIBS" + LIBS="$LIBS $JACK_LIBS" + AC_TRY_LINK([ +#include + ],[ +return jack_client_close(NULL); + ],,[ + rtmidi_have_jack=no + AC_MSG_WARN([JACK is not usable. Disabling JACK.]) + ]) + LIBS="$rtmidi_save_libs" + ]) + AS_IF(test "x$rtmidi_have_jack" = "xyes",[ + AC_CHECK_LIB(pthread, pthread_create, ,[ + rtmidi_have_jack=no + AC_MSG_WARN([RtMidi requires the pthread library disabling JACK!]) + ]) + ]) + AS_IF(test "x$rtmidi_have_jack" = "xyes",[ + AC_CHECK_LIB(jack, jack_port_rename, AC_DEFINE(JACK_HAS_PORT_RENAME), ) + rtmidi_save_libs="$LIBS" + LIBS="$LIBS $JACK_LIBS" + AC_TRY_LINK([ +#include + ],[ +return jack_port_uuid(NULL); + ],[RTMIDI_API="$RTMIDI_API -D__UNIX_JACK_HAS_UUID__"]) + LIBS="$rtmidi_save_libs" + RTMIDI_API="$RTMIDI_API -D__UNIX_JACK__" + RTMIDI_LIB_CFLAGS="$RTMIDI_LIB_CFLAGS $JACK_CFLAGS" + RTMIDI_LIBS="$RTMIDI_LIBS $JACK_LIBS" + rtmidi_pkconfig_requirements="$rtmidi_pkconfig_requirements jack" + RTMIDI_HAVE_VIRTUAL_DEVICES=yes + $1 + ],[ + m4_default([$2],[AC_MSG_ERROR(JACK support requires the jack library!)]) + ]) + AC_LANG_POP(C++) +])dnl RTMIDI_LIB_JACK diff --git a/rtmidi-m4/rtmidi_lib_winks.m4 b/rtmidi-m4/rtmidi_lib_winks.m4 new file mode 100644 index 00000000..d440476c --- /dev/null +++ b/rtmidi-m4/rtmidi_lib_winks.m4 @@ -0,0 +1,47 @@ +# AC_LIB_WINKS(FUNCTION, +# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND], +# [OTHER-LIBRARIES]) +# ------------------------------------------------------ +# +# Use a cache variable name containing both the library and function name, +# because the test really is for library $1 defining function $2, not +# just for library $1. Separate tests with the same $1 and different $2s +# may have different results. +# +# Note that using directly AS_VAR_PUSHDEF([ac_Lib], [ac_cv_lib_$1_$2]) +# is asking for troubles, since AC_CHECK_LIB($lib, fun) would give +# ac_cv_lib_$lib_fun, which is definitely not what was meant. Hence +# the AS_LITERAL_IF indirection. +# +# FIXME: This macro is extremely suspicious. It DEFINEs unconditionally, +# whatever the FUNCTION, in addition to not being a *S macro. Note +# that the cache does depend upon the function we are looking for. +# +# It is on purpose we used `ac_check_lib_save_LIBS' and not just +# `ac_save_LIBS': there are many macros which don't want to see `LIBS' +# changed but still want to use AC_CHECK_LIB, so they save `LIBS'. +# And ``ac_save_LIBS' is too tempting a name, so let's leave them some +# freedom. +AC_DEFUN([RTMIDI_LIB_WINKS],[ + AC_LANG_PUSH(C++) + AC_CACHE_CHECK([for midiOutGetNumDevs in -lksuser], [ac_cv_lib_winks],[ + ac_check_lib_save_LIBS="$LIBS" + LIBS="-lsetupapi -lksuser $LIBS" + AC_LINK_IFELSE([AC_LANG_PROGRAM([ +#include "windows.h" +#include "mmsystem.h" + ],[[void * x= &midiOutGetNumDevs;]])], + [ac_cv_lib_winks=yes], + [ac_cv_lib_winks=no]) + LIBS=$ac_check_lib_save_LIBS]) + AS_IF([test "${ac_cv_lib_winks}" = yes], + [ + AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_LIBWINKS),1,[Define this to 1 if windows kernel streaming libraries are present]) + RTMIDI_LIBS="$RTMIDI_LIBS -lsetupapi -lksuser" + RTMIDI_API="$RTMIDI_API -D__WINDOWS_KS__" + $1 + ],[ + m4_default([$2],[AC_MSG_ERROR(Windows mulitmedia library not found!)] ) + ]) + AC_LANG_POP(C++) +])dnl RTMIDI_LIB_WINKS diff --git a/rtmidi-m4/rtmidi_lib_winmm.m4 b/rtmidi-m4/rtmidi_lib_winmm.m4 new file mode 100644 index 00000000..9be4513d --- /dev/null +++ b/rtmidi-m4/rtmidi_lib_winmm.m4 @@ -0,0 +1,47 @@ +# AC_LIB_WINMM(FUNCTION, +# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND], +# [OTHER-LIBRARIES]) +# ------------------------------------------------------ +# +# Use a cache variable name containing both the library and function name, +# because the test really is for library $1 defining function $2, not +# just for library $1. Separate tests with the same $1 and different $2s +# may have different results. +# +# Note that using directly AS_VAR_PUSHDEF([ac_Lib], [ac_cv_lib_$1_$2]) +# is asking for troubles, since AC_CHECK_LIB($lib, fun) would give +# ac_cv_lib_$lib_fun, which is definitely not what was meant. Hence +# the AS_LITERAL_IF indirection. +# +# FIXME: This macro is extremely suspicious. It DEFINEs unconditionally, +# whatever the FUNCTION, in addition to not being a *S macro. Note +# that the cache does depend upon the function we are looking for. +# +# It is on purpose we used `ac_check_lib_save_LIBS' and not just +# `ac_save_LIBS': there are many macros which don't want to see `LIBS' +# changed but still want to use AC_CHECK_LIB, so they save `LIBS'. +# And ``ac_save_LIBS' is too tempting a name, so let's leave them some +# freedom. +AC_DEFUN([RTMIDI_LIB_WINMM],[ + AC_LANG_PUSH(C++) + AC_CACHE_CHECK([for midiOutGetNumDevs in -lwinmm], [ac_cv_lib_winmm],[ + ac_check_lib_save_LIBS="$LIBS" + LIBS="-lwinmm $LIBS" + AC_LINK_IFELSE([AC_LANG_PROGRAM([ +#include "windows.h" +#include "mmsystem.h" + ],[[int x= midiOutGetNumDevs();]])], + [ac_cv_lib_winmm=yes], + [ac_cv_lib_winmm=no]) + LIBS=$ac_check_lib_save_LIBS]) + AS_IF([test "${ac_cv_lib_winmm}" = yes], + [ + AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_LIBWINMM)) + RTMIDI_LIBS="$RTMIDI_LIBS -lwinmm" + RTMIDI_API="$RTMIDI_API -D__WINDOWS_MM__" + $1 + ],[ + m4_default([$2],[AC_MSG_ERROR(Windows mulitmedia library not found!)] ) + ]) + AC_LANG_POP(C++) +])dnl RTMIDI_LIB_WINMM diff --git a/rtmidi.pc.in b/rtmidi.pc.in new file mode 100644 index 00000000..2d017c89 --- /dev/null +++ b/rtmidi.pc.in @@ -0,0 +1,12 @@ +prefix=@prefix@ +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include/rtmidi@rtmidi_suffix@ + +Name: librtmidi@rtmidi_suffix@ +Description: RtMidi@rtmidi_suffix@ - a set of C++ classes that provide a common API for realtime MIDI input/output +Version: @PACKAGE_VERSION@ +Requires: @rtmidi_pkconfig_requirements@ +Libs: -L${libdir} -lrtmidi@rtmidi_suffix@ +Libs.private: -lpthread +Cflags: -pthread -I${includedir} @RTMIDI_API@ diff --git a/rtmidi_c.cpp b/rtmidi_c.cpp new file mode 100644 index 00000000..d4a0b0fa --- /dev/null +++ b/rtmidi_c.cpp @@ -0,0 +1,347 @@ +#include +#include +#include "rtmidi_c.h" +#include "RtMidi.h" + +#define RTMIDI_CLASSNAME "C interface" + +/* Compile-time assertions that will break if the enums are changed in + * the future without synchronizing them properly. If you get (g++) + * "error: ‘StaticAssert::StaticAssert() [with bool b = false]’ is + * private within this context", it means enums are not aligned. */ +template class StaticAssert { private: StaticAssert() {} }; +template<> class StaticAssert{ public: StaticAssert() {} }; +#define ENUM_EQUAL(x,y) StaticAssert<(int)x==(int)y>() +class StaticAssertions { StaticAssertions() { + ENUM_EQUAL( RT_MIDI_API_UNSPECIFIED, RtMidi::UNSPECIFIED ); + ENUM_EQUAL( RT_MIDI_API_MACOSX_CORE, RtMidi::MACOSX_CORE ); + ENUM_EQUAL( RT_MIDI_API_LINUX_ALSA, RtMidi::LINUX_ALSA ); + ENUM_EQUAL( RT_MIDI_API_UNIX_JACK, RtMidi::UNIX_JACK ); + ENUM_EQUAL( RT_MIDI_API_WINDOWS_MM, RtMidi::WINDOWS_MM ); + ENUM_EQUAL( RT_MIDI_API_RTMIDI_DUMMY, RtMidi::RTMIDI_DUMMY ); + + ENUM_EQUAL( RT_ERROR_WARNING, RtMidiError::WARNING ); + ENUM_EQUAL( RT_ERROR_DEBUG_WARNING, RtMidiError::DEBUG_WARNING ); + ENUM_EQUAL( RT_ERROR_UNSPECIFIED, RtMidiError::UNSPECIFIED ); + ENUM_EQUAL( RT_ERROR_NO_DEVICES_FOUND, RtMidiError::NO_DEVICES_FOUND ); + ENUM_EQUAL( RT_ERROR_INVALID_DEVICE, RtMidiError::INVALID_DEVICE ); + ENUM_EQUAL( RT_ERROR_MEMORY_ERROR, RtMidiError::MEMORY_ERROR ); + ENUM_EQUAL( RT_ERROR_INVALID_PARAMETER, RtMidiError::INVALID_PARAMETER ); + ENUM_EQUAL( RT_ERROR_INVALID_USE, RtMidiError::INVALID_USE ); + ENUM_EQUAL( RT_ERROR_DRIVER_ERROR, RtMidiError::DRIVER_ERROR ); + ENUM_EQUAL( RT_ERROR_SYSTEM_ERROR, RtMidiError::SYSTEM_ERROR ); + ENUM_EQUAL( RT_ERROR_THREAD_ERROR, RtMidiError::THREAD_ERROR ); +}}; + +class CallbackProxyUserData +{ + public: + CallbackProxyUserData (RtMidiCCallback cCallback, void *userData) + : c_callback (cCallback), user_data (userData) + { + } + RtMidiCCallback c_callback; + void *user_data; +}; + +/* RtMidi API */ +int rtmidi_get_compiled_api (enum RtMidiApi *apis, unsigned int apis_size) +{ + std::vector v; + try { + rtmidi::Midi::getCompiledApi(v); + } catch (...) { + return -1; + } + if (apis) { + unsigned int i; + for (i = 0; i < v.size() && i < apis_size; i++) + apis[i] = (RtMidiApi) v[i]; + return (int)i; + } + // return length for NULL argument. + return v.size(); +} + +void rtmidi_error (rtmidi::MidiApi *api, enum RtMidiErrorType type, const char* errorString) +{ + // std::string msg = errorString; + api->error (RTMIDI_ERROR(errorString,(rtmidi::Error::Type)type)); /* (RtMidiError::Type) type, msg); */ +} + +void rtmidi_open_port (RtMidiPtr device, unsigned int portNumber, const char *portName) +{ + std::string name = portName; + try { + ((rtmidi::Midi*)device->ptr)->openPort (portNumber, name); + + } catch (const RtMidiError & err) { + device->ok = false; + device->msg = err.what (); + } +} + +void rtmidi_open_virtual_port (RtMidiPtr device, const char *portName) +{ + std::string name = portName; + try { + ((rtmidi::Midi*)device->ptr)->openVirtualPort (name); + + } catch (const RtMidiError & err) { + device->ok = false; + device->msg = err.what (); + } + +} + +void rtmidi_close_port (RtMidiPtr device) +{ + try { + ((rtmidi::Midi*)device->ptr)->closePort (); + + } catch (const RtMidiError & err) { + device->ok = false; + device->msg = err.what (); + } +} + +unsigned int rtmidi_get_port_count (RtMidiPtr device) +{ + try { + return ((rtmidi::Midi *)device->ptr)->getPortCount (); + + } catch (const RtMidiError & err) { + device->ok = false; + device->msg = err.what (); + return -1; + } +} + +const char* rtmidi_get_port_name (RtMidiPtr device, unsigned int portNumber) +{ + try { + std::string name = ((rtmidi::Midi*)device->ptr)->getPortName (portNumber); + return strdup (name.c_str ()); + + } catch (const RtMidiError & err) { + device->ok = false; + device->msg = err.what (); + return ""; + } +} + +/* MidiIn API */ +RtMidiInPtr rtmidi_in_create_default () +{ + RtMidiInWrapper* wrp = new RtMidiInWrapper; + + try { + rtmidi::MidiIn* rIn = new rtmidi::MidiIn (); + + wrp->ptr = (void*) rIn; + wrp->data = 0; + wrp->ok = true; + wrp->msg = ""; + + } catch (const RtMidiError & err) { + wrp->ptr = 0; + wrp->data = 0; + wrp->ok = false; + wrp->msg = err.what (); + } + + return wrp; +} + +RtMidiInPtr rtmidi_in_create (enum RtMidiApi api, const char *clientName, unsigned int queueSizeLimit) +{ + std::string name = clientName; + RtMidiInWrapper* wrp = new RtMidiInWrapper; + + try { + rtmidi::MidiIn* rIn = new rtmidi::MidiIn ((rtmidi::ApiType) api, name, queueSizeLimit); + + wrp->ptr = (void*) rIn; + wrp->data = 0; + wrp->ok = true; + wrp->msg = ""; + + } catch (const RtMidiError & err) { + wrp->ptr = 0; + wrp->data = 0; + wrp->ok = false; + wrp->msg = err.what (); + } + + return wrp; +} + +void rtmidi_in_free (RtMidiInPtr device) +{ + if (device->data) + delete (CallbackProxyUserData*) device->data; + delete (rtmidi::MidiIn*) device->ptr; + delete device; +} + +enum RtMidiApi rtmidi_in_get_current_api (RtMidiInPtr device) +{ + try { + return (RtMidiApi) ((rtmidi::MidiIn*)device->ptr)->getCurrentApi (); + + } catch (const RtMidiError & err) { + device->ok = false; + device->msg = err.what (); + + return RT_MIDI_API_UNSPECIFIED; + } +} + +static +void callback_proxy (double timeStamp, std::vector *message, void *userData) +{ + CallbackProxyUserData* data = reinterpret_cast (userData); + data->c_callback (timeStamp, message->data (), message->size (), data->user_data); +} + +void rtmidi_in_set_callback (RtMidiInPtr device, RtMidiCCallback callback, void *userData) +{ + device->data = (void*) new CallbackProxyUserData (callback, userData); + try { + ((rtmidi::MidiIn*)device->ptr)->setCallback (callback_proxy, device->data); + } catch (const RtMidiError & err) { + device->ok = false; + device->msg = err.what (); + delete (CallbackProxyUserData*) device->data; + device->data = 0; + } +} + +void rtmidi_in_cancel_callback (RtMidiInPtr device) +{ + try { + ((rtmidi::MidiIn*)device->ptr)->cancelCallback (); + delete (CallbackProxyUserData*) device->data; + device->data = 0; + } catch (const RtMidiError & err) { + device->ok = false; + device->msg = err.what (); + } +} + +void rtmidi_in_ignore_types (RtMidiInPtr device, bool midiSysex, bool midiTime, bool midiSense) +{ + ((rtmidi::MidiIn*)device->ptr)->ignoreTypes (midiSysex, midiTime, midiSense); +} + +double rtmidi_in_get_message (RtMidiInPtr device, + unsigned char *message, + size_t *size) +{ + try { + // FIXME: use allocator to achieve efficient buffering + std::vector v; + double ret = ((rtmidi::MidiIn*)device->ptr)->getMessage (v); + + if (v.size () > 0 && v.size() <= *size) { + memcpy (message, v.data (), (int) v.size ()); + } + + *size = v.size(); + return ret; + } + catch (const RtMidiError & err) { + device->ok = false; + device->msg = err.what (); + return -1; + } + catch (...) { + device->ok = false; + device->msg = "Unknown error"; + return -1; + } +} + +/* RtMidiOut API */ +RtMidiOutPtr rtmidi_out_create_default () +{ + RtMidiOutWrapper* wrp = new RtMidiOutWrapper; + + try { + rtmidi::MidiOut* rOut = new rtmidi::MidiOut (); + + wrp->ptr = (void*) rOut; + wrp->data = 0; + wrp->ok = true; + wrp->msg = ""; + + } catch (const RtMidiError & err) { + wrp->ptr = 0; + wrp->data = 0; + wrp->ok = false; + wrp->msg = err.what (); + } + + return wrp; +} + +RtMidiOutPtr rtmidi_out_create (enum RtMidiApi api, const char *clientName) +{ + RtMidiOutWrapper* wrp = new RtMidiOutWrapper; + std::string name = clientName; + + try { + rtmidi::MidiOut* rOut = new rtmidi::MidiOut ((rtmidi::ApiType) api, name); + + wrp->ptr = (void*) rOut; + wrp->data = 0; + wrp->ok = true; + wrp->msg = ""; + + } catch (const RtMidiError & err) { + wrp->ptr = 0; + wrp->data = 0; + wrp->ok = false; + wrp->msg = err.what (); + } + + + return wrp; +} + +void rtmidi_out_free (RtMidiOutPtr device) +{ + delete ((rtmidi::MidiOut*)device->ptr); + delete device; +} + +enum RtMidiApi rtmidi_out_get_current_api (RtMidiPtr device) +{ + try { + return (RtMidiApi) ((rtmidi::MidiOut*)device->ptr)->getCurrentApi (); + + } catch (const RtMidiError & err) { + device->ok = false; + device->msg = err.what (); + + return RT_MIDI_API_UNSPECIFIED; + } +} + +int rtmidi_out_send_message (RtMidiOutPtr device, const unsigned char *message, int length) +{ + try { + ((RtMidiOut*) device->ptr)->sendMessage (message, length); + return 0; + } + catch (const RtMidiError & err) { + device->ok = false; + device->msg = err.what (); + return -1; + } + catch (...) { + device->ok = false; + device->msg = "Unknown error"; + return -1; + } +} diff --git a/rtmidi_c.h b/rtmidi_c.h new file mode 100644 index 00000000..b996f1f6 --- /dev/null +++ b/rtmidi_c.h @@ -0,0 +1,190 @@ + +#include +#include +#ifndef RTMIDI_C_H +#define RTMIDI_C_H + +#if defined(RTMIDI_EXPORT) +#define RTMIDIAPI __declspec(dllexport) +#else +#define RTMIDIAPI //__declspec(dllimport) +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +//! Wraps an RtMidi object for C function return statuses. +struct RtMidiWrapper { + //! The wrapped RtMidi object. + void* ptr; + void* data; + + //! True when the last function call was OK. + bool ok; + + //! If an error occured (ok != true), set to an error message. + const char* msg; +}; +struct RtMidiInWrapper { + void* ptr; + void* data; + bool ok; + const char* msg; +}; +struct RtMidiOutWrapper { + void* ptr; + void* data; + bool ok; + const char* msg; +}; + +//! Typedef for a generic RtMidi pointer. +typedef struct RtMidiWrapper* RtMidiPtr; + +//! Typedef for a generic RtMidiIn pointer. +typedef struct RtMidiInWrapper* RtMidiInPtr; + +//! Typedef for a generic RtMidiOut pointer. +typedef struct RtMidiOutWrapper* RtMidiOutPtr; + + +enum RtMidiApi { + RT_MIDI_API_UNSPECIFIED, /*!< Search for a working compiled API. */ + RT_MIDI_API_MACOSX_CORE, /*!< Macintosh OS-X CoreMIDI API. */ + RT_MIDI_API_LINUX_ALSA, /*!< The Advanced Linux Sound Architecture API. */ + RT_MIDI_API_UNIX_JACK, /*!< The Jack Low-Latency MIDI Server API. */ + RT_MIDI_API_WINDOWS_MM, /*!< The Microsoft Multimedia MIDI API. */ + RT_MIDI_API_WINDOWS_KS, /*!< The Microsoft Kernel Streaming MIDI API. */ + RT_MIDI_API_RTMIDI_DUMMY, /*!< A compilable but non-functional API. */ + RT_MIDI_API_ALL_API /*!< Use all available APIs for port selection. */ + }; + +enum RtMidiErrorType { + RT_ERROR_WARNING, RT_ERROR_DEBUG_WARNING, RT_ERROR_UNSPECIFIED, RT_ERROR_NO_DEVICES_FOUND, + RT_ERROR_INVALID_DEVICE, RT_ERROR_MEMORY_ERROR, RT_ERROR_INVALID_PARAMETER, RT_ERROR_INVALID_USE, + RT_ERROR_DRIVER_ERROR, RT_ERROR_SYSTEM_ERROR, RT_ERROR_THREAD_ERROR +}; + +/*! The type of a RtMidi callback function. + * \param timeStamp The time at which the message has been received. + * \param message The midi message. + * \param userData Additional user data for the callback. + */ +typedef void(* RtMidiCCallback) (double timeStamp, const unsigned char* message, + size_t messageSize, void *userData); + + +/* RtMidi API */ + +/*! Determine the available compiled MIDI APIs. + * If the given `apis` parameter is null, returns the number of available APIs. + * Otherwise, fill the given apis array with the RtMidi::Api values. + * + * \param apis An array or a null value. + * \param apis_size Number of elements pointed to by apis + * \return number of items needed for apis array if apis==NULL, or + * number of items written to apis array otherwise. A negative + * return value indicates an error. +*/ +RTMIDIAPI int rtmidi_get_compiled_api (enum RtMidiApi *apis, unsigned int apis_size); + +//! Report an error. +RTMIDIAPI void rtmidi_error (enum RtMidiErrorType type, const char* errorString); + +/*! Open a MIDI port. + * + * \param port Must be greater than 0 + * \param portName Name for the application port. + */ +RTMIDIAPI void rtmidi_open_port (RtMidiPtr device, unsigned int portNumber, const char *portName); + +/*! Creates a virtual MIDI port to which other software applications can + * connect. + * + * \param portName Name for the application port. + */ +RTMIDIAPI void rtmidi_open_virtual_port (RtMidiPtr device, const char *portName); + +/*! Close a MIDI connection. + */ +RTMIDIAPI void rtmidi_close_port (RtMidiPtr device); + +/*! Return the number of available MIDI ports. + */ +RTMIDIAPI unsigned int rtmidi_get_port_count (RtMidiPtr device); + +/*! Return a string identifier for the specified MIDI input port number. + */ +RTMIDIAPI const char* rtmidi_get_port_name (RtMidiPtr device, unsigned int portNumber); + +/* RtMidiIn API */ + +//! Create a default RtMidiInPtr value, with no initialization. +RTMIDIAPI RtMidiInPtr rtmidi_in_create_default (); + +/*! Create a RtMidiInPtr value, with given api, clientName and queueSizeLimit. + * + * \param api An optional API id can be specified. + * \param clientName An optional client name can be specified. This + * will be used to group the ports that are created + * by the application. + * \param queueSizeLimit An optional size of the MIDI input queue can be + * specified. + */ +RTMIDIAPI RtMidiInPtr rtmidi_in_create (enum RtMidiApi api, const char *clientName, unsigned int queueSizeLimit); + +//! Deallocate the given pointer. +RTMIDIAPI void rtmidi_in_free (RtMidiInPtr device); + +//! Returns the MIDI API specifier for the given instance of RtMidiIn. +RTMIDIAPI enum RtMidiApi rtmidi_in_get_current_api (RtMidiPtr device); + +//! Set a callback function to be invoked for incoming MIDI messages. +RTMIDIAPI void rtmidi_in_set_callback (RtMidiInPtr device, RtMidiCCallback callback, void *userData); + +//! Cancel use of the current callback function (if one exists). +RTMIDIAPI void rtmidi_in_cancel_callback (RtMidiInPtr device); + +//! Specify whether certain MIDI message types should be queued or ignored during input. +RTMIDIAPI void rtmidi_in_ignore_types (RtMidiInPtr device, bool midiSysex, bool midiTime, bool midiSense); + +/*! Fill the user-provided array with the data bytes for the next available + * MIDI message in the input queue and return the event delta-time in seconds. + * + * \param message Must point to a char* that is already allocated. + * SYSEX messages maximum size being 1024, a statically + * allocated array could + * be sufficient. + * \param size Is used to return the size of the message obtained. + */ +RTMIDIAPI double rtmidi_in_get_message (RtMidiInPtr device, unsigned char *message, size_t *size); + +/* RtMidiOut API */ + +//! Create a default RtMidiInPtr value, with no initialization. +RTMIDIAPI RtMidiOutPtr rtmidi_out_create_default (); + +/*! Create a RtMidiOutPtr value, with given and clientName. + * + * \param api An optional API id can be specified. + * \param clientName An optional client name can be specified. This + * will be used to group the ports that are created + * by the application. + */ +RTMIDIAPI RtMidiOutPtr rtmidi_out_create (enum RtMidiApi api, const char *clientName); + +//! Deallocate the given pointer. +RTMIDIAPI void rtmidi_out_free (RtMidiOutPtr device); + +//! Returns the MIDI API specifier for the given instance of RtMidiOut. +RTMIDIAPI enum RtMidiApi rtmidi_out_get_current_api (RtMidiPtr device); + +//! Immediately send a single message out an open MIDI output port. +RTMIDIAPI int rtmidi_out_send_message (RtMidiOutPtr device, const unsigned char *message, int length); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/tests/Makefile.am b/tests/Makefile.am new file mode 100644 index 00000000..07851ea9 --- /dev/null +++ b/tests/Makefile.am @@ -0,0 +1,185 @@ +### RtMidi tests Makefile - for various flavors of unix +#RTMIDITESTCXXFLAGS += -I$(top_srcdir)/%D% +#RTMIDITESTLDFLAGS += -L$(top_builddir)/%D% -lrtmidi@rtmidi_suffix@ @LIBS@ + +check_PROGRAMS += \ + %D%/midiprobe \ + %D%/midiout \ + %D%/qmidiin \ + %D%/cmidiin \ + %D%/sysextest \ + %D%/midiprobe2 \ + %D%/midiprobe-all \ + %D%/cmidiin2 \ + %D%/qmidiin2 \ + %D%/midiout2 \ + %D%/loopback \ + %D%/errors \ + %D%/midiclock_in \ + %D%/midiclock_out + +TESTS += \ + %D%/midiprobe \ + %D%/midiprobe2 \ + %D%/midiprobe-all \ + %D%/errors + +CLEANFILES += \ + %D%/*.class + +EXTRA_DIST += \ + %D%/cmidiin.dsp \ + %D%/midiout.dsp \ + %D%/midiprobe.dsp \ + %D%/qmidiin.dsp \ + %D%/sysextest.dsp \ + %D%/RtMidi.dsw + + +if RTMIDI_HAVE_VIRTUAL_DEVICES +TESTS += %D%/loopback +endif + + +%C%_midiprobe_SOURCES = %D%/midiprobe.cpp +%C%_midiout_SOURCES = %D%/midiout.cpp +%C%_qmidiin_SOURCES = %D%/qmidiin.cpp +%C%_cmidiin_SOURCES = %D%/cmidiin.cpp +%C%_sysextest_SOURCES = %D%/sysextest.cpp +%C%_midiprobe2_SOURCES = %D%/midiprobe2.cpp +%C%_midiprobe_all_SOURCES = %D%/midiprobe-all.cpp +%C%_cmidiin2_SOURCES = %D%/cmidiin2.cpp +%C%_qmidiin2_SOURCES = %D%/qmidiin2.cpp +%C%_midiout2_SOURCES = %D%/midiout2.cpp +%C%_loopback_SOURCES = %D%/loopback.cpp +%C%_errors_SOURCES = %D%/errors.cpp +%C%_midiclock_in_SOURCES = %D%/midiclock.cpp +%C%_midiclock_out_SOURCES = %D%/midiclock.cpp + +# When a nonstandard gettext library or wrapper is used, +# we need extra flags. +%C%_midiprobe_CXXFLAGS = $(AM_CXXFLAGS) $(RTMIDITESTCXXFLAGS) -DRTMIDI_NO_WARN_DEPRECATED +%C%_midiout_CXXFLAGS = $(AM_CXXFLAGS) $(RTMIDITESTCXXFLAGS) -DRTMIDI_NO_WARN_DEPRECATED +%C%_qmidiin_CXXFLAGS = $(AM_CXXFLAGS) $(RTMIDITESTCXXFLAGS) -DRTMIDI_NO_WARN_DEPRECATED +%C%_cmidiin_CXXFLAGS = $(AM_CXXFLAGS) $(RTMIDITESTCXXFLAGS) -DRTMIDI_NO_WARN_DEPRECATED +%C%_sysextest_CXXFLAGS = $(AM_CXXFLAGS) $(RTMIDITESTCXXFLAGS) -DRTMIDI_NO_WARN_DEPRECATED +%C%_midiprobe2_CXXFLAGS = $(AM_CXXFLAGS) $(RTMIDITESTCXXFLAGS) -DRTMIDI_NO_WARN_DEPRECATED +%C%_midiprobe_all_CXXFLAGS = $(AM_CXXFLAGS) $(RTMIDITESTCXXFLAGS) -DRTMIDI_NO_WARN_DEPRECATED +%C%_cmidiin2_CXXFLAGS = $(AM_CXXFLAGS) $(RTMIDITESTCXXFLAGS) -DRTMIDI_NO_WARN_DEPRECATED +%C%_qmidiin2_CXXFLAGS = $(AM_CXXFLAGS) $(RTMIDITESTCXXFLAGS) -DRTMIDI_NO_WARN_DEPRECATED +%C%_midiout2_CXXFLAGS = $(AM_CXXFLAGS) $(RTMIDITESTCXXFLAGS) -DRTMIDI_NO_WARN_DEPRECATED +%C%_loopback_CXXFLAGS = $(AM_CXXFLAGS) $(RTMIDITESTCXXFLAGS) -DRTMIDI_NO_WARN_DEPRECATED +%C%_errors_CXXFLAGS = $(AM_CXXFLAGS) $(RTMIDITESTCXXFLAGS) -DRTMIDI_NO_WARN_DEPRECATED +%C%_midiclock_in_CXXFLAGS = $(AM_CXXFLAGS) $(RTMIDITESTCXXFLAGS) -DRTMIDI_NO_WARN_DEPRECATED +%C%_midiclock_out_CXXFLAGS = $(AM_CXXFLAGS) $(RTMIDITESTCXXFLAGS) -DRTMIDI_NO_WARN_DEPRECATED + + +%C%_midiprobe_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) +%C%_midiout_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) +%C%_qmidiin_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) +%C%_cmidiin_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) +%C%_sysextest_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) +%C%_midiprobe2_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) +%C%_midiprobe_all_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) +%C%_cmidiin2_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) +%C%_qmidiin2_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) +%C%_midiout2_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) +%C%_loopback_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) +%C%_errors_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) +%C%_midiclock_in_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) +%C%_midiclock_out_LDFLAGS = $(AM_LDFLAGS) $(RTMIDITESTLDFLAGS) + + +%C%_midiprobe_LDADD = $(RTMIDILIBRARYNAME) +%C%_midiout_LDADD = $(RTMIDILIBRARYNAME) +%C%_qmidiin_LDADD = $(RTMIDILIBRARYNAME) +%C%_cmidiin_LDADD = $(RTMIDILIBRARYNAME) +%C%_sysextest_LDADD = $(RTMIDILIBRARYNAME) +%C%_midiprobe2_LDADD = $(RTMIDILIBRARYNAME) +%C%_midiprobe_all_LDADD = $(RTMIDILIBRARYNAME) +%C%_cmidiin2_LDADD = $(RTMIDILIBRARYNAME) +%C%_qmidiin2_LDADD = $(RTMIDILIBRARYNAME) +%C%_midiout2_LDADD = $(RTMIDILIBRARYNAME) +%C%_loopback_LDADD = $(RTMIDILIBRARYNAME) +%C%_errors_LDADD = $(RTMIDILIBRARYNAME) +%C%_midiclock_in_LDADD = $(RTMIDILIBRARYNAME) +%C%_midiclock_out_LDADD = $(RTMIDILIBRARYNAME) + + +if RTMIDICOPYDLLS + +#------------------------------------------------------------------------------------- +# Installing DLLs +#------------------------------------------------------------------------------------- + + + +rtmidi_installdll: + @echo 'solving references for $(DLLLINKFILE)... ' + set -e -x; \ + DLLSEARCHPATH="$(DLLSEARCHPATH)$(LOCALDLLSEARCHPATH)" ; \ + for f in `LANG=C $(OBJDUMP) -p $(DLLEXEDIR)/$(DLLLINKFILE) |sed '/^\s*DLL Name:.*\(lib\|thread\|wx\|mingw\|gcc\|stdc++\)/ { s/^\s*DLL Name:\s*//; p } ; d '`; \ + do \ + echo -n checking "$$f ... " ; \ + if [ ! -f $(DLLEXEDIR)/$$f ] ; then \ + echo -n "searching... " ; \ + IFS=: ; \ + for d in $$DLLSEARCHPATH ; do \ + echo "looking in $$d" ; \ + IFS= ; \ + fullname="$$d/$$f" ; \ + echo "testing $$fullname" ; \ + if test -f "$$fullname" ; \ + then \ + if cmp "$$fullname" "`pwd`/$(DLLEXEDIR)/$$f"; \ + then \ + echo "ok." ;\ + else \ + echo "installing $$fullname " ; \ + $(INSTALL_PROGRAM_ENV) $(INSTALL_DATA) "$$fullname" "$(DLLEXEDIR)" ; \ + fi ; \ + $(MAKE) $(AM_MAKEFLAGS) DLLLINKFILE="$$f" DLLEXEDIR="$(DLLEXEDIR)" rtmidi_installdll ; \ + elif test -f "$${fullname}.gz" ; \ + then \ + if cmp "$${fullname}.gz" "`pwd`/$(DLLEXEDIR)/$${f}.gz"; \ + then \ + echo "ok." ;\ + else \ + echo "installing $$fullname " ; \ + $(INSTALL_PROGRAM_ENV) $(INSTALL_DATA) "$${fullname}.gz" "$(DLLEXEDIR)" ; \ + fi; \ + GZIP=$(GZIP_ENV) gzip -dc $(DLLEXEDIR)/`basename "$${fullname}.gz"` >$(DLLEXEDIR)/"$$f" ; \ + $(MAKE) $(AM_MAKEFLAGS) DLLLINKFILE="$$f" DLLEXEDIR="$(DLLEXEDIR)" rtmidi_installdll ; \ + fi ; \ + done ; \ + fi ; \ + echo "done." ;\ + done ; + +#------------------------------------------------------------------------------------- +# Certain fixed files +#------------------------------------------------------------------------------------- + + + +check-am: check-dll-rtmidi + +check-dll-rtmidi: all-am + $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) + $(MAKE) $(AM_MAKEFLAGS) linkchecks-rtmidi + +linkchecks-rtmidi: + set -e -x ; \ + for d in `echo $(DLLPROGRAMS)| tr ' ' '\n' | grep -i -e '$(EXEEXT)$$\|.dll$$'` ; \ + do \ + ls -l "$$d" ; \ + file=`basename "$$d"` ; \ + dir=`dirname "$$d"` ; \ + $(MAKE) $(AM_MAKEFLAGS) DLLLINKFILE="$$file" DLLEXEDIR="$$dir" rtmidi_installdll ; \ + if test -f "$$dir/.libs/$$file"; \ + then \ + $(MAKE) $(AM_MAKEFLAGS) DLLLINKFILE="$$file" DLLEXEDIR="$$dir/.libs" rtmidi_installdll ; \ + fi ; \ + done +endif + diff --git a/tests/Makefile.in b/tests/Makefile.in deleted file mode 100644 index 1826737e..00000000 --- a/tests/Makefile.in +++ /dev/null @@ -1,49 +0,0 @@ -### Do not edit -- Generated by 'configure --with-whatever' from Makefile.in -### RtMidi tests Makefile - for various flavors of unix - -PROGRAMS = midiprobe midiout qmidiin cmidiin sysextest -RM = /bin/rm -SRC_PATH = .. -INCLUDE = .. -OBJECT_PATH = @object_path@ -vpath %.o $(OBJECT_PATH) - -OBJECTS = RtMidi.o - -CC = @CXX@ -DEFS = @CPPFLAGS@ -CFLAGS = @CXXFLAGS@ -CFLAGS += -I$(INCLUDE) -I$(INCLUDE)/include -LIBRARY = @LIBS@ - -%.o : $(SRC_PATH)/%.cpp - $(CC) $(CFLAGS) $(DEFS) -c $(<) -o $(OBJECT_PATH)/$@ - -all : $(PROGRAMS) - -midiprobe : midiprobe.cpp $(OBJECTS) - $(CC) $(CFLAGS) $(DEFS) -o midiprobe midiprobe.cpp $(OBJECT_PATH)/RtMidi.o $(LIBRARY) - -midiout : midiout.cpp $(OBJECTS) - $(CC) $(CFLAGS) $(DEFS) -o midiout midiout.cpp $(OBJECT_PATH)/RtMidi.o $(LIBRARY) - -qmidiin : qmidiin.cpp $(OBJECTS) - $(CC) $(CFLAGS) $(DEFS) -o qmidiin qmidiin.cpp $(OBJECT_PATH)/RtMidi.o $(LIBRARY) - -cmidiin : cmidiin.cpp $(OBJECTS) - $(CC) $(CFLAGS) $(DEFS) -o cmidiin cmidiin.cpp $(OBJECT_PATH)/RtMidi.o $(LIBRARY) - -sysextest : sysextest.cpp $(OBJECTS) - $(CC) $(CFLAGS) $(DEFS) -o sysextest sysextest.cpp $(OBJECT_PATH)/RtMidi.o $(LIBRARY) - -clean : - $(RM) -f $(OBJECT_PATH)/*.o - $(RM) -f $(PROGRAMS) *.exe - $(RM) -f *~ - $(RM) -fR *.dSYM - -distclean: clean - $(RM) -f Makefile - -strip : - strip $(PROGRAMS) diff --git a/tests/cmidiin.cpp b/tests/cmidiin.cpp index be78dbbd..49e48edb 100644 --- a/tests/cmidiin.cpp +++ b/tests/cmidiin.cpp @@ -19,7 +19,7 @@ void usage( void ) { exit( 0 ); } -void mycallback( double deltatime, std::vector< unsigned char > *message, void */*userData*/ ) +void mycallback( double deltatime, std::vector< unsigned char > *message, void * /* userData */ ) { unsigned int nBytes = message->size(); for ( unsigned int i=0; i +#include +#include "RtMidi.h" + +void mycallback( double deltatime, std::vector< unsigned char > *message, void * /* userData */ ) +{ + unsigned int nBytes = message->size(); + for ( unsigned int i=0; i 0 ) + std::cout << "stamp = " << deltatime << std::endl; +} + +// This function should be embedded in a try/catch block in case of +// an exception. It offers the user a choice of MIDI ports to open. +// It returns false if there are no ports available. +bool chooseMidiPort( rtmidi::MidiIn &rtmidi ); + +int main( int /* argc */, char */*argv*/[] ) +{ + + std::vector message; + std::cout << "\nWould you like to check all output ports? [Y/n] "; + + std::string keyHit; + std::getline( std::cin, keyHit ); + rtmidi::ApiType type = rtmidi::ALL_API; + if ( keyHit == "n" ) { + type = rtmidi::UNSPECIFIED; + } + + try { + + // rtmidi::MidiIn constructor + rtmidi::MidiIn midiin(type); + + // Call function to select port. + if ( chooseMidiPort( midiin ) == false ) return 0; + + // Set our callback function. This should be done immediately after + // opening the port to avoid having incoming messages written to the + // queue instead of sent to the callback function. + midiin.setCallback( &mycallback ); + + // Don't ignore sysex, timing, or active sensing messages. + midiin.ignoreTypes( false, false, false ); + + std::cout << "\nReading MIDI input ... press to quit.\n"; + char input; + std::cin.get(input); + + } catch ( rtmidi::Error &error ) { + error.printMessage(); + } +} + +bool chooseMidiPort( rtmidi::MidiIn &midi ) +{ + std::cout << "\nWould you like to open a virtual input port? [y/N] "; + + std::string keyHit; + std::getline( std::cin, keyHit ); + if ( keyHit == "y" ) { + midi.openVirtualPort("RtMidi virtual input"); + return true; + } + + std::string portName; + rtmidi::PortList list = midi.getPortList(rtmidi::PortDescriptor::INPUT); + if ( list.empty() ) { + std::cout << "No input ports available!" << std::endl; + return false; + } + + rtmidi::Pointer selected = list.front(); + if ( list.size() == 1 ) { + std::cout << "\nOpening " << selected->getName() << std::endl; + } else { + int nr; + std::vector > pointers(list.size()); + // copy the data into a structure that is used by the user interface. + std::copy(list.begin(),list.end(),pointers.begin()); + for (nr = 0 ; nr < (int)pointers.size(); nr++) { + portName = pointers[nr]->getName(rtmidi::PortDescriptor::LONG_NAME + | rtmidi::PortDescriptor::UNIQUE_PORT_NAME + | rtmidi::PortDescriptor::INCLUDE_API); + std::cout << " Input port #" << nr << ": " << portName << '\n'; + } + + do { + std::cout << "\nChoose a port number: "; + std::cin >> nr; + } while ( nr >= (int)pointers.size() ); + std::getline( std::cin, keyHit ); // used to clear out stdin + selected = pointers[nr]; + } + + /* The midi setup might have changed meanwhile. + Our portlist is under our control. So we enumerate this list. */ + // midi.openPort( i ); + midi.openPort(selected); + return true; +} diff --git a/tests/errors.cpp b/tests/errors.cpp new file mode 100644 index 00000000..f6b1ecf0 --- /dev/null +++ b/tests/errors.cpp @@ -0,0 +1,69 @@ +//*****************************************// +// loopback +// by Tobis Schlemmer, 2014. +// inspired by virtual-loopback-test-automated.js from the node-midi project. +// donated to RtMidi. +// +/*! \example loopback.cpp + Simple program to test MIDI input and + output in an internal loop using a user callback function. +*/ +//*****************************************// + +#include +#include +#include "RtMidi.h" + +// Platform-dependent sleep routines. +#if defined(__WINDOWS_MM__) +#include +#define SLEEP( milliseconds ) Sleep( (DWORD) milliseconds ) +#else // Unix variants +#include +#define SLEEP( milliseconds ) usleep( (unsigned long) (milliseconds * 1000.0) ) +#endif + +#define rtmidi_abort \ + std::cerr << __FILE__ << ":" << __LINE__ << ": rtmidi_aborting" << std::endl; \ + abort + +using namespace rtmidi; + +bool ok = false; + + +int main( int /* argc */, char * /*argv*/[] ) +{ + + std::vector types = Midi::getCompiledApi(); + if (types.size() > 1) { + for (size_t i = 0 ; i < types.size() ; i++) { + try { + MidiIn in (types[i]); + PortList ports = in.getPortList(PortDescriptor::INPUT); + if (ports.size()>1) { + MidiIn in2 (types[i?0:1]); + try { + in2.openPort(ports.front()); + } catch (Error & e) { + std::string msg = e.getMessage(); + e.printMessage(); + if (e.getType() != Error::INVALID_DEVICE) { + rtmidi_abort(); + } + } + } + } catch (Error & e) { + std::string msg = e.getMessage(); + e.printMessage(); + if (msg != rtmidi_gettext("")) { + if (e.getType() != Error::WARNING && + e.getType() != Error::NO_DEVICES_FOUND) { + rtmidi_abort(); + } + } + } + } + } + return 0; +} diff --git a/tests/loopback.cpp b/tests/loopback.cpp new file mode 100644 index 00000000..7bc1fc38 --- /dev/null +++ b/tests/loopback.cpp @@ -0,0 +1,210 @@ +//*****************************************// +// loopback +// by Tobis Schlemmer, 2014. +// inspired by virtual-loopback-test-automated.js from the node-midi project. +// donated to RtMidi. +// +/*! \example loopback.cpp + Simple program to test MIDI input and + output in an internal loop using a user callback function. +*/ +//*****************************************// + +#include +#include +#include "RtMidi.h" + +// Platform-dependent sleep routines. +#if defined(__WINDOWS_MM__) +#include +#define SLEEP( milliseconds ) Sleep( (DWORD) milliseconds ) +#else // Unix variants +#include +#define SLEEP( milliseconds ) usleep( (unsigned long) (milliseconds * 1000.0) ) +#endif + + +/* Here, we store the expected output. Timing is not tested */ +std::vector virtualinstring; +const char * virtualinstringgoal = + "\xc0\x5\xf1\x3c\xb0\x7\x64\x90\x40\x5a\x80\x40\x28\xb0\x7\x28\xf0\x43\x4\x3\x2\xf7"; +std::vector instring; +const char * instringgoal = + "\xc0\x6\xf1\x3d\xb0\x8\x64\x90\x41\x5a\x80\x41\x28\xb0\x8\x28\xf0\x43\x4\x3\x3\xf7"; + +inline size_t getlength(const char * messages) { + size_t retval = 0; + const unsigned char * c = reinterpret_cast(messages); + while (*(c++) != 0xf7) retval++; + return ++retval; +} + +void mycallback1( double /* deltatime */, std::vector< unsigned char > *message, void * /* userData */ ) +{ + unsigned int nBytes = message->size(); + for ( unsigned int i=0; iat(i)); + // std::cout << "\\x" << std::hex << (int)message->at(i) << std::flush; + } + /* if ( nBytes > 0 ) + std::cout << "stamp = " << deltatime << std::endl; + */ +} + +void mycallback2( double /* deltatime */, std::vector< unsigned char > *message, void * /* userData */ ) +{ + unsigned int nBytes = message->size(); + for ( unsigned int i=0; iat(i)); + // std::cout << "\\x" << std::hex << (int)message->at(i); + } + /* + if ( nBytes > 0 ) + std::cout << "stamp = " << deltatime << std::endl; + */ +} + + + +int main( int /* argc */, char * /*argv*/[] ) +{ + + std::vector message; + + try { + + // rtmidi::MidiIn constructor + rtmidi::MidiIn virtualin; + // rtmidi::MidiIn constructor + rtmidi::MidiOut virtualout; + + virtualin.openVirtualPort("RtMidi Test Virtual In"); + virtualout.openVirtualPort("RtMidi Test Virtual Out"); + + rtmidi::Pointer indescriptor + = virtualin.getDescriptor(true); + + rtmidi::Pointer outdescriptor + = virtualout.getDescriptor(true); + + { // avoid problems with wrong destruction order + /* use smart pointers to handle deletion */ + rtmidi::Pointer midiin(outdescriptor->getInputApi()); + if (!midiin) abort(); + rtmidi::Pointer midiout(indescriptor->getOutputApi()); + if (!midiout) abort(); + + + + midiin->openPort(outdescriptor); + midiout->openPort(indescriptor); + + + // Set our callback function. This should be done immediately after + // opening the port to avoid having incoming messages written to the + // queue instead of sent to the callback function. + midiin->setCallback( &mycallback1 ); + virtualin.setCallback( &mycallback2 ); + + // Don't ignore sysex, timing, or active sensing messages. + // Don't ignore sysex, timing, or active sensing messages. + midiin->ignoreTypes( false, false, false ); + virtualin.ignoreTypes( false, false, false ); + + SLEEP( 5000 ); + + // Send out a series of MIDI messages. + + // Program change: 192, 5 + message.push_back( 192 ); + message.push_back( 5 ); + midiout->sendMessage( &message ); + message[1] = 6; + virtualout.sendMessage(&message); + + SLEEP( 500 ); + + message[0] = 0xF1; + message[1] = 60; + midiout->sendMessage( &message ); + message[1] = 61; + virtualout.sendMessage(&message); + + // Control Change: 176, 7, 100 (volume) + message[0] = 176; + message[1] = 7; + message.push_back( 100 ); + midiout->sendMessage( &message ); + message[1] = 8; + virtualout.sendMessage ( &message ); + + // Note On: 144, 64, 90 + message[0] = 144; + message[1] = 64; + message[2] = 90; + midiout->sendMessage( &message ); + message[1] = 65; + virtualout.sendMessage( &message ); + + SLEEP( 500 ); + + // Note Off: 128, 64, 40 + message[0] = 128; + message[1] = 64; + message[2] = 40; + midiout->sendMessage( &message ); + message[1] = 65; + virtualout.sendMessage( &message ); + + SLEEP( 500 ); + + // Control Change: 176, 7, 40 + message[0] = 176; + message[1] = 7; + message[2] = 40; + midiout->sendMessage( &message ); + message[1] = 8; + virtualout.sendMessage( &message ); + + SLEEP( 500 ); + + // Sysex: 240, 67, 4, 3, 2, 247 + message[0] = 240; + message[1] = 67; + message[2] = 4; + message.push_back( 3 ); + message.push_back( 2 ); + message.push_back( 247 ); + midiout->sendMessage( &message ); + message[4] = 3; + virtualout.sendMessage( &message ); + + SLEEP( 500 ); + } + const unsigned char * goal = reinterpret_cast(instringgoal); + size_t i; + std::cout << "Virtual output -> input:" << std::endl; + if (instring.size() != getlength(instringgoal)) abort(); + for (i = 0 ; i < instring.size() && goal[i] ; i++){ + std::cout << " " << std::hex << (int) instring[i]; + std::cout << "/" << std::hex << (int) goal[i] << std::flush; + if (instring[i] != goal[i]) abort(); + } + std::cout << std::endl; + if (i != instring.size()) abort(); + goal = reinterpret_cast(virtualinstringgoal); + std::cout << "Output -> virtual input:" << std::endl; + if (instring.size() != getlength(virtualinstringgoal)) abort(); + for (i = 0 ; i < virtualinstring.size() && goal[i] ; i++) { + std::cout << " " << std::hex << (int) virtualinstring[i]; + std::cout << "/" << std::hex << (int) goal[i] << std::flush; + if (virtualinstring[i] != goal[i]) abort(); + } + std::cout << std::endl; + if (i != virtualinstring.size()) abort(); + + } catch ( rtmidi::Error &error ) { + error.printMessage(); + } + return 0; +} diff --git a/tests/midiclock.cpp b/tests/midiclock.cpp new file mode 100644 index 00000000..babf4f9f --- /dev/null +++ b/tests/midiclock.cpp @@ -0,0 +1,231 @@ +//*****************************************// +// midiclock.cpp +// +// Simple program to test MIDI clock sync. Run midiclock_in in one +// console and midiclock_out in the other, make sure to choose +// options that connect the clocks between programs on your platform. +// +// (C)2016 Refer to README.md in this archive for copyright. +// +//*****************************************// + +#include +#include +#include "RtMidi.h" + +// Platform-dependent sleep routines. +#if defined(__WINDOWS_MM__) + #include + #define SLEEP( milliseconds ) Sleep( (DWORD) milliseconds ) +#else // Unix variants + #include + #define SLEEP( milliseconds ) usleep( (unsigned long) (milliseconds * 1000.0) ) +#endif + +// These functions should be embedded in a try/catch block in case of +// an exception. It offers the user a choice of MIDI ports to open. +// It returns false if there are no ports available. +bool chooseInputPort( RtMidiIn *rtmidi ); +bool chooseOutputPort( RtMidiOut *rtmidi ); + +void mycallback( double deltatime, std::vector< unsigned char > *message, void *user ) +{ + unsigned int *clock_count = reinterpret_cast(user); + + // Ignore longer messages + if (message->size() != 1) + return; + + unsigned int msg = message->at(0); + if (msg == 0xFA) + std::cout << "START received" << std::endl; + if (msg == 0xFB) + std::cout << "CONTINUE received" << std::endl; + if (msg == 0xFC) + std::cout << "STOP received" << std::endl; + if (msg == 0xF8) { + if (++*clock_count == 24) { + double bpm = 60.0 / 24.0 / deltatime; + std::cout << "One beat, estimated BPM = " << bpm <setCallback( &mycallback, &clock_count ); + + // Don't ignore sysex, timing, or active sensing messages. + midiin->ignoreTypes( false, false, false ); + + std::cout << "\nReading MIDI input ... press to quit.\n"; + char input; + std::cin.get(input); + + } catch ( RtMidiError &error ) { + error.printMessage(); + } + + cleanup: + + delete midiin; + + return 0; +} + +int clock_out() +{ + RtMidiOut *midiout = 0; + std::vector message; + int sleep_ms = 0, k = 0, j = 0; + + // RtMidiOut constructor + try { + midiout = new RtMidiOut(); + } + catch ( RtMidiError &error ) { + error.printMessage(); + exit( EXIT_FAILURE ); + } + + // Call function to select port. + try { + if ( chooseOutputPort( midiout ) == false ) goto cleanup; + } + catch ( RtMidiError &error ) { + error.printMessage(); + goto cleanup; + } + + // Period in ms = 100 BPM + // 100*24 ticks / 1 minute, so (60*1000) / (100*24) = 25 ms / tick + sleep_ms = 25; + std::cout << "Generating clock at " + << (60.0 / 24.0 / sleep_ms * 1000.0) + << " BPM." << std::endl; + + // Send out a series of MIDI clock messages. + // MIDI start + message.clear(); + message.push_back( 0xFA ); + midiout->sendMessage( &message ); + std::cout << "MIDI start" << std::endl; + + for (j=0; j < 8; j++) + { + if (j > 0) + { + // MIDI continue + message.clear(); + message.push_back( 0xFB ); + midiout->sendMessage( &message ); + std::cout << "MIDI continue" << std::endl; + } + + for (k=0; k < 96; k++) { + // MIDI clock + message.clear(); + message.push_back( 0xF8 ); + midiout->sendMessage( &message ); + if (k % 24 == 0) + std::cout << "MIDI clock (one beat)" << std::endl; + SLEEP( sleep_ms ); + } + + // MIDI stop + message.clear(); + message.push_back( 0xFC ); + midiout->sendMessage( &message ); + std::cout << "MIDI stop" << std::endl; + SLEEP( 500 ); + } + + // MIDI stop + message.clear(); + message.push_back( 0xFC ); + midiout->sendMessage( &message ); + std::cout << "MIDI stop" << std::endl; + + SLEEP( 500 ); + + std::cout << "Done!" << std::endl; + + // Clean up + cleanup: + delete midiout; + + return 0; +} + +int main( int, const char *argv[] ) +{ + std::string prog(argv[0]); + if (prog.find("midiclock_in") != prog.npos) { + clock_in(); + } + else if (prog.find("midiclock_out") != prog.npos) { + clock_out(); + } + else { + std::cout << "Don't know what to do as " << prog << std::endl; + } + return 0; +} + +template +bool choosePort( RT *rtmidi, const char *dir ) +{ + std::string portName; + unsigned int i = 0, nPorts = rtmidi->getPortCount(); + if ( nPorts == 0 ) { + std::cout << "No " << dir << " ports available!" << std::endl; + return false; + } + + if ( nPorts == 1 ) { + std::cout << "\nOpening " << rtmidi->getPortName() << std::endl; + } + else { + for ( i=0; igetPortName(i); + std::cout << " " << dir << " port #" << i << ": " << portName << '\n'; + } + + do { + std::cout << "\nChoose a port number: "; + std::cin >> i; + } while ( i >= nPorts ); + } + + std::cout << "\n"; + rtmidi->openPort( i ); + + return true; +} + +bool chooseInputPort( RtMidiIn *rtmidi ) +{ + return choosePort( rtmidi, "input" ); +} + +bool chooseOutputPort( RtMidiOut *rtmidi ) +{ + return choosePort( rtmidi, "output" ); +} diff --git a/tests/midiout.cpp b/tests/midiout.cpp index 05505cc6..49c5b081 100644 --- a/tests/midiout.cpp +++ b/tests/midiout.cpp @@ -24,7 +24,7 @@ // It returns false if there are no ports available. bool chooseMidiPort( RtMidiOut *rtmidi ); -int main( void ) +int main( int /* argc*/, char */*argv*/[] ) { RtMidiOut *midiout = 0; std::vector message; diff --git a/tests/midiout2.cpp b/tests/midiout2.cpp new file mode 100644 index 00000000..c68e045c --- /dev/null +++ b/tests/midiout2.cpp @@ -0,0 +1,173 @@ +//*****************************************// +// midiout.cpp +// by Gary Scavone, 2003-2014. +// and Tobias Schlemmer 2014 +// +/*! \example midiout2.cpp + Simple program to test MIDI output. +*/ +// *****************************************// + + + +#include +#include +#include "RtMidi.h" + +// Platform-dependent sleep routines. +#if defined(__WINDOWS_MM__) +#include +#define SLEEP( milliseconds ) Sleep( (DWORD) milliseconds ) +#undef UNIQUE_PORT_NAME +#else // Unix variants +#include +#define SLEEP( milliseconds ) usleep( (unsigned long) (milliseconds * 1000.0) ) +#endif + +// This function should be embedded in a try/catch block in case of +// an exception. It offers the user a choice of MIDI ports to open. +// It returns false if there are no ports available. +bool chooseMidiPort( rtmidi::MidiOut &midi ); + +//! The main program +int main( int /* argc*/, char */*argv*/[] ) +{ + std::vector message; + std::cout << "\nWould you like to check all output ports? [Y/n] "; + + std::string keyHit; + std::getline( std::cin, keyHit ); + rtmidi::ApiType type = rtmidi::ALL_API; + if ( keyHit == "n" ) { + type = rtmidi::UNSPECIFIED; + } + + // rtmidi::MidiOut constructor + try { + rtmidi::MidiOut midiout(type); + + // Call function to select port. + try { + if ( chooseMidiPort( midiout ) == false ) return 1; + } + catch ( rtmidi::Error &error ) { + error.printMessage(); + return 2; + } + + + SLEEP( 5000 ); + + // Send out a series of MIDI messages. + + // Program change: 192, 5 + message.push_back( 192 ); + message.push_back( 5 ); + midiout.sendMessage( &message ); + + SLEEP( 500 ); + + message[0] = 0xF1; + message[1] = 60; + midiout.sendMessage( &message ); + + // Control Change: 176, 7, 100 (volume) + message[0] = 176; + message[1] = 7; + message.push_back( 100 ); + midiout.sendMessage( &message ); + + // Note On: 144, 64, 90 + message[0] = 144; + message[1] = 64; + message[2] = 90; + midiout.sendMessage( &message ); + + SLEEP( 500 ); + + // Note Off: 128, 64, 40 + message[0] = 128; + message[1] = 64; + message[2] = 40; + midiout.sendMessage( &message ); + + SLEEP( 500 ); + + // Control Change: 176, 7, 40 + message[0] = 176; + message[1] = 7; + message[2] = 40; + midiout.sendMessage( &message ); + + SLEEP( 500 ); + + // Sysex: 240, 67, 4, 3, 2, 247 + message[0] = 240; + message[1] = 67; + message[2] = 4; + message.push_back( 3 ); + message.push_back( 2 ); + message.push_back( 247 ); + midiout.sendMessage( &message ); + + + } + catch ( rtmidi::Error &error ) { + error.printMessage(); + exit( EXIT_FAILURE ); + } + + return 0; +} + +bool chooseMidiPort( rtmidi::MidiOut &midi ) +{ + std::cout << "\nWould you like to open a virtual output port? [y/N] "; + + std::string keyHit; + std::getline( std::cin, keyHit ); + if ( keyHit == "y" ) { + midi.openVirtualPort("RtMidi virtual output"); + std::cout << "Press return to start the transmission." << std::endl; + std::getline( std::cin, keyHit ); + + return true; + } + + std::string portName; + rtmidi::PortList list = midi.getPortList(rtmidi::PortDescriptor::OUTPUT); + if ( list.empty() ) { + std::cout << "No output ports available!" << std::endl; + return false; + } + + rtmidi::Pointer selected = list.front(); + if ( list.size() == 1 ) { + std::cout << "\nOpening " << selected->getName() << std::endl; + } else { + int nr; + std::vector > pointers(list.size()); + // copy the data into a structure that is used by the user interface. + std::copy(list.begin(),list.end(),pointers.begin()); + for (nr = 0 ; nr < (int)pointers.size(); nr++) { + portName = pointers[nr]->getName(rtmidi::PortDescriptor::LONG_NAME + | rtmidi::PortDescriptor::UNIQUE_PORT_NAME + | rtmidi::PortDescriptor::INCLUDE_API); + std::cout << " Output port #" << nr << ": " << portName << '\n'; + } + + do { + std::cout << "\nChoose a port number: "; + std::cin >> nr; + } while ( nr >= (int)pointers.size() ); + std::getline( std::cin, keyHit ); // used to clear out stdin + selected = pointers[nr]; + } + + /* The midi setup might have changed meanwhile. + Our portlist is under our control. So we enumerate this list. */ + // midi.openPort( i ); + midi.openPort(selected); + + return true; +} diff --git a/tests/midiprobe-all.cpp b/tests/midiprobe-all.cpp new file mode 100644 index 00000000..90839fe0 --- /dev/null +++ b/tests/midiprobe-all.cpp @@ -0,0 +1,122 @@ +// midiprobe.cpp +// +// Simple program to check MIDI inputs and outputs. +// +// by Gary Scavone, 2003-2012. + +#include +#include +#include +#include "RtMidi.h" + +int main() +{ + // Create an api map. + + std::vector< RtMidi::Api > apis; + rtmidi::Midi :: getCompiledApi( apis ); + + std::cout << "\nCompiled APIs:\n"; + for ( unsigned int i=0; igetName() << std::endl; + for (int j = 0 ; j < 4 ; j++ ) { + std::cout << j << ":f:f: " << (*i)->getName (j) << std::endl; + std::cout << j << ":t:f: " << (*i)->getName (j | rtmidi::PortDescriptor::UNIQUE_PORT_NAME) << std::endl; + std::cout << j << ":f:t: " << (*i)->getName (j | rtmidi::PortDescriptor::INCLUDE_API) << std::endl; + std::cout << j << ":t:t: " << (*i)->getName (j | rtmidi::PortDescriptor::UNIQUE_PORT_NAME + | rtmidi::PortDescriptor::INCLUDE_API) << std::endl; + std::cout << std::endl; + } + std::cout << std::endl; + } + + std::cout << "**********************************************************************" << std::endl; + + // RtMidiOut constructor ... exception possible + rtmidi::MidiOut midiout (rtmidi::ALL_API); + list = midiout.getPortList(); + + std::cout << "\nCurrent output API: " << rtmidi::getApiName(midiout.getCurrentApi()) << std::endl; + + // Check inputs. + std::cout << "\nThere are " << list.size() << " MIDI output sinks available.\n"; + + for (rtmidi::PortList::iterator i = list.begin(); + i != list.end(); + i++) { + std::cout << " Output Port: " << (*i)->getName() << std::endl; + for (int j = 0 ; j < 4 ; j++ ) { + std::cout << j << ":f:f: " << (*i)->getName (j) << std::endl; + std::cout << j << ":t:f: " << (*i)->getName (j | rtmidi::PortDescriptor::UNIQUE_PORT_NAME) << std::endl; + std::cout << j << ":f:t: " << (*i)->getName (j | rtmidi::PortDescriptor::INCLUDE_API) << std::endl; + std::cout << j << ":t:t: " << (*i)->getName (j | rtmidi::PortDescriptor::UNIQUE_PORT_NAME + | rtmidi::PortDescriptor::INCLUDE_API) << std::endl; + std::cout << std::endl; + } + std::cout << std::endl; + } + + std::cout << "**********************************************************************" << std::endl; + std::cout << "* entering unlimited mode *" << std::endl; + std::cout << "**********************************************************************" << std::endl; + + list = midiin.getPortList(rtmidi::PortDescriptor::UNLIMITED); + // Check inputs. + std::cout << "\nThere are " << list.size() << " MIDI input sources available in unlimited mode.\n"; + for (rtmidi::PortList::iterator i = list.begin(); + i != list.end(); + i++) { + std::cout << " Input Port: " << (*i)->getName() << std::endl; + for (int j = 0 ; j < 4 ; j++ ) { + std::cout << j << ":f:f: " << (*i)->getName (j) << std::endl; + std::cout << j << ":t:f: " << (*i)->getName (j | rtmidi::PortDescriptor::UNIQUE_PORT_NAME) << std::endl; + std::cout << j << ":f:t: " << (*i)->getName (j | rtmidi::PortDescriptor::INCLUDE_API) << std::endl; + std::cout << j << ":t:t: " << (*i)->getName (j | rtmidi::PortDescriptor::UNIQUE_PORT_NAME + | rtmidi::PortDescriptor::INCLUDE_API) << std::endl; + std::cout << std::endl; + } + std::cout << std::endl; + } + + std::cout << "**********************************************************************" << std::endl; + list = midiout.getPortList(rtmidi::PortDescriptor::UNLIMITED); + + // Check inputs. + std::cout << "\nThere are " << list.size() << " MIDI output sinks available in unlimited mode.\n"; + + for (rtmidi::PortList::iterator i = list.begin(); + i != list.end(); + i++) { + std::cout << " Output Port: " << (*i)->getName() << std::endl; + for (int j = 0 ; j < 4 ; j++ ) { + std::cout << j << ":f:f: " << (*i)->getName (j) << std::endl; + std::cout << j << ":t:f: " << (*i)->getName (j | rtmidi::PortDescriptor::UNIQUE_PORT_NAME) << std::endl; + std::cout << j << ":f:t: " << (*i)->getName (j | rtmidi::PortDescriptor::INCLUDE_API) << std::endl; + std::cout << j << ":t:t: " << (*i)->getName (j | rtmidi::PortDescriptor::UNIQUE_PORT_NAME + | rtmidi::PortDescriptor::INCLUDE_API) << std::endl; + std::cout << std::endl; + } + std::cout << std::endl; + } + + } catch ( rtmidi::Error &error ) { + error.printMessage(); + } + + return 0; +} diff --git a/tests/midiprobe.cpp b/tests/midiprobe.cpp index 6576e152..7ae4fe65 100644 --- a/tests/midiprobe.cpp +++ b/tests/midiprobe.cpp @@ -13,9 +13,8 @@ int main() { // Create an api map. std::map apiMap; - apiMap[RtMidi::MACOSX_CORE] = "OS-X CoreMidi"; + apiMap[RtMidi::MACOSX_CORE] = "OS-X CoreMIDI"; apiMap[RtMidi::WINDOWS_MM] = "Windows MultiMedia"; - apiMap[RtMidi::WINDOWS_KS] = "Windows Kernel Straming"; apiMap[RtMidi::UNIX_JACK] = "Jack Client"; apiMap[RtMidi::LINUX_ALSA] = "Linux ALSA"; apiMap[RtMidi::RTMIDI_DUMMY] = "RtMidi Dummy"; diff --git a/tests/midiprobe2.cpp b/tests/midiprobe2.cpp new file mode 100644 index 00000000..0fae3d8e --- /dev/null +++ b/tests/midiprobe2.cpp @@ -0,0 +1,137 @@ +/*! \example midiprobe2.cpp + + Simple program to check MIDI inputs and outputs. +*/ +// +// by Gary Scavone, 2003-2014. +// and Tobias Schlemmer 2014 + +#include +#include +#include +#include "RtMidi.h" + +int main() +{ + // Create an api map. + std::map apiMap; + apiMap[rtmidi::MACOSX_CORE] = "OS-X CoreMidi"; + apiMap[rtmidi::WINDOWS_MM] = "Windows MultiMedia"; + apiMap[rtmidi::WINDOWS_KS] = "Windows Kernel Straming"; + apiMap[rtmidi::UNIX_JACK] = "Jack Client"; + apiMap[rtmidi::LINUX_ALSA] = "Linux ALSA"; + apiMap[rtmidi::DUMMY] = "RtMidi Dummy"; + apiMap[rtmidi::ALL_API] = "All RtMidi APIs"; + + std::vector< rtmidi::ApiType > apis; + rtmidi::Midi :: getCompiledApi( apis ); + + std::cout << "\nCompiled APIs:\n"; + for ( unsigned int i=0; igetName() << std::endl; + for (int j = 0 ; j < 4 ; j++ ) { + std::cout << j << ":f:f: " << (*i)->getName (j) << std::endl; + std::cout << j << ":t:f: " << (*i)->getName (j | rtmidi::PortDescriptor::UNIQUE_PORT_NAME) << std::endl; + std::cout << j << ":f:t: " << (*i)->getName (j | rtmidi::PortDescriptor::INCLUDE_API) << std::endl; + std::cout << j << ":t:t: " << (*i)->getName (j | rtmidi::PortDescriptor::UNIQUE_PORT_NAME + | rtmidi::PortDescriptor::INCLUDE_API) << std::endl; + std::cout << std::endl; + } + std::cout << std::endl; + } + + std::cout << "**********************************************************************" << std::endl; + + // rtmidi::MidiOut constructor ... exception possible + rtmidi::MidiOut midiout; + + std::cout << "\nCurrent output API: " << apiMap[ midiout.getCurrentApi() ] << std::endl; + + list = midiout.getPortList(); + + // Check inputs. + std::cout << "\nThere are " << list.size() << " MIDI output sinks available.\n"; + + for (rtmidi::PortList::iterator i = list.begin(); + i != list.end(); + i++) { + std::cout << " Output Port: " << (*i)->getName() << std::endl; + for (int j = 0 ; j < 4 ; j++ ) { + std::cout << j << ":f:f: " << (*i)->getName (j) << std::endl; + std::cout << j << ":t:f: " << (*i)->getName (j | rtmidi::PortDescriptor::UNIQUE_PORT_NAME) << std::endl; + std::cout << j << ":f:t: " << (*i)->getName (j | rtmidi::PortDescriptor::INCLUDE_API) << std::endl; + std::cout << j << ":t:t: " << (*i)->getName (j | rtmidi::PortDescriptor::UNIQUE_PORT_NAME + | rtmidi::PortDescriptor::INCLUDE_API) << std::endl; + std::cout << std::endl; + } + std::cout << std::endl; + } + + std::cout << "**********************************************************************" << std::endl; + std::cout << "* entering unlimited mode *" << std::endl; + std::cout << "**********************************************************************" << std::endl; + + list = midiin.getPortList(rtmidi::PortDescriptor::UNLIMITED); + // Check inputs. + std::cout << "\nThere are " << list.size() << " MIDI input sources available in unlimited mode.\n"; + for (rtmidi::PortList::iterator i = list.begin(); + i != list.end(); + i++) { + std::cout << " Input Port: " << (*i)->getName() << std::endl; + for (int j = 0 ; j < 4 ; j++ ) { + std::cout << j << ":f:f: " << (*i)->getName (j) << std::endl; + std::cout << j << ":t:f: " << (*i)->getName (j | rtmidi::PortDescriptor::UNIQUE_PORT_NAME) << std::endl; + std::cout << j << ":f:t: " << (*i)->getName (j | rtmidi::PortDescriptor::INCLUDE_API) << std::endl; + std::cout << j << ":t:t: " << (*i)->getName (j | rtmidi::PortDescriptor::UNIQUE_PORT_NAME + | rtmidi::PortDescriptor::INCLUDE_API) << std::endl; + std::cout << std::endl; + } + std::cout << std::endl; + } + + std::cout << "**********************************************************************" << std::endl; + list = midiout.getPortList(rtmidi::PortDescriptor::UNLIMITED); + + // Check inputs. + std::cout << "\nThere are " << list.size() << " MIDI output sinks available in unlimited mode.\n"; + + for (rtmidi::PortList::iterator i = list.begin(); + i != list.end(); + i++) { + std::cout << " Output Port: " << (*i)->getName() << std::endl; + for (int j = 0 ; j < 4 ; j++ ) { + std::cout << j << ":f:f: " << (*i)->getName (j) << std::endl; + std::cout << j << ":t:f: " << (*i)->getName (j | rtmidi::PortDescriptor::UNIQUE_PORT_NAME) << std::endl; + std::cout << j << ":f:t: " << (*i)->getName (j | rtmidi::PortDescriptor::INCLUDE_API) << std::endl; + std::cout << j << ":t:t: " << (*i)->getName (j | rtmidi::PortDescriptor::UNIQUE_PORT_NAME + | rtmidi::PortDescriptor::INCLUDE_API) << std::endl; + std::cout << std::endl; + } + std::cout << std::endl; + } + + + + } catch ( rtmidi::Error &error ) { + error.printMessage(); + } + + return 0; +} diff --git a/tests/qmidiin.cpp b/tests/qmidiin.cpp index afd112b0..dbd9fdf6 100644 --- a/tests/qmidiin.cpp +++ b/tests/qmidiin.cpp @@ -77,7 +77,7 @@ int main( int argc, char *argv[] ) (void) signal(SIGINT, finish); // Periodically check input queue. - std::cout << "Reading MIDI from port ... quit with Ctrl-C.\n"; + std::cout << "Reading MIDI from port " << midiin->getPortName() << " ... quit with Ctrl-C.\n"; while ( !done ) { stamp = midiin->getMessage( &message ); nBytes = message.size(); diff --git a/tests/qmidiin2.cpp b/tests/qmidiin2.cpp new file mode 100644 index 00000000..20956c8d --- /dev/null +++ b/tests/qmidiin2.cpp @@ -0,0 +1,126 @@ +//*****************************************// +// qmidiin.cpp +// by Gary Scavone, 2003-2014. +// and Tobias Schlemmer, 2014 +// +/*! \example qmidiin2.cpp + Simple program to test MIDI input and + retrieval from the queue. +*/ +//*****************************************// + +#include +#include +#include +#include "RtMidi.h" + +// Platform-dependent sleep routines. +#if defined(__WINDOWS_MM__) +#include +#define SLEEP( milliseconds ) Sleep( (DWORD) milliseconds ) +#undef UNIQUE_PORT_NAME +#else // Unix variants +#include +#define SLEEP( milliseconds ) usleep( (unsigned long) (milliseconds * 1000.0) ) +#endif + +bool done; +static void finish( int /*ignore*/ ){ done = true; } + +void usage( rtmidi::PortList list ) { + // Error function in case of incorrect command-line + // argument specifications. + std::cout << "\nusage: qmidiin \n"; + std::cout << " where port = the device to use (default = first available port).\n\n"; + + std::cout << "Available ports:" << std::endl; + int flags = rtmidi::PortDescriptor::SESSION_PATH | + rtmidi::PortDescriptor::UNIQUE_PORT_NAME | + rtmidi::PortDescriptor::INCLUDE_API; + for (rtmidi::PortList::iterator i = list.begin(); + i != list.end(); i++) { + std::cout << "\"" + << (*i)->getName(rtmidi::PortDescriptor::SESSION_PATH | + rtmidi::PortDescriptor::UNIQUE_PORT_NAME | + rtmidi::PortDescriptor::INCLUDE_API) + << "\""; + std::cout << "\t"; + std::cout << (*i)->getName() << std::endl; + } + exit( 0 ); +} + +int main( int argc, char *argv[] ) +{ + std::vector message; + int nBytes, i; + double stamp; + + + // rtmidi::MidiIn constructor + try { + rtmidi::MidiIn midiin(rtmidi::ALL_API); + + + rtmidi::PortList list = midiin.getPortList(); + + + // Minimal command-line check. + if ( argc > 2 ) usage(list); + + rtmidi::Pointer port = 0; + // Check available ports vs. specified. + if ( argc == 2 ) { + for (rtmidi::PortList::iterator i = list.begin(); + i != list.end(); i++) { + if (argv[1] == (*i)->getName(rtmidi::PortDescriptor::SESSION_PATH | + rtmidi::PortDescriptor::UNIQUE_PORT_NAME | + rtmidi::PortDescriptor::INCLUDE_API)) { + port = *i; + break; + } + } + } else { + port = list.front(); + } + if ( !port ) { + std::cout << "Invalid port specifier!\n"; + usage(list); + } + + try { + midiin.openPort( port ); + } + catch ( rtmidi::Error &error ) { + error.printMessage(); + return 1; + } + + // Don't ignore sysex, timing, or active sensing messages. + midiin.ignoreTypes( false, false, false ); + + // Install an interrupt handler function. + done = false; + (void) signal(SIGINT, finish); + + // Periodically check input queue. + std::cout << "Reading MIDI from port ... quit with Ctrl-C.\n"; + while ( !done ) { + stamp = midiin.getMessage( &message ); + nBytes = message.size(); + for ( i=0; i 0 ) + std::cout << "stamp = " << stamp << std::endl; + + // Sleep for 10 milliseconds. + SLEEP( 10 ); + } + } + catch ( rtmidi::Error &error ) { + error.printMessage(); + exit( EXIT_FAILURE ); + } + + return 0; +} diff --git a/tests/sysextest.cpp b/tests/sysextest.cpp index 8402c74c..e2cf2a2b 100644 --- a/tests/sysextest.cpp +++ b/tests/sysextest.cpp @@ -1,9 +1,9 @@ //*****************************************// -// sysextest.cpp // by Gary Scavone, 2003-2005. -// -// Simple program to test MIDI sysex sending and receiving. -// +/*! \example sysextest.cpp + + program to test MIDI sysex sending and receiving. +*/ //*****************************************// #include diff --git a/throwing-functions.txt b/throwing-functions.txt new file mode 100644 index 00000000..b6ca765b --- /dev/null +++ b/throwing-functions.txt @@ -0,0 +1,66 @@ +-*- Org -*- +* throw +|------------------------------------+-------------------+--------------------------------| +| Function | Type | Should be caught inside RtMidi | +|------------------------------------+-------------------+--------------------------------| +| Midi::error | all | n | +| MidiApi :: error(Error e) | all | n | +| MidiIn :: MidiIn | INVALID_PARAMETER | impossible | +| | NO_DEVICES_FOUND | | +| MidiOut :: MidiOut | INVALID_PARAMETER | impossible | +| | NO_DEVICES_FOUND | | +| CoreSequencer::getPortCapabilities | WARNING | y | +| CoreSequencer::createPort | INVALID_PARAMETER | y | +| | DRIVER_ERROR | | +| CoreSequencer::createVirtualPort | INVALID_PARAMETER | y | +| | DRIVER_ERROR | | +| CoreSequencer::init | DRIVER_ERROR | y | +| AlsaSequencer::connectPorts | DRIVER_ERROR | y | +| AlsaSequencer::init | DRIVER_ERROR | y | +| WinMMSequencer::getPortName | INVALID_PARAMETER | Y | +| JackSequencer::init | NO_DEVICES_FOUND | y | +| JackMidiData::openPort | DRIVER_ERROR | | +|------------------------------------+-------------------+--------------------------------| +* error +|----------------------------+-----------------+-----------------------------| +| Function | Type | Can be caught inside RtMidi | +|----------------------------+-----------------+-----------------------------| +| MidiIn :: openMidiApi | vom Konstructor | | +| MidiInWinMM :: initialize | WARNING | yes | +| MidiOutWinMM :: initialize | WARNING | yes | +| | | | +| | | | +|----------------------------+-----------------+-----------------------------| + +* backtrace +** CoreSequencer::getPortCapabilities +|-------------------------------------+-------------------| +| Function | Type | +|-------------------------------------+-------------------| +| CorePortDescriptor::getCapabilities | WARNING | +| CorePortDescriptor::getPortList | -- | +| CoreMidiData::openPort | INVALID_PARAMETER | +| | DRIVER_ERROR | +| CoreSequencer::CoreSequencer | DRIVER_ERROR | +| AlsaSequencer::GetPortName | DRIVER_ERROR | +| AlsaSequencer::getPortCapabilities | DRIVER_ERROR | +| AlsaSequencer::getNextClient | DRIVER_ERROR | +| AlsaSequencer::getNextPort | DRIVER_ERROR | +| AlsaSequencer::DRIVER_ERROR | DRIVER_ERROR | +| AlsaSequencer::deletePort | DRIVER_ERROR | +| AlsaSequencer::connectPorts | DRIVER_ERROR | +| AlsaSequencer::closePort | DRIVER_ERROR | +| AlsaSequencer::startQueue | DRIVER_ERROR | +| AlsaSequencer::GetClient | DRIVER_ERROR | +| AlsaMidiData::connectPorts | DRIVER_ERROR | +| JackSequencer::getPortList | NO_DEVICES_FOUND | +| JackSequencer::getPort | NO_DEVICES_FOUND | +| JackSequencer::getPortName | NO_DEVICES_FOUND | +| JackSequencer::createPort | NO_DEVICES_FOUND | +| JackSequencer::deletePort | NO_DEVICES_FOUND | +| JackSequencer::connectPorts | NO_DEVICES_FOUND | +| JackSequencer::closePort | NO_DEVICES_FOUND | +| JackMidiData::init | NO_DEVICES_FOUND | +| JackMidiData::connectPorts | NO_DEVICES_FOUND | +| MidiOutJack :: initialize | NO_DEVICES_FOUND | +| | |