[
  {
    "path": ".gitignore",
    "content": ".DS_Store\n\n# Compiled Object files\n*.slo\n*.lo\n*.o\ndebug\n\n# Compiled Dynamic libraries\n*.so\n*.dylib\n\n# Compiled Static libraries\n*.lai\n*.la\n*.a\n\n# Executables\ncursynth\na.out\n\n# Autotools\nMakefile.in\nar-lib\nconfig.guess\nconfig.rpath\nconfig.sub\nconfig.h.in\n*.la\n*.lo\n*~\n.deps/\n.libs/\nMakefile\naclocal.m4\nautom4te.cache\nautoscan.log\ncompile\nconfig.h\nconfig.log\nconfig.status\nconfigure\ndepcomp\ninstall-sh\nlibtool\nltmain.sh\nm4/\nmissing\nstamp*\nstdin.info\n*.tar.gz\nstdin.info\n"
  },
  {
    "path": "ABOUT-NLS",
    "content": "1 Notes on the Free Translation Project\n***************************************\n\nFree software is going international!  The Free Translation Project is\na way to get maintainers of free software, translators, and users all\ntogether, so that free software will gradually become able to speak many\nlanguages.  A few packages already provide translations for their\nmessages.\n\n   If you found this `ABOUT-NLS' file inside a distribution, you may\nassume that the distributed package does use GNU `gettext' internally,\nitself available at your nearest GNU archive site.  But you do _not_\nneed to install GNU `gettext' prior to configuring, installing or using\nthis package with messages translated.\n\n   Installers will find here some useful hints.  These notes also\nexplain how users should proceed for getting the programs to use the\navailable translations.  They tell how people wanting to contribute and\nwork on translations can contact the appropriate team.\n\n1.1 INSTALL Matters\n===================\n\nSome packages are \"localizable\" when properly installed; the programs\nthey contain can be made to speak your own native language.  Most such\npackages use GNU `gettext'.  Other packages have their own ways to\ninternationalization, predating GNU `gettext'.\n\n   By default, this package will be installed to allow translation of\nmessages.  It will automatically detect whether the system already\nprovides the GNU `gettext' functions.  Installers may use special\noptions at configuration time for changing the default behaviour.  The\ncommand:\n\n     ./configure --disable-nls\n\nwill _totally_ disable translation of messages.\n\n   When you already have GNU `gettext' installed on your system and run\nconfigure without an option for your new package, `configure' will\nprobably detect the previously built and installed `libintl' library\nand will decide to use it.  If not, you may have to to use the\n`--with-libintl-prefix' option to tell `configure' where to look for it.\n\n   Internationalized packages usually have many `po/LL.po' files, where\nLL gives an ISO 639 two-letter code identifying the language.  Unless\ntranslations have been forbidden at `configure' time by using the\n`--disable-nls' switch, all available translations are installed\ntogether with the package.  However, the environment variable `LINGUAS'\nmay be set, prior to configuration, to limit the installed set.\n`LINGUAS' should then contain a space separated list of two-letter\ncodes, stating which languages are allowed.\n\n1.2 Using This Package\n======================\n\nAs a user, if your language has been installed for this package, you\nonly have to set the `LANG' environment variable to the appropriate\n`LL_CC' combination.  If you happen to have the `LC_ALL' or some other\n`LC_xxx' environment variables set, you should unset them before\nsetting `LANG', otherwise the setting of `LANG' will not have the\ndesired effect.  Here `LL' is an ISO 639 two-letter language code, and\n`CC' is an ISO 3166 two-letter country code.  For example, let's\nsuppose that you speak German and live in Germany.  At the shell\nprompt, merely execute `setenv LANG de_DE' (in `csh'),\n`export LANG; LANG=de_DE' (in `sh') or `export LANG=de_DE' (in `bash').\nThis can be done from your `.login' or `.profile' file, once and for\nall.\n\n   You might think that the country code specification is redundant.\nBut in fact, some languages have dialects in different countries.  For\nexample, `de_AT' is used for Austria, and `pt_BR' for Brazil.  The\ncountry code serves to distinguish the dialects.\n\n   The locale naming convention of `LL_CC', with `LL' denoting the\nlanguage and `CC' denoting the country, is the one use on systems based\non GNU libc.  On other systems, some variations of this scheme are\nused, such as `LL' or `LL_CC.ENCODING'.  You can get the list of\nlocales supported by your system for your language by running the\ncommand `locale -a | grep '^LL''.\n\n   Not all programs have translations for all languages.  By default, an\nEnglish message is shown in place of a nonexistent translation.  If you\nunderstand other languages, you can set up a priority list of languages.\nThis is done through a different environment variable, called\n`LANGUAGE'.  GNU `gettext' gives preference to `LANGUAGE' over `LANG'\nfor the purpose of message handling, but you still need to have `LANG'\nset to the primary language; this is required by other parts of the\nsystem libraries.  For example, some Swedish users who would rather\nread translations in German than English for when Swedish is not\navailable, set `LANGUAGE' to `sv:de' while leaving `LANG' to `sv_SE'.\n\n   Special advice for Norwegian users: The language code for Norwegian\nbokma*l changed from `no' to `nb' recently (in 2003).  During the\ntransition period, while some message catalogs for this language are\ninstalled under `nb' and some older ones under `no', it's recommended\nfor Norwegian users to set `LANGUAGE' to `nb:no' so that both newer and\nolder translations are used.\n\n   In the `LANGUAGE' environment variable, but not in the `LANG'\nenvironment variable, `LL_CC' combinations can be abbreviated as `LL'\nto denote the language's main dialect.  For example, `de' is equivalent\nto `de_DE' (German as spoken in Germany), and `pt' to `pt_PT'\n(Portuguese as spoken in Portugal) in this context.\n\n1.3 Translating Teams\n=====================\n\nFor the Free Translation Project to be a success, we need interested\npeople who like their own language and write it well, and who are also\nable to synergize with other translators speaking the same language.\nEach translation team has its own mailing list.  The up-to-date list of\nteams can be found at the Free Translation Project's homepage,\n`http://translationproject.org/', in the \"Teams\" area.\n\n   If you'd like to volunteer to _work_ at translating messages, you\nshould become a member of the translating team for your own language.\nThe subscribing address is _not_ the same as the list itself, it has\n`-request' appended.  For example, speakers of Swedish can send a\nmessage to `sv-request@li.org', having this message body:\n\n     subscribe\n\n   Keep in mind that team members are expected to participate\n_actively_ in translations, or at solving translational difficulties,\nrather than merely lurking around.  If your team does not exist yet and\nyou want to start one, or if you are unsure about what to do or how to\nget started, please write to `coordinator@translationproject.org' to\nreach the coordinator for all translator teams.\n\n   The English team is special.  It works at improving and uniformizing\nthe terminology in use.  Proven linguistic skills are praised more than\nprogramming skills, here.\n\n1.4 Available Packages\n======================\n\nLanguages are not equally supported in all packages.  The following\nmatrix shows the current state of internationalization, as of June\n2010.  The matrix shows, in regard of each package, for which languages\nPO files have been submitted to translation coordination, with a\ntranslation percentage of at least 50%.\n\n     Ready PO files       af am an ar as ast az be be@latin bg bn_IN bs ca\n                        +--------------------------------------------------+\n     a2ps               |                       []                      [] |\n     aegis              |                                                  |\n     ant-phone          |                                                  |\n     anubis             |                                                  |\n     aspell             |                []                             [] |\n     bash               |                                                  |\n     bfd                |                                                  |\n     bibshelf           |                []                                |\n     binutils           |                                                  |\n     bison              |                                                  |\n     bison-runtime      |                []                                |\n     bluez-pin          | []             []                                |\n     bombono-dvd        |                                                  |\n     buzztard           |                                                  |\n     cflow              |                                                  |\n     clisp              |                                                  |\n     coreutils          |                                   []          [] |\n     cpio               |                                                  |\n     cppi               |                                                  |\n     cpplib             |                                               [] |\n     cryptsetup         |                                                  |\n     dfarc              |                                                  |\n     dialog             |                             []                [] |\n     dico               |                                                  |\n     diffutils          |                                               [] |\n     dink               |                                                  |\n     doodle             |                                                  |\n     e2fsprogs          |                                               [] |\n     enscript           |                                               [] |\n     exif               |                                                  |\n     fetchmail          |                                               [] |\n     findutils          |                                   []             |\n     flex               |                                               [] |\n     freedink           |                                                  |\n     gas                |                                                  |\n     gawk               |                []                             [] |\n     gcal               |                                               [] |\n     gcc                |                                                  |\n     gettext-examples   | []             []                 []          [] |\n     gettext-runtime    |                                   []          [] |\n     gettext-tools      |                                   []          [] |\n     gip                |                                   []             |\n     gjay               |                                                  |\n     gliv               |                                   []             |\n     glunarclock        |                []                 []             |\n     gnubiff            |                                                  |\n     gnucash            |                                               [] |\n     gnuedu             |                                                  |\n     gnulib             |                                                  |\n     gnunet             |                                                  |\n     gnunet-gtk         |                                                  |\n     gnutls             |                                                  |\n     gold               |                                                  |\n     gpe-aerial         |                                                  |\n     gpe-beam           |                                                  |\n     gpe-bluetooth      |                                                  |\n     gpe-calendar       |                                                  |\n     gpe-clock          |                []                                |\n     gpe-conf           |                                                  |\n     gpe-contacts       |                                                  |\n     gpe-edit           |                                                  |\n     gpe-filemanager    |                                                  |\n     gpe-go             |                                                  |\n     gpe-login          |                                                  |\n     gpe-ownerinfo      |                []                                |\n     gpe-package        |                                                  |\n     gpe-sketchbook     |                                                  |\n     gpe-su             |                []                                |\n     gpe-taskmanager    |                []                                |\n     gpe-timesheet      |                []                                |\n     gpe-today          |                []                                |\n     gpe-todo           |                                                  |\n     gphoto2            |                                                  |\n     gprof              |                                   []             |\n     gpsdrive           |                                                  |\n     gramadoir          |                                                  |\n     grep               |                                                  |\n     grub               |                []                             [] |\n     gsasl              |                                                  |\n     gss                |                                                  |\n     gst-plugins-bad    |                                   []             |\n     gst-plugins-base   |                                   []             |\n     gst-plugins-good   |                                   []             |\n     gst-plugins-ugly   |                                   []             |\n     gstreamer          | []                                []          [] |\n     gtick              |                                                  |\n     gtkam              |                       []                         |\n     gtkorphan          |                                   []             |\n     gtkspell           | []             []     []                         |\n     gutenprint         |                                                  |\n     hello              |                                   []             |\n     help2man           |                                                  |\n     hylafax            |                                                  |\n     idutils            |                                                  |\n     indent             |                                   []          [] |\n     iso_15924          |                                                  |\n     iso_3166           | []          []        []          []  []   [] [] |\n     iso_3166_2         |                                                  |\n     iso_4217           |                                                  |\n     iso_639            |             [] []     []              []         |\n     iso_639_3          |                                                  |\n     jwhois             |                                                  |\n     kbd                |                                                  |\n     keytouch           |                                               [] |\n     keytouch-editor    |                                                  |\n     keytouch-keyboa... |                                               [] |\n     klavaro            |          []                                      |\n     latrine            |                                                  |\n     ld                 |                                   []             |\n     leafpad            |                                   []          [] |\n     libc               |                                   []          [] |\n     libexif            |                       ()                         |\n     libextractor       |                                                  |\n     libgnutls          |                                                  |\n     libgpewidget       |                                                  |\n     libgpg-error       |                                                  |\n     libgphoto2         |                                                  |\n     libgphoto2_port    |                                                  |\n     libgsasl           |                                                  |\n     libiconv           |                                   []             |\n     libidn             |                                                  |\n     lifelines          |                                                  |\n     liferea            |                             []                [] |\n     lilypond           |                                                  |\n     linkdr             |          []                                      |\n     lordsawar          |                                                  |\n     lprng              |                                                  |\n     lynx               |                                               [] |\n     m4                 |                                                  |\n     mailfromd          |                                                  |\n     mailutils          |                                                  |\n     make               |                                                  |\n     man-db             |                                                  |\n     man-db-manpages    |                                                  |\n     minicom            |                                                  |\n     mkisofs            |                                                  |\n     myserver           |                                                  |\n     nano               |                                   []          [] |\n     opcodes            |                                                  |\n     parted             |                                                  |\n     pies               |                                                  |\n     popt               |                                                  |\n     psmisc             |                                                  |\n     pspp               |                                               [] |\n     pwdutils           |                                                  |\n     radius             |                                               [] |\n     recode             |                       []                      [] |\n     rosegarden         |                                                  |\n     rpm                |                                                  |\n     rush               |                                                  |\n     sarg               |                                                  |\n     screem             |                                                  |\n     scrollkeeper       |                    [] []                      [] |\n     sed                |                []                             [] |\n     sharutils          |                                   []          [] |\n     shishi             |                                                  |\n     skencil            |                                                  |\n     solfege            |                                                  |\n     solfege-manual     |                                                  |\n     soundtracker       |                                                  |\n     sp                 |                                                  |\n     sysstat            |                                                  |\n     tar                |                                   []             |\n     texinfo            |                                                  |\n     tin                |                                                  |\n     unicode-han-tra... |                                                  |\n     unicode-transla... |                                                  |\n     util-linux-ng      |                                               [] |\n     vice               |                                                  |\n     vmm                |                                                  |\n     vorbis-tools       |                                                  |\n     wastesedge         |                                                  |\n     wdiff              |                                                  |\n     wget               |                       []                      [] |\n     wyslij-po          |                                                  |\n     xchat              |                []     []          []          [] |\n     xdg-user-dirs      | []    []    [] []     []    []    []  []      [] |\n     xkeyboard-config   |                                   []          [] |\n                        +--------------------------------------------------+\n                          af am an ar as ast az be be@latin bg bn_IN bs ca\n                           6  0  1  2  3 19   1 10     3    28   3    1 38\n\n                          crh cs da  de  el en en_GB en_ZA eo es et eu fa\n                        +-------------------------------------------------+\n     a2ps               |     [] []  []  []     []            [] []       |\n     aegis              |        []  []                       []          |\n     ant-phone          |        []  ()                                   |\n     anubis             |        []  []                                   |\n     aspell             |     [] []  []         []            []          |\n     bash               |     []                           [] []          |\n     bfd                |                                     []          |\n     bibshelf           |        []  []                       []          |\n     binutils           |                                     []          |\n     bison              |            []  []                               |\n     bison-runtime      |        []  []  []                      []       |\n     bluez-pin          |     [] []  []  []                [] []          |\n     bombono-dvd        |        []                                       |\n     buzztard           |     [] []  []                                   |\n     cflow              |        []  []                                   |\n     clisp              |        []  []     []                []          |\n     coreutils          |     [] []  []                          []       |\n     cpio               |                                                 |\n     cppi               |                                                 |\n     cpplib             |        []  []                       []          |\n     cryptsetup         |            []                                   |\n     dfarc              |        []  []                       []          |\n     dialog             |        []  []                    [] []    []    |\n     dico               |                                                 |\n     diffutils          |     [] []  []  []                [] []          |\n     dink               |        []  []                       []          |\n     doodle             |            []                                   |\n     e2fsprogs          |     []     []                       []          |\n     enscript           |        []  []         []                        |\n     exif               |     () []  []                                   |\n     fetchmail          |     [] []  ()  []     []            []          |\n     findutils          |     [] []  []                                   |\n     flex               |            []                       []          |\n     freedink           |        []  []                       []          |\n     gas                |                                     []          |\n     gawk               |        []  []                       []          |\n     gcal               |                                     []          |\n     gcc                |            []                       []          |\n     gettext-examples   |            []  []                [] []          |\n     gettext-runtime    |        []  []                    [] []          |\n     gettext-tools      |            []                       []    []    |\n     gip                |        []  []                       []    []    |\n     gjay               |            []                                   |\n     gliv               |     [] []  []                                   |\n     glunarclock        |        []  []                                   |\n     gnubiff            |            ()                                   |\n     gnucash            |     []     ()  ()     ()            ()          |\n     gnuedu             |        []                           []          |\n     gnulib             |            []                       []          |\n     gnunet             |                                                 |\n     gnunet-gtk         |        []                                       |\n     gnutls             |     []     []                                   |\n     gold               |                                     []          |\n     gpe-aerial         |     [] []  []                       []          |\n     gpe-beam           |     [] []  []                       []          |\n     gpe-bluetooth      |        []  []                                   |\n     gpe-calendar       |        []                                       |\n     gpe-clock          |     [] []  []                       []          |\n     gpe-conf           |     [] []  []                                   |\n     gpe-contacts       |        []  []                       []          |\n     gpe-edit           |        []  []                                   |\n     gpe-filemanager    |        []  []                       []          |\n     gpe-go             |     [] []  []                       []          |\n     gpe-login          |        []  []                                   |\n     gpe-ownerinfo      |     [] []  []                       []          |\n     gpe-package        |        []  []                       []          |\n     gpe-sketchbook     |     [] []  []                       []          |\n     gpe-su             |     [] []  []                       []          |\n     gpe-taskmanager    |     [] []  []                       []          |\n     gpe-timesheet      |     [] []  []                       []          |\n     gpe-today          |     [] []  []                       []          |\n     gpe-todo           |        []  []                       []          |\n     gphoto2            |     [] []  ()         []            []    []    |\n     gprof              |        []  []                       []          |\n     gpsdrive           |        []                           [] []       |\n     gramadoir          |        []  []                    []             |\n     grep               |     []                                          |\n     grub               |        []  []                                   |\n     gsasl              |            []                                   |\n     gss                |                                                 |\n     gst-plugins-bad    |     [] []  []                       []    []    |\n     gst-plugins-base   |     [] []  []                       []    []    |\n     gst-plugins-good   |     [] []  []  []                   []    []    |\n     gst-plugins-ugly   |     [] []  []  []                   []    []    |\n     gstreamer          |     [] []  []                       []    []    |\n     gtick              |        []  ()                    []             |\n     gtkam              |     [] []  ()                    [] []          |\n     gtkorphan          |     [] []  []                    []             |\n     gtkspell           |     [] []  []  []                [] []    []    |\n     gutenprint         |        []  []         []                        |\n     hello              |        []  []                    [] []          |\n     help2man           |            []                                   |\n     hylafax            |            []                       []          |\n     idutils            |        []  []                                   |\n     indent             |     [] []  []                    [] [] [] []    |\n     iso_15924          |        []      ()                [] []          |\n     iso_3166           | []  [] []  []  ()                [] [] [] ()    |\n     iso_3166_2         |                ()                               |\n     iso_4217           |     [] []  []  ()                   [] []       |\n     iso_639            | []  [] []  []  ()                [] []          |\n     iso_639_3          | []                                              |\n     jwhois             |                                     []          |\n     kbd                |     [] []  []  []                   []          |\n     keytouch           |        []  []                                   |\n     keytouch-editor    |        []  []                                   |\n     keytouch-keyboa... |        []                                       |\n     klavaro            |     [] []  []                    []             |\n     latrine            |        []  ()                                   |\n     ld                 |        []                           []          |\n     leafpad            |     [] []  []  []                   []    []    |\n     libc               |     [] []  []                       []          |\n     libexif            |        []  []         ()                        |\n     libextractor       |                                                 |\n     libgnutls          |     []                                          |\n     libgpewidget       |        []  []                                   |\n     libgpg-error       |     []     []                                   |\n     libgphoto2         |        []  ()                                   |\n     libgphoto2_port    |        []  ()                             []    |\n     libgsasl           |                                                 |\n     libiconv           |     [] []  []                    []    []       |\n     libidn             |     []     []                    []             |\n     lifelines          |        []  ()                                   |\n     liferea            |     []     []  []                   []    []    |\n     lilypond           |     []     []                       []          |\n     linkdr             |        []  []                       []          |\n     lordsawar          |        []                                       |\n     lprng              |                                                 |\n     lynx               |     [] []  []                          []       |\n     m4                 |     [] []  []  []                               |\n     mailfromd          |                                                 |\n     mailutils          |                                     []          |\n     make               |        []  []                       []          |\n     man-db             |                                                 |\n     man-db-manpages    |                                                 |\n     minicom            |     [] []  []                       []          |\n     mkisofs            |                                                 |\n     myserver           |                                                 |\n     nano               |            []                       []    []    |\n     opcodes            |            []                       []          |\n     parted             |     []     []                                   |\n     pies               |                                                 |\n     popt               |     [] []  []                    [] []          |\n     psmisc             |     []     []                             []    |\n     pspp               |                                     []          |\n     pwdutils           |        []                                       |\n     radius             |                                     []          |\n     recode             |     [] []  []  []                [] []          |\n     rosegarden         |     ()     ()                       ()          |\n     rpm                |        []  []                       []          |\n     rush               |                                                 |\n     sarg               |                                                 |\n     screem             |                                                 |\n     scrollkeeper       |     [] []  []         []            []          |\n     sed                |     []     []  []                [] [] []       |\n     sharutils          |        []  []                       [] []       |\n     shishi             |                                                 |\n     skencil            |        []  ()                       []          |\n     solfege            |            []                    []    []       |\n     solfege-manual     |                                  []    []       |\n     soundtracker       |        []  []                       []          |\n     sp                 |            []                                   |\n     sysstat            |        []  []                             []    |\n     tar                |     []     []                          [] []    |\n     texinfo            |            []                    [] []          |\n     tin                |            []                          []       |\n     unicode-han-tra... |                                                 |\n     unicode-transla... |                                                 |\n     util-linux-ng      |     [] []  []                       []          |\n     vice               |        ()  ()                                   |\n     vmm                |            []                                   |\n     vorbis-tools       |     []                           []             |\n     wastesedge         |        []                                       |\n     wdiff              |            []                       []          |\n     wget               |     []     []                          []       |\n     wyslij-po          |                                                 |\n     xchat              |     []     []  []                   [] []       |\n     xdg-user-dirs      | []  [] []  []  []                [] [] [] []    |\n     xkeyboard-config   | []  [] []  []                    [] []          |\n                        +-------------------------------------------------+\n                          crh cs da  de  el en en_GB en_ZA eo es et eu fa\n                           5  64 105 117 18  1   8     0   28 89 18 19  0\n\n                          fi  fr  ga gl gu he hi hr hu hy id  is it ja ka kn\n                        +----------------------------------------------------+\n     a2ps               | []  []                          []        []       |\n     aegis              |     []                                 []          |\n     ant-phone          |     []                                 []          |\n     anubis             | []  []                          []     []          |\n     aspell             |     []  []                      []     []          |\n     bash               | []  []                          []        []       |\n     bfd                | []  []                          []                 |\n     bibshelf           | []  []  []                      []     []          |\n     binutils           | []  []                          []                 |\n     bison              | []  []  []                      []                 |\n     bison-runtime      | []  []  []                      []     [] []       |\n     bluez-pin          | []  []  []                [] [] []  []    []       |\n     bombono-dvd        | []                                                 |\n     buzztard           |                                 []                 |\n     cflow              | []      []                      []                 |\n     clisp              |     []                                             |\n     coreutils          |     []  []                []    []     []          |\n     cpio               | []  []  []                      []                 |\n     cppi               | []  []                                             |\n     cpplib             | []  []                          []                 |\n     cryptsetup         |     []                          []     []          |\n     dfarc              | []  []                                 []          |\n     dialog             |     []  [] []                   []  [] [] []       |\n     dico               |                                                    |\n     diffutils          | []  []  [] []    []       []    []     [] []       |\n     dink               |     []                                             |\n     doodle             |         []                             []          |\n     e2fsprogs          |     []                          []                 |\n     enscript           |     []  []             []       []                 |\n     exif               | []  []                          []  [] [] []       |\n     fetchmail          |     []                          []     [] []       |\n     findutils          | []  []  []                []    []     []          |\n     flex               | []  []  []                                         |\n     freedink           | []  []                          []                 |\n     gas                |     []                          []                 |\n     gawk               |     []  []       []             []     () []       |\n     gcal               |     []                                             |\n     gcc                |                                 []                 |\n     gettext-examples   | []  []  []                []    []     [] []       |\n     gettext-runtime    | []  []  []                      []     [] []       |\n     gettext-tools      |     []                          []     [] []       |\n     gip                | []  []  [] []                   []        []       |\n     gjay               | []                                                 |\n     gliv               | []  ()                                             |\n     glunarclock        | []      []                []    []                 |\n     gnubiff            |     ()                          []     ()          |\n     gnucash            | ()  ()           ()       ()           () []       |\n     gnuedu             |     []                                 []          |\n     gnulib             | []  []  []                []           [] []       |\n     gnunet             |                                                    |\n     gnunet-gtk         |     []                                             |\n     gnutls             |     []                                 []          |\n     gold               | []                              []                 |\n     gpe-aerial         | []  []                          []                 |\n     gpe-beam           | []  []                          []        []       |\n     gpe-bluetooth      | []                              []     [] []       |\n     gpe-calendar       | []                                        []       |\n     gpe-clock          | []  []                    []    []        []       |\n     gpe-conf           | []  []                          []        []       |\n     gpe-contacts       | []  []                          []        []       |\n     gpe-edit           | []                              []        []       |\n     gpe-filemanager    | []                        []    []        []       |\n     gpe-go             | []  []                    []    []        []       |\n     gpe-login          | []                              []        []       |\n     gpe-ownerinfo      | []  []                    []    []        []       |\n     gpe-package        | []                              []        []       |\n     gpe-sketchbook     | []  []                          []        []       |\n     gpe-su             | []  []     []             []    []        []       |\n     gpe-taskmanager    | []  []                    []    []        []       |\n     gpe-timesheet      | []  []  []                      []        []       |\n     gpe-today          | []  []  [] []             []    []        []       |\n     gpe-todo           | []                              []        []       |\n     gphoto2            | []  []                    []    []     [] []       |\n     gprof              | []  []  []                      []                 |\n     gpsdrive           |            []                   []     []          |\n     gramadoir          |     []  []                      []                 |\n     grep               | []                                     []          |\n     grub               | []                        []    []     []          |\n     gsasl              | []  []  []                      []     []          |\n     gss                | []  []  []                      []     []          |\n     gst-plugins-bad    | []  []                    []    []     [] []       |\n     gst-plugins-base   | []  []                    []    []     [] []       |\n     gst-plugins-good   | []  []                    []    []     [] []       |\n     gst-plugins-ugly   | []  []                    []    []     [] []       |\n     gstreamer          | []  []                    []    []     []          |\n     gtick              | []  []  []                      []     []          |\n     gtkam              |     []                    []    []     [] []       |\n     gtkorphan          |     []                          []     []          |\n     gtkspell           | []  []  [] []             [] [] []     [] []       |\n     gutenprint         | []  []                    []           []          |\n     hello              | []      []                      []                 |\n     help2man           | []  []                                             |\n     hylafax            |                                 []                 |\n     idutils            | []  []  []                []    []     []          |\n     indent             | []  []  [] []             []    []     [] []       |\n     iso_15924          | []  ()                          []     []          |\n     iso_3166           | []  ()  [] [] [] [] [] [] []    []     [] []       |\n     iso_3166_2         |     ()                    []    []     []          |\n     iso_4217           | []  ()                    []    []     [] []       |\n     iso_639            | []  ()  []    []          []    []     [] []    [] |\n     iso_639_3          |     ()                                 []       [] |\n     jwhois             | []  []                    []    []     []          |\n     kbd                |     []                          []                 |\n     keytouch           | []  []  []                []    []     []          |\n     keytouch-editor    | []      []                []    []     []          |\n     keytouch-keyboa... | []      []                []    []     []          |\n     klavaro            |            []             []                       |\n     latrine            | []                              []     []          |\n     ld                 | []  []  []                      []                 |\n     leafpad            | []  []  []       []       []    []     [] ()       |\n     libc               | []  []     []                   []        []       |\n     libexif            |                                        []          |\n     libextractor       |                                                    |\n     libgnutls          |     []                                 []          |\n     libgpewidget       | []      []                      []        []       |\n     libgpg-error       |     []                                 []          |\n     libgphoto2         |     []                                 [] []       |\n     libgphoto2_port    |     []                                 [] []       |\n     libgsasl           | []  []  []                      []     []          |\n     libiconv           | []  []  []                      []     [] []       |\n     libidn             | []  []                          []     []          |\n     lifelines          |     ()                                             |\n     liferea            |     []                    []           [] []       |\n     lilypond           | []  []                                             |\n     linkdr             | []               []    [] []           []          |\n     lordsawar          |                                                    |\n     lprng              |                                 []                 |\n     lynx               |     []                    []    []     [] []       |\n     m4                 | []  []  [] []                   []        []       |\n     mailfromd          |                                                    |\n     mailutils          |     []                          []                 |\n     make               | []  []  [] []    []    []       []     [] []       |\n     man-db             |                                 []     []          |\n     man-db-manpages    |                                 []                 |\n     minicom            | []  []                    []    []        []       |\n     mkisofs            | []  []                          []     []          |\n     myserver           |                                                    |\n     nano               | []  []  [] []             []           []          |\n     opcodes            | []  []  []                      []                 |\n     parted             |     []                          []     [] []       |\n     pies               |                                                    |\n     popt               | []  []  [] []             []    []  [] [] []       |\n     psmisc             | []  []                          []                 |\n     pspp               |                                                    |\n     pwdutils           |     []                          []                 |\n     radius             |     []                          []                 |\n     recode             | []  []  [] []    []       []    []     []          |\n     rosegarden         | ()  ()                          ()     () ()       |\n     rpm                |                                 []        []       |\n     rush               |                                                    |\n     sarg               |     []                                             |\n     screem             |                                        [] []       |\n     scrollkeeper       | []                        []    []     []          |\n     sed                | []  []  [] []             []    []     [] []       |\n     sharutils          | []  []  []                []    []     [] []       |\n     shishi             |     []                                             |\n     skencil            |     []                                             |\n     solfege            | []  []     []                          []          |\n     solfege-manual     |     []     []                                      |\n     soundtracker       |     []                                 []          |\n     sp                 |     []                                    ()       |\n     sysstat            | []  []                          []     [] []       |\n     tar                | []  []  []                []    []     [] []       |\n     texinfo            |     []                          []     [] []       |\n     tin                |     []                                             |\n     unicode-han-tra... |                                                    |\n     unicode-transla... |     []  []                                         |\n     util-linux-ng      | []  []                    []    []     [] []       |\n     vice               |     ()                    ()           ()          |\n     vmm                |     []                                             |\n     vorbis-tools       |                                 []                 |\n     wastesedge         |     ()                                 ()          |\n     wdiff              | []                                                 |\n     wget               | []  []  []             [] []    []     [] []       |\n     wyslij-po          | []  []                          []                 |\n     xchat              | []  []        []    []    []    []     [] []    [] |\n     xdg-user-dirs      | []  []  [] [] [] [] []    []    []  [] [] []    [] |\n     xkeyboard-config   | []  []                    []    []     []          |\n                        +----------------------------------------------------+\n                          fi  fr  ga gl gu he hi hr hu hy id  is it ja ka kn\n                          105 121 53 20  4  8  3  5 53  2 120  5 84 67  0  4\n\n                          ko ku ky lg lt lv mk ml mn mr ms mt nb nds ne\n                        +-----------------------------------------------+\n     a2ps               |                               []              |\n     aegis              |                                               |\n     ant-phone          |                                               |\n     anubis             |                               []    []        |\n     aspell             |                         []                    |\n     bash               |                                               |\n     bfd                |                                               |\n     bibshelf           |                []             []              |\n     binutils           |                                               |\n     bison              |                               []              |\n     bison-runtime      |       []    [] []             []    []        |\n     bluez-pin          |    [] []    [] []             []              |\n     bombono-dvd        |                                               |\n     buzztard           |                                               |\n     cflow              |                                               |\n     clisp              |                                               |\n     coreutils          |          []                                   |\n     cpio               |                                               |\n     cppi               |                                               |\n     cpplib             |                                               |\n     cryptsetup         |                                               |\n     dfarc              |                   []                          |\n     dialog             |    []       [] []             []    []        |\n     dico               |                                               |\n     diffutils          |                []             []              |\n     dink               |                                               |\n     doodle             |                                               |\n     e2fsprogs          |                                               |\n     enscript           |                                               |\n     exif               |                []                             |\n     fetchmail          |                                               |\n     findutils          |                                               |\n     flex               |                                               |\n     freedink           |                                     []        |\n     gas                |                                               |\n     gawk               |                                               |\n     gcal               |                                               |\n     gcc                |                                               |\n     gettext-examples   |       []       []             [] []           |\n     gettext-runtime    | []                                            |\n     gettext-tools      | []                                            |\n     gip                |                []             []              |\n     gjay               |                                               |\n     gliv               |                                               |\n     glunarclock        |                []                             |\n     gnubiff            |                                               |\n     gnucash            | ()          ()                      ()     () |\n     gnuedu             |                                               |\n     gnulib             |                                               |\n     gnunet             |                                               |\n     gnunet-gtk         |                                               |\n     gnutls             |                               []              |\n     gold               |                                               |\n     gpe-aerial         |                []                             |\n     gpe-beam           |                []                             |\n     gpe-bluetooth      |                []                []           |\n     gpe-calendar       |                []                             |\n     gpe-clock          | []    []       []             [] []           |\n     gpe-conf           | []             []                             |\n     gpe-contacts       | []             []                             |\n     gpe-edit           |                []                             |\n     gpe-filemanager    | []             []                             |\n     gpe-go             | []             []                []           |\n     gpe-login          |                []                             |\n     gpe-ownerinfo      |                []             []              |\n     gpe-package        | []             []                             |\n     gpe-sketchbook     | []             []                             |\n     gpe-su             | []    []       []             [] [] []        |\n     gpe-taskmanager    | [] [] []       []             [] []           |\n     gpe-timesheet      |                []             []              |\n     gpe-today          |       []       []             [] []           |\n     gpe-todo           |                []                   []        |\n     gphoto2            |                                               |\n     gprof              |                               []              |\n     gpsdrive           |                                               |\n     gramadoir          |                                               |\n     grep               |                                               |\n     grub               |                                               |\n     gsasl              |                                               |\n     gss                |                                               |\n     gst-plugins-bad    |             [] []                [] []        |\n     gst-plugins-base   |             [] []                             |\n     gst-plugins-good   |                []                []           |\n     gst-plugins-ugly   |             [] []             [] [] []        |\n     gstreamer          |                                               |\n     gtick              |                                               |\n     gtkam              |                                     []        |\n     gtkorphan          |                []                      []     |\n     gtkspell           |       []    [] []       []    []    [] []     |\n     gutenprint         |                                               |\n     hello              | []             []             []              |\n     help2man           |                                               |\n     hylafax            |                                               |\n     idutils            |                                               |\n     indent             |                                               |\n     iso_15924          |             [] []                             |\n     iso_3166           | [] []       () [] [] []    []       []        |\n     iso_3166_2         |                                               |\n     iso_4217           |             []                      []        |\n     iso_639            |                      []    []                 |\n     iso_639_3          |                            []                 |\n     jwhois             |                []                             |\n     kbd                |                                               |\n     keytouch           |                []                             |\n     keytouch-editor    |                []                             |\n     keytouch-keyboa... |                []                             |\n     klavaro            |                                     []        |\n     latrine            |                []                             |\n     ld                 |                                               |\n     leafpad            | []          [] []                             |\n     libc               | []                                            |\n     libexif            |                                               |\n     libextractor       |                                               |\n     libgnutls          |                               []              |\n     libgpewidget       |                []             []              |\n     libgpg-error       |                                               |\n     libgphoto2         |                                               |\n     libgphoto2_port    |                                               |\n     libgsasl           |                                               |\n     libiconv           |                                               |\n     libidn             |                                               |\n     lifelines          |                                               |\n     liferea            |                                               |\n     lilypond           |                                               |\n     linkdr             |                                               |\n     lordsawar          |                                               |\n     lprng              |                                               |\n     lynx               |                                               |\n     m4                 |                                               |\n     mailfromd          |                                               |\n     mailutils          |                                               |\n     make               | []                                            |\n     man-db             |                                               |\n     man-db-manpages    |                                               |\n     minicom            |                                     []        |\n     mkisofs            |                                               |\n     myserver           |                                               |\n     nano               |                               []    []        |\n     opcodes            |                                               |\n     parted             |                                               |\n     pies               |                                               |\n     popt               | []             []                   []        |\n     psmisc             |                                               |\n     pspp               |                                               |\n     pwdutils           |                                               |\n     radius             |                                               |\n     recode             |                                               |\n     rosegarden         |                                               |\n     rpm                |                                               |\n     rush               |                                               |\n     sarg               |                                               |\n     screem             |                                               |\n     scrollkeeper       |                                     []     [] |\n     sed                |                                               |\n     sharutils          |                                               |\n     shishi             |                                               |\n     skencil            |                                               |\n     solfege            |                                     []        |\n     solfege-manual     |                                               |\n     soundtracker       |                                               |\n     sp                 |                                               |\n     sysstat            |                []                             |\n     tar                |       []                                      |\n     texinfo            |                                     []        |\n     tin                |                                               |\n     unicode-han-tra... |                                               |\n     unicode-transla... |                                               |\n     util-linux-ng      |                                               |\n     vice               |                                               |\n     vmm                |                                               |\n     vorbis-tools       |                                               |\n     wastesedge         |                                               |\n     wdiff              |                                               |\n     wget               |             []                                |\n     wyslij-po          |                                               |\n     xchat              | []             [] []                          |\n     xdg-user-dirs      | [] []       [] [] []       []       [] []     |\n     xkeyboard-config   | []    []    []                                |\n                        +-----------------------------------------------+\n                          ko ku ky lg lt lv mk ml mn mr ms mt nb nds ne\n                          20  5 10  1 13 48  4  2  2  4 24 10 20  3   1\n\n                          nl  nn or pa pl  ps pt pt_BR ro ru rw sk sl sq sr\n                        +---------------------------------------------------+\n     a2ps               | []           []     []  []   [] []       []    [] |\n     aegis              | []                      []      []                |\n     ant-phone          |                         []   []                   |\n     anubis             | []           []                 []                |\n     aspell             | []                           [] []    [] []       |\n     bash               | []                                    []          |\n     bfd                |                                 []                |\n     bibshelf           | []  []                                            |\n     binutils           |                                 []    []          |\n     bison              | []           []                 []                |\n     bison-runtime      | []           []     []  []   [] []       []       |\n     bluez-pin          | []           []         []   [] []    [] []    [] |\n     bombono-dvd        |     []                          ()                |\n     buzztard           | []  []                                            |\n     cflow              |              []                                   |\n     clisp              | []                              []                |\n     coreutils          | []           []     []  []      []       []       |\n     cpio               | []           []                 []                |\n     cppi               |              []                                   |\n     cpplib             | []                                                |\n     cryptsetup         | []                                                |\n     dfarc              |              []                                   |\n     dialog             | []           []         []      []                |\n     dico               |              []                                   |\n     diffutils          | []           []         []   [] []             [] |\n     dink               | ()                                                |\n     doodle             | []                                          []    |\n     e2fsprogs          | []           []                                   |\n     enscript           | []                      []   [] []       []       |\n     exif               | []           []              [] ()    []          |\n     fetchmail          | []           []                 []          []    |\n     findutils          | []           []     []          []       []       |\n     flex               | []           []         []   [] []                |\n     freedink           | []           []                                   |\n     gas                |                                                   |\n     gawk               | []           []         []   []                   |\n     gcal               |                                                   |\n     gcc                |                                                [] |\n     gettext-examples   | []           []     []       [] []    [] []    [] |\n     gettext-runtime    | []  []       []     []       [] []    [] []    [] |\n     gettext-tools      |              []              [] []    [] []    [] |\n     gip                | []           []                 []    []       [] |\n     gjay               |                                                   |\n     gliv               | []           []         []   [] []    []          |\n     glunarclock        | []                      []   []       []       [] |\n     gnubiff            | []                           ()                   |\n     gnucash            | []           ()         ()      ()                |\n     gnuedu             | []                                                |\n     gnulib             | []           []                 []       []       |\n     gnunet             |                                                   |\n     gnunet-gtk         |                                                   |\n     gnutls             | []           []                                   |\n     gold               |                                                   |\n     gpe-aerial         | []                  []  []   [] []       []    [] |\n     gpe-beam           | []                  []  []   [] []       []    [] |\n     gpe-bluetooth      | []                      []                        |\n     gpe-calendar       |                         []      []       []    [] |\n     gpe-clock          | []                  []  []   [] []    [] []    [] |\n     gpe-conf           | []                  []  []   [] []    [] []       |\n     gpe-contacts       |                         []   [] []       []    [] |\n     gpe-edit           | []           []                          []       |\n     gpe-filemanager    | []                              []       []       |\n     gpe-go             | []           []         []   [] []    [] []    [] |\n     gpe-login          | []                      []                        |\n     gpe-ownerinfo      | []                  []  []   [] []    [] []    [] |\n     gpe-package        | []                                       []       |\n     gpe-sketchbook     | []                  []  []   [] []       []    [] |\n     gpe-su             | []                  []  []   [] []    [] []    [] |\n     gpe-taskmanager    | []                  []  []   [] []    [] []    [] |\n     gpe-timesheet      | []                  []  []   [] []    [] []    [] |\n     gpe-today          | []                  []  []   [] []    [] []    [] |\n     gpe-todo           | []                      []      []       []    [] |\n     gphoto2            | []        [] []         []   [] []    []       [] |\n     gprof              | []                      []   []                   |\n     gpsdrive           | []                              []                |\n     gramadoir          | []                                    []          |\n     grep               | []           []                 []    []          |\n     grub               | []           []                 []                |\n     gsasl              | []           []                       []       [] |\n     gss                |              []              []       []          |\n     gst-plugins-bad    | []           []         []      []    []    []    |\n     gst-plugins-base   | []           []         []      []    []          |\n     gst-plugins-good   | []           []         []      []    []          |\n     gst-plugins-ugly   | []           []         []      []    [] []       |\n     gstreamer          | []           []         []      []    []          |\n     gtick              | []                              []    []          |\n     gtkam              | []        [] []         []      []    []          |\n     gtkorphan          | []                                                |\n     gtkspell           | []           []     []  []   [] []    [] [] [] [] |\n     gutenprint         | []                              []                |\n     hello              | []           []                       [] []       |\n     help2man           |              []                 []                |\n     hylafax            | []                                                |\n     idutils            | []           []         []   [] []                |\n     indent             | []           []         []   [] []    []       [] |\n     iso_15924          | []           []                 []       []       |\n     iso_3166           | []  [] [] [] []     ()  []   [] [] [] [] [] [] [] |\n     iso_3166_2         | []           []                          []       |\n     iso_4217           | []  []       []     []          [] []    []    [] |\n     iso_639            | []     [] [] []                 [] [] [] []    [] |\n     iso_639_3          |        [] []                                      |\n     jwhois             | []           []         []   []                   |\n     kbd                | []           []              []                   |\n     keytouch           | []           []                       []          |\n     keytouch-editor    | []           []                       []          |\n     keytouch-keyboa... | []           []                       []          |\n     klavaro            | []                      []                        |\n     latrine            |              []                 []                |\n     ld                 |                                                   |\n     leafpad            | []  []       []     []  []      []    [] []    [] |\n     libc               | []           []                 []    []          |\n     libexif            | []           []         ()            []          |\n     libextractor       |                                                   |\n     libgnutls          | []           []                                   |\n     libgpewidget       | []           []                          []       |\n     libgpg-error       |              []              []                   |\n     libgphoto2         | []           []                                   |\n     libgphoto2_port    | []           []         []      []    []          |\n     libgsasl           | []           []              []       []       [] |\n     libiconv           | []           []                       [] []    [] |\n     libidn             | []           []                                   |\n     lifelines          | []           []                                   |\n     liferea            | []           []     []  []   [] ()    ()    []    |\n     lilypond           | []                                                |\n     linkdr             | []                  []          []                |\n     lordsawar          |                                                   |\n     lprng              |              []                                   |\n     lynx               | []                      []      []                |\n     m4                 | []           []         []   [] []                |\n     mailfromd          |              []                                   |\n     mailutils          |              []                                   |\n     make               | []           []         []      []                |\n     man-db             | []           []                 []                |\n     man-db-manpages    | []           []                 []                |\n     minicom            |              []         []   [] []                |\n     mkisofs            | []           []                 []                |\n     myserver           |                                                   |\n     nano               | []           []         []      []                |\n     opcodes            | []                           []                   |\n     parted             | []           []                 []    []          |\n     pies               |              []                                   |\n     popt               | []           []     []          []                |\n     psmisc             | []           []                 []                |\n     pspp               | []                      []                        |\n     pwdutils           |              []                                   |\n     radius             | []           []                 []                |\n     recode             | []           []     []  []   [] []    [] []       |\n     rosegarden         |              ()                 ()                |\n     rpm                | []           []     []                            |\n     rush               | []           []                                   |\n     sarg               |                                                   |\n     screem             |                                                   |\n     scrollkeeper       | []  []       []              [] []    []    [] [] |\n     sed                | []           []     []  []   [] []    [] []    [] |\n     sharutils          | []           []                 []             [] |\n     shishi             |              []                                   |\n     skencil            |                     []  []                        |\n     solfege            | []           []         []      []                |\n     solfege-manual     | []           []         []                        |\n     soundtracker       |                                       []          |\n     sp                 |                                                   |\n     sysstat            | []           []         []      []                |\n     tar                | []           []                 []       []       |\n     texinfo            | []           []              [] []                |\n     tin                |                                 []                |\n     unicode-han-tra... |                                                   |\n     unicode-transla... |                                                   |\n     util-linux-ng      | []           []         []      []       []       |\n     vice               | []                                                |\n     vmm                | []                                                |\n     vorbis-tools       | []           []                                   |\n     wastesedge         | []                                                |\n     wdiff              | []           []                                   |\n     wget               | []           []     []  []      []    [] []       |\n     wyslij-po          | []  []       []                                   |\n     xchat              | []        [] []     []          []    [] [] [] [] |\n     xdg-user-dirs      | []  [] [] [] []  [] []  []   [] []    [] [] [] [] |\n     xkeyboard-config   | []           []                 []                |\n                        +---------------------------------------------------+\n                          nl  nn or pa pl  ps pt pt_BR ro ru rw sk sl sq sr\n                          135 10  4  7 105  1 29  62   47 91  3 54 46  9 37\n\n                          sv  sw ta te tg th tr uk vi  wa zh_CN zh_HK zh_TW\n                        +---------------------------------------------------+\n     a2ps               | []              [] [] [] []                       | 27\n     aegis              |                          []                       |  9\n     ant-phone          | []                 []    []      []               |  9\n     anubis             | []                 [] [] []                       | 15\n     aspell             |                       [] []  []                   | 20\n     bash               | []                    [] []                       | 12\n     bfd                |                          []                       |  6\n     bibshelf           | []                       []      []               | 16\n     binutils           |                       [] []                       |  8\n     bison              | []                       []                       | 12\n     bison-runtime      | []              []    [] []      []          []   | 29\n     bluez-pin          | []              [] [] [] []  []  []          []   | 37\n     bombono-dvd        |                          []                       |  4\n     buzztard           |                          []                       |  7\n     cflow              |                       [] []      []               |  9\n     clisp              |                                                   | 10\n     coreutils          | []                    [] []      []               | 22\n     cpio               | []                 [] [] []      []          []   | 13\n     cppi               |                       [] []                       |  5\n     cpplib             | []                 [] [] []      []          []   | 14\n     cryptsetup         | []                       []                       |  7\n     dfarc              |                          []                       |  9\n     dialog             | []  []          []       []  []  []          []   | 30\n     dico               |                       []                          |  2\n     diffutils          | []                 [] [] []      []          []   | 30\n     dink               |                                                   |  4\n     doodle             | []                       []                       |  7\n     e2fsprogs          | []                 []    []                       | 11\n     enscript           | []                 [] [] []                       | 17\n     exif               | []                       []      []               | 16\n     fetchmail          |                    []    []      []               | 17\n     findutils          | []                 [] [] []      []               | 20\n     flex               | []                 []    []                  []   | 15\n     freedink           |                          []                       | 10\n     gas                |                    []                             |  4\n     gawk               | []                 []    []      []               | 18\n     gcal               | []                 []                             |  5\n     gcc                | []                 []            []               |  7\n     gettext-examples   | []                 [] [] []      []    []    []   | 34\n     gettext-runtime    | []                 [] [] []      []    []    []   | 29\n     gettext-tools      | []                 [] [] []      []          []   | 22\n     gip                | []                       []      []          []   | 22\n     gjay               |                          []                       |  3\n     gliv               | []                 []    []                       | 14\n     glunarclock        | []                       []  []  []          []   | 19\n     gnubiff            | []                       []                       |  4\n     gnucash            |                    () [] ()      []          ()   | 10\n     gnuedu             |                          []                  []   |  7\n     gnulib             | []                    [] []      []               | 16\n     gnunet             |                          []                       |  1\n     gnunet-gtk         | []                 []    []                       |  5\n     gnutls             | []                       []      []               | 10\n     gold               |                          []                       |  4\n     gpe-aerial         | []                       []      []               | 18\n     gpe-beam           | []                       []      []               | 19\n     gpe-bluetooth      | []                       []      []               | 13\n     gpe-calendar       | []                       []  []  []               | 12\n     gpe-clock          | []                 []    []  []  []               | 28\n     gpe-conf           | []                       []  []  []               | 20\n     gpe-contacts       | []                       []      []               | 17\n     gpe-edit           | []                       []      []               | 12\n     gpe-filemanager    | []                       []  []  []               | 16\n     gpe-go             | []                 []    []  []  []               | 25\n     gpe-login          | []                       []      []               | 11\n     gpe-ownerinfo      | []                 []    []      []          []   | 25\n     gpe-package        | []                       []      []               | 13\n     gpe-sketchbook     | []                       []      []               | 20\n     gpe-su             | []                 []    []  []  []               | 30\n     gpe-taskmanager    | []                 []    []  []  []               | 29\n     gpe-timesheet      | []                 []    []      []          []   | 25\n     gpe-today          | []                 []    []  []  []          []   | 30\n     gpe-todo           | []                       []  []  []               | 17\n     gphoto2            | []                    [] []      []          []   | 24\n     gprof              | []                 []    []                       | 15\n     gpsdrive           | []                       []      []               | 11\n     gramadoir          | []                       []      []               | 11\n     grep               |                 []       []      []               | 10\n     grub               | []                       []      []               | 14\n     gsasl              | []                       []      []          []   | 14\n     gss                | []                       []      []               | 11\n     gst-plugins-bad    | []                 []    []      []               | 26\n     gst-plugins-base   | []                 [] [] []      []               | 24\n     gst-plugins-good   | []                 []    []      []               | 24\n     gst-plugins-ugly   | []                 [] [] []      []               | 29\n     gstreamer          | []                    [] []      []               | 22\n     gtick              |                       [] []      []               | 13\n     gtkam              | []                       []      []               | 20\n     gtkorphan          | []                       []      []               | 14\n     gtkspell           | []              [] [] [] []  []  []    []    []   | 45\n     gutenprint         | []                                                | 10\n     hello              | []              [] []    []      []          []   | 21\n     help2man           | []                       []                       |  7\n     hylafax            |                          []                       |  5\n     idutils            | []                 []    []      []               | 17\n     indent             | []                 [] [] []      []          []   | 30\n     iso_15924          |                 ()    [] ()      []          []   | 16\n     iso_3166           | []        []    () [] [] ()  []  []    []    ()   | 53\n     iso_3166_2         |                 ()    [] ()      []               |  9\n     iso_4217           | []              () [] [] ()      []    []         | 26\n     iso_639            | []     [] []    ()    [] ()  []  []    []    []   | 38\n     iso_639_3          |        []                ()                       |  8\n     jwhois             | []                 []    []      []          []   | 16\n     kbd                | []                 [] [] []      []               | 15\n     keytouch           | []                       []      []               | 16\n     keytouch-editor    | []                       []      []               | 14\n     keytouch-keyboa... | []                       []      []               | 14\n     klavaro            |                          []                       | 11\n     latrine            |                    []    []      []               | 10\n     ld                 | []                 []    []                  []   | 11\n     leafpad            | []                 [] [] []      []          []   | 33\n     libc               | []                 []    []      []          []   | 21\n     libexif            |                          []      ()               |  7\n     libextractor       |                          []                       |  1\n     libgnutls          | []                       []      []               |  9\n     libgpewidget       | []                       []      []               | 14\n     libgpg-error       | []                       []      []               |  9\n     libgphoto2         |                       [] []                       |  8\n     libgphoto2_port    | []                    [] []                  []   | 14\n     libgsasl           | []                       []      []               | 13\n     libiconv           | []                       []  []  []               | 21\n     libidn             | ()                       []      []               | 11\n     lifelines          | []                                                |  4\n     liferea            | []                 []            []               | 21\n     lilypond           |                          []                       |  7\n     linkdr             | []                 []    []      []          []   | 17\n     lordsawar          |                                                   |  1\n     lprng              |                          []                       |  3\n     lynx               | []                 [] [] []                       | 17\n     m4                 | []                       []      []          []   | 19\n     mailfromd          |                       [] []                       |  3\n     mailutils          |                          []                       |  5\n     make               | []                 []    []      []               | 21\n     man-db             | []                       []      []               |  8\n     man-db-manpages    |                                                   |  4\n     minicom            | []                       []                       | 16\n     mkisofs            |                          []      []               |  9\n     myserver           |                                                   |  0\n     nano               | []                       []      []          []   | 21\n     opcodes            | []                 []    []                       | 11\n     parted             | []                 [] [] []                  []   | 15\n     pies               |                       [] []                       |  3\n     popt               | []              [] []    []      []          []   | 27\n     psmisc             | []                       []                       | 11\n     pspp               |                                                   |  4\n     pwdutils           | []                       []                       |  6\n     radius             |                       [] []                       |  9\n     recode             | []                 []    []      []               | 28\n     rosegarden         | ()                                                |  0\n     rpm                | []                       []                  []   | 11\n     rush               |                       [] []                       |  4\n     sarg               |                                                   |  1\n     screem             |                          []                       |  3\n     scrollkeeper       | []                 [] [] []                  []   | 27\n     sed                | []                 []    []      []          []   | 30\n     sharutils          | []                 []    []      []          []   | 22\n     shishi             |                          []                       |  3\n     skencil            | []                       []                       |  7\n     solfege            | []                 []    []      []               | 16\n     solfege-manual     |                    []                             |  8\n     soundtracker       | []                 []    []                       |  9\n     sp                 |                    []                             |  3\n     sysstat            |                          []      []               | 15\n     tar                | []                 [] [] []      []          []   | 23\n     texinfo            | []                 [] [] []      []               | 17\n     tin                |                                                   |  4\n     unicode-han-tra... |                                                   |  0\n     unicode-transla... |                                                   |  2\n     util-linux-ng      | []                 [] [] []                       | 20\n     vice               | ()                 ()                             |  1\n     vmm                |                          []                       |  4\n     vorbis-tools       |                          []                       |  6\n     wastesedge         |                                                   |  2\n     wdiff              | []                       []                       |  7\n     wget               | []                 []    []      []          []   | 26\n     wyslij-po          |                       [] []                       |  8\n     xchat              | []              []    [] []      []          []   | 36\n     xdg-user-dirs      | []     [] []    [] [] [] []      []    []    []   | 63\n     xkeyboard-config   | []                    [] []                       | 22\n                        +---------------------------------------------------+\n       85 teams           sv  sw ta te tg th tr uk vi  wa zh_CN zh_HK zh_TW\n      178 domains         119  1  3  3  0 10 65 51 155 17  98     7    41    2618\n\n   Some counters in the preceding matrix are higher than the number of\nvisible blocks let us expect.  This is because a few extra PO files are\nused for implementing regional variants of languages, or language\ndialects.\n\n   For a PO file in the matrix above to be effective, the package to\nwhich it applies should also have been internationalized and\ndistributed as such by its maintainer.  There might be an observable\nlag between the mere existence a PO file and its wide availability in a\ndistribution.\n\n   If June 2010 seems to be old, you may fetch a more recent copy of\nthis `ABOUT-NLS' file on most GNU archive sites.  The most up-to-date\nmatrix with full percentage details can be found at\n`http://translationproject.org/extra/matrix.html'.\n\n1.5 Using `gettext' in new packages\n===================================\n\nIf you are writing a freely available program and want to\ninternationalize it you are welcome to use GNU `gettext' in your\npackage.  Of course you have to respect the GNU Library General Public\nLicense which covers the use of the GNU `gettext' library.  This means\nin particular that even non-free programs can use `libintl' as a shared\nlibrary, whereas only free software can use `libintl' as a static\nlibrary or use modified versions of `libintl'.\n\n   Once the sources are changed appropriately and the setup can handle\nthe use of `gettext' the only thing missing are the translations.  The\nFree Translation Project is also available for packages which are not\ndeveloped inside the GNU project.  Therefore the information given above\napplies also for every other Free Software Project.  Contact\n`coordinator@translationproject.org' to make the `.pot' files available\nto the translation teams.\n\n"
  },
  {
    "path": "AUTHORS",
    "content": "Little IO <littleioaudio@gmail.com>\nMatt Tytel <matthewtytel@gmail.com>\n"
  },
  {
    "path": "COPYING",
    "content": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU General Public License is a free, copyleft license for\nsoftware and other kinds of works.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nthe GNU General Public License is intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.  We, the Free Software Foundation, use the\nGNU General Public License for most of our software; it applies also to\nany other work released this way by its authors.  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  To protect your rights, we need to prevent others from denying you\nthese rights or asking you to surrender the rights.  Therefore, you have\ncertain responsibilities if you distribute copies of the software, or if\nyou modify it: responsibilities to respect the freedom of others.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must pass on to the recipients the same\nfreedoms that you received.  You must make sure that they, too, receive\nor can get the source code.  And you must show them these terms so they\nknow their rights.\n\n  Developers that use the GNU GPL protect your rights with two steps:\n(1) assert copyright on the software, and (2) offer you this License\ngiving you legal permission to copy, distribute and/or modify it.\n\n  For the developers' and authors' protection, the GPL clearly explains\nthat there is no warranty for this free software.  For both users' and\nauthors' sake, the GPL requires that modified versions be marked as\nchanged, so that their problems will not be attributed erroneously to\nauthors of previous versions.\n\n  Some devices are designed to deny users access to install or run\nmodified versions of the software inside them, although the manufacturer\ncan do so.  This is fundamentally incompatible with the aim of\nprotecting users' freedom to change the software.  The systematic\npattern of such abuse occurs in the area of products for individuals to\nuse, which is precisely where it is most unacceptable.  Therefore, we\nhave designed this version of the GPL to prohibit the practice for those\nproducts.  If such problems arise substantially in other domains, we\nstand ready to extend this provision to those domains in future versions\nof the GPL, as needed to protect the freedom of users.\n\n  Finally, every program is threatened constantly by software patents.\nStates should not allow patents to restrict development and use of\nsoftware on general-purpose computers, but in those that do, we wish to\navoid the special danger that patents applied to a free program could\nmake it effectively proprietary.  To prevent this, the GPL assures that\npatents cannot be used to render the program non-free.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Use with the GNU Affero General Public License.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU Affero General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the special requirements of the GNU Affero General Public License,\nsection 13, concerning interaction through a network will apply to the\ncombination as such.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\n  If the program does terminal interaction, make it output a short\nnotice like this when it starts in an interactive mode:\n\n    <program>  Copyright (C) <year>  <name of author>\n    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, your program's commands\nmight be different; for a GUI interface, you would use an \"about box\".\n\n  You should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU GPL, see\n<http://www.gnu.org/licenses/>.\n\n  The GNU General Public License does not permit incorporating your program\ninto proprietary programs.  If your program is a subroutine library, you\nmay consider it more useful to permit linking proprietary applications with\nthe library.  If this is what you want to do, use the GNU Lesser General\nPublic License instead of this License.  But first, please read\n<http://www.gnu.org/philosophy/why-not-lgpl.html>.\n"
  },
  {
    "path": "ChangeLog",
    "content": "2014-03-15  Matt Tytel  <matthewtytel@gmail.com>\n\n\t* patches/*: Edited levels of all patches.\n\t* configure.ac: Bumped version to 1.4\n\t* src/cursynth_gui.cpp: Updated website to gnu.org/software/cursynth\n\n2014-01-22  gettextize  <bug-gnu-gettext@gnu.org>\n\n\t* Makefile.am (ACLOCAL_AMFLAGS): New variable.\n\t(EXTRA_DIST): Add config.rpath, m4/ChangeLog.\n\t* configure.ac (AC_CONFIG_FILES): Add po/Makefile.in.\n\t(AM_GNU_GETTEXT_VERSION): Bump to 0.18.3.\n\nCopyright 2013-2015 Matt Tytel\nCopying and distribution of this file, with or without modification, are\npromitted provided the copyright notice and this notice are preserved.\n"
  },
  {
    "path": "INSTALL",
    "content": "Installation Instructions\n*************************\n\nCopyright (C) 1994-1996, 1999-2002, 2004-2013 Free Software Foundation,\nInc.\n\n   Copying and distribution of this file, with or without modification,\nare permitted in any medium without royalty provided the copyright\nnotice and this notice are preserved.  This file is offered as-is,\nwithout warranty of any kind.\n\nBasic Installation\n==================\n\n   Briefly, these shell commands should configure, build and install\nthis package:\n\n$ ./configure\n$ make\n$ sudo make install\n\nThe following more-detailed instructions are generic; see the `README'\nfile for instructions specific to this package.  Some packages provide\nthis `INSTALL' file but do not implement all of the features documented\nbelow.  The lack of an optional feature in a given package is not\nnecessarily a bug.  More recommendations for GNU packages can be found\nin *note Makefile Conventions: (standards)Makefile Conventions.\n\n   The `configure' shell script attempts to guess correct values for\nvarious system-dependent variables used during compilation.  It uses\nthose values to create a `Makefile' in each directory of the package.\nIt may also create one or more `.h' files containing system-dependent\ndefinitions.  Finally, it creates a shell script `config.status' that\nyou can run in the future to recreate the current configuration, and a\nfile `config.log' containing compiler output (useful mainly for\ndebugging `configure').\n\n   It can also use an optional file (typically called `config.cache'\nand enabled with `--cache-file=config.cache' or simply `-C') that saves\nthe results of its tests to speed up reconfiguring.  Caching is\ndisabled by default to prevent problems with accidental use of stale\ncache files.\n\n   If you need to do unusual things to compile the package, please try\nto figure out how `configure' could check whether to do them, and mail\ndiffs or instructions to the address given in the `README' so they can\nbe considered for the next release.  If you are using the cache, and at\nsome point `config.cache' contains results you don't want to keep, you\nmay remove or edit it.\n\n   The file `configure.ac' (or `configure.in') is used to create\n`configure' by a program called `autoconf'.  You need `configure.ac' if\nyou want to change it or regenerate `configure' using a newer version\nof `autoconf'.\n\n   The simplest way to compile this package is:\n\n  1. `cd' to the directory containing the package's source code and type\n     `./configure' to configure the package for your system.\n\n     Running `configure' might take a while.  While running, it prints\n     some messages telling which features it is checking for.\n\n  2. Type `make' to compile the package.\n\n  3. Optionally, type `make check' to run any self-tests that come with\n     the package, generally using the just-built uninstalled binaries.\n\n  4. Type `make install' to install the programs and any data files and\n     documentation.  When installing into a prefix owned by root, it is\n     recommended that the package be configured and built as a regular\n     user, and only the `make install' phase executed with root\n     privileges.\n\n  5. Optionally, type `make installcheck' to repeat any self-tests, but\n     this time using the binaries in their final installed location.\n     This target does not install anything.  Running this target as a\n     regular user, particularly if the prior `make install' required\n     root privileges, verifies that the installation completed\n     correctly.\n\n  6. You can remove the program binaries and object files from the\n     source code directory by typing `make clean'.  To also remove the\n     files that `configure' created (so you can compile the package for\n     a different kind of computer), type `make distclean'.  There is\n     also a `make maintainer-clean' target, but that is intended mainly\n     for the package's developers.  If you use it, you may have to get\n     all sorts of other programs in order to regenerate files that came\n     with the distribution.\n\n  7. Often, you can also type `make uninstall' to remove the installed\n     files again.  In practice, not all packages have tested that\n     uninstallation works correctly, even though it is required by the\n     GNU Coding Standards.\n\n  8. Some packages, particularly those that use Automake, provide `make\n     distcheck', which can by used by developers to test that all other\n     targets like `make install' and `make uninstall' work correctly.\n     This target is generally not run by end users.\n\nCompilers and Options\n=====================\n\n   Some systems require unusual options for compilation or linking that\nthe `configure' script does not know about.  Run `./configure --help'\nfor details on some of the pertinent environment variables.\n\n   You can give `configure' initial values for configuration parameters\nby setting variables in the command line or in the environment.  Here\nis an example:\n\n     ./configure CC=c99 CFLAGS=-g LIBS=-lposix\n\n   *Note Defining Variables::, for more details.\n\nCompiling For Multiple Architectures\n====================================\n\n   You can compile the package for more than one kind of computer at the\nsame time, by placing the object files for each architecture in their\nown directory.  To do this, you can use GNU `make'.  `cd' to the\ndirectory where you want the object files and executables to go and run\nthe `configure' script.  `configure' automatically checks for the\nsource code in the directory that `configure' is in and in `..'.  This\nis known as a \"VPATH\" build.\n\n   With a non-GNU `make', it is safer to compile the package for one\narchitecture at a time in the source code directory.  After you have\ninstalled the package for one architecture, use `make distclean' before\nreconfiguring for another architecture.\n\n   On MacOS X 10.5 and later systems, you can create libraries and\nexecutables that work on multiple system types--known as \"fat\" or\n\"universal\" binaries--by specifying multiple `-arch' options to the\ncompiler but only a single `-arch' option to the preprocessor.  Like\nthis:\n\n     ./configure CC=\"gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64\" \\\n                 CXX=\"g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64\" \\\n                 CPP=\"gcc -E\" CXXCPP=\"g++ -E\"\n\n   This is not guaranteed to produce working output in all cases, you\nmay have to build one architecture at a time and combine the results\nusing the `lipo' tool if you have problems.\n\nInstallation Names\n==================\n\n   By default, `make install' installs the package's commands under\n`/usr/local/bin', include files under `/usr/local/include', etc.  You\ncan specify an installation prefix other than `/usr/local' by giving\n`configure' the option `--prefix=PREFIX', where PREFIX must be an\nabsolute file name.\n\n   You can specify separate installation prefixes for\narchitecture-specific files and architecture-independent files.  If you\npass the option `--exec-prefix=PREFIX' to `configure', the package uses\nPREFIX as the prefix for installing programs and libraries.\nDocumentation and other data files still use the regular prefix.\n\n   In addition, if you use an unusual directory layout you can give\noptions like `--bindir=DIR' to specify different values for particular\nkinds of files.  Run `configure --help' for a list of the directories\nyou can set and what kinds of files go in them.  In general, the\ndefault for these options is expressed in terms of `${prefix}', so that\nspecifying just `--prefix' will affect all of the other directory\nspecifications that were not explicitly provided.\n\n   The most portable way to affect installation locations is to pass the\ncorrect locations to `configure'; however, many packages provide one or\nboth of the following shortcuts of passing variable assignments to the\n`make install' command line to change installation locations without\nhaving to reconfigure or recompile.\n\n   The first method involves providing an override variable for each\naffected directory.  For example, `make install\nprefix=/alternate/directory' will choose an alternate location for all\ndirectory configuration variables that were expressed in terms of\n`${prefix}'.  Any directories that were specified during `configure',\nbut not in terms of `${prefix}', must each be overridden at install\ntime for the entire installation to be relocated.  The approach of\nmakefile variable overrides for each directory variable is required by\nthe GNU Coding Standards, and ideally causes no recompilation.\nHowever, some platforms have known limitations with the semantics of\nshared libraries that end up requiring recompilation when using this\nmethod, particularly noticeable in packages that use GNU Libtool.\n\n   The second method involves providing the `DESTDIR' variable.  For\nexample, `make install DESTDIR=/alternate/directory' will prepend\n`/alternate/directory' before all installation names.  The approach of\n`DESTDIR' overrides is not required by the GNU Coding Standards, and\ndoes not work on platforms that have drive letters.  On the other hand,\nit does better at avoiding recompilation issues, and works well even\nwhen some directory options were not specified in terms of `${prefix}'\nat `configure' time.\n\nOptional Features\n=================\n\n   If the package supports it, you can cause programs to be installed\nwith an extra prefix or suffix on their names by giving `configure' the\noption `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.\n\n   Some packages pay attention to `--enable-FEATURE' options to\n`configure', where FEATURE indicates an optional part of the package.\nThey may also pay attention to `--with-PACKAGE' options, where PACKAGE\nis something like `gnu-as' or `x' (for the X Window System).  The\n`README' should mention any `--enable-' and `--with-' options that the\npackage recognizes.\n\n   For packages that use the X Window System, `configure' can usually\nfind the X include and library files automatically, but if it doesn't,\nyou can use the `configure' options `--x-includes=DIR' and\n`--x-libraries=DIR' to specify their locations.\n\n   Some packages offer the ability to configure how verbose the\nexecution of `make' will be.  For these packages, running `./configure\n--enable-silent-rules' sets the default to minimal output, which can be\noverridden with `make V=1'; while running `./configure\n--disable-silent-rules' sets the default to verbose, which can be\noverridden with `make V=0'.\n\nParticular systems\n==================\n\n   On HP-UX, the default C compiler is not ANSI C compatible.  If GNU\nCC is not installed, it is recommended to use the following options in\norder to use an ANSI C compiler:\n\n     ./configure CC=\"cc -Ae -D_XOPEN_SOURCE=500\"\n\nand if that doesn't work, install pre-built binaries of GCC for HP-UX.\n\n   HP-UX `make' updates targets which have the same time stamps as\ntheir prerequisites, which makes it generally unusable when shipped\ngenerated files such as `configure' are involved.  Use GNU `make'\ninstead.\n\n   On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot\nparse its `<wchar.h>' header file.  The option `-nodtk' can be used as\na workaround.  If GNU CC is not installed, it is therefore recommended\nto try\n\n     ./configure CC=\"cc\"\n\nand if that doesn't work, try\n\n     ./configure CC=\"cc -nodtk\"\n\n   On Solaris, don't put `/usr/ucb' early in your `PATH'.  This\ndirectory contains several dysfunctional programs; working variants of\nthese programs are available in `/usr/bin'.  So, if you need `/usr/ucb'\nin your `PATH', put it _after_ `/usr/bin'.\n\n   On Haiku, software installed for all users goes in `/boot/common',\nnot `/usr/local'.  It is recommended to use the following options:\n\n     ./configure --prefix=/boot/common\n\nSpecifying the System Type\n==========================\n\n   There may be some features `configure' cannot figure out\nautomatically, but needs to determine by the type of machine the package\nwill run on.  Usually, assuming the package is built to be run on the\n_same_ architectures, `configure' can figure that out, but if it prints\na message saying it cannot guess the machine type, give it the\n`--build=TYPE' option.  TYPE can either be a short name for the system\ntype, such as `sun4', or a canonical name which has the form:\n\n     CPU-COMPANY-SYSTEM\n\nwhere SYSTEM can have one of these forms:\n\n     OS\n     KERNEL-OS\n\n   See the file `config.sub' for the possible values of each field.  If\n`config.sub' isn't included in this package, then this package doesn't\nneed to know the machine type.\n\n   If you are _building_ compiler tools for cross-compiling, you should\nuse the option `--target=TYPE' to select the type of system they will\nproduce code for.\n\n   If you want to _use_ a cross compiler, that generates code for a\nplatform different from the build platform, you should specify the\n\"host\" platform (i.e., that on which the generated programs will\neventually be run) with `--host=TYPE'.\n\nSharing Defaults\n================\n\n   If you want to set default values for `configure' scripts to share,\nyou can create a site shell script called `config.site' that gives\ndefault values for variables like `CC', `cache_file', and `prefix'.\n`configure' looks for `PREFIX/share/config.site' if it exists, then\n`PREFIX/etc/config.site' if it exists.  Or, you can set the\n`CONFIG_SITE' environment variable to the location of the site script.\nA warning: not all `configure' scripts look for a site script.\n\nDefining Variables\n==================\n\n   Variables not defined in a site shell script can be set in the\nenvironment passed to `configure'.  However, some packages may run\nconfigure again during the build, and the customized values of these\nvariables may be lost.  In order to avoid this problem, you should set\nthem in the `configure' command line, using `VAR=value'.  For example:\n\n     ./configure CC=/usr/local2/bin/gcc\n\ncauses the specified `gcc' to be used as the C compiler (unless it is\noverridden in the site shell script).\n\nUnfortunately, this technique does not work for `CONFIG_SHELL' due to\nan Autoconf limitation.  Until the limitation is lifted, you can use\nthis workaround:\n\n     CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash\n\n`configure' Invocation\n======================\n\n   `configure' recognizes the following options to control how it\noperates.\n\n`--help'\n`-h'\n     Print a summary of all of the options to `configure', and exit.\n\n`--help=short'\n`--help=recursive'\n     Print a summary of the options unique to this package's\n     `configure', and exit.  The `short' variant lists options used\n     only in the top level, while the `recursive' variant lists options\n     also present in any nested packages.\n\n`--version'\n`-V'\n     Print the version of Autoconf used to generate the `configure'\n     script, and exit.\n\n`--cache-file=FILE'\n     Enable the cache: use and save the results of the tests in FILE,\n     traditionally `config.cache'.  FILE defaults to `/dev/null' to\n     disable caching.\n\n`--config-cache'\n`-C'\n     Alias for `--cache-file=config.cache'.\n\n`--quiet'\n`--silent'\n`-q'\n     Do not print messages saying which checks are being made.  To\n     suppress all normal output, redirect it to `/dev/null' (any error\n     messages will still be shown).\n\n`--srcdir=DIR'\n     Look for the package's source code in directory DIR.  Usually\n     `configure' can determine that directory automatically.\n\n`--prefix=DIR'\n     Use DIR as the installation prefix.  *note Installation Names::\n     for more details, including other options available for fine-tuning\n     the installation locations.\n\n`--no-create'\n`-n'\n     Run the configure checks, but stop before creating any output\n     files.\n\n`configure' also accepts some other, not widely useful, options.  Run\n`configure --help' for more details.\n"
  },
  {
    "path": "Makefile.am",
    "content": "SUBDIRS = cJSON rtaudio rtmidi mopo src po doc\nEXTRA_DIST = config.rpath patches\n\npatchesdir = $(pkgdatadir)/patches\npatches_DATA = $(top_srcdir)/patches/*.mite\n\nACLOCAL_AMFLAGS = -I m4\nLDFLAGS += -L/usr/local/opt/gettext/lib\nCPPFLAGS += -I/usr/local/opt/gettext/include\n"
  },
  {
    "path": "NEWS",
    "content": "No news is good news.\n"
  },
  {
    "path": "README",
    "content": "cursynth - a GNU program\n------------\ncursynth is a polyphonic, MIDI enabled, subtractive synth that runs in your\nterminal with an ascii interface.\n\ncursynth will connect to all MIDI devices and send output to the default audio\ndevice on your system.\n\n### Building\nIf you just want to build Cursynth, check out [ftp://ftp.gnu.org/gnu/cursynth]\nfor latest source releases that don't require as much to build.\n\nIf you want to develop Cursynth, this source is the right place.\nRun these commands to build the project from source:\n\n$ autoreconf -i\n$ ./configure\n$ make\n\nAnd then if you want to install, next run:\n\n$ sudo make install\n\n### Usage\ncursynth [--buffer-size OR -b preferred-buffer-size]\n         [--sample-rate OR -s preferred-sample-rate]\n         [--version OR -V]\n\n### Controls\n* awsedftgyhujkolp;' - a playable keyboard (no key up events)\n* \\`1234567890 - a slider for the current selected control\n* up/down - previous/next control\n* left/right - decrement/increment control\n* F1 (or [shift] + H) - help/controls\n* [shift] + L - browse/load patches\n* [shift] + S - save patch\n* m - arm midi learn\n* c - erase midi learn\n\n### Requirements:\n* OS: Mac OSX or GNU/Linux\n* Terminal: a color enabled terminal with minimum 120x44 ascii characters\n* If you want key up events, you have to use a MIDI keyboard\n\n### TODO:\n* Make a LV2 plugin version of cursynth\n* More modulation sources and destinations\n* Routable Envelopes\n* On startup select audio output device\n* On startup select MIDI input device\n* Lot's more...\n\nQuestions? Feature requests? Bugs? email matthewtytel@gmail.com\n\nCopyright 2013-2015 Matt Tytel <matthewtytel@gmail.com>\n"
  },
  {
    "path": "cJSON/LICENSE",
    "content": "  Copyright (c) 2009 Dave Gamble\n \n  Permission is hereby granted, free of charge, to any person obtaining a copy\n  of this software and associated documentation files (the \"Software\"), to deal\n  in the Software without restriction, including without limitation the rights\n  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n  copies of the Software, and to permit persons to whom the Software is\n  furnished to do so, subject to the following conditions:\n \n  The above copyright notice and this permission notice shall be included in\n  all copies or substantial portions of the Software.\n \n  THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n  THE SOFTWARE.\n\n"
  },
  {
    "path": "cJSON/Makefile.am",
    "content": "noinst_LIBRARIES = libcJSON.a\nlibcJSON_a_SOURCES = cJSON.c cJSON.h\n"
  },
  {
    "path": "cJSON/cJSON.c",
    "content": "/*\n  Copyright (c) 2009 Dave Gamble\n\n  Permission is hereby granted, free of charge, to any person obtaining a copy\n  of this software and associated documentation files (the \"Software\"), to deal\n  in the Software without restriction, including without limitation the rights\n  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n  copies of the Software, and to permit persons to whom the Software is\n  furnished to do so, subject to the following conditions:\n\n  The above copyright notice and this permission notice shall be included in\n  all copies or substantial portions of the Software.\n\n  THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n  THE SOFTWARE.\n*/\n\n/* cJSON */\n/* JSON parser in C. */\n\n#include <string.h>\n#include <stdio.h>\n#include <math.h>\n#include <stdlib.h>\n#include <float.h>\n#include <limits.h>\n#include <ctype.h>\n#include \"cJSON.h\"\n\nstatic const char *ep;\n\nconst char *cJSON_GetErrorPtr(void) {return ep;}\n\nstatic int cJSON_strcasecmp(const char *s1,const char *s2)\n{\n\tif (!s1) return (s1==s2)?0:1;if (!s2) return 1;\n\tfor(; tolower(*s1) == tolower(*s2); ++s1, ++s2)\tif(*s1 == 0)\treturn 0;\n\treturn tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2);\n}\n\nstatic void *(*cJSON_malloc)(size_t sz) = malloc;\nstatic void (*cJSON_free)(void *ptr) = free;\n\nstatic char* cJSON_strdup(const char* str)\n{\n      size_t len;\n      char* copy;\n\n      len = strlen(str) + 1;\n      if (!(copy = (char*)cJSON_malloc(len))) return 0;\n      memcpy(copy,str,len);\n      return copy;\n}\n\nvoid cJSON_InitHooks(cJSON_Hooks* hooks)\n{\n    if (!hooks) { /* Reset hooks */\n        cJSON_malloc = malloc;\n        cJSON_free = free;\n        return;\n    }\n\n\tcJSON_malloc = (hooks->malloc_fn)?hooks->malloc_fn:malloc;\n\tcJSON_free\t = (hooks->free_fn)?hooks->free_fn:free;\n}\n\n/* Internal constructor. */\nstatic cJSON *cJSON_New_Item(void)\n{\n\tcJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON));\n\tif (node) memset(node,0,sizeof(cJSON));\n\treturn node;\n}\n\n/* Delete a cJSON structure. */\nvoid cJSON_Delete(cJSON *c)\n{\n\tcJSON *next;\n\twhile (c)\n\t{\n\t\tnext=c->next;\n\t\tif (!(c->type&cJSON_IsReference) && c->child) cJSON_Delete(c->child);\n\t\tif (!(c->type&cJSON_IsReference) && c->valuestring) cJSON_free(c->valuestring);\n\t\tif (c->string) cJSON_free(c->string);\n\t\tcJSON_free(c);\n\t\tc=next;\n\t}\n}\n\n/* Parse the input text to generate a number, and populate the result into item. */\nstatic const char *parse_number(cJSON *item,const char *num)\n{\n\tdouble n=0,sign=1,scale=0;int subscale=0,signsubscale=1;\n\n\tif (*num=='-') sign=-1,num++;\t/* Has sign? */\n\tif (*num=='0') num++;\t\t\t/* is zero */\n\tif (*num>='1' && *num<='9')\tdo\tn=(n*10.0)+(*num++ -'0');\twhile (*num>='0' && *num<='9');\t/* Number? */\n\tif (*num=='.' && num[1]>='0' && num[1]<='9') {num++;\t\tdo\tn=(n*10.0)+(*num++ -'0'),scale--; while (*num>='0' && *num<='9');}\t/* Fractional part? */\n\tif (*num=='e' || *num=='E')\t\t/* Exponent? */\n\t{\tnum++;if (*num=='+') num++;\telse if (*num=='-') signsubscale=-1,num++;\t\t/* With sign? */\n\t\twhile (*num>='0' && *num<='9') subscale=(subscale*10)+(*num++ - '0');\t/* Number? */\n\t}\n\n\tn=sign*n*pow(10.0,(scale+subscale*signsubscale));\t/* number = +/- number.fraction * 10^+/- exponent */\n\t\n\titem->valuedouble=n;\n\titem->valueint=(int)n;\n\titem->type=cJSON_Number;\n\treturn num;\n}\n\n/* Render the number nicely from the given item into a string. */\nstatic char *print_number(cJSON *item)\n{\n\tchar *str;\n\tdouble d=item->valuedouble;\n\tif (fabs(((double)item->valueint)-d)<=DBL_EPSILON && d<=INT_MAX && d>=INT_MIN)\n\t{\n\t\tstr=(char*)cJSON_malloc(21);\t/* 2^64+1 can be represented in 21 chars. */\n\t\tif (str) sprintf(str,\"%d\",item->valueint);\n\t}\n\telse\n\t{\n\t\tstr=(char*)cJSON_malloc(64);\t/* This is a nice tradeoff. */\n\t\tif (str)\n\t\t{\n\t\t\tif (fabs(floor(d)-d)<=DBL_EPSILON && fabs(d)<1.0e60)sprintf(str,\"%.0f\",d);\n\t\t\telse if (fabs(d)<1.0e-6 || fabs(d)>1.0e9)\t\t\tsprintf(str,\"%e\",d);\n\t\t\telse\t\t\t\t\t\t\t\t\t\t\t\tsprintf(str,\"%f\",d);\n\t\t}\n\t}\n\treturn str;\n}\n\nstatic unsigned parse_hex4(const char *str)\n{\n\tunsigned h=0;\n\tif (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;\n\th=(h&15)<<4;str++;\n\tif (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;\n\th=(h&15)<<4;str++;\n\tif (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;\n\th=(h&15)<<4;str++;\n\tif (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;\n\treturn h;\n}\n\n/* Parse the input text into an unescaped cstring, and populate item. */\nstatic const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };\nstatic const char *parse_string(cJSON *item,const char *str)\n{\n\tconst char *ptr=str+1;char *ptr2;char *out;int len=0;unsigned uc,uc2;\n\tif (*str!='\\\"') {ep=str;return 0;}\t/* not a string! */\n\t\n\twhile (*ptr!='\\\"' && *ptr && ++len) if (*ptr++ == '\\\\') ptr++;\t/* Skip escaped quotes. */\n\t\n\tout=(char*)cJSON_malloc(len+1);\t/* This is how long we need for the string, roughly. */\n\tif (!out) return 0;\n\t\n\tptr=str+1;ptr2=out;\n\twhile (*ptr!='\\\"' && *ptr)\n\t{\n\t\tif (*ptr!='\\\\') *ptr2++=*ptr++;\n\t\telse\n\t\t{\n\t\t\tptr++;\n\t\t\tswitch (*ptr)\n\t\t\t{\n\t\t\t\tcase 'b': *ptr2++='\\b';\tbreak;\n\t\t\t\tcase 'f': *ptr2++='\\f';\tbreak;\n\t\t\t\tcase 'n': *ptr2++='\\n';\tbreak;\n\t\t\t\tcase 'r': *ptr2++='\\r';\tbreak;\n\t\t\t\tcase 't': *ptr2++='\\t';\tbreak;\n\t\t\t\tcase 'u':\t /* transcode utf16 to utf8. */\n\t\t\t\t\tuc=parse_hex4(ptr+1);ptr+=4;\t/* get the unicode char. */\n\n\t\t\t\t\tif ((uc>=0xDC00 && uc<=0xDFFF) || uc==0)\tbreak;\t/* check for invalid.\t*/\n\n\t\t\t\t\tif (uc>=0xD800 && uc<=0xDBFF)\t/* UTF16 surrogate pairs.\t*/\n\t\t\t\t\t{\n\t\t\t\t\t\tif (ptr[1]!='\\\\' || ptr[2]!='u')\tbreak;\t/* missing second-half of surrogate.\t*/\n\t\t\t\t\t\tuc2=parse_hex4(ptr+3);ptr+=6;\n\t\t\t\t\t\tif (uc2<0xDC00 || uc2>0xDFFF)\t\tbreak;\t/* invalid second-half of surrogate.\t*/\n\t\t\t\t\t\tuc=0x10000 + (((uc&0x3FF)<<10) | (uc2&0x3FF));\n\t\t\t\t\t}\n\n\t\t\t\t\tlen=4;if (uc<0x80) len=1;else if (uc<0x800) len=2;else if (uc<0x10000) len=3; ptr2+=len;\n\t\t\t\t\t\n\t\t\t\t\tswitch (len) {\n\t\t\t\t\t\tcase 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;\n\t\t\t\t\t\tcase 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;\n\t\t\t\t\t\tcase 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;\n\t\t\t\t\t\tcase 1: *--ptr2 =(uc | firstByteMark[len]);\n\t\t\t\t\t}\n\t\t\t\t\tptr2+=len;\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:  *ptr2++=*ptr; break;\n\t\t\t}\n\t\t\tptr++;\n\t\t}\n\t}\n\t*ptr2=0;\n\tif (*ptr=='\\\"') ptr++;\n\titem->valuestring=out;\n\titem->type=cJSON_String;\n\treturn ptr;\n}\n\n/* Render the cstring provided to an escaped version that can be printed. */\nstatic char *print_string_ptr(const char *str)\n{\n\tconst char *ptr;char *ptr2,*out;int len=0;unsigned char token;\n\t\n\tif (!str) return cJSON_strdup(\"\");\n\tptr=str;while ((token=*ptr) && ++len) {if (strchr(\"\\\"\\\\\\b\\f\\n\\r\\t\",token)) len++; else if (token<32) len+=5;ptr++;}\n\t\n\tout=(char*)cJSON_malloc(len+3);\n\tif (!out) return 0;\n\n\tptr2=out;ptr=str;\n\t*ptr2++='\\\"';\n\twhile (*ptr)\n\t{\n\t\tif ((unsigned char)*ptr>31 && *ptr!='\\\"' && *ptr!='\\\\') *ptr2++=*ptr++;\n\t\telse\n\t\t{\n\t\t\t*ptr2++='\\\\';\n\t\t\tswitch (token=*ptr++)\n\t\t\t{\n\t\t\t\tcase '\\\\':\t*ptr2++='\\\\';\tbreak;\n\t\t\t\tcase '\\\"':\t*ptr2++='\\\"';\tbreak;\n\t\t\t\tcase '\\b':\t*ptr2++='b';\tbreak;\n\t\t\t\tcase '\\f':\t*ptr2++='f';\tbreak;\n\t\t\t\tcase '\\n':\t*ptr2++='n';\tbreak;\n\t\t\t\tcase '\\r':\t*ptr2++='r';\tbreak;\n\t\t\t\tcase '\\t':\t*ptr2++='t';\tbreak;\n\t\t\t\tdefault: sprintf(ptr2,\"u%04x\",token);ptr2+=5;\tbreak;\t/* escape and print */\n\t\t\t}\n\t\t}\n\t}\n\t*ptr2++='\\\"';*ptr2++=0;\n\treturn out;\n}\n/* Invote print_string_ptr (which is useful) on an item. */\nstatic char *print_string(cJSON *item)\t{return print_string_ptr(item->valuestring);}\n\n/* Predeclare these prototypes. */\nstatic const char *parse_value(cJSON *item,const char *value);\nstatic char *print_value(cJSON *item,int depth,int fmt);\nstatic const char *parse_array(cJSON *item,const char *value);\nstatic char *print_array(cJSON *item,int depth,int fmt);\nstatic const char *parse_object(cJSON *item,const char *value);\nstatic char *print_object(cJSON *item,int depth,int fmt);\n\n/* Utility to jump whitespace and cr/lf */\nstatic const char *skip(const char *in) {while (in && *in && (unsigned char)*in<=32) in++; return in;}\n\n/* Parse an object - create a new root, and populate. */\ncJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated)\n{\n\tconst char *end=0;\n\tcJSON *c=cJSON_New_Item();\n\tep=0;\n\tif (!c) return 0;       /* memory fail */\n\n\tend=parse_value(c,skip(value));\n\tif (!end)\t{cJSON_Delete(c);return 0;}\t/* parse failure. ep is set. */\n\n\t/* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */\n\tif (require_null_terminated) {end=skip(end);if (*end) {cJSON_Delete(c);ep=end;return 0;}}\n\tif (return_parse_end) *return_parse_end=end;\n\treturn c;\n}\n/* Default options for cJSON_Parse */\ncJSON *cJSON_Parse(const char *value) {return cJSON_ParseWithOpts(value,0,0);}\n\n/* Render a cJSON item/entity/structure to text. */\nchar *cJSON_Print(cJSON *item)\t\t\t\t{return print_value(item,0,1);}\nchar *cJSON_PrintUnformatted(cJSON *item)\t{return print_value(item,0,0);}\n\n/* Parser core - when encountering text, process appropriately. */\nstatic const char *parse_value(cJSON *item,const char *value)\n{\n\tif (!value)\t\t\t\t\t\treturn 0;\t/* Fail on null. */\n\tif (!strncmp(value,\"null\",4))\t{ item->type=cJSON_NULL;  return value+4; }\n\tif (!strncmp(value,\"false\",5))\t{ item->type=cJSON_False; return value+5; }\n\tif (!strncmp(value,\"true\",4))\t{ item->type=cJSON_True; item->valueint=1;\treturn value+4; }\n\tif (*value=='\\\"')\t\t\t\t{ return parse_string(item,value); }\n\tif (*value=='-' || (*value>='0' && *value<='9'))\t{ return parse_number(item,value); }\n\tif (*value=='[')\t\t\t\t{ return parse_array(item,value); }\n\tif (*value=='{')\t\t\t\t{ return parse_object(item,value); }\n\n\tep=value;return 0;\t/* failure. */\n}\n\n/* Render a value to text. */\nstatic char *print_value(cJSON *item,int depth,int fmt)\n{\n\tchar *out=0;\n\tif (!item) return 0;\n\tswitch ((item->type)&255)\n\t{\n\t\tcase cJSON_NULL:\tout=cJSON_strdup(\"null\");\tbreak;\n\t\tcase cJSON_False:\tout=cJSON_strdup(\"false\");break;\n\t\tcase cJSON_True:\tout=cJSON_strdup(\"true\"); break;\n\t\tcase cJSON_Number:\tout=print_number(item);break;\n\t\tcase cJSON_String:\tout=print_string(item);break;\n\t\tcase cJSON_Array:\tout=print_array(item,depth,fmt);break;\n\t\tcase cJSON_Object:\tout=print_object(item,depth,fmt);break;\n\t}\n\treturn out;\n}\n\n/* Build an array from input text. */\nstatic const char *parse_array(cJSON *item,const char *value)\n{\n\tcJSON *child;\n\tif (*value!='[')\t{ep=value;return 0;}\t/* not an array! */\n\n\titem->type=cJSON_Array;\n\tvalue=skip(value+1);\n\tif (*value==']') return value+1;\t/* empty array. */\n\n\titem->child=child=cJSON_New_Item();\n\tif (!item->child) return 0;\t\t /* memory fail */\n\tvalue=skip(parse_value(child,skip(value)));\t/* skip any spacing, get the value. */\n\tif (!value) return 0;\n\n\twhile (*value==',')\n\t{\n\t\tcJSON *new_item;\n\t\tif (!(new_item=cJSON_New_Item())) return 0; \t/* memory fail */\n\t\tchild->next=new_item;new_item->prev=child;child=new_item;\n\t\tvalue=skip(parse_value(child,skip(value+1)));\n\t\tif (!value) return 0;\t/* memory fail */\n\t}\n\n\tif (*value==']') return value+1;\t/* end of array */\n\tep=value;return 0;\t/* malformed. */\n}\n\n/* Render an array to text */\nstatic char *print_array(cJSON *item,int depth,int fmt)\n{\n\tchar **entries;\n\tchar *out=0,*ptr,*ret;int len=5;\n\tcJSON *child=item->child;\n\tint numentries=0,i=0,fail=0;\n\t\n\t/* How many entries in the array? */\n\twhile (child) numentries++,child=child->next;\n\t/* Explicitly handle numentries==0 */\n\tif (!numentries)\n\t{\n\t\tout=(char*)cJSON_malloc(3);\n\t\tif (out) strcpy(out,\"[]\");\n\t\treturn out;\n\t}\n\t/* Allocate an array to hold the values for each */\n\tentries=(char**)cJSON_malloc(numentries*sizeof(char*));\n\tif (!entries) return 0;\n\tmemset(entries,0,numentries*sizeof(char*));\n\t/* Retrieve all the results: */\n\tchild=item->child;\n\twhile (child && !fail)\n\t{\n\t\tret=print_value(child,depth+1,fmt);\n\t\tentries[i++]=ret;\n\t\tif (ret) len+=strlen(ret)+2+(fmt?1:0); else fail=1;\n\t\tchild=child->next;\n\t}\n\t\n\t/* If we didn't fail, try to malloc the output string */\n\tif (!fail) out=(char*)cJSON_malloc(len);\n\t/* If that fails, we fail. */\n\tif (!out) fail=1;\n\n\t/* Handle failure. */\n\tif (fail)\n\t{\n\t\tfor (i=0;i<numentries;i++) if (entries[i]) cJSON_free(entries[i]);\n\t\tcJSON_free(entries);\n\t\treturn 0;\n\t}\n\t\n\t/* Compose the output array. */\n\t*out='[';\n\tptr=out+1;*ptr=0;\n\tfor (i=0;i<numentries;i++)\n\t{\n\t\tstrcpy(ptr,entries[i]);ptr+=strlen(entries[i]);\n\t\tif (i!=numentries-1) {*ptr++=',';if(fmt)*ptr++=' ';*ptr=0;}\n\t\tcJSON_free(entries[i]);\n\t}\n\tcJSON_free(entries);\n\t*ptr++=']';*ptr++=0;\n\treturn out;\t\n}\n\n/* Build an object from the text. */\nstatic const char *parse_object(cJSON *item,const char *value)\n{\n\tcJSON *child;\n\tif (*value!='{')\t{ep=value;return 0;}\t/* not an object! */\n\t\n\titem->type=cJSON_Object;\n\tvalue=skip(value+1);\n\tif (*value=='}') return value+1;\t/* empty array. */\n\t\n\titem->child=child=cJSON_New_Item();\n\tif (!item->child) return 0;\n\tvalue=skip(parse_string(child,skip(value)));\n\tif (!value) return 0;\n\tchild->string=child->valuestring;child->valuestring=0;\n\tif (*value!=':') {ep=value;return 0;}\t/* fail! */\n\tvalue=skip(parse_value(child,skip(value+1)));\t/* skip any spacing, get the value. */\n\tif (!value) return 0;\n\t\n\twhile (*value==',')\n\t{\n\t\tcJSON *new_item;\n\t\tif (!(new_item=cJSON_New_Item()))\treturn 0; /* memory fail */\n\t\tchild->next=new_item;new_item->prev=child;child=new_item;\n\t\tvalue=skip(parse_string(child,skip(value+1)));\n\t\tif (!value) return 0;\n\t\tchild->string=child->valuestring;child->valuestring=0;\n\t\tif (*value!=':') {ep=value;return 0;}\t/* fail! */\n\t\tvalue=skip(parse_value(child,skip(value+1)));\t/* skip any spacing, get the value. */\n\t\tif (!value) return 0;\n\t}\n\t\n\tif (*value=='}') return value+1;\t/* end of array */\n\tep=value;return 0;\t/* malformed. */\n}\n\n/* Render an object to text. */\nstatic char *print_object(cJSON *item,int depth,int fmt)\n{\n\tchar **entries=0,**names=0;\n\tchar *out=0,*ptr,*ret,*str;int len=7,i=0,j;\n\tcJSON *child=item->child;\n\tint numentries=0,fail=0;\n\t/* Count the number of entries. */\n\twhile (child) numentries++,child=child->next;\n\t/* Explicitly handle empty object case */\n\tif (!numentries)\n\t{\n\t\tout=(char*)cJSON_malloc(fmt?depth+4:3);\n\t\tif (!out)\treturn 0;\n\t\tptr=out;*ptr++='{';\n\t\tif (fmt) {*ptr++='\\n';for (i=0;i<depth-1;i++) *ptr++='\\t';}\n\t\t*ptr++='}';*ptr++=0;\n\t\treturn out;\n\t}\n\t/* Allocate space for the names and the objects */\n\tentries=(char**)cJSON_malloc(numentries*sizeof(char*));\n\tif (!entries) return 0;\n\tnames=(char**)cJSON_malloc(numentries*sizeof(char*));\n\tif (!names) {cJSON_free(entries);return 0;}\n\tmemset(entries,0,sizeof(char*)*numentries);\n\tmemset(names,0,sizeof(char*)*numentries);\n\n\t/* Collect all the results into our arrays: */\n\tchild=item->child;depth++;if (fmt) len+=depth;\n\twhile (child)\n\t{\n\t\tnames[i]=str=print_string_ptr(child->string);\n\t\tentries[i++]=ret=print_value(child,depth,fmt);\n\t\tif (str && ret) len+=strlen(ret)+strlen(str)+2+(fmt?2+depth:0); else fail=1;\n\t\tchild=child->next;\n\t}\n\t\n\t/* Try to allocate the output string */\n\tif (!fail) out=(char*)cJSON_malloc(len);\n\tif (!out) fail=1;\n\n\t/* Handle failure */\n\tif (fail)\n\t{\n\t\tfor (i=0;i<numentries;i++) {if (names[i]) cJSON_free(names[i]);if (entries[i]) cJSON_free(entries[i]);}\n\t\tcJSON_free(names);cJSON_free(entries);\n\t\treturn 0;\n\t}\n\t\n\t/* Compose the output: */\n\t*out='{';ptr=out+1;if (fmt)*ptr++='\\n';*ptr=0;\n\tfor (i=0;i<numentries;i++)\n\t{\n\t\tif (fmt) for (j=0;j<depth;j++) *ptr++=' ';\n\t\tstrcpy(ptr,names[i]);ptr+=strlen(names[i]);\n\t\t*ptr++=':';if (fmt) *ptr++=' ';\n\t\tstrcpy(ptr,entries[i]);ptr+=strlen(entries[i]);\n\t\tif (i!=numentries-1) *ptr++=',';\n\t\tif (fmt) *ptr++='\\n';*ptr=0;\n\t\tcJSON_free(names[i]);cJSON_free(entries[i]);\n\t}\n\t\n\tcJSON_free(names);cJSON_free(entries);\n\tif (fmt) for (i=0;i<depth-1;i++) *ptr++=' ';\n\t*ptr++='}';*ptr++=0;\n\treturn out;\t\n}\n\n/* Get Array size/item / object item. */\nint    cJSON_GetArraySize(cJSON *array)\t\t\t\t\t\t\t{cJSON *c=array->child;int i=0;while(c)i++,c=c->next;return i;}\ncJSON *cJSON_GetArrayItem(cJSON *array,int item)\t\t\t\t{cJSON *c=array->child;  while (c && item>0) item--,c=c->next; return c;}\ncJSON *cJSON_GetObjectItem(cJSON *object,const char *string)\t{cJSON *c=object->child; while (c && cJSON_strcasecmp(c->string,string)) c=c->next; return c;}\n\n/* Utility for array list handling. */\nstatic void suffix_object(cJSON *prev,cJSON *item) {prev->next=item;item->prev=prev;}\n/* Utility for handling references. */\nstatic cJSON *create_reference(cJSON *item) {cJSON *ref=cJSON_New_Item();if (!ref) return 0;memcpy(ref,item,sizeof(cJSON));ref->string=0;ref->type|=cJSON_IsReference;ref->next=ref->prev=0;return ref;}\n\n/* Add item to array/object. */\nvoid   cJSON_AddItemToArray(cJSON *array, cJSON *item)\t\t\t\t\t\t{cJSON *c=array->child;if (!item) return; if (!c) {array->child=item;} else {while (c && c->next) c=c->next; suffix_object(c,item);}}\nvoid   cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item)\t{if (!item) return; if (item->string) cJSON_free(item->string);item->string=cJSON_strdup(string);cJSON_AddItemToArray(object,item);}\nvoid\tcJSON_AddItemReferenceToArray(cJSON *array, cJSON *item)\t\t\t\t\t\t{cJSON_AddItemToArray(array,create_reference(item));}\nvoid\tcJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item)\t{cJSON_AddItemToObject(object,string,create_reference(item));}\n\ncJSON *cJSON_DetachItemFromArray(cJSON *array,int which)\t\t\t{cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return 0;\n\tif (c->prev) c->prev->next=c->next;if (c->next) c->next->prev=c->prev;if (c==array->child) array->child=c->next;c->prev=c->next=0;return c;}\nvoid   cJSON_DeleteItemFromArray(cJSON *array,int which)\t\t\t{cJSON_Delete(cJSON_DetachItemFromArray(array,which));}\ncJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string) {int i=0;cJSON *c=object->child;while (c && cJSON_strcasecmp(c->string,string)) i++,c=c->next;if (c) return cJSON_DetachItemFromArray(object,i);return 0;}\nvoid   cJSON_DeleteItemFromObject(cJSON *object,const char *string) {cJSON_Delete(cJSON_DetachItemFromObject(object,string));}\n\n/* Replace array/object items with new ones. */\nvoid   cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem)\t\t{cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return;\n\tnewitem->next=c->next;newitem->prev=c->prev;if (newitem->next) newitem->next->prev=newitem;\n\tif (c==array->child) array->child=newitem; else newitem->prev->next=newitem;c->next=c->prev=0;cJSON_Delete(c);}\nvoid   cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem){int i=0;cJSON *c=object->child;while(c && cJSON_strcasecmp(c->string,string))i++,c=c->next;if(c){newitem->string=cJSON_strdup(string);cJSON_ReplaceItemInArray(object,i,newitem);}}\n\n/* Create basic types: */\ncJSON *cJSON_CreateNull(void)\t\t\t\t\t{cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_NULL;return item;}\ncJSON *cJSON_CreateTrue(void)\t\t\t\t\t{cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_True;return item;}\ncJSON *cJSON_CreateFalse(void)\t\t\t\t\t{cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_False;return item;}\ncJSON *cJSON_CreateBool(int b)\t\t\t\t\t{cJSON *item=cJSON_New_Item();if(item)item->type=b?cJSON_True:cJSON_False;return item;}\ncJSON *cJSON_CreateNumber(double num)\t\t\t{cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_Number;item->valuedouble=num;item->valueint=(int)num;}return item;}\ncJSON *cJSON_CreateString(const char *string)\t{cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_String;item->valuestring=cJSON_strdup(string);}return item;}\ncJSON *cJSON_CreateArray(void)\t\t\t\t\t{cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Array;return item;}\ncJSON *cJSON_CreateObject(void)\t\t\t\t\t{cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Object;return item;}\n\n/* Create Arrays: */\ncJSON *cJSON_CreateIntArray(const int *numbers,int count)\t\t{int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}\ncJSON *cJSON_CreateFloatArray(const float *numbers,int count)\t{int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}\ncJSON *cJSON_CreateDoubleArray(const double *numbers,int count)\t{int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}\ncJSON *cJSON_CreateStringArray(const char **strings,int count)\t{int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateString(strings[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}\n\n/* Duplication */\ncJSON *cJSON_Duplicate(cJSON *item,int recurse)\n{\n\tcJSON *newitem,*cptr,*nptr=0,*newchild;\n\t/* Bail on bad ptr */\n\tif (!item) return 0;\n\t/* Create new item */\n\tnewitem=cJSON_New_Item();\n\tif (!newitem) return 0;\n\t/* Copy over all vars */\n\tnewitem->type=item->type&(~cJSON_IsReference),newitem->valueint=item->valueint,newitem->valuedouble=item->valuedouble;\n\tif (item->valuestring)\t{newitem->valuestring=cJSON_strdup(item->valuestring);\tif (!newitem->valuestring)\t{cJSON_Delete(newitem);return 0;}}\n\tif (item->string)\t\t{newitem->string=cJSON_strdup(item->string);\t\t\tif (!newitem->string)\t\t{cJSON_Delete(newitem);return 0;}}\n\t/* If non-recursive, then we're done! */\n\tif (!recurse) return newitem;\n\t/* Walk the ->next chain for the child. */\n\tcptr=item->child;\n\twhile (cptr)\n\t{\n\t\tnewchild=cJSON_Duplicate(cptr,1);\t\t/* Duplicate (with recurse) each item in the ->next chain */\n\t\tif (!newchild) {cJSON_Delete(newitem);return 0;}\n\t\tif (nptr)\t{nptr->next=newchild,newchild->prev=nptr;nptr=newchild;}\t/* If newitem->child already set, then crosswire ->prev and ->next and move on */\n\t\telse\t\t{newitem->child=newchild;nptr=newchild;}\t\t\t\t\t/* Set newitem->child and move to it */\n\t\tcptr=cptr->next;\n\t}\n\treturn newitem;\n}\n\nvoid cJSON_Minify(char *json)\n{\n\tchar *into=json;\n\twhile (*json)\n\t{\n\t\tif (*json==' ') json++;\n\t\telse if (*json=='\\t') json++;\t// Whitespace characters.\n\t\telse if (*json=='\\r') json++;\n\t\telse if (*json=='\\n') json++;\n\t\telse if (*json=='/' && json[1]=='/')  while (*json && *json!='\\n') json++;\t// double-slash comments, to end of line.\n\t\telse if (*json=='/' && json[1]=='*') {while (*json && !(*json=='*' && json[1]=='/')) json++;json+=2;}\t// multiline comments.\n\t\telse if (*json=='\\\"'){*into++=*json++;while (*json && *json!='\\\"'){if (*json=='\\\\') *into++=*json++;*into++=*json++;}*into++=*json++;} // string literals, which are \\\" sensitive.\n\t\telse *into++=*json++;\t\t\t// All other characters.\n\t}\n\t*into=0;\t// and null-terminate.\n}\n"
  },
  {
    "path": "cJSON/cJSON.h",
    "content": "/*\n  Copyright (c) 2009 Dave Gamble\n \n  Permission is hereby granted, free of charge, to any person obtaining a copy\n  of this software and associated documentation files (the \"Software\"), to deal\n  in the Software without restriction, including without limitation the rights\n  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n  copies of the Software, and to permit persons to whom the Software is\n  furnished to do so, subject to the following conditions:\n \n  The above copyright notice and this permission notice shall be included in\n  all copies or substantial portions of the Software.\n \n  THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n  THE SOFTWARE.\n*/\n\n#ifndef cJSON__h\n#define cJSON__h\n\n#ifdef __cplusplus\nextern \"C\"\n{\n#endif\n\n/* cJSON Types: */\n#define cJSON_False 0\n#define cJSON_True 1\n#define cJSON_NULL 2\n#define cJSON_Number 3\n#define cJSON_String 4\n#define cJSON_Array 5\n#define cJSON_Object 6\n\t\n#define cJSON_IsReference 256\n\n/* The cJSON structure: */\ntypedef struct cJSON {\n\tstruct cJSON *next,*prev;\t/* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */\n\tstruct cJSON *child;\t\t/* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */\n\n\tint type;\t\t\t\t\t/* The type of the item, as above. */\n\n\tchar *valuestring;\t\t\t/* The item's string, if type==cJSON_String */\n\tint valueint;\t\t\t\t/* The item's number, if type==cJSON_Number */\n\tdouble valuedouble;\t\t\t/* The item's number, if type==cJSON_Number */\n\n\tchar *string;\t\t\t\t/* The item's name string, if this item is the child of, or is in the list of subitems of an object. */\n} cJSON;\n\ntypedef struct cJSON_Hooks {\n      void *(*malloc_fn)(size_t sz);\n      void (*free_fn)(void *ptr);\n} cJSON_Hooks;\n\n/* Supply malloc, realloc and free functions to cJSON */\nextern void cJSON_InitHooks(cJSON_Hooks* hooks);\n\n\n/* Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished. */\nextern cJSON *cJSON_Parse(const char *value);\n/* Render a cJSON entity to text for transfer/storage. Free the char* when finished. */\nextern char  *cJSON_Print(cJSON *item);\n/* Render a cJSON entity to text for transfer/storage without any formatting. Free the char* when finished. */\nextern char  *cJSON_PrintUnformatted(cJSON *item);\n/* Delete a cJSON entity and all subentities. */\nextern void   cJSON_Delete(cJSON *c);\n\n/* Returns the number of items in an array (or object). */\nextern int\t  cJSON_GetArraySize(cJSON *array);\n/* Retrieve item number \"item\" from array \"array\". Returns NULL if unsuccessful. */\nextern cJSON *cJSON_GetArrayItem(cJSON *array,int item);\n/* Get item \"string\" from object. Case insensitive. */\nextern cJSON *cJSON_GetObjectItem(cJSON *object,const char *string);\n\n/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */\nextern const char *cJSON_GetErrorPtr(void);\n\t\n/* These calls create a cJSON item of the appropriate type. */\nextern cJSON *cJSON_CreateNull(void);\nextern cJSON *cJSON_CreateTrue(void);\nextern cJSON *cJSON_CreateFalse(void);\nextern cJSON *cJSON_CreateBool(int b);\nextern cJSON *cJSON_CreateNumber(double num);\nextern cJSON *cJSON_CreateString(const char *string);\nextern cJSON *cJSON_CreateArray(void);\nextern cJSON *cJSON_CreateObject(void);\n\n/* These utilities create an Array of count items. */\nextern cJSON *cJSON_CreateIntArray(const int *numbers,int count);\nextern cJSON *cJSON_CreateFloatArray(const float *numbers,int count);\nextern cJSON *cJSON_CreateDoubleArray(const double *numbers,int count);\nextern cJSON *cJSON_CreateStringArray(const char **strings,int count);\n\n/* Append item to the specified array/object. */\nextern void cJSON_AddItemToArray(cJSON *array, cJSON *item);\nextern void\tcJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item);\n/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */\nextern void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);\nextern void\tcJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item);\n\n/* Remove/Detatch items from Arrays/Objects. */\nextern cJSON *cJSON_DetachItemFromArray(cJSON *array,int which);\nextern void   cJSON_DeleteItemFromArray(cJSON *array,int which);\nextern cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string);\nextern void   cJSON_DeleteItemFromObject(cJSON *object,const char *string);\n\t\n/* Update array items. */\nextern void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem);\nextern void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);\n\n/* Duplicate a cJSON item */\nextern cJSON *cJSON_Duplicate(cJSON *item,int recurse);\n/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will\nneed to be released. With recurse!=0, it will duplicate any children connected to the item.\nThe item->next and ->prev pointers are always zero on return from Duplicate. */\n\n/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */\nextern cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated);\n\nextern void cJSON_Minify(char *json);\n\n/* Macros for creating things quickly. */\n#define cJSON_AddNullToObject(object,name)\t\tcJSON_AddItemToObject(object, name, cJSON_CreateNull())\n#define cJSON_AddTrueToObject(object,name)\t\tcJSON_AddItemToObject(object, name, cJSON_CreateTrue())\n#define cJSON_AddFalseToObject(object,name)\t\tcJSON_AddItemToObject(object, name, cJSON_CreateFalse())\n#define cJSON_AddBoolToObject(object,name,b)\tcJSON_AddItemToObject(object, name, cJSON_CreateBool(b))\n#define cJSON_AddNumberToObject(object,name,n)\tcJSON_AddItemToObject(object, name, cJSON_CreateNumber(n))\n#define cJSON_AddStringToObject(object,name,s)\tcJSON_AddItemToObject(object, name, cJSON_CreateString(s))\n\n/* When assigning an integer value, it needs to be propagated to valuedouble too. */\n#define cJSON_SetIntValue(object,val)\t\t\t((object)?(object)->valueint=(object)->valuedouble=(val):(val))\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "configure.ac",
    "content": "#                                               -*- Autoconf -*-\n# Process this file with autoconf to produce a configure script.\n\nAC_PREREQ([2.68])\nAC_INIT([cursynth], [1.6], [littleioaudio@gmail.com])\nAM_INIT_AUTOMAKE([-Wall -Werror foreign])\nAM_SILENT_RULES([yes])\nAC_CONFIG_SRCDIR([src/cursynth.cpp])\nAC_CONFIG_HEADERS([config.h])\n\n# Checks for programs.\nAC_PROG_CXX([c++ g++ cxx])\nAC_PROG_CC\nAC_PROG_INSTALL\nAC_PROG_RANLIB\nAM_PROG_CC_C_O\nAM_PROG_AR\nAM_GNU_GETTEXT([external])\nAM_GNU_GETTEXT_VERSION([0.18.3])\n\n# Checks for libraries.\nAC_CHECK_LIB([intl], [gettext])\nAC_CHECK_LIB([ncurses], [curs_set])\nAC_CHECK_LIB([pthread], [pthread_create])\n\n# Checks for header files.\nAC_CHECK_HEADERS([fcntl.h float.h libintl.h limits.h locale.h math.h ncurses.h stddef.h stdlib.h string.h strings.h sys/ioctl.h sys/time.h unistd.h])\n\n# Get flags for rtaudio and rtmidi.\nAC_CANONICAL_HOST\nAC_MSG_CHECKING(for audio API)\ncase $host in\n  *-*-netbsd*)\n    AC_MSG_RESULT(using OSS)\n    api=\"$api -D__LINUX_OSS__\"\n    LIBS=\"$LIBS -lossaudio\"\n    AC_CHECK_LIB(pthread, pthread_create, , AC_MSG_ERROR(cursynth requires the pthread library!))\n  ;;\n\n  *-*-linux*)\n  AC_ARG_WITH(jack, [  --with-jack = choose JACK server support (Mac OSX and GNU/Linux only)], [\n    api=\"$api -D__UNIX_JACK__\"\n    AC_MSG_RESULT(using JACK)\n    AC_CHECK_LIB(jack, jack_client_open, , AC_MSG_ERROR(JACK support requires the jack library!))\n    AC_CHECK_LIB(asound, snd_pcm_open, , AC_MSG_ERROR(Jack support also requires the asound library!))], )\n\n  # Look for ALSA flag\n  AC_ARG_WITH(alsa, [  --with-alsa = choose native ALSA API support (GNU/Linux only)], [\n    api=\"$api -D__LINUX_ALSA__\"\n    req=\"$req alsa\"\n    AC_MSG_RESULT(using ALSA)\n    AC_CHECK_LIB(asound, snd_pcm_open, , AC_MSG_ERROR(ALSA support requires the asound library!))], )\n\n  # Look for PULSE flag\n  AC_ARG_WITH(pulse, [  --with-pulse = choose PulseAudio API support (GNU/Linux only)], [\n    api=\"$api -D__LINUX_PULSE__\"\n    req=\"$req libpulse-simple\"\n    AC_MSG_RESULT(using PulseAudio)\n    PKG_CHECK_MODULES([PULSE], [libpulse-simple], , AC_MSG_ERROR(PulseAudio support requires the pulse-simple library!))\n        LIBS=\"$LIBS `pkg-config --libs libpulse-simple`\" ], )\n\n  # Look for OSS flag\n  AC_ARG_WITH(oss, [  --with-oss = choose OSS API support (GNU/Linux only)], [\n    api=\"$api -D__LINUX_OSS__\"\n    AC_MSG_RESULT(using OSS)], )\n\n  # If no audio api flags specified, use ALSA\n  if [test \"$api\" == \"\";] then\n    AC_MSG_RESULT(using ALSA)\n    AC_SUBST( api, [-D__LINUX_ALSA__] )\n    req=\"$req alsa\"\n    AC_CHECK_LIB(asound, snd_pcm_open, , AC_MSG_ERROR(ALSA support requires the asound library!))\n  fi\n\n  AC_CHECK_LIB(pthread, pthread_create, , AC_MSG_ERROR(cursynth requires the pthread library!))\n  ;;\n\n  *-apple*)\n  AC_ARG_WITH(jack, [  --with-jack = choose JACK server support (unix only)], [\n    api=\"$api -D__UNIX_JACK__\"\n    AC_MSG_RESULT(using JACK)\n    AC_CHECK_LIB(jack, jack_client_open, , AC_MSG_ERROR(JACK support requires the jack library!))], )\n\n  # Look for Core flag\n  AC_ARG_WITH(core, [  --with-core = choose CoreAudio API support (MAC OSX only)], [\n    api=\"$api -D__MACOSX_CORE__\"\n    AC_MSG_RESULT(using CoreAudio)\n    AC_CHECK_HEADER(CoreAudio/CoreAudio.h, [], [AC_MSG_ERROR(CoreAudio header files not found!)] )\n    LIBS=\"$LIBS -framework CoreAudio -framework CoreMIDI -framework CoreFoundation\" ], )\n\n  # If no audio api flags specified, use CoreAudio\n  if [test \"$api\" == \"\"; ] then\n    AC_SUBST( api, [-D__MACOSX_CORE__] )\n    AC_MSG_RESULT(using CoreAudio)\n    AC_CHECK_HEADER(CoreAudio/CoreAudio.h,\n      [],\n      [AC_MSG_ERROR(CoreAudio header files not found!)] )\n    LIBS=\"$LIBS -framework CoreAudio -framework CoreMIDI -framework CoreFoundation\"\n  fi\n\n  AC_CHECK_LIB(pthread, pthread_create, , AC_MSG_ERROR(cursynth requires the pthread library!))\n  ;;\n\n  *-mingw32*)\n  AC_ARG_WITH(asio, [  --with-asio = choose ASIO API support (Windows only)], [\n    api=\"$api -D__WINDOWS_ASIO__\"\n    AC_MSG_RESULT(using ASIO)\n    AC_SUBST( objects, [\"asio.o asiodrivers.o asiolist.o iasiothiscallresolver.o\"] ) ], )\n\n  # Look for DirectSound flag\n  AC_ARG_WITH(ds, [  --with-ds = choose DirectSound API support (Windows only)], [\n    api=\"$api -D__WINDOWS_DS__\"\n    AC_MSG_RESULT(using DirectSound)\n    LIBS=\"-ldsound -lwinmm $LIBS\" ], )\n\n  # If no audio api flags specified, use DirectSound\n  if [test \"$api\" == \"\";] then\n    AC_SUBST( api, [-D__WINDOWS_DS__] )\n    AC_MSG_RESULT(using DirectSound)\n    LIBS=\"-ldsound -lwinmm $LIBS\"\n  fi\n\n  LIBS=\"-lole32 $LIBS\"\n  ;;\n\n  *)\n  # Default case for unknown realtime systems.\n  AC_MSG_ERROR(Unknown system type for realtime support!)\n  ;;\nesac\n\n# Checks for typedefs, structures, and compiler characteristics.\nAC_C_INLINE\nAC_TYPE_PID_T\nAC_C_RESTRICT\nAC_TYPE_SIZE_T\nAC_TYPE_UINT16_T\nAC_TYPE_UINT32_T\nAC_TYPE_UINT64_T\nAC_CHECK_TYPES([ptrdiff_t])\n\n# Checks for library functions.\nAC_FUNC_ALLOCA\nAC_FUNC_ERROR_AT_LINE\nAC_FUNC_FORK\nAC_FUNC_MALLOC\nAC_CHECK_FUNCS([dup2 floor gettimeofday memset modf pow rmdir strcasecmp strchr strdup strerror])\n\nAC_CONFIG_SUBDIRS([mopo\n                   rtaudio\n                   rtmidi])\n\nAC_CONFIG_FILES([Makefile po/Makefile.in\n                 src/Makefile\n                 cJSON/Makefile\n                 doc/Makefile])\nAC_OUTPUT\n"
  },
  {
    "path": "doc/.gitignore",
    "content": "# Documentation\nmdate-sh\ncursynth.info\ntexinfo.tex\nversion.texi\nstdin.info\n*.html\n"
  },
  {
    "path": "doc/Makefile.am",
    "content": "info_TEXINFOS = cursynth.texi\ncursynth_TEXINFOS = cursynth.texi\n"
  },
  {
    "path": "doc/cursynth.texi",
    "content": "\\input texinfo   @c -*-texinfo-*-\n@comment $Id@w{$}\n@comment %**start of header\n@setfilename cursynth.info\n@include version.texi\n@settitle GNU Sample @value{VERSION}\n@syncodeindex pg cp\n@comment %**end of header\n@copying\nThis manual is for GNU Sample (version @value{VERSION}, @value{UPDATED}),\nwhich is an example in the Texinfo documentation.\n\nCopyright @copyright{} 2013 Free Software Foundation, Inc.\n\n@quotation\nPermission is granted to copy, distribute and/or modify this document\nunder the terms of the GNU Free Documentation License, Version 1.3 or\nany later version published by the Free Software Foundation; with no\nInvariant Sections, with no Front-Cover Texts, and with no Back-Cover\nTexts.  A copy of the license is included in the section entitled\n``GNU Free Documentation License''.\n@end quotation\n@end copying\n\n@dircategory Texinfo documentation system\n@direntry\n* cursynth: (cursynth)Invoking cursynth.\n@end direntry\n\n@titlepage\n@title GNU Sample\n@subtitle for version @value{VERSION}, @value{UPDATED}\n@author Matt Tytel (@email{matthewtytel@@gmail.com})\n@page\n@vskip 0pt plus 1filll\n@insertcopying\n@end titlepage\n\n@contents\n\n@ifnottex\n@node Top\n@top GNU Sample\n\nThis manual is for cursynth (version @value{VERSION}, @value{UPDATED}).\ncursynth is a music synthesizer. It's polyphonic and MIDI enabled and it runs\ngraphically within a terminal session.\n@end ifnottex\n\n@menu\n* Invoking cursynth::\n* Controls::\n* Synthesis::\n* Oscillators::\n* Filter::\n* Amplifier::\n* Modulation Matrix::\n* Effects::\n* Articulation::\n* Patches::\n* GNU Free Documentation License::\n* Index::\n@end menu\n\n\n@node Invoking cursynth\n@chapter Invoking cursynth\n\n@pindex cursynth\n@cindex invoking @command{cursynth}\n\nTo start cursynth, run:\n\n$ cursynth\n\ncursynth will take over the current terminal session and show you all the\nsynthesis settings as sliders and text selections on the screen.\n\nStart typing on your keyboard's home row to hear cursynth for the first time.\nTyping F1 or 'H' will show help and information.\n\n@node Controls\n@chapter Controls\n\n@pindex cursynth\n@cindex controls\n\ncursynth is MIDI enabled so if you have a working MIDI keyboard or controller,\ncursynth will respond to note/velocity/etc events and can learn what parameters\nto change when a knob or slider is moved through MIDI learn.\n\n@itemize @bullet\n@item awsedftgyhujkolp;' - a playable keyboard (no key up events)\n@item \\`1234567890 - a slider for the current selected control\n@item up/down - previous/next control\n@item left/right - decrement/increment control\n@item F1 (or [shift] + H) - help/controls\n@item [shift] + L - browse/load patches\n@item [shift] + S - save patch\n@item m - arm MIDI learn\n@item c - erase MIDI learn\n@end itemize\n\n\n@node Synthesis\n@chapter Synthesis\n\n@pindex cursynth\n@cindex synthesis\n\ncursynth uses a very common form of synthesis called *Subtractive Synthesis*.\nThere are three major components in cursynth's synthesis:\n\n@itemize @bullet\n@item Oscillators\n@item Filter\n@item Amplifier\n@end itemize\n\nSynthesis starts with the two oscillators that create the initial sound. The\noutput of the two oscillators are mixed together and fed into the envelope\ncontrolled filter. The output of the filter is fed into the envelope controlled\namplifier. Since cursynth is a polyphonic synthesizer, there is a copy of each\ncomponent (oscillator, filter, amplifier) for each voice. The output of all the\nvoices are combined into a single output that is fed into the delay line.\n\n\n@node Oscillators\n@chapter Oscillators\n\n@pindex cursynth\n@cindex oscillators\n\nThe initial sound creation in cursynth happens in the oscillators. There are two\noscillators and you can choose the wave type for each from the 13 waveforms:\n\n@itemize @bullet\n@item sin\n@item triangle\n@item square\n@item down saw\n@item up saw\n@item three step\n@item four step\n@item eight step\n@item three pyramid\n@item five pyramid\n@item nine pyramid\n@item white noise\n@end itemize\n\nYou can control the second oscillator's transpose relative to the given note\nand fine tune the frequency using the tune parameter.\n\nThe two oscillators are hooked into a cross frequency modulation cycle. That\nis, oscillator 1 modifies the frequency of oscillator 2 and oscillator 2 in\nturn modifies the frequency of oscillator 1. Cross modulation greatly expands\nthe types of sounds you can get from the oscillators.\n\nThe output of the two oscillators are mixed together using a ratio definted\nby the 'oscillator mix' parameter. A value of 0.5 mixes the oscillators\nequally. A value of 0.0 is only the first oscillator, A value of 1.0 is only\noscillator 2.\n\n\n@node Filter\n@chapter Filter\n\n@pindex cursynth\n@cindex filter\n\ncursynth has a resonant filter for each voice. This filter can either be a\nlow-pass or high-pass filter.\n\nYou can positively or negatively keytrack the filter so that higher notes\nwill have a higher cutoff and lower notes will have a lower cutoff.\n\nThe filter also has an ADSR envelope that controls the filter cutoff. It can\nalso be routed to other things using the modulation matrix.\n\n\n@node Amplifier\n@chapter Amplifier\n\n@pindex cursynth\n@cindex amplifier\n\ncursynth has an amplifier that is controlled by an ADSR amplifier. You can also\nvelocity track the notes so the faster you hit a note on a MIDI keyboard, the\nbigger the amplitude of the voice will be.\n\n@node Modulation Matrix\n@chapter Modulation Matrix\n\n@pindex cursynth\n@cindex matrix\n\ncursynth has a modulation matrix so you can add custom modulation to cursynth's\nrouting. For example, you can set an LFO as the source and the pitch as a\ndestination with a small modulation scale to create a vibrato.\n\nThere are five fields for five separate modulation settings.\n\n\n@node Effects\n@chapter Effects\n\n@pindex cursynth\n@cindex effects\n\ncursynth currently has a single delay effect. The audio of all the synth voices\nare combined into one signal that is passed into the delay effect.\n\nYou can control the feedback amount and delay time.\n\n\n@node Articulation\n@chapter Articulation\n\n@pindex cursynth\n@cindex articulation\n\ncursynth has a number of controls that change how it acts as a synthesizer.\n\n@itemize @bullet\n@item polyphony\n@item legato\n@item portamento\n@item portamento type\n@item pitch bend range\n@end itemize\n\npolyphony controls the maximum number of active voices at any time.\n\nlegato controls what happens when a note overrides a currently active note\nbecause we had too many active voices. 'off' will cause the note to retrigger,\nrestarting all oscillators, envelopes and LFOs. 'on' will not retrigger any\noscillators, envelopes or LFOs but will set the frequency to the new note.\n\nportamento controls how long it takes to slide the frequency from one note to\nanother note. cursynth has a linear (in semitones) slide measured in\nseconds-per-octave.\n\nportamento type controls when the notes slide. When 'off' notes never slide\ntheir frequency. When 'on' notes always slide their frequency. When 'auto'\nnotes slide only when the note that is being overriden is still held down on\nthe keyboard, that is will jump to the new frequency immediately if the\noverriden note was already released.\n\npitch bend range controls how much the pitch wheel affects the pitch of all the\nvoices, measured in semitones.\n\n\n@node Patches\n@chapter Patches\n\n@pindex cursynth\n@cindex patches\n\ncursynth is a synthesizer that can make a variety of different sounds through\ndifferent settings. You can save to, and load these settings from cursynth\npatches.\n\nTo load, press 'L' (shift + 'l'), then select from the patch list. You can test\nthe patch by playing on your keyboard. When you decide on a patch, press enter\nto finish loading.\n\nTo save, press 'S' (shift + 's'), then name your patch and hit enter. The patch\nwill save to $HOME/.cursynth/patches/\n\nAll cursynth patches have a .mite extensions and there are two locations where\ncursynth looks for them:\n\n@itemize @bullet\n@item a system data share directory, (usually /usr/local/share/cursynth/patches/)\n@item $HOME/.cursynth/patches/\n@end itemize\n\nPatches are also human readable so you can edit them with your text editor if\nyou wish.\n\n\n@node GNU Free Documentation License\n@appendix GNU Free Documentation License\n\n@include fdl.texi\n\n\n@node Index\n@unnumbered Index\n\n@printindex cp\n\n@bye\n"
  },
  {
    "path": "doc/fdl.texi",
    "content": "@cindex FDL, GNU Free Documentation License\n@center Version 1.2, November 2002\n\n@display\nCopyright @copyright{} 2000,2001,2002 Free Software Foundation, Inc.\n59 Temple Place, Suite 330, Boston, MA  02111-1307, USA\n\nEveryone is permitted to copy and distribute verbatim copies\nof this license document, but changing it is not allowed.\n@end display\n\n@enumerate 0\n@item\nPREAMBLE\n\nThe purpose of this License is to make a manual, textbook, or other\nfunctional and useful document @dfn{free} in the sense of freedom: to\nassure everyone the effective freedom to copy and redistribute it,\nwith or without modifying it, either commercially or noncommercially.\nSecondarily, this License preserves for the author and publisher a way\nto get credit for their work, while not being considered responsible\nfor modifications made by others.\n\nThis License is a kind of ``copyleft'', which means that derivative\nworks of the document must themselves be free in the same sense.  It\ncomplements the GNU General Public License, which is a copyleft\nlicense designed for free software.\n\nWe have designed this License in order to use it for manuals for free\nsoftware, because free software needs free documentation: a free\nprogram should come with manuals providing the same freedoms that the\nsoftware does.  But this License is not limited to software manuals;\nit can be used for any textual work, regardless of subject matter or\nwhether it is published as a printed book.  We recommend this License\nprincipally for works whose purpose is instruction or reference.\n\n@item\nAPPLICABILITY AND DEFINITIONS\n\nThis License applies to any manual or other work, in any medium, that\ncontains a notice placed by the copyright holder saying it can be\ndistributed under the terms of this License.  Such a notice grants a\nworld-wide, royalty-free license, unlimited in duration, to use that\nwork under the conditions stated herein.  The ``Document'', below,\nrefers to any such manual or work.  Any member of the public is a\nlicensee, and is addressed as ``you''.  You accept the license if you\ncopy, modify or distribute the work in a way requiring permission\nunder copyright law.\n\nA ``Modified Version'' of the Document means any work containing the\nDocument or a portion of it, either copied verbatim, or with\nmodifications and/or translated into another language.\n\nA ``Secondary Section'' is a named appendix or a front-matter section\nof the Document that deals exclusively with the relationship of the\npublishers or authors of the Document to the Document's overall\nsubject (or to related matters) and contains nothing that could fall\ndirectly within that overall subject.  (Thus, if the Document is in\npart a textbook of mathematics, a Secondary Section may not explain\nany mathematics.)  The relationship could be a matter of historical\nconnection with the subject or with related matters, or of legal,\ncommercial, philosophical, ethical or political position regarding\nthem.\n\nThe ``Invariant Sections'' are certain Secondary Sections whose titles\nare designated, as being those of Invariant Sections, in the notice\nthat says that the Document is released under this License.  If a\nsection does not fit the above definition of Secondary then it is not\nallowed to be designated as Invariant.  The Document may contain zero\nInvariant Sections.  If the Document does not identify any Invariant\nSections then there are none.\n\nThe ``Cover Texts'' are certain short passages of text that are listed,\nas Front-Cover Texts or Back-Cover Texts, in the notice that says that\nthe Document is released under this License.  A Front-Cover Text may\nbe at most 5 words, and a Back-Cover Text may be at most 25 words.\n\nA ``Transparent'' copy of the Document means a machine-readable copy,\nrepresented in a format whose specification is available to the\ngeneral public, that is suitable for revising the document\nstraightforwardly with generic text editors or (for images composed of\npixels) generic paint programs or (for drawings) some widely available\ndrawing editor, and that is suitable for input to text formatters or\nfor automatic translation to a variety of formats suitable for input\nto text formatters.  A copy made in an otherwise Transparent file\nformat whose markup, or absence of markup, has been arranged to thwart\nor discourage subsequent modification by readers is not Transparent.\nAn image format is not Transparent if used for any substantial amount\nof text.  A copy that is not ``Transparent'' is called ``Opaque''.\n\nExamples of suitable formats for Transparent copies include plain\n@sc{ascii} without markup, Texinfo input format, La@TeX{} input\nformat, @acronym{SGML} or @acronym{XML} using a publicly available\n@acronym{DTD}, and standard-conforming simple @acronym{HTML},\nPostScript or @acronym{PDF} designed for human modification.  Examples\nof transparent image formats include @acronym{PNG}, @acronym{XCF} and\n@acronym{JPG}.  Opaque formats include proprietary formats that can be\nread and edited only by proprietary word processors, @acronym{SGML} or\n@acronym{XML} for which the @acronym{DTD} and/or processing tools are\nnot generally available, and the machine-generated @acronym{HTML},\nPostScript or @acronym{PDF} produced by some word processors for\noutput purposes only.\n\nThe ``Title Page'' means, for a printed book, the title page itself,\nplus such following pages as are needed to hold, legibly, the material\nthis License requires to appear in the title page.  For works in\nformats which do not have any title page as such, ``Title Page'' means\nthe text near the most prominent appearance of the work's title,\npreceding the beginning of the body of the text.\n\nA section ``Entitled XYZ'' means a named subunit of the Document whose\ntitle either is precisely XYZ or contains XYZ in parentheses following\ntext that translates XYZ in another language.  (Here XYZ stands for a\nspecific section name mentioned below, such as ``Acknowledgements'',\n``Dedications'', ``Endorsements'', or ``History''.)  To ``Preserve the Title''\nof such a section when you modify the Document means that it remains a\nsection ``Entitled XYZ'' according to this definition.\n\nThe Document may include Warranty Disclaimers next to the notice which\nstates that this License applies to the Document.  These Warranty\nDisclaimers are considered to be included by reference in this\nLicense, but only as regards disclaiming warranties: any other\nimplication that these Warranty Disclaimers may have is void and has\nno effect on the meaning of this License.\n\n@item\nVERBATIM COPYING\n\nYou may copy and distribute the Document in any medium, either\ncommercially or noncommercially, provided that this License, the\ncopyright notices, and the license notice saying this License applies\nto the Document are reproduced in all copies, and that you add no other\nconditions whatsoever to those of this License.  You may not use\ntechnical measures to obstruct or control the reading or further\ncopying of the copies you make or distribute.  However, you may accept\ncompensation in exchange for copies.  If you distribute a large enough\nnumber of copies you must also follow the conditions in section 3.\n\nYou may also lend copies, under the same conditions stated above, and\nyou may publicly display copies.\n\n@item\nCOPYING IN QUANTITY\n\nIf you publish printed copies (or copies in media that commonly have\nprinted covers) of the Document, numbering more than 100, and the\nDocument's license notice requires Cover Texts, you must enclose the\ncopies in covers that carry, clearly and legibly, all these Cover\nTexts: Front-Cover Texts on the front cover, and Back-Cover Texts on\nthe back cover.  Both covers must also clearly and legibly identify\nyou as the publisher of these copies.  The front cover must present\nthe full title with all words of the title equally prominent and\nvisible.  You may add other material on the covers in addition.\nCopying with changes limited to the covers, as long as they preserve\nthe title of the Document and satisfy these conditions, can be treated\nas verbatim copying in other respects.\n\nIf the required texts for either cover are too voluminous to fit\nlegibly, you should put the first ones listed (as many as fit\nreasonably) on the actual cover, and continue the rest onto adjacent\npages.\n\nIf you publish or distribute Opaque copies of the Document numbering\nmore than 100, you must either include a machine-readable Transparent\ncopy along with each Opaque copy, or state in or with each Opaque copy\na computer-network location from which the general network-using\npublic has access to download using public-standard network protocols\na complete Transparent copy of the Document, free of added material.\nIf you use the latter option, you must take reasonably prudent steps,\nwhen you begin distribution of Opaque copies in quantity, to ensure\nthat this Transparent copy will remain thus accessible at the stated\nlocation until at least one year after the last time you distribute an\nOpaque copy (directly or through your agents or retailers) of that\nedition to the public.\n\nIt is requested, but not required, that you contact the authors of the\nDocument well before redistributing any large number of copies, to give\nthem a chance to provide you with an updated version of the Document.\n\n@item\nMODIFICATIONS\n\nYou may copy and distribute a Modified Version of the Document under\nthe conditions of sections 2 and 3 above, provided that you release\nthe Modified Version under precisely this License, with the Modified\nVersion filling the role of the Document, thus licensing distribution\nand modification of the Modified Version to whoever possesses a copy\nof it.  In addition, you must do these things in the Modified Version:\n\n@enumerate A\n@item\nUse in the Title Page (and on the covers, if any) a title distinct\nfrom that of the Document, and from those of previous versions\n(which should, if there were any, be listed in the History section\nof the Document).  You may use the same title as a previous version\nif the original publisher of that version gives permission.\n\n@item\nList on the Title Page, as authors, one or more persons or entities\nresponsible for authorship of the modifications in the Modified\nVersion, together with at least five of the principal authors of the\nDocument (all of its principal authors, if it has fewer than five),\nunless they release you from this requirement.\n\n@item\nState on the Title page the name of the publisher of the\nModified Version, as the publisher.\n\n@item\nPreserve all the copyright notices of the Document.\n\n@item\nAdd an appropriate copyright notice for your modifications\nadjacent to the other copyright notices.\n\n@item\nInclude, immediately after the copyright notices, a license notice\ngiving the public permission to use the Modified Version under the\nterms of this License, in the form shown in the Addendum below.\n\n@item\nPreserve in that license notice the full lists of Invariant Sections\nand required Cover Texts given in the Document's license notice.\n\n@item\nInclude an unaltered copy of this License.\n\n@item\nPreserve the section Entitled ``History'', Preserve its Title, and add\nto it an item stating at least the title, year, new authors, and\npublisher of the Modified Version as given on the Title Page.  If\nthere is no section Entitled ``History'' in the Document, create one\nstating the title, year, authors, and publisher of the Document as\ngiven on its Title Page, then add an item describing the Modified\nVersion as stated in the previous sentence.\n\n@item\nPreserve the network location, if any, given in the Document for\npublic access to a Transparent copy of the Document, and likewise\nthe network locations given in the Document for previous versions\nit was based on.  These may be placed in the ``History'' section.\nYou may omit a network location for a work that was published at\nleast four years before the Document itself, or if the original\npublisher of the version it refers to gives permission.\n\n@item\nFor any section Entitled ``Acknowledgements'' or ``Dedications'', Preserve\nthe Title of the section, and preserve in the section all the\nsubstance and tone of each of the contributor acknowledgements and/or\ndedications given therein.\n\n@item\nPreserve all the Invariant Sections of the Document,\nunaltered in their text and in their titles.  Section numbers\nor the equivalent are not considered part of the section titles.\n\n@item\nDelete any section Entitled ``Endorsements''.  Such a section\nmay not be included in the Modified Version.\n\n@item\nDo not retitle any existing section to be Entitled ``Endorsements'' or\nto conflict in title with any Invariant Section.\n\n@item\nPreserve any Warranty Disclaimers.\n@end enumerate\n\nIf the Modified Version includes new front-matter sections or\nappendices that qualify as Secondary Sections and contain no material\ncopied from the Document, you may at your option designate some or all\nof these sections as invariant.  To do this, add their titles to the\nlist of Invariant Sections in the Modified Version's license notice.\nThese titles must be distinct from any other section titles.\n\nYou may add a section Entitled ``Endorsements'', provided it contains\nnothing but endorsements of your Modified Version by various\nparties---for example, statements of peer review or that the text has\nbeen approved by an organization as the authoritative definition of a\nstandard.\n\nYou may add a passage of up to five words as a Front-Cover Text, and a\npassage of up to 25 words as a Back-Cover Text, to the end of the list\nof Cover Texts in the Modified Version.  Only one passage of\nFront-Cover Text and one of Back-Cover Text may be added by (or\nthrough arrangements made by) any one entity.  If the Document already\nincludes a cover text for the same cover, previously added by you or\nby arrangement made by the same entity you are acting on behalf of,\nyou may not add another; but you may replace the old one, on explicit\npermission from the previous publisher that added the old one.\n\nThe author(s) and publisher(s) of the Document do not by this License\ngive permission to use their names for publicity for or to assert or\nimply endorsement of any Modified Version.\n\n@item\nCOMBINING DOCUMENTS\n\nYou may combine the Document with other documents released under this\nLicense, under the terms defined in section 4 above for modified\nversions, provided that you include in the combination all of the\nInvariant Sections of all of the original documents, unmodified, and\nlist them all as Invariant Sections of your combined work in its\nlicense notice, and that you preserve all their Warranty Disclaimers.\n\nThe combined work need only contain one copy of this License, and\nmultiple identical Invariant Sections may be replaced with a single\ncopy.  If there are multiple Invariant Sections with the same name but\ndifferent contents, make the title of each such section unique by\nadding at the end of it, in parentheses, the name of the original\nauthor or publisher of that section if known, or else a unique number.\nMake the same adjustment to the section titles in the list of\nInvariant Sections in the license notice of the combined work.\n\nIn the combination, you must combine any sections Entitled ``History''\nin the various original documents, forming one section Entitled\n``History''; likewise combine any sections Entitled ``Acknowledgements'',\nand any sections Entitled ``Dedications''.  You must delete all\nsections Entitled ``Endorsements.''\n\n@item\nCOLLECTIONS OF DOCUMENTS\n\nYou may make a collection consisting of the Document and other documents\nreleased under this License, and replace the individual copies of this\nLicense in the various documents with a single copy that is included in\nthe collection, provided that you follow the rules of this License for\nverbatim copying of each of the documents in all other respects.\n\nYou may extract a single document from such a collection, and distribute\nit individually under this License, provided you insert a copy of this\nLicense into the extracted document, and follow this License in all\nother respects regarding verbatim copying of that document.\n\n@item\nAGGREGATION WITH INDEPENDENT WORKS\n\nA compilation of the Document or its derivatives with other separate\nand independent documents or works, in or on a volume of a storage or\ndistribution medium, is called an ``aggregate'' if the copyright\nresulting from the compilation is not used to limit the legal rights\nof the compilation's users beyond what the individual works permit.\nWhen the Document is included in an aggregate, this License does not\napply to the other works in the aggregate which are not themselves\nderivative works of the Document.\n\nIf the Cover Text requirement of section 3 is applicable to these\ncopies of the Document, then if the Document is less than one half of\nthe entire aggregate, the Document's Cover Texts may be placed on\ncovers that bracket the Document within the aggregate, or the\nelectronic equivalent of covers if the Document is in electronic form.\nOtherwise they must appear on printed covers that bracket the whole\naggregate.\n\n@item\nTRANSLATION\n\nTranslation is considered a kind of modification, so you may\ndistribute translations of the Document under the terms of section 4.\nReplacing Invariant Sections with translations requires special\npermission from their copyright holders, but you may include\ntranslations of some or all Invariant Sections in addition to the\noriginal versions of these Invariant Sections.  You may include a\ntranslation of this License, and all the license notices in the\nDocument, and any Warranty Disclaimers, provided that you also include\nthe original English version of this License and the original versions\nof those notices and disclaimers.  In case of a disagreement between\nthe translation and the original version of this License or a notice\nor disclaimer, the original version will prevail.\n\nIf a section in the Document is Entitled ``Acknowledgements'',\n``Dedications'', or ``History'', the requirement (section 4) to Preserve\nits Title (section 1) will typically require changing the actual\ntitle.\n\n@item\nTERMINATION\n\nYou may not copy, modify, sublicense, or distribute the Document except\nas expressly provided for under this License.  Any other attempt to\ncopy, modify, sublicense or distribute the Document is void, and will\nautomatically terminate your rights under this License.  However,\nparties who have received copies, or rights, from you under this\nLicense will not have their licenses terminated so long as such\nparties remain in full compliance.\n\n@item\nFUTURE REVISIONS OF THIS LICENSE\n\nThe Free Software Foundation may publish new, revised versions\nof the GNU Free Documentation License from time to time.  Such new\nversions will be similar in spirit to the present version, but may\ndiffer in detail to address new problems or concerns.  See\n@uref{http://www.gnu.org/copyleft/}.\n\nEach version of the License is given a distinguishing version number.\nIf the Document specifies that a particular numbered version of this\nLicense ``or any later version'' applies to it, you have the option of\nfollowing the terms and conditions either of that specified version or\nof any later version that has been published (not as a draft) by the\nFree Software Foundation.  If the Document does not specify a version\nnumber of this License, you may choose any version ever published (not\nas a draft) by the Free Software Foundation.\n@end enumerate\n\n@page\n@appendixsec ADDENDUM: How to use this License for your documents\n\nTo use this License in a document you have written, include a copy of\nthe License in the document and put the following copyright and\nlicense notices just after the title page:\n\n@smallexample\n@group\n  Copyright (C)  @var{year}  @var{your name}.\n  Permission is granted to copy, distribute and/or modify this document\n  under the terms of the GNU Free Documentation License, Version 1.2\n  or any later version published by the Free Software Foundation;\n  with no Invariant Sections, no Front-Cover Texts, and no Back-Cover\n  Texts.  A copy of the license is included in the section entitled ``GNU\n  Free Documentation License''.\n@end group\n@end smallexample\n\nIf you have Invariant Sections, Front-Cover Texts and Back-Cover Texts,\nreplace the ``with...Texts.'' line with this:\n\n@smallexample\n@group\n    with the Invariant Sections being @var{list their titles}, with\n    the Front-Cover Texts being @var{list}, and with the Back-Cover Texts\n    being @var{list}.\n@end group\n@end smallexample\n\nIf you have Invariant Sections without Cover Texts, or some other\ncombination of the three, merge those two alternatives to suit the\nsituation.\n\nIf your document contains nontrivial examples of program code, we\nrecommend releasing these examples in parallel under your choice of\nfree software license, such as the GNU General Public License,\nto permit their use in free software.\n\n@c Local Variables:\n@c ispell-local-pdict: \"ispell-dict\"\n@c End:\n"
  },
  {
    "path": "mopo/.gitignore",
    "content": "# Compiled Object files\n*.slo\n*.lo\n*.o\n\n# Compiled Dynamic libraries\n*.so\n*.dylib\n\n# Compiled Static libraries\n*.lai\n*.la\n*.a\n\n# Executables\nmopo_test\na.out\n\n# Autotools\nar-lib\n*.in\n*.la\n*.lo\n*~\n.deps/\n.libs/\nMakefile\naclocal.m4\nautom4te.cache\nautoscan.log\ncompile\nconfig.guess\nconfig.h\nconfig.log\nconfig.status\nconfig.sub\nconfigure\ndepcomp\ninstall-sh\nlibtool\nltmain.sh\nm4/\nmissing\nstamp*\n*.tar.gz\n"
  },
  {
    "path": "mopo/AUTHORS",
    "content": "Little IO <littleioaudio@gmail.com>\nMatt Tytel <matthewtytel@gmail.com>\n"
  },
  {
    "path": "mopo/COPYING",
    "content": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU General Public License is a free, copyleft license for\nsoftware and other kinds of works.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nthe GNU General Public License is intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.  We, the Free Software Foundation, use the\nGNU General Public License for most of our software; it applies also to\nany other work released this way by its authors.  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  To protect your rights, we need to prevent others from denying you\nthese rights or asking you to surrender the rights.  Therefore, you have\ncertain responsibilities if you distribute copies of the software, or if\nyou modify it: responsibilities to respect the freedom of others.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must pass on to the recipients the same\nfreedoms that you received.  You must make sure that they, too, receive\nor can get the source code.  And you must show them these terms so they\nknow their rights.\n\n  Developers that use the GNU GPL protect your rights with two steps:\n(1) assert copyright on the software, and (2) offer you this License\ngiving you legal permission to copy, distribute and/or modify it.\n\n  For the developers' and authors' protection, the GPL clearly explains\nthat there is no warranty for this free software.  For both users' and\nauthors' sake, the GPL requires that modified versions be marked as\nchanged, so that their problems will not be attributed erroneously to\nauthors of previous versions.\n\n  Some devices are designed to deny users access to install or run\nmodified versions of the software inside them, although the manufacturer\ncan do so.  This is fundamentally incompatible with the aim of\nprotecting users' freedom to change the software.  The systematic\npattern of such abuse occurs in the area of products for individuals to\nuse, which is precisely where it is most unacceptable.  Therefore, we\nhave designed this version of the GPL to prohibit the practice for those\nproducts.  If such problems arise substantially in other domains, we\nstand ready to extend this provision to those domains in future versions\nof the GPL, as needed to protect the freedom of users.\n\n  Finally, every program is threatened constantly by software patents.\nStates should not allow patents to restrict development and use of\nsoftware on general-purpose computers, but in those that do, we wish to\navoid the special danger that patents applied to a free program could\nmake it effectively proprietary.  To prevent this, the GPL assures that\npatents cannot be used to render the program non-free.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Use with the GNU Affero General Public License.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU Affero General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the special requirements of the GNU Affero General Public License,\nsection 13, concerning interaction through a network will apply to the\ncombination as such.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\n  If the program does terminal interaction, make it output a short\nnotice like this when it starts in an interactive mode:\n\n    <program>  Copyright (C) <year>  <name of author>\n    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, your program's commands\nmight be different; for a GUI interface, you would use an \"about box\".\n\n  You should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU GPL, see\n<http://www.gnu.org/licenses/>.\n\n  The GNU General Public License does not permit incorporating your program\ninto proprietary programs.  If your program is a subroutine library, you\nmay consider it more useful to permit linking proprietary applications with\nthe library.  If this is what you want to do, use the GNU Lesser General\nPublic License instead of this License.  But first, please read\n<http://www.gnu.org/philosophy/why-not-lgpl.html>.\n"
  },
  {
    "path": "mopo/ChangeLog",
    "content": ""
  },
  {
    "path": "mopo/INSTALL",
    "content": "Installation Instructions\n*************************\n\nCopyright (C) 1994-1996, 1999-2002, 2004-2013 Free Software Foundation,\nInc.\n\n   Copying and distribution of this file, with or without modification,\nare permitted in any medium without royalty provided the copyright\nnotice and this notice are preserved.  This file is offered as-is,\nwithout warranty of any kind.\n\nBasic Installation\n==================\n\n   Briefly, the shell commands `./configure; make; make install' should\nconfigure, build, and install this package.  The following\nmore-detailed instructions are generic; see the `README' file for\ninstructions specific to this package.  Some packages provide this\n`INSTALL' file but do not implement all of the features documented\nbelow.  The lack of an optional feature in a given package is not\nnecessarily a bug.  More recommendations for GNU packages can be found\nin *note Makefile Conventions: (standards)Makefile Conventions.\n\n   The `configure' shell script attempts to guess correct values for\nvarious system-dependent variables used during compilation.  It uses\nthose values to create a `Makefile' in each directory of the package.\nIt may also create one or more `.h' files containing system-dependent\ndefinitions.  Finally, it creates a shell script `config.status' that\nyou can run in the future to recreate the current configuration, and a\nfile `config.log' containing compiler output (useful mainly for\ndebugging `configure').\n\n   It can also use an optional file (typically called `config.cache'\nand enabled with `--cache-file=config.cache' or simply `-C') that saves\nthe results of its tests to speed up reconfiguring.  Caching is\ndisabled by default to prevent problems with accidental use of stale\ncache files.\n\n   If you need to do unusual things to compile the package, please try\nto figure out how `configure' could check whether to do them, and mail\ndiffs or instructions to the address given in the `README' so they can\nbe considered for the next release.  If you are using the cache, and at\nsome point `config.cache' contains results you don't want to keep, you\nmay remove or edit it.\n\n   The file `configure.ac' (or `configure.in') is used to create\n`configure' by a program called `autoconf'.  You need `configure.ac' if\nyou want to change it or regenerate `configure' using a newer version\nof `autoconf'.\n\n   The simplest way to compile this package is:\n\n  1. `cd' to the directory containing the package's source code and type\n     `./configure' to configure the package for your system.\n\n     Running `configure' might take a while.  While running, it prints\n     some messages telling which features it is checking for.\n\n  2. Type `make' to compile the package.\n\n  3. Optionally, type `make check' to run any self-tests that come with\n     the package, generally using the just-built uninstalled binaries.\n\n  4. Type `make install' to install the programs and any data files and\n     documentation.  When installing into a prefix owned by root, it is\n     recommended that the package be configured and built as a regular\n     user, and only the `make install' phase executed with root\n     privileges.\n\n  5. Optionally, type `make installcheck' to repeat any self-tests, but\n     this time using the binaries in their final installed location.\n     This target does not install anything.  Running this target as a\n     regular user, particularly if the prior `make install' required\n     root privileges, verifies that the installation completed\n     correctly.\n\n  6. You can remove the program binaries and object files from the\n     source code directory by typing `make clean'.  To also remove the\n     files that `configure' created (so you can compile the package for\n     a different kind of computer), type `make distclean'.  There is\n     also a `make maintainer-clean' target, but that is intended mainly\n     for the package's developers.  If you use it, you may have to get\n     all sorts of other programs in order to regenerate files that came\n     with the distribution.\n\n  7. Often, you can also type `make uninstall' to remove the installed\n     files again.  In practice, not all packages have tested that\n     uninstallation works correctly, even though it is required by the\n     GNU Coding Standards.\n\n  8. Some packages, particularly those that use Automake, provide `make\n     distcheck', which can by used by developers to test that all other\n     targets like `make install' and `make uninstall' work correctly.\n     This target is generally not run by end users.\n\nCompilers and Options\n=====================\n\n   Some systems require unusual options for compilation or linking that\nthe `configure' script does not know about.  Run `./configure --help'\nfor details on some of the pertinent environment variables.\n\n   You can give `configure' initial values for configuration parameters\nby setting variables in the command line or in the environment.  Here\nis an example:\n\n     ./configure CC=c99 CFLAGS=-g LIBS=-lposix\n\n   *Note Defining Variables::, for more details.\n\nCompiling For Multiple Architectures\n====================================\n\n   You can compile the package for more than one kind of computer at the\nsame time, by placing the object files for each architecture in their\nown directory.  To do this, you can use GNU `make'.  `cd' to the\ndirectory where you want the object files and executables to go and run\nthe `configure' script.  `configure' automatically checks for the\nsource code in the directory that `configure' is in and in `..'.  This\nis known as a \"VPATH\" build.\n\n   With a non-GNU `make', it is safer to compile the package for one\narchitecture at a time in the source code directory.  After you have\ninstalled the package for one architecture, use `make distclean' before\nreconfiguring for another architecture.\n\n   On MacOS X 10.5 and later systems, you can create libraries and\nexecutables that work on multiple system types--known as \"fat\" or\n\"universal\" binaries--by specifying multiple `-arch' options to the\ncompiler but only a single `-arch' option to the preprocessor.  Like\nthis:\n\n     ./configure CC=\"gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64\" \\\n                 CXX=\"g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64\" \\\n                 CPP=\"gcc -E\" CXXCPP=\"g++ -E\"\n\n   This is not guaranteed to produce working output in all cases, you\nmay have to build one architecture at a time and combine the results\nusing the `lipo' tool if you have problems.\n\nInstallation Names\n==================\n\n   By default, `make install' installs the package's commands under\n`/usr/local/bin', include files under `/usr/local/include', etc.  You\ncan specify an installation prefix other than `/usr/local' by giving\n`configure' the option `--prefix=PREFIX', where PREFIX must be an\nabsolute file name.\n\n   You can specify separate installation prefixes for\narchitecture-specific files and architecture-independent files.  If you\npass the option `--exec-prefix=PREFIX' to `configure', the package uses\nPREFIX as the prefix for installing programs and libraries.\nDocumentation and other data files still use the regular prefix.\n\n   In addition, if you use an unusual directory layout you can give\noptions like `--bindir=DIR' to specify different values for particular\nkinds of files.  Run `configure --help' for a list of the directories\nyou can set and what kinds of files go in them.  In general, the\ndefault for these options is expressed in terms of `${prefix}', so that\nspecifying just `--prefix' will affect all of the other directory\nspecifications that were not explicitly provided.\n\n   The most portable way to affect installation locations is to pass the\ncorrect locations to `configure'; however, many packages provide one or\nboth of the following shortcuts of passing variable assignments to the\n`make install' command line to change installation locations without\nhaving to reconfigure or recompile.\n\n   The first method involves providing an override variable for each\naffected directory.  For example, `make install\nprefix=/alternate/directory' will choose an alternate location for all\ndirectory configuration variables that were expressed in terms of\n`${prefix}'.  Any directories that were specified during `configure',\nbut not in terms of `${prefix}', must each be overridden at install\ntime for the entire installation to be relocated.  The approach of\nmakefile variable overrides for each directory variable is required by\nthe GNU Coding Standards, and ideally causes no recompilation.\nHowever, some platforms have known limitations with the semantics of\nshared libraries that end up requiring recompilation when using this\nmethod, particularly noticeable in packages that use GNU Libtool.\n\n   The second method involves providing the `DESTDIR' variable.  For\nexample, `make install DESTDIR=/alternate/directory' will prepend\n`/alternate/directory' before all installation names.  The approach of\n`DESTDIR' overrides is not required by the GNU Coding Standards, and\ndoes not work on platforms that have drive letters.  On the other hand,\nit does better at avoiding recompilation issues, and works well even\nwhen some directory options were not specified in terms of `${prefix}'\nat `configure' time.\n\nOptional Features\n=================\n\n   If the package supports it, you can cause programs to be installed\nwith an extra prefix or suffix on their names by giving `configure' the\noption `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.\n\n   Some packages pay attention to `--enable-FEATURE' options to\n`configure', where FEATURE indicates an optional part of the package.\nThey may also pay attention to `--with-PACKAGE' options, where PACKAGE\nis something like `gnu-as' or `x' (for the X Window System).  The\n`README' should mention any `--enable-' and `--with-' options that the\npackage recognizes.\n\n   For packages that use the X Window System, `configure' can usually\nfind the X include and library files automatically, but if it doesn't,\nyou can use the `configure' options `--x-includes=DIR' and\n`--x-libraries=DIR' to specify their locations.\n\n   Some packages offer the ability to configure how verbose the\nexecution of `make' will be.  For these packages, running `./configure\n--enable-silent-rules' sets the default to minimal output, which can be\noverridden with `make V=1'; while running `./configure\n--disable-silent-rules' sets the default to verbose, which can be\noverridden with `make V=0'.\n\nParticular systems\n==================\n\n   On HP-UX, the default C compiler is not ANSI C compatible.  If GNU\nCC is not installed, it is recommended to use the following options in\norder to use an ANSI C compiler:\n\n     ./configure CC=\"cc -Ae -D_XOPEN_SOURCE=500\"\n\nand if that doesn't work, install pre-built binaries of GCC for HP-UX.\n\n   HP-UX `make' updates targets which have the same time stamps as\ntheir prerequisites, which makes it generally unusable when shipped\ngenerated files such as `configure' are involved.  Use GNU `make'\ninstead.\n\n   On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot\nparse its `<wchar.h>' header file.  The option `-nodtk' can be used as\na workaround.  If GNU CC is not installed, it is therefore recommended\nto try\n\n     ./configure CC=\"cc\"\n\nand if that doesn't work, try\n\n     ./configure CC=\"cc -nodtk\"\n\n   On Solaris, don't put `/usr/ucb' early in your `PATH'.  This\ndirectory contains several dysfunctional programs; working variants of\nthese programs are available in `/usr/bin'.  So, if you need `/usr/ucb'\nin your `PATH', put it _after_ `/usr/bin'.\n\n   On Haiku, software installed for all users goes in `/boot/common',\nnot `/usr/local'.  It is recommended to use the following options:\n\n     ./configure --prefix=/boot/common\n\nSpecifying the System Type\n==========================\n\n   There may be some features `configure' cannot figure out\nautomatically, but needs to determine by the type of machine the package\nwill run on.  Usually, assuming the package is built to be run on the\n_same_ architectures, `configure' can figure that out, but if it prints\na message saying it cannot guess the machine type, give it the\n`--build=TYPE' option.  TYPE can either be a short name for the system\ntype, such as `sun4', or a canonical name which has the form:\n\n     CPU-COMPANY-SYSTEM\n\nwhere SYSTEM can have one of these forms:\n\n     OS\n     KERNEL-OS\n\n   See the file `config.sub' for the possible values of each field.  If\n`config.sub' isn't included in this package, then this package doesn't\nneed to know the machine type.\n\n   If you are _building_ compiler tools for cross-compiling, you should\nuse the option `--target=TYPE' to select the type of system they will\nproduce code for.\n\n   If you want to _use_ a cross compiler, that generates code for a\nplatform different from the build platform, you should specify the\n\"host\" platform (i.e., that on which the generated programs will\neventually be run) with `--host=TYPE'.\n\nSharing Defaults\n================\n\n   If you want to set default values for `configure' scripts to share,\nyou can create a site shell script called `config.site' that gives\ndefault values for variables like `CC', `cache_file', and `prefix'.\n`configure' looks for `PREFIX/share/config.site' if it exists, then\n`PREFIX/etc/config.site' if it exists.  Or, you can set the\n`CONFIG_SITE' environment variable to the location of the site script.\nA warning: not all `configure' scripts look for a site script.\n\nDefining Variables\n==================\n\n   Variables not defined in a site shell script can be set in the\nenvironment passed to `configure'.  However, some packages may run\nconfigure again during the build, and the customized values of these\nvariables may be lost.  In order to avoid this problem, you should set\nthem in the `configure' command line, using `VAR=value'.  For example:\n\n     ./configure CC=/usr/local2/bin/gcc\n\ncauses the specified `gcc' to be used as the C compiler (unless it is\noverridden in the site shell script).\n\nUnfortunately, this technique does not work for `CONFIG_SHELL' due to\nan Autoconf limitation.  Until the limitation is lifted, you can use\nthis workaround:\n\n     CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash\n\n`configure' Invocation\n======================\n\n   `configure' recognizes the following options to control how it\noperates.\n\n`--help'\n`-h'\n     Print a summary of all of the options to `configure', and exit.\n\n`--help=short'\n`--help=recursive'\n     Print a summary of the options unique to this package's\n     `configure', and exit.  The `short' variant lists options used\n     only in the top level, while the `recursive' variant lists options\n     also present in any nested packages.\n\n`--version'\n`-V'\n     Print the version of Autoconf used to generate the `configure'\n     script, and exit.\n\n`--cache-file=FILE'\n     Enable the cache: use and save the results of the tests in FILE,\n     traditionally `config.cache'.  FILE defaults to `/dev/null' to\n     disable caching.\n\n`--config-cache'\n`-C'\n     Alias for `--cache-file=config.cache'.\n\n`--quiet'\n`--silent'\n`-q'\n     Do not print messages saying which checks are being made.  To\n     suppress all normal output, redirect it to `/dev/null' (any error\n     messages will still be shown).\n\n`--srcdir=DIR'\n     Look for the package's source code in directory DIR.  Usually\n     `configure' can determine that directory automatically.\n\n`--prefix=DIR'\n     Use DIR as the installation prefix.  *note Installation Names::\n     for more details, including other options available for fine-tuning\n     the installation locations.\n\n`--no-create'\n`-n'\n     Run the configure checks, but stop before creating any output\n     files.\n\n`configure' also accepts some other, not widely useful, options.  Run\n`configure --help' for more details.\n"
  },
  {
    "path": "mopo/Makefile.am",
    "content": "SUBDIRS = src\n"
  },
  {
    "path": "mopo/NEWS",
    "content": ""
  },
  {
    "path": "mopo/README",
    "content": "mopo: MOdular and POlyphonic synthesis library.\n-----------------------------\n\nmopo is an audio synthesis library aimed at creating modular polyphonic synthesizers.\n"
  },
  {
    "path": "mopo/configure.ac",
    "content": "#                                               -*- Autoconf -*-\n# Process this file with autoconf to produce a configure script.\n\nAC_PREREQ([2.68])\nAC_INIT([mopo], [0.1], [littleioaudio@gmail.com])\nAM_INIT_AUTOMAKE([-Wall -Werror foreign])\nAM_SILENT_RULES(yes)\nAC_CONFIG_SRCDIR([src/delay.cpp])\n\n# Checks for programs.\nAC_PROG_CXX\nAC_PROG_CC\nAC_PROG_RANLIB\nAM_PROG_AR\n\n# Checks for libraries.\nAC_CHECK_LIB([pthread], [pthread_create])\n\n# Checks for header files.\nAC_CHECK_HEADERS([limits.h stddef.h stdlib.h string.h strings.h unistd.h])\n\n# Checks for typedefs, structures, and compiler characteristics.\nAC_C_INLINE\nAC_C_RESTRICT\nAC_TYPE_SIZE_T\nAC_CHECK_TYPES([ptrdiff_t])\n\n# Checks for library functions.\nAC_FUNC_FORK\nAC_FUNC_MALLOC\nAC_CHECK_FUNCS([dup2 memset modf pow rmdir strcasecmp strchr strdup strerror])\n\nAC_CONFIG_FILES([Makefile\n                 src/Makefile])\nAC_OUTPUT\n"
  },
  {
    "path": "mopo/src/Makefile.am",
    "content": "noinst_LIBRARIES = libmopo.a\nlibmopo_a_SOURCES = delay.cpp \\\n                    delay.h \\\n                    envelope.cpp \\\n                    envelope.h \\\n                    feedback.cpp \\\n                    feedback.h \\\n                    filter.cpp \\\n                    filter.h \\\n                    linear_slope.cpp \\\n                    linear_slope.h \\\n                    memory.h \\\n                    midi_lookup.cpp \\\n                    midi_lookup.h \\\n                    mono_panner.cpp \\\n                    mono_panner.h \\\n                    mopo.h \\\n                    operators.cpp \\\n                    operators.h \\\n                    oscillator.cpp \\\n                    oscillator.h \\\n                    processor.cpp \\\n                    processor.h \\\n                    processor_router.cpp \\\n                    processor_router.h \\\n                    send_receive.cpp \\\n                    send_receive.h \\\n                    smooth_filter.cpp \\\n                    smooth_filter.h \\\n                    smooth_value.cpp \\\n                    smooth_value.h \\\n                    step_generator.cpp \\\n                    step_generator.h \\\n                    tick_router.h \\\n                    trigger_operators.cpp \\\n                    trigger_operators.h \\\n                    value.cpp \\\n                    value.h \\\n                    utils.h \\\n                    voice_handler.cpp \\\n                    voice_handler.h \\\n                    wave.cpp \\\n                    wave.h\n"
  },
  {
    "path": "mopo/src/delay.cpp",
    "content": "/* Copyright 2013-2015 Matt Tytel\n *\n * mopo is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * mopo is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with mopo.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"delay.h\"\n\nnamespace mopo {\n\n  Delay::Delay() : Processor(Delay::kNumInputs, 1) { }\n\n  void Delay::process() {\n    for (int i = 0; i < buffer_size_; ++i)\n      outputs_[0]->buffer[i] = tick(i);\n  }\n} // namespace mopo\n"
  },
  {
    "path": "mopo/src/delay.h",
    "content": "/* Copyright 2013-2015 Matt Tytel\n *\n * mopo is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * mopo is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with mopo.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#pragma once\n#ifndef DELAY_H\n#define DELAY_H\n\n#include \"memory.h\"\n#include \"processor.h\"\n\nnamespace mopo {\n\n  // A signal delay processor with wet/dry, delay time and feedback controls.\n  // Handles fractional delay amounts through interpolation.\n  class Delay : public Processor {\n    public:\n      enum Inputs {\n        kAudio,\n        kWet,\n        kDelayTime,\n        kFeedback,\n        kNumInputs\n      };\n\n      Delay();\n\n      virtual Processor* clone() const { return new Delay(*this); }\n      virtual void process();\n\n    protected:\n      mopo_float tick(int i) {\n        mopo_float input = inputs_[kAudio]->at(i);\n        mopo_float wet = inputs_[kWet]->at(i);\n        mopo_float period = inputs_[kDelayTime]->at(i) * sample_rate_;\n        mopo_float feedback = inputs_[kFeedback]->at(i);\n\n        mopo_float read = memory_.get(period);\n        memory_.push(input + read * feedback);\n        return INTERPOLATE(input, read, wet);\n      }\n\n      Memory memory_;\n  };\n} // namespace mopo\n\n#endif // DELAY_H\n"
  },
  {
    "path": "mopo/src/envelope.cpp",
    "content": "/* Copyright 2013-2015 Matt Tytel\n *\n * mopo is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * mopo is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with mopo.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"envelope.h\"\n\n#include <cmath>\n\n#define KILL_TIME 0.02\n\nnamespace mopo {\n\n  Envelope::Envelope() :\n      Processor(kNumInputs, kNumOutputs), state_(kReleasing),\n      current_value_(0), decay_decay_(0), release_decay_(0) { }\n\n  void Envelope::trigger(mopo_float event, int offset) {\n    if (event == kVoiceOn)\n      state_ = kKilling;\n    else if (event == kVoiceOff) {\n      state_ = kReleasing;\n      outputs_[kFinished]->trigger(kVoiceOff, offset);\n    }\n    else if (event == kVoiceReset) {\n      state_ = kAttacking;\n      current_value_ = 0.0;\n    }\n  }\n\n  void Envelope::process() {\n    outputs_[kFinished]->clearTrigger();\n    // Only update decay and release rate once per buffer.\n    mopo_float decay_samples =\n        sample_rate_ * inputs_[kDecay]->at(buffer_size_ - 1);\n    decay_decay_ = pow(CLOSE_ENOUGH, 1.0 / decay_samples);\n\n    mopo_float release_samples =\n        sample_rate_ * inputs_[kRelease]->at(buffer_size_ - 1);\n    release_decay_ = pow(CLOSE_ENOUGH, 1.0 / release_samples);\n\n    int i = 0;\n    if (inputs_[kTrigger]->source->triggered) {\n      int trigger_offset = inputs_[kRelease]->source->trigger_offset;\n\n      for (; i < trigger_offset; ++i)\n        outputs_[kValue]->buffer[i] = tick(i);\n\n      trigger(inputs_[kTrigger]->source->trigger_value, trigger_offset);\n    }\n\n    for (; i < buffer_size_; ++i)\n      outputs_[kValue]->buffer[i] = tick(i);\n  }\n\n  inline mopo_float Envelope::tick(int i) {\n    if (state_ == kAttacking) {\n      if (inputs_[kAttack]->at(i) <= 0)\n        current_value_ = 1;\n      else {\n        mopo_float change = 1.0 / (sample_rate_ * inputs_[kAttack]->at(i));\n        current_value_ = CLAMP(current_value_ + change, 0, 1);\n      }\n      if (current_value_ >= 1)\n        state_ = kDecaying;\n    }\n    else if (state_ == kDecaying) {\n      current_value_ = INTERPOLATE(inputs_[kSustain]->at(i), current_value_,\n                                   decay_decay_);\n    }\n    else if (state_ == kKilling) {\n      current_value_ -= CLAMP(1 / (KILL_TIME * sample_rate_), 0, 1);\n      if (current_value_ <= 0) {\n        outputs_[kFinished]->trigger(kVoiceReset, i);\n        state_ = kAttacking;\n      }\n    }\n    else if (state_ == kReleasing)\n      current_value_ *= release_decay_;\n    return current_value_;\n  }\n} // namespace mopo\n"
  },
  {
    "path": "mopo/src/envelope.h",
    "content": "/* Copyright 2013-2015 Matt Tytel\n *\n * mopo is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * mopo is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with mopo.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#pragma once\n#ifndef ENVELOPE_H\n#define ENVELOPE_H\n\n#include \"processor.h\"\n\n#define CLOSE_ENOUGH (1.0 / 256.0)\n\nnamespace mopo {\n\n  // An ADSR (Attack, Decay, Sustain, Release) Envelope.\n  // The attack is a linear scale and completes in the exact amount of time.\n  // The decay and release are exponential and get down to the _CLOSE_ENOUGH_\n  // level in the specified amount of time.\n  //\n  // The reason for this is that technically the decay and release\n  // take an extremely long time to finish because they are exponential. But\n  // users are used to specifying the amount of time the decay or release take\n  // so we make this compromise of _CLOSE_ENOUGH_.\n  class Envelope : public Processor {\n    public:\n      enum Inputs {\n        kAttack,\n        kDecay,\n        kSustain,\n        kRelease,\n        kTrigger,\n        kNumInputs\n      };\n\n      enum Outputs {\n        kValue,\n        kFinished,\n        kNumOutputs\n      };\n\n      enum State {\n        kAttacking,\n        kDecaying,\n        kReleasing,\n        kKilling,\n      };\n\n      Envelope();\n\n      virtual Processor* clone() const { return new Envelope(*this); }\n      void process();\n      void trigger(mopo_float event, int offset);\n\n    private:\n      mopo_float tick(int i);\n\n      State state_;\n      mopo_float current_value_;\n      mopo_float decay_decay_;\n      mopo_float release_decay_;\n  };\n} // namespace mopo\n\n#endif // ENVELOPE_H\n"
  },
  {
    "path": "mopo/src/feedback.cpp",
    "content": "/* Copyright 2013-2015 Matt Tytel\n *\n * mopo is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * mopo is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with mopo.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"feedback.h\"\n\n#include \"processor_router.h\"\n\nnamespace mopo {\n\n  void Feedback::process() {\n    memcpy(buffer_, inputs_[0]->source->buffer,\n           buffer_size_ * sizeof(mopo_float));\n    refreshOutput();\n  }\n\n  void Feedback::refreshOutput() {\n    memcpy(outputs_[0]->buffer, buffer_, MAX_BUFFER_SIZE * sizeof(mopo_float));\n  }\n} // namespace mopo\n"
  },
  {
    "path": "mopo/src/feedback.h",
    "content": "/* Copyright 2013-2015 Matt Tytel\n *\n * mopo is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * mopo is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with mopo.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#pragma once\n#ifndef FEEDBACK_H\n#define FEEDBACK_H\n\n#include \"processor.h\"\n\nnamespace mopo {\n\n  // A special processor for the purpose of feedback loops in the signal flow.\n  // Feedback can be used for batch buffer feedback processing or sample by\n  // sample feedback processing.\n  class Feedback : public Processor {\n    public:\n      Feedback() : Processor(1, 1) { }\n\n      virtual Processor* clone() const { return new Feedback(*this); }\n      virtual void process();\n      virtual void refreshOutput();\n\n      inline void tick(int i) {\n        buffer_[i] = inputs_[0]->source->buffer[i];\n      }\n\n      inline void tickBeginRefreshOutput() {\n        outputs_[0]->buffer[0] = buffer_[buffer_size_ - 1];\n      }\n\n      inline void tickRefreshOutput(int i) {\n        MOPO_ASSERT(i > 0 && i < buffer_size_);\n        outputs_[0]->buffer[i] = buffer_[i - 1];\n      }\n\n    protected:\n      mopo_float buffer_[MAX_BUFFER_SIZE];\n  };\n} // namespace mopo\n\n#endif // FEEDBACK_H\n"
  },
  {
    "path": "mopo/src/filter.cpp",
    "content": "/* Copyright 2013-2015 Matt Tytel\n *\n * mopo is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * mopo is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with mopo.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"filter.h\"\n\n#include <cmath>\n\nnamespace mopo {\n\n  Filter::Filter() : Processor(Filter::kNumInputs, 1) {\n    current_type_ = kNumTypes;\n    current_cutoff_ = 0.0;\n    current_resonance_ = 0.0;\n\n    in_0_ = in_1_ = in_2_ = 0.0;\n    out_0_ = out_1_ = 0.0;\n    past_in_1_ = past_in_2_ = past_out_1_ = past_out_2_ = 0.0;\n  }\n\n  void Filter::process() {\n    current_type_ = static_cast<Type>(inputs_[kType]->at(0));\n    computeCoefficients(current_type_, inputs_[kCutoff]->at(0),\n                                       inputs_[kResonance]->at(0));\n\n    int i = 0;\n    if (inputs_[kReset]->source->triggered &&\n        inputs_[kReset]->source->trigger_value == kVoiceReset) {\n      int trigger_offset = inputs_[kReset]->source->trigger_offset;\n      for (; i < trigger_offset; ++i)\n        outputs_[0]->buffer[i] = tick(i);\n\n      reset();\n    }\n    for (; i < buffer_size_; ++i)\n      outputs_[0]->buffer[i] = tick(i);\n  }\n\n  inline mopo_float Filter::tick(int i) {\n    mopo_float input = inputs_[kAudio]->at(i);\n    mopo_float cutoff = inputs_[kCutoff]->at(i);\n    mopo_float resonance = inputs_[kResonance]->at(i);\n\n    if (cutoff != current_cutoff_ || resonance != current_resonance_)\n      computeCoefficients(current_type_, cutoff, resonance);\n\n    mopo_float out = input * in_0_ + past_in_1_ * in_1_ + past_in_2_ * in_2_ -\n                     past_out_1_ * out_0_ - past_out_2_ * out_1_;\n    past_in_2_ = past_in_1_;\n    past_in_1_ = input;\n    past_out_2_ = past_out_1_;\n    past_out_1_ = out;\n    return out;\n  }\n\n  inline void Filter::reset() {\n    past_in_1_ = past_in_2_ = past_out_1_ = past_out_2_ = 0;\n  }\n\n  inline void Filter::computeCoefficients(Type type,\n                                          mopo_float cutoff,\n                                          mopo_float resonance) {\n    mopo_float sf = 1.0 / tan(PI * cutoff / sample_rate_);\n    mopo_float sf_squared = sf * sf;\n    mopo_float norm = 1.0 + 1.0 / resonance * sf + sf_squared;\n\n    switch(type) {\n      case kLP12: {\n        in_2_ = in_0_ = 1.0 / norm;\n        in_1_ = 2.0 / norm;\n        out_0_ = 2.0 * (1.0 - sf_squared) / norm;\n        out_1_ = (1.0 - 1.0 / resonance * sf + sf_squared) / norm;\n        break;\n      }\n      case kHP12: {\n        in_2_ = in_0_ = sf_squared / norm;\n        in_1_ = -2.0 * sf_squared / norm;\n        out_0_ = 2.0 * (1.0 - sf_squared) / norm;\n        out_1_ = (1.0 - 1.0 / resonance * sf + sf_squared) / norm;\n        break;\n      }\n      case kBP12: {\n        in_2_ = in_0_ = sf / norm;\n        in_1_ = 0.0;\n        out_0_ = 2.0 * (1.0 - sf_squared) / norm;\n        out_1_ = (1.0 - 1.0 / resonance * sf + sf_squared) / norm;\n        break;\n      }\n      case kAP12: {\n        in_0_ = 1.0 / norm;\n        in_1_ = -2.0 * (1.0 - sf_squared) / norm;\n        in_2_ = (1.0 - 1.0 / resonance * sf + sf_squared) / norm;\n        out_0_ = -in_1_;\n        out_1_ = in_2_;\n        break;\n      }\n      default:\n        in_2_ = in_1_ = in_0_ = out_1_ = out_0_ = 0.0;\n    }\n\n    current_cutoff_ = cutoff;\n    current_resonance_ = resonance;\n  }\n} // namespace mopo\n"
  },
  {
    "path": "mopo/src/filter.h",
    "content": "/* Copyright 2013-2015 Matt Tytel\n *\n * mopo is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * mopo is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with mopo.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#pragma once\n#ifndef FILTER_H\n#define FILTER_H\n\n#include \"processor.h\"\n\nnamespace mopo {\n\n  // 12 dB per octave filters. There is a low pass filter, high pass filter,\n  // band pass filter, and all pass filter.\n  class Filter : public Processor {\n    public:\n      enum Inputs {\n        kAudio,\n        kType,\n        kCutoff,\n        kResonance,\n        kReset,\n        kNumInputs\n      };\n\n      enum Type {\n        kLP12,\n        kHP12,\n        kBP12,\n        kAP12,\n        kNumTypes,\n      };\n\n      Filter();\n\n      virtual Processor* clone() const { return new Filter(*this); }\n      virtual void process();\n\n    private:\n      mopo_float tick(int i);\n      void reset();\n      void computeCoefficients(Type type, mopo_float cutoff,\n                                          mopo_float resonance);\n\n      Type current_type_;\n      mopo_float current_cutoff_, current_resonance_;\n\n      mopo_float in_0_, in_1_, in_2_;\n      mopo_float out_0_, out_1_;\n\n      mopo_float past_in_1_, past_in_2_;\n      mopo_float past_out_1_, past_out_2_;\n  };\n} // namespace mopo\n\n#endif // FILTER_H\n"
  },
  {
    "path": "mopo/src/linear_slope.cpp",
    "content": "/* Copyright 2013-2015 Matt Tytel\n *\n * mopo is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * mopo is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with mopo.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"linear_slope.h\"\n\n#include \"utils.h\"\n\n#include <cmath>\n\nnamespace mopo {\n\n  LinearSlope::LinearSlope() : Processor(kNumInputs, 1) {\n    last_value_ = 0.0;\n  }\n\n  void LinearSlope::process() {\n    int i = 0;\n    if (inputs_[kTriggerJump]->source->triggered) {\n      int trigger_offset = inputs_[kTriggerJump]->source->trigger_offset;\n      for (; i < trigger_offset; ++i) {\n        last_value_ = tick(i);\n        outputs_[0]->buffer[i] = last_value_;\n      }\n\n      last_value_ = inputs_[kTarget]->at(i);\n    }\n\n    for (; i < buffer_size_; ++i) {\n      last_value_ = tick(i);\n      outputs_[0]->buffer[i] = last_value_;\n    }\n  }\n\n  inline mopo_float LinearSlope::tick(int i) {\n    mopo_float target = inputs_[kTarget]->at(i);\n    if (utils::closeToZero(inputs_[kRunSeconds]->at(i)))\n      return inputs_[kTarget]->at(i);\n\n    mopo_float increment = 1.0 / (sample_rate_ * inputs_[kRunSeconds]->at(0));\n    if (target <= last_value_)\n      return CLAMP(last_value_ - increment, target, last_value_);\n    return CLAMP(last_value_ + increment, last_value_, target);\n  }\n} // namespace mopo\n"
  },
  {
    "path": "mopo/src/linear_slope.h",
    "content": "/* Copyright 2013-2015 Matt Tytel\n *\n * mopo is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * mopo is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with mopo.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#pragma once\n#ifndef LINEAR_SLOPE_H\n#define LINEAR_SLOPE_H\n\n#include \"value.h\"\n\nnamespace mopo {\n\n  // A processor that will slope to the target value over a given amount of\n  // time. Useful for portamento or smoothing out values.\n  class LinearSlope : public Processor {\n    public:\n      enum Inputs {\n        kTarget,\n        kRunSeconds,\n        kTriggerJump,\n        kNumInputs\n      };\n\n      LinearSlope();\n\n      virtual Processor* clone() const { return new LinearSlope(*this); }\n      virtual void process();\n\n    private:\n      mopo_float tick(int i);\n\n      mopo_float last_value_;\n  };\n} // namespace mopo\n\n#endif // LINEAR_SLOPE_H\n"
  },
  {
    "path": "mopo/src/memory.h",
    "content": "/* Copyright 2013-2015 Matt Tytel\n *\n * mopo is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * mopo is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with mopo.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#pragma once\n#ifndef MEMORY_H\n#define MEMORY_H\n\n#include \"mopo.h\"\n\n#include <algorithm>\n#include <cmath>\n#include <cstring>\n\n// MAX_MEMORY must be a power of 2.\n#define MAX_MEMORY 1048576\n#define MEMORY_BITMASK 1048575\n\nnamespace mopo {\n\n  // A processor utility to store a stream of data for later lookup.\n  class Memory {\n    public:\n      Memory() : offset_(0) {\n        memset(memory_, 0, MAX_MEMORY * sizeof(mopo_float));\n      }\n\n      inline void push(mopo_float sample) {\n        offset_ = (offset_ + 1) & MEMORY_BITMASK;\n        memory_[offset_] = sample;\n      }\n\n      inline mopo_float getIndex(int index) const {\n        return memory_[(offset_ - index) & MEMORY_BITMASK];\n      }\n\n      inline mopo_float get(mopo_float past) const {\n        double float_index;\n        mopo_float sample_fraction = modf(past, &float_index);\n        int index = std::max<int>(float_index, 1);\n\n        // TODO(mtytel): Quadratic or all-pass interpolation is better.\n        mopo_float from = getIndex(index - 1);\n        mopo_float to = getIndex(index);\n        return INTERPOLATE(from, to, sample_fraction);\n      }\n\n    protected:\n      mopo_float memory_[MAX_MEMORY];\n      unsigned int offset_;\n  };\n} // namespace mopo\n\n#endif // MEMORY_H\n"
  },
  {
    "path": "mopo/src/midi_lookup.cpp",
    "content": "/* Copyright 2013-2015 Matt Tytel\n *\n * mopo is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * mopo is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with mopo.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"midi_lookup.h\"\n\nnamespace mopo {\n\n  const MidiLookupSingleton MidiLookup::lookup_;\n} // namespace mopo\n"
  },
  {
    "path": "mopo/src/midi_lookup.h",
    "content": "/* Copyright 2013-2015 Matt Tytel\n *\n * mopo is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * mopo is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with mopo.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#pragma once\n#ifndef MIDI_LOOKUP_H\n#define MIDI_LOOKUP_H\n\n#include \"mopo.h\"\n\n#include <cmath>\n\n#define MIDI_0_FREQUENCY 8.1757989156\n#define NOTES_PER_OCTAVE 12\n#define CENTS_PER_NOTE 100\n#define MAX_CENTS (MIDI_SIZE * CENTS_PER_NOTE)\n\nnamespace mopo {\n\n  class MidiLookupSingleton {\n    public:\n      MidiLookupSingleton() {\n        mopo_float cents_per_octave = CENTS_PER_NOTE * NOTES_PER_OCTAVE;\n        for (int i = 0; i <= MAX_CENTS; ++i) {\n          frequency_lookup_[i] = MIDI_0_FREQUENCY *\n                                 pow(2, i / cents_per_octave);\n        }\n      }\n\n      mopo_float centsLookup(mopo_float cents_from_0) const {\n        if (cents_from_0 >= MAX_CENTS)\n          return frequency_lookup_[MAX_CENTS];\n        if (cents_from_0 <= 0)\n          return frequency_lookup_[0];\n\n        int full_cents = cents_from_0;\n        mopo_float fraction_cents = cents_from_0 - full_cents;\n\n        return INTERPOLATE(frequency_lookup_[full_cents],\n                           frequency_lookup_[full_cents + 1], fraction_cents);\n      }\n\n    private:\n      mopo_float frequency_lookup_[MAX_CENTS + 1];\n  };\n\n  class MidiLookup {\n    public:\n      static mopo_float centsLookup(mopo_float cents_from_0) {\n        return lookup_.centsLookup(cents_from_0);\n      }\n\n    private:\n      static const MidiLookupSingleton lookup_;\n  };\n} // namespace mopo\n\n#endif // MIDI_LOOKUP_H\n"
  },
  {
    "path": "mopo/src/mono_panner.cpp",
    "content": "/* Copyright 2013-2015 Matt Tytel\n *\n * mopo is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * mopo is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with mopo.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"mono_panner.h\"\n\n#include \"mopo.h\"\n#include \"wave.h\"\n\n#include <cmath>\n\n#define LEFT_ROTATION 100.325\n#define RIGHT_ROTATION 100.125\n\nnamespace mopo {\n\n  MonoPanner::MonoPanner() :\n      Processor(MonoPanner::kNumInputs, MonoPanner::kNumOutputs) { }\n\n  void MonoPanner::process() {\n    double integral;\n    for (int i = 0; i < buffer_size_; ++i) {\n      mopo_float audio = inputs_[kAudio]->at(i);\n      mopo_float pan = inputs_[kPan]->at(i);\n      mopo_float left_gain = Wave::fullsin(modf(pan + LEFT_ROTATION,\n                                                &integral));\n      mopo_float right_gain = Wave::fullsin(modf(pan + RIGHT_ROTATION,\n                                                 &integral));\n\n      outputs_[kLeft]->buffer[i] = audio * left_gain;\n      outputs_[kRight]->buffer[i] = audio * right_gain;\n    }\n  }\n} // namespace mopo\n"
  },
  {
    "path": "mopo/src/mono_panner.h",
    "content": "/* Copyright 2013-2015 Matt Tytel\n *\n * mopo is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * mopo is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with mopo.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#pragma once\n#ifndef MONO_PANNER_H\n#define MONO_PANNER_H\n\n#include \"processor.h\"\n\nnamespace mopo {\n\n  // A processor that will split a single signal into two signals, left and\n  // right. The amplitude of the two outputs is set by the pan amount, ranging\n  // from all the way left, all the way right, or equally split.\n  class MonoPanner : public Processor {\n    public:\n      enum Inputs {\n        kAudio,\n        kPan,\n        kNumInputs\n      };\n\n      enum Outputs {\n        kLeft,\n        kRight,\n        kNumOutputs\n      };\n\n      MonoPanner();\n\n      virtual Processor* clone() const { return new MonoPanner(*this); }\n      virtual void process();\n  };\n} // namespace mopo\n\n#endif // MONO_PANNER_H\n"
  },
  {
    "path": "mopo/src/mopo.h",
    "content": "/* Copyright 2013-2015 Matt Tytel\n *\n * mopo is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * mopo is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with mopo.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#pragma once\n#ifndef MOPO_H\n#define MOPO_H\n\n// Utilities.\n#define UNUSED(x) (void)(x)\n#define CLAMP(v, s, b) ((v) < (s) ? (s) : ((v) > (b) ? (b) : (v)))\n#define INTERPOLATE(s, e, f) ((s) + (f) * ((e) - (s)))\n\n// Debugging.\n#define DEBUG\n#ifdef DEBUG\n#include <cassert>\n#define MOPO_ASSERT(x) assert(x)\n#else\n#define MOPO_ASSERT(x) (void)(x)\n#endif // DEBUG\n\nnamespace mopo {\n\n  const double PI = 3.1415926535897932384626433832795;\n  const int MAX_BUFFER_SIZE = 4096;\n  const int DEFAULT_BUFFER_SIZE = 64;\n  const int DEFAULT_SAMPLE_RATE = 44100;\n  const int MIDI_SIZE = 128;\n  const int PPQ = 15360; // Pulses per quarter note.\n\n  typedef double mopo_float;\n\n  // Common types of events across different Processors.\n  enum VoiceEvent {\n    kVoiceOff,     // Stop. (e.g. release in an envelope)\n    kVoiceOn,      // Start. (e.g. start attack in an envelope)\n    kVoiceReset,   // Reset. Immediately reset to initial state.\n  };\n} // namespace mopo\n\n#endif // MOPO_H\n"
  },
  {
    "path": "mopo/src/operators.cpp",
    "content": "/* Copyright 2013-2015 Matt Tytel\n *\n * mopo is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * mopo is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with mopo.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"operators.h\"\n\nnamespace mopo {\n\n  void Operator::process() {\n    for (int i = 0; i < buffer_size_; ++i)\n      tick(i);\n  }\n\n  void VariableAdd::process() {\n    memset(outputs_[0]->buffer, 0, buffer_size_ * sizeof(mopo_float));\n\n    int num_inputs = inputs_.size();\n    for (int i = 0; i < num_inputs; ++i) {\n      if (inputs_[i]->source != &Processor::null_source_) {\n        for (int s = 0; s < buffer_size_; ++s)\n          outputs_[0]->buffer[s] += inputs_[i]->at(s);\n      }\n    }\n  }\n} // namespace mopo\n"
  },
  {
    "path": "mopo/src/operators.h",
    "content": "/* Copyright 2013-2015 Matt Tytel\n *\n * mopo is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * mopo is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with mopo.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#pragma once\n#ifndef OPERATORS_H\n#define OPERATORS_H\n\n#include \"midi_lookup.h\"\n#include \"processor.h\"\n\nnamespace mopo {\n\n  // A base class for arithmetic operators.\n  class Operator : public Processor {\n    public:\n      Operator(int num_inputs, int num_outputs) :\n          Processor(num_inputs, num_outputs) { }\n\n      virtual void process();\n      virtual void tick(int i) = 0;\n  };\n\n  // A processor that will clamp a signal output to a given window.\n  class Clamp : public Operator {\n    public:\n      Clamp(mopo_float min = -1, mopo_float max = 1) : Operator(1, 1),\n                                                       min_(min), max_(max) { }\n\n      virtual Processor* clone() const { return new Clamp(*this); }\n\n      inline void tick(int i) {\n        outputs_[0]->buffer[i] = CLAMP(inputs_[0]->at(i), min_, max_);\n      }\n\n    private:\n      mopo_float min_, max_;\n  };\n\n  // A processor that will invert a signal.\n  class Negate : public Operator {\n    public:\n      Negate() : Operator(1, 1) { }\n\n      virtual Processor* clone() const { return new Negate(*this); }\n\n      inline void tick(int i) {\n        outputs_[0]->buffer[i] = -inputs_[0]->at(i);\n      }\n  };\n\n  // A processor that will scale a signal by a given scalar.\n  class LinearScale : public Operator {\n    public:\n      LinearScale(mopo_float scale = 1) : Operator(1, 1), scale_(scale) { }\n      virtual Processor* clone() const { return new LinearScale(*this); }\n\n      inline void tick(int i) {\n        outputs_[0]->buffer[i] = scale_ * inputs_[0]->at(i);\n      }\n\n    private:\n      mopo_float scale_;\n  };\n\n  // A processor that will convert a stream of midi to a stream of frequencies.\n  class MidiScale : public Operator {\n    public:\n      MidiScale() : Operator(1, 1) { }\n\n      virtual Processor* clone() const { return new MidiScale(*this); }\n\n      inline void tick(int i) {\n        outputs_[0]->buffer[i] =\n            MidiLookup::centsLookup(CENTS_PER_NOTE * inputs_[0]->at(i));\n      }\n  };\n\n  // A processor that will add two streams together.\n  class Add : public Operator {\n    public:\n      Add() : Operator(2, 1) { }\n\n      virtual Processor* clone() const { return new Add(*this); }\n\n      inline void tick(int i) {\n        outputs_[0]->buffer[i] = inputs_[0]->at(i) + inputs_[1]->at(i);\n      }\n  };\n\n  // A processor that will add a variable number of strings together.\n  class VariableAdd : public Operator {\n    public:\n      VariableAdd(int num_inputs) : Operator(num_inputs, 1) { }\n\n      virtual Processor* clone() const { return new VariableAdd(*this); }\n\n      void process();\n      inline void tick(int i) {\n        int num_inputs = inputs_.size();\n        outputs_[0]->buffer[i] = 0.0;\n        for (int input = 0; input < num_inputs; ++input)\n          outputs_[0]->buffer[i] += inputs_[input]->at(i);\n      }\n  };\n\n  // A processor that will subtract one stream from another.\n  class Subtract : public Operator {\n    public:\n      Subtract() : Operator(2, 1) { }\n\n      virtual Processor* clone() const { return new Subtract(*this); }\n\n      inline void tick(int i) {\n        outputs_[0]->buffer[i] = inputs_[0]->at(i) - inputs_[1]->at(i);\n      }\n  };\n\n  // A processor that will multiply to streams together.\n  class Multiply : public Operator {\n    public:\n      Multiply() : Operator(2, 1) { }\n\n      virtual Processor* clone() const { return new Multiply(*this); }\n\n      inline void tick(int i) {\n        outputs_[0]->buffer[i] = inputs_[0]->at(i) * inputs_[1]->at(i);\n      }\n  };\n\n  // A processor that will interpolate two streams by an interpolation stream.\n  class Interpolate : public Operator {\n    public:\n      enum Inputs {\n        kFrom,\n        kTo,\n        kFractional,\n        kNumInputs\n      };\n\n      Interpolate() : Operator(kNumInputs, 1) { }\n\n      virtual Processor* clone() const { return new Interpolate(*this); }\n\n      inline void tick(int i) {\n        outputs_[0]->buffer[i] = INTERPOLATE(inputs_[kFrom]->at(i),\n                                             inputs_[kTo]->at(i),\n                                             inputs_[kFractional]->at(i));\n      }\n  };\n} // namespace mopo\n\n#endif // OPERATORS_H\n"
  },
  {
    "path": "mopo/src/oscillator.cpp",
    "content": "/* Copyright 2013-2015 Matt Tytel\n *\n * mopo is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * mopo is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with mopo.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"oscillator.h\"\n\n#include <cmath>\n\nnamespace mopo {\n\n  Oscillator::Oscillator() : Processor(kNumInputs, 1),\n                             offset_(0.0), waveform_(Wave::kSin) { }\n\n  void Oscillator::preprocess() {\n    waveform_ = static_cast<Wave::Type>(inputs_[kWaveform]->at(0));\n  }\n\n  void Oscillator::process() {\n    preprocess();\n\n    int i = 0;\n    if (inputs_[kReset]->source->triggered &&\n        inputs_[kReset]->source->trigger_value == kVoiceReset) {\n      int trigger_offset = inputs_[kReset]->source->trigger_offset;\n      for (; i < trigger_offset; ++i)\n        tick(i);\n\n      offset_ = 0.0;\n    }\n    for (; i < buffer_size_; ++i)\n      tick(i);\n  }\n} // namespace mopo\n"
  },
  {
    "path": "mopo/src/oscillator.h",
    "content": "/* Copyright 2013-2015 Matt Tytel\n *\n * mopo is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * mopo is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with mopo.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#pragma once\n#ifndef OSCILLATOR_H\n#define OSCILLATOR_H\n\n#include \"processor.h\"\n#include \"wave.h\"\n\nnamespace mopo {\n\n  // A processor that produces an oscillation stream based on the input\n  // frequency, phase, and waveform. You can reset the waveform stream using\n  // the reset input.\n  class Oscillator : public Processor {\n    public:\n      enum Inputs {\n        kFrequency,\n        kPhase,\n        kWaveform,\n        kReset,\n        kNumInputs\n      };\n\n      Oscillator();\n\n      virtual Processor* clone() const { return new Oscillator(*this); }\n      void preprocess();\n      void process();\n\n      inline void tick(int i) {\n        mopo_float frequency = inputs_[kFrequency]->at(i);\n        mopo_float phase = inputs_[kPhase]->at(i);\n\n        offset_ += frequency / sample_rate_;\n        double integral;\n        offset_ = modf(offset_, &integral);\n        outputs_[0]->buffer[i] =\n            Wave::blwave(waveform_, offset_ + phase, frequency);\n      }\n\n    protected:\n      mopo_float offset_;\n      Wave::Type waveform_;\n  };\n} // namespace mopo\n\n#endif // OSCILLATOR_H\n"
  },
  {
    "path": "mopo/src/processor.cpp",
    "content": "/* Copyright 2013-2015 Matt Tytel\n *\n * mopo is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * mopo is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with mopo.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"processor.h\"\n\n#include \"processor_router.h\"\n\nnamespace mopo {\n\n  const Processor::Output Processor::null_source_;\n\n  Processor::Processor(int num_inputs, int num_outputs) :\n      sample_rate_(DEFAULT_SAMPLE_RATE), buffer_size_(DEFAULT_BUFFER_SIZE),\n      router_(0) {\n    for (int i = 0; i < num_inputs; ++i) {\n      Input* input = new Input();\n\n      // All inputs start off with null input.\n      input->source = &Processor::null_source_;\n      registerInput(input);\n    }\n\n    for (int i = 0; i < num_outputs; ++i) {\n      Output* output = new Output();\n\n      // All outputs are owned by this Processor.\n      output->owner = this;\n      registerOutput(output);\n    }\n  }\n\n  void Processor::plug(const Output* source) {\n    plug(source, 0);\n  }\n\n  void Processor::plug(const Output* source, unsigned int input_index) {\n    MOPO_ASSERT(input_index < inputs_.size());\n    MOPO_ASSERT(source);\n\n    inputs_[input_index]->source = source;\n\n    if (router_)\n      router_->connect(this, source, input_index);\n  }\n\n  void Processor::plug(const Processor* source) {\n    plug(source, 0);\n  }\n\n  void Processor::plug(const Processor* source, unsigned int input_index) {\n    plug(source->output(), input_index);\n  }\n\n  void Processor::plugNext(const Output* source) {\n    for (size_t i = 0; i < inputs_.size(); ++i) {\n      if (inputs_[i]->source == &Processor::null_source_) {\n        plug(source, i);\n        return;\n      }\n    }\n  }\n\n  void Processor::plugNext(const Processor* source) {\n    plugNext(source->output());\n  }\n\n  void Processor::unplugIndex(unsigned int input_index) {\n    inputs_[input_index]->source = &Processor::null_source_;\n  }\n\n  void Processor::unplug(const Output* source) {\n    for (unsigned int i = 0; i < inputs_.size(); ++i) {\n      if (inputs_[i]->source == source)\n        inputs_[i]->source = &Processor::null_source_;\n    }\n  }\n\n  void Processor::unplug(const Processor* source) {\n    for (unsigned int i = 0; i < inputs_.size(); ++i) {\n      if (inputs_[i]->source->owner == source)\n        inputs_[i]->source = &Processor::null_source_;\n    }\n  }\n\n  void Processor::registerInput(Input* input) {\n    inputs_.push_back(input);\n    if (router_ && input->source != &Processor::null_source_)\n      router_->connect(this, input->source, inputs_.size() - 1);\n  }\n\n  void Processor::registerOutput(Output* output) {\n    outputs_.push_back(output);\n  }\n\n  Processor::Input* Processor::input(unsigned int index) const {\n    MOPO_ASSERT(index < inputs_.size());\n\n    return inputs_[index];\n  }\n\n  Processor::Output* Processor::output(unsigned int index) const {\n    MOPO_ASSERT(index < outputs_.size());\n\n    return outputs_[index];\n  }\n} // namespace mopo\n"
  },
  {
    "path": "mopo/src/processor.h",
    "content": "/* Copyright 2013-2015 Matt Tytel\n *\n * mopo is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * mopo is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with mopo.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#pragma once\n#ifndef PROCESSOR_H\n#define PROCESSOR_H\n\n#include \"mopo.h\"\n\n#include <cstring>\n#include <vector>\n\nnamespace mopo {\n\n  class ProcessorRouter;\n\n  class Processor {\n    public:\n      // An output port from the Processor.\n      struct Output {\n        Output() {\n          owner = 0;\n          clearBuffer();\n          clearTrigger();\n        }\n\n        void trigger(mopo_float value, int offset = 0) {\n          triggered = true;\n          trigger_offset = offset;\n          trigger_value = value;\n        }\n\n        void clearTrigger() {\n          triggered = false;\n          trigger_offset = 0;\n          trigger_value = 0.0;\n        }\n\n        void clearBuffer() {\n          memset(buffer, 0, MAX_BUFFER_SIZE * sizeof(mopo_float));\n        }\n\n        const Processor* owner;\n        mopo_float buffer[MAX_BUFFER_SIZE];\n\n        bool triggered;\n        int trigger_offset;\n        mopo_float trigger_value;\n      };\n\n      // An input port to the Processor. You can plug an Output into on of\n      // these inputs.\n      struct Input {\n        Input() { source = 0; }\n\n        const Output* source;\n\n        mopo_float at(int i) const { return source->buffer[i]; }\n      };\n\n      Processor(int num_inputs, int num_outputs);\n\n      // Currently need to override this boiler plate clone.\n      // TODO(mtytel): Should probably make a macro for this.\n      virtual Processor* clone() const = 0;\n\n      // Subclasses override this for main processing code.\n      virtual void process() = 0;\n\n      // Subclasses should override this if they need to adjust for change in\n      // sample rate.\n      virtual void setSampleRate(int sample_rate) {\n        sample_rate_ = sample_rate;\n      }\n\n      virtual void setBufferSize(int buffer_size) {\n        buffer_size_ = buffer_size;\n      }\n\n      // Attaches an output to an input in this processor.\n      void plug(const Output* source);\n      void plug(const Output* source, unsigned int input_index);\n      void plug(const Processor* source);\n      void plug(const Processor* source, unsigned int input_index);\n\n      // Attaches an output to the first available input in this processor.\n      void plugNext(const Output* source);\n      void plugNext(const Processor* source);\n\n      // Remove a connection between two processors.\n      virtual void unplugIndex(unsigned int input_index);\n      virtual void unplug(const Output* source);\n      virtual void unplug(const Processor* source);\n\n      // Sets the ProcessorRouter that will own this Processor.\n      void router(ProcessorRouter* router) { router_ = router; }\n\n      // Returns the ProcessorRouter that owns this Processor.\n      const ProcessorRouter* router() const { return router_; }\n\n      virtual void registerInput(Input* input);\n      virtual void registerOutput(Output* output);\n\n      virtual int numInputs() const { return inputs_.size(); }\n      virtual int numOutputs() const { return outputs_.size(); }\n\n      // Returns the Input port corresponding to the passed in index.\n      Input* input(unsigned int index = 0) const;\n\n      // Returns the Output port corresponding to the passed in index.\n      Output* output(unsigned int index = 0) const;\n\n    protected:\n      int sample_rate_;\n      int buffer_size_;\n\n      std::vector<Input*> inputs_;\n      std::vector<Output*> outputs_;\n\n      ProcessorRouter* router_;\n\n      static const Output null_source_;\n  };\n} // namespace mopo\n\n#endif // PROCESSOR_H\n"
  },
  {
    "path": "mopo/src/processor_router.cpp",
    "content": "/* Copyright 2013-2015 Matt Tytel\n *\n * mopo is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * mopo is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with mopo.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"processor_router.h\"\n\n#include \"feedback.h\"\n#include \"mopo.h\"\n\n#include <algorithm>\n#include <vector>\n\nnamespace mopo {\n\n  ProcessorRouter::ProcessorRouter(int num_inputs, int num_outputs) :\n      Processor(num_inputs, num_outputs) {\n    order_ = new std::vector<const Processor*>();\n    feedback_order_ = new std::vector<const Feedback*>();\n  }\n\n  ProcessorRouter::ProcessorRouter(const ProcessorRouter& original) :\n      Processor(original), order_(original.order_),\n      feedback_order_(original.feedback_order_) {\n    size_t num_processors = order_->size();\n    for (size_t i = 0; i < num_processors; ++i) {\n      const Processor* next = order_->at(i);\n      processors_[next] = next->clone();\n    }\n\n    size_t num_feedbacks = feedback_order_->size();\n    for (size_t i = 0; i < num_feedbacks; ++i) {\n      const Feedback* next = feedback_order_->at(i);\n      feedback_processors_[next] = new Feedback(*next);\n    }\n  }\n\n  void ProcessorRouter::process() {\n    updateAllProcessors();\n\n    // First make sure all the Feedback loops are ready to be read.\n    int num_feedbacks = feedback_order_->size();\n    for (int i = 0; i < num_feedbacks; ++i)\n      feedback_processors_[feedback_order_->at(i)]->refreshOutput();\n\n    // Run all the main processors.\n    int num_processors = order_->size();\n    for (int i = 0; i < num_processors; ++i)\n      processors_[order_->at(i)]->process();\n\n    // Store the outputs into the Feedback objects for next time.\n    for (int i = 0; i < num_feedbacks; ++i)\n      feedback_processors_[feedback_order_->at(i)]->process();\n\n    MOPO_ASSERT(num_processors != 0);\n  }\n\n  void ProcessorRouter::setSampleRate(int sample_rate) {\n    Processor::setSampleRate(sample_rate);\n    updateAllProcessors();\n\n    int num_processors = order_->size();\n    for (int i = 0; i < num_processors; ++i)\n      processors_[order_->at(i)]->setSampleRate(sample_rate);\n\n    int num_feedbacks = feedback_order_->size();\n    for (int i = 0; i < num_feedbacks; ++i)\n      feedback_processors_[feedback_order_->at(i)]->setSampleRate(sample_rate);\n  }\n\n  void ProcessorRouter::setBufferSize(int buffer_size) {\n    Processor::setBufferSize(buffer_size);\n    updateAllProcessors();\n\n    int num_processors = order_->size();\n    for (int i = 0; i < num_processors; ++i)\n      processors_[order_->at(i)]->setBufferSize(buffer_size);\n\n    int num_feedbacks = feedback_order_->size();\n    for (int i = 0; i < num_feedbacks; ++i)\n      feedback_processors_[feedback_order_->at(i)]->setBufferSize(buffer_size);\n  }\n\n  void ProcessorRouter::addProcessor(Processor* processor) {\n    MOPO_ASSERT(processor->router() == NULL || processor->router() == this);\n    processor->router(this);\n    order_->push_back(processor);\n    processors_[processor] = processor;\n\n    for (int i = 0; i < processor->numInputs(); ++i)\n      connect(processor, processor->input(i)->source, i);\n  }\n\n  void ProcessorRouter::removeProcessor(const Processor* processor) {\n    MOPO_ASSERT(processor->router() == this);\n    std::vector<const Processor*>::iterator pos =\n        std::find(order_->begin(), order_->end(), processor);\n    MOPO_ASSERT(pos != order_->end());\n    order_->erase(pos, pos + 1);\n    processors_.erase(processor);\n  }\n\n  void ProcessorRouter::connect(Processor* destination,\n                                const Output* source, int index) {\n    if (isDownstream(destination, source->owner)) {\n      // We are introducing a cycle so insert a Feedback node.\n      Feedback* feedback = new Feedback();\n      feedback->plug(source);\n      destination->plug(feedback, index);\n      addFeedback(feedback);\n    }\n    else {\n      // Not introducing a cycle so just make sure _destination_ is in order.\n      reorder(destination);\n    }\n  }\n\n  void ProcessorRouter::reorder(Processor* processor) {\n    // Get all the dependencies inside this router.\n    std::set<const Processor*> dependencies = getDependencies(processor);\n\n    // Stably reorder putting dependencies first.\n    std::vector<const Processor*> new_order;\n    new_order.reserve(order_->size());\n    int num_processors = processors_.size();\n\n    // First put the dependencies.\n    for (int i = 0; i < num_processors; ++i) {\n      if (order_->at(i) != processor &&\n          dependencies.find(order_->at(i)) != dependencies.end()) {\n        new_order.push_back(order_->at(i));\n      }\n    }\n\n    // Then the processor if it is in this router.\n    if (processors_.find(processor) != processors_.end())\n      new_order.push_back(processor);\n\n    // Then the remaining processors.\n    for (int i = 0; i < num_processors; ++i) {\n      if (order_->at(i) != processor &&\n          dependencies.find(order_->at(i)) == dependencies.end()) {\n        new_order.push_back(order_->at(i));\n      }\n    }\n\n    MOPO_ASSERT(new_order.size() == processors_.size());\n    (*order_) = new_order;\n\n    // Make sure our parent is ordered as well.\n    if (router_)\n      router_->reorder(processor);\n  }\n\n  bool ProcessorRouter::isDownstream(const Processor* first,\n                                     const Processor* second) {\n    std::set<const Processor*> dependencies = getDependencies(second);\n    return dependencies.find(first) != dependencies.end();\n  }\n\n  bool ProcessorRouter::areOrdered(const Processor* first,\n                                   const Processor* second) {\n    const Processor* first_context = getContext(first);\n    const Processor* second_context = getContext(second);\n\n    if (first_context && second_context) {\n      size_t num_processors = order_->size();\n      for (size_t i = 0; i < num_processors; ++i) {\n        if (order_->at(i) == first_context)\n          return true;\n        else if (order_->at(i) == second_context)\n          return false;\n      }\n    }\n    else if (router_)\n      return router_->areOrdered(first, second);\n\n    return true;\n  }\n\n  void ProcessorRouter::addFeedback(Feedback* feedback) {\n    feedback->router(this);\n    feedback_order_->push_back(feedback);\n    feedback_processors_[feedback] = feedback;\n  }\n\n  void ProcessorRouter::updateAllProcessors() {\n    size_t num_processors = order_->size();\n    for (int i = 0; i < num_processors; ++i) {\n      const Processor* next = order_->at(i);\n      if (processors_.find(next) == processors_.end())\n        processors_[next] = next->clone();\n    }\n\n    size_t num_feedbacks = feedback_order_->size();\n    for (int i = 0; i < num_feedbacks; ++i) {\n      const Feedback* next = feedback_order_->at(i);\n      if (feedback_processors_.find(next) == feedback_processors_.end())\n        feedback_processors_[next] = new Feedback(*next);\n    }\n  }\n\n  const Processor* ProcessorRouter::getContext(const Processor* processor) {\n    const Processor* context = processor;\n    while (context && processors_.find(context) == processors_.end())\n      context = context->router();\n\n    return context;\n  }\n\n  std::set<const Processor*> ProcessorRouter::getDependencies(\n      const Processor* processor) {\n    std::vector<const Processor*> inputs;\n    std::set<const Processor*> visited;\n    std::set<const Processor*> dependencies;\n    const Processor* context = getContext(processor);\n\n    inputs.push_back(processor);\n    for (size_t i = 0; i < inputs.size(); ++i) {\n      // Find the parent that is inside this router.\n      const Processor* dependency = getContext(inputs[i]);\n\n      // If _inputs[i]_ has an ancestor in this context, then it is a\n      // dependency. If it is outside this router context, we don't need to\n      // check its inputs.\n      if (dependency) {\n        dependencies.insert(dependency);\n\n        for (int j = 0; j < inputs[i]->numInputs(); ++j) {\n          const Input* input = inputs[i]->input(j);\n          if (input->source && input->source->owner &&\n              visited.find(input->source->owner) == visited.end()) {\n            inputs.push_back(input->source->owner);\n            visited.insert(input->source->owner);\n          }\n        }\n      }\n    }\n\n    // Make sure our context isn't listed as a dependency.\n    dependencies.erase(context);\n\n    return dependencies;\n  }\n} // namespace mopo\n"
  },
  {
    "path": "mopo/src/processor_router.h",
    "content": "/* Copyright 2013-2015 Matt Tytel\n *\n * mopo is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * mopo is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with mopo.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#pragma once\n#ifndef PROCESSOR_ROUTER_H\n#define PROCESSOR_ROUTER_H\n\n#include \"processor.h\"\n\n#include <map>\n#include <set>\n#include <vector>\n\nnamespace mopo {\n\n  class Feedback;\n\n  class ProcessorRouter : public Processor {\n    public:\n      ProcessorRouter(int num_inputs = 0, int num_outputs = 0);\n      ProcessorRouter(const ProcessorRouter& original);\n\n      virtual Processor* clone() const { return new ProcessorRouter(*this); }\n      virtual void process();\n      virtual void setSampleRate(int sample_rate);\n      virtual void setBufferSize(int buffer_size);\n\n      virtual void addProcessor(Processor* processor);\n      virtual void removeProcessor(const Processor* processor);\n\n      // Any time new dependencies are added into the ProcessorRouter graph, we\n      // should call _connect_ on the destination Processor and source Output.\n      void connect(Processor* destination, const Output* source, int index);\n      bool isDownstream(const Processor* first, const Processor* second);\n      bool areOrdered(const Processor* first, const Processor* second);\n\n    protected:\n      // When we create a cycle into the ProcessorRouter graph, we must insert\n      // a Feedback node and add it here.\n      virtual void addFeedback(Feedback* feedback);\n\n      // Makes sure _processor_ runs in a topologically sorted order in\n      // relation to all other Processors in _this_.\n      void reorder(Processor* processor);\n\n      // Ensures we have all copies of all processors and feedback processors.\n      virtual void updateAllProcessors();\n\n      // Returns the ancestor of _processor_ which is a child of _this_.\n      // Returns NULL if _processor_ is not a descendant of _this_.\n      const Processor* getContext(const Processor* processor);\n      std::set<const Processor*> getDependencies(const Processor* processor);\n\n      std::vector<const Processor*>* order_;\n      std::map<const Processor*, Processor*> processors_;\n\n      std::vector<const Feedback*>* feedback_order_;\n      std::map<const Feedback*, Feedback*> feedback_processors_;\n  };\n} // namespace mopo\n\n#endif // PROCESSOR_ROUTER_H\n"
  },
  {
    "path": "mopo/src/send_receive.cpp",
    "content": "/* Copyright 2013-2015 Matt Tytel\n *\n * mopo is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * mopo is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with mopo.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"send_receive.h\"\n\n#include \"processor_router.h\"\n\nnamespace mopo {\n\n  Send::Send() : Processor(1, 1) {\n    memory_output_ = new MemoryOutput();\n    memory_output_->owner = this;\n    memory_output_->memory = &memory_;\n  }\n\n  void Send::process() {\n    for (int i = 0; i < buffer_size_; ++i)\n      memory_.push(inputs_[0]->at(i));\n    memory_output_->memory = &memory_;\n  }\n\n  Receive::Receive() : Processor(kNumInputs, 1) {\n    memory_input_ = new MemoryInput();\n    memory_input_->owner = this;\n  }\n\n  void Receive::process() {\n    mopo_float adjust = buffer_size_;\n    if (router_ && !router_->areOrdered(memory_input_->source->owner,\n                                        memory_input_->owner)) {\n      adjust = 0;\n    }\n\n    for (int i = 0; i < buffer_size_; ++i) {\n      mopo_float time = inputs_[kDelayTime]->at(i) * sample_rate_ + adjust;\n      outputs_[0]->buffer[i] = memory_input_->get(time);\n      adjust -= 1.0;\n    }\n  }\n\n  void Receive::setSend(const Send* send, bool dependent) {\n    memory_input_->source = send->memory_output();\n    if (dependent)\n      plug(send, kDependent);\n  }\n} // namespace mopo\n"
  },
  {
    "path": "mopo/src/send_receive.h",
    "content": "/* Copyright 2013-2015 Matt Tytel\n *\n * mopo is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * mopo is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with mopo.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#pragma once\n#ifndef SEND_RECEIVE_H\n#define SEND_RECEIVE_H\n\n#include \"memory.h\"\n#include \"processor.h\"\n\n// TODO(mtytel): This classes don't work with polyphony. Fix that.\n\nnamespace mopo {\n\n  class Send;\n  class Receive;\n\n  struct MemoryOutput {\n    MemoryOutput() : owner(0), memory(0) { }\n\n    const Send* owner;\n    Memory* memory;\n\n    inline mopo_float get(mopo_float past) const {\n      return memory->get(past);\n    }\n  };\n\n  struct MemoryInput {\n    MemoryInput() : owner(0), source(0) { }\n\n    const Receive* owner;\n    const MemoryOutput* source;\n\n    inline mopo_float get(mopo_float past) const {\n      return source->get(past);\n    }\n  };\n\n  class Send : public Processor {\n    public:\n      Send();\n\n      virtual Processor* clone() const { return new Send(*this); }\n      virtual void process();\n\n      inline mopo_float get(mopo_float past) const {\n        return memory_.get(past);\n      }\n\n      const MemoryOutput* memory_output() const { return memory_output_; }\n\n    protected:\n      Memory memory_;\n\n      MemoryOutput* memory_output_;\n  };\n\n  class Receive : public Processor {\n    public:\n      enum Inputs {\n        kDependent,\n        kDelayTime,\n        kNumInputs\n      };\n\n      Receive();\n\n      virtual Processor* clone() const { return new Receive(*this); }\n      virtual void process();\n\n      void setSend(const Send* send, bool dependent = true);\n\n    protected:\n      MemoryInput* memory_input_;\n  };\n} // namespace mopo\n\n#endif // SEND_RECEIVE_H\n"
  },
  {
    "path": "mopo/src/smooth_filter.cpp",
    "content": "/* Copyright 2013-2015 Matt Tytel\n *\n * mopo is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * mopo is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with mopo.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"smooth_filter.h\"\n\nnamespace mopo {\n\n  SmoothFilter::SmoothFilter() : Processor(SmoothFilter::kNumInputs, 1) {\n    last_value_ = 0.0;\n  }\n\n  void SmoothFilter::process() {\n    mopo_float decay = inputs_[kDecay]->at(0);\n\n    for (int i = 0; i < buffer_size_; ++i) {\n      mopo_float target = inputs_[kTarget]->at(i);\n      last_value_ = INTERPOLATE(last_value_, target, decay);\n      outputs_[0]->buffer[i] = last_value_;\n    }\n  }\n} // namespace mopo\n"
  },
  {
    "path": "mopo/src/smooth_filter.h",
    "content": "/* Copyright 2013-2015 Matt Tytel\n *\n * mopo is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * mopo is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with mopo.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#pragma once\n#ifndef SMOOTH_FILTER_H\n#define SMOOTH_FILTER_H\n\n#include \"processor.h\"\n\nnamespace mopo {\n\n  class SmoothFilter : public Processor {\n    public:\n      enum Inputs {\n        kTarget,\n        kDecay,\n        kTriggerJump,\n        kNumInputs\n      };\n\n      SmoothFilter();\n\n      virtual Processor* clone() const { return new SmoothFilter(*this); }\n      virtual void process();\n\n    private:\n      mopo_float last_value_;\n  };\n} // namespace mopo\n\n#endif // FILTER_H\n"
  },
  {
    "path": "mopo/src/smooth_value.cpp",
    "content": "/* Copyright 2013-2015 Matt Tytel\n *\n * mopo is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * mopo is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with mopo.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"smooth_value.h\"\n\n#include <cmath>\n\n#define SMOOTH_CUTOFF 3.0\n\nnamespace mopo {\n\n  SmoothValue::SmoothValue(mopo_float value) :\n      Value(value), target_value_(value) { }\n\n  void SmoothValue::setSampleRate(int sample_rate) {\n    sample_rate_ = sample_rate;\n    decay_ = 1 - exp(-2.0 * PI * SMOOTH_CUTOFF / sample_rate_);\n  }\n\n  void SmoothValue::process() {\n    for (int i = 0; i < buffer_size_; ++i)\n      outputs_[0]->buffer[i] = tick();\n  }\n\n  inline mopo_float SmoothValue::tick() {\n    value_ = INTERPOLATE(value_, target_value_, decay_);\n    return value_;\n  }\n} // namespace mopo\n"
  },
  {
    "path": "mopo/src/smooth_value.h",
    "content": "/* Copyright 2013-2015 Matt Tytel\n *\n * mopo is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * mopo is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with mopo.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#pragma once\n#ifndef SMOOTH_VALUE_H\n#define SMOOTH_VALUE_H\n\n#include \"value.h\"\n\nnamespace mopo {\n\n  class SmoothValue : public Value {\n    public:\n      SmoothValue(mopo_float value = 0.0);\n\n      virtual Processor* clone() const { return new SmoothValue(*this); }\n      virtual void process();\n\n      virtual void setSampleRate(int sample_rate);\n\n      void set(mopo_float value) { target_value_ = value; }\n      void setHard(mopo_float value) {\n        Value::set(value);\n        target_value_ = value;\n      }\n\n    private:\n      mopo_float tick();\n\n      mopo_float target_value_;\n      mopo_float decay_;\n  };\n} // namespace mopo\n\n#endif // SMOOTH_VALUE_H\n"
  },
  {
    "path": "mopo/src/step_generator.cpp",
    "content": "/* Copyright 2013-2015 Matt Tytel\n *\n * mopo is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * mopo is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with mopo.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"step_generator.h\"\n\n#include <cmath>\n\nnamespace mopo {\n\n  StepGenerator::StepGenerator(int max_steps) :\n      Processor(kNumInputs + max_steps, 1), offset_(0.0), current_step_(0) { }\n\n  void StepGenerator::process() {\n    unsigned int num_steps = static_cast<int>(inputs_[kNumSteps]->at(0));\n\n    int i = 0;\n    if (inputs_[kReset]->source->triggered &&\n        inputs_[kReset]->source->trigger_value == kVoiceReset)\n      i = inputs_[kReset]->source->trigger_offset;\n\n    mopo_float total = 0.0;\n    for (; i < buffer_size_; ++i)\n      total += inputs_[kFrequency]->at(i);\n\n    total /= sample_rate_;\n    double integral;\n    offset_ = modf(offset_ + total, &integral);\n    current_step_ = (current_step_ + num_steps) % num_steps;\n\n    for (i = 0; i < buffer_size_; ++i)\n      outputs_[0]->buffer[i] = inputs_[kSteps + current_step_]->at(i);\n  }\n} // namespace mopo\n"
  },
  {
    "path": "mopo/src/step_generator.h",
    "content": "/* Copyright 2013-2015 Matt Tytel\n *\n * mopo is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * mopo is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with mopo.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#pragma once\n#ifndef STEP_GENERATOR_H\n#define STEP_GENERATOR_H\n\n#include \"processor.h\"\n\n#define DEFAULT_MAX_STEPS 128\n\nnamespace mopo {\n\n  class StepGenerator : public Processor {\n    public:\n      enum Inputs {\n        kFrequency,\n        kNumSteps,\n        kReset,\n        kSteps,\n        kNumInputs\n      };\n\n      StepGenerator(int max_steps = DEFAULT_MAX_STEPS);\n\n      virtual Processor* clone() const { return new StepGenerator(*this); }\n\n      void process();\n\n    protected:\n      mopo_float offset_;\n      unsigned int current_step_;\n  };\n} // namespace mopo\n\n#endif // STEP_GENERATOR_H\n"
  },
  {
    "path": "mopo/src/tick_router.h",
    "content": "/* Copyright 2013-2015 Matt Tytel\n *\n * mopo is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * mopo is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with mopo.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#pragma once\n#ifndef TICK_ROUTER_H\n#define TICK_ROUTER_H\n\n#include \"processor_router.h\"\n\nnamespace mopo {\n\n  class TickRouter : public ProcessorRouter {\n    public:\n      TickRouter(int num_inputs = 0, int num_outputs = 0) :\n          ProcessorRouter(num_inputs, num_outputs) { }\n\n      virtual void process() = 0;\n      virtual void tick(int i) = 0;\n  };\n} // namespace mopo\n\n#endif // PROCESSOR_ROUTER_H\n"
  },
  {
    "path": "mopo/src/trigger_operators.cpp",
    "content": "/* Copyright 2013-2015 Matt Tytel\n *\n * mopo is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * mopo is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with mopo.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"trigger_operators.h\"\n\nnamespace mopo {\n\n  TriggerCombiner::TriggerCombiner() : Processor(2, 1) { }\n\n  void TriggerCombiner::process() {\n    outputs_[0]->clearTrigger();\n\n    if (inputs_[0]->source->triggered) {\n      outputs_[0]->trigger(inputs_[0]->source->trigger_value,\n                           inputs_[0]->source->trigger_offset);\n    }\n    else if (inputs_[1]->source->triggered) {\n      outputs_[0]->trigger(inputs_[1]->source->trigger_value,\n                           inputs_[1]->source->trigger_offset);\n    }\n  }\n\n  TriggerWait::TriggerWait() : Processor(kNumInputs, 1) { }\n\n  void TriggerWait::waitTrigger(mopo_float trigger_value) {\n    waiting_ = true;\n    trigger_value_ = trigger_value;\n  }\n\n  void TriggerWait::sendTrigger(int trigger_offset) {\n    if (waiting_)\n      outputs_[0]->trigger(trigger_value_, trigger_offset);\n    waiting_ = false;\n  }\n\n  void TriggerWait::process() {\n    outputs_[0]->clearTrigger();\n\n    if (inputs_[kWait]->source->triggered &&\n        inputs_[kTrigger]->source->triggered) {\n\n      if (inputs_[kWait]->source->trigger_offset <=\n          inputs_[kTrigger]->source->trigger_offset) {\n        waitTrigger(inputs_[kWait]->source->trigger_value);\n        sendTrigger(inputs_[kTrigger]->source->trigger_offset);\n      }\n      else {\n        sendTrigger(inputs_[kTrigger]->source->trigger_offset);\n        waitTrigger(inputs_[kWait]->source->trigger_value);\n      }\n    }\n    else if (inputs_[kWait]->source->triggered)\n      waitTrigger(inputs_[kWait]->source->trigger_value);\n    else if (inputs_[kTrigger]->source->triggered)\n      sendTrigger(inputs_[kTrigger]->source->trigger_offset);\n  }\n\n  LegatoFilter::LegatoFilter() : Processor(kNumInputs, kNumOutputs),\n                                 last_value_(kVoiceOff) { }\n\n  void LegatoFilter::process() {\n    outputs_[kRetrigger]->clearTrigger();\n    outputs_[kRemain]->clearTrigger();\n    if (!inputs_[kTrigger]->source->triggered)\n      return;\n\n    if (inputs_[kTrigger]->source->trigger_value == kVoiceOn &&\n        last_value_ == kVoiceOn && inputs_[kLegato]->at(0)) {\n      outputs_[kRemain]->trigger(inputs_[kTrigger]->source->trigger_value,\n                                 inputs_[kTrigger]->source->trigger_offset);\n    }\n    else {\n      outputs_[kRetrigger]->trigger(inputs_[kTrigger]->source->trigger_value,\n                                    inputs_[kTrigger]->source->trigger_offset);\n    }\n    last_value_ = inputs_[kTrigger]->source->trigger_value;\n  }\n\n  PortamentoFilter::PortamentoFilter() : Processor(kNumInputs, 1),\n                                         last_value_(kVoiceOff) { }\n\n  void PortamentoFilter::process() {\n    outputs_[0]->clearTrigger();\n    if (!inputs_[kTrigger]->source->triggered)\n      return;\n\n    int state = static_cast<int>(inputs_[kPortamento]->at(0));\n    if (inputs_[kTrigger]->source->trigger_value != kVoiceOff) {\n      if (state == kPortamentoOff || (state == kPortamentoAuto &&\n                                      last_value_ == kVoiceOff)) {\n        outputs_[0]->trigger(inputs_[kTrigger]->source->trigger_value,\n                             inputs_[kTrigger]->source->trigger_offset);\n      }\n    }\n\n    last_value_ = inputs_[kTrigger]->source->trigger_value;\n  }\n} // namespace mopo\n"
  },
  {
    "path": "mopo/src/trigger_operators.h",
    "content": "/* Copyright 2013-2015 Matt Tytel\n *\n * mopo is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * mopo is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with mopo.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#pragma once\n#ifndef TRIGGER_OPERATORS_H\n#define TRIGGER_OPERATORS_H\n\n#include \"processor.h\"\n\nnamespace mopo {\n\n  class TriggerCombiner : public Processor {\n    public:\n      TriggerCombiner();\n\n      virtual Processor* clone() const { return new TriggerCombiner(*this); }\n\n      void process();\n  };\n\n  class TriggerWait : public Processor {\n    public:\n      enum Inputs {\n        kWait,\n        kTrigger,\n        kNumInputs\n      };\n\n      TriggerWait();\n\n      virtual Processor* clone() const { return new TriggerWait(*this); }\n\n      void process();\n\n    private:\n      void waitTrigger(mopo_float trigger_value);\n      void sendTrigger(int trigger_offset);\n\n      bool waiting_;\n      mopo_float trigger_value_;\n  };\n\n  class LegatoFilter : public Processor {\n    public:\n      enum Inputs {\n        kLegato,\n        kTrigger,\n        kNumInputs\n      };\n\n      enum Outputs {\n        kRetrigger,\n        kRemain,\n        kNumOutputs\n      };\n\n      LegatoFilter();\n\n      virtual Processor* clone() const { return new LegatoFilter(*this); }\n\n      void process();\n\n    private:\n      mopo_float last_value_;\n  };\n\n  class PortamentoFilter : public Processor {\n    public:\n      enum Inputs {\n        kPortamento,\n        kTrigger,\n        kNumInputs\n      };\n\n      enum State {\n        kPortamentoOff,\n        kPortamentoAuto,\n        kPortamentoOn,\n        kNumPortamentoStates,\n      };\n\n      PortamentoFilter();\n\n      virtual Processor* clone() const { return new PortamentoFilter(*this); }\n\n      void process();\n\n    private:\n      mopo_float last_value_;\n  };\n} // namespace mopo\n\n#endif // TRIGGER_OPERATORS_H\n"
  },
  {
    "path": "mopo/src/utils.h",
    "content": "/* Copyright 2013-2015 Matt Tytel\n *\n * mopo is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * mopo is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with mopo.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#pragma once\n#ifndef UTILS_H\n#define UTILS_H\n\n#include \"mopo.h\"\n\n#define EPSILON 0.000000000001\n\nnamespace mopo {\n\n  namespace utils {\n\n    inline bool closeToZero(mopo_float value) {\n      return value <= EPSILON && value >= -EPSILON;\n    }\n\n    inline bool isSilent(const mopo_float* buffer, int length) {\n      for (int i = 0; i < length; ++i) {\n        if (!closeToZero(buffer[i]))\n          return false;\n      }\n      return true;\n    }\n  } // namespace utils\n} // namespace mopo\n\n#endif // UTILS_H\n"
  },
  {
    "path": "mopo/src/value.cpp",
    "content": "/* Copyright 2013-2015 Matt Tytel\n *\n * mopo is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * mopo is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with mopo.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"value.h\"\n\nnamespace mopo {\n\n  Value::Value(mopo_float value) : Processor(kNumInputs, 1), value_(value) {\n    for (int i = 0; i < MAX_BUFFER_SIZE; ++i)\n      outputs_[0]->buffer[i] = value_;\n  }\n\n  void Value::process() {\n    if (outputs_[0]->buffer[0] == value_ &&\n        outputs_[0]->buffer[buffer_size_ - 1] == value_ &&\n        !inputs_[kSet]->source->triggered) {\n      return;\n    }\n\n    int i = 0;\n    if (inputs_[kSet]->source->triggered) {\n      int trigger_offset = inputs_[kSet]->source->trigger_offset;\n\n      for (; i < trigger_offset; ++i)\n        outputs_[0]->buffer[i] = value_;\n\n      value_ = inputs_[kSet]->source->trigger_value;\n    }\n\n    for (; i < buffer_size_; ++i)\n      outputs_[0]->buffer[i] = value_;\n  }\n\n  void Value::set(mopo_float value) {\n    value_ = value;\n    for (int i = 0; i < buffer_size_; ++i)\n      outputs_[0]->buffer[i] = value_;\n  }\n} // namespace mopo\n"
  },
  {
    "path": "mopo/src/value.h",
    "content": "/* Copyright 2013-2015 Matt Tytel\n *\n * mopo is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * mopo is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with mopo.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#pragma once\n#ifndef VALUE_H\n#define VALUE_H\n\n#include \"processor.h\"\n\nnamespace mopo {\n\n  class Value : public Processor {\n    public:\n      enum Inputs {\n        kSet,\n        kNumInputs\n      };\n\n      Value(mopo_float value = 0.0);\n\n      virtual Processor* clone() const { return new Value(*this); }\n      virtual void process();\n\n      mopo_float value() const { return value_; }\n      virtual void set(mopo_float value);\n\n    protected:\n      mopo_float value_;\n  };\n} // namespace mopo\n\n#endif // VALUE_H\n"
  },
  {
    "path": "mopo/src/voice_handler.cpp",
    "content": "/* Copyright 2013-2015 Matt Tytel\n *\n * mopo is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * mopo is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with mopo.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"voice_handler.h\"\n\n#include \"utils.h\"\n\nnamespace mopo {\n\n  Voice::Voice(Processor* processor) : processor_(processor) { }\n\n  VoiceHandler::VoiceHandler(size_t polyphony) :\n      Processor(kNumInputs, 1), polyphony_(0), sustain_(false),\n      voice_output_(0), voice_killer_(0) {\n    setPolyphony(polyphony);\n  }\n\n  void VoiceHandler::prepareVoiceTriggers(Voice* voice) {\n    note_.clearTrigger();\n    velocity_.clearTrigger();\n    voice_event_.clearTrigger();\n\n    if (voice->hasNewEvent()) {\n      voice_event_.trigger(voice->state()->event);\n      if (voice->state()->event == kVoiceOn) {\n        note_.trigger(voice->state()->note);\n        velocity_.trigger(voice->state()->velocity);\n      }\n\n      voice->clearEvent();\n    }\n  }\n\n  void VoiceHandler::processVoice(Voice* voice) {\n    voice->processor()->process();\n    for (int i = 0; i < buffer_size_; ++i)\n      outputs_[0]->buffer[i] += voice_output_->buffer[i];\n  }\n\n  void VoiceHandler::process() {\n    global_router_.process();\n\n    size_t polyphony = static_cast<size_t>(inputs_[kPolyphony]->at(0));\n    setPolyphony(CLAMP(polyphony, 1, polyphony));\n    memset(outputs_[0]->buffer, 0, buffer_size_ * sizeof(mopo_float));\n\n    std::list<Voice*>::iterator iter = active_voices_.begin();\n    while (iter != active_voices_.end()) {\n      Voice* voice = *iter;\n      prepareVoiceTriggers(voice);\n      processVoice(voice);\n\n      // Remove voice if the right processor has a full silent buffer.\n      if (voice_killer_ && voice->state()->event != kVoiceOn &&\n          utils::isSilent(voice_killer_->buffer, buffer_size_)) {\n        free_voices_.push_back(voice);\n        iter = active_voices_.erase(iter);\n      }\n      else\n        iter++;\n    }\n  }\n\n  void VoiceHandler::setSampleRate(int sample_rate) {\n    Processor::setSampleRate(sample_rate);\n    voice_router_.setSampleRate(sample_rate);\n    global_router_.setSampleRate(sample_rate);\n    std::set<Voice*>::iterator iter = all_voices_.begin();\n    for (; iter != all_voices_.end(); ++iter)\n      (*iter)->processor()->setSampleRate(sample_rate);\n  }\n\n  void VoiceHandler::setBufferSize(int buffer_size) {\n    Processor::setBufferSize(buffer_size);\n    voice_router_.setBufferSize(buffer_size);\n    global_router_.setBufferSize(buffer_size);\n    std::set<Voice*>::iterator iter = all_voices_.begin();\n    for (; iter != all_voices_.end(); ++iter)\n      (*iter)->processor()->setBufferSize(buffer_size);\n  }\n\n  void VoiceHandler::sustainOn() {\n    sustain_ = true;\n  }\n\n  void VoiceHandler::sustainOff() {\n    sustain_ = false;\n    std::list<Voice*>::iterator iter = sustained_voices_.begin();\n    for (; iter != sustained_voices_.end(); ++iter) {\n      Voice* voice = *iter;\n      voice->deactivate();\n    }\n    sustained_voices_.clear();\n  }\n\n  void VoiceHandler::noteOn(mopo_float note, mopo_float velocity) {\n    Voice* voice = 0;\n    pressed_notes_.push_back(note);\n    if (free_voices_.size() && active_voices_.size() < polyphony_) {\n      voice = free_voices_.front();\n      free_voices_.pop_front();\n    }\n    else {\n      voice = active_voices_.front();\n      active_voices_.pop_front();\n    }\n\n    voice->activate(note, velocity);\n    active_voices_.push_back(voice);\n  }\n\n  void VoiceHandler::noteOff(mopo_float note) {\n    std::list<mopo_float>::iterator note_iter = pressed_notes_.begin();\n    while (note_iter != pressed_notes_.end()) {\n      if (*note_iter == note)\n        note_iter = pressed_notes_.erase(note_iter);\n      else\n        note_iter++;\n    }\n\n    std::list<Voice*>::iterator iter = active_voices_.begin();\n    for (; iter != active_voices_.end(); ++iter) {\n      Voice* voice = *iter;\n      if (voice->state()->note == note) {\n        if (sustain_)\n          sustained_voices_.push_back(voice);\n        else {\n          if (polyphony_ == 1 && pressed_notes_.size())\n            voice->activate(pressed_notes_.back(), voice->state()->velocity);\n          else\n            voice->deactivate();\n        }\n      }\n    }\n  }\n\n  void VoiceHandler::setPolyphony(size_t polyphony) {\n    while (all_voices_.size() < polyphony) {\n      Voice* new_voice = createVoice();\n      all_voices_.insert(new_voice);\n      free_voices_.push_back(new_voice);\n    }\n\n    while (active_voices_.size() > polyphony) {\n      active_voices_.front()->deactivate();\n      active_voices_.pop_front();\n    }\n\n    polyphony_ = polyphony;\n  }\n\n  void VoiceHandler::addProcessor(Processor* processor) {\n    voice_router_.addProcessor(processor);\n  }\n\n  void VoiceHandler::addGlobalProcessor(Processor* processor) {\n    global_router_.addProcessor(processor);\n  }\n\n  Voice* VoiceHandler::createVoice() {\n    return new Voice(voice_router_.clone());\n  }\n} // namespace mopo\n"
  },
  {
    "path": "mopo/src/voice_handler.h",
    "content": "/* Copyright 2013-2015 Matt Tytel\n *\n * mopo is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * mopo is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with mopo.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#pragma once\n#ifndef VOICE_HANDLER_H\n#define VOICE_HANDLER_H\n\n#include \"processor_router.h\"\n#include \"value.h\"\n\n#include <map>\n#include <list>\n\nnamespace mopo {\n\n  struct VoiceState {\n    VoiceEvent event;\n    mopo_float note;\n    mopo_float velocity;\n  };\n\n  class Voice {\n    public:\n      Voice(Processor* voice);\n\n      Processor* processor() { return processor_; }\n      const VoiceState* state() { return &state_; }\n\n      void activate(mopo_float note, mopo_float velocity) {\n        new_event_ = true;\n        state_.event = kVoiceOn;\n        state_.note = note;\n        state_.velocity = velocity;\n      }\n\n      void deactivate() {\n        new_event_ = true;\n        state_.event = kVoiceOff;\n      }\n\n      bool hasNewEvent() {\n        return new_event_;\n      }\n\n      void clearEvent() {\n        new_event_ = false;\n      }\n\n    private:\n      bool new_event_;\n      VoiceState state_;\n      Processor* processor_;\n  };\n\n  class VoiceHandler : public Processor {\n    public:\n      enum Inputs {\n        kPolyphony,\n        kNumInputs\n      };\n\n      VoiceHandler(size_t polyphony = 1);\n\n      virtual Processor* clone() const { MOPO_ASSERT(false); return NULL; }\n      virtual void process();\n      virtual void setSampleRate(int sample_rate);\n      virtual void setBufferSize(int buffer_size);\n\n      void noteOn(mopo_float note, mopo_float velocity = 1);\n      void noteOff(mopo_float note);\n      void sustainOn();\n      void sustainOff();\n\n      Output* voice_event() { return &voice_event_; }\n      Output* note() { return &note_; }\n      Output* velocity() { return &velocity_; }\n\n      void addProcessor(Processor* processor);\n      void addGlobalProcessor(Processor* processor);\n\n      void setPolyphony(size_t polyphony);\n\n      void setVoiceOutput(const Output* output) {\n        voice_output_ = output;\n      }\n      void setVoiceOutput(const Processor* output) {\n        setVoiceOutput(output->output());\n      }\n      void setVoiceKiller(const Output* killer) {\n        voice_killer_ = killer;\n      }\n      void setVoiceKiller(const Processor* killer) {\n        setVoiceKiller(killer->output());\n      }\n\n    private:\n      Voice* createVoice();\n      void prepareVoiceTriggers(Voice* voice);\n      void processVoice(Voice* voice);\n\n      size_t polyphony_;\n      bool sustain_;\n      const Output* voice_output_;\n      const Output* voice_killer_;\n      Output voice_event_;\n      Output note_;\n      Output velocity_;\n\n      std::list<mopo_float> pressed_notes_;\n      std::set<Voice*> all_voices_;\n      std::list<Voice*> free_voices_;\n      std::list<Voice*> sustained_voices_;\n      std::list<Voice*> active_voices_;\n\n      ProcessorRouter voice_router_;\n      ProcessorRouter global_router_;\n  };\n} // namespace mopo\n\n#endif // VOICE_HANDLER_H\n"
  },
  {
    "path": "mopo/src/wave.cpp",
    "content": "/* Copyright 2013-2015 Matt Tytel\n *\n * mopo is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * mopo is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with mopo.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"wave.h\"\n\nnamespace mopo {\n\n  const WaveLookup Wave::lookup_;\n} // namespace mopo\n"
  },
  {
    "path": "mopo/src/wave.h",
    "content": "/* Copyright 2013-2015 Matt Tytel\n *\n * mopo is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * mopo is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with mopo.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#pragma once\n#ifndef WAVE_H\n#define WAVE_H\n\n#include \"mopo.h\"\n#include <cmath>\n#include <cstdlib>\n\n#define LOOKUP_SIZE 2048\n#define HIGH_FREQUENCY 20000\n#define MAX_HARMONICS 100\n\nnamespace mopo {\n\n  class WaveLookup {\n    public:\n      WaveLookup() {\n        // Sin lookup table.\n        for (int i = 0; i < LOOKUP_SIZE + 1; ++i)\n          sin_[i] = sin((2 * PI * i) / LOOKUP_SIZE);\n\n        // Square lookup table.\n        for (int i = 0; i < LOOKUP_SIZE + 1; ++i) {\n          int p = i;\n          mopo_float scale = 4.0 / PI;\n          square_[0][i] = scale * sin_[p];\n\n          for (int h = 1; h < MAX_HARMONICS; ++h) {\n            p = (p + i) % LOOKUP_SIZE;\n            square_[h][i] = square_[h - 1][i];\n\n            if (h % 2 == 0)\n              square_[h][i] += scale * sin_[p] / (h + 1);\n          }\n        }\n\n        // Saw lookup table.\n        for (int i = 0; i < LOOKUP_SIZE + 1; ++i) {\n          int index = (i + (LOOKUP_SIZE / 2)) % LOOKUP_SIZE;\n          int p = i;\n          mopo_float scale = 2.0 / PI;\n          saw_[0][index] = scale * sin_[p];\n\n          for (int h = 1; h < MAX_HARMONICS; ++h) {\n            p = (p + i) % LOOKUP_SIZE;\n            mopo_float harmonic = scale * sin_[p] / (h + 1);\n\n            if (h % 2 == 0)\n              saw_[h][index] = saw_[h - 1][index] + harmonic;\n            else\n              saw_[h][index] = saw_[h - 1][index] - harmonic;\n          }\n        }\n\n        // Triangle lookup table.\n        for (int i = 0; i < LOOKUP_SIZE + 1; ++i) {\n          int p = i;\n          mopo_float scale = 8.0 / (PI * PI);\n          triangle_[0][i] = scale * sin_[p];\n\n          for (int h = 1; h < MAX_HARMONICS; ++h) {\n            p = (p + i) % LOOKUP_SIZE;\n            triangle_[h][i] = triangle_[h - 1][i];\n            mopo_float harmonic = scale * sin_[p] / ((h + 1) * (h + 1));\n\n            if (h % 4 == 0)\n              triangle_[h][i] += harmonic;\n            else if (h % 2 == 0)\n              triangle_[h][i] -= harmonic;\n          }\n        }\n      }\n\n      inline mopo_float fullsin(mopo_float t) const {\n        double integral;\n        mopo_float fractional = modf(t * LOOKUP_SIZE, &integral);\n        int index = integral;\n        return INTERPOLATE(sin_[index], sin_[index + 1], fractional);\n      }\n\n      inline mopo_float square(mopo_float t, int harmonics) const {\n        double integral;\n        mopo_float fractional = modf(t * LOOKUP_SIZE, &integral);\n        int index = integral;\n        return INTERPOLATE(square_[harmonics][index],\n                           square_[harmonics][index + 1], fractional);\n      }\n\n      inline mopo_float upsaw(mopo_float t, int harmonics) const {\n        double integral;\n        mopo_float fractional = modf(t * LOOKUP_SIZE, &integral);\n        int index = integral;\n        return INTERPOLATE(saw_[harmonics][index],\n                           saw_[harmonics][index + 1], fractional);\n      }\n\n      inline mopo_float downsaw(mopo_float t, int harmonics) const {\n        return -upsaw(t, harmonics);\n      }\n\n      inline mopo_float triangle(mopo_float t, int harmonics) const {\n        double integral;\n        mopo_float fractional = modf(t * LOOKUP_SIZE, &integral);\n        int index = integral;\n        return INTERPOLATE(triangle_[harmonics][index],\n                           triangle_[harmonics][index + 1], fractional);\n      }\n\n      template<size_t steps>\n      inline mopo_float step(mopo_float t, int harmonics) const {\n        return (1.0 * steps) / (steps - 1) * (upsaw(t, harmonics) +\n               downsaw(steps * t, harmonics / steps) / steps);\n      }\n\n      template<size_t steps>\n      inline mopo_float pyramid(mopo_float t, int harmonics) const {\n        size_t squares = steps - 1;\n        mopo_float phase_increment = 1.0 / (2.0 * squares);\n\n        mopo_float phase = 0.5 + t;\n        mopo_float out = 0.0;\n\n        double integral;\n        for (size_t i = 0; i < squares; ++i) {\n          out += square(modf(phase, &integral), harmonics);\n          phase += phase_increment;\n        }\n        out /= squares;\n        return out;\n      }\n\n    private:\n      // Make them 1 larger for wrapping.\n      mopo_float sin_[LOOKUP_SIZE + 1];\n      mopo_float square_[MAX_HARMONICS][LOOKUP_SIZE + 1];\n      mopo_float saw_[MAX_HARMONICS][LOOKUP_SIZE + 1];\n      mopo_float triangle_[MAX_HARMONICS][LOOKUP_SIZE + 1];\n  };\n\n  class Wave {\n    public:\n      enum Type {\n        kSin,\n        kTriangle,\n        kSquare,\n        kDownSaw,\n        kUpSaw,\n        kThreeStep,\n        kFourStep,\n        kEightStep,\n        kThreePyramid,\n        kFivePyramid,\n        kNinePyramid,\n        kWhiteNoise,\n        kNumWaveforms\n      };\n\n      static inline mopo_float blwave(Type waveform, mopo_float t,\n                                      mopo_float frequency) {\n        if (fabs(frequency) < 1)\n          return wave(waveform, t);\n        int harmonics = HIGH_FREQUENCY / fabs(frequency) - 1;\n        if (harmonics >= MAX_HARMONICS)\n          return wave(waveform, t);\n\n        switch (waveform) {\n          case kSin:\n            return lookup_.fullsin(t);\n          case kTriangle:\n            return lookup_.triangle(t, harmonics);\n          case kSquare:\n            return lookup_.square(t, harmonics);\n          case kDownSaw:\n            return lookup_.downsaw(t, harmonics);\n          case kUpSaw:\n            return lookup_.upsaw(t, harmonics);\n          case kThreeStep:\n            return lookup_.step<3>(t, harmonics);\n          case kFourStep:\n            return lookup_.step<4>(t, harmonics);\n          case kEightStep:\n            return lookup_.step<8>(t, harmonics);\n          case kThreePyramid:\n            return lookup_.pyramid<3>(t, harmonics);\n          case kFivePyramid:\n            return lookup_.pyramid<5>(t, harmonics);\n          case kNinePyramid:\n            return lookup_.pyramid<9>(t, harmonics);\n          default:\n            return wave(waveform, t);\n        }\n      }\n\n      static inline mopo_float wave(Type waveform, mopo_float t) {\n        switch (waveform) {\n          case kSin:\n            return fullsin(t);\n          case kSquare:\n            return square(t);\n          case kTriangle:\n            return triangle(t);\n          case kDownSaw:\n            return downsaw(t);\n          case kUpSaw:\n            return upsaw(t);\n          case kThreeStep:\n            return step<3>(t);\n          case kFourStep:\n            return step<4>(t);\n          case kEightStep:\n            return step<8>(t);\n          case kThreePyramid:\n            return pyramid<3>(t);\n          case kFivePyramid:\n            return pyramid<5>(t);\n          case kNinePyramid:\n            return pyramid<9>(t);\n          case kWhiteNoise:\n            return whitenoise();\n          default:\n            return 0;\n        }\n      }\n\n      static inline mopo_float nullwave() {\n        return 0;\n      }\n\n      static inline mopo_float whitenoise() {\n        return (2.0 * rand()) / RAND_MAX - 1;\n      }\n\n      static inline mopo_float fullsin(mopo_float t) {\n        return lookup_.fullsin(t);\n      }\n\n      static inline mopo_float square(mopo_float t) {\n        return t < 0.5 ? 1 : -1;\n      }\n\n      static inline mopo_float triangle(mopo_float t) {\n        double integral;\n        return fabsf(2.0f - 4.0f * modf(t + 0.75f, &integral)) - 1;\n      }\n\n      static inline mopo_float downsaw(mopo_float t) {\n        return -upsaw(t);\n      }\n\n      static inline mopo_float upsaw(mopo_float t) {\n        return t * 2 - 1;\n      }\n\n      static inline mopo_float hannwave(mopo_float t) {\n        return 0.5f * (1.0f - cosf(2.0f * PI * t));\n      }\n\n      template<size_t steps>\n      static inline mopo_float step(mopo_float t) {\n        mopo_float section = (int)(steps * t);\n        return 2 * section / (steps - 1) - 1;\n      }\n\n      template<size_t steps>\n      static inline mopo_float pyramid(mopo_float t) {\n        size_t squares = steps - 1;\n        mopo_float phase_increment = 1.0 / (2.0 * squares);\n\n        mopo_float phase = 0.5 + t;\n        mopo_float out = 0.0;\n\n        double integral;\n        for (size_t i = 0; i < squares; ++i) {\n          out += square(modf(phase, &integral));\n          phase += phase_increment;\n        }\n        out /= squares;\n        return out;\n      }\n\n    protected:\n      static const WaveLookup lookup_;\n  };\n} // namespace mopo\n\n#endif // WAVE_H\n"
  },
  {
    "path": "patches/bit_sin.mite",
    "content": "{\n \"amp attack\": 0.890625,\n \"amp decay\": 0.679688,\n \"amp release\": 0.534376,\n \"amp sustain\": 0,\n \"cross modulation\": 0,\n \"cutoff\": 81.171875,\n \"delay dry/wet\": 0.421875,\n \"delay feedback\": -0.518750,\n \"delay time\": 0.706094,\n \"fil attack\": 0,\n \"fil decay\": 0.093750,\n \"fil env depth\": 0,\n \"fil release\": 3,\n \"fil sustain\": 0.601562,\n \"filter type\": 0,\n \"keytrack\": 1,\n \"legato\": 0,\n \"lfo 1 frequency\": 10,\n \"lfo 1 waveform\": 2,\n \"lfo 2 frequency\": 2,\n \"lfo 2 waveform\": 0,\n \"mod destination 1\": 4,\n \"mod destination 2\": 0,\n \"mod destination 3\": 0,\n \"mod destination 4\": 0,\n \"mod destination 5\": 0,\n \"mod scale 1\": 0.500000,\n \"mod scale 2\": 0.010000,\n \"mod scale 3\": 0.010000,\n \"mod scale 4\": 0.010000,\n \"mod scale 5\": 0.010000,\n \"mod source 1\": 3,\n \"mod source 2\": 0,\n \"mod source 3\": 0,\n \"mod source 4\": 0,\n \"mod source 5\": 0,\n \"osc 1 waveform\": 0,\n \"osc 2 transpose\": 24,\n \"osc 2 tune\": 0.345625,\n \"osc 2 waveform\": 0,\n \"osc mix\": 0.445313,\n \"pitch bend range\": 4,\n \"polyphony\": 12,\n \"portamento\": 0.027188,\n \"portamento type\": 0,\n \"resonance\": 0.500000,\n \"velocity track\": 0.300000,\n \"volume\": 0.554688\n}"
  },
  {
    "path": "patches/bwang.mite",
    "content": "{\n \"amp attack\": 0,\n \"amp decay\": 2.153125,\n \"amp release\": 0.300000,\n \"amp sustain\": 0,\n \"cross modulation\": 0,\n \"cutoff\": 46.367188,\n \"delay dry/wet\": 0.182812,\n \"delay feedback\": -0.253125,\n \"delay time\": 0.137344,\n \"fil attack\": 0,\n \"fil decay\": 2.175000,\n \"fil env depth\": 42,\n \"fil release\": 0.159375,\n \"fil sustain\": 0.281250,\n \"filter type\": 0,\n \"keytrack\": 0.609375,\n \"legato\": 0,\n \"lfo 1 frequency\": 2,\n \"lfo 1 waveform\": 0,\n \"lfo 2 frequency\": 2,\n \"lfo 2 waveform\": 0,\n \"mod destination 1\": 0,\n \"mod destination 2\": 0,\n \"mod destination 3\": 0,\n \"mod destination 4\": 0,\n \"mod destination 5\": 0,\n \"mod scale 1\": 0.010000,\n \"mod scale 2\": 0.010000,\n \"mod scale 3\": 0.010000,\n \"mod scale 4\": 0.010000,\n \"mod scale 5\": 0.010000,\n \"mod source 1\": 0,\n \"mod source 2\": 0,\n \"mod source 3\": 0,\n \"mod source 4\": 0,\n \"mod source 5\": 0,\n \"osc 1 waveform\": 5,\n \"osc 2 transpose\": -12,\n \"osc 2 tune\": 0.173750,\n \"osc 2 waveform\": 7,\n \"osc mix\": 0.484375,\n \"pitch bend range\": 2,\n \"polyphony\": 17,\n \"portamento\": 0.010000,\n \"portamento type\": 0,\n \"resonance\": 7.984375,\n \"velocity track\": 0.300000,\n \"volume\": 0.232813\n}"
  },
  {
    "path": "patches/default.mite",
    "content": "{\n \"amp attack\": 0.010000,\n \"amp decay\": 0.700000,\n \"amp release\": 0.300000,\n \"amp sustain\": 0,\n \"cross modulation\": 0.000000,\n \"cutoff\": 92,\n \"delay dry/wet\": 0.300000,\n \"delay feedback\": -0.300000,\n \"delay time\": 0.060000,\n \"fil attack\": 0,\n \"fil decay\": 0.300000,\n \"fil env depth\": 12,\n \"fil release\": 0.300000,\n \"fil sustain\": 0,\n \"filter type\": 0,\n \"keytrack\": 0,\n \"legato\": 0,\n \"lfo 1 frequency\": 2,\n \"lfo 1 waveform\": 0,\n \"lfo 2 frequency\": 2,\n \"lfo 2 waveform\": 0,\n \"mod destination 1\": 0,\n \"mod destination 2\": 0,\n \"mod destination 3\": 0,\n \"mod destination 4\": 0,\n \"mod destination 5\": 0,\n \"mod scale 1\": 0.010000,\n \"mod scale 2\": 0.010000,\n \"mod scale 3\": 0.010000,\n \"mod scale 4\": 0.010000,\n \"mod scale 5\": 0.010000,\n \"mod source 1\": 0,\n \"mod source 2\": 0,\n \"mod source 3\": 0,\n \"mod source 4\": 0,\n \"mod source 5\": 0,\n \"osc 1 waveform\": 3,\n \"osc 2 transpose\": -12,\n \"osc 2 tune\": 0.080000,\n \"osc 2 waveform\": 3,\n \"osc mix\": 0.500000,\n \"pitch bend range\": 2,\n \"polyphony\": 1,\n \"portamento\": 0.010000,\n \"portamento type\": 0,\n \"resonance\": 3,\n \"velocity track\": 0.300000,\n \"volume\": 0.600000\n}\n"
  },
  {
    "path": "patches/loaded_room.mite",
    "content": "{\n \"amp attack\": 0.010000,\n \"amp decay\": 2.437500,\n \"amp release\": 0.300000,\n \"amp sustain\": 0,\n \"cross modulation\": 0.189063,\n \"cutoff\": 80.593750,\n \"delay dry/wet\": 0.500000,\n \"delay feedback\": -0.503125,\n \"delay time\": 0.149219,\n \"fil attack\": 0,\n \"fil decay\": 2.835938,\n \"fil env depth\": 48,\n \"fil release\": 0.300000,\n \"fil sustain\": 0,\n \"filter type\": 0,\n \"keytrack\": 0,\n \"legato\": 0,\n \"lfo 1 frequency\": 8.953125,\n \"lfo 1 waveform\": 0,\n \"lfo 2 frequency\": 2.031250,\n \"lfo 2 waveform\": 2,\n \"mod destination 1\": 3,\n \"mod destination 2\": 2,\n \"mod destination 3\": 4,\n \"mod destination 4\": 0,\n \"mod destination 5\": 0,\n \"mod scale 1\": 0.718750,\n \"mod scale 2\": 0.135000,\n \"mod scale 3\": 0.500000,\n \"mod scale 4\": 0.010000,\n \"mod scale 5\": 0.010000,\n \"mod source 1\": 3,\n \"mod source 2\": 3,\n \"mod source 3\": 4,\n \"mod source 4\": 0,\n \"mod source 5\": 0,\n \"osc 1 waveform\": 6,\n \"osc 2 transpose\": -12,\n \"osc 2 tune\": 0.080000,\n \"osc 2 waveform\": 7,\n \"osc mix\": 0.375000,\n \"pitch bend range\": 2,\n \"polyphony\": 10,\n \"portamento\": 0.010000,\n \"portamento type\": 0,\n \"resonance\": 3.445312,\n \"velocity track\": 0.300000,\n \"volume\": 0.279688\n}"
  },
  {
    "path": "patches/test_patch1.mite",
    "content": "{\n \"amp attack\": 0.408438,\n \"amp decay\": 0.723437,\n \"amp release\": 0.229688,\n \"amp sustain\": 0,\n \"cross modulation\": 0,\n \"cutoff\": 63.382812,\n \"delay dry/wet\": 0.300000,\n \"delay feedback\": -0.409375,\n \"delay time\": 0.060000,\n \"fil attack\": 0.468750,\n \"fil decay\": 0.300000,\n \"fil env depth\": 46,\n \"fil release\": 0.300000,\n \"fil sustain\": 0,\n \"filter type\": 0,\n \"keytrack\": 0,\n \"legato\": 0,\n \"lfo 1 frequency\": 2,\n \"lfo 1 waveform\": 0,\n \"lfo 2 frequency\": 2,\n \"lfo 2 waveform\": 0,\n \"mod destination 1\": 0,\n \"mod destination 2\": 0,\n \"mod destination 3\": 0,\n \"mod destination 4\": 0,\n \"mod destination 5\": 0,\n \"mod scale 1\": 0.010000,\n \"mod scale 2\": 0.010000,\n \"mod scale 3\": 0.010000,\n \"mod scale 4\": 0.010000,\n \"mod scale 5\": 0.010000,\n \"mod source 1\": 0,\n \"mod source 2\": 0,\n \"mod source 3\": 0,\n \"mod source 4\": 0,\n \"mod source 5\": 0,\n \"osc 1 waveform\": 4,\n \"osc 2 transpose\": -12,\n \"osc 2 tune\": 0.080000,\n \"osc 2 waveform\": 4,\n \"osc mix\": 0.500000,\n \"pitch bend range\": 2,\n \"polyphony\": 12,\n \"portamento\": 0.010000,\n \"portamento type\": 0,\n \"resonance\": 4.359375,\n \"velocity track\": 0.300000,\n \"volume\": 0.404688\n}"
  },
  {
    "path": "patches/test_patch2.mite",
    "content": "{\n \"amp attack\": 0,\n \"amp decay\": 0.160937,\n \"amp release\": 0.229688,\n \"amp sustain\": 0,\n \"cross modulation\": 0,\n \"cutoff\": 63.382812,\n \"delay dry/wet\": 0.675000,\n \"delay feedback\": -0.596875,\n \"delay time\": 0.353906,\n \"fil attack\": 0,\n \"fil decay\": 0.159375,\n \"fil env depth\": 46,\n \"fil release\": 0.300000,\n \"fil sustain\": 0,\n \"filter type\": 0,\n \"keytrack\": 0,\n \"legato\": 0,\n \"lfo 1 frequency\": 2,\n \"lfo 1 waveform\": 0,\n \"lfo 2 frequency\": 2,\n \"lfo 2 waveform\": 0,\n \"mod destination 1\": 0,\n \"mod destination 2\": 0,\n \"mod destination 3\": 0,\n \"mod destination 4\": 0,\n \"mod destination 5\": 0,\n \"mod scale 1\": 0.010000,\n \"mod scale 2\": 0.010000,\n \"mod scale 3\": 0.010000,\n \"mod scale 4\": 0.010000,\n \"mod scale 5\": 0.010000,\n \"mod source 1\": 0,\n \"mod source 2\": 0,\n \"mod source 3\": 0,\n \"mod source 4\": 0,\n \"mod source 5\": 0,\n \"osc 1 waveform\": 4,\n \"osc 2 transpose\": 12,\n \"osc 2 tune\": 0.345625,\n \"osc 2 waveform\": 4,\n \"osc mix\": 0.500000,\n \"pitch bend range\": 2,\n \"polyphony\": 12,\n \"portamento\": 0.010000,\n \"portamento type\": 0,\n \"resonance\": 4.359375,\n \"velocity track\": 0.300000,\n \"volume\": 0.584375\n}"
  },
  {
    "path": "patches/water_wobble.mite",
    "content": "{\n \"amp attack\": 0.281250,\n \"amp decay\": 1.262500,\n \"amp release\": 0.300000,\n \"amp sustain\": 0,\n \"cross modulation\": 0,\n \"cutoff\": 56.421875,\n \"delay dry/wet\": 0.401562,\n \"delay feedback\": -0.612500,\n \"delay time\": 0.060000,\n \"fil attack\": 0,\n \"fil decay\": 2.175000,\n \"fil env depth\": 34,\n \"fil release\": 0.159375,\n \"fil sustain\": 0.281250,\n \"filter type\": 0,\n \"keytrack\": 0.390625,\n \"legato\": 0,\n \"lfo 1 frequency\": 8.015625,\n \"lfo 1 waveform\": 0,\n \"lfo 2 frequency\": 6.328125,\n \"lfo 2 waveform\": 0,\n \"mod destination 1\": 2,\n \"mod destination 2\": 5,\n \"mod destination 3\": 0,\n \"mod destination 4\": 0,\n \"mod destination 5\": 0,\n \"mod scale 1\": 0.166250,\n \"mod scale 2\": 0.437500,\n \"mod scale 3\": 0.010000,\n \"mod scale 4\": 0.010000,\n \"mod scale 5\": 0.010000,\n \"mod source 1\": 3,\n \"mod source 2\": 4,\n \"mod source 3\": 0,\n \"mod source 4\": 0,\n \"mod source 5\": 0,\n \"osc 1 waveform\": 4,\n \"osc 2 transpose\": 7,\n \"osc 2 tune\": 0.298750,\n \"osc 2 waveform\": 6,\n \"osc mix\": 0.484375,\n \"pitch bend range\": 2,\n \"polyphony\": 17,\n \"portamento\": 0.010000,\n \"portamento type\": 0,\n \"resonance\": 7.531250,\n \"velocity track\": 0.300000,\n \"volume\": 0.154688\n}"
  },
  {
    "path": "patches/whistle.mite",
    "content": "{\n \"amp attack\": 0.117188,\n \"amp decay\": 0.957812,\n \"amp release\": 0.534376,\n \"amp sustain\": 0,\n \"cross modulation\": 0,\n \"cutoff\": 76.531250,\n \"delay dry/wet\": 1.416312e-12,\n \"delay feedback\": -0.596875,\n \"delay time\": 0.168281,\n \"fil attack\": 0,\n \"fil decay\": 0.093750,\n \"fil env depth\": 0,\n \"fil release\": 3,\n \"fil sustain\": 0.601562,\n \"filter type\": 0,\n \"keytrack\": 1,\n \"legato\": 0,\n \"lfo 1 frequency\": 5.359375,\n \"lfo 1 waveform\": 0,\n \"lfo 2 frequency\": 2,\n \"lfo 2 waveform\": 0,\n \"mod destination 1\": 1,\n \"mod destination 2\": 0,\n \"mod destination 3\": 0,\n \"mod destination 4\": 0,\n \"mod destination 5\": 0,\n \"mod scale 1\": 0.010000,\n \"mod scale 2\": 0.010000,\n \"mod scale 3\": 0.010000,\n \"mod scale 4\": 0.010000,\n \"mod scale 5\": 0.010000,\n \"mod source 1\": 3,\n \"mod source 2\": 0,\n \"mod source 3\": 0,\n \"mod source 4\": 0,\n \"mod source 5\": 0,\n \"osc 1 waveform\": 11,\n \"osc 2 transpose\": 0,\n \"osc 2 tune\": 0.345625,\n \"osc 2 waveform\": 11,\n \"osc mix\": 0.242188,\n \"pitch bend range\": 2,\n \"polyphony\": 13,\n \"portamento\": 0.027188,\n \"portamento type\": 0,\n \"resonance\": 15,\n \"velocity track\": 0.300000,\n \"volume\": 0.576563\n}"
  },
  {
    "path": "patches/whoooo.mite",
    "content": "{\n \"amp attack\": 0.164063,\n \"amp decay\": 2.320312,\n \"amp release\": 0.534376,\n \"amp sustain\": 0,\n \"cross modulation\": 0,\n \"cutoff\": 81.171875,\n \"delay dry/wet\": 1.416332e-12,\n \"delay feedback\": -0.596875,\n \"delay time\": 0.404453,\n \"fil attack\": 0,\n \"fil decay\": 0.093750,\n \"fil env depth\": 0,\n \"fil release\": 3,\n \"fil sustain\": 0.601562,\n \"filter type\": 0,\n \"keytrack\": 1,\n \"legato\": 0,\n \"lfo 1 frequency\": 5.359375,\n \"lfo 1 waveform\": 0,\n \"lfo 2 frequency\": 2,\n \"lfo 2 waveform\": 0,\n \"mod destination 1\": 4,\n \"mod destination 2\": 0,\n \"mod destination 3\": 0,\n \"mod destination 4\": 0,\n \"mod destination 5\": 0,\n \"mod scale 1\": 0.056875,\n \"mod scale 2\": 0.010000,\n \"mod scale 3\": 0.010000,\n \"mod scale 4\": 0.010000,\n \"mod scale 5\": 0.010000,\n \"mod source 1\": 3,\n \"mod source 2\": 0,\n \"mod source 3\": 0,\n \"mod source 4\": 0,\n \"mod source 5\": 0,\n \"osc 1 waveform\": 0,\n \"osc 2 transpose\": 24,\n \"osc 2 tune\": 0.345625,\n \"osc 2 waveform\": 0,\n \"osc mix\": 0.445313,\n \"pitch bend range\": 4,\n \"polyphony\": 12,\n \"portamento\": 0.027188,\n \"portamento type\": 0,\n \"resonance\": 0.500000,\n \"velocity track\": 0.300000,\n \"volume\": 0.515625\n}"
  },
  {
    "path": "patches/womp.mite",
    "content": "{\n \"amp attack\": 0.197500,\n \"amp decay\": 0.700000,\n \"amp release\": 0.300000,\n \"amp sustain\": 0,\n \"cross modulation\": 0,\n \"cutoff\": 57.968750,\n \"delay dry/wet\": 0.401562,\n \"delay feedback\": -0.612500,\n \"delay time\": 0.137344,\n \"fil attack\": 0.445312,\n \"fil decay\": 2.175000,\n \"fil env depth\": 34,\n \"fil release\": 0.159375,\n \"fil sustain\": 0.281250,\n \"filter type\": 0,\n \"keytrack\": 0,\n \"legato\": 0,\n \"lfo 1 frequency\": 2,\n \"lfo 1 waveform\": 0,\n \"lfo 2 frequency\": 2,\n \"lfo 2 waveform\": 0,\n \"mod destination 1\": 0,\n \"mod destination 2\": 0,\n \"mod destination 3\": 0,\n \"mod destination 4\": 0,\n \"mod destination 5\": 0,\n \"mod scale 1\": 0.010000,\n \"mod scale 2\": 0.010000,\n \"mod scale 3\": 0.010000,\n \"mod scale 4\": 0.010000,\n \"mod scale 5\": 0.010000,\n \"mod source 1\": 0,\n \"mod source 2\": 0,\n \"mod source 3\": 0,\n \"mod source 4\": 0,\n \"mod source 5\": 0,\n \"osc 1 waveform\": 5,\n \"osc 2 transpose\": 19,\n \"osc 2 tune\": 0.173750,\n \"osc 2 waveform\": 5,\n \"osc mix\": 0.484375,\n \"pitch bend range\": 2,\n \"polyphony\": 17,\n \"portamento\": 0.010000,\n \"portamento type\": 0,\n \"resonance\": 3,\n \"velocity track\": 0.300000,\n \"volume\": 0.271875\n}"
  },
  {
    "path": "po/.gitignore",
    "content": "# Ignore everything in this directory\n*\n\n# Except these files\n!.gitignore\n\n!ChangeLog\n!LINGUAS\n!POTFILES.in\n!Makevars\n\n!*.po\n"
  },
  {
    "path": "po/Makevars",
    "content": "# Makefile variables for PO directory in any package using GNU gettext.\n\n# Usually the message domain is the same as the package name.\nDOMAIN = $(PACKAGE)\n\n# These two variables depend on the location of this directory.\nsubdir = po\ntop_builddir = ..\n\n# These options get passed to xgettext.\nXGETTEXT_OPTIONS = --keyword=_ --keyword=N_\n\n# This is the copyright holder that gets inserted into the header of the\n# $(DOMAIN).pot file.  Set this to the copyright holder of the surrounding\n# package.  (Note that the msgstr strings, extracted from the package's\n# sources, belong to the copyright holder of the package.)  Translators are\n# expected to transfer the copyright for their translations to this person\n# or entity, or to disclaim their copyright.  The empty string stands for\n# the public domain; in this case the translators are expected to disclaim\n# their copyright.\nCOPYRIGHT_HOLDER = Matt Tytel\n\n# This is the email address or URL to which the translators shall report\n# bugs in the untranslated strings:\n# - Strings which are not entire sentences, see the maintainer guidelines\n#   in the GNU gettext documentation, section 'Preparing Strings'.\n# - Strings which use unclear terms or require additional context to be\n#   understood.\n# - Strings which make invalid assumptions about notation of date, time or\n#   money.\n# - Pluralisation problems.\n# - Incorrect English spelling.\n# - Incorrect formatting.\n# It can be your email address, or a mailing list address where translators\n# can write to without being subscribed, or the URL of a web page through\n# which the translators can contact you.\nMSGID_BUGS_ADDRESS = matthewtytel@gmail.com\n\n# This is the list of locale categories, beyond LC_MESSAGES, for which the\n# message catalogs shall be used.  It is usually empty.\nEXTRA_LOCALE_CATEGORIES =\n\n# This tells whether the $(DOMAIN).pot file contains messages with an 'msgctxt'\n# context.  Possible values are \"yes\" and \"no\".  Set this to yes if the\n# package uses functions taking also a message context, like pgettext(), or\n# if in $(XGETTEXT_OPTIONS) you define keywords with a context argument.\nUSE_MSGCTXT = no\n\n# These options get passed to msgmerge.\n# Useful options are in particular:\n#   --previous            to keep previous msgids of translated messages,\n#   --quiet               to reduce the verbosity.\nMSGMERGE_OPTIONS =\n"
  },
  {
    "path": "po/POTFILES.in",
    "content": "# List of source files which contain translatable strings.\nsrc/cursynth_gui.cpp\n"
  },
  {
    "path": "rtaudio/.gitignore",
    "content": "librtaudio.so*\nlibrtaudio.dylib.4\nrtaudio-config\nlibrtaudio.pc\n"
  },
  {
    "path": "rtaudio/Makefile.am",
    "content": "noinst_LIBRARIES = librtaudio.a\nlibrtaudio_a_SOURCES = RtAudio.cpp RtAudio.h RtError.h\n"
  },
  {
    "path": "rtaudio/RtAudio.cpp",
    "content": "/************************************************************************/\r\n/*! \\class RtAudio\r\n    \\brief Realtime audio i/o C++ classes.\r\n\r\n    RtAudio provides a common API (Application Programming Interface)\r\n    for realtime audio input/output across GNU/Linux (native ALSA, Jack,\r\n    and OSS), Macintosh OS X (CoreAudio and Jack), and Windows\r\n    (DirectSound and ASIO) operating systems.\r\n\r\n    RtAudio WWW site: http://www.music.mcgill.ca/~gary/rtaudio/\r\n\r\n    RtAudio: realtime audio i/o C++ classes\r\n    Copyright (c) 2001-2013 Gary P. Scavone\r\n\r\n    Permission is hereby granted, free of charge, to any person\r\n    obtaining a copy of this software and associated documentation files\r\n    (the \"Software\"), to deal in the Software without restriction,\r\n    including without limitation the rights to use, copy, modify, merge,\r\n    publish, distribute, sublicense, and/or sell copies of the Software,\r\n    and to permit persons to whom the Software is furnished to do so,\r\n    subject to the following conditions:\r\n\r\n    The above copyright notice and this permission notice shall be\r\n    included in all copies or substantial portions of the Software.\r\n\r\n    Any person wishing to distribute modifications to the Software is\r\n    asked to send the modifications to the original developer so that\r\n    they can be incorporated into the canonical version.  This is,\r\n    however, not a binding provision of this license.\r\n\r\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\r\n    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r\n    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\r\n    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR\r\n    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF\r\n    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\r\n    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r\n*/\r\n/************************************************************************/\r\n\r\n// RtAudio: Version 4.0.12\r\n\r\n#include \"RtAudio.h\"\r\n#include <iostream>\r\n#include <cstdlib>\r\n#include <cstring>\r\n#include <climits>\r\n\r\n// Static variable definitions.\r\nconst unsigned int RtApi::MAX_SAMPLE_RATES = 14;\r\nconst unsigned int RtApi::SAMPLE_RATES[] = {\r\n  4000, 5512, 8000, 9600, 11025, 16000, 22050,\r\n  32000, 44100, 48000, 88200, 96000, 176400, 192000\r\n};\r\n\r\n#if defined(__WINDOWS_DS__) || defined(__WINDOWS_ASIO__)\r\n  #define MUTEX_INITIALIZE(A) InitializeCriticalSection(A)\r\n  #define MUTEX_DESTROY(A)    DeleteCriticalSection(A)\r\n  #define MUTEX_LOCK(A)       EnterCriticalSection(A)\r\n  #define MUTEX_UNLOCK(A)     LeaveCriticalSection(A)\r\n#elif defined(__LINUX_ALSA__) || defined(__LINUX_PULSE__) || defined(__UNIX_JACK__) || defined(__LINUX_OSS__) || defined(__MACOSX_CORE__)\r\n  // pthread API\r\n  #define MUTEX_INITIALIZE(A) pthread_mutex_init(A, NULL)\r\n  #define MUTEX_DESTROY(A)    pthread_mutex_destroy(A)\r\n  #define MUTEX_LOCK(A)       pthread_mutex_lock(A)\r\n  #define MUTEX_UNLOCK(A)     pthread_mutex_unlock(A)\r\n#else\r\n  #define MUTEX_INITIALIZE(A) abs(*A) // dummy definitions\r\n  #define MUTEX_DESTROY(A)    abs(*A) // dummy definitions\r\n#endif\r\n\r\n// *************************************************** //\r\n//\r\n// RtAudio definitions.\r\n//\r\n// *************************************************** //\r\n\r\nvoid RtAudio :: getCompiledApi( std::vector<RtAudio::Api> &apis ) throw()\r\n{\r\n  apis.clear();\r\n\r\n  // The order here will control the order of RtAudio's API search in\r\n  // the constructor.\r\n#if defined(__UNIX_JACK__)\r\n  apis.push_back( UNIX_JACK );\r\n#endif\r\n#if defined(__LINUX_ALSA__)\r\n  apis.push_back( LINUX_ALSA );\r\n#endif\r\n#if defined(__LINUX_PULSE__)\r\n  apis.push_back( LINUX_PULSE );\r\n#endif\r\n#if defined(__LINUX_OSS__)\r\n  apis.push_back( LINUX_OSS );\r\n#endif\r\n#if defined(__WINDOWS_ASIO__)\r\n  apis.push_back( WINDOWS_ASIO );\r\n#endif\r\n#if defined(__WINDOWS_DS__)\r\n  apis.push_back( WINDOWS_DS );\r\n#endif\r\n#if defined(__MACOSX_CORE__)\r\n  apis.push_back( MACOSX_CORE );\r\n#endif\r\n#if defined(__RTAUDIO_DUMMY__)\r\n  apis.push_back( RTAUDIO_DUMMY );\r\n#endif\r\n}\r\n\r\nvoid RtAudio :: openRtApi( RtAudio::Api api )\r\n{\r\n  if ( rtapi_ )\r\n    delete rtapi_;\r\n  rtapi_ = 0;\r\n\r\n#if defined(__UNIX_JACK__)\r\n  if ( api == UNIX_JACK )\r\n    rtapi_ = new RtApiJack();\r\n#endif\r\n#if defined(__LINUX_ALSA__)\r\n  if ( api == LINUX_ALSA )\r\n    rtapi_ = new RtApiAlsa();\r\n#endif\r\n#if defined(__LINUX_PULSE__)\r\n  if ( api == LINUX_PULSE )\r\n    rtapi_ = new RtApiPulse();\r\n#endif\r\n#if defined(__LINUX_OSS__)\r\n  if ( api == LINUX_OSS )\r\n    rtapi_ = new RtApiOss();\r\n#endif\r\n#if defined(__WINDOWS_ASIO__)\r\n  if ( api == WINDOWS_ASIO )\r\n    rtapi_ = new RtApiAsio();\r\n#endif\r\n#if defined(__WINDOWS_DS__)\r\n  if ( api == WINDOWS_DS )\r\n    rtapi_ = new RtApiDs();\r\n#endif\r\n#if defined(__MACOSX_CORE__)\r\n  if ( api == MACOSX_CORE )\r\n    rtapi_ = new RtApiCore();\r\n#endif\r\n#if defined(__RTAUDIO_DUMMY__)\r\n  if ( api == RTAUDIO_DUMMY )\r\n    rtapi_ = new RtApiDummy();\r\n#endif\r\n}\r\n\r\nRtAudio :: RtAudio( RtAudio::Api api ) throw()\r\n{\r\n  rtapi_ = 0;\r\n\r\n  if ( api != UNSPECIFIED ) {\r\n    // Attempt to open the specified API.\r\n    openRtApi( api );\r\n    if ( rtapi_ ) return;\r\n\r\n    // No compiled support for specified API value.  Issue a debug\r\n    // warning and continue as if no API was specified.\r\n    std::cerr << \"\\nRtAudio: no compiled support for specified API argument!\\n\" << std::endl;\r\n  }\r\n\r\n  // Iterate through the compiled APIs and return as soon as we find\r\n  // one with at least one device or we reach the end of the list.\r\n  std::vector< RtAudio::Api > apis;\r\n  getCompiledApi( apis );\r\n  for ( unsigned int i=0; i<apis.size(); i++ ) {\r\n    openRtApi( apis[i] );\r\n    if ( rtapi_->getDeviceCount() ) break;\r\n  }\r\n\r\n  if ( rtapi_ ) return;\r\n\r\n  // It should not be possible to get here because the preprocessor\r\n  // definition __RTAUDIO_DUMMY__ is automatically defined if no\r\n  // API-specific definitions are passed to the compiler. But just in\r\n  // case something weird happens, we'll print out an error message.\r\n  std::cerr << \"\\nRtAudio: no compiled API support found ... critical error!!\\n\\n\";\r\n}\r\n\r\nRtAudio :: ~RtAudio() throw()\r\n{\r\n  delete rtapi_;\r\n}\r\n\r\nvoid RtAudio :: openStream( RtAudio::StreamParameters *outputParameters,\r\n                            RtAudio::StreamParameters *inputParameters,\r\n                            RtAudioFormat format, unsigned int sampleRate,\r\n                            unsigned int *bufferFrames,\r\n                            RtAudioCallback callback, void *userData,\r\n                            RtAudio::StreamOptions *options,\r\n                            RtAudioErrorCallback errorCallback )\r\n{\r\n  return rtapi_->openStream( outputParameters, inputParameters, format,\r\n                             sampleRate, bufferFrames, callback,\r\n                             userData, options, errorCallback );\r\n}\r\n\r\n// *************************************************** //\r\n//\r\n// Public RtApi definitions (see end of file for\r\n// private or protected utility functions).\r\n//\r\n// *************************************************** //\r\n\r\nRtApi :: RtApi()\r\n{\r\n  stream_.state = STREAM_CLOSED;\r\n  stream_.mode = UNINITIALIZED;\r\n  stream_.apiHandle = 0;\r\n  stream_.userBuffer[0] = 0;\r\n  stream_.userBuffer[1] = 0;\r\n  MUTEX_INITIALIZE( &stream_.mutex );\r\n  showWarnings_ = true;\r\n}\r\n\r\nRtApi :: ~RtApi()\r\n{\r\n  MUTEX_DESTROY( &stream_.mutex );\r\n}\r\n\r\nvoid RtApi :: openStream( RtAudio::StreamParameters *oParams,\r\n                          RtAudio::StreamParameters *iParams,\r\n                          RtAudioFormat format, unsigned int sampleRate,\r\n                          unsigned int *bufferFrames,\r\n                          RtAudioCallback callback, void *userData,\r\n                          RtAudio::StreamOptions *options,\r\n                          RtAudioErrorCallback errorCallback )\r\n{\r\n  if ( stream_.state != STREAM_CLOSED ) {\r\n    errorText_ = \"RtApi::openStream: a stream is already open!\";\r\n    error( RtError::INVALID_USE );\r\n    return;\r\n  }\r\n\r\n  if ( oParams && oParams->nChannels < 1 ) {\r\n    errorText_ = \"RtApi::openStream: a non-NULL output StreamParameters structure cannot have an nChannels value less than one.\";\r\n    error( RtError::INVALID_USE );\r\n    return;\r\n  }\r\n\r\n  if ( iParams && iParams->nChannels < 1 ) {\r\n    errorText_ = \"RtApi::openStream: a non-NULL input StreamParameters structure cannot have an nChannels value less than one.\";\r\n    error( RtError::INVALID_USE );\r\n    return;\r\n  }\r\n\r\n  if ( oParams == NULL && iParams == NULL ) {\r\n    errorText_ = \"RtApi::openStream: input and output StreamParameters structures are both NULL!\";\r\n    error( RtError::INVALID_USE );\r\n    return;\r\n  }\r\n\r\n  if ( formatBytes(format) == 0 ) {\r\n    errorText_ = \"RtApi::openStream: 'format' parameter value is undefined.\";\r\n    error( RtError::INVALID_USE );\r\n    return;\r\n  }\r\n\r\n  unsigned int nDevices = getDeviceCount();\r\n  unsigned int oChannels = 0;\r\n  if ( oParams ) {\r\n    oChannels = oParams->nChannels;\r\n    if ( oParams->deviceId >= nDevices ) {\r\n      errorText_ = \"RtApi::openStream: output device parameter value is invalid.\";\r\n      error( RtError::INVALID_USE );\r\n      return;\r\n    }\r\n  }\r\n\r\n  unsigned int iChannels = 0;\r\n  if ( iParams ) {\r\n    iChannels = iParams->nChannels;\r\n    if ( iParams->deviceId >= nDevices ) {\r\n      errorText_ = \"RtApi::openStream: input device parameter value is invalid.\";\r\n      error( RtError::INVALID_USE );\r\n      return;\r\n    }\r\n  }\r\n\r\n  clearStreamInfo();\r\n  bool result;\r\n\r\n  if ( oChannels > 0 ) {\r\n\r\n    result = probeDeviceOpen( oParams->deviceId, OUTPUT, oChannels, oParams->firstChannel,\r\n                              sampleRate, format, bufferFrames, options );\r\n    if ( result == false ) {\r\n      error( RtError::SYSTEM_ERROR );\r\n      return;\r\n    }\r\n  }\r\n\r\n  if ( iChannels > 0 ) {\r\n\r\n    result = probeDeviceOpen( iParams->deviceId, INPUT, iChannels, iParams->firstChannel,\r\n                              sampleRate, format, bufferFrames, options );\r\n    if ( result == false ) {\r\n      if ( oChannels > 0 ) closeStream();\r\n      error( RtError::SYSTEM_ERROR );\r\n      return;\r\n    }\r\n  }\r\n\r\n  stream_.callbackInfo.callback = (void *) callback;\r\n  stream_.callbackInfo.userData = userData;\r\n  stream_.callbackInfo.errorCallback = (void *) errorCallback;\r\n\r\n  if ( options ) options->numberOfBuffers = stream_.nBuffers;\r\n  stream_.state = STREAM_STOPPED;\r\n}\r\n\r\nunsigned int RtApi :: getDefaultInputDevice( void )\r\n{\r\n  // Should be implemented in subclasses if possible.\r\n  return 0;\r\n}\r\n\r\nunsigned int RtApi :: getDefaultOutputDevice( void )\r\n{\r\n  // Should be implemented in subclasses if possible.\r\n  return 0;\r\n}\r\n\r\nvoid RtApi :: closeStream( void )\r\n{\r\n  // MUST be implemented in subclasses!\r\n  return;\r\n}\r\n\r\nbool RtApi :: probeDeviceOpen( unsigned int /*device*/, StreamMode /*mode*/, unsigned int /*channels*/,\r\n                               unsigned int /*firstChannel*/, unsigned int /*sampleRate*/,\r\n                               RtAudioFormat /*format*/, unsigned int * /*bufferSize*/,\r\n                               RtAudio::StreamOptions * /*options*/ )\r\n{\r\n  // MUST be implemented in subclasses!\r\n  return FAILURE;\r\n}\r\n\r\nvoid RtApi :: tickStreamTime( void )\r\n{\r\n  // Subclasses that do not provide their own implementation of\r\n  // getStreamTime should call this function once per buffer I/O to\r\n  // provide basic stream time support.\r\n\r\n  stream_.streamTime += ( stream_.bufferSize * 1.0 / stream_.sampleRate );\r\n\r\n#if defined( HAVE_GETTIMEOFDAY )\r\n  gettimeofday( &stream_.lastTickTimestamp, NULL );\r\n#endif\r\n}\r\n\r\nlong RtApi :: getStreamLatency( void )\r\n{\r\n  verifyStream();\r\n\r\n  long totalLatency = 0;\r\n  if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX )\r\n    totalLatency = stream_.latency[0];\r\n  if ( stream_.mode == INPUT || stream_.mode == DUPLEX )\r\n    totalLatency += stream_.latency[1];\r\n\r\n  return totalLatency;\r\n}\r\n\r\ndouble RtApi :: getStreamTime( void )\r\n{\r\n  verifyStream();\r\n\r\n#if defined( HAVE_GETTIMEOFDAY )\r\n  // Return a very accurate estimate of the stream time by\r\n  // adding in the elapsed time since the last tick.\r\n  struct timeval then;\r\n  struct timeval now;\r\n\r\n  if ( stream_.state != STREAM_RUNNING || stream_.streamTime == 0.0 )\r\n    return stream_.streamTime;\r\n\r\n  gettimeofday( &now, NULL );\r\n  then = stream_.lastTickTimestamp;\r\n  return stream_.streamTime +\r\n    ((now.tv_sec + 0.000001 * now.tv_usec) -\r\n     (then.tv_sec + 0.000001 * then.tv_usec));     \r\n#else\r\n  return stream_.streamTime;\r\n#endif\r\n}\r\n\r\nunsigned int RtApi :: getStreamSampleRate( void )\r\n{\r\n verifyStream();\r\n\r\n return stream_.sampleRate;\r\n}\r\n\r\n\r\n// *************************************************** //\r\n//\r\n// OS/API-specific methods.\r\n//\r\n// *************************************************** //\r\n\r\n#if defined(__MACOSX_CORE__)\r\n\r\n// The OS X CoreAudio API is designed to use a separate callback\r\n// procedure for each of its audio devices.  A single RtAudio duplex\r\n// stream using two different devices is supported here, though it\r\n// cannot be guaranteed to always behave correctly because we cannot\r\n// synchronize these two callbacks.\r\n//\r\n// A property listener is installed for over/underrun information.\r\n// However, no functionality is currently provided to allow property\r\n// listeners to trigger user handlers because it is unclear what could\r\n// be done if a critical stream parameter (buffer size, sample rate,\r\n// device disconnect) notification arrived.  The listeners entail\r\n// quite a bit of extra code and most likely, a user program wouldn't\r\n// be prepared for the result anyway.  However, we do provide a flag\r\n// to the client callback function to inform of an over/underrun.\r\n\r\n// A structure to hold various information related to the CoreAudio API\r\n// implementation.\r\nstruct CoreHandle {\r\n  AudioDeviceID id[2];    // device ids\r\n#if defined( MAC_OS_X_VERSION_10_5 ) && ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 )\r\n  AudioDeviceIOProcID procId[2];\r\n#endif\r\n  UInt32 iStream[2];      // device stream index (or first if using multiple)\r\n  UInt32 nStreams[2];     // number of streams to use\r\n  bool xrun[2];\r\n  char *deviceBuffer;\r\n  pthread_cond_t condition;\r\n  int drainCounter;       // Tracks callback counts when draining\r\n  bool internalDrain;     // Indicates if stop is initiated from callback or not.\r\n\r\n  CoreHandle()\r\n    :deviceBuffer(0), drainCounter(0), internalDrain(false) { nStreams[0] = 1; nStreams[1] = 1; id[0] = 0; id[1] = 0; xrun[0] = false; xrun[1] = false; }\r\n};\r\n\r\nRtApiCore:: RtApiCore()\r\n{\r\n#if defined( AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER )\r\n  // This is a largely undocumented but absolutely necessary\r\n  // requirement starting with OS-X 10.6.  If not called, queries and\r\n  // updates to various audio device properties are not handled\r\n  // correctly.\r\n  CFRunLoopRef theRunLoop = NULL;\r\n  AudioObjectPropertyAddress property = { kAudioHardwarePropertyRunLoop,\r\n                                          kAudioObjectPropertyScopeGlobal,\r\n                                          kAudioObjectPropertyElementMaster };\r\n  OSStatus result = AudioObjectSetPropertyData( kAudioObjectSystemObject, &property, 0, NULL, sizeof(CFRunLoopRef), &theRunLoop);\r\n  if ( result != noErr ) {\r\n    errorText_ = \"RtApiCore::RtApiCore: error setting run loop property!\";\r\n    error( RtError::WARNING );\r\n  }\r\n#endif\r\n}\r\n\r\nRtApiCore :: ~RtApiCore()\r\n{\r\n  // The subclass destructor gets called before the base class\r\n  // destructor, so close an existing stream before deallocating\r\n  // apiDeviceId memory.\r\n  if ( stream_.state != STREAM_CLOSED ) closeStream();\r\n}\r\n\r\nunsigned int RtApiCore :: getDeviceCount( void )\r\n{\r\n  // Find out how many audio devices there are, if any.\r\n  UInt32 dataSize;\r\n  AudioObjectPropertyAddress propertyAddress = { kAudioHardwarePropertyDevices, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };\r\n  OSStatus result = AudioObjectGetPropertyDataSize( kAudioObjectSystemObject, &propertyAddress, 0, NULL, &dataSize );\r\n  if ( result != noErr ) {\r\n    errorText_ = \"RtApiCore::getDeviceCount: OS-X error getting device info!\";\r\n    error( RtError::WARNING );\r\n    return 0;\r\n  }\r\n\r\n  return dataSize / sizeof( AudioDeviceID );\r\n}\r\n\r\nunsigned int RtApiCore :: getDefaultInputDevice( void )\r\n{\r\n  unsigned int nDevices = getDeviceCount();\r\n  if ( nDevices <= 1 ) return 0;\r\n\r\n  AudioDeviceID id;\r\n  UInt32 dataSize = sizeof( AudioDeviceID );\r\n  AudioObjectPropertyAddress property = { kAudioHardwarePropertyDefaultInputDevice, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };\r\n  OSStatus result = AudioObjectGetPropertyData( kAudioObjectSystemObject, &property, 0, NULL, &dataSize, &id );\r\n  if ( result != noErr ) {\r\n    errorText_ = \"RtApiCore::getDefaultInputDevice: OS-X system error getting device.\";\r\n    error( RtError::WARNING );\r\n    return 0;\r\n  }\r\n\r\n  dataSize *= nDevices;\r\n  AudioDeviceID deviceList[ nDevices ];\r\n  property.mSelector = kAudioHardwarePropertyDevices;\r\n  result = AudioObjectGetPropertyData( kAudioObjectSystemObject, &property, 0, NULL, &dataSize, (void *) &deviceList );\r\n  if ( result != noErr ) {\r\n    errorText_ = \"RtApiCore::getDefaultInputDevice: OS-X system error getting device IDs.\";\r\n    error( RtError::WARNING );\r\n    return 0;\r\n  }\r\n\r\n  for ( unsigned int i=0; i<nDevices; i++ )\r\n    if ( id == deviceList[i] ) return i;\r\n\r\n  errorText_ = \"RtApiCore::getDefaultInputDevice: No default device found!\";\r\n  error( RtError::WARNING );\r\n  return 0;\r\n}\r\n\r\nunsigned int RtApiCore :: getDefaultOutputDevice( void )\r\n{\r\n  unsigned int nDevices = getDeviceCount();\r\n  if ( nDevices <= 1 ) return 0;\r\n\r\n  AudioDeviceID id;\r\n  UInt32 dataSize = sizeof( AudioDeviceID );\r\n  AudioObjectPropertyAddress property = { kAudioHardwarePropertyDefaultOutputDevice, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };\r\n  OSStatus result = AudioObjectGetPropertyData( kAudioObjectSystemObject, &property, 0, NULL, &dataSize, &id );\r\n  if ( result != noErr ) {\r\n    errorText_ = \"RtApiCore::getDefaultOutputDevice: OS-X system error getting device.\";\r\n    error( RtError::WARNING );\r\n    return 0;\r\n  }\r\n\r\n  dataSize = sizeof( AudioDeviceID ) * nDevices;\r\n  AudioDeviceID deviceList[ nDevices ];\r\n  property.mSelector = kAudioHardwarePropertyDevices;\r\n  result = AudioObjectGetPropertyData( kAudioObjectSystemObject, &property, 0, NULL, &dataSize, (void *) &deviceList );\r\n  if ( result != noErr ) {\r\n    errorText_ = \"RtApiCore::getDefaultOutputDevice: OS-X system error getting device IDs.\";\r\n    error( RtError::WARNING );\r\n    return 0;\r\n  }\r\n\r\n  for ( unsigned int i=0; i<nDevices; i++ )\r\n    if ( id == deviceList[i] ) return i;\r\n\r\n  errorText_ = \"RtApiCore::getDefaultOutputDevice: No default device found!\";\r\n  error( RtError::WARNING );\r\n  return 0;\r\n}\r\n\r\nRtAudio::DeviceInfo RtApiCore :: getDeviceInfo( unsigned int device )\r\n{\r\n  RtAudio::DeviceInfo info;\r\n  info.probed = false;\r\n\r\n  // Get device ID\r\n  unsigned int nDevices = getDeviceCount();\r\n  if ( nDevices == 0 ) {\r\n    errorText_ = \"RtApiCore::getDeviceInfo: no devices found!\";\r\n    error( RtError::INVALID_USE );\r\n    return info;\r\n  }\r\n\r\n  if ( device >= nDevices ) {\r\n    errorText_ = \"RtApiCore::getDeviceInfo: device ID is invalid!\";\r\n    error( RtError::INVALID_USE );\r\n    return info;\r\n  }\r\n\r\n  AudioDeviceID deviceList[ nDevices ];\r\n  UInt32 dataSize = sizeof( AudioDeviceID ) * nDevices;\r\n  AudioObjectPropertyAddress property = { kAudioHardwarePropertyDevices,\r\n                                          kAudioObjectPropertyScopeGlobal,\r\n                                          kAudioObjectPropertyElementMaster };\r\n  OSStatus result = AudioObjectGetPropertyData( kAudioObjectSystemObject, &property,\r\n                                                0, NULL, &dataSize, (void *) &deviceList );\r\n  if ( result != noErr ) {\r\n    errorText_ = \"RtApiCore::getDeviceInfo: OS-X system error getting device IDs.\";\r\n    error( RtError::WARNING );\r\n    return info;\r\n  }\r\n\r\n  AudioDeviceID id = deviceList[ device ];\r\n\r\n  // Get the device name.\r\n  info.name.erase();\r\n  CFStringRef cfname;\r\n  dataSize = sizeof( CFStringRef );\r\n  property.mSelector = kAudioObjectPropertyManufacturer;\r\n  result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, &cfname );\r\n  if ( result != noErr ) {\r\n    errorStream_ << \"RtApiCore::probeDeviceInfo: system error (\" << getErrorCode( result ) << \") getting device manufacturer.\";\r\n    errorText_ = errorStream_.str();\r\n    error( RtError::WARNING );\r\n    return info;\r\n  }\r\n\r\n  //const char *mname = CFStringGetCStringPtr( cfname, CFStringGetSystemEncoding() );\r\n  int length = CFStringGetLength(cfname);\r\n  char *mname = (char *)malloc(length * 3 + 1);\r\n  CFStringGetCString(cfname, mname, length * 3 + 1, CFStringGetSystemEncoding());\r\n  info.name.append( (const char *)mname, strlen(mname) );\r\n  info.name.append( \": \" );\r\n  CFRelease( cfname );\r\n  free(mname);\r\n\r\n  property.mSelector = kAudioObjectPropertyName;\r\n  result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, &cfname );\r\n  if ( result != noErr ) {\r\n    errorStream_ << \"RtApiCore::probeDeviceInfo: system error (\" << getErrorCode( result ) << \") getting device name.\";\r\n    errorText_ = errorStream_.str();\r\n    error( RtError::WARNING );\r\n    return info;\r\n  }\r\n\r\n  //const char *name = CFStringGetCStringPtr( cfname, CFStringGetSystemEncoding() );\r\n  length = CFStringGetLength(cfname);\r\n  char *name = (char *)malloc(length * 3 + 1);\r\n  CFStringGetCString(cfname, name, length * 3 + 1, CFStringGetSystemEncoding());\r\n  info.name.append( (const char *)name, strlen(name) );\r\n  CFRelease( cfname );\r\n  free(name);\r\n\r\n  // Get the output stream \"configuration\".\r\n  AudioBufferList\t*bufferList = nil;\r\n  property.mSelector = kAudioDevicePropertyStreamConfiguration;\r\n  property.mScope = kAudioDevicePropertyScopeOutput;\r\n  //  property.mElement = kAudioObjectPropertyElementWildcard;\r\n  dataSize = 0;\r\n  result = AudioObjectGetPropertyDataSize( id, &property, 0, NULL, &dataSize );\r\n  if ( result != noErr || dataSize == 0 ) {\r\n    errorStream_ << \"RtApiCore::getDeviceInfo: system error (\" << getErrorCode( result ) << \") getting output stream configuration info for device (\" << device << \").\";\r\n    errorText_ = errorStream_.str();\r\n    error( RtError::WARNING );\r\n    return info;\r\n  }\r\n\r\n  // Allocate the AudioBufferList.\r\n  bufferList = (AudioBufferList *) malloc( dataSize );\r\n  if ( bufferList == NULL ) {\r\n    errorText_ = \"RtApiCore::getDeviceInfo: memory error allocating output AudioBufferList.\";\r\n    error( RtError::WARNING );\r\n    return info;\r\n  }\r\n\r\n  result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, bufferList );\r\n  if ( result != noErr || dataSize == 0 ) {\r\n    free( bufferList );\r\n    errorStream_ << \"RtApiCore::getDeviceInfo: system error (\" << getErrorCode( result ) << \") getting output stream configuration for device (\" << device << \").\";\r\n    errorText_ = errorStream_.str();\r\n    error( RtError::WARNING );\r\n    return info;\r\n  }\r\n\r\n  // Get output channel information.\r\n  unsigned int i, nStreams = bufferList->mNumberBuffers;\r\n  for ( i=0; i<nStreams; i++ )\r\n    info.outputChannels += bufferList->mBuffers[i].mNumberChannels;\r\n  free( bufferList );\r\n\r\n  // Get the input stream \"configuration\".\r\n  property.mScope = kAudioDevicePropertyScopeInput;\r\n  result = AudioObjectGetPropertyDataSize( id, &property, 0, NULL, &dataSize );\r\n  if ( result != noErr || dataSize == 0 ) {\r\n    errorStream_ << \"RtApiCore::getDeviceInfo: system error (\" << getErrorCode( result ) << \") getting input stream configuration info for device (\" << device << \").\";\r\n    errorText_ = errorStream_.str();\r\n    error( RtError::WARNING );\r\n    return info;\r\n  }\r\n\r\n  // Allocate the AudioBufferList.\r\n  bufferList = (AudioBufferList *) malloc( dataSize );\r\n  if ( bufferList == NULL ) {\r\n    errorText_ = \"RtApiCore::getDeviceInfo: memory error allocating input AudioBufferList.\";\r\n    error( RtError::WARNING );\r\n    return info;\r\n  }\r\n\r\n  result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, bufferList );\r\n  if (result != noErr || dataSize == 0) {\r\n    free( bufferList );\r\n    errorStream_ << \"RtApiCore::getDeviceInfo: system error (\" << getErrorCode( result ) << \") getting input stream configuration for device (\" << device << \").\";\r\n    errorText_ = errorStream_.str();\r\n    error( RtError::WARNING );\r\n    return info;\r\n  }\r\n\r\n  // Get input channel information.\r\n  nStreams = bufferList->mNumberBuffers;\r\n  for ( i=0; i<nStreams; i++ )\r\n    info.inputChannels += bufferList->mBuffers[i].mNumberChannels;\r\n  free( bufferList );\r\n\r\n  // If device opens for both playback and capture, we determine the channels.\r\n  if ( info.outputChannels > 0 && info.inputChannels > 0 )\r\n    info.duplexChannels = (info.outputChannels > info.inputChannels) ? info.inputChannels : info.outputChannels;\r\n\r\n  // Probe the device sample rates.\r\n  bool isInput = false;\r\n  if ( info.outputChannels == 0 ) isInput = true;\r\n\r\n  // Determine the supported sample rates.\r\n  property.mSelector = kAudioDevicePropertyAvailableNominalSampleRates;\r\n  if ( isInput == false ) property.mScope = kAudioDevicePropertyScopeOutput;\r\n  result = AudioObjectGetPropertyDataSize( id, &property, 0, NULL, &dataSize );\r\n  if ( result != kAudioHardwareNoError || dataSize == 0 ) {\r\n    errorStream_ << \"RtApiCore::getDeviceInfo: system error (\" << getErrorCode( result ) << \") getting sample rate info.\";\r\n    errorText_ = errorStream_.str();\r\n    error( RtError::WARNING );\r\n    return info;\r\n  }\r\n\r\n  UInt32 nRanges = dataSize / sizeof( AudioValueRange );\r\n  AudioValueRange rangeList[ nRanges ];\r\n  result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, &rangeList );\r\n  if ( result != kAudioHardwareNoError ) {\r\n    errorStream_ << \"RtApiCore::getDeviceInfo: system error (\" << getErrorCode( result ) << \") getting sample rates.\";\r\n    errorText_ = errorStream_.str();\r\n    error( RtError::WARNING );\r\n    return info;\r\n  }\r\n\r\n  Float64 minimumRate = 100000000.0, maximumRate = 0.0;\r\n  for ( UInt32 i=0; i<nRanges; i++ ) {\r\n    if ( rangeList[i].mMinimum < minimumRate ) minimumRate = rangeList[i].mMinimum;\r\n    if ( rangeList[i].mMaximum > maximumRate ) maximumRate = rangeList[i].mMaximum;\r\n  }\r\n\r\n  info.sampleRates.clear();\r\n  for ( unsigned int k=0; k<MAX_SAMPLE_RATES; k++ ) {\r\n    if ( SAMPLE_RATES[k] >= (unsigned int) minimumRate && SAMPLE_RATES[k] <= (unsigned int) maximumRate )\r\n      info.sampleRates.push_back( SAMPLE_RATES[k] );\r\n  }\r\n\r\n  if ( info.sampleRates.size() == 0 ) {\r\n    errorStream_ << \"RtApiCore::probeDeviceInfo: No supported sample rates found for device (\" << device << \").\";\r\n    errorText_ = errorStream_.str();\r\n    error( RtError::WARNING );\r\n    return info;\r\n  }\r\n\r\n  // CoreAudio always uses 32-bit floating point data for PCM streams.\r\n  // Thus, any other \"physical\" formats supported by the device are of\r\n  // no interest to the client.\r\n  info.nativeFormats = RTAUDIO_FLOAT32;\r\n\r\n  if ( info.outputChannels > 0 )\r\n    if ( getDefaultOutputDevice() == device ) info.isDefaultOutput = true;\r\n  if ( info.inputChannels > 0 )\r\n    if ( getDefaultInputDevice() == device ) info.isDefaultInput = true;\r\n\r\n  info.probed = true;\r\n  return info;\r\n}\r\n\r\nstatic OSStatus callbackHandler( AudioDeviceID inDevice,\r\n                                 const AudioTimeStamp* /*inNow*/,\r\n                                 const AudioBufferList* inInputData,\r\n                                 const AudioTimeStamp* /*inInputTime*/,\r\n                                 AudioBufferList* outOutputData,\r\n                                 const AudioTimeStamp* /*inOutputTime*/,\r\n                                 void* infoPointer )\r\n{\r\n  CallbackInfo *info = (CallbackInfo *) infoPointer;\r\n\r\n  RtApiCore *object = (RtApiCore *) info->object;\r\n  if ( object->callbackEvent( inDevice, inInputData, outOutputData ) == false )\r\n    return kAudioHardwareUnspecifiedError;\r\n  else\r\n    return kAudioHardwareNoError;\r\n}\r\n\r\nstatic OSStatus xrunListener( AudioObjectID /*inDevice*/,\r\n                              UInt32 nAddresses,\r\n                              const AudioObjectPropertyAddress properties[],\r\n                              void* handlePointer )\r\n{\r\n  CoreHandle *handle = (CoreHandle *) handlePointer;\r\n  for ( UInt32 i=0; i<nAddresses; i++ ) {\r\n    if ( properties[i].mSelector == kAudioDeviceProcessorOverload ) {\r\n      if ( properties[i].mScope == kAudioDevicePropertyScopeInput )\r\n        handle->xrun[1] = true;\r\n      else\r\n        handle->xrun[0] = true;\r\n    }\r\n  }\r\n\r\n  return kAudioHardwareNoError;\r\n}\r\n\r\nstatic OSStatus rateListener( AudioObjectID inDevice,\r\n                              UInt32 /*nAddresses*/,\r\n                              const AudioObjectPropertyAddress /*properties*/[],\r\n                              void* ratePointer )\r\n{\r\n\r\n  Float64 *rate = (Float64 *) ratePointer;\r\n  UInt32 dataSize = sizeof( Float64 );\r\n  AudioObjectPropertyAddress property = { kAudioDevicePropertyNominalSampleRate,\r\n                                          kAudioObjectPropertyScopeGlobal,\r\n                                          kAudioObjectPropertyElementMaster };\r\n  AudioObjectGetPropertyData( inDevice, &property, 0, NULL, &dataSize, rate );\r\n  return kAudioHardwareNoError;\r\n}\r\n\r\nbool RtApiCore :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels,\r\n                                   unsigned int firstChannel, unsigned int sampleRate,\r\n                                   RtAudioFormat format, unsigned int *bufferSize,\r\n                                   RtAudio::StreamOptions *options )\r\n{\r\n  // Get device ID\r\n  unsigned int nDevices = getDeviceCount();\r\n  if ( nDevices == 0 ) {\r\n    // This should not happen because a check is made before this function is called.\r\n    errorText_ = \"RtApiCore::probeDeviceOpen: no devices found!\";\r\n    return FAILURE;\r\n  }\r\n\r\n  if ( device >= nDevices ) {\r\n    // This should not happen because a check is made before this function is called.\r\n    errorText_ = \"RtApiCore::probeDeviceOpen: device ID is invalid!\";\r\n    return FAILURE;\r\n  }\r\n\r\n  AudioDeviceID deviceList[ nDevices ];\r\n  UInt32 dataSize = sizeof( AudioDeviceID ) * nDevices;\r\n  AudioObjectPropertyAddress property = { kAudioHardwarePropertyDevices,\r\n                                          kAudioObjectPropertyScopeGlobal,\r\n                                          kAudioObjectPropertyElementMaster };\r\n  OSStatus result = AudioObjectGetPropertyData( kAudioObjectSystemObject, &property,\r\n                                                0, NULL, &dataSize, (void *) &deviceList );\r\n  if ( result != noErr ) {\r\n    errorText_ = \"RtApiCore::probeDeviceOpen: OS-X system error getting device IDs.\";\r\n    return FAILURE;\r\n  }\r\n\r\n  AudioDeviceID id = deviceList[ device ];\r\n\r\n  // Setup for stream mode.\r\n  bool isInput = false;\r\n  if ( mode == INPUT ) {\r\n    isInput = true;\r\n    property.mScope = kAudioDevicePropertyScopeInput;\r\n  }\r\n  else\r\n    property.mScope = kAudioDevicePropertyScopeOutput;\r\n\r\n  // Get the stream \"configuration\".\r\n  AudioBufferList\t*bufferList = nil;\r\n  dataSize = 0;\r\n  property.mSelector = kAudioDevicePropertyStreamConfiguration;\r\n  result = AudioObjectGetPropertyDataSize( id, &property, 0, NULL, &dataSize );\r\n  if ( result != noErr || dataSize == 0 ) {\r\n    errorStream_ << \"RtApiCore::probeDeviceOpen: system error (\" << getErrorCode( result ) << \") getting stream configuration info for device (\" << device << \").\";\r\n    errorText_ = errorStream_.str();\r\n    return FAILURE;\r\n  }\r\n\r\n  // Allocate the AudioBufferList.\r\n  bufferList = (AudioBufferList *) malloc( dataSize );\r\n  if ( bufferList == NULL ) {\r\n    errorText_ = \"RtApiCore::probeDeviceOpen: memory error allocating AudioBufferList.\";\r\n    return FAILURE;\r\n  }\r\n\r\n  result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, bufferList );\r\n  if (result != noErr || dataSize == 0) {\r\n    errorStream_ << \"RtApiCore::probeDeviceOpen: system error (\" << getErrorCode( result ) << \") getting stream configuration for device (\" << device << \").\";\r\n    errorText_ = errorStream_.str();\r\n    return FAILURE;\r\n  }\r\n\r\n  // Search for one or more streams that contain the desired number of\r\n  // channels. CoreAudio devices can have an arbitrary number of\r\n  // streams and each stream can have an arbitrary number of channels.\r\n  // For each stream, a single buffer of interleaved samples is\r\n  // provided.  RtAudio prefers the use of one stream of interleaved\r\n  // data or multiple consecutive single-channel streams.  However, we\r\n  // now support multiple consecutive multi-channel streams of\r\n  // interleaved data as well.\r\n  UInt32 iStream, offsetCounter = firstChannel;\r\n  UInt32 nStreams = bufferList->mNumberBuffers;\r\n  bool monoMode = false;\r\n  bool foundStream = false;\r\n\r\n  // First check that the device supports the requested number of\r\n  // channels.\r\n  UInt32 deviceChannels = 0;\r\n  for ( iStream=0; iStream<nStreams; iStream++ )\r\n    deviceChannels += bufferList->mBuffers[iStream].mNumberChannels;\r\n\r\n  if ( deviceChannels < ( channels + firstChannel ) ) {\r\n    free( bufferList );\r\n    errorStream_ << \"RtApiCore::probeDeviceOpen: the device (\" << device << \") does not support the requested channel count.\";\r\n    errorText_ = errorStream_.str();\r\n    return FAILURE;\r\n  }\r\n\r\n  // Look for a single stream meeting our needs.\r\n  UInt32 firstStream, streamCount = 1, streamChannels = 0, channelOffset = 0;\r\n  for ( iStream=0; iStream<nStreams; iStream++ ) {\r\n    streamChannels = bufferList->mBuffers[iStream].mNumberChannels;\r\n    if ( streamChannels >= channels + offsetCounter ) {\r\n      firstStream = iStream;\r\n      channelOffset = offsetCounter;\r\n      foundStream = true;\r\n      break;\r\n    }\r\n    if ( streamChannels > offsetCounter ) break;\r\n    offsetCounter -= streamChannels;\r\n  }\r\n\r\n  // If we didn't find a single stream above, then we should be able\r\n  // to meet the channel specification with multiple streams.\r\n  if ( foundStream == false ) {\r\n    monoMode = true;\r\n    offsetCounter = firstChannel;\r\n    for ( iStream=0; iStream<nStreams; iStream++ ) {\r\n      streamChannels = bufferList->mBuffers[iStream].mNumberChannels;\r\n      if ( streamChannels > offsetCounter ) break;\r\n      offsetCounter -= streamChannels;\r\n    }\r\n\r\n    firstStream = iStream;\r\n    channelOffset = offsetCounter;\r\n    Int32 channelCounter = channels + offsetCounter - streamChannels;\r\n\r\n    if ( streamChannels > 1 ) monoMode = false;\r\n    while ( channelCounter > 0 ) {\r\n      streamChannels = bufferList->mBuffers[++iStream].mNumberChannels;\r\n      if ( streamChannels > 1 ) monoMode = false;\r\n      channelCounter -= streamChannels;\r\n      streamCount++;\r\n    }\r\n  }\r\n\r\n  free( bufferList );\r\n\r\n  // Determine the buffer size.\r\n  AudioValueRange\tbufferRange;\r\n  dataSize = sizeof( AudioValueRange );\r\n  property.mSelector = kAudioDevicePropertyBufferFrameSizeRange;\r\n  result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, &bufferRange );\r\n\r\n  if ( result != noErr ) {\r\n    errorStream_ << \"RtApiCore::probeDeviceOpen: system error (\" << getErrorCode( result ) << \") getting buffer size range for device (\" << device << \").\";\r\n    errorText_ = errorStream_.str();\r\n    return FAILURE;\r\n  }\r\n\r\n  if ( bufferRange.mMinimum > *bufferSize ) *bufferSize = (unsigned long) bufferRange.mMinimum;\r\n  else if ( bufferRange.mMaximum < *bufferSize ) *bufferSize = (unsigned long) bufferRange.mMaximum;\r\n  if ( options && options->flags & RTAUDIO_MINIMIZE_LATENCY ) *bufferSize = (unsigned long) bufferRange.mMinimum;\r\n\r\n  // Set the buffer size.  For multiple streams, I'm assuming we only\r\n  // need to make this setting for the master channel.\r\n  UInt32 theSize = (UInt32) *bufferSize;\r\n  dataSize = sizeof( UInt32 );\r\n  property.mSelector = kAudioDevicePropertyBufferFrameSize;\r\n  result = AudioObjectSetPropertyData( id, &property, 0, NULL, dataSize, &theSize );\r\n\r\n  if ( result != noErr ) {\r\n    errorStream_ << \"RtApiCore::probeDeviceOpen: system error (\" << getErrorCode( result ) << \") setting the buffer size for device (\" << device << \").\";\r\n    errorText_ = errorStream_.str();\r\n    return FAILURE;\r\n  }\r\n\r\n  // If attempting to setup a duplex stream, the bufferSize parameter\r\n  // MUST be the same in both directions!\r\n  *bufferSize = theSize;\r\n  if ( stream_.mode == OUTPUT && mode == INPUT && *bufferSize != stream_.bufferSize ) {\r\n    errorStream_ << \"RtApiCore::probeDeviceOpen: system error setting buffer size for duplex stream on device (\" << device << \").\";\r\n    errorText_ = errorStream_.str();\r\n    return FAILURE;\r\n  }\r\n\r\n  stream_.bufferSize = *bufferSize;\r\n  stream_.nBuffers = 1;\r\n\r\n  // Try to set \"hog\" mode ... it's not clear to me this is working.\r\n  if ( options && options->flags & RTAUDIO_HOG_DEVICE ) {\r\n    pid_t hog_pid;\r\n    dataSize = sizeof( hog_pid );\r\n    property.mSelector = kAudioDevicePropertyHogMode;\r\n    result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, &hog_pid );\r\n    if ( result != noErr ) {\r\n      errorStream_ << \"RtApiCore::probeDeviceOpen: system error (\" << getErrorCode( result ) << \") getting 'hog' state!\";\r\n      errorText_ = errorStream_.str();\r\n      return FAILURE;\r\n    }\r\n\r\n    if ( hog_pid != getpid() ) {\r\n      hog_pid = getpid();\r\n      result = AudioObjectSetPropertyData( id, &property, 0, NULL, dataSize, &hog_pid );\r\n      if ( result != noErr ) {\r\n        errorStream_ << \"RtApiCore::probeDeviceOpen: system error (\" << getErrorCode( result ) << \") setting 'hog' state!\";\r\n        errorText_ = errorStream_.str();\r\n        return FAILURE;\r\n      }\r\n    }\r\n  }\r\n\r\n  // Check and if necessary, change the sample rate for the device.\r\n  Float64 nominalRate;\r\n  dataSize = sizeof( Float64 );\r\n  property.mSelector = kAudioDevicePropertyNominalSampleRate;\r\n  result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, &nominalRate );\r\n\r\n  if ( result != noErr ) {\r\n    errorStream_ << \"RtApiCore::probeDeviceOpen: system error (\" << getErrorCode( result ) << \") getting current sample rate.\";\r\n    errorText_ = errorStream_.str();\r\n    return FAILURE;\r\n  }\r\n\r\n  // Only change the sample rate if off by more than 1 Hz.\r\n  if ( fabs( nominalRate - (double)sampleRate ) > 1.0 ) {\r\n\r\n    // Set a property listener for the sample rate change\r\n    Float64 reportedRate = 0.0;\r\n    AudioObjectPropertyAddress tmp = { kAudioDevicePropertyNominalSampleRate, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };\r\n    result = AudioObjectAddPropertyListener( id, &tmp, rateListener, (void *) &reportedRate );\r\n    if ( result != noErr ) {\r\n      errorStream_ << \"RtApiCore::probeDeviceOpen: system error (\" << getErrorCode( result ) << \") setting sample rate property listener for device (\" << device << \").\";\r\n      errorText_ = errorStream_.str();\r\n      return FAILURE;\r\n    }\r\n\r\n    nominalRate = (Float64) sampleRate;\r\n    result = AudioObjectSetPropertyData( id, &property, 0, NULL, dataSize, &nominalRate );\r\n\r\n    if ( result != noErr ) {\r\n      errorStream_ << \"RtApiCore::probeDeviceOpen: system error (\" << getErrorCode( result ) << \") setting sample rate for device (\" << device << \").\";\r\n      errorText_ = errorStream_.str();\r\n      return FAILURE;\r\n    }\r\n\r\n    // Now wait until the reported nominal rate is what we just set.\r\n    UInt32 microCounter = 0;\r\n    while ( reportedRate != nominalRate ) {\r\n      microCounter += 5000;\r\n      if ( microCounter > 5000000 ) break;\r\n      usleep( 5000 );\r\n    }\r\n\r\n    // Remove the property listener.\r\n    AudioObjectRemovePropertyListener( id, &tmp, rateListener, (void *) &reportedRate );\r\n\r\n    if ( microCounter > 5000000 ) {\r\n      errorStream_ << \"RtApiCore::probeDeviceOpen: timeout waiting for sample rate update for device (\" << device << \").\";\r\n      errorText_ = errorStream_.str();\r\n      return FAILURE;\r\n    }\r\n  }\r\n\r\n  // Now set the stream format for all streams.  Also, check the\r\n  // physical format of the device and change that if necessary.\r\n  AudioStreamBasicDescription\tdescription;\r\n  dataSize = sizeof( AudioStreamBasicDescription );\r\n  property.mSelector = kAudioStreamPropertyVirtualFormat;\r\n  result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, &description );\r\n  if ( result != noErr ) {\r\n    errorStream_ << \"RtApiCore::probeDeviceOpen: system error (\" << getErrorCode( result ) << \") getting stream format for device (\" << device << \").\";\r\n    errorText_ = errorStream_.str();\r\n    return FAILURE;\r\n  }\r\n\r\n  // Set the sample rate and data format id.  However, only make the\r\n  // change if the sample rate is not within 1.0 of the desired\r\n  // rate and the format is not linear pcm.\r\n  bool updateFormat = false;\r\n  if ( fabs( description.mSampleRate - (Float64)sampleRate ) > 1.0 ) {\r\n    description.mSampleRate = (Float64) sampleRate;\r\n    updateFormat = true;\r\n  }\r\n\r\n  if ( description.mFormatID != kAudioFormatLinearPCM ) {\r\n    description.mFormatID = kAudioFormatLinearPCM;\r\n    updateFormat = true;\r\n  }\r\n\r\n  if ( updateFormat ) {\r\n    result = AudioObjectSetPropertyData( id, &property, 0, NULL, dataSize, &description );\r\n    if ( result != noErr ) {\r\n      errorStream_ << \"RtApiCore::probeDeviceOpen: system error (\" << getErrorCode( result ) << \") setting sample rate or data format for device (\" << device << \").\";\r\n      errorText_ = errorStream_.str();\r\n      return FAILURE;\r\n    }\r\n  }\r\n\r\n  // Now check the physical format.\r\n  property.mSelector = kAudioStreamPropertyPhysicalFormat;\r\n  result = AudioObjectGetPropertyData( id, &property, 0, NULL,  &dataSize, &description );\r\n  if ( result != noErr ) {\r\n    errorStream_ << \"RtApiCore::probeDeviceOpen: system error (\" << getErrorCode( result ) << \") getting stream physical format for device (\" << device << \").\";\r\n    errorText_ = errorStream_.str();\r\n    return FAILURE;\r\n  }\r\n\r\n  //std::cout << \"Current physical stream format:\" << std::endl;\r\n  //std::cout << \"   mBitsPerChan = \" << description.mBitsPerChannel << std::endl;\r\n  //std::cout << \"   aligned high = \" << (description.mFormatFlags & kAudioFormatFlagIsAlignedHigh) << \", isPacked = \" << (description.mFormatFlags & kAudioFormatFlagIsPacked) << std::endl;\r\n  //std::cout << \"   bytesPerFrame = \" << description.mBytesPerFrame << std::endl;\r\n  //std::cout << \"   sample rate = \" << description.mSampleRate << std::endl;\r\n\r\n  if ( description.mFormatID != kAudioFormatLinearPCM || description.mBitsPerChannel < 16 ) {\r\n    description.mFormatID = kAudioFormatLinearPCM;\r\n    //description.mSampleRate = (Float64) sampleRate;\r\n    AudioStreamBasicDescription\ttestDescription = description;\r\n    UInt32 formatFlags;\r\n\r\n    // We'll try higher bit rates first and then work our way down.\r\n    std::vector< std::pair<UInt32, UInt32>  > physicalFormats;\r\n    formatFlags = (description.mFormatFlags | kLinearPCMFormatFlagIsFloat) & ~kLinearPCMFormatFlagIsSignedInteger;\r\n    physicalFormats.push_back( std::pair<Float32, UInt32>( 32, formatFlags ) );\r\n    formatFlags = (description.mFormatFlags | kLinearPCMFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked) & ~kLinearPCMFormatFlagIsFloat;\r\n    physicalFormats.push_back( std::pair<Float32, UInt32>( 32, formatFlags ) );\r\n    physicalFormats.push_back( std::pair<Float32, UInt32>( 24, formatFlags ) );   // 24-bit packed\r\n    formatFlags &= ~( kAudioFormatFlagIsPacked | kAudioFormatFlagIsAlignedHigh );\r\n    physicalFormats.push_back( std::pair<Float32, UInt32>( 24.2, formatFlags ) ); // 24-bit in 4 bytes, aligned low\r\n    formatFlags |= kAudioFormatFlagIsAlignedHigh;\r\n    physicalFormats.push_back( std::pair<Float32, UInt32>( 24.4, formatFlags ) ); // 24-bit in 4 bytes, aligned high\r\n    formatFlags = (description.mFormatFlags | kLinearPCMFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked) & ~kLinearPCMFormatFlagIsFloat;\r\n    physicalFormats.push_back( std::pair<Float32, UInt32>( 16, formatFlags ) );\r\n    physicalFormats.push_back( std::pair<Float32, UInt32>( 8, formatFlags ) );\r\n\r\n    bool setPhysicalFormat = false;\r\n    for( unsigned int i=0; i<physicalFormats.size(); i++ ) {\r\n      testDescription = description;\r\n      testDescription.mBitsPerChannel = (UInt32) physicalFormats[i].first;\r\n      testDescription.mFormatFlags = physicalFormats[i].second;\r\n      if ( (24 == (UInt32)physicalFormats[i].first) && ~( physicalFormats[i].second & kAudioFormatFlagIsPacked ) )\r\n        testDescription.mBytesPerFrame =  4 * testDescription.mChannelsPerFrame;\r\n      else\r\n        testDescription.mBytesPerFrame =  testDescription.mBitsPerChannel/8 * testDescription.mChannelsPerFrame;\r\n      testDescription.mBytesPerPacket = testDescription.mBytesPerFrame * testDescription.mFramesPerPacket;\r\n      result = AudioObjectSetPropertyData( id, &property, 0, NULL, dataSize, &testDescription );\r\n      if ( result == noErr ) {\r\n        setPhysicalFormat = true;\r\n        //std::cout << \"Updated physical stream format:\" << std::endl;\r\n        //std::cout << \"   mBitsPerChan = \" << testDescription.mBitsPerChannel << std::endl;\r\n        //std::cout << \"   aligned high = \" << (testDescription.mFormatFlags & kAudioFormatFlagIsAlignedHigh) << \", isPacked = \" << (testDescription.mFormatFlags & kAudioFormatFlagIsPacked) << std::endl;\r\n        //std::cout << \"   bytesPerFrame = \" << testDescription.mBytesPerFrame << std::endl;\r\n        //std::cout << \"   sample rate = \" << testDescription.mSampleRate << std::endl;\r\n        break;\r\n      }\r\n    }\r\n\r\n    if ( !setPhysicalFormat ) {\r\n      errorStream_ << \"RtApiCore::probeDeviceOpen: system error (\" << getErrorCode( result ) << \") setting physical data format for device (\" << device << \").\";\r\n      errorText_ = errorStream_.str();\r\n      return FAILURE;\r\n    }\r\n  } // done setting virtual/physical formats.\r\n\r\n  // Get the stream / device latency.\r\n  UInt32 latency;\r\n  dataSize = sizeof( UInt32 );\r\n  property.mSelector = kAudioDevicePropertyLatency;\r\n  if ( AudioObjectHasProperty( id, &property ) == true ) {\r\n    result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, &latency );\r\n    if ( result == kAudioHardwareNoError ) stream_.latency[ mode ] = latency;\r\n    else {\r\n      errorStream_ << \"RtApiCore::probeDeviceOpen: system error (\" << getErrorCode( result ) << \") getting device latency for device (\" << device << \").\";\r\n      errorText_ = errorStream_.str();\r\n      error( RtError::WARNING );\r\n    }\r\n  }\r\n\r\n  // Byte-swapping: According to AudioHardware.h, the stream data will\r\n  // always be presented in native-endian format, so we should never\r\n  // need to byte swap.\r\n  stream_.doByteSwap[mode] = false;\r\n\r\n  // From the CoreAudio documentation, PCM data must be supplied as\r\n  // 32-bit floats.\r\n  stream_.userFormat = format;\r\n  stream_.deviceFormat[mode] = RTAUDIO_FLOAT32;\r\n\r\n  if ( streamCount == 1 )\r\n    stream_.nDeviceChannels[mode] = description.mChannelsPerFrame;\r\n  else // multiple streams\r\n    stream_.nDeviceChannels[mode] = channels;\r\n  stream_.nUserChannels[mode] = channels;\r\n  stream_.channelOffset[mode] = channelOffset;  // offset within a CoreAudio stream\r\n  if ( options && options->flags & RTAUDIO_NONINTERLEAVED ) stream_.userInterleaved = false;\r\n  else stream_.userInterleaved = true;\r\n  stream_.deviceInterleaved[mode] = true;\r\n  if ( monoMode == true ) stream_.deviceInterleaved[mode] = false;\r\n\r\n  // Set flags for buffer conversion.\r\n  stream_.doConvertBuffer[mode] = false;\r\n  if ( stream_.userFormat != stream_.deviceFormat[mode] )\r\n    stream_.doConvertBuffer[mode] = true;\r\n  if ( stream_.nUserChannels[mode] < stream_.nDeviceChannels[mode] )\r\n    stream_.doConvertBuffer[mode] = true;\r\n  if ( streamCount == 1 ) {\r\n    if ( stream_.nUserChannels[mode] > 1 &&\r\n         stream_.userInterleaved != stream_.deviceInterleaved[mode] )\r\n      stream_.doConvertBuffer[mode] = true;\r\n  }\r\n  else if ( monoMode && stream_.userInterleaved )\r\n    stream_.doConvertBuffer[mode] = true;\r\n\r\n  // Allocate our CoreHandle structure for the stream.\r\n  CoreHandle *handle = 0;\r\n  if ( stream_.apiHandle == 0 ) {\r\n    try {\r\n      handle = new CoreHandle;\r\n    }\r\n    catch ( std::bad_alloc& ) {\r\n      errorText_ = \"RtApiCore::probeDeviceOpen: error allocating CoreHandle memory.\";\r\n      goto error;\r\n    }\r\n\r\n    if ( pthread_cond_init( &handle->condition, NULL ) ) {\r\n      errorText_ = \"RtApiCore::probeDeviceOpen: error initializing pthread condition variable.\";\r\n      goto error;\r\n    }\r\n    stream_.apiHandle = (void *) handle;\r\n  }\r\n  else\r\n    handle = (CoreHandle *) stream_.apiHandle;\r\n  handle->iStream[mode] = firstStream;\r\n  handle->nStreams[mode] = streamCount;\r\n  handle->id[mode] = id;\r\n\r\n  // Allocate necessary internal buffers.\r\n  unsigned long bufferBytes;\r\n  bufferBytes = stream_.nUserChannels[mode] * *bufferSize * formatBytes( stream_.userFormat );\r\n  //  stream_.userBuffer[mode] = (char *) calloc( bufferBytes, 1 );\r\n  stream_.userBuffer[mode] = (char *) malloc( bufferBytes * sizeof(char) );\r\n  memset( stream_.userBuffer[mode], 0, bufferBytes * sizeof(char) );\r\n  if ( stream_.userBuffer[mode] == NULL ) {\r\n    errorText_ = \"RtApiCore::probeDeviceOpen: error allocating user buffer memory.\";\r\n    goto error;\r\n  }\r\n\r\n  // If possible, we will make use of the CoreAudio stream buffers as\r\n  // \"device buffers\".  However, we can't do this if using multiple\r\n  // streams.\r\n  if ( stream_.doConvertBuffer[mode] && handle->nStreams[mode] > 1 ) {\r\n\r\n    bool makeBuffer = true;\r\n    bufferBytes = stream_.nDeviceChannels[mode] * formatBytes( stream_.deviceFormat[mode] );\r\n    if ( mode == INPUT ) {\r\n      if ( stream_.mode == OUTPUT && stream_.deviceBuffer ) {\r\n        unsigned long bytesOut = stream_.nDeviceChannels[0] * formatBytes( stream_.deviceFormat[0] );\r\n        if ( bufferBytes <= bytesOut ) makeBuffer = false;\r\n      }\r\n    }\r\n\r\n    if ( makeBuffer ) {\r\n      bufferBytes *= *bufferSize;\r\n      if ( stream_.deviceBuffer ) free( stream_.deviceBuffer );\r\n      stream_.deviceBuffer = (char *) calloc( bufferBytes, 1 );\r\n      if ( stream_.deviceBuffer == NULL ) {\r\n        errorText_ = \"RtApiCore::probeDeviceOpen: error allocating device buffer memory.\";\r\n        goto error;\r\n      }\r\n    }\r\n  }\r\n\r\n  stream_.sampleRate = sampleRate;\r\n  stream_.device[mode] = device;\r\n  stream_.state = STREAM_STOPPED;\r\n  stream_.callbackInfo.object = (void *) this;\r\n\r\n  // Setup the buffer conversion information structure.\r\n  if ( stream_.doConvertBuffer[mode] ) {\r\n    if ( streamCount > 1 ) setConvertInfo( mode, 0 );\r\n    else setConvertInfo( mode, channelOffset );\r\n  }\r\n\r\n  if ( mode == INPUT && stream_.mode == OUTPUT && stream_.device[0] == device )\r\n    // Only one callback procedure per device.\r\n    stream_.mode = DUPLEX;\r\n  else {\r\n#if defined( MAC_OS_X_VERSION_10_5 ) && ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 )\r\n    result = AudioDeviceCreateIOProcID( id, callbackHandler, (void *) &stream_.callbackInfo, &handle->procId[mode] );\r\n#else\r\n    // deprecated in favor of AudioDeviceCreateIOProcID()\r\n    result = AudioDeviceAddIOProc( id, callbackHandler, (void *) &stream_.callbackInfo );\r\n#endif\r\n    if ( result != noErr ) {\r\n      errorStream_ << \"RtApiCore::probeDeviceOpen: system error setting callback for device (\" << device << \").\";\r\n      errorText_ = errorStream_.str();\r\n      goto error;\r\n    }\r\n    if ( stream_.mode == OUTPUT && mode == INPUT )\r\n      stream_.mode = DUPLEX;\r\n    else\r\n      stream_.mode = mode;\r\n  }\r\n\r\n  // Setup the device property listener for over/underload.\r\n  property.mSelector = kAudioDeviceProcessorOverload;\r\n  result = AudioObjectAddPropertyListener( id, &property, xrunListener, (void *) handle );\r\n\r\n  return SUCCESS;\r\n\r\n error:\r\n  if ( handle ) {\r\n    pthread_cond_destroy( &handle->condition );\r\n    delete handle;\r\n    stream_.apiHandle = 0;\r\n  }\r\n\r\n  for ( int i=0; i<2; i++ ) {\r\n    if ( stream_.userBuffer[i] ) {\r\n      free( stream_.userBuffer[i] );\r\n      stream_.userBuffer[i] = 0;\r\n    }\r\n  }\r\n\r\n  if ( stream_.deviceBuffer ) {\r\n    free( stream_.deviceBuffer );\r\n    stream_.deviceBuffer = 0;\r\n  }\r\n\r\n  stream_.state = STREAM_CLOSED;\r\n  return FAILURE;\r\n}\r\n\r\nvoid RtApiCore :: closeStream( void )\r\n{\r\n  if ( stream_.state == STREAM_CLOSED ) {\r\n    errorText_ = \"RtApiCore::closeStream(): no open stream to close!\";\r\n    error( RtError::WARNING );\r\n    return;\r\n  }\r\n\r\n  CoreHandle *handle = (CoreHandle *) stream_.apiHandle;\r\n  if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) {\r\n    if ( stream_.state == STREAM_RUNNING )\r\n      AudioDeviceStop( handle->id[0], callbackHandler );\r\n#if defined( MAC_OS_X_VERSION_10_5 ) && ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 )\r\n    AudioDeviceDestroyIOProcID( handle->id[0], handle->procId[0] );\r\n#else\r\n    // deprecated in favor of AudioDeviceDestroyIOProcID()\r\n    AudioDeviceRemoveIOProc( handle->id[0], callbackHandler );\r\n#endif\r\n  }\r\n\r\n  if ( stream_.mode == INPUT || ( stream_.mode == DUPLEX && stream_.device[0] != stream_.device[1] ) ) {\r\n    if ( stream_.state == STREAM_RUNNING )\r\n      AudioDeviceStop( handle->id[1], callbackHandler );\r\n#if defined( MAC_OS_X_VERSION_10_5 ) && ( MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 )\r\n    AudioDeviceDestroyIOProcID( handle->id[1], handle->procId[1] );\r\n#else\r\n    // deprecated in favor of AudioDeviceDestroyIOProcID()\r\n    AudioDeviceRemoveIOProc( handle->id[1], callbackHandler );\r\n#endif\r\n  }\r\n\r\n  for ( int i=0; i<2; i++ ) {\r\n    if ( stream_.userBuffer[i] ) {\r\n      free( stream_.userBuffer[i] );\r\n      stream_.userBuffer[i] = 0;\r\n    }\r\n  }\r\n\r\n  if ( stream_.deviceBuffer ) {\r\n    free( stream_.deviceBuffer );\r\n    stream_.deviceBuffer = 0;\r\n  }\r\n\r\n  // Destroy pthread condition variable.\r\n  pthread_cond_destroy( &handle->condition );\r\n  delete handle;\r\n  stream_.apiHandle = 0;\r\n\r\n  stream_.mode = UNINITIALIZED;\r\n  stream_.state = STREAM_CLOSED;\r\n}\r\n\r\nvoid RtApiCore :: startStream( void )\r\n{\r\n  verifyStream();\r\n  if ( stream_.state == STREAM_RUNNING ) {\r\n    errorText_ = \"RtApiCore::startStream(): the stream is already running!\";\r\n    error( RtError::WARNING );\r\n    return;\r\n  }\r\n\r\n  OSStatus result = noErr;\r\n  CoreHandle *handle = (CoreHandle *) stream_.apiHandle;\r\n  if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) {\r\n\r\n    result = AudioDeviceStart( handle->id[0], callbackHandler );\r\n    if ( result != noErr ) {\r\n      errorStream_ << \"RtApiCore::startStream: system error (\" << getErrorCode( result ) << \") starting callback procedure on device (\" << stream_.device[0] << \").\";\r\n      errorText_ = errorStream_.str();\r\n      goto unlock;\r\n    }\r\n  }\r\n\r\n  if ( stream_.mode == INPUT ||\r\n       ( stream_.mode == DUPLEX && stream_.device[0] != stream_.device[1] ) ) {\r\n\r\n    result = AudioDeviceStart( handle->id[1], callbackHandler );\r\n    if ( result != noErr ) {\r\n      errorStream_ << \"RtApiCore::startStream: system error starting input callback procedure on device (\" << stream_.device[1] << \").\";\r\n      errorText_ = errorStream_.str();\r\n      goto unlock;\r\n    }\r\n  }\r\n\r\n  handle->drainCounter = 0;\r\n  handle->internalDrain = false;\r\n  stream_.state = STREAM_RUNNING;\r\n\r\n unlock:\r\n  if ( result == noErr ) return;\r\n  error( RtError::SYSTEM_ERROR );\r\n}\r\n\r\nvoid RtApiCore :: stopStream( void )\r\n{\r\n  verifyStream();\r\n  if ( stream_.state == STREAM_STOPPED ) {\r\n    errorText_ = \"RtApiCore::stopStream(): the stream is already stopped!\";\r\n    error( RtError::WARNING );\r\n    return;\r\n  }\r\n\r\n  OSStatus result = noErr;\r\n  CoreHandle *handle = (CoreHandle *) stream_.apiHandle;\r\n  if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) {\r\n\r\n    if ( handle->drainCounter == 0 ) {\r\n      handle->drainCounter = 2;\r\n      pthread_cond_wait( &handle->condition, &stream_.mutex ); // block until signaled\r\n    }\r\n\r\n    result = AudioDeviceStop( handle->id[0], callbackHandler );\r\n    if ( result != noErr ) {\r\n      errorStream_ << \"RtApiCore::stopStream: system error (\" << getErrorCode( result ) << \") stopping callback procedure on device (\" << stream_.device[0] << \").\";\r\n      errorText_ = errorStream_.str();\r\n      goto unlock;\r\n    }\r\n  }\r\n\r\n  if ( stream_.mode == INPUT || ( stream_.mode == DUPLEX && stream_.device[0] != stream_.device[1] ) ) {\r\n\r\n    result = AudioDeviceStop( handle->id[1], callbackHandler );\r\n    if ( result != noErr ) {\r\n      errorStream_ << \"RtApiCore::stopStream: system error (\" << getErrorCode( result ) << \") stopping input callback procedure on device (\" << stream_.device[1] << \").\";\r\n      errorText_ = errorStream_.str();\r\n      goto unlock;\r\n    }\r\n  }\r\n\r\n  stream_.state = STREAM_STOPPED;\r\n\r\n unlock:\r\n  if ( result == noErr ) return;\r\n  error( RtError::SYSTEM_ERROR );\r\n}\r\n\r\nvoid RtApiCore :: abortStream( void )\r\n{\r\n  verifyStream();\r\n  if ( stream_.state == STREAM_STOPPED ) {\r\n    errorText_ = \"RtApiCore::abortStream(): the stream is already stopped!\";\r\n    error( RtError::WARNING );\r\n    return;\r\n  }\r\n\r\n  CoreHandle *handle = (CoreHandle *) stream_.apiHandle;\r\n  handle->drainCounter = 2;\r\n\r\n  stopStream();\r\n}\r\n\r\n// This function will be called by a spawned thread when the user\r\n// callback function signals that the stream should be stopped or\r\n// aborted.  It is better to handle it this way because the\r\n// callbackEvent() function probably should return before the AudioDeviceStop()\r\n// function is called.\r\nstatic void *coreStopStream( void *ptr )\r\n{\r\n  CallbackInfo *info = (CallbackInfo *) ptr;\r\n  RtApiCore *object = (RtApiCore *) info->object;\r\n\r\n  object->stopStream();\r\n  pthread_exit( NULL );\r\n}\r\n\r\nbool RtApiCore :: callbackEvent( AudioDeviceID deviceId,\r\n                                 const AudioBufferList *inBufferList,\r\n                                 const AudioBufferList *outBufferList )\r\n{\r\n  if ( stream_.state == STREAM_STOPPED || stream_.state == STREAM_STOPPING ) return SUCCESS;\r\n  if ( stream_.state == STREAM_CLOSED ) {\r\n    errorText_ = \"RtApiCore::callbackEvent(): the stream is closed ... this shouldn't happen!\";\r\n    error( RtError::WARNING );\r\n    return FAILURE;\r\n  }\r\n\r\n  CallbackInfo *info = (CallbackInfo *) &stream_.callbackInfo;\r\n  CoreHandle *handle = (CoreHandle *) stream_.apiHandle;\r\n\r\n  // Check if we were draining the stream and signal is finished.\r\n  if ( handle->drainCounter > 3 ) {\r\n    ThreadHandle threadId;\r\n\r\n    stream_.state = STREAM_STOPPING;\r\n    if ( handle->internalDrain == true )\r\n      pthread_create( &threadId, NULL, coreStopStream, info );\r\n    else // external call to stopStream()\r\n      pthread_cond_signal( &handle->condition );\r\n    return SUCCESS;\r\n  }\r\n\r\n  AudioDeviceID outputDevice = handle->id[0];\r\n\r\n  // Invoke user callback to get fresh output data UNLESS we are\r\n  // draining stream or duplex mode AND the input/output devices are\r\n  // different AND this function is called for the input device.\r\n  if ( handle->drainCounter == 0 && ( stream_.mode != DUPLEX || deviceId == outputDevice ) ) {\r\n    RtAudioCallback callback = (RtAudioCallback) info->callback;\r\n    double streamTime = getStreamTime();\r\n    RtAudioStreamStatus status = 0;\r\n    if ( stream_.mode != INPUT && handle->xrun[0] == true ) {\r\n      status |= RTAUDIO_OUTPUT_UNDERFLOW;\r\n      handle->xrun[0] = false;\r\n    }\r\n    if ( stream_.mode != OUTPUT && handle->xrun[1] == true ) {\r\n      status |= RTAUDIO_INPUT_OVERFLOW;\r\n      handle->xrun[1] = false;\r\n    }\r\n\r\n    int cbReturnValue = callback( stream_.userBuffer[0], stream_.userBuffer[1],\r\n                                  stream_.bufferSize, streamTime, status, info->userData );\r\n    if ( cbReturnValue == 2 ) {\r\n      stream_.state = STREAM_STOPPING;\r\n      handle->drainCounter = 2;\r\n      abortStream();\r\n      return SUCCESS;\r\n    }\r\n    else if ( cbReturnValue == 1 ) {\r\n      handle->drainCounter = 1;\r\n      handle->internalDrain = true;\r\n    }\r\n  }\r\n\r\n  if ( stream_.mode == OUTPUT || ( stream_.mode == DUPLEX && deviceId == outputDevice ) ) {\r\n\r\n    if ( handle->drainCounter > 1 ) { // write zeros to the output stream\r\n\r\n      if ( handle->nStreams[0] == 1 ) {\r\n        memset( outBufferList->mBuffers[handle->iStream[0]].mData,\r\n                0,\r\n                outBufferList->mBuffers[handle->iStream[0]].mDataByteSize );\r\n      }\r\n      else { // fill multiple streams with zeros\r\n        for ( unsigned int i=0; i<handle->nStreams[0]; i++ ) {\r\n          memset( outBufferList->mBuffers[handle->iStream[0]+i].mData,\r\n                  0,\r\n                  outBufferList->mBuffers[handle->iStream[0]+i].mDataByteSize );\r\n        }\r\n      }\r\n    }\r\n    else if ( handle->nStreams[0] == 1 ) {\r\n      if ( stream_.doConvertBuffer[0] ) { // convert directly to CoreAudio stream buffer\r\n        convertBuffer( (char *) outBufferList->mBuffers[handle->iStream[0]].mData,\r\n                       stream_.userBuffer[0], stream_.convertInfo[0] );\r\n      }\r\n      else { // copy from user buffer\r\n        memcpy( outBufferList->mBuffers[handle->iStream[0]].mData,\r\n                stream_.userBuffer[0],\r\n                outBufferList->mBuffers[handle->iStream[0]].mDataByteSize );\r\n      }\r\n    }\r\n    else { // fill multiple streams\r\n      Float32 *inBuffer = (Float32 *) stream_.userBuffer[0];\r\n      if ( stream_.doConvertBuffer[0] ) {\r\n        convertBuffer( stream_.deviceBuffer, stream_.userBuffer[0], stream_.convertInfo[0] );\r\n        inBuffer = (Float32 *) stream_.deviceBuffer;\r\n      }\r\n\r\n      if ( stream_.deviceInterleaved[0] == false ) { // mono mode\r\n        UInt32 bufferBytes = outBufferList->mBuffers[handle->iStream[0]].mDataByteSize;\r\n        for ( unsigned int i=0; i<stream_.nUserChannels[0]; i++ ) {\r\n          memcpy( outBufferList->mBuffers[handle->iStream[0]+i].mData,\r\n                  (void *)&inBuffer[i*stream_.bufferSize], bufferBytes );\r\n        }\r\n      }\r\n      else { // fill multiple multi-channel streams with interleaved data\r\n        UInt32 streamChannels, channelsLeft, inJump, outJump, inOffset;\r\n        Float32 *out, *in;\r\n\r\n        bool inInterleaved = ( stream_.userInterleaved ) ? true : false;\r\n        UInt32 inChannels = stream_.nUserChannels[0];\r\n        if ( stream_.doConvertBuffer[0] ) {\r\n          inInterleaved = true; // device buffer will always be interleaved for nStreams > 1 and not mono mode\r\n          inChannels = stream_.nDeviceChannels[0];\r\n        }\r\n\r\n        if ( inInterleaved ) inOffset = 1;\r\n        else inOffset = stream_.bufferSize;\r\n\r\n        channelsLeft = inChannels;\r\n        for ( unsigned int i=0; i<handle->nStreams[0]; i++ ) {\r\n          in = inBuffer;\r\n          out = (Float32 *) outBufferList->mBuffers[handle->iStream[0]+i].mData;\r\n          streamChannels = outBufferList->mBuffers[handle->iStream[0]+i].mNumberChannels;\r\n\r\n          outJump = 0;\r\n          // Account for possible channel offset in first stream\r\n          if ( i == 0 && stream_.channelOffset[0] > 0 ) {\r\n            streamChannels -= stream_.channelOffset[0];\r\n            outJump = stream_.channelOffset[0];\r\n            out += outJump;\r\n          }\r\n\r\n          // Account for possible unfilled channels at end of the last stream\r\n          if ( streamChannels > channelsLeft ) {\r\n            outJump = streamChannels - channelsLeft;\r\n            streamChannels = channelsLeft;\r\n          }\r\n\r\n          // Determine input buffer offsets and skips\r\n          if ( inInterleaved ) {\r\n            inJump = inChannels;\r\n            in += inChannels - channelsLeft;\r\n          }\r\n          else {\r\n            inJump = 1;\r\n            in += (inChannels - channelsLeft) * inOffset;\r\n          }\r\n\r\n          for ( unsigned int i=0; i<stream_.bufferSize; i++ ) {\r\n            for ( unsigned int j=0; j<streamChannels; j++ ) {\r\n              *out++ = in[j*inOffset];\r\n            }\r\n            out += outJump;\r\n            in += inJump;\r\n          }\r\n          channelsLeft -= streamChannels;\r\n        }\r\n      }\r\n    }\r\n\r\n    if ( handle->drainCounter ) {\r\n      handle->drainCounter++;\r\n      goto unlock;\r\n    }\r\n  }\r\n\r\n  AudioDeviceID inputDevice;\r\n  inputDevice = handle->id[1];\r\n  if ( stream_.mode == INPUT || ( stream_.mode == DUPLEX && deviceId == inputDevice ) ) {\r\n\r\n    if ( handle->nStreams[1] == 1 ) {\r\n      if ( stream_.doConvertBuffer[1] ) { // convert directly from CoreAudio stream buffer\r\n        convertBuffer( stream_.userBuffer[1],\r\n                       (char *) inBufferList->mBuffers[handle->iStream[1]].mData,\r\n                       stream_.convertInfo[1] );\r\n      }\r\n      else { // copy to user buffer\r\n        memcpy( stream_.userBuffer[1],\r\n                inBufferList->mBuffers[handle->iStream[1]].mData,\r\n                inBufferList->mBuffers[handle->iStream[1]].mDataByteSize );\r\n      }\r\n    }\r\n    else { // read from multiple streams\r\n      Float32 *outBuffer = (Float32 *) stream_.userBuffer[1];\r\n      if ( stream_.doConvertBuffer[1] ) outBuffer = (Float32 *) stream_.deviceBuffer;\r\n\r\n      if ( stream_.deviceInterleaved[1] == false ) { // mono mode\r\n        UInt32 bufferBytes = inBufferList->mBuffers[handle->iStream[1]].mDataByteSize;\r\n        for ( unsigned int i=0; i<stream_.nUserChannels[1]; i++ ) {\r\n          memcpy( (void *)&outBuffer[i*stream_.bufferSize],\r\n                  inBufferList->mBuffers[handle->iStream[1]+i].mData, bufferBytes );\r\n        }\r\n      }\r\n      else { // read from multiple multi-channel streams\r\n        UInt32 streamChannels, channelsLeft, inJump, outJump, outOffset;\r\n        Float32 *out, *in;\r\n\r\n        bool outInterleaved = ( stream_.userInterleaved ) ? true : false;\r\n        UInt32 outChannels = stream_.nUserChannels[1];\r\n        if ( stream_.doConvertBuffer[1] ) {\r\n          outInterleaved = true; // device buffer will always be interleaved for nStreams > 1 and not mono mode\r\n          outChannels = stream_.nDeviceChannels[1];\r\n        }\r\n\r\n        if ( outInterleaved ) outOffset = 1;\r\n        else outOffset = stream_.bufferSize;\r\n\r\n        channelsLeft = outChannels;\r\n        for ( unsigned int i=0; i<handle->nStreams[1]; i++ ) {\r\n          out = outBuffer;\r\n          in = (Float32 *) inBufferList->mBuffers[handle->iStream[1]+i].mData;\r\n          streamChannels = inBufferList->mBuffers[handle->iStream[1]+i].mNumberChannels;\r\n\r\n          inJump = 0;\r\n          // Account for possible channel offset in first stream\r\n          if ( i == 0 && stream_.channelOffset[1] > 0 ) {\r\n            streamChannels -= stream_.channelOffset[1];\r\n            inJump = stream_.channelOffset[1];\r\n            in += inJump;\r\n          }\r\n\r\n          // Account for possible unread channels at end of the last stream\r\n          if ( streamChannels > channelsLeft ) {\r\n            inJump = streamChannels - channelsLeft;\r\n            streamChannels = channelsLeft;\r\n          }\r\n\r\n          // Determine output buffer offsets and skips\r\n          if ( outInterleaved ) {\r\n            outJump = outChannels;\r\n            out += outChannels - channelsLeft;\r\n          }\r\n          else {\r\n            outJump = 1;\r\n            out += (outChannels - channelsLeft) * outOffset;\r\n          }\r\n\r\n          for ( unsigned int i=0; i<stream_.bufferSize; i++ ) {\r\n            for ( unsigned int j=0; j<streamChannels; j++ ) {\r\n              out[j*outOffset] = *in++;\r\n            }\r\n            out += outJump;\r\n            in += inJump;\r\n          }\r\n          channelsLeft -= streamChannels;\r\n        }\r\n      }\r\n      \r\n      if ( stream_.doConvertBuffer[1] ) { // convert from our internal \"device\" buffer\r\n        convertBuffer( stream_.userBuffer[1],\r\n                       stream_.deviceBuffer,\r\n                       stream_.convertInfo[1] );\r\n      }\r\n    }\r\n  }\r\n\r\n unlock:\r\n  //MUTEX_UNLOCK( &stream_.mutex );\r\n\r\n  RtApi::tickStreamTime();\r\n  return SUCCESS;\r\n}\r\n\r\nconst char* RtApiCore :: getErrorCode( OSStatus code )\r\n{\r\n  switch( code ) {\r\n\r\n  case kAudioHardwareNotRunningError:\r\n    return \"kAudioHardwareNotRunningError\";\r\n\r\n  case kAudioHardwareUnspecifiedError:\r\n    return \"kAudioHardwareUnspecifiedError\";\r\n\r\n  case kAudioHardwareUnknownPropertyError:\r\n    return \"kAudioHardwareUnknownPropertyError\";\r\n\r\n  case kAudioHardwareBadPropertySizeError:\r\n    return \"kAudioHardwareBadPropertySizeError\";\r\n\r\n  case kAudioHardwareIllegalOperationError:\r\n    return \"kAudioHardwareIllegalOperationError\";\r\n\r\n  case kAudioHardwareBadObjectError:\r\n    return \"kAudioHardwareBadObjectError\";\r\n\r\n  case kAudioHardwareBadDeviceError:\r\n    return \"kAudioHardwareBadDeviceError\";\r\n\r\n  case kAudioHardwareBadStreamError:\r\n    return \"kAudioHardwareBadStreamError\";\r\n\r\n  case kAudioHardwareUnsupportedOperationError:\r\n    return \"kAudioHardwareUnsupportedOperationError\";\r\n\r\n  case kAudioDeviceUnsupportedFormatError:\r\n    return \"kAudioDeviceUnsupportedFormatError\";\r\n\r\n  case kAudioDevicePermissionsError:\r\n    return \"kAudioDevicePermissionsError\";\r\n\r\n  default:\r\n    return \"CoreAudio unknown error\";\r\n  }\r\n}\r\n\r\n  //******************** End of __MACOSX_CORE__ *********************//\r\n#endif\r\n\r\n#if defined(__UNIX_JACK__)\r\n\r\n// JACK is a low-latency audio server, originally written for the\r\n// GNU/Linux operating system and now also ported to OS-X. It can\r\n// connect a number of different applications to an audio device, as\r\n// well as allowing them to share audio between themselves.\r\n//\r\n// When using JACK with RtAudio, \"devices\" refer to JACK clients that\r\n// have ports connected to the server.  The JACK server is typically\r\n// started in a terminal as follows:\r\n//\r\n// .jackd -d alsa -d hw:0\r\n//\r\n// or through an interface program such as qjackctl.  Many of the\r\n// parameters normally set for a stream are fixed by the JACK server\r\n// and can be specified when the JACK server is started.  In\r\n// particular,\r\n//\r\n// .jackd -d alsa -d hw:0 -r 44100 -p 512 -n 4\r\n//\r\n// specifies a sample rate of 44100 Hz, a buffer size of 512 sample\r\n// frames, and number of buffers = 4.  Once the server is running, it\r\n// is not possible to override these values.  If the values are not\r\n// specified in the command-line, the JACK server uses default values.\r\n//\r\n// The JACK server does not have to be running when an instance of\r\n// RtApiJack is created, though the function getDeviceCount() will\r\n// report 0 devices found until JACK has been started.  When no\r\n// devices are available (i.e., the JACK server is not running), a\r\n// stream cannot be opened.\r\n\r\n#include <jack/jack.h>\r\n#include <unistd.h>\r\n#include <cstdio>\r\n\r\n// A structure to hold various information related to the Jack API\r\n// implementation.\r\nstruct JackHandle {\r\n  jack_client_t *client;\r\n  jack_port_t **ports[2];\r\n  std::string deviceName[2];\r\n  bool xrun[2];\r\n  pthread_cond_t condition;\r\n  int drainCounter;       // Tracks callback counts when draining\r\n  bool internalDrain;     // Indicates if stop is initiated from callback or not.\r\n\r\n  JackHandle()\r\n    :client(0), drainCounter(0), internalDrain(false) { ports[0] = 0; ports[1] = 0; xrun[0] = false; xrun[1] = false; }\r\n};\r\n\r\nstatic void jackSilentError( const char * ) {};\r\n\r\nRtApiJack :: RtApiJack()\r\n{\r\n  // Nothing to do here.\r\n#if !defined(__RTAUDIO_DEBUG__)\r\n  // Turn off Jack's internal error reporting.\r\n  jack_set_error_function( &jackSilentError );\r\n#endif\r\n}\r\n\r\nRtApiJack :: ~RtApiJack()\r\n{\r\n  if ( stream_.state != STREAM_CLOSED ) closeStream();\r\n}\r\n\r\nunsigned int RtApiJack :: getDeviceCount( void )\r\n{\r\n  // See if we can become a jack client.\r\n  jack_options_t options = (jack_options_t) ( JackNoStartServer ); //JackNullOption;\r\n  jack_status_t *status = NULL;\r\n  jack_client_t *client = jack_client_open( \"RtApiJackCount\", options, status );\r\n  if ( client == 0 ) return 0;\r\n\r\n  const char **ports;\r\n  std::string port, previousPort;\r\n  unsigned int nChannels = 0, nDevices = 0;\r\n  ports = jack_get_ports( client, NULL, NULL, 0 );\r\n  if ( ports ) {\r\n    // Parse the port names up to the first colon (:).\r\n    size_t iColon = 0;\r\n    do {\r\n      port = (char *) ports[ nChannels ];\r\n      iColon = port.find(\":\");\r\n      if ( iColon != std::string::npos ) {\r\n        port = port.substr( 0, iColon + 1 );\r\n        if ( port != previousPort ) {\r\n          nDevices++;\r\n          previousPort = port;\r\n        }\r\n      }\r\n    } while ( ports[++nChannels] );\r\n    free( ports );\r\n  }\r\n\r\n  jack_client_close( client );\r\n  return nDevices;\r\n}\r\n\r\nRtAudio::DeviceInfo RtApiJack :: getDeviceInfo( unsigned int device )\r\n{\r\n  RtAudio::DeviceInfo info;\r\n  info.probed = false;\r\n\r\n  jack_options_t options = (jack_options_t) ( JackNoStartServer ); //JackNullOption\r\n  jack_status_t *status = NULL;\r\n  jack_client_t *client = jack_client_open( \"RtApiJackInfo\", options, status );\r\n  if ( client == 0 ) {\r\n    errorText_ = \"RtApiJack::getDeviceInfo: Jack server not found or connection error!\";\r\n    error( RtError::WARNING );\r\n    return info;\r\n  }\r\n\r\n  const char **ports;\r\n  std::string port, previousPort;\r\n  unsigned int nPorts = 0, nDevices = 0;\r\n  ports = jack_get_ports( client, NULL, NULL, 0 );\r\n  if ( ports ) {\r\n    // Parse the port names up to the first colon (:).\r\n    size_t iColon = 0;\r\n    do {\r\n      port = (char *) ports[ nPorts ];\r\n      iColon = port.find(\":\");\r\n      if ( iColon != std::string::npos ) {\r\n        port = port.substr( 0, iColon );\r\n        if ( port != previousPort ) {\r\n          if ( nDevices == device ) info.name = port;\r\n          nDevices++;\r\n          previousPort = port;\r\n        }\r\n      }\r\n    } while ( ports[++nPorts] );\r\n    free( ports );\r\n  }\r\n\r\n  if ( device >= nDevices ) {\r\n    jack_client_close( client );\r\n    errorText_ = \"RtApiJack::getDeviceInfo: device ID is invalid!\";\r\n    error( RtError::INVALID_USE );\r\n    return info;\r\n  }\r\n\r\n  // Get the current jack server sample rate.\r\n  info.sampleRates.clear();\r\n  info.sampleRates.push_back( jack_get_sample_rate( client ) );\r\n\r\n  // Count the available ports containing the client name as device\r\n  // channels.  Jack \"input ports\" equal RtAudio output channels.\r\n  unsigned int nChannels = 0;\r\n  ports = jack_get_ports( client, info.name.c_str(), NULL, JackPortIsInput );\r\n  if ( ports ) {\r\n    while ( ports[ nChannels ] ) nChannels++;\r\n    free( ports );\r\n    info.outputChannels = nChannels;\r\n  }\r\n\r\n  // Jack \"output ports\" equal RtAudio input channels.\r\n  nChannels = 0;\r\n  ports = jack_get_ports( client, info.name.c_str(), NULL, JackPortIsOutput );\r\n  if ( ports ) {\r\n    while ( ports[ nChannels ] ) nChannels++;\r\n    free( ports );\r\n    info.inputChannels = nChannels;\r\n  }\r\n\r\n  if ( info.outputChannels == 0 && info.inputChannels == 0 ) {\r\n    jack_client_close(client);\r\n    errorText_ = \"RtApiJack::getDeviceInfo: error determining Jack input/output channels!\";\r\n    error( RtError::WARNING );\r\n    return info;\r\n  }\r\n\r\n  // If device opens for both playback and capture, we determine the channels.\r\n  if ( info.outputChannels > 0 && info.inputChannels > 0 )\r\n    info.duplexChannels = (info.outputChannels > info.inputChannels) ? info.inputChannels : info.outputChannels;\r\n\r\n  // Jack always uses 32-bit floats.\r\n  info.nativeFormats = RTAUDIO_FLOAT32;\r\n\r\n  // Jack doesn't provide default devices so we'll use the first available one.\r\n  if ( device == 0 && info.outputChannels > 0 )\r\n    info.isDefaultOutput = true;\r\n  if ( device == 0 && info.inputChannels > 0 )\r\n    info.isDefaultInput = true;\r\n\r\n  jack_client_close(client);\r\n  info.probed = true;\r\n  return info;\r\n}\r\n\r\nstatic int jackCallbackHandler( jack_nframes_t nframes, void *infoPointer )\r\n{\r\n  CallbackInfo *info = (CallbackInfo *) infoPointer;\r\n\r\n  RtApiJack *object = (RtApiJack *) info->object;\r\n  if ( object->callbackEvent( (unsigned long) nframes ) == false ) return 1;\r\n\r\n  return 0;\r\n}\r\n\r\n// This function will be called by a spawned thread when the Jack\r\n// server signals that it is shutting down.  It is necessary to handle\r\n// it this way because the jackShutdown() function must return before\r\n// the jack_deactivate() function (in closeStream()) will return.\r\nstatic void *jackCloseStream( void *ptr )\r\n{\r\n  CallbackInfo *info = (CallbackInfo *) ptr;\r\n  RtApiJack *object = (RtApiJack *) info->object;\r\n\r\n  object->closeStream();\r\n\r\n  pthread_exit( NULL );\r\n}\r\nstatic void jackShutdown( void *infoPointer )\r\n{\r\n  CallbackInfo *info = (CallbackInfo *) infoPointer;\r\n  RtApiJack *object = (RtApiJack *) info->object;\r\n\r\n  // Check current stream state.  If stopped, then we'll assume this\r\n  // was called as a result of a call to RtApiJack::stopStream (the\r\n  // deactivation of a client handle causes this function to be called).\r\n  // If not, we'll assume the Jack server is shutting down or some\r\n  // other problem occurred and we should close the stream.\r\n  if ( object->isStreamRunning() == false ) return;\r\n\r\n  ThreadHandle threadId;\r\n  pthread_create( &threadId, NULL, jackCloseStream, info );\r\n  std::cerr << \"\\nRtApiJack: the Jack server is shutting down this client ... stream stopped and closed!!\\n\" << std::endl;\r\n}\r\n\r\nstatic int jackXrun( void *infoPointer )\r\n{\r\n  JackHandle *handle = (JackHandle *) infoPointer;\r\n\r\n  if ( handle->ports[0] ) handle->xrun[0] = true;\r\n  if ( handle->ports[1] ) handle->xrun[1] = true;\r\n\r\n  return 0;\r\n}\r\n\r\nbool RtApiJack :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels,\r\n                                   unsigned int firstChannel, unsigned int sampleRate,\r\n                                   RtAudioFormat format, unsigned int *bufferSize,\r\n                                   RtAudio::StreamOptions *options )\r\n{\r\n  JackHandle *handle = (JackHandle *) stream_.apiHandle;\r\n\r\n  // Look for jack server and try to become a client (only do once per stream).\r\n  jack_client_t *client = 0;\r\n  if ( mode == OUTPUT || ( mode == INPUT && stream_.mode != OUTPUT ) ) {\r\n    jack_options_t jackoptions = (jack_options_t) ( JackNoStartServer ); //JackNullOption;\r\n    jack_status_t *status = NULL;\r\n    if ( options && !options->streamName.empty() )\r\n      client = jack_client_open( options->streamName.c_str(), jackoptions, status );\r\n    else\r\n      client = jack_client_open( \"RtApiJack\", jackoptions, status );\r\n    if ( client == 0 ) {\r\n      errorText_ = \"RtApiJack::probeDeviceOpen: Jack server not found or connection error!\";\r\n      error( RtError::WARNING );\r\n      return FAILURE;\r\n    }\r\n  }\r\n  else {\r\n    // The handle must have been created on an earlier pass.\r\n    client = handle->client;\r\n  }\r\n\r\n  const char **ports;\r\n  std::string port, previousPort, deviceName;\r\n  unsigned int nPorts = 0, nDevices = 0;\r\n  ports = jack_get_ports( client, NULL, NULL, 0 );\r\n  if ( ports ) {\r\n    // Parse the port names up to the first colon (:).\r\n    size_t iColon = 0;\r\n    do {\r\n      port = (char *) ports[ nPorts ];\r\n      iColon = port.find(\":\");\r\n      if ( iColon != std::string::npos ) {\r\n        port = port.substr( 0, iColon );\r\n        if ( port != previousPort ) {\r\n          if ( nDevices == device ) deviceName = port;\r\n          nDevices++;\r\n          previousPort = port;\r\n        }\r\n      }\r\n    } while ( ports[++nPorts] );\r\n    free( ports );\r\n  }\r\n\r\n  if ( device >= nDevices ) {\r\n    errorText_ = \"RtApiJack::probeDeviceOpen: device ID is invalid!\";\r\n    return FAILURE;\r\n  }\r\n\r\n  // Count the available ports containing the client name as device\r\n  // channels.  Jack \"input ports\" equal RtAudio output channels.\r\n  unsigned int nChannels = 0;\r\n  unsigned long flag = JackPortIsInput;\r\n  if ( mode == INPUT ) flag = JackPortIsOutput;\r\n  ports = jack_get_ports( client, deviceName.c_str(), NULL, flag );\r\n  if ( ports ) {\r\n    while ( ports[ nChannels ] ) nChannels++;\r\n    free( ports );\r\n  }\r\n\r\n  // Compare the jack ports for specified client to the requested number of channels.\r\n  if ( nChannels < (channels + firstChannel) ) {\r\n    errorStream_ << \"RtApiJack::probeDeviceOpen: requested number of channels (\" << channels << \") + offset (\" << firstChannel << \") not found for specified device (\" << device << \":\" << deviceName << \").\";\r\n    errorText_ = errorStream_.str();\r\n    return FAILURE;\r\n  }\r\n\r\n  // Check the jack server sample rate.\r\n  unsigned int jackRate = jack_get_sample_rate( client );\r\n  if ( sampleRate != jackRate ) {\r\n    jack_client_close( client );\r\n    errorStream_ << \"RtApiJack::probeDeviceOpen: the requested sample rate (\" << sampleRate << \") is different than the JACK server rate (\" << jackRate << \").\";\r\n    errorText_ = errorStream_.str();\r\n    return FAILURE;\r\n  }\r\n  stream_.sampleRate = jackRate;\r\n\r\n  // Get the latency of the JACK port.\r\n  ports = jack_get_ports( client, deviceName.c_str(), NULL, flag );\r\n  if ( ports[ firstChannel ] ) {\r\n    // Added by Ge Wang\r\n    jack_latency_callback_mode_t cbmode = (mode == INPUT ? JackCaptureLatency : JackPlaybackLatency);\r\n    // the range (usually the min and max are equal)\r\n    jack_latency_range_t latrange; latrange.min = latrange.max = 0;\r\n    // get the latency range\r\n    jack_port_get_latency_range( jack_port_by_name( client, ports[firstChannel] ), cbmode, &latrange );\r\n    // be optimistic, use the min!\r\n    stream_.latency[mode] = latrange.min;\r\n    //stream_.latency[mode] = jack_port_get_latency( jack_port_by_name( client, ports[ firstChannel ] ) );\r\n  }\r\n  free( ports );\r\n\r\n  // The jack server always uses 32-bit floating-point data.\r\n  stream_.deviceFormat[mode] = RTAUDIO_FLOAT32;\r\n  stream_.userFormat = format;\r\n\r\n  if ( options && options->flags & RTAUDIO_NONINTERLEAVED ) stream_.userInterleaved = false;\r\n  else stream_.userInterleaved = true;\r\n\r\n  // Jack always uses non-interleaved buffers.\r\n  stream_.deviceInterleaved[mode] = false;\r\n\r\n  // Jack always provides host byte-ordered data.\r\n  stream_.doByteSwap[mode] = false;\r\n\r\n  // Get the buffer size.  The buffer size and number of buffers\r\n  // (periods) is set when the jack server is started.\r\n  stream_.bufferSize = (int) jack_get_buffer_size( client );\r\n  *bufferSize = stream_.bufferSize;\r\n\r\n  stream_.nDeviceChannels[mode] = channels;\r\n  stream_.nUserChannels[mode] = channels;\r\n\r\n  // Set flags for buffer conversion.\r\n  stream_.doConvertBuffer[mode] = false;\r\n  if ( stream_.userFormat != stream_.deviceFormat[mode] )\r\n    stream_.doConvertBuffer[mode] = true;\r\n  if ( stream_.userInterleaved != stream_.deviceInterleaved[mode] &&\r\n       stream_.nUserChannels[mode] > 1 )\r\n    stream_.doConvertBuffer[mode] = true;\r\n\r\n  // Allocate our JackHandle structure for the stream.\r\n  if ( handle == 0 ) {\r\n    try {\r\n      handle = new JackHandle;\r\n    }\r\n    catch ( std::bad_alloc& ) {\r\n      errorText_ = \"RtApiJack::probeDeviceOpen: error allocating JackHandle memory.\";\r\n      goto error;\r\n    }\r\n\r\n    if ( pthread_cond_init(&handle->condition, NULL) ) {\r\n      errorText_ = \"RtApiJack::probeDeviceOpen: error initializing pthread condition variable.\";\r\n      goto error;\r\n    }\r\n    stream_.apiHandle = (void *) handle;\r\n    handle->client = client;\r\n  }\r\n  handle->deviceName[mode] = deviceName;\r\n\r\n  // Allocate necessary internal buffers.\r\n  unsigned long bufferBytes;\r\n  bufferBytes = stream_.nUserChannels[mode] * *bufferSize * formatBytes( stream_.userFormat );\r\n  stream_.userBuffer[mode] = (char *) calloc( bufferBytes, 1 );\r\n  if ( stream_.userBuffer[mode] == NULL ) {\r\n    errorText_ = \"RtApiJack::probeDeviceOpen: error allocating user buffer memory.\";\r\n    goto error;\r\n  }\r\n\r\n  if ( stream_.doConvertBuffer[mode] ) {\r\n\r\n    bool makeBuffer = true;\r\n    if ( mode == OUTPUT )\r\n      bufferBytes = stream_.nDeviceChannels[0] * formatBytes( stream_.deviceFormat[0] );\r\n    else { // mode == INPUT\r\n      bufferBytes = stream_.nDeviceChannels[1] * formatBytes( stream_.deviceFormat[1] );\r\n      if ( stream_.mode == OUTPUT && stream_.deviceBuffer ) {\r\n        unsigned long bytesOut = stream_.nDeviceChannels[0] * formatBytes(stream_.deviceFormat[0]);\r\n        if ( bufferBytes < bytesOut ) makeBuffer = false;\r\n      }\r\n    }\r\n\r\n    if ( makeBuffer ) {\r\n      bufferBytes *= *bufferSize;\r\n      if ( stream_.deviceBuffer ) free( stream_.deviceBuffer );\r\n      stream_.deviceBuffer = (char *) calloc( bufferBytes, 1 );\r\n      if ( stream_.deviceBuffer == NULL ) {\r\n        errorText_ = \"RtApiJack::probeDeviceOpen: error allocating device buffer memory.\";\r\n        goto error;\r\n      }\r\n    }\r\n  }\r\n\r\n  // Allocate memory for the Jack ports (channels) identifiers.\r\n  handle->ports[mode] = (jack_port_t **) malloc ( sizeof (jack_port_t *) * channels );\r\n  if ( handle->ports[mode] == NULL )  {\r\n    errorText_ = \"RtApiJack::probeDeviceOpen: error allocating port memory.\";\r\n    goto error;\r\n  }\r\n\r\n  stream_.device[mode] = device;\r\n  stream_.channelOffset[mode] = firstChannel;\r\n  stream_.state = STREAM_STOPPED;\r\n  stream_.callbackInfo.object = (void *) this;\r\n\r\n  if ( stream_.mode == OUTPUT && mode == INPUT )\r\n    // We had already set up the stream for output.\r\n    stream_.mode = DUPLEX;\r\n  else {\r\n    stream_.mode = mode;\r\n    jack_set_process_callback( handle->client, jackCallbackHandler, (void *) &stream_.callbackInfo );\r\n    jack_set_xrun_callback( handle->client, jackXrun, (void *) &handle );\r\n    jack_on_shutdown( handle->client, jackShutdown, (void *) &stream_.callbackInfo );\r\n  }\r\n\r\n  // Register our ports.\r\n  char label[64];\r\n  if ( mode == OUTPUT ) {\r\n    for ( unsigned int i=0; i<stream_.nUserChannels[0]; i++ ) {\r\n      snprintf( label, 64, \"outport %d\", i );\r\n      handle->ports[0][i] = jack_port_register( handle->client, (const char *)label,\r\n                                                JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0 );\r\n    }\r\n  }\r\n  else {\r\n    for ( unsigned int i=0; i<stream_.nUserChannels[1]; i++ ) {\r\n      snprintf( label, 64, \"inport %d\", i );\r\n      handle->ports[1][i] = jack_port_register( handle->client, (const char *)label,\r\n                                                JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0 );\r\n    }\r\n  }\r\n\r\n  // Setup the buffer conversion information structure.  We don't use\r\n  // buffers to do channel offsets, so we override that parameter\r\n  // here.\r\n  if ( stream_.doConvertBuffer[mode] ) setConvertInfo( mode, 0 );\r\n\r\n  return SUCCESS;\r\n\r\n error:\r\n  if ( handle ) {\r\n    pthread_cond_destroy( &handle->condition );\r\n    jack_client_close( handle->client );\r\n\r\n    if ( handle->ports[0] ) free( handle->ports[0] );\r\n    if ( handle->ports[1] ) free( handle->ports[1] );\r\n\r\n    delete handle;\r\n    stream_.apiHandle = 0;\r\n  }\r\n\r\n  for ( int i=0; i<2; i++ ) {\r\n    if ( stream_.userBuffer[i] ) {\r\n      free( stream_.userBuffer[i] );\r\n      stream_.userBuffer[i] = 0;\r\n    }\r\n  }\r\n\r\n  if ( stream_.deviceBuffer ) {\r\n    free( stream_.deviceBuffer );\r\n    stream_.deviceBuffer = 0;\r\n  }\r\n\r\n  return FAILURE;\r\n}\r\n\r\nvoid RtApiJack :: closeStream( void )\r\n{\r\n  if ( stream_.state == STREAM_CLOSED ) {\r\n    errorText_ = \"RtApiJack::closeStream(): no open stream to close!\";\r\n    error( RtError::WARNING );\r\n    return;\r\n  }\r\n\r\n  JackHandle *handle = (JackHandle *) stream_.apiHandle;\r\n  if ( handle ) {\r\n\r\n    if ( stream_.state == STREAM_RUNNING )\r\n      jack_deactivate( handle->client );\r\n\r\n    jack_client_close( handle->client );\r\n  }\r\n\r\n  if ( handle ) {\r\n    if ( handle->ports[0] ) free( handle->ports[0] );\r\n    if ( handle->ports[1] ) free( handle->ports[1] );\r\n    pthread_cond_destroy( &handle->condition );\r\n    delete handle;\r\n    stream_.apiHandle = 0;\r\n  }\r\n\r\n  for ( int i=0; i<2; i++ ) {\r\n    if ( stream_.userBuffer[i] ) {\r\n      free( stream_.userBuffer[i] );\r\n      stream_.userBuffer[i] = 0;\r\n    }\r\n  }\r\n\r\n  if ( stream_.deviceBuffer ) {\r\n    free( stream_.deviceBuffer );\r\n    stream_.deviceBuffer = 0;\r\n  }\r\n\r\n  stream_.mode = UNINITIALIZED;\r\n  stream_.state = STREAM_CLOSED;\r\n}\r\n\r\nvoid RtApiJack :: startStream( void )\r\n{\r\n  verifyStream();\r\n  if ( stream_.state == STREAM_RUNNING ) {\r\n    errorText_ = \"RtApiJack::startStream(): the stream is already running!\";\r\n    error( RtError::WARNING );\r\n    return;\r\n  }\r\n\r\n  JackHandle *handle = (JackHandle *) stream_.apiHandle;\r\n  int result = jack_activate( handle->client );\r\n  if ( result ) {\r\n    errorText_ = \"RtApiJack::startStream(): unable to activate JACK client!\";\r\n    goto unlock;\r\n  }\r\n\r\n  const char **ports;\r\n\r\n  // Get the list of available ports.\r\n  if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) {\r\n    result = 1;\r\n    ports = jack_get_ports( handle->client, handle->deviceName[0].c_str(), NULL, JackPortIsInput);\r\n    if ( ports == NULL) {\r\n      errorText_ = \"RtApiJack::startStream(): error determining available JACK input ports!\";\r\n      goto unlock;\r\n    }\r\n\r\n    // Now make the port connections.  Since RtAudio wasn't designed to\r\n    // allow the user to select particular channels of a device, we'll\r\n    // just open the first \"nChannels\" ports with offset.\r\n    for ( unsigned int i=0; i<stream_.nUserChannels[0]; i++ ) {\r\n      result = 1;\r\n      if ( ports[ stream_.channelOffset[0] + i ] )\r\n        result = jack_connect( handle->client, jack_port_name( handle->ports[0][i] ), ports[ stream_.channelOffset[0] + i ] );\r\n      if ( result ) {\r\n        free( ports );\r\n        errorText_ = \"RtApiJack::startStream(): error connecting output ports!\";\r\n        goto unlock;\r\n      }\r\n    }\r\n    free(ports);\r\n  }\r\n\r\n  if ( stream_.mode == INPUT || stream_.mode == DUPLEX ) {\r\n    result = 1;\r\n    ports = jack_get_ports( handle->client, handle->deviceName[1].c_str(), NULL, JackPortIsOutput );\r\n    if ( ports == NULL) {\r\n      errorText_ = \"RtApiJack::startStream(): error determining available JACK output ports!\";\r\n      goto unlock;\r\n    }\r\n\r\n    // Now make the port connections.  See note above.\r\n    for ( unsigned int i=0; i<stream_.nUserChannels[1]; i++ ) {\r\n      result = 1;\r\n      if ( ports[ stream_.channelOffset[1] + i ] )\r\n        result = jack_connect( handle->client, ports[ stream_.channelOffset[1] + i ], jack_port_name( handle->ports[1][i] ) );\r\n      if ( result ) {\r\n        free( ports );\r\n        errorText_ = \"RtApiJack::startStream(): error connecting input ports!\";\r\n        goto unlock;\r\n      }\r\n    }\r\n    free(ports);\r\n  }\r\n\r\n  handle->drainCounter = 0;\r\n  handle->internalDrain = false;\r\n  stream_.state = STREAM_RUNNING;\r\n\r\n unlock:\r\n  if ( result == 0 ) return;\r\n  error( RtError::SYSTEM_ERROR );\r\n}\r\n\r\nvoid RtApiJack :: stopStream( void )\r\n{\r\n  verifyStream();\r\n  if ( stream_.state == STREAM_STOPPED ) {\r\n    errorText_ = \"RtApiJack::stopStream(): the stream is already stopped!\";\r\n    error( RtError::WARNING );\r\n    return;\r\n  }\r\n\r\n  JackHandle *handle = (JackHandle *) stream_.apiHandle;\r\n  if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) {\r\n\r\n    if ( handle->drainCounter == 0 ) {\r\n      handle->drainCounter = 2;\r\n      pthread_cond_wait( &handle->condition, &stream_.mutex ); // block until signaled\r\n    }\r\n  }\r\n\r\n  jack_deactivate( handle->client );\r\n  stream_.state = STREAM_STOPPED;\r\n}\r\n\r\nvoid RtApiJack :: abortStream( void )\r\n{\r\n  verifyStream();\r\n  if ( stream_.state == STREAM_STOPPED ) {\r\n    errorText_ = \"RtApiJack::abortStream(): the stream is already stopped!\";\r\n    error( RtError::WARNING );\r\n    return;\r\n  }\r\n\r\n  JackHandle *handle = (JackHandle *) stream_.apiHandle;\r\n  handle->drainCounter = 2;\r\n\r\n  stopStream();\r\n}\r\n\r\n// This function will be called by a spawned thread when the user\r\n// callback function signals that the stream should be stopped or\r\n// aborted.  It is necessary to handle it this way because the\r\n// callbackEvent() function must return before the jack_deactivate()\r\n// function will return.\r\nstatic void *jackStopStream( void *ptr )\r\n{\r\n  CallbackInfo *info = (CallbackInfo *) ptr;\r\n  RtApiJack *object = (RtApiJack *) info->object;\r\n\r\n  object->stopStream();\r\n  pthread_exit( NULL );\r\n}\r\n\r\nbool RtApiJack :: callbackEvent( unsigned long nframes )\r\n{\r\n  if ( stream_.state == STREAM_STOPPED || stream_.state == STREAM_STOPPING ) return SUCCESS;\r\n  if ( stream_.state == STREAM_CLOSED ) {\r\n    errorText_ = \"RtApiCore::callbackEvent(): the stream is closed ... this shouldn't happen!\";\r\n    error( RtError::WARNING );\r\n    return FAILURE;\r\n  }\r\n  if ( stream_.bufferSize != nframes ) {\r\n    errorText_ = \"RtApiCore::callbackEvent(): the JACK buffer size has changed ... cannot process!\";\r\n    error( RtError::WARNING );\r\n    return FAILURE;\r\n  }\r\n\r\n  CallbackInfo *info = (CallbackInfo *) &stream_.callbackInfo;\r\n  JackHandle *handle = (JackHandle *) stream_.apiHandle;\r\n\r\n  // Check if we were draining the stream and signal is finished.\r\n  if ( handle->drainCounter > 3 ) {\r\n    ThreadHandle threadId;\r\n\r\n    stream_.state = STREAM_STOPPING;\r\n    if ( handle->internalDrain == true )\r\n      pthread_create( &threadId, NULL, jackStopStream, info );\r\n    else\r\n      pthread_cond_signal( &handle->condition );\r\n    return SUCCESS;\r\n  }\r\n\r\n  // Invoke user callback first, to get fresh output data.\r\n  if ( handle->drainCounter == 0 ) {\r\n    RtAudioCallback callback = (RtAudioCallback) info->callback;\r\n    double streamTime = getStreamTime();\r\n    RtAudioStreamStatus status = 0;\r\n    if ( stream_.mode != INPUT && handle->xrun[0] == true ) {\r\n      status |= RTAUDIO_OUTPUT_UNDERFLOW;\r\n      handle->xrun[0] = false;\r\n    }\r\n    if ( stream_.mode != OUTPUT && handle->xrun[1] == true ) {\r\n      status |= RTAUDIO_INPUT_OVERFLOW;\r\n      handle->xrun[1] = false;\r\n    }\r\n    int cbReturnValue = callback( stream_.userBuffer[0], stream_.userBuffer[1],\r\n                                  stream_.bufferSize, streamTime, status, info->userData );\r\n    if ( cbReturnValue == 2 ) {\r\n      stream_.state = STREAM_STOPPING;\r\n      handle->drainCounter = 2;\r\n      ThreadHandle id;\r\n      pthread_create( &id, NULL, jackStopStream, info );\r\n      return SUCCESS;\r\n    }\r\n    else if ( cbReturnValue == 1 ) {\r\n      handle->drainCounter = 1;\r\n      handle->internalDrain = true;\r\n    }\r\n  }\r\n\r\n  jack_default_audio_sample_t *jackbuffer;\r\n  unsigned long bufferBytes = nframes * sizeof( jack_default_audio_sample_t );\r\n  if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) {\r\n\r\n    if ( handle->drainCounter > 1 ) { // write zeros to the output stream\r\n\r\n      for ( unsigned int i=0; i<stream_.nDeviceChannels[0]; i++ ) {\r\n        jackbuffer = (jack_default_audio_sample_t *) jack_port_get_buffer( handle->ports[0][i], (jack_nframes_t) nframes );\r\n        memset( jackbuffer, 0, bufferBytes );\r\n      }\r\n\r\n    }\r\n    else if ( stream_.doConvertBuffer[0] ) {\r\n\r\n      convertBuffer( stream_.deviceBuffer, stream_.userBuffer[0], stream_.convertInfo[0] );\r\n\r\n      for ( unsigned int i=0; i<stream_.nDeviceChannels[0]; i++ ) {\r\n        jackbuffer = (jack_default_audio_sample_t *) jack_port_get_buffer( handle->ports[0][i], (jack_nframes_t) nframes );\r\n        memcpy( jackbuffer, &stream_.deviceBuffer[i*bufferBytes], bufferBytes );\r\n      }\r\n    }\r\n    else { // no buffer conversion\r\n      for ( unsigned int i=0; i<stream_.nUserChannels[0]; i++ ) {\r\n        jackbuffer = (jack_default_audio_sample_t *) jack_port_get_buffer( handle->ports[0][i], (jack_nframes_t) nframes );\r\n        memcpy( jackbuffer, &stream_.userBuffer[0][i*bufferBytes], bufferBytes );\r\n      }\r\n    }\r\n\r\n    if ( handle->drainCounter ) {\r\n      handle->drainCounter++;\r\n      goto unlock;\r\n    }\r\n  }\r\n\r\n  if ( stream_.mode == INPUT || stream_.mode == DUPLEX ) {\r\n\r\n    if ( stream_.doConvertBuffer[1] ) {\r\n      for ( unsigned int i=0; i<stream_.nDeviceChannels[1]; i++ ) {\r\n        jackbuffer = (jack_default_audio_sample_t *) jack_port_get_buffer( handle->ports[1][i], (jack_nframes_t) nframes );\r\n        memcpy( &stream_.deviceBuffer[i*bufferBytes], jackbuffer, bufferBytes );\r\n      }\r\n      convertBuffer( stream_.userBuffer[1], stream_.deviceBuffer, stream_.convertInfo[1] );\r\n    }\r\n    else { // no buffer conversion\r\n      for ( unsigned int i=0; i<stream_.nUserChannels[1]; i++ ) {\r\n        jackbuffer = (jack_default_audio_sample_t *) jack_port_get_buffer( handle->ports[1][i], (jack_nframes_t) nframes );\r\n        memcpy( &stream_.userBuffer[1][i*bufferBytes], jackbuffer, bufferBytes );\r\n      }\r\n    }\r\n  }\r\n\r\n unlock:\r\n  RtApi::tickStreamTime();\r\n  return SUCCESS;\r\n}\r\n  //******************** End of __UNIX_JACK__ *********************//\r\n#endif\r\n\r\n#if defined(__WINDOWS_ASIO__) // ASIO API on Windows\r\n\r\n// The ASIO API is designed around a callback scheme, so this\r\n// implementation is similar to that used for OS-X CoreAudio and GNU/Linux\r\n// Jack.  The primary constraint with ASIO is that it only allows\r\n// access to a single driver at a time.  Thus, it is not possible to\r\n// have more than one simultaneous RtAudio stream.\r\n//\r\n// This implementation also requires a number of external ASIO files\r\n// and a few global variables.  The ASIO callback scheme does not\r\n// allow for the passing of user data, so we must create a global\r\n// pointer to our callbackInfo structure.\r\n//\r\n// On unix systems, we make use of a pthread condition variable.\r\n// Since there is no equivalent in Windows, I hacked something based\r\n// on information found in\r\n// http://www.cs.wustl.edu/~schmidt/win32-cv-1.html.\r\n\r\n#include \"asiosys.h\"\r\n#include \"asio.h\"\r\n#include \"iasiothiscallresolver.h\"\r\n#include \"asiodrivers.h\"\r\n#include <cmath>\r\n\r\nstatic AsioDrivers drivers;\r\nstatic ASIOCallbacks asioCallbacks;\r\nstatic ASIODriverInfo driverInfo;\r\nstatic CallbackInfo *asioCallbackInfo;\r\nstatic bool asioXRun;\r\n\r\nstruct AsioHandle {\r\n  int drainCounter;       // Tracks callback counts when draining\r\n  bool internalDrain;     // Indicates if stop is initiated from callback or not.\r\n  ASIOBufferInfo *bufferInfos;\r\n  HANDLE condition;\r\n\r\n  AsioHandle()\r\n    :drainCounter(0), internalDrain(false), bufferInfos(0) {}\r\n};\r\n\r\n// Function declarations (definitions at end of section)\r\nstatic const char* getAsioErrorString( ASIOError result );\r\nstatic void sampleRateChanged( ASIOSampleRate sRate );\r\nstatic long asioMessages( long selector, long value, void* message, double* opt );\r\n\r\nRtApiAsio :: RtApiAsio()\r\n{\r\n  // ASIO cannot run on a multi-threaded appartment. You can call\r\n  // CoInitialize beforehand, but it must be for appartment threading\r\n  // (in which case, CoInitilialize will return S_FALSE here).\r\n  coInitialized_ = false;\r\n  HRESULT hr = CoInitialize( NULL ); \r\n  if ( FAILED(hr) ) {\r\n    errorText_ = \"RtApiAsio::ASIO requires a single-threaded appartment. Call CoInitializeEx(0,COINIT_APARTMENTTHREADED)\";\r\n    error( RtError::WARNING );\r\n  }\r\n  coInitialized_ = true;\r\n\r\n  drivers.removeCurrentDriver();\r\n  driverInfo.asioVersion = 2;\r\n\r\n  // See note in DirectSound implementation about GetDesktopWindow().\r\n  driverInfo.sysRef = GetForegroundWindow();\r\n}\r\n\r\nRtApiAsio :: ~RtApiAsio()\r\n{\r\n  if ( stream_.state != STREAM_CLOSED ) closeStream();\r\n  if ( coInitialized_ ) CoUninitialize();\r\n}\r\n\r\nunsigned int RtApiAsio :: getDeviceCount( void )\r\n{\r\n  return (unsigned int) drivers.asioGetNumDev();\r\n}\r\n\r\nRtAudio::DeviceInfo RtApiAsio :: getDeviceInfo( unsigned int device )\r\n{\r\n  RtAudio::DeviceInfo info;\r\n  info.probed = false;\r\n\r\n  // Get device ID\r\n  unsigned int nDevices = getDeviceCount();\r\n  if ( nDevices == 0 ) {\r\n    errorText_ = \"RtApiAsio::getDeviceInfo: no devices found!\";\r\n    error( RtError::INVALID_USE );\r\n    return info;\r\n  }\r\n\r\n  if ( device >= nDevices ) {\r\n    errorText_ = \"RtApiAsio::getDeviceInfo: device ID is invalid!\";\r\n    error( RtError::INVALID_USE );\r\n    return info;\r\n  }\r\n\r\n  // If a stream is already open, we cannot probe other devices.  Thus, use the saved results.\r\n  if ( stream_.state != STREAM_CLOSED ) {\r\n    if ( device >= devices_.size() ) {\r\n      errorText_ = \"RtApiAsio::getDeviceInfo: device ID was not present before stream was opened.\";\r\n      error( RtError::WARNING );\r\n      return info;\r\n    }\r\n    return devices_[ device ];\r\n  }\r\n\r\n  char driverName[32];\r\n  ASIOError result = drivers.asioGetDriverName( (int) device, driverName, 32 );\r\n  if ( result != ASE_OK ) {\r\n    errorStream_ << \"RtApiAsio::getDeviceInfo: unable to get driver name (\" << getAsioErrorString( result ) << \").\";\r\n    errorText_ = errorStream_.str();\r\n    error( RtError::WARNING );\r\n    return info;\r\n  }\r\n\r\n  info.name = driverName;\r\n\r\n  if ( !drivers.loadDriver( driverName ) ) {\r\n    errorStream_ << \"RtApiAsio::getDeviceInfo: unable to load driver (\" << driverName << \").\";\r\n    errorText_ = errorStream_.str();\r\n    error( RtError::WARNING );\r\n    return info;\r\n  }\r\n\r\n  result = ASIOInit( &driverInfo );\r\n  if ( result != ASE_OK ) {\r\n    errorStream_ << \"RtApiAsio::getDeviceInfo: error (\" << getAsioErrorString( result ) << \") initializing driver (\" << driverName << \").\";\r\n    errorText_ = errorStream_.str();\r\n    error( RtError::WARNING );\r\n    return info;\r\n  }\r\n\r\n  // Determine the device channel information.\r\n  long inputChannels, outputChannels;\r\n  result = ASIOGetChannels( &inputChannels, &outputChannels );\r\n  if ( result != ASE_OK ) {\r\n    drivers.removeCurrentDriver();\r\n    errorStream_ << \"RtApiAsio::getDeviceInfo: error (\" << getAsioErrorString( result ) << \") getting channel count (\" << driverName << \").\";\r\n    errorText_ = errorStream_.str();\r\n    error( RtError::WARNING );\r\n    return info;\r\n  }\r\n\r\n  info.outputChannels = outputChannels;\r\n  info.inputChannels = inputChannels;\r\n  if ( info.outputChannels > 0 && info.inputChannels > 0 )\r\n    info.duplexChannels = (info.outputChannels > info.inputChannels) ? info.inputChannels : info.outputChannels;\r\n\r\n  // Determine the supported sample rates.\r\n  info.sampleRates.clear();\r\n  for ( unsigned int i=0; i<MAX_SAMPLE_RATES; i++ ) {\r\n    result = ASIOCanSampleRate( (ASIOSampleRate) SAMPLE_RATES[i] );\r\n    if ( result == ASE_OK )\r\n      info.sampleRates.push_back( SAMPLE_RATES[i] );\r\n  }\r\n\r\n  // Determine supported data types ... just check first channel and assume rest are the same.\r\n  ASIOChannelInfo channelInfo;\r\n  channelInfo.channel = 0;\r\n  channelInfo.isInput = true;\r\n  if ( info.inputChannels <= 0 ) channelInfo.isInput = false;\r\n  result = ASIOGetChannelInfo( &channelInfo );\r\n  if ( result != ASE_OK ) {\r\n    drivers.removeCurrentDriver();\r\n    errorStream_ << \"RtApiAsio::getDeviceInfo: error (\" << getAsioErrorString( result ) << \") getting driver channel info (\" << driverName << \").\";\r\n    errorText_ = errorStream_.str();\r\n    error( RtError::WARNING );\r\n    return info;\r\n  }\r\n\r\n  info.nativeFormats = 0;\r\n  if ( channelInfo.type == ASIOSTInt16MSB || channelInfo.type == ASIOSTInt16LSB )\r\n    info.nativeFormats |= RTAUDIO_SINT16;\r\n  else if ( channelInfo.type == ASIOSTInt32MSB || channelInfo.type == ASIOSTInt32LSB )\r\n    info.nativeFormats |= RTAUDIO_SINT32;\r\n  else if ( channelInfo.type == ASIOSTFloat32MSB || channelInfo.type == ASIOSTFloat32LSB )\r\n    info.nativeFormats |= RTAUDIO_FLOAT32;\r\n  else if ( channelInfo.type == ASIOSTFloat64MSB || channelInfo.type == ASIOSTFloat64LSB )\r\n    info.nativeFormats |= RTAUDIO_FLOAT64;\r\n  else if ( channelInfo.type == ASIOSTInt24MSB || channelInfo.type == ASIOSTInt24LSB )\r\n    info.nativeFormats |= RTAUDIO_SINT24;\r\n\r\n  if ( info.outputChannels > 0 )\r\n    if ( getDefaultOutputDevice() == device ) info.isDefaultOutput = true;\r\n  if ( info.inputChannels > 0 )\r\n    if ( getDefaultInputDevice() == device ) info.isDefaultInput = true;\r\n\r\n  info.probed = true;\r\n  drivers.removeCurrentDriver();\r\n  return info;\r\n}\r\n\r\nstatic void bufferSwitch( long index, ASIOBool processNow )\r\n{\r\n  RtApiAsio *object = (RtApiAsio *) asioCallbackInfo->object;\r\n  object->callbackEvent( index );\r\n}\r\n\r\nvoid RtApiAsio :: saveDeviceInfo( void )\r\n{\r\n  devices_.clear();\r\n\r\n  unsigned int nDevices = getDeviceCount();\r\n  devices_.resize( nDevices );\r\n  for ( unsigned int i=0; i<nDevices; i++ )\r\n    devices_[i] = getDeviceInfo( i );\r\n}\r\n\r\nbool RtApiAsio :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels,\r\n                                   unsigned int firstChannel, unsigned int sampleRate,\r\n                                   RtAudioFormat format, unsigned int *bufferSize,\r\n                                   RtAudio::StreamOptions *options )\r\n{\r\n  // For ASIO, a duplex stream MUST use the same driver.\r\n  if ( mode == INPUT && stream_.mode == OUTPUT && stream_.device[0] != device ) {\r\n    errorText_ = \"RtApiAsio::probeDeviceOpen: an ASIO duplex stream must use the same device for input and output!\";\r\n    return FAILURE;\r\n  }\r\n\r\n  char driverName[32];\r\n  ASIOError result = drivers.asioGetDriverName( (int) device, driverName, 32 );\r\n  if ( result != ASE_OK ) {\r\n    errorStream_ << \"RtApiAsio::probeDeviceOpen: unable to get driver name (\" << getAsioErrorString( result ) << \").\";\r\n    errorText_ = errorStream_.str();\r\n    return FAILURE;\r\n  }\r\n\r\n  // Only load the driver once for duplex stream.\r\n  if ( mode != INPUT || stream_.mode != OUTPUT ) {\r\n    // The getDeviceInfo() function will not work when a stream is open\r\n    // because ASIO does not allow multiple devices to run at the same\r\n    // time.  Thus, we'll probe the system before opening a stream and\r\n    // save the results for use by getDeviceInfo().\r\n    this->saveDeviceInfo();\r\n\r\n    if ( !drivers.loadDriver( driverName ) ) {\r\n      errorStream_ << \"RtApiAsio::probeDeviceOpen: unable to load driver (\" << driverName << \").\";\r\n      errorText_ = errorStream_.str();\r\n      return FAILURE;\r\n    }\r\n\r\n    result = ASIOInit( &driverInfo );\r\n    if ( result != ASE_OK ) {\r\n      errorStream_ << \"RtApiAsio::probeDeviceOpen: error (\" << getAsioErrorString( result ) << \") initializing driver (\" << driverName << \").\";\r\n      errorText_ = errorStream_.str();\r\n      return FAILURE;\r\n    }\r\n  }\r\n\r\n  // Check the device channel count.\r\n  long inputChannels, outputChannels;\r\n  result = ASIOGetChannels( &inputChannels, &outputChannels );\r\n  if ( result != ASE_OK ) {\r\n    drivers.removeCurrentDriver();\r\n    errorStream_ << \"RtApiAsio::probeDeviceOpen: error (\" << getAsioErrorString( result ) << \") getting channel count (\" << driverName << \").\";\r\n    errorText_ = errorStream_.str();\r\n    return FAILURE;\r\n  }\r\n\r\n  if ( ( mode == OUTPUT && (channels+firstChannel) > (unsigned int) outputChannels) ||\r\n       ( mode == INPUT && (channels+firstChannel) > (unsigned int) inputChannels) ) {\r\n    drivers.removeCurrentDriver();\r\n    errorStream_ << \"RtApiAsio::probeDeviceOpen: driver (\" << driverName << \") does not support requested channel count (\" << channels << \") + offset (\" << firstChannel << \").\";\r\n    errorText_ = errorStream_.str();\r\n    return FAILURE;\r\n  }\r\n  stream_.nDeviceChannels[mode] = channels;\r\n  stream_.nUserChannels[mode] = channels;\r\n  stream_.channelOffset[mode] = firstChannel;\r\n\r\n  // Verify the sample rate is supported.\r\n  result = ASIOCanSampleRate( (ASIOSampleRate) sampleRate );\r\n  if ( result != ASE_OK ) {\r\n    drivers.removeCurrentDriver();\r\n    errorStream_ << \"RtApiAsio::probeDeviceOpen: driver (\" << driverName << \") does not support requested sample rate (\" << sampleRate << \").\";\r\n    errorText_ = errorStream_.str();\r\n    return FAILURE;\r\n  }\r\n\r\n  // Get the current sample rate\r\n  ASIOSampleRate currentRate;\r\n  result = ASIOGetSampleRate( &currentRate );\r\n  if ( result != ASE_OK ) {\r\n    drivers.removeCurrentDriver();\r\n    errorStream_ << \"RtApiAsio::probeDeviceOpen: driver (\" << driverName << \") error getting sample rate.\";\r\n    errorText_ = errorStream_.str();\r\n    return FAILURE;\r\n  }\r\n\r\n  // Set the sample rate only if necessary\r\n  if ( currentRate != sampleRate ) {\r\n    result = ASIOSetSampleRate( (ASIOSampleRate) sampleRate );\r\n    if ( result != ASE_OK ) {\r\n      drivers.removeCurrentDriver();\r\n      errorStream_ << \"RtApiAsio::probeDeviceOpen: driver (\" << driverName << \") error setting sample rate (\" << sampleRate << \").\";\r\n      errorText_ = errorStream_.str();\r\n      return FAILURE;\r\n    }\r\n  }\r\n\r\n  // Determine the driver data type.\r\n  ASIOChannelInfo channelInfo;\r\n  channelInfo.channel = 0;\r\n  if ( mode == OUTPUT ) channelInfo.isInput = false;\r\n  else channelInfo.isInput = true;\r\n  result = ASIOGetChannelInfo( &channelInfo );\r\n  if ( result != ASE_OK ) {\r\n    drivers.removeCurrentDriver();\r\n    errorStream_ << \"RtApiAsio::probeDeviceOpen: driver (\" << driverName << \") error (\" << getAsioErrorString( result ) << \") getting data format.\";\r\n    errorText_ = errorStream_.str();\r\n    return FAILURE;\r\n  }\r\n\r\n  // Assuming WINDOWS host is always little-endian.\r\n  stream_.doByteSwap[mode] = false;\r\n  stream_.userFormat = format;\r\n  stream_.deviceFormat[mode] = 0;\r\n  if ( channelInfo.type == ASIOSTInt16MSB || channelInfo.type == ASIOSTInt16LSB ) {\r\n    stream_.deviceFormat[mode] = RTAUDIO_SINT16;\r\n    if ( channelInfo.type == ASIOSTInt16MSB ) stream_.doByteSwap[mode] = true;\r\n  }\r\n  else if ( channelInfo.type == ASIOSTInt32MSB || channelInfo.type == ASIOSTInt32LSB ) {\r\n    stream_.deviceFormat[mode] = RTAUDIO_SINT32;\r\n    if ( channelInfo.type == ASIOSTInt32MSB ) stream_.doByteSwap[mode] = true;\r\n  }\r\n  else if ( channelInfo.type == ASIOSTFloat32MSB || channelInfo.type == ASIOSTFloat32LSB ) {\r\n    stream_.deviceFormat[mode] = RTAUDIO_FLOAT32;\r\n    if ( channelInfo.type == ASIOSTFloat32MSB ) stream_.doByteSwap[mode] = true;\r\n  }\r\n  else if ( channelInfo.type == ASIOSTFloat64MSB || channelInfo.type == ASIOSTFloat64LSB ) {\r\n    stream_.deviceFormat[mode] = RTAUDIO_FLOAT64;\r\n    if ( channelInfo.type == ASIOSTFloat64MSB ) stream_.doByteSwap[mode] = true;\r\n  }\r\n  else if ( channelInfo.type == ASIOSTInt24MSB || channelInfo.type == ASIOSTInt24LSB ) {\r\n    stream_.deviceFormat[mode] = RTAUDIO_SINT24;\r\n    if ( channelInfo.type == ASIOSTInt24MSB ) stream_.doByteSwap[mode] = true;\r\n  }\r\n\r\n  if ( stream_.deviceFormat[mode] == 0 ) {\r\n    drivers.removeCurrentDriver();\r\n    errorStream_ << \"RtApiAsio::probeDeviceOpen: driver (\" << driverName << \") data format not supported by RtAudio.\";\r\n    errorText_ = errorStream_.str();\r\n    return FAILURE;\r\n  }\r\n\r\n  // Set the buffer size.  For a duplex stream, this will end up\r\n  // setting the buffer size based on the input constraints, which\r\n  // should be ok.\r\n  long minSize, maxSize, preferSize, granularity;\r\n  result = ASIOGetBufferSize( &minSize, &maxSize, &preferSize, &granularity );\r\n  if ( result != ASE_OK ) {\r\n    drivers.removeCurrentDriver();\r\n    errorStream_ << \"RtApiAsio::probeDeviceOpen: driver (\" << driverName << \") error (\" << getAsioErrorString( result ) << \") getting buffer size.\";\r\n    errorText_ = errorStream_.str();\r\n    return FAILURE;\r\n  }\r\n\r\n  if ( *bufferSize < (unsigned int) minSize ) *bufferSize = (unsigned int) minSize;\r\n  else if ( *bufferSize > (unsigned int) maxSize ) *bufferSize = (unsigned int) maxSize;\r\n  else if ( granularity == -1 ) {\r\n    // Make sure bufferSize is a power of two.\r\n    int log2_of_min_size = 0;\r\n    int log2_of_max_size = 0;\r\n\r\n    for ( unsigned int i = 0; i < sizeof(long) * 8; i++ ) {\r\n      if ( minSize & ((long)1 << i) ) log2_of_min_size = i;\r\n      if ( maxSize & ((long)1 << i) ) log2_of_max_size = i;\r\n    }\r\n\r\n    long min_delta = std::abs( (long)*bufferSize - ((long)1 << log2_of_min_size) );\r\n    int min_delta_num = log2_of_min_size;\r\n\r\n    for (int i = log2_of_min_size + 1; i <= log2_of_max_size; i++) {\r\n      long current_delta = std::abs( (long)*bufferSize - ((long)1 << i) );\r\n      if (current_delta < min_delta) {\r\n        min_delta = current_delta;\r\n        min_delta_num = i;\r\n      }\r\n    }\r\n\r\n    *bufferSize = ( (unsigned int)1 << min_delta_num );\r\n    if ( *bufferSize < (unsigned int) minSize ) *bufferSize = (unsigned int) minSize;\r\n    else if ( *bufferSize > (unsigned int) maxSize ) *bufferSize = (unsigned int) maxSize;\r\n  }\r\n  else if ( granularity != 0 ) {\r\n    // Set to an even multiple of granularity, rounding up.\r\n    *bufferSize = (*bufferSize + granularity-1) / granularity * granularity;\r\n  }\r\n\r\n  if ( mode == INPUT && stream_.mode == OUTPUT && stream_.bufferSize != *bufferSize ) {\r\n    drivers.removeCurrentDriver();\r\n    errorText_ = \"RtApiAsio::probeDeviceOpen: input/output buffersize discrepancy!\";\r\n    return FAILURE;\r\n  }\r\n\r\n  stream_.bufferSize = *bufferSize;\r\n  stream_.nBuffers = 2;\r\n\r\n  if ( options && options->flags & RTAUDIO_NONINTERLEAVED ) stream_.userInterleaved = false;\r\n  else stream_.userInterleaved = true;\r\n\r\n  // ASIO always uses non-interleaved buffers.\r\n  stream_.deviceInterleaved[mode] = false;\r\n\r\n  // Allocate, if necessary, our AsioHandle structure for the stream.\r\n  AsioHandle *handle = (AsioHandle *) stream_.apiHandle;\r\n  if ( handle == 0 ) {\r\n    try {\r\n      handle = new AsioHandle;\r\n    }\r\n    catch ( std::bad_alloc& ) {\r\n      //if ( handle == NULL ) {    \r\n      drivers.removeCurrentDriver();\r\n      errorText_ = \"RtApiAsio::probeDeviceOpen: error allocating AsioHandle memory.\";\r\n      return FAILURE;\r\n    }\r\n    handle->bufferInfos = 0;\r\n\r\n    // Create a manual-reset event.\r\n    handle->condition = CreateEvent( NULL,   // no security\r\n                                     TRUE,   // manual-reset\r\n                                     FALSE,  // non-signaled initially\r\n                                     NULL ); // unnamed\r\n    stream_.apiHandle = (void *) handle;\r\n  }\r\n\r\n  // Create the ASIO internal buffers.  Since RtAudio sets up input\r\n  // and output separately, we'll have to dispose of previously\r\n  // created output buffers for a duplex stream.\r\n  long inputLatency, outputLatency;\r\n  if ( mode == INPUT && stream_.mode == OUTPUT ) {\r\n    ASIODisposeBuffers();\r\n    if ( handle->bufferInfos ) free( handle->bufferInfos );\r\n  }\r\n\r\n  // Allocate, initialize, and save the bufferInfos in our stream callbackInfo structure.\r\n  bool buffersAllocated = false;\r\n  unsigned int i, nChannels = stream_.nDeviceChannels[0] + stream_.nDeviceChannels[1];\r\n  handle->bufferInfos = (ASIOBufferInfo *) malloc( nChannels * sizeof(ASIOBufferInfo) );\r\n  if ( handle->bufferInfos == NULL ) {\r\n    errorStream_ << \"RtApiAsio::probeDeviceOpen: error allocating bufferInfo memory for driver (\" << driverName << \").\";\r\n    errorText_ = errorStream_.str();\r\n    goto error;\r\n  }\r\n\r\n  ASIOBufferInfo *infos;\r\n  infos = handle->bufferInfos;\r\n  for ( i=0; i<stream_.nDeviceChannels[0]; i++, infos++ ) {\r\n    infos->isInput = ASIOFalse;\r\n    infos->channelNum = i + stream_.channelOffset[0];\r\n    infos->buffers[0] = infos->buffers[1] = 0;\r\n  }\r\n  for ( i=0; i<stream_.nDeviceChannels[1]; i++, infos++ ) {\r\n    infos->isInput = ASIOTrue;\r\n    infos->channelNum = i + stream_.channelOffset[1];\r\n    infos->buffers[0] = infos->buffers[1] = 0;\r\n  }\r\n\r\n  // Set up the ASIO callback structure and create the ASIO data buffers.\r\n  asioCallbacks.bufferSwitch = &bufferSwitch;\r\n  asioCallbacks.sampleRateDidChange = &sampleRateChanged;\r\n  asioCallbacks.asioMessage = &asioMessages;\r\n  asioCallbacks.bufferSwitchTimeInfo = NULL;\r\n  result = ASIOCreateBuffers( handle->bufferInfos, nChannels, stream_.bufferSize, &asioCallbacks );\r\n  if ( result != ASE_OK ) {\r\n    errorStream_ << \"RtApiAsio::probeDeviceOpen: driver (\" << driverName << \") error (\" << getAsioErrorString( result ) << \") creating buffers.\";\r\n    errorText_ = errorStream_.str();\r\n    goto error;\r\n  }\r\n  buffersAllocated = true;\r\n\r\n  // Set flags for buffer conversion.\r\n  stream_.doConvertBuffer[mode] = false;\r\n  if ( stream_.userFormat != stream_.deviceFormat[mode] )\r\n    stream_.doConvertBuffer[mode] = true;\r\n  if ( stream_.userInterleaved != stream_.deviceInterleaved[mode] &&\r\n       stream_.nUserChannels[mode] > 1 )\r\n    stream_.doConvertBuffer[mode] = true;\r\n\r\n  // Allocate necessary internal buffers\r\n  unsigned long bufferBytes;\r\n  bufferBytes = stream_.nUserChannels[mode] * *bufferSize * formatBytes( stream_.userFormat );\r\n  stream_.userBuffer[mode] = (char *) calloc( bufferBytes, 1 );\r\n  if ( stream_.userBuffer[mode] == NULL ) {\r\n    errorText_ = \"RtApiAsio::probeDeviceOpen: error allocating user buffer memory.\";\r\n    goto error;\r\n  }\r\n\r\n  if ( stream_.doConvertBuffer[mode] ) {\r\n\r\n    bool makeBuffer = true;\r\n    bufferBytes = stream_.nDeviceChannels[mode] * formatBytes( stream_.deviceFormat[mode] );\r\n    if ( mode == INPUT ) {\r\n      if ( stream_.mode == OUTPUT && stream_.deviceBuffer ) {\r\n        unsigned long bytesOut = stream_.nDeviceChannels[0] * formatBytes( stream_.deviceFormat[0] );\r\n        if ( bufferBytes <= bytesOut ) makeBuffer = false;\r\n      }\r\n    }\r\n\r\n    if ( makeBuffer ) {\r\n      bufferBytes *= *bufferSize;\r\n      if ( stream_.deviceBuffer ) free( stream_.deviceBuffer );\r\n      stream_.deviceBuffer = (char *) calloc( bufferBytes, 1 );\r\n      if ( stream_.deviceBuffer == NULL ) {\r\n        errorText_ = \"RtApiAsio::probeDeviceOpen: error allocating device buffer memory.\";\r\n        goto error;\r\n      }\r\n    }\r\n  }\r\n\r\n  stream_.sampleRate = sampleRate;\r\n  stream_.device[mode] = device;\r\n  stream_.state = STREAM_STOPPED;\r\n  asioCallbackInfo = &stream_.callbackInfo;\r\n  stream_.callbackInfo.object = (void *) this;\r\n  if ( stream_.mode == OUTPUT && mode == INPUT )\r\n    // We had already set up an output stream.\r\n    stream_.mode = DUPLEX;\r\n  else\r\n    stream_.mode = mode;\r\n\r\n  // Determine device latencies\r\n  result = ASIOGetLatencies( &inputLatency, &outputLatency );\r\n  if ( result != ASE_OK ) {\r\n    errorStream_ << \"RtApiAsio::probeDeviceOpen: driver (\" << driverName << \") error (\" << getAsioErrorString( result ) << \") getting latency.\";\r\n    errorText_ = errorStream_.str();\r\n    error( RtError::WARNING); // warn but don't fail\r\n  }\r\n  else {\r\n    stream_.latency[0] = outputLatency;\r\n    stream_.latency[1] = inputLatency;\r\n  }\r\n\r\n  // Setup the buffer conversion information structure.  We don't use\r\n  // buffers to do channel offsets, so we override that parameter\r\n  // here.\r\n  if ( stream_.doConvertBuffer[mode] ) setConvertInfo( mode, 0 );\r\n\r\n  return SUCCESS;\r\n\r\n error:\r\n  if ( buffersAllocated )\r\n    ASIODisposeBuffers();\r\n  drivers.removeCurrentDriver();\r\n\r\n  if ( handle ) {\r\n    CloseHandle( handle->condition );\r\n    if ( handle->bufferInfos )\r\n      free( handle->bufferInfos );\r\n    delete handle;\r\n    stream_.apiHandle = 0;\r\n  }\r\n\r\n  for ( int i=0; i<2; i++ ) {\r\n    if ( stream_.userBuffer[i] ) {\r\n      free( stream_.userBuffer[i] );\r\n      stream_.userBuffer[i] = 0;\r\n    }\r\n  }\r\n\r\n  if ( stream_.deviceBuffer ) {\r\n    free( stream_.deviceBuffer );\r\n    stream_.deviceBuffer = 0;\r\n  }\r\n\r\n  return FAILURE;\r\n}\r\n\r\nvoid RtApiAsio :: closeStream()\r\n{\r\n  if ( stream_.state == STREAM_CLOSED ) {\r\n    errorText_ = \"RtApiAsio::closeStream(): no open stream to close!\";\r\n    error( RtError::WARNING );\r\n    return;\r\n  }\r\n\r\n  if ( stream_.state == STREAM_RUNNING ) {\r\n    stream_.state = STREAM_STOPPED;\r\n    ASIOStop();\r\n  }\r\n  ASIODisposeBuffers();\r\n  drivers.removeCurrentDriver();\r\n\r\n  AsioHandle *handle = (AsioHandle *) stream_.apiHandle;\r\n  if ( handle ) {\r\n    CloseHandle( handle->condition );\r\n    if ( handle->bufferInfos )\r\n      free( handle->bufferInfos );\r\n    delete handle;\r\n    stream_.apiHandle = 0;\r\n  }\r\n\r\n  for ( int i=0; i<2; i++ ) {\r\n    if ( stream_.userBuffer[i] ) {\r\n      free( stream_.userBuffer[i] );\r\n      stream_.userBuffer[i] = 0;\r\n    }\r\n  }\r\n\r\n  if ( stream_.deviceBuffer ) {\r\n    free( stream_.deviceBuffer );\r\n    stream_.deviceBuffer = 0;\r\n  }\r\n\r\n  stream_.mode = UNINITIALIZED;\r\n  stream_.state = STREAM_CLOSED;\r\n}\r\n\r\nbool stopThreadCalled = false;\r\n\r\nvoid RtApiAsio :: startStream()\r\n{\r\n  verifyStream();\r\n  if ( stream_.state == STREAM_RUNNING ) {\r\n    errorText_ = \"RtApiAsio::startStream(): the stream is already running!\";\r\n    error( RtError::WARNING );\r\n    return;\r\n  }\r\n\r\n  AsioHandle *handle = (AsioHandle *) stream_.apiHandle;\r\n  ASIOError result = ASIOStart();\r\n  if ( result != ASE_OK ) {\r\n    errorStream_ << \"RtApiAsio::startStream: error (\" << getAsioErrorString( result ) << \") starting device.\";\r\n    errorText_ = errorStream_.str();\r\n    goto unlock;\r\n  }\r\n\r\n  handle->drainCounter = 0;\r\n  handle->internalDrain = false;\r\n  ResetEvent( handle->condition );\r\n  stream_.state = STREAM_RUNNING;\r\n  asioXRun = false;\r\n\r\n unlock:\r\n  stopThreadCalled = false;\r\n\r\n  if ( result == ASE_OK ) return;\r\n  error( RtError::SYSTEM_ERROR );\r\n}\r\n\r\nvoid RtApiAsio :: stopStream()\r\n{\r\n  verifyStream();\r\n  if ( stream_.state == STREAM_STOPPED ) {\r\n    errorText_ = \"RtApiAsio::stopStream(): the stream is already stopped!\";\r\n    error( RtError::WARNING );\r\n    return;\r\n  }\r\n\r\n  AsioHandle *handle = (AsioHandle *) stream_.apiHandle;\r\n  if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) {\r\n    if ( handle->drainCounter == 0 ) {\r\n      handle->drainCounter = 2;\r\n      WaitForSingleObject( handle->condition, INFINITE );  // block until signaled\r\n    }\r\n  }\r\n\r\n  stream_.state = STREAM_STOPPED;\r\n\r\n  ASIOError result = ASIOStop();\r\n  if ( result != ASE_OK ) {\r\n    errorStream_ << \"RtApiAsio::stopStream: error (\" << getAsioErrorString( result ) << \") stopping device.\";\r\n    errorText_ = errorStream_.str();\r\n  }\r\n\r\n  if ( result == ASE_OK ) return;\r\n  error( RtError::SYSTEM_ERROR );\r\n}\r\n\r\nvoid RtApiAsio :: abortStream()\r\n{\r\n  verifyStream();\r\n  if ( stream_.state == STREAM_STOPPED ) {\r\n    errorText_ = \"RtApiAsio::abortStream(): the stream is already stopped!\";\r\n    error( RtError::WARNING );\r\n    return;\r\n  }\r\n\r\n  // The following lines were commented-out because some behavior was\r\n  // noted where the device buffers need to be zeroed to avoid\r\n  // continuing sound, even when the device buffers are completely\r\n  // disposed.  So now, calling abort is the same as calling stop.\r\n  // AsioHandle *handle = (AsioHandle *) stream_.apiHandle;\r\n  // handle->drainCounter = 2;\r\n  stopStream();\r\n}\r\n\r\n// This function will be called by a spawned thread when the user\r\n// callback function signals that the stream should be stopped or\r\n// aborted.  It is necessary to handle it this way because the\r\n// callbackEvent() function must return before the ASIOStop()\r\n// function will return.\r\nstatic unsigned __stdcall asioStopStream( void *ptr )\r\n{\r\n  CallbackInfo *info = (CallbackInfo *) ptr;\r\n  RtApiAsio *object = (RtApiAsio *) info->object;\r\n\r\n  object->stopStream();\r\n  _endthreadex( 0 );\r\n  return 0;\r\n}\r\n\r\nbool RtApiAsio :: callbackEvent( long bufferIndex )\r\n{\r\n  if ( stream_.state == STREAM_STOPPED || stream_.state == STREAM_STOPPING ) return SUCCESS;\r\n  if ( stream_.state == STREAM_CLOSED ) {\r\n    errorText_ = \"RtApiAsio::callbackEvent(): the stream is closed ... this shouldn't happen!\";\r\n    error( RtError::WARNING );\r\n    return FAILURE;\r\n  }\r\n\r\n  CallbackInfo *info = (CallbackInfo *) &stream_.callbackInfo;\r\n  AsioHandle *handle = (AsioHandle *) stream_.apiHandle;\r\n\r\n  // Check if we were draining the stream and signal if finished.\r\n  if ( handle->drainCounter > 3 ) {\r\n\r\n    stream_.state = STREAM_STOPPING;\r\n    if ( handle->internalDrain == false )\r\n      SetEvent( handle->condition );\r\n    else { // spawn a thread to stop the stream\r\n      unsigned threadId;\r\n      stream_.callbackInfo.thread = _beginthreadex( NULL, 0, &asioStopStream,\r\n                                                    &stream_.callbackInfo, 0, &threadId );\r\n    }\r\n    return SUCCESS;\r\n  }\r\n\r\n  // Invoke user callback to get fresh output data UNLESS we are\r\n  // draining stream.\r\n  if ( handle->drainCounter == 0 ) {\r\n    RtAudioCallback callback = (RtAudioCallback) info->callback;\r\n    double streamTime = getStreamTime();\r\n    RtAudioStreamStatus status = 0;\r\n    if ( stream_.mode != INPUT && asioXRun == true ) {\r\n      status |= RTAUDIO_OUTPUT_UNDERFLOW;\r\n      asioXRun = false;\r\n    }\r\n    if ( stream_.mode != OUTPUT && asioXRun == true ) {\r\n      status |= RTAUDIO_INPUT_OVERFLOW;\r\n      asioXRun = false;\r\n    }\r\n    int cbReturnValue = callback( stream_.userBuffer[0], stream_.userBuffer[1],\r\n                                     stream_.bufferSize, streamTime, status, info->userData );\r\n    if ( cbReturnValue == 2 ) {\r\n      stream_.state = STREAM_STOPPING;\r\n      handle->drainCounter = 2;\r\n      unsigned threadId;\r\n      stream_.callbackInfo.thread = _beginthreadex( NULL, 0, &asioStopStream,\r\n                                                    &stream_.callbackInfo, 0, &threadId );\r\n      return SUCCESS;\r\n    }\r\n    else if ( cbReturnValue == 1 ) {\r\n      handle->drainCounter = 1;\r\n      handle->internalDrain = true;\r\n    }\r\n  }\r\n\r\n  unsigned int nChannels, bufferBytes, i, j;\r\n  nChannels = stream_.nDeviceChannels[0] + stream_.nDeviceChannels[1];\r\n  if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) {\r\n\r\n    bufferBytes = stream_.bufferSize * formatBytes( stream_.deviceFormat[0] );\r\n\r\n    if ( handle->drainCounter > 1 ) { // write zeros to the output stream\r\n\r\n      for ( i=0, j=0; i<nChannels; i++ ) {\r\n        if ( handle->bufferInfos[i].isInput != ASIOTrue )\r\n          memset( handle->bufferInfos[i].buffers[bufferIndex], 0, bufferBytes );\r\n      }\r\n\r\n    }\r\n    else if ( stream_.doConvertBuffer[0] ) {\r\n\r\n      convertBuffer( stream_.deviceBuffer, stream_.userBuffer[0], stream_.convertInfo[0] );\r\n      if ( stream_.doByteSwap[0] )\r\n        byteSwapBuffer( stream_.deviceBuffer,\r\n                        stream_.bufferSize * stream_.nDeviceChannels[0],\r\n                        stream_.deviceFormat[0] );\r\n\r\n      for ( i=0, j=0; i<nChannels; i++ ) {\r\n        if ( handle->bufferInfos[i].isInput != ASIOTrue )\r\n          memcpy( handle->bufferInfos[i].buffers[bufferIndex],\r\n                  &stream_.deviceBuffer[j++*bufferBytes], bufferBytes );\r\n      }\r\n\r\n    }\r\n    else {\r\n\r\n      if ( stream_.doByteSwap[0] )\r\n        byteSwapBuffer( stream_.userBuffer[0],\r\n                        stream_.bufferSize * stream_.nUserChannels[0],\r\n                        stream_.userFormat );\r\n\r\n      for ( i=0, j=0; i<nChannels; i++ ) {\r\n        if ( handle->bufferInfos[i].isInput != ASIOTrue )\r\n          memcpy( handle->bufferInfos[i].buffers[bufferIndex],\r\n                  &stream_.userBuffer[0][bufferBytes*j++], bufferBytes );\r\n      }\r\n\r\n    }\r\n\r\n    if ( handle->drainCounter ) {\r\n      handle->drainCounter++;\r\n      goto unlock;\r\n    }\r\n  }\r\n\r\n  if ( stream_.mode == INPUT || stream_.mode == DUPLEX ) {\r\n\r\n    bufferBytes = stream_.bufferSize * formatBytes(stream_.deviceFormat[1]);\r\n\r\n    if (stream_.doConvertBuffer[1]) {\r\n\r\n      // Always interleave ASIO input data.\r\n      for ( i=0, j=0; i<nChannels; i++ ) {\r\n        if ( handle->bufferInfos[i].isInput == ASIOTrue )\r\n          memcpy( &stream_.deviceBuffer[j++*bufferBytes],\r\n                  handle->bufferInfos[i].buffers[bufferIndex],\r\n                  bufferBytes );\r\n      }\r\n\r\n      if ( stream_.doByteSwap[1] )\r\n        byteSwapBuffer( stream_.deviceBuffer,\r\n                        stream_.bufferSize * stream_.nDeviceChannels[1],\r\n                        stream_.deviceFormat[1] );\r\n      convertBuffer( stream_.userBuffer[1], stream_.deviceBuffer, stream_.convertInfo[1] );\r\n\r\n    }\r\n    else {\r\n      for ( i=0, j=0; i<nChannels; i++ ) {\r\n        if ( handle->bufferInfos[i].isInput == ASIOTrue ) {\r\n          memcpy( &stream_.userBuffer[1][bufferBytes*j++],\r\n                  handle->bufferInfos[i].buffers[bufferIndex],\r\n                  bufferBytes );\r\n        }\r\n      }\r\n\r\n      if ( stream_.doByteSwap[1] )\r\n        byteSwapBuffer( stream_.userBuffer[1],\r\n                        stream_.bufferSize * stream_.nUserChannels[1],\r\n                        stream_.userFormat );\r\n    }\r\n  }\r\n\r\n unlock:\r\n  // The following call was suggested by Malte Clasen.  While the API\r\n  // documentation indicates it should not be required, some device\r\n  // drivers apparently do not function correctly without it.\r\n  ASIOOutputReady();\r\n\r\n  RtApi::tickStreamTime();\r\n  return SUCCESS;\r\n}\r\n\r\nstatic void sampleRateChanged( ASIOSampleRate sRate )\r\n{\r\n  // The ASIO documentation says that this usually only happens during\r\n  // external sync.  Audio processing is not stopped by the driver,\r\n  // actual sample rate might not have even changed, maybe only the\r\n  // sample rate status of an AES/EBU or S/PDIF digital input at the\r\n  // audio device.\r\n\r\n  RtApi *object = (RtApi *) asioCallbackInfo->object;\r\n  try {\r\n    object->stopStream();\r\n  }\r\n  catch ( RtError &exception ) {\r\n    std::cerr << \"\\nRtApiAsio: sampleRateChanged() error (\" << exception.getMessage() << \")!\\n\" << std::endl;\r\n    return;\r\n  }\r\n\r\n  std::cerr << \"\\nRtApiAsio: driver reports sample rate changed to \" << sRate << \" ... stream stopped!!!\\n\" << std::endl;\r\n}\r\n\r\nstatic long asioMessages( long selector, long value, void* message, double* opt )\r\n{\r\n  long ret = 0;\r\n\r\n  switch( selector ) {\r\n  case kAsioSelectorSupported:\r\n    if ( value == kAsioResetRequest\r\n         || value == kAsioEngineVersion\r\n         || value == kAsioResyncRequest\r\n         || value == kAsioLatenciesChanged\r\n         // The following three were added for ASIO 2.0, you don't\r\n         // necessarily have to support them.\r\n         || value == kAsioSupportsTimeInfo\r\n         || value == kAsioSupportsTimeCode\r\n         || value == kAsioSupportsInputMonitor)\r\n      ret = 1L;\r\n    break;\r\n  case kAsioResetRequest:\r\n    // Defer the task and perform the reset of the driver during the\r\n    // next \"safe\" situation.  You cannot reset the driver right now,\r\n    // as this code is called from the driver.  Reset the driver is\r\n    // done by completely destruct is. I.e. ASIOStop(),\r\n    // ASIODisposeBuffers(), Destruction Afterwards you initialize the\r\n    // driver again.\r\n    std::cerr << \"\\nRtApiAsio: driver reset requested!!!\" << std::endl;\r\n    ret = 1L;\r\n    break;\r\n  case kAsioResyncRequest:\r\n    // This informs the application that the driver encountered some\r\n    // non-fatal data loss.  It is used for synchronization purposes\r\n    // of different media.  Added mainly to work around the Win16Mutex\r\n    // problems in Windows 95/98 with the Windows Multimedia system,\r\n    // which could lose data because the Mutex was held too long by\r\n    // another thread.  However a driver can issue it in other\r\n    // situations, too.\r\n    // std::cerr << \"\\nRtApiAsio: driver resync requested!!!\" << std::endl;\r\n    asioXRun = true;\r\n    ret = 1L;\r\n    break;\r\n  case kAsioLatenciesChanged:\r\n    // This will inform the host application that the drivers were\r\n    // latencies changed.  Beware, it this does not mean that the\r\n    // buffer sizes have changed!  You might need to update internal\r\n    // delay data.\r\n    std::cerr << \"\\nRtApiAsio: driver latency may have changed!!!\" << std::endl;\r\n    ret = 1L;\r\n    break;\r\n  case kAsioEngineVersion:\r\n    // Return the supported ASIO version of the host application.  If\r\n    // a host application does not implement this selector, ASIO 1.0\r\n    // is assumed by the driver.\r\n    ret = 2L;\r\n    break;\r\n  case kAsioSupportsTimeInfo:\r\n    // Informs the driver whether the\r\n    // asioCallbacks.bufferSwitchTimeInfo() callback is supported.\r\n    // For compatibility with ASIO 1.0 drivers the host application\r\n    // should always support the \"old\" bufferSwitch method, too.\r\n    ret = 0;\r\n    break;\r\n  case kAsioSupportsTimeCode:\r\n    // Informs the driver whether application is interested in time\r\n    // code info.  If an application does not need to know about time\r\n    // code, the driver has less work to do.\r\n    ret = 0;\r\n    break;\r\n  }\r\n  return ret;\r\n}\r\n\r\nstatic const char* getAsioErrorString( ASIOError result )\r\n{\r\n  struct Messages \r\n  {\r\n    ASIOError value;\r\n    const char*message;\r\n  };\r\n\r\n  static const Messages m[] = \r\n    {\r\n      {   ASE_NotPresent,    \"Hardware input or output is not present or available.\" },\r\n      {   ASE_HWMalfunction,  \"Hardware is malfunctioning.\" },\r\n      {   ASE_InvalidParameter, \"Invalid input parameter.\" },\r\n      {   ASE_InvalidMode,      \"Invalid mode.\" },\r\n      {   ASE_SPNotAdvancing,     \"Sample position not advancing.\" },\r\n      {   ASE_NoClock,            \"Sample clock or rate cannot be determined or is not present.\" },\r\n      {   ASE_NoMemory,           \"Not enough memory to complete the request.\" }\r\n    };\r\n\r\n  for ( unsigned int i = 0; i < sizeof(m)/sizeof(m[0]); ++i )\r\n    if ( m[i].value == result ) return m[i].message;\r\n\r\n  return \"Unknown error.\";\r\n}\r\n//******************** End of __WINDOWS_ASIO__ *********************//\r\n#endif\r\n\r\n\r\n#if defined(__WINDOWS_DS__) // Windows DirectSound API\r\n\r\n// Modified by Robin Davies, October 2005\r\n// - Improvements to DirectX pointer chasing. \r\n// - Bug fix for non-power-of-two Asio granularity used by Edirol PCR-A30.\r\n// - Auto-call CoInitialize for DSOUND and ASIO platforms.\r\n// Various revisions for RtAudio 4.0 by Gary Scavone, April 2007\r\n// Changed device query structure for RtAudio 4.0.7, January 2010\r\n\r\n#include <dsound.h>\r\n#include <assert.h>\r\n#include <algorithm>\r\n\r\n#if defined(__MINGW32__)\r\n  // missing from latest mingw winapi\r\n#define WAVE_FORMAT_96M08 0x00010000 /* 96 kHz, Mono, 8-bit */\r\n#define WAVE_FORMAT_96S08 0x00020000 /* 96 kHz, Stereo, 8-bit */\r\n#define WAVE_FORMAT_96M16 0x00040000 /* 96 kHz, Mono, 16-bit */\r\n#define WAVE_FORMAT_96S16 0x00080000 /* 96 kHz, Stereo, 16-bit */\r\n#endif\r\n\r\n#define MINIMUM_DEVICE_BUFFER_SIZE 32768\r\n\r\n#ifdef _MSC_VER // if Microsoft Visual C++\r\n#pragma comment( lib, \"winmm.lib\" ) // then, auto-link winmm.lib. Otherwise, it has to be added manually.\r\n#endif\r\n\r\nstatic inline DWORD dsPointerBetween( DWORD pointer, DWORD laterPointer, DWORD earlierPointer, DWORD bufferSize )\r\n{\r\n  if ( pointer > bufferSize ) pointer -= bufferSize;\r\n  if ( laterPointer < earlierPointer ) laterPointer += bufferSize;\r\n  if ( pointer < earlierPointer ) pointer += bufferSize;\r\n  return pointer >= earlierPointer && pointer < laterPointer;\r\n}\r\n\r\n// A structure to hold various information related to the DirectSound\r\n// API implementation.\r\nstruct DsHandle {\r\n  unsigned int drainCounter; // Tracks callback counts when draining\r\n  bool internalDrain;        // Indicates if stop is initiated from callback or not.\r\n  void *id[2];\r\n  void *buffer[2];\r\n  bool xrun[2];\r\n  UINT bufferPointer[2];  \r\n  DWORD dsBufferSize[2];\r\n  DWORD dsPointerLeadTime[2]; // the number of bytes ahead of the safe pointer to lead by.\r\n  HANDLE condition;\r\n\r\n  DsHandle()\r\n    :drainCounter(0), internalDrain(false) { id[0] = 0; id[1] = 0; buffer[0] = 0; buffer[1] = 0; xrun[0] = false; xrun[1] = false; bufferPointer[0] = 0; bufferPointer[1] = 0; }\r\n};\r\n\r\n// Declarations for utility functions, callbacks, and structures\r\n// specific to the DirectSound implementation.\r\nstatic BOOL CALLBACK deviceQueryCallback( LPGUID lpguid,\r\n                                          LPCTSTR description,\r\n                                          LPCTSTR module,\r\n                                          LPVOID lpContext );\r\n\r\nstatic const char* getErrorString( int code );\r\n\r\nstatic unsigned __stdcall callbackHandler( void *ptr );\r\n\r\nstruct DsDevice {\r\n  LPGUID id[2];\r\n  bool validId[2];\r\n  bool found;\r\n  std::string name;\r\n\r\n  DsDevice()\r\n  : found(false) { validId[0] = false; validId[1] = false; }\r\n};\r\n\r\nstruct DsProbeData {\r\n  bool isInput;\r\n  std::vector<struct DsDevice>* dsDevices;\r\n};\r\n\r\nRtApiDs :: RtApiDs()\r\n{\r\n  // Dsound will run both-threaded. If CoInitialize fails, then just\r\n  // accept whatever the mainline chose for a threading model.\r\n  coInitialized_ = false;\r\n  HRESULT hr = CoInitialize( NULL );\r\n  if ( !FAILED( hr ) ) coInitialized_ = true;\r\n}\r\n\r\nRtApiDs :: ~RtApiDs()\r\n{\r\n  if ( coInitialized_ ) CoUninitialize(); // balanced call.\r\n  if ( stream_.state != STREAM_CLOSED ) closeStream();\r\n}\r\n\r\n// The DirectSound default output is always the first device.\r\nunsigned int RtApiDs :: getDefaultOutputDevice( void )\r\n{\r\n  return 0;\r\n}\r\n\r\n// The DirectSound default input is always the first input device,\r\n// which is the first capture device enumerated.\r\nunsigned int RtApiDs :: getDefaultInputDevice( void )\r\n{\r\n  return 0;\r\n}\r\n\r\nunsigned int RtApiDs :: getDeviceCount( void )\r\n{\r\n  // Set query flag for previously found devices to false, so that we\r\n  // can check for any devices that have disappeared.\r\n  for ( unsigned int i=0; i<dsDevices.size(); i++ )\r\n    dsDevices[i].found = false;\r\n\r\n  // Query DirectSound devices.\r\n  struct DsProbeData probeInfo;\r\n  probeInfo.isInput = false;\r\n  probeInfo.dsDevices = &dsDevices;\r\n  HRESULT result = DirectSoundEnumerate( (LPDSENUMCALLBACK) deviceQueryCallback, &probeInfo );\r\n  if ( FAILED( result ) ) {\r\n    errorStream_ << \"RtApiDs::getDeviceCount: error (\" << getErrorString( result ) << \") enumerating output devices!\";\r\n    errorText_ = errorStream_.str();\r\n    error( RtError::WARNING );\r\n  }\r\n\r\n  // Query DirectSoundCapture devices.\r\n  probeInfo.isInput = true;\r\n  result = DirectSoundCaptureEnumerate( (LPDSENUMCALLBACK) deviceQueryCallback, &probeInfo );\r\n  if ( FAILED( result ) ) {\r\n    errorStream_ << \"RtApiDs::getDeviceCount: error (\" << getErrorString( result ) << \") enumerating input devices!\";\r\n    errorText_ = errorStream_.str();\r\n    error( RtError::WARNING );\r\n  }\r\n\r\n  // Clean out any devices that may have disappeared.\r\n  std::vector< int > indices;\r\n  for ( unsigned int i=0; i<dsDevices.size(); i++ )\r\n    if ( dsDevices[i].found == false ) indices.push_back( i );\r\n  unsigned int nErased = 0;\r\n  for ( unsigned int i=0; i<indices.size(); i++ )\r\n    dsDevices.erase( dsDevices.begin()-nErased++ );\r\n\r\n  return dsDevices.size();\r\n}\r\n\r\nRtAudio::DeviceInfo RtApiDs :: getDeviceInfo( unsigned int device )\r\n{\r\n  RtAudio::DeviceInfo info;\r\n  info.probed = false;\r\n\r\n  if ( dsDevices.size() == 0 ) {\r\n    // Force a query of all devices\r\n    getDeviceCount();\r\n    if ( dsDevices.size() == 0 ) {\r\n      errorText_ = \"RtApiDs::getDeviceInfo: no devices found!\";\r\n      error( RtError::INVALID_USE );\r\n      return info;\r\n    }\r\n  }\r\n\r\n  if ( device >= dsDevices.size() ) {\r\n    errorText_ = \"RtApiDs::getDeviceInfo: device ID is invalid!\";\r\n    error( RtError::INVALID_USE );\r\n    return info;\r\n  }\r\n\r\n  HRESULT result;\r\n  if ( dsDevices[ device ].validId[0] == false ) goto probeInput;\r\n\r\n  LPDIRECTSOUND output;\r\n  DSCAPS outCaps;\r\n  result = DirectSoundCreate( dsDevices[ device ].id[0], &output, NULL );\r\n  if ( FAILED( result ) ) {\r\n    errorStream_ << \"RtApiDs::getDeviceInfo: error (\" << getErrorString( result ) << \") opening output device (\" << dsDevices[ device ].name << \")!\";\r\n    errorText_ = errorStream_.str();\r\n    error( RtError::WARNING );\r\n    goto probeInput;\r\n  }\r\n\r\n  outCaps.dwSize = sizeof( outCaps );\r\n  result = output->GetCaps( &outCaps );\r\n  if ( FAILED( result ) ) {\r\n    output->Release();\r\n    errorStream_ << \"RtApiDs::getDeviceInfo: error (\" << getErrorString( result ) << \") getting capabilities!\";\r\n    errorText_ = errorStream_.str();\r\n    error( RtError::WARNING );\r\n    goto probeInput;\r\n  }\r\n\r\n  // Get output channel information.\r\n  info.outputChannels = ( outCaps.dwFlags & DSCAPS_PRIMARYSTEREO ) ? 2 : 1;\r\n\r\n  // Get sample rate information.\r\n  info.sampleRates.clear();\r\n  for ( unsigned int k=0; k<MAX_SAMPLE_RATES; k++ ) {\r\n    if ( SAMPLE_RATES[k] >= (unsigned int) outCaps.dwMinSecondarySampleRate &&\r\n         SAMPLE_RATES[k] <= (unsigned int) outCaps.dwMaxSecondarySampleRate )\r\n      info.sampleRates.push_back( SAMPLE_RATES[k] );\r\n  }\r\n\r\n  // Get format information.\r\n  if ( outCaps.dwFlags & DSCAPS_PRIMARY16BIT ) info.nativeFormats |= RTAUDIO_SINT16;\r\n  if ( outCaps.dwFlags & DSCAPS_PRIMARY8BIT ) info.nativeFormats |= RTAUDIO_SINT8;\r\n\r\n  output->Release();\r\n\r\n  if ( getDefaultOutputDevice() == device )\r\n    info.isDefaultOutput = true;\r\n\r\n  if ( dsDevices[ device ].validId[1] == false ) {\r\n    info.name = dsDevices[ device ].name;\r\n    info.probed = true;\r\n    return info;\r\n  }\r\n\r\n probeInput:\r\n\r\n  LPDIRECTSOUNDCAPTURE input;\r\n  result = DirectSoundCaptureCreate( dsDevices[ device ].id[1], &input, NULL );\r\n  if ( FAILED( result ) ) {\r\n    errorStream_ << \"RtApiDs::getDeviceInfo: error (\" << getErrorString( result ) << \") opening input device (\" << dsDevices[ device ].name << \")!\";\r\n    errorText_ = errorStream_.str();\r\n    error( RtError::WARNING );\r\n    return info;\r\n  }\r\n\r\n  DSCCAPS inCaps;\r\n  inCaps.dwSize = sizeof( inCaps );\r\n  result = input->GetCaps( &inCaps );\r\n  if ( FAILED( result ) ) {\r\n    input->Release();\r\n    errorStream_ << \"RtApiDs::getDeviceInfo: error (\" << getErrorString( result ) << \") getting object capabilities (\" << dsDevices[ device ].name << \")!\";\r\n    errorText_ = errorStream_.str();\r\n    error( RtError::WARNING );\r\n    return info;\r\n  }\r\n\r\n  // Get input channel information.\r\n  info.inputChannels = inCaps.dwChannels;\r\n\r\n  // Get sample rate and format information.\r\n  std::vector<unsigned int> rates;\r\n  if ( inCaps.dwChannels >= 2 ) {\r\n    if ( inCaps.dwFormats & WAVE_FORMAT_1S16 ) info.nativeFormats |= RTAUDIO_SINT16;\r\n    if ( inCaps.dwFormats & WAVE_FORMAT_2S16 ) info.nativeFormats |= RTAUDIO_SINT16;\r\n    if ( inCaps.dwFormats & WAVE_FORMAT_4S16 ) info.nativeFormats |= RTAUDIO_SINT16;\r\n    if ( inCaps.dwFormats & WAVE_FORMAT_96S16 ) info.nativeFormats |= RTAUDIO_SINT16;\r\n    if ( inCaps.dwFormats & WAVE_FORMAT_1S08 ) info.nativeFormats |= RTAUDIO_SINT8;\r\n    if ( inCaps.dwFormats & WAVE_FORMAT_2S08 ) info.nativeFormats |= RTAUDIO_SINT8;\r\n    if ( inCaps.dwFormats & WAVE_FORMAT_4S08 ) info.nativeFormats |= RTAUDIO_SINT8;\r\n    if ( inCaps.dwFormats & WAVE_FORMAT_96S08 ) info.nativeFormats |= RTAUDIO_SINT8;\r\n\r\n    if ( info.nativeFormats & RTAUDIO_SINT16 ) {\r\n      if ( inCaps.dwFormats & WAVE_FORMAT_1S16 ) rates.push_back( 11025 );\r\n      if ( inCaps.dwFormats & WAVE_FORMAT_2S16 ) rates.push_back( 22050 );\r\n      if ( inCaps.dwFormats & WAVE_FORMAT_4S16 ) rates.push_back( 44100 );\r\n      if ( inCaps.dwFormats & WAVE_FORMAT_96S16 ) rates.push_back( 96000 );\r\n    }\r\n    else if ( info.nativeFormats & RTAUDIO_SINT8 ) {\r\n      if ( inCaps.dwFormats & WAVE_FORMAT_1S08 ) rates.push_back( 11025 );\r\n      if ( inCaps.dwFormats & WAVE_FORMAT_2S08 ) rates.push_back( 22050 );\r\n      if ( inCaps.dwFormats & WAVE_FORMAT_4S08 ) rates.push_back( 44100 );\r\n      if ( inCaps.dwFormats & WAVE_FORMAT_96S08 ) rates.push_back( 96000 );\r\n    }\r\n  }\r\n  else if ( inCaps.dwChannels == 1 ) {\r\n    if ( inCaps.dwFormats & WAVE_FORMAT_1M16 ) info.nativeFormats |= RTAUDIO_SINT16;\r\n    if ( inCaps.dwFormats & WAVE_FORMAT_2M16 ) info.nativeFormats |= RTAUDIO_SINT16;\r\n    if ( inCaps.dwFormats & WAVE_FORMAT_4M16 ) info.nativeFormats |= RTAUDIO_SINT16;\r\n    if ( inCaps.dwFormats & WAVE_FORMAT_96M16 ) info.nativeFormats |= RTAUDIO_SINT16;\r\n    if ( inCaps.dwFormats & WAVE_FORMAT_1M08 ) info.nativeFormats |= RTAUDIO_SINT8;\r\n    if ( inCaps.dwFormats & WAVE_FORMAT_2M08 ) info.nativeFormats |= RTAUDIO_SINT8;\r\n    if ( inCaps.dwFormats & WAVE_FORMAT_4M08 ) info.nativeFormats |= RTAUDIO_SINT8;\r\n    if ( inCaps.dwFormats & WAVE_FORMAT_96M08 ) info.nativeFormats |= RTAUDIO_SINT8;\r\n\r\n    if ( info.nativeFormats & RTAUDIO_SINT16 ) {\r\n      if ( inCaps.dwFormats & WAVE_FORMAT_1M16 ) rates.push_back( 11025 );\r\n      if ( inCaps.dwFormats & WAVE_FORMAT_2M16 ) rates.push_back( 22050 );\r\n      if ( inCaps.dwFormats & WAVE_FORMAT_4M16 ) rates.push_back( 44100 );\r\n      if ( inCaps.dwFormats & WAVE_FORMAT_96M16 ) rates.push_back( 96000 );\r\n    }\r\n    else if ( info.nativeFormats & RTAUDIO_SINT8 ) {\r\n      if ( inCaps.dwFormats & WAVE_FORMAT_1M08 ) rates.push_back( 11025 );\r\n      if ( inCaps.dwFormats & WAVE_FORMAT_2M08 ) rates.push_back( 22050 );\r\n      if ( inCaps.dwFormats & WAVE_FORMAT_4M08 ) rates.push_back( 44100 );\r\n      if ( inCaps.dwFormats & WAVE_FORMAT_96M08 ) rates.push_back( 96000 );\r\n    }\r\n  }\r\n  else info.inputChannels = 0; // technically, this would be an error\r\n\r\n  input->Release();\r\n\r\n  if ( info.inputChannels == 0 ) return info;\r\n\r\n  // Copy the supported rates to the info structure but avoid duplication.\r\n  bool found;\r\n  for ( unsigned int i=0; i<rates.size(); i++ ) {\r\n    found = false;\r\n    for ( unsigned int j=0; j<info.sampleRates.size(); j++ ) {\r\n      if ( rates[i] == info.sampleRates[j] ) {\r\n        found = true;\r\n        break;\r\n      }\r\n    }\r\n    if ( found == false ) info.sampleRates.push_back( rates[i] );\r\n  }\r\n  std::sort( info.sampleRates.begin(), info.sampleRates.end() );\r\n\r\n  // If device opens for both playback and capture, we determine the channels.\r\n  if ( info.outputChannels > 0 && info.inputChannels > 0 )\r\n    info.duplexChannels = (info.outputChannels > info.inputChannels) ? info.inputChannels : info.outputChannels;\r\n\r\n  if ( device == 0 ) info.isDefaultInput = true;\r\n\r\n  // Copy name and return.\r\n  info.name = dsDevices[ device ].name;\r\n  info.probed = true;\r\n  return info;\r\n}\r\n\r\nbool RtApiDs :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels,\r\n                                 unsigned int firstChannel, unsigned int sampleRate,\r\n                                 RtAudioFormat format, unsigned int *bufferSize,\r\n                                 RtAudio::StreamOptions *options )\r\n{\r\n  if ( channels + firstChannel > 2 ) {\r\n    errorText_ = \"RtApiDs::probeDeviceOpen: DirectSound does not support more than 2 channels per device.\";\r\n    return FAILURE;\r\n  }\r\n\r\n  unsigned int nDevices = dsDevices.size();\r\n  if ( nDevices == 0 ) {\r\n    // This should not happen because a check is made before this function is called.\r\n    errorText_ = \"RtApiDs::probeDeviceOpen: no devices found!\";\r\n    return FAILURE;\r\n  }\r\n\r\n  if ( device >= nDevices ) {\r\n    // This should not happen because a check is made before this function is called.\r\n    errorText_ = \"RtApiDs::probeDeviceOpen: device ID is invalid!\";\r\n    return FAILURE;\r\n  }\r\n\r\n  if ( mode == OUTPUT ) {\r\n    if ( dsDevices[ device ].validId[0] == false ) {\r\n      errorStream_ << \"RtApiDs::probeDeviceOpen: device (\" << device << \") does not support output!\";\r\n      errorText_ = errorStream_.str();\r\n      return FAILURE;\r\n    }\r\n  }\r\n  else { // mode == INPUT\r\n    if ( dsDevices[ device ].validId[1] == false ) {\r\n      errorStream_ << \"RtApiDs::probeDeviceOpen: device (\" << device << \") does not support input!\";\r\n      errorText_ = errorStream_.str();\r\n      return FAILURE;\r\n    }\r\n  }\r\n\r\n  // According to a note in PortAudio, using GetDesktopWindow()\r\n  // instead of GetForegroundWindow() is supposed to avoid problems\r\n  // that occur when the application's window is not the foreground\r\n  // window.  Also, if the application window closes before the\r\n  // DirectSound buffer, DirectSound can crash.  In the past, I had\r\n  // problems when using GetDesktopWindow() but it seems fine now\r\n  // (January 2010).  I'll leave it commented here.\r\n  // HWND hWnd = GetForegroundWindow();\r\n  HWND hWnd = GetDesktopWindow();\r\n\r\n  // Check the numberOfBuffers parameter and limit the lowest value to\r\n  // two.  This is a judgement call and a value of two is probably too\r\n  // low for capture, but it should work for playback.\r\n  int nBuffers = 0;\r\n  if ( options ) nBuffers = options->numberOfBuffers;\r\n  if ( options && options->flags & RTAUDIO_MINIMIZE_LATENCY ) nBuffers = 2;\r\n  if ( nBuffers < 2 ) nBuffers = 3;\r\n\r\n  // Check the lower range of the user-specified buffer size and set\r\n  // (arbitrarily) to a lower bound of 32.\r\n  if ( *bufferSize < 32 ) *bufferSize = 32;\r\n\r\n  // Create the wave format structure.  The data format setting will\r\n  // be determined later.\r\n  WAVEFORMATEX waveFormat;\r\n  ZeroMemory( &waveFormat, sizeof(WAVEFORMATEX) );\r\n  waveFormat.wFormatTag = WAVE_FORMAT_PCM;\r\n  waveFormat.nChannels = channels + firstChannel;\r\n  waveFormat.nSamplesPerSec = (unsigned long) sampleRate;\r\n\r\n  // Determine the device buffer size. By default, we'll use the value\r\n  // defined above (32K), but we will grow it to make allowances for\r\n  // very large software buffer sizes.\r\n  DWORD dsBufferSize = MINIMUM_DEVICE_BUFFER_SIZE;\r\n  DWORD dsPointerLeadTime = 0;\r\n\r\n  void *ohandle = 0, *bhandle = 0;\r\n  HRESULT result;\r\n  if ( mode == OUTPUT ) {\r\n\r\n    LPDIRECTSOUND output;\r\n    result = DirectSoundCreate( dsDevices[ device ].id[0], &output, NULL );\r\n    if ( FAILED( result ) ) {\r\n      errorStream_ << \"RtApiDs::probeDeviceOpen: error (\" << getErrorString( result ) << \") opening output device (\" << dsDevices[ device ].name << \")!\";\r\n      errorText_ = errorStream_.str();\r\n      return FAILURE;\r\n    }\r\n\r\n    DSCAPS outCaps;\r\n    outCaps.dwSize = sizeof( outCaps );\r\n    result = output->GetCaps( &outCaps );\r\n    if ( FAILED( result ) ) {\r\n      output->Release();\r\n      errorStream_ << \"RtApiDs::probeDeviceOpen: error (\" << getErrorString( result ) << \") getting capabilities (\" << dsDevices[ device ].name << \")!\";\r\n      errorText_ = errorStream_.str();\r\n      return FAILURE;\r\n    }\r\n\r\n    // Check channel information.\r\n    if ( channels + firstChannel == 2 && !( outCaps.dwFlags & DSCAPS_PRIMARYSTEREO ) ) {\r\n      errorStream_ << \"RtApiDs::getDeviceInfo: the output device (\" << dsDevices[ device ].name << \") does not support stereo playback.\";\r\n      errorText_ = errorStream_.str();\r\n      return FAILURE;\r\n    }\r\n\r\n    // Check format information.  Use 16-bit format unless not\r\n    // supported or user requests 8-bit.\r\n    if ( outCaps.dwFlags & DSCAPS_PRIMARY16BIT &&\r\n         !( format == RTAUDIO_SINT8 && outCaps.dwFlags & DSCAPS_PRIMARY8BIT ) ) {\r\n      waveFormat.wBitsPerSample = 16;\r\n      stream_.deviceFormat[mode] = RTAUDIO_SINT16;\r\n    }\r\n    else {\r\n      waveFormat.wBitsPerSample = 8;\r\n      stream_.deviceFormat[mode] = RTAUDIO_SINT8;\r\n    }\r\n    stream_.userFormat = format;\r\n\r\n    // Update wave format structure and buffer information.\r\n    waveFormat.nBlockAlign = waveFormat.nChannels * waveFormat.wBitsPerSample / 8;\r\n    waveFormat.nAvgBytesPerSec = waveFormat.nSamplesPerSec * waveFormat.nBlockAlign;\r\n    dsPointerLeadTime = nBuffers * (*bufferSize) * (waveFormat.wBitsPerSample / 8) * channels;\r\n\r\n    // If the user wants an even bigger buffer, increase the device buffer size accordingly.\r\n    while ( dsPointerLeadTime * 2U > dsBufferSize )\r\n      dsBufferSize *= 2;\r\n\r\n    // Set cooperative level to DSSCL_EXCLUSIVE ... sound stops when window focus changes.\r\n    // result = output->SetCooperativeLevel( hWnd, DSSCL_EXCLUSIVE );\r\n    // Set cooperative level to DSSCL_PRIORITY ... sound remains when window focus changes.\r\n    result = output->SetCooperativeLevel( hWnd, DSSCL_PRIORITY );\r\n    if ( FAILED( result ) ) {\r\n      output->Release();\r\n      errorStream_ << \"RtApiDs::probeDeviceOpen: error (\" << getErrorString( result ) << \") setting cooperative level (\" << dsDevices[ device ].name << \")!\";\r\n      errorText_ = errorStream_.str();\r\n      return FAILURE;\r\n    }\r\n\r\n    // Even though we will write to the secondary buffer, we need to\r\n    // access the primary buffer to set the correct output format\r\n    // (since the default is 8-bit, 22 kHz!).  Setup the DS primary\r\n    // buffer description.\r\n    DSBUFFERDESC bufferDescription;\r\n    ZeroMemory( &bufferDescription, sizeof( DSBUFFERDESC ) );\r\n    bufferDescription.dwSize = sizeof( DSBUFFERDESC );\r\n    bufferDescription.dwFlags = DSBCAPS_PRIMARYBUFFER;\r\n\r\n    // Obtain the primary buffer\r\n    LPDIRECTSOUNDBUFFER buffer;\r\n    result = output->CreateSoundBuffer( &bufferDescription, &buffer, NULL );\r\n    if ( FAILED( result ) ) {\r\n      output->Release();\r\n      errorStream_ << \"RtApiDs::probeDeviceOpen: error (\" << getErrorString( result ) << \") accessing primary buffer (\" << dsDevices[ device ].name << \")!\";\r\n      errorText_ = errorStream_.str();\r\n      return FAILURE;\r\n    }\r\n\r\n    // Set the primary DS buffer sound format.\r\n    result = buffer->SetFormat( &waveFormat );\r\n    if ( FAILED( result ) ) {\r\n      output->Release();\r\n      errorStream_ << \"RtApiDs::probeDeviceOpen: error (\" << getErrorString( result ) << \") setting primary buffer format (\" << dsDevices[ device ].name << \")!\";\r\n      errorText_ = errorStream_.str();\r\n      return FAILURE;\r\n    }\r\n\r\n    // Setup the secondary DS buffer description.\r\n    ZeroMemory( &bufferDescription, sizeof( DSBUFFERDESC ) );\r\n    bufferDescription.dwSize = sizeof( DSBUFFERDESC );\r\n    bufferDescription.dwFlags = ( DSBCAPS_STICKYFOCUS |\r\n                                  DSBCAPS_GLOBALFOCUS |\r\n                                  DSBCAPS_GETCURRENTPOSITION2 |\r\n                                  DSBCAPS_LOCHARDWARE );  // Force hardware mixing\r\n    bufferDescription.dwBufferBytes = dsBufferSize;\r\n    bufferDescription.lpwfxFormat = &waveFormat;\r\n\r\n    // Try to create the secondary DS buffer.  If that doesn't work,\r\n    // try to use software mixing.  Otherwise, there's a problem.\r\n    result = output->CreateSoundBuffer( &bufferDescription, &buffer, NULL );\r\n    if ( FAILED( result ) ) {\r\n      bufferDescription.dwFlags = ( DSBCAPS_STICKYFOCUS |\r\n                                    DSBCAPS_GLOBALFOCUS |\r\n                                    DSBCAPS_GETCURRENTPOSITION2 |\r\n                                    DSBCAPS_LOCSOFTWARE );  // Force software mixing\r\n      result = output->CreateSoundBuffer( &bufferDescription, &buffer, NULL );\r\n      if ( FAILED( result ) ) {\r\n        output->Release();\r\n        errorStream_ << \"RtApiDs::probeDeviceOpen: error (\" << getErrorString( result ) << \") creating secondary buffer (\" << dsDevices[ device ].name << \")!\";\r\n        errorText_ = errorStream_.str();\r\n        return FAILURE;\r\n      }\r\n    }\r\n\r\n    // Get the buffer size ... might be different from what we specified.\r\n    DSBCAPS dsbcaps;\r\n    dsbcaps.dwSize = sizeof( DSBCAPS );\r\n    result = buffer->GetCaps( &dsbcaps );\r\n    if ( FAILED( result ) ) {\r\n      output->Release();\r\n      buffer->Release();\r\n      errorStream_ << \"RtApiDs::probeDeviceOpen: error (\" << getErrorString( result ) << \") getting buffer settings (\" << dsDevices[ device ].name << \")!\";\r\n      errorText_ = errorStream_.str();\r\n      return FAILURE;\r\n    }\r\n\r\n    dsBufferSize = dsbcaps.dwBufferBytes;\r\n\r\n    // Lock the DS buffer\r\n    LPVOID audioPtr;\r\n    DWORD dataLen;\r\n    result = buffer->Lock( 0, dsBufferSize, &audioPtr, &dataLen, NULL, NULL, 0 );\r\n    if ( FAILED( result ) ) {\r\n      output->Release();\r\n      buffer->Release();\r\n      errorStream_ << \"RtApiDs::probeDeviceOpen: error (\" << getErrorString( result ) << \") locking buffer (\" << dsDevices[ device ].name << \")!\";\r\n      errorText_ = errorStream_.str();\r\n      return FAILURE;\r\n    }\r\n\r\n    // Zero the DS buffer\r\n    ZeroMemory( audioPtr, dataLen );\r\n\r\n    // Unlock the DS buffer\r\n    result = buffer->Unlock( audioPtr, dataLen, NULL, 0 );\r\n    if ( FAILED( result ) ) {\r\n      output->Release();\r\n      buffer->Release();\r\n      errorStream_ << \"RtApiDs::probeDeviceOpen: error (\" << getErrorString( result ) << \") unlocking buffer (\" << dsDevices[ device ].name << \")!\";\r\n      errorText_ = errorStream_.str();\r\n      return FAILURE;\r\n    }\r\n\r\n    ohandle = (void *) output;\r\n    bhandle = (void *) buffer;\r\n  }\r\n\r\n  if ( mode == INPUT ) {\r\n\r\n    LPDIRECTSOUNDCAPTURE input;\r\n    result = DirectSoundCaptureCreate( dsDevices[ device ].id[1], &input, NULL );\r\n    if ( FAILED( result ) ) {\r\n      errorStream_ << \"RtApiDs::probeDeviceOpen: error (\" << getErrorString( result ) << \") opening input device (\" << dsDevices[ device ].name << \")!\";\r\n      errorText_ = errorStream_.str();\r\n      return FAILURE;\r\n    }\r\n\r\n    DSCCAPS inCaps;\r\n    inCaps.dwSize = sizeof( inCaps );\r\n    result = input->GetCaps( &inCaps );\r\n    if ( FAILED( result ) ) {\r\n      input->Release();\r\n      errorStream_ << \"RtApiDs::probeDeviceOpen: error (\" << getErrorString( result ) << \") getting input capabilities (\" << dsDevices[ device ].name << \")!\";\r\n      errorText_ = errorStream_.str();\r\n      return FAILURE;\r\n    }\r\n\r\n    // Check channel information.\r\n    if ( inCaps.dwChannels < channels + firstChannel ) {\r\n      errorText_ = \"RtApiDs::getDeviceInfo: the input device does not support requested input channels.\";\r\n      return FAILURE;\r\n    }\r\n\r\n    // Check format information.  Use 16-bit format unless user\r\n    // requests 8-bit.\r\n    DWORD deviceFormats;\r\n    if ( channels + firstChannel == 2 ) {\r\n      deviceFormats = WAVE_FORMAT_1S08 | WAVE_FORMAT_2S08 | WAVE_FORMAT_4S08 | WAVE_FORMAT_96S08;\r\n      if ( format == RTAUDIO_SINT8 && inCaps.dwFormats & deviceFormats ) {\r\n        waveFormat.wBitsPerSample = 8;\r\n        stream_.deviceFormat[mode] = RTAUDIO_SINT8;\r\n      }\r\n      else { // assume 16-bit is supported\r\n        waveFormat.wBitsPerSample = 16;\r\n        stream_.deviceFormat[mode] = RTAUDIO_SINT16;\r\n      }\r\n    }\r\n    else { // channel == 1\r\n      deviceFormats = WAVE_FORMAT_1M08 | WAVE_FORMAT_2M08 | WAVE_FORMAT_4M08 | WAVE_FORMAT_96M08;\r\n      if ( format == RTAUDIO_SINT8 && inCaps.dwFormats & deviceFormats ) {\r\n        waveFormat.wBitsPerSample = 8;\r\n        stream_.deviceFormat[mode] = RTAUDIO_SINT8;\r\n      }\r\n      else { // assume 16-bit is supported\r\n        waveFormat.wBitsPerSample = 16;\r\n        stream_.deviceFormat[mode] = RTAUDIO_SINT16;\r\n      }\r\n    }\r\n    stream_.userFormat = format;\r\n\r\n    // Update wave format structure and buffer information.\r\n    waveFormat.nBlockAlign = waveFormat.nChannels * waveFormat.wBitsPerSample / 8;\r\n    waveFormat.nAvgBytesPerSec = waveFormat.nSamplesPerSec * waveFormat.nBlockAlign;\r\n    dsPointerLeadTime = nBuffers * (*bufferSize) * (waveFormat.wBitsPerSample / 8) * channels;\r\n\r\n    // If the user wants an even bigger buffer, increase the device buffer size accordingly.\r\n    while ( dsPointerLeadTime * 2U > dsBufferSize )\r\n      dsBufferSize *= 2;\r\n\r\n    // Setup the secondary DS buffer description.\r\n    DSCBUFFERDESC bufferDescription;\r\n    ZeroMemory( &bufferDescription, sizeof( DSCBUFFERDESC ) );\r\n    bufferDescription.dwSize = sizeof( DSCBUFFERDESC );\r\n    bufferDescription.dwFlags = 0;\r\n    bufferDescription.dwReserved = 0;\r\n    bufferDescription.dwBufferBytes = dsBufferSize;\r\n    bufferDescription.lpwfxFormat = &waveFormat;\r\n\r\n    // Create the capture buffer.\r\n    LPDIRECTSOUNDCAPTUREBUFFER buffer;\r\n    result = input->CreateCaptureBuffer( &bufferDescription, &buffer, NULL );\r\n    if ( FAILED( result ) ) {\r\n      input->Release();\r\n      errorStream_ << \"RtApiDs::probeDeviceOpen: error (\" << getErrorString( result ) << \") creating input buffer (\" << dsDevices[ device ].name << \")!\";\r\n      errorText_ = errorStream_.str();\r\n      return FAILURE;\r\n    }\r\n\r\n    // Get the buffer size ... might be different from what we specified.\r\n    DSCBCAPS dscbcaps;\r\n    dscbcaps.dwSize = sizeof( DSCBCAPS );\r\n    result = buffer->GetCaps( &dscbcaps );\r\n    if ( FAILED( result ) ) {\r\n      input->Release();\r\n      buffer->Release();\r\n      errorStream_ << \"RtApiDs::probeDeviceOpen: error (\" << getErrorString( result ) << \") getting buffer settings (\" << dsDevices[ device ].name << \")!\";\r\n      errorText_ = errorStream_.str();\r\n      return FAILURE;\r\n    }\r\n\r\n    dsBufferSize = dscbcaps.dwBufferBytes;\r\n\r\n    // NOTE: We could have a problem here if this is a duplex stream\r\n    // and the play and capture hardware buffer sizes are different\r\n    // (I'm actually not sure if that is a problem or not).\r\n    // Currently, we are not verifying that.\r\n\r\n    // Lock the capture buffer\r\n    LPVOID audioPtr;\r\n    DWORD dataLen;\r\n    result = buffer->Lock( 0, dsBufferSize, &audioPtr, &dataLen, NULL, NULL, 0 );\r\n    if ( FAILED( result ) ) {\r\n      input->Release();\r\n      buffer->Release();\r\n      errorStream_ << \"RtApiDs::probeDeviceOpen: error (\" << getErrorString( result ) << \") locking input buffer (\" << dsDevices[ device ].name << \")!\";\r\n      errorText_ = errorStream_.str();\r\n      return FAILURE;\r\n    }\r\n\r\n    // Zero the buffer\r\n    ZeroMemory( audioPtr, dataLen );\r\n\r\n    // Unlock the buffer\r\n    result = buffer->Unlock( audioPtr, dataLen, NULL, 0 );\r\n    if ( FAILED( result ) ) {\r\n      input->Release();\r\n      buffer->Release();\r\n      errorStream_ << \"RtApiDs::probeDeviceOpen: error (\" << getErrorString( result ) << \") unlocking input buffer (\" << dsDevices[ device ].name << \")!\";\r\n      errorText_ = errorStream_.str();\r\n      return FAILURE;\r\n    }\r\n\r\n    ohandle = (void *) input;\r\n    bhandle = (void *) buffer;\r\n  }\r\n\r\n  // Set various stream parameters\r\n  DsHandle *handle = 0;\r\n  stream_.nDeviceChannels[mode] = channels + firstChannel;\r\n  stream_.nUserChannels[mode] = channels;\r\n  stream_.bufferSize = *bufferSize;\r\n  stream_.channelOffset[mode] = firstChannel;\r\n  stream_.deviceInterleaved[mode] = true;\r\n  if ( options && options->flags & RTAUDIO_NONINTERLEAVED ) stream_.userInterleaved = false;\r\n  else stream_.userInterleaved = true;\r\n\r\n  // Set flag for buffer conversion\r\n  stream_.doConvertBuffer[mode] = false;\r\n  if (stream_.nUserChannels[mode] != stream_.nDeviceChannels[mode])\r\n    stream_.doConvertBuffer[mode] = true;\r\n  if (stream_.userFormat != stream_.deviceFormat[mode])\r\n    stream_.doConvertBuffer[mode] = true;\r\n  if ( stream_.userInterleaved != stream_.deviceInterleaved[mode] &&\r\n       stream_.nUserChannels[mode] > 1 )\r\n    stream_.doConvertBuffer[mode] = true;\r\n\r\n  // Allocate necessary internal buffers\r\n  long bufferBytes = stream_.nUserChannels[mode] * *bufferSize * formatBytes( stream_.userFormat );\r\n  stream_.userBuffer[mode] = (char *) calloc( bufferBytes, 1 );\r\n  if ( stream_.userBuffer[mode] == NULL ) {\r\n    errorText_ = \"RtApiDs::probeDeviceOpen: error allocating user buffer memory.\";\r\n    goto error;\r\n  }\r\n\r\n  if ( stream_.doConvertBuffer[mode] ) {\r\n\r\n    bool makeBuffer = true;\r\n    bufferBytes = stream_.nDeviceChannels[mode] * formatBytes( stream_.deviceFormat[mode] );\r\n    if ( mode == INPUT ) {\r\n      if ( stream_.mode == OUTPUT && stream_.deviceBuffer ) {\r\n        unsigned long bytesOut = stream_.nDeviceChannels[0] * formatBytes( stream_.deviceFormat[0] );\r\n        if ( bufferBytes <= (long) bytesOut ) makeBuffer = false;\r\n      }\r\n    }\r\n\r\n    if ( makeBuffer ) {\r\n      bufferBytes *= *bufferSize;\r\n      if ( stream_.deviceBuffer ) free( stream_.deviceBuffer );\r\n      stream_.deviceBuffer = (char *) calloc( bufferBytes, 1 );\r\n      if ( stream_.deviceBuffer == NULL ) {\r\n        errorText_ = \"RtApiDs::probeDeviceOpen: error allocating device buffer memory.\";\r\n        goto error;\r\n      }\r\n    }\r\n  }\r\n\r\n  // Allocate our DsHandle structures for the stream.\r\n  if ( stream_.apiHandle == 0 ) {\r\n    try {\r\n      handle = new DsHandle;\r\n    }\r\n    catch ( std::bad_alloc& ) {\r\n      errorText_ = \"RtApiDs::probeDeviceOpen: error allocating AsioHandle memory.\";\r\n      goto error;\r\n    }\r\n\r\n    // Create a manual-reset event.\r\n    handle->condition = CreateEvent( NULL,   // no security\r\n                                     TRUE,   // manual-reset\r\n                                     FALSE,  // non-signaled initially\r\n                                     NULL ); // unnamed\r\n    stream_.apiHandle = (void *) handle;\r\n  }\r\n  else\r\n    handle = (DsHandle *) stream_.apiHandle;\r\n  handle->id[mode] = ohandle;\r\n  handle->buffer[mode] = bhandle;\r\n  handle->dsBufferSize[mode] = dsBufferSize;\r\n  handle->dsPointerLeadTime[mode] = dsPointerLeadTime;\r\n\r\n  stream_.device[mode] = device;\r\n  stream_.state = STREAM_STOPPED;\r\n  if ( stream_.mode == OUTPUT && mode == INPUT )\r\n    // We had already set up an output stream.\r\n    stream_.mode = DUPLEX;\r\n  else\r\n    stream_.mode = mode;\r\n  stream_.nBuffers = nBuffers;\r\n  stream_.sampleRate = sampleRate;\r\n\r\n  // Setup the buffer conversion information structure.\r\n  if ( stream_.doConvertBuffer[mode] ) setConvertInfo( mode, firstChannel );\r\n\r\n  // Setup the callback thread.\r\n  if ( stream_.callbackInfo.isRunning == false ) {\r\n    unsigned threadId;\r\n    stream_.callbackInfo.isRunning = true;\r\n    stream_.callbackInfo.object = (void *) this;\r\n    stream_.callbackInfo.thread = _beginthreadex( NULL, 0, &callbackHandler,\r\n                                                  &stream_.callbackInfo, 0, &threadId );\r\n    if ( stream_.callbackInfo.thread == 0 ) {\r\n      errorText_ = \"RtApiDs::probeDeviceOpen: error creating callback thread!\";\r\n      goto error;\r\n    }\r\n\r\n    // Boost DS thread priority\r\n    SetThreadPriority( (HANDLE) stream_.callbackInfo.thread, THREAD_PRIORITY_HIGHEST );\r\n  }\r\n  return SUCCESS;\r\n\r\n error:\r\n  if ( handle ) {\r\n    if ( handle->buffer[0] ) { // the object pointer can be NULL and valid\r\n      LPDIRECTSOUND object = (LPDIRECTSOUND) handle->id[0];\r\n      LPDIRECTSOUNDBUFFER buffer = (LPDIRECTSOUNDBUFFER) handle->buffer[0];\r\n      if ( buffer ) buffer->Release();\r\n      object->Release();\r\n    }\r\n    if ( handle->buffer[1] ) {\r\n      LPDIRECTSOUNDCAPTURE object = (LPDIRECTSOUNDCAPTURE) handle->id[1];\r\n      LPDIRECTSOUNDCAPTUREBUFFER buffer = (LPDIRECTSOUNDCAPTUREBUFFER) handle->buffer[1];\r\n      if ( buffer ) buffer->Release();\r\n      object->Release();\r\n    }\r\n    CloseHandle( handle->condition );\r\n    delete handle;\r\n    stream_.apiHandle = 0;\r\n  }\r\n\r\n  for ( int i=0; i<2; i++ ) {\r\n    if ( stream_.userBuffer[i] ) {\r\n      free( stream_.userBuffer[i] );\r\n      stream_.userBuffer[i] = 0;\r\n    }\r\n  }\r\n\r\n  if ( stream_.deviceBuffer ) {\r\n    free( stream_.deviceBuffer );\r\n    stream_.deviceBuffer = 0;\r\n  }\r\n\r\n  stream_.state = STREAM_CLOSED;\r\n  return FAILURE;\r\n}\r\n\r\nvoid RtApiDs :: closeStream()\r\n{\r\n  if ( stream_.state == STREAM_CLOSED ) {\r\n    errorText_ = \"RtApiDs::closeStream(): no open stream to close!\";\r\n    error( RtError::WARNING );\r\n    return;\r\n  }\r\n\r\n  // Stop the callback thread.\r\n  stream_.callbackInfo.isRunning = false;\r\n  WaitForSingleObject( (HANDLE) stream_.callbackInfo.thread, INFINITE );\r\n  CloseHandle( (HANDLE) stream_.callbackInfo.thread );\r\n\r\n  DsHandle *handle = (DsHandle *) stream_.apiHandle;\r\n  if ( handle ) {\r\n    if ( handle->buffer[0] ) { // the object pointer can be NULL and valid\r\n      LPDIRECTSOUND object = (LPDIRECTSOUND) handle->id[0];\r\n      LPDIRECTSOUNDBUFFER buffer = (LPDIRECTSOUNDBUFFER) handle->buffer[0];\r\n      if ( buffer ) {\r\n        buffer->Stop();\r\n        buffer->Release();\r\n      }\r\n      object->Release();\r\n    }\r\n    if ( handle->buffer[1] ) {\r\n      LPDIRECTSOUNDCAPTURE object = (LPDIRECTSOUNDCAPTURE) handle->id[1];\r\n      LPDIRECTSOUNDCAPTUREBUFFER buffer = (LPDIRECTSOUNDCAPTUREBUFFER) handle->buffer[1];\r\n      if ( buffer ) {\r\n        buffer->Stop();\r\n        buffer->Release();\r\n      }\r\n      object->Release();\r\n    }\r\n    CloseHandle( handle->condition );\r\n    delete handle;\r\n    stream_.apiHandle = 0;\r\n  }\r\n\r\n  for ( int i=0; i<2; i++ ) {\r\n    if ( stream_.userBuffer[i] ) {\r\n      free( stream_.userBuffer[i] );\r\n      stream_.userBuffer[i] = 0;\r\n    }\r\n  }\r\n\r\n  if ( stream_.deviceBuffer ) {\r\n    free( stream_.deviceBuffer );\r\n    stream_.deviceBuffer = 0;\r\n  }\r\n\r\n  stream_.mode = UNINITIALIZED;\r\n  stream_.state = STREAM_CLOSED;\r\n}\r\n\r\nvoid RtApiDs :: startStream()\r\n{\r\n  verifyStream();\r\n  if ( stream_.state == STREAM_RUNNING ) {\r\n    errorText_ = \"RtApiDs::startStream(): the stream is already running!\";\r\n    error( RtError::WARNING );\r\n    return;\r\n  }\r\n\r\n  DsHandle *handle = (DsHandle *) stream_.apiHandle;\r\n\r\n  // Increase scheduler frequency on lesser windows (a side-effect of\r\n  // increasing timer accuracy).  On greater windows (Win2K or later),\r\n  // this is already in effect.\r\n  timeBeginPeriod( 1 ); \r\n\r\n  buffersRolling = false;\r\n  duplexPrerollBytes = 0;\r\n\r\n  if ( stream_.mode == DUPLEX ) {\r\n    // 0.5 seconds of silence in DUPLEX mode while the devices spin up and synchronize.\r\n    duplexPrerollBytes = (int) ( 0.5 * stream_.sampleRate * formatBytes( stream_.deviceFormat[1] ) * stream_.nDeviceChannels[1] );\r\n  }\r\n\r\n  HRESULT result = 0;\r\n  if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) {\r\n\r\n    LPDIRECTSOUNDBUFFER buffer = (LPDIRECTSOUNDBUFFER) handle->buffer[0];\r\n    result = buffer->Play( 0, 0, DSBPLAY_LOOPING );\r\n    if ( FAILED( result ) ) {\r\n      errorStream_ << \"RtApiDs::startStream: error (\" << getErrorString( result ) << \") starting output buffer!\";\r\n      errorText_ = errorStream_.str();\r\n      goto unlock;\r\n    }\r\n  }\r\n\r\n  if ( stream_.mode == INPUT || stream_.mode == DUPLEX ) {\r\n\r\n    LPDIRECTSOUNDCAPTUREBUFFER buffer = (LPDIRECTSOUNDCAPTUREBUFFER) handle->buffer[1];\r\n    result = buffer->Start( DSCBSTART_LOOPING );\r\n    if ( FAILED( result ) ) {\r\n      errorStream_ << \"RtApiDs::startStream: error (\" << getErrorString( result ) << \") starting input buffer!\";\r\n      errorText_ = errorStream_.str();\r\n      goto unlock;\r\n    }\r\n  }\r\n\r\n  handle->drainCounter = 0;\r\n  handle->internalDrain = false;\r\n  ResetEvent( handle->condition );\r\n  stream_.state = STREAM_RUNNING;\r\n\r\n unlock:\r\n  if ( FAILED( result ) ) error( RtError::SYSTEM_ERROR );\r\n}\r\n\r\nvoid RtApiDs :: stopStream()\r\n{\r\n  verifyStream();\r\n  if ( stream_.state == STREAM_STOPPED ) {\r\n    errorText_ = \"RtApiDs::stopStream(): the stream is already stopped!\";\r\n    error( RtError::WARNING );\r\n    return;\r\n  }\r\n\r\n  HRESULT result = 0;\r\n  LPVOID audioPtr;\r\n  DWORD dataLen;\r\n  DsHandle *handle = (DsHandle *) stream_.apiHandle;\r\n  if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) {\r\n    if ( handle->drainCounter == 0 ) {\r\n      handle->drainCounter = 2;\r\n      WaitForSingleObject( handle->condition, INFINITE );  // block until signaled\r\n    }\r\n\r\n    stream_.state = STREAM_STOPPED;\r\n\r\n    // Stop the buffer and clear memory\r\n    LPDIRECTSOUNDBUFFER buffer = (LPDIRECTSOUNDBUFFER) handle->buffer[0];\r\n    result = buffer->Stop();\r\n    if ( FAILED( result ) ) {\r\n      errorStream_ << \"RtApiDs::stopStream: error (\" << getErrorString( result ) << \") stopping output buffer!\";\r\n      errorText_ = errorStream_.str();\r\n      goto unlock;\r\n    }\r\n\r\n    // Lock the buffer and clear it so that if we start to play again,\r\n    // we won't have old data playing.\r\n    result = buffer->Lock( 0, handle->dsBufferSize[0], &audioPtr, &dataLen, NULL, NULL, 0 );\r\n    if ( FAILED( result ) ) {\r\n      errorStream_ << \"RtApiDs::stopStream: error (\" << getErrorString( result ) << \") locking output buffer!\";\r\n      errorText_ = errorStream_.str();\r\n      goto unlock;\r\n    }\r\n\r\n    // Zero the DS buffer\r\n    ZeroMemory( audioPtr, dataLen );\r\n\r\n    // Unlock the DS buffer\r\n    result = buffer->Unlock( audioPtr, dataLen, NULL, 0 );\r\n    if ( FAILED( result ) ) {\r\n      errorStream_ << \"RtApiDs::stopStream: error (\" << getErrorString( result ) << \") unlocking output buffer!\";\r\n      errorText_ = errorStream_.str();\r\n      goto unlock;\r\n    }\r\n\r\n    // If we start playing again, we must begin at beginning of buffer.\r\n    handle->bufferPointer[0] = 0;\r\n  }\r\n\r\n  if ( stream_.mode == INPUT || stream_.mode == DUPLEX ) {\r\n    LPDIRECTSOUNDCAPTUREBUFFER buffer = (LPDIRECTSOUNDCAPTUREBUFFER) handle->buffer[1];\r\n    audioPtr = NULL;\r\n    dataLen = 0;\r\n\r\n    stream_.state = STREAM_STOPPED;\r\n\r\n    result = buffer->Stop();\r\n    if ( FAILED( result ) ) {\r\n      errorStream_ << \"RtApiDs::stopStream: error (\" << getErrorString( result ) << \") stopping input buffer!\";\r\n      errorText_ = errorStream_.str();\r\n      goto unlock;\r\n    }\r\n\r\n    // Lock the buffer and clear it so that if we start to play again,\r\n    // we won't have old data playing.\r\n    result = buffer->Lock( 0, handle->dsBufferSize[1], &audioPtr, &dataLen, NULL, NULL, 0 );\r\n    if ( FAILED( result ) ) {\r\n      errorStream_ << \"RtApiDs::stopStream: error (\" << getErrorString( result ) << \") locking input buffer!\";\r\n      errorText_ = errorStream_.str();\r\n      goto unlock;\r\n    }\r\n\r\n    // Zero the DS buffer\r\n    ZeroMemory( audioPtr, dataLen );\r\n\r\n    // Unlock the DS buffer\r\n    result = buffer->Unlock( audioPtr, dataLen, NULL, 0 );\r\n    if ( FAILED( result ) ) {\r\n      errorStream_ << \"RtApiDs::stopStream: error (\" << getErrorString( result ) << \") unlocking input buffer!\";\r\n      errorText_ = errorStream_.str();\r\n      goto unlock;\r\n    }\r\n\r\n    // If we start recording again, we must begin at beginning of buffer.\r\n    handle->bufferPointer[1] = 0;\r\n  }\r\n\r\n unlock:\r\n  timeEndPeriod( 1 ); // revert to normal scheduler frequency on lesser windows.\r\n  if ( FAILED( result ) ) error( RtError::SYSTEM_ERROR );\r\n}\r\n\r\nvoid RtApiDs :: abortStream()\r\n{\r\n  verifyStream();\r\n  if ( stream_.state == STREAM_STOPPED ) {\r\n    errorText_ = \"RtApiDs::abortStream(): the stream is already stopped!\";\r\n    error( RtError::WARNING );\r\n    return;\r\n  }\r\n\r\n  DsHandle *handle = (DsHandle *) stream_.apiHandle;\r\n  handle->drainCounter = 2;\r\n\r\n  stopStream();\r\n}\r\n\r\nvoid RtApiDs :: callbackEvent()\r\n{\r\n  if ( stream_.state == STREAM_STOPPED || stream_.state == STREAM_STOPPING ) {\r\n    Sleep( 50 ); // sleep 50 milliseconds\r\n    return;\r\n  }\r\n\r\n  if ( stream_.state == STREAM_CLOSED ) {\r\n    errorText_ = \"RtApiDs::callbackEvent(): the stream is closed ... this shouldn't happen!\";\r\n    error( RtError::WARNING );\r\n    return;\r\n  }\r\n\r\n  CallbackInfo *info = (CallbackInfo *) &stream_.callbackInfo;\r\n  DsHandle *handle = (DsHandle *) stream_.apiHandle;\r\n\r\n  // Check if we were draining the stream and signal is finished.\r\n  if ( handle->drainCounter > stream_.nBuffers + 2 ) {\r\n\r\n    stream_.state = STREAM_STOPPING;\r\n    if ( handle->internalDrain == false )\r\n      SetEvent( handle->condition );\r\n    else\r\n      stopStream();\r\n    return;\r\n  }\r\n\r\n  // Invoke user callback to get fresh output data UNLESS we are\r\n  // draining stream.\r\n  if ( handle->drainCounter == 0 ) {\r\n    RtAudioCallback callback = (RtAudioCallback) info->callback;\r\n    double streamTime = getStreamTime();\r\n    RtAudioStreamStatus status = 0;\r\n    if ( stream_.mode != INPUT && handle->xrun[0] == true ) {\r\n      status |= RTAUDIO_OUTPUT_UNDERFLOW;\r\n      handle->xrun[0] = false;\r\n    }\r\n    if ( stream_.mode != OUTPUT && handle->xrun[1] == true ) {\r\n      status |= RTAUDIO_INPUT_OVERFLOW;\r\n      handle->xrun[1] = false;\r\n    }\r\n    int cbReturnValue = callback( stream_.userBuffer[0], stream_.userBuffer[1],\r\n                                  stream_.bufferSize, streamTime, status, info->userData );\r\n    if ( cbReturnValue == 2 ) {\r\n      stream_.state = STREAM_STOPPING;\r\n      handle->drainCounter = 2;\r\n      abortStream();\r\n      return;\r\n    }\r\n    else if ( cbReturnValue == 1 ) {\r\n      handle->drainCounter = 1;\r\n      handle->internalDrain = true;\r\n    }\r\n  }\r\n\r\n  HRESULT result;\r\n  DWORD currentWritePointer, safeWritePointer;\r\n  DWORD currentReadPointer, safeReadPointer;\r\n  UINT nextWritePointer;\r\n\r\n  LPVOID buffer1 = NULL;\r\n  LPVOID buffer2 = NULL;\r\n  DWORD bufferSize1 = 0;\r\n  DWORD bufferSize2 = 0;\r\n\r\n  char *buffer;\r\n  long bufferBytes;\r\n\r\n  if ( buffersRolling == false ) {\r\n    if ( stream_.mode == DUPLEX ) {\r\n      //assert( handle->dsBufferSize[0] == handle->dsBufferSize[1] );\r\n\r\n      // It takes a while for the devices to get rolling. As a result,\r\n      // there's no guarantee that the capture and write device pointers\r\n      // will move in lockstep.  Wait here for both devices to start\r\n      // rolling, and then set our buffer pointers accordingly.\r\n      // e.g. Crystal Drivers: the capture buffer starts up 5700 to 9600\r\n      // bytes later than the write buffer.\r\n\r\n      // Stub: a serious risk of having a pre-emptive scheduling round\r\n      // take place between the two GetCurrentPosition calls... but I'm\r\n      // really not sure how to solve the problem.  Temporarily boost to\r\n      // Realtime priority, maybe; but I'm not sure what priority the\r\n      // DirectSound service threads run at. We *should* be roughly\r\n      // within a ms or so of correct.\r\n\r\n      LPDIRECTSOUNDBUFFER dsWriteBuffer = (LPDIRECTSOUNDBUFFER) handle->buffer[0];\r\n      LPDIRECTSOUNDCAPTUREBUFFER dsCaptureBuffer = (LPDIRECTSOUNDCAPTUREBUFFER) handle->buffer[1];\r\n\r\n      DWORD startSafeWritePointer, startSafeReadPointer;\r\n\r\n      result = dsWriteBuffer->GetCurrentPosition( NULL, &startSafeWritePointer );\r\n      if ( FAILED( result ) ) {\r\n        errorStream_ << \"RtApiDs::callbackEvent: error (\" << getErrorString( result ) << \") getting current write position!\";\r\n        errorText_ = errorStream_.str();\r\n        error( RtError::SYSTEM_ERROR );\r\n        return;\r\n      }\r\n      result = dsCaptureBuffer->GetCurrentPosition( NULL, &startSafeReadPointer );\r\n      if ( FAILED( result ) ) {\r\n        errorStream_ << \"RtApiDs::callbackEvent: error (\" << getErrorString( result ) << \") getting current read position!\";\r\n        errorText_ = errorStream_.str();\r\n        error( RtError::SYSTEM_ERROR );\r\n        return;\r\n      }\r\n      while ( true ) {\r\n        result = dsWriteBuffer->GetCurrentPosition( NULL, &safeWritePointer );\r\n        if ( FAILED( result ) ) {\r\n          errorStream_ << \"RtApiDs::callbackEvent: error (\" << getErrorString( result ) << \") getting current write position!\";\r\n          errorText_ = errorStream_.str();\r\n          error( RtError::SYSTEM_ERROR );\r\n          return;\r\n        }\r\n        result = dsCaptureBuffer->GetCurrentPosition( NULL, &safeReadPointer );\r\n        if ( FAILED( result ) ) {\r\n          errorStream_ << \"RtApiDs::callbackEvent: error (\" << getErrorString( result ) << \") getting current read position!\";\r\n          errorText_ = errorStream_.str();\r\n          error( RtError::SYSTEM_ERROR );\r\n          return;\r\n        }\r\n        if ( safeWritePointer != startSafeWritePointer && safeReadPointer != startSafeReadPointer ) break;\r\n        Sleep( 1 );\r\n      }\r\n\r\n      //assert( handle->dsBufferSize[0] == handle->dsBufferSize[1] );\r\n\r\n      handle->bufferPointer[0] = safeWritePointer + handle->dsPointerLeadTime[0];\r\n      if ( handle->bufferPointer[0] >= handle->dsBufferSize[0] ) handle->bufferPointer[0] -= handle->dsBufferSize[0];\r\n      handle->bufferPointer[1] = safeReadPointer;\r\n    }\r\n    else if ( stream_.mode == OUTPUT ) {\r\n\r\n      // Set the proper nextWritePosition after initial startup.\r\n      LPDIRECTSOUNDBUFFER dsWriteBuffer = (LPDIRECTSOUNDBUFFER) handle->buffer[0];\r\n      result = dsWriteBuffer->GetCurrentPosition( &currentWritePointer, &safeWritePointer );\r\n      if ( FAILED( result ) ) {\r\n        errorStream_ << \"RtApiDs::callbackEvent: error (\" << getErrorString( result ) << \") getting current write position!\";\r\n        errorText_ = errorStream_.str();\r\n        error( RtError::SYSTEM_ERROR );\r\n        return;\r\n      }\r\n      handle->bufferPointer[0] = safeWritePointer + handle->dsPointerLeadTime[0];\r\n      if ( handle->bufferPointer[0] >= handle->dsBufferSize[0] ) handle->bufferPointer[0] -= handle->dsBufferSize[0];\r\n    }\r\n\r\n    buffersRolling = true;\r\n  }\r\n\r\n  if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) {\r\n    \r\n    LPDIRECTSOUNDBUFFER dsBuffer = (LPDIRECTSOUNDBUFFER) handle->buffer[0];\r\n\r\n    if ( handle->drainCounter > 1 ) { // write zeros to the output stream\r\n      bufferBytes = stream_.bufferSize * stream_.nUserChannels[0];\r\n      bufferBytes *= formatBytes( stream_.userFormat );\r\n      memset( stream_.userBuffer[0], 0, bufferBytes );\r\n    }\r\n\r\n    // Setup parameters and do buffer conversion if necessary.\r\n    if ( stream_.doConvertBuffer[0] ) {\r\n      buffer = stream_.deviceBuffer;\r\n      convertBuffer( buffer, stream_.userBuffer[0], stream_.convertInfo[0] );\r\n      bufferBytes = stream_.bufferSize * stream_.nDeviceChannels[0];\r\n      bufferBytes *= formatBytes( stream_.deviceFormat[0] );\r\n    }\r\n    else {\r\n      buffer = stream_.userBuffer[0];\r\n      bufferBytes = stream_.bufferSize * stream_.nUserChannels[0];\r\n      bufferBytes *= formatBytes( stream_.userFormat );\r\n    }\r\n\r\n    // No byte swapping necessary in DirectSound implementation.\r\n\r\n    // Ahhh ... windoze.  16-bit data is signed but 8-bit data is\r\n    // unsigned.  So, we need to convert our signed 8-bit data here to\r\n    // unsigned.\r\n    if ( stream_.deviceFormat[0] == RTAUDIO_SINT8 )\r\n      for ( int i=0; i<bufferBytes; i++ ) buffer[i] = (unsigned char) ( buffer[i] + 128 );\r\n\r\n    DWORD dsBufferSize = handle->dsBufferSize[0];\r\n    nextWritePointer = handle->bufferPointer[0];\r\n\r\n    DWORD endWrite, leadPointer;\r\n    while ( true ) {\r\n      // Find out where the read and \"safe write\" pointers are.\r\n      result = dsBuffer->GetCurrentPosition( &currentWritePointer, &safeWritePointer );\r\n      if ( FAILED( result ) ) {\r\n        errorStream_ << \"RtApiDs::callbackEvent: error (\" << getErrorString( result ) << \") getting current write position!\";\r\n        errorText_ = errorStream_.str();\r\n        error( RtError::SYSTEM_ERROR );\r\n        return;\r\n      }\r\n\r\n      // We will copy our output buffer into the region between\r\n      // safeWritePointer and leadPointer.  If leadPointer is not\r\n      // beyond the next endWrite position, wait until it is.\r\n      leadPointer = safeWritePointer + handle->dsPointerLeadTime[0];\r\n      //std::cout << \"safeWritePointer = \" << safeWritePointer << \", leadPointer = \" << leadPointer << \", nextWritePointer = \" << nextWritePointer << std::endl;\r\n      if ( leadPointer > dsBufferSize ) leadPointer -= dsBufferSize;\r\n      if ( leadPointer < nextWritePointer ) leadPointer += dsBufferSize; // unwrap offset\r\n      endWrite = nextWritePointer + bufferBytes;\r\n\r\n      // Check whether the entire write region is behind the play pointer.\r\n      if ( leadPointer >= endWrite ) break;\r\n\r\n      // If we are here, then we must wait until the leadPointer advances\r\n      // beyond the end of our next write region. We use the\r\n      // Sleep() function to suspend operation until that happens.\r\n      double millis = ( endWrite - leadPointer ) * 1000.0;\r\n      millis /= ( formatBytes( stream_.deviceFormat[0]) * stream_.nDeviceChannels[0] * stream_.sampleRate);\r\n      if ( millis < 1.0 ) millis = 1.0;\r\n      Sleep( (DWORD) millis );\r\n    }\r\n\r\n    if ( dsPointerBetween( nextWritePointer, safeWritePointer, currentWritePointer, dsBufferSize )\r\n         || dsPointerBetween( endWrite, safeWritePointer, currentWritePointer, dsBufferSize ) ) { \r\n      // We've strayed into the forbidden zone ... resync the read pointer.\r\n      handle->xrun[0] = true;\r\n      nextWritePointer = safeWritePointer + handle->dsPointerLeadTime[0] - bufferBytes;\r\n      if ( nextWritePointer >= dsBufferSize ) nextWritePointer -= dsBufferSize;\r\n      handle->bufferPointer[0] = nextWritePointer;\r\n      endWrite = nextWritePointer + bufferBytes;\r\n    }\r\n\r\n    // Lock free space in the buffer\r\n    result = dsBuffer->Lock( nextWritePointer, bufferBytes, &buffer1,\r\n                             &bufferSize1, &buffer2, &bufferSize2, 0 );\r\n    if ( FAILED( result ) ) {\r\n      errorStream_ << \"RtApiDs::callbackEvent: error (\" << getErrorString( result ) << \") locking buffer during playback!\";\r\n      errorText_ = errorStream_.str();\r\n      error( RtError::SYSTEM_ERROR );\r\n      return;\r\n    }\r\n\r\n    // Copy our buffer into the DS buffer\r\n    CopyMemory( buffer1, buffer, bufferSize1 );\r\n    if ( buffer2 != NULL ) CopyMemory( buffer2, buffer+bufferSize1, bufferSize2 );\r\n\r\n    // Update our buffer offset and unlock sound buffer\r\n    dsBuffer->Unlock( buffer1, bufferSize1, buffer2, bufferSize2 );\r\n    if ( FAILED( result ) ) {\r\n      errorStream_ << \"RtApiDs::callbackEvent: error (\" << getErrorString( result ) << \") unlocking buffer during playback!\";\r\n      errorText_ = errorStream_.str();\r\n      error( RtError::SYSTEM_ERROR );\r\n      return;\r\n    }\r\n    nextWritePointer = ( nextWritePointer + bufferSize1 + bufferSize2 ) % dsBufferSize;\r\n    handle->bufferPointer[0] = nextWritePointer;\r\n\r\n    if ( handle->drainCounter ) {\r\n      handle->drainCounter++;\r\n      goto unlock;\r\n    }\r\n  }\r\n\r\n  if ( stream_.mode == INPUT || stream_.mode == DUPLEX ) {\r\n\r\n    // Setup parameters.\r\n    if ( stream_.doConvertBuffer[1] ) {\r\n      buffer = stream_.deviceBuffer;\r\n      bufferBytes = stream_.bufferSize * stream_.nDeviceChannels[1];\r\n      bufferBytes *= formatBytes( stream_.deviceFormat[1] );\r\n    }\r\n    else {\r\n      buffer = stream_.userBuffer[1];\r\n      bufferBytes = stream_.bufferSize * stream_.nUserChannels[1];\r\n      bufferBytes *= formatBytes( stream_.userFormat );\r\n    }\r\n\r\n    LPDIRECTSOUNDCAPTUREBUFFER dsBuffer = (LPDIRECTSOUNDCAPTUREBUFFER) handle->buffer[1];\r\n    long nextReadPointer = handle->bufferPointer[1];\r\n    DWORD dsBufferSize = handle->dsBufferSize[1];\r\n\r\n    // Find out where the write and \"safe read\" pointers are.\r\n    result = dsBuffer->GetCurrentPosition( &currentReadPointer, &safeReadPointer );\r\n    if ( FAILED( result ) ) {\r\n      errorStream_ << \"RtApiDs::callbackEvent: error (\" << getErrorString( result ) << \") getting current read position!\";\r\n      errorText_ = errorStream_.str();\r\n      error( RtError::SYSTEM_ERROR );\r\n      return;\r\n    }\r\n\r\n    if ( safeReadPointer < (DWORD)nextReadPointer ) safeReadPointer += dsBufferSize; // unwrap offset\r\n    DWORD endRead = nextReadPointer + bufferBytes;\r\n\r\n    // Handling depends on whether we are INPUT or DUPLEX. \r\n    // If we're in INPUT mode then waiting is a good thing. If we're in DUPLEX mode,\r\n    // then a wait here will drag the write pointers into the forbidden zone.\r\n    // \r\n    // In DUPLEX mode, rather than wait, we will back off the read pointer until \r\n    // it's in a safe position. This causes dropouts, but it seems to be the only \r\n    // practical way to sync up the read and write pointers reliably, given the \r\n    // the very complex relationship between phase and increment of the read and write \r\n    // pointers.\r\n    //\r\n    // In order to minimize audible dropouts in DUPLEX mode, we will\r\n    // provide a pre-roll period of 0.5 seconds in which we return\r\n    // zeros from the read buffer while the pointers sync up.\r\n\r\n    if ( stream_.mode == DUPLEX ) {\r\n      if ( safeReadPointer < endRead ) {\r\n        if ( duplexPrerollBytes <= 0 ) {\r\n          // Pre-roll time over. Be more agressive.\r\n          int adjustment = endRead-safeReadPointer;\r\n\r\n          handle->xrun[1] = true;\r\n          // Two cases:\r\n          //   - large adjustments: we've probably run out of CPU cycles, so just resync exactly,\r\n          //     and perform fine adjustments later.\r\n          //   - small adjustments: back off by twice as much.\r\n          if ( adjustment >= 2*bufferBytes )\r\n            nextReadPointer = safeReadPointer-2*bufferBytes;\r\n          else\r\n            nextReadPointer = safeReadPointer-bufferBytes-adjustment;\r\n\r\n          if ( nextReadPointer < 0 ) nextReadPointer += dsBufferSize;\r\n\r\n        }\r\n        else {\r\n          // In pre=roll time. Just do it.\r\n          nextReadPointer = safeReadPointer - bufferBytes;\r\n          while ( nextReadPointer < 0 ) nextReadPointer += dsBufferSize;\r\n        }\r\n        endRead = nextReadPointer + bufferBytes;\r\n      }\r\n    }\r\n    else { // mode == INPUT\r\n      while ( safeReadPointer < endRead && stream_.callbackInfo.isRunning ) {\r\n        // See comments for playback.\r\n        double millis = (endRead - safeReadPointer) * 1000.0;\r\n        millis /= ( formatBytes(stream_.deviceFormat[1]) * stream_.nDeviceChannels[1] * stream_.sampleRate);\r\n        if ( millis < 1.0 ) millis = 1.0;\r\n        Sleep( (DWORD) millis );\r\n\r\n        // Wake up and find out where we are now.\r\n        result = dsBuffer->GetCurrentPosition( &currentReadPointer, &safeReadPointer );\r\n        if ( FAILED( result ) ) {\r\n          errorStream_ << \"RtApiDs::callbackEvent: error (\" << getErrorString( result ) << \") getting current read position!\";\r\n          errorText_ = errorStream_.str();\r\n          error( RtError::SYSTEM_ERROR );\r\n          return;\r\n        }\r\n      \r\n        if ( safeReadPointer < (DWORD)nextReadPointer ) safeReadPointer += dsBufferSize; // unwrap offset\r\n      }\r\n    }\r\n\r\n    // Lock free space in the buffer\r\n    result = dsBuffer->Lock( nextReadPointer, bufferBytes, &buffer1,\r\n                             &bufferSize1, &buffer2, &bufferSize2, 0 );\r\n    if ( FAILED( result ) ) {\r\n      errorStream_ << \"RtApiDs::callbackEvent: error (\" << getErrorString( result ) << \") locking capture buffer!\";\r\n      errorText_ = errorStream_.str();\r\n      error( RtError::SYSTEM_ERROR );\r\n      return;\r\n    }\r\n\r\n    if ( duplexPrerollBytes <= 0 ) {\r\n      // Copy our buffer into the DS buffer\r\n      CopyMemory( buffer, buffer1, bufferSize1 );\r\n      if ( buffer2 != NULL ) CopyMemory( buffer+bufferSize1, buffer2, bufferSize2 );\r\n    }\r\n    else {\r\n      memset( buffer, 0, bufferSize1 );\r\n      if ( buffer2 != NULL ) memset( buffer + bufferSize1, 0, bufferSize2 );\r\n      duplexPrerollBytes -= bufferSize1 + bufferSize2;\r\n    }\r\n\r\n    // Update our buffer offset and unlock sound buffer\r\n    nextReadPointer = ( nextReadPointer + bufferSize1 + bufferSize2 ) % dsBufferSize;\r\n    dsBuffer->Unlock( buffer1, bufferSize1, buffer2, bufferSize2 );\r\n    if ( FAILED( result ) ) {\r\n      errorStream_ << \"RtApiDs::callbackEvent: error (\" << getErrorString( result ) << \") unlocking capture buffer!\";\r\n      errorText_ = errorStream_.str();\r\n      error( RtError::SYSTEM_ERROR );\r\n      return;\r\n    }\r\n    handle->bufferPointer[1] = nextReadPointer;\r\n\r\n    // No byte swapping necessary in DirectSound implementation.\r\n\r\n    // If necessary, convert 8-bit data from unsigned to signed.\r\n    if ( stream_.deviceFormat[1] == RTAUDIO_SINT8 )\r\n      for ( int j=0; j<bufferBytes; j++ ) buffer[j] = (signed char) ( buffer[j] - 128 );\r\n\r\n    // Do buffer conversion if necessary.\r\n    if ( stream_.doConvertBuffer[1] )\r\n      convertBuffer( stream_.userBuffer[1], stream_.deviceBuffer, stream_.convertInfo[1] );\r\n  }\r\n\r\n unlock:\r\n  RtApi::tickStreamTime();\r\n}\r\n\r\n// Definitions for utility functions and callbacks\r\n// specific to the DirectSound implementation.\r\n\r\nstatic unsigned __stdcall callbackHandler( void *ptr )\r\n{\r\n  CallbackInfo *info = (CallbackInfo *) ptr;\r\n  RtApiDs *object = (RtApiDs *) info->object;\r\n  bool* isRunning = &info->isRunning;\r\n\r\n  while ( *isRunning == true ) {\r\n    object->callbackEvent();\r\n  }\r\n\r\n  _endthreadex( 0 );\r\n  return 0;\r\n}\r\n\r\n#include \"tchar.h\"\r\n\r\nstatic std::string convertTChar( LPCTSTR name )\r\n{\r\n#if defined( UNICODE ) || defined( _UNICODE )\r\n  int length = WideCharToMultiByte(CP_UTF8, 0, name, -1, NULL, 0, NULL, NULL);\r\n  std::string s( length-1, '\\0' );\r\n  WideCharToMultiByte(CP_UTF8, 0, name, -1, &s[0], length, NULL, NULL);\r\n#else\r\n  std::string s( name );\r\n#endif\r\n\r\n  return s;\r\n}\r\n\r\nstatic BOOL CALLBACK deviceQueryCallback( LPGUID lpguid,\r\n                                          LPCTSTR description,\r\n                                          LPCTSTR module,\r\n                                          LPVOID lpContext )\r\n{\r\n  struct DsProbeData& probeInfo = *(struct DsProbeData*) lpContext;\r\n  std::vector<struct DsDevice>& dsDevices = *probeInfo.dsDevices;\r\n\r\n  HRESULT hr;\r\n  bool validDevice = false;\r\n  if ( probeInfo.isInput == true ) {\r\n    DSCCAPS caps;\r\n    LPDIRECTSOUNDCAPTURE object;\r\n\r\n    hr = DirectSoundCaptureCreate(  lpguid, &object,   NULL );\r\n    if ( hr != DS_OK ) return TRUE;\r\n\r\n    caps.dwSize = sizeof(caps);\r\n    hr = object->GetCaps( &caps );\r\n    if ( hr == DS_OK ) {\r\n      if ( caps.dwChannels > 0 && caps.dwFormats > 0 )\r\n        validDevice = true;\r\n    }\r\n    object->Release();\r\n  }\r\n  else {\r\n    DSCAPS caps;\r\n    LPDIRECTSOUND object;\r\n    hr = DirectSoundCreate(  lpguid, &object,   NULL );\r\n    if ( hr != DS_OK ) return TRUE;\r\n\r\n    caps.dwSize = sizeof(caps);\r\n    hr = object->GetCaps( &caps );\r\n    if ( hr == DS_OK ) {\r\n      if ( caps.dwFlags & DSCAPS_PRIMARYMONO || caps.dwFlags & DSCAPS_PRIMARYSTEREO )\r\n        validDevice = true;\r\n    }\r\n    object->Release();\r\n  }\r\n\r\n  // If good device, then save its name and guid.\r\n  std::string name = convertTChar( description );\r\n  //if ( name == \"Primary Sound Driver\" || name == \"Primary Sound Capture Driver\" )\r\n  if ( lpguid == NULL )\r\n    name = \"Default Device\";\r\n  if ( validDevice ) {\r\n    for ( unsigned int i=0; i<dsDevices.size(); i++ ) {\r\n      if ( dsDevices[i].name == name ) {\r\n        dsDevices[i].found = true;\r\n        if ( probeInfo.isInput ) {\r\n          dsDevices[i].id[1] = lpguid;\r\n          dsDevices[i].validId[1] = true;\r\n        }\r\n        else {\r\n          dsDevices[i].id[0] = lpguid;\r\n          dsDevices[i].validId[0] = true;\r\n        }\r\n        return TRUE;\r\n      }\r\n    }\r\n\r\n    DsDevice device;\r\n    device.name = name;\r\n    device.found = true;\r\n    if ( probeInfo.isInput ) {\r\n      device.id[1] = lpguid;\r\n      device.validId[1] = true;\r\n    }\r\n    else {\r\n      device.id[0] = lpguid;\r\n      device.validId[0] = true;\r\n    }\r\n    dsDevices.push_back( device );\r\n  }\r\n\r\n  return TRUE;\r\n}\r\n\r\nstatic const char* getErrorString( int code )\r\n{\r\n  switch ( code ) {\r\n\r\n  case DSERR_ALLOCATED:\r\n    return \"Already allocated\";\r\n\r\n  case DSERR_CONTROLUNAVAIL:\r\n    return \"Control unavailable\";\r\n\r\n  case DSERR_INVALIDPARAM:\r\n    return \"Invalid parameter\";\r\n\r\n  case DSERR_INVALIDCALL:\r\n    return \"Invalid call\";\r\n\r\n  case DSERR_GENERIC:\r\n    return \"Generic error\";\r\n\r\n  case DSERR_PRIOLEVELNEEDED:\r\n    return \"Priority level needed\";\r\n\r\n  case DSERR_OUTOFMEMORY:\r\n    return \"Out of memory\";\r\n\r\n  case DSERR_BADFORMAT:\r\n    return \"The sample rate or the channel format is not supported\";\r\n\r\n  case DSERR_UNSUPPORTED:\r\n    return \"Not supported\";\r\n\r\n  case DSERR_NODRIVER:\r\n    return \"No driver\";\r\n\r\n  case DSERR_ALREADYINITIALIZED:\r\n    return \"Already initialized\";\r\n\r\n  case DSERR_NOAGGREGATION:\r\n    return \"No aggregation\";\r\n\r\n  case DSERR_BUFFERLOST:\r\n    return \"Buffer lost\";\r\n\r\n  case DSERR_OTHERAPPHASPRIO:\r\n    return \"Another application already has priority\";\r\n\r\n  case DSERR_UNINITIALIZED:\r\n    return \"Uninitialized\";\r\n\r\n  default:\r\n    return \"DirectSound unknown error\";\r\n  }\r\n}\r\n//******************** End of __WINDOWS_DS__ *********************//\r\n#endif\r\n\r\n\r\n#if defined(__LINUX_ALSA__)\r\n\r\n#include <alsa/asoundlib.h>\r\n#include <unistd.h>\r\n\r\n  // A structure to hold various information related to the ALSA API\r\n  // implementation.\r\nstruct AlsaHandle {\r\n  snd_pcm_t *handles[2];\r\n  bool synchronized;\r\n  bool xrun[2];\r\n  pthread_cond_t runnable_cv;\r\n  bool runnable;\r\n\r\n  AlsaHandle()\r\n    :synchronized(false), runnable(false) { xrun[0] = false; xrun[1] = false; }\r\n};\r\n\r\nstatic void *alsaCallbackHandler( void * ptr );\r\n\r\nRtApiAlsa :: RtApiAlsa()\r\n{\r\n  // Nothing to do here.\r\n}\r\n\r\nRtApiAlsa :: ~RtApiAlsa()\r\n{\r\n  if ( stream_.state != STREAM_CLOSED ) closeStream();\r\n}\r\n\r\nunsigned int RtApiAlsa :: getDeviceCount( void )\r\n{\r\n  unsigned nDevices = 0;\r\n  int result, subdevice, card;\r\n  char name[64];\r\n  snd_ctl_t *handle;\r\n\r\n  // Count cards and devices\r\n  card = -1;\r\n  snd_card_next( &card );\r\n  while ( card >= 0 ) {\r\n    sprintf( name, \"hw:%d\", card );\r\n    result = snd_ctl_open( &handle, name, 0 );\r\n    if ( result < 0 ) {\r\n      errorStream_ << \"RtApiAlsa::getDeviceCount: control open, card = \" << card << \", \" << snd_strerror( result ) << \".\";\r\n      errorText_ = errorStream_.str();\r\n      error( RtError::WARNING );\r\n      goto nextcard;\r\n    }\r\n    subdevice = -1;\r\n    while( 1 ) {\r\n      result = snd_ctl_pcm_next_device( handle, &subdevice );\r\n      if ( result < 0 ) {\r\n        errorStream_ << \"RtApiAlsa::getDeviceCount: control next device, card = \" << card << \", \" << snd_strerror( result ) << \".\";\r\n        errorText_ = errorStream_.str();\r\n        error( RtError::WARNING );\r\n        break;\r\n      }\r\n      if ( subdevice < 0 )\r\n        break;\r\n      nDevices++;\r\n    }\r\n  nextcard:\r\n    snd_ctl_close( handle );\r\n    snd_card_next( &card );\r\n  }\r\n\r\n  result = snd_ctl_open( &handle, \"default\", 0 );\r\n  if (result == 0) {\r\n    nDevices++;\r\n    snd_ctl_close( handle );\r\n  }\r\n\r\n  return nDevices;\r\n}\r\n\r\nRtAudio::DeviceInfo RtApiAlsa :: getDeviceInfo( unsigned int device )\r\n{\r\n  RtAudio::DeviceInfo info;\r\n  info.probed = false;\r\n\r\n  unsigned nDevices = 0;\r\n  int result, subdevice, card;\r\n  char name[64];\r\n  snd_ctl_t *chandle;\r\n\r\n  // Count cards and devices\r\n  card = -1;\r\n  snd_card_next( &card );\r\n  while ( card >= 0 ) {\r\n    sprintf( name, \"hw:%d\", card );\r\n    result = snd_ctl_open( &chandle, name, SND_CTL_NONBLOCK );\r\n    if ( result < 0 ) {\r\n      errorStream_ << \"RtApiAlsa::getDeviceInfo: control open, card = \" << card << \", \" << snd_strerror( result ) << \".\";\r\n      errorText_ = errorStream_.str();\r\n      error( RtError::WARNING );\r\n      goto nextcard;\r\n    }\r\n    subdevice = -1;\r\n    while( 1 ) {\r\n      result = snd_ctl_pcm_next_device( chandle, &subdevice );\r\n      if ( result < 0 ) {\r\n        errorStream_ << \"RtApiAlsa::getDeviceInfo: control next device, card = \" << card << \", \" << snd_strerror( result ) << \".\";\r\n        errorText_ = errorStream_.str();\r\n        error( RtError::WARNING );\r\n        break;\r\n      }\r\n      if ( subdevice < 0 ) break;\r\n      if ( nDevices == device ) {\r\n        sprintf( name, \"hw:%d,%d\", card, subdevice );\r\n        goto foundDevice;\r\n      }\r\n      nDevices++;\r\n    }\r\n  nextcard:\r\n    snd_ctl_close( chandle );\r\n    snd_card_next( &card );\r\n  }\r\n\r\n  result = snd_ctl_open( &chandle, \"default\", SND_CTL_NONBLOCK );\r\n  if ( result == 0 ) {\r\n    if ( nDevices == device ) {\r\n      strcpy( name, \"default\" );\r\n      goto foundDevice;\r\n    }\r\n    nDevices++;\r\n  }\r\n\r\n  if ( nDevices == 0 ) {\r\n    errorText_ = \"RtApiAlsa::getDeviceInfo: no devices found!\";\r\n    error( RtError::INVALID_USE );\r\n    return info;\r\n  }\r\n\r\n  if ( device >= nDevices ) {\r\n    errorText_ = \"RtApiAlsa::getDeviceInfo: device ID is invalid!\";\r\n    error( RtError::INVALID_USE );\r\n    return info;\r\n  }\r\n\r\n foundDevice:\r\n\r\n  // If a stream is already open, we cannot probe the stream devices.\r\n  // Thus, use the saved results.\r\n  if ( stream_.state != STREAM_CLOSED &&\r\n       ( stream_.device[0] == device || stream_.device[1] == device ) ) {\r\n    snd_ctl_close( chandle );\r\n    if ( device >= devices_.size() ) {\r\n      errorText_ = \"RtApiAlsa::getDeviceInfo: device ID was not present before stream was opened.\";\r\n      error( RtError::WARNING );\r\n      return info;\r\n    }\r\n    return devices_[ device ];\r\n  }\r\n\r\n  int openMode = SND_PCM_ASYNC;\r\n  snd_pcm_stream_t stream;\r\n  snd_pcm_info_t *pcminfo;\r\n  snd_pcm_info_alloca( &pcminfo );\r\n  snd_pcm_t *phandle;\r\n  snd_pcm_hw_params_t *params;\r\n  snd_pcm_hw_params_alloca( &params );\r\n\r\n  // First try for playback unless default device (which has subdev -1)\r\n  stream = SND_PCM_STREAM_PLAYBACK;\r\n  snd_pcm_info_set_stream( pcminfo, stream );\r\n  if ( subdevice != -1 ) {\r\n    snd_pcm_info_set_device( pcminfo, subdevice );\r\n    snd_pcm_info_set_subdevice( pcminfo, 0 );\r\n\r\n    result = snd_ctl_pcm_info( chandle, pcminfo );\r\n    if ( result < 0 ) {\r\n      // Device probably doesn't support playback.\r\n      goto captureProbe;\r\n    }\r\n  }\r\n\r\n  result = snd_pcm_open( &phandle, name, stream, openMode | SND_PCM_NONBLOCK );\r\n  if ( result < 0 ) {\r\n    errorStream_ << \"RtApiAlsa::getDeviceInfo: snd_pcm_open error for device (\" << name << \"), \" << snd_strerror( result ) << \".\";\r\n    errorText_ = errorStream_.str();\r\n    error( RtError::WARNING );\r\n    goto captureProbe;\r\n  }\r\n\r\n  // The device is open ... fill the parameter structure.\r\n  result = snd_pcm_hw_params_any( phandle, params );\r\n  if ( result < 0 ) {\r\n    snd_pcm_close( phandle );\r\n    errorStream_ << \"RtApiAlsa::getDeviceInfo: snd_pcm_hw_params error for device (\" << name << \"), \" << snd_strerror( result ) << \".\";\r\n    errorText_ = errorStream_.str();\r\n    error( RtError::WARNING );\r\n    goto captureProbe;\r\n  }\r\n\r\n  // Get output channel information.\r\n  unsigned int value;\r\n  result = snd_pcm_hw_params_get_channels_max( params, &value );\r\n  if ( result < 0 ) {\r\n    snd_pcm_close( phandle );\r\n    errorStream_ << \"RtApiAlsa::getDeviceInfo: error getting device (\" << name << \") output channels, \" << snd_strerror( result ) << \".\";\r\n    errorText_ = errorStream_.str();\r\n    error( RtError::WARNING );\r\n    goto captureProbe;\r\n  }\r\n  info.outputChannels = value;\r\n  snd_pcm_close( phandle );\r\n\r\n captureProbe:\r\n  stream = SND_PCM_STREAM_CAPTURE;\r\n  snd_pcm_info_set_stream( pcminfo, stream );\r\n\r\n  // Now try for capture unless default device (with subdev = -1)\r\n  if ( subdevice != -1 ) {\r\n    result = snd_ctl_pcm_info( chandle, pcminfo );\r\n    snd_ctl_close( chandle );\r\n    if ( result < 0 ) {\r\n      // Device probably doesn't support capture.\r\n      if ( info.outputChannels == 0 ) return info;\r\n      goto probeParameters;\r\n    }\r\n  }\r\n\r\n  result = snd_pcm_open( &phandle, name, stream, openMode | SND_PCM_NONBLOCK);\r\n  if ( result < 0 ) {\r\n    errorStream_ << \"RtApiAlsa::getDeviceInfo: snd_pcm_open error for device (\" << name << \"), \" << snd_strerror( result ) << \".\";\r\n    errorText_ = errorStream_.str();\r\n    error( RtError::WARNING );\r\n    if ( info.outputChannels == 0 ) return info;\r\n    goto probeParameters;\r\n  }\r\n\r\n  // The device is open ... fill the parameter structure.\r\n  result = snd_pcm_hw_params_any( phandle, params );\r\n  if ( result < 0 ) {\r\n    snd_pcm_close( phandle );\r\n    errorStream_ << \"RtApiAlsa::getDeviceInfo: snd_pcm_hw_params error for device (\" << name << \"), \" << snd_strerror( result ) << \".\";\r\n    errorText_ = errorStream_.str();\r\n    error( RtError::WARNING );\r\n    if ( info.outputChannels == 0 ) return info;\r\n    goto probeParameters;\r\n  }\r\n\r\n  result = snd_pcm_hw_params_get_channels_max( params, &value );\r\n  if ( result < 0 ) {\r\n    snd_pcm_close( phandle );\r\n    errorStream_ << \"RtApiAlsa::getDeviceInfo: error getting device (\" << name << \") input channels, \" << snd_strerror( result ) << \".\";\r\n    errorText_ = errorStream_.str();\r\n    error( RtError::WARNING );\r\n    if ( info.outputChannels == 0 ) return info;\r\n    goto probeParameters;\r\n  }\r\n  info.inputChannels = value;\r\n  snd_pcm_close( phandle );\r\n\r\n  // If device opens for both playback and capture, we determine the channels.\r\n  if ( info.outputChannels > 0 && info.inputChannels > 0 )\r\n    info.duplexChannels = (info.outputChannels > info.inputChannels) ? info.inputChannels : info.outputChannels;\r\n\r\n  // ALSA doesn't provide default devices so we'll use the first available one.\r\n  if ( device == 0 && info.outputChannels > 0 )\r\n    info.isDefaultOutput = true;\r\n  if ( device == 0 && info.inputChannels > 0 )\r\n    info.isDefaultInput = true;\r\n\r\n probeParameters:\r\n  // At this point, we just need to figure out the supported data\r\n  // formats and sample rates.  We'll proceed by opening the device in\r\n  // the direction with the maximum number of channels, or playback if\r\n  // they are equal.  This might limit our sample rate options, but so\r\n  // be it.\r\n\r\n  if ( info.outputChannels >= info.inputChannels )\r\n    stream = SND_PCM_STREAM_PLAYBACK;\r\n  else\r\n    stream = SND_PCM_STREAM_CAPTURE;\r\n  snd_pcm_info_set_stream( pcminfo, stream );\r\n\r\n  result = snd_pcm_open( &phandle, name, stream, openMode | SND_PCM_NONBLOCK);\r\n  if ( result < 0 ) {\r\n    errorStream_ << \"RtApiAlsa::getDeviceInfo: snd_pcm_open error for device (\" << name << \"), \" << snd_strerror( result ) << \".\";\r\n    errorText_ = errorStream_.str();\r\n    error( RtError::WARNING );\r\n    return info;\r\n  }\r\n\r\n  // The device is open ... fill the parameter structure.\r\n  result = snd_pcm_hw_params_any( phandle, params );\r\n  if ( result < 0 ) {\r\n    snd_pcm_close( phandle );\r\n    errorStream_ << \"RtApiAlsa::getDeviceInfo: snd_pcm_hw_params error for device (\" << name << \"), \" << snd_strerror( result ) << \".\";\r\n    errorText_ = errorStream_.str();\r\n    error( RtError::WARNING );\r\n    return info;\r\n  }\r\n\r\n  // Test our discrete set of sample rate values.\r\n  info.sampleRates.clear();\r\n  for ( unsigned int i=0; i<MAX_SAMPLE_RATES; i++ ) {\r\n    if ( snd_pcm_hw_params_test_rate( phandle, params, SAMPLE_RATES[i], 0 ) == 0 )\r\n      info.sampleRates.push_back( SAMPLE_RATES[i] );\r\n  }\r\n  if ( info.sampleRates.size() == 0 ) {\r\n    snd_pcm_close( phandle );\r\n    errorStream_ << \"RtApiAlsa::getDeviceInfo: no supported sample rates found for device (\" << name << \").\";\r\n    errorText_ = errorStream_.str();\r\n    error( RtError::WARNING );\r\n    return info;\r\n  }\r\n\r\n  // Probe the supported data formats ... we don't care about endian-ness just yet\r\n  snd_pcm_format_t format;\r\n  info.nativeFormats = 0;\r\n  format = SND_PCM_FORMAT_S8;\r\n  if ( snd_pcm_hw_params_test_format( phandle, params, format ) == 0 )\r\n    info.nativeFormats |= RTAUDIO_SINT8;\r\n  format = SND_PCM_FORMAT_S16;\r\n  if ( snd_pcm_hw_params_test_format( phandle, params, format ) == 0 )\r\n    info.nativeFormats |= RTAUDIO_SINT16;\r\n  format = SND_PCM_FORMAT_S24;\r\n  if ( snd_pcm_hw_params_test_format( phandle, params, format ) == 0 )\r\n    info.nativeFormats |= RTAUDIO_SINT24;\r\n  format = SND_PCM_FORMAT_S32;\r\n  if ( snd_pcm_hw_params_test_format( phandle, params, format ) == 0 )\r\n    info.nativeFormats |= RTAUDIO_SINT32;\r\n  format = SND_PCM_FORMAT_FLOAT;\r\n  if ( snd_pcm_hw_params_test_format( phandle, params, format ) == 0 )\r\n    info.nativeFormats |= RTAUDIO_FLOAT32;\r\n  format = SND_PCM_FORMAT_FLOAT64;\r\n  if ( snd_pcm_hw_params_test_format( phandle, params, format ) == 0 )\r\n    info.nativeFormats |= RTAUDIO_FLOAT64;\r\n\r\n  // Check that we have at least one supported format\r\n  if ( info.nativeFormats == 0 ) {\r\n    errorStream_ << \"RtApiAlsa::getDeviceInfo: pcm device (\" << name << \") data format not supported by RtAudio.\";\r\n    errorText_ = errorStream_.str();\r\n    error( RtError::WARNING );\r\n    return info;\r\n  }\r\n\r\n  // Get the device name\r\n  char *cardname;\r\n  result = snd_card_get_name( card, &cardname );\r\n  if ( result >= 0 )\r\n    sprintf( name, \"hw:%s,%d\", cardname, subdevice );\r\n  info.name = name;\r\n\r\n  // That's all ... close the device and return\r\n  snd_pcm_close( phandle );\r\n  info.probed = true;\r\n  return info;\r\n}\r\n\r\nvoid RtApiAlsa :: saveDeviceInfo( void )\r\n{\r\n  devices_.clear();\r\n\r\n  unsigned int nDevices = getDeviceCount();\r\n  devices_.resize( nDevices );\r\n  for ( unsigned int i=0; i<nDevices; i++ )\r\n    devices_[i] = getDeviceInfo( i );\r\n}\r\n\r\nbool RtApiAlsa :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels,\r\n                                   unsigned int firstChannel, unsigned int sampleRate,\r\n                                   RtAudioFormat format, unsigned int *bufferSize,\r\n                                   RtAudio::StreamOptions *options )\r\n\r\n{\r\n#if defined(__RTAUDIO_DEBUG__)\r\n  snd_output_t *out;\r\n  snd_output_stdio_attach(&out, stderr, 0);\r\n#endif\r\n\r\n  // I'm not using the \"plug\" interface ... too much inconsistent behavior.\r\n\r\n  unsigned nDevices = 0;\r\n  int result, subdevice, card;\r\n  char name[64];\r\n  snd_ctl_t *chandle;\r\n\r\n  if ( options && options->flags & RTAUDIO_ALSA_USE_DEFAULT )\r\n    snprintf(name, sizeof(name), \"%s\", \"default\");\r\n  else {\r\n    // Count cards and devices\r\n    card = -1;\r\n    snd_card_next( &card );\r\n    while ( card >= 0 ) {\r\n      sprintf( name, \"hw:%d\", card );\r\n      result = snd_ctl_open( &chandle, name, SND_CTL_NONBLOCK );\r\n      if ( result < 0 ) {\r\n        errorStream_ << \"RtApiAlsa::probeDeviceOpen: control open, card = \" << card << \", \" << snd_strerror( result ) << \".\";\r\n        errorText_ = errorStream_.str();\r\n        return FAILURE;\r\n      }\r\n      subdevice = -1;\r\n      while( 1 ) {\r\n        result = snd_ctl_pcm_next_device( chandle, &subdevice );\r\n        if ( result < 0 ) break;\r\n        if ( subdevice < 0 ) break;\r\n        if ( nDevices == device ) {\r\n          sprintf( name, \"hw:%d,%d\", card, subdevice );\r\n          snd_ctl_close( chandle );\r\n          goto foundDevice;\r\n        }\r\n        nDevices++;\r\n      }\r\n      snd_ctl_close( chandle );\r\n      snd_card_next( &card );\r\n    }\r\n\r\n    result = snd_ctl_open( &chandle, \"default\", SND_CTL_NONBLOCK );\r\n    if ( result == 0 ) {\r\n      if ( nDevices == device ) {\r\n        strcpy( name, \"default\" );\r\n        goto foundDevice;\r\n      }\r\n      nDevices++;\r\n    }\r\n\r\n    if ( nDevices == 0 ) {\r\n      // This should not happen because a check is made before this function is called.\r\n      errorText_ = \"RtApiAlsa::probeDeviceOpen: no devices found!\";\r\n      return FAILURE;\r\n    }\r\n\r\n    if ( device >= nDevices ) {\r\n      // This should not happen because a check is made before this function is called.\r\n      errorText_ = \"RtApiAlsa::probeDeviceOpen: device ID is invalid!\";\r\n      return FAILURE;\r\n    }\r\n  }\r\n\r\n foundDevice:\r\n\r\n  // The getDeviceInfo() function will not work for a device that is\r\n  // already open.  Thus, we'll probe the system before opening a\r\n  // stream and save the results for use by getDeviceInfo().\r\n  if ( mode == OUTPUT || ( mode == INPUT && stream_.mode != OUTPUT ) ) // only do once\r\n    this->saveDeviceInfo();\r\n\r\n  snd_pcm_stream_t stream;\r\n  if ( mode == OUTPUT )\r\n    stream = SND_PCM_STREAM_PLAYBACK;\r\n  else\r\n    stream = SND_PCM_STREAM_CAPTURE;\r\n\r\n  snd_pcm_t *phandle;\r\n  int openMode = SND_PCM_ASYNC;\r\n  result = snd_pcm_open( &phandle, name, stream, openMode );\r\n  if ( result < 0 ) {\r\n    if ( mode == OUTPUT )\r\n      errorStream_ << \"RtApiAlsa::probeDeviceOpen: pcm device (\" << name << \") won't open for output.\";\r\n    else\r\n      errorStream_ << \"RtApiAlsa::probeDeviceOpen: pcm device (\" << name << \") won't open for input.\";\r\n    errorText_ = errorStream_.str();\r\n    return FAILURE;\r\n  }\r\n\r\n  // Fill the parameter structure.\r\n  snd_pcm_hw_params_t *hw_params;\r\n  snd_pcm_hw_params_alloca( &hw_params );\r\n  result = snd_pcm_hw_params_any( phandle, hw_params );\r\n  if ( result < 0 ) {\r\n    snd_pcm_close( phandle );\r\n    errorStream_ << \"RtApiAlsa::probeDeviceOpen: error getting pcm device (\" << name << \") parameters, \" << snd_strerror( result ) << \".\";\r\n    errorText_ = errorStream_.str();\r\n    return FAILURE;\r\n  }\r\n\r\n#if defined(__RTAUDIO_DEBUG__)\r\n  fprintf( stderr, \"\\nRtApiAlsa: dump hardware params just after device open:\\n\\n\" );\r\n  snd_pcm_hw_params_dump( hw_params, out );\r\n#endif\r\n\r\n  // Set access ... check user preference.\r\n  if ( options && options->flags & RTAUDIO_NONINTERLEAVED ) {\r\n    stream_.userInterleaved = false;\r\n    result = snd_pcm_hw_params_set_access( phandle, hw_params, SND_PCM_ACCESS_RW_NONINTERLEAVED );\r\n    if ( result < 0 ) {\r\n      result = snd_pcm_hw_params_set_access( phandle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED );\r\n      stream_.deviceInterleaved[mode] =  true;\r\n    }\r\n    else\r\n      stream_.deviceInterleaved[mode] = false;\r\n  }\r\n  else {\r\n    stream_.userInterleaved = true;\r\n    result = snd_pcm_hw_params_set_access( phandle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED );\r\n    if ( result < 0 ) {\r\n      result = snd_pcm_hw_params_set_access( phandle, hw_params, SND_PCM_ACCESS_RW_NONINTERLEAVED );\r\n      stream_.deviceInterleaved[mode] =  false;\r\n    }\r\n    else\r\n      stream_.deviceInterleaved[mode] =  true;\r\n  }\r\n\r\n  if ( result < 0 ) {\r\n    snd_pcm_close( phandle );\r\n    errorStream_ << \"RtApiAlsa::probeDeviceOpen: error setting pcm device (\" << name << \") access, \" << snd_strerror( result ) << \".\";\r\n    errorText_ = errorStream_.str();\r\n    return FAILURE;\r\n  }\r\n\r\n  // Determine how to set the device format.\r\n  stream_.userFormat = format;\r\n  snd_pcm_format_t deviceFormat = SND_PCM_FORMAT_UNKNOWN;\r\n\r\n  if ( format == RTAUDIO_SINT8 )\r\n    deviceFormat = SND_PCM_FORMAT_S8;\r\n  else if ( format == RTAUDIO_SINT16 )\r\n    deviceFormat = SND_PCM_FORMAT_S16;\r\n  else if ( format == RTAUDIO_SINT24 )\r\n    deviceFormat = SND_PCM_FORMAT_S24;\r\n  else if ( format == RTAUDIO_SINT32 )\r\n    deviceFormat = SND_PCM_FORMAT_S32;\r\n  else if ( format == RTAUDIO_FLOAT32 )\r\n    deviceFormat = SND_PCM_FORMAT_FLOAT;\r\n  else if ( format == RTAUDIO_FLOAT64 )\r\n    deviceFormat = SND_PCM_FORMAT_FLOAT64;\r\n\r\n  if ( snd_pcm_hw_params_test_format(phandle, hw_params, deviceFormat) == 0) {\r\n    stream_.deviceFormat[mode] = format;\r\n    goto setFormat;\r\n  }\r\n\r\n  // The user requested format is not natively supported by the device.\r\n  deviceFormat = SND_PCM_FORMAT_FLOAT64;\r\n  if ( snd_pcm_hw_params_test_format( phandle, hw_params, deviceFormat ) == 0 ) {\r\n    stream_.deviceFormat[mode] = RTAUDIO_FLOAT64;\r\n    goto setFormat;\r\n  }\r\n\r\n  deviceFormat = SND_PCM_FORMAT_FLOAT;\r\n  if ( snd_pcm_hw_params_test_format(phandle, hw_params, deviceFormat ) == 0 ) {\r\n    stream_.deviceFormat[mode] = RTAUDIO_FLOAT32;\r\n    goto setFormat;\r\n  }\r\n\r\n  deviceFormat = SND_PCM_FORMAT_S32;\r\n  if ( snd_pcm_hw_params_test_format(phandle, hw_params, deviceFormat ) == 0 ) {\r\n    stream_.deviceFormat[mode] = RTAUDIO_SINT32;\r\n    goto setFormat;\r\n  }\r\n\r\n  deviceFormat = SND_PCM_FORMAT_S24;\r\n  if ( snd_pcm_hw_params_test_format(phandle, hw_params, deviceFormat ) == 0 ) {\r\n    stream_.deviceFormat[mode] = RTAUDIO_SINT24;\r\n    goto setFormat;\r\n  }\r\n\r\n  deviceFormat = SND_PCM_FORMAT_S16;\r\n  if ( snd_pcm_hw_params_test_format(phandle, hw_params, deviceFormat ) == 0 ) {\r\n    stream_.deviceFormat[mode] = RTAUDIO_SINT16;\r\n    goto setFormat;\r\n  }\r\n\r\n  deviceFormat = SND_PCM_FORMAT_S8;\r\n  if ( snd_pcm_hw_params_test_format(phandle, hw_params, deviceFormat ) == 0 ) {\r\n    stream_.deviceFormat[mode] = RTAUDIO_SINT8;\r\n    goto setFormat;\r\n  }\r\n\r\n  // If we get here, no supported format was found.\r\n  snd_pcm_close( phandle );\r\n  errorStream_ << \"RtApiAlsa::probeDeviceOpen: pcm device \" << device << \" data format not supported by RtAudio.\";\r\n  errorText_ = errorStream_.str();\r\n  return FAILURE;\r\n\r\n setFormat:\r\n  result = snd_pcm_hw_params_set_format( phandle, hw_params, deviceFormat );\r\n  if ( result < 0 ) {\r\n    snd_pcm_close( phandle );\r\n    errorStream_ << \"RtApiAlsa::probeDeviceOpen: error setting pcm device (\" << name << \") data format, \" << snd_strerror( result ) << \".\";\r\n    errorText_ = errorStream_.str();\r\n    return FAILURE;\r\n  }\r\n\r\n  // Determine whether byte-swaping is necessary.\r\n  stream_.doByteSwap[mode] = false;\r\n  if ( deviceFormat != SND_PCM_FORMAT_S8 ) {\r\n    result = snd_pcm_format_cpu_endian( deviceFormat );\r\n    if ( result == 0 )\r\n      stream_.doByteSwap[mode] = true;\r\n    else if (result < 0) {\r\n      snd_pcm_close( phandle );\r\n      errorStream_ << \"RtApiAlsa::probeDeviceOpen: error getting pcm device (\" << name << \") endian-ness, \" << snd_strerror( result ) << \".\";\r\n      errorText_ = errorStream_.str();\r\n      return FAILURE;\r\n    }\r\n  }\r\n\r\n  // Set the sample rate.\r\n  result = snd_pcm_hw_params_set_rate_near( phandle, hw_params, (unsigned int*) &sampleRate, 0 );\r\n  if ( result < 0 ) {\r\n    snd_pcm_close( phandle );\r\n    errorStream_ << \"RtApiAlsa::probeDeviceOpen: error setting sample rate on device (\" << name << \"), \" << snd_strerror( result ) << \".\";\r\n    errorText_ = errorStream_.str();\r\n    return FAILURE;\r\n  }\r\n\r\n  // Determine the number of channels for this device.  We support a possible\r\n  // minimum device channel number > than the value requested by the user.\r\n  stream_.nUserChannels[mode] = channels;\r\n  unsigned int value;\r\n  result = snd_pcm_hw_params_get_channels_max( hw_params, &value );\r\n  unsigned int deviceChannels = value;\r\n  if ( result < 0 || deviceChannels < channels + firstChannel ) {\r\n    snd_pcm_close( phandle );\r\n    errorStream_ << \"RtApiAlsa::probeDeviceOpen: requested channel parameters not supported by device (\" << name << \"), \" << snd_strerror( result ) << \".\";\r\n    errorText_ = errorStream_.str();\r\n    return FAILURE;\r\n  }\r\n\r\n  result = snd_pcm_hw_params_get_channels_min( hw_params, &value );\r\n  if ( result < 0 ) {\r\n    snd_pcm_close( phandle );\r\n    errorStream_ << \"RtApiAlsa::probeDeviceOpen: error getting minimum channels for device (\" << name << \"), \" << snd_strerror( result ) << \".\";\r\n    errorText_ = errorStream_.str();\r\n    return FAILURE;\r\n  }\r\n  deviceChannels = value;\r\n  if ( deviceChannels < channels + firstChannel ) deviceChannels = channels + firstChannel;\r\n  stream_.nDeviceChannels[mode] = deviceChannels;\r\n\r\n  // Set the device channels.\r\n  result = snd_pcm_hw_params_set_channels( phandle, hw_params, deviceChannels );\r\n  if ( result < 0 ) {\r\n    snd_pcm_close( phandle );\r\n    errorStream_ << \"RtApiAlsa::probeDeviceOpen: error setting channels for device (\" << name << \"), \" << snd_strerror( result ) << \".\";\r\n    errorText_ = errorStream_.str();\r\n    return FAILURE;\r\n  }\r\n\r\n  // Set the buffer (or period) size.\r\n  int dir = 0;\r\n  snd_pcm_uframes_t periodSize = *bufferSize;\r\n  result = snd_pcm_hw_params_set_period_size_near( phandle, hw_params, &periodSize, &dir );\r\n  if ( result < 0 ) {\r\n    snd_pcm_close( phandle );\r\n    errorStream_ << \"RtApiAlsa::probeDeviceOpen: error setting period size for device (\" << name << \"), \" << snd_strerror( result ) << \".\";\r\n    errorText_ = errorStream_.str();\r\n    return FAILURE;\r\n  }\r\n  *bufferSize = periodSize;\r\n\r\n  // Set the buffer number, which in ALSA is referred to as the \"period\".\r\n  unsigned int periods = 0;\r\n  if ( options && options->flags & RTAUDIO_MINIMIZE_LATENCY ) periods = 2;\r\n  if ( options && options->numberOfBuffers > 0 ) periods = options->numberOfBuffers;\r\n  if ( periods < 2 ) periods = 4; // a fairly safe default value\r\n  result = snd_pcm_hw_params_set_periods_near( phandle, hw_params, &periods, &dir );\r\n  if ( result < 0 ) {\r\n    snd_pcm_close( phandle );\r\n    errorStream_ << \"RtApiAlsa::probeDeviceOpen: error setting periods for device (\" << name << \"), \" << snd_strerror( result ) << \".\";\r\n    errorText_ = errorStream_.str();\r\n    return FAILURE;\r\n  }\r\n\r\n  // If attempting to setup a duplex stream, the bufferSize parameter\r\n  // MUST be the same in both directions!\r\n  if ( stream_.mode == OUTPUT && mode == INPUT && *bufferSize != stream_.bufferSize ) {\r\n    snd_pcm_close( phandle );\r\n    errorStream_ << \"RtApiAlsa::probeDeviceOpen: system error setting buffer size for duplex stream on device (\" << name << \").\";\r\n    errorText_ = errorStream_.str();\r\n    return FAILURE;\r\n  }\r\n\r\n  stream_.bufferSize = *bufferSize;\r\n\r\n  // Install the hardware configuration\r\n  result = snd_pcm_hw_params( phandle, hw_params );\r\n  if ( result < 0 ) {\r\n    snd_pcm_close( phandle );\r\n    errorStream_ << \"RtApiAlsa::probeDeviceOpen: error installing hardware configuration on device (\" << name << \"), \" << snd_strerror( result ) << \".\";\r\n    errorText_ = errorStream_.str();\r\n    return FAILURE;\r\n  }\r\n\r\n#if defined(__RTAUDIO_DEBUG__)\r\n  fprintf(stderr, \"\\nRtApiAlsa: dump hardware params after installation:\\n\\n\");\r\n  snd_pcm_hw_params_dump( hw_params, out );\r\n#endif\r\n\r\n  // Set the software configuration to fill buffers with zeros and prevent device stopping on xruns.\r\n  snd_pcm_sw_params_t *sw_params = NULL;\r\n  snd_pcm_sw_params_alloca( &sw_params );\r\n  snd_pcm_sw_params_current( phandle, sw_params );\r\n  snd_pcm_sw_params_set_start_threshold( phandle, sw_params, *bufferSize );\r\n  snd_pcm_sw_params_set_stop_threshold( phandle, sw_params, ULONG_MAX );\r\n  snd_pcm_sw_params_set_silence_threshold( phandle, sw_params, 0 );\r\n\r\n  // The following two settings were suggested by Theo Veenker\r\n  //snd_pcm_sw_params_set_avail_min( phandle, sw_params, *bufferSize );\r\n  //snd_pcm_sw_params_set_xfer_align( phandle, sw_params, 1 );\r\n\r\n  // here are two options for a fix\r\n  //snd_pcm_sw_params_set_silence_size( phandle, sw_params, ULONG_MAX );\r\n  snd_pcm_uframes_t val;\r\n  snd_pcm_sw_params_get_boundary( sw_params, &val );\r\n  snd_pcm_sw_params_set_silence_size( phandle, sw_params, val );\r\n\r\n  result = snd_pcm_sw_params( phandle, sw_params );\r\n  if ( result < 0 ) {\r\n    snd_pcm_close( phandle );\r\n    errorStream_ << \"RtApiAlsa::probeDeviceOpen: error installing software configuration on device (\" << name << \"), \" << snd_strerror( result ) << \".\";\r\n    errorText_ = errorStream_.str();\r\n    return FAILURE;\r\n  }\r\n\r\n#if defined(__RTAUDIO_DEBUG__)\r\n  fprintf(stderr, \"\\nRtApiAlsa: dump software params after installation:\\n\\n\");\r\n  snd_pcm_sw_params_dump( sw_params, out );\r\n#endif\r\n\r\n  // Set flags for buffer conversion\r\n  stream_.doConvertBuffer[mode] = false;\r\n  if ( stream_.userFormat != stream_.deviceFormat[mode] )\r\n    stream_.doConvertBuffer[mode] = true;\r\n  if ( stream_.nUserChannels[mode] < stream_.nDeviceChannels[mode] )\r\n    stream_.doConvertBuffer[mode] = true;\r\n  if ( stream_.userInterleaved != stream_.deviceInterleaved[mode] &&\r\n       stream_.nUserChannels[mode] > 1 )\r\n    stream_.doConvertBuffer[mode] = true;\r\n\r\n  // Allocate the ApiHandle if necessary and then save.\r\n  AlsaHandle *apiInfo = 0;\r\n  if ( stream_.apiHandle == 0 ) {\r\n    try {\r\n      apiInfo = (AlsaHandle *) new AlsaHandle;\r\n    }\r\n    catch ( std::bad_alloc& ) {\r\n      errorText_ = \"RtApiAlsa::probeDeviceOpen: error allocating AlsaHandle memory.\";\r\n      goto error;\r\n    }\r\n\r\n    if ( pthread_cond_init( &apiInfo->runnable_cv, NULL ) ) {\r\n      errorText_ = \"RtApiAlsa::probeDeviceOpen: error initializing pthread condition variable.\";\r\n      goto error;\r\n    }\r\n\r\n    stream_.apiHandle = (void *) apiInfo;\r\n    apiInfo->handles[0] = 0;\r\n    apiInfo->handles[1] = 0;\r\n  }\r\n  else {\r\n    apiInfo = (AlsaHandle *) stream_.apiHandle;\r\n  }\r\n  apiInfo->handles[mode] = phandle;\r\n  phandle = 0;\r\n\r\n  // Allocate necessary internal buffers.\r\n  unsigned long bufferBytes;\r\n  bufferBytes = stream_.nUserChannels[mode] * *bufferSize * formatBytes( stream_.userFormat );\r\n  stream_.userBuffer[mode] = (char *) calloc( bufferBytes, 1 );\r\n  if ( stream_.userBuffer[mode] == NULL ) {\r\n    errorText_ = \"RtApiAlsa::probeDeviceOpen: error allocating user buffer memory.\";\r\n    goto error;\r\n  }\r\n\r\n  if ( stream_.doConvertBuffer[mode] ) {\r\n\r\n    bool makeBuffer = true;\r\n    bufferBytes = stream_.nDeviceChannels[mode] * formatBytes( stream_.deviceFormat[mode] );\r\n    if ( mode == INPUT ) {\r\n      if ( stream_.mode == OUTPUT && stream_.deviceBuffer ) {\r\n        unsigned long bytesOut = stream_.nDeviceChannels[0] * formatBytes( stream_.deviceFormat[0] );\r\n        if ( bufferBytes <= bytesOut ) makeBuffer = false;\r\n      }\r\n    }\r\n\r\n    if ( makeBuffer ) {\r\n      bufferBytes *= *bufferSize;\r\n      if ( stream_.deviceBuffer ) free( stream_.deviceBuffer );\r\n      stream_.deviceBuffer = (char *) calloc( bufferBytes, 1 );\r\n      if ( stream_.deviceBuffer == NULL ) {\r\n        errorText_ = \"RtApiAlsa::probeDeviceOpen: error allocating device buffer memory.\";\r\n        goto error;\r\n      }\r\n    }\r\n  }\r\n\r\n  stream_.sampleRate = sampleRate;\r\n  stream_.nBuffers = periods;\r\n  stream_.device[mode] = device;\r\n  stream_.state = STREAM_STOPPED;\r\n\r\n  // Setup the buffer conversion information structure.\r\n  if ( stream_.doConvertBuffer[mode] ) setConvertInfo( mode, firstChannel );\r\n\r\n  // Setup thread if necessary.\r\n  if ( stream_.mode == OUTPUT && mode == INPUT ) {\r\n    // We had already set up an output stream.\r\n    stream_.mode = DUPLEX;\r\n    // Link the streams if possible.\r\n    apiInfo->synchronized = false;\r\n    if ( snd_pcm_link( apiInfo->handles[0], apiInfo->handles[1] ) == 0 )\r\n      apiInfo->synchronized = true;\r\n    else {\r\n      errorText_ = \"RtApiAlsa::probeDeviceOpen: unable to synchronize input and output devices.\";\r\n      error( RtError::WARNING );\r\n    }\r\n  }\r\n  else {\r\n    stream_.mode = mode;\r\n\r\n    // Setup callback thread.\r\n    stream_.callbackInfo.object = (void *) this;\r\n\r\n    // Set the thread attributes for joinable and realtime scheduling\r\n    // priority (optional).  The higher priority will only take affect\r\n    // if the program is run as root or suid. Note, under GNU/Linux\r\n    // processes with CAP_SYS_NICE privilege, a user can change\r\n    // scheduling policy and priority (thus need not be root). See\r\n    // POSIX \"capabilities\".\r\n    pthread_attr_t attr;\r\n    pthread_attr_init( &attr );\r\n    pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_JOINABLE );\r\n\r\n#ifdef SCHED_RR // Undefined with some OSes (eg: NetBSD 1.6.x with GNU Pthread)\r\n    if ( options && options->flags & RTAUDIO_SCHEDULE_REALTIME ) {\r\n      // We previously attempted to increase the audio callback priority\r\n      // to SCHED_RR here via the attributes.  However, while no errors\r\n      // were reported in doing so, it did not work.  So, now this is\r\n      // done in the alsaCallbackHandler function.\r\n      stream_.callbackInfo.doRealtime = true;\r\n      int priority = options->priority;\r\n      int min = sched_get_priority_min( SCHED_RR );\r\n      int max = sched_get_priority_max( SCHED_RR );\r\n      if ( priority < min ) priority = min;\r\n      else if ( priority > max ) priority = max;\r\n      stream_.callbackInfo.priority = priority;\r\n    }\r\n#endif\r\n\r\n    stream_.callbackInfo.isRunning = true;\r\n    result = pthread_create( &stream_.callbackInfo.thread, &attr, alsaCallbackHandler, &stream_.callbackInfo );\r\n    pthread_attr_destroy( &attr );\r\n    if ( result ) {\r\n      stream_.callbackInfo.isRunning = false;\r\n      errorText_ = \"RtApiAlsa::error creating callback thread!\";\r\n      goto error;\r\n    }\r\n  }\r\n\r\n  return SUCCESS;\r\n\r\n error:\r\n  if ( apiInfo ) {\r\n    pthread_cond_destroy( &apiInfo->runnable_cv );\r\n    if ( apiInfo->handles[0] ) snd_pcm_close( apiInfo->handles[0] );\r\n    if ( apiInfo->handles[1] ) snd_pcm_close( apiInfo->handles[1] );\r\n    delete apiInfo;\r\n    stream_.apiHandle = 0;\r\n  }\r\n\r\n  if ( phandle) snd_pcm_close( phandle );\r\n\r\n  for ( int i=0; i<2; i++ ) {\r\n    if ( stream_.userBuffer[i] ) {\r\n      free( stream_.userBuffer[i] );\r\n      stream_.userBuffer[i] = 0;\r\n    }\r\n  }\r\n\r\n  if ( stream_.deviceBuffer ) {\r\n    free( stream_.deviceBuffer );\r\n    stream_.deviceBuffer = 0;\r\n  }\r\n\r\n  stream_.state = STREAM_CLOSED;\r\n  return FAILURE;\r\n}\r\n\r\nvoid RtApiAlsa :: closeStream()\r\n{\r\n  if ( stream_.state == STREAM_CLOSED ) {\r\n    errorText_ = \"RtApiAlsa::closeStream(): no open stream to close!\";\r\n    error( RtError::WARNING );\r\n    return;\r\n  }\r\n\r\n  AlsaHandle *apiInfo = (AlsaHandle *) stream_.apiHandle;\r\n  stream_.callbackInfo.isRunning = false;\r\n  MUTEX_LOCK( &stream_.mutex );\r\n  if ( stream_.state == STREAM_STOPPED ) {\r\n    apiInfo->runnable = true;\r\n    pthread_cond_signal( &apiInfo->runnable_cv );\r\n  }\r\n  MUTEX_UNLOCK( &stream_.mutex );\r\n  pthread_join( stream_.callbackInfo.thread, NULL );\r\n\r\n  if ( stream_.state == STREAM_RUNNING ) {\r\n    stream_.state = STREAM_STOPPED;\r\n    if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX )\r\n      snd_pcm_drop( apiInfo->handles[0] );\r\n    if ( stream_.mode == INPUT || stream_.mode == DUPLEX )\r\n      snd_pcm_drop( apiInfo->handles[1] );\r\n  }\r\n\r\n  if ( apiInfo ) {\r\n    pthread_cond_destroy( &apiInfo->runnable_cv );\r\n    if ( apiInfo->handles[0] ) snd_pcm_close( apiInfo->handles[0] );\r\n    if ( apiInfo->handles[1] ) snd_pcm_close( apiInfo->handles[1] );\r\n    delete apiInfo;\r\n    stream_.apiHandle = 0;\r\n  }\r\n\r\n  for ( int i=0; i<2; i++ ) {\r\n    if ( stream_.userBuffer[i] ) {\r\n      free( stream_.userBuffer[i] );\r\n      stream_.userBuffer[i] = 0;\r\n    }\r\n  }\r\n\r\n  if ( stream_.deviceBuffer ) {\r\n    free( stream_.deviceBuffer );\r\n    stream_.deviceBuffer = 0;\r\n  }\r\n\r\n  stream_.mode = UNINITIALIZED;\r\n  stream_.state = STREAM_CLOSED;\r\n}\r\n\r\nvoid RtApiAlsa :: startStream()\r\n{\r\n  // This method calls snd_pcm_prepare if the device isn't already in that state.\r\n\r\n  verifyStream();\r\n  if ( stream_.state == STREAM_RUNNING ) {\r\n    errorText_ = \"RtApiAlsa::startStream(): the stream is already running!\";\r\n    error( RtError::WARNING );\r\n    return;\r\n  }\r\n\r\n  MUTEX_LOCK( &stream_.mutex );\r\n\r\n  int result = 0;\r\n  snd_pcm_state_t state;\r\n  AlsaHandle *apiInfo = (AlsaHandle *) stream_.apiHandle;\r\n  snd_pcm_t **handle = (snd_pcm_t **) apiInfo->handles;\r\n  if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) {\r\n    state = snd_pcm_state( handle[0] );\r\n    if ( state != SND_PCM_STATE_PREPARED ) {\r\n      result = snd_pcm_prepare( handle[0] );\r\n      if ( result < 0 ) {\r\n        errorStream_ << \"RtApiAlsa::startStream: error preparing output pcm device, \" << snd_strerror( result ) << \".\";\r\n        errorText_ = errorStream_.str();\r\n        goto unlock;\r\n      }\r\n    }\r\n  }\r\n\r\n  if ( ( stream_.mode == INPUT || stream_.mode == DUPLEX ) && !apiInfo->synchronized ) {\r\n    state = snd_pcm_state( handle[1] );\r\n    if ( state != SND_PCM_STATE_PREPARED ) {\r\n      result = snd_pcm_prepare( handle[1] );\r\n      if ( result < 0 ) {\r\n        errorStream_ << \"RtApiAlsa::startStream: error preparing input pcm device, \" << snd_strerror( result ) << \".\";\r\n        errorText_ = errorStream_.str();\r\n        goto unlock;\r\n      }\r\n    }\r\n  }\r\n\r\n  stream_.state = STREAM_RUNNING;\r\n\r\n unlock:\r\n  apiInfo->runnable = true;\r\n  pthread_cond_signal( &apiInfo->runnable_cv );\r\n  MUTEX_UNLOCK( &stream_.mutex );\r\n\r\n  if ( result >= 0 ) return;\r\n  error( RtError::SYSTEM_ERROR );\r\n}\r\n\r\nvoid RtApiAlsa :: stopStream()\r\n{\r\n  verifyStream();\r\n  if ( stream_.state == STREAM_STOPPED ) {\r\n    errorText_ = \"RtApiAlsa::stopStream(): the stream is already stopped!\";\r\n    error( RtError::WARNING );\r\n    return;\r\n  }\r\n\r\n  stream_.state = STREAM_STOPPED;\r\n  MUTEX_LOCK( &stream_.mutex );\r\n\r\n  int result = 0;\r\n  AlsaHandle *apiInfo = (AlsaHandle *) stream_.apiHandle;\r\n  snd_pcm_t **handle = (snd_pcm_t **) apiInfo->handles;\r\n  if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) {\r\n    if ( apiInfo->synchronized ) \r\n      result = snd_pcm_drop( handle[0] );\r\n    else\r\n      result = snd_pcm_drain( handle[0] );\r\n    if ( result < 0 ) {\r\n      errorStream_ << \"RtApiAlsa::stopStream: error draining output pcm device, \" << snd_strerror( result ) << \".\";\r\n      errorText_ = errorStream_.str();\r\n      goto unlock;\r\n    }\r\n  }\r\n\r\n  if ( ( stream_.mode == INPUT || stream_.mode == DUPLEX ) && !apiInfo->synchronized ) {\r\n    result = snd_pcm_drop( handle[1] );\r\n    if ( result < 0 ) {\r\n      errorStream_ << \"RtApiAlsa::stopStream: error stopping input pcm device, \" << snd_strerror( result ) << \".\";\r\n      errorText_ = errorStream_.str();\r\n      goto unlock;\r\n    }\r\n  }\r\n\r\n unlock:\r\n  MUTEX_UNLOCK( &stream_.mutex );\r\n\r\n  if ( result >= 0 ) return;\r\n  error( RtError::SYSTEM_ERROR );\r\n}\r\n\r\nvoid RtApiAlsa :: abortStream()\r\n{\r\n  verifyStream();\r\n  if ( stream_.state == STREAM_STOPPED ) {\r\n    errorText_ = \"RtApiAlsa::abortStream(): the stream is already stopped!\";\r\n    error( RtError::WARNING );\r\n    return;\r\n  }\r\n\r\n  stream_.state = STREAM_STOPPED;\r\n  MUTEX_LOCK( &stream_.mutex );\r\n\r\n  int result = 0;\r\n  AlsaHandle *apiInfo = (AlsaHandle *) stream_.apiHandle;\r\n  snd_pcm_t **handle = (snd_pcm_t **) apiInfo->handles;\r\n  if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) {\r\n    result = snd_pcm_drop( handle[0] );\r\n    if ( result < 0 ) {\r\n      errorStream_ << \"RtApiAlsa::abortStream: error aborting output pcm device, \" << snd_strerror( result ) << \".\";\r\n      errorText_ = errorStream_.str();\r\n      goto unlock;\r\n    }\r\n  }\r\n\r\n  if ( ( stream_.mode == INPUT || stream_.mode == DUPLEX ) && !apiInfo->synchronized ) {\r\n    result = snd_pcm_drop( handle[1] );\r\n    if ( result < 0 ) {\r\n      errorStream_ << \"RtApiAlsa::abortStream: error aborting input pcm device, \" << snd_strerror( result ) << \".\";\r\n      errorText_ = errorStream_.str();\r\n      goto unlock;\r\n    }\r\n  }\r\n\r\n unlock:\r\n  MUTEX_UNLOCK( &stream_.mutex );\r\n\r\n  if ( result >= 0 ) return;\r\n  error( RtError::SYSTEM_ERROR );\r\n}\r\n\r\nvoid RtApiAlsa :: callbackEvent()\r\n{\r\n  AlsaHandle *apiInfo = (AlsaHandle *) stream_.apiHandle;\r\n  if ( stream_.state == STREAM_STOPPED ) {\r\n    MUTEX_LOCK( &stream_.mutex );\r\n    while ( !apiInfo->runnable )\r\n      pthread_cond_wait( &apiInfo->runnable_cv, &stream_.mutex );\r\n\r\n    if ( stream_.state != STREAM_RUNNING ) {\r\n      MUTEX_UNLOCK( &stream_.mutex );\r\n      return;\r\n    }\r\n    MUTEX_UNLOCK( &stream_.mutex );\r\n  }\r\n\r\n  if ( stream_.state == STREAM_CLOSED ) {\r\n    errorText_ = \"RtApiAlsa::callbackEvent(): the stream is closed ... this shouldn't happen!\";\r\n    error( RtError::WARNING );\r\n    return;\r\n  }\r\n\r\n  int doStopStream = 0;\r\n  RtAudioCallback callback = (RtAudioCallback) stream_.callbackInfo.callback;\r\n  double streamTime = getStreamTime();\r\n  RtAudioStreamStatus status = 0;\r\n  if ( stream_.mode != INPUT && apiInfo->xrun[0] == true ) {\r\n    status |= RTAUDIO_OUTPUT_UNDERFLOW;\r\n    apiInfo->xrun[0] = false;\r\n  }\r\n  if ( stream_.mode != OUTPUT && apiInfo->xrun[1] == true ) {\r\n    status |= RTAUDIO_INPUT_OVERFLOW;\r\n    apiInfo->xrun[1] = false;\r\n  }\r\n  doStopStream = callback( stream_.userBuffer[0], stream_.userBuffer[1],\r\n                           stream_.bufferSize, streamTime, status, stream_.callbackInfo.userData );\r\n\r\n  if ( doStopStream == 2 ) {\r\n    abortStream();\r\n    return;\r\n  }\r\n\r\n  MUTEX_LOCK( &stream_.mutex );\r\n\r\n  // The state might change while waiting on a mutex.\r\n  if ( stream_.state == STREAM_STOPPED ) goto unlock;\r\n\r\n  int result;\r\n  char *buffer;\r\n  int channels;\r\n  snd_pcm_t **handle;\r\n  snd_pcm_sframes_t frames;\r\n  RtAudioFormat format;\r\n  handle = (snd_pcm_t **) apiInfo->handles;\r\n\r\n  if ( stream_.mode == INPUT || stream_.mode == DUPLEX ) {\r\n\r\n    // Setup parameters.\r\n    if ( stream_.doConvertBuffer[1] ) {\r\n      buffer = stream_.deviceBuffer;\r\n      channels = stream_.nDeviceChannels[1];\r\n      format = stream_.deviceFormat[1];\r\n    }\r\n    else {\r\n      buffer = stream_.userBuffer[1];\r\n      channels = stream_.nUserChannels[1];\r\n      format = stream_.userFormat;\r\n    }\r\n\r\n    // Read samples from device in interleaved/non-interleaved format.\r\n    if ( stream_.deviceInterleaved[1] )\r\n      result = snd_pcm_readi( handle[1], buffer, stream_.bufferSize );\r\n    else {\r\n      void *bufs[channels];\r\n      size_t offset = stream_.bufferSize * formatBytes( format );\r\n      for ( int i=0; i<channels; i++ )\r\n        bufs[i] = (void *) (buffer + (i * offset));\r\n      result = snd_pcm_readn( handle[1], bufs, stream_.bufferSize );\r\n    }\r\n\r\n    if ( result < (int) stream_.bufferSize ) {\r\n      // Either an error or overrun occured.\r\n      if ( result == -EPIPE ) {\r\n        snd_pcm_state_t state = snd_pcm_state( handle[1] );\r\n        if ( state == SND_PCM_STATE_XRUN ) {\r\n          apiInfo->xrun[1] = true;\r\n          result = snd_pcm_prepare( handle[1] );\r\n          if ( result < 0 ) {\r\n            errorStream_ << \"RtApiAlsa::callbackEvent: error preparing device after overrun, \" << snd_strerror( result ) << \".\";\r\n            errorText_ = errorStream_.str();\r\n          }\r\n        }\r\n        else {\r\n          errorStream_ << \"RtApiAlsa::callbackEvent: error, current state is \" << snd_pcm_state_name( state ) << \", \" << snd_strerror( result ) << \".\";\r\n          errorText_ = errorStream_.str();\r\n        }\r\n      }\r\n      else {\r\n        errorStream_ << \"RtApiAlsa::callbackEvent: audio read error, \" << snd_strerror( result ) << \".\";\r\n        errorText_ = errorStream_.str();\r\n      }\r\n      error( RtError::WARNING );\r\n      goto tryOutput;\r\n    }\r\n\r\n    // Do byte swapping if necessary.\r\n    if ( stream_.doByteSwap[1] )\r\n      byteSwapBuffer( buffer, stream_.bufferSize * channels, format );\r\n\r\n    // Do buffer conversion if necessary.\r\n    if ( stream_.doConvertBuffer[1] )\r\n      convertBuffer( stream_.userBuffer[1], stream_.deviceBuffer, stream_.convertInfo[1] );\r\n\r\n    // Check stream latency\r\n    result = snd_pcm_delay( handle[1], &frames );\r\n    if ( result == 0 && frames > 0 ) stream_.latency[1] = frames;\r\n  }\r\n\r\n tryOutput:\r\n\r\n  if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) {\r\n\r\n    // Setup parameters and do buffer conversion if necessary.\r\n    if ( stream_.doConvertBuffer[0] ) {\r\n      buffer = stream_.deviceBuffer;\r\n      convertBuffer( buffer, stream_.userBuffer[0], stream_.convertInfo[0] );\r\n      channels = stream_.nDeviceChannels[0];\r\n      format = stream_.deviceFormat[0];\r\n    }\r\n    else {\r\n      buffer = stream_.userBuffer[0];\r\n      channels = stream_.nUserChannels[0];\r\n      format = stream_.userFormat;\r\n    }\r\n\r\n    // Do byte swapping if necessary.\r\n    if ( stream_.doByteSwap[0] )\r\n      byteSwapBuffer(buffer, stream_.bufferSize * channels, format);\r\n\r\n    // Write samples to device in interleaved/non-interleaved format.\r\n    if ( stream_.deviceInterleaved[0] )\r\n      result = snd_pcm_writei( handle[0], buffer, stream_.bufferSize );\r\n    else {\r\n      void *bufs[channels];\r\n      size_t offset = stream_.bufferSize * formatBytes( format );\r\n      for ( int i=0; i<channels; i++ )\r\n        bufs[i] = (void *) (buffer + (i * offset));\r\n      result = snd_pcm_writen( handle[0], bufs, stream_.bufferSize );\r\n    }\r\n\r\n    if ( result < (int) stream_.bufferSize ) {\r\n      // Either an error or underrun occured.\r\n      if ( result == -EPIPE ) {\r\n        snd_pcm_state_t state = snd_pcm_state( handle[0] );\r\n        if ( state == SND_PCM_STATE_XRUN ) {\r\n          apiInfo->xrun[0] = true;\r\n          result = snd_pcm_prepare( handle[0] );\r\n          if ( result < 0 ) {\r\n            errorStream_ << \"RtApiAlsa::callbackEvent: error preparing device after underrun, \" << snd_strerror( result ) << \".\";\r\n            errorText_ = errorStream_.str();\r\n          }\r\n        }\r\n        else {\r\n          errorStream_ << \"RtApiAlsa::callbackEvent: error, current state is \" << snd_pcm_state_name( state ) << \", \" << snd_strerror( result ) << \".\";\r\n          errorText_ = errorStream_.str();\r\n        }\r\n      }\r\n      else {\r\n        errorStream_ << \"RtApiAlsa::callbackEvent: audio write error, \" << snd_strerror( result ) << \".\";\r\n        errorText_ = errorStream_.str();\r\n      }\r\n      error( RtError::WARNING );\r\n      goto unlock;\r\n    }\r\n\r\n    // Check stream latency\r\n    result = snd_pcm_delay( handle[0], &frames );\r\n    if ( result == 0 && frames > 0 ) stream_.latency[0] = frames;\r\n  }\r\n\r\n unlock:\r\n  MUTEX_UNLOCK( &stream_.mutex );\r\n\r\n  RtApi::tickStreamTime();\r\n  if ( doStopStream == 1 ) this->stopStream();\r\n}\r\n\r\nstatic void *alsaCallbackHandler( void *ptr )\r\n{\r\n  CallbackInfo *info = (CallbackInfo *) ptr;\r\n  RtApiAlsa *object = (RtApiAlsa *) info->object;\r\n  bool *isRunning = &info->isRunning;\r\n\r\n#ifdef SCHED_RR // Undefined with some OSes (eg: NetBSD 1.6.x with GNU Pthread)\r\n  if ( &info->doRealtime ) {\r\n    pthread_t tID = pthread_self();\t // ID of this thread\r\n    sched_param prio = { info->priority }; // scheduling priority of thread\r\n    pthread_setschedparam( tID, SCHED_RR, &prio );\r\n  }\r\n#endif\r\n\r\n  while ( *isRunning == true ) {\r\n    pthread_testcancel();\r\n    object->callbackEvent();\r\n  }\r\n\r\n  pthread_exit( NULL );\r\n}\r\n\r\n//******************** End of __LINUX_ALSA__ *********************//\r\n#endif\r\n\r\n#if defined(__LINUX_PULSE__)\r\n\r\n// Code written by Peter Meerwald, pmeerw@pmeerw.net\r\n// and Tristan Matthews.\r\n\r\n#include <pulse/error.h>\r\n#include <pulse/simple.h>\r\n#include <cstdio>\r\n\r\nstatic const unsigned int SUPPORTED_SAMPLERATES[] = { 8000, 16000, 22050, 32000,\r\n                                                      44100, 48000, 96000, 0};\r\n\r\nstruct rtaudio_pa_format_mapping_t {\r\n  RtAudioFormat rtaudio_format;\r\n  pa_sample_format_t pa_format;\r\n};\r\n\r\nstatic const rtaudio_pa_format_mapping_t supported_sampleformats[] = {\r\n  {RTAUDIO_SINT16, PA_SAMPLE_S16LE},\r\n  {RTAUDIO_SINT32, PA_SAMPLE_S32LE},\r\n  {RTAUDIO_FLOAT32, PA_SAMPLE_FLOAT32LE},\r\n  {0, PA_SAMPLE_INVALID}};\r\n\r\nstruct PulseAudioHandle {\r\n  pa_simple *s_play;\r\n  pa_simple *s_rec;\r\n  pthread_t thread;\r\n  pthread_cond_t runnable_cv;\r\n  bool runnable;\r\n  PulseAudioHandle() : s_play(0), s_rec(0), runnable(false) { }\r\n};\r\n\r\nRtApiPulse::~RtApiPulse()\r\n{\r\n  if ( stream_.state != STREAM_CLOSED )\r\n    closeStream();\r\n}\r\n\r\nunsigned int RtApiPulse::getDeviceCount( void )\r\n{\r\n  return 1;\r\n}\r\n\r\nRtAudio::DeviceInfo RtApiPulse::getDeviceInfo( unsigned int device )\r\n{\r\n  RtAudio::DeviceInfo info;\r\n  info.probed = true;\r\n  info.name = \"PulseAudio\";\r\n  info.outputChannels = 2;\r\n  info.inputChannels = 2;\r\n  info.duplexChannels = 2;\r\n  info.isDefaultOutput = true;\r\n  info.isDefaultInput = true;\r\n\r\n  for ( const unsigned int *sr = SUPPORTED_SAMPLERATES; *sr; ++sr )\r\n    info.sampleRates.push_back( *sr );\r\n\r\n  info.nativeFormats = RTAUDIO_SINT16 | RTAUDIO_SINT32 | RTAUDIO_FLOAT32;\r\n\r\n  return info;\r\n}\r\n\r\nstatic void *pulseaudio_callback( void * user )\r\n{\r\n  CallbackInfo *cbi = static_cast<CallbackInfo *>( user );\r\n  RtApiPulse *context = static_cast<RtApiPulse *>( cbi->object );\r\n  volatile bool *isRunning = &cbi->isRunning;\r\n\r\n  while ( *isRunning ) {\r\n    pthread_testcancel();\r\n    context->callbackEvent();\r\n  }\r\n\r\n  pthread_exit( NULL );\r\n}\r\n\r\nvoid RtApiPulse::closeStream( void )\r\n{\r\n  PulseAudioHandle *pah = static_cast<PulseAudioHandle *>( stream_.apiHandle );\r\n\r\n  stream_.callbackInfo.isRunning = false;\r\n  if ( pah ) {\r\n    MUTEX_LOCK( &stream_.mutex );\r\n    if ( stream_.state == STREAM_STOPPED ) {\r\n      pah->runnable = true;\r\n      pthread_cond_signal( &pah->runnable_cv );\r\n    }\r\n    MUTEX_UNLOCK( &stream_.mutex );\r\n\r\n    pthread_join( pah->thread, 0 );\r\n    if ( pah->s_play ) {\r\n      pa_simple_flush( pah->s_play, NULL );\r\n      pa_simple_free( pah->s_play );\r\n    }\r\n    if ( pah->s_rec )\r\n      pa_simple_free( pah->s_rec );\r\n\r\n    pthread_cond_destroy( &pah->runnable_cv );\r\n    delete pah;\r\n    stream_.apiHandle = 0;\r\n  }\r\n\r\n  if ( stream_.userBuffer[0] ) {\r\n    free( stream_.userBuffer[0] );\r\n    stream_.userBuffer[0] = 0;\r\n  }\r\n  if ( stream_.userBuffer[1] ) {\r\n    free( stream_.userBuffer[1] );\r\n    stream_.userBuffer[1] = 0;\r\n  }\r\n\r\n  stream_.state = STREAM_CLOSED;\r\n  stream_.mode = UNINITIALIZED;\r\n}\r\n\r\nvoid RtApiPulse::callbackEvent( void )\r\n{\r\n  PulseAudioHandle *pah = static_cast<PulseAudioHandle *>( stream_.apiHandle );\r\n\r\n  if ( stream_.state == STREAM_STOPPED ) {\r\n    MUTEX_LOCK( &stream_.mutex );\r\n    while ( !pah->runnable )\r\n      pthread_cond_wait( &pah->runnable_cv, &stream_.mutex );\r\n\r\n    if ( stream_.state != STREAM_RUNNING ) {\r\n      MUTEX_UNLOCK( &stream_.mutex );\r\n      return;\r\n    }\r\n    MUTEX_UNLOCK( &stream_.mutex );\r\n  }\r\n\r\n  if ( stream_.state == STREAM_CLOSED ) {\r\n    errorText_ = \"RtApiPulse::callbackEvent(): the stream is closed ... \"\r\n      \"this shouldn't happen!\";\r\n    error( RtError::WARNING );\r\n    return;\r\n  }\r\n\r\n  RtAudioCallback callback = (RtAudioCallback) stream_.callbackInfo.callback;\r\n  double streamTime = getStreamTime();\r\n  RtAudioStreamStatus status = 0;\r\n  int doStopStream = callback( stream_.userBuffer[OUTPUT], stream_.userBuffer[INPUT],\r\n                               stream_.bufferSize, streamTime, status,\r\n                               stream_.callbackInfo.userData );\r\n\r\n  if ( doStopStream == 2 ) {\r\n    abortStream();\r\n    return;\r\n  }\r\n\r\n  MUTEX_LOCK( &stream_.mutex );\r\n  void *pulse_in = stream_.doConvertBuffer[INPUT] ? stream_.deviceBuffer : stream_.userBuffer[INPUT];\r\n  void *pulse_out = stream_.doConvertBuffer[OUTPUT] ? stream_.deviceBuffer : stream_.userBuffer[OUTPUT];\r\n\r\n  if ( stream_.state != STREAM_RUNNING )\r\n    goto unlock;\r\n\r\n  int pa_error;\r\n  size_t bytes;\r\n  if (stream_.mode == OUTPUT || stream_.mode == DUPLEX ) {\r\n    if ( stream_.doConvertBuffer[OUTPUT] ) {\r\n        convertBuffer( stream_.deviceBuffer,\r\n                       stream_.userBuffer[OUTPUT],\r\n                       stream_.convertInfo[OUTPUT] );\r\n        bytes = stream_.nDeviceChannels[OUTPUT] * stream_.bufferSize *\r\n                formatBytes( stream_.deviceFormat[OUTPUT] );\r\n    } else\r\n        bytes = stream_.nUserChannels[OUTPUT] * stream_.bufferSize *\r\n                formatBytes( stream_.userFormat );\r\n\r\n    if ( pa_simple_write( pah->s_play, pulse_out, bytes, &pa_error ) < 0 ) {\r\n      errorStream_ << \"RtApiPulse::callbackEvent: audio write error, \" <<\r\n        pa_strerror( pa_error ) << \".\";\r\n      errorText_ = errorStream_.str();\r\n      error( RtError::WARNING );\r\n    }\r\n  }\r\n\r\n  if ( stream_.mode == INPUT || stream_.mode == DUPLEX) {\r\n    if ( stream_.doConvertBuffer[INPUT] )\r\n      bytes = stream_.nDeviceChannels[INPUT] * stream_.bufferSize *\r\n        formatBytes( stream_.deviceFormat[INPUT] );\r\n    else\r\n      bytes = stream_.nUserChannels[INPUT] * stream_.bufferSize *\r\n        formatBytes( stream_.userFormat );\r\n            \r\n    if ( pa_simple_read( pah->s_rec, pulse_in, bytes, &pa_error ) < 0 ) {\r\n      errorStream_ << \"RtApiPulse::callbackEvent: audio read error, \" <<\r\n        pa_strerror( pa_error ) << \".\";\r\n      errorText_ = errorStream_.str();\r\n      error( RtError::WARNING );\r\n    }\r\n    if ( stream_.doConvertBuffer[INPUT] ) {\r\n      convertBuffer( stream_.userBuffer[INPUT],\r\n                     stream_.deviceBuffer,\r\n                     stream_.convertInfo[INPUT] );\r\n    }\r\n  }\r\n\r\n unlock:\r\n  MUTEX_UNLOCK( &stream_.mutex );\r\n  RtApi::tickStreamTime();\r\n\r\n  if ( doStopStream == 1 )\r\n    stopStream();\r\n}\r\n\r\nvoid RtApiPulse::startStream( void )\r\n{\r\n  PulseAudioHandle *pah = static_cast<PulseAudioHandle *>( stream_.apiHandle );\r\n\r\n  if ( stream_.state == STREAM_CLOSED ) {\r\n    errorText_ = \"RtApiPulse::startStream(): the stream is not open!\";\r\n    error( RtError::INVALID_USE );\r\n    return;\r\n  }\r\n  if ( stream_.state == STREAM_RUNNING ) {\r\n    errorText_ = \"RtApiPulse::startStream(): the stream is already running!\";\r\n    error( RtError::WARNING );\r\n    return;\r\n  }\r\n\r\n  MUTEX_LOCK( &stream_.mutex );\r\n\r\n  stream_.state = STREAM_RUNNING;\r\n\r\n  pah->runnable = true;\r\n  pthread_cond_signal( &pah->runnable_cv );\r\n  MUTEX_UNLOCK( &stream_.mutex );\r\n}\r\n\r\nvoid RtApiPulse::stopStream( void )\r\n{\r\n  PulseAudioHandle *pah = static_cast<PulseAudioHandle *>( stream_.apiHandle );\r\n\r\n  if ( stream_.state == STREAM_CLOSED ) {\r\n    errorText_ = \"RtApiPulse::stopStream(): the stream is not open!\";\r\n    error( RtError::INVALID_USE );\r\n    return;\r\n  }\r\n  if ( stream_.state == STREAM_STOPPED ) {\r\n    errorText_ = \"RtApiPulse::stopStream(): the stream is already stopped!\";\r\n    error( RtError::WARNING );\r\n    return;\r\n  }\r\n\r\n  stream_.state = STREAM_STOPPED;\r\n  MUTEX_LOCK( &stream_.mutex );\r\n\r\n  if ( pah && pah->s_play ) {\r\n    int pa_error;\r\n    if ( pa_simple_drain( pah->s_play, &pa_error ) < 0 ) {\r\n      errorStream_ << \"RtApiPulse::stopStream: error draining output device, \" <<\r\n        pa_strerror( pa_error ) << \".\";\r\n      errorText_ = errorStream_.str();\r\n      MUTEX_UNLOCK( &stream_.mutex );\r\n      error( RtError::SYSTEM_ERROR );\r\n      return;\r\n    }\r\n  }\r\n\r\n  stream_.state = STREAM_STOPPED;\r\n  MUTEX_UNLOCK( &stream_.mutex );\r\n}\r\n\r\nvoid RtApiPulse::abortStream( void )\r\n{\r\n  PulseAudioHandle *pah = static_cast<PulseAudioHandle*>( stream_.apiHandle );\r\n\r\n  if ( stream_.state == STREAM_CLOSED ) {\r\n    errorText_ = \"RtApiPulse::abortStream(): the stream is not open!\";\r\n    error( RtError::INVALID_USE );\r\n    return;\r\n  }\r\n  if ( stream_.state == STREAM_STOPPED ) {\r\n    errorText_ = \"RtApiPulse::abortStream(): the stream is already stopped!\";\r\n    error( RtError::WARNING );\r\n    return;\r\n  }\r\n\r\n  stream_.state = STREAM_STOPPED;\r\n  MUTEX_LOCK( &stream_.mutex );\r\n\r\n  if ( pah && pah->s_play ) {\r\n    int pa_error;\r\n    if ( pa_simple_flush( pah->s_play, &pa_error ) < 0 ) {\r\n      errorStream_ << \"RtApiPulse::abortStream: error flushing output device, \" <<\r\n        pa_strerror( pa_error ) << \".\";\r\n      errorText_ = errorStream_.str();\r\n      MUTEX_UNLOCK( &stream_.mutex );\r\n      error( RtError::SYSTEM_ERROR );\r\n      return;\r\n    }\r\n  }\r\n\r\n  stream_.state = STREAM_STOPPED;\r\n  MUTEX_UNLOCK( &stream_.mutex );\r\n}\r\n\r\nbool RtApiPulse::probeDeviceOpen( unsigned int device, StreamMode mode,\r\n                                  unsigned int channels, unsigned int firstChannel,\r\n                                  unsigned int sampleRate, RtAudioFormat format,\r\n                                  unsigned int *bufferSize, RtAudio::StreamOptions *options )\r\n{\r\n  PulseAudioHandle *pah = 0;\r\n  unsigned long bufferBytes = 0;\r\n  pa_sample_spec ss;\r\n\r\n  if ( device != 0 ) return false;\r\n  if ( mode != INPUT && mode != OUTPUT ) return false;\r\n  if ( channels != 1 && channels != 2 ) {\r\n    errorText_ = \"RtApiPulse::probeDeviceOpen: unsupported number of channels.\";\r\n    return false;\r\n  }\r\n  ss.channels = channels;\r\n\r\n  if ( firstChannel != 0 ) return false;\r\n\r\n  bool sr_found = false;\r\n  for ( const unsigned int *sr = SUPPORTED_SAMPLERATES; *sr; ++sr ) {\r\n    if ( sampleRate == *sr ) {\r\n      sr_found = true;\r\n      stream_.sampleRate = sampleRate;\r\n      ss.rate = sampleRate;\r\n      break;\r\n    }\r\n  }\r\n  if ( !sr_found ) {\r\n    errorText_ = \"RtApiPulse::probeDeviceOpen: unsupported sample rate.\";\r\n    return false;\r\n  }\r\n\r\n  bool sf_found = 0;\r\n  for ( const rtaudio_pa_format_mapping_t *sf = supported_sampleformats;\r\n        sf->rtaudio_format && sf->pa_format != PA_SAMPLE_INVALID; ++sf ) {\r\n    if ( format == sf->rtaudio_format ) {\r\n      sf_found = true;\r\n      stream_.userFormat = sf->rtaudio_format;\r\n      ss.format = sf->pa_format;\r\n      break;\r\n    }\r\n  }\r\n  if ( !sf_found ) {\r\n    errorText_ = \"RtApiPulse::probeDeviceOpen: unsupported sample format.\";\r\n    return false;\r\n  }\r\n\r\n  // Set interleaving parameters.\r\n  if ( options && options->flags & RTAUDIO_NONINTERLEAVED ) stream_.userInterleaved = false;\r\n  else stream_.userInterleaved = true;\r\n  stream_.deviceInterleaved[mode] = true;\r\n  stream_.nBuffers = 1;\r\n  stream_.doByteSwap[mode] = false;\r\n  stream_.doConvertBuffer[mode] = channels > 1 && !stream_.userInterleaved;\r\n  stream_.deviceFormat[mode] = stream_.userFormat;\r\n  stream_.nUserChannels[mode] = channels;\r\n  stream_.nDeviceChannels[mode] = channels + firstChannel;\r\n  stream_.channelOffset[mode] = 0;\r\n\r\n  // Allocate necessary internal buffers.\r\n  bufferBytes = stream_.nUserChannels[mode] * *bufferSize * formatBytes( stream_.userFormat );\r\n  stream_.userBuffer[mode] = (char *) calloc( bufferBytes, 1 );\r\n  if ( stream_.userBuffer[mode] == NULL ) {\r\n    errorText_ = \"RtApiPulse::probeDeviceOpen: error allocating user buffer memory.\";\r\n    goto error;\r\n  }\r\n  stream_.bufferSize = *bufferSize;\r\n\r\n  if ( stream_.doConvertBuffer[mode] ) {\r\n\r\n    bool makeBuffer = true;\r\n    bufferBytes = stream_.nDeviceChannels[mode] * formatBytes( stream_.deviceFormat[mode] );\r\n    if ( mode == INPUT ) {\r\n      if ( stream_.mode == OUTPUT && stream_.deviceBuffer ) {\r\n        unsigned long bytesOut = stream_.nDeviceChannels[0] * formatBytes( stream_.deviceFormat[0] );\r\n        if ( bufferBytes <= bytesOut ) makeBuffer = false;\r\n      }\r\n    }\r\n\r\n    if ( makeBuffer ) {\r\n      bufferBytes *= *bufferSize;\r\n      if ( stream_.deviceBuffer ) free( stream_.deviceBuffer );\r\n      stream_.deviceBuffer = (char *) calloc( bufferBytes, 1 );\r\n      if ( stream_.deviceBuffer == NULL ) {\r\n        errorText_ = \"RtApiPulse::probeDeviceOpen: error allocating device buffer memory.\";\r\n        goto error;\r\n      }\r\n    }\r\n  }\r\n\r\n  stream_.device[mode] = device;\r\n\r\n  // Setup the buffer conversion information structure.\r\n  if ( stream_.doConvertBuffer[mode] ) setConvertInfo( mode, firstChannel );\r\n\r\n  if ( !stream_.apiHandle ) {\r\n    PulseAudioHandle *pah = new PulseAudioHandle;\r\n    if ( !pah ) {\r\n      errorText_ = \"RtApiPulse::probeDeviceOpen: error allocating memory for handle.\";\r\n      goto error;\r\n    }\r\n\r\n    stream_.apiHandle = pah;\r\n    if ( pthread_cond_init( &pah->runnable_cv, NULL ) != 0 ) {\r\n      errorText_ = \"RtApiPulse::probeDeviceOpen: error creating condition variable.\";\r\n      goto error;\r\n    }\r\n  }\r\n  pah = static_cast<PulseAudioHandle *>( stream_.apiHandle );\r\n\r\n  int error;\r\n  switch ( mode ) {\r\n  case INPUT:\r\n    pah->s_rec = pa_simple_new( NULL, \"RtAudio\", PA_STREAM_RECORD, NULL, \"Record\", &ss, NULL, NULL, &error );\r\n    if ( !pah->s_rec ) {\r\n      errorText_ = \"RtApiPulse::probeDeviceOpen: error connecting input to PulseAudio server.\";\r\n      goto error;\r\n    }\r\n    break;\r\n  case OUTPUT:\r\n    pah->s_play = pa_simple_new( NULL, \"RtAudio\", PA_STREAM_PLAYBACK, NULL, \"Playback\", &ss, NULL, NULL, &error );\r\n    if ( !pah->s_play ) {\r\n      errorText_ = \"RtApiPulse::probeDeviceOpen: error connecting output to PulseAudio server.\";\r\n      goto error;\r\n    }\r\n    break;\r\n  default:\r\n    goto error;\r\n  }\r\n\r\n  if ( stream_.mode == UNINITIALIZED )\r\n    stream_.mode = mode;\r\n  else if ( stream_.mode == mode )\r\n    goto error;\r\n  else\r\n    stream_.mode = DUPLEX;\r\n\r\n  if ( !stream_.callbackInfo.isRunning ) {\r\n    stream_.callbackInfo.object = this;\r\n    stream_.callbackInfo.isRunning = true;\r\n    if ( pthread_create( &pah->thread, NULL, pulseaudio_callback, (void *)&stream_.callbackInfo) != 0 ) {\r\n      errorText_ = \"RtApiPulse::probeDeviceOpen: error creating thread.\";\r\n      goto error;\r\n    }\r\n  }\r\n\r\n  stream_.state = STREAM_STOPPED;\r\n  return true;\r\n \r\n error:\r\n  if ( pah && stream_.callbackInfo.isRunning ) {\r\n    pthread_cond_destroy( &pah->runnable_cv );\r\n    delete pah;\r\n    stream_.apiHandle = 0;\r\n  }\r\n\r\n  for ( int i=0; i<2; i++ ) {\r\n    if ( stream_.userBuffer[i] ) {\r\n      free( stream_.userBuffer[i] );\r\n      stream_.userBuffer[i] = 0;\r\n    }\r\n  }\r\n\r\n  if ( stream_.deviceBuffer ) {\r\n    free( stream_.deviceBuffer );\r\n    stream_.deviceBuffer = 0;\r\n  }\r\n\r\n  return FAILURE;\r\n}\r\n\r\n//******************** End of __LINUX_PULSE__ *********************//\r\n#endif\r\n\r\n#if defined(__LINUX_OSS__)\r\n\r\n#include <unistd.h>\r\n#include <sys/ioctl.h>\r\n#include <unistd.h>\r\n#include <fcntl.h>\r\n#include \"soundcard.h\"\r\n#include <errno.h>\r\n#include <math.h>\r\n\r\nstatic void *ossCallbackHandler(void * ptr);\r\n\r\n// A structure to hold various information related to the OSS API\r\n// implementation.\r\nstruct OssHandle {\r\n  int id[2];    // device ids\r\n  bool xrun[2];\r\n  bool triggered;\r\n  pthread_cond_t runnable;\r\n\r\n  OssHandle()\r\n    :triggered(false) { id[0] = 0; id[1] = 0; xrun[0] = false; xrun[1] = false; }\r\n};\r\n\r\nRtApiOss :: RtApiOss()\r\n{\r\n  // Nothing to do here.\r\n}\r\n\r\nRtApiOss :: ~RtApiOss()\r\n{\r\n  if ( stream_.state != STREAM_CLOSED ) closeStream();\r\n}\r\n\r\nunsigned int RtApiOss :: getDeviceCount( void )\r\n{\r\n  int mixerfd = open( \"/dev/mixer\", O_RDWR, 0 );\r\n  if ( mixerfd == -1 ) {\r\n    errorText_ = \"RtApiOss::getDeviceCount: error opening '/dev/mixer'.\";\r\n    error( RtError::WARNING );\r\n    return 0;\r\n  }\r\n\r\n  oss_sysinfo sysinfo;\r\n  if ( ioctl( mixerfd, SNDCTL_SYSINFO, &sysinfo ) == -1 ) {\r\n    close( mixerfd );\r\n    errorText_ = \"RtApiOss::getDeviceCount: error getting sysinfo, OSS version >= 4.0 is required.\";\r\n    error( RtError::WARNING );\r\n    return 0;\r\n  }\r\n\r\n  close( mixerfd );\r\n  return sysinfo.numaudios;\r\n}\r\n\r\nRtAudio::DeviceInfo RtApiOss :: getDeviceInfo( unsigned int device )\r\n{\r\n  RtAudio::DeviceInfo info;\r\n  info.probed = false;\r\n\r\n  int mixerfd = open( \"/dev/mixer\", O_RDWR, 0 );\r\n  if ( mixerfd == -1 ) {\r\n    errorText_ = \"RtApiOss::getDeviceInfo: error opening '/dev/mixer'.\";\r\n    error( RtError::WARNING );\r\n    return info;\r\n  }\r\n\r\n  oss_sysinfo sysinfo;\r\n  int result = ioctl( mixerfd, SNDCTL_SYSINFO, &sysinfo );\r\n  if ( result == -1 ) {\r\n    close( mixerfd );\r\n    errorText_ = \"RtApiOss::getDeviceInfo: error getting sysinfo, OSS version >= 4.0 is required.\";\r\n    error( RtError::WARNING );\r\n    return info;\r\n  }\r\n\r\n  unsigned nDevices = sysinfo.numaudios;\r\n  if ( nDevices == 0 ) {\r\n    close( mixerfd );\r\n    errorText_ = \"RtApiOss::getDeviceInfo: no devices found!\";\r\n    error( RtError::INVALID_USE );\r\n    return info;\r\n  }\r\n\r\n  if ( device >= nDevices ) {\r\n    close( mixerfd );\r\n    errorText_ = \"RtApiOss::getDeviceInfo: device ID is invalid!\";\r\n    error( RtError::INVALID_USE );\r\n    return info;\r\n  }\r\n\r\n  oss_audioinfo ainfo;\r\n  ainfo.dev = device;\r\n  result = ioctl( mixerfd, SNDCTL_AUDIOINFO, &ainfo );\r\n  close( mixerfd );\r\n  if ( result == -1 ) {\r\n    errorStream_ << \"RtApiOss::getDeviceInfo: error getting device (\" << ainfo.name << \") info.\";\r\n    errorText_ = errorStream_.str();\r\n    error( RtError::WARNING );\r\n    return info;\r\n  }\r\n\r\n  // Probe channels\r\n  if ( ainfo.caps & PCM_CAP_OUTPUT ) info.outputChannels = ainfo.max_channels;\r\n  if ( ainfo.caps & PCM_CAP_INPUT ) info.inputChannels = ainfo.max_channels;\r\n  if ( ainfo.caps & PCM_CAP_DUPLEX ) {\r\n    if ( info.outputChannels > 0 && info.inputChannels > 0 && ainfo.caps & PCM_CAP_DUPLEX )\r\n      info.duplexChannels = (info.outputChannels > info.inputChannels) ? info.inputChannels : info.outputChannels;\r\n  }\r\n\r\n  // Probe data formats ... do for input\r\n  unsigned long mask = ainfo.iformats;\r\n  if ( mask & AFMT_S16_LE || mask & AFMT_S16_BE )\r\n    info.nativeFormats |= RTAUDIO_SINT16;\r\n  if ( mask & AFMT_S8 )\r\n    info.nativeFormats |= RTAUDIO_SINT8;\r\n  if ( mask & AFMT_S32_LE || mask & AFMT_S32_BE )\r\n    info.nativeFormats |= RTAUDIO_SINT32;\r\n  if ( mask & AFMT_FLOAT )\r\n    info.nativeFormats |= RTAUDIO_FLOAT32;\r\n  if ( mask & AFMT_S24_LE || mask & AFMT_S24_BE )\r\n    info.nativeFormats |= RTAUDIO_SINT24;\r\n\r\n  // Check that we have at least one supported format\r\n  if ( info.nativeFormats == 0 ) {\r\n    errorStream_ << \"RtApiOss::getDeviceInfo: device (\" << ainfo.name << \") data format not supported by RtAudio.\";\r\n    errorText_ = errorStream_.str();\r\n    error( RtError::WARNING );\r\n    return info;\r\n  }\r\n\r\n  // Probe the supported sample rates.\r\n  info.sampleRates.clear();\r\n  if ( ainfo.nrates ) {\r\n    for ( unsigned int i=0; i<ainfo.nrates; i++ ) {\r\n      for ( unsigned int k=0; k<MAX_SAMPLE_RATES; k++ ) {\r\n        if ( ainfo.rates[i] == SAMPLE_RATES[k] ) {\r\n          info.sampleRates.push_back( SAMPLE_RATES[k] );\r\n          break;\r\n        }\r\n      }\r\n    }\r\n  }\r\n  else {\r\n    // Check min and max rate values;\r\n    for ( unsigned int k=0; k<MAX_SAMPLE_RATES; k++ ) {\r\n      if ( ainfo.min_rate <= (int) SAMPLE_RATES[k] && ainfo.max_rate >= (int) SAMPLE_RATES[k] )\r\n        info.sampleRates.push_back( SAMPLE_RATES[k] );\r\n    }\r\n  }\r\n\r\n  if ( info.sampleRates.size() == 0 ) {\r\n    errorStream_ << \"RtApiOss::getDeviceInfo: no supported sample rates found for device (\" << ainfo.name << \").\";\r\n    errorText_ = errorStream_.str();\r\n    error( RtError::WARNING );\r\n  }\r\n  else {\r\n    info.probed = true;\r\n    info.name = ainfo.name;\r\n  }\r\n\r\n  return info;\r\n}\r\n\r\n\r\nbool RtApiOss :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels,\r\n                                  unsigned int firstChannel, unsigned int sampleRate,\r\n                                  RtAudioFormat format, unsigned int *bufferSize,\r\n                                  RtAudio::StreamOptions *options )\r\n{\r\n  int mixerfd = open( \"/dev/mixer\", O_RDWR, 0 );\r\n  if ( mixerfd == -1 ) {\r\n    errorText_ = \"RtApiOss::probeDeviceOpen: error opening '/dev/mixer'.\";\r\n    return FAILURE;\r\n  }\r\n\r\n  oss_sysinfo sysinfo;\r\n  int result = ioctl( mixerfd, SNDCTL_SYSINFO, &sysinfo );\r\n  if ( result == -1 ) {\r\n    close( mixerfd );\r\n    errorText_ = \"RtApiOss::probeDeviceOpen: error getting sysinfo, OSS version >= 4.0 is required.\";\r\n    return FAILURE;\r\n  }\r\n\r\n  unsigned nDevices = sysinfo.numaudios;\r\n  if ( nDevices == 0 ) {\r\n    // This should not happen because a check is made before this function is called.\r\n    close( mixerfd );\r\n    errorText_ = \"RtApiOss::probeDeviceOpen: no devices found!\";\r\n    return FAILURE;\r\n  }\r\n\r\n  if ( device >= nDevices ) {\r\n    // This should not happen because a check is made before this function is called.\r\n    close( mixerfd );\r\n    errorText_ = \"RtApiOss::probeDeviceOpen: device ID is invalid!\";\r\n    return FAILURE;\r\n  }\r\n\r\n  oss_audioinfo ainfo;\r\n  ainfo.dev = device;\r\n  result = ioctl( mixerfd, SNDCTL_AUDIOINFO, &ainfo );\r\n  close( mixerfd );\r\n  if ( result == -1 ) {\r\n    errorStream_ << \"RtApiOss::getDeviceInfo: error getting device (\" << ainfo.name << \") info.\";\r\n    errorText_ = errorStream_.str();\r\n    return FAILURE;\r\n  }\r\n\r\n  // Check if device supports input or output\r\n  if ( ( mode == OUTPUT && !( ainfo.caps & PCM_CAP_OUTPUT ) ) ||\r\n       ( mode == INPUT && !( ainfo.caps & PCM_CAP_INPUT ) ) ) {\r\n    if ( mode == OUTPUT )\r\n      errorStream_ << \"RtApiOss::probeDeviceOpen: device (\" << ainfo.name << \") does not support output.\";\r\n    else\r\n      errorStream_ << \"RtApiOss::probeDeviceOpen: device (\" << ainfo.name << \") does not support input.\";\r\n    errorText_ = errorStream_.str();\r\n    return FAILURE;\r\n  }\r\n\r\n  int flags = 0;\r\n  OssHandle *handle = (OssHandle *) stream_.apiHandle;\r\n  if ( mode == OUTPUT )\r\n    flags |= O_WRONLY;\r\n  else { // mode == INPUT\r\n    if (stream_.mode == OUTPUT && stream_.device[0] == device) {\r\n      // We just set the same device for playback ... close and reopen for duplex (OSS only).\r\n      close( handle->id[0] );\r\n      handle->id[0] = 0;\r\n      if ( !( ainfo.caps & PCM_CAP_DUPLEX ) ) {\r\n        errorStream_ << \"RtApiOss::probeDeviceOpen: device (\" << ainfo.name << \") does not support duplex mode.\";\r\n        errorText_ = errorStream_.str();\r\n        return FAILURE;\r\n      }\r\n      // Check that the number previously set channels is the same.\r\n      if ( stream_.nUserChannels[0] != channels ) {\r\n        errorStream_ << \"RtApiOss::probeDeviceOpen: input/output channels must be equal for OSS duplex device (\" << ainfo.name << \").\";\r\n        errorText_ = errorStream_.str();\r\n        return FAILURE;\r\n      }\r\n      flags |= O_RDWR;\r\n    }\r\n    else\r\n      flags |= O_RDONLY;\r\n  }\r\n\r\n  // Set exclusive access if specified.\r\n  if ( options && options->flags & RTAUDIO_HOG_DEVICE ) flags |= O_EXCL;\r\n\r\n  // Try to open the device.\r\n  int fd;\r\n  fd = open( ainfo.devnode, flags, 0 );\r\n  if ( fd == -1 ) {\r\n    if ( errno == EBUSY )\r\n      errorStream_ << \"RtApiOss::probeDeviceOpen: device (\" << ainfo.name << \") is busy.\";\r\n    else\r\n      errorStream_ << \"RtApiOss::probeDeviceOpen: error opening device (\" << ainfo.name << \").\";\r\n    errorText_ = errorStream_.str();\r\n    return FAILURE;\r\n  }\r\n\r\n  // For duplex operation, specifically set this mode (this doesn't seem to work).\r\n  /*\r\n    if ( flags | O_RDWR ) {\r\n    result = ioctl( fd, SNDCTL_DSP_SETDUPLEX, NULL );\r\n    if ( result == -1) {\r\n    errorStream_ << \"RtApiOss::probeDeviceOpen: error setting duplex mode for device (\" << ainfo.name << \").\";\r\n    errorText_ = errorStream_.str();\r\n    return FAILURE;\r\n    }\r\n    }\r\n  */\r\n\r\n  // Check the device channel support.\r\n  stream_.nUserChannels[mode] = channels;\r\n  if ( ainfo.max_channels < (int)(channels + firstChannel) ) {\r\n    close( fd );\r\n    errorStream_ << \"RtApiOss::probeDeviceOpen: the device (\" << ainfo.name << \") does not support requested channel parameters.\";\r\n    errorText_ = errorStream_.str();\r\n    return FAILURE;\r\n  }\r\n\r\n  // Set the number of channels.\r\n  int deviceChannels = channels + firstChannel;\r\n  result = ioctl( fd, SNDCTL_DSP_CHANNELS, &deviceChannels );\r\n  if ( result == -1 || deviceChannels < (int)(channels + firstChannel) ) {\r\n    close( fd );\r\n    errorStream_ << \"RtApiOss::probeDeviceOpen: error setting channel parameters on device (\" << ainfo.name << \").\";\r\n    errorText_ = errorStream_.str();\r\n    return FAILURE;\r\n  }\r\n  stream_.nDeviceChannels[mode] = deviceChannels;\r\n\r\n  // Get the data format mask\r\n  int mask;\r\n  result = ioctl( fd, SNDCTL_DSP_GETFMTS, &mask );\r\n  if ( result == -1 ) {\r\n    close( fd );\r\n    errorStream_ << \"RtApiOss::probeDeviceOpen: error getting device (\" << ainfo.name << \") data formats.\";\r\n    errorText_ = errorStream_.str();\r\n    return FAILURE;\r\n  }\r\n\r\n  // Determine how to set the device format.\r\n  stream_.userFormat = format;\r\n  int deviceFormat = -1;\r\n  stream_.doByteSwap[mode] = false;\r\n  if ( format == RTAUDIO_SINT8 ) {\r\n    if ( mask & AFMT_S8 ) {\r\n      deviceFormat = AFMT_S8;\r\n      stream_.deviceFormat[mode] = RTAUDIO_SINT8;\r\n    }\r\n  }\r\n  else if ( format == RTAUDIO_SINT16 ) {\r\n    if ( mask & AFMT_S16_NE ) {\r\n      deviceFormat = AFMT_S16_NE;\r\n      stream_.deviceFormat[mode] = RTAUDIO_SINT16;\r\n    }\r\n    else if ( mask & AFMT_S16_OE ) {\r\n      deviceFormat = AFMT_S16_OE;\r\n      stream_.deviceFormat[mode] = RTAUDIO_SINT16;\r\n      stream_.doByteSwap[mode] = true;\r\n    }\r\n  }\r\n  else if ( format == RTAUDIO_SINT24 ) {\r\n    if ( mask & AFMT_S24_NE ) {\r\n      deviceFormat = AFMT_S24_NE;\r\n      stream_.deviceFormat[mode] = RTAUDIO_SINT24;\r\n    }\r\n    else if ( mask & AFMT_S24_OE ) {\r\n      deviceFormat = AFMT_S24_OE;\r\n      stream_.deviceFormat[mode] = RTAUDIO_SINT24;\r\n      stream_.doByteSwap[mode] = true;\r\n    }\r\n  }\r\n  else if ( format == RTAUDIO_SINT32 ) {\r\n    if ( mask & AFMT_S32_NE ) {\r\n      deviceFormat = AFMT_S32_NE;\r\n      stream_.deviceFormat[mode] = RTAUDIO_SINT32;\r\n    }\r\n    else if ( mask & AFMT_S32_OE ) {\r\n      deviceFormat = AFMT_S32_OE;\r\n      stream_.deviceFormat[mode] = RTAUDIO_SINT32;\r\n      stream_.doByteSwap[mode] = true;\r\n    }\r\n  }\r\n\r\n  if ( deviceFormat == -1 ) {\r\n    // The user requested format is not natively supported by the device.\r\n    if ( mask & AFMT_S16_NE ) {\r\n      deviceFormat = AFMT_S16_NE;\r\n      stream_.deviceFormat[mode] = RTAUDIO_SINT16;\r\n    }\r\n    else if ( mask & AFMT_S32_NE ) {\r\n      deviceFormat = AFMT_S32_NE;\r\n      stream_.deviceFormat[mode] = RTAUDIO_SINT32;\r\n    }\r\n    else if ( mask & AFMT_S24_NE ) {\r\n      deviceFormat = AFMT_S24_NE;\r\n      stream_.deviceFormat[mode] = RTAUDIO_SINT24;\r\n    }\r\n    else if ( mask & AFMT_S16_OE ) {\r\n      deviceFormat = AFMT_S16_OE;\r\n      stream_.deviceFormat[mode] = RTAUDIO_SINT16;\r\n      stream_.doByteSwap[mode] = true;\r\n    }\r\n    else if ( mask & AFMT_S32_OE ) {\r\n      deviceFormat = AFMT_S32_OE;\r\n      stream_.deviceFormat[mode] = RTAUDIO_SINT32;\r\n      stream_.doByteSwap[mode] = true;\r\n    }\r\n    else if ( mask & AFMT_S24_OE ) {\r\n      deviceFormat = AFMT_S24_OE;\r\n      stream_.deviceFormat[mode] = RTAUDIO_SINT24;\r\n      stream_.doByteSwap[mode] = true;\r\n    }\r\n    else if ( mask & AFMT_S8) {\r\n      deviceFormat = AFMT_S8;\r\n      stream_.deviceFormat[mode] = RTAUDIO_SINT8;\r\n    }\r\n  }\r\n\r\n  if ( stream_.deviceFormat[mode] == 0 ) {\r\n    // This really shouldn't happen ...\r\n    close( fd );\r\n    errorStream_ << \"RtApiOss::probeDeviceOpen: device (\" << ainfo.name << \") data format not supported by RtAudio.\";\r\n    errorText_ = errorStream_.str();\r\n    return FAILURE;\r\n  }\r\n\r\n  // Set the data format.\r\n  int temp = deviceFormat;\r\n  result = ioctl( fd, SNDCTL_DSP_SETFMT, &deviceFormat );\r\n  if ( result == -1 || deviceFormat != temp ) {\r\n    close( fd );\r\n    errorStream_ << \"RtApiOss::probeDeviceOpen: error setting data format on device (\" << ainfo.name << \").\";\r\n    errorText_ = errorStream_.str();\r\n    return FAILURE;\r\n  }\r\n\r\n  // Attempt to set the buffer size.  According to OSS, the minimum\r\n  // number of buffers is two.  The supposed minimum buffer size is 16\r\n  // bytes, so that will be our lower bound.  The argument to this\r\n  // call is in the form 0xMMMMSSSS (hex), where the buffer size (in\r\n  // bytes) is given as 2^SSSS and the number of buffers as 2^MMMM.\r\n  // We'll check the actual value used near the end of the setup\r\n  // procedure.\r\n  int ossBufferBytes = *bufferSize * formatBytes( stream_.deviceFormat[mode] ) * deviceChannels;\r\n  if ( ossBufferBytes < 16 ) ossBufferBytes = 16;\r\n  int buffers = 0;\r\n  if ( options ) buffers = options->numberOfBuffers;\r\n  if ( options && options->flags & RTAUDIO_MINIMIZE_LATENCY ) buffers = 2;\r\n  if ( buffers < 2 ) buffers = 3;\r\n  temp = ((int) buffers << 16) + (int)( log10( (double)ossBufferBytes ) / log10( 2.0 ) );\r\n  result = ioctl( fd, SNDCTL_DSP_SETFRAGMENT, &temp );\r\n  if ( result == -1 ) {\r\n    close( fd );\r\n    errorStream_ << \"RtApiOss::probeDeviceOpen: error setting buffer size on device (\" << ainfo.name << \").\";\r\n    errorText_ = errorStream_.str();\r\n    return FAILURE;\r\n  }\r\n  stream_.nBuffers = buffers;\r\n\r\n  // Save buffer size (in sample frames).\r\n  *bufferSize = ossBufferBytes / ( formatBytes(stream_.deviceFormat[mode]) * deviceChannels );\r\n  stream_.bufferSize = *bufferSize;\r\n\r\n  // Set the sample rate.\r\n  int srate = sampleRate;\r\n  result = ioctl( fd, SNDCTL_DSP_SPEED, &srate );\r\n  if ( result == -1 ) {\r\n    close( fd );\r\n    errorStream_ << \"RtApiOss::probeDeviceOpen: error setting sample rate (\" << sampleRate << \") on device (\" << ainfo.name << \").\";\r\n    errorText_ = errorStream_.str();\r\n    return FAILURE;\r\n  }\r\n\r\n  // Verify the sample rate setup worked.\r\n  if ( abs( srate - sampleRate ) > 100 ) {\r\n    close( fd );\r\n    errorStream_ << \"RtApiOss::probeDeviceOpen: device (\" << ainfo.name << \") does not support sample rate (\" << sampleRate << \").\";\r\n    errorText_ = errorStream_.str();\r\n    return FAILURE;\r\n  }\r\n  stream_.sampleRate = sampleRate;\r\n\r\n  if ( mode == INPUT && stream_.mode == OUTPUT && stream_.device[0] == device) {\r\n    // We're doing duplex setup here.\r\n    stream_.deviceFormat[0] = stream_.deviceFormat[1];\r\n    stream_.nDeviceChannels[0] = deviceChannels;\r\n  }\r\n\r\n  // Set interleaving parameters.\r\n  stream_.userInterleaved = true;\r\n  stream_.deviceInterleaved[mode] =  true;\r\n  if ( options && options->flags & RTAUDIO_NONINTERLEAVED )\r\n    stream_.userInterleaved = false;\r\n\r\n  // Set flags for buffer conversion\r\n  stream_.doConvertBuffer[mode] = false;\r\n  if ( stream_.userFormat != stream_.deviceFormat[mode] )\r\n    stream_.doConvertBuffer[mode] = true;\r\n  if ( stream_.nUserChannels[mode] < stream_.nDeviceChannels[mode] )\r\n    stream_.doConvertBuffer[mode] = true;\r\n  if ( stream_.userInterleaved != stream_.deviceInterleaved[mode] &&\r\n       stream_.nUserChannels[mode] > 1 )\r\n    stream_.doConvertBuffer[mode] = true;\r\n\r\n  // Allocate the stream handles if necessary and then save.\r\n  if ( stream_.apiHandle == 0 ) {\r\n    try {\r\n      handle = new OssHandle;\r\n    }\r\n    catch ( std::bad_alloc& ) {\r\n      errorText_ = \"RtApiOss::probeDeviceOpen: error allocating OssHandle memory.\";\r\n      goto error;\r\n    }\r\n\r\n    if ( pthread_cond_init( &handle->runnable, NULL ) ) {\r\n      errorText_ = \"RtApiOss::probeDeviceOpen: error initializing pthread condition variable.\";\r\n      goto error;\r\n    }\r\n\r\n    stream_.apiHandle = (void *) handle;\r\n  }\r\n  else {\r\n    handle = (OssHandle *) stream_.apiHandle;\r\n  }\r\n  handle->id[mode] = fd;\r\n\r\n  // Allocate necessary internal buffers.\r\n  unsigned long bufferBytes;\r\n  bufferBytes = stream_.nUserChannels[mode] * *bufferSize * formatBytes( stream_.userFormat );\r\n  stream_.userBuffer[mode] = (char *) calloc( bufferBytes, 1 );\r\n  if ( stream_.userBuffer[mode] == NULL ) {\r\n    errorText_ = \"RtApiOss::probeDeviceOpen: error allocating user buffer memory.\";\r\n    goto error;\r\n  }\r\n\r\n  if ( stream_.doConvertBuffer[mode] ) {\r\n\r\n    bool makeBuffer = true;\r\n    bufferBytes = stream_.nDeviceChannels[mode] * formatBytes( stream_.deviceFormat[mode] );\r\n    if ( mode == INPUT ) {\r\n      if ( stream_.mode == OUTPUT && stream_.deviceBuffer ) {\r\n        unsigned long bytesOut = stream_.nDeviceChannels[0] * formatBytes( stream_.deviceFormat[0] );\r\n        if ( bufferBytes <= bytesOut ) makeBuffer = false;\r\n      }\r\n    }\r\n\r\n    if ( makeBuffer ) {\r\n      bufferBytes *= *bufferSize;\r\n      if ( stream_.deviceBuffer ) free( stream_.deviceBuffer );\r\n      stream_.deviceBuffer = (char *) calloc( bufferBytes, 1 );\r\n      if ( stream_.deviceBuffer == NULL ) {\r\n        errorText_ = \"RtApiOss::probeDeviceOpen: error allocating device buffer memory.\";\r\n        goto error;\r\n      }\r\n    }\r\n  }\r\n\r\n  stream_.device[mode] = device;\r\n  stream_.state = STREAM_STOPPED;\r\n\r\n  // Setup the buffer conversion information structure.\r\n  if ( stream_.doConvertBuffer[mode] ) setConvertInfo( mode, firstChannel );\r\n\r\n  // Setup thread if necessary.\r\n  if ( stream_.mode == OUTPUT && mode == INPUT ) {\r\n    // We had already set up an output stream.\r\n    stream_.mode = DUPLEX;\r\n    if ( stream_.device[0] == device ) handle->id[0] = fd;\r\n  }\r\n  else {\r\n    stream_.mode = mode;\r\n\r\n    // Setup callback thread.\r\n    stream_.callbackInfo.object = (void *) this;\r\n\r\n    // Set the thread attributes for joinable and realtime scheduling\r\n    // priority.  The higher priority will only take affect if the\r\n    // program is run as root or suid.\r\n    pthread_attr_t attr;\r\n    pthread_attr_init( &attr );\r\n    pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_JOINABLE );\r\n#ifdef SCHED_RR // Undefined with some OSes (eg: NetBSD 1.6.x with GNU Pthread)\r\n    if ( options && options->flags & RTAUDIO_SCHEDULE_REALTIME ) {\r\n      struct sched_param param;\r\n      int priority = options->priority;\r\n      int min = sched_get_priority_min( SCHED_RR );\r\n      int max = sched_get_priority_max( SCHED_RR );\r\n      if ( priority < min ) priority = min;\r\n      else if ( priority > max ) priority = max;\r\n      param.sched_priority = priority;\r\n      pthread_attr_setschedparam( &attr, &param );\r\n      pthread_attr_setschedpolicy( &attr, SCHED_RR );\r\n    }\r\n    else\r\n      pthread_attr_setschedpolicy( &attr, SCHED_OTHER );\r\n#else\r\n    pthread_attr_setschedpolicy( &attr, SCHED_OTHER );\r\n#endif\r\n\r\n    stream_.callbackInfo.isRunning = true;\r\n    result = pthread_create( &stream_.callbackInfo.thread, &attr, ossCallbackHandler, &stream_.callbackInfo );\r\n    pthread_attr_destroy( &attr );\r\n    if ( result ) {\r\n      stream_.callbackInfo.isRunning = false;\r\n      errorText_ = \"RtApiOss::error creating callback thread!\";\r\n      goto error;\r\n    }\r\n  }\r\n\r\n  return SUCCESS;\r\n\r\n error:\r\n  if ( handle ) {\r\n    pthread_cond_destroy( &handle->runnable );\r\n    if ( handle->id[0] ) close( handle->id[0] );\r\n    if ( handle->id[1] ) close( handle->id[1] );\r\n    delete handle;\r\n    stream_.apiHandle = 0;\r\n  }\r\n\r\n  for ( int i=0; i<2; i++ ) {\r\n    if ( stream_.userBuffer[i] ) {\r\n      free( stream_.userBuffer[i] );\r\n      stream_.userBuffer[i] = 0;\r\n    }\r\n  }\r\n\r\n  if ( stream_.deviceBuffer ) {\r\n    free( stream_.deviceBuffer );\r\n    stream_.deviceBuffer = 0;\r\n  }\r\n\r\n  return FAILURE;\r\n}\r\n\r\nvoid RtApiOss :: closeStream()\r\n{\r\n  if ( stream_.state == STREAM_CLOSED ) {\r\n    errorText_ = \"RtApiOss::closeStream(): no open stream to close!\";\r\n    error( RtError::WARNING );\r\n    return;\r\n  }\r\n\r\n  OssHandle *handle = (OssHandle *) stream_.apiHandle;\r\n  stream_.callbackInfo.isRunning = false;\r\n  MUTEX_LOCK( &stream_.mutex );\r\n  if ( stream_.state == STREAM_STOPPED )\r\n    pthread_cond_signal( &handle->runnable );\r\n  MUTEX_UNLOCK( &stream_.mutex );\r\n  pthread_join( stream_.callbackInfo.thread, NULL );\r\n\r\n  if ( stream_.state == STREAM_RUNNING ) {\r\n    if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX )\r\n      ioctl( handle->id[0], SNDCTL_DSP_HALT, 0 );\r\n    else\r\n      ioctl( handle->id[1], SNDCTL_DSP_HALT, 0 );\r\n    stream_.state = STREAM_STOPPED;\r\n  }\r\n\r\n  if ( handle ) {\r\n    pthread_cond_destroy( &handle->runnable );\r\n    if ( handle->id[0] ) close( handle->id[0] );\r\n    if ( handle->id[1] ) close( handle->id[1] );\r\n    delete handle;\r\n    stream_.apiHandle = 0;\r\n  }\r\n\r\n  for ( int i=0; i<2; i++ ) {\r\n    if ( stream_.userBuffer[i] ) {\r\n      free( stream_.userBuffer[i] );\r\n      stream_.userBuffer[i] = 0;\r\n    }\r\n  }\r\n\r\n  if ( stream_.deviceBuffer ) {\r\n    free( stream_.deviceBuffer );\r\n    stream_.deviceBuffer = 0;\r\n  }\r\n\r\n  stream_.mode = UNINITIALIZED;\r\n  stream_.state = STREAM_CLOSED;\r\n}\r\n\r\nvoid RtApiOss :: startStream()\r\n{\r\n  verifyStream();\r\n  if ( stream_.state == STREAM_RUNNING ) {\r\n    errorText_ = \"RtApiOss::startStream(): the stream is already running!\";\r\n    error( RtError::WARNING );\r\n    return;\r\n  }\r\n\r\n  MUTEX_LOCK( &stream_.mutex );\r\n\r\n  stream_.state = STREAM_RUNNING;\r\n\r\n  // No need to do anything else here ... OSS automatically starts\r\n  // when fed samples.\r\n\r\n  MUTEX_UNLOCK( &stream_.mutex );\r\n\r\n  OssHandle *handle = (OssHandle *) stream_.apiHandle;\r\n  pthread_cond_signal( &handle->runnable );\r\n}\r\n\r\nvoid RtApiOss :: stopStream()\r\n{\r\n  verifyStream();\r\n  if ( stream_.state == STREAM_STOPPED ) {\r\n    errorText_ = \"RtApiOss::stopStream(): the stream is already stopped!\";\r\n    error( RtError::WARNING );\r\n    return;\r\n  }\r\n\r\n  MUTEX_LOCK( &stream_.mutex );\r\n\r\n  // The state might change while waiting on a mutex.\r\n  if ( stream_.state == STREAM_STOPPED ) {\r\n    MUTEX_UNLOCK( &stream_.mutex );\r\n    return;\r\n  }\r\n\r\n  int result = 0;\r\n  OssHandle *handle = (OssHandle *) stream_.apiHandle;\r\n  if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) {\r\n\r\n    // Flush the output with zeros a few times.\r\n    char *buffer;\r\n    int samples;\r\n    RtAudioFormat format;\r\n\r\n    if ( stream_.doConvertBuffer[0] ) {\r\n      buffer = stream_.deviceBuffer;\r\n      samples = stream_.bufferSize * stream_.nDeviceChannels[0];\r\n      format = stream_.deviceFormat[0];\r\n    }\r\n    else {\r\n      buffer = stream_.userBuffer[0];\r\n      samples = stream_.bufferSize * stream_.nUserChannels[0];\r\n      format = stream_.userFormat;\r\n    }\r\n\r\n    memset( buffer, 0, samples * formatBytes(format) );\r\n    for ( unsigned int i=0; i<stream_.nBuffers+1; i++ ) {\r\n      result = write( handle->id[0], buffer, samples * formatBytes(format) );\r\n      if ( result == -1 ) {\r\n        errorText_ = \"RtApiOss::stopStream: audio write error.\";\r\n        error( RtError::WARNING );\r\n      }\r\n    }\r\n\r\n    result = ioctl( handle->id[0], SNDCTL_DSP_HALT, 0 );\r\n    if ( result == -1 ) {\r\n      errorStream_ << \"RtApiOss::stopStream: system error stopping callback procedure on device (\" << stream_.device[0] << \").\";\r\n      errorText_ = errorStream_.str();\r\n      goto unlock;\r\n    }\r\n    handle->triggered = false;\r\n  }\r\n\r\n  if ( stream_.mode == INPUT || ( stream_.mode == DUPLEX && handle->id[0] != handle->id[1] ) ) {\r\n    result = ioctl( handle->id[1], SNDCTL_DSP_HALT, 0 );\r\n    if ( result == -1 ) {\r\n      errorStream_ << \"RtApiOss::stopStream: system error stopping input callback procedure on device (\" << stream_.device[0] << \").\";\r\n      errorText_ = errorStream_.str();\r\n      goto unlock;\r\n    }\r\n  }\r\n\r\n unlock:\r\n  stream_.state = STREAM_STOPPED;\r\n  MUTEX_UNLOCK( &stream_.mutex );\r\n\r\n  if ( result != -1 ) return;\r\n  error( RtError::SYSTEM_ERROR );\r\n}\r\n\r\nvoid RtApiOss :: abortStream()\r\n{\r\n  verifyStream();\r\n  if ( stream_.state == STREAM_STOPPED ) {\r\n    errorText_ = \"RtApiOss::abortStream(): the stream is already stopped!\";\r\n    error( RtError::WARNING );\r\n    return;\r\n  }\r\n\r\n  MUTEX_LOCK( &stream_.mutex );\r\n\r\n  // The state might change while waiting on a mutex.\r\n  if ( stream_.state == STREAM_STOPPED ) {\r\n    MUTEX_UNLOCK( &stream_.mutex );\r\n    return;\r\n  }\r\n\r\n  int result = 0;\r\n  OssHandle *handle = (OssHandle *) stream_.apiHandle;\r\n  if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) {\r\n    result = ioctl( handle->id[0], SNDCTL_DSP_HALT, 0 );\r\n    if ( result == -1 ) {\r\n      errorStream_ << \"RtApiOss::abortStream: system error stopping callback procedure on device (\" << stream_.device[0] << \").\";\r\n      errorText_ = errorStream_.str();\r\n      goto unlock;\r\n    }\r\n    handle->triggered = false;\r\n  }\r\n\r\n  if ( stream_.mode == INPUT || ( stream_.mode == DUPLEX && handle->id[0] != handle->id[1] ) ) {\r\n    result = ioctl( handle->id[1], SNDCTL_DSP_HALT, 0 );\r\n    if ( result == -1 ) {\r\n      errorStream_ << \"RtApiOss::abortStream: system error stopping input callback procedure on device (\" << stream_.device[0] << \").\";\r\n      errorText_ = errorStream_.str();\r\n      goto unlock;\r\n    }\r\n  }\r\n\r\n unlock:\r\n  stream_.state = STREAM_STOPPED;\r\n  MUTEX_UNLOCK( &stream_.mutex );\r\n\r\n  if ( result != -1 ) return;\r\n  error( RtError::SYSTEM_ERROR );\r\n}\r\n\r\nvoid RtApiOss :: callbackEvent()\r\n{\r\n  OssHandle *handle = (OssHandle *) stream_.apiHandle;\r\n  if ( stream_.state == STREAM_STOPPED ) {\r\n    MUTEX_LOCK( &stream_.mutex );\r\n    pthread_cond_wait( &handle->runnable, &stream_.mutex );\r\n    if ( stream_.state != STREAM_RUNNING ) {\r\n      MUTEX_UNLOCK( &stream_.mutex );\r\n      return;\r\n    }\r\n    MUTEX_UNLOCK( &stream_.mutex );\r\n  }\r\n\r\n  if ( stream_.state == STREAM_CLOSED ) {\r\n    errorText_ = \"RtApiOss::callbackEvent(): the stream is closed ... this shouldn't happen!\";\r\n    error( RtError::WARNING );\r\n    return;\r\n  }\r\n\r\n  // Invoke user callback to get fresh output data.\r\n  int doStopStream = 0;\r\n  RtAudioCallback callback = (RtAudioCallback) stream_.callbackInfo.callback;\r\n  double streamTime = getStreamTime();\r\n  RtAudioStreamStatus status = 0;\r\n  if ( stream_.mode != INPUT && handle->xrun[0] == true ) {\r\n    status |= RTAUDIO_OUTPUT_UNDERFLOW;\r\n    handle->xrun[0] = false;\r\n  }\r\n  if ( stream_.mode != OUTPUT && handle->xrun[1] == true ) {\r\n    status |= RTAUDIO_INPUT_OVERFLOW;\r\n    handle->xrun[1] = false;\r\n  }\r\n  doStopStream = callback( stream_.userBuffer[0], stream_.userBuffer[1],\r\n                           stream_.bufferSize, streamTime, status, stream_.callbackInfo.userData );\r\n  if ( doStopStream == 2 ) {\r\n    this->abortStream();\r\n    return;\r\n  }\r\n\r\n  MUTEX_LOCK( &stream_.mutex );\r\n\r\n  // The state might change while waiting on a mutex.\r\n  if ( stream_.state == STREAM_STOPPED ) goto unlock;\r\n\r\n  int result;\r\n  char *buffer;\r\n  int samples;\r\n  RtAudioFormat format;\r\n\r\n  if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) {\r\n\r\n    // Setup parameters and do buffer conversion if necessary.\r\n    if ( stream_.doConvertBuffer[0] ) {\r\n      buffer = stream_.deviceBuffer;\r\n      convertBuffer( buffer, stream_.userBuffer[0], stream_.convertInfo[0] );\r\n      samples = stream_.bufferSize * stream_.nDeviceChannels[0];\r\n      format = stream_.deviceFormat[0];\r\n    }\r\n    else {\r\n      buffer = stream_.userBuffer[0];\r\n      samples = stream_.bufferSize * stream_.nUserChannels[0];\r\n      format = stream_.userFormat;\r\n    }\r\n\r\n    // Do byte swapping if necessary.\r\n    if ( stream_.doByteSwap[0] )\r\n      byteSwapBuffer( buffer, samples, format );\r\n\r\n    if ( stream_.mode == DUPLEX && handle->triggered == false ) {\r\n      int trig = 0;\r\n      ioctl( handle->id[0], SNDCTL_DSP_SETTRIGGER, &trig );\r\n      result = write( handle->id[0], buffer, samples * formatBytes(format) );\r\n      trig = PCM_ENABLE_INPUT|PCM_ENABLE_OUTPUT;\r\n      ioctl( handle->id[0], SNDCTL_DSP_SETTRIGGER, &trig );\r\n      handle->triggered = true;\r\n    }\r\n    else\r\n      // Write samples to device.\r\n      result = write( handle->id[0], buffer, samples * formatBytes(format) );\r\n\r\n    if ( result == -1 ) {\r\n      // We'll assume this is an underrun, though there isn't a\r\n      // specific means for determining that.\r\n      handle->xrun[0] = true;\r\n      errorText_ = \"RtApiOss::callbackEvent: audio write error.\";\r\n      error( RtError::WARNING );\r\n      // Continue on to input section.\r\n    }\r\n  }\r\n\r\n  if ( stream_.mode == INPUT || stream_.mode == DUPLEX ) {\r\n\r\n    // Setup parameters.\r\n    if ( stream_.doConvertBuffer[1] ) {\r\n      buffer = stream_.deviceBuffer;\r\n      samples = stream_.bufferSize * stream_.nDeviceChannels[1];\r\n      format = stream_.deviceFormat[1];\r\n    }\r\n    else {\r\n      buffer = stream_.userBuffer[1];\r\n      samples = stream_.bufferSize * stream_.nUserChannels[1];\r\n      format = stream_.userFormat;\r\n    }\r\n\r\n    // Read samples from device.\r\n    result = read( handle->id[1], buffer, samples * formatBytes(format) );\r\n\r\n    if ( result == -1 ) {\r\n      // We'll assume this is an overrun, though there isn't a\r\n      // specific means for determining that.\r\n      handle->xrun[1] = true;\r\n      errorText_ = \"RtApiOss::callbackEvent: audio read error.\";\r\n      error( RtError::WARNING );\r\n      goto unlock;\r\n    }\r\n\r\n    // Do byte swapping if necessary.\r\n    if ( stream_.doByteSwap[1] )\r\n      byteSwapBuffer( buffer, samples, format );\r\n\r\n    // Do buffer conversion if necessary.\r\n    if ( stream_.doConvertBuffer[1] )\r\n      convertBuffer( stream_.userBuffer[1], stream_.deviceBuffer, stream_.convertInfo[1] );\r\n  }\r\n\r\n unlock:\r\n  MUTEX_UNLOCK( &stream_.mutex );\r\n\r\n  RtApi::tickStreamTime();\r\n  if ( doStopStream == 1 ) this->stopStream();\r\n}\r\n\r\nstatic void *ossCallbackHandler( void *ptr )\r\n{\r\n  CallbackInfo *info = (CallbackInfo *) ptr;\r\n  RtApiOss *object = (RtApiOss *) info->object;\r\n  bool *isRunning = &info->isRunning;\r\n\r\n  while ( *isRunning == true ) {\r\n    pthread_testcancel();\r\n    object->callbackEvent();\r\n  }\r\n\r\n  pthread_exit( NULL );\r\n}\r\n\r\n//******************** End of __LINUX_OSS__ *********************//\r\n#endif\r\n\r\n\r\n// *************************************************** //\r\n//\r\n// Protected common (OS-independent) RtAudio methods.\r\n//\r\n// *************************************************** //\r\n\r\n// This method can be modified to control the behavior of error\r\n// message printing.\r\nvoid RtApi :: error( RtError::Type type )\r\n{\r\n  errorStream_.str(\"\"); // clear the ostringstream\r\n\r\n  RtAudioErrorCallback errorCallback = (RtAudioErrorCallback) stream_.callbackInfo.errorCallback;\r\n  if ( errorCallback ) {\r\n    // abortStream() can generate new error messages. Ignore them. Just keep original one.\r\n    static bool firstErrorOccured = false;\r\n\r\n    if ( firstErrorOccured )\r\n      return;\r\n\r\n    firstErrorOccured = true;\r\n    const std::string errorMessage = errorText_;\r\n\r\n    if ( type != RtError::WARNING && stream_.state != STREAM_STOPPED) {\r\n      stream_.callbackInfo.isRunning = false; // exit from the thread\r\n      abortStream();\r\n    }\r\n\r\n    errorCallback( type, errorMessage );\r\n    firstErrorOccured = false;\r\n    return;\r\n  }\r\n\r\n  if ( type == RtError::WARNING && showWarnings_ == true )\r\n    std::cerr << '\\n' << errorText_ << \"\\n\\n\";\r\n  else if ( type != RtError::WARNING )\r\n    throw( RtError( errorText_, type ) );\r\n}\r\n\r\nvoid RtApi :: verifyStream()\r\n{\r\n  if ( stream_.state == STREAM_CLOSED ) {\r\n    errorText_ = \"RtApi:: a stream is not open!\";\r\n    error( RtError::INVALID_USE );\r\n  }\r\n}\r\n\r\nvoid RtApi :: clearStreamInfo()\r\n{\r\n  stream_.mode = UNINITIALIZED;\r\n  stream_.state = STREAM_CLOSED;\r\n  stream_.sampleRate = 0;\r\n  stream_.bufferSize = 0;\r\n  stream_.nBuffers = 0;\r\n  stream_.userFormat = 0;\r\n  stream_.userInterleaved = true;\r\n  stream_.streamTime = 0.0;\r\n  stream_.apiHandle = 0;\r\n  stream_.deviceBuffer = 0;\r\n  stream_.callbackInfo.callback = 0;\r\n  stream_.callbackInfo.userData = 0;\r\n  stream_.callbackInfo.isRunning = false;\r\n  stream_.callbackInfo.errorCallback = 0;\r\n  for ( int i=0; i<2; i++ ) {\r\n    stream_.device[i] = 11111;\r\n    stream_.doConvertBuffer[i] = false;\r\n    stream_.deviceInterleaved[i] = true;\r\n    stream_.doByteSwap[i] = false;\r\n    stream_.nUserChannels[i] = 0;\r\n    stream_.nDeviceChannels[i] = 0;\r\n    stream_.channelOffset[i] = 0;\r\n    stream_.deviceFormat[i] = 0;\r\n    stream_.latency[i] = 0;\r\n    stream_.userBuffer[i] = 0;\r\n    stream_.convertInfo[i].channels = 0;\r\n    stream_.convertInfo[i].inJump = 0;\r\n    stream_.convertInfo[i].outJump = 0;\r\n    stream_.convertInfo[i].inFormat = 0;\r\n    stream_.convertInfo[i].outFormat = 0;\r\n    stream_.convertInfo[i].inOffset.clear();\r\n    stream_.convertInfo[i].outOffset.clear();\r\n  }\r\n}\r\n\r\nunsigned int RtApi :: formatBytes( RtAudioFormat format )\r\n{\r\n  if ( format == RTAUDIO_SINT16 )\r\n    return 2;\r\n  else if ( format == RTAUDIO_SINT32 || format == RTAUDIO_FLOAT32 )\r\n    return 4;\r\n  else if ( format == RTAUDIO_FLOAT64 )\r\n    return 8;\r\n  else if ( format == RTAUDIO_SINT24 )\r\n    return 3;\r\n  else if ( format == RTAUDIO_SINT8 )\r\n    return 1;\r\n\r\n  errorText_ = \"RtApi::formatBytes: undefined format.\";\r\n  error( RtError::WARNING );\r\n\r\n  return 0;\r\n}\r\n\r\nvoid RtApi :: setConvertInfo( StreamMode mode, unsigned int firstChannel )\r\n{\r\n  if ( mode == INPUT ) { // convert device to user buffer\r\n    stream_.convertInfo[mode].inJump = stream_.nDeviceChannels[1];\r\n    stream_.convertInfo[mode].outJump = stream_.nUserChannels[1];\r\n    stream_.convertInfo[mode].inFormat = stream_.deviceFormat[1];\r\n    stream_.convertInfo[mode].outFormat = stream_.userFormat;\r\n  }\r\n  else { // convert user to device buffer\r\n    stream_.convertInfo[mode].inJump = stream_.nUserChannels[0];\r\n    stream_.convertInfo[mode].outJump = stream_.nDeviceChannels[0];\r\n    stream_.convertInfo[mode].inFormat = stream_.userFormat;\r\n    stream_.convertInfo[mode].outFormat = stream_.deviceFormat[0];\r\n  }\r\n\r\n  if ( stream_.convertInfo[mode].inJump < stream_.convertInfo[mode].outJump )\r\n    stream_.convertInfo[mode].channels = stream_.convertInfo[mode].inJump;\r\n  else\r\n    stream_.convertInfo[mode].channels = stream_.convertInfo[mode].outJump;\r\n\r\n  // Set up the interleave/deinterleave offsets.\r\n  if ( stream_.deviceInterleaved[mode] != stream_.userInterleaved ) {\r\n    if ( ( mode == OUTPUT && stream_.deviceInterleaved[mode] ) ||\r\n         ( mode == INPUT && stream_.userInterleaved ) ) {\r\n      for ( int k=0; k<stream_.convertInfo[mode].channels; k++ ) {\r\n        stream_.convertInfo[mode].inOffset.push_back( k * stream_.bufferSize );\r\n        stream_.convertInfo[mode].outOffset.push_back( k );\r\n        stream_.convertInfo[mode].inJump = 1;\r\n      }\r\n    }\r\n    else {\r\n      for ( int k=0; k<stream_.convertInfo[mode].channels; k++ ) {\r\n        stream_.convertInfo[mode].inOffset.push_back( k );\r\n        stream_.convertInfo[mode].outOffset.push_back( k * stream_.bufferSize );\r\n        stream_.convertInfo[mode].outJump = 1;\r\n      }\r\n    }\r\n  }\r\n  else { // no (de)interleaving\r\n    if ( stream_.userInterleaved ) {\r\n      for ( int k=0; k<stream_.convertInfo[mode].channels; k++ ) {\r\n        stream_.convertInfo[mode].inOffset.push_back( k );\r\n        stream_.convertInfo[mode].outOffset.push_back( k );\r\n      }\r\n    }\r\n    else {\r\n      for ( int k=0; k<stream_.convertInfo[mode].channels; k++ ) {\r\n        stream_.convertInfo[mode].inOffset.push_back( k * stream_.bufferSize );\r\n        stream_.convertInfo[mode].outOffset.push_back( k * stream_.bufferSize );\r\n        stream_.convertInfo[mode].inJump = 1;\r\n        stream_.convertInfo[mode].outJump = 1;\r\n      }\r\n    }\r\n  }\r\n\r\n  // Add channel offset.\r\n  if ( firstChannel > 0 ) {\r\n    if ( stream_.deviceInterleaved[mode] ) {\r\n      if ( mode == OUTPUT ) {\r\n        for ( int k=0; k<stream_.convertInfo[mode].channels; k++ )\r\n          stream_.convertInfo[mode].outOffset[k] += firstChannel;\r\n      }\r\n      else {\r\n        for ( int k=0; k<stream_.convertInfo[mode].channels; k++ )\r\n          stream_.convertInfo[mode].inOffset[k] += firstChannel;\r\n      }\r\n    }\r\n    else {\r\n      if ( mode == OUTPUT ) {\r\n        for ( int k=0; k<stream_.convertInfo[mode].channels; k++ )\r\n          stream_.convertInfo[mode].outOffset[k] += ( firstChannel * stream_.bufferSize );\r\n      }\r\n      else {\r\n        for ( int k=0; k<stream_.convertInfo[mode].channels; k++ )\r\n          stream_.convertInfo[mode].inOffset[k] += ( firstChannel  * stream_.bufferSize );\r\n      }\r\n    }\r\n  }\r\n}\r\n\r\nvoid RtApi :: convertBuffer( char *outBuffer, char *inBuffer, ConvertInfo &info )\r\n{\r\n  // This function does format conversion, input/output channel compensation, and\r\n  // data interleaving/deinterleaving.  24-bit integers are assumed to occupy\r\n  // the lower three bytes of a 32-bit integer.\r\n\r\n  // Clear our device buffer when in/out duplex device channels are different\r\n  if ( outBuffer == stream_.deviceBuffer && stream_.mode == DUPLEX &&\r\n       ( stream_.nDeviceChannels[0] < stream_.nDeviceChannels[1] ) )\r\n    memset( outBuffer, 0, stream_.bufferSize * info.outJump * formatBytes( info.outFormat ) );\r\n\r\n  int j;\r\n  if (info.outFormat == RTAUDIO_FLOAT64) {\r\n    Float64 scale;\r\n    Float64 *out = (Float64 *)outBuffer;\r\n\r\n    if (info.inFormat == RTAUDIO_SINT8) {\r\n      signed char *in = (signed char *)inBuffer;\r\n      scale = 1.0 / 127.5;\r\n      for (unsigned int i=0; i<stream_.bufferSize; i++) {\r\n        for (j=0; j<info.channels; j++) {\r\n          out[info.outOffset[j]] = (Float64) in[info.inOffset[j]];\r\n          out[info.outOffset[j]] += 0.5;\r\n          out[info.outOffset[j]] *= scale;\r\n        }\r\n        in += info.inJump;\r\n        out += info.outJump;\r\n      }\r\n    }\r\n    else if (info.inFormat == RTAUDIO_SINT16) {\r\n      Int16 *in = (Int16 *)inBuffer;\r\n      scale = 1.0 / 32767.5;\r\n      for (unsigned int i=0; i<stream_.bufferSize; i++) {\r\n        for (j=0; j<info.channels; j++) {\r\n          out[info.outOffset[j]] = (Float64) in[info.inOffset[j]];\r\n          out[info.outOffset[j]] += 0.5;\r\n          out[info.outOffset[j]] *= scale;\r\n        }\r\n        in += info.inJump;\r\n        out += info.outJump;\r\n      }\r\n    }\r\n    else if (info.inFormat == RTAUDIO_SINT24) {\r\n      Int24 *in = (Int24 *)inBuffer;\r\n      scale = 1.0 / 8388607.5;\r\n      for (unsigned int i=0; i<stream_.bufferSize; i++) {\r\n        for (j=0; j<info.channels; j++) {\r\n          out[info.outOffset[j]] = (Float64) (in[info.inOffset[j]].asInt());\r\n          out[info.outOffset[j]] += 0.5;\r\n          out[info.outOffset[j]] *= scale;\r\n        }\r\n        in += info.inJump;\r\n        out += info.outJump;\r\n      }\r\n    }\r\n    else if (info.inFormat == RTAUDIO_SINT32) {\r\n      Int32 *in = (Int32 *)inBuffer;\r\n      scale = 1.0 / 2147483647.5;\r\n      for (unsigned int i=0; i<stream_.bufferSize; i++) {\r\n        for (j=0; j<info.channels; j++) {\r\n          out[info.outOffset[j]] = (Float64) in[info.inOffset[j]];\r\n          out[info.outOffset[j]] += 0.5;\r\n          out[info.outOffset[j]] *= scale;\r\n        }\r\n        in += info.inJump;\r\n        out += info.outJump;\r\n      }\r\n    }\r\n    else if (info.inFormat == RTAUDIO_FLOAT32) {\r\n      Float32 *in = (Float32 *)inBuffer;\r\n      for (unsigned int i=0; i<stream_.bufferSize; i++) {\r\n        for (j=0; j<info.channels; j++) {\r\n          out[info.outOffset[j]] = (Float64) in[info.inOffset[j]];\r\n        }\r\n        in += info.inJump;\r\n        out += info.outJump;\r\n      }\r\n    }\r\n    else if (info.inFormat == RTAUDIO_FLOAT64) {\r\n      // Channel compensation and/or (de)interleaving only.\r\n      Float64 *in = (Float64 *)inBuffer;\r\n      for (unsigned int i=0; i<stream_.bufferSize; i++) {\r\n        for (j=0; j<info.channels; j++) {\r\n          out[info.outOffset[j]] = in[info.inOffset[j]];\r\n        }\r\n        in += info.inJump;\r\n        out += info.outJump;\r\n      }\r\n    }\r\n  }\r\n  else if (info.outFormat == RTAUDIO_FLOAT32) {\r\n    Float32 scale;\r\n    Float32 *out = (Float32 *)outBuffer;\r\n\r\n    if (info.inFormat == RTAUDIO_SINT8) {\r\n      signed char *in = (signed char *)inBuffer;\r\n      scale = (Float32) ( 1.0 / 127.5 );\r\n      for (unsigned int i=0; i<stream_.bufferSize; i++) {\r\n        for (j=0; j<info.channels; j++) {\r\n          out[info.outOffset[j]] = (Float32) in[info.inOffset[j]];\r\n          out[info.outOffset[j]] += 0.5;\r\n          out[info.outOffset[j]] *= scale;\r\n        }\r\n        in += info.inJump;\r\n        out += info.outJump;\r\n      }\r\n    }\r\n    else if (info.inFormat == RTAUDIO_SINT16) {\r\n      Int16 *in = (Int16 *)inBuffer;\r\n      scale = (Float32) ( 1.0 / 32767.5 );\r\n      for (unsigned int i=0; i<stream_.bufferSize; i++) {\r\n        for (j=0; j<info.channels; j++) {\r\n          out[info.outOffset[j]] = (Float32) in[info.inOffset[j]];\r\n          out[info.outOffset[j]] += 0.5;\r\n          out[info.outOffset[j]] *= scale;\r\n        }\r\n        in += info.inJump;\r\n        out += info.outJump;\r\n      }\r\n    }\r\n    else if (info.inFormat == RTAUDIO_SINT24) {\r\n      Int24 *in = (Int24 *)inBuffer;\r\n      scale = (Float32) ( 1.0 / 8388607.5 );\r\n      for (unsigned int i=0; i<stream_.bufferSize; i++) {\r\n        for (j=0; j<info.channels; j++) {\r\n          out[info.outOffset[j]] = (Float32) (in[info.inOffset[j]].asInt());\r\n          out[info.outOffset[j]] += 0.5;\r\n          out[info.outOffset[j]] *= scale;\r\n        }\r\n        in += info.inJump;\r\n        out += info.outJump;\r\n      }\r\n    }\r\n    else if (info.inFormat == RTAUDIO_SINT32) {\r\n      Int32 *in = (Int32 *)inBuffer;\r\n      scale = (Float32) ( 1.0 / 2147483647.5 );\r\n      for (unsigned int i=0; i<stream_.bufferSize; i++) {\r\n        for (j=0; j<info.channels; j++) {\r\n          out[info.outOffset[j]] = (Float32) in[info.inOffset[j]];\r\n          out[info.outOffset[j]] += 0.5;\r\n          out[info.outOffset[j]] *= scale;\r\n        }\r\n        in += info.inJump;\r\n        out += info.outJump;\r\n      }\r\n    }\r\n    else if (info.inFormat == RTAUDIO_FLOAT32) {\r\n      // Channel compensation and/or (de)interleaving only.\r\n      Float32 *in = (Float32 *)inBuffer;\r\n      for (unsigned int i=0; i<stream_.bufferSize; i++) {\r\n        for (j=0; j<info.channels; j++) {\r\n          out[info.outOffset[j]] = in[info.inOffset[j]];\r\n        }\r\n        in += info.inJump;\r\n        out += info.outJump;\r\n      }\r\n    }\r\n    else if (info.inFormat == RTAUDIO_FLOAT64) {\r\n      Float64 *in = (Float64 *)inBuffer;\r\n      for (unsigned int i=0; i<stream_.bufferSize; i++) {\r\n        for (j=0; j<info.channels; j++) {\r\n          out[info.outOffset[j]] = (Float32) in[info.inOffset[j]];\r\n        }\r\n        in += info.inJump;\r\n        out += info.outJump;\r\n      }\r\n    }\r\n  }\r\n  else if (info.outFormat == RTAUDIO_SINT32) {\r\n    Int32 *out = (Int32 *)outBuffer;\r\n    if (info.inFormat == RTAUDIO_SINT8) {\r\n      signed char *in = (signed char *)inBuffer;\r\n      for (unsigned int i=0; i<stream_.bufferSize; i++) {\r\n        for (j=0; j<info.channels; j++) {\r\n          out[info.outOffset[j]] = (Int32) in[info.inOffset[j]];\r\n          out[info.outOffset[j]] <<= 24;\r\n        }\r\n        in += info.inJump;\r\n        out += info.outJump;\r\n      }\r\n    }\r\n    else if (info.inFormat == RTAUDIO_SINT16) {\r\n      Int16 *in = (Int16 *)inBuffer;\r\n      for (unsigned int i=0; i<stream_.bufferSize; i++) {\r\n        for (j=0; j<info.channels; j++) {\r\n          out[info.outOffset[j]] = (Int32) in[info.inOffset[j]];\r\n          out[info.outOffset[j]] <<= 16;\r\n        }\r\n        in += info.inJump;\r\n        out += info.outJump;\r\n      }\r\n    }\r\n    else if (info.inFormat == RTAUDIO_SINT24) {\r\n      Int24 *in = (Int24 *)inBuffer;\r\n      for (unsigned int i=0; i<stream_.bufferSize; i++) {\r\n        for (j=0; j<info.channels; j++) {\r\n          out[info.outOffset[j]] = (Int32) in[info.inOffset[j]].asInt();\r\n          out[info.outOffset[j]] <<= 8;\r\n        }\r\n        in += info.inJump;\r\n        out += info.outJump;\r\n      }\r\n    }\r\n    else if (info.inFormat == RTAUDIO_SINT32) {\r\n      // Channel compensation and/or (de)interleaving only.\r\n      Int32 *in = (Int32 *)inBuffer;\r\n      for (unsigned int i=0; i<stream_.bufferSize; i++) {\r\n        for (j=0; j<info.channels; j++) {\r\n          out[info.outOffset[j]] = in[info.inOffset[j]];\r\n        }\r\n        in += info.inJump;\r\n        out += info.outJump;\r\n      }\r\n    }\r\n    else if (info.inFormat == RTAUDIO_FLOAT32) {\r\n      Float32 *in = (Float32 *)inBuffer;\r\n      for (unsigned int i=0; i<stream_.bufferSize; i++) {\r\n        for (j=0; j<info.channels; j++) {\r\n          out[info.outOffset[j]] = (Int32) (in[info.inOffset[j]] * 2147483647.5 - 0.5);\r\n        }\r\n        in += info.inJump;\r\n        out += info.outJump;\r\n      }\r\n    }\r\n    else if (info.inFormat == RTAUDIO_FLOAT64) {\r\n      Float64 *in = (Float64 *)inBuffer;\r\n      for (unsigned int i=0; i<stream_.bufferSize; i++) {\r\n        for (j=0; j<info.channels; j++) {\r\n          out[info.outOffset[j]] = (Int32) (in[info.inOffset[j]] * 2147483647.5 - 0.5);\r\n        }\r\n        in += info.inJump;\r\n        out += info.outJump;\r\n      }\r\n    }\r\n  }\r\n  else if (info.outFormat == RTAUDIO_SINT24) {\r\n    Int24 *out = (Int24 *)outBuffer;\r\n    if (info.inFormat == RTAUDIO_SINT8) {\r\n      signed char *in = (signed char *)inBuffer;\r\n      for (unsigned int i=0; i<stream_.bufferSize; i++) {\r\n        for (j=0; j<info.channels; j++) {\r\n          out[info.outOffset[j]] = (Int32) (in[info.inOffset[j]] << 16);\r\n          //out[info.outOffset[j]] <<= 16;\r\n        }\r\n        in += info.inJump;\r\n        out += info.outJump;\r\n      }\r\n    }\r\n    else if (info.inFormat == RTAUDIO_SINT16) {\r\n      Int16 *in = (Int16 *)inBuffer;\r\n      for (unsigned int i=0; i<stream_.bufferSize; i++) {\r\n        for (j=0; j<info.channels; j++) {\r\n          out[info.outOffset[j]] = (Int32) (in[info.inOffset[j]] << 8);\r\n          //out[info.outOffset[j]] <<= 8;\r\n        }\r\n        in += info.inJump;\r\n        out += info.outJump;\r\n      }\r\n    }\r\n    else if (info.inFormat == RTAUDIO_SINT24) {\r\n      // Channel compensation and/or (de)interleaving only.\r\n      Int24 *in = (Int24 *)inBuffer;\r\n      for (unsigned int i=0; i<stream_.bufferSize; i++) {\r\n        for (j=0; j<info.channels; j++) {\r\n          out[info.outOffset[j]] = in[info.inOffset[j]];\r\n        }\r\n        in += info.inJump;\r\n        out += info.outJump;\r\n      }\r\n    }\r\n    else if (info.inFormat == RTAUDIO_SINT32) {\r\n      Int32 *in = (Int32 *)inBuffer;\r\n      for (unsigned int i=0; i<stream_.bufferSize; i++) {\r\n        for (j=0; j<info.channels; j++) {\r\n          out[info.outOffset[j]] = (Int32) (in[info.inOffset[j]] >> 8);\r\n          //out[info.outOffset[j]] >>= 8;\r\n        }\r\n        in += info.inJump;\r\n        out += info.outJump;\r\n      }\r\n    }\r\n    else if (info.inFormat == RTAUDIO_FLOAT32) {\r\n      Float32 *in = (Float32 *)inBuffer;\r\n      for (unsigned int i=0; i<stream_.bufferSize; i++) {\r\n        for (j=0; j<info.channels; j++) {\r\n          out[info.outOffset[j]] = (Int32) (in[info.inOffset[j]] * 8388607.5 - 0.5);\r\n        }\r\n        in += info.inJump;\r\n        out += info.outJump;\r\n      }\r\n    }\r\n    else if (info.inFormat == RTAUDIO_FLOAT64) {\r\n      Float64 *in = (Float64 *)inBuffer;\r\n      for (unsigned int i=0; i<stream_.bufferSize; i++) {\r\n        for (j=0; j<info.channels; j++) {\r\n          out[info.outOffset[j]] = (Int32) (in[info.inOffset[j]] * 8388607.5 - 0.5);\r\n        }\r\n        in += info.inJump;\r\n        out += info.outJump;\r\n      }\r\n    }\r\n  }\r\n  else if (info.outFormat == RTAUDIO_SINT16) {\r\n    Int16 *out = (Int16 *)outBuffer;\r\n    if (info.inFormat == RTAUDIO_SINT8) {\r\n      signed char *in = (signed char *)inBuffer;\r\n      for (unsigned int i=0; i<stream_.bufferSize; i++) {\r\n        for (j=0; j<info.channels; j++) {\r\n          out[info.outOffset[j]] = (Int16) in[info.inOffset[j]];\r\n          out[info.outOffset[j]] <<= 8;\r\n        }\r\n        in += info.inJump;\r\n        out += info.outJump;\r\n      }\r\n    }\r\n    else if (info.inFormat == RTAUDIO_SINT16) {\r\n      // Channel compensation and/or (de)interleaving only.\r\n      Int16 *in = (Int16 *)inBuffer;\r\n      for (unsigned int i=0; i<stream_.bufferSize; i++) {\r\n        for (j=0; j<info.channels; j++) {\r\n          out[info.outOffset[j]] = in[info.inOffset[j]];\r\n        }\r\n        in += info.inJump;\r\n        out += info.outJump;\r\n      }\r\n    }\r\n    else if (info.inFormat == RTAUDIO_SINT24) {\r\n      Int24 *in = (Int24 *)inBuffer;\r\n      for (unsigned int i=0; i<stream_.bufferSize; i++) {\r\n        for (j=0; j<info.channels; j++) {\r\n          out[info.outOffset[j]] = (Int16) (in[info.inOffset[j]].asInt() >> 8);\r\n        }\r\n        in += info.inJump;\r\n        out += info.outJump;\r\n      }\r\n    }\r\n    else if (info.inFormat == RTAUDIO_SINT32) {\r\n      Int32 *in = (Int32 *)inBuffer;\r\n      for (unsigned int i=0; i<stream_.bufferSize; i++) {\r\n        for (j=0; j<info.channels; j++) {\r\n          out[info.outOffset[j]] = (Int16) ((in[info.inOffset[j]] >> 16) & 0x0000ffff);\r\n        }\r\n        in += info.inJump;\r\n        out += info.outJump;\r\n      }\r\n    }\r\n    else if (info.inFormat == RTAUDIO_FLOAT32) {\r\n      Float32 *in = (Float32 *)inBuffer;\r\n      for (unsigned int i=0; i<stream_.bufferSize; i++) {\r\n        for (j=0; j<info.channels; j++) {\r\n          out[info.outOffset[j]] = (Int16) (in[info.inOffset[j]] * 32767.5 - 0.5);\r\n        }\r\n        in += info.inJump;\r\n        out += info.outJump;\r\n      }\r\n    }\r\n    else if (info.inFormat == RTAUDIO_FLOAT64) {\r\n      Float64 *in = (Float64 *)inBuffer;\r\n      for (unsigned int i=0; i<stream_.bufferSize; i++) {\r\n        for (j=0; j<info.channels; j++) {\r\n          out[info.outOffset[j]] = (Int16) (in[info.inOffset[j]] * 32767.5 - 0.5);\r\n        }\r\n        in += info.inJump;\r\n        out += info.outJump;\r\n      }\r\n    }\r\n  }\r\n  else if (info.outFormat == RTAUDIO_SINT8) {\r\n    signed char *out = (signed char *)outBuffer;\r\n    if (info.inFormat == RTAUDIO_SINT8) {\r\n      // Channel compensation and/or (de)interleaving only.\r\n      signed char *in = (signed char *)inBuffer;\r\n      for (unsigned int i=0; i<stream_.bufferSize; i++) {\r\n        for (j=0; j<info.channels; j++) {\r\n          out[info.outOffset[j]] = in[info.inOffset[j]];\r\n        }\r\n        in += info.inJump;\r\n        out += info.outJump;\r\n      }\r\n    }\r\n    if (info.inFormat == RTAUDIO_SINT16) {\r\n      Int16 *in = (Int16 *)inBuffer;\r\n      for (unsigned int i=0; i<stream_.bufferSize; i++) {\r\n        for (j=0; j<info.channels; j++) {\r\n          out[info.outOffset[j]] = (signed char) ((in[info.inOffset[j]] >> 8) & 0x00ff);\r\n        }\r\n        in += info.inJump;\r\n        out += info.outJump;\r\n      }\r\n    }\r\n    else if (info.inFormat == RTAUDIO_SINT24) {\r\n      Int24 *in = (Int24 *)inBuffer;\r\n      for (unsigned int i=0; i<stream_.bufferSize; i++) {\r\n        for (j=0; j<info.channels; j++) {\r\n          out[info.outOffset[j]] = (signed char) (in[info.inOffset[j]].asInt() >> 16);\r\n        }\r\n        in += info.inJump;\r\n        out += info.outJump;\r\n      }\r\n    }\r\n    else if (info.inFormat == RTAUDIO_SINT32) {\r\n      Int32 *in = (Int32 *)inBuffer;\r\n      for (unsigned int i=0; i<stream_.bufferSize; i++) {\r\n        for (j=0; j<info.channels; j++) {\r\n          out[info.outOffset[j]] = (signed char) ((in[info.inOffset[j]] >> 24) & 0x000000ff);\r\n        }\r\n        in += info.inJump;\r\n        out += info.outJump;\r\n      }\r\n    }\r\n    else if (info.inFormat == RTAUDIO_FLOAT32) {\r\n      Float32 *in = (Float32 *)inBuffer;\r\n      for (unsigned int i=0; i<stream_.bufferSize; i++) {\r\n        for (j=0; j<info.channels; j++) {\r\n          out[info.outOffset[j]] = (signed char) (in[info.inOffset[j]] * 127.5 - 0.5);\r\n        }\r\n        in += info.inJump;\r\n        out += info.outJump;\r\n      }\r\n    }\r\n    else if (info.inFormat == RTAUDIO_FLOAT64) {\r\n      Float64 *in = (Float64 *)inBuffer;\r\n      for (unsigned int i=0; i<stream_.bufferSize; i++) {\r\n        for (j=0; j<info.channels; j++) {\r\n          out[info.outOffset[j]] = (signed char) (in[info.inOffset[j]] * 127.5 - 0.5);\r\n        }\r\n        in += info.inJump;\r\n        out += info.outJump;\r\n      }\r\n    }\r\n  }\r\n}\r\n\r\n//static inline uint16_t bswap_16(uint16_t x) { return (x>>8) | (x<<8); }\r\n//static inline uint32_t bswap_32(uint32_t x) { return (bswap_16(x&0xffff)<<16) | (bswap_16(x>>16)); }\r\n//static inline uint64_t bswap_64(uint64_t x) { return (((unsigned long long)bswap_32(x&0xffffffffull))<<32) | (bswap_32(x>>32)); }\r\n\r\nvoid RtApi :: byteSwapBuffer( char *buffer, unsigned int samples, RtAudioFormat format )\r\n{\r\n  register char val;\r\n  register char *ptr;\r\n\r\n  ptr = buffer;\r\n  if ( format == RTAUDIO_SINT16 ) {\r\n    for ( unsigned int i=0; i<samples; i++ ) {\r\n      // Swap 1st and 2nd bytes.\r\n      val = *(ptr);\r\n      *(ptr) = *(ptr+1);\r\n      *(ptr+1) = val;\r\n\r\n      // Increment 2 bytes.\r\n      ptr += 2;\r\n    }\r\n  }\r\n  else if ( format == RTAUDIO_SINT32 ||\r\n            format == RTAUDIO_FLOAT32 ) {\r\n    for ( unsigned int i=0; i<samples; i++ ) {\r\n      // Swap 1st and 4th bytes.\r\n      val = *(ptr);\r\n      *(ptr) = *(ptr+3);\r\n      *(ptr+3) = val;\r\n\r\n      // Swap 2nd and 3rd bytes.\r\n      ptr += 1;\r\n      val = *(ptr);\r\n      *(ptr) = *(ptr+1);\r\n      *(ptr+1) = val;\r\n\r\n      // Increment 3 more bytes.\r\n      ptr += 3;\r\n    }\r\n  }\r\n  else if ( format == RTAUDIO_SINT24 ) {\r\n    for ( unsigned int i=0; i<samples; i++ ) {\r\n      // Swap 1st and 3rd bytes.\r\n      val = *(ptr);\r\n      *(ptr) = *(ptr+2);\r\n      *(ptr+2) = val;\r\n\r\n      // Increment 2 more bytes.\r\n      ptr += 2;\r\n    }\r\n  }\r\n  else if ( format == RTAUDIO_FLOAT64 ) {\r\n    for ( unsigned int i=0; i<samples; i++ ) {\r\n      // Swap 1st and 8th bytes\r\n      val = *(ptr);\r\n      *(ptr) = *(ptr+7);\r\n      *(ptr+7) = val;\r\n\r\n      // Swap 2nd and 7th bytes\r\n      ptr += 1;\r\n      val = *(ptr);\r\n      *(ptr) = *(ptr+5);\r\n      *(ptr+5) = val;\r\n\r\n      // Swap 3rd and 6th bytes\r\n      ptr += 1;\r\n      val = *(ptr);\r\n      *(ptr) = *(ptr+3);\r\n      *(ptr+3) = val;\r\n\r\n      // Swap 4th and 5th bytes\r\n      ptr += 1;\r\n      val = *(ptr);\r\n      *(ptr) = *(ptr+1);\r\n      *(ptr+1) = val;\r\n\r\n      // Increment 5 more bytes.\r\n      ptr += 5;\r\n    }\r\n  }\r\n}\r\n\r\n  // Indentation settings for Vim and Emacs\r\n  //\r\n  // Local Variables:\r\n  // c-basic-offset: 2\r\n  // indent-tabs-mode: nil\r\n  // End:\r\n  //\r\n  // vim: et sts=2 sw=2\r\n\r\n"
  },
  {
    "path": "rtaudio/RtAudio.h",
    "content": "/************************************************************************/\n/*! \\class RtAudio\n    \\brief Realtime audio i/o C++ classes.\n\n    RtAudio provides a common API (Application Programming Interface)\n    for realtime audio input/output across GNU/Linux (native ALSA, Jack,\n    and OSS), Macintosh OS X (CoreAudio and Jack), and Windows\n    (DirectSound and ASIO) operating systems.\n\n    RtAudio WWW site: http://www.music.mcgill.ca/~gary/rtaudio/\n\n    RtAudio: realtime audio i/o C++ classes\n    Copyright (c) 2001-2013 Gary P. Scavone\n\n    Permission is hereby granted, free of charge, to any person\n    obtaining a copy of this software and associated documentation files\n    (the \"Software\"), to deal in the Software without restriction,\n    including without limitation the rights to use, copy, modify, merge,\n    publish, distribute, sublicense, and/or sell copies of the Software,\n    and to permit persons to whom the Software is furnished to do so,\n    subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be\n    included in all copies or substantial portions of the Software.\n\n    Any person wishing to distribute modifications to the Software is\n    asked to send the modifications to the original developer so that\n    they can be incorporated into the canonical version.  This is,\n    however, not a binding provision of this license.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR\n    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF\n    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\n    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n*/\n/************************************************************************/\n\n/*!\n  \\file RtAudio.h\n */\n\n#ifndef __RTAUDIO_H\n#define __RTAUDIO_H\n\n#include <string>\n#include <vector>\n#include \"RtError.h\"\n\n// RtAudio version\nstatic const std::string RT_AUDIO_VERSION( \"4.0.12\" );\n\n/*! \\typedef typedef unsigned long RtAudioFormat;\n    \\brief RtAudio data format type.\n\n    Support for signed integers and floats.  Audio data fed to/from an\n    RtAudio stream is assumed to ALWAYS be in host byte order.  The\n    internal routines will automatically take care of any necessary\n    byte-swapping between the host format and the soundcard.  Thus,\n    endian-ness is not a concern in the following format definitions.\n\n    - \\e RTAUDIO_SINT8:   8-bit signed integer.\n    - \\e RTAUDIO_SINT16:  16-bit signed integer.\n    - \\e RTAUDIO_SINT24:  24-bit signed integer.\n    - \\e RTAUDIO_SINT32:  32-bit signed integer.\n    - \\e RTAUDIO_FLOAT32: Normalized between plus/minus 1.0.\n    - \\e RTAUDIO_FLOAT64: Normalized between plus/minus 1.0.\n*/\ntypedef unsigned long RtAudioFormat;\nstatic const RtAudioFormat RTAUDIO_SINT8 = 0x1;    // 8-bit signed integer.\nstatic const RtAudioFormat RTAUDIO_SINT16 = 0x2;   // 16-bit signed integer.\nstatic const RtAudioFormat RTAUDIO_SINT24 = 0x4;   // 24-bit signed integer.\nstatic const RtAudioFormat RTAUDIO_SINT32 = 0x8;   // 32-bit signed integer.\nstatic const RtAudioFormat RTAUDIO_FLOAT32 = 0x10; // Normalized between plus/minus 1.0.\nstatic const RtAudioFormat RTAUDIO_FLOAT64 = 0x20; // Normalized between plus/minus 1.0.\n\n/*! \\typedef typedef unsigned long RtAudioStreamFlags;\n    \\brief RtAudio stream option flags.\n\n    The following flags can be OR'ed together to allow a client to\n    make changes to the default stream behavior:\n\n    - \\e RTAUDIO_NONINTERLEAVED:   Use non-interleaved buffers (default = interleaved).\n    - \\e RTAUDIO_MINIMIZE_LATENCY: Attempt to set stream parameters for lowest possible latency.\n    - \\e RTAUDIO_HOG_DEVICE:       Attempt grab device for exclusive use.\n    - \\e RTAUDIO_ALSA_USE_DEFAULT: Use the \"default\" PCM device (ALSA only).\n\n    By default, RtAudio streams pass and receive audio data from the\n    client in an interleaved format.  By passing the\n    RTAUDIO_NONINTERLEAVED flag to the openStream() function, audio\n    data will instead be presented in non-interleaved buffers.  In\n    this case, each buffer argument in the RtAudioCallback function\n    will point to a single array of data, with \\c nFrames samples for\n    each channel concatenated back-to-back.  For example, the first\n    sample of data for the second channel would be located at index \\c\n    nFrames (assuming the \\c buffer pointer was recast to the correct\n    data type for the stream).\n\n    Certain audio APIs offer a number of parameters that influence the\n    I/O latency of a stream.  By default, RtAudio will attempt to set\n    these parameters internally for robust (glitch-free) performance\n    (though some APIs, like Windows Direct Sound, make this difficult).\n    By passing the RTAUDIO_MINIMIZE_LATENCY flag to the openStream()\n    function, internal stream settings will be influenced in an attempt\n    to minimize stream latency, though possibly at the expense of stream\n    performance.\n\n    If the RTAUDIO_HOG_DEVICE flag is set, RtAudio will attempt to\n    open the input and/or output stream device(s) for exclusive use.\n    Note that this is not possible with all supported audio APIs.\n\n    If the RTAUDIO_SCHEDULE_REALTIME flag is set, RtAudio will attempt \n    to select realtime scheduling (round-robin) for the callback thread.\n\n    If the RTAUDIO_ALSA_USE_DEFAULT flag is set, RtAudio will attempt to\n    open the \"default\" PCM device when using the ALSA API. Note that this\n    will override any specified input or output device id.\n*/\ntypedef unsigned int RtAudioStreamFlags;\nstatic const RtAudioStreamFlags RTAUDIO_NONINTERLEAVED = 0x1;    // Use non-interleaved buffers (default = interleaved).\nstatic const RtAudioStreamFlags RTAUDIO_MINIMIZE_LATENCY = 0x2;  // Attempt to set stream parameters for lowest possible latency.\nstatic const RtAudioStreamFlags RTAUDIO_HOG_DEVICE = 0x4;        // Attempt grab device and prevent use by others.\nstatic const RtAudioStreamFlags RTAUDIO_SCHEDULE_REALTIME = 0x8; // Try to select realtime scheduling for callback thread.\nstatic const RtAudioStreamFlags RTAUDIO_ALSA_USE_DEFAULT = 0x10; // Use the \"default\" PCM device (ALSA only).\n\n/*! \\typedef typedef unsigned long RtAudioStreamStatus;\n    \\brief RtAudio stream status (over- or underflow) flags.\n\n    Notification of a stream over- or underflow is indicated by a\n    non-zero stream \\c status argument in the RtAudioCallback function.\n    The stream status can be one of the following two options,\n    depending on whether the stream is open for output and/or input:\n\n    - \\e RTAUDIO_INPUT_OVERFLOW:   Input data was discarded because of an overflow condition at the driver.\n    - \\e RTAUDIO_OUTPUT_UNDERFLOW: The output buffer ran low, likely producing a break in the output sound.\n*/\ntypedef unsigned int RtAudioStreamStatus;\nstatic const RtAudioStreamStatus RTAUDIO_INPUT_OVERFLOW = 0x1;    // Input data was discarded because of an overflow condition at the driver.\nstatic const RtAudioStreamStatus RTAUDIO_OUTPUT_UNDERFLOW = 0x2;  // The output buffer ran low, likely causing a gap in the output sound.\n\n//! RtAudio callback function prototype.\n/*!\n   All RtAudio clients must create a function of type RtAudioCallback\n   to read and/or write data from/to the audio stream.  When the\n   underlying audio system is ready for new input or output data, this\n   function will be invoked.\n\n   \\param outputBuffer For output (or duplex) streams, the client\n          should write \\c nFrames of audio sample frames into this\n          buffer.  This argument should be recast to the datatype\n          specified when the stream was opened.  For input-only\n          streams, this argument will be NULL.\n\n   \\param inputBuffer For input (or duplex) streams, this buffer will\n          hold \\c nFrames of input audio sample frames.  This\n          argument should be recast to the datatype specified when the\n          stream was opened.  For output-only streams, this argument\n          will be NULL.\n\n   \\param nFrames The number of sample frames of input or output\n          data in the buffers.  The actual buffer size in bytes is\n          dependent on the data type and number of channels in use.\n\n   \\param streamTime The number of seconds that have elapsed since the\n          stream was started.\n\n   \\param status If non-zero, this argument indicates a data overflow\n          or underflow condition for the stream.  The particular\n          condition can be determined by comparison with the\n          RtAudioStreamStatus flags.\n\n   \\param userData A pointer to optional data provided by the client\n          when opening the stream (default = NULL).\n\n   To continue normal stream operation, the RtAudioCallback function\n   should return a value of zero.  To stop the stream and drain the\n   output buffer, the function should return a value of one.  To abort\n   the stream immediately, the client should return a value of two.\n */\ntypedef int (*RtAudioCallback)( void *outputBuffer, void *inputBuffer,\n                                unsigned int nFrames,\n                                double streamTime,\n                                RtAudioStreamStatus status,\n                                void *userData );\n\n//! RtAudio error callback function prototype.\n/*!\n    \\param type Type of error.\n    \\param errorText Error description.\n */\ntypedef void (*RtAudioErrorCallback)( RtError::Type type, const std::string &errorText );\n\n// **************************************************************** //\n//\n// RtAudio class declaration.\n//\n// RtAudio is a \"controller\" used to select an available audio i/o\n// interface.  It presents a common API for the user to call but all\n// functionality is implemented by the class RtApi and its\n// subclasses.  RtAudio creates an instance of an RtApi subclass\n// based on the user's API choice.  If no choice is made, RtAudio\n// attempts to make a \"logical\" API selection.\n//\n// **************************************************************** //\n\nclass RtApi;\n\nclass RtAudio\n{\n public:\n\n  //! Audio API specifier arguments.\n  enum Api {\n    UNSPECIFIED,    /*!< Search for a working compiled API. */\n    LINUX_ALSA,     /*!< The Advanced GNU/Linux Sound Architecture API. */\n    LINUX_PULSE,    /*!< The GNU/Linux PulseAudio API. */\n    LINUX_OSS,      /*!< The GNU/Linux Open Sound System API. */\n    UNIX_JACK,      /*!< The Jack Low-Latency Audio Server API. */\n    MACOSX_CORE,    /*!< Macintosh OS-X Core Audio API. */\n    WINDOWS_ASIO,   /*!< The Steinberg Audio Stream I/O API. */\n    WINDOWS_DS,     /*!< The Microsoft Direct Sound API. */\n    RTAUDIO_DUMMY   /*!< A compilable but non-functional API. */\n  };\n\n  //! The public device information structure for returning queried values.\n  struct DeviceInfo {\n    bool probed;                  /*!< true if the device capabilities were successfully probed. */\n    std::string name;             /*!< Character string device identifier. */\n    unsigned int outputChannels;  /*!< Maximum output channels supported by device. */\n    unsigned int inputChannels;   /*!< Maximum input channels supported by device. */\n    unsigned int duplexChannels;  /*!< Maximum simultaneous input/output channels supported by device. */\n    bool isDefaultOutput;         /*!< true if this is the default output device. */\n    bool isDefaultInput;          /*!< true if this is the default input device. */\n    std::vector<unsigned int> sampleRates; /*!< Supported sample rates (queried from list of standard rates). */\n    RtAudioFormat nativeFormats;  /*!< Bit mask of supported data formats. */\n\n    // Default constructor.\n    DeviceInfo()\n      :probed(false), outputChannels(0), inputChannels(0), duplexChannels(0),\n       isDefaultOutput(false), isDefaultInput(false), nativeFormats(0) {}\n  };\n\n  //! The structure for specifying input or ouput stream parameters.\n  struct StreamParameters {\n    unsigned int deviceId;     /*!< Device index (0 to getDeviceCount() - 1). */\n    unsigned int nChannels;    /*!< Number of channels. */\n    unsigned int firstChannel; /*!< First channel index on device (default = 0). */\n\n    // Default constructor.\n    StreamParameters()\n      : deviceId(0), nChannels(0), firstChannel(0) {}\n  };\n\n  //! The structure for specifying stream options.\n  /*!\n    The following flags can be OR'ed together to allow a client to\n    make changes to the default stream behavior:\n\n    - \\e RTAUDIO_NONINTERLEAVED:    Use non-interleaved buffers (default = interleaved).\n    - \\e RTAUDIO_MINIMIZE_LATENCY:  Attempt to set stream parameters for lowest possible latency.\n    - \\e RTAUDIO_HOG_DEVICE:        Attempt grab device for exclusive use.\n    - \\e RTAUDIO_SCHEDULE_REALTIME: Attempt to select realtime scheduling for callback thread.\n    - \\e RTAUDIO_ALSA_USE_DEFAULT:  Use the \"default\" PCM device (ALSA only).\n\n    By default, RtAudio streams pass and receive audio data from the\n    client in an interleaved format.  By passing the\n    RTAUDIO_NONINTERLEAVED flag to the openStream() function, audio\n    data will instead be presented in non-interleaved buffers.  In\n    this case, each buffer argument in the RtAudioCallback function\n    will point to a single array of data, with \\c nFrames samples for\n    each channel concatenated back-to-back.  For example, the first\n    sample of data for the second channel would be located at index \\c\n    nFrames (assuming the \\c buffer pointer was recast to the correct\n    data type for the stream).\n\n    Certain audio APIs offer a number of parameters that influence the\n    I/O latency of a stream.  By default, RtAudio will attempt to set\n    these parameters internally for robust (glitch-free) performance\n    (though some APIs, like Windows Direct Sound, make this difficult).\n    By passing the RTAUDIO_MINIMIZE_LATENCY flag to the openStream()\n    function, internal stream settings will be influenced in an attempt\n    to minimize stream latency, though possibly at the expense of stream\n    performance.\n\n    If the RTAUDIO_HOG_DEVICE flag is set, RtAudio will attempt to\n    open the input and/or output stream device(s) for exclusive use.\n    Note that this is not possible with all supported audio APIs.\n\n    If the RTAUDIO_SCHEDULE_REALTIME flag is set, RtAudio will attempt \n    to select realtime scheduling (round-robin) for the callback thread.\n    The \\c priority parameter will only be used if the RTAUDIO_SCHEDULE_REALTIME\n    flag is set. It defines the thread's realtime priority.\n\n    If the RTAUDIO_ALSA_USE_DEFAULT flag is set, RtAudio will attempt to\n    open the \"default\" PCM device when using the ALSA API. Note that this\n    will override any specified input or output device id.\n\n    The \\c numberOfBuffers parameter can be used to control stream\n    latency in the Windows DirectSound, GNU/Linux OSS, and GNU/Linux Alsa APIs\n    only.  A value of two is usually the smallest allowed.  Larger\n    numbers can potentially result in more robust stream performance,\n    though likely at the cost of stream latency.  The value set by the\n    user is replaced during execution of the RtAudio::openStream()\n    function by the value actually used by the system.\n\n    The \\c streamName parameter can be used to set the client name\n    when using the Jack API.  By default, the client name is set to\n    RtApiJack.  However, if you wish to create multiple instances of\n    RtAudio with Jack, each instance must have a unique client name.\n  */\n  struct StreamOptions {\n    RtAudioStreamFlags flags;      /*!< A bit-mask of stream flags (RTAUDIO_NONINTERLEAVED, RTAUDIO_MINIMIZE_LATENCY, RTAUDIO_HOG_DEVICE, RTAUDIO_ALSA_USE_DEFAULT). */\n    unsigned int numberOfBuffers;  /*!< Number of stream buffers. */\n    std::string streamName;        /*!< A stream name (currently used only in Jack). */\n    int priority;                  /*!< Scheduling priority of callback thread (only used with flag RTAUDIO_SCHEDULE_REALTIME). */\n\n    // Default constructor.\n    StreamOptions()\n    : flags(0), numberOfBuffers(0), priority(0) {}\n  };\n\n  //! A static function to determine the current RtAudio version.\n  static std::string getVersion( void ) { return RT_AUDIO_VERSION; }\n\n  //! A static function to determine the available compiled audio APIs.\n  /*!\n    The values returned in the std::vector can be compared against\n    the enumerated list values.  Note that there can be more than one\n    API compiled for certain operating systems.\n  */\n  static void getCompiledApi( std::vector<RtAudio::Api> &apis ) throw();\n\n  //! The class constructor.\n  /*!\n    The constructor performs minor initialization tasks.  No exceptions\n    can be thrown.\n\n    If no API argument is specified and multiple API support has been\n    compiled, the default order of use is JACK, ALSA, OSS (GNU/Linux\n    systems) and ASIO, DS (Windows systems).\n  */\n  RtAudio( RtAudio::Api api=UNSPECIFIED ) throw();\n\n  //! The destructor.\n  /*!\n    If a stream is running or open, it will be stopped and closed\n    automatically.\n  */\n  ~RtAudio() throw();\n\n  //! Returns the audio API specifier for the current instance of RtAudio.\n  RtAudio::Api getCurrentApi( void ) throw();\n\n  //! A public function that queries for the number of audio devices available.\n  /*!\n    This function performs a system query of available devices each time it\n    is called, thus supporting devices connected \\e after instantiation. If\n    a system error occurs during processing, a warning will be issued. \n  */\n  unsigned int getDeviceCount( void ) throw();\n\n  //! Return an RtAudio::DeviceInfo structure for a specified device number.\n  /*!\n\n    Any device integer between 0 and getDeviceCount() - 1 is valid.\n    If an invalid argument is provided, an RtError (type = INVALID_USE)\n    will be thrown.  If a device is busy or otherwise unavailable, the\n    structure member \"probed\" will have a value of \"false\" and all\n    other members are undefined.  If the specified device is the\n    current default input or output device, the corresponding\n    \"isDefault\" member will have a value of \"true\".\n  */\n  RtAudio::DeviceInfo getDeviceInfo( unsigned int device );\n\n  //! A function that returns the index of the default output device.\n  /*!\n    If the underlying audio API does not provide a \"default\n    device\", or if no devices are available, the return value will be\n    0.  Note that this is a valid device identifier and it is the\n    client's responsibility to verify that a device is available\n    before attempting to open a stream.\n  */\n  unsigned int getDefaultOutputDevice( void ) throw();\n\n  //! A function that returns the index of the default input device.\n  /*!\n    If the underlying audio API does not provide a \"default\n    device\", or if no devices are available, the return value will be\n    0.  Note that this is a valid device identifier and it is the\n    client's responsibility to verify that a device is available\n    before attempting to open a stream.\n  */\n  unsigned int getDefaultInputDevice( void ) throw();\n\n  //! A public function for opening a stream with the specified parameters.\n  /*!\n    An RtError (type = SYSTEM_ERROR) is thrown if a stream cannot be\n    opened with the specified parameters or an error occurs during\n    processing.  An RtError (type = INVALID_USE) is thrown if any\n    invalid device ID or channel number parameters are specified.\n\n    \\param outputParameters Specifies output stream parameters to use\n           when opening a stream, including a device ID, number of channels,\n           and starting channel number.  For input-only streams, this\n           argument should be NULL.  The device ID is an index value between\n           0 and getDeviceCount() - 1.\n    \\param inputParameters Specifies input stream parameters to use\n           when opening a stream, including a device ID, number of channels,\n           and starting channel number.  For output-only streams, this\n           argument should be NULL.  The device ID is an index value between\n           0 and getDeviceCount() - 1.\n    \\param format An RtAudioFormat specifying the desired sample data format.\n    \\param sampleRate The desired sample rate (sample frames per second).\n    \\param *bufferFrames A pointer to a value indicating the desired\n           internal buffer size in sample frames.  The actual value\n           used by the device is returned via the same pointer.  A\n           value of zero can be specified, in which case the lowest\n           allowable value is determined.\n    \\param callback A client-defined function that will be invoked\n           when input data is available and/or output data is needed.\n    \\param userData An optional pointer to data that can be accessed\n           from within the callback function.\n    \\param options An optional pointer to a structure containing various\n           global stream options, including a list of OR'ed RtAudioStreamFlags\n           and a suggested number of stream buffers that can be used to \n           control stream latency.  More buffers typically result in more\n           robust performance, though at a cost of greater latency.  If a\n           value of zero is specified, a system-specific median value is\n           chosen.  If the RTAUDIO_MINIMIZE_LATENCY flag bit is set, the\n           lowest allowable value is used.  The actual value used is\n           returned via the structure argument.  The parameter is API dependent.\n    \\param errorCallback A client-defined function that will be invoked\n           when an error has occured.\n  */\n  void openStream( RtAudio::StreamParameters *outputParameters,\n                   RtAudio::StreamParameters *inputParameters,\n                   RtAudioFormat format, unsigned int sampleRate,\n                   unsigned int *bufferFrames, RtAudioCallback callback,\n                   void *userData = NULL, RtAudio::StreamOptions *options = NULL, RtAudioErrorCallback errorCallback = NULL );\n\n  //! A function that closes a stream and frees any associated stream memory.\n  /*!\n    If a stream is not open, this function issues a warning and\n    returns (no exception is thrown).\n  */\n  void closeStream( void ) throw();\n\n  //! A function that starts a stream.\n  /*!\n    An RtError (type = SYSTEM_ERROR) is thrown if an error occurs\n    during processing.  An RtError (type = INVALID_USE) is thrown if a\n    stream is not open.  A warning is issued if the stream is already\n    running.\n  */\n  void startStream( void );\n\n  //! Stop a stream, allowing any samples remaining in the output queue to be played.\n  /*!\n    An RtError (type = SYSTEM_ERROR) is thrown if an error occurs\n    during processing.  An RtError (type = INVALID_USE) is thrown if a\n    stream is not open.  A warning is issued if the stream is already\n    stopped.\n  */\n  void stopStream( void );\n\n  //! Stop a stream, discarding any samples remaining in the input/output queue.\n  /*!\n    An RtError (type = SYSTEM_ERROR) is thrown if an error occurs\n    during processing.  An RtError (type = INVALID_USE) is thrown if a\n    stream is not open.  A warning is issued if the stream is already\n    stopped.\n  */\n  void abortStream( void );\n\n  //! Returns true if a stream is open and false if not.\n  bool isStreamOpen( void ) const throw();\n\n  //! Returns true if the stream is running and false if it is stopped or not open.\n  bool isStreamRunning( void ) const throw();\n\n  //! Returns the number of elapsed seconds since the stream was started.\n  /*!\n    If a stream is not open, an RtError (type = INVALID_USE) will be thrown.\n  */\n  double getStreamTime( void );\n\n  //! Returns the internal stream latency in sample frames.\n  /*!\n    The stream latency refers to delay in audio input and/or output\n    caused by internal buffering by the audio system and/or hardware.\n    For duplex streams, the returned value will represent the sum of\n    the input and output latencies.  If a stream is not open, an\n    RtError (type = INVALID_USE) will be thrown.  If the API does not\n    report latency, the return value will be zero.\n  */\n  long getStreamLatency( void );\n\n //! Returns actual sample rate in use by the stream.\n /*!\n   On some systems, the sample rate used may be slightly different\n   than that specified in the stream parameters.  If a stream is not\n   open, an RtError (type = INVALID_USE) will be thrown.\n */\n  unsigned int getStreamSampleRate( void );\n\n  //! Specify whether warning messages should be printed to stderr.\n  void showWarnings( bool value = true ) throw();\n\n protected:\n\n  void openRtApi( RtAudio::Api api );\n  RtApi *rtapi_;\n};\n\n// Operating system dependent thread functionality.\n#if defined(__WINDOWS_DS__) || defined(__WINDOWS_ASIO__)\n  #include <windows.h>\n  #include <process.h>\n\n  typedef unsigned long ThreadHandle;\n  typedef CRITICAL_SECTION StreamMutex;\n\n#elif defined(__LINUX_ALSA__) || defined(__LINUX_PULSE__) || defined(__UNIX_JACK__) || defined(__LINUX_OSS__) || defined(__MACOSX_CORE__)\n  // Using pthread library for various flavors of unix.\n  #include <pthread.h>\n\n  typedef pthread_t ThreadHandle;\n  typedef pthread_mutex_t StreamMutex;\n\n#else // Setup for \"dummy\" behavior\n\n  #define __RTAUDIO_DUMMY__\n  typedef int ThreadHandle;\n  typedef int StreamMutex;\n\n#endif\n\n// This global structure type is used to pass callback information\n// between the private RtAudio stream structure and global callback\n// handling functions.\nstruct CallbackInfo {\n  void *object;    // Used as a \"this\" pointer.\n  ThreadHandle thread;\n  void *callback;\n  void *userData;\n  void *errorCallback;\n  void *apiInfo;   // void pointer for API specific callback information\n  bool isRunning;\n  bool doRealtime;\n  int priority;\n\n  // Default constructor.\n  CallbackInfo()\n  :object(0), callback(0), userData(0), errorCallback(0), apiInfo(0), isRunning(false), doRealtime(false) {}\n};\n\n// **************************************************************** //\n//\n// RtApi class declaration.\n//\n// Subclasses of RtApi contain all API- and OS-specific code necessary\n// to fully implement the RtAudio API.\n//\n// Note that RtApi is an abstract base class and cannot be\n// explicitly instantiated.  The class RtAudio will create an\n// instance of an RtApi subclass (RtApiOss, RtApiAlsa,\n// RtApiJack, RtApiCore, RtApiDs, or RtApiAsio).\n//\n// **************************************************************** //\n\n#pragma pack(push, 1)\nclass S24 {\n\n protected:\n  unsigned char c3[3];\n\n public:\n  S24() {}\n\n  S24& operator = ( const int& i ) {\n    c3[0] = (i & 0x000000ff);\n    c3[1] = (i & 0x0000ff00) >> 8;\n    c3[2] = (i & 0x00ff0000) >> 16;\n    return *this;\n  }\n\n  S24( const S24& v ) { *this = v; }\n  S24( const double& d ) { *this = (int) d; }\n  S24( const float& f ) { *this = (int) f; }\n  S24( const signed short& s ) { *this = (int) s; }\n  S24( const char& c ) { *this = (int) c; }\n\n  int asInt() {\n    int i = c3[0] | (c3[1] << 8) | (c3[2] << 16);\n    if (i & 0x800000) i |= ~0xffffff;\n    return i;\n  }\n};\n#pragma pack(pop)\n\n#if defined( HAVE_GETTIMEOFDAY )\n  #include <sys/time.h>\n#endif\n\n#include <sstream>\n\nclass RtApi\n{\npublic:\n\n  RtApi();\n  virtual ~RtApi();\n  virtual RtAudio::Api getCurrentApi( void ) = 0;\n  virtual unsigned int getDeviceCount( void ) = 0;\n  virtual RtAudio::DeviceInfo getDeviceInfo( unsigned int device ) = 0;\n  virtual unsigned int getDefaultInputDevice( void );\n  virtual unsigned int getDefaultOutputDevice( void );\n  void openStream( RtAudio::StreamParameters *outputParameters,\n                   RtAudio::StreamParameters *inputParameters,\n                   RtAudioFormat format, unsigned int sampleRate,\n                   unsigned int *bufferFrames, RtAudioCallback callback,\n                   void *userData, RtAudio::StreamOptions *options,\n                   RtAudioErrorCallback errorCallback );\n  virtual void closeStream( void );\n  virtual void startStream( void ) = 0;\n  virtual void stopStream( void ) = 0;\n  virtual void abortStream( void ) = 0;\n  long getStreamLatency( void );\n  unsigned int getStreamSampleRate( void );\n  virtual double getStreamTime( void );\n  bool isStreamOpen( void ) const { return stream_.state != STREAM_CLOSED; }\n  bool isStreamRunning( void ) const { return stream_.state == STREAM_RUNNING; }\n  void showWarnings( bool value ) { showWarnings_ = value; }\n\n\nprotected:\n\n  static const unsigned int MAX_SAMPLE_RATES;\n  static const unsigned int SAMPLE_RATES[];\n\n  enum { FAILURE, SUCCESS };\n\n  enum StreamState {\n    STREAM_STOPPED,\n    STREAM_STOPPING,\n    STREAM_RUNNING,\n    STREAM_CLOSED = -50\n  };\n\n  enum StreamMode {\n    OUTPUT,\n    INPUT,\n    DUPLEX,\n    UNINITIALIZED = -75\n  };\n\n  // A protected structure used for buffer conversion.\n  struct ConvertInfo {\n    int channels;\n    int inJump, outJump;\n    RtAudioFormat inFormat, outFormat;\n    std::vector<int> inOffset;\n    std::vector<int> outOffset;\n  };\n\n  // A protected structure for audio streams.\n  struct RtApiStream {\n    unsigned int device[2];    // Playback and record, respectively.\n    void *apiHandle;           // void pointer for API specific stream handle information\n    StreamMode mode;           // OUTPUT, INPUT, or DUPLEX.\n    StreamState state;         // STOPPED, RUNNING, or CLOSED\n    char *userBuffer[2];       // Playback and record, respectively.\n    char *deviceBuffer;\n    bool doConvertBuffer[2];   // Playback and record, respectively.\n    bool userInterleaved;\n    bool deviceInterleaved[2]; // Playback and record, respectively.\n    bool doByteSwap[2];        // Playback and record, respectively.\n    unsigned int sampleRate;\n    unsigned int bufferSize;\n    unsigned int nBuffers;\n    unsigned int nUserChannels[2];    // Playback and record, respectively.\n    unsigned int nDeviceChannels[2];  // Playback and record channels, respectively.\n    unsigned int channelOffset[2];    // Playback and record, respectively.\n    unsigned long latency[2];         // Playback and record, respectively.\n    RtAudioFormat userFormat;\n    RtAudioFormat deviceFormat[2];    // Playback and record, respectively.\n    StreamMutex mutex;\n    CallbackInfo callbackInfo;\n    ConvertInfo convertInfo[2];\n    double streamTime;         // Number of elapsed seconds since the stream started.\n\n#if defined(HAVE_GETTIMEOFDAY)\n    struct timeval lastTickTimestamp;\n#endif\n\n    RtApiStream()\n      :apiHandle(0), deviceBuffer(0) { device[0] = 11111; device[1] = 11111; }\n  };\n\n  typedef S24 Int24;\n  typedef signed short Int16;\n  typedef signed int Int32;\n  typedef float Float32;\n  typedef double Float64;\n\n  std::ostringstream errorStream_;\n  std::string errorText_;\n  bool showWarnings_;\n  RtApiStream stream_;\n\n  /*!\n    Protected, api-specific method that attempts to open a device\n    with the given parameters.  This function MUST be implemented by\n    all subclasses.  If an error is encountered during the probe, a\n    \"warning\" message is reported and FAILURE is returned. A\n    successful probe is indicated by a return value of SUCCESS.\n  */\n  virtual bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, \n                                unsigned int firstChannel, unsigned int sampleRate,\n                                RtAudioFormat format, unsigned int *bufferSize,\n                                RtAudio::StreamOptions *options );\n\n  //! A protected function used to increment the stream time.\n  void tickStreamTime( void );\n\n  //! Protected common method to clear an RtApiStream structure.\n  void clearStreamInfo();\n\n  /*!\n    Protected common method that throws an RtError (type =\n    INVALID_USE) if a stream is not open.\n  */\n  void verifyStream( void );\n\n  //! Protected common error method to allow global control over error handling.\n  void error( RtError::Type type );\n\n  /*!\n    Protected method used to perform format, channel number, and/or interleaving\n    conversions between the user and device buffers.\n  */\n  void convertBuffer( char *outBuffer, char *inBuffer, ConvertInfo &info );\n\n  //! Protected common method used to perform byte-swapping on buffers.\n  void byteSwapBuffer( char *buffer, unsigned int samples, RtAudioFormat format );\n\n  //! Protected common method that returns the number of bytes for a given format.\n  unsigned int formatBytes( RtAudioFormat format );\n\n  //! Protected common method that sets up the parameters for buffer conversion.\n  void setConvertInfo( StreamMode mode, unsigned int firstChannel );\n};\n\n// **************************************************************** //\n//\n// Inline RtAudio definitions.\n//\n// **************************************************************** //\n\ninline RtAudio::Api RtAudio :: getCurrentApi( void ) throw() { return rtapi_->getCurrentApi(); }\ninline unsigned int RtAudio :: getDeviceCount( void ) throw() { return rtapi_->getDeviceCount(); }\ninline RtAudio::DeviceInfo RtAudio :: getDeviceInfo( unsigned int device ) { return rtapi_->getDeviceInfo( device ); }\ninline unsigned int RtAudio :: getDefaultInputDevice( void ) throw() { return rtapi_->getDefaultInputDevice(); }\ninline unsigned int RtAudio :: getDefaultOutputDevice( void ) throw() { return rtapi_->getDefaultOutputDevice(); }\ninline void RtAudio :: closeStream( void ) throw() { return rtapi_->closeStream(); }\ninline void RtAudio :: startStream( void ) { return rtapi_->startStream(); }\ninline void RtAudio :: stopStream( void )  { return rtapi_->stopStream(); }\ninline void RtAudio :: abortStream( void ) { return rtapi_->abortStream(); }\ninline bool RtAudio :: isStreamOpen( void ) const throw() { return rtapi_->isStreamOpen(); }\ninline bool RtAudio :: isStreamRunning( void ) const throw() { return rtapi_->isStreamRunning(); }\ninline long RtAudio :: getStreamLatency( void ) { return rtapi_->getStreamLatency(); }\ninline unsigned int RtAudio :: getStreamSampleRate( void ) { return rtapi_->getStreamSampleRate(); }\ninline double RtAudio :: getStreamTime( void ) { return rtapi_->getStreamTime(); }\ninline void RtAudio :: showWarnings( bool value ) throw() { rtapi_->showWarnings( value ); }\n\n// RtApi Subclass prototypes.\n\n#if defined(__MACOSX_CORE__)\n\n#include <CoreAudio/AudioHardware.h>\n\nclass RtApiCore: public RtApi\n{\npublic:\n\n  RtApiCore();\n  ~RtApiCore();\n  RtAudio::Api getCurrentApi( void ) { return RtAudio::MACOSX_CORE; }\n  unsigned int getDeviceCount( void );\n  RtAudio::DeviceInfo getDeviceInfo( unsigned int device );\n  unsigned int getDefaultOutputDevice( void );\n  unsigned int getDefaultInputDevice( void );\n  void closeStream( void );\n  void startStream( void );\n  void stopStream( void );\n  void abortStream( void );\n  long getStreamLatency( void );\n\n  // This function is intended for internal use only.  It must be\n  // public because it is called by the internal callback handler,\n  // which is not a member of RtAudio.  External use of this function\n  // will most likely produce highly undesireable results!\n  bool callbackEvent( AudioDeviceID deviceId,\n                      const AudioBufferList *inBufferList,\n                      const AudioBufferList *outBufferList );\n\n  private:\n\n  bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, \n                        unsigned int firstChannel, unsigned int sampleRate,\n                        RtAudioFormat format, unsigned int *bufferSize,\n                        RtAudio::StreamOptions *options );\n  static const char* getErrorCode( OSStatus code );\n};\n\n#endif\n\n#if defined(__UNIX_JACK__)\n\nclass RtApiJack: public RtApi\n{\npublic:\n\n  RtApiJack();\n  ~RtApiJack();\n  RtAudio::Api getCurrentApi( void ) { return RtAudio::UNIX_JACK; }\n  unsigned int getDeviceCount( void );\n  RtAudio::DeviceInfo getDeviceInfo( unsigned int device );\n  void closeStream( void );\n  void startStream( void );\n  void stopStream( void );\n  void abortStream( void );\n  long getStreamLatency( void );\n\n  // This function is intended for internal use only.  It must be\n  // public because it is called by the internal callback handler,\n  // which is not a member of RtAudio.  External use of this function\n  // will most likely produce highly undesireable results!\n  bool callbackEvent( unsigned long nframes );\n\n  private:\n\n  bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, \n                        unsigned int firstChannel, unsigned int sampleRate,\n                        RtAudioFormat format, unsigned int *bufferSize,\n                        RtAudio::StreamOptions *options );\n};\n\n#endif\n\n#if defined(__WINDOWS_ASIO__)\n\nclass RtApiAsio: public RtApi\n{\npublic:\n\n  RtApiAsio();\n  ~RtApiAsio();\n  RtAudio::Api getCurrentApi( void ) { return RtAudio::WINDOWS_ASIO; }\n  unsigned int getDeviceCount( void );\n  RtAudio::DeviceInfo getDeviceInfo( unsigned int device );\n  void closeStream( void );\n  void startStream( void );\n  void stopStream( void );\n  void abortStream( void );\n  long getStreamLatency( void );\n\n  // This function is intended for internal use only.  It must be\n  // public because it is called by the internal callback handler,\n  // which is not a member of RtAudio.  External use of this function\n  // will most likely produce highly undesireable results!\n  bool callbackEvent( long bufferIndex );\n\n  private:\n\n  std::vector<RtAudio::DeviceInfo> devices_;\n  void saveDeviceInfo( void );\n  bool coInitialized_;\n  bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, \n                        unsigned int firstChannel, unsigned int sampleRate,\n                        RtAudioFormat format, unsigned int *bufferSize,\n                        RtAudio::StreamOptions *options );\n};\n\n#endif\n\n#if defined(__WINDOWS_DS__)\n\nclass RtApiDs: public RtApi\n{\npublic:\n\n  RtApiDs();\n  ~RtApiDs();\n  RtAudio::Api getCurrentApi( void ) { return RtAudio::WINDOWS_DS; }\n  unsigned int getDeviceCount( void );\n  unsigned int getDefaultOutputDevice( void );\n  unsigned int getDefaultInputDevice( void );\n  RtAudio::DeviceInfo getDeviceInfo( unsigned int device );\n  void closeStream( void );\n  void startStream( void );\n  void stopStream( void );\n  void abortStream( void );\n  long getStreamLatency( void );\n\n  // This function is intended for internal use only.  It must be\n  // public because it is called by the internal callback handler,\n  // which is not a member of RtAudio.  External use of this function\n  // will most likely produce highly undesireable results!\n  void callbackEvent( void );\n\n  private:\n\n  bool coInitialized_;\n  bool buffersRolling;\n  long duplexPrerollBytes;\n  std::vector<struct DsDevice> dsDevices;\n  bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, \n                        unsigned int firstChannel, unsigned int sampleRate,\n                        RtAudioFormat format, unsigned int *bufferSize,\n                        RtAudio::StreamOptions *options );\n};\n\n#endif\n\n#if defined(__LINUX_ALSA__)\n\nclass RtApiAlsa: public RtApi\n{\npublic:\n\n  RtApiAlsa();\n  ~RtApiAlsa();\n  RtAudio::Api getCurrentApi() { return RtAudio::LINUX_ALSA; }\n  unsigned int getDeviceCount( void );\n  RtAudio::DeviceInfo getDeviceInfo( unsigned int device );\n  void closeStream( void );\n  void startStream( void );\n  void stopStream( void );\n  void abortStream( void );\n\n  // This function is intended for internal use only.  It must be\n  // public because it is called by the internal callback handler,\n  // which is not a member of RtAudio.  External use of this function\n  // will most likely produce highly undesireable results!\n  void callbackEvent( void );\n\n  private:\n\n  std::vector<RtAudio::DeviceInfo> devices_;\n  void saveDeviceInfo( void );\n  bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, \n                        unsigned int firstChannel, unsigned int sampleRate,\n                        RtAudioFormat format, unsigned int *bufferSize,\n                        RtAudio::StreamOptions *options );\n};\n\n#endif\n\n#if defined(__LINUX_PULSE__)\n\nclass RtApiPulse: public RtApi\n{\npublic:\n  ~RtApiPulse();\n  RtAudio::Api getCurrentApi() { return RtAudio::LINUX_PULSE; }\n  unsigned int getDeviceCount( void );\n  RtAudio::DeviceInfo getDeviceInfo( unsigned int device );\n  void closeStream( void );\n  void startStream( void );\n  void stopStream( void );\n  void abortStream( void );\n\n  // This function is intended for internal use only.  It must be\n  // public because it is called by the internal callback handler,\n  // which is not a member of RtAudio.  External use of this function\n  // will most likely produce highly undesireable results!\n  void callbackEvent( void );\n\n  private:\n\n  std::vector<RtAudio::DeviceInfo> devices_;\n  void saveDeviceInfo( void );\n  bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels,\n                        unsigned int firstChannel, unsigned int sampleRate,\n                        RtAudioFormat format, unsigned int *bufferSize,\n                        RtAudio::StreamOptions *options );\n};\n\n#endif\n\n#if defined(__LINUX_OSS__)\n\nclass RtApiOss: public RtApi\n{\npublic:\n\n  RtApiOss();\n  ~RtApiOss();\n  RtAudio::Api getCurrentApi() { return RtAudio::LINUX_OSS; }\n  unsigned int getDeviceCount( void );\n  RtAudio::DeviceInfo getDeviceInfo( unsigned int device );\n  void closeStream( void );\n  void startStream( void );\n  void stopStream( void );\n  void abortStream( void );\n\n  // This function is intended for internal use only.  It must be\n  // public because it is called by the internal callback handler,\n  // which is not a member of RtAudio.  External use of this function\n  // will most likely produce highly undesireable results!\n  void callbackEvent( void );\n\n  private:\n\n  bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, \n                        unsigned int firstChannel, unsigned int sampleRate,\n                        RtAudioFormat format, unsigned int *bufferSize,\n                        RtAudio::StreamOptions *options );\n};\n\n#endif\n\n#if defined(__RTAUDIO_DUMMY__)\n\nclass RtApiDummy: public RtApi\n{\npublic:\n\n  RtApiDummy() { errorText_ = \"RtApiDummy: This class provides no functionality.\"; error( RtError::WARNING ); }\n  RtAudio::Api getCurrentApi( void ) { return RtAudio::RTAUDIO_DUMMY; }\n  unsigned int getDeviceCount( void ) { return 0; }\n  RtAudio::DeviceInfo getDeviceInfo( unsigned int /*device*/ ) { RtAudio::DeviceInfo info; return info; }\n  void closeStream( void ) {}\n  void startStream( void ) {}\n  void stopStream( void ) {}\n  void abortStream( void ) {}\n\n  private:\n\n  bool probeDeviceOpen( unsigned int /*device*/, StreamMode /*mode*/, unsigned int /*channels*/, \n                        unsigned int /*firstChannel*/, unsigned int /*sampleRate*/,\n                        RtAudioFormat /*format*/, unsigned int * /*bufferSize*/,\n                        RtAudio::StreamOptions * /*options*/ ) { return false; }\n};\n\n#endif\n\n#endif\n\n// Indentation settings for Vim and Emacs\n//\n// Local Variables:\n// c-basic-offset: 2\n// indent-tabs-mode: nil\n// End:\n//\n// vim: et sts=2 sw=2\n"
  },
  {
    "path": "rtaudio/RtError.h",
    "content": "/************************************************************************/\n/*! \\class RtError\n    \\brief Exception handling class for RtAudio & RtMidi.\n\n    The RtError class is quite simple but it does allow errors to be\n    \"caught\" by RtError::Type. See the RtAudio and RtMidi\n    documentation to know which methods can throw an RtError.\n\n*/\n/************************************************************************/\n\n#ifndef RTERROR_H\n#define RTERROR_H\n\n#include <exception>\n#include <iostream>\n#include <string>\n\nclass RtError : public std::exception\n{\n public:\n  //! Defined RtError types.\n  enum Type {\n    WARNING,           /*!< A non-critical error. */\n    DEBUG_WARNING,     /*!< A non-critical error which might be useful for debugging. */\n    UNSPECIFIED,       /*!< The default, unspecified error type. */\n    NO_DEVICES_FOUND,  /*!< No devices found on system. */\n    INVALID_DEVICE,    /*!< An invalid device ID was specified. */\n    MEMORY_ERROR,      /*!< An error occured during memory allocation. */\n    INVALID_PARAMETER, /*!< An invalid parameter was specified to a function. */\n    INVALID_USE,       /*!< The function was called incorrectly. */\n    DRIVER_ERROR,      /*!< A system driver error occured. */\n    SYSTEM_ERROR,      /*!< A system error occured. */\n    THREAD_ERROR       /*!< A thread error occured. */\n  };\n\n  //! The constructor.\n  RtError( const std::string& message, Type type = RtError::UNSPECIFIED ) throw() : message_(message), type_(type) {}\n \n  //! The destructor.\n  virtual ~RtError( void ) throw() {}\n\n  //! Prints thrown error message to stderr.\n  virtual void printMessage( void ) const throw() { std::cerr << '\\n' << message_ << \"\\n\\n\"; }\n\n  //! Returns the thrown error message type.\n  virtual const Type& getType(void) const throw() { return type_; }\n\n  //! Returns the thrown error message string.\n  virtual const std::string& getMessage(void) const throw() { return message_; }\n\n  //! Returns the thrown error message as a c-style string.\n  virtual const char* what( void ) const throw() { return message_.c_str(); }\n\n protected:\n  std::string message_;\n  Type type_;\n};\n\n#endif\n"
  },
  {
    "path": "rtaudio/configure.ac",
    "content": "# Process this file with autoconf to produce a configure script.\nAC_INIT(RtAudio, 4.0, gary@music.mcgill.ca, rtaudio)\nAC_CONFIG_AUX_DIR(config)\nAC_CONFIG_SRCDIR(RtAudio.cpp)\nAC_CONFIG_FILES([rtaudio-config librtaudio.pc Makefile tests/Makefile])\nAM_INIT_AUTOMAKE([-Wall -Werror foreign])\nAM_SILENT_RULES([yes])\n\n# Fill GXX with something before test.\nAC_SUBST( GXX, [\"no\"] )\n\ndnl Check for pkg-config program, used for configuring some libraries.\nm4_define_default([PKG_PROG_PKG_CONFIG],\n[AC_MSG_CHECKING([pkg-config])\nAC_MSG_RESULT([no])])\n\nPKG_PROG_PKG_CONFIG\nAM_PROG_AR\n\ndnl If the pkg-config autoconf support isn't installed, define its\ndnl autoconf macro to disable any packages depending on it.\nm4_define_default([PKG_CHECK_MODULES],\n[AC_MSG_CHECKING([$1])\nAC_MSG_RESULT([no])\n$4])\n\n# Checks for programs.\nAC_PROG_CXX(c++ g++ CC cxx)\nAC_PROG_RANLIB\nAC_PATH_PROG(AR, ar, no)\nif [[ $AR = \"no\" ]] ; then\n    AC_MSG_ERROR(\"Could not find ar - needed to create a library\");\nfi\n\n# Checks for header files.\nAC_HEADER_STDC\nAC_CHECK_HEADERS(sys/ioctl.h unistd.h)\n\n# Check for debug\nAC_MSG_CHECKING(whether to compile debug version)\nAC_ARG_ENABLE(debug,\n  [  --enable-debug = enable various debug output],\n  [AC_SUBST( cppflag, [-D__RTAUDIO_DEBUG__] ) AC_SUBST( cxxflag, [-g] ) AC_SUBST( object_path, [Debug] ) AC_MSG_RESULT(yes)],\n  [AC_SUBST( cppflag, [] ) AC_SUBST( cxxflag, [-O2] ) AC_SUBST( object_path, [Release] ) AC_MSG_RESULT(no)])\n\n\n# Checks for functions\nAC_CHECK_FUNC(gettimeofday, [cppflag=\"$cppflag -DHAVE_GETTIMEOFDAY\"], )\n\n# For -I and -D flags\nCPPFLAGS=\"$CPPFLAGS $cppflag\"\n\n# For debugging and optimization ... overwrite default because it has both -g and -O2\n#CXXFLAGS=\"$CXXFLAGS $cxxflag\"\nCXXFLAGS=\"$cxxflag\"\n\n# Check compiler and use -Wall if gnu.\nif [test $GXX = \"yes\" ;] then\n  AC_SUBST( cxxflag, [-Wall] )\nfi\n\nCXXFLAGS=\"$CXXFLAGS $cxxflag\"\n\nAC_CANONICAL_HOST\n\nAC_SUBST( sharedlib, [\"librtaudio.so\"] )\nAC_SUBST( sharedname, [\"librtaudio.so.\\$(RELEASE)\"] )\nAC_SUBST( libflags, [\"-shared -Wl,-soname,\\$(SHARED).\\$(MAJOR) -o \\$(SHARED).\\$(RELEASE)\"] )\ncase $host in\n  *-apple*)\n  AC_SUBST( sharedlib, [\"librtaudio.dylib\"] )\n  AC_SUBST( sharedname, [\"librtaudio.\\$(RELEASE).dylib\"] )\n  AC_SUBST( libflags, [\"-dynamiclib -o librtaudio.\\$(RELEASE).dylib\"] )\nesac\n\n# Checks for package options and external software\nAC_SUBST( api, [\"\"] )\nAC_SUBST( req, [\"\"] )\nAC_MSG_CHECKING(for audio API)\ncase $host in\n  *-*-netbsd*)\n    AC_MSG_RESULT(using OSS)\n    api=\"$api -D__LINUX_OSS__\"\n    LIBS=\"$LIBS -lossaudio\"\n    AC_CHECK_LIB(pthread, pthread_create, , AC_MSG_ERROR(RtAudio requires the pthread library!))\n  ;;\n\n  *-*-linux*)\n  AC_ARG_WITH(jack, [  --with-jack = choose JACK server support (Mac OSX and GNU/Linux only)], [\n    api=\"$api -D__UNIX_JACK__\"\n    AC_MSG_RESULT(using JACK)\n    AC_CHECK_LIB(jack, jack_client_open, , AC_MSG_ERROR(JACK support requires the jack library!))\n    AC_CHECK_LIB(asound, snd_pcm_open, , AC_MSG_ERROR(Jack support also requires the asound library!))], )\n\n  # Look for ALSA flag\n  AC_ARG_WITH(alsa, [  --with-alsa = choose native ALSA API support (GNU/Linux only)], [\n    api=\"$api -D__LINUX_ALSA__\"\n    req=\"$req alsa\"\n    AC_MSG_RESULT(using ALSA)\n    AC_CHECK_LIB(asound, snd_pcm_open, , AC_MSG_ERROR(ALSA support requires the asound library!))], )\n\n  # Look for PULSE flag\n  AC_ARG_WITH(pulse, [  --with-pulse = choose PulseAudio API support (GNU/Linux only)], [\n    api=\"$api -D__LINUX_PULSE__\"\n    req=\"$req libpulse-simple\"\n    AC_MSG_RESULT(using PulseAudio)\n    PKG_CHECK_MODULES([PULSE], [libpulse-simple], , AC_MSG_ERROR(PulseAudio support requires the pulse-simple library!))\n        LIBS=\"$LIBS `pkg-config --libs libpulse-simple`\" ], )\n\n  # Look for OSS flag\n  AC_ARG_WITH(oss, [  --with-oss = choose OSS API support (GNU/Linux only)], [\n    api=\"$api -D__LINUX_OSS__\"\n    AC_MSG_RESULT(using OSS)], )\n\n  # If no audio api flags specified, use ALSA\n  if [test \"$api\" == \"\";] then\n    AC_MSG_RESULT(using ALSA)\n    AC_SUBST( api, [-D__LINUX_ALSA__] )\n    req=\"$req alsa\"\n    AC_CHECK_LIB(asound, snd_pcm_open, , AC_MSG_ERROR(ALSA support requires the asound library!))\n  fi\n\n  AC_CHECK_LIB(pthread, pthread_create, , AC_MSG_ERROR(RtAudio requires the pthread library!))\n  ;;\n\n  *-apple*)\n  AC_ARG_WITH(jack, [  --with-jack = choose JACK server support (unix only)], [\n    api=\"$api -D__UNIX_JACK__\"\n    AC_MSG_RESULT(using JACK)\n    AC_CHECK_LIB(jack, jack_client_open, , AC_MSG_ERROR(JACK support requires the jack library!))], )\n\n#    AC_CHECK_HEADER(jack/jack.h, [], [AC_MSG_ERROR(Jack header file not found!)] )\n#    LIBS=\"$LIBS -framework jackmp\" ], )\n\n\n  # Look for Core flag\n  AC_ARG_WITH(core, [  --with-core = choose CoreAudio API support (Mac OSX only)], [\n    api=\"$api -D__MACOSX_CORE__\"\n    AC_MSG_RESULT(using CoreAudio)\n    AC_CHECK_HEADER(CoreAudio/CoreAudio.h, [], [AC_MSG_ERROR(CoreAudio header files not found!)] )\n    LIBS=\"$LIBS -framework CoreAudio -framework CoreFoundation\" ], )\n\n  # If no audio api flags specified, use CoreAudio\n  if [test \"$api\" == \"\"; ] then\n    AC_SUBST( api, [-D__MACOSX_CORE__] )\n    AC_MSG_RESULT(using CoreAudio)\n    AC_CHECK_HEADER(CoreAudio/CoreAudio.h,\n      [],\n      [AC_MSG_ERROR(CoreAudio header files not found!)] )\n    AC_SUBST( LIBS, [\"-framework CoreAudio -framework CoreFoundation\"] )\n  fi\n\n  AC_CHECK_LIB(pthread, pthread_create, , AC_MSG_ERROR(RtAudio requires the pthread library!))\n  ;;\n\n  *-mingw32*)\n  AC_ARG_WITH(asio, [  --with-asio = choose ASIO API support (windoze only)], [\n    api=\"$api -D__WINDOWS_ASIO__\"\n    AC_MSG_RESULT(using ASIO)\n    AC_SUBST( objects, [\"asio.o asiodrivers.o asiolist.o iasiothiscallresolver.o\"] ) ], )\n\n  # Look for DirectSound flag\n  AC_ARG_WITH(ds, [  --with-ds = choose DirectSound API support (windoze only)], [\n    api=\"$api -D__WINDOWS_DS__\"\n    AC_MSG_RESULT(using DirectSound)\n    LIBS=\"-ldsound -lwinmm $LIBS\" ], )\n\n  # If no audio api flags specified, use DirectSound\n  if [test \"$api\" == \"\";] then\n    AC_SUBST( api, [-D__WINDOWS_DS__] )\n    AC_MSG_RESULT(using DirectSound)\n    LIBS=\"-ldsound -lwinmm $LIBS\"\n  fi\n\n  LIBS=\"-lole32 $LIBS\"\n  ;;\n\n  *)\n  # Default case for unknown realtime systems.\n  AC_MSG_ERROR(Unknown system type for realtime support!)\n  ;;\nesac\n\nCPPFLAGS=\"$CPPFLAGS $api\"\n\nAC_OUTPUT\n\nchmod oug+x rtaudio-config\n"
  },
  {
    "path": "rtaudio/contrib/python/pyrtaudio/PyRtAudioTest.py",
    "content": "\r\nimport rtaudio as rt\r\n\r\nfrom math import cos\r\n\r\nimport struct\r\n\r\n\r\nclass audio_generator:\r\n    def __init__(self):\r\n        self.idx = -1\r\n        self.freq = 440.\r\n    def __call__(self):\r\n\tself.idx += 1\r\n\tif self.idx%48000 == 0:\r\n            self.freq *= 2**(1/12.)\t\r\n        return 0.5*cos(2.*3.1416*self.freq*self.idx/48000.)\r\n\r\n\r\nclass callback:\r\n    def __init__(self, gen):\r\n        self.gen = gen\r\n\tself.i = 0\r\n    def __call__(self,playback, capture):\r\n        [struct.pack_into(\"f\", playback, 4*o, self.gen()) for o in xrange(256)]\r\n\tself.i = self.i + 256\r\n\tif self.i > 48000*10:\r\n            print '.'\r\n            return 1\r\n\r\ndac = rt.RtAudio()\r\n\r\nn = dac.getDeviceCount()\r\nprint 'Number of devices available: ', n\r\n\r\nfor i in range(n):\r\n    try:\r\n        print dac.getDeviceInfo(i)\r\n    except rt.RtError as e:\r\n\tprint e\r\n\r\n\r\nprint 'Default output device: ', dac.getDefaultOutputDevice()\r\nprint 'Default input device: ', dac.getDefaultInputDevice()\r\n\r\nprint 'is stream open: ', dac.isStreamOpen()\r\nprint 'is stream running: ', dac.isStreamRunning()\r\n\r\noParams = {'deviceId': 1, 'nChannels': 1, 'firstChannel': 0}\r\niParams = {'deviceId': 1, 'nChannels': 1, 'firstChannel': 0}\r\n\r\ntry:\r\n  dac.openStream(oParams,oParams,48000,256,callback(audio_generator()) )\r\nexcept rt.RtError as e:\r\n  print e\r\nelse:\r\n  dac.startStream()\r\n\r\n  import time\r\n  print 'latency: ', dac.getStreamLatency()\r\n\r\n  while (dac.isStreamRunning()):\r\n    time.sleep(0.1)\r\n\r\n  print dac.getStreamTime()\r\n\r\n  dac.stopStream()\r\n  dac.abortStream()\r\n  dac.closeStream()\r\n\r\n"
  },
  {
    "path": "rtaudio/contrib/python/pyrtaudio/readme",
    "content": "PyRtAudio - a python wrapper around RtAudio that allows to perform audio i/o operations in real-time from the python language.\r\n\r\nBy Antoine Lefebvre, 2011\r\n\r\nThis software is in the development stage. Do not expect compatibility\r\nwith future versions. Comments, suggestions, new features, bug fixes,\r\netc. are welcome.\r\n\r\n\r\nThis distribution of PyRtAudio contains the following:\r\n\r\n- rtaudiomodule.cpp: the python wrapper code\r\n- setup.py: a setup script use to compile and install PyRtAudio\r\n- examples: a single PyRtAudioTest.py script\r\n\r\nINSTALLATION\r\n\r\nThe compilation and installation of the PyRtAudio module is handled by\r\nthe python Distribution Utilities (\"Distutils\"). Provided that your\r\nsystem has a C++ compiler and is properly configure, the following\r\ncommand should be sufficient:\r\n\r\n>> python setup.py install\r\n\r\nPlease refer to the distutils documentation for installation problems: http://docs.python.org/distutils/index.html \r\n\r\nLEGAL AND ETHICAL:\r\n\r\nThe PyRtAudio license is the same as the RtAudio license:\r\n\r\n    PyRtAudio: a python wrapper around RtAudio\r\n    Copyright (c)2011 Antoine Lefebvre\r\n\r\n    Permission is hereby granted, free of charge, to any person\r\n    obtaining a copy of this software and associated documentation files\r\n    (the \"Software\"), to deal in the Software without restriction,\r\n    including without limitation the rights to use, copy, modify, merge,\r\n    publish, distribute, sublicense, and/or sell copies of the Software,\r\n    and to permit persons to whom the Software is furnished to do so,\r\n    subject to the following conditions:\r\n\r\n    The above copyright notice and this permission notice shall be\r\n    included in all copies or substantial portions of the Software.\r\n\r\n    Any person wishing to distribute modifications to the Software is\r\n    asked to send the modifications to the original developer so that\r\n    they can be incorporated into the canonical version.  This is,\r\n    however, not a binding provision of this license.\r\n\r\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\r\n    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r\n    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\r\n    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR\r\n    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF\r\n    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\r\n    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r\n\r\n"
  },
  {
    "path": "rtaudio/contrib/python/pyrtaudio/rtaudiomodule.cpp",
    "content": "/************************************************************************/\n/*  PyRtAudio: a python wrapper around RtAudio\n    Copyright (c) 2011 Antoine Lefebvre\n\n    Permission is hereby granted, free of charge, to any person\n    obtaining a copy of this software and associated documentation files\n    (the \"Software\"), to deal in the Software without restriction,\n    including without limitation the rights to use, copy, modify, merge,\n    publish, distribute, sublicense, and/or sell copies of the Software,\n    and to permit persons to whom the Software is furnished to do so,\n    subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be\n    included in all copies or substantial portions of the Software.\n\n    Any person wishing to distribute modifications to the Software is\n    asked to send the modifications to the original developer so that\n    they can be incorporated into the canonical version.  This is,\n    however, not a binding provision of this license.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR\n    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF\n    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\n    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n*/\n/************************************************************************/\n\n// This software is in the development stage\n// Do not expect compatibility with future versions.\n// Comments, suggestions, new features, bug fixes, etc. are welcome\n\n#include <Python.h>\n\n#include \"RtAudio.h\" \n\nextern \"C\" {\n\n    typedef struct \n    {\n        PyObject_HEAD;\n        RtAudio *dac;\n        RtAudioFormat _format;\n        int _bufferSize;\n        unsigned int inputChannels;\n        PyObject *callback_func;\n    } PyRtAudio;\n\n    static PyObject *RtAudioError;\n\n    static int callback(void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames,\n        double streamTime, RtAudioStreamStatus status, void *data )\n    {\n        PyRtAudio* self = (PyRtAudio*) data;\n\n        if (status == RTAUDIO_OUTPUT_UNDERFLOW)\n            printf(\"underflow.\\n\");\n\n        if (self == NULL) return -1;\n\n        float* in = (float *) inputBuffer;\n        float* out = (float *) outputBuffer;\n\n        PyObject *py_callback_func = self->callback_func;\n\n        int retval = 0;\n\n        if (py_callback_func) {\n            PyGILState_STATE gstate = PyGILState_Ensure();\n\n            PyObject* iBuffer = PyBuffer_FromMemory(in, sizeof(float) * self->inputChannels * nBufferFrames);\n            PyObject* oBuffer = PyBuffer_FromReadWriteMemory(out, sizeof(float) * nBufferFrames);\n            PyObject *arglist =  Py_BuildValue(\"(O,O)\", oBuffer, iBuffer);\n\n            if (arglist == NULL) {\n                printf(\"error.\\n\");\n                PyErr_Print();\n                PyGILState_Release(gstate);\n                return 2;\n            }\n\n            // Calling the callback\n            PyObject *result = PyEval_CallObject(py_callback_func, arglist);\n\n            if (PyErr_Occurred() != NULL) {\n                PyErr_Print();\n            }\n            else if PyInt_Check(result) {\n              retval = PyInt_AsLong(result);\n            }\n            \n            Py_DECREF(arglist);\n            Py_DECREF(oBuffer);\n            Py_DECREF(iBuffer);\n            Py_XDECREF(result);\n\n            PyGILState_Release(gstate);            \n        }\n\n        return retval;\n    }\n\n\n\n    static void RtAudio_dealloc(PyRtAudio *self)\n    {\n        printf(\"RtAudio_dealloc.\\n\");\n        if (self == NULL) return;\n\n        if (self->dac) {\n            self->dac->closeStream();\n            Py_CLEAR(self->callback_func);\n            delete self->dac;\n        }\n\n        self->ob_type->tp_free((PyObject *) self);\n    }\n\n\n    static PyObject* RtAudio_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\n    {\n        printf(\"RtAudio_new.\\n\");\n        PyRtAudio *self;\n        char *api = NULL;\n\n        if(!PyArg_ParseTuple(args, \"|s\", &api))\n            return NULL;\n\n        self = (PyRtAudio *) type->tp_alloc(type, 0);\n\n        if(self == NULL) return NULL;\n\n        self->dac = NULL;\n        self->callback_func = NULL;\n\n        try {\n            if (api == NULL)\n                self->dac = new RtAudio;\n            else if(!strcmp(api, \"jack\"))\n                self->dac = new RtAudio(RtAudio::UNIX_JACK);\n            else if(!strcmp(api, \"alsa\"))\n                self->dac = new RtAudio(RtAudio::LINUX_ALSA);\n            else if(!strcmp(api, \"oss\"))\n                self->dac = new RtAudio(RtAudio::LINUX_ALSA);\n            else if(!strcmp(api, \"core\"))\n                self->dac = new RtAudio(RtAudio::MACOSX_CORE);\n            else if(!strcmp(api, \"asio\"))\n                self->dac = new RtAudio(RtAudio::WINDOWS_ASIO);\n            else if(!strcmp(api, \"directsound\"))\n                self->dac = new RtAudio(RtAudio::WINDOWS_DS);\n        }\n        catch (RtError &error) {\n            PyErr_SetString(RtAudioError, error.getMessage().c_str());\n            Py_INCREF(RtAudioError);\n            return NULL;\n        }\n\n        self->dac->showWarnings(false);\n\n        //Py_XINCREF(self);\n        return (PyObject *) self;\n    }\n\n    static int RtAudio_init(PyRtAudio *self, PyObject *args, PyObject *kwds)\n    {\n        printf(\"RtAudio_init.\\n\");\n        //if (self == NULL) return 0;\n        return 0;\n    }\n\n    // This functions does not yet support all the features of the RtAudio::openStream method.\n    // Please send your patches if you improves this.\n    static PyObject* RtAudio_openStream(PyRtAudio *self, PyObject *args)\n    {\n        if (self == NULL) return NULL;\n\n        if (self->dac == NULL) {\n            printf(\"the dac is null.\\n\");\n            Py_RETURN_NONE;\n        }\n\n        PyObject *oParamsObj;\n        PyObject *iParamsObj;\n        int fs;\n        unsigned int bf;\n        PyObject *pycallback;\n\n        if (!PyArg_ParseTuple(args, \"OOiiO\", &oParamsObj, &iParamsObj, &fs, &bf, &pycallback)) \n            return NULL;\n\n        RtAudio::StreamParameters oParams;\n        oParams.deviceId = 1;\n        oParams.nChannels = 1;\n        oParams.firstChannel = 0;\n\n        if (PyDict_Check(oParamsObj)) {\n            if (PyDict_Contains(oParamsObj, PyString_FromString(\"deviceId\"))) {\n                PyObject *value = PyDict_GetItem(oParamsObj, PyString_FromString(\"deviceId\"));\n                oParams.deviceId = PyInt_AsLong(value);\n            }\n            if (PyDict_Contains(oParamsObj, PyString_FromString(\"nChannels\"))) {\n                PyObject *value = PyDict_GetItem(oParamsObj, PyString_FromString(\"nChannels\"));\n                oParams.nChannels = PyInt_AsLong(value);\n            }\n            if (PyDict_Contains(oParamsObj, PyString_FromString(\"firstChannel\"))) {\n                PyObject *value = PyDict_GetItem(oParamsObj, PyString_FromString(\"firstChannel\"));\n                oParams.firstChannel = PyInt_AsLong(value);\n            }\n        }\n        else {\n            printf(\"First argument must be a dictionary. Default values will be used.\\n\");\n        }\n\n        RtAudio::StreamParameters iParams;\n        iParams.deviceId = 1;\n        iParams.nChannels = 2;\n        iParams.firstChannel = 0;\n\n        if (PyDict_Check(iParamsObj)) {\n            if (PyDict_Contains(iParamsObj, PyString_FromString(\"deviceId\"))) {\n                PyObject *value = PyDict_GetItem(iParamsObj, PyString_FromString(\"deviceId\"));\n                iParams.deviceId = PyInt_AsLong(value);\n            }\n            if (PyDict_Contains(iParamsObj, PyString_FromString(\"nChannels\"))) {\n                PyObject *value = PyDict_GetItem(iParamsObj, PyString_FromString(\"nChannels\"));\n                iParams.nChannels = PyInt_AsLong(value);\n            }\n            if (PyDict_Contains(iParamsObj, PyString_FromString(\"firstChannel\"))) {\n                PyObject *value = PyDict_GetItem(iParamsObj, PyString_FromString(\"firstChannel\"));\n                iParams.firstChannel = PyInt_AsLong(value);\n            }\n        }\n        else {\n            printf(\"Second argument must be a dictionary. Default values will be used.\\n\");\n        }\n\n\n        if (!PyCallable_Check(pycallback)) {\n            PyErr_SetString(PyExc_TypeError, \"Need a callable object!\");\n            Py_XINCREF(PyExc_TypeError);\n            return NULL;\n        }\n\n        // sanity check the callback ?\n\n\n        Py_INCREF(pycallback);         /* Add a reference to new callback */\n        self->callback_func = pycallback; /*Remember new callback */\n\n        // add support for other format\n        self->_format = RTAUDIO_FLOAT32;\n\n        // add support for other options\n        RtAudio::StreamOptions options;\n        options.flags = RTAUDIO_NONINTERLEAVED;\n\n        try {\n            if (self->dac->isStreamOpen())\n                self->dac->closeStream();\n            self->dac->openStream(&oParams, &iParams, self->_format, fs, &bf, &callback, self, &options);\n        }\n        catch ( RtError& error ) {\n            PyErr_SetString(RtAudioError, error.getMessage().c_str());\n            Py_INCREF(RtAudioError);\n            return NULL;\n        }\n\n        self->inputChannels = iParams.nChannels;\n\n        Py_RETURN_NONE;\n    }\n\n    static PyObject* RtAudio_closeStream(PyRtAudio *self, PyObject *args)\n    {\n        printf(\"RtAudio_closeStream.\\n\");\n        if (self == NULL || self->dac == NULL) return NULL;\n\n        try {\n            self->dac->closeStream();\n            Py_CLEAR(self->callback_func);\n        }\n        catch(RtError &error) {\n            PyErr_SetString(RtAudioError, error.getMessage().c_str());\n            Py_INCREF(RtAudioError);\n            return NULL;\n        }\n\n        Py_RETURN_NONE;\n    }\n\n    static PyObject* RtAudio_startStream(PyRtAudio *self, PyObject *args)\n    {\n        if (self == NULL || self->dac == NULL) return NULL;\n\n        try {\n            self->dac->startStream();\n        }\n        catch(RtError &error) {\n            PyErr_SetString(RtAudioError, error.getMessage().c_str());\n            Py_INCREF(RtAudioError);\n            return NULL;\n        }\n\n        Py_RETURN_NONE;\n    }\n\n\n    static PyObject* RtAudio_stopStream(PyRtAudio *self, PyObject *args)\n    {\n        printf(\"RtAudio_stopStream.\\n\");\n        if (self == NULL || self->dac == NULL) return NULL;\n\n        try {\n            self->dac->stopStream();\n        }\n        catch(RtError &error) {\n            PyErr_SetString(RtAudioError, error.getMessage().c_str());\n            Py_INCREF(RtAudioError);\n            return NULL;\n        }\n\n        Py_RETURN_NONE;\n    }\n\n    static PyObject* RtAudio_abortStream(PyRtAudio *self, PyObject *args)\n    {\n        printf(\"RtAudio_abortStream.\\n\");\n        if (self == NULL || self->dac == NULL) return NULL;\n\n        try {\n            self->dac->abortStream();\n        }\n        catch(RtError &error) {\n            PyErr_SetString(RtAudioError, error.getMessage().c_str());\n            Py_INCREF(RtAudioError);\n            return NULL;\n        }\n        Py_RETURN_NONE;\n    }\n\n    static PyObject* RtAudio_isStreamRunning(PyRtAudio *self, PyObject *args)\n    {\n       if (self == NULL || self->dac == NULL) return NULL;\n\n       if (self->dac == NULL) {\n            Py_RETURN_FALSE;\n        }\n        if (self->dac->isStreamRunning())\n            Py_RETURN_TRUE;\n        else\n            Py_RETURN_FALSE;\n    }\n\n    static PyObject* RtAudio_isStreamOpen(PyRtAudio *self, PyObject *args)\n    {\n        if (self == NULL || self->dac == NULL) return NULL;\n\n        if (self->dac == NULL) {\n            Py_RETURN_FALSE;\n        }\n        if (self->dac->isStreamOpen())\n            Py_RETURN_TRUE;\n        else\n            Py_RETURN_FALSE;\n\n    }\n\n    static PyObject* RtAudio_getDeviceCount(PyRtAudio *self, PyObject *args)\n    {\n        if (self == NULL || self->dac == NULL) return NULL;\n\n        return PyInt_FromLong(self->dac->getDeviceCount());\n    }\n\n    static PyObject* RtAudio_getDeviceInfo(PyRtAudio *self, PyObject *args)\n    {\n        if (self == NULL || self->dac == NULL) return NULL;\n\n        int device;\n        if (!PyArg_ParseTuple(args, \"i\", &device))\n            return NULL;\n\n        try {\n            RtAudio::DeviceInfo info = self->dac->getDeviceInfo(device);\n\n            PyObject* info_dict = PyDict_New();\n\n            if (info.probed) {\n                Py_INCREF(Py_True);\n                PyDict_SetItemString(info_dict, \"probed\", Py_True);\n            }\n            else {\n                Py_INCREF(Py_False);\n                PyDict_SetItemString(info_dict, \"probed\", Py_False);\n            }\n            PyObject* obj;\n\n            obj = PyString_FromString(info.name.c_str());\n            PyDict_SetItemString(info_dict, \"name\", obj);\n\n            obj = PyInt_FromLong(info.outputChannels);\n            PyDict_SetItemString(info_dict, \"outputChannels\", obj);\n\n            obj = PyInt_FromLong(info.inputChannels);\n            PyDict_SetItemString(info_dict, \"inputChannels\", obj);\n\n            obj = PyInt_FromLong(info.duplexChannels);\n            PyDict_SetItemString(info_dict, \"duplexChannels\", obj);\n\n            if (info.isDefaultOutput) {\n                Py_INCREF(Py_True);\n                PyDict_SetItemString(info_dict, \"isDefaultOutput\", Py_True);\n            }\n            else {\n                Py_INCREF(Py_False);\n                PyDict_SetItemString(info_dict, \"isDefaultOutput\", Py_False);\n            }\n\n            if (info.isDefaultInput) {\n                Py_INCREF(Py_True);\n                PyDict_SetItemString(info_dict, \"isDefaultInput\", Py_True);\n            }\n            else {\n                Py_INCREF(Py_False);\n                PyDict_SetItemString(info_dict, \"isDefaultInput\", Py_False);\n            }\n\n            return info_dict;\n\n        }\n        catch(RtError &error) {\n            PyErr_SetString(RtAudioError, error.getMessage().c_str());\n            Py_INCREF(RtAudioError);\n            return NULL;\n        }\n    }\n\n    static PyObject* RtAudio_getDefaultOutputDevice(PyRtAudio *self, PyObject *args)\n    {\n        if (self == NULL || self->dac == NULL) return NULL;\n        return PyInt_FromLong(self->dac->getDefaultOutputDevice());\n    }\n\n    static PyObject* RtAudio_getDefaultInputDevice(PyRtAudio *self, PyObject *args)\n    {\n        if (self == NULL || self->dac == NULL) return NULL;\n        return PyInt_FromLong(self->dac->getDefaultInputDevice());\n    }\n\n    static PyObject* RtAudio_getStreamTime(PyRtAudio *self, PyObject *args)\n    {\n        if (self == NULL || self->dac == NULL) return NULL;\n        return PyFloat_FromDouble( self->dac->getStreamTime() );\n    }\n\n    static PyObject* RtAudio_getStreamLatency(PyRtAudio *self, PyObject *args)\n    {\n        if (self == NULL || self->dac == NULL) return NULL;\n        return PyInt_FromLong( self->dac->getStreamLatency() );\n    }\n\n    static PyObject* RtAudio_getStreamSampleRate(PyRtAudio *self, PyObject *args)\n    {\n        if (self == NULL || self->dac == NULL) return NULL;\n        return PyInt_FromLong( self->dac->getStreamSampleRate() );\n    }\n\n    static PyObject* RtAudio_showWarnings(PyRtAudio *self, PyObject *args)\n    {\n        if (self == NULL || self->dac == NULL) return NULL;\n\n        PyObject *obj;\n        if (!PyArg_ParseTuple(args, \"O\", &obj))\n            return NULL;\n\n        if (!PyBool_Check(obj))\n            return NULL;\n\n        if (obj == Py_True)\n            self->dac->showWarnings(true);\n        else if (obj == Py_False)\n            self->dac->showWarnings(false);\n        else {\n            printf(\"not true nor false\\n\");\n        }\n        Py_RETURN_NONE;\n    }\n\n\n    static PyMethodDef RtAudio_methods[] = \n    {\n        // TO BE DONE: getCurrentApi(void)\n        {\"getDeviceCount\", (PyCFunction) RtAudio_getDeviceCount, METH_NOARGS,\n        \"A public function that queries for the number of audio devices available.\"},\n        {\"getDeviceInfo\", (PyCFunction) RtAudio_getDeviceInfo, METH_VARARGS,\n        \"Return a dictionary with information for a specified device number.\"},\n        {\"getDefaultOutputDevice\", (PyCFunction) RtAudio_getDefaultOutputDevice, METH_NOARGS,\n        \"A function that returns the index of the default output device.\"},\n        {\"getDefaultInputDevice\", (PyCFunction) RtAudio_getDefaultInputDevice, METH_NOARGS,\n        \"A function that returns the index of the default input device.\"},\n        {\"openStream\", (PyCFunction) RtAudio_openStream, METH_VARARGS,\n        \"A public method for opening a stream with the specified parameters.\"},\n        {\"closeStream\", (PyCFunction) RtAudio_closeStream, METH_NOARGS,\n        \"A function that closes a stream and frees any associated stream memory. \"},\n        {\"startStream\", (PyCFunction) RtAudio_startStream, METH_NOARGS,\n        \"A function that starts a stream. \"},\n        {\"stopStream\", (PyCFunction) RtAudio_stopStream, METH_NOARGS,\n        \"Stop a stream, allowing any samples remaining in the output queue to be played. \"},\n        {\"abortStream\", (PyCFunction) RtAudio_abortStream, METH_NOARGS,\n        \"Stop a stream, discarding any samples remaining in the input/output queue.\"},\n        {\"isStreamOpen\", (PyCFunction) RtAudio_isStreamOpen, METH_NOARGS,\n        \"Returns true if a stream is open and false if not.\"},\n        {\"isStreamRunning\", (PyCFunction) RtAudio_isStreamRunning, METH_NOARGS,\n        \"Returns true if the stream is running and false if it is stopped or not open.\"},\n        {\"getStreamTime\", (PyCFunction) RtAudio_getStreamTime, METH_NOARGS,\n        \"Returns the number of elapsed seconds since the stream was started.\"},\n        {\"getStreamLatency\", (PyCFunction) RtAudio_getStreamLatency, METH_NOARGS,\n        \"Returns the internal stream latency in sample frames.\"},\n        {\"getStreamSampleRate\", (PyCFunction) RtAudio_getStreamSampleRate, METH_NOARGS,\n        \"Returns actual sample rate in use by the stream.\"},\n        {\"showWarnings\", (PyCFunction) RtAudio_showWarnings, METH_VARARGS,\n        \"Specify whether warning messages should be printed to stderr.\"},\n        // TO BE DONE: getCompiledApi (std::vector< RtAudio::Api > &apis) throw ()\n        {NULL}\n    };\n\n\n    static PyTypeObject RtAudio_type = {\n        PyObject_HEAD_INIT(NULL)\n        0,                         /*ob_size*/\n        \"rtaudio.RtAudio\",             /*tp_name*/\n        sizeof(RtAudio), /*tp_basicsize*/\n        0,                         /*tp_itemsize*/\n        (destructor) RtAudio_dealloc,                         /*tp_dealloc*/\n        0,                         /*tp_print*/\n        0,                         /*tp_getattr*/\n        0,                         /*tp_setattr*/\n        0,                         /*tp_compare*/\n        0,                         /*tp_repr*/\n        0,                         /*tp_as_number*/\n        0,                         /*tp_as_sequence*/\n        0,                         /*tp_as_mapping*/\n        0,                         /*tp_hash */\n        0,                         /*tp_call*/\n        0,                         /*tp_str*/\n        0,                         /*tp_getattro*/\n        0,                         /*tp_setattro*/\n        0,                         /*tp_as_buffer*/\n        Py_TPFLAGS_DEFAULT,        /*tp_flags*/\n        \"Audio input device\",           /* tp_doc */\n        0,               /* tp_traverse */\n        0,               /* tp_clear */\n        0,               /* tp_richcompare */\n        0,               /* tp_weaklistoffset */\n        0,               /* tp_iter */\n        0,               /* tp_iternext */\n        RtAudio_methods,             /* tp_methods */\n        0,              /* tp_members */\n        0,                         /* tp_getset */\n        0,                         /* tp_base */\n        0,                         /* tp_dict */\n        0,                         /* tp_descr_get */\n        0,                         /* tp_descr_set */\n        0,                         /* tp_dictoffset */\n        (initproc)RtAudio_init,      /* tp_init */\n        0,                         /* tp_alloc */\n        RtAudio_new,                 /* tp_new */\n        0, /* Low-level free-memory routine */\n\t    0, /* For PyObject_IS_GC */\n\t    0, // PyObject *tp_bases;\n\t    0, // PyObject *tp_mro; /* method resolution order */\n\t    0, //PyObject *tp_cache;\n\t    0, //PyObject *tp_subclasses;\n\t    0, //PyObject *tp_weaklist;\n\t    0, //destructor tp_del;\n        //0,\t/* Type attribute cache version tag. Added in version 2.6 */\n    };\n\n\n\n#ifndef PyMODINIT_FUNC\t/* declarations for DLL import/export */\n#define PyMODINIT_FUNC void\n#endif\n    PyMODINIT_FUNC\n    initrtaudio(void) \n    {\n        PyEval_InitThreads();\n\n        if (PyType_Ready(&RtAudio_type) < 0)\n            return;\n\n        PyObject* module = Py_InitModule3(\"rtaudio\", NULL, \"RtAudio wrapper.\");\n        if (module == NULL)\n            return;\n\n        Py_INCREF(&RtAudio_type);\n        PyModule_AddObject(module, \"RtAudio\", (PyObject *)&RtAudio_type);\n\n        RtAudioError = PyErr_NewException(\"rtaudio.RtError\", NULL, NULL);\n        Py_INCREF(RtAudioError);\n        PyModule_AddObject(module, \"RtError\", RtAudioError);\n    }\n}\n"
  },
  {
    "path": "rtaudio/contrib/python/pyrtaudio/setup.py",
    "content": "#!/bin/env python\n\nimport os\nfrom distutils.core import setup, Extension\n\nif hasattr(os, 'uname'):\n    OSNAME = os.uname()[0]\nelse:\n    OSNAME = 'Windows'\n\n\ndefine_macros = []\nlibraries = []\nextra_link_args = []\nextra_compile_args = ['-I../../../']\nsources = ['rtaudiomodule.cpp', '../../../RtAudio.cpp']\n\n\nif OSNAME == 'Linux':\n    define_macros=[(\"__LINUX_ALSA__\", ''),\n                   ('__LINUX_JACK__', ''),\n                   ('__LINUX_OSS__', '')]\n    libraries = ['asound', 'jack', 'pthread']\n\nelif OSNAME == 'Darwin':\n    define_macros = [('__MACOSX_CORE__', '')]\n    libraries = ['pthread', 'stdc++']\n    extra_link_args = ['-framework', 'CoreAudio']\n\nelif OSNAME == 'Windows':\n    define_macros = [('__WINDOWS_DS__', None),\n                     ('__WINDOWS_ASIO__', None),\n\t\t     ('__LITTLE_ENDIAN__',None),\n\t\t     ('WIN32',None)]\n    libraries = ['winmm', 'dsound', 'Advapi32','Ole32','User32']\n    sources += ['../../../include/asio.cpp',\n                '../../../include/asiodrivers.cpp',\n                '../../../include/asiolist.cpp',\n                '../../../include/iasiothiscallresolver.cpp']\n    extra_compile_args.append('-I../../../include/')\n    extra_compile_args.append('-EHsc')\n\n\n\naudio = Extension('rtaudio',\n                 sources=sources,\n                 libraries=libraries,\n                 define_macros=define_macros,\n\t\t extra_compile_args = extra_compile_args,\n                 extra_link_args = extra_link_args,\n                 )\n\n\nsetup(name = 'rtaudio',\n      version = '0.1',\n      description = 'Python RtAudio interface',\n      ext_modules = [audio])\n\n"
  },
  {
    "path": "rtaudio/include/asio.cpp",
    "content": "/*\r\n\tSteinberg Audio Stream I/O API\r\n\t(c) 1996, Steinberg Soft- und Hardware GmbH\r\n\r\n\tasio.cpp\r\n\t\r\n\tasio functions entries which translate the\r\n\tasio interface to the asiodrvr class methods\r\n*/ \r\n\t\r\n#include <string.h>\r\n#include \"asiosys.h\"\t\t// platform definition\r\n#include \"asio.h\"\r\n\r\n#if MAC\r\n#include \"asiodrvr.h\"\r\n\r\n#pragma export on\r\n\r\nAsioDriver *theAsioDriver = 0;\r\n\r\nextern \"C\"\r\n{\r\n\r\nlong main()\r\n{\r\n\treturn 'ASIO';\r\n}\r\n\r\n#elif WINDOWS\r\n\r\n#include \"windows.h\"\r\n#include \"iasiodrv.h\"\r\n#include \"asiodrivers.h\"\r\n\r\nIASIO *theAsioDriver = 0;\r\nextern AsioDrivers *asioDrivers;\r\n\r\n#elif SGI || SUN || BEOS || LINUX\r\n#include \"asiodrvr.h\"\r\nstatic AsioDriver *theAsioDriver = 0;\r\n#endif\r\n\r\n//-----------------------------------------------------------------------------------------------------\r\nASIOError ASIOInit(ASIODriverInfo *info)\r\n{\r\n#if MAC || SGI || SUN || BEOS || LINUX\r\n\tif(theAsioDriver)\r\n\t{\r\n\t\tdelete theAsioDriver;\r\n\t\ttheAsioDriver = 0;\r\n\t}\t\t\r\n\tinfo->driverVersion = 0;\r\n\tstrcpy(info->name, \"No ASIO Driver\");\r\n\ttheAsioDriver = getDriver();\r\n\tif(!theAsioDriver)\r\n\t{\r\n\t\tstrcpy(info->errorMessage, \"Not enough memory for the ASIO driver!\"); \r\n\t\treturn ASE_NotPresent;\r\n\t}\r\n\tif(!theAsioDriver->init(info->sysRef))\r\n\t{\r\n\t\ttheAsioDriver->getErrorMessage(info->errorMessage);\r\n\t\tdelete theAsioDriver;\r\n\t\ttheAsioDriver = 0;\r\n\t\treturn ASE_NotPresent;\r\n\t}\r\n\tstrcpy(info->errorMessage, \"No ASIO Driver Error\");\r\n\ttheAsioDriver->getDriverName(info->name);\r\n\tinfo->driverVersion = theAsioDriver->getDriverVersion();\r\n\treturn ASE_OK;\r\n\r\n#else\r\n\r\n\tinfo->driverVersion = 0;\r\n\tstrcpy(info->name, \"No ASIO Driver\");\r\n\tif(theAsioDriver)\t// must be loaded!\r\n\t{\r\n\t\tif(!theAsioDriver->init(info->sysRef))\r\n\t\t{\r\n\t\t\ttheAsioDriver->getErrorMessage(info->errorMessage);\r\n\t\t\ttheAsioDriver = 0;\r\n\t\t\treturn ASE_NotPresent;\r\n\t\t}\t\t\r\n\r\n\t\tstrcpy(info->errorMessage, \"No ASIO Driver Error\");\r\n\t\ttheAsioDriver->getDriverName(info->name);\r\n\t\tinfo->driverVersion = theAsioDriver->getDriverVersion();\r\n\t\treturn ASE_OK;\r\n\t}\r\n\treturn ASE_NotPresent;\r\n\r\n#endif\t// !MAC\r\n}\r\n\r\nASIOError ASIOExit(void)\r\n{\r\n\tif(theAsioDriver)\r\n\t{\r\n#if WINDOWS\r\n\t\tasioDrivers->removeCurrentDriver();\r\n#else\r\n\t\tdelete theAsioDriver;\r\n#endif\r\n\t}\t\t\r\n\ttheAsioDriver = 0;\r\n\treturn ASE_OK;\r\n}\r\n\r\nASIOError ASIOStart(void)\r\n{\r\n\tif(!theAsioDriver)\r\n\t\treturn ASE_NotPresent;\r\n\treturn theAsioDriver->start();\r\n}\r\n\r\nASIOError ASIOStop(void)\r\n{\r\n\tif(!theAsioDriver)\r\n\t\treturn ASE_NotPresent;\r\n\treturn theAsioDriver->stop();\r\n}\r\n\r\nASIOError ASIOGetChannels(long *numInputChannels, long *numOutputChannels)\r\n{\r\n\tif(!theAsioDriver)\r\n\t{\r\n\t\t*numInputChannels = *numOutputChannels = 0;\r\n\t\treturn ASE_NotPresent;\r\n\t}\r\n\treturn theAsioDriver->getChannels(numInputChannels, numOutputChannels);\r\n}\r\n\r\nASIOError ASIOGetLatencies(long *inputLatency, long *outputLatency)\r\n{\r\n\tif(!theAsioDriver)\r\n\t{\r\n\t\t*inputLatency = *outputLatency = 0;\r\n\t\treturn ASE_NotPresent;\r\n\t}\r\n\treturn theAsioDriver->getLatencies(inputLatency, outputLatency);\r\n}\r\n\r\nASIOError ASIOGetBufferSize(long *minSize, long *maxSize, long *preferredSize, long *granularity)\r\n{\r\n\tif(!theAsioDriver)\r\n\t{\r\n\t\t*minSize = *maxSize = *preferredSize = *granularity = 0;\r\n\t\treturn ASE_NotPresent;\r\n\t}\r\n\treturn theAsioDriver->getBufferSize(minSize, maxSize, preferredSize, granularity);\r\n}\r\n\r\nASIOError ASIOCanSampleRate(ASIOSampleRate sampleRate)\r\n{\r\n\tif(!theAsioDriver)\r\n\t\treturn ASE_NotPresent;\r\n\treturn theAsioDriver->canSampleRate(sampleRate);\r\n}\r\n\r\nASIOError ASIOGetSampleRate(ASIOSampleRate *currentRate)\r\n{\r\n\tif(!theAsioDriver)\r\n\t\treturn ASE_NotPresent;\r\n\treturn theAsioDriver->getSampleRate(currentRate);\r\n}\r\n\r\nASIOError ASIOSetSampleRate(ASIOSampleRate sampleRate)\r\n{\r\n\tif(!theAsioDriver)\r\n\t\treturn ASE_NotPresent;\r\n\treturn theAsioDriver->setSampleRate(sampleRate);\r\n}\r\n\r\nASIOError ASIOGetClockSources(ASIOClockSource *clocks, long *numSources)\r\n{\r\n\tif(!theAsioDriver)\r\n\t{\r\n\t\t*numSources = 0;\r\n\t\treturn ASE_NotPresent;\r\n\t}\r\n\treturn theAsioDriver->getClockSources(clocks, numSources);\r\n}\r\n\r\nASIOError ASIOSetClockSource(long reference)\r\n{\r\n\tif(!theAsioDriver)\r\n\t\treturn ASE_NotPresent;\r\n\treturn theAsioDriver->setClockSource(reference);\r\n}\r\n\r\nASIOError ASIOGetSamplePosition(ASIOSamples *sPos, ASIOTimeStamp *tStamp)\r\n{\r\n\tif(!theAsioDriver)\r\n\t\treturn ASE_NotPresent;\r\n\treturn theAsioDriver->getSamplePosition(sPos, tStamp);\r\n}\r\n\r\nASIOError ASIOGetChannelInfo(ASIOChannelInfo *info)\r\n{\r\n\tif(!theAsioDriver)\r\n\t{\r\n\t\tinfo->channelGroup = -1;\r\n\t\tinfo->type = ASIOSTInt16MSB;\r\n\t\tstrcpy(info->name, \"None\");\r\n\t\treturn ASE_NotPresent;\r\n\t}\r\n\treturn theAsioDriver->getChannelInfo(info);\r\n}\r\n\r\nASIOError ASIOCreateBuffers(ASIOBufferInfo *bufferInfos, long numChannels,\r\n\tlong bufferSize, ASIOCallbacks *callbacks)\r\n{\r\n\tif(!theAsioDriver)\r\n\t{\r\n\t\tASIOBufferInfo *info = bufferInfos;\r\n\t\tfor(long i = 0; i < numChannels; i++, info++)\r\n\t\t\tinfo->buffers[0] = info->buffers[1] = 0;\r\n\t\treturn ASE_NotPresent;\r\n\t}\r\n\treturn theAsioDriver->createBuffers(bufferInfos, numChannels, bufferSize, callbacks);\r\n}\r\n\r\nASIOError ASIODisposeBuffers(void)\r\n{\r\n\tif(!theAsioDriver)\r\n\t\treturn ASE_NotPresent;\r\n\treturn theAsioDriver->disposeBuffers();\r\n}\r\n\r\nASIOError ASIOControlPanel(void)\r\n{\r\n\tif(!theAsioDriver)\r\n\t\treturn ASE_NotPresent;\r\n\treturn theAsioDriver->controlPanel();\r\n}\r\n\r\nASIOError ASIOFuture(long selector, void *opt)\r\n{\r\n\tif(!theAsioDriver)\r\n\t\treturn ASE_NotPresent;\r\n\treturn theAsioDriver->future(selector, opt);\r\n}\r\n\r\nASIOError ASIOOutputReady(void)\r\n{\r\n\tif(!theAsioDriver)\r\n\t\treturn ASE_NotPresent;\r\n\treturn theAsioDriver->outputReady();\r\n}\r\n\r\n#if MAC\r\n}\t// extern \"C\"\r\n#pragma export off\r\n#endif\r\n\r\n\r\n"
  },
  {
    "path": "rtaudio/include/asio.h",
    "content": "//---------------------------------------------------------------------------------------------------\r\n//---------------------------------------------------------------------------------------------------\r\n\r\n/*\r\n\tSteinberg Audio Stream I/O API\r\n\t(c) 1997 - 2005, Steinberg Media Technologies GmbH\r\n\r\n\tASIO Interface Specification v 2.1\r\n\r\n\t2005 - Added support for DSD sample data (in cooperation with Sony)\r\n\r\n\r\n\tbasic concept is an i/o synchronous double-buffer scheme:\r\n\t\r\n\ton bufferSwitch(index == 0), host will read/write:\r\n\r\n\t\tafter ASIOStart(), the\r\n  read  first input buffer A (index 0)\r\n\t|   will be invalid (empty)\r\n\t*   ------------------------\r\n\t|------------------------|-----------------------|\r\n\t|                        |                       |\r\n\t|  Input Buffer A (0)    |   Input Buffer B (1)  |\r\n\t|                        |                       |\r\n\t|------------------------|-----------------------|\r\n\t|                        |                       |\r\n\t|  Output Buffer A (0)   |   Output Buffer B (1) |\r\n\t|                        |                       |\r\n\t|------------------------|-----------------------|\r\n\t*                        -------------------------\r\n\t|                        before calling ASIOStart(),\r\n  write                      host will have filled output\r\n                             buffer B (index 1) already\r\n\r\n  *please* take special care of proper statement of input\r\n  and output latencies (see ASIOGetLatencies()), these\r\n  control sequencer sync accuracy\r\n\r\n*/\r\n\r\n//---------------------------------------------------------------------------------------------------\r\n//---------------------------------------------------------------------------------------------------\r\n\r\n/*\r\n\r\nprototypes summary:\r\n\r\nASIOError ASIOInit(ASIODriverInfo *info);\r\nASIOError ASIOExit(void);\r\nASIOError ASIOStart(void);\r\nASIOError ASIOStop(void);\r\nASIOError ASIOGetChannels(long *numInputChannels, long *numOutputChannels);\r\nASIOError ASIOGetLatencies(long *inputLatency, long *outputLatency);\r\nASIOError ASIOGetBufferSize(long *minSize, long *maxSize, long *preferredSize, long *granularity);\r\nASIOError ASIOCanSampleRate(ASIOSampleRate sampleRate);\r\nASIOError ASIOGetSampleRate(ASIOSampleRate *currentRate);\r\nASIOError ASIOSetSampleRate(ASIOSampleRate sampleRate);\r\nASIOError ASIOGetClockSources(ASIOClockSource *clocks, long *numSources);\r\nASIOError ASIOSetClockSource(long reference);\r\nASIOError ASIOGetSamplePosition (ASIOSamples *sPos, ASIOTimeStamp *tStamp);\r\nASIOError ASIOGetChannelInfo(ASIOChannelInfo *info);\r\nASIOError ASIOCreateBuffers(ASIOBufferInfo *bufferInfos, long numChannels,\r\n\tlong bufferSize, ASIOCallbacks *callbacks);\r\nASIOError ASIODisposeBuffers(void);\r\nASIOError ASIOControlPanel(void);\r\nvoid *ASIOFuture(long selector, void *params);\r\nASIOError ASIOOutputReady(void);\r\n\r\n*/\r\n\r\n//---------------------------------------------------------------------------------------------------\r\n//---------------------------------------------------------------------------------------------------\r\n\r\n#ifndef __ASIO_H\r\n#define __ASIO_H\r\n\r\n// force 4 byte alignment\r\n#if defined(_MSC_VER) && !defined(__MWERKS__) \r\n#pragma pack(push,4)\r\n#elif PRAGMA_ALIGN_SUPPORTED\r\n#pragma options align = native\r\n#endif\r\n\r\n//- - - - - - - - - - - - - - - - - - - - - - - - -\r\n// Type definitions\r\n//- - - - - - - - - - - - - - - - - - - - - - - - -\r\n\r\n// number of samples data type is 64 bit integer\r\n#if NATIVE_INT64\r\n\ttypedef long long int ASIOSamples;\r\n#else\r\n\ttypedef struct ASIOSamples {\r\n\t\tunsigned long hi;\r\n\t\tunsigned long lo;\r\n\t} ASIOSamples;\r\n#endif\r\n\r\n// Timestamp data type is 64 bit integer,\r\n// Time format is Nanoseconds.\r\n#if NATIVE_INT64\r\n\ttypedef long long int ASIOTimeStamp ;\r\n#else\r\n\ttypedef struct ASIOTimeStamp {\r\n\t\tunsigned long hi;\r\n\t\tunsigned long lo;\r\n\t} ASIOTimeStamp;\r\n#endif\r\n\r\n// Samplerates are expressed in IEEE 754 64 bit double float,\r\n// native format as host computer\r\n#if IEEE754_64FLOAT\r\n\ttypedef double ASIOSampleRate;\r\n#else\r\n\ttypedef struct ASIOSampleRate {\r\n\t\tchar ieee[8];\r\n\t} ASIOSampleRate;\r\n#endif\r\n\r\n// Boolean values are expressed as long\r\ntypedef long ASIOBool;\r\nenum {\r\n\tASIOFalse = 0,\r\n\tASIOTrue = 1\r\n};\r\n\r\n// Sample Types are expressed as long\r\ntypedef long ASIOSampleType;\r\nenum {\r\n\tASIOSTInt16MSB   = 0,\r\n\tASIOSTInt24MSB   = 1,\t\t// used for 20 bits as well\r\n\tASIOSTInt32MSB   = 2,\r\n\tASIOSTFloat32MSB = 3,\t\t// IEEE 754 32 bit float\r\n\tASIOSTFloat64MSB = 4,\t\t// IEEE 754 64 bit double float\r\n\r\n\t// these are used for 32 bit data buffer, with different alignment of the data inside\r\n\t// 32 bit PCI bus systems can be more easily used with these\r\n\tASIOSTInt32MSB16 = 8,\t\t// 32 bit data with 16 bit alignment\r\n\tASIOSTInt32MSB18 = 9,\t\t// 32 bit data with 18 bit alignment\r\n\tASIOSTInt32MSB20 = 10,\t\t// 32 bit data with 20 bit alignment\r\n\tASIOSTInt32MSB24 = 11,\t\t// 32 bit data with 24 bit alignment\r\n\t\r\n\tASIOSTInt16LSB   = 16,\r\n\tASIOSTInt24LSB   = 17,\t\t// used for 20 bits as well\r\n\tASIOSTInt32LSB   = 18,\r\n\tASIOSTFloat32LSB = 19,\t\t// IEEE 754 32 bit float, as found on Intel x86 architecture\r\n\tASIOSTFloat64LSB = 20, \t\t// IEEE 754 64 bit double float, as found on Intel x86 architecture\r\n\r\n\t// these are used for 32 bit data buffer, with different alignment of the data inside\r\n\t// 32 bit PCI bus systems can more easily used with these\r\n\tASIOSTInt32LSB16 = 24,\t\t// 32 bit data with 18 bit alignment\r\n\tASIOSTInt32LSB18 = 25,\t\t// 32 bit data with 18 bit alignment\r\n\tASIOSTInt32LSB20 = 26,\t\t// 32 bit data with 20 bit alignment\r\n\tASIOSTInt32LSB24 = 27,\t\t// 32 bit data with 24 bit alignment\r\n\r\n\t//\tASIO DSD format.\r\n\tASIOSTDSDInt8LSB1   = 32,\t\t// DSD 1 bit data, 8 samples per byte. First sample in Least significant bit.\r\n\tASIOSTDSDInt8MSB1   = 33,\t\t// DSD 1 bit data, 8 samples per byte. First sample in Most significant bit.\r\n\tASIOSTDSDInt8NER8\t= 40,\t\t// DSD 8 bit data, 1 sample per byte. No Endianness required.\r\n\r\n\tASIOSTLastEntry\r\n};\r\n\r\n/*-----------------------------------------------------------------------------\r\n// DSD operation and buffer layout\r\n// Definition by Steinberg/Sony Oxford.\r\n//\r\n// We have tried to treat DSD as PCM and so keep a consistant structure across\r\n// the ASIO interface.\r\n//\r\n// DSD's sample rate is normally referenced as a multiple of 44.1Khz, so\r\n// the standard sample rate is refered to as 64Fs (or 2.8224Mhz). We looked\r\n// at making a special case for DSD and adding a field to the ASIOFuture that\r\n// would allow the user to select the Over Sampleing Rate (OSR) as a seperate\r\n// entity but decided in the end just to treat it as a simple value of\r\n// 2.8224Mhz and use the standard interface to set it.\r\n//\r\n// The second problem was the \"word\" size, in PCM the word size is always a\r\n// greater than or equal to 8 bits (a byte). This makes life easy as we can\r\n// then pack the samples into the \"natural\" size for the machine.\r\n// In DSD the \"word\" size is 1 bit. This is not a major problem and can easily\r\n// be dealt with if we ensure that we always deal with a multiple of 8 samples.\r\n//\r\n// DSD brings with it another twist to the Endianness religion. How are the\r\n// samples packed into the byte. It would be nice to just say the most significant\r\n// bit is always the first sample, however there would then be a performance hit\r\n// on little endian machines. Looking at how some of the processing goes...\r\n// Little endian machines like the first sample to be in the Least Significant Bit,\r\n//   this is because when you write it to memory the data is in the correct format\r\n//   to be shifted in and out of the words.\r\n// Big endian machine prefer the first sample to be in the Most Significant Bit,\r\n//   again for the same reasion.\r\n//\r\n// And just when things were looking really muddy there is a proposed extension to\r\n// DSD that uses 8 bit word sizes. It does not care what endianness you use.\r\n//\r\n// Switching the driver between DSD and PCM mode\r\n// ASIOFuture allows for extending the ASIO API quite transparently.\r\n// See kAsioSetIoFormat, kAsioGetIoFormat, kAsioCanDoIoFormat\r\n//\r\n//-----------------------------------------------------------------------------*/\r\n\r\n\r\n//- - - - - - - - - - - - - - - - - - - - - - - - -\r\n// Error codes\r\n//- - - - - - - - - - - - - - - - - - - - - - - - -\r\n\r\ntypedef long ASIOError;\r\nenum {\r\n\tASE_OK = 0,             // This value will be returned whenever the call succeeded\r\n\tASE_SUCCESS = 0x3f4847a0,\t// unique success return value for ASIOFuture calls\r\n\tASE_NotPresent = -1000, // hardware input or output is not present or available\r\n\tASE_HWMalfunction,      // hardware is malfunctioning (can be returned by any ASIO function)\r\n\tASE_InvalidParameter,   // input parameter invalid\r\n\tASE_InvalidMode,        // hardware is in a bad mode or used in a bad mode\r\n\tASE_SPNotAdvancing,     // hardware is not running when sample position is inquired\r\n\tASE_NoClock,            // sample clock or rate cannot be determined or is not present\r\n\tASE_NoMemory            // not enough memory for completing the request\r\n};\r\n\r\n//---------------------------------------------------------------------------------------------------\r\n//---------------------------------------------------------------------------------------------------\r\n\r\n//- - - - - - - - - - - - - - - - - - - - - - - - -\r\n// Time Info support\r\n//- - - - - - - - - - - - - - - - - - - - - - - - -\r\n\r\ntypedef struct ASIOTimeCode\r\n{       \r\n\tdouble          speed;                  // speed relation (fraction of nominal speed)\r\n\t                                        // optional; set to 0. or 1. if not supported\r\n\tASIOSamples     timeCodeSamples;        // time in samples\r\n\tunsigned long   flags;                  // some information flags (see below)\r\n\tchar future[64];\r\n} ASIOTimeCode;\r\n\r\ntypedef enum ASIOTimeCodeFlags\r\n{\r\n\tkTcValid                = 1,\r\n\tkTcRunning              = 1 << 1,\r\n\tkTcReverse              = 1 << 2,\r\n\tkTcOnspeed              = 1 << 3,\r\n\tkTcStill                = 1 << 4,\r\n\t\r\n\tkTcSpeedValid           = 1 << 8\r\n}  ASIOTimeCodeFlags;\r\n\r\ntypedef struct AsioTimeInfo\r\n{\r\n\tdouble          speed;                  // absolute speed (1. = nominal)\r\n\tASIOTimeStamp   systemTime;             // system time related to samplePosition, in nanoseconds\r\n\t                                        // on mac, must be derived from Microseconds() (not UpTime()!)\r\n\t                                        // on windows, must be derived from timeGetTime()\r\n\tASIOSamples     samplePosition;\r\n\tASIOSampleRate  sampleRate;             // current rate\r\n\tunsigned long flags;                    // (see below)\r\n\tchar reserved[12];\r\n} AsioTimeInfo;\r\n\r\ntypedef enum AsioTimeInfoFlags\r\n{\r\n\tkSystemTimeValid        = 1,            // must always be valid\r\n\tkSamplePositionValid    = 1 << 1,       // must always be valid\r\n\tkSampleRateValid        = 1 << 2,\r\n\tkSpeedValid             = 1 << 3,\r\n\t\r\n\tkSampleRateChanged      = 1 << 4,\r\n\tkClockSourceChanged     = 1 << 5\r\n} AsioTimeInfoFlags;\r\n\r\ntypedef struct ASIOTime                          // both input/output\r\n{\r\n\tlong reserved[4];                       // must be 0\r\n\tstruct AsioTimeInfo     timeInfo;       // required\r\n\tstruct ASIOTimeCode     timeCode;       // optional, evaluated if (timeCode.flags & kTcValid)\r\n} ASIOTime;\r\n\r\n/*\r\n\r\nusing time info:\r\nit is recommended to use the new method with time info even if the asio\r\ndevice does not support timecode; continuous calls to ASIOGetSamplePosition\r\nand ASIOGetSampleRate are avoided, and there is a more defined relationship\r\nbetween callback time and the time info.\r\n\r\nsee the example below.\r\nto initiate time info mode, after you have received the callbacks pointer in\r\nASIOCreateBuffers, you will call the asioMessage callback with kAsioSupportsTimeInfo\r\nas the argument. if this returns 1, host has accepted time info mode.\r\nnow host expects the new callback bufferSwitchTimeInfo to be used instead\r\nof the old bufferSwitch method. the ASIOTime structure is assumed to be valid\r\nand accessible until the callback returns.\r\n\r\nusing time code:\r\nif the device supports reading time code, it will call host's asioMessage callback\r\nwith kAsioSupportsTimeCode as the selector. it may then fill the according\r\nfields and set the kTcValid flag.\r\nhost will call the future method with the kAsioEnableTimeCodeRead selector when\r\nit wants to enable or disable tc reading by the device. you should also support\r\nthe kAsioCanTimeInfo and kAsioCanTimeCode selectors in ASIOFuture (see example).\r\n\r\nnote:\r\nthe AsioTimeInfo/ASIOTimeCode pair is supposed to work in both directions.\r\nas a matter of convention, the relationship between the sample\r\nposition counter and the time code at buffer switch time is\r\n(ignoring offset between tc and sample pos when tc is running):\r\n\r\non input:\tsample 0 -> input  buffer sample 0 -> time code 0\r\non output:\tsample 0 -> output buffer sample 0 -> time code 0\r\n\r\nthis means that for 'real' calculations, one has to take into account\r\nthe according latencies.\r\n\r\nexample:\r\n\r\nASIOTime asioTime;\r\n\r\nin createBuffers()\r\n{\r\n\tmemset(&asioTime, 0, sizeof(ASIOTime));\r\n\tAsioTimeInfo* ti = &asioTime.timeInfo;\r\n\tti->sampleRate = theSampleRate;\r\n\tASIOTimeCode* tc = &asioTime.timeCode;\r\n\ttc->speed = 1.;\r\n\ttimeInfoMode = false;\r\n\tcanTimeCode = false;\r\n\tif(callbacks->asioMessage(kAsioSupportsTimeInfo, 0, 0, 0) == 1)\r\n\t{\r\n\t\ttimeInfoMode = true;\r\n#if kCanTimeCode\r\n\t\tif(callbacks->asioMessage(kAsioSupportsTimeCode, 0, 0, 0) == 1)\r\n\t\t\tcanTimeCode = true;\r\n#endif\r\n\t}\r\n}\r\n\r\nvoid switchBuffers(long doubleBufferIndex, bool processNow)\r\n{\r\n\tif(timeInfoMode)\r\n\t{\r\n\t\tAsioTimeInfo* ti = &asioTime.timeInfo;\r\n\t\tti->flags =\tkSystemTimeValid | kSamplePositionValid | kSampleRateValid;\r\n\t\tti->systemTime = theNanoSeconds;\r\n\t\tti->samplePosition = theSamplePosition;\r\n\t\tif(ti->sampleRate != theSampleRate)\r\n\t\t\tti->flags |= kSampleRateChanged;\r\n\t\tti->sampleRate = theSampleRate;\r\n\r\n#if kCanTimeCode\r\n\t\tif(canTimeCode && timeCodeEnabled)\r\n\t\t{\r\n\t\t\tASIOTimeCode* tc = &asioTime.timeCode;\r\n\t\t\ttc->timeCodeSamples = tcSamples;\t\t\t\t\t\t// tc in samples\r\n\t\t\ttc->flags = kTcValid | kTcRunning | kTcOnspeed;\t\t\t// if so...\r\n\t\t}\r\n\t\tASIOTime* bb = callbacks->bufferSwitchTimeInfo(&asioTime, doubleBufferIndex, processNow ? ASIOTrue : ASIOFalse);\r\n#else\r\n\t\tcallbacks->bufferSwitchTimeInfo(&asioTime, doubleBufferIndex, processNow ? ASIOTrue : ASIOFalse);\r\n#endif\r\n\t}\r\n\telse\r\n\t\tcallbacks->bufferSwitch(doubleBufferIndex, ASIOFalse);\r\n}\r\n\r\nASIOError ASIOFuture(long selector, void *params)\r\n{\r\n\tswitch(selector)\r\n\t{\r\n\t\tcase kAsioEnableTimeCodeRead:\r\n\t\t\ttimeCodeEnabled = true;\r\n\t\t\treturn ASE_SUCCESS;\r\n\t\tcase kAsioDisableTimeCodeRead:\r\n\t\t\ttimeCodeEnabled = false;\r\n\t\t\treturn ASE_SUCCESS;\r\n\t\tcase kAsioCanTimeInfo:\r\n\t\t\treturn ASE_SUCCESS;\r\n\t\t#if kCanTimeCode\r\n\t\tcase kAsioCanTimeCode:\r\n\t\t\treturn ASE_SUCCESS;\r\n\t\t#endif\r\n\t}\r\n\treturn ASE_NotPresent;\r\n};\r\n\r\n*/\r\n\r\n//- - - - - - - - - - - - - - - - - - - - - - - - -\r\n// application's audio stream handler callbacks\r\n//- - - - - - - - - - - - - - - - - - - - - - - - -\r\n\r\ntypedef struct ASIOCallbacks\r\n{\r\n\tvoid (*bufferSwitch) (long doubleBufferIndex, ASIOBool directProcess);\r\n\t\t// bufferSwitch indicates that both input and output are to be processed.\r\n\t\t// the current buffer half index (0 for A, 1 for B) determines\r\n\t\t// - the output buffer that the host should start to fill. the other buffer\r\n\t\t//   will be passed to output hardware regardless of whether it got filled\r\n\t\t//   in time or not.\r\n\t\t// - the input buffer that is now filled with incoming data. Note that\r\n\t\t//   because of the synchronicity of i/o, the input always has at\r\n\t\t//   least one buffer latency in relation to the output.\r\n\t\t// directProcess suggests to the host whether it should immedeately\r\n\t\t// start processing (directProcess == ASIOTrue), or whether its process\r\n\t\t// should be deferred because the call comes from a very low level\r\n\t\t// (for instance, a high level priority interrupt), and direct processing\r\n\t\t// would cause timing instabilities for the rest of the system. If in doubt,\r\n\t\t// directProcess should be set to ASIOFalse.\r\n\t\t// Note: bufferSwitch may be called at interrupt time for highest efficiency.\r\n\r\n\tvoid (*sampleRateDidChange) (ASIOSampleRate sRate);\r\n\t\t// gets called when the AudioStreamIO detects a sample rate change\r\n\t\t// If sample rate is unknown, 0 is passed (for instance, clock loss\r\n\t\t// when externally synchronized).\r\n\r\n\tlong (*asioMessage) (long selector, long value, void* message, double* opt);\r\n\t\t// generic callback for various purposes, see selectors below.\r\n\t\t// note this is only present if the asio version is 2 or higher\r\n\r\n\tASIOTime* (*bufferSwitchTimeInfo) (ASIOTime* params, long doubleBufferIndex, ASIOBool directProcess);\r\n\t\t// new callback with time info. makes ASIOGetSamplePosition() and various\r\n\t\t// calls to ASIOGetSampleRate obsolete,\r\n\t\t// and allows for timecode sync etc. to be preferred; will be used if\r\n\t\t// the driver calls asioMessage with selector kAsioSupportsTimeInfo.\r\n} ASIOCallbacks;\r\n\r\n// asioMessage selectors\r\nenum\r\n{\r\n\tkAsioSelectorSupported = 1,\t// selector in <value>, returns 1L if supported,\r\n\t\t\t\t\t\t\t\t// 0 otherwise\r\n    kAsioEngineVersion,\t\t\t// returns engine (host) asio implementation version,\r\n\t\t\t\t\t\t\t\t// 2 or higher\r\n\tkAsioResetRequest,\t\t\t// request driver reset. if accepted, this\r\n\t\t\t\t\t\t\t\t// will close the driver (ASIO_Exit() ) and\r\n\t\t\t\t\t\t\t\t// re-open it again (ASIO_Init() etc). some\r\n\t\t\t\t\t\t\t\t// drivers need to reconfigure for instance\r\n\t\t\t\t\t\t\t\t// when the sample rate changes, or some basic\r\n\t\t\t\t\t\t\t\t// changes have been made in ASIO_ControlPanel().\r\n\t\t\t\t\t\t\t\t// returns 1L; note the request is merely passed\r\n\t\t\t\t\t\t\t\t// to the application, there is no way to determine\r\n\t\t\t\t\t\t\t\t// if it gets accepted at this time (but it usually\r\n\t\t\t\t\t\t\t\t// will be).\r\n\tkAsioBufferSizeChange,\t\t// not yet supported, will currently always return 0L.\r\n\t\t\t\t\t\t\t\t// for now, use kAsioResetRequest instead.\r\n\t\t\t\t\t\t\t\t// once implemented, the new buffer size is expected\r\n\t\t\t\t\t\t\t\t// in <value>, and on success returns 1L\r\n\tkAsioResyncRequest,\t\t\t// the driver went out of sync, such that\r\n\t\t\t\t\t\t\t\t// the timestamp is no longer valid. this\r\n\t\t\t\t\t\t\t\t// is a request to re-start the engine and\r\n\t\t\t\t\t\t\t\t// slave devices (sequencer). returns 1 for ok,\r\n\t\t\t\t\t\t\t\t// 0 if not supported.\r\n\tkAsioLatenciesChanged, \t\t// the drivers latencies have changed. The engine\r\n\t\t\t\t\t\t\t\t// will refetch the latencies.\r\n\tkAsioSupportsTimeInfo,\t\t// if host returns true here, it will expect the\r\n\t\t\t\t\t\t\t\t// callback bufferSwitchTimeInfo to be called instead\r\n\t\t\t\t\t\t\t\t// of bufferSwitch\r\n\tkAsioSupportsTimeCode,\t\t// \r\n\tkAsioMMCCommand,\t\t\t// unused - value: number of commands, message points to mmc commands\r\n\tkAsioSupportsInputMonitor,\t// kAsioSupportsXXX return 1 if host supports this\r\n\tkAsioSupportsInputGain,     // unused and undefined\r\n\tkAsioSupportsInputMeter,    // unused and undefined\r\n\tkAsioSupportsOutputGain,    // unused and undefined\r\n\tkAsioSupportsOutputMeter,   // unused and undefined\r\n\tkAsioOverload,              // driver detected an overload\r\n\r\n\tkAsioNumMessageSelectors\r\n};\r\n\r\n//---------------------------------------------------------------------------------------------------\r\n//---------------------------------------------------------------------------------------------------\r\n\r\n//- - - - - - - - - - - - - - - - - - - - - - - - -\r\n// (De-)Construction\r\n//- - - - - - - - - - - - - - - - - - - - - - - - -\r\n\r\ntypedef struct ASIODriverInfo\r\n{\r\n\tlong asioVersion;\t\t// currently, 2\r\n\tlong driverVersion;\t\t// driver specific\r\n\tchar name[32];\r\n\tchar errorMessage[124];\r\n\tvoid *sysRef;\t\t\t// on input: system reference\r\n\t\t\t\t\t\t\t// (Windows: application main window handle, Mac & SGI: 0)\r\n} ASIODriverInfo;\r\n\r\nASIOError ASIOInit(ASIODriverInfo *info);\r\n/* Purpose:\r\n\t  Initialize the AudioStreamIO.\r\n\tParameter:\r\n\t  info: pointer to an ASIODriver structure:\r\n\t    - asioVersion:\r\n\t\t\t- on input, the host version. *** Note *** this is 0 for earlier asio\r\n\t\t\timplementations, and the asioMessage callback is implemeted\r\n\t\t\tonly if asioVersion is 2 or greater. sorry but due to a design fault\r\n\t\t\tthe driver doesn't have access to the host version in ASIOInit :-(\r\n\t\t\tadded selector for host (engine) version in the asioMessage callback\r\n\t\t\tso we're ok from now on.\r\n\t\t\t- on return, asio implementation version.\r\n\t\t\t  older versions are 1\r\n\t\t\t  if you support this version (namely, ASIO_outputReady() )\r\n\t\t\t  this should be 2 or higher. also see the note in\r\n\t\t\t  ASIO_getTimeStamp() !\r\n\t    - version: on return, the driver version (format is driver specific)\r\n\t    - name: on return, a null-terminated string containing the driver's name\r\n\t\t- error message: on return, should contain a user message describing\r\n\t\t  the type of error that occured during ASIOInit(), if any.\r\n\t\t- sysRef: platform specific\r\n\tReturns:\r\n\t  If neither input nor output is present ASE_NotPresent\r\n\t  will be returned.\r\n\t  ASE_NoMemory, ASE_HWMalfunction are other possible error conditions\r\n*/\r\n\r\nASIOError ASIOExit(void);\r\n/* Purpose:\r\n\t  Terminates the AudioStreamIO.\r\n\tParameter:\r\n\t  None.\r\n\tReturns:\r\n\t  If neither input nor output is present ASE_NotPresent\r\n\t  will be returned.\r\n\tNotes: this implies ASIOStop() and ASIODisposeBuffers(),\r\n\t  meaning that no host callbacks must be accessed after ASIOExit().\r\n*/\r\n\r\n//- - - - - - - - - - - - - - - - - - - - - - - - -\r\n// Start/Stop\r\n//- - - - - - - - - - - - - - - - - - - - - - - - -\r\n\r\nASIOError ASIOStart(void);\r\n/* Purpose:\r\n\t  Start input and output processing synchronously.\r\n\t  This will\r\n\t  - reset the sample counter to zero\r\n\t  - start the hardware (both input and output)\r\n\t    The first call to the hosts' bufferSwitch(index == 0) then tells\r\n\t    the host to read from input buffer A (index 0), and start\r\n\t    processing to output buffer A while output buffer B (which\r\n\t    has been filled by the host prior to calling ASIOStart())\r\n\t    is possibly sounding (see also ASIOGetLatencies()) \r\n\tParameter:\r\n\t  None.\r\n\tReturns:\r\n\t  If neither input nor output is present, ASE_NotPresent\r\n\t  will be returned.\r\n\t  If the hardware fails to start, ASE_HWMalfunction will be returned.\r\n\tNotes:\r\n\t  There is no restriction on the time that ASIOStart() takes\r\n\t  to perform (that is, it is not considered a realtime trigger).\r\n*/\r\n\r\nASIOError ASIOStop(void);\r\n/* Purpose:\r\n\t  Stops input and output processing altogether.\r\n\tParameter:\r\n\t  None.\r\n\tReturns:\r\n\t  If neither input nor output is present ASE_NotPresent\r\n\t  will be returned.\r\n\tNotes:\r\n\t  On return from ASIOStop(), the driver must in no\r\n\t  case call the hosts' bufferSwitch() routine.\r\n*/\r\n\r\n//- - - - - - - - - - - - - - - - - - - - - - - - -\r\n// Inquiry methods and sample rate\r\n//- - - - - - - - - - - - - - - - - - - - - - - - -\r\n\r\nASIOError ASIOGetChannels(long *numInputChannels, long *numOutputChannels);\r\n/* Purpose:\r\n\t  Returns number of individual input/output channels.\r\n\tParameter:\r\n\t  numInputChannels will hold the number of available input channels\r\n\t  numOutputChannels will hold the number of available output channels\r\n\tReturns:\r\n\t  If no input/output is present ASE_NotPresent will be returned.\r\n\t  If only inputs, or only outputs are available, the according\r\n\t  other parameter will be zero, and ASE_OK is returned.\r\n*/\r\n\r\nASIOError ASIOGetLatencies(long *inputLatency, long *outputLatency);\r\n/* Purpose:\r\n\t  Returns the input and output latencies. This includes\r\n\t  device specific delays, like FIFOs etc.\r\n\tParameter:\r\n\t  inputLatency will hold the 'age' of the first sample frame\r\n\t  in the input buffer when the hosts reads it in bufferSwitch()\r\n\t  (this is theoretical, meaning it does not include the overhead\r\n\t  and delay between the actual physical switch, and the time\r\n\t  when bufferSitch() enters).\r\n\t  This will usually be the size of one block in sample frames, plus\r\n\t  device specific latencies.\r\n\r\n\t  outputLatency will specify the time between the buffer switch,\r\n\t  and the time when the next play buffer will start to sound.\r\n\t  The next play buffer is defined as the one the host starts\r\n\t  processing after (or at) bufferSwitch(), indicated by the\r\n\t  index parameter (0 for buffer A, 1 for buffer B).\r\n\t  It will usually be either one block, if the host writes directly\r\n\t  to a dma buffer, or two or more blocks if the buffer is 'latched' by\r\n\t  the driver. As an example, on ASIOStart(), the host will have filled\r\n\t  the play buffer at index 1 already; when it gets the callback (with\r\n\t  the parameter index == 0), this tells it to read from the input\r\n\t  buffer 0, and start to fill the play buffer 0 (assuming that now\r\n\t  play buffer 1 is already sounding). In this case, the output\r\n\t  latency is one block. If the driver decides to copy buffer 1\r\n\t  at that time, and pass it to the hardware at the next slot (which\r\n\t  is most commonly done, but should be avoided), the output latency\r\n\t  becomes two blocks instead, resulting in a total i/o latency of at least\r\n\t  3 blocks. As memory access is the main bottleneck in native dsp processing,\r\n\t  and to acheive less latency, it is highly recommended to try to avoid\r\n\t  copying (this is also why the driver is the owner of the buffers). To\r\n\t  summarize, the minimum i/o latency can be acheived if the input buffer\r\n\t  is processed by the host into the output buffer which will physically\r\n\t  start to sound on the next time slice. Also note that the host expects\r\n\t  the bufferSwitch() callback to be accessed for each time slice in order\r\n\t  to retain sync, possibly recursively; if it fails to process a block in\r\n\t  time, it will suspend its operation for some time in order to recover.\r\n\tReturns:\r\n\t  If no input/output is present ASE_NotPresent will be returned.\r\n*/\r\n\r\nASIOError ASIOGetBufferSize(long *minSize, long *maxSize, long *preferredSize, long *granularity);\r\n/* Purpose:\r\n\t  Returns min, max, and preferred buffer sizes for input/output\r\n\tParameter:\r\n\t  minSize will hold the minimum buffer size\r\n\t  maxSize will hold the maxium possible buffer size\r\n\t  preferredSize will hold the preferred buffer size (a size which\r\n\t  best fits performance and hardware requirements)\r\n\t  granularity will hold the granularity at which buffer sizes\r\n\t  may differ. Usually, the buffer size will be a power of 2;\r\n\t  in this case, granularity will hold -1 on return, signalling\r\n\t  possible buffer sizes starting from minSize, increased in\r\n\t  powers of 2 up to maxSize.\r\n\tReturns:\r\n\t  If no input/output is present ASE_NotPresent will be returned.\r\n\tNotes:\r\n\t  When minimum and maximum buffer size are equal,\r\n\t  the preferred buffer size has to be the same value as well; granularity\r\n\t  should be 0 in this case.\r\n*/\r\n\r\nASIOError ASIOCanSampleRate(ASIOSampleRate sampleRate);\r\n/* Purpose:\r\n\t  Inquires the hardware for the available sample rates.\r\n\tParameter:\r\n\t  sampleRate is the rate in question.\r\n\tReturns:\r\n\t  If the inquired sample rate is not supported, ASE_NoClock will be returned.\r\n\t  If no input/output is present ASE_NotPresent will be returned.\r\n*/\r\nASIOError ASIOGetSampleRate(ASIOSampleRate *currentRate);\r\n/* Purpose:\r\n\t  Get the current sample Rate.\r\n\tParameter:\r\n\t  currentRate will hold the current sample rate on return.\r\n\tReturns:\r\n\t  If sample rate is unknown, sampleRate will be 0 and ASE_NoClock will be returned.\r\n\t  If no input/output is present ASE_NotPresent will be returned.\r\n\tNotes:\r\n*/\r\n\r\nASIOError ASIOSetSampleRate(ASIOSampleRate sampleRate);\r\n/* Purpose:\r\n\t  Set the hardware to the requested sample Rate. If sampleRate == 0,\r\n\t  enable external sync.\r\n\tParameter:\r\n\t  sampleRate: on input, the requested rate\r\n\tReturns:\r\n\t  If sampleRate is unknown ASE_NoClock will be returned.\r\n\t  If the current clock is external, and sampleRate is != 0,\r\n\t  ASE_InvalidMode will be returned\r\n\t  If no input/output is present ASE_NotPresent will be returned.\r\n\tNotes:\r\n*/\r\n\r\ntypedef struct ASIOClockSource\r\n{\r\n\tlong index;\t\t\t\t\t// as used for ASIOSetClockSource()\r\n\tlong associatedChannel;\t\t// for instance, S/PDIF or AES/EBU\r\n\tlong associatedGroup;\t\t// see channel groups (ASIOGetChannelInfo())\r\n\tASIOBool isCurrentSource;\t// ASIOTrue if this is the current clock source\r\n\tchar name[32];\t\t\t\t// for user selection\r\n} ASIOClockSource;\r\n\r\nASIOError ASIOGetClockSources(ASIOClockSource *clocks, long *numSources);\r\n/* Purpose:\r\n\t  Get the available external audio clock sources\r\n\tParameter:\r\n\t  clocks points to an array of ASIOClockSource structures:\r\n\t  \t- index: this is used to identify the clock source\r\n\t  \t  when ASIOSetClockSource() is accessed, should be\r\n\t  \t  an index counting from zero\r\n\t  \t- associatedInputChannel: the first channel of an associated\r\n\t  \t  input group, if any.\r\n\t  \t- associatedGroup: the group index of that channel.\r\n\t  \t  groups of channels are defined to seperate for\r\n\t  \t  instance analog, S/PDIF, AES/EBU, ADAT connectors etc,\r\n\t  \t  when present simultaniously. Note that associated channel\r\n\t  \t  is enumerated according to numInputs/numOutputs, means it\r\n\t  \t  is independant from a group (see also ASIOGetChannelInfo())\r\n\t  \t  inputs are associated to a clock if the physical connection\r\n\t  \t  transfers both data and clock (like S/PDIF, AES/EBU, or\r\n\t  \t  ADAT inputs). if there is no input channel associated with\r\n\t  \t  the clock source (like Word Clock, or internal oscillator), both\r\n\t  \t  associatedChannel and associatedGroup should be set to -1.\r\n\t  \t- isCurrentSource: on exit, ASIOTrue if this is the current clock\r\n\t  \t  source, ASIOFalse else\r\n\t\t- name: a null-terminated string for user selection of the available sources.\r\n\t  numSources:\r\n\t      on input: the number of allocated array members\r\n\t      on output: the number of available clock sources, at least\r\n\t      1 (internal clock generator).\r\n\tReturns:\r\n\t  If no input/output is present ASE_NotPresent will be returned.\r\n\tNotes:\r\n*/\r\n\r\nASIOError ASIOSetClockSource(long index);\r\n/* Purpose:\r\n\t  Set the audio clock source\r\n\tParameter:\r\n\t  index as obtained from an inquiry to ASIOGetClockSources()\r\n\tReturns:\r\n\t  If no input/output is present ASE_NotPresent will be returned.\r\n\t  If the clock can not be selected because an input channel which\r\n\t  carries the current clock source is active, ASE_InvalidMode\r\n\t  *may* be returned (this depends on the properties of the driver\r\n\t  and/or hardware).\r\n\tNotes:\r\n\t  Should *not* return ASE_NoClock if there is no clock signal present\r\n\t  at the selected source; this will be inquired via ASIOGetSampleRate().\r\n\t  It should call the host callback procedure sampleRateHasChanged(),\r\n\t  if the switch causes a sample rate change, or if no external clock\r\n\t  is present at the selected source.\r\n*/\r\n\r\nASIOError ASIOGetSamplePosition (ASIOSamples *sPos, ASIOTimeStamp *tStamp);\r\n/* Purpose:\r\n\t  Inquires the sample position/time stamp pair.\r\n\tParameter:\r\n\t  sPos will hold the sample position on return. The sample\r\n\t  position is reset to zero when ASIOStart() gets called.\r\n\t  tStamp will hold the system time when the sample position\r\n\t  was latched.\r\n\tReturns:\r\n\t  If no input/output is present, ASE_NotPresent will be returned.\r\n\t  If there is no clock, ASE_SPNotAdvancing will be returned.\r\n\tNotes:\r\n\r\n\t  in order to be able to synchronise properly,\r\n\t  the sample position / time stamp pair must refer to the current block,\r\n\t  that is, the engine will call ASIOGetSamplePosition() in its bufferSwitch()\r\n\t  callback and expect the time for the current block. thus, when requested\r\n\t  in the very first bufferSwitch after ASIO_Start(), the sample position\r\n\t  should be zero, and the time stamp should refer to the very time where\r\n\t  the stream was started. it also means that the sample position must be\r\n\t  block aligned. the driver must ensure proper interpolation if the system\r\n\t  time can not be determined for the block position. the driver is responsible\r\n\t  for precise time stamps as it usually has most direct access to lower\r\n\t  level resources. proper behaviour of ASIO_GetSamplePosition() and ASIO_GetLatencies()\r\n\t  are essential for precise media synchronization!\r\n*/\r\n\r\ntypedef struct ASIOChannelInfo\r\n{\r\n\tlong channel;\t\t\t// on input, channel index\r\n\tASIOBool isInput;\t\t// on input\r\n\tASIOBool isActive;\t\t// on exit\r\n\tlong channelGroup;\t\t// dto\r\n\tASIOSampleType type;\t// dto\r\n\tchar name[32];\t\t\t// dto\r\n} ASIOChannelInfo;\r\n\r\nASIOError ASIOGetChannelInfo(ASIOChannelInfo *info);\r\n/* Purpose:\r\n\t  retreive information about the nature of a channel\r\n\tParameter:\r\n\t  info: pointer to a ASIOChannelInfo structure with\r\n\t  \t- channel: on input, the channel index of the channel in question.\r\n\t  \t- isInput: on input, ASIOTrue if info for an input channel is\r\n\t  \t  requested, else output\r\n\t\t- channelGroup: on return, the channel group that the channel\r\n\t\t  belongs to. For drivers which support different types of\r\n\t\t  channels, like analog, S/PDIF, AES/EBU, ADAT etc interfaces,\r\n\t\t  there should be a reasonable grouping of these types. Groups\r\n\t\t  are always independant form a channel index, that is, a channel\r\n\t\t  index always counts from 0 to numInputs/numOutputs regardless\r\n\t\t  of the group it may belong to.\r\n\t\t  There will always be at least one group (group 0). Please\r\n\t\t  also note that by default, the host may decide to activate\r\n\t\t  channels 0 and 1; thus, these should belong to the most\r\n\t\t  useful type (analog i/o, if present).\r\n\t  \t- type: on return, contains the sample type of the channel\r\n\t  \t- isActive: on return, ASIOTrue if channel is active as it was\r\n\t  \t  installed by ASIOCreateBuffers(), ASIOFalse else\r\n\t  \t- name:  describing the type of channel in question. Used to allow\r\n\t  \t  for user selection, and enabling of specific channels. examples:\r\n\t      \"Analog In\", \"SPDIF Out\" etc\r\n\tReturns:\r\n\t  If no input/output is present ASE_NotPresent will be returned.\r\n\tNotes:\r\n\t  If possible, the string should be organised such that the first\r\n\t  characters are most significantly describing the nature of the\r\n\t  port, to allow for identification even if the view showing the\r\n\t  port name is too small to display more than 8 characters, for\r\n\t  instance.\r\n*/\r\n\r\n//- - - - - - - - - - - - - - - - - - - - - - - - -\r\n// Buffer preparation\r\n//- - - - - - - - - - - - - - - - - - - - - - - - -\r\n\r\ntypedef struct ASIOBufferInfo\r\n{\r\n\tASIOBool isInput;\t\t\t// on input:  ASIOTrue: input, else output\r\n\tlong channelNum;\t\t\t// on input:  channel index\r\n\tvoid *buffers[2];\t\t\t// on output: double buffer addresses\r\n} ASIOBufferInfo;\r\n\r\nASIOError ASIOCreateBuffers(ASIOBufferInfo *bufferInfos, long numChannels,\r\n\tlong bufferSize, ASIOCallbacks *callbacks);\r\n\r\n/* Purpose:\r\n\t  Allocates input/output buffers for all input and output channels to be activated.\r\n\tParameter:\r\n\t  bufferInfos is a pointer to an array of ASIOBufferInfo structures:\r\n\t    - isInput: on input, ASIOTrue if the buffer is to be allocated\r\n\t      for an input, output buffer else\r\n\t    - channelNum: on input, the index of the channel in question\r\n\t      (counting from 0)\r\n\t    - buffers: on exit, 2 pointers to the halves of the channels' double-buffer.\r\n\t      the size of the buffer(s) of course depend on both the ASIOSampleType\r\n\t      as obtained from ASIOGetChannelInfo(), and bufferSize\r\n\t  numChannels is the sum of all input and output channels to be created;\r\n\t  thus bufferInfos is a pointer to an array of numChannels ASIOBufferInfo\r\n\t  structures.\r\n\t  bufferSize selects one of the possible buffer sizes as obtained from\r\n\t  ASIOGetBufferSizes().\r\n\t  callbacks is a pointer to an ASIOCallbacks structure.\r\n\tReturns:\r\n\t  If not enough memory is available ASE_NoMemory will be returned.\r\n\t  If no input/output is present ASE_NotPresent will be returned.\r\n\t  If bufferSize is not supported, or one or more of the bufferInfos elements\r\n\t  contain invalid settings, ASE_InvalidMode will be returned.\r\n\tNotes:\r\n\t  If individual channel selection is not possible but requested,\r\n\t  the driver has to handle this. namely, bufferSwitch() will only\r\n\t  have filled buffers of enabled outputs. If possible, processing\r\n\t  and buss activities overhead should be avoided for channels which\r\n\t  were not enabled here.\r\n*/\r\n\r\nASIOError ASIODisposeBuffers(void);\r\n/* Purpose:\r\n\t  Releases all buffers for the device.\r\n\tParameter:\r\n\t  None.\r\n\tReturns:\r\n\t  If no buffer were ever prepared, ASE_InvalidMode will be returned.\r\n\t  If no input/output is present ASE_NotPresent will be returned.\r\n\tNotes:\r\n\t  This implies ASIOStop().\r\n*/\r\n\r\nASIOError ASIOControlPanel(void);\r\n/* Purpose:\r\n\t  request the driver to start a control panel component\r\n\t  for device specific user settings. This will not be\r\n\t  accessed on some platforms (where the component is accessed\r\n\t  instead).\r\n\tParameter:\r\n\t  None.\r\n\tReturns:\r\n\t  If no panel is available ASE_NotPresent will be returned.\r\n\t  Actually, the return code is ignored.\r\n\tNotes:\r\n\t  if the user applied settings which require a re-configuration\r\n\t  of parts or all of the enigine and/or driver (such as a change of\r\n\t  the block size), the asioMessage callback can be used (see\r\n\t  ASIO_Callbacks).\r\n*/\r\n\r\nASIOError ASIOFuture(long selector, void *params);\r\n/* Purpose:\r\n\t  various\r\n\tParameter:\r\n\t  selector: operation Code as to be defined. zero is reserved for\r\n\t  testing purposes.\r\n\t  params: depends on the selector; usually pointer to a structure\r\n\t  for passing and retreiving any type and amount of parameters.\r\n\tReturns:\r\n\t  the return value is also selector dependant. if the selector\r\n\t  is unknown, ASE_InvalidParameter should be returned to prevent\r\n\t  further calls with this selector. on success, ASE_SUCCESS\r\n\t  must be returned (note: ASE_OK is *not* sufficient!)\r\n\tNotes:\r\n\t  see selectors defined below.\t  \r\n*/\r\n\r\nenum\r\n{\r\n\tkAsioEnableTimeCodeRead = 1,\t// no arguments\r\n\tkAsioDisableTimeCodeRead,\t\t// no arguments\r\n\tkAsioSetInputMonitor,\t\t\t// ASIOInputMonitor* in params\r\n\tkAsioTransport,\t\t\t\t\t// ASIOTransportParameters* in params\r\n\tkAsioSetInputGain,\t\t\t\t// ASIOChannelControls* in params, apply gain\r\n\tkAsioGetInputMeter,\t\t\t\t// ASIOChannelControls* in params, fill meter\r\n\tkAsioSetOutputGain,\t\t\t\t// ASIOChannelControls* in params, apply gain\r\n\tkAsioGetOutputMeter,\t\t\t// ASIOChannelControls* in params, fill meter\r\n\tkAsioCanInputMonitor,\t\t\t// no arguments for kAsioCanXXX selectors\r\n\tkAsioCanTimeInfo,\r\n\tkAsioCanTimeCode,\r\n\tkAsioCanTransport,\r\n\tkAsioCanInputGain,\r\n\tkAsioCanInputMeter,\r\n\tkAsioCanOutputGain,\r\n\tkAsioCanOutputMeter,\r\n\r\n\t//\tDSD support\r\n\t//\tThe following extensions are required to allow switching\r\n\t//\tand control of the DSD subsystem.\r\n\tkAsioSetIoFormat\t\t\t= 0x23111961,\t\t/* ASIOIoFormat * in params.\t\t\t*/\r\n\tkAsioGetIoFormat\t\t\t= 0x23111983,\t\t/* ASIOIoFormat * in params.\t\t\t*/\r\n\tkAsioCanDoIoFormat\t\t\t= 0x23112004,\t\t/* ASIOIoFormat * in params.\t\t\t*/\r\n};\r\n\r\ntypedef struct ASIOInputMonitor\r\n{\r\n\tlong input;\t\t// this input was set to monitor (or off), -1: all\r\n\tlong output;\t// suggested output for monitoring the input (if so)\r\n\tlong gain;\t\t// suggested gain, ranging 0 - 0x7fffffffL (-inf to +12 dB)\r\n\tASIOBool state;\t// ASIOTrue => on, ASIOFalse => off\r\n\tlong pan;\t\t// suggested pan, 0 => all left, 0x7fffffff => right\r\n} ASIOInputMonitor;\r\n\r\ntypedef struct ASIOChannelControls\r\n{\r\n\tlong channel;\t\t\t// on input, channel index\r\n\tASIOBool isInput;\t\t// on input\r\n\tlong gain;\t\t\t\t// on input,  ranges 0 thru 0x7fffffff\r\n\tlong meter;\t\t\t\t// on return, ranges 0 thru 0x7fffffff\r\n\tchar future[32];\r\n} ASIOChannelControls;\r\n\r\ntypedef struct ASIOTransportParameters\r\n{\r\n\tlong command;\t\t// see enum below\r\n\tASIOSamples samplePosition;\r\n\tlong track;\r\n\tlong trackSwitches[16];\t\t// 512 tracks on/off\r\n\tchar future[64];\r\n} ASIOTransportParameters;\r\n\r\nenum\r\n{\r\n\tkTransStart = 1,\r\n\tkTransStop,\r\n\tkTransLocate,\t\t// to samplePosition\r\n\tkTransPunchIn,\r\n\tkTransPunchOut,\r\n\tkTransArmOn,\t\t// track\r\n\tkTransArmOff,\t\t// track\r\n\tkTransMonitorOn,\t// track\r\n\tkTransMonitorOff,\t// track\r\n\tkTransArm,\t\t\t// trackSwitches\r\n\tkTransMonitor\t\t// trackSwitches\r\n};\r\n\r\n/*\r\n// DSD support\r\n//\tSome notes on how to use ASIOIoFormatType.\r\n//\r\n//\tThe caller will fill the format with the request types.\r\n//\tIf the board can do the request then it will leave the\r\n//\tvalues unchanged. If the board does not support the\r\n//\trequest then it will change that entry to Invalid (-1)\r\n//\r\n//\tSo to request DSD then\r\n//\r\n//\tASIOIoFormat NeedThis={kASIODSDFormat};\r\n//\r\n//\tif(ASE_SUCCESS != ASIOFuture(kAsioSetIoFormat,&NeedThis) ){\r\n//\t\t// If the board did not accept one of the parameters then the\r\n//\t\t// whole call will fail and the failing parameter will\r\n//\t\t// have had its value changes to -1.\r\n//\t}\r\n//\r\n// Note: Switching between the formats need to be done before the \"prepared\"\r\n// state (see ASIO 2 documentation) is entered.\r\n*/\r\ntypedef long int ASIOIoFormatType;\r\nenum ASIOIoFormatType_e\r\n{\r\n\tkASIOFormatInvalid = -1,\r\n\tkASIOPCMFormat = 0,\r\n\tkASIODSDFormat = 1,\r\n};\r\n\r\ntypedef struct ASIOIoFormat_s\r\n{\r\n\tASIOIoFormatType\tFormatType;\r\n\tchar\t\t\t\tfuture[512-sizeof(ASIOIoFormatType)];\r\n} ASIOIoFormat;\r\n\r\n\r\nASIOError ASIOOutputReady(void);\r\n/* Purpose:\r\n\t  this tells the driver that the host has completed processing\r\n\t  the output buffers. if the data format required by the hardware\r\n\t  differs from the supported asio formats, but the hardware\r\n\t  buffers are DMA buffers, the driver will have to convert\r\n\t  the audio stream data; as the bufferSwitch callback is\r\n\t  usually issued at dma block switch time, the driver will\r\n\t  have to convert the *previous* host buffer, which increases\r\n\t  the output latency by one block.\r\n\t  when the host finds out that ASIOOutputReady() returns\r\n\t  true, it will issue this call whenever it completed\r\n\t  output processing. then the driver can convert the\r\n\t  host data directly to the dma buffer to be played next,\r\n\t  reducing output latency by one block.\r\n\t  another way to look at it is, that the buffer switch is called\r\n\t  in order to pass the *input* stream to the host, so that it can\r\n\t  process the input into the output, and the output stream is passed\r\n\t  to the driver when the host has completed its process.\r\n\tParameter:\r\n\t\tNone\r\n\tReturns:\r\n\t  only if the above mentioned scenario is given, and a reduction\r\n\t  of output latency can be acheived by this mechanism, should\r\n\t  ASE_OK be returned. otherwise (and usually), ASE_NotPresent\r\n\t  should be returned in order to prevent further calls to this\r\n\t  function. note that the host may want to determine if it is\r\n\t  to use this when the system is not yet fully initialized, so\r\n\t  ASE_OK should always be returned if the mechanism makes sense.\t  \r\n\tNotes:\r\n\t  please remeber to adjust ASIOGetLatencies() according to\r\n\t  whether ASIOOutputReady() was ever called or not, if your\r\n\t  driver supports this scenario.\r\n\t  also note that the engine may fail to call ASIO_OutputReady()\r\n\t  in time in overload cases. as already mentioned, bufferSwitch\r\n      should be called for every block regardless of whether a block\r\n      could be processed in time.\r\n*/\r\n\r\n// restore old alignment\r\n#if defined(_MSC_VER) && !defined(__MWERKS__) \r\n#pragma pack(pop)\r\n#elif PRAGMA_ALIGN_SUPPORTED\r\n#pragma options align = reset\r\n#endif\r\n\r\n#endif\r\n\r\n"
  },
  {
    "path": "rtaudio/include/asiodrivers.cpp",
    "content": "#include <string.h>\r\n#include \"asiodrivers.h\"\r\n\r\nAsioDrivers* asioDrivers = 0;\r\n\r\nbool loadAsioDriver(char *name);\r\n\r\nbool loadAsioDriver(char *name)\r\n{\r\n\tif(!asioDrivers)\r\n\t\tasioDrivers = new AsioDrivers();\r\n\tif(asioDrivers)\r\n\t\treturn asioDrivers->loadDriver(name);\r\n\treturn false;\r\n}\r\n\r\n//------------------------------------------------------------------------------------\r\n\r\n#if MAC\r\n\r\nbool resolveASIO(unsigned long aconnID);\r\n\r\nAsioDrivers::AsioDrivers() : CodeFragments(\"ASIO Drivers\", 'AsDr', 'Asio')\r\n{\r\n\tconnID = -1;\r\n\tcurIndex = -1;\r\n}\r\n\r\nAsioDrivers::~AsioDrivers()\r\n{\r\n\tremoveCurrentDriver();\r\n}\r\n\r\nbool AsioDrivers::getCurrentDriverName(char *name)\r\n{\r\n\tif(curIndex >= 0)\r\n\t\treturn getName(curIndex, name);\r\n\treturn false;\r\n}\r\n\r\nlong AsioDrivers::getDriverNames(char **names, long maxDrivers)\r\n{\r\n\tfor(long i = 0; i < getNumFragments() && i < maxDrivers; i++)\r\n\t\tgetName(i, names[i]);\r\n\treturn getNumFragments() < maxDrivers ? getNumFragments() : maxDrivers;\r\n}\r\n\r\nbool AsioDrivers::loadDriver(char *name)\r\n{\r\n\tchar dname[64];\r\n\tunsigned long newID;\r\n\r\n\tfor(long i = 0; i < getNumFragments(); i++)\r\n\t{\r\n\t\tif(getName(i, dname) && !strcmp(name, dname))\r\n\t\t{\r\n\t\t\tif(newInstance(i, &newID))\r\n\t\t\t{\r\n\t\t\t\tif(resolveASIO(newID))\r\n\t\t\t\t{\r\n\t\t\t\t\tif(connID != -1)\r\n\t\t\t\t\t\tremoveInstance(curIndex, connID);\r\n\t\t\t\t\tcurIndex = i;\r\n\t\t\t\t\tconnID = newID;\r\n\t\t\t\t\treturn true;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nvoid AsioDrivers::removeCurrentDriver()\r\n{\r\n\tif(connID != -1)\r\n\t\tremoveInstance(curIndex, connID);\r\n\tconnID = -1;\r\n\tcurIndex = -1;\r\n}\r\n\r\n//------------------------------------------------------------------------------------\r\n\r\n#elif WINDOWS\r\n\r\n#include \"iasiodrv.h\"\r\n\r\nextern IASIO* theAsioDriver;\r\n\r\nAsioDrivers::AsioDrivers() : AsioDriverList()\r\n{\r\n\tcurIndex = -1;\r\n}\r\n\r\nAsioDrivers::~AsioDrivers()\r\n{\r\n}\r\n\r\nbool AsioDrivers::getCurrentDriverName(char *name)\r\n{\r\n\tif(curIndex >= 0)\r\n\t\treturn asioGetDriverName(curIndex, name, 32) == 0 ? true : false;\r\n\tname[0] = 0;\r\n\treturn false;\r\n}\r\n\r\nlong AsioDrivers::getDriverNames(char **names, long maxDrivers)\r\n{\r\n\tfor(long i = 0; i < asioGetNumDev() && i < maxDrivers; i++)\r\n\t\tasioGetDriverName(i, names[i], 32);\r\n\treturn asioGetNumDev() < maxDrivers ? asioGetNumDev() : maxDrivers;\r\n}\r\n\r\nbool AsioDrivers::loadDriver(char *name)\r\n{\r\n\tchar dname[64];\r\n\tchar curName[64];\r\n\r\n\tfor(long i = 0; i < asioGetNumDev(); i++)\r\n\t{\r\n\t\tif(!asioGetDriverName(i, dname, 32) && !strcmp(name, dname))\r\n\t\t{\r\n\t\t\tcurName[0] = 0;\r\n\t\t\tgetCurrentDriverName(curName);\t// in case we fail...\r\n\t\t\tremoveCurrentDriver();\r\n\r\n\t\t\tif(!asioOpenDriver(i, (void **)&theAsioDriver))\r\n\t\t\t{\r\n\t\t\t\tcurIndex = i;\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\ttheAsioDriver = 0;\r\n\t\t\t\tif(curName[0] && strcmp(dname, curName))\r\n\t\t\t\t\tloadDriver(curName);\t// try restore\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nvoid AsioDrivers::removeCurrentDriver()\r\n{\r\n\tif(curIndex != -1)\r\n\t\tasioCloseDriver(curIndex);\r\n\tcurIndex = -1;\r\n}\r\n\r\n#elif SGI || BEOS\r\n\r\n#include \"asiolist.h\"\r\n\r\nAsioDrivers::AsioDrivers() \r\n\t: AsioDriverList()\r\n{\r\n\tcurIndex = -1;\r\n}\r\n\r\nAsioDrivers::~AsioDrivers()\r\n{\r\n}\r\n\r\nbool AsioDrivers::getCurrentDriverName(char *name)\r\n{\r\n\treturn false;\r\n}\r\n\r\nlong AsioDrivers::getDriverNames(char **names, long maxDrivers)\r\n{\r\n\treturn 0;\r\n}\r\n\r\nbool AsioDrivers::loadDriver(char *name)\r\n{\r\n\treturn false;\r\n}\r\n\r\nvoid AsioDrivers::removeCurrentDriver()\r\n{\r\n}\r\n\r\n#else\r\n#error implement me\r\n#endif\r\n"
  },
  {
    "path": "rtaudio/include/asiodrivers.h",
    "content": "#ifndef __AsioDrivers__\r\n#define __AsioDrivers__\r\n\r\n#include \"ginclude.h\"\r\n\r\n#if MAC\r\n#include \"CodeFragments.hpp\"\r\n\r\nclass AsioDrivers : public CodeFragments\r\n\r\n#elif WINDOWS\r\n#include <windows.h>\r\n#include \"asiolist.h\"\r\n\r\nclass AsioDrivers : public AsioDriverList\r\n\r\n#elif SGI || BEOS\r\n#include \"asiolist.h\"\r\n\r\nclass AsioDrivers : public AsioDriverList\r\n\r\n#else\r\n#error implement me\r\n#endif\r\n\r\n{\r\npublic:\r\n\tAsioDrivers();\r\n\t~AsioDrivers();\r\n\t\r\n\tbool getCurrentDriverName(char *name);\r\n\tlong getDriverNames(char **names, long maxDrivers);\r\n\tbool loadDriver(char *name);\r\n\tvoid removeCurrentDriver();\r\n\tlong getCurrentDriverIndex() {return curIndex;}\r\nprotected:\r\n\tunsigned long connID;\r\n\tlong curIndex;\r\n};\r\n\r\n#endif\r\n"
  },
  {
    "path": "rtaudio/include/asiodrvr.h",
    "content": "/*\r\n\tSteinberg Audio Stream I/O API\r\n\t(c) 1996, Steinberg Soft- und Hardware GmbH\r\n\tcharlie (May 1996)\r\n\r\n\tasiodrvr.h\r\n\tc++ superclass to implement asio functionality. from this,\r\n\tyou can derive whatever required\r\n*/\r\n\r\n#ifndef _asiodrvr_\r\n#define _asiodrvr_\r\n\r\n// cpu and os system we are running on\r\n#include \"asiosys.h\"\r\n// basic \"C\" interface\r\n#include \"asio.h\"\r\n\r\nclass AsioDriver;\r\nextern AsioDriver *getDriver();\t\t// for generic constructor \r\n\r\n#if WINDOWS\r\n#include <windows.h>\r\n#include \"combase.h\"\r\n#include \"iasiodrv.h\"\r\nclass AsioDriver : public IASIO ,public CUnknown\r\n{\r\npublic:\r\n\tAsioDriver(LPUNKNOWN pUnk, HRESULT *phr);\r\n\r\n\tDECLARE_IUNKNOWN\r\n\t// Factory method\r\n\tstatic CUnknown *CreateInstance(LPUNKNOWN pUnk, HRESULT *phr);\r\n\t// IUnknown\r\n\tvirtual HRESULT STDMETHODCALLTYPE NonDelegatingQueryInterface(REFIID riid,void **ppvObject);\r\n\r\n#else\r\n\r\nclass AsioDriver\r\n{\r\npublic:\r\n\tAsioDriver();\r\n#endif\r\n\tvirtual ~AsioDriver();\r\n\r\n\tvirtual ASIOBool init(void* sysRef);\r\n\tvirtual void getDriverName(char *name);\t// max 32 bytes incl. terminating zero\r\n\tvirtual long getDriverVersion();\r\n\tvirtual void getErrorMessage(char *string);\t// max 124 bytes incl.\r\n\r\n\tvirtual ASIOError start();\r\n\tvirtual ASIOError stop();\r\n\r\n\tvirtual ASIOError getChannels(long *numInputChannels, long *numOutputChannels);\r\n\tvirtual ASIOError getLatencies(long *inputLatency, long *outputLatency);\r\n\tvirtual ASIOError getBufferSize(long *minSize, long *maxSize,\r\n\t\tlong *preferredSize, long *granularity);\r\n\r\n\tvirtual ASIOError canSampleRate(ASIOSampleRate sampleRate);\r\n\tvirtual ASIOError getSampleRate(ASIOSampleRate *sampleRate);\r\n\tvirtual ASIOError setSampleRate(ASIOSampleRate sampleRate);\r\n\tvirtual ASIOError getClockSources(ASIOClockSource *clocks, long *numSources);\r\n\tvirtual ASIOError setClockSource(long reference);\r\n\r\n\tvirtual ASIOError getSamplePosition(ASIOSamples *sPos, ASIOTimeStamp *tStamp);\r\n\tvirtual ASIOError getChannelInfo(ASIOChannelInfo *info);\r\n\r\n\tvirtual ASIOError createBuffers(ASIOBufferInfo *bufferInfos, long numChannels,\r\n\t\tlong bufferSize, ASIOCallbacks *callbacks);\r\n\tvirtual ASIOError disposeBuffers();\r\n\r\n\tvirtual ASIOError controlPanel();\r\n\tvirtual ASIOError future(long selector, void *opt);\r\n\tvirtual ASIOError outputReady();\r\n};\r\n#endif\r\n"
  },
  {
    "path": "rtaudio/include/asiolist.cpp",
    "content": "#include <windows.h>\n#include \"iasiodrv.h\"\n#include \"asiolist.h\"\n\n#define ASIODRV_DESC\t\t\"description\"\n#define INPROC_SERVER\t\t\"InprocServer32\"\n#define ASIO_PATH\t\t\t\"software\\\\asio\"\n#define COM_CLSID\t\t\t\"clsid\"\n\n// ******************************************************************\n// Local Functions \n// ******************************************************************\nstatic LONG findDrvPath (char *clsidstr,char *dllpath,int dllpathsize)\n{\n\tHKEY\t\t\thkEnum,hksub,hkpath;\n\tchar\t\t\tdatabuf[512];\n\tLONG \t\t\tcr,rc = -1;\n\tDWORD\t\t\tdatatype,datasize;\n\tDWORD\t\t\tindex;\n\tOFSTRUCT\t\tofs;\n\tHFILE\t\t\thfile;\n\tBOOL\t\t\tfound = FALSE;\n\n#ifdef UNICODE\n\tCharLowerBuffA(clsidstr,strlen(clsidstr));\n\tif ((cr = RegOpenKeyA(HKEY_CLASSES_ROOT,COM_CLSID,&hkEnum)) == ERROR_SUCCESS) {\n\n\t\tindex = 0;\n\t\twhile (cr == ERROR_SUCCESS && !found) {\n\t\t\tcr = RegEnumKeyA(hkEnum,index++,databuf,512);\n\t\t\tif (cr == ERROR_SUCCESS) {\n\t\t\t\tCharLowerBuffA(databuf,strlen(databuf));\n\t\t\t\tif (!(strcmp(databuf,clsidstr))) {\n\t\t\t\t\tif ((cr = RegOpenKeyExA(hkEnum,databuf,0,KEY_READ,&hksub)) == ERROR_SUCCESS) {\n\t\t\t\t\t\tif ((cr = RegOpenKeyExA(hksub,INPROC_SERVER,0,KEY_READ,&hkpath)) == ERROR_SUCCESS) {\n\t\t\t\t\t\t\tdatatype = REG_SZ; datasize = (DWORD)dllpathsize;\n\t\t\t\t\t\t\tcr = RegQueryValueEx(hkpath,0,0,&datatype,(LPBYTE)dllpath,&datasize);\n\t\t\t\t\t\t\tif (cr == ERROR_SUCCESS) {\n\t\t\t\t\t\t\t\tmemset(&ofs,0,sizeof(OFSTRUCT));\n\t\t\t\t\t\t\t\tofs.cBytes = sizeof(OFSTRUCT); \n\t\t\t\t\t\t\t\thfile = OpenFile(dllpath,&ofs,OF_EXIST);\n\t\t\t\t\t\t\t\tif (hfile) rc = 0; \n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tRegCloseKey(hkpath);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tRegCloseKey(hksub);\n\t\t\t\t\t}\n\t\t\t\t\tfound = TRUE;\t// break out \n\t\t\t\t}\n\t\t\t}\n\t\t}\t\t\t\t\n\t\tRegCloseKey(hkEnum);\n\t}\n#else\n\tCharLowerBuff(clsidstr,strlen(clsidstr));\n\tif ((cr = RegOpenKey(HKEY_CLASSES_ROOT,COM_CLSID,&hkEnum)) == ERROR_SUCCESS) {\n\n\t\tindex = 0;\n\t\twhile (cr == ERROR_SUCCESS && !found) {\n\t\t\tcr = RegEnumKey(hkEnum,index++,databuf,512);\n\t\t\tif (cr == ERROR_SUCCESS) {\n\t\t\t\tCharLowerBuff(databuf,strlen(databuf));\n\t\t\t\tif (!(strcmp(databuf,clsidstr))) {\n\t\t\t\t\tif ((cr = RegOpenKeyEx(hkEnum,databuf,0,KEY_READ,&hksub)) == ERROR_SUCCESS) {\n\t\t\t\t\t\tif ((cr = RegOpenKeyEx(hksub,INPROC_SERVER,0,KEY_READ,&hkpath)) == ERROR_SUCCESS) {\n\t\t\t\t\t\t\tdatatype = REG_SZ; datasize = (DWORD)dllpathsize;\n\t\t\t\t\t\t\tcr = RegQueryValueEx(hkpath,0,0,&datatype,(LPBYTE)dllpath,&datasize);\n\t\t\t\t\t\t\tif (cr == ERROR_SUCCESS) {\n\t\t\t\t\t\t\t\tmemset(&ofs,0,sizeof(OFSTRUCT));\n\t\t\t\t\t\t\t\tofs.cBytes = sizeof(OFSTRUCT); \n\t\t\t\t\t\t\t\thfile = OpenFile(dllpath,&ofs,OF_EXIST);\n\t\t\t\t\t\t\t\tif (hfile) rc = 0; \n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tRegCloseKey(hkpath);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tRegCloseKey(hksub);\n\t\t\t\t\t}\n\t\t\t\t\tfound = TRUE;\t// break out \n\t\t\t\t}\n\t\t\t}\n\t\t}\t\t\t\t\n\t\tRegCloseKey(hkEnum);\n\t}\n#endif\n\treturn rc;\n}\n\n\nstatic LPASIODRVSTRUCT newDrvStruct (HKEY hkey,char *keyname,int drvID,LPASIODRVSTRUCT lpdrv)\n{\n\tHKEY\thksub;\n\tchar\tdatabuf[256];\n\tchar\tdllpath[MAXPATHLEN];\n\tWORD\twData[100];\n\tCLSID\tclsid;\n\tDWORD\tdatatype,datasize;\n\tLONG\tcr,rc;\n\n\tif (!lpdrv) {\n\t\tif ((cr = RegOpenKeyExA(hkey,keyname,0,KEY_READ,&hksub)) == ERROR_SUCCESS) {\n\n\t\t\tdatatype = REG_SZ; datasize = 256;\n\t\t\tcr = RegQueryValueExA(hksub,COM_CLSID,0,&datatype,(LPBYTE)databuf,&datasize);\n\t\t\tif (cr == ERROR_SUCCESS) {\n\t\t\t\trc = findDrvPath (databuf,dllpath,MAXPATHLEN);\n\t\t\t\tif (rc == 0) {\n\t\t\t\t\tlpdrv = new ASIODRVSTRUCT[1];\n\t\t\t\t\tif (lpdrv) {\n\t\t\t\t\t\tmemset(lpdrv,0,sizeof(ASIODRVSTRUCT));\n\t\t\t\t\t\tlpdrv->drvID = drvID;\n\t\t\t\t\t\tMultiByteToWideChar(CP_ACP,0,(LPCSTR)databuf,-1,(LPWSTR)wData,100);\n\t\t\t\t\t\tif ((cr = CLSIDFromString((LPOLESTR)wData,(LPCLSID)&clsid)) == S_OK) {\n\t\t\t\t\t\t\tmemcpy(&lpdrv->clsid,&clsid,sizeof(CLSID));\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tdatatype = REG_SZ; datasize = 256;\n\t\t\t\t\t\tcr = RegQueryValueExA(hksub,ASIODRV_DESC,0,&datatype,(LPBYTE)databuf,&datasize);\n\t\t\t\t\t\tif (cr == ERROR_SUCCESS) {\n\t\t\t\t\t\t\tstrcpy(lpdrv->drvname,databuf);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse strcpy(lpdrv->drvname,keyname);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tRegCloseKey(hksub);\n\t\t}\n\t}\t\n\telse lpdrv->next = newDrvStruct(hkey,keyname,drvID+1,lpdrv->next);\n\n\treturn lpdrv;\n}\n\nstatic void deleteDrvStruct (LPASIODRVSTRUCT lpdrv)\n{\n\tIASIO\t*iasio;\n\n\tif (lpdrv != 0) {\n\t\tdeleteDrvStruct(lpdrv->next);\n\t\tif (lpdrv->asiodrv) {\n\t\t\tiasio = (IASIO *)lpdrv->asiodrv;\n\t\t\tiasio->Release();\n\t\t}\n\t\tdelete lpdrv;\n\t}\n}\n\n\nstatic LPASIODRVSTRUCT getDrvStruct (int drvID,LPASIODRVSTRUCT lpdrv)\n{\n\twhile (lpdrv) {\n\t\tif (lpdrv->drvID == drvID) return lpdrv;\n\t\tlpdrv = lpdrv->next;\n\t}\n\treturn 0;\n}\n// ******************************************************************\n\n\n// ******************************************************************\n//\tAsioDriverList\n// ******************************************************************\nAsioDriverList::AsioDriverList ()\n{\n\tHKEY\t\t\thkEnum = 0;\n\tchar\t\t\tkeyname[MAXDRVNAMELEN];\n\tLPASIODRVSTRUCT\tpdl;\n\tLONG \t\t\tcr;\n\tDWORD\t\t\tindex = 0;\n\tBOOL\t\t\tfin = FALSE;\n\n\tnumdrv\t\t= 0;\n\tlpdrvlist\t= 0;\n\n#ifdef UNICODE\n\tcr = RegOpenKeyA(HKEY_LOCAL_MACHINE,ASIO_PATH,&hkEnum);\n#else\n\tcr = RegOpenKey(HKEY_LOCAL_MACHINE,ASIO_PATH,&hkEnum);\n#endif\n\twhile (cr == ERROR_SUCCESS) {\n#ifdef UNICODE\n\t\tif ((cr = RegEnumKeyA(hkEnum,index++,keyname,MAXDRVNAMELEN))== ERROR_SUCCESS) {\n#else\n\t\tif ((cr = RegEnumKey(hkEnum,index++,keyname,MAXDRVNAMELEN))== ERROR_SUCCESS) {\n#endif\n\t\t\tlpdrvlist = newDrvStruct (hkEnum,keyname,0,lpdrvlist);\n\t\t}\n\t\telse fin = TRUE;\n\t}\n\tif (hkEnum) RegCloseKey(hkEnum);\n\n\tpdl = lpdrvlist;\n\twhile (pdl) {\n\t\tnumdrv++;\n\t\tpdl = pdl->next;\n\t}\n\n\tif (numdrv) CoInitialize(0);\t// initialize COM\n}\n\nAsioDriverList::~AsioDriverList ()\n{\n\tif (numdrv) {\n\t\tdeleteDrvStruct(lpdrvlist);\n\t\tCoUninitialize();\n\t}\n}\n\n\nLONG AsioDriverList::asioGetNumDev (VOID)\n{\n\treturn (LONG)numdrv;\n}\n\n\nLONG AsioDriverList::asioOpenDriver (int drvID,LPVOID *asiodrv)\n{\n\tLPASIODRVSTRUCT\tlpdrv = 0;\n\tlong\t\t\trc;\n\n\tif (!asiodrv) return DRVERR_INVALID_PARAM;\n\n\tif ((lpdrv = getDrvStruct(drvID,lpdrvlist)) != 0) {\n\t\tif (!lpdrv->asiodrv) {\n\t\t\trc = CoCreateInstance(lpdrv->clsid,0,CLSCTX_INPROC_SERVER,lpdrv->clsid,asiodrv);\n\t\t\tif (rc == S_OK) {\n\t\t\t\tlpdrv->asiodrv = *asiodrv;\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t\t// else if (rc == REGDB_E_CLASSNOTREG)\n\t\t\t//\tstrcpy (info->messageText, \"Driver not registered in the Registration Database!\");\n\t\t}\n\t\telse rc = DRVERR_DEVICE_ALREADY_OPEN;\n\t}\n\telse rc = DRVERR_DEVICE_NOT_FOUND;\n\t\n\treturn rc;\n}\n\n\nLONG AsioDriverList::asioCloseDriver (int drvID)\n{\n\tLPASIODRVSTRUCT\tlpdrv = 0;\n\tIASIO\t\t\t*iasio;\n\n\tif ((lpdrv = getDrvStruct(drvID,lpdrvlist)) != 0) {\n\t\tif (lpdrv->asiodrv) {\n\t\t\tiasio = (IASIO *)lpdrv->asiodrv;\n\t\t\tiasio->Release();\n\t\t\tlpdrv->asiodrv = 0;\n\t\t}\n\t}\n\n\treturn 0;\n}\n\nLONG AsioDriverList::asioGetDriverName (int drvID,char *drvname,int drvnamesize)\n{\t\n\tLPASIODRVSTRUCT\t\t\tlpdrv = 0;\n\n\tif (!drvname) return DRVERR_INVALID_PARAM;\n\n\tif ((lpdrv = getDrvStruct(drvID,lpdrvlist)) != 0) {\n\t\tif (strlen(lpdrv->drvname) < (unsigned int)drvnamesize) {\n\t\t\tstrcpy(drvname,lpdrv->drvname);\n\t\t}\n\t\telse {\n\t\t\tmemcpy(drvname,lpdrv->drvname,drvnamesize-4);\n\t\t\tdrvname[drvnamesize-4] = '.';\n\t\t\tdrvname[drvnamesize-3] = '.';\n\t\t\tdrvname[drvnamesize-2] = '.';\n\t\t\tdrvname[drvnamesize-1] = 0;\n\t\t}\n\t\treturn 0;\n\t}\n\treturn DRVERR_DEVICE_NOT_FOUND;\n}\n\nLONG AsioDriverList::asioGetDriverPath (int drvID,char *dllpath,int dllpathsize)\n{\n\tLPASIODRVSTRUCT\t\t\tlpdrv = 0;\n\n\tif (!dllpath) return DRVERR_INVALID_PARAM;\n\n\tif ((lpdrv = getDrvStruct(drvID,lpdrvlist)) != 0) {\n\t\tif (strlen(lpdrv->dllpath) < (unsigned int)dllpathsize) {\n\t\t\tstrcpy(dllpath,lpdrv->dllpath);\n\t\t\treturn 0;\n\t\t}\n\t\tdllpath[0] = 0;\n\t\treturn DRVERR_INVALID_PARAM;\n\t}\n\treturn DRVERR_DEVICE_NOT_FOUND;\n}\n\nLONG AsioDriverList::asioGetDriverCLSID (int drvID,CLSID *clsid)\n{\n\tLPASIODRVSTRUCT\t\t\tlpdrv = 0;\n\n\tif (!clsid) return DRVERR_INVALID_PARAM;\n\n\tif ((lpdrv = getDrvStruct(drvID,lpdrvlist)) != 0) {\n\t\tmemcpy(clsid,&lpdrv->clsid,sizeof(CLSID));\n\t\treturn 0;\n\t}\n\treturn DRVERR_DEVICE_NOT_FOUND;\n}\n\n\n"
  },
  {
    "path": "rtaudio/include/asiolist.h",
    "content": "#ifndef __asiolist__\r\n#define __asiolist__\r\n\r\n#define DRVERR\t\t\t-5000\r\n#define DRVERR_INVALID_PARAM\t\tDRVERR-1\r\n#define DRVERR_DEVICE_ALREADY_OPEN\tDRVERR-2\r\n#define DRVERR_DEVICE_NOT_FOUND\t\tDRVERR-3\r\n\r\n#define MAXPATHLEN\t\t\t512\r\n#define MAXDRVNAMELEN\t\t128\r\n\r\nstruct asiodrvstruct\r\n{\r\n\tint\t\t\t\t\t\tdrvID;\r\n\tCLSID\t\t\t\t\tclsid;\r\n\tchar\t\t\t\t\tdllpath[MAXPATHLEN];\r\n\tchar\t\t\t\t\tdrvname[MAXDRVNAMELEN];\r\n\tLPVOID\t\t\t\t\tasiodrv;\r\n\tstruct asiodrvstruct\t*next;\r\n};\r\n\r\ntypedef struct asiodrvstruct ASIODRVSTRUCT;\r\ntypedef ASIODRVSTRUCT\t*LPASIODRVSTRUCT;\r\n\r\nclass AsioDriverList {\r\npublic:\r\n\tAsioDriverList();\r\n\t~AsioDriverList();\r\n\t\r\n\tLONG asioOpenDriver (int,VOID **);\r\n\tLONG asioCloseDriver (int);\r\n\r\n\t// nice to have\r\n\tLONG asioGetNumDev (VOID);\r\n\tLONG asioGetDriverName (int,char *,int);\t\t\r\n\tLONG asioGetDriverPath (int,char *,int);\r\n\tLONG asioGetDriverCLSID (int,CLSID *);\r\n\r\n\t// or use directly access\r\n\tLPASIODRVSTRUCT\tlpdrvlist;\r\n\tint\t\t\t\tnumdrv;\r\n};\r\n\r\ntypedef class AsioDriverList *LPASIODRIVERLIST;\r\n\r\n#endif\r\n"
  },
  {
    "path": "rtaudio/include/asiosys.h",
    "content": "#ifndef __asiosys__\r\n\t#define __asiosys__\r\n\r\n\t#ifdef WIN32\r\n\t\t#undef MAC \r\n\t\t#define PPC 0\r\n\t\t#define WINDOWS 1\r\n\t\t#define SGI 0\r\n\t\t#define SUN 0\r\n\t\t#define LINUX 0\r\n\t\t#define BEOS 0\r\n\r\n\t\t#define NATIVE_INT64 0\r\n\t\t#define IEEE754_64FLOAT 1\r\n\t\r\n\t#elif BEOS\r\n\t\t#define MAC 0\r\n\t\t#define PPC 0\r\n\t\t#define WINDOWS 0\r\n\t\t#define PC 0\r\n\t\t#define SGI 0\r\n\t\t#define SUN 0\r\n\t\t#define LINUX 0\r\n\t\t\r\n\t\t#define NATIVE_INT64 0\r\n\t\t#define IEEE754_64FLOAT 1\r\n\t\t\r\n\t\t#ifndef DEBUG\r\n\t\t\t#define DEBUG 0\r\n\t\t \t#if DEBUG\r\n\t\t \t\tvoid DEBUGGERMESSAGE(char *string);\r\n\t\t \t#else\r\n\t\t  \t\t#define DEBUGGERMESSAGE(a)\r\n\t\t\t#endif\r\n\t\t#endif\r\n\r\n\t#elif SGI\r\n\t\t#define MAC 0\r\n\t\t#define PPC 0\r\n\t\t#define WINDOWS 0\r\n\t\t#define PC 0\r\n\t\t#define SUN 0\r\n\t\t#define LINUX 0\r\n\t\t#define BEOS 0\r\n\t\t\r\n\t\t#define NATIVE_INT64 0\r\n\t\t#define IEEE754_64FLOAT 1\r\n\t\t\r\n\t\t#ifndef DEBUG\r\n\t\t\t#define DEBUG 0\r\n\t\t \t#if DEBUG\r\n\t\t \t\tvoid DEBUGGERMESSAGE(char *string);\r\n\t\t \t#else\r\n\t\t  \t\t#define DEBUGGERMESSAGE(a)\r\n\t\t\t#endif\r\n\t\t#endif\r\n\r\n\t#else\t// MAC\r\n\r\n\t\t#define MAC 1\r\n\t\t#define PPC 1\r\n\t\t#define WINDOWS 0\r\n\t\t#define PC 0\r\n\t\t#define SGI 0\r\n\t\t#define SUN 0\r\n\t\t#define LINUX 0\r\n\t\t#define BEOS 0\r\n\r\n\t\t#define NATIVE_INT64 0\r\n\t\t#define IEEE754_64FLOAT 1\r\n\r\n\t\t#ifndef DEBUG\r\n\t\t\t#define DEBUG 0\r\n\t\t\t#if DEBUG\r\n\t\t\t\tvoid DEBUGGERMESSAGE(char *string);\r\n\t\t\t#else\r\n\t\t\t\t#define DEBUGGERMESSAGE(a)\r\n\t\t\t#endif\r\n\t\t#endif\r\n\t#endif\r\n\r\n#endif\r\n"
  },
  {
    "path": "rtaudio/include/dsound.h",
    "content": "/*==========================================================================;\n *\n *  Copyright (c) Microsoft Corporation.  All rights reserved.\n *\n *  File:       dsound.h\n *  Content:    DirectSound include file\n *\n **************************************************************************/\n\n#define COM_NO_WINDOWS_H\n#include <objbase.h>\n#include <float.h>\n\n#ifndef DIRECTSOUND_VERSION\n#define DIRECTSOUND_VERSION 0x0900  /* Version 9.0 */\n#endif\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif // __cplusplus\n\n#ifndef __DSOUND_INCLUDED__\n#define __DSOUND_INCLUDED__\n\n/* Type definitions shared with Direct3D */\n\n#ifndef DX_SHARED_DEFINES\n\ntypedef float D3DVALUE, *LPD3DVALUE;\n\n#ifndef D3DCOLOR_DEFINED\ntypedef DWORD D3DCOLOR;\n#define D3DCOLOR_DEFINED\n#endif\n\n#ifndef LPD3DCOLOR_DEFINED\ntypedef DWORD *LPD3DCOLOR;\n#define LPD3DCOLOR_DEFINED\n#endif\n\n#ifndef D3DVECTOR_DEFINED\ntypedef struct _D3DVECTOR {\n    float x;\n    float y;\n    float z;\n} D3DVECTOR;\n#define D3DVECTOR_DEFINED\n#endif\n\n#ifndef LPD3DVECTOR_DEFINED\ntypedef D3DVECTOR *LPD3DVECTOR;\n#define LPD3DVECTOR_DEFINED\n#endif\n\n#define DX_SHARED_DEFINES\n#endif // DX_SHARED_DEFINES\n\n#define _FACDS  0x878   /* DirectSound's facility code */\n#define MAKE_DSHRESULT(code)  MAKE_HRESULT(1, _FACDS, code)\n\n// DirectSound Component GUID {47D4D946-62E8-11CF-93BC-444553540000}\nDEFINE_GUID(CLSID_DirectSound, 0x47d4d946, 0x62e8, 0x11cf, 0x93, 0xbc, 0x44, 0x45, 0x53, 0x54, 0x0, 0x0);\n\n// DirectSound 8.0 Component GUID {3901CC3F-84B5-4FA4-BA35-AA8172B8A09B}\nDEFINE_GUID(CLSID_DirectSound8, 0x3901cc3f, 0x84b5, 0x4fa4, 0xba, 0x35, 0xaa, 0x81, 0x72, 0xb8, 0xa0, 0x9b);\n\n// DirectSound Capture Component GUID {B0210780-89CD-11D0-AF08-00A0C925CD16}\nDEFINE_GUID(CLSID_DirectSoundCapture, 0xb0210780, 0x89cd, 0x11d0, 0xaf, 0x8, 0x0, 0xa0, 0xc9, 0x25, 0xcd, 0x16);\n\n// DirectSound 8.0 Capture Component GUID {E4BCAC13-7F99-4908-9A8E-74E3BF24B6E1}\nDEFINE_GUID(CLSID_DirectSoundCapture8, 0xe4bcac13, 0x7f99, 0x4908, 0x9a, 0x8e, 0x74, 0xe3, 0xbf, 0x24, 0xb6, 0xe1);\n\n// DirectSound Full Duplex Component GUID {FEA4300C-7959-4147-B26A-2377B9E7A91D}\nDEFINE_GUID(CLSID_DirectSoundFullDuplex, 0xfea4300c, 0x7959, 0x4147, 0xb2, 0x6a, 0x23, 0x77, 0xb9, 0xe7, 0xa9, 0x1d);\n\n\n// DirectSound default playback device GUID {DEF00000-9C6D-47ED-AAF1-4DDA8F2B5C03}\nDEFINE_GUID(DSDEVID_DefaultPlayback, 0xdef00000, 0x9c6d, 0x47ed, 0xaa, 0xf1, 0x4d, 0xda, 0x8f, 0x2b, 0x5c, 0x03);\n\n// DirectSound default capture device GUID {DEF00001-9C6D-47ED-AAF1-4DDA8F2B5C03}\nDEFINE_GUID(DSDEVID_DefaultCapture, 0xdef00001, 0x9c6d, 0x47ed, 0xaa, 0xf1, 0x4d, 0xda, 0x8f, 0x2b, 0x5c, 0x03);\n\n// DirectSound default device for voice playback {DEF00002-9C6D-47ED-AAF1-4DDA8F2B5C03}\nDEFINE_GUID(DSDEVID_DefaultVoicePlayback, 0xdef00002, 0x9c6d, 0x47ed, 0xaa, 0xf1, 0x4d, 0xda, 0x8f, 0x2b, 0x5c, 0x03);\n\n// DirectSound default device for voice capture {DEF00003-9C6D-47ED-AAF1-4DDA8F2B5C03}\nDEFINE_GUID(DSDEVID_DefaultVoiceCapture, 0xdef00003, 0x9c6d, 0x47ed, 0xaa, 0xf1, 0x4d, 0xda, 0x8f, 0x2b, 0x5c, 0x03);\n\n\n//\n// Forward declarations for interfaces.\n// 'struct' not 'class' per the way DECLARE_INTERFACE_ is defined\n//\n\n#ifdef __cplusplus\nstruct IDirectSound;\nstruct IDirectSoundBuffer;\nstruct IDirectSound3DListener;\nstruct IDirectSound3DBuffer;\nstruct IDirectSoundCapture;\nstruct IDirectSoundCaptureBuffer;\nstruct IDirectSoundNotify;\n#endif // __cplusplus\n\n\n//\n// DirectSound 8.0 interfaces.\n//\n\n#if DIRECTSOUND_VERSION >= 0x0800\n\n#ifdef __cplusplus\nstruct IDirectSound8;\nstruct IDirectSoundBuffer8;\nstruct IDirectSoundCaptureBuffer8;\nstruct IDirectSoundFXGargle;\nstruct IDirectSoundFXChorus;\nstruct IDirectSoundFXFlanger;\nstruct IDirectSoundFXEcho;\nstruct IDirectSoundFXDistortion;\nstruct IDirectSoundFXCompressor;\nstruct IDirectSoundFXParamEq;\nstruct IDirectSoundFXWavesReverb;\nstruct IDirectSoundFXI3DL2Reverb;\nstruct IDirectSoundCaptureFXAec;\nstruct IDirectSoundCaptureFXNoiseSuppress;\nstruct IDirectSoundFullDuplex;\n#endif // __cplusplus\n\n// IDirectSound8, IDirectSoundBuffer8 and IDirectSoundCaptureBuffer8 are the\n// only DirectSound 7.0 interfaces with changed functionality in version 8.0.\n// The other level 8 interfaces as equivalent to their level 7 counterparts:\n\n#define IDirectSoundCapture8            IDirectSoundCapture\n#define IDirectSound3DListener8         IDirectSound3DListener\n#define IDirectSound3DBuffer8           IDirectSound3DBuffer\n#define IDirectSoundNotify8             IDirectSoundNotify\n#define IDirectSoundFXGargle8           IDirectSoundFXGargle\n#define IDirectSoundFXChorus8           IDirectSoundFXChorus\n#define IDirectSoundFXFlanger8          IDirectSoundFXFlanger\n#define IDirectSoundFXEcho8             IDirectSoundFXEcho\n#define IDirectSoundFXDistortion8       IDirectSoundFXDistortion\n#define IDirectSoundFXCompressor8       IDirectSoundFXCompressor\n#define IDirectSoundFXParamEq8          IDirectSoundFXParamEq\n#define IDirectSoundFXWavesReverb8      IDirectSoundFXWavesReverb\n#define IDirectSoundFXI3DL2Reverb8      IDirectSoundFXI3DL2Reverb\n#define IDirectSoundCaptureFXAec8       IDirectSoundCaptureFXAec\n#define IDirectSoundCaptureFXNoiseSuppress8 IDirectSoundCaptureFXNoiseSuppress\n#define IDirectSoundFullDuplex8         IDirectSoundFullDuplex\n\n#endif // DIRECTSOUND_VERSION >= 0x0800\n\ntypedef struct IDirectSound                 *LPDIRECTSOUND;\ntypedef struct IDirectSoundBuffer           *LPDIRECTSOUNDBUFFER;\ntypedef struct IDirectSound3DListener       *LPDIRECTSOUND3DLISTENER;\ntypedef struct IDirectSound3DBuffer         *LPDIRECTSOUND3DBUFFER;\ntypedef struct IDirectSoundCapture          *LPDIRECTSOUNDCAPTURE;\ntypedef struct IDirectSoundCaptureBuffer    *LPDIRECTSOUNDCAPTUREBUFFER;\ntypedef struct IDirectSoundNotify           *LPDIRECTSOUNDNOTIFY;\n\n\n#if DIRECTSOUND_VERSION >= 0x0800\n\ntypedef struct IDirectSoundFXGargle         *LPDIRECTSOUNDFXGARGLE;\ntypedef struct IDirectSoundFXChorus         *LPDIRECTSOUNDFXCHORUS;\ntypedef struct IDirectSoundFXFlanger        *LPDIRECTSOUNDFXFLANGER;\ntypedef struct IDirectSoundFXEcho           *LPDIRECTSOUNDFXECHO;\ntypedef struct IDirectSoundFXDistortion     *LPDIRECTSOUNDFXDISTORTION;\ntypedef struct IDirectSoundFXCompressor     *LPDIRECTSOUNDFXCOMPRESSOR;\ntypedef struct IDirectSoundFXParamEq        *LPDIRECTSOUNDFXPARAMEQ;\ntypedef struct IDirectSoundFXWavesReverb    *LPDIRECTSOUNDFXWAVESREVERB;\ntypedef struct IDirectSoundFXI3DL2Reverb    *LPDIRECTSOUNDFXI3DL2REVERB;\ntypedef struct IDirectSoundCaptureFXAec     *LPDIRECTSOUNDCAPTUREFXAEC;\ntypedef struct IDirectSoundCaptureFXNoiseSuppress *LPDIRECTSOUNDCAPTUREFXNOISESUPPRESS;\ntypedef struct IDirectSoundFullDuplex       *LPDIRECTSOUNDFULLDUPLEX;\n\ntypedef struct IDirectSound8                *LPDIRECTSOUND8;\ntypedef struct IDirectSoundBuffer8          *LPDIRECTSOUNDBUFFER8;\ntypedef struct IDirectSound3DListener8      *LPDIRECTSOUND3DLISTENER8;\ntypedef struct IDirectSound3DBuffer8        *LPDIRECTSOUND3DBUFFER8;\ntypedef struct IDirectSoundCapture8         *LPDIRECTSOUNDCAPTURE8;\ntypedef struct IDirectSoundCaptureBuffer8   *LPDIRECTSOUNDCAPTUREBUFFER8;\ntypedef struct IDirectSoundNotify8          *LPDIRECTSOUNDNOTIFY8;\ntypedef struct IDirectSoundFXGargle8        *LPDIRECTSOUNDFXGARGLE8;\ntypedef struct IDirectSoundFXChorus8        *LPDIRECTSOUNDFXCHORUS8;\ntypedef struct IDirectSoundFXFlanger8       *LPDIRECTSOUNDFXFLANGER8;\ntypedef struct IDirectSoundFXEcho8          *LPDIRECTSOUNDFXECHO8;\ntypedef struct IDirectSoundFXDistortion8    *LPDIRECTSOUNDFXDISTORTION8;\ntypedef struct IDirectSoundFXCompressor8    *LPDIRECTSOUNDFXCOMPRESSOR8;\ntypedef struct IDirectSoundFXParamEq8       *LPDIRECTSOUNDFXPARAMEQ8;\ntypedef struct IDirectSoundFXWavesReverb8   *LPDIRECTSOUNDFXWAVESREVERB8;\ntypedef struct IDirectSoundFXI3DL2Reverb8   *LPDIRECTSOUNDFXI3DL2REVERB8;\ntypedef struct IDirectSoundCaptureFXAec8    *LPDIRECTSOUNDCAPTUREFXAEC8;\ntypedef struct IDirectSoundCaptureFXNoiseSuppress8 *LPDIRECTSOUNDCAPTUREFXNOISESUPPRESS8;\ntypedef struct IDirectSoundFullDuplex8      *LPDIRECTSOUNDFULLDUPLEX8;\n\n#endif // DIRECTSOUND_VERSION >= 0x0800\n\n//\n// IID definitions for the unchanged DirectSound 8.0 interfaces\n//\n\n#if DIRECTSOUND_VERSION >= 0x0800\n\n#define IID_IDirectSoundCapture8            IID_IDirectSoundCapture\n#define IID_IDirectSound3DListener8         IID_IDirectSound3DListener\n#define IID_IDirectSound3DBuffer8           IID_IDirectSound3DBuffer\n#define IID_IDirectSoundNotify8             IID_IDirectSoundNotify\n#define IID_IDirectSoundFXGargle8           IID_IDirectSoundFXGargle\n#define IID_IDirectSoundFXChorus8           IID_IDirectSoundFXChorus\n#define IID_IDirectSoundFXFlanger8          IID_IDirectSoundFXFlanger\n#define IID_IDirectSoundFXEcho8             IID_IDirectSoundFXEcho\n#define IID_IDirectSoundFXDistortion8       IID_IDirectSoundFXDistortion\n#define IID_IDirectSoundFXCompressor8       IID_IDirectSoundFXCompressor\n#define IID_IDirectSoundFXParamEq8          IID_IDirectSoundFXParamEq\n#define IID_IDirectSoundFXWavesReverb8      IID_IDirectSoundFXWavesReverb\n#define IID_IDirectSoundFXI3DL2Reverb8      IID_IDirectSoundFXI3DL2Reverb\n#define IID_IDirectSoundCaptureFXAec8       IID_IDirectSoundCaptureFXAec\n#define IID_IDirectSoundCaptureFXNoiseSuppress8 IID_IDirectSoundCaptureFXNoiseSuppress\n#define IID_IDirectSoundFullDuplex8         IID_IDirectSoundFullDuplex\n\n#endif // DIRECTSOUND_VERSION >= 0x0800\n\n//\n// Compatibility typedefs\n//\n\n#ifndef _LPCWAVEFORMATEX_DEFINED\n#define _LPCWAVEFORMATEX_DEFINED\ntypedef const WAVEFORMATEX *LPCWAVEFORMATEX;\n#endif // _LPCWAVEFORMATEX_DEFINED\n\n#ifndef __LPCGUID_DEFINED__\n#define __LPCGUID_DEFINED__\ntypedef const GUID *LPCGUID;\n#endif // __LPCGUID_DEFINED__\n\ntypedef LPDIRECTSOUND *LPLPDIRECTSOUND;\ntypedef LPDIRECTSOUNDBUFFER *LPLPDIRECTSOUNDBUFFER;\ntypedef LPDIRECTSOUND3DLISTENER *LPLPDIRECTSOUND3DLISTENER;\ntypedef LPDIRECTSOUND3DBUFFER *LPLPDIRECTSOUND3DBUFFER;\ntypedef LPDIRECTSOUNDCAPTURE *LPLPDIRECTSOUNDCAPTURE;\ntypedef LPDIRECTSOUNDCAPTUREBUFFER *LPLPDIRECTSOUNDCAPTUREBUFFER;\ntypedef LPDIRECTSOUNDNOTIFY *LPLPDIRECTSOUNDNOTIFY;\n\n#if DIRECTSOUND_VERSION >= 0x0800\ntypedef LPDIRECTSOUND8 *LPLPDIRECTSOUND8;\ntypedef LPDIRECTSOUNDBUFFER8 *LPLPDIRECTSOUNDBUFFER8;\ntypedef LPDIRECTSOUNDCAPTURE8 *LPLPDIRECTSOUNDCAPTURE8;\ntypedef LPDIRECTSOUNDCAPTUREBUFFER8 *LPLPDIRECTSOUNDCAPTUREBUFFER8;\n#endif // DIRECTSOUND_VERSION >= 0x0800\n\n//\n// Structures\n//\n\ntypedef struct _DSCAPS\n{\n    DWORD           dwSize;\n    DWORD           dwFlags;\n    DWORD           dwMinSecondarySampleRate;\n    DWORD           dwMaxSecondarySampleRate;\n    DWORD           dwPrimaryBuffers;\n    DWORD           dwMaxHwMixingAllBuffers;\n    DWORD           dwMaxHwMixingStaticBuffers;\n    DWORD           dwMaxHwMixingStreamingBuffers;\n    DWORD           dwFreeHwMixingAllBuffers;\n    DWORD           dwFreeHwMixingStaticBuffers;\n    DWORD           dwFreeHwMixingStreamingBuffers;\n    DWORD           dwMaxHw3DAllBuffers;\n    DWORD           dwMaxHw3DStaticBuffers;\n    DWORD           dwMaxHw3DStreamingBuffers;\n    DWORD           dwFreeHw3DAllBuffers;\n    DWORD           dwFreeHw3DStaticBuffers;\n    DWORD           dwFreeHw3DStreamingBuffers;\n    DWORD           dwTotalHwMemBytes;\n    DWORD           dwFreeHwMemBytes;\n    DWORD           dwMaxContigFreeHwMemBytes;\n    DWORD           dwUnlockTransferRateHwBuffers;\n    DWORD           dwPlayCpuOverheadSwBuffers;\n    DWORD           dwReserved1;\n    DWORD           dwReserved2;\n} DSCAPS, *LPDSCAPS;\n\ntypedef const DSCAPS *LPCDSCAPS;\n\ntypedef struct _DSBCAPS\n{\n    DWORD           dwSize;\n    DWORD           dwFlags;\n    DWORD           dwBufferBytes;\n    DWORD           dwUnlockTransferRate;\n    DWORD           dwPlayCpuOverhead;\n} DSBCAPS, *LPDSBCAPS;\n\ntypedef const DSBCAPS *LPCDSBCAPS;\n\n#if DIRECTSOUND_VERSION >= 0x0800\n\n    typedef struct _DSEFFECTDESC\n    {\n        DWORD       dwSize;\n        DWORD       dwFlags;\n        GUID        guidDSFXClass;\n        DWORD_PTR   dwReserved1;\n        DWORD_PTR   dwReserved2;\n    } DSEFFECTDESC, *LPDSEFFECTDESC;\n    typedef const DSEFFECTDESC *LPCDSEFFECTDESC;\n\n    #define DSFX_LOCHARDWARE    0x00000001\n    #define DSFX_LOCSOFTWARE    0x00000002\n\n    enum\n    {\n        DSFXR_PRESENT,          // 0\n        DSFXR_LOCHARDWARE,      // 1\n        DSFXR_LOCSOFTWARE,      // 2\n        DSFXR_UNALLOCATED,      // 3\n        DSFXR_FAILED,           // 4\n        DSFXR_UNKNOWN,          // 5\n        DSFXR_SENDLOOP          // 6\n    };\n\n    typedef struct _DSCEFFECTDESC\n    {\n        DWORD       dwSize;\n        DWORD       dwFlags;\n        GUID        guidDSCFXClass;\n        GUID        guidDSCFXInstance;\n        DWORD       dwReserved1;\n        DWORD       dwReserved2;\n    } DSCEFFECTDESC, *LPDSCEFFECTDESC;\n    typedef const DSCEFFECTDESC *LPCDSCEFFECTDESC;\n\n    #define DSCFX_LOCHARDWARE   0x00000001\n    #define DSCFX_LOCSOFTWARE   0x00000002\n\n    #define DSCFXR_LOCHARDWARE  0x00000010\n    #define DSCFXR_LOCSOFTWARE  0x00000020\n\n#endif // DIRECTSOUND_VERSION >= 0x0800\n\ntypedef struct _DSBUFFERDESC\n{\n    DWORD           dwSize;\n    DWORD           dwFlags;\n    DWORD           dwBufferBytes;\n    DWORD           dwReserved;\n    LPWAVEFORMATEX  lpwfxFormat;\n#if DIRECTSOUND_VERSION >= 0x0700\n    GUID            guid3DAlgorithm;\n#endif\n} DSBUFFERDESC, *LPDSBUFFERDESC;\n\ntypedef const DSBUFFERDESC *LPCDSBUFFERDESC;\n\n// Older version of this structure:\n\ntypedef struct _DSBUFFERDESC1\n{\n    DWORD           dwSize;\n    DWORD           dwFlags;\n    DWORD           dwBufferBytes;\n    DWORD           dwReserved;\n    LPWAVEFORMATEX  lpwfxFormat;\n} DSBUFFERDESC1, *LPDSBUFFERDESC1;\n\ntypedef const DSBUFFERDESC1 *LPCDSBUFFERDESC1;\n\ntypedef struct _DS3DBUFFER\n{\n    DWORD           dwSize;\n    D3DVECTOR       vPosition;\n    D3DVECTOR       vVelocity;\n    DWORD           dwInsideConeAngle;\n    DWORD           dwOutsideConeAngle;\n    D3DVECTOR       vConeOrientation;\n    LONG            lConeOutsideVolume;\n    D3DVALUE        flMinDistance;\n    D3DVALUE        flMaxDistance;\n    DWORD           dwMode;\n} DS3DBUFFER, *LPDS3DBUFFER;\n\ntypedef const DS3DBUFFER *LPCDS3DBUFFER;\n\ntypedef struct _DS3DLISTENER\n{\n    DWORD           dwSize;\n    D3DVECTOR       vPosition;\n    D3DVECTOR       vVelocity;\n    D3DVECTOR       vOrientFront;\n    D3DVECTOR       vOrientTop;\n    D3DVALUE        flDistanceFactor;\n    D3DVALUE        flRolloffFactor;\n    D3DVALUE        flDopplerFactor;\n} DS3DLISTENER, *LPDS3DLISTENER;\n\ntypedef const DS3DLISTENER *LPCDS3DLISTENER;\n\ntypedef struct _DSCCAPS\n{\n    DWORD           dwSize;\n    DWORD           dwFlags;\n    DWORD           dwFormats;\n    DWORD           dwChannels;\n} DSCCAPS, *LPDSCCAPS;\n\ntypedef const DSCCAPS *LPCDSCCAPS;\n\ntypedef struct _DSCBUFFERDESC1\n{\n    DWORD           dwSize;\n    DWORD           dwFlags;\n    DWORD           dwBufferBytes;\n    DWORD           dwReserved;\n    LPWAVEFORMATEX  lpwfxFormat;\n} DSCBUFFERDESC1, *LPDSCBUFFERDESC1;\n\ntypedef struct _DSCBUFFERDESC\n{\n    DWORD           dwSize;\n    DWORD           dwFlags;\n    DWORD           dwBufferBytes;\n    DWORD           dwReserved;\n    LPWAVEFORMATEX  lpwfxFormat;\n#if DIRECTSOUND_VERSION >= 0x0800\n    DWORD           dwFXCount;\n    LPDSCEFFECTDESC lpDSCFXDesc;\n#endif\n} DSCBUFFERDESC, *LPDSCBUFFERDESC;\n\ntypedef const DSCBUFFERDESC *LPCDSCBUFFERDESC;\n\ntypedef struct _DSCBCAPS\n{\n    DWORD           dwSize;\n    DWORD           dwFlags;\n    DWORD           dwBufferBytes;\n    DWORD           dwReserved;\n} DSCBCAPS, *LPDSCBCAPS;\n\ntypedef const DSCBCAPS *LPCDSCBCAPS;\n\ntypedef struct _DSBPOSITIONNOTIFY\n{\n    DWORD           dwOffset;\n    HANDLE          hEventNotify;\n} DSBPOSITIONNOTIFY, *LPDSBPOSITIONNOTIFY;\n\ntypedef const DSBPOSITIONNOTIFY *LPCDSBPOSITIONNOTIFY;\n\n//\n// DirectSound API\n//\n\ntypedef BOOL (CALLBACK *LPDSENUMCALLBACKA)(LPGUID, LPCSTR, LPCSTR, LPVOID);\ntypedef BOOL (CALLBACK *LPDSENUMCALLBACKW)(LPGUID, LPCWSTR, LPCWSTR, LPVOID);\n\nextern HRESULT WINAPI DirectSoundCreate(LPCGUID pcGuidDevice, LPDIRECTSOUND *ppDS, LPUNKNOWN pUnkOuter);\nextern HRESULT WINAPI DirectSoundEnumerateA(LPDSENUMCALLBACKA pDSEnumCallback, LPVOID pContext);\nextern HRESULT WINAPI DirectSoundEnumerateW(LPDSENUMCALLBACKW pDSEnumCallback, LPVOID pContext);\n\nextern HRESULT WINAPI DirectSoundCaptureCreate(LPCGUID pcGuidDevice, LPDIRECTSOUNDCAPTURE *ppDSC, LPUNKNOWN pUnkOuter);\nextern HRESULT WINAPI DirectSoundCaptureEnumerateA(LPDSENUMCALLBACKA pDSEnumCallback, LPVOID pContext);\nextern HRESULT WINAPI DirectSoundCaptureEnumerateW(LPDSENUMCALLBACKW pDSEnumCallback, LPVOID pContext);\n\n#if DIRECTSOUND_VERSION >= 0x0800\nextern HRESULT WINAPI DirectSoundCreate8(LPCGUID pcGuidDevice, LPDIRECTSOUND8 *ppDS8, LPUNKNOWN pUnkOuter);\nextern HRESULT WINAPI DirectSoundCaptureCreate8(LPCGUID pcGuidDevice, LPDIRECTSOUNDCAPTURE8 *ppDSC8, LPUNKNOWN pUnkOuter);\nextern HRESULT WINAPI DirectSoundFullDuplexCreate(LPCGUID pcGuidCaptureDevice, LPCGUID pcGuidRenderDevice,\n        LPCDSCBUFFERDESC pcDSCBufferDesc, LPCDSBUFFERDESC pcDSBufferDesc, HWND hWnd,\n        DWORD dwLevel, LPDIRECTSOUNDFULLDUPLEX* ppDSFD, LPDIRECTSOUNDCAPTUREBUFFER8 *ppDSCBuffer8,\n        LPDIRECTSOUNDBUFFER8 *ppDSBuffer8, LPUNKNOWN pUnkOuter);\n#define DirectSoundFullDuplexCreate8 DirectSoundFullDuplexCreate\n\nextern HRESULT WINAPI GetDeviceID(LPCGUID pGuidSrc, LPGUID pGuidDest);\n#endif // DIRECTSOUND_VERSION >= 0x0800\n\n#ifdef UNICODE\n#define LPDSENUMCALLBACK            LPDSENUMCALLBACKW\n#define DirectSoundEnumerate        DirectSoundEnumerateW\n#define DirectSoundCaptureEnumerate DirectSoundCaptureEnumerateW\n#else // UNICODE\n#define LPDSENUMCALLBACK            LPDSENUMCALLBACKA\n#define DirectSoundEnumerate        DirectSoundEnumerateA\n#define DirectSoundCaptureEnumerate DirectSoundCaptureEnumerateA\n#endif // UNICODE\n\n//\n// IUnknown\n//\n\n#if !defined(__cplusplus) || defined(CINTERFACE)\n#ifndef IUnknown_QueryInterface\n#define IUnknown_QueryInterface(p,a,b)  (p)->lpVtbl->QueryInterface(p,a,b)\n#endif // IUnknown_QueryInterface\n#ifndef IUnknown_AddRef\n#define IUnknown_AddRef(p)              (p)->lpVtbl->AddRef(p)\n#endif // IUnknown_AddRef\n#ifndef IUnknown_Release\n#define IUnknown_Release(p)             (p)->lpVtbl->Release(p)\n#endif // IUnknown_Release\n#else // !defined(__cplusplus) || defined(CINTERFACE)\n#ifndef IUnknown_QueryInterface\n#define IUnknown_QueryInterface(p,a,b)  (p)->QueryInterface(a,b)\n#endif // IUnknown_QueryInterface\n#ifndef IUnknown_AddRef\n#define IUnknown_AddRef(p)              (p)->AddRef()\n#endif // IUnknown_AddRef\n#ifndef IUnknown_Release\n#define IUnknown_Release(p)             (p)->Release()\n#endif // IUnknown_Release\n#endif // !defined(__cplusplus) || defined(CINTERFACE)\n\n#ifndef __IReferenceClock_INTERFACE_DEFINED__\n#define __IReferenceClock_INTERFACE_DEFINED__\n\ntypedef LONGLONG REFERENCE_TIME;\ntypedef REFERENCE_TIME *LPREFERENCE_TIME;\n\nDEFINE_GUID(IID_IReferenceClock, 0x56a86897, 0x0ad4, 0x11ce, 0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70);\n\n#undef INTERFACE\n#define INTERFACE IReferenceClock\n\nDECLARE_INTERFACE_(IReferenceClock, IUnknown)\n{\n    // IUnknown methods\n    STDMETHOD(QueryInterface)       (THIS_ REFIID, LPVOID *) PURE;\n    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;\n    STDMETHOD_(ULONG,Release)       (THIS) PURE;\n\n    // IReferenceClock methods\n    STDMETHOD(GetTime)              (THIS_ REFERENCE_TIME *pTime) PURE;\n    STDMETHOD(AdviseTime)           (THIS_ REFERENCE_TIME rtBaseTime, REFERENCE_TIME rtStreamTime,\n                                           HANDLE hEvent, LPDWORD pdwAdviseCookie) PURE;\n    STDMETHOD(AdvisePeriodic)       (THIS_ REFERENCE_TIME rtStartTime, REFERENCE_TIME rtPeriodTime,\n                                           HANDLE hSemaphore, LPDWORD pdwAdviseCookie) PURE;\n    STDMETHOD(Unadvise)             (THIS_ DWORD dwAdviseCookie) PURE;\n};\n\n#endif // __IReferenceClock_INTERFACE_DEFINED__\n\n#ifndef IReferenceClock_QueryInterface\n\n#define IReferenceClock_QueryInterface(p,a,b)      IUnknown_QueryInterface(p,a,b)\n#define IReferenceClock_AddRef(p)                  IUnknown_AddRef(p)\n#define IReferenceClock_Release(p)                 IUnknown_Release(p)\n\n#if !defined(__cplusplus) || defined(CINTERFACE)\n#define IReferenceClock_GetTime(p,a)               (p)->lpVtbl->GetTime(p,a)\n#define IReferenceClock_AdviseTime(p,a,b,c,d)      (p)->lpVtbl->AdviseTime(p,a,b,c,d)\n#define IReferenceClock_AdvisePeriodic(p,a,b,c,d)  (p)->lpVtbl->AdvisePeriodic(p,a,b,c,d)\n#define IReferenceClock_Unadvise(p,a)              (p)->lpVtbl->Unadvise(p,a)\n#else // !defined(__cplusplus) || defined(CINTERFACE)\n#define IReferenceClock_GetTime(p,a)               (p)->GetTime(a)\n#define IReferenceClock_AdviseTime(p,a,b,c,d)      (p)->AdviseTime(a,b,c,d)\n#define IReferenceClock_AdvisePeriodic(p,a,b,c,d)  (p)->AdvisePeriodic(a,b,c,d)\n#define IReferenceClock_Unadvise(p,a)              (p)->Unadvise(a)\n#endif // !defined(__cplusplus) || defined(CINTERFACE)\n\n#endif // IReferenceClock_QueryInterface\n\n//\n// IDirectSound\n//\n\nDEFINE_GUID(IID_IDirectSound, 0x279AFA83, 0x4981, 0x11CE, 0xA5, 0x21, 0x00, 0x20, 0xAF, 0x0B, 0xE5, 0x60);\n\n#undef INTERFACE\n#define INTERFACE IDirectSound\n\nDECLARE_INTERFACE_(IDirectSound, IUnknown)\n{\n    // IUnknown methods\n    STDMETHOD(QueryInterface)       (THIS_ REFIID, LPVOID *) PURE;\n    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;\n    STDMETHOD_(ULONG,Release)       (THIS) PURE;\n\n    // IDirectSound methods\n    STDMETHOD(CreateSoundBuffer)    (THIS_ LPCDSBUFFERDESC pcDSBufferDesc, LPDIRECTSOUNDBUFFER *ppDSBuffer, LPUNKNOWN pUnkOuter) PURE;\n    STDMETHOD(GetCaps)              (THIS_ LPDSCAPS pDSCaps) PURE;\n    STDMETHOD(DuplicateSoundBuffer) (THIS_ LPDIRECTSOUNDBUFFER pDSBufferOriginal, LPDIRECTSOUNDBUFFER *ppDSBufferDuplicate) PURE;\n    STDMETHOD(SetCooperativeLevel)  (THIS_ HWND hwnd, DWORD dwLevel) PURE;\n    STDMETHOD(Compact)              (THIS) PURE;\n    STDMETHOD(GetSpeakerConfig)     (THIS_ LPDWORD pdwSpeakerConfig) PURE;\n    STDMETHOD(SetSpeakerConfig)     (THIS_ DWORD dwSpeakerConfig) PURE;\n    STDMETHOD(Initialize)           (THIS_ LPCGUID pcGuidDevice) PURE;\n};\n\n#define IDirectSound_QueryInterface(p,a,b)       IUnknown_QueryInterface(p,a,b)\n#define IDirectSound_AddRef(p)                   IUnknown_AddRef(p)\n#define IDirectSound_Release(p)                  IUnknown_Release(p)\n\n#if !defined(__cplusplus) || defined(CINTERFACE)\n#define IDirectSound_CreateSoundBuffer(p,a,b,c)  (p)->lpVtbl->CreateSoundBuffer(p,a,b,c)\n#define IDirectSound_GetCaps(p,a)                (p)->lpVtbl->GetCaps(p,a)\n#define IDirectSound_DuplicateSoundBuffer(p,a,b) (p)->lpVtbl->DuplicateSoundBuffer(p,a,b)\n#define IDirectSound_SetCooperativeLevel(p,a,b)  (p)->lpVtbl->SetCooperativeLevel(p,a,b)\n#define IDirectSound_Compact(p)                  (p)->lpVtbl->Compact(p)\n#define IDirectSound_GetSpeakerConfig(p,a)       (p)->lpVtbl->GetSpeakerConfig(p,a)\n#define IDirectSound_SetSpeakerConfig(p,b)       (p)->lpVtbl->SetSpeakerConfig(p,b)\n#define IDirectSound_Initialize(p,a)             (p)->lpVtbl->Initialize(p,a)\n#else // !defined(__cplusplus) || defined(CINTERFACE)\n#define IDirectSound_CreateSoundBuffer(p,a,b,c)  (p)->CreateSoundBuffer(a,b,c)\n#define IDirectSound_GetCaps(p,a)                (p)->GetCaps(a)\n#define IDirectSound_DuplicateSoundBuffer(p,a,b) (p)->DuplicateSoundBuffer(a,b)\n#define IDirectSound_SetCooperativeLevel(p,a,b)  (p)->SetCooperativeLevel(a,b)\n#define IDirectSound_Compact(p)                  (p)->Compact()\n#define IDirectSound_GetSpeakerConfig(p,a)       (p)->GetSpeakerConfig(a)\n#define IDirectSound_SetSpeakerConfig(p,b)       (p)->SetSpeakerConfig(b)\n#define IDirectSound_Initialize(p,a)             (p)->Initialize(a)\n#endif // !defined(__cplusplus) || defined(CINTERFACE)\n\n#if DIRECTSOUND_VERSION >= 0x0800\n\n//\n// IDirectSound8\n//\n\nDEFINE_GUID(IID_IDirectSound8, 0xC50A7E93, 0xF395, 0x4834, 0x9E, 0xF6, 0x7F, 0xA9, 0x9D, 0xE5, 0x09, 0x66);\n\n#undef INTERFACE\n#define INTERFACE IDirectSound8\n\nDECLARE_INTERFACE_(IDirectSound8, IDirectSound)\n{\n    // IUnknown methods\n    STDMETHOD(QueryInterface)       (THIS_ REFIID, LPVOID *) PURE;\n    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;\n    STDMETHOD_(ULONG,Release)       (THIS) PURE;\n\n    // IDirectSound methods\n    STDMETHOD(CreateSoundBuffer)    (THIS_ LPCDSBUFFERDESC pcDSBufferDesc, LPDIRECTSOUNDBUFFER *ppDSBuffer, LPUNKNOWN pUnkOuter) PURE;\n    STDMETHOD(GetCaps)              (THIS_ LPDSCAPS pDSCaps) PURE;\n    STDMETHOD(DuplicateSoundBuffer) (THIS_ LPDIRECTSOUNDBUFFER pDSBufferOriginal, LPDIRECTSOUNDBUFFER *ppDSBufferDuplicate) PURE;\n    STDMETHOD(SetCooperativeLevel)  (THIS_ HWND hwnd, DWORD dwLevel) PURE;\n    STDMETHOD(Compact)              (THIS) PURE;\n    STDMETHOD(GetSpeakerConfig)     (THIS_ LPDWORD pdwSpeakerConfig) PURE;\n    STDMETHOD(SetSpeakerConfig)     (THIS_ DWORD dwSpeakerConfig) PURE;\n    STDMETHOD(Initialize)           (THIS_ LPCGUID pcGuidDevice) PURE;\n\n    // IDirectSound8 methods\n    STDMETHOD(VerifyCertification)  (THIS_ LPDWORD pdwCertified) PURE;\n};\n\n#define IDirectSound8_QueryInterface(p,a,b)       IDirectSound_QueryInterface(p,a,b)\n#define IDirectSound8_AddRef(p)                   IDirectSound_AddRef(p)\n#define IDirectSound8_Release(p)                  IDirectSound_Release(p)\n#define IDirectSound8_CreateSoundBuffer(p,a,b,c)  IDirectSound_CreateSoundBuffer(p,a,b,c)\n#define IDirectSound8_GetCaps(p,a)                IDirectSound_GetCaps(p,a)\n#define IDirectSound8_DuplicateSoundBuffer(p,a,b) IDirectSound_DuplicateSoundBuffer(p,a,b)\n#define IDirectSound8_SetCooperativeLevel(p,a,b)  IDirectSound_SetCooperativeLevel(p,a,b)\n#define IDirectSound8_Compact(p)                  IDirectSound_Compact(p)\n#define IDirectSound8_GetSpeakerConfig(p,a)       IDirectSound_GetSpeakerConfig(p,a)\n#define IDirectSound8_SetSpeakerConfig(p,a)       IDirectSound_SetSpeakerConfig(p,a)\n#define IDirectSound8_Initialize(p,a)             IDirectSound_Initialize(p,a)\n\n#if !defined(__cplusplus) || defined(CINTERFACE)\n#define IDirectSound8_VerifyCertification(p,a)           (p)->lpVtbl->VerifyCertification(p,a)\n#else // !defined(__cplusplus) || defined(CINTERFACE)\n#define IDirectSound8_VerifyCertification(p,a)           (p)->VerifyCertification(a)\n#endif // !defined(__cplusplus) || defined(CINTERFACE)\n\n#endif // DIRECTSOUND_VERSION >= 0x0800\n\n//\n// IDirectSoundBuffer\n//\n\nDEFINE_GUID(IID_IDirectSoundBuffer, 0x279AFA85, 0x4981, 0x11CE, 0xA5, 0x21, 0x00, 0x20, 0xAF, 0x0B, 0xE5, 0x60);\n\n#undef INTERFACE\n#define INTERFACE IDirectSoundBuffer\n\nDECLARE_INTERFACE_(IDirectSoundBuffer, IUnknown)\n{\n    // IUnknown methods\n    STDMETHOD(QueryInterface)       (THIS_ REFIID, LPVOID *) PURE;\n    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;\n    STDMETHOD_(ULONG,Release)       (THIS) PURE;\n\n    // IDirectSoundBuffer methods\n    STDMETHOD(GetCaps)              (THIS_ LPDSBCAPS pDSBufferCaps) PURE;\n    STDMETHOD(GetCurrentPosition)   (THIS_ LPDWORD pdwCurrentPlayCursor, LPDWORD pdwCurrentWriteCursor) PURE;\n    STDMETHOD(GetFormat)            (THIS_ LPWAVEFORMATEX pwfxFormat, DWORD dwSizeAllocated, LPDWORD pdwSizeWritten) PURE;\n    STDMETHOD(GetVolume)            (THIS_ LPLONG plVolume) PURE;\n    STDMETHOD(GetPan)               (THIS_ LPLONG plPan) PURE;\n    STDMETHOD(GetFrequency)         (THIS_ LPDWORD pdwFrequency) PURE;\n    STDMETHOD(GetStatus)            (THIS_ LPDWORD pdwStatus) PURE;\n    STDMETHOD(Initialize)           (THIS_ LPDIRECTSOUND pDirectSound, LPCDSBUFFERDESC pcDSBufferDesc) PURE;\n    STDMETHOD(Lock)                 (THIS_ DWORD dwOffset, DWORD dwBytes, LPVOID *ppvAudioPtr1, LPDWORD pdwAudioBytes1,\n                                           LPVOID *ppvAudioPtr2, LPDWORD pdwAudioBytes2, DWORD dwFlags) PURE;\n    STDMETHOD(Play)                 (THIS_ DWORD dwReserved1, DWORD dwPriority, DWORD dwFlags) PURE;\n    STDMETHOD(SetCurrentPosition)   (THIS_ DWORD dwNewPosition) PURE;\n    STDMETHOD(SetFormat)            (THIS_ LPCWAVEFORMATEX pcfxFormat) PURE;\n    STDMETHOD(SetVolume)            (THIS_ LONG lVolume) PURE;\n    STDMETHOD(SetPan)               (THIS_ LONG lPan) PURE;\n    STDMETHOD(SetFrequency)         (THIS_ DWORD dwFrequency) PURE;\n    STDMETHOD(Stop)                 (THIS) PURE;\n    STDMETHOD(Unlock)               (THIS_ LPVOID pvAudioPtr1, DWORD dwAudioBytes1, LPVOID pvAudioPtr2, DWORD dwAudioBytes2) PURE;\n    STDMETHOD(Restore)              (THIS) PURE;\n};\n\n#define IDirectSoundBuffer_QueryInterface(p,a,b)        IUnknown_QueryInterface(p,a,b)\n#define IDirectSoundBuffer_AddRef(p)                    IUnknown_AddRef(p)\n#define IDirectSoundBuffer_Release(p)                   IUnknown_Release(p)\n\n#if !defined(__cplusplus) || defined(CINTERFACE)\n#define IDirectSoundBuffer_GetCaps(p,a)                 (p)->lpVtbl->GetCaps(p,a)\n#define IDirectSoundBuffer_GetCurrentPosition(p,a,b)    (p)->lpVtbl->GetCurrentPosition(p,a,b)\n#define IDirectSoundBuffer_GetFormat(p,a,b,c)           (p)->lpVtbl->GetFormat(p,a,b,c)\n#define IDirectSoundBuffer_GetVolume(p,a)               (p)->lpVtbl->GetVolume(p,a)\n#define IDirectSoundBuffer_GetPan(p,a)                  (p)->lpVtbl->GetPan(p,a)\n#define IDirectSoundBuffer_GetFrequency(p,a)            (p)->lpVtbl->GetFrequency(p,a)\n#define IDirectSoundBuffer_GetStatus(p,a)               (p)->lpVtbl->GetStatus(p,a)\n#define IDirectSoundBuffer_Initialize(p,a,b)            (p)->lpVtbl->Initialize(p,a,b)\n#define IDirectSoundBuffer_Lock(p,a,b,c,d,e,f,g)        (p)->lpVtbl->Lock(p,a,b,c,d,e,f,g)\n#define IDirectSoundBuffer_Play(p,a,b,c)                (p)->lpVtbl->Play(p,a,b,c)\n#define IDirectSoundBuffer_SetCurrentPosition(p,a)      (p)->lpVtbl->SetCurrentPosition(p,a)\n#define IDirectSoundBuffer_SetFormat(p,a)               (p)->lpVtbl->SetFormat(p,a)\n#define IDirectSoundBuffer_SetVolume(p,a)               (p)->lpVtbl->SetVolume(p,a)\n#define IDirectSoundBuffer_SetPan(p,a)                  (p)->lpVtbl->SetPan(p,a)\n#define IDirectSoundBuffer_SetFrequency(p,a)            (p)->lpVtbl->SetFrequency(p,a)\n#define IDirectSoundBuffer_Stop(p)                      (p)->lpVtbl->Stop(p)\n#define IDirectSoundBuffer_Unlock(p,a,b,c,d)            (p)->lpVtbl->Unlock(p,a,b,c,d)\n#define IDirectSoundBuffer_Restore(p)                   (p)->lpVtbl->Restore(p)\n#else // !defined(__cplusplus) || defined(CINTERFACE)\n#define IDirectSoundBuffer_GetCaps(p,a)                 (p)->GetCaps(a)\n#define IDirectSoundBuffer_GetCurrentPosition(p,a,b)    (p)->GetCurrentPosition(a,b)\n#define IDirectSoundBuffer_GetFormat(p,a,b,c)           (p)->GetFormat(a,b,c)\n#define IDirectSoundBuffer_GetVolume(p,a)               (p)->GetVolume(a)\n#define IDirectSoundBuffer_GetPan(p,a)                  (p)->GetPan(a)\n#define IDirectSoundBuffer_GetFrequency(p,a)            (p)->GetFrequency(a)\n#define IDirectSoundBuffer_GetStatus(p,a)               (p)->GetStatus(a)\n#define IDirectSoundBuffer_Initialize(p,a,b)            (p)->Initialize(a,b)\n#define IDirectSoundBuffer_Lock(p,a,b,c,d,e,f,g)        (p)->Lock(a,b,c,d,e,f,g)\n#define IDirectSoundBuffer_Play(p,a,b,c)                (p)->Play(a,b,c)\n#define IDirectSoundBuffer_SetCurrentPosition(p,a)      (p)->SetCurrentPosition(a)\n#define IDirectSoundBuffer_SetFormat(p,a)               (p)->SetFormat(a)\n#define IDirectSoundBuffer_SetVolume(p,a)               (p)->SetVolume(a)\n#define IDirectSoundBuffer_SetPan(p,a)                  (p)->SetPan(a)\n#define IDirectSoundBuffer_SetFrequency(p,a)            (p)->SetFrequency(a)\n#define IDirectSoundBuffer_Stop(p)                      (p)->Stop()\n#define IDirectSoundBuffer_Unlock(p,a,b,c,d)            (p)->Unlock(a,b,c,d)\n#define IDirectSoundBuffer_Restore(p)                   (p)->Restore()\n#endif // !defined(__cplusplus) || defined(CINTERFACE)\n\n#if DIRECTSOUND_VERSION >= 0x0800\n\n//\n// IDirectSoundBuffer8\n//\n\nDEFINE_GUID(IID_IDirectSoundBuffer8, 0x6825a449, 0x7524, 0x4d82, 0x92, 0x0f, 0x50, 0xe3, 0x6a, 0xb3, 0xab, 0x1e);\n\n#undef INTERFACE\n#define INTERFACE IDirectSoundBuffer8\n\nDECLARE_INTERFACE_(IDirectSoundBuffer8, IDirectSoundBuffer)\n{\n    // IUnknown methods\n    STDMETHOD(QueryInterface)       (THIS_ REFIID, LPVOID *) PURE;\n    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;\n    STDMETHOD_(ULONG,Release)       (THIS) PURE;\n\n    // IDirectSoundBuffer methods\n    STDMETHOD(GetCaps)              (THIS_ LPDSBCAPS pDSBufferCaps) PURE;\n    STDMETHOD(GetCurrentPosition)   (THIS_ LPDWORD pdwCurrentPlayCursor, LPDWORD pdwCurrentWriteCursor) PURE;\n    STDMETHOD(GetFormat)            (THIS_ LPWAVEFORMATEX pwfxFormat, DWORD dwSizeAllocated, LPDWORD pdwSizeWritten) PURE;\n    STDMETHOD(GetVolume)            (THIS_ LPLONG plVolume) PURE;\n    STDMETHOD(GetPan)               (THIS_ LPLONG plPan) PURE;\n    STDMETHOD(GetFrequency)         (THIS_ LPDWORD pdwFrequency) PURE;\n    STDMETHOD(GetStatus)            (THIS_ LPDWORD pdwStatus) PURE;\n    STDMETHOD(Initialize)           (THIS_ LPDIRECTSOUND pDirectSound, LPCDSBUFFERDESC pcDSBufferDesc) PURE;\n    STDMETHOD(Lock)                 (THIS_ DWORD dwOffset, DWORD dwBytes, LPVOID *ppvAudioPtr1, LPDWORD pdwAudioBytes1,\n                                           LPVOID *ppvAudioPtr2, LPDWORD pdwAudioBytes2, DWORD dwFlags) PURE;\n    STDMETHOD(Play)                 (THIS_ DWORD dwReserved1, DWORD dwPriority, DWORD dwFlags) PURE;\n    STDMETHOD(SetCurrentPosition)   (THIS_ DWORD dwNewPosition) PURE;\n    STDMETHOD(SetFormat)            (THIS_ LPCWAVEFORMATEX pcfxFormat) PURE;\n    STDMETHOD(SetVolume)            (THIS_ LONG lVolume) PURE;\n    STDMETHOD(SetPan)               (THIS_ LONG lPan) PURE;\n    STDMETHOD(SetFrequency)         (THIS_ DWORD dwFrequency) PURE;\n    STDMETHOD(Stop)                 (THIS) PURE;\n    STDMETHOD(Unlock)               (THIS_ LPVOID pvAudioPtr1, DWORD dwAudioBytes1, LPVOID pvAudioPtr2, DWORD dwAudioBytes2) PURE;\n    STDMETHOD(Restore)              (THIS) PURE;\n\n    // IDirectSoundBuffer8 methods\n    STDMETHOD(SetFX)                (THIS_ DWORD dwEffectsCount, LPDSEFFECTDESC pDSFXDesc, LPDWORD pdwResultCodes) PURE;\n    STDMETHOD(AcquireResources)     (THIS_ DWORD dwFlags, DWORD dwEffectsCount, LPDWORD pdwResultCodes) PURE;\n    STDMETHOD(GetObjectInPath)      (THIS_ REFGUID rguidObject, DWORD dwIndex, REFGUID rguidInterface, LPVOID *ppObject) PURE;\n};\n\n// Special GUID meaning \"select all objects\" for use in GetObjectInPath()\nDEFINE_GUID(GUID_All_Objects, 0xaa114de5, 0xc262, 0x4169, 0xa1, 0xc8, 0x23, 0xd6, 0x98, 0xcc, 0x73, 0xb5);\n\n#define IDirectSoundBuffer8_QueryInterface(p,a,b)           IUnknown_QueryInterface(p,a,b)\n#define IDirectSoundBuffer8_AddRef(p)                       IUnknown_AddRef(p)\n#define IDirectSoundBuffer8_Release(p)                      IUnknown_Release(p)\n\n#define IDirectSoundBuffer8_GetCaps(p,a)                    IDirectSoundBuffer_GetCaps(p,a)\n#define IDirectSoundBuffer8_GetCurrentPosition(p,a,b)       IDirectSoundBuffer_GetCurrentPosition(p,a,b)\n#define IDirectSoundBuffer8_GetFormat(p,a,b,c)              IDirectSoundBuffer_GetFormat(p,a,b,c)\n#define IDirectSoundBuffer8_GetVolume(p,a)                  IDirectSoundBuffer_GetVolume(p,a)\n#define IDirectSoundBuffer8_GetPan(p,a)                     IDirectSoundBuffer_GetPan(p,a)\n#define IDirectSoundBuffer8_GetFrequency(p,a)               IDirectSoundBuffer_GetFrequency(p,a)\n#define IDirectSoundBuffer8_GetStatus(p,a)                  IDirectSoundBuffer_GetStatus(p,a)\n#define IDirectSoundBuffer8_Initialize(p,a,b)               IDirectSoundBuffer_Initialize(p,a,b)\n#define IDirectSoundBuffer8_Lock(p,a,b,c,d,e,f,g)           IDirectSoundBuffer_Lock(p,a,b,c,d,e,f,g)\n#define IDirectSoundBuffer8_Play(p,a,b,c)                   IDirectSoundBuffer_Play(p,a,b,c)\n#define IDirectSoundBuffer8_SetCurrentPosition(p,a)         IDirectSoundBuffer_SetCurrentPosition(p,a)\n#define IDirectSoundBuffer8_SetFormat(p,a)                  IDirectSoundBuffer_SetFormat(p,a)\n#define IDirectSoundBuffer8_SetVolume(p,a)                  IDirectSoundBuffer_SetVolume(p,a)\n#define IDirectSoundBuffer8_SetPan(p,a)                     IDirectSoundBuffer_SetPan(p,a)\n#define IDirectSoundBuffer8_SetFrequency(p,a)               IDirectSoundBuffer_SetFrequency(p,a)\n#define IDirectSoundBuffer8_Stop(p)                         IDirectSoundBuffer_Stop(p)\n#define IDirectSoundBuffer8_Unlock(p,a,b,c,d)               IDirectSoundBuffer_Unlock(p,a,b,c,d)\n#define IDirectSoundBuffer8_Restore(p)                      IDirectSoundBuffer_Restore(p)\n\n#if !defined(__cplusplus) || defined(CINTERFACE)\n#define IDirectSoundBuffer8_SetFX(p,a,b,c)                  (p)->lpVtbl->SetFX(p,a,b,c)\n#define IDirectSoundBuffer8_AcquireResources(p,a,b,c)       (p)->lpVtbl->AcquireResources(p,a,b,c)\n#define IDirectSoundBuffer8_GetObjectInPath(p,a,b,c,d)      (p)->lpVtbl->GetObjectInPath(p,a,b,c,d)\n#else // !defined(__cplusplus) || defined(CINTERFACE)\n#define IDirectSoundBuffer8_SetFX(p,a,b,c)                  (p)->SetFX(a,b,c)\n#define IDirectSoundBuffer8_AcquireResources(p,a,b,c)       (p)->AcquireResources(a,b,c)\n#define IDirectSoundBuffer8_GetObjectInPath(p,a,b,c,d)      (p)->GetObjectInPath(a,b,c,d)\n#endif // !defined(__cplusplus) || defined(CINTERFACE)\n\n#endif // DIRECTSOUND_VERSION >= 0x0800\n\n//\n// IDirectSound3DListener\n//\n\nDEFINE_GUID(IID_IDirectSound3DListener, 0x279AFA84, 0x4981, 0x11CE, 0xA5, 0x21, 0x00, 0x20, 0xAF, 0x0B, 0xE5, 0x60);\n\n#undef INTERFACE\n#define INTERFACE IDirectSound3DListener\n\nDECLARE_INTERFACE_(IDirectSound3DListener, IUnknown)\n{\n    // IUnknown methods\n    STDMETHOD(QueryInterface)           (THIS_ REFIID, LPVOID *) PURE;\n    STDMETHOD_(ULONG,AddRef)            (THIS) PURE;\n    STDMETHOD_(ULONG,Release)           (THIS) PURE;\n\n    // IDirectSound3DListener methods\n    STDMETHOD(GetAllParameters)         (THIS_ LPDS3DLISTENER pListener) PURE;\n    STDMETHOD(GetDistanceFactor)        (THIS_ D3DVALUE* pflDistanceFactor) PURE;\n    STDMETHOD(GetDopplerFactor)         (THIS_ D3DVALUE* pflDopplerFactor) PURE;\n    STDMETHOD(GetOrientation)           (THIS_ D3DVECTOR* pvOrientFront, D3DVECTOR* pvOrientTop) PURE;\n    STDMETHOD(GetPosition)              (THIS_ D3DVECTOR* pvPosition) PURE;\n    STDMETHOD(GetRolloffFactor)         (THIS_ D3DVALUE* pflRolloffFactor) PURE;\n    STDMETHOD(GetVelocity)              (THIS_ D3DVECTOR* pvVelocity) PURE;\n    STDMETHOD(SetAllParameters)         (THIS_ LPCDS3DLISTENER pcListener, DWORD dwApply) PURE;\n    STDMETHOD(SetDistanceFactor)        (THIS_ D3DVALUE flDistanceFactor, DWORD dwApply) PURE;\n    STDMETHOD(SetDopplerFactor)         (THIS_ D3DVALUE flDopplerFactor, DWORD dwApply) PURE;\n    STDMETHOD(SetOrientation)           (THIS_ D3DVALUE xFront, D3DVALUE yFront, D3DVALUE zFront,\n                                               D3DVALUE xTop, D3DVALUE yTop, D3DVALUE zTop, DWORD dwApply) PURE;\n    STDMETHOD(SetPosition)              (THIS_ D3DVALUE x, D3DVALUE y, D3DVALUE z, DWORD dwApply) PURE;\n    STDMETHOD(SetRolloffFactor)         (THIS_ D3DVALUE flRolloffFactor, DWORD dwApply) PURE;\n    STDMETHOD(SetVelocity)              (THIS_ D3DVALUE x, D3DVALUE y, D3DVALUE z, DWORD dwApply) PURE;\n    STDMETHOD(CommitDeferredSettings)   (THIS) PURE;\n};\n\n#define IDirectSound3DListener_QueryInterface(p,a,b)            IUnknown_QueryInterface(p,a,b)\n#define IDirectSound3DListener_AddRef(p)                        IUnknown_AddRef(p)\n#define IDirectSound3DListener_Release(p)                       IUnknown_Release(p)\n\n#if !defined(__cplusplus) || defined(CINTERFACE)\n#define IDirectSound3DListener_GetAllParameters(p,a)            (p)->lpVtbl->GetAllParameters(p,a)\n#define IDirectSound3DListener_GetDistanceFactor(p,a)           (p)->lpVtbl->GetDistanceFactor(p,a)\n#define IDirectSound3DListener_GetDopplerFactor(p,a)            (p)->lpVtbl->GetDopplerFactor(p,a)\n#define IDirectSound3DListener_GetOrientation(p,a,b)            (p)->lpVtbl->GetOrientation(p,a,b)\n#define IDirectSound3DListener_GetPosition(p,a)                 (p)->lpVtbl->GetPosition(p,a)\n#define IDirectSound3DListener_GetRolloffFactor(p,a)            (p)->lpVtbl->GetRolloffFactor(p,a)\n#define IDirectSound3DListener_GetVelocity(p,a)                 (p)->lpVtbl->GetVelocity(p,a)\n#define IDirectSound3DListener_SetAllParameters(p,a,b)          (p)->lpVtbl->SetAllParameters(p,a,b)\n#define IDirectSound3DListener_SetDistanceFactor(p,a,b)         (p)->lpVtbl->SetDistanceFactor(p,a,b)\n#define IDirectSound3DListener_SetDopplerFactor(p,a,b)          (p)->lpVtbl->SetDopplerFactor(p,a,b)\n#define IDirectSound3DListener_SetOrientation(p,a,b,c,d,e,f,g)  (p)->lpVtbl->SetOrientation(p,a,b,c,d,e,f,g)\n#define IDirectSound3DListener_SetPosition(p,a,b,c,d)           (p)->lpVtbl->SetPosition(p,a,b,c,d)\n#define IDirectSound3DListener_SetRolloffFactor(p,a,b)          (p)->lpVtbl->SetRolloffFactor(p,a,b)\n#define IDirectSound3DListener_SetVelocity(p,a,b,c,d)           (p)->lpVtbl->SetVelocity(p,a,b,c,d)\n#define IDirectSound3DListener_CommitDeferredSettings(p)        (p)->lpVtbl->CommitDeferredSettings(p)\n#else // !defined(__cplusplus) || defined(CINTERFACE)\n#define IDirectSound3DListener_GetAllParameters(p,a)            (p)->GetAllParameters(a)\n#define IDirectSound3DListener_GetDistanceFactor(p,a)           (p)->GetDistanceFactor(a)\n#define IDirectSound3DListener_GetDopplerFactor(p,a)            (p)->GetDopplerFactor(a)\n#define IDirectSound3DListener_GetOrientation(p,a,b)            (p)->GetOrientation(a,b)\n#define IDirectSound3DListener_GetPosition(p,a)                 (p)->GetPosition(a)\n#define IDirectSound3DListener_GetRolloffFactor(p,a)            (p)->GetRolloffFactor(a)\n#define IDirectSound3DListener_GetVelocity(p,a)                 (p)->GetVelocity(a)\n#define IDirectSound3DListener_SetAllParameters(p,a,b)          (p)->SetAllParameters(a,b)\n#define IDirectSound3DListener_SetDistanceFactor(p,a,b)         (p)->SetDistanceFactor(a,b)\n#define IDirectSound3DListener_SetDopplerFactor(p,a,b)          (p)->SetDopplerFactor(a,b)\n#define IDirectSound3DListener_SetOrientation(p,a,b,c,d,e,f,g)  (p)->SetOrientation(a,b,c,d,e,f,g)\n#define IDirectSound3DListener_SetPosition(p,a,b,c,d)           (p)->SetPosition(a,b,c,d)\n#define IDirectSound3DListener_SetRolloffFactor(p,a,b)          (p)->SetRolloffFactor(a,b)\n#define IDirectSound3DListener_SetVelocity(p,a,b,c,d)           (p)->SetVelocity(a,b,c,d)\n#define IDirectSound3DListener_CommitDeferredSettings(p)        (p)->CommitDeferredSettings()\n#endif // !defined(__cplusplus) || defined(CINTERFACE)\n\n//\n// IDirectSound3DBuffer\n//\n\nDEFINE_GUID(IID_IDirectSound3DBuffer, 0x279AFA86, 0x4981, 0x11CE, 0xA5, 0x21, 0x00, 0x20, 0xAF, 0x0B, 0xE5, 0x60);\n\n#undef INTERFACE\n#define INTERFACE IDirectSound3DBuffer\n\nDECLARE_INTERFACE_(IDirectSound3DBuffer, IUnknown)\n{\n    // IUnknown methods\n    STDMETHOD(QueryInterface)       (THIS_ REFIID, LPVOID *) PURE;\n    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;\n    STDMETHOD_(ULONG,Release)       (THIS) PURE;\n\n    // IDirectSound3DBuffer methods\n    STDMETHOD(GetAllParameters)     (THIS_ LPDS3DBUFFER pDs3dBuffer) PURE;\n    STDMETHOD(GetConeAngles)        (THIS_ LPDWORD pdwInsideConeAngle, LPDWORD pdwOutsideConeAngle) PURE;\n    STDMETHOD(GetConeOrientation)   (THIS_ D3DVECTOR* pvOrientation) PURE;\n    STDMETHOD(GetConeOutsideVolume) (THIS_ LPLONG plConeOutsideVolume) PURE;\n    STDMETHOD(GetMaxDistance)       (THIS_ D3DVALUE* pflMaxDistance) PURE;\n    STDMETHOD(GetMinDistance)       (THIS_ D3DVALUE* pflMinDistance) PURE;\n    STDMETHOD(GetMode)              (THIS_ LPDWORD pdwMode) PURE;\n    STDMETHOD(GetPosition)          (THIS_ D3DVECTOR* pvPosition) PURE;\n    STDMETHOD(GetVelocity)          (THIS_ D3DVECTOR* pvVelocity) PURE;\n    STDMETHOD(SetAllParameters)     (THIS_ LPCDS3DBUFFER pcDs3dBuffer, DWORD dwApply) PURE;\n    STDMETHOD(SetConeAngles)        (THIS_ DWORD dwInsideConeAngle, DWORD dwOutsideConeAngle, DWORD dwApply) PURE;\n    STDMETHOD(SetConeOrientation)   (THIS_ D3DVALUE x, D3DVALUE y, D3DVALUE z, DWORD dwApply) PURE;\n    STDMETHOD(SetConeOutsideVolume) (THIS_ LONG lConeOutsideVolume, DWORD dwApply) PURE;\n    STDMETHOD(SetMaxDistance)       (THIS_ D3DVALUE flMaxDistance, DWORD dwApply) PURE;\n    STDMETHOD(SetMinDistance)       (THIS_ D3DVALUE flMinDistance, DWORD dwApply) PURE;\n    STDMETHOD(SetMode)              (THIS_ DWORD dwMode, DWORD dwApply) PURE;\n    STDMETHOD(SetPosition)          (THIS_ D3DVALUE x, D3DVALUE y, D3DVALUE z, DWORD dwApply) PURE;\n    STDMETHOD(SetVelocity)          (THIS_ D3DVALUE x, D3DVALUE y, D3DVALUE z, DWORD dwApply) PURE;\n};\n\n#define IDirectSound3DBuffer_QueryInterface(p,a,b)          IUnknown_QueryInterface(p,a,b)\n#define IDirectSound3DBuffer_AddRef(p)                      IUnknown_AddRef(p)\n#define IDirectSound3DBuffer_Release(p)                     IUnknown_Release(p)\n\n#if !defined(__cplusplus) || defined(CINTERFACE)\n#define IDirectSound3DBuffer_GetAllParameters(p,a)          (p)->lpVtbl->GetAllParameters(p,a)\n#define IDirectSound3DBuffer_GetConeAngles(p,a,b)           (p)->lpVtbl->GetConeAngles(p,a,b)\n#define IDirectSound3DBuffer_GetConeOrientation(p,a)        (p)->lpVtbl->GetConeOrientation(p,a)\n#define IDirectSound3DBuffer_GetConeOutsideVolume(p,a)      (p)->lpVtbl->GetConeOutsideVolume(p,a)\n#define IDirectSound3DBuffer_GetPosition(p,a)               (p)->lpVtbl->GetPosition(p,a)\n#define IDirectSound3DBuffer_GetMinDistance(p,a)            (p)->lpVtbl->GetMinDistance(p,a)\n#define IDirectSound3DBuffer_GetMaxDistance(p,a)            (p)->lpVtbl->GetMaxDistance(p,a)\n#define IDirectSound3DBuffer_GetMode(p,a)                   (p)->lpVtbl->GetMode(p,a)\n#define IDirectSound3DBuffer_GetVelocity(p,a)               (p)->lpVtbl->GetVelocity(p,a)\n#define IDirectSound3DBuffer_SetAllParameters(p,a,b)        (p)->lpVtbl->SetAllParameters(p,a,b)\n#define IDirectSound3DBuffer_SetConeAngles(p,a,b,c)         (p)->lpVtbl->SetConeAngles(p,a,b,c)\n#define IDirectSound3DBuffer_SetConeOrientation(p,a,b,c,d)  (p)->lpVtbl->SetConeOrientation(p,a,b,c,d)\n#define IDirectSound3DBuffer_SetConeOutsideVolume(p,a,b)    (p)->lpVtbl->SetConeOutsideVolume(p,a,b)\n#define IDirectSound3DBuffer_SetPosition(p,a,b,c,d)         (p)->lpVtbl->SetPosition(p,a,b,c,d)\n#define IDirectSound3DBuffer_SetMinDistance(p,a,b)          (p)->lpVtbl->SetMinDistance(p,a,b)\n#define IDirectSound3DBuffer_SetMaxDistance(p,a,b)          (p)->lpVtbl->SetMaxDistance(p,a,b)\n#define IDirectSound3DBuffer_SetMode(p,a,b)                 (p)->lpVtbl->SetMode(p,a,b)\n#define IDirectSound3DBuffer_SetVelocity(p,a,b,c,d)         (p)->lpVtbl->SetVelocity(p,a,b,c,d)\n#else // !defined(__cplusplus) || defined(CINTERFACE)\n#define IDirectSound3DBuffer_GetAllParameters(p,a)          (p)->GetAllParameters(a)\n#define IDirectSound3DBuffer_GetConeAngles(p,a,b)           (p)->GetConeAngles(a,b)\n#define IDirectSound3DBuffer_GetConeOrientation(p,a)        (p)->GetConeOrientation(a)\n#define IDirectSound3DBuffer_GetConeOutsideVolume(p,a)      (p)->GetConeOutsideVolume(a)\n#define IDirectSound3DBuffer_GetPosition(p,a)               (p)->GetPosition(a)\n#define IDirectSound3DBuffer_GetMinDistance(p,a)            (p)->GetMinDistance(a)\n#define IDirectSound3DBuffer_GetMaxDistance(p,a)            (p)->GetMaxDistance(a)\n#define IDirectSound3DBuffer_GetMode(p,a)                   (p)->GetMode(a)\n#define IDirectSound3DBuffer_GetVelocity(p,a)               (p)->GetVelocity(a)\n#define IDirectSound3DBuffer_SetAllParameters(p,a,b)        (p)->SetAllParameters(a,b)\n#define IDirectSound3DBuffer_SetConeAngles(p,a,b,c)         (p)->SetConeAngles(a,b,c)\n#define IDirectSound3DBuffer_SetConeOrientation(p,a,b,c,d)  (p)->SetConeOrientation(a,b,c,d)\n#define IDirectSound3DBuffer_SetConeOutsideVolume(p,a,b)    (p)->SetConeOutsideVolume(a,b)\n#define IDirectSound3DBuffer_SetPosition(p,a,b,c,d)         (p)->SetPosition(a,b,c,d)\n#define IDirectSound3DBuffer_SetMinDistance(p,a,b)          (p)->SetMinDistance(a,b)\n#define IDirectSound3DBuffer_SetMaxDistance(p,a,b)          (p)->SetMaxDistance(a,b)\n#define IDirectSound3DBuffer_SetMode(p,a,b)                 (p)->SetMode(a,b)\n#define IDirectSound3DBuffer_SetVelocity(p,a,b,c,d)         (p)->SetVelocity(a,b,c,d)\n#endif // !defined(__cplusplus) || defined(CINTERFACE)\n\n//\n// IDirectSoundCapture\n//\n\nDEFINE_GUID(IID_IDirectSoundCapture, 0xb0210781, 0x89cd, 0x11d0, 0xaf, 0x8, 0x0, 0xa0, 0xc9, 0x25, 0xcd, 0x16);\n\n#undef INTERFACE\n#define INTERFACE IDirectSoundCapture\n\nDECLARE_INTERFACE_(IDirectSoundCapture, IUnknown)\n{\n    // IUnknown methods\n    STDMETHOD(QueryInterface)       (THIS_ REFIID, LPVOID *) PURE;\n    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;\n    STDMETHOD_(ULONG,Release)       (THIS) PURE;\n\n    // IDirectSoundCapture methods\n    STDMETHOD(CreateCaptureBuffer)  (THIS_ LPCDSCBUFFERDESC pcDSCBufferDesc, LPDIRECTSOUNDCAPTUREBUFFER *ppDSCBuffer, LPUNKNOWN pUnkOuter) PURE;\n    STDMETHOD(GetCaps)              (THIS_ LPDSCCAPS pDSCCaps) PURE;\n    STDMETHOD(Initialize)           (THIS_ LPCGUID pcGuidDevice) PURE;\n};\n\n#define IDirectSoundCapture_QueryInterface(p,a,b)           IUnknown_QueryInterface(p,a,b)\n#define IDirectSoundCapture_AddRef(p)                       IUnknown_AddRef(p)\n#define IDirectSoundCapture_Release(p)                      IUnknown_Release(p)\n\n#if !defined(__cplusplus) || defined(CINTERFACE)\n#define IDirectSoundCapture_CreateCaptureBuffer(p,a,b,c)    (p)->lpVtbl->CreateCaptureBuffer(p,a,b,c)\n#define IDirectSoundCapture_GetCaps(p,a)                    (p)->lpVtbl->GetCaps(p,a)\n#define IDirectSoundCapture_Initialize(p,a)                 (p)->lpVtbl->Initialize(p,a)\n#else // !defined(__cplusplus) || defined(CINTERFACE)\n#define IDirectSoundCapture_CreateCaptureBuffer(p,a,b,c)    (p)->CreateCaptureBuffer(a,b,c)\n#define IDirectSoundCapture_GetCaps(p,a)                    (p)->GetCaps(a)\n#define IDirectSoundCapture_Initialize(p,a)                 (p)->Initialize(a)\n#endif // !defined(__cplusplus) || defined(CINTERFACE)\n\n//\n// IDirectSoundCaptureBuffer\n//\n\nDEFINE_GUID(IID_IDirectSoundCaptureBuffer, 0xb0210782, 0x89cd, 0x11d0, 0xaf, 0x8, 0x0, 0xa0, 0xc9, 0x25, 0xcd, 0x16);\n\n#undef INTERFACE\n#define INTERFACE IDirectSoundCaptureBuffer\n\nDECLARE_INTERFACE_(IDirectSoundCaptureBuffer, IUnknown)\n{\n    // IUnknown methods\n    STDMETHOD(QueryInterface)       (THIS_ REFIID, LPVOID *) PURE;\n    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;\n    STDMETHOD_(ULONG,Release)       (THIS) PURE;\n\n    // IDirectSoundCaptureBuffer methods\n    STDMETHOD(GetCaps)              (THIS_ LPDSCBCAPS pDSCBCaps) PURE;\n    STDMETHOD(GetCurrentPosition)   (THIS_ LPDWORD pdwCapturePosition, LPDWORD pdwReadPosition) PURE;\n    STDMETHOD(GetFormat)            (THIS_ LPWAVEFORMATEX pwfxFormat, DWORD dwSizeAllocated, LPDWORD pdwSizeWritten) PURE;\n    STDMETHOD(GetStatus)            (THIS_ LPDWORD pdwStatus) PURE;\n    STDMETHOD(Initialize)           (THIS_ LPDIRECTSOUNDCAPTURE pDirectSoundCapture, LPCDSCBUFFERDESC pcDSCBufferDesc) PURE;\n    STDMETHOD(Lock)                 (THIS_ DWORD dwOffset, DWORD dwBytes, LPVOID *ppvAudioPtr1, LPDWORD pdwAudioBytes1,\n                                           LPVOID *ppvAudioPtr2, LPDWORD pdwAudioBytes2, DWORD dwFlags) PURE;\n    STDMETHOD(Start)                (THIS_ DWORD dwFlags) PURE;\n    STDMETHOD(Stop)                 (THIS) PURE;\n    STDMETHOD(Unlock)               (THIS_ LPVOID pvAudioPtr1, DWORD dwAudioBytes1, LPVOID pvAudioPtr2, DWORD dwAudioBytes2) PURE;\n};\n\n#define IDirectSoundCaptureBuffer_QueryInterface(p,a,b)         IUnknown_QueryInterface(p,a,b)\n#define IDirectSoundCaptureBuffer_AddRef(p)                     IUnknown_AddRef(p)\n#define IDirectSoundCaptureBuffer_Release(p)                    IUnknown_Release(p)\n\n#if !defined(__cplusplus) || defined(CINTERFACE)\n#define IDirectSoundCaptureBuffer_GetCaps(p,a)                  (p)->lpVtbl->GetCaps(p,a)\n#define IDirectSoundCaptureBuffer_GetCurrentPosition(p,a,b)     (p)->lpVtbl->GetCurrentPosition(p,a,b)\n#define IDirectSoundCaptureBuffer_GetFormat(p,a,b,c)            (p)->lpVtbl->GetFormat(p,a,b,c)\n#define IDirectSoundCaptureBuffer_GetStatus(p,a)                (p)->lpVtbl->GetStatus(p,a)\n#define IDirectSoundCaptureBuffer_Initialize(p,a,b)             (p)->lpVtbl->Initialize(p,a,b)\n#define IDirectSoundCaptureBuffer_Lock(p,a,b,c,d,e,f,g)         (p)->lpVtbl->Lock(p,a,b,c,d,e,f,g)\n#define IDirectSoundCaptureBuffer_Start(p,a)                    (p)->lpVtbl->Start(p,a)\n#define IDirectSoundCaptureBuffer_Stop(p)                       (p)->lpVtbl->Stop(p)\n#define IDirectSoundCaptureBuffer_Unlock(p,a,b,c,d)             (p)->lpVtbl->Unlock(p,a,b,c,d)\n#else // !defined(__cplusplus) || defined(CINTERFACE)\n#define IDirectSoundCaptureBuffer_GetCaps(p,a)                  (p)->GetCaps(a)\n#define IDirectSoundCaptureBuffer_GetCurrentPosition(p,a,b)     (p)->GetCurrentPosition(a,b)\n#define IDirectSoundCaptureBuffer_GetFormat(p,a,b,c)            (p)->GetFormat(a,b,c)\n#define IDirectSoundCaptureBuffer_GetStatus(p,a)                (p)->GetStatus(a)\n#define IDirectSoundCaptureBuffer_Initialize(p,a,b)             (p)->Initialize(a,b)\n#define IDirectSoundCaptureBuffer_Lock(p,a,b,c,d,e,f,g)         (p)->Lock(a,b,c,d,e,f,g)\n#define IDirectSoundCaptureBuffer_Start(p,a)                    (p)->Start(a)\n#define IDirectSoundCaptureBuffer_Stop(p)                       (p)->Stop()\n#define IDirectSoundCaptureBuffer_Unlock(p,a,b,c,d)             (p)->Unlock(a,b,c,d)\n#endif // !defined(__cplusplus) || defined(CINTERFACE)\n\n\n#if DIRECTSOUND_VERSION >= 0x0800\n\n//\n// IDirectSoundCaptureBuffer8\n//\n\nDEFINE_GUID(IID_IDirectSoundCaptureBuffer8, 0x990df4, 0xdbb, 0x4872, 0x83, 0x3e, 0x6d, 0x30, 0x3e, 0x80, 0xae, 0xb6);\n\n#undef INTERFACE\n#define INTERFACE IDirectSoundCaptureBuffer8\n\nDECLARE_INTERFACE_(IDirectSoundCaptureBuffer8, IDirectSoundCaptureBuffer)\n{\n    // IUnknown methods\n    STDMETHOD(QueryInterface)       (THIS_ REFIID, LPVOID *) PURE;\n    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;\n    STDMETHOD_(ULONG,Release)       (THIS) PURE;\n\n    // IDirectSoundCaptureBuffer methods\n    STDMETHOD(GetCaps)              (THIS_ LPDSCBCAPS pDSCBCaps) PURE;\n    STDMETHOD(GetCurrentPosition)   (THIS_ LPDWORD pdwCapturePosition, LPDWORD pdwReadPosition) PURE;\n    STDMETHOD(GetFormat)            (THIS_ LPWAVEFORMATEX pwfxFormat, DWORD dwSizeAllocated, LPDWORD pdwSizeWritten) PURE;\n    STDMETHOD(GetStatus)            (THIS_ LPDWORD pdwStatus) PURE;\n    STDMETHOD(Initialize)           (THIS_ LPDIRECTSOUNDCAPTURE pDirectSoundCapture, LPCDSCBUFFERDESC pcDSCBufferDesc) PURE;\n    STDMETHOD(Lock)                 (THIS_ DWORD dwOffset, DWORD dwBytes, LPVOID *ppvAudioPtr1, LPDWORD pdwAudioBytes1,\n                                           LPVOID *ppvAudioPtr2, LPDWORD pdwAudioBytes2, DWORD dwFlags) PURE;\n    STDMETHOD(Start)                (THIS_ DWORD dwFlags) PURE;\n    STDMETHOD(Stop)                 (THIS) PURE;\n    STDMETHOD(Unlock)               (THIS_ LPVOID pvAudioPtr1, DWORD dwAudioBytes1, LPVOID pvAudioPtr2, DWORD dwAudioBytes2) PURE;\n\n    // IDirectSoundCaptureBuffer8 methods\n    STDMETHOD(GetObjectInPath)      (THIS_ REFGUID rguidObject, DWORD dwIndex, REFGUID rguidInterface, LPVOID *ppObject) PURE;\n    STDMETHOD(GetFXStatus)          (DWORD dwFXCount, LPDWORD pdwFXStatus) PURE;\n};\n\n#define IDirectSoundCaptureBuffer8_QueryInterface(p,a,b)            IUnknown_QueryInterface(p,a,b)\n#define IDirectSoundCaptureBuffer8_AddRef(p)                        IUnknown_AddRef(p)\n#define IDirectSoundCaptureBuffer8_Release(p)                       IUnknown_Release(p)\n\n#define IDirectSoundCaptureBuffer8_GetCaps(p,a)                     IDirectSoundCaptureBuffer_GetCaps(p,a)\n#define IDirectSoundCaptureBuffer8_GetCurrentPosition(p,a,b)        IDirectSoundCaptureBuffer_GetCurrentPosition(p,a,b)\n#define IDirectSoundCaptureBuffer8_GetFormat(p,a,b,c)               IDirectSoundCaptureBuffer_GetFormat(p,a,b,c)\n#define IDirectSoundCaptureBuffer8_GetStatus(p,a)                   IDirectSoundCaptureBuffer_GetStatus(p,a)\n#define IDirectSoundCaptureBuffer8_Initialize(p,a,b)                IDirectSoundCaptureBuffer_Initialize(p,a,b)\n#define IDirectSoundCaptureBuffer8_Lock(p,a,b,c,d,e,f,g)            IDirectSoundCaptureBuffer_Lock(p,a,b,c,d,e,f,g)\n#define IDirectSoundCaptureBuffer8_Start(p,a)                       IDirectSoundCaptureBuffer_Start(p,a)\n#define IDirectSoundCaptureBuffer8_Stop(p)                          IDirectSoundCaptureBuffer_Stop(p))\n#define IDirectSoundCaptureBuffer8_Unlock(p,a,b,c,d)                IDirectSoundCaptureBuffer_Unlock(p,a,b,c,d)\n\n#if !defined(__cplusplus) || defined(CINTERFACE)\n#define IDirectSoundCaptureBuffer8_GetObjectInPath(p,a,b,c,d)       (p)->lpVtbl->GetObjectInPath(p,a,b,c,d)\n#define IDirectSoundCaptureBuffer8_GetFXStatus(p,a,b)               (p)->lpVtbl->GetFXStatus(p,a,b)\n#else // !defined(__cplusplus) || defined(CINTERFACE)\n#define IDirectSoundCaptureBuffer8_GetObjectInPath(p,a,b,c,d)       (p)->GetObjectInPath(a,b,c,d)\n#define IDirectSoundCaptureBuffer8_GetFXStatus(p,a,b)               (p)->GetFXStatus(a,b)\n#endif // !defined(__cplusplus) || defined(CINTERFACE)\n\n#endif // DIRECTSOUND_VERSION >= 0x0800\n\n//\n// IDirectSoundNotify\n//\n\nDEFINE_GUID(IID_IDirectSoundNotify, 0xb0210783, 0x89cd, 0x11d0, 0xaf, 0x8, 0x0, 0xa0, 0xc9, 0x25, 0xcd, 0x16);\n\n#undef INTERFACE\n#define INTERFACE IDirectSoundNotify\n\nDECLARE_INTERFACE_(IDirectSoundNotify, IUnknown)\n{\n    // IUnknown methods\n    STDMETHOD(QueryInterface)           (THIS_ REFIID, LPVOID *) PURE;\n    STDMETHOD_(ULONG,AddRef)            (THIS) PURE;\n    STDMETHOD_(ULONG,Release)           (THIS) PURE;\n\n    // IDirectSoundNotify methods\n    STDMETHOD(SetNotificationPositions) (THIS_ DWORD dwPositionNotifies, LPCDSBPOSITIONNOTIFY pcPositionNotifies) PURE;\n};\n\n#define IDirectSoundNotify_QueryInterface(p,a,b)            IUnknown_QueryInterface(p,a,b)\n#define IDirectSoundNotify_AddRef(p)                        IUnknown_AddRef(p)\n#define IDirectSoundNotify_Release(p)                       IUnknown_Release(p)\n\n#if !defined(__cplusplus) || defined(CINTERFACE)\n#define IDirectSoundNotify_SetNotificationPositions(p,a,b)  (p)->lpVtbl->SetNotificationPositions(p,a,b)\n#else // !defined(__cplusplus) || defined(CINTERFACE)\n#define IDirectSoundNotify_SetNotificationPositions(p,a,b)  (p)->SetNotificationPositions(a,b)\n#endif // !defined(__cplusplus) || defined(CINTERFACE)\n\n//\n// IKsPropertySet\n//\n\n#ifndef _IKsPropertySet_\n#define _IKsPropertySet_\n\n#ifdef __cplusplus\n// 'struct' not 'class' per the way DECLARE_INTERFACE_ is defined\nstruct IKsPropertySet;\n#endif // __cplusplus\n\ntypedef struct IKsPropertySet *LPKSPROPERTYSET;\n\n#define KSPROPERTY_SUPPORT_GET  0x00000001\n#define KSPROPERTY_SUPPORT_SET  0x00000002\n\nDEFINE_GUID(IID_IKsPropertySet, 0x31efac30, 0x515c, 0x11d0, 0xa9, 0xaa, 0x00, 0xaa, 0x00, 0x61, 0xbe, 0x93);\n\n#undef INTERFACE\n#define INTERFACE IKsPropertySet\n\nDECLARE_INTERFACE_(IKsPropertySet, IUnknown)\n{\n    // IUnknown methods\n    STDMETHOD(QueryInterface)   (THIS_ REFIID, LPVOID *) PURE;\n    STDMETHOD_(ULONG,AddRef)    (THIS) PURE;\n    STDMETHOD_(ULONG,Release)   (THIS) PURE;\n\n    // IKsPropertySet methods\n    STDMETHOD(Get)              (THIS_ REFGUID rguidPropSet, ULONG ulId, LPVOID pInstanceData, ULONG ulInstanceLength,\n                                       LPVOID pPropertyData, ULONG ulDataLength, PULONG pulBytesReturned) PURE;\n    STDMETHOD(Set)              (THIS_ REFGUID rguidPropSet, ULONG ulId, LPVOID pInstanceData, ULONG ulInstanceLength,\n                                       LPVOID pPropertyData, ULONG ulDataLength) PURE;\n    STDMETHOD(QuerySupport)     (THIS_ REFGUID rguidPropSet, ULONG ulId, PULONG pulTypeSupport) PURE;\n};\n\n#define IKsPropertySet_QueryInterface(p,a,b)       IUnknown_QueryInterface(p,a,b)\n#define IKsPropertySet_AddRef(p)                   IUnknown_AddRef(p)\n#define IKsPropertySet_Release(p)                  IUnknown_Release(p)\n\n#if !defined(__cplusplus) || defined(CINTERFACE)\n#define IKsPropertySet_Get(p,a,b,c,d,e,f,g)        (p)->lpVtbl->Get(p,a,b,c,d,e,f,g)\n#define IKsPropertySet_Set(p,a,b,c,d,e,f)          (p)->lpVtbl->Set(p,a,b,c,d,e,f)\n#define IKsPropertySet_QuerySupport(p,a,b,c)       (p)->lpVtbl->QuerySupport(p,a,b,c)\n#else // !defined(__cplusplus) || defined(CINTERFACE)\n#define IKsPropertySet_Get(p,a,b,c,d,e,f,g)        (p)->Get(a,b,c,d,e,f,g)\n#define IKsPropertySet_Set(p,a,b,c,d,e,f)          (p)->Set(a,b,c,d,e,f)\n#define IKsPropertySet_QuerySupport(p,a,b,c)       (p)->QuerySupport(a,b,c)\n#endif // !defined(__cplusplus) || defined(CINTERFACE)\n\n#endif // _IKsPropertySet_\n\n#if DIRECTSOUND_VERSION >= 0x0800\n\n//\n// IDirectSoundFXGargle\n//\n\nDEFINE_GUID(IID_IDirectSoundFXGargle, 0xd616f352, 0xd622, 0x11ce, 0xaa, 0xc5, 0x00, 0x20, 0xaf, 0x0b, 0x99, 0xa3);\n\ntypedef struct _DSFXGargle\n{\n    DWORD       dwRateHz;               // Rate of modulation in hz\n    DWORD       dwWaveShape;            // DSFXGARGLE_WAVE_xxx\n} DSFXGargle, *LPDSFXGargle;\n\n#define DSFXGARGLE_WAVE_TRIANGLE        0\n#define DSFXGARGLE_WAVE_SQUARE          1\n\ntypedef const DSFXGargle *LPCDSFXGargle;\n\n#define DSFXGARGLE_RATEHZ_MIN           1\n#define DSFXGARGLE_RATEHZ_MAX           1000\n\n#undef INTERFACE\n#define INTERFACE IDirectSoundFXGargle\n\nDECLARE_INTERFACE_(IDirectSoundFXGargle, IUnknown)\n{\n    // IUnknown methods\n    STDMETHOD(QueryInterface)       (THIS_ REFIID, LPVOID *) PURE;\n    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;\n    STDMETHOD_(ULONG,Release)       (THIS) PURE;\n\n    // IDirectSoundFXGargle methods\n    STDMETHOD(SetAllParameters)     (THIS_ LPCDSFXGargle pcDsFxGargle) PURE;\n    STDMETHOD(GetAllParameters)     (THIS_ LPDSFXGargle pDsFxGargle) PURE;\n};\n\n#define IDirectSoundFXGargle_QueryInterface(p,a,b)          IUnknown_QueryInterface(p,a,b)\n#define IDirectSoundFXGargle_AddRef(p)                      IUnknown_AddRef(p)\n#define IDirectSoundFXGargle_Release(p)                     IUnknown_Release(p)\n\n#if !defined(__cplusplus) || defined(CINTERFACE)\n#define IDirectSoundFXGargle_SetAllParameters(p,a)          (p)->lpVtbl->SetAllParameters(p,a)\n#define IDirectSoundFXGargle_GetAllParameters(p,a)          (p)->lpVtbl->GetAllParameters(p,a)\n#else // !defined(__cplusplus) || defined(CINTERFACE)\n#define IDirectSoundFXGargle_SetAllParameters(p,a)          (p)->SetAllParameters(a)\n#define IDirectSoundFXGargle_GetAllParameters(p,a)          (p)->GetAllParameters(a)\n#endif // !defined(__cplusplus) || defined(CINTERFACE)\n\n//\n// IDirectSoundFXChorus\n//\n\nDEFINE_GUID(IID_IDirectSoundFXChorus, 0x880842e3, 0x145f, 0x43e6, 0xa9, 0x34, 0xa7, 0x18, 0x06, 0xe5, 0x05, 0x47);\n\ntypedef struct _DSFXChorus\n{\n    FLOAT       fWetDryMix;\n    FLOAT       fDepth;\n    FLOAT       fFeedback;\n    FLOAT       fFrequency;\n    LONG        lWaveform;          // LFO shape; DSFXCHORUS_WAVE_xxx\n    FLOAT       fDelay;\n    LONG        lPhase;\n} DSFXChorus, *LPDSFXChorus;\n\ntypedef const DSFXChorus *LPCDSFXChorus;\n\n#define DSFXCHORUS_WAVE_TRIANGLE        0\n#define DSFXCHORUS_WAVE_SIN             1\n\n#define DSFXCHORUS_WETDRYMIX_MIN        0.0f\n#define DSFXCHORUS_WETDRYMIX_MAX        100.0f\n#define DSFXCHORUS_DEPTH_MIN            0.0f\n#define DSFXCHORUS_DEPTH_MAX            100.0f\n#define DSFXCHORUS_FEEDBACK_MIN         -99.0f\n#define DSFXCHORUS_FEEDBACK_MAX         99.0f\n#define DSFXCHORUS_FREQUENCY_MIN        0.0f\n#define DSFXCHORUS_FREQUENCY_MAX        10.0f\n#define DSFXCHORUS_DELAY_MIN            0.0f\n#define DSFXCHORUS_DELAY_MAX            20.0f\n#define DSFXCHORUS_PHASE_MIN            0\n#define DSFXCHORUS_PHASE_MAX            4\n\n#define DSFXCHORUS_PHASE_NEG_180        0\n#define DSFXCHORUS_PHASE_NEG_90         1\n#define DSFXCHORUS_PHASE_ZERO           2\n#define DSFXCHORUS_PHASE_90             3\n#define DSFXCHORUS_PHASE_180            4\n\n#undef INTERFACE\n#define INTERFACE IDirectSoundFXChorus\n\nDECLARE_INTERFACE_(IDirectSoundFXChorus, IUnknown)\n{\n    // IUnknown methods\n    STDMETHOD(QueryInterface)       (THIS_ REFIID, LPVOID *) PURE;\n    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;\n    STDMETHOD_(ULONG,Release)       (THIS) PURE;\n\n    // IDirectSoundFXChorus methods\n    STDMETHOD(SetAllParameters)     (THIS_ LPCDSFXChorus pcDsFxChorus) PURE;\n    STDMETHOD(GetAllParameters)     (THIS_ LPDSFXChorus pDsFxChorus) PURE;\n};\n\n#define IDirectSoundFXChorus_QueryInterface(p,a,b)          IUnknown_QueryInterface(p,a,b)\n#define IDirectSoundFXChorus_AddRef(p)                      IUnknown_AddRef(p)\n#define IDirectSoundFXChorus_Release(p)                     IUnknown_Release(p)\n\n#if !defined(__cplusplus) || defined(CINTERFACE)\n#define IDirectSoundFXChorus_SetAllParameters(p,a)          (p)->lpVtbl->SetAllParameters(p,a)\n#define IDirectSoundFXChorus_GetAllParameters(p,a)          (p)->lpVtbl->GetAllParameters(p,a)\n#else // !defined(__cplusplus) || defined(CINTERFACE)\n#define IDirectSoundFXChorus_SetAllParameters(p,a)          (p)->SetAllParameters(a)\n#define IDirectSoundFXChorus_GetAllParameters(p,a)          (p)->GetAllParameters(a)\n#endif // !defined(__cplusplus) || defined(CINTERFACE)\n\n//\n// IDirectSoundFXFlanger\n//\n\nDEFINE_GUID(IID_IDirectSoundFXFlanger, 0x903e9878, 0x2c92, 0x4072, 0x9b, 0x2c, 0xea, 0x68, 0xf5, 0x39, 0x67, 0x83);\n\ntypedef struct _DSFXFlanger\n{\n    FLOAT       fWetDryMix;\n    FLOAT       fDepth;\n    FLOAT       fFeedback;\n    FLOAT       fFrequency;\n    LONG        lWaveform;\n    FLOAT       fDelay;\n    LONG        lPhase;\n} DSFXFlanger, *LPDSFXFlanger;\n\ntypedef const DSFXFlanger *LPCDSFXFlanger;\n\n#define DSFXFLANGER_WAVE_TRIANGLE       0\n#define DSFXFLANGER_WAVE_SIN            1\n\n#define DSFXFLANGER_WETDRYMIX_MIN       0.0f\n#define DSFXFLANGER_WETDRYMIX_MAX       100.0f\n#define DSFXFLANGER_FREQUENCY_MIN       0.0f\n#define DSFXFLANGER_FREQUENCY_MAX       10.0f\n#define DSFXFLANGER_DEPTH_MIN           0.0f\n#define DSFXFLANGER_DEPTH_MAX           100.0f\n#define DSFXFLANGER_PHASE_MIN           0\n#define DSFXFLANGER_PHASE_MAX           4\n#define DSFXFLANGER_FEEDBACK_MIN        -99.0f\n#define DSFXFLANGER_FEEDBACK_MAX        99.0f\n#define DSFXFLANGER_DELAY_MIN           0.0f\n#define DSFXFLANGER_DELAY_MAX           4.0f\n\n#define DSFXFLANGER_PHASE_NEG_180       0\n#define DSFXFLANGER_PHASE_NEG_90        1\n#define DSFXFLANGER_PHASE_ZERO          2\n#define DSFXFLANGER_PHASE_90            3\n#define DSFXFLANGER_PHASE_180           4\n\n#undef INTERFACE\n#define INTERFACE IDirectSoundFXFlanger\n\nDECLARE_INTERFACE_(IDirectSoundFXFlanger, IUnknown)\n{\n    // IUnknown methods\n    STDMETHOD(QueryInterface)       (THIS_ REFIID, LPVOID *) PURE;\n    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;\n    STDMETHOD_(ULONG,Release)       (THIS) PURE;\n\n    // IDirectSoundFXFlanger methods\n    STDMETHOD(SetAllParameters)     (THIS_ LPCDSFXFlanger pcDsFxFlanger) PURE;\n    STDMETHOD(GetAllParameters)     (THIS_ LPDSFXFlanger pDsFxFlanger) PURE;\n};\n\n#define IDirectSoundFXFlanger_QueryInterface(p,a,b)         IUnknown_QueryInterface(p,a,b)\n#define IDirectSoundFXFlanger_AddRef(p)                     IUnknown_AddRef(p)\n#define IDirectSoundFXFlanger_Release(p)                    IUnknown_Release(p)\n\n#if !defined(__cplusplus) || defined(CINTERFACE)\n#define IDirectSoundFXFlanger_SetAllParameters(p,a)         (p)->lpVtbl->SetAllParameters(p,a)\n#define IDirectSoundFXFlanger_GetAllParameters(p,a)         (p)->lpVtbl->GetAllParameters(p,a)\n#else // !defined(__cplusplus) || defined(CINTERFACE)\n#define IDirectSoundFXFlanger_SetAllParameters(p,a)         (p)->SetAllParameters(a)\n#define IDirectSoundFXFlanger_GetAllParameters(p,a)         (p)->GetAllParameters(a)\n#endif // !defined(__cplusplus) || defined(CINTERFACE)\n\n//\n// IDirectSoundFXEcho\n//\n\nDEFINE_GUID(IID_IDirectSoundFXEcho, 0x8bd28edf, 0x50db, 0x4e92, 0xa2, 0xbd, 0x44, 0x54, 0x88, 0xd1, 0xed, 0x42);\n\ntypedef struct _DSFXEcho\n{\n    FLOAT   fWetDryMix;\n    FLOAT   fFeedback;\n    FLOAT   fLeftDelay;\n    FLOAT   fRightDelay;\n    LONG    lPanDelay;\n} DSFXEcho, *LPDSFXEcho;\n\ntypedef const DSFXEcho *LPCDSFXEcho;\n\n#define DSFXECHO_WETDRYMIX_MIN      0.0f\n#define DSFXECHO_WETDRYMIX_MAX      100.0f\n#define DSFXECHO_FEEDBACK_MIN       0.0f\n#define DSFXECHO_FEEDBACK_MAX       100.0f\n#define DSFXECHO_LEFTDELAY_MIN      1.0f\n#define DSFXECHO_LEFTDELAY_MAX      2000.0f\n#define DSFXECHO_RIGHTDELAY_MIN     1.0f\n#define DSFXECHO_RIGHTDELAY_MAX     2000.0f\n#define DSFXECHO_PANDELAY_MIN       0\n#define DSFXECHO_PANDELAY_MAX       1\n\n#undef INTERFACE\n#define INTERFACE IDirectSoundFXEcho\n\nDECLARE_INTERFACE_(IDirectSoundFXEcho, IUnknown)\n{\n    // IUnknown methods\n    STDMETHOD(QueryInterface)       (THIS_ REFIID, LPVOID *) PURE;\n    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;\n    STDMETHOD_(ULONG,Release)       (THIS) PURE;\n\n    // IDirectSoundFXEcho methods\n    STDMETHOD(SetAllParameters)     (THIS_ LPCDSFXEcho pcDsFxEcho) PURE;\n    STDMETHOD(GetAllParameters)     (THIS_ LPDSFXEcho pDsFxEcho) PURE;\n};\n\n#define IDirectSoundFXEcho_QueryInterface(p,a,b)            IUnknown_QueryInterface(p,a,b)\n#define IDirectSoundFXEcho_AddRef(p)                        IUnknown_AddRef(p)\n#define IDirectSoundFXEcho_Release(p)                       IUnknown_Release(p)\n\n#if !defined(__cplusplus) || defined(CINTERFACE)\n#define IDirectSoundFXEcho_SetAllParameters(p,a)            (p)->lpVtbl->SetAllParameters(p,a)\n#define IDirectSoundFXEcho_GetAllParameters(p,a)            (p)->lpVtbl->GetAllParameters(p,a)\n#else // !defined(__cplusplus) || defined(CINTERFACE)\n#define IDirectSoundFXEcho_SetAllParameters(p,a)            (p)->SetAllParameters(a)\n#define IDirectSoundFXEcho_GetAllParameters(p,a)            (p)->GetAllParameters(a)\n#endif // !defined(__cplusplus) || defined(CINTERFACE)\n\n//\n// IDirectSoundFXDistortion\n//\n\nDEFINE_GUID(IID_IDirectSoundFXDistortion, 0x8ecf4326, 0x455f, 0x4d8b, 0xbd, 0xa9, 0x8d, 0x5d, 0x3e, 0x9e, 0x3e, 0x0b);\n\ntypedef struct _DSFXDistortion\n{\n    FLOAT   fGain;\n    FLOAT   fEdge;\n    FLOAT   fPostEQCenterFrequency;\n    FLOAT   fPostEQBandwidth;\n    FLOAT   fPreLowpassCutoff;\n} DSFXDistortion, *LPDSFXDistortion;\n\ntypedef const DSFXDistortion *LPCDSFXDistortion;\n\n#define DSFXDISTORTION_GAIN_MIN                     -60.0f\n#define DSFXDISTORTION_GAIN_MAX                     0.0f\n#define DSFXDISTORTION_EDGE_MIN                     0.0f\n#define DSFXDISTORTION_EDGE_MAX                     100.0f\n#define DSFXDISTORTION_POSTEQCENTERFREQUENCY_MIN    100.0f\n#define DSFXDISTORTION_POSTEQCENTERFREQUENCY_MAX    8000.0f\n#define DSFXDISTORTION_POSTEQBANDWIDTH_MIN          100.0f\n#define DSFXDISTORTION_POSTEQBANDWIDTH_MAX          8000.0f\n#define DSFXDISTORTION_PRELOWPASSCUTOFF_MIN         100.0f\n#define DSFXDISTORTION_PRELOWPASSCUTOFF_MAX         8000.0f\n\n#undef INTERFACE\n#define INTERFACE IDirectSoundFXDistortion\n\nDECLARE_INTERFACE_(IDirectSoundFXDistortion, IUnknown)\n{\n    // IUnknown methods\n    STDMETHOD(QueryInterface)       (THIS_ REFIID, LPVOID *) PURE;\n    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;\n    STDMETHOD_(ULONG,Release)       (THIS) PURE;\n\n    // IDirectSoundFXDistortion methods\n    STDMETHOD(SetAllParameters)     (THIS_ LPCDSFXDistortion pcDsFxDistortion) PURE;\n    STDMETHOD(GetAllParameters)     (THIS_ LPDSFXDistortion pDsFxDistortion) PURE;\n};\n\n#define IDirectSoundFXDistortion_QueryInterface(p,a,b)      IUnknown_QueryInterface(p,a,b)\n#define IDirectSoundFXDistortion_AddRef(p)                  IUnknown_AddRef(p)\n#define IDirectSoundFXDistortion_Release(p)                 IUnknown_Release(p)\n\n#if !defined(__cplusplus) || defined(CINTERFACE)\n#define IDirectSoundFXDistortion_SetAllParameters(p,a)      (p)->lpVtbl->SetAllParameters(p,a)\n#define IDirectSoundFXDistortion_GetAllParameters(p,a)      (p)->lpVtbl->GetAllParameters(p,a)\n#else // !defined(__cplusplus) || defined(CINTERFACE)\n#define IDirectSoundFXDistortion_SetAllParameters(p,a)      (p)->SetAllParameters(a)\n#define IDirectSoundFXDistortion_GetAllParameters(p,a)      (p)->GetAllParameters(a)\n#endif // !defined(__cplusplus) || defined(CINTERFACE)\n\n//\n// IDirectSoundFXCompressor\n//\n\nDEFINE_GUID(IID_IDirectSoundFXCompressor, 0x4bbd1154, 0x62f6, 0x4e2c, 0xa1, 0x5c, 0xd3, 0xb6, 0xc4, 0x17, 0xf7, 0xa0);\n\ntypedef struct _DSFXCompressor\n{\n    FLOAT   fGain;\n    FLOAT   fAttack;\n    FLOAT   fRelease;\n    FLOAT   fThreshold;\n    FLOAT   fRatio;\n    FLOAT   fPredelay;\n} DSFXCompressor, *LPDSFXCompressor;\n\ntypedef const DSFXCompressor *LPCDSFXCompressor;\n\n#define DSFXCOMPRESSOR_GAIN_MIN             -60.0f\n#define DSFXCOMPRESSOR_GAIN_MAX             60.0f\n#define DSFXCOMPRESSOR_ATTACK_MIN           0.01f\n#define DSFXCOMPRESSOR_ATTACK_MAX           500.0f\n#define DSFXCOMPRESSOR_RELEASE_MIN          50.0f\n#define DSFXCOMPRESSOR_RELEASE_MAX          3000.0f\n#define DSFXCOMPRESSOR_THRESHOLD_MIN        -60.0f\n#define DSFXCOMPRESSOR_THRESHOLD_MAX        0.0f\n#define DSFXCOMPRESSOR_RATIO_MIN            1.0f\n#define DSFXCOMPRESSOR_RATIO_MAX            100.0f\n#define DSFXCOMPRESSOR_PREDELAY_MIN         0.0f\n#define DSFXCOMPRESSOR_PREDELAY_MAX         4.0f\n\n#undef INTERFACE\n#define INTERFACE IDirectSoundFXCompressor\n\nDECLARE_INTERFACE_(IDirectSoundFXCompressor, IUnknown)\n{\n    // IUnknown methods\n    STDMETHOD(QueryInterface)       (THIS_ REFIID, LPVOID *) PURE;\n    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;\n    STDMETHOD_(ULONG,Release)       (THIS) PURE;\n\n    // IDirectSoundFXCompressor methods\n    STDMETHOD(SetAllParameters)     (THIS_ LPCDSFXCompressor pcDsFxCompressor) PURE;\n    STDMETHOD(GetAllParameters)     (THIS_ LPDSFXCompressor pDsFxCompressor) PURE;\n};\n\n#define IDirectSoundFXCompressor_QueryInterface(p,a,b)      IUnknown_QueryInterface(p,a,b)\n#define IDirectSoundFXCompressor_AddRef(p)                  IUnknown_AddRef(p)\n#define IDirectSoundFXCompressor_Release(p)                 IUnknown_Release(p)\n\n#if !defined(__cplusplus) || defined(CINTERFACE)\n#define IDirectSoundFXCompressor_SetAllParameters(p,a)      (p)->lpVtbl->SetAllParameters(p,a)\n#define IDirectSoundFXCompressor_GetAllParameters(p,a)      (p)->lpVtbl->GetAllParameters(p,a)\n#else // !defined(__cplusplus) || defined(CINTERFACE)\n#define IDirectSoundFXCompressor_SetAllParameters(p,a)      (p)->SetAllParameters(a)\n#define IDirectSoundFXCompressor_GetAllParameters(p,a)      (p)->GetAllParameters(a)\n#endif // !defined(__cplusplus) || defined(CINTERFACE)\n\n//\n// IDirectSoundFXParamEq\n//\n\nDEFINE_GUID(IID_IDirectSoundFXParamEq, 0xc03ca9fe, 0xfe90, 0x4204, 0x80, 0x78, 0x82, 0x33, 0x4c, 0xd1, 0x77, 0xda);\n\ntypedef struct _DSFXParamEq\n{\n    FLOAT   fCenter;\n    FLOAT   fBandwidth;\n    FLOAT   fGain;\n} DSFXParamEq, *LPDSFXParamEq;\n\ntypedef const DSFXParamEq *LPCDSFXParamEq;\n\n#define DSFXPARAMEQ_CENTER_MIN      80.0f\n#define DSFXPARAMEQ_CENTER_MAX      16000.0f\n#define DSFXPARAMEQ_BANDWIDTH_MIN   1.0f\n#define DSFXPARAMEQ_BANDWIDTH_MAX   36.0f\n#define DSFXPARAMEQ_GAIN_MIN        -15.0f\n#define DSFXPARAMEQ_GAIN_MAX        15.0f\n\n#undef INTERFACE\n#define INTERFACE IDirectSoundFXParamEq\n\nDECLARE_INTERFACE_(IDirectSoundFXParamEq, IUnknown)\n{\n    // IUnknown methods\n    STDMETHOD(QueryInterface)       (THIS_ REFIID, LPVOID *) PURE;\n    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;\n    STDMETHOD_(ULONG,Release)       (THIS) PURE;\n\n    // IDirectSoundFXParamEq methods\n    STDMETHOD(SetAllParameters)     (THIS_ LPCDSFXParamEq pcDsFxParamEq) PURE;\n    STDMETHOD(GetAllParameters)     (THIS_ LPDSFXParamEq pDsFxParamEq) PURE;\n};\n\n#define IDirectSoundFXParamEq_QueryInterface(p,a,b)      IUnknown_QueryInterface(p,a,b)\n#define IDirectSoundFXParamEq_AddRef(p)                  IUnknown_AddRef(p)\n#define IDirectSoundFXParamEq_Release(p)                 IUnknown_Release(p)\n\n#if !defined(__cplusplus) || defined(CINTERFACE)\n#define IDirectSoundFXParamEq_SetAllParameters(p,a)      (p)->lpVtbl->SetAllParameters(p,a)\n#define IDirectSoundFXParamEq_GetAllParameters(p,a)      (p)->lpVtbl->GetAllParameters(p,a)\n#else // !defined(__cplusplus) || defined(CINTERFACE)\n#define IDirectSoundFXParamEq_SetAllParameters(p,a)      (p)->SetAllParameters(a)\n#define IDirectSoundFXParamEq_GetAllParameters(p,a)      (p)->GetAllParameters(a)\n#endif // !defined(__cplusplus) || defined(CINTERFACE)\n\n//\n// IDirectSoundFXI3DL2Reverb\n//\n\nDEFINE_GUID(IID_IDirectSoundFXI3DL2Reverb, 0x4b166a6a, 0x0d66, 0x43f3, 0x80, 0xe3, 0xee, 0x62, 0x80, 0xde, 0xe1, 0xa4);\n\ntypedef struct _DSFXI3DL2Reverb\n{\n    LONG    lRoom;                  // [-10000, 0]      default: -1000 mB\n    LONG    lRoomHF;                // [-10000, 0]      default: 0 mB\n    FLOAT   flRoomRolloffFactor;    // [0.0, 10.0]      default: 0.0\n    FLOAT   flDecayTime;            // [0.1, 20.0]      default: 1.49s\n    FLOAT   flDecayHFRatio;         // [0.1, 2.0]       default: 0.83\n    LONG    lReflections;           // [-10000, 1000]   default: -2602 mB\n    FLOAT   flReflectionsDelay;     // [0.0, 0.3]       default: 0.007 s\n    LONG    lReverb;                // [-10000, 2000]   default: 200 mB\n    FLOAT   flReverbDelay;          // [0.0, 0.1]       default: 0.011 s\n    FLOAT   flDiffusion;            // [0.0, 100.0]     default: 100.0 %\n    FLOAT   flDensity;              // [0.0, 100.0]     default: 100.0 %\n    FLOAT   flHFReference;          // [20.0, 20000.0]  default: 5000.0 Hz\n} DSFXI3DL2Reverb, *LPDSFXI3DL2Reverb;\n\ntypedef const DSFXI3DL2Reverb *LPCDSFXI3DL2Reverb;\n\n#define DSFX_I3DL2REVERB_ROOM_MIN                   (-10000)\n#define DSFX_I3DL2REVERB_ROOM_MAX                   0\n#define DSFX_I3DL2REVERB_ROOM_DEFAULT               (-1000)\n\n#define DSFX_I3DL2REVERB_ROOMHF_MIN                 (-10000)\n#define DSFX_I3DL2REVERB_ROOMHF_MAX                 0\n#define DSFX_I3DL2REVERB_ROOMHF_DEFAULT             (-100)\n\n#define DSFX_I3DL2REVERB_ROOMROLLOFFFACTOR_MIN      0.0f\n#define DSFX_I3DL2REVERB_ROOMROLLOFFFACTOR_MAX      10.0f\n#define DSFX_I3DL2REVERB_ROOMROLLOFFFACTOR_DEFAULT  0.0f\n\n#define DSFX_I3DL2REVERB_DECAYTIME_MIN              0.1f\n#define DSFX_I3DL2REVERB_DECAYTIME_MAX              20.0f\n#define DSFX_I3DL2REVERB_DECAYTIME_DEFAULT          1.49f\n\n#define DSFX_I3DL2REVERB_DECAYHFRATIO_MIN           0.1f\n#define DSFX_I3DL2REVERB_DECAYHFRATIO_MAX           2.0f\n#define DSFX_I3DL2REVERB_DECAYHFRATIO_DEFAULT       0.83f\n\n#define DSFX_I3DL2REVERB_REFLECTIONS_MIN            (-10000)\n#define DSFX_I3DL2REVERB_REFLECTIONS_MAX            1000\n#define DSFX_I3DL2REVERB_REFLECTIONS_DEFAULT        (-2602)\n\n#define DSFX_I3DL2REVERB_REFLECTIONSDELAY_MIN       0.0f\n#define DSFX_I3DL2REVERB_REFLECTIONSDELAY_MAX       0.3f\n#define DSFX_I3DL2REVERB_REFLECTIONSDELAY_DEFAULT   0.007f\n\n#define DSFX_I3DL2REVERB_REVERB_MIN                 (-10000)\n#define DSFX_I3DL2REVERB_REVERB_MAX                 2000\n#define DSFX_I3DL2REVERB_REVERB_DEFAULT             (200)\n\n#define DSFX_I3DL2REVERB_REVERBDELAY_MIN            0.0f\n#define DSFX_I3DL2REVERB_REVERBDELAY_MAX            0.1f\n#define DSFX_I3DL2REVERB_REVERBDELAY_DEFAULT        0.011f\n\n#define DSFX_I3DL2REVERB_DIFFUSION_MIN              0.0f\n#define DSFX_I3DL2REVERB_DIFFUSION_MAX              100.0f\n#define DSFX_I3DL2REVERB_DIFFUSION_DEFAULT          100.0f\n\n#define DSFX_I3DL2REVERB_DENSITY_MIN                0.0f\n#define DSFX_I3DL2REVERB_DENSITY_MAX                100.0f\n#define DSFX_I3DL2REVERB_DENSITY_DEFAULT            100.0f\n\n#define DSFX_I3DL2REVERB_HFREFERENCE_MIN            20.0f\n#define DSFX_I3DL2REVERB_HFREFERENCE_MAX            20000.0f\n#define DSFX_I3DL2REVERB_HFREFERENCE_DEFAULT        5000.0f\n\n#define DSFX_I3DL2REVERB_QUALITY_MIN                0\n#define DSFX_I3DL2REVERB_QUALITY_MAX                3\n#define DSFX_I3DL2REVERB_QUALITY_DEFAULT            2\n\n#undef INTERFACE\n#define INTERFACE IDirectSoundFXI3DL2Reverb\n\nDECLARE_INTERFACE_(IDirectSoundFXI3DL2Reverb, IUnknown)\n{\n    // IUnknown methods\n    STDMETHOD(QueryInterface)       (THIS_ REFIID, LPVOID *) PURE;\n    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;\n    STDMETHOD_(ULONG,Release)       (THIS) PURE;\n\n    // IDirectSoundFXI3DL2Reverb methods\n    STDMETHOD(SetAllParameters)     (THIS_ LPCDSFXI3DL2Reverb pcDsFxI3DL2Reverb) PURE;\n    STDMETHOD(GetAllParameters)     (THIS_ LPDSFXI3DL2Reverb pDsFxI3DL2Reverb) PURE;\n    STDMETHOD(SetPreset)            (THIS_ DWORD dwPreset) PURE;\n    STDMETHOD(GetPreset)            (THIS_ LPDWORD pdwPreset) PURE;\n    STDMETHOD(SetQuality)           (THIS_ LONG lQuality) PURE;\n    STDMETHOD(GetQuality)           (THIS_ LONG *plQuality) PURE;\n};\n\n#define IDirectSoundFXI3DL2Reverb_QueryInterface(p,a,b)     IUnknown_QueryInterface(p,a,b)\n#define IDirectSoundFXI3DL2Reverb_AddRef(p)                 IUnknown_AddRef(p)\n#define IDirectSoundFXI3DL2Reverb_Release(p)                IUnknown_Release(p)\n\n#if !defined(__cplusplus) || defined(CINTERFACE)\n#define IDirectSoundFXI3DL2Reverb_SetAllParameters(p,a)     (p)->lpVtbl->SetAllParameters(p,a)\n#define IDirectSoundFXI3DL2Reverb_GetAllParameters(p,a)     (p)->lpVtbl->GetAllParameters(p,a)\n#define IDirectSoundFXI3DL2Reverb_SetPreset(p,a)            (p)->lpVtbl->SetPreset(p,a)\n#define IDirectSoundFXI3DL2Reverb_GetPreset(p,a)            (p)->lpVtbl->GetPreset(p,a)\n#else // !defined(__cplusplus) || defined(CINTERFACE)\n#define IDirectSoundFXI3DL2Reverb_SetAllParameters(p,a)     (p)->SetAllParameters(a)\n#define IDirectSoundFXI3DL2Reverb_GetAllParameters(p,a)     (p)->GetAllParameters(a)\n#define IDirectSoundFXI3DL2Reverb_SetPreset(p,a)            (p)->SetPreset(a)\n#define IDirectSoundFXI3DL2Reverb_GetPreset(p,a)            (p)->GetPreset(a)\n#endif // !defined(__cplusplus) || defined(CINTERFACE)\n\n//\n// IDirectSoundFXWavesReverb\n//\n\nDEFINE_GUID(IID_IDirectSoundFXWavesReverb,0x46858c3a,0x0dc6,0x45e3,0xb7,0x60,0xd4,0xee,0xf1,0x6c,0xb3,0x25);\n\ntypedef struct _DSFXWavesReverb\n{\n    FLOAT   fInGain;                // [-96.0,0.0]            default: 0.0 dB\n    FLOAT   fReverbMix;             // [-96.0,0.0]            default: 0.0 db\n    FLOAT   fReverbTime;            // [0.001,3000.0]         default: 1000.0 ms\n    FLOAT   fHighFreqRTRatio;       // [0.001,0.999]          default: 0.001\n} DSFXWavesReverb, *LPDSFXWavesReverb;\n\ntypedef const DSFXWavesReverb *LPCDSFXWavesReverb;\n\n#define DSFX_WAVESREVERB_INGAIN_MIN                 -96.0f\n#define DSFX_WAVESREVERB_INGAIN_MAX                 0.0f\n#define DSFX_WAVESREVERB_INGAIN_DEFAULT             0.0f\n#define DSFX_WAVESREVERB_REVERBMIX_MIN              -96.0f\n#define DSFX_WAVESREVERB_REVERBMIX_MAX              0.0f\n#define DSFX_WAVESREVERB_REVERBMIX_DEFAULT          0.0f\n#define DSFX_WAVESREVERB_REVERBTIME_MIN             0.001f\n#define DSFX_WAVESREVERB_REVERBTIME_MAX             3000.0f\n#define DSFX_WAVESREVERB_REVERBTIME_DEFAULT         1000.0f\n#define DSFX_WAVESREVERB_HIGHFREQRTRATIO_MIN        0.001f\n#define DSFX_WAVESREVERB_HIGHFREQRTRATIO_MAX        0.999f\n#define DSFX_WAVESREVERB_HIGHFREQRTRATIO_DEFAULT    0.001f\n\n#undef INTERFACE\n#define INTERFACE IDirectSoundFXWavesReverb\n\nDECLARE_INTERFACE_(IDirectSoundFXWavesReverb, IUnknown)\n{\n    // IUnknown methods\n    STDMETHOD(QueryInterface)       (THIS_ REFIID, LPVOID *) PURE;\n    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;\n    STDMETHOD_(ULONG,Release)       (THIS) PURE;\n\n    // IDirectSoundFXWavesReverb methods\n    STDMETHOD(SetAllParameters)     (THIS_ LPCDSFXWavesReverb pcDsFxWavesReverb) PURE;\n    STDMETHOD(GetAllParameters)     (THIS_ LPDSFXWavesReverb pDsFxWavesReverb) PURE;\n};\n\n#define IDirectSoundFXWavesReverb_QueryInterface(p,a,b)     IUnknown_QueryInterface(p,a,b)\n#define IDirectSoundFXWavesReverb_AddRef(p)                 IUnknown_AddRef(p)\n#define IDirectSoundFXWavesReverb_Release(p)                IUnknown_Release(p)\n\n#if !defined(__cplusplus) || defined(CINTERFACE)\n#define IDirectSoundFXWavesReverb_SetAllParameters(p,a)     (p)->lpVtbl->SetAllParameters(p,a)\n#define IDirectSoundFXWavesReverb_GetAllParameters(p,a)     (p)->lpVtbl->GetAllParameters(p,a)\n#else // !defined(__cplusplus) || defined(CINTERFACE)\n#define IDirectSoundFXWavesReverb_SetAllParameters(p,a)     (p)->SetAllParameters(a)\n#define IDirectSoundFXWavesReverb_GetAllParameters(p,a)     (p)->GetAllParameters(a)\n#endif // !defined(__cplusplus) || defined(CINTERFACE)\n\n//\n// IDirectSoundCaptureFXAec\n//\n\nDEFINE_GUID(IID_IDirectSoundCaptureFXAec, 0xad74143d, 0x903d, 0x4ab7, 0x80, 0x66, 0x28, 0xd3, 0x63, 0x03, 0x6d, 0x65);\n\ntypedef struct _DSCFXAec\n{\n    BOOL    fEnable;\n    BOOL    fNoiseFill;\n    DWORD   dwMode;\n} DSCFXAec, *LPDSCFXAec;\n\ntypedef const DSCFXAec *LPCDSCFXAec;\n\n// These match the AEC_MODE_* constants in the DDK's ksmedia.h file\n#define DSCFX_AEC_MODE_PASS_THROUGH                     0x0\n#define DSCFX_AEC_MODE_HALF_DUPLEX                      0x1\n#define DSCFX_AEC_MODE_FULL_DUPLEX                      0x2\n\n// These match the AEC_STATUS_* constants in ksmedia.h\n#define DSCFX_AEC_STATUS_HISTORY_UNINITIALIZED          0x0\n#define DSCFX_AEC_STATUS_HISTORY_CONTINUOUSLY_CONVERGED 0x1\n#define DSCFX_AEC_STATUS_HISTORY_PREVIOUSLY_DIVERGED    0x2\n#define DSCFX_AEC_STATUS_CURRENTLY_CONVERGED            0x8\n\n#undef INTERFACE\n#define INTERFACE IDirectSoundCaptureFXAec\n\nDECLARE_INTERFACE_(IDirectSoundCaptureFXAec, IUnknown)\n{\n    // IUnknown methods\n    STDMETHOD(QueryInterface)       (THIS_ REFIID, LPVOID *) PURE;\n    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;\n    STDMETHOD_(ULONG,Release)       (THIS) PURE;\n\n    // IDirectSoundCaptureFXAec methods\n    STDMETHOD(SetAllParameters)     (THIS_ LPCDSCFXAec pDscFxAec) PURE;\n    STDMETHOD(GetAllParameters)     (THIS_ LPDSCFXAec pDscFxAec) PURE;\n    STDMETHOD(GetStatus)            (THIS_ PDWORD pdwStatus) PURE;\n    STDMETHOD(Reset)                (THIS) PURE;\n};\n\n#define IDirectSoundCaptureFXAec_QueryInterface(p,a,b)     IUnknown_QueryInterface(p,a,b)\n#define IDirectSoundCaptureFXAec_AddRef(p)                 IUnknown_AddRef(p)\n#define IDirectSoundCaptureFXAec_Release(p)                IUnknown_Release(p)\n\n#if !defined(__cplusplus) || defined(CINTERFACE)\n#define IDirectSoundCaptureFXAec_SetAllParameters(p,a)     (p)->lpVtbl->SetAllParameters(p,a)\n#define IDirectSoundCaptureFXAec_GetAllParameters(p,a)     (p)->lpVtbl->GetAllParameters(p,a)\n#else // !defined(__cplusplus) || defined(CINTERFACE)\n#define IDirectSoundCaptureFXAec_SetAllParameters(p,a)     (p)->SetAllParameters(a)\n#define IDirectSoundCaptureFXAec_GetAllParameters(p,a)     (p)->GetAllParameters(a)\n#endif // !defined(__cplusplus) || defined(CINTERFACE)\n\n\n//\n// IDirectSoundCaptureFXNoiseSuppress\n//\n\nDEFINE_GUID(IID_IDirectSoundCaptureFXNoiseSuppress, 0xed311e41, 0xfbae, 0x4175, 0x96, 0x25, 0xcd, 0x8, 0x54, 0xf6, 0x93, 0xca);\n\ntypedef struct _DSCFXNoiseSuppress\n{\n    BOOL    fEnable;\n} DSCFXNoiseSuppress, *LPDSCFXNoiseSuppress;\n\ntypedef const DSCFXNoiseSuppress *LPCDSCFXNoiseSuppress;\n\n#undef INTERFACE\n#define INTERFACE IDirectSoundCaptureFXNoiseSuppress\n\nDECLARE_INTERFACE_(IDirectSoundCaptureFXNoiseSuppress, IUnknown)\n{\n    // IUnknown methods\n    STDMETHOD(QueryInterface)       (THIS_ REFIID, LPVOID *) PURE;\n    STDMETHOD_(ULONG,AddRef)        (THIS) PURE;\n    STDMETHOD_(ULONG,Release)       (THIS) PURE;\n\n    // IDirectSoundCaptureFXNoiseSuppress methods\n    STDMETHOD(SetAllParameters)     (THIS_ LPCDSCFXNoiseSuppress pcDscFxNoiseSuppress) PURE;\n    STDMETHOD(GetAllParameters)     (THIS_ LPDSCFXNoiseSuppress pDscFxNoiseSuppress) PURE;\n    STDMETHOD(Reset)                (THIS) PURE;\n};\n\n#define IDirectSoundCaptureFXNoiseSuppress_QueryInterface(p,a,b)     IUnknown_QueryInterface(p,a,b)\n#define IDirectSoundCaptureFXNoiseSuppress_AddRef(p)                 IUnknown_AddRef(p)\n#define IDirectSoundCaptureFXNoiseSuppress_Release(p)                IUnknown_Release(p)\n\n#if !defined(__cplusplus) || defined(CINTERFACE)\n#define IDirectSoundCaptureFXNoiseSuppress_SetAllParameters(p,a)     (p)->lpVtbl->SetAllParameters(p,a)\n#define IDirectSoundCaptureFXNoiseSuppress_GetAllParameters(p,a)     (p)->lpVtbl->GetAllParameters(p,a)\n#else // !defined(__cplusplus) || defined(CINTERFACE)\n#define IDirectSoundCaptureFXNoiseSuppress_SetAllParameters(p,a)     (p)->SetAllParameters(a)\n#define IDirectSoundCaptureFXNoiseSuppress_GetAllParameters(p,a)     (p)->GetAllParameters(a)\n#endif // !defined(__cplusplus) || defined(CINTERFACE)\n\n\n//\n// IDirectSoundFullDuplex\n//\n\n#ifndef _IDirectSoundFullDuplex_\n#define _IDirectSoundFullDuplex_\n\n#ifdef __cplusplus\n// 'struct' not 'class' per the way DECLARE_INTERFACE_ is defined\nstruct IDirectSoundFullDuplex;\n#endif // __cplusplus\n\ntypedef struct IDirectSoundFullDuplex *LPDIRECTSOUNDFULLDUPLEX;\n\nDEFINE_GUID(IID_IDirectSoundFullDuplex, 0xedcb4c7a, 0xdaab, 0x4216, 0xa4, 0x2e, 0x6c, 0x50, 0x59, 0x6d, 0xdc, 0x1d);\n\n#undef INTERFACE\n#define INTERFACE IDirectSoundFullDuplex\n\nDECLARE_INTERFACE_(IDirectSoundFullDuplex, IUnknown)\n{\n    // IUnknown methods\n    STDMETHOD(QueryInterface)   (THIS_ REFIID, LPVOID *) PURE;\n    STDMETHOD_(ULONG,AddRef)    (THIS) PURE;\n    STDMETHOD_(ULONG,Release)   (THIS) PURE;\n\n    // IDirectSoundFullDuplex methods\n    STDMETHOD(Initialize)     (THIS_ LPCGUID pCaptureGuid, LPCGUID pRenderGuid, LPCDSCBUFFERDESC lpDscBufferDesc, LPCDSBUFFERDESC lpDsBufferDesc, HWND hWnd, DWORD dwLevel, LPLPDIRECTSOUNDCAPTUREBUFFER8 lplpDirectSoundCaptureBuffer8, LPLPDIRECTSOUNDBUFFER8 lplpDirectSoundBuffer8) PURE;\n};\n\n#define IDirectSoundFullDuplex_QueryInterface(p,a,b)    IUnknown_QueryInterface(p,a,b)\n#define IDirectSoundFullDuplex_AddRef(p)                IUnknown_AddRef(p)\n#define IDirectSoundFullDuplex_Release(p)               IUnknown_Release(p)\n\n#if !defined(__cplusplus) || defined(CINTERFACE)\n#define IDirectSoundFullDuplex_Initialize(p,a,b,c,d,e,f,g,h)     (p)->lpVtbl->Initialize(p,a,b,c,d,e,f,g,h)\n#else // !defined(__cplusplus) || defined(CINTERFACE)\n#define IDirectSoundFullDuplex_Initialize(p,a,b,c,d,e,f,g,h)     (p)->Initialize(a,b,c,d,e,f,g,h)\n#endif // !defined(__cplusplus) || defined(CINTERFACE)\n\n#endif // _IDirectSoundFullDuplex_\n\n#endif // DIRECTSOUND_VERSION >= 0x0800\n\n//\n// Return Codes\n//\n\n// The function completed successfully\n#define DS_OK                           S_OK\n\n// The call succeeded, but we had to substitute the 3D algorithm\n#define DS_NO_VIRTUALIZATION            MAKE_HRESULT(0, _FACDS, 10)\n\n// The call failed because resources (such as a priority level)\n// were already being used by another caller\n#define DSERR_ALLOCATED                 MAKE_DSHRESULT(10)\n\n// The control (vol, pan, etc.) requested by the caller is not available\n#define DSERR_CONTROLUNAVAIL            MAKE_DSHRESULT(30)\n\n// An invalid parameter was passed to the returning function\n#define DSERR_INVALIDPARAM              E_INVALIDARG\n\n// This call is not valid for the current state of this object\n#define DSERR_INVALIDCALL               MAKE_DSHRESULT(50)\n\n// An undetermined error occurred inside the DirectSound subsystem\n#define DSERR_GENERIC                   E_FAIL\n\n// The caller does not have the priority level required for the function to\n// succeed\n#define DSERR_PRIOLEVELNEEDED           MAKE_DSHRESULT(70)\n\n// Not enough free memory is available to complete the operation\n#define DSERR_OUTOFMEMORY               E_OUTOFMEMORY\n\n// The specified WAVE format is not supported\n#define DSERR_BADFORMAT                 MAKE_DSHRESULT(100)\n\n// The function called is not supported at this time\n#define DSERR_UNSUPPORTED               E_NOTIMPL\n\n// No sound driver is available for use\n#define DSERR_NODRIVER                  MAKE_DSHRESULT(120)\n// This object is already initialized\n#define DSERR_ALREADYINITIALIZED        MAKE_DSHRESULT(130)\n\n// This object does not support aggregation\n#define DSERR_NOAGGREGATION             CLASS_E_NOAGGREGATION\n\n// The buffer memory has been lost, and must be restored\n#define DSERR_BUFFERLOST                MAKE_DSHRESULT(150)\n\n// Another app has a higher priority level, preventing this call from\n// succeeding\n#define DSERR_OTHERAPPHASPRIO           MAKE_DSHRESULT(160)\n\n// This object has not been initialized\n#define DSERR_UNINITIALIZED             MAKE_DSHRESULT(170)\n\n// The requested COM interface is not available\n#define DSERR_NOINTERFACE               E_NOINTERFACE\n\n// Access is denied\n#define DSERR_ACCESSDENIED              E_ACCESSDENIED\n\n// Tried to create a DSBCAPS_CTRLFX buffer shorter than DSBSIZE_FX_MIN milliseconds\n#define DSERR_BUFFERTOOSMALL            MAKE_DSHRESULT(180)\n\n// Attempt to use DirectSound 8 functionality on an older DirectSound object\n#define DSERR_DS8_REQUIRED              MAKE_DSHRESULT(190)\n\n// A circular loop of send effects was detected\n#define DSERR_SENDLOOP                  MAKE_DSHRESULT(200)\n\n// The GUID specified in an audiopath file does not match a valid MIXIN buffer\n#define DSERR_BADSENDBUFFERGUID         MAKE_DSHRESULT(210)\n\n// The object requested was not found (numerically equal to DMUS_E_NOT_FOUND)\n#define DSERR_OBJECTNOTFOUND            MAKE_DSHRESULT(4449)\n\n// The effects requested could not be found on the system, or they were found\n// but in the wrong order, or in the wrong hardware/software locations.\n#define DSERR_FXUNAVAILABLE             MAKE_DSHRESULT(220)\n\n//\n// Flags\n//\n\n#define DSCAPS_PRIMARYMONO          0x00000001\n#define DSCAPS_PRIMARYSTEREO        0x00000002\n#define DSCAPS_PRIMARY8BIT          0x00000004\n#define DSCAPS_PRIMARY16BIT         0x00000008\n#define DSCAPS_CONTINUOUSRATE       0x00000010\n#define DSCAPS_EMULDRIVER           0x00000020\n#define DSCAPS_CERTIFIED            0x00000040\n#define DSCAPS_SECONDARYMONO        0x00000100\n#define DSCAPS_SECONDARYSTEREO      0x00000200\n#define DSCAPS_SECONDARY8BIT        0x00000400\n#define DSCAPS_SECONDARY16BIT       0x00000800\n\n#define DSSCL_NORMAL                0x00000001\n#define DSSCL_PRIORITY              0x00000002\n#define DSSCL_EXCLUSIVE             0x00000003\n#define DSSCL_WRITEPRIMARY          0x00000004\n\n#define DSSPEAKER_DIRECTOUT         0x00000000\n#define DSSPEAKER_HEADPHONE         0x00000001\n#define DSSPEAKER_MONO              0x00000002\n#define DSSPEAKER_QUAD              0x00000003\n#define DSSPEAKER_STEREO            0x00000004\n#define DSSPEAKER_SURROUND          0x00000005\n#define DSSPEAKER_5POINT1           0x00000006  // obsolete 5.1 setting\n#define DSSPEAKER_7POINT1           0x00000007  // obsolete 7.1 setting\n#define DSSPEAKER_7POINT1_SURROUND  0x00000008  // correct 7.1 Home Theater setting\n#define DSSPEAKER_7POINT1_WIDE      DSSPEAKER_7POINT1\n#if (DIRECTSOUND_VERSION >= 0x1000)\n    #define DSSPEAKER_5POINT1_SURROUND  0x00000009  // correct 5.1 setting\n    #define DSSPEAKER_5POINT1_BACK      DSSPEAKER_5POINT1\n#endif\n\n#define DSSPEAKER_GEOMETRY_MIN      0x00000005  //   5 degrees\n#define DSSPEAKER_GEOMETRY_NARROW   0x0000000A  //  10 degrees\n#define DSSPEAKER_GEOMETRY_WIDE     0x00000014  //  20 degrees\n#define DSSPEAKER_GEOMETRY_MAX      0x000000B4  // 180 degrees\n\n#define DSSPEAKER_COMBINED(c, g)    ((DWORD)(((BYTE)(c)) | ((DWORD)((BYTE)(g))) << 16))\n#define DSSPEAKER_CONFIG(a)         ((BYTE)(a))\n#define DSSPEAKER_GEOMETRY(a)       ((BYTE)(((DWORD)(a) >> 16) & 0x00FF))\n\n#define DSBCAPS_PRIMARYBUFFER       0x00000001\n#define DSBCAPS_STATIC              0x00000002\n#define DSBCAPS_LOCHARDWARE         0x00000004\n#define DSBCAPS_LOCSOFTWARE         0x00000008\n#define DSBCAPS_CTRL3D              0x00000010\n#define DSBCAPS_CTRLFREQUENCY       0x00000020\n#define DSBCAPS_CTRLPAN             0x00000040\n#define DSBCAPS_CTRLVOLUME          0x00000080\n#define DSBCAPS_CTRLPOSITIONNOTIFY  0x00000100\n#define DSBCAPS_CTRLFX              0x00000200\n#define DSBCAPS_STICKYFOCUS         0x00004000\n#define DSBCAPS_GLOBALFOCUS         0x00008000\n#define DSBCAPS_GETCURRENTPOSITION2 0x00010000\n#define DSBCAPS_MUTE3DATMAXDISTANCE 0x00020000\n#define DSBCAPS_LOCDEFER            0x00040000\n#if (DIRECTSOUND_VERSION >= 0x1000)\n    // Force GetCurrentPosition() to return a buffer's true play position;\n    // unmodified by aids to enhance backward compatibility.\n    #define DSBCAPS_TRUEPLAYPOSITION    0x00080000\n#endif\n\n#define DSBPLAY_LOOPING             0x00000001\n#define DSBPLAY_LOCHARDWARE         0x00000002\n#define DSBPLAY_LOCSOFTWARE         0x00000004\n#define DSBPLAY_TERMINATEBY_TIME    0x00000008\n#define DSBPLAY_TERMINATEBY_DISTANCE    0x000000010\n#define DSBPLAY_TERMINATEBY_PRIORITY    0x000000020\n\n#define DSBSTATUS_PLAYING           0x00000001\n#define DSBSTATUS_BUFFERLOST        0x00000002\n#define DSBSTATUS_LOOPING           0x00000004\n#define DSBSTATUS_LOCHARDWARE       0x00000008\n#define DSBSTATUS_LOCSOFTWARE       0x00000010\n#define DSBSTATUS_TERMINATED        0x00000020\n\n#define DSBLOCK_FROMWRITECURSOR     0x00000001\n#define DSBLOCK_ENTIREBUFFER        0x00000002\n\n#define DSBFREQUENCY_ORIGINAL       0\n#define DSBFREQUENCY_MIN            100\n#if DIRECTSOUND_VERSION >= 0x0900\n#define DSBFREQUENCY_MAX            200000\n#else\n#define DSBFREQUENCY_MAX            100000\n#endif\n\n#define DSBPAN_LEFT                 -10000\n#define DSBPAN_CENTER               0\n#define DSBPAN_RIGHT                10000\n\n#define DSBVOLUME_MIN               -10000\n#define DSBVOLUME_MAX               0\n\n#define DSBSIZE_MIN                 4\n#define DSBSIZE_MAX                 0x0FFFFFFF\n#define DSBSIZE_FX_MIN              150  // NOTE: Milliseconds, not bytes\n\n#define DSBNOTIFICATIONS_MAX        100000UL\n\n#define DS3DMODE_NORMAL             0x00000000\n#define DS3DMODE_HEADRELATIVE       0x00000001\n#define DS3DMODE_DISABLE            0x00000002\n\n#define DS3D_IMMEDIATE              0x00000000\n#define DS3D_DEFERRED               0x00000001\n\n#define DS3D_MINDISTANCEFACTOR      FLT_MIN\n#define DS3D_MAXDISTANCEFACTOR      FLT_MAX\n#define DS3D_DEFAULTDISTANCEFACTOR  1.0f\n\n#define DS3D_MINROLLOFFFACTOR       0.0f\n#define DS3D_MAXROLLOFFFACTOR       10.0f\n#define DS3D_DEFAULTROLLOFFFACTOR   1.0f\n\n#define DS3D_MINDOPPLERFACTOR       0.0f\n#define DS3D_MAXDOPPLERFACTOR       10.0f\n#define DS3D_DEFAULTDOPPLERFACTOR   1.0f\n\n#define DS3D_DEFAULTMINDISTANCE     1.0f\n#define DS3D_DEFAULTMAXDISTANCE     1000000000.0f\n\n#define DS3D_MINCONEANGLE           0\n#define DS3D_MAXCONEANGLE           360\n#define DS3D_DEFAULTCONEANGLE       360\n\n#define DS3D_DEFAULTCONEOUTSIDEVOLUME DSBVOLUME_MAX\n\n// IDirectSoundCapture attributes\n\n#define DSCCAPS_EMULDRIVER          DSCAPS_EMULDRIVER\n#define DSCCAPS_CERTIFIED           DSCAPS_CERTIFIED\n#define DSCCAPS_MULTIPLECAPTURE     0x00000001\n\n// IDirectSoundCaptureBuffer attributes\n\n#define DSCBCAPS_WAVEMAPPED         0x80000000\n\n#if DIRECTSOUND_VERSION >= 0x0800\n#define DSCBCAPS_CTRLFX             0x00000200\n#endif\n\n\n#define DSCBLOCK_ENTIREBUFFER       0x00000001\n\n#define DSCBSTATUS_CAPTURING        0x00000001\n#define DSCBSTATUS_LOOPING          0x00000002\n\n#define DSCBSTART_LOOPING           0x00000001\n\n#define DSBPN_OFFSETSTOP            0xFFFFFFFF\n\n#define DS_CERTIFIED                0x00000000\n#define DS_UNCERTIFIED              0x00000001\n\n\n//\n// Flags for the I3DL2 effects\n//\n\n//\n// I3DL2 Material Presets\n//\n\nenum\n{\n    DSFX_I3DL2_MATERIAL_PRESET_SINGLEWINDOW,\n    DSFX_I3DL2_MATERIAL_PRESET_DOUBLEWINDOW,\n    DSFX_I3DL2_MATERIAL_PRESET_THINDOOR,\n    DSFX_I3DL2_MATERIAL_PRESET_THICKDOOR,\n    DSFX_I3DL2_MATERIAL_PRESET_WOODWALL,\n    DSFX_I3DL2_MATERIAL_PRESET_BRICKWALL,\n    DSFX_I3DL2_MATERIAL_PRESET_STONEWALL,\n    DSFX_I3DL2_MATERIAL_PRESET_CURTAIN\n};\n\n#define I3DL2_MATERIAL_PRESET_SINGLEWINDOW    -2800,0.71f\n#define I3DL2_MATERIAL_PRESET_DOUBLEWINDOW    -5000,0.40f\n#define I3DL2_MATERIAL_PRESET_THINDOOR        -1800,0.66f\n#define I3DL2_MATERIAL_PRESET_THICKDOOR       -4400,0.64f\n#define I3DL2_MATERIAL_PRESET_WOODWALL        -4000,0.50f\n#define I3DL2_MATERIAL_PRESET_BRICKWALL       -5000,0.60f\n#define I3DL2_MATERIAL_PRESET_STONEWALL       -6000,0.68f\n#define I3DL2_MATERIAL_PRESET_CURTAIN         -1200,0.15f\n\nenum\n{\n    DSFX_I3DL2_ENVIRONMENT_PRESET_DEFAULT,\n    DSFX_I3DL2_ENVIRONMENT_PRESET_GENERIC,\n    DSFX_I3DL2_ENVIRONMENT_PRESET_PADDEDCELL,\n    DSFX_I3DL2_ENVIRONMENT_PRESET_ROOM,\n    DSFX_I3DL2_ENVIRONMENT_PRESET_BATHROOM,\n    DSFX_I3DL2_ENVIRONMENT_PRESET_LIVINGROOM,\n    DSFX_I3DL2_ENVIRONMENT_PRESET_STONEROOM,\n    DSFX_I3DL2_ENVIRONMENT_PRESET_AUDITORIUM,\n    DSFX_I3DL2_ENVIRONMENT_PRESET_CONCERTHALL,\n    DSFX_I3DL2_ENVIRONMENT_PRESET_CAVE,\n    DSFX_I3DL2_ENVIRONMENT_PRESET_ARENA,\n    DSFX_I3DL2_ENVIRONMENT_PRESET_HANGAR,\n    DSFX_I3DL2_ENVIRONMENT_PRESET_CARPETEDHALLWAY,\n    DSFX_I3DL2_ENVIRONMENT_PRESET_HALLWAY,\n    DSFX_I3DL2_ENVIRONMENT_PRESET_STONECORRIDOR,\n    DSFX_I3DL2_ENVIRONMENT_PRESET_ALLEY,\n    DSFX_I3DL2_ENVIRONMENT_PRESET_FOREST,\n    DSFX_I3DL2_ENVIRONMENT_PRESET_CITY,\n    DSFX_I3DL2_ENVIRONMENT_PRESET_MOUNTAINS,\n    DSFX_I3DL2_ENVIRONMENT_PRESET_QUARRY,\n    DSFX_I3DL2_ENVIRONMENT_PRESET_PLAIN,\n    DSFX_I3DL2_ENVIRONMENT_PRESET_PARKINGLOT,\n    DSFX_I3DL2_ENVIRONMENT_PRESET_SEWERPIPE,\n    DSFX_I3DL2_ENVIRONMENT_PRESET_UNDERWATER,\n    DSFX_I3DL2_ENVIRONMENT_PRESET_SMALLROOM,\n    DSFX_I3DL2_ENVIRONMENT_PRESET_MEDIUMROOM,\n    DSFX_I3DL2_ENVIRONMENT_PRESET_LARGEROOM,\n    DSFX_I3DL2_ENVIRONMENT_PRESET_MEDIUMHALL,\n    DSFX_I3DL2_ENVIRONMENT_PRESET_LARGEHALL,\n    DSFX_I3DL2_ENVIRONMENT_PRESET_PLATE\n};\n\n//\n// I3DL2 Reverberation Presets Values\n//\n\n#define I3DL2_ENVIRONMENT_PRESET_DEFAULT         -1000, -100, 0.0f, 1.49f, 0.83f, -2602, 0.007f,   200, 0.011f, 100.0f, 100.0f, 5000.0f\n#define I3DL2_ENVIRONMENT_PRESET_GENERIC         -1000, -100, 0.0f, 1.49f, 0.83f, -2602, 0.007f,   200, 0.011f, 100.0f, 100.0f, 5000.0f\n#define I3DL2_ENVIRONMENT_PRESET_PADDEDCELL      -1000,-6000, 0.0f, 0.17f, 0.10f, -1204, 0.001f,   207, 0.002f, 100.0f, 100.0f, 5000.0f\n#define I3DL2_ENVIRONMENT_PRESET_ROOM            -1000, -454, 0.0f, 0.40f, 0.83f, -1646, 0.002f,    53, 0.003f, 100.0f, 100.0f, 5000.0f\n#define I3DL2_ENVIRONMENT_PRESET_BATHROOM        -1000,-1200, 0.0f, 1.49f, 0.54f,  -370, 0.007f,  1030, 0.011f, 100.0f,  60.0f, 5000.0f\n#define I3DL2_ENVIRONMENT_PRESET_LIVINGROOM      -1000,-6000, 0.0f, 0.50f, 0.10f, -1376, 0.003f, -1104, 0.004f, 100.0f, 100.0f, 5000.0f\n#define I3DL2_ENVIRONMENT_PRESET_STONEROOM       -1000, -300, 0.0f, 2.31f, 0.64f,  -711, 0.012f,    83, 0.017f, 100.0f, 100.0f, 5000.0f\n#define I3DL2_ENVIRONMENT_PRESET_AUDITORIUM      -1000, -476, 0.0f, 4.32f, 0.59f,  -789, 0.020f,  -289, 0.030f, 100.0f, 100.0f, 5000.0f\n#define I3DL2_ENVIRONMENT_PRESET_CONCERTHALL     -1000, -500, 0.0f, 3.92f, 0.70f, -1230, 0.020f,    -2, 0.029f, 100.0f, 100.0f, 5000.0f\n#define I3DL2_ENVIRONMENT_PRESET_CAVE            -1000,    0, 0.0f, 2.91f, 1.30f,  -602, 0.015f,  -302, 0.022f, 100.0f, 100.0f, 5000.0f\n#define I3DL2_ENVIRONMENT_PRESET_ARENA           -1000, -698, 0.0f, 7.24f, 0.33f, -1166, 0.020f,    16, 0.030f, 100.0f, 100.0f, 5000.0f\n#define I3DL2_ENVIRONMENT_PRESET_HANGAR          -1000,-1000, 0.0f,10.05f, 0.23f,  -602, 0.020f,   198, 0.030f, 100.0f, 100.0f, 5000.0f\n#define I3DL2_ENVIRONMENT_PRESET_CARPETEDHALLWAY -1000,-4000, 0.0f, 0.30f, 0.10f, -1831, 0.002f, -1630, 0.030f, 100.0f, 100.0f, 5000.0f\n#define I3DL2_ENVIRONMENT_PRESET_HALLWAY         -1000, -300, 0.0f, 1.49f, 0.59f, -1219, 0.007f,   441, 0.011f, 100.0f, 100.0f, 5000.0f\n#define I3DL2_ENVIRONMENT_PRESET_STONECORRIDOR   -1000, -237, 0.0f, 2.70f, 0.79f, -1214, 0.013f,   395, 0.020f, 100.0f, 100.0f, 5000.0f\n#define I3DL2_ENVIRONMENT_PRESET_ALLEY           -1000, -270, 0.0f, 1.49f, 0.86f, -1204, 0.007f,    -4, 0.011f, 100.0f, 100.0f, 5000.0f\n#define I3DL2_ENVIRONMENT_PRESET_FOREST          -1000,-3300, 0.0f, 1.49f, 0.54f, -2560, 0.162f,  -613, 0.088f,  79.0f, 100.0f, 5000.0f\n#define I3DL2_ENVIRONMENT_PRESET_CITY            -1000, -800, 0.0f, 1.49f, 0.67f, -2273, 0.007f, -2217, 0.011f,  50.0f, 100.0f, 5000.0f\n#define I3DL2_ENVIRONMENT_PRESET_MOUNTAINS       -1000,-2500, 0.0f, 1.49f, 0.21f, -2780, 0.300f, -2014, 0.100f,  27.0f, 100.0f, 5000.0f\n#define I3DL2_ENVIRONMENT_PRESET_QUARRY          -1000,-1000, 0.0f, 1.49f, 0.83f,-10000, 0.061f,   500, 0.025f, 100.0f, 100.0f, 5000.0f\n#define I3DL2_ENVIRONMENT_PRESET_PLAIN           -1000,-2000, 0.0f, 1.49f, 0.50f, -2466, 0.179f, -2514, 0.100f,  21.0f, 100.0f, 5000.0f\n#define I3DL2_ENVIRONMENT_PRESET_PARKINGLOT      -1000,    0, 0.0f, 1.65f, 1.50f, -1363, 0.008f, -1153, 0.012f, 100.0f, 100.0f, 5000.0f\n#define I3DL2_ENVIRONMENT_PRESET_SEWERPIPE       -1000,-1000, 0.0f, 2.81f, 0.14f,   429, 0.014f,   648, 0.021f,  80.0f,  60.0f, 5000.0f\n#define I3DL2_ENVIRONMENT_PRESET_UNDERWATER      -1000,-4000, 0.0f, 1.49f, 0.10f,  -449, 0.007f,  1700, 0.011f, 100.0f, 100.0f, 5000.0f\n\n//\n// Examples simulating 'musical' reverb presets\n//\n// Name       Decay time   Description\n// Small Room    1.1s      A small size room with a length of 5m or so.\n// Medium Room   1.3s      A medium size room with a length of 10m or so.\n// Large Room    1.5s      A large size room suitable for live performances.\n// Medium Hall   1.8s      A medium size concert hall.\n// Large Hall    1.8s      A large size concert hall suitable for a full orchestra.\n// Plate         1.3s      A plate reverb simulation.\n//\n\n#define I3DL2_ENVIRONMENT_PRESET_SMALLROOM       -1000, -600, 0.0f, 1.10f, 0.83f,  -400, 0.005f,   500, 0.010f, 100.0f, 100.0f, 5000.0f\n#define I3DL2_ENVIRONMENT_PRESET_MEDIUMROOM      -1000, -600, 0.0f, 1.30f, 0.83f, -1000, 0.010f,  -200, 0.020f, 100.0f, 100.0f, 5000.0f\n#define I3DL2_ENVIRONMENT_PRESET_LARGEROOM       -1000, -600, 0.0f, 1.50f, 0.83f, -1600, 0.020f, -1000, 0.040f, 100.0f, 100.0f, 5000.0f\n#define I3DL2_ENVIRONMENT_PRESET_MEDIUMHALL      -1000, -600, 0.0f, 1.80f, 0.70f, -1300, 0.015f,  -800, 0.030f, 100.0f, 100.0f, 5000.0f\n#define I3DL2_ENVIRONMENT_PRESET_LARGEHALL       -1000, -600, 0.0f, 1.80f, 0.70f, -2000, 0.030f, -1400, 0.060f, 100.0f, 100.0f, 5000.0f\n#define I3DL2_ENVIRONMENT_PRESET_PLATE           -1000, -200, 0.0f, 1.30f, 0.90f,     0, 0.002f,     0, 0.010f, 100.0f,  75.0f, 5000.0f\n\n//\n// DirectSound3D Algorithms\n//\n\n// Default DirectSound3D algorithm {00000000-0000-0000-0000-000000000000}\n#define DS3DALG_DEFAULT GUID_NULL\n\n// No virtualization (Pan3D) {C241333F-1C1B-11d2-94F5-00C04FC28ACA}\nDEFINE_GUID(DS3DALG_NO_VIRTUALIZATION, 0xc241333f, 0x1c1b, 0x11d2, 0x94, 0xf5, 0x0, 0xc0, 0x4f, 0xc2, 0x8a, 0xca);\n\n// High-quality HRTF algorithm {C2413340-1C1B-11d2-94F5-00C04FC28ACA}\nDEFINE_GUID(DS3DALG_HRTF_FULL, 0xc2413340, 0x1c1b, 0x11d2, 0x94, 0xf5, 0x0, 0xc0, 0x4f, 0xc2, 0x8a, 0xca);\n\n// Lower-quality HRTF algorithm {C2413342-1C1B-11d2-94F5-00C04FC28ACA}\nDEFINE_GUID(DS3DALG_HRTF_LIGHT, 0xc2413342, 0x1c1b, 0x11d2, 0x94, 0xf5, 0x0, 0xc0, 0x4f, 0xc2, 0x8a, 0xca);\n\n\n#if DIRECTSOUND_VERSION >= 0x0800\n\n//\n// DirectSound Internal Effect Algorithms\n//\n\n\n// Gargle {DAFD8210-5711-4B91-9FE3-F75B7AE279BF}\nDEFINE_GUID(GUID_DSFX_STANDARD_GARGLE, 0xdafd8210, 0x5711, 0x4b91, 0x9f, 0xe3, 0xf7, 0x5b, 0x7a, 0xe2, 0x79, 0xbf);\n\n// Chorus {EFE6629C-81F7-4281-BD91-C9D604A95AF6}\nDEFINE_GUID(GUID_DSFX_STANDARD_CHORUS, 0xefe6629c, 0x81f7, 0x4281, 0xbd, 0x91, 0xc9, 0xd6, 0x04, 0xa9, 0x5a, 0xf6);\n\n// Flanger {EFCA3D92-DFD8-4672-A603-7420894BAD98}\nDEFINE_GUID(GUID_DSFX_STANDARD_FLANGER, 0xefca3d92, 0xdfd8, 0x4672, 0xa6, 0x03, 0x74, 0x20, 0x89, 0x4b, 0xad, 0x98);\n\n// Echo/Delay {EF3E932C-D40B-4F51-8CCF-3F98F1B29D5D}\nDEFINE_GUID(GUID_DSFX_STANDARD_ECHO, 0xef3e932c, 0xd40b, 0x4f51, 0x8c, 0xcf, 0x3f, 0x98, 0xf1, 0xb2, 0x9d, 0x5d);\n\n// Distortion {EF114C90-CD1D-484E-96E5-09CFAF912A21}\nDEFINE_GUID(GUID_DSFX_STANDARD_DISTORTION, 0xef114c90, 0xcd1d, 0x484e, 0x96, 0xe5, 0x09, 0xcf, 0xaf, 0x91, 0x2a, 0x21);\n\n// Compressor/Limiter {EF011F79-4000-406D-87AF-BFFB3FC39D57}\nDEFINE_GUID(GUID_DSFX_STANDARD_COMPRESSOR, 0xef011f79, 0x4000, 0x406d, 0x87, 0xaf, 0xbf, 0xfb, 0x3f, 0xc3, 0x9d, 0x57);\n\n// Parametric Equalization {120CED89-3BF4-4173-A132-3CB406CF3231}\nDEFINE_GUID(GUID_DSFX_STANDARD_PARAMEQ, 0x120ced89, 0x3bf4, 0x4173, 0xa1, 0x32, 0x3c, 0xb4, 0x06, 0xcf, 0x32, 0x31);\n\n// I3DL2 Environmental Reverberation: Reverb (Listener) Effect {EF985E71-D5C7-42D4-BA4D-2D073E2E96F4}\nDEFINE_GUID(GUID_DSFX_STANDARD_I3DL2REVERB, 0xef985e71, 0xd5c7, 0x42d4, 0xba, 0x4d, 0x2d, 0x07, 0x3e, 0x2e, 0x96, 0xf4);\n\n// Waves Reverberation {87FC0268-9A55-4360-95AA-004A1D9DE26C}\nDEFINE_GUID(GUID_DSFX_WAVES_REVERB, 0x87fc0268, 0x9a55, 0x4360, 0x95, 0xaa, 0x00, 0x4a, 0x1d, 0x9d, 0xe2, 0x6c);\n\n//\n// DirectSound Capture Effect Algorithms\n//\n\n\n// Acoustic Echo Canceller {BF963D80-C559-11D0-8A2B-00A0C9255AC1}\n// Matches KSNODETYPE_ACOUSTIC_ECHO_CANCEL in ksmedia.h\nDEFINE_GUID(GUID_DSCFX_CLASS_AEC, 0xBF963D80L, 0xC559, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1);\n\n// Microsoft AEC {CDEBB919-379A-488a-8765-F53CFD36DE40}\nDEFINE_GUID(GUID_DSCFX_MS_AEC, 0xcdebb919, 0x379a, 0x488a, 0x87, 0x65, 0xf5, 0x3c, 0xfd, 0x36, 0xde, 0x40);\n\n// System AEC {1C22C56D-9879-4f5b-A389-27996DDC2810}\nDEFINE_GUID(GUID_DSCFX_SYSTEM_AEC, 0x1c22c56d, 0x9879, 0x4f5b, 0xa3, 0x89, 0x27, 0x99, 0x6d, 0xdc, 0x28, 0x10);\n\n// Noise Supression {E07F903F-62FD-4e60-8CDD-DEA7236665B5}\n// Matches KSNODETYPE_NOISE_SUPPRESS in post Windows ME DDK's ksmedia.h\nDEFINE_GUID(GUID_DSCFX_CLASS_NS, 0xe07f903f, 0x62fd, 0x4e60, 0x8c, 0xdd, 0xde, 0xa7, 0x23, 0x66, 0x65, 0xb5);\n\n// Microsoft Noise Suppresion {11C5C73B-66E9-4ba1-A0BA-E814C6EED92D}\nDEFINE_GUID(GUID_DSCFX_MS_NS, 0x11c5c73b, 0x66e9, 0x4ba1, 0xa0, 0xba, 0xe8, 0x14, 0xc6, 0xee, 0xd9, 0x2d);\n\n// System Noise Suppresion {5AB0882E-7274-4516-877D-4EEE99BA4FD0}\nDEFINE_GUID(GUID_DSCFX_SYSTEM_NS, 0x5ab0882e, 0x7274, 0x4516, 0x87, 0x7d, 0x4e, 0xee, 0x99, 0xba, 0x4f, 0xd0);\n\n#endif // DIRECTSOUND_VERSION >= 0x0800\n\n#endif // __DSOUND_INCLUDED__\n\n\n\n#ifdef __cplusplus\n};\n#endif // __cplusplus\n\n"
  },
  {
    "path": "rtaudio/include/ginclude.h",
    "content": "#ifndef __gInclude__\r\n#define __gInclude__\r\n\r\n#if SGI \r\n\t#undef BEOS \r\n\t#undef MAC \r\n\t#undef WINDOWS\r\n\t//\r\n\t#define ASIO_BIG_ENDIAN 1\r\n\t#define ASIO_CPU_MIPS 1\r\n#elif defined WIN32\r\n\t#undef BEOS \r\n\t#undef MAC \r\n\t#undef SGI\r\n\t#define WINDOWS 1\r\n\t#define ASIO_LITTLE_ENDIAN 1\r\n\t#define ASIO_CPU_X86 1\r\n#elif BEOS\r\n\t#undef MAC \r\n\t#undef SGI\r\n\t#undef WINDOWS\r\n\t#define ASIO_LITTLE_ENDIAN 1\r\n\t#define ASIO_CPU_X86 1\r\n\t//\r\n#else\r\n\t#define MAC 1\r\n\t#undef BEOS \r\n\t#undef WINDOWS\r\n\t#undef SGI\r\n\t#define ASIO_BIG_ENDIAN 1\r\n\t#define ASIO_CPU_PPC 1\r\n#endif\r\n\r\n// always\r\n#define NATIVE_INT64 0\r\n#define IEEE754_64FLOAT 1\r\n\r\n#endif\t// __gInclude__\r\n"
  },
  {
    "path": "rtaudio/include/iasiodrv.h",
    "content": "#include \"asiosys.h\"\r\n#include \"asio.h\"\r\n\r\n/* Forward Declarations */ \r\n\r\n#ifndef __ASIODRIVER_FWD_DEFINED__\r\n#define __ASIODRIVER_FWD_DEFINED__\r\ntypedef interface IASIO IASIO;\r\n#endif \t/* __ASIODRIVER_FWD_DEFINED__ */\r\n\r\ninterface IASIO : public IUnknown\r\n{\r\n\r\n\tvirtual ASIOBool init(void *sysHandle) = 0;\r\n\tvirtual void getDriverName(char *name) = 0;\t\r\n\tvirtual long getDriverVersion() = 0;\r\n\tvirtual void getErrorMessage(char *string) = 0;\t\r\n\tvirtual ASIOError start() = 0;\r\n\tvirtual ASIOError stop() = 0;\r\n\tvirtual ASIOError getChannels(long *numInputChannels, long *numOutputChannels) = 0;\r\n\tvirtual ASIOError getLatencies(long *inputLatency, long *outputLatency) = 0;\r\n\tvirtual ASIOError getBufferSize(long *minSize, long *maxSize,\r\n\t\tlong *preferredSize, long *granularity) = 0;\r\n\tvirtual ASIOError canSampleRate(ASIOSampleRate sampleRate) = 0;\r\n\tvirtual ASIOError getSampleRate(ASIOSampleRate *sampleRate) = 0;\r\n\tvirtual ASIOError setSampleRate(ASIOSampleRate sampleRate) = 0;\r\n\tvirtual ASIOError getClockSources(ASIOClockSource *clocks, long *numSources) = 0;\r\n\tvirtual ASIOError setClockSource(long reference) = 0;\r\n\tvirtual ASIOError getSamplePosition(ASIOSamples *sPos, ASIOTimeStamp *tStamp) = 0;\r\n\tvirtual ASIOError getChannelInfo(ASIOChannelInfo *info) = 0;\r\n\tvirtual ASIOError createBuffers(ASIOBufferInfo *bufferInfos, long numChannels,\r\n\t\tlong bufferSize, ASIOCallbacks *callbacks) = 0;\r\n\tvirtual ASIOError disposeBuffers() = 0;\r\n\tvirtual ASIOError controlPanel() = 0;\r\n\tvirtual ASIOError future(long selector,void *opt) = 0;\r\n\tvirtual ASIOError outputReady() = 0;\r\n};\r\n"
  },
  {
    "path": "rtaudio/include/iasiothiscallresolver.cpp",
    "content": "/*\n\tIASIOThiscallResolver.cpp see the comments in iasiothiscallresolver.h for\n    the top level description - this comment describes the technical details of\n    the implementation.\n\n    The latest version of this file is available from:\n    http://www.audiomulch.com/~rossb/code/calliasio\n\n    please email comments to Ross Bencina <rossb@audiomulch.com>\n\n    BACKGROUND\n\n    The IASIO interface declared in the Steinberg ASIO 2 SDK declares\n    functions with no explicit calling convention. This causes MSVC++ to default\n    to using the thiscall convention, which is a proprietary convention not\n    implemented by some non-microsoft compilers - notably borland BCC,\n    C++Builder, and gcc. MSVC++ is the defacto standard compiler used by\n    Steinberg. As a result of this situation, the ASIO sdk will compile with\n    any compiler, however attempting to execute the compiled code will cause a\n    crash due to different default calling conventions on non-Microsoft\n    compilers.\n\n    IASIOThiscallResolver solves the problem by providing an adapter class that\n    delegates to the IASIO interface using the correct calling convention\n    (thiscall). Due to the lack of support for thiscall in the Borland and GCC\n    compilers, the calls have been implemented in assembly language.\n\n    A number of macros are defined for thiscall function calls with different\n    numbers of parameters, with and without return values - it may be possible\n    to modify the format of these macros to make them work with other inline\n    assemblers.\n\n\n    THISCALL DEFINITION\n\n    A number of definitions of the thiscall calling convention are floating\n    around the internet. The following definition has been validated against\n    output from the MSVC++ compiler:\n\n    For non-vararg functions, thiscall works as follows: the object (this)\n    pointer is passed in ECX. All arguments are passed on the stack in\n    right to left order. The return value is placed in EAX. The callee\n    clears the passed arguments from the stack.\n\n\n    FINDING FUNCTION POINTERS FROM AN IASIO POINTER\n\n    The first field of a COM object is a pointer to its vtble. Thus a pointer\n    to an object implementing the IASIO interface also points to a pointer to\n    that object's vtbl. The vtble is a table of function pointers for all of\n    the virtual functions exposed by the implemented interfaces.\n\n    If we consider a variable declared as a pointer to IASO:\n\n    IASIO *theAsioDriver\n\n    theAsioDriver points to:\n\n    object implementing IASIO\n    {\n        IASIOvtbl *vtbl\n        other data\n    }\n\n    in other words, theAsioDriver points to a pointer to an IASIOvtbl\n\n    vtbl points to a table of function pointers:\n\n    IASIOvtbl ( interface IASIO : public IUnknown )\n    {\n    (IUnknown functions)\n    0   virtual HRESULT STDMETHODCALLTYPE (*QueryInterface)(REFIID riid, void **ppv) = 0;\n    4   virtual ULONG STDMETHODCALLTYPE (*AddRef)() = 0;\n    8   virtual ULONG STDMETHODCALLTYPE (*Release)() = 0;      \n\n    (IASIO functions)\n    12\tvirtual ASIOBool (*init)(void *sysHandle) = 0;\n    16\tvirtual void (*getDriverName)(char *name) = 0;\n    20\tvirtual long (*getDriverVersion)() = 0;\n    24\tvirtual void (*getErrorMessage)(char *string) = 0;\n    28\tvirtual ASIOError (*start)() = 0;\n    32\tvirtual ASIOError (*stop)() = 0;\n    36\tvirtual ASIOError (*getChannels)(long *numInputChannels, long *numOutputChannels) = 0;\n    40\tvirtual ASIOError (*getLatencies)(long *inputLatency, long *outputLatency) = 0;\n    44\tvirtual ASIOError (*getBufferSize)(long *minSize, long *maxSize,\n            long *preferredSize, long *granularity) = 0;\n    48\tvirtual ASIOError (*canSampleRate)(ASIOSampleRate sampleRate) = 0;\n    52\tvirtual ASIOError (*getSampleRate)(ASIOSampleRate *sampleRate) = 0;\n    56\tvirtual ASIOError (*setSampleRate)(ASIOSampleRate sampleRate) = 0;\n    60\tvirtual ASIOError (*getClockSources)(ASIOClockSource *clocks, long *numSources) = 0;\n    64\tvirtual ASIOError (*setClockSource)(long reference) = 0;\n    68\tvirtual ASIOError (*getSamplePosition)(ASIOSamples *sPos, ASIOTimeStamp *tStamp) = 0;\n    72\tvirtual ASIOError (*getChannelInfo)(ASIOChannelInfo *info) = 0;\n    76\tvirtual ASIOError (*createBuffers)(ASIOBufferInfo *bufferInfos, long numChannels,\n            long bufferSize, ASIOCallbacks *callbacks) = 0;\n    80\tvirtual ASIOError (*disposeBuffers)() = 0;\n    84\tvirtual ASIOError (*controlPanel)() = 0;\n    88\tvirtual ASIOError (*future)(long selector,void *opt) = 0;\n    92\tvirtual ASIOError (*outputReady)() = 0;\n    };\n\n    The numbers in the left column show the byte offset of each function ptr\n    from the beginning of the vtbl. These numbers are used in the code below\n    to select different functions.\n\n    In order to find the address of a particular function, theAsioDriver\n    must first be dereferenced to find the value of the vtbl pointer:\n\n    mov     eax, theAsioDriver\n    mov     edx, [theAsioDriver]  // edx now points to vtbl[0]\n\n    Then an offset must be added to the vtbl pointer to select a\n    particular function, for example vtbl+44 points to the slot containing\n    a pointer to the getBufferSize function.\n\n    Finally vtbl+x must be dereferenced to obtain the value of the function\n    pointer stored in that address:\n\n    call    [edx+44]    // call the function pointed to by\n                        // the value in the getBufferSize field of the vtbl\n\n\n    SEE ALSO\n\n    Martin Fay's OpenASIO DLL at http://www.martinfay.com solves the same\n    problem by providing a new COM interface which wraps IASIO with an\n    interface that uses portable calling conventions. OpenASIO must be compiled\n    with MSVC, and requires that you ship the OpenASIO DLL with your\n    application.\n\n    \n    ACKNOWLEDGEMENTS\n\n    Ross Bencina: worked out the thiscall details above, wrote the original\n    Borland asm macros, and a patch for asio.cpp (which is no longer needed).\n    Thanks to Martin Fay for introducing me to the issues discussed here,\n    and to Rene G. Ceballos for assisting with asm dumps from MSVC++.\n\n    Antti Silvast: converted the original calliasio to work with gcc and NASM\n    by implementing the asm code in a separate file.\n\n\tFraser Adams: modified the original calliasio containing the Borland inline\n    asm to add inline asm for gcc i.e. Intel syntax for Borland and AT&T syntax\n    for gcc. This seems a neater approach for gcc than to have a separate .asm\n    file and it means that we only need one version of the thiscall patch.\n\n    Fraser Adams: rewrote the original calliasio patch in the form of the\n    IASIOThiscallResolver class in order to avoid modifications to files from\n    the Steinberg SDK, which may have had potential licence issues.\n\n    Andrew Baldwin: contributed fixes for compatibility problems with more\n    recent versions of the gcc assembler.\n*/\n\n\n// We only need IASIOThiscallResolver at all if we are on Win32. For other\n// platforms we simply bypass the IASIOThiscallResolver definition to allow us\n// to be safely #include'd whatever the platform to keep client code portable\n#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) && !defined(_WIN64)\n\n\n// If microsoft compiler we can call IASIO directly so IASIOThiscallResolver\n// is not used.\n#if !defined(_MSC_VER)\n\n\n#include <new>\n#include <assert.h>\n\n// We have a mechanism in iasiothiscallresolver.h to ensure that asio.h is\n// #include'd before it in client code, we do NOT want to do this test here.\n#define iasiothiscallresolver_sourcefile 1\n#include \"iasiothiscallresolver.h\"\n#undef iasiothiscallresolver_sourcefile\n\n// iasiothiscallresolver.h redefines ASIOInit for clients, but we don't want\n// this macro defined in this translation unit.\n#undef ASIOInit\n\n\n// theAsioDriver is a global pointer to the current IASIO instance which the\n// ASIO SDK uses to perform all actions on the IASIO interface. We substitute\n// our own forwarding interface into this pointer.\nextern IASIO* theAsioDriver;\n\n\n// The following macros define the inline assembler for BORLAND first then gcc\n\n#if defined(__BCPLUSPLUS__) || defined(__BORLANDC__)          \n\n\n#define CALL_THISCALL_0( resultName, thisPtr, funcOffset )\\\n    void *this_ = (thisPtr);                                                \\\n    __asm {                                                                 \\\n        mov     ecx, this_            ;                                     \\\n        mov     eax, [ecx]            ;                                     \\\n        call    [eax+funcOffset]      ;                                     \\\n        mov     resultName, eax       ;                                     \\\n    }\n\n\n#define CALL_VOID_THISCALL_1( thisPtr, funcOffset, param1 )\\\n    void *this_ = (thisPtr);                                                \\\n    __asm {                                                                 \\\n        mov     eax, param1           ;                                     \\\n        push    eax                   ;                                     \\\n        mov     ecx, this_            ;                                     \\\n        mov     eax, [ecx]            ;                                     \\\n        call    [eax+funcOffset]      ;                                     \\\n    }\n\n\n#define CALL_THISCALL_1( resultName, thisPtr, funcOffset, param1 )\\\n    void *this_ = (thisPtr);                                                \\\n    __asm {                                                                 \\\n        mov     eax, param1           ;                                     \\\n        push    eax                   ;                                     \\\n        mov     ecx, this_            ;                                     \\\n        mov     eax, [ecx]            ;                                     \\\n        call    [eax+funcOffset]      ;                                     \\\n        mov     resultName, eax       ;                                     \\\n    }\n\n\n#define CALL_THISCALL_1_DOUBLE( resultName, thisPtr, funcOffset, param1 )\\\n    void *this_ = (thisPtr);                                                \\\n    void *doubleParamPtr_ (&param1);                                        \\\n    __asm {                                                                 \\\n        mov     eax, doubleParamPtr_  ;                                     \\\n        push    [eax+4]               ;                                     \\\n        push    [eax]                 ;                                     \\\n        mov     ecx, this_            ;                                     \\\n        mov     eax, [ecx]            ;                                     \\\n        call    [eax+funcOffset]      ;                                     \\\n        mov     resultName, eax       ;                                     \\\n    }\n\n\n#define CALL_THISCALL_2( resultName, thisPtr, funcOffset, param1, param2 )\\\n    void *this_ = (thisPtr);                                                \\\n    __asm {                                                                 \\\n        mov     eax, param2           ;                                     \\\n        push    eax                   ;                                     \\\n        mov     eax, param1           ;                                     \\\n        push    eax                   ;                                     \\\n        mov     ecx, this_            ;                                     \\\n        mov     eax, [ecx]            ;                                     \\\n        call    [eax+funcOffset]      ;                                     \\\n        mov     resultName, eax       ;                                     \\\n    }\n\n\n#define CALL_THISCALL_4( resultName, thisPtr, funcOffset, param1, param2, param3, param4 )\\\n    void *this_ = (thisPtr);                                                \\\n    __asm {                                                                 \\\n        mov     eax, param4           ;                                     \\\n        push    eax                   ;                                     \\\n        mov     eax, param3           ;                                     \\\n        push    eax                   ;                                     \\\n        mov     eax, param2           ;                                     \\\n        push    eax                   ;                                     \\\n        mov     eax, param1           ;                                     \\\n        push    eax                   ;                                     \\\n        mov     ecx, this_            ;                                     \\\n        mov     eax, [ecx]            ;                                     \\\n        call    [eax+funcOffset]      ;                                     \\\n        mov     resultName, eax       ;                                     \\\n    }\n\n\n#elif defined(__GNUC__)\n\n\n#define CALL_THISCALL_0( resultName, thisPtr, funcOffset )                  \\\n    __asm__ __volatile__ (\"movl (%1), %%edx\\n\\t\"                            \\\n                          \"call *\"#funcOffset\"(%%edx)\\n\\t\"                  \\\n                          :\"=a\"(resultName) /* Output Operands */           \\\n                          :\"c\"(thisPtr)     /* Input Operands */            \\\n                          : \"%edx\" /* Clobbered Registers */                \\\n                         );                                                 \\\n\n\n#define CALL_VOID_THISCALL_1( thisPtr, funcOffset, param1 )                 \\\n    __asm__ __volatile__ (\"pushl %0\\n\\t\"                                    \\\n                          \"movl (%1), %%edx\\n\\t\"                            \\\n                          \"call *\"#funcOffset\"(%%edx)\\n\\t\"                  \\\n                          :                 /* Output Operands */           \\\n                          :\"r\"(param1),     /* Input Operands */            \\\n                           \"c\"(thisPtr)                                     \\\n                          : \"%edx\" /* Clobbered Registers */                \\\n                         );                                                 \\\n\n\n#define CALL_THISCALL_1( resultName, thisPtr, funcOffset, param1 )          \\\n    __asm__ __volatile__ (\"pushl %1\\n\\t\"                                    \\\n                          \"movl (%2), %%edx\\n\\t\"                            \\\n                          \"call *\"#funcOffset\"(%%edx)\\n\\t\"                  \\\n                          :\"=a\"(resultName) /* Output Operands */           \\\n                          :\"r\"(param1),     /* Input Operands */            \\\n                           \"c\"(thisPtr)                                     \\\n                          : \"%edx\" /* Clobbered Registers */                \\\n                          );                                                \\\n\n\n#define CALL_THISCALL_1_DOUBLE( resultName, thisPtr, funcOffset, param1 )   \\\n    do {                                                                    \\\n    double param1f64 = param1; /* Cast explicitly to double */              \\\n    double *param1f64Ptr = &param1f64; /* Make pointer to address */        \\\n     __asm__ __volatile__ (\"pushl 4(%1)\\n\\t\"                                \\\n                           \"pushl (%1)\\n\\t\"                                 \\\n                           \"movl (%2), %%edx\\n\\t\"                           \\\n                           \"call *\"#funcOffset\"(%%edx);\\n\\t\"                \\\n                           : \"=a\"(resultName) /* Output Operands */         \\\n                           : \"r\"(param1f64Ptr),  /* Input Operands */       \\\n                           \"c\"(thisPtr),                                    \\\n                           \"m\"(*param1f64Ptr) /* Using address */           \\\n                           : \"%edx\" /* Clobbered Registers */               \\\n                           );                                               \\\n    } while (0);                                                            \\\n\n\n#define CALL_THISCALL_2( resultName, thisPtr, funcOffset, param1, param2 )  \\\n    __asm__ __volatile__ (\"pushl %1\\n\\t\"                                    \\\n                          \"pushl %2\\n\\t\"                                    \\\n                          \"movl (%3), %%edx\\n\\t\"                            \\\n                          \"call *\"#funcOffset\"(%%edx)\\n\\t\"                  \\\n                          :\"=a\"(resultName) /* Output Operands */           \\\n                          :\"r\"(param2),     /* Input Operands */            \\\n                           \"r\"(param1),                                     \\\n                           \"c\"(thisPtr)                                     \\\n                          : \"%edx\" /* Clobbered Registers */                \\\n                          );                                                \\\n\n\n#define CALL_THISCALL_4( resultName, thisPtr, funcOffset, param1, param2, param3, param4 )\\\n    __asm__ __volatile__ (\"pushl %1\\n\\t\"                                    \\\n                          \"pushl %2\\n\\t\"                                    \\\n                          \"pushl %3\\n\\t\"                                    \\\n                          \"pushl %4\\n\\t\"                                    \\\n                          \"movl (%5), %%edx\\n\\t\"                            \\\n                          \"call *\"#funcOffset\"(%%edx)\\n\\t\"                  \\\n                          :\"=a\"(resultName) /* Output Operands */           \\\n                          :\"r\"(param4),     /* Input Operands  */           \\\n                           \"r\"(param3),                                     \\\n                           \"r\"(param2),                                     \\\n                           \"r\"(param1),                                     \\\n                           \"c\"(thisPtr)                                     \\\n                          : \"%edx\" /* Clobbered Registers */                \\\n                          );                                                \\\n\n#endif\n\n\n\n// Our static singleton instance.\nIASIOThiscallResolver IASIOThiscallResolver::instance;\n\n// Constructor called to initialize static Singleton instance above. Note that\n// it is important not to clear that_ incase it has already been set by the call\n// to placement new in ASIOInit().\nIASIOThiscallResolver::IASIOThiscallResolver()\n{\n}\n\n// Constructor called from ASIOInit() below\nIASIOThiscallResolver::IASIOThiscallResolver(IASIO* that)\n: that_( that )\n{\n}\n\n// Implement IUnknown methods as assert(false). IASIOThiscallResolver is not\n// really a COM object, just a wrapper which will work with the ASIO SDK.\n// If you wanted to use ASIO without the SDK you might want to implement COM\n// aggregation in these methods.\nHRESULT STDMETHODCALLTYPE IASIOThiscallResolver::QueryInterface(REFIID riid, void **ppv)\n{\n    (void)riid;     // suppress unused variable warning\n\n    assert( false ); // this function should never be called by the ASIO SDK.\n\n    *ppv = NULL;\n    return E_NOINTERFACE;\n}\n\nULONG STDMETHODCALLTYPE IASIOThiscallResolver::AddRef()\n{\n    assert( false ); // this function should never be called by the ASIO SDK.\n\n    return 1;\n}\n\nULONG STDMETHODCALLTYPE IASIOThiscallResolver::Release()\n{\n    assert( false ); // this function should never be called by the ASIO SDK.\n    \n    return 1;\n}\n\n\n// Implement the IASIO interface methods by performing the vptr manipulation\n// described above then delegating to the real implementation.\nASIOBool IASIOThiscallResolver::init(void *sysHandle)\n{\n    ASIOBool result;\n    CALL_THISCALL_1( result, that_, 12, sysHandle );\n    return result;\n}\n\nvoid IASIOThiscallResolver::getDriverName(char *name)\n{\n    CALL_VOID_THISCALL_1( that_, 16, name );\n}\n\nlong IASIOThiscallResolver::getDriverVersion()\n{\n    ASIOBool result;\n    CALL_THISCALL_0( result, that_, 20 );\n    return result;\n}\n\nvoid IASIOThiscallResolver::getErrorMessage(char *string)\n{\n     CALL_VOID_THISCALL_1( that_, 24, string );\n}\n\nASIOError IASIOThiscallResolver::start()\n{\n    ASIOBool result;\n    CALL_THISCALL_0( result, that_, 28 );\n    return result;\n}\n\nASIOError IASIOThiscallResolver::stop()\n{\n    ASIOBool result;\n    CALL_THISCALL_0( result, that_, 32 );\n    return result;\n}\n\nASIOError IASIOThiscallResolver::getChannels(long *numInputChannels, long *numOutputChannels)\n{\n    ASIOBool result;\n    CALL_THISCALL_2( result, that_, 36, numInputChannels, numOutputChannels );\n    return result;\n}\n\nASIOError IASIOThiscallResolver::getLatencies(long *inputLatency, long *outputLatency)\n{\n    ASIOBool result;\n    CALL_THISCALL_2( result, that_, 40, inputLatency, outputLatency );\n    return result;\n}\n\nASIOError IASIOThiscallResolver::getBufferSize(long *minSize, long *maxSize,\n        long *preferredSize, long *granularity)\n{\n    ASIOBool result;\n    CALL_THISCALL_4( result, that_, 44, minSize, maxSize, preferredSize, granularity );\n    return result;\n}\n\nASIOError IASIOThiscallResolver::canSampleRate(ASIOSampleRate sampleRate)\n{\n    ASIOBool result;\n    CALL_THISCALL_1_DOUBLE( result, that_, 48, sampleRate );\n    return result;\n}\n\nASIOError IASIOThiscallResolver::getSampleRate(ASIOSampleRate *sampleRate)\n{\n    ASIOBool result;\n    CALL_THISCALL_1( result, that_, 52, sampleRate );\n    return result;\n}\n\nASIOError IASIOThiscallResolver::setSampleRate(ASIOSampleRate sampleRate)\n{    \n    ASIOBool result;\n    CALL_THISCALL_1_DOUBLE( result, that_, 56, sampleRate );\n    return result;\n}\n\nASIOError IASIOThiscallResolver::getClockSources(ASIOClockSource *clocks, long *numSources)\n{\n    ASIOBool result;\n    CALL_THISCALL_2( result, that_, 60, clocks, numSources );\n    return result;\n}\n\nASIOError IASIOThiscallResolver::setClockSource(long reference)\n{\n    ASIOBool result;\n    CALL_THISCALL_1( result, that_, 64, reference );\n    return result;\n}\n\nASIOError IASIOThiscallResolver::getSamplePosition(ASIOSamples *sPos, ASIOTimeStamp *tStamp)\n{\n    ASIOBool result;\n    CALL_THISCALL_2( result, that_, 68, sPos, tStamp );\n    return result;\n}\n\nASIOError IASIOThiscallResolver::getChannelInfo(ASIOChannelInfo *info)\n{\n    ASIOBool result;\n    CALL_THISCALL_1( result, that_, 72, info );\n    return result;\n}\n\nASIOError IASIOThiscallResolver::createBuffers(ASIOBufferInfo *bufferInfos,\n        long numChannels, long bufferSize, ASIOCallbacks *callbacks)\n{\n    ASIOBool result;\n    CALL_THISCALL_4( result, that_, 76, bufferInfos, numChannels, bufferSize, callbacks );\n    return result;\n}\n\nASIOError IASIOThiscallResolver::disposeBuffers()\n{\n    ASIOBool result;\n    CALL_THISCALL_0( result, that_, 80 );\n    return result;\n}\n\nASIOError IASIOThiscallResolver::controlPanel()\n{\n    ASIOBool result;\n    CALL_THISCALL_0( result, that_, 84 );\n    return result;\n}\n\nASIOError IASIOThiscallResolver::future(long selector,void *opt)\n{\n    ASIOBool result;\n    CALL_THISCALL_2( result, that_, 88, selector, opt );\n    return result;\n}\n\nASIOError IASIOThiscallResolver::outputReady()\n{\n    ASIOBool result;\n    CALL_THISCALL_0( result, that_, 92 );\n    return result;\n}\n\n\n// Implement our substitute ASIOInit() method\nASIOError IASIOThiscallResolver::ASIOInit(ASIODriverInfo *info)\n{\n    // To ensure that our instance's vptr is correctly constructed, even if\n    // ASIOInit is called prior to main(), we explicitly call its constructor\n    // (potentially over the top of an existing instance). Note that this is\n    // pretty ugly, and is only safe because IASIOThiscallResolver has no\n    // destructor and contains no objects with destructors.\n    new((void*)&instance) IASIOThiscallResolver( theAsioDriver );\n\n    // Interpose between ASIO client code and the real driver.\n    theAsioDriver = &instance;\n\n    // Note that we never need to switch theAsioDriver back to point to the\n    // real driver because theAsioDriver is reset to zero in ASIOExit().\n\n    // Delegate to the real ASIOInit\n\treturn ::ASIOInit(info);\n}\n\n\n#endif /* !defined(_MSC_VER) */\n\n#endif /* Win32 */\n\n"
  },
  {
    "path": "rtaudio/include/iasiothiscallresolver.h",
    "content": "// ****************************************************************************\r\n//\r\n// Changed:         I have modified this file slightly (includes) to work  with\r\n//                  RtAudio. RtAudio.cpp must include this file after asio.h.                                                    \r\n//\r\n// File:\t\t\tIASIOThiscallResolver.h\r\n// Description:     The IASIOThiscallResolver class implements the IASIO\r\n//\t\t\t\t\tinterface and acts as a proxy to the real IASIO interface by\r\n//                  calling through its vptr table using the thiscall calling\r\n//                  convention. To put it another way, we interpose\r\n//                  IASIOThiscallResolver between ASIO SDK code and the driver.\r\n//                  This is necessary because most non-Microsoft compilers don't\r\n//                  implement the thiscall calling convention used by IASIO.\r\n//\r\n//\t\t\t\t\tiasiothiscallresolver.cpp contains the background of this\r\n//\t\t\t\t\tproblem plus a technical description of the vptr\r\n//                  manipulations.\r\n//\r\n//\t\t\t\t\tIn order to use this mechanism one simply has to add\r\n//\t\t\t\t\tiasiothiscallresolver.cpp to the list of files to compile\r\n//                  and #include <iasiothiscallresolver.h>\r\n//\r\n//\t\t\t\t\tNote that this #include must come after the other ASIO SDK\r\n//                  #includes, for example:\r\n//\r\n//\t\t\t\t\t#include <windows.h>\r\n//\t\t\t\t\t#include <asiosys.h>\r\n//\t\t\t\t\t#include <asio.h>\r\n//\t\t\t\t\t#include <asiodrivers.h>\r\n//\t\t\t\t\t#include <iasiothiscallresolver.h>\r\n//\r\n//\t\t\t\t\tActually the important thing is to #include\r\n//                  <iasiothiscallresolver.h> after <asio.h>. We have\r\n//                  incorporated a test to enforce this ordering.\r\n//\r\n//\t\t\t\t\tThe code transparently takes care of the interposition by\r\n//                  using macro substitution to intercept calls to ASIOInit()\r\n//                  and ASIOExit(). We save the original ASIO global\r\n//                  \"theAsioDriver\" in our \"that\" variable, and then set\r\n//                  \"theAsioDriver\" to equal our IASIOThiscallResolver instance.\r\n//\r\n// \t\t\t\t\tWhilst this method of resolving the thiscall problem requires\r\n//\t\t\t\t\tthe addition of #include <iasiothiscallresolver.h> to client\r\n//                  code it has the advantage that it does not break the terms\r\n//                  of the ASIO licence by publishing it. We are NOT modifying\r\n//                  any Steinberg code here, we are merely implementing the IASIO\r\n//\t\t\t\t\tinterface in the same way that we would need to do if we\r\n//\t\t\t\t\twished to provide an open source ASIO driver.\r\n//\r\n//\t\t\t\t\tFor compilation with MinGW -lole32 needs to be added to the\r\n//                  linker options. For BORLAND, linking with Import32.lib is\r\n//                  sufficient.\r\n//\r\n//\t\t\t\t\tThe dependencies are with: CoInitialize, CoUninitialize,\r\n//\t\t\t\t\tCoCreateInstance, CLSIDFromString - used by asiolist.cpp\r\n//\t\t\t\t\tand are required on Windows whether ThiscallResolver is used\r\n//\t\t\t\t\tor not.\r\n//\r\n//\t\t\t\t\tSearching for the above strings in the root library path\r\n//\t\t\t\t\tof your compiler should enable the correct libraries to be\r\n//\t\t\t\t\tidentified if they aren't immediately obvious.\r\n//\r\n//                  Note that the current implementation of IASIOThiscallResolver\r\n//                  is not COM compliant - it does not correctly implement the\r\n//                  IUnknown interface. Implementing it is not necessary because\r\n//                  it is not called by parts of the ASIO SDK which call through\r\n//                  theAsioDriver ptr. The IUnknown methods are implemented as\r\n//                  assert(false) to ensure that the code fails if they are\r\n//                  ever called.\r\n// Restrictions:\tNone. Public Domain & Open Source distribute freely\r\n//\t\t\t\t\tYou may use IASIOThiscallResolver commercially as well as\r\n//                  privately.\r\n//\t\t\t\t\tYou the user assume the responsibility for the use of the\r\n//\t\t\t\t\tfiles, binary or text, and there is no guarantee or warranty,\r\n//\t\t\t\t\texpressed or implied, including but not limited to the\r\n//\t\t\t\t\timplied warranties of merchantability and fitness for a\r\n//\t\t\t\t\tparticular purpose. You assume all responsibility and agree\r\n//\t\t\t\t\tto hold no entity, copyright holder or distributors liable\r\n//\t\t\t\t\tfor any loss of data or inaccurate representations of data\r\n//\t\t\t\t\tas a result of using IASIOThiscallResolver.\r\n// Version:         1.4 Added separate macro CALL_THISCALL_1_DOUBLE from\r\n//                  Andrew Baldwin, and volatile for whole gcc asm blocks,\r\n//                  both for compatibility with newer gcc versions. Cleaned up\r\n//                  Borland asm to use one less register.\r\n//                  1.3 Switched to including assert.h for better compatibility.\r\n//                  Wrapped entire .h and .cpp contents with a check for\r\n//                  _MSC_VER to provide better compatibility with MS compilers.\r\n//                  Changed Singleton implementation to use static instance\r\n//                  instead of freestore allocated instance. Removed ASIOExit\r\n//                  macro as it is no longer needed.\r\n//                  1.2 Removed semicolons from ASIOInit and ASIOExit macros to\r\n//                  allow them to be embedded in expressions (if statements).\r\n//                  Cleaned up some comments. Removed combase.c dependency (it\r\n//                  doesn't compile with BCB anyway) by stubbing IUnknown.\r\n//                  1.1 Incorporated comments from Ross Bencina including things\r\n//\t\t\t\t\tsuch as changing name from ThiscallResolver to\r\n//\t\t\t\t\tIASIOThiscallResolver, tidying up the constructor, fixing\r\n//\t\t\t\t\ta bug in IASIOThiscallResolver::ASIOExit() and improving\r\n//\t\t\t\t\tportability through the use of conditional compilation\r\n//\t\t\t\t\t1.0 Initial working version.\r\n// Created:\t\t\t6/09/2003\r\n// Authors:         Fraser Adams\r\n//                  Ross Bencina\r\n//                  Rene G. Ceballos\r\n//                  Martin Fay\r\n//                  Antti Silvast\r\n//                  Andrew Baldwin\r\n//\r\n// ****************************************************************************\r\n\r\n\r\n#ifndef included_iasiothiscallresolver_h\r\n#define included_iasiothiscallresolver_h\r\n\r\n// We only need IASIOThiscallResolver at all if we are on Win32. For other\r\n// platforms we simply bypass the IASIOThiscallResolver definition to allow us\r\n// to be safely #include'd whatever the platform to keep client code portable\r\n//#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)\r\n#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) && !defined(_WIN64)\r\n\r\n\r\n// If microsoft compiler we can call IASIO directly so IASIOThiscallResolver\r\n// is not used.\r\n#if !defined(_MSC_VER)\r\n\r\n\r\n// The following is in order to ensure that this header is only included after\r\n// the other ASIO headers (except for the case of iasiothiscallresolver.cpp).\r\n// We need to do this because IASIOThiscallResolver works by eclipsing the\r\n// original definition of ASIOInit() with a macro (see below).\r\n#if !defined(iasiothiscallresolver_sourcefile)\r\n\t#if !defined(__ASIO_H)\r\n\t#error iasiothiscallresolver.h must be included AFTER asio.h\r\n\t#endif\r\n#endif\r\n\r\n#include <windows.h>\r\n#include \"iasiodrv.h\" /* From ASIO SDK */\r\n\r\n\r\nclass IASIOThiscallResolver : public IASIO {\r\nprivate:\r\n\tIASIO* that_; // Points to the real IASIO\r\n\r\n\tstatic IASIOThiscallResolver instance; // Singleton instance\r\n\r\n\t// Constructors - declared private so construction is limited to\r\n    // our Singleton instance\r\n    IASIOThiscallResolver();\r\n\tIASIOThiscallResolver(IASIO* that);\r\npublic:\r\n\r\n    // Methods from the IUnknown interface. We don't fully implement IUnknown\r\n    // because the ASIO SDK never calls these methods through theAsioDriver ptr.\r\n    // These methods are implemented as assert(false).\r\n    virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppv);\r\n    virtual ULONG STDMETHODCALLTYPE AddRef();\r\n    virtual ULONG STDMETHODCALLTYPE Release();\r\n\r\n    // Methods from the IASIO interface, implemented as forwarning calls to that.\r\n\tvirtual ASIOBool init(void *sysHandle);\r\n\tvirtual void getDriverName(char *name);\r\n\tvirtual long getDriverVersion();\r\n\tvirtual void getErrorMessage(char *string);\r\n\tvirtual ASIOError start();\r\n\tvirtual ASIOError stop();\r\n\tvirtual ASIOError getChannels(long *numInputChannels, long *numOutputChannels);\r\n\tvirtual ASIOError getLatencies(long *inputLatency, long *outputLatency);\r\n\tvirtual ASIOError getBufferSize(long *minSize, long *maxSize, long *preferredSize, long *granularity);\r\n\tvirtual ASIOError canSampleRate(ASIOSampleRate sampleRate);\r\n\tvirtual ASIOError getSampleRate(ASIOSampleRate *sampleRate);\r\n\tvirtual ASIOError setSampleRate(ASIOSampleRate sampleRate);\r\n\tvirtual ASIOError getClockSources(ASIOClockSource *clocks, long *numSources);\r\n\tvirtual ASIOError setClockSource(long reference);\r\n\tvirtual ASIOError getSamplePosition(ASIOSamples *sPos, ASIOTimeStamp *tStamp);\r\n\tvirtual ASIOError getChannelInfo(ASIOChannelInfo *info);\r\n\tvirtual ASIOError createBuffers(ASIOBufferInfo *bufferInfos, long numChannels, long bufferSize, ASIOCallbacks *callbacks);\r\n\tvirtual ASIOError disposeBuffers();\r\n\tvirtual ASIOError controlPanel();\r\n\tvirtual ASIOError future(long selector,void *opt);\r\n\tvirtual ASIOError outputReady();\r\n\r\n    // Class method, see ASIOInit() macro below.\r\n    static ASIOError ASIOInit(ASIODriverInfo *info); // Delegates to ::ASIOInit\r\n};\r\n\r\n\r\n// Replace calls to ASIOInit with our interposing version.\r\n// This macro enables us to perform thiscall resolution simply by #including\r\n// <iasiothiscallresolver.h> after the asio #includes (this file _must_ be\r\n// included _after_ the asio #includes)\r\n\r\n#define ASIOInit(name) IASIOThiscallResolver::ASIOInit((name))\r\n\r\n\r\n#endif /* !defined(_MSC_VER) */\r\n\r\n#endif /* Win32 */\r\n\r\n#endif /* included_iasiothiscallresolver_h */\r\n\r\n\r\n"
  },
  {
    "path": "rtaudio/include/soundcard.h",
    "content": "/*\n * soundcard.h\n */\n\n/*-\n * Copyright by Hannu Savolainen 1993 / 4Front Technologies 1993-2006\n * Modified for the new FreeBSD sound driver by Luigi Rizzo, 1997\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above\n *    copyright notice, this list of conditions and the following\n *    disclaimer in the documentation and/or other materials provided\n *    with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED\n * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A\n * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR\n * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF\n * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED\n * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN\n * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n *\n * $FreeBSD: src/sys/sys/soundcard.h,v 1.48 2006/11/26 11:55:48 netchild Exp $\n */\n\n/*\n * Unless coordinating changes with 4Front Technologies, do NOT make any\n * modifications to ioctl commands, types, etc. that would break\n * compatibility with the OSS API.\n */\n\n#ifndef _SYS_SOUNDCARD_H_\n#define _SYS_SOUNDCARD_H_\n /*\n  * If you make modifications to this file, please contact me before\n  * distributing the modified version. There is already enough\n  * diversity in the world.\n  *\n  * Regards,\n  * Hannu Savolainen\n  * hannu@voxware.pp.fi\n  *\n  **********************************************************************\n  * PS.\tThe Hacker's Guide to VoxWare available from\n  *     nic.funet.fi:pub/Linux/ALPHA/sound. The file is\n  *\tsnd-sdk-doc-0.1.ps.gz (gzipped postscript). It contains\n  *\tsome useful information about programming with VoxWare.\n  *\t(NOTE! The pub/Linux/ALPHA/ directories are hidden. You have\n  *\tto cd inside them before the files are accessible.)\n  **********************************************************************\n  */\n\n/*\n * SOUND_VERSION is only used by the voxware driver. Hopefully apps\n * should not depend on it, but rather look at the capabilities\n * of the driver in the kernel!\n */\n#define SOUND_VERSION  301\n#define VOXWARE\t\t/* does this have any use ? */\n\n/*\n * Supported card ID numbers (Should be somewhere else? We keep\n * them here just for compativility with the old driver, but these\n * constants are of little or no use).\n */\n\n#define SNDCARD_ADLIB          1\n#define SNDCARD_SB             2\n#define SNDCARD_PAS            3\n#define SNDCARD_GUS            4\n#define SNDCARD_MPU401         5\n#define SNDCARD_SB16           6\n#define SNDCARD_SB16MIDI       7\n#define SNDCARD_UART6850       8\n#define SNDCARD_GUS16          9\n#define SNDCARD_MSS            10\n#define SNDCARD_PSS            11\n#define SNDCARD_SSCAPE         12\n#define SNDCARD_PSS_MPU        13\n#define SNDCARD_PSS_MSS        14\n#define SNDCARD_SSCAPE_MSS     15\n#define SNDCARD_TRXPRO         16\n#define SNDCARD_TRXPRO_SB      17\n#define SNDCARD_TRXPRO_MPU     18\n#define SNDCARD_MAD16          19\n#define SNDCARD_MAD16_MPU      20\n#define SNDCARD_CS4232         21\n#define SNDCARD_CS4232_MPU     22\n#define SNDCARD_MAUI           23\n#define SNDCARD_PSEUDO_MSS     24\n#define SNDCARD_AWE32          25\n#define SNDCARD_NSS            26\n#define SNDCARD_UART16550      27\n#define SNDCARD_OPL            28\n\n#include <sys/types.h>\n#include <machine/endian.h>\n#ifndef _IOWR\n#include <sys/ioccom.h>\n#endif  /* !_IOWR */\n\n/*\n * The first part of this file contains the new FreeBSD sound ioctl\n * interface. Tries to minimize the number of different ioctls, and\n * to be reasonably general.\n *\n * 970821: some of the new calls have not been implemented yet.\n */\n\n/*\n * the following three calls extend the generic file descriptor\n * interface. AIONWRITE is the dual of FIONREAD, i.e. returns the max\n * number of bytes for a write operation to be non-blocking.\n *\n * AIOGSIZE/AIOSSIZE are used to change the behaviour of the device,\n * from a character device (default) to a block device. In block mode,\n * (not to be confused with blocking mode) the main difference for the\n * application is that select() will return only when a complete\n * block can be read/written to the device, whereas in character mode\n * select will return true when one byte can be exchanged. For audio\n * devices, character mode makes select almost useless since one byte\n * will always be ready by the next sample time (which is often only a\n * handful of microseconds away).\n * Use a size of 0 or 1 to return to character mode.\n */\n#define\tAIONWRITE   _IOR('A', 10, int)   /* get # bytes to write */\nstruct snd_size {\n    int play_size;\n    int rec_size;\n};\n#define\tAIOGSIZE    _IOR('A', 11, struct snd_size)/* read current blocksize */\n#define\tAIOSSIZE    _IOWR('A', 11, struct snd_size)  /* sets blocksize */\n\n/*\n * The following constants define supported audio formats. The\n * encoding follows voxware conventions, i.e. 1 bit for each supported\n * format. We extend it by using bit 31 (RO) to indicate full-duplex\n * capability, and bit 29 (RO) to indicate that the card supports/\n * needs different formats on capture & playback channels.\n * Bit 29 (RW) is used to indicate/ask stereo.\n *\n * The number of bits required to store the sample is:\n *  o  4 bits for the IDA ADPCM format,\n *  o  8 bits for 8-bit formats, mu-law and A-law,\n *  o  16 bits for the 16-bit formats, and\n *  o  32 bits for the 24/32-bit formats.\n *  o  undefined for the MPEG audio format.\n */\n\n#define AFMT_QUERY\t0x00000000\t/* Return current format */\n#define AFMT_MU_LAW\t0x00000001\t/* Logarithmic mu-law */\n#define AFMT_A_LAW\t0x00000002\t/* Logarithmic A-law */\n#define AFMT_IMA_ADPCM\t0x00000004\t/* A 4:1 compressed format where 16-bit\n\t\t\t\t\t * squence represented using the\n\t\t\t\t\t * the average 4 bits per sample */\n#define AFMT_U8\t\t0x00000008\t/* Unsigned 8-bit */\n#define AFMT_S16_LE\t0x00000010\t/* Little endian signed 16-bit */\n#define AFMT_S16_BE\t0x00000020\t/* Big endian signed 16-bit */\n#define AFMT_S8\t\t0x00000040\t/* Signed 8-bit */\n#define AFMT_U16_LE\t0x00000080\t/* Little endian unsigned 16-bit */\n#define AFMT_U16_BE\t0x00000100\t/* Big endian unsigned 16-bit */\n#define AFMT_MPEG\t0x00000200\t/* MPEG MP2/MP3 audio */\n#define AFMT_AC3\t0x00000400\t/* Dolby Digital AC3 */\n\n#if _BYTE_ORDER == _LITTLE_ENDIAN\n#define AFMT_S16_NE\tAFMT_S16_LE\t/* native endian signed 16 */\n#else\n#define AFMT_S16_NE\tAFMT_S16_BE\n#endif\n\n/*\n * 32-bit formats below used for 24-bit audio data where the data is stored\n * in the 24 most significant bits and the least significant bits are not used\n * (should be set to 0).\n */\n#define AFMT_S32_LE\t0x00001000\t/* Little endian signed 32-bit */\n#define AFMT_S32_BE\t0x00002000\t/* Big endian signed 32-bit */\n#define AFMT_U32_LE\t0x00004000\t/* Little endian unsigned 32-bit */\n#define AFMT_U32_BE\t0x00008000\t/* Big endian unsigned 32-bit */\n#define AFMT_S24_LE\t0x00010000\t/* Little endian signed 24-bit */\n#define AFMT_S24_BE\t0x00020000\t/* Big endian signed 24-bit */\n#define AFMT_U24_LE\t0x00040000\t/* Little endian unsigned 24-bit */\n#define AFMT_U24_BE\t0x00080000\t/* Big endian unsigned 24-bit */\n\n#define AFMT_STEREO\t0x10000000\t/* can do/want stereo\t*/\n\n/*\n * the following are really capabilities\n */\n#define AFMT_WEIRD\t0x20000000\t/* weird hardware...\t*/\n    /*\n     * AFMT_WEIRD reports that the hardware might need to operate\n     * with different formats in the playback and capture\n     * channels when operating in full duplex.\n     * As an example, SoundBlaster16 cards only support U8 in one\n     * direction and S16 in the other one, and applications should\n     * be aware of this limitation.\n     */\n#define AFMT_FULLDUPLEX\t0x80000000\t/* can do full duplex\t*/\n\n/*\n * The following structure is used to get/set format and sampling rate.\n * While it would be better to have things such as stereo, bits per\n * sample, endiannes, etc split in different variables, it turns out\n * that formats are not that many, and not all combinations are possible.\n * So we followed the Voxware approach of associating one bit to each\n * format.\n */\n\ntypedef struct _snd_chan_param {\n    u_long\tplay_rate;\t/* sampling rate\t\t\t*/\n    u_long\trec_rate;\t/* sampling rate\t\t\t*/\n    u_long\tplay_format;\t/* everything describing the format\t*/\n    u_long\trec_format;\t/* everything describing the format\t*/\n} snd_chan_param;\n#define\tAIOGFMT    _IOR('f', 12, snd_chan_param)   /* get format */\n#define\tAIOSFMT    _IOWR('f', 12, snd_chan_param)  /* sets format */\n\n/*\n * The following structure is used to get/set the mixer setting.\n * Up to 32 mixers are supported, each one with up to 32 channels.\n */\ntypedef struct _snd_mix_param {\n    u_char\tsubdev;\t/* which output\t\t\t\t*/\n    u_char\tline;\t/* which input\t\t\t\t*/\n    u_char\tleft,right; /* volumes, 0..255, 0 = mute\t*/\n} snd_mix_param ;\n\n/* XXX AIOGMIX, AIOSMIX not implemented yet */\n#define AIOGMIX\t_IOWR('A', 13, snd_mix_param)\t/* return mixer status */\n#define AIOSMIX\t_IOWR('A', 14, snd_mix_param)\t/* sets mixer status   */\n\n/*\n * channel specifiers used in AIOSTOP and AIOSYNC\n */\n#define\tAIOSYNC_PLAY\t0x1\t/* play chan */\n#define\tAIOSYNC_CAPTURE\t0x2\t/* capture chan */\n/* AIOSTOP stop & flush a channel, returns the residual count */\n#define\tAIOSTOP\t_IOWR ('A', 15, int)\n\n/* alternate method used to notify the sync condition */\n#define\tAIOSYNC_SIGNAL\t0x100\n#define\tAIOSYNC_SELECT\t0x200\n\n/* what the 'pos' field refers to */\n#define AIOSYNC_READY\t0x400\n#define AIOSYNC_FREE\t0x800\n\ntypedef struct _snd_sync_parm {\n    long chan ; /* play or capture channel, plus modifier */\n    long pos;\n} snd_sync_parm;\n#define\tAIOSYNC\t_IOWR ('A', 15, snd_sync_parm)\t/* misc. synchronization */\n\n/*\n * The following is used to return device capabilities. If the structure\n * passed to the ioctl is zeroed, default values are returned for rate\n * and formats, a bitmap of available mixers is returned, and values\n * (inputs, different levels) for the first one are returned.\n *\n * If  formats, mixers, inputs are instantiated, then detailed info\n * are returned depending on the call.\n */\ntypedef struct _snd_capabilities {\n    u_long\trate_min, rate_max;\t/* min-max sampling rate */\n    u_long\tformats;\n    u_long\tbufsize; /* DMA buffer size */\n    u_long\tmixers; /* bitmap of available mixers */\n    u_long\tinputs; /* bitmap of available inputs (per mixer) */\n    u_short\tleft, right;\t/* how many levels are supported */\n} snd_capabilities;\n#define AIOGCAP\t_IOWR('A', 15, snd_capabilities)\t/* get capabilities */\n\n/*\n * here is the old (Voxware) ioctl interface\n */\n\n/*\n * IOCTL Commands for /dev/sequencer\n */\n\n#define SNDCTL_SEQ_RESET\t_IO  ('Q', 0)\n#define SNDCTL_SEQ_SYNC\t\t_IO  ('Q', 1)\n#define SNDCTL_SYNTH_INFO\t_IOWR('Q', 2, struct synth_info)\n#define SNDCTL_SEQ_CTRLRATE\t_IOWR('Q', 3, int) /* Set/get timer res.(hz) */\n#define SNDCTL_SEQ_GETOUTCOUNT\t_IOR ('Q', 4, int)\n#define SNDCTL_SEQ_GETINCOUNT\t_IOR ('Q', 5, int)\n#define SNDCTL_SEQ_PERCMODE\t_IOW ('Q', 6, int)\n#define SNDCTL_FM_LOAD_INSTR\t_IOW ('Q', 7, struct sbi_instrument)\t/* Valid for FM only */\n#define SNDCTL_SEQ_TESTMIDI\t_IOW ('Q', 8, int)\n#define SNDCTL_SEQ_RESETSAMPLES\t_IOW ('Q', 9, int)\n#define SNDCTL_SEQ_NRSYNTHS\t_IOR ('Q',10, int)\n#define SNDCTL_SEQ_NRMIDIS\t_IOR ('Q',11, int)\n#define SNDCTL_MIDI_INFO\t_IOWR('Q',12, struct midi_info)\n#define SNDCTL_SEQ_THRESHOLD\t_IOW ('Q',13, int)\n#define SNDCTL_SEQ_TRESHOLD\tSNDCTL_SEQ_THRESHOLD\t/* there was once a typo */\n#define SNDCTL_SYNTH_MEMAVL\t_IOWR('Q',14, int) /* in=dev#, out=memsize */\n#define SNDCTL_FM_4OP_ENABLE\t_IOW ('Q',15, int) /* in=dev# */\n#define SNDCTL_PMGR_ACCESS\t_IOWR('Q',16, struct patmgr_info)\n#define SNDCTL_SEQ_PANIC\t_IO  ('Q',17)\n#define SNDCTL_SEQ_OUTOFBAND\t_IOW ('Q',18, struct seq_event_rec)\n#define SNDCTL_SEQ_GETTIME\t_IOR ('Q',19, int)\n\nstruct seq_event_rec {\n\tu_char arr[8];\n};\n\n#define SNDCTL_TMR_TIMEBASE\t_IOWR('T', 1, int)\n#define SNDCTL_TMR_START\t_IO  ('T', 2)\n#define SNDCTL_TMR_STOP\t\t_IO  ('T', 3)\n#define SNDCTL_TMR_CONTINUE\t_IO  ('T', 4)\n#define SNDCTL_TMR_TEMPO\t_IOWR('T', 5, int)\n#define SNDCTL_TMR_SOURCE\t_IOWR('T', 6, int)\n#   define TMR_INTERNAL\t\t0x00000001\n#   define TMR_EXTERNAL\t\t0x00000002\n#\tdefine TMR_MODE_MIDI\t0x00000010\n#\tdefine TMR_MODE_FSK\t0x00000020\n#\tdefine TMR_MODE_CLS\t0x00000040\n#\tdefine TMR_MODE_SMPTE\t0x00000080\n#define SNDCTL_TMR_METRONOME\t_IOW ('T', 7, int)\n#define SNDCTL_TMR_SELECT\t_IOW ('T', 8, int)\n\n/*\n *\tEndian aware patch key generation algorithm.\n */\n\n#if defined(_AIX) || defined(AIX)\n#  define _PATCHKEY(id) (0xfd00|id)\n#else\n#  define _PATCHKEY(id) ((id<<8)|0xfd)\n#endif\n\n/*\n *\tSample loading mechanism for internal synthesizers (/dev/sequencer)\n *\tThe following patch_info structure has been designed to support\n *\tGravis UltraSound. It tries to be universal format for uploading\n *\tsample based patches but is probably too limited.\n */\n\nstruct patch_info {\n/*\t\tu_short key;\t\t Use GUS_PATCH here */\n\tshort key;\t\t /* Use GUS_PATCH here */\n#define GUS_PATCH\t_PATCHKEY(0x04)\n#define OBSOLETE_GUS_PATCH\t_PATCHKEY(0x02)\n\n\tshort device_no;\t/* Synthesizer number */\n\tshort instr_no;\t\t/* Midi pgm# */\n\n\tu_long mode;\n/*\n * The least significant byte has the same format than the GUS .PAT\n * files\n */\n#define WAVE_16_BITS\t0x01\t/* bit 0 = 8 or 16 bit wave data. */\n#define WAVE_UNSIGNED\t0x02\t/* bit 1 = Signed - Unsigned data. */\n#define WAVE_LOOPING\t0x04\t/* bit 2 = looping enabled-1. */\n#define WAVE_BIDIR_LOOP\t0x08\t/* bit 3 = Set is bidirectional looping. */\n#define WAVE_LOOP_BACK\t0x10\t/* bit 4 = Set is looping backward. */\n#define WAVE_SUSTAIN_ON\t0x20\t/* bit 5 = Turn sustaining on. (Env. pts. 3)*/\n#define WAVE_ENVELOPES\t0x40\t/* bit 6 = Enable envelopes - 1 */\n\t\t\t\t/* \t(use the env_rate/env_offs fields). */\n/* Linux specific bits */\n#define WAVE_VIBRATO\t0x00010000\t/* The vibrato info is valid */\n#define WAVE_TREMOLO\t0x00020000\t/* The tremolo info is valid */\n#define WAVE_SCALE\t0x00040000\t/* The scaling info is valid */\n/* Other bits must be zeroed */\n\n\tlong len;\t/* Size of the wave data in bytes */\n\tlong loop_start, loop_end; /* Byte offsets from the beginning */\n\n/*\n * The base_freq and base_note fields are used when computing the\n * playback speed for a note. The base_note defines the tone frequency\n * which is heard if the sample is played using the base_freq as the\n * playback speed.\n *\n * The low_note and high_note fields define the minimum and maximum note\n * frequencies for which this sample is valid. It is possible to define\n * more than one samples for an instrument number at the same time. The\n * low_note and high_note fields are used to select the most suitable one.\n *\n * The fields base_note, high_note and low_note should contain\n * the note frequency multiplied by 1000. For example value for the\n * middle A is 440*1000.\n */\n\n\tu_int base_freq;\n\tu_long base_note;\n\tu_long high_note;\n\tu_long low_note;\n\tint panning;\t/* -128=left, 127=right */\n\tint detuning;\n\n/*\tNew fields introduced in version 1.99.5\t*/\n\n       /* Envelope. Enabled by mode bit WAVE_ENVELOPES\t*/\n\tu_char\tenv_rate[ 6 ];\t /* GUS HW ramping rate */\n\tu_char\tenv_offset[ 6 ]; /* 255 == 100% */\n\n\t/*\n\t * The tremolo, vibrato and scale info are not supported yet.\n\t * Enable by setting the mode bits WAVE_TREMOLO, WAVE_VIBRATO or\n\t * WAVE_SCALE\n\t */\n\n\tu_char\ttremolo_sweep;\n\tu_char\ttremolo_rate;\n\tu_char\ttremolo_depth;\n\n\tu_char\tvibrato_sweep;\n\tu_char\tvibrato_rate;\n\tu_char\tvibrato_depth;\n\n\tint\t\tscale_frequency;\n\tu_int\tscale_factor;\t\t/* from 0 to 2048 or 0 to 2 */\n\n\tint\t\tvolume;\n\tint\t\tspare[4];\n\tchar data[1];\t/* The waveform data starts here */\n};\n\nstruct sysex_info {\n\tshort key;\t\t/* Use GUS_PATCH here */\n#define SYSEX_PATCH\t_PATCHKEY(0x05)\n#define MAUI_PATCH\t_PATCHKEY(0x06)\n\tshort device_no;\t/* Synthesizer number */\n\tlong len;\t/* Size of the sysex data in bytes */\n\tu_char data[1];\t/* Sysex data starts here */\n};\n\n/*\n * Patch management interface (/dev/sequencer, /dev/patmgr#)\n * Don't use these calls if you want to maintain compatibility with\n * the future versions of the driver.\n */\n\n#define PS_NO_PATCHES\t\t0\t/* No patch support on device */\n#define\tPS_MGR_NOT_OK\t\t1\t/* Plain patch support (no mgr) */\n#define\tPS_MGR_OK\t\t2\t/* Patch manager supported */\n#define\tPS_MANAGED\t\t3\t/* Patch manager running */\n\n#define SNDCTL_PMGR_IFACE\t\t_IOWR('P', 1, struct patmgr_info)\n\n/*\n * The patmgr_info is a fixed size structure which is used for two\n * different purposes. The intended use is for communication between\n * the application using /dev/sequencer and the patch manager daemon\n * associated with a synthesizer device (ioctl(SNDCTL_PMGR_ACCESS)).\n *\n * This structure is also used with ioctl(SNDCTL_PGMR_IFACE) which allows\n * a patch manager daemon to read and write device parameters. This\n * ioctl available through /dev/sequencer also. Avoid using it since it's\n * extremely hardware dependent. In addition access trough /dev/sequencer\n * may confuse the patch manager daemon.\n */\n\nstruct patmgr_info {\t/* Note! size must be < 4k since kmalloc() is used */\n\t  u_long key;\t/* Don't worry. Reserved for communication\n\t  \t\t\t   between the patch manager and the driver. */\n#define PM_K_EVENT\t\t1 /* Event from the /dev/sequencer driver */\n#define PM_K_COMMAND\t\t2 /* Request from an application */\n#define PM_K_RESPONSE\t\t3 /* From patmgr to application */\n#define PM_ERROR\t\t4 /* Error returned by the patmgr */\n\t  int device;\n\t  int command;\n\n/*\n * Commands 0x000 to 0xfff reserved for patch manager programs\n */\n#define PM_GET_DEVTYPE\t1\t/* Returns type of the patch mgr interface of dev */\n#define\t\tPMTYPE_FM2\t1\t/* 2 OP fm */\n#define\t\tPMTYPE_FM4\t2\t/* Mixed 4 or 2 op FM (OPL-3) */\n#define\t\tPMTYPE_WAVE\t3\t/* Wave table synthesizer (GUS) */\n#define PM_GET_NRPGM\t2\t/* Returns max # of midi programs in parm1 */\n#define PM_GET_PGMMAP\t3\t/* Returns map of loaded midi programs in data8 */\n#define PM_GET_PGM_PATCHES 4\t/* Return list of patches of a program (parm1) */\n#define PM_GET_PATCH\t5\t/* Return patch header of patch parm1 */\n#define PM_SET_PATCH\t6\t/* Set patch header of patch parm1 */\n#define PM_READ_PATCH\t7\t/* Read patch (wave) data */\n#define PM_WRITE_PATCH\t8\t/* Write patch (wave) data */\n\n/*\n * Commands 0x1000 to 0xffff are for communication between the patch manager\n * and the client\n */\n#define _PM_LOAD_PATCH\t0x100\n\n/*\n * Commands above 0xffff reserved for device specific use\n */\n\n\tlong parm1;\n\tlong parm2;\n\tlong parm3;\n\n\tunion {\n\t\tu_char data8[4000];\n\t\tu_short data16[2000];\n\t\tu_long data32[1000];\n\t\tstruct patch_info patch;\n\t} data;\n};\n\n/*\n * When a patch manager daemon is present, it will be informed by the\n * driver when something important happens. For example when the\n * /dev/sequencer is opened or closed. A record with key == PM_K_EVENT is\n * returned. The command field contains the event type:\n */\n#define PM_E_OPENED\t\t1\t/* /dev/sequencer opened */\n#define PM_E_CLOSED\t\t2\t/* /dev/sequencer closed */\n#define PM_E_PATCH_RESET\t3\t/* SNDCTL_RESETSAMPLES called */\n#define PM_E_PATCH_LOADED\t4\t/* A patch has been loaded by appl */\n\n/*\n * /dev/sequencer input events.\n *\n * The data written to the /dev/sequencer is a stream of events. Events\n * are records of 4 or 8 bytes. The first byte defines the size.\n * Any number of events can be written with a write call. There\n * is a set of macros for sending these events. Use these macros if you\n * want to maximize portability of your program.\n *\n * Events SEQ_WAIT, SEQ_MIDIPUTC and SEQ_ECHO. Are also input events.\n * (All input events are currently 4 bytes long. Be prepared to support\n * 8 byte events also. If you receive any event having first byte >= 128,\n * it's a 8 byte event.\n *\n * The events are documented at the end of this file.\n *\n * Normal events (4 bytes)\n * There is also a 8 byte version of most of the 4 byte events. The\n * 8 byte one is recommended.\n */\n#define SEQ_NOTEOFF\t\t0\n#define SEQ_FMNOTEOFF\t\tSEQ_NOTEOFF\t/* Just old name */\n#define SEQ_NOTEON\t\t1\n#define\tSEQ_FMNOTEON\t\tSEQ_NOTEON\n#define SEQ_WAIT\t\tTMR_WAIT_ABS\n#define SEQ_PGMCHANGE\t\t3\n#define SEQ_FMPGMCHANGE\t\tSEQ_PGMCHANGE\n#define SEQ_SYNCTIMER\t\tTMR_START\n#define SEQ_MIDIPUTC\t\t5\n#define SEQ_DRUMON\t\t6\t/*** OBSOLETE ***/\n#define SEQ_DRUMOFF\t\t7\t/*** OBSOLETE ***/\n#define SEQ_ECHO\t\tTMR_ECHO\t/* For synching programs with output */\n#define SEQ_AFTERTOUCH\t\t9\n#define SEQ_CONTROLLER\t\t10\n\n/*\n *\tMidi controller numbers\n *\n * Controllers 0 to 31 (0x00 to 0x1f) and 32 to 63 (0x20 to 0x3f)\n * are continuous controllers.\n * In the MIDI 1.0 these controllers are sent using two messages.\n * Controller numbers 0 to 31 are used to send the MSB and the\n * controller numbers 32 to 63 are for the LSB. Note that just 7 bits\n * are used in MIDI bytes.\n */\n\n#define\tCTL_BANK_SELECT\t\t0x00\n#define\tCTL_MODWHEEL\t\t0x01\n#define CTL_BREATH\t\t0x02\n/*\tundefined\t\t0x03 */\n#define CTL_FOOT\t\t0x04\n#define CTL_PORTAMENTO_TIME\t0x05\n#define CTL_DATA_ENTRY\t\t0x06\n#define CTL_MAIN_VOLUME\t\t0x07\n#define CTL_BALANCE\t\t0x08\n/*\tundefined\t\t0x09 */\n#define CTL_PAN\t\t\t0x0a\n#define CTL_EXPRESSION\t\t0x0b\n/*\tundefined\t\t0x0c - 0x0f */\n#define CTL_GENERAL_PURPOSE1\t0x10\n#define CTL_GENERAL_PURPOSE2\t0x11\n#define CTL_GENERAL_PURPOSE3\t0x12\n#define CTL_GENERAL_PURPOSE4\t0x13\n/*\tundefined\t\t0x14 - 0x1f */\n\n/*\tundefined\t\t0x20 */\n\n/*\n * The controller numbers 0x21 to 0x3f are reserved for the\n * least significant bytes of the controllers 0x00 to 0x1f.\n * These controllers are not recognised by the driver.\n *\n * Controllers 64 to 69 (0x40 to 0x45) are on/off switches.\n * 0=OFF and 127=ON (intermediate values are possible)\n */\n#define CTL_DAMPER_PEDAL\t0x40\n#define CTL_SUSTAIN\t\tCTL_DAMPER_PEDAL\t/* Alias */\n#define CTL_HOLD\t\tCTL_DAMPER_PEDAL\t/* Alias */\n#define CTL_PORTAMENTO\t\t0x41\n#define CTL_SOSTENUTO\t\t0x42\n#define CTL_SOFT_PEDAL\t\t0x43\n/*\tundefined\t\t0x44 */\n#define CTL_HOLD2\t\t0x45\n/*\tundefined\t\t0x46 - 0x4f */\n\n#define CTL_GENERAL_PURPOSE5\t0x50\n#define CTL_GENERAL_PURPOSE6\t0x51\n#define CTL_GENERAL_PURPOSE7\t0x52\n#define CTL_GENERAL_PURPOSE8\t0x53\n/*\tundefined\t\t0x54 - 0x5a */\n#define CTL_EXT_EFF_DEPTH\t0x5b\n#define CTL_TREMOLO_DEPTH\t0x5c\n#define CTL_CHORUS_DEPTH\t0x5d\n#define CTL_DETUNE_DEPTH\t0x5e\n#define CTL_CELESTE_DEPTH\tCTL_DETUNE_DEPTH /* Alias for the above one */\n#define CTL_PHASER_DEPTH\t0x5f\n#define CTL_DATA_INCREMENT\t0x60\n#define CTL_DATA_DECREMENT\t0x61\n#define CTL_NONREG_PARM_NUM_LSB\t0x62\n#define CTL_NONREG_PARM_NUM_MSB\t0x63\n#define CTL_REGIST_PARM_NUM_LSB\t0x64\n#define CTL_REGIST_PARM_NUM_MSB\t0x65\n/*\tundefined\t\t0x66 - 0x78 */\n/*\treserved\t\t0x79 - 0x7f */\n\n/* Pseudo controllers (not midi compatible) */\n#define CTRL_PITCH_BENDER\t255\n#define CTRL_PITCH_BENDER_RANGE\t254\n#define CTRL_EXPRESSION\t\t253\t/* Obsolete */\n#define CTRL_MAIN_VOLUME\t252\t/* Obsolete */\n\n#define SEQ_BALANCE\t\t11\n#define SEQ_VOLMODE             12\n\n/*\n * Volume mode decides how volumes are used\n */\n\n#define VOL_METHOD_ADAGIO\t1\n#define VOL_METHOD_LINEAR\t2\n\n/*\n * Note! SEQ_WAIT, SEQ_MIDIPUTC and SEQ_ECHO are used also as\n *\t input events.\n */\n\n/*\n * Event codes 0xf0 to 0xfc are reserved for future extensions.\n */\n\n#define SEQ_FULLSIZE\t\t0xfd\t/* Long events */\n/*\n * SEQ_FULLSIZE events are used for loading patches/samples to the\n * synthesizer devices. These events are passed directly to the driver\n * of the associated synthesizer device. There is no limit to the size\n * of the extended events. These events are not queued but executed\n * immediately when the write() is called (execution can take several\n * seconds of time).\n *\n * When a SEQ_FULLSIZE message is written to the device, it must\n * be written using exactly one write() call. Other events cannot\n * be mixed to the same write.\n *\n * For FM synths (YM3812/OPL3) use struct sbi_instrument and write\n * it to the /dev/sequencer. Don't write other data together with\n * the instrument structure Set the key field of the structure to\n * FM_PATCH. The device field is used to route the patch to the\n * corresponding device.\n *\n * For Gravis UltraSound use struct patch_info. Initialize the key field\n * to GUS_PATCH.\n */\n#define SEQ_PRIVATE\t0xfe\t/* Low level HW dependent events (8 bytes) */\n#define SEQ_EXTENDED\t0xff\t/* Extended events (8 bytes) OBSOLETE */\n\n/*\n * Record for FM patches\n */\n\ntypedef u_char sbi_instr_data[32];\n\nstruct sbi_instrument {\n\tu_short\tkey;\t/* FM_PATCH or OPL3_PATCH */\n#define FM_PATCH\t_PATCHKEY(0x01)\n#define OPL3_PATCH\t_PATCHKEY(0x03)\n\tshort\t\tdevice;\t\t/* Synth# (0-4)\t*/\n\tint \t\tchannel;\t/* Program# to be initialized  */\n\tsbi_instr_data\toperators;\t/* Reg. settings for operator cells\n\t\t\t\t\t * (.SBI format)\t*/\n};\n\nstruct synth_info {\t/* Read only */\n\tchar\tname[30];\n\tint\tdevice;\t\t/* 0-N. INITIALIZE BEFORE CALLING */\n\tint\tsynth_type;\n#define SYNTH_TYPE_FM\t\t\t0\n#define SYNTH_TYPE_SAMPLE\t\t1\n#define SYNTH_TYPE_MIDI\t\t\t2\t/* Midi interface */\n\n\tint\tsynth_subtype;\n#define FM_TYPE_ADLIB\t\t\t0x00\n#define FM_TYPE_OPL3\t\t\t0x01\n#define MIDI_TYPE_MPU401\t\t0x401\n\n#define SAMPLE_TYPE_BASIC\t\t0x10\n#define SAMPLE_TYPE_GUS\t\t\tSAMPLE_TYPE_BASIC\n#define SAMPLE_TYPE_AWE32\t\t0x20\n\n\tint\tperc_mode;\t/* No longer supported */\n\tint\tnr_voices;\n\tint\tnr_drums;\t/* Obsolete field */\n\tint\tinstr_bank_size;\n\tu_long\tcapabilities;\n#define SYNTH_CAP_PERCMODE\t0x00000001 /* No longer used */\n#define SYNTH_CAP_OPL3\t\t0x00000002 /* Set if OPL3 supported */\n#define SYNTH_CAP_INPUT\t\t0x00000004 /* Input (MIDI) device */\n\tint\tdummies[19];\t/* Reserve space */\n};\n\nstruct sound_timer_info {\n\tchar name[32];\n\tint caps;\n};\n\nstruct midi_info {\n\tchar\t\tname[30];\n\tint\t\tdevice;\t\t/* 0-N. INITIALIZE BEFORE CALLING */\n\tu_long\tcapabilities;\t/* To be defined later */\n\tint\t\tdev_type;\n\tint\t\tdummies[18];\t/* Reserve space */\n};\n\n/*\n * ioctl commands for the /dev/midi##\n */\ntypedef struct {\n\tu_char cmd;\n\tchar nr_args, nr_returns;\n\tu_char data[30];\n} mpu_command_rec;\n\n#define SNDCTL_MIDI_PRETIME\t_IOWR('m', 0, int)\n#define SNDCTL_MIDI_MPUMODE\t_IOWR('m', 1, int)\n#define SNDCTL_MIDI_MPUCMD\t_IOWR('m', 2, mpu_command_rec)\n#define MIOSPASSTHRU\t\t_IOWR('m', 3, int)\n#define MIOGPASSTHRU\t\t_IOWR('m', 4, int)\n\n/*\n * IOCTL commands for /dev/dsp and /dev/audio\n */\n\n#define SNDCTL_DSP_RESET\t_IO  ('P', 0)\n#define SNDCTL_DSP_SYNC\t\t_IO  ('P', 1)\n#define SNDCTL_DSP_SPEED\t_IOWR('P', 2, int)\n#define SNDCTL_DSP_STEREO\t_IOWR('P', 3, int)\n#define SNDCTL_DSP_GETBLKSIZE\t_IOR('P', 4, int)\n#define SNDCTL_DSP_SETBLKSIZE   _IOW('P', 4, int)\n#define SNDCTL_DSP_SETFMT\t_IOWR('P',5, int) /* Selects ONE fmt*/\n\n/*\n * SOUND_PCM_WRITE_CHANNELS is not that different\n * from SNDCTL_DSP_STEREO\n */\n#define SOUND_PCM_WRITE_CHANNELS\t_IOWR('P', 6, int)\n#define SNDCTL_DSP_CHANNELS\tSOUND_PCM_WRITE_CHANNELS\n#define SOUND_PCM_WRITE_FILTER\t_IOWR('P', 7, int)\n#define SNDCTL_DSP_POST\t\t_IO  ('P', 8)\n\n/*\n * SNDCTL_DSP_SETBLKSIZE and the following two calls mostly do\n * the same thing, i.e. set the block size used in DMA transfers.\n */\n#define SNDCTL_DSP_SUBDIVIDE\t_IOWR('P', 9, int)\n#define SNDCTL_DSP_SETFRAGMENT\t_IOWR('P',10, int)\n\n\n#define SNDCTL_DSP_GETFMTS\t_IOR ('P',11, int) /* Returns a mask */\n/*\n * Buffer status queries.\n */\ntypedef struct audio_buf_info {\n    int fragments;\t/* # of avail. frags (partly used ones not counted) */\n    int fragstotal;\t/* Total # of fragments allocated */\n    int fragsize;\t/* Size of a fragment in bytes */\n\n    int bytes;\t/* Avail. space in bytes (includes partly used fragments) */\n\t\t/* Note! 'bytes' could be more than fragments*fragsize */\n} audio_buf_info;\n\n#define SNDCTL_DSP_GETOSPACE\t_IOR ('P',12, audio_buf_info)\n#define SNDCTL_DSP_GETISPACE\t_IOR ('P',13, audio_buf_info)\n\n/*\n * SNDCTL_DSP_NONBLOCK is the same (but less powerful, since the\n * action cannot be undone) of FIONBIO. The same can be achieved\n * by opening the device with O_NDELAY\n */\n#define SNDCTL_DSP_NONBLOCK\t_IO  ('P',14)\n\n#define SNDCTL_DSP_GETCAPS\t_IOR ('P',15, int)\n#define DSP_CAP_REVISION\t0x000000ff /* revision level (0 to 255) */\n#define DSP_CAP_DUPLEX\t\t0x00000100 /* Full duplex record/playback */\n#define DSP_CAP_REALTIME\t0x00000200 /* Real time capability */\n#define DSP_CAP_BATCH\t\t0x00000400\n    /*\n     * Device has some kind of internal buffers which may\n     * cause some delays and decrease precision of timing\n     */\n#define DSP_CAP_COPROC\t\t0x00000800\n    /* Has a coprocessor, sometimes it's a DSP but usually not */\n#define DSP_CAP_TRIGGER\t\t0x00001000 /* Supports SETTRIGGER */\n#define DSP_CAP_MMAP 0x00002000 /* Supports mmap() */\n\n/*\n * What do these function do ?\n */\n#define SNDCTL_DSP_GETTRIGGER\t_IOR ('P',16, int)\n#define SNDCTL_DSP_SETTRIGGER\t_IOW ('P',16, int)\n#define PCM_ENABLE_INPUT\t0x00000001\n#define PCM_ENABLE_OUTPUT\t0x00000002\n\ntypedef struct count_info {\n\tint bytes;\t/* Total # of bytes processed */\n\tint blocks;\t/* # of fragment transitions since last time */\n\tint ptr;\t/* Current DMA pointer value */\n} count_info;\n\n/*\n * GETIPTR and GETISPACE are not that different... same for out.\n */\n#define SNDCTL_DSP_GETIPTR\t_IOR ('P',17, count_info)\n#define SNDCTL_DSP_GETOPTR\t_IOR ('P',18, count_info)\n\ntypedef struct buffmem_desc {\n\tcaddr_t buffer;\n\tint size;\n} buffmem_desc;\n\n#define SNDCTL_DSP_MAPINBUF\t_IOR ('P', 19, buffmem_desc)\n#define SNDCTL_DSP_MAPOUTBUF\t_IOR ('P', 20, buffmem_desc)\n#define SNDCTL_DSP_SETSYNCRO\t_IO  ('P', 21)\n#define SNDCTL_DSP_SETDUPLEX\t_IO  ('P', 22)\n#define SNDCTL_DSP_GETODELAY\t_IOR ('P', 23, int)\n\n/*\n * I guess these are the readonly version of the same\n * functions that exist above as SNDCTL_DSP_...\n */\n#define SOUND_PCM_READ_RATE\t_IOR ('P', 2, int)\n#define SOUND_PCM_READ_CHANNELS\t_IOR ('P', 6, int)\n#define SOUND_PCM_READ_BITS\t_IOR ('P', 5, int)\n#define SOUND_PCM_READ_FILTER\t_IOR ('P', 7, int)\n\n/*\n * ioctl calls to be used in communication with coprocessors and\n * DSP chips.\n */\n\ntypedef struct copr_buffer {\n\tint command;\t/* Set to 0 if not used */\n\tint flags;\n#define CPF_NONE\t\t0x0000\n#define CPF_FIRST\t\t0x0001\t/* First block */\n#define CPF_LAST\t\t0x0002\t/* Last block */\n\tint len;\n\tint offs;\t/* If required by the device (0 if not used) */\n\n\tu_char data[4000]; /* NOTE! 4000 is not 4k */\n} copr_buffer;\n\ntypedef struct copr_debug_buf {\n\tint command;\t/* Used internally. Set to 0 */\n\tint parm1;\n\tint parm2;\n\tint flags;\n\tint len;\t/* Length of data in bytes */\n} copr_debug_buf;\n\ntypedef struct copr_msg {\n\tint len;\n\tu_char data[4000];\n} copr_msg;\n\n#define SNDCTL_COPR_RESET       _IO  ('C',  0)\n#define SNDCTL_COPR_LOAD\t_IOWR('C',  1, copr_buffer)\n#define SNDCTL_COPR_RDATA\t_IOWR('C',  2, copr_debug_buf)\n#define SNDCTL_COPR_RCODE\t_IOWR('C',  3, copr_debug_buf)\n#define SNDCTL_COPR_WDATA\t_IOW ('C',  4, copr_debug_buf)\n#define SNDCTL_COPR_WCODE\t_IOW ('C',  5, copr_debug_buf)\n#define SNDCTL_COPR_RUN\t\t_IOWR('C',  6, copr_debug_buf)\n#define SNDCTL_COPR_HALT\t_IOWR('C',  7, copr_debug_buf)\n#define SNDCTL_COPR_SENDMSG\t_IOW ('C',  8, copr_msg)\n#define SNDCTL_COPR_RCVMSG\t_IOR ('C',  9, copr_msg)\n\n/*\n * IOCTL commands for /dev/mixer\n */\n\n/*\n * Mixer devices\n *\n * There can be up to 20 different analog mixer channels. The\n * SOUND_MIXER_NRDEVICES gives the currently supported maximum.\n * The SOUND_MIXER_READ_DEVMASK returns a bitmask which tells\n * the devices supported by the particular mixer.\n */\n\n#define SOUND_MIXER_NRDEVICES\t25\n#define SOUND_MIXER_VOLUME\t0\t/* Master output level */\n#define SOUND_MIXER_BASS\t1\t/* Treble level of all output channels */\n#define SOUND_MIXER_TREBLE\t2\t/* Bass level of all output channels */\n#define SOUND_MIXER_SYNTH\t3\t/* Volume of synthesier input */\n#define SOUND_MIXER_PCM\t\t4\t/* Output level for the audio device */\n#define SOUND_MIXER_SPEAKER\t5\t/* Output level for the PC speaker\n\t\t\t\t\t * signals */\n#define SOUND_MIXER_LINE\t6\t/* Volume level for the line in jack */\n#define SOUND_MIXER_MIC\t\t7\t/* Volume for the signal coming from\n\t\t\t\t\t * the microphone jack */\n#define SOUND_MIXER_CD\t\t8\t/* Volume level for the input signal\n\t\t\t\t\t * connected to the CD audio input */\n#define SOUND_MIXER_IMIX\t9\t/* Recording monitor. It controls the\n\t\t\t\t\t * output volume of the selected\n\t\t\t\t\t * recording sources while recording */\n#define SOUND_MIXER_ALTPCM\t10\t/* Volume of the alternative codec\n\t\t\t\t\t * device */\n#define SOUND_MIXER_RECLEV\t11\t/* Global recording level */\n#define SOUND_MIXER_IGAIN\t12\t/* Input gain */\n#define SOUND_MIXER_OGAIN\t13\t/* Output gain */\n/*\n * The AD1848 codec and compatibles have three line level inputs\n * (line, aux1 and aux2). Since each card manufacturer have assigned\n * different meanings to these inputs, it's inpractical to assign\n * specific meanings (line, cd, synth etc.) to them.\n */\n#define SOUND_MIXER_LINE1\t14\t/* Input source 1  (aux1) */\n#define SOUND_MIXER_LINE2\t15\t/* Input source 2  (aux2) */\n#define SOUND_MIXER_LINE3\t16\t/* Input source 3  (line) */\n#define SOUND_MIXER_DIGITAL1    17      /* Digital (input) 1 */\n#define SOUND_MIXER_DIGITAL2    18      /* Digital (input) 2 */\n#define SOUND_MIXER_DIGITAL3    19      /* Digital (input) 3 */\n#define SOUND_MIXER_PHONEIN     20      /* Phone input */\n#define SOUND_MIXER_PHONEOUT    21      /* Phone output */\n#define SOUND_MIXER_VIDEO       22      /* Video/TV (audio) in */\n#define SOUND_MIXER_RADIO       23      /* Radio in */\n#define SOUND_MIXER_MONITOR     24      /* Monitor (usually mic) volume */\n\n\n/*\n * Some on/off settings (SOUND_SPECIAL_MIN - SOUND_SPECIAL_MAX)\n * Not counted to SOUND_MIXER_NRDEVICES, but use the same number space\n */\n#define SOUND_ONOFF_MIN\t\t28\n#define SOUND_ONOFF_MAX\t\t30\n#define SOUND_MIXER_MUTE\t28\t/* 0 or 1 */\n#define SOUND_MIXER_ENHANCE\t29\t/* Enhanced stereo (0, 40, 60 or 80) */\n#define SOUND_MIXER_LOUD\t30\t/* 0 or 1 */\n\n/* Note!\tNumber 31 cannot be used since the sign bit is reserved */\n#define SOUND_MIXER_NONE        31\n\n#define SOUND_DEVICE_LABELS\t{ \\\n\t\"Vol  \", \"Bass \", \"Trebl\", \"Synth\", \"Pcm  \", \"Spkr \", \"Line \", \\\n\t\"Mic  \", \"CD   \", \"Mix  \", \"Pcm2 \", \"Rec  \", \"IGain\", \"OGain\", \\\n\t\"Line1\", \"Line2\", \"Line3\", \"Digital1\", \"Digital2\", \"Digital3\", \\\n\t\"PhoneIn\", \"PhoneOut\", \"Video\", \"Radio\", \"Monitor\"}\n\n#define SOUND_DEVICE_NAMES\t{ \\\n\t\"vol\", \"bass\", \"treble\", \"synth\", \"pcm\", \"speaker\", \"line\", \\\n\t\"mic\", \"cd\", \"mix\", \"pcm2\", \"rec\", \"igain\", \"ogain\", \\\n\t\"line1\", \"line2\", \"line3\", \"dig1\", \"dig2\", \"dig3\", \\\n\t\"phin\", \"phout\", \"video\", \"radio\", \"monitor\"}\n\n/*\tDevice bitmask identifiers\t*/\n\n#define SOUND_MIXER_RECSRC\t0xff\t/* 1 bit per recording source */\n#define SOUND_MIXER_DEVMASK\t0xfe\t/* 1 bit per supported device */\n#define SOUND_MIXER_RECMASK\t0xfd\t/* 1 bit per supp. recording source */\n#define SOUND_MIXER_CAPS\t0xfc\n#define SOUND_CAP_EXCL_INPUT\t0x00000001\t/* Only 1 rec. src at a time */\n#define SOUND_MIXER_STEREODEVS\t0xfb\t/* Mixer channels supporting stereo */\n\n/*\tDevice mask bits\t*/\n\n#define SOUND_MASK_VOLUME\t(1 << SOUND_MIXER_VOLUME)\n#define SOUND_MASK_BASS\t\t(1 << SOUND_MIXER_BASS)\n#define SOUND_MASK_TREBLE\t(1 << SOUND_MIXER_TREBLE)\n#define SOUND_MASK_SYNTH\t(1 << SOUND_MIXER_SYNTH)\n#define SOUND_MASK_PCM\t\t(1 << SOUND_MIXER_PCM)\n#define SOUND_MASK_SPEAKER\t(1 << SOUND_MIXER_SPEAKER)\n#define SOUND_MASK_LINE\t\t(1 << SOUND_MIXER_LINE)\n#define SOUND_MASK_MIC\t\t(1 << SOUND_MIXER_MIC)\n#define SOUND_MASK_CD\t\t(1 << SOUND_MIXER_CD)\n#define SOUND_MASK_IMIX\t\t(1 << SOUND_MIXER_IMIX)\n#define SOUND_MASK_ALTPCM\t(1 << SOUND_MIXER_ALTPCM)\n#define SOUND_MASK_RECLEV\t(1 << SOUND_MIXER_RECLEV)\n#define SOUND_MASK_IGAIN\t(1 << SOUND_MIXER_IGAIN)\n#define SOUND_MASK_OGAIN\t(1 << SOUND_MIXER_OGAIN)\n#define SOUND_MASK_LINE1\t(1 << SOUND_MIXER_LINE1)\n#define SOUND_MASK_LINE2\t(1 << SOUND_MIXER_LINE2)\n#define SOUND_MASK_LINE3\t(1 << SOUND_MIXER_LINE3)\n#define SOUND_MASK_DIGITAL1     (1 << SOUND_MIXER_DIGITAL1)\n#define SOUND_MASK_DIGITAL2     (1 << SOUND_MIXER_DIGITAL2)\n#define SOUND_MASK_DIGITAL3     (1 << SOUND_MIXER_DIGITAL3)\n#define SOUND_MASK_PHONEIN      (1 << SOUND_MIXER_PHONEIN)\n#define SOUND_MASK_PHONEOUT     (1 << SOUND_MIXER_PHONEOUT)\n#define SOUND_MASK_RADIO        (1 << SOUND_MIXER_RADIO)\n#define SOUND_MASK_VIDEO        (1 << SOUND_MIXER_VIDEO)\n#define SOUND_MASK_MONITOR      (1 << SOUND_MIXER_MONITOR)\n\n/* Obsolete macros */\n#define SOUND_MASK_MUTE\t\t(1 << SOUND_MIXER_MUTE)\n#define SOUND_MASK_ENHANCE\t(1 << SOUND_MIXER_ENHANCE)\n#define SOUND_MASK_LOUD\t\t(1 << SOUND_MIXER_LOUD)\n\n#define MIXER_READ(dev)\t\t_IOR('M', dev, int)\n#define SOUND_MIXER_READ_VOLUME\t\tMIXER_READ(SOUND_MIXER_VOLUME)\n#define SOUND_MIXER_READ_BASS\t\tMIXER_READ(SOUND_MIXER_BASS)\n#define SOUND_MIXER_READ_TREBLE\t\tMIXER_READ(SOUND_MIXER_TREBLE)\n#define SOUND_MIXER_READ_SYNTH\t\tMIXER_READ(SOUND_MIXER_SYNTH)\n#define SOUND_MIXER_READ_PCM\t\tMIXER_READ(SOUND_MIXER_PCM)\n#define SOUND_MIXER_READ_SPEAKER\tMIXER_READ(SOUND_MIXER_SPEAKER)\n#define SOUND_MIXER_READ_LINE\t\tMIXER_READ(SOUND_MIXER_LINE)\n#define SOUND_MIXER_READ_MIC\t\tMIXER_READ(SOUND_MIXER_MIC)\n#define SOUND_MIXER_READ_CD\t\tMIXER_READ(SOUND_MIXER_CD)\n#define SOUND_MIXER_READ_IMIX\t\tMIXER_READ(SOUND_MIXER_IMIX)\n#define SOUND_MIXER_READ_ALTPCM\t\tMIXER_READ(SOUND_MIXER_ALTPCM)\n#define SOUND_MIXER_READ_RECLEV\t\tMIXER_READ(SOUND_MIXER_RECLEV)\n#define SOUND_MIXER_READ_IGAIN\t\tMIXER_READ(SOUND_MIXER_IGAIN)\n#define SOUND_MIXER_READ_OGAIN\t\tMIXER_READ(SOUND_MIXER_OGAIN)\n#define SOUND_MIXER_READ_LINE1\t\tMIXER_READ(SOUND_MIXER_LINE1)\n#define SOUND_MIXER_READ_LINE2\t\tMIXER_READ(SOUND_MIXER_LINE2)\n#define SOUND_MIXER_READ_LINE3\t\tMIXER_READ(SOUND_MIXER_LINE3)\n#define SOUND_MIXER_READ_DIGITAL1\tMIXER_READ(SOUND_MIXER_DIGITAL1)\n#define SOUND_MIXER_READ_DIGITAL2\tMIXER_READ(SOUND_MIXER_DIGITAL2)\n#define SOUND_MIXER_READ_DIGITAL3\tMIXER_READ(SOUND_MIXER_DIGITAL3)\n#define SOUND_MIXER_READ_PHONEIN      \tMIXER_READ(SOUND_MIXER_PHONEIN)\n#define SOUND_MIXER_READ_PHONEOUT\tMIXER_READ(SOUND_MIXER_PHONEOUT)\n#define SOUND_MIXER_READ_RADIO\t\tMIXER_READ(SOUND_MIXER_RADIO)\n#define SOUND_MIXER_READ_VIDEO\t\tMIXER_READ(SOUND_MIXER_VIDEO)\n#define SOUND_MIXER_READ_MONITOR\tMIXER_READ(SOUND_MIXER_MONITOR)\n\n/* Obsolete macros */\n#define SOUND_MIXER_READ_MUTE\t\tMIXER_READ(SOUND_MIXER_MUTE)\n#define SOUND_MIXER_READ_ENHANCE\tMIXER_READ(SOUND_MIXER_ENHANCE)\n#define SOUND_MIXER_READ_LOUD\t\tMIXER_READ(SOUND_MIXER_LOUD)\n\n#define SOUND_MIXER_READ_RECSRC\t\tMIXER_READ(SOUND_MIXER_RECSRC)\n#define SOUND_MIXER_READ_DEVMASK\tMIXER_READ(SOUND_MIXER_DEVMASK)\n#define SOUND_MIXER_READ_RECMASK\tMIXER_READ(SOUND_MIXER_RECMASK)\n#define SOUND_MIXER_READ_STEREODEVS\tMIXER_READ(SOUND_MIXER_STEREODEVS)\n#define SOUND_MIXER_READ_CAPS\t\tMIXER_READ(SOUND_MIXER_CAPS)\n\n#define MIXER_WRITE(dev)\t\t_IOWR('M', dev, int)\n#define SOUND_MIXER_WRITE_VOLUME\tMIXER_WRITE(SOUND_MIXER_VOLUME)\n#define SOUND_MIXER_WRITE_BASS\t\tMIXER_WRITE(SOUND_MIXER_BASS)\n#define SOUND_MIXER_WRITE_TREBLE\tMIXER_WRITE(SOUND_MIXER_TREBLE)\n#define SOUND_MIXER_WRITE_SYNTH\t\tMIXER_WRITE(SOUND_MIXER_SYNTH)\n#define SOUND_MIXER_WRITE_PCM\t\tMIXER_WRITE(SOUND_MIXER_PCM)\n#define SOUND_MIXER_WRITE_SPEAKER\tMIXER_WRITE(SOUND_MIXER_SPEAKER)\n#define SOUND_MIXER_WRITE_LINE\t\tMIXER_WRITE(SOUND_MIXER_LINE)\n#define SOUND_MIXER_WRITE_MIC\t\tMIXER_WRITE(SOUND_MIXER_MIC)\n#define SOUND_MIXER_WRITE_CD\t\tMIXER_WRITE(SOUND_MIXER_CD)\n#define SOUND_MIXER_WRITE_IMIX\t\tMIXER_WRITE(SOUND_MIXER_IMIX)\n#define SOUND_MIXER_WRITE_ALTPCM\tMIXER_WRITE(SOUND_MIXER_ALTPCM)\n#define SOUND_MIXER_WRITE_RECLEV\tMIXER_WRITE(SOUND_MIXER_RECLEV)\n#define SOUND_MIXER_WRITE_IGAIN\t\tMIXER_WRITE(SOUND_MIXER_IGAIN)\n#define SOUND_MIXER_WRITE_OGAIN\t\tMIXER_WRITE(SOUND_MIXER_OGAIN)\n#define SOUND_MIXER_WRITE_LINE1\t\tMIXER_WRITE(SOUND_MIXER_LINE1)\n#define SOUND_MIXER_WRITE_LINE2\t\tMIXER_WRITE(SOUND_MIXER_LINE2)\n#define SOUND_MIXER_WRITE_LINE3\t\tMIXER_WRITE(SOUND_MIXER_LINE3)\n#define SOUND_MIXER_WRITE_DIGITAL1\tMIXER_WRITE(SOUND_MIXER_DIGITAL1)\n#define SOUND_MIXER_WRITE_DIGITAL2\tMIXER_WRITE(SOUND_MIXER_DIGITAL2)\n#define SOUND_MIXER_WRITE_DIGITAL3\tMIXER_WRITE(SOUND_MIXER_DIGITAL3)\n#define SOUND_MIXER_WRITE_PHONEIN      \tMIXER_WRITE(SOUND_MIXER_PHONEIN)\n#define SOUND_MIXER_WRITE_PHONEOUT\tMIXER_WRITE(SOUND_MIXER_PHONEOUT)\n#define SOUND_MIXER_WRITE_RADIO\t\tMIXER_WRITE(SOUND_MIXER_RADIO)\n#define SOUND_MIXER_WRITE_VIDEO\t\tMIXER_WRITE(SOUND_MIXER_VIDEO)\n#define SOUND_MIXER_WRITE_MONITOR\tMIXER_WRITE(SOUND_MIXER_MONITOR)\n\n#define SOUND_MIXER_WRITE_MUTE\t\tMIXER_WRITE(SOUND_MIXER_MUTE)\n#define SOUND_MIXER_WRITE_ENHANCE\tMIXER_WRITE(SOUND_MIXER_ENHANCE)\n#define SOUND_MIXER_WRITE_LOUD\t\tMIXER_WRITE(SOUND_MIXER_LOUD)\n\n#define SOUND_MIXER_WRITE_RECSRC\tMIXER_WRITE(SOUND_MIXER_RECSRC)\n\ntypedef struct mixer_info {\n  char id[16];\n  char name[32];\n  int  modify_counter;\n  int fillers[10];\n} mixer_info;\n\n#define SOUND_MIXER_INFO\t\t_IOR('M', 101, mixer_info)\n\n#define LEFT_CHN\t0\n#define RIGHT_CHN\t1\n\n/*\n * Level 2 event types for /dev/sequencer\n */\n\n/*\n * The 4 most significant bits of byte 0 specify the class of\n * the event:\n *\n *\t0x8X = system level events,\n *\t0x9X = device/port specific events, event[1] = device/port,\n *\t\tThe last 4 bits give the subtype:\n *\t\t\t0x02\t= Channel event (event[3] = chn).\n *\t\t\t0x01\t= note event (event[4] = note).\n *\t\t\t(0x01 is not used alone but always with bit 0x02).\n *\t       event[2] = MIDI message code (0x80=note off etc.)\n *\n */\n\n#define EV_SEQ_LOCAL\t\t0x80\n#define EV_TIMING\t\t0x81\n#define EV_CHN_COMMON\t\t0x92\n#define EV_CHN_VOICE\t\t0x93\n#define EV_SYSEX\t\t0x94\n/*\n * Event types 200 to 220 are reserved for application use.\n * These numbers will not be used by the driver.\n */\n\n/*\n * Events for event type EV_CHN_VOICE\n */\n\n#define MIDI_NOTEOFF\t\t0x80\n#define MIDI_NOTEON\t\t0x90\n#define MIDI_KEY_PRESSURE\t0xA0\n\n/*\n * Events for event type EV_CHN_COMMON\n */\n\n#define MIDI_CTL_CHANGE\t\t0xB0\n#define MIDI_PGM_CHANGE\t\t0xC0\n#define MIDI_CHN_PRESSURE\t0xD0\n#define MIDI_PITCH_BEND\t\t0xE0\n\n#define MIDI_SYSTEM_PREFIX\t0xF0\n\n/*\n * Timer event types\n */\n#define TMR_WAIT_REL\t\t1\t/* Time relative to the prev time */\n#define TMR_WAIT_ABS\t\t2\t/* Absolute time since TMR_START */\n#define TMR_STOP\t\t3\n#define TMR_START\t\t4\n#define TMR_CONTINUE\t\t5\n#define TMR_TEMPO\t\t6\n#define TMR_ECHO\t\t8\n#define TMR_CLOCK\t\t9\t/* MIDI clock */\n#define TMR_SPP\t\t\t10\t/* Song position pointer */\n#define TMR_TIMESIG\t\t11\t/* Time signature */\n\n/*\n *\tLocal event types\n */\n#define LOCL_STARTAUDIO\t\t1\n\n#if (!defined(_KERNEL) && !defined(INKERNEL)) || defined(USE_SEQ_MACROS)\n/*\n *\tSome convenience macros to simplify programming of the\n *\t/dev/sequencer interface\n *\n *\tThese macros define the API which should be used when possible.\n */\n\n#ifndef USE_SIMPLE_MACROS\nvoid seqbuf_dump(void);\t/* This function must be provided by programs */\n\n/* Sample seqbuf_dump() implementation:\n *\n *\tSEQ_DEFINEBUF (2048);\t-- Defines a buffer for 2048 bytes\n *\n *\tint seqfd;\t\t-- The file descriptor for /dev/sequencer.\n *\n *\tvoid\n *\tseqbuf_dump ()\n *\t{\n *\t  if (_seqbufptr)\n *\t    if (write (seqfd, _seqbuf, _seqbufptr) == -1)\n *\t      {\n *\t\tperror (\"write /dev/sequencer\");\n *\t\texit (-1);\n *\t      }\n *\t  _seqbufptr = 0;\n *\t}\n */\n\n#define SEQ_DEFINEBUF(len)\t\t\\\n\tu_char _seqbuf[len]; int _seqbuflen = len;int _seqbufptr = 0\n#define SEQ_USE_EXTBUF()\t\t\\\n\textern u_char _seqbuf[]; \\\n\textern int _seqbuflen;extern int _seqbufptr\n#define SEQ_DECLAREBUF()\t\tSEQ_USE_EXTBUF()\n#define SEQ_PM_DEFINES\t\t\tstruct patmgr_info _pm_info\n#define _SEQ_NEEDBUF(len)\t\t\\\n\tif ((_seqbufptr+(len)) > _seqbuflen) \\\n\t\tseqbuf_dump()\n#define _SEQ_ADVBUF(len)\t\t_seqbufptr += len\n#define SEQ_DUMPBUF\t\t\tseqbuf_dump\n#else\n/*\n * This variation of the sequencer macros is used just to format one event\n * using fixed buffer.\n *\n * The program using the macro library must define the following macros before\n * using this library.\n *\n * #define _seqbuf \t\t name of the buffer (u_char[])\n * #define _SEQ_ADVBUF(len)\t If the applic needs to know the exact\n *\t\t\t\t size of the event, this macro can be used.\n *\t\t\t\t Otherwise this must be defined as empty.\n * #define _seqbufptr\t\t Define the name of index variable or 0 if\n *\t\t\t\t not required.\n */\n#define _SEQ_NEEDBUF(len)\t/* empty */\n#endif\n\n#define PM_LOAD_PATCH(dev, bank, pgm)\t\\\n\t(SEQ_DUMPBUF(), _pm_info.command = _PM_LOAD_PATCH, \\\n\t_pm_info.device=dev, _pm_info.data.data8[0]=pgm, \\\n\t_pm_info.parm1 = bank, _pm_info.parm2 = 1, \\\n\tioctl(seqfd, SNDCTL_PMGR_ACCESS, &_pm_info))\n#define PM_LOAD_PATCHES(dev, bank, pgm) \\\n\t(SEQ_DUMPBUF(), _pm_info.command = _PM_LOAD_PATCH, \\\n\t_pm_info.device=dev, bcopy( pgm, _pm_info.data.data8,  128), \\\n\t_pm_info.parm1 = bank, _pm_info.parm2 = 128, \\\n\tioctl(seqfd, SNDCTL_PMGR_ACCESS, &_pm_info))\n\n#define SEQ_VOLUME_MODE(dev, mode)\t{ \\\n\t_SEQ_NEEDBUF(8);\\\n\t_seqbuf[_seqbufptr] = SEQ_EXTENDED;\\\n\t_seqbuf[_seqbufptr+1] = SEQ_VOLMODE;\\\n\t_seqbuf[_seqbufptr+2] = (dev);\\\n\t_seqbuf[_seqbufptr+3] = (mode);\\\n\t_seqbuf[_seqbufptr+4] = 0;\\\n\t_seqbuf[_seqbufptr+5] = 0;\\\n\t_seqbuf[_seqbufptr+6] = 0;\\\n\t_seqbuf[_seqbufptr+7] = 0;\\\n\t_SEQ_ADVBUF(8);}\n\n/*\n * Midi voice messages\n */\n\n#define _CHN_VOICE(dev, event, chn, note, parm)  { \\\n\t_SEQ_NEEDBUF(8);\\\n\t_seqbuf[_seqbufptr] = EV_CHN_VOICE;\\\n\t_seqbuf[_seqbufptr+1] = (dev);\\\n\t_seqbuf[_seqbufptr+2] = (event);\\\n\t_seqbuf[_seqbufptr+3] = (chn);\\\n\t_seqbuf[_seqbufptr+4] = (note);\\\n\t_seqbuf[_seqbufptr+5] = (parm);\\\n\t_seqbuf[_seqbufptr+6] = (0);\\\n\t_seqbuf[_seqbufptr+7] = 0;\\\n\t_SEQ_ADVBUF(8);}\n\n#define SEQ_START_NOTE(dev, chn, note, vol) \\\n\t\t_CHN_VOICE(dev, MIDI_NOTEON, chn, note, vol)\n\n#define SEQ_STOP_NOTE(dev, chn, note, vol) \\\n\t\t_CHN_VOICE(dev, MIDI_NOTEOFF, chn, note, vol)\n\n#define SEQ_KEY_PRESSURE(dev, chn, note, pressure) \\\n\t\t_CHN_VOICE(dev, MIDI_KEY_PRESSURE, chn, note, pressure)\n\n/*\n * Midi channel messages\n */\n\n#define _CHN_COMMON(dev, event, chn, p1, p2, w14) { \\\n\t_SEQ_NEEDBUF(8);\\\n\t_seqbuf[_seqbufptr] = EV_CHN_COMMON;\\\n\t_seqbuf[_seqbufptr+1] = (dev);\\\n\t_seqbuf[_seqbufptr+2] = (event);\\\n\t_seqbuf[_seqbufptr+3] = (chn);\\\n\t_seqbuf[_seqbufptr+4] = (p1);\\\n\t_seqbuf[_seqbufptr+5] = (p2);\\\n\t*(short *)&_seqbuf[_seqbufptr+6] = (w14);\\\n\t_SEQ_ADVBUF(8);}\n/*\n * SEQ_SYSEX permits sending of sysex messages. (It may look that it permits\n * sending any MIDI bytes but it's absolutely not possible. Trying to do\n * so _will_ cause problems with MPU401 intelligent mode).\n *\n * Sysex messages are sent in blocks of 1 to 6 bytes. Longer messages must be\n * sent by calling SEQ_SYSEX() several times (there must be no other events\n * between them). First sysex fragment must have 0xf0 in the first byte\n * and the last byte (buf[len-1] of the last fragment must be 0xf7. No byte\n * between these sysex start and end markers cannot be larger than 0x7f. Also\n * lengths of each fragments (except the last one) must be 6.\n *\n * Breaking the above rules may work with some MIDI ports but is likely to\n * cause fatal problems with some other devices (such as MPU401).\n */\n#define SEQ_SYSEX(dev, buf, len) { \\\n\tint i, l=(len); if (l>6)l=6;\\\n\t_SEQ_NEEDBUF(8);\\\n\t_seqbuf[_seqbufptr] = EV_SYSEX;\\\n\tfor(i=0;i<l;i++)_seqbuf[_seqbufptr+i+1] = (buf)[i];\\\n\tfor(i=l;i<6;i++)_seqbuf[_seqbufptr+i+1] = 0xff;\\\n\t_SEQ_ADVBUF(8);}\n\n#define SEQ_CHN_PRESSURE(dev, chn, pressure) \\\n\t_CHN_COMMON(dev, MIDI_CHN_PRESSURE, chn, pressure, 0, 0)\n\n#define SEQ_SET_PATCH(dev, chn, patch) \\\n\t_CHN_COMMON(dev, MIDI_PGM_CHANGE, chn, patch, 0, 0)\n\n#define SEQ_CONTROL(dev, chn, controller, value) \\\n\t_CHN_COMMON(dev, MIDI_CTL_CHANGE, chn, controller, 0, value)\n\n#define SEQ_BENDER(dev, chn, value) \\\n\t_CHN_COMMON(dev, MIDI_PITCH_BEND, chn, 0, 0, value)\n\n\n#define SEQ_V2_X_CONTROL(dev, voice, controller, value)\t{ \\\n\t_SEQ_NEEDBUF(8);\\\n\t_seqbuf[_seqbufptr] = SEQ_EXTENDED;\\\n\t_seqbuf[_seqbufptr+1] = SEQ_CONTROLLER;\\\n\t_seqbuf[_seqbufptr+2] = (dev);\\\n\t_seqbuf[_seqbufptr+3] = (voice);\\\n\t_seqbuf[_seqbufptr+4] = (controller);\\\n\t*(short *)&_seqbuf[_seqbufptr+5] = (value);\\\n\t_seqbuf[_seqbufptr+7] = 0;\\\n\t_SEQ_ADVBUF(8);}\n\n/*\n * The following 5 macros are incorrectly implemented and obsolete.\n * Use SEQ_BENDER and SEQ_CONTROL (with proper controller) instead.\n */\n\n#define SEQ_PITCHBEND(dev, voice, value) \\\n\tSEQ_V2_X_CONTROL(dev, voice, CTRL_PITCH_BENDER, value)\n#define SEQ_BENDER_RANGE(dev, voice, value) \\\n\tSEQ_V2_X_CONTROL(dev, voice, CTRL_PITCH_BENDER_RANGE, value)\n#define SEQ_EXPRESSION(dev, voice, value) \\\n\tSEQ_CONTROL(dev, voice, CTL_EXPRESSION, value*128)\n#define SEQ_MAIN_VOLUME(dev, voice, value) \\\n\tSEQ_CONTROL(dev, voice, CTL_MAIN_VOLUME, (value*16383)/100)\n#define SEQ_PANNING(dev, voice, pos) \\\n\tSEQ_CONTROL(dev, voice, CTL_PAN, (pos+128) / 2)\n\n/*\n * Timing and syncronization macros\n */\n\n#define _TIMER_EVENT(ev, parm)\t\t{ \\\n\t_SEQ_NEEDBUF(8);\\\n\t_seqbuf[_seqbufptr+0] = EV_TIMING; \\\n\t_seqbuf[_seqbufptr+1] = (ev); \\\n\t_seqbuf[_seqbufptr+2] = 0;\\\n\t_seqbuf[_seqbufptr+3] = 0;\\\n\t*(u_int *)&_seqbuf[_seqbufptr+4] = (parm); \\\n\t_SEQ_ADVBUF(8); \\\n\t}\n\n#define SEQ_START_TIMER()\t\t_TIMER_EVENT(TMR_START, 0)\n#define SEQ_STOP_TIMER()\t\t_TIMER_EVENT(TMR_STOP, 0)\n#define SEQ_CONTINUE_TIMER()\t\t_TIMER_EVENT(TMR_CONTINUE, 0)\n#define SEQ_WAIT_TIME(ticks)\t\t_TIMER_EVENT(TMR_WAIT_ABS, ticks)\n#define SEQ_DELTA_TIME(ticks)\t\t_TIMER_EVENT(TMR_WAIT_REL, ticks)\n#define SEQ_ECHO_BACK(key)\t\t_TIMER_EVENT(TMR_ECHO, key)\n#define SEQ_SET_TEMPO(value)\t\t_TIMER_EVENT(TMR_TEMPO, value)\n#define SEQ_SONGPOS(pos)\t\t_TIMER_EVENT(TMR_SPP, pos)\n#define SEQ_TIME_SIGNATURE(sig)\t\t_TIMER_EVENT(TMR_TIMESIG, sig)\n\n/*\n * Local control events\n */\n\n#define _LOCAL_EVENT(ev, parm)\t\t{ \\\n\t_SEQ_NEEDBUF(8);\\\n\t_seqbuf[_seqbufptr+0] = EV_SEQ_LOCAL; \\\n\t_seqbuf[_seqbufptr+1] = (ev); \\\n\t_seqbuf[_seqbufptr+2] = 0;\\\n\t_seqbuf[_seqbufptr+3] = 0;\\\n\t*(u_int *)&_seqbuf[_seqbufptr+4] = (parm); \\\n\t_SEQ_ADVBUF(8); \\\n\t}\n\n#define SEQ_PLAYAUDIO(devmask)\t\t_LOCAL_EVENT(LOCL_STARTAUDIO, devmask)\n/*\n * Events for the level 1 interface only\n */\n\n#define SEQ_MIDIOUT(device, byte)\t{ \\\n\t_SEQ_NEEDBUF(4);\\\n\t_seqbuf[_seqbufptr] = SEQ_MIDIPUTC;\\\n\t_seqbuf[_seqbufptr+1] = (byte);\\\n\t_seqbuf[_seqbufptr+2] = (device);\\\n\t_seqbuf[_seqbufptr+3] = 0;\\\n\t_SEQ_ADVBUF(4);}\n\n/*\n * Patch loading.\n */\n#define SEQ_WRPATCH(patchx, len)\t{ \\\n\tif (_seqbufptr) seqbuf_dump(); \\\n\tif (write(seqfd, (char*)(patchx), len)==-1) \\\n\t   perror(\"Write patch: /dev/sequencer\"); \\\n\t}\n\n#define SEQ_WRPATCH2(patchx, len)\t\\\n\t( seqbuf_dump(), write(seqfd, (char*)(patchx), len) )\n\n#endif\n\n/*\n * Here I have moved all the aliases for ioctl names.\n */\n\n#define SNDCTL_DSP_SAMPLESIZE\tSNDCTL_DSP_SETFMT\n#define SOUND_PCM_WRITE_BITS\tSNDCTL_DSP_SETFMT\n#define SOUND_PCM_SETFMT\tSNDCTL_DSP_SETFMT\n\n#define SOUND_PCM_WRITE_RATE\tSNDCTL_DSP_SPEED\n#define SOUND_PCM_POST\t\tSNDCTL_DSP_POST\n#define SOUND_PCM_RESET\t\tSNDCTL_DSP_RESET\n#define SOUND_PCM_SYNC\t\tSNDCTL_DSP_SYNC\n#define SOUND_PCM_SUBDIVIDE\tSNDCTL_DSP_SUBDIVIDE\n#define SOUND_PCM_SETFRAGMENT\tSNDCTL_DSP_SETFRAGMENT\n#define SOUND_PCM_GETFMTS\tSNDCTL_DSP_GETFMTS\n#define SOUND_PCM_GETOSPACE\tSNDCTL_DSP_GETOSPACE\n#define SOUND_PCM_GETISPACE\tSNDCTL_DSP_GETISPACE\n#define SOUND_PCM_NONBLOCK\tSNDCTL_DSP_NONBLOCK\n#define SOUND_PCM_GETCAPS\tSNDCTL_DSP_GETCAPS\n#define SOUND_PCM_GETTRIGGER\tSNDCTL_DSP_GETTRIGGER\n#define SOUND_PCM_SETTRIGGER\tSNDCTL_DSP_SETTRIGGER\n#define SOUND_PCM_SETSYNCRO\tSNDCTL_DSP_SETSYNCRO\n#define SOUND_PCM_GETIPTR\tSNDCTL_DSP_GETIPTR\n#define SOUND_PCM_GETOPTR\tSNDCTL_DSP_GETOPTR\n#define SOUND_PCM_MAPINBUF\tSNDCTL_DSP_MAPINBUF\n#define SOUND_PCM_MAPOUTBUF\tSNDCTL_DSP_MAPOUTBUF\n\n/***********************************************************************/\n\n/**\n * XXX OSSv4 defines -- some bits taken straight out of the new\n * sys/soundcard.h bundled with recent OSS releases.\n *\n * NB:  These macros and structures will be reorganized and inserted\n * \tin appropriate places throughout this file once the code begins\n * \tto take shape.\n *\n * @todo reorganize layout more like the 4Front version\n * @todo ask about maintaining __SIOWR vs. _IOWR ioctl cmd defines\n */\n\n/**\n * @note The @c OSSV4_EXPERIMENT macro is meant to wrap new development code\n * in the sound system relevant to adopting 4Front's OSSv4 specification.\n * Users should not enable this!  Really!\n */\n#if 0\n# define OSSV4_EXPERIMENT 1\n#else\n# undef OSSV4_EXPERIMENT\n#endif\n\n#ifdef SOUND_VERSION\n# undef SOUND_VERSION\n# define SOUND_VERSION\t0x040000\n#endif\t/* !SOUND_VERSION */\n\n#define OSS_LONGNAME_SIZE\t64\n#define OSS_LABEL_SIZE\t\t16\n#define OSS_DEVNODE_SIZE        32\ntypedef char oss_longname_t[OSS_LONGNAME_SIZE];\ntypedef char oss_label_t[OSS_LABEL_SIZE];\ntypedef char oss_devnode_t[OSS_DEVNODE_SIZE];\n\ntypedef struct audio_errinfo\n{\n\tint\t\tplay_underruns;\n\tint\t\trec_overruns;\n\tunsigned int\tplay_ptradjust;\n\tunsigned int\trec_ptradjust;\n\tint\t\tplay_errorcount;\n\tint\t\trec_errorcount;\n\tint\t\tplay_lasterror;\n\tint\t\trec_lasterror;\n\tlong\t\tplay_errorparm;\n\tlong\t\trec_errorparm;\n\tint\t\tfiller[16];\n} audio_errinfo;\n\n#define SNDCTL_DSP_GETPLAYVOL           _IOR ('P', 24, int)\n#define SNDCTL_DSP_SETPLAYVOL           _IOWR('P', 24, int)\n#define SNDCTL_DSP_GETERROR             _IOR ('P', 25, audio_errinfo)\n\n\n/*\n ****************************************************************************\n * Sync groups for audio devices\n */\ntypedef struct oss_syncgroup\n{\n  int id;\n  int mode;\n  int filler[16];\n} oss_syncgroup;\n\n#define SNDCTL_DSP_SYNCGROUP            _IOWR('P', 28, oss_syncgroup)\n#define SNDCTL_DSP_SYNCSTART            _IOW ('P', 29, int)\n\n/*\n **************************************************************************\n * \"cooked\" mode enables software based conversions for sample rate, sample\n * format (bits) and number of channels (mono/stereo). These conversions are\n * required with some devices that support only one sample rate or just stereo\n * to let the applications to use other formats. The cooked mode is enabled by\n * default. However it's necessary to disable this mode when mmap() is used or\n * when very deterministic timing is required. SNDCTL_DSP_COOKEDMODE is an\n * optional call introduced in OSS 3.9.6f. It's _error return must be ignored_\n * since normally this call will return erno=EINVAL.\n *\n * SNDCTL_DSP_COOKEDMODE must be called immediately after open before doing\n * anything else. Otherwise the call will not have any effect.\n */\n#define SNDCTL_DSP_COOKEDMODE           _IOW ('P', 30, int)\n\n/*\n **************************************************************************\n * SNDCTL_DSP_SILENCE and SNDCTL_DSP_SKIP are new calls in OSS 3.99.0\n * that can be used to implement pause/continue during playback (no effect\n * on recording).\n */\n#define SNDCTL_DSP_SILENCE              _IO  ('P', 31)\n#define SNDCTL_DSP_SKIP                 _IO  ('P', 32)\n\n/*\n ****************************************************************************\n * Abort transfer (reset) functions for input and output\n */\n#define SNDCTL_DSP_HALT_INPUT\t\t_IO  ('P', 33)\n#define SNDCTL_DSP_RESET_INPUT\tSNDCTL_DSP_HALT_INPUT\t/* Old name */\n#define SNDCTL_DSP_HALT_OUTPUT\t\t_IO  ('P', 34)\n#define SNDCTL_DSP_RESET_OUTPUT\tSNDCTL_DSP_HALT_OUTPUT\t/* Old name */\n\n/*\n ****************************************************************************\n * Low water level control\n */\n#define SNDCTL_DSP_LOW_WATER\t\t_IOW ('P', 34, int)\n\n/** @todo Get rid of OSS_NO_LONG_LONG references? */\n\n/*\n ****************************************************************************\n * 64 bit pointer support. Only available in environments that support\n * the 64 bit (long long) integer type.\n */\n#ifndef OSS_NO_LONG_LONG\ntypedef struct\n{\n  long long samples;\n  int fifo_samples;\n  int filler[32];\t\t/* For future use */\n} oss_count_t;\n\n#define SNDCTL_DSP_CURRENT_IPTR\t\t_IOR ('P', 35, oss_count_t)\n#define SNDCTL_DSP_CURRENT_OPTR\t\t_IOR ('P', 36, oss_count_t)\n#endif\n\n/*\n ****************************************************************************\n * Interface for selecting recording sources and playback output routings.\n */\n#define SNDCTL_DSP_GET_RECSRC_NAMES     _IOR ('P', 37, oss_mixer_enuminfo)\n#define SNDCTL_DSP_GET_RECSRC           _IOR ('P', 38, int)\n#define SNDCTL_DSP_SET_RECSRC           _IOWR('P', 38, int)\n\n#define SNDCTL_DSP_GET_PLAYTGT_NAMES    _IOR ('P', 39, oss_mixer_enuminfo)\n#define SNDCTL_DSP_GET_PLAYTGT          _IOR ('P', 40, int)\n#define SNDCTL_DSP_SET_PLAYTGT          _IOWR('P', 40, int)\n#define SNDCTL_DSP_GETRECVOL            _IOR ('P', 41, int)\n#define SNDCTL_DSP_SETRECVOL            _IOWR('P', 41, int)\n\n/*\n ***************************************************************************\n * Some calls for setting the channel assignment with multi channel devices\n * (see the manual for details).                                                 */\n#define SNDCTL_DSP_GET_CHNORDER         _IOR ('P', 42, unsigned long long)\n#define SNDCTL_DSP_SET_CHNORDER         _IOWR('P', 42, unsigned long long)\n#       define CHID_UNDEF       0\n#       define CHID_L           1                                               #       define CHID_R           2\n#       define CHID_C           3\n#       define CHID_LFE         4\n#       define CHID_LS          5\n#       define CHID_RS          6\n#       define CHID_LR          7\n#       define CHID_RR          8\n#define CHNORDER_UNDEF          0x0000000000000000ULL\n#define CHNORDER_NORMAL         0x0000000087654321ULL\n\n#define MAX_PEAK_CHANNELS\t128\ntypedef unsigned short oss_peaks_t[MAX_PEAK_CHANNELS];\n#define SNDCTL_DSP_GETIPEAKS\t\t_IOR('P', 43, oss_peaks_t)\n#define SNDCTL_DSP_GETOPEAKS\t\t_IOR('P', 44, oss_peaks_t)\n#define SNDCTL_DSP_POLICY               _IOW('P', 45, int)    /* See the manual */\n\n/*\n * OSS_SYSIFO is obsolete. Use SNDCTL_SYSINFO insteads.\n */\n#define OSS_GETVERSION                  _IOR ('M', 118, int)\n\n/**\n * @brief\tArgument for SNDCTL_SYSINFO ioctl.\n *\n * For use w/ the SNDCTL_SYSINFO ioctl available on audio (/dev/dsp*),\n * mixer, and MIDI devices.\n */\ntypedef struct oss_sysinfo\n{\n\tchar\tproduct[32];\t/* For example OSS/Free, OSS/Linux or\n\t\t\t\t   OSS/Solaris */\n\tchar\tversion[32];\t/* For example 4.0a */\n\tint\tversionnum;\t/* See OSS_GETVERSION */\n\tchar\toptions[128];\t/* Reserved */\n\n\tint\tnumaudios;\t/* # of audio/dsp devices */\n\tint\topenedaudio[8];\t/* Bit mask telling which audio devices\n\t\t\t\t   are busy */\n\n\tint\tnumsynths;\t/* # of availavle synth devices */\n\tint\tnummidis;\t/* # of available MIDI ports */\n\tint\tnumtimers;\t/* # of available timer devices */\n\tint\tnummixers;\t/* # of mixer devices */\n\n\tint\topenedmidi[8];\t/* Bit mask telling which midi devices\n\t\t\t\t   are busy */\n\tint\tnumcards;\t/* Number of sound cards in the system */\n\tint\tfiller[241];\t/* For future expansion (set to -1) */\n} oss_sysinfo;\n\ntypedef struct oss_mixext\n{\n  int dev;\t\t\t/* Mixer device number */\n  int ctrl;\t\t\t/* Controller number */\n  int type;\t\t\t/* Entry type */\n#\tdefine MIXT_DEVROOT\t 0\t/* Device root entry */\n#\tdefine MIXT_GROUP\t 1\t/* Controller group */\n#\tdefine MIXT_ONOFF\t 2\t/* OFF (0) or ON (1) */\n#\tdefine MIXT_ENUM\t 3\t/* Enumerated (0 to maxvalue) */\n#\tdefine MIXT_MONOSLIDER\t 4\t/* Mono slider (0 to 100) */\n#\tdefine MIXT_STEREOSLIDER 5\t/* Stereo slider (dual 0 to 100) */\n#\tdefine MIXT_MESSAGE\t 6\t/* (Readable) textual message */\n#\tdefine MIXT_MONOVU\t 7\t/* VU meter value (mono) */\n#\tdefine MIXT_STEREOVU\t 8\t/* VU meter value (stereo) */\n#\tdefine MIXT_MONOPEAK\t 9\t/* VU meter peak value (mono) */\n#\tdefine MIXT_STEREOPEAK\t10\t/* VU meter peak value (stereo) */\n#\tdefine MIXT_RADIOGROUP\t11\t/* Radio button group */\n#\tdefine MIXT_MARKER\t12\t/* Separator between normal and extension entries */\n#\tdefine MIXT_VALUE\t13\t/* Decimal value entry */\n#\tdefine MIXT_HEXVALUE\t14\t/* Hexadecimal value entry */\n#\tdefine MIXT_MONODB\t15\t/* Mono atten. slider (0 to -144) */\n#\tdefine MIXT_STEREODB\t16\t/* Stereo atten. slider (dual 0 to -144) */\n#\tdefine MIXT_SLIDER\t17\t/* Slider (mono) with full integer range */\n#\tdefine MIXT_3D\t\t18\n\n  /* Possible value range (minvalue to maxvalue) */\n  /* Note that maxvalue may also be smaller than minvalue */\n  int maxvalue;\n  int minvalue;\n\n  int flags;\n#\tdefine MIXF_READABLE\t0x00000001\t/* Has readable value */\n#\tdefine MIXF_WRITEABLE\t0x00000002\t/* Has writeable value */\n#\tdefine MIXF_POLL\t0x00000004\t/* May change itself */\n#\tdefine MIXF_HZ\t\t0x00000008\t/* Herz scale */\n#\tdefine MIXF_STRING\t0x00000010\t/* Use dynamic extensions for value */\n#\tdefine MIXF_DYNAMIC\t0x00000010\t/* Supports dynamic extensions */\n#\tdefine MIXF_OKFAIL\t0x00000020\t/* Interpret value as 1=OK, 0=FAIL */\n#\tdefine MIXF_FLAT\t0x00000040\t/* Flat vertical space requirements */\n#\tdefine MIXF_LEGACY\t0x00000080\t/* Legacy mixer control group */\n  char id[16];\t\t\t/* Mnemonic ID (mainly for internal use) */\n  int parent;\t\t\t/* Entry# of parent (group) node (-1 if root) */\n\n  int dummy;\t\t\t/* Internal use */\n\n  int timestamp;\n\n  char data[64];\t\t/* Misc data (entry type dependent) */\n  unsigned char enum_present[32];\t/* Mask of allowed enum values */\n  int control_no;\t\t/* SOUND_MIXER_VOLUME..SOUND_MIXER_MIDI */\n  /* (-1 means not indicated) */\n\n/*\n * The desc field is reserved for internal purposes of OSS. It should not be \n * used by applications.\n */\n  unsigned int desc;\n#define MIXEXT_SCOPE_MASK\t\t\t0x0000003f\n#define MIXEXT_SCOPE_OTHER\t\t\t0x00000000\n#define MIXEXT_SCOPE_INPUT\t\t\t0x00000001\n#define MIXEXT_SCOPE_OUTPUT\t\t\t0x00000002\n#define MIXEXT_SCOPE_MONITOR\t\t\t0x00000003\n#define MIXEXT_SCOPE_RECSWITCH\t\t\t0x00000004\n\n  char extname[32];\n  int update_counter;\n  int filler[7];\n} oss_mixext;\n\ntypedef struct oss_mixext_root\n{\n  char id[16];\n  char name[48];\n} oss_mixext_root;\n\ntypedef struct oss_mixer_value\n{\n  int dev;\n  int ctrl;\n  int value;\n  int flags;\t\t\t/* Reserved for future use. Initialize to 0 */\n  int timestamp;\t\t/* Must be set to oss_mixext.timestamp */\n  int filler[8];\t\t/* Reserved for future use. Initialize to 0 */\n} oss_mixer_value;\n\n#define OSS_ENUM_MAXVALUE       255\ntypedef struct oss_mixer_enuminfo\n{\n\tint\tdev;\n\tint\tctrl;\n\tint\tnvalues;\n\tint\tversion;                  /* Read the manual */\n\tshort\tstrindex[OSS_ENUM_MAXVALUE];\n\tchar\tstrings[3000];\n} oss_mixer_enuminfo;\n\n#define OPEN_READ       PCM_ENABLE_INPUT\n#define OPEN_WRITE      PCM_ENABLE_OUTPUT\n#define OPEN_READWRITE  (OPEN_READ|OPEN_WRITE)\n\n/**\n * @brief\tArgument for SNDCTL_AUDIOINFO ioctl.\n *\n * For use w/ the SNDCTL_AUDIOINFO ioctl available on audio (/dev/dsp*)\n * devices.\n */\ntypedef struct oss_audioinfo\n{\n\tint\tdev;\t\t/* Audio device number */\n\tchar\tname[64];\n\tint\tbusy;\t\t/* 0, OPEN_READ, OPEN_WRITE or OPEN_READWRITE */\n\tint\tpid;\n\tint\tcaps;\t\t/* DSP_CAP_INPUT, DSP_CAP_OUTPUT */\n\tint\tiformats;\n\tint\toformats;\n\tint\tmagic;\t\t/* Reserved for internal use */\n\tchar \tcmd[64];\t/* Command using the device (if known) */\n\tint\tcard_number;\n\tint\tport_number;\n\tint\tmixer_dev;\n\tint\treal_device;\t/* Obsolete field. Replaced by devnode */\n\tint\tenabled;\t/* 1=enabled, 0=device not ready at this\n\t\t\t\t   moment */\n\tint\tflags;\t\t/* For internal use only - no practical\n\t\t\t\t   meaning */\n\tint\tmin_rate;\t/* Sample rate limits */\n\tint\tmax_rate;\n\tint\tmin_channels;\t/* Number of channels supported */\n\tint\tmax_channels;\n\tint\tbinding;\t/* DSP_BIND_FRONT, etc. 0 means undefined */\n\tint\trate_source;\n\tchar\thandle[32];\n\t#define OSS_MAX_SAMPLE_RATES\t20\t/* Cannot be changed  */\n\tunsigned int nrates;\n\tunsigned int rates[OSS_MAX_SAMPLE_RATES]; /* Please read the manual before using these */\n\toss_longname_t\tsong_name;\t/* Song name (if given) */\n\toss_label_t\tlabel;\t\t/* Device label (if given) */\n\tint\t\tlatency;\t/* In usecs, -1=unknown */\n\toss_devnode_t\tdevnode;\t/* Device special file name (inside\n\t\t\t\t\t   /dev) */\n\tint filler[186];\n} oss_audioinfo;\n\ntypedef struct oss_mixerinfo\n{\n  int dev;\n  char id[16];\n  char name[32];\n  int modify_counter;\n  int card_number;\n  int port_number;\n  char handle[32];\n  int magic;\t\t\t/* Reserved */\n  int enabled;\t\t\t/* Reserved */\n  int caps;\n#define MIXER_CAP_VIRTUAL\t\t\t\t0x00000001\n  int flags;\t\t\t/* Reserved */\n  int nrext;\n  /*\n   * The priority field can be used to select the default (motherboard)\n   * mixer device. The mixer with the highest priority is the\n   * most preferred one. -2 or less means that this device cannot be used\n   * as the default mixer.\n   */\n  int priority;\n  int filler[254];\t\t/* Reserved */\n} oss_mixerinfo;\n\ntypedef struct oss_midi_info\n{\n  int dev;\t\t\t/* Midi device number */\n  char name[64];\n  int busy;\t\t\t/* 0, OPEN_READ, OPEN_WRITE or OPEN_READWRITE */\n  int pid;\n  char cmd[64];\t\t\t/* Command using the device (if known) */\n  int caps;\n#define MIDI_CAP_MPU401\t\t0x00000001\t/**** OBSOLETE ****/\n#define MIDI_CAP_INPUT\t\t0x00000002\n#define MIDI_CAP_OUTPUT\t\t0x00000004\n#define MIDI_CAP_INOUT\t\t(MIDI_CAP_INPUT|MIDI_CAP_OUTPUT)\n#define MIDI_CAP_VIRTUAL\t0x00000008\t/* Pseudo device */\n#define MIDI_CAP_MTCINPUT\t0x00000010\t/* Supports SNDCTL_MIDI_MTCINPUT */\n#define MIDI_CAP_CLIENT\t\t0x00000020\t/* Virtual client side device */\n#define MIDI_CAP_SERVER\t\t0x00000040\t/* Virtual server side device */\n#define MIDI_CAP_INTERNAL\t0x00000080\t/* Internal (synth) device */\n#define MIDI_CAP_EXTERNAL\t0x00000100\t/* external (MIDI port) device */\n#define MIDI_CAP_PTOP\t\t0x00000200\t/* Point to point link to one device */\n#define MIDI_CAP_MTC\t\t0x00000400\t/* MTC/SMPTE (control) device */\n  int magic;\t\t\t/* Reserved for internal use */\n  int card_number;\n  int port_number;\n  int enabled;\t\t\t/* 1=enabled, 0=device not ready at this moment */\n  int flags;\t\t\t/* For internal use only - no practical meaning */\n  char handle[32];\n  oss_longname_t song_name;\t/* Song name (if known) */\n  oss_label_t label;\t\t/* Device label (if given) */\n  int latency;\t\t\t/* In usecs, -1=unknown */\n  int filler[244];\n} oss_midi_info;\n\ntypedef struct oss_card_info\n{\n  int card;\n  char shortname[16];\n  char longname[128];\n  int flags;\n  int filler[256];\n} oss_card_info;\n\n#define SNDCTL_SYSINFO          _IOR ('X', 1, oss_sysinfo)\n#define OSS_SYSINFO             SNDCTL_SYSINFO /* Old name */\n\n#define SNDCTL_MIX_NRMIX\t_IOR ('X', 2, int)\n#define SNDCTL_MIX_NREXT\t_IOWR('X', 3, int)\n#define SNDCTL_MIX_EXTINFO\t_IOWR('X', 4, oss_mixext)\n#define SNDCTL_MIX_READ\t\t_IOWR('X', 5, oss_mixer_value)\n#define SNDCTL_MIX_WRITE\t_IOWR('X', 6, oss_mixer_value)\n\n#define SNDCTL_AUDIOINFO\t_IOWR('X', 7, oss_audioinfo)\n#define SNDCTL_MIX_ENUMINFO\t_IOWR('X', 8, oss_mixer_enuminfo)\n#define SNDCTL_MIDIINFO\t\t_IOWR('X', 9, oss_midi_info)\n#define SNDCTL_MIXERINFO\t_IOWR('X',10, oss_mixerinfo)\n#define SNDCTL_CARDINFO\t\t_IOWR('X',11, oss_card_info)\n\n/*\n * Few more \"globally\" available ioctl calls.\n */\n#define SNDCTL_SETSONG          _IOW ('Y', 2, oss_longname_t)\n#define SNDCTL_GETSONG          _IOR ('Y', 2, oss_longname_t)\n#define SNDCTL_SETNAME          _IOW ('Y', 3, oss_longname_t)\n#define SNDCTL_SETLABEL         _IOW ('Y', 4, oss_label_t)\n#define SNDCTL_GETLABEL         _IOR ('Y', 4, oss_label_t)\n\n#endif\t/* !_SYS_SOUNDCARD_H_ */\n"
  },
  {
    "path": "rtaudio/install",
    "content": "RtAudio - a set of C++ classes which provide a common API for realtime audio input/output across GNU/Linux (native ALSA, JACK, PulseAudio, and OSS), Macintosh OS X (CoreAudio and JACK), and Windows (DirectSound and ASIO) operating systems.\n\nBy Gary P. Scavone, 2001-2013.\n\nTo configure and compile (on Unix systems and MinGW):\n\n1. Unpack the RtAudio distribution (tar -xzf rtaudio-x.x.tar.gz).\n2. From within the directory containing this file, run configure:\n\n   ./configure\n\n3. Typing \"make\" will compile static and shared libraries.\n\n4. From within the \"tests\" directory, type \"make\" to compile the example programs.\n\nA few options can be passed to configure, including:\n\n  --enable-debug = enable various debug output\n  --with-alsa = choose native ALSA API support (GNU/Linux only)\n  --with-pulse = choose native PulseAudio API support (GNU/Linux only)\n  --with-oss = choose OSS API support (GNU/Linux only)\n  --with-jack = choose JACK server support (GNU/Linux or Macintosh OS-X)\n  --with-core = choose CoreAudio API support (Macintosh OS-X only)\n  --with-asio = choose ASIO API support (windows only)\n  --with-ds = choose DirectSound API support (windows only)\n\nTyping \"./configure --help\" will display all the available options.  Note that you can provide more than one \"--with-\" flag to the configure script to enable multiple API support.\n\nIf you wish to use a different compiler than that selected by configure, specify that compiler in the command line (ex. to use CC):\n\n  ./configure CXX=CC\n\n\nWINDOWS USERS:\n\nRtAudio compiles with the MinGW compiler or MS Visual Studio.\n\nVisual C++ 6.0 project files (very old) are included for the test programs in the /tests/Windows/ directory.  These projects compile API support for both ASIO and DirectSound.\n\n\nGNU/LINUX OSS:\n\nThe OSS API support in RtAudio has not been tested for many years.  I'm not even sure there are OSS drivers supporting recent linux kernels.  In all likelihood, the OSS API code in RtAudio will disappear within the next year or two (if you don't want this to happen, let me know).\n"
  },
  {
    "path": "rtaudio/librtaudio.pc.in",
    "content": "prefix=/usr/local\nexec_prefix=${prefix}\nlibdir=${exec_prefix}/lib\nincludedir=${prefix}/include        \n\nName: librtaudio\nDescription: RtAudio - a set of C++ classes that provide a common API for realtime audio input/output\nVersion: 4.0.12\nRequires: @req@ \nLibs: -L${libdir} -lrtaudio\nLibs.private: -lpthread\nCflags: -pthread -I${includedir} @CPPFLAGS@"
  },
  {
    "path": "rtaudio/readme",
    "content": "RtAudio - a set of C++ classes that provide a common API for realtime audio input/output across GNU/Linux (native ALSA, JACK, PulseAudio and OSS), Macintosh OS X (CoreAudio and JACK), and Windows (DirectSound and ASIO) operating systems.\n\nBy Gary P. Scavone, 2001-2013.\n\nThis distribution of RtAudio contains the following:\n\ndoc:      RtAudio documentation (see doc/html/index.html)\ntests:    example RtAudio programs\ninclude:  header and source files necessary for ASIO, DS & OSS compilation\ntests/Windows: Visual C++ .net test program workspace and projects\n\nOVERVIEW:\n\nRtAudio is a set of C++ classes that provides a common API (Application Programming Interface) for realtime audio input/output across GNU/Linux (native ALSA, JACK, and OSS), Macintosh OS X, SGI, and Windows (DirectSound and ASIO) operating systems.  RtAudio significantly simplifies the process of interacting with computer audio hardware.  It was designed with the following objectives:\n\n  - object-oriented C++ design\n  - simple, common API across all supported platforms\n  - only one source and two header files for easy inclusion in programming projects\n  - allow simultaneous multi-api support\n  - support dynamic connection of devices\n  - provide extensive audio device parameter control\n  - allow audio device capability probing\n  - automatic internal conversion for data format, channel number compensation, (de)interleaving, and byte-swapping\n\nRtAudio incorporates the concept of audio streams, which represent audio output (playback) and/or input (recording).  Available audio devices and their capabilities can be enumerated and then specified when opening a stream.  Where applicable, multiple API support can be compiled and a particular API specified when creating an RtAudio instance.  See the \\ref apinotes section for information specific to each of the supported audio APIs.\n\nFURTHER READING:\n\nFor complete documentation on RtAudio, see the doc directory of the distribution or surf to http://www.music.mcgill.ca/~gary/rtaudio/.\n\n\nLEGAL AND ETHICAL:\n\nThe RtAudio license is similar to the MIT License.\n\n    RtAudio: a set of realtime audio i/o C++ classes\n    Copyright (c) 2001-2013 Gary P. Scavone\n\n    Permission is hereby granted, free of charge, to any person\n    obtaining a copy of this software and associated documentation files\n    (the \"Software\"), to deal in the Software without restriction,\n    including without limitation the rights to use, copy, modify, merge,\n    publish, distribute, sublicense, and/or sell copies of the Software,\n    and to permit persons to whom the Software is furnished to do so,\n    subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be\n    included in all copies or substantial portions of the Software.\n\n    Any person wishing to distribute modifications to the Software is\n    asked to send the modifications to the original developer so that\n    they can be incorporated into the canonical version.  This is,\n    however, not a binding provision of this license.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR\n    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF\n    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\n    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "rtaudio/rtaudio-config.in",
    "content": "#! /bin/sh\nif (test \"x$#\" != \"x1\") ; then\n  echo \"Usage: $0 [--libs | --cxxflags | --cppflags]\"\n  exit;\nfi\n\nLIBRARY=\"@LIBS@\"\nCXXFLAGS=\"@CXXFLAGS@\"\nCPPFLAGS=\"@CPPFLAGS@\"\n\nif (test \"x$1\" == \"x--libs\") ; then\n  echo \"$LIBRARY\"\nelif (test \"x$1\" == \"x--cxxflags\") ; then\n  echo \"$CXXFLAGS\"\nelif (test \"x$1\" == \"x--cppflags\") ; then\n  echo \"$CPPFLAGS\"\nelse\n  echo \"Unknown option: $1\"\nfi\n"
  },
  {
    "path": "rtaudio/tests/Windows/audioprobe.dsp",
    "content": "# Microsoft Developer Studio Project File - Name=\"audioprobe\" - Package Owner=<4>\r\n# Microsoft Developer Studio Generated Build File, Format Version 6.00\r\n# ** DO NOT EDIT **\r\n\r\n# TARGTYPE \"Win32 (x86) Console Application\" 0x0103\r\n\r\nCFG=audioprobe - Win32 Debug\r\n!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r\n!MESSAGE use the Export Makefile command and run\r\n!MESSAGE \r\n!MESSAGE NMAKE /f \"audioprobe.mak\".\r\n!MESSAGE \r\n!MESSAGE You can specify a configuration when running NMAKE\r\n!MESSAGE by defining the macro CFG on the command line. For example:\r\n!MESSAGE \r\n!MESSAGE NMAKE /f \"audioprobe.mak\" CFG=\"audioprobe - Win32 Debug\"\r\n!MESSAGE \r\n!MESSAGE Possible choices for configuration are:\r\n!MESSAGE \r\n!MESSAGE \"audioprobe - Win32 Release\" (based on \"Win32 (x86) Console Application\")\r\n!MESSAGE \"audioprobe - Win32 Debug\" (based on \"Win32 (x86) Console Application\")\r\n!MESSAGE \r\n\r\n# Begin Project\r\n# PROP AllowPerConfigDependencies 0\r\n# PROP Scc_ProjName \"\"\r\n# PROP Scc_LocalPath \"\"\r\nCPP=cl.exe\r\nRSC=rc.exe\r\n\r\n!IF  \"$(CFG)\" == \"audioprobe - Win32 Release\"\r\n\r\n# PROP BASE Use_MFC 0\r\n# PROP BASE Use_Debug_Libraries 0\r\n# PROP BASE Output_Dir \"audioprobe___Win32_Release\"\r\n# PROP BASE Intermediate_Dir \"audioprobe___Win32_Release\"\r\n# PROP BASE Target_Dir \"\"\r\n# PROP Use_MFC 0\r\n# PROP Use_Debug_Libraries 0\r\n# PROP Output_Dir \"\"\r\n# PROP Intermediate_Dir \"Release\"\r\n# PROP Ignore_Export_Lib 0\r\n# PROP Target_Dir \"\"\r\n# ADD BASE CPP /nologo /W3 /GX /O2 /D \"WIN32\" /D \"NDEBUG\" /D \"_CONSOLE\" /D \"_MBCS\" /YX /FD /c\r\n# ADD CPP /nologo /MT /W3 /GX /O2 /I \"../../\" /I \"../../include\" /D \"NDEBUG\" /D \"__WINDOW_DS__\" /D \"__WINDOWS_DS__\" /D \"__WINDOWS_ASIO__\" /D \"WIN32\" /D \"_CONSOLE\" /D \"_MBCS\" /YX /FD /c\r\n# ADD BASE RSC /l 0x409 /d \"NDEBUG\"\r\n# ADD RSC /l 0x409 /d \"NDEBUG\"\r\nBSC32=bscmake.exe\r\n# ADD BASE BSC32 /nologo\r\n# ADD BSC32 /nologo\r\nLINK32=link.exe\r\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\r\n# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib dsound.lib /nologo /subsystem:console /machine:I386\r\n\r\n!ELSEIF  \"$(CFG)\" == \"audioprobe - Win32 Debug\"\r\n\r\n# PROP BASE Use_MFC 0\r\n# PROP BASE Use_Debug_Libraries 1\r\n# PROP BASE Output_Dir \"audioprobe___Win32_Debug\"\r\n# PROP BASE Intermediate_Dir \"audioprobe___Win32_Debug\"\r\n# PROP BASE Target_Dir \"\"\r\n# PROP Use_MFC 0\r\n# PROP Use_Debug_Libraries 1\r\n# PROP Output_Dir \"\"\r\n# PROP Intermediate_Dir \"Debug\"\r\n# PROP Ignore_Export_Lib 0\r\n# PROP Target_Dir \"\"\r\n# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D \"WIN32\" /D \"_DEBUG\" /D \"_CONSOLE\" /D \"_MBCS\" /YX /FD /GZ /c\r\n# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I \"../../\" /I \"../../include\" /D \"_DEBUG\" /D \"__WINDOWS_DS__\" /D \"__WINDOWS_ASIO__\" /D \"WIN32\" /D \"_CONSOLE\" /D \"_MBCS\" /YX /FD /GZ /c\r\n# ADD BASE RSC /l 0x409 /d \"_DEBUG\"\r\n# ADD RSC /l 0x409 /d \"_DEBUG\"\r\nBSC32=bscmake.exe\r\n# ADD BASE BSC32 /nologo\r\n# ADD BSC32 /nologo\r\nLINK32=link.exe\r\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r\n# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib dsound.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r\n\r\n!ENDIF \r\n\r\n# Begin Target\r\n\r\n# Name \"audioprobe - Win32 Release\"\r\n# Name \"audioprobe - Win32 Debug\"\r\n# Begin Group \"Source Files\"\r\n\r\n# PROP Default_Filter \"cpp;c;cxx;rc;def;r;odl;idl;hpj;bat\"\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\asio.cpp\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\asiodrivers.cpp\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\asiolist.cpp\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\audioprobe.cpp\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\iasiothiscallresolver.cpp\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\RtAudio.cpp\r\n# End Source File\r\n# End Group\r\n# Begin Group \"Header Files\"\r\n\r\n# PROP Default_Filter \"h;hpp;hxx;hm;inl\"\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\asio.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\asiodrivers.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\asiodrvr.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\asiolist.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\asiosys.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\ginclude.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\iasiodrv.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\iasiothiscallresolver.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\RtAudio.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\RtError.h\r\n# End Source File\r\n# End Group\r\n# Begin Group \"Resource Files\"\r\n\r\n# PROP Default_Filter \"ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe\"\r\n# End Group\r\n# End Target\r\n# End Project\r\n"
  },
  {
    "path": "rtaudio/tests/Windows/duplex.dsp",
    "content": "# Microsoft Developer Studio Project File - Name=\"duplex\" - Package Owner=<4>\r\n# Microsoft Developer Studio Generated Build File, Format Version 6.00\r\n# ** DO NOT EDIT **\r\n\r\n# TARGTYPE \"Win32 (x86) Console Application\" 0x0103\r\n\r\nCFG=duplex - Win32 Debug\r\n!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r\n!MESSAGE use the Export Makefile command and run\r\n!MESSAGE \r\n!MESSAGE NMAKE /f \"duplex.mak\".\r\n!MESSAGE \r\n!MESSAGE You can specify a configuration when running NMAKE\r\n!MESSAGE by defining the macro CFG on the command line. For example:\r\n!MESSAGE \r\n!MESSAGE NMAKE /f \"duplex.mak\" CFG=\"duplex - Win32 Debug\"\r\n!MESSAGE \r\n!MESSAGE Possible choices for configuration are:\r\n!MESSAGE \r\n!MESSAGE \"duplex - Win32 Release\" (based on \"Win32 (x86) Console Application\")\r\n!MESSAGE \"duplex - Win32 Debug\" (based on \"Win32 (x86) Console Application\")\r\n!MESSAGE \r\n\r\n# Begin Project\r\n# PROP AllowPerConfigDependencies 0\r\n# PROP Scc_ProjName \"\"\r\n# PROP Scc_LocalPath \"\"\r\nCPP=cl.exe\r\nRSC=rc.exe\r\n\r\n!IF  \"$(CFG)\" == \"duplex - Win32 Release\"\r\n\r\n# PROP BASE Use_MFC 0\r\n# PROP BASE Use_Debug_Libraries 0\r\n# PROP BASE Output_Dir \"duplex___Win32_Release\"\r\n# PROP BASE Intermediate_Dir \"duplex___Win32_Release\"\r\n# PROP BASE Target_Dir \"\"\r\n# PROP Use_MFC 0\r\n# PROP Use_Debug_Libraries 0\r\n# PROP Output_Dir \"\"\r\n# PROP Intermediate_Dir \"Release\"\r\n# PROP Ignore_Export_Lib 0\r\n# PROP Target_Dir \"\"\r\n# ADD BASE CPP /nologo /W3 /GX /O2 /D \"WIN32\" /D \"NDEBUG\" /D \"_CONSOLE\" /D \"_MBCS\" /YX /FD /c\r\n# ADD CPP /nologo /MT /W3 /GX /O2 /I \"../../\" /I \"../../include\" /D \"NDEBUG\" /D \"__WINDOWS_DS__\" /D \"WIN32\" /D \"_CONSOLE\" /D \"_MBCS\" /D \"__WINDOWS_ASIO__\" /YX /FD /c\r\n# ADD BASE RSC /l 0x409 /d \"NDEBUG\"\r\n# ADD RSC /l 0x409 /d \"NDEBUG\"\r\nBSC32=bscmake.exe\r\n# ADD BASE BSC32 /nologo\r\n# ADD BSC32 /nologo\r\nLINK32=link.exe\r\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\r\n# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib dsound.lib /nologo /subsystem:console /machine:I386\r\n\r\n!ELSEIF  \"$(CFG)\" == \"duplex - Win32 Debug\"\r\n\r\n# PROP BASE Use_MFC 0\r\n# PROP BASE Use_Debug_Libraries 1\r\n# PROP BASE Output_Dir \"duplex___Win32_Debug\"\r\n# PROP BASE Intermediate_Dir \"duplex___Win32_Debug\"\r\n# PROP BASE Target_Dir \"\"\r\n# PROP Use_MFC 0\r\n# PROP Use_Debug_Libraries 1\r\n# PROP Output_Dir \"\"\r\n# PROP Intermediate_Dir \"Debug\"\r\n# PROP Ignore_Export_Lib 0\r\n# PROP Target_Dir \"\"\r\n# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D \"WIN32\" /D \"_DEBUG\" /D \"_CONSOLE\" /D \"_MBCS\" /YX /FD /GZ /c\r\n# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I \"../../\" /I \"../../include\" /D \"_DEBUG\" /D \"__WINDOWS_ASIO__.__WINDOWS_DS__\" /D \"WIN32\" /D \"_CONSOLE\" /D \"_MBCS\" /D \"__WINDOWS_ASIO__\" /D \"__WINDOWS_DS__\" /YX /FD /GZ /c\r\n# ADD BASE RSC /l 0x409 /d \"_DEBUG\"\r\n# ADD RSC /l 0x409 /d \"_DEBUG\"\r\nBSC32=bscmake.exe\r\n# ADD BASE BSC32 /nologo\r\n# ADD BSC32 /nologo\r\nLINK32=link.exe\r\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r\n# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib dsound.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r\n\r\n!ENDIF \r\n\r\n# Begin Target\r\n\r\n# Name \"duplex - Win32 Release\"\r\n# Name \"duplex - Win32 Debug\"\r\n# Begin Group \"Source Files\"\r\n\r\n# PROP Default_Filter \"cpp;c;cxx;rc;def;r;odl;idl;hpj;bat\"\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\asio.cpp\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\asiodrivers.cpp\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\asiolist.cpp\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\duplex.cpp\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\iasiothiscallresolver.cpp\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\RtAudio.cpp\r\n# End Source File\r\n# End Group\r\n# Begin Group \"Header Files\"\r\n\r\n# PROP Default_Filter \"h;hpp;hxx;hm;inl\"\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\asio.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\asiodrivers.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\asiodrvr.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\asiolist.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\asiosys.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\ginclude.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\iasiodrv.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\iasiothiscallresolver.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\RtAudio.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\RtError.h\r\n# End Source File\r\n# End Group\r\n# Begin Group \"Resource Files\"\r\n\r\n# PROP Default_Filter \"ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe\"\r\n# End Group\r\n# End Target\r\n# End Project\r\n"
  },
  {
    "path": "rtaudio/tests/Windows/playraw.dsp",
    "content": "# Microsoft Developer Studio Project File - Name=\"playraw\" - Package Owner=<4>\r\n# Microsoft Developer Studio Generated Build File, Format Version 6.00\r\n# ** DO NOT EDIT **\r\n\r\n# TARGTYPE \"Win32 (x86) Console Application\" 0x0103\r\n\r\nCFG=playraw - Win32 Debug\r\n!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r\n!MESSAGE use the Export Makefile command and run\r\n!MESSAGE \r\n!MESSAGE NMAKE /f \"playraw.mak\".\r\n!MESSAGE \r\n!MESSAGE You can specify a configuration when running NMAKE\r\n!MESSAGE by defining the macro CFG on the command line. For example:\r\n!MESSAGE \r\n!MESSAGE NMAKE /f \"playraw.mak\" CFG=\"playraw - Win32 Debug\"\r\n!MESSAGE \r\n!MESSAGE Possible choices for configuration are:\r\n!MESSAGE \r\n!MESSAGE \"playraw - Win32 Release\" (based on \"Win32 (x86) Console Application\")\r\n!MESSAGE \"playraw - Win32 Debug\" (based on \"Win32 (x86) Console Application\")\r\n!MESSAGE \r\n\r\n# Begin Project\r\n# PROP AllowPerConfigDependencies 0\r\n# PROP Scc_ProjName \"\"\r\n# PROP Scc_LocalPath \"\"\r\nCPP=cl.exe\r\nRSC=rc.exe\r\n\r\n!IF  \"$(CFG)\" == \"playraw - Win32 Release\"\r\n\r\n# PROP BASE Use_MFC 0\r\n# PROP BASE Use_Debug_Libraries 0\r\n# PROP BASE Output_Dir \"playraw___Win32_Release\"\r\n# PROP BASE Intermediate_Dir \"playraw___Win32_Release\"\r\n# PROP BASE Target_Dir \"\"\r\n# PROP Use_MFC 0\r\n# PROP Use_Debug_Libraries 0\r\n# PROP Output_Dir \"\"\r\n# PROP Intermediate_Dir \"Release\"\r\n# PROP Ignore_Export_Lib 0\r\n# PROP Target_Dir \"\"\r\n# ADD BASE CPP /nologo /W3 /GX /O2 /D \"WIN32\" /D \"NDEBUG\" /D \"_CONSOLE\" /D \"_MBCS\" /YX /FD /c\r\n# ADD CPP /nologo /MT /W3 /GX /O2 /I \"../../\" /I \"../../include\" /D \"NDEBUG\" /D \"WIN32\" /D \"_CONSOLE\" /D \"_MBCS\" /D \"__WINDOWS_ASIO__\" /D \"__WINDOWS_DS__\" /YX /FD /c\r\n# ADD BASE RSC /l 0x409 /d \"NDEBUG\"\r\n# ADD RSC /l 0x409 /d \"NDEBUG\"\r\nBSC32=bscmake.exe\r\n# ADD BASE BSC32 /nologo\r\n# ADD BSC32 /nologo\r\nLINK32=link.exe\r\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\r\n# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib dsound.lib /nologo /subsystem:console /machine:I386\r\n\r\n!ELSEIF  \"$(CFG)\" == \"playraw - Win32 Debug\"\r\n\r\n# PROP BASE Use_MFC 0\r\n# PROP BASE Use_Debug_Libraries 1\r\n# PROP BASE Output_Dir \"playraw___Win32_Debug\"\r\n# PROP BASE Intermediate_Dir \"playraw___Win32_Debug\"\r\n# PROP BASE Target_Dir \"\"\r\n# PROP Use_MFC 0\r\n# PROP Use_Debug_Libraries 1\r\n# PROP Output_Dir \"\"\r\n# PROP Intermediate_Dir \"Debug\"\r\n# PROP Ignore_Export_Lib 0\r\n# PROP Target_Dir \"\"\r\n# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D \"WIN32\" /D \"_DEBUG\" /D \"_CONSOLE\" /D \"_MBCS\" /YX /FD /GZ /c\r\n# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I \"../../\" /I \"../../include\" /D \"_DEBUG\" /D \"WIN32\" /D \"_CONSOLE\" /D \"_MBCS\" /D \"__WINDOWS_ASIO__\" /D \"__WINDOWS_DS__\" /YX /FD /GZ /c\r\n# ADD BASE RSC /l 0x409 /d \"_DEBUG\"\r\n# ADD RSC /l 0x409 /d \"_DEBUG\"\r\nBSC32=bscmake.exe\r\n# ADD BASE BSC32 /nologo\r\n# ADD BSC32 /nologo\r\nLINK32=link.exe\r\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r\n# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib dsound.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r\n\r\n!ENDIF \r\n\r\n# Begin Target\r\n\r\n# Name \"playraw - Win32 Release\"\r\n# Name \"playraw - Win32 Debug\"\r\n# Begin Group \"Source Files\"\r\n\r\n# PROP Default_Filter \"cpp;c;cxx;rc;def;r;odl;idl;hpj;bat\"\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\asio.cpp\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\asiodrivers.cpp\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\asiolist.cpp\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\iasiothiscallresolver.cpp\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\playraw.cpp\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\RtAudio.cpp\r\n# End Source File\r\n# End Group\r\n# Begin Group \"Header Files\"\r\n\r\n# PROP Default_Filter \"h;hpp;hxx;hm;inl\"\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\asio.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\asiodrivers.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\asiodrvr.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\asiolist.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\asiosys.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\ginclude.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\iasiodrv.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\iasiothiscallresolver.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\RtAudio.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\RtError.h\r\n# End Source File\r\n# End Group\r\n# Begin Group \"Resource Files\"\r\n\r\n# PROP Default_Filter \"ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe\"\r\n# End Group\r\n# End Target\r\n# End Project\r\n"
  },
  {
    "path": "rtaudio/tests/Windows/playsaw.dsp",
    "content": "# Microsoft Developer Studio Project File - Name=\"playsaw\" - Package Owner=<4>\r\n# Microsoft Developer Studio Generated Build File, Format Version 6.00\r\n# ** DO NOT EDIT **\r\n\r\n# TARGTYPE \"Win32 (x86) Console Application\" 0x0103\r\n\r\nCFG=playsaw - Win32 Debug\r\n!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r\n!MESSAGE use the Export Makefile command and run\r\n!MESSAGE \r\n!MESSAGE NMAKE /f \"playsaw.mak\".\r\n!MESSAGE \r\n!MESSAGE You can specify a configuration when running NMAKE\r\n!MESSAGE by defining the macro CFG on the command line. For example:\r\n!MESSAGE \r\n!MESSAGE NMAKE /f \"playsaw.mak\" CFG=\"playsaw - Win32 Debug\"\r\n!MESSAGE \r\n!MESSAGE Possible choices for configuration are:\r\n!MESSAGE \r\n!MESSAGE \"playsaw - Win32 Release\" (based on \"Win32 (x86) Console Application\")\r\n!MESSAGE \"playsaw - Win32 Debug\" (based on \"Win32 (x86) Console Application\")\r\n!MESSAGE \r\n\r\n# Begin Project\r\n# PROP AllowPerConfigDependencies 0\r\n# PROP Scc_ProjName \"\"\r\n# PROP Scc_LocalPath \"\"\r\nCPP=cl.exe\r\nRSC=rc.exe\r\n\r\n!IF  \"$(CFG)\" == \"playsaw - Win32 Release\"\r\n\r\n# PROP BASE Use_MFC 0\r\n# PROP BASE Use_Debug_Libraries 0\r\n# PROP BASE Output_Dir \"playsaw___Win32_Release\"\r\n# PROP BASE Intermediate_Dir \"playsaw___Win32_Release\"\r\n# PROP BASE Target_Dir \"\"\r\n# PROP Use_MFC 0\r\n# PROP Use_Debug_Libraries 0\r\n# PROP Output_Dir \"\"\r\n# PROP Intermediate_Dir \"Release\"\r\n# PROP Ignore_Export_Lib 0\r\n# PROP Target_Dir \"\"\r\n# ADD BASE CPP /nologo /W3 /GX /O2 /D \"WIN32\" /D \"NDEBUG\" /D \"_CONSOLE\" /D \"_MBCS\" /YX /FD /c\r\n# ADD CPP /nologo /MT /W3 /GX /O2 /I \"../../\" /I \"../../include\" /D \"NDEBUG\" /D \"WIN32\" /D \"_CONSOLE\" /D \"_MBCS\" /D \"__WINDOWS_ASIO__\" /D \"__WINDOWS_DS__\" /YX /FD /c\r\n# ADD BASE RSC /l 0x409 /d \"NDEBUG\"\r\n# ADD RSC /l 0x409 /d \"NDEBUG\"\r\nBSC32=bscmake.exe\r\n# ADD BASE BSC32 /nologo\r\n# ADD BSC32 /nologo\r\nLINK32=link.exe\r\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\r\n# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib dsound.lib /nologo /subsystem:console /machine:I386\r\n\r\n!ELSEIF  \"$(CFG)\" == \"playsaw - Win32 Debug\"\r\n\r\n# PROP BASE Use_MFC 0\r\n# PROP BASE Use_Debug_Libraries 1\r\n# PROP BASE Output_Dir \"playsaw___Win32_Debug\"\r\n# PROP BASE Intermediate_Dir \"playsaw___Win32_Debug\"\r\n# PROP BASE Target_Dir \"\"\r\n# PROP Use_MFC 0\r\n# PROP Use_Debug_Libraries 1\r\n# PROP Output_Dir \"\"\r\n# PROP Intermediate_Dir \"Debug\"\r\n# PROP Ignore_Export_Lib 0\r\n# PROP Target_Dir \"\"\r\n# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D \"WIN32\" /D \"_DEBUG\" /D \"_CONSOLE\" /D \"_MBCS\" /YX /FD /GZ /c\r\n# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I \"../../\" /I \"../../include\" /D \"_DEBUG\" /D \"WIN32\" /D \"_CONSOLE\" /D \"_MBCS\" /D \"__WINDOWS_ASIO__\" /D \"__WINDOWS_DS__\" /YX /FD /GZ /c\r\n# ADD BASE RSC /l 0x409 /d \"_DEBUG\"\r\n# ADD RSC /l 0x409 /d \"_DEBUG\"\r\nBSC32=bscmake.exe\r\n# ADD BASE BSC32 /nologo\r\n# ADD BSC32 /nologo\r\nLINK32=link.exe\r\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r\n# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib dsound.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r\n\r\n!ENDIF \r\n\r\n# Begin Target\r\n\r\n# Name \"playsaw - Win32 Release\"\r\n# Name \"playsaw - Win32 Debug\"\r\n# Begin Group \"Source Files\"\r\n\r\n# PROP Default_Filter \"cpp;c;cxx;rc;def;r;odl;idl;hpj;bat\"\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\asio.cpp\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\asiodrivers.cpp\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\asiolist.cpp\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\iasiothiscallresolver.cpp\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\playsaw.cpp\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\RtAudio.cpp\r\n# End Source File\r\n# End Group\r\n# Begin Group \"Header Files\"\r\n\r\n# PROP Default_Filter \"h;hpp;hxx;hm;inl\"\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\asio.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\asiodrivers.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\asiodrvr.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\asiolist.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\asiosys.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\ginclude.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\iasiodrv.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\iasiothiscallresolver.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\RtAudio.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\RtError.h\r\n# End Source File\r\n# End Group\r\n# Begin Group \"Resource Files\"\r\n\r\n# PROP Default_Filter \"ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe\"\r\n# End Group\r\n# End Target\r\n# End Project\r\n"
  },
  {
    "path": "rtaudio/tests/Windows/record.dsp",
    "content": "# Microsoft Developer Studio Project File - Name=\"record\" - Package Owner=<4>\r\n# Microsoft Developer Studio Generated Build File, Format Version 6.00\r\n# ** DO NOT EDIT **\r\n\r\n# TARGTYPE \"Win32 (x86) Console Application\" 0x0103\r\n\r\nCFG=record - Win32 Debug\r\n!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r\n!MESSAGE use the Export Makefile command and run\r\n!MESSAGE \r\n!MESSAGE NMAKE /f \"record.mak\".\r\n!MESSAGE \r\n!MESSAGE You can specify a configuration when running NMAKE\r\n!MESSAGE by defining the macro CFG on the command line. For example:\r\n!MESSAGE \r\n!MESSAGE NMAKE /f \"record.mak\" CFG=\"record - Win32 Debug\"\r\n!MESSAGE \r\n!MESSAGE Possible choices for configuration are:\r\n!MESSAGE \r\n!MESSAGE \"record - Win32 Release\" (based on \"Win32 (x86) Console Application\")\r\n!MESSAGE \"record - Win32 Debug\" (based on \"Win32 (x86) Console Application\")\r\n!MESSAGE \r\n\r\n# Begin Project\r\n# PROP AllowPerConfigDependencies 0\r\n# PROP Scc_ProjName \"\"\r\n# PROP Scc_LocalPath \"\"\r\nCPP=cl.exe\r\nRSC=rc.exe\r\n\r\n!IF  \"$(CFG)\" == \"record - Win32 Release\"\r\n\r\n# PROP BASE Use_MFC 0\r\n# PROP BASE Use_Debug_Libraries 0\r\n# PROP BASE Output_Dir \"record___Win32_Release\"\r\n# PROP BASE Intermediate_Dir \"record___Win32_Release\"\r\n# PROP BASE Target_Dir \"\"\r\n# PROP Use_MFC 0\r\n# PROP Use_Debug_Libraries 0\r\n# PROP Output_Dir \"\"\r\n# PROP Intermediate_Dir \"Release\"\r\n# PROP Ignore_Export_Lib 0\r\n# PROP Target_Dir \"\"\r\n# ADD BASE CPP /nologo /W3 /GX /O2 /D \"WIN32\" /D \"NDEBUG\" /D \"_CONSOLE\" /D \"_MBCS\" /YX /FD /c\r\n# ADD CPP /nologo /MT /W3 /GX /O2 /I \"../../\" /I \"../../include\" /D \"NDEBUG\" /D \"WIN32\" /D \"_CONSOLE\" /D \"_MBCS\" /D \"__WINDOWS_ASIO__\" /D \"__WINDOWS_DS__\" /YX /FD /c\r\n# ADD BASE RSC /l 0x409 /d \"NDEBUG\"\r\n# ADD RSC /l 0x409 /d \"NDEBUG\"\r\nBSC32=bscmake.exe\r\n# ADD BASE BSC32 /nologo\r\n# ADD BSC32 /nologo\r\nLINK32=link.exe\r\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\r\n# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib dsound.lib /nologo /subsystem:console /machine:I386\r\n\r\n!ELSEIF  \"$(CFG)\" == \"record - Win32 Debug\"\r\n\r\n# PROP BASE Use_MFC 0\r\n# PROP BASE Use_Debug_Libraries 1\r\n# PROP BASE Output_Dir \"record___Win32_Debug\"\r\n# PROP BASE Intermediate_Dir \"record___Win32_Debug\"\r\n# PROP BASE Target_Dir \"\"\r\n# PROP Use_MFC 0\r\n# PROP Use_Debug_Libraries 1\r\n# PROP Output_Dir \"\"\r\n# PROP Intermediate_Dir \"Debug\"\r\n# PROP Ignore_Export_Lib 0\r\n# PROP Target_Dir \"\"\r\n# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D \"WIN32\" /D \"_DEBUG\" /D \"_CONSOLE\" /D \"_MBCS\" /YX /FD /GZ /c\r\n# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I \"../../\" /I \"../../include\" /D \"_DEBUG\" /D \"WIN32\" /D \"_CONSOLE\" /D \"_MBCS\" /D \"__WINDOWS_ASIO__\" /D \"__WINDOWS_DS__\" /YX /FD /GZ /c\r\n# ADD BASE RSC /l 0x409 /d \"_DEBUG\"\r\n# ADD RSC /l 0x409 /d \"_DEBUG\"\r\nBSC32=bscmake.exe\r\n# ADD BASE BSC32 /nologo\r\n# ADD BSC32 /nologo\r\nLINK32=link.exe\r\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r\n# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib dsound.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r\n\r\n!ENDIF \r\n\r\n# Begin Target\r\n\r\n# Name \"record - Win32 Release\"\r\n# Name \"record - Win32 Debug\"\r\n# Begin Group \"Source Files\"\r\n\r\n# PROP Default_Filter \"cpp;c;cxx;rc;def;r;odl;idl;hpj;bat\"\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\asio.cpp\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\asiodrivers.cpp\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\asiolist.cpp\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\iasiothiscallresolver.cpp\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\record.cpp\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\RtAudio.cpp\r\n# End Source File\r\n# End Group\r\n# Begin Group \"Header Files\"\r\n\r\n# PROP Default_Filter \"h;hpp;hxx;hm;inl\"\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\asio.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\asiodrivers.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\asiodrvr.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\asiolist.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\asiosys.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\ginclude.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\iasiodrv.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\iasiothiscallresolver.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\RtAudio.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\RtError.h\r\n# End Source File\r\n# End Group\r\n# Begin Group \"Resource Files\"\r\n\r\n# PROP Default_Filter \"ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe\"\r\n# End Group\r\n# End Target\r\n# End Project\r\n"
  },
  {
    "path": "rtaudio/tests/Windows/rtaudio.dsw",
    "content": "Microsoft Developer Studio Workspace File, Format Version 6.00\r\n# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!\r\n\r\n###############################################################################\r\n\r\nProject: \"audioprobe\"=.\\audioprobe.dsp - Package Owner=<4>\r\n\r\nPackage=<5>\r\n{{{\r\n}}}\r\n\r\nPackage=<4>\r\n{{{\r\n}}}\r\n\r\n###############################################################################\r\n\r\nProject: \"duplex\"=.\\duplex.dsp - Package Owner=<4>\r\n\r\nPackage=<5>\r\n{{{\r\n}}}\r\n\r\nPackage=<4>\r\n{{{\r\n}}}\r\n\r\n###############################################################################\r\n\r\nProject: \"playraw\"=.\\playraw.dsp - Package Owner=<4>\r\n\r\nPackage=<5>\r\n{{{\r\n}}}\r\n\r\nPackage=<4>\r\n{{{\r\n}}}\r\n\r\n###############################################################################\r\n\r\nProject: \"playsaw\"=.\\playsaw.dsp - Package Owner=<4>\r\n\r\nPackage=<5>\r\n{{{\r\n}}}\r\n\r\nPackage=<4>\r\n{{{\r\n}}}\r\n\r\n###############################################################################\r\n\r\nProject: \"record\"=.\\record.dsp - Package Owner=<4>\r\n\r\nPackage=<5>\r\n{{{\r\n}}}\r\n\r\nPackage=<4>\r\n{{{\r\n}}}\r\n\r\n###############################################################################\r\n\r\nProject: \"testall\"=.\\testall.dsp - Package Owner=<4>\r\n\r\nPackage=<5>\r\n{{{\r\n}}}\r\n\r\nPackage=<4>\r\n{{{\r\n}}}\r\n\r\n###############################################################################\r\n\r\nProject: \"teststops\"=.\\teststops.dsp - Package Owner=<4>\r\n\r\nPackage=<5>\r\n{{{\r\n}}}\r\n\r\nPackage=<4>\r\n{{{\r\n}}}\r\n\r\n###############################################################################\r\n\r\nGlobal:\r\n\r\nPackage=<5>\r\n{{{\r\n}}}\r\n\r\nPackage=<3>\r\n{{{\r\n}}}\r\n\r\n###############################################################################\r\n\r\n"
  },
  {
    "path": "rtaudio/tests/Windows/testall.dsp",
    "content": "# Microsoft Developer Studio Project File - Name=\"testall\" - Package Owner=<4>\r\n# Microsoft Developer Studio Generated Build File, Format Version 6.00\r\n# ** DO NOT EDIT **\r\n\r\n# TARGTYPE \"Win32 (x86) Console Application\" 0x0103\r\n\r\nCFG=testall - Win32 Debug\r\n!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r\n!MESSAGE use the Export Makefile command and run\r\n!MESSAGE \r\n!MESSAGE NMAKE /f \"testall.mak\".\r\n!MESSAGE \r\n!MESSAGE You can specify a configuration when running NMAKE\r\n!MESSAGE by defining the macro CFG on the command line. For example:\r\n!MESSAGE \r\n!MESSAGE NMAKE /f \"testall.mak\" CFG=\"testall - Win32 Debug\"\r\n!MESSAGE \r\n!MESSAGE Possible choices for configuration are:\r\n!MESSAGE \r\n!MESSAGE \"testall - Win32 Release\" (based on \"Win32 (x86) Console Application\")\r\n!MESSAGE \"testall - Win32 Debug\" (based on \"Win32 (x86) Console Application\")\r\n!MESSAGE \r\n\r\n# Begin Project\r\n# PROP AllowPerConfigDependencies 0\r\n# PROP Scc_ProjName \"\"\r\n# PROP Scc_LocalPath \"\"\r\nCPP=cl.exe\r\nRSC=rc.exe\r\n\r\n!IF  \"$(CFG)\" == \"testall - Win32 Release\"\r\n\r\n# PROP BASE Use_MFC 0\r\n# PROP BASE Use_Debug_Libraries 0\r\n# PROP BASE Output_Dir \"testall___Win32_Release\"\r\n# PROP BASE Intermediate_Dir \"testall___Win32_Release\"\r\n# PROP BASE Target_Dir \"\"\r\n# PROP Use_MFC 0\r\n# PROP Use_Debug_Libraries 0\r\n# PROP Output_Dir \"\"\r\n# PROP Intermediate_Dir \"Release\"\r\n# PROP Ignore_Export_Lib 0\r\n# PROP Target_Dir \"\"\r\n# ADD BASE CPP /nologo /W3 /GX /O2 /D \"WIN32\" /D \"NDEBUG\" /D \"_CONSOLE\" /D \"_MBCS\" /YX /FD /c\r\n# ADD CPP /nologo /MT /W3 /GX /O2 /I \"../../\" /I \"../../include\" /D \"NDEBUG\" /D \"WIN32\" /D \"_CONSOLE\" /D \"_MBCS\" /D \"__WINDOWS_ASIO__\" /D \"__WINDOWS_DS__\" /YX /FD /c\r\n# ADD BASE RSC /l 0x409 /d \"NDEBUG\"\r\n# ADD RSC /l 0x409 /d \"NDEBUG\"\r\nBSC32=bscmake.exe\r\n# ADD BASE BSC32 /nologo\r\n# ADD BSC32 /nologo\r\nLINK32=link.exe\r\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\r\n# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib dsound.lib /nologo /subsystem:console /machine:I386\r\n\r\n!ELSEIF  \"$(CFG)\" == \"testall - Win32 Debug\"\r\n\r\n# PROP BASE Use_MFC 0\r\n# PROP BASE Use_Debug_Libraries 1\r\n# PROP BASE Output_Dir \"testall___Win32_Debug\"\r\n# PROP BASE Intermediate_Dir \"testall___Win32_Debug\"\r\n# PROP BASE Target_Dir \"\"\r\n# PROP Use_MFC 0\r\n# PROP Use_Debug_Libraries 1\r\n# PROP Output_Dir \"\"\r\n# PROP Intermediate_Dir \"Debug\"\r\n# PROP Ignore_Export_Lib 0\r\n# PROP Target_Dir \"\"\r\n# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D \"WIN32\" /D \"_DEBUG\" /D \"_CONSOLE\" /D \"_MBCS\" /YX /FD /GZ /c\r\n# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I \"../../\" /I \"../../include\" /D \"_DEBUG\" /D \"WIN32\" /D \"_CONSOLE\" /D \"_MBCS\" /D \"__WINDOWS_ASIO__\" /D \"__WINDOWS_DS__\" /YX /FD /GZ /c\r\n# ADD BASE RSC /l 0x409 /d \"_DEBUG\"\r\n# ADD RSC /l 0x409 /d \"_DEBUG\"\r\nBSC32=bscmake.exe\r\n# ADD BASE BSC32 /nologo\r\n# ADD BSC32 /nologo\r\nLINK32=link.exe\r\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r\n# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib dsound.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r\n\r\n!ENDIF \r\n\r\n# Begin Target\r\n\r\n# Name \"testall - Win32 Release\"\r\n# Name \"testall - Win32 Debug\"\r\n# Begin Group \"Source Files\"\r\n\r\n# PROP Default_Filter \"cpp;c;cxx;rc;def;r;odl;idl;hpj;bat\"\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\asio.cpp\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\asiodrivers.cpp\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\asiolist.cpp\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\iasiothiscallresolver.cpp\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\RtAudio.cpp\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\testall.cpp\r\n# End Source File\r\n# End Group\r\n# Begin Group \"Header Files\"\r\n\r\n# PROP Default_Filter \"h;hpp;hxx;hm;inl\"\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\asio.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\asiodrivers.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\asiodrvr.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\asiolist.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\asiosys.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\ginclude.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\iasiodrv.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\iasiothiscallresolver.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\RtAudio.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\RtError.h\r\n# End Source File\r\n# End Group\r\n# Begin Group \"Resource Files\"\r\n\r\n# PROP Default_Filter \"ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe\"\r\n# End Group\r\n# End Target\r\n# End Project\r\n"
  },
  {
    "path": "rtaudio/tests/Windows/teststops.dsp",
    "content": "# Microsoft Developer Studio Project File - Name=\"teststops\" - Package Owner=<4>\r\n# Microsoft Developer Studio Generated Build File, Format Version 6.00\r\n# ** DO NOT EDIT **\r\n\r\n# TARGTYPE \"Win32 (x86) Console Application\" 0x0103\r\n\r\nCFG=teststops - Win32 Debug\r\n!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r\n!MESSAGE use the Export Makefile command and run\r\n!MESSAGE \r\n!MESSAGE NMAKE /f \"teststops.mak\".\r\n!MESSAGE \r\n!MESSAGE You can specify a configuration when running NMAKE\r\n!MESSAGE by defining the macro CFG on the command line. For example:\r\n!MESSAGE \r\n!MESSAGE NMAKE /f \"teststops.mak\" CFG=\"teststops - Win32 Debug\"\r\n!MESSAGE \r\n!MESSAGE Possible choices for configuration are:\r\n!MESSAGE \r\n!MESSAGE \"teststops - Win32 Release\" (based on \"Win32 (x86) Console Application\")\r\n!MESSAGE \"teststops - Win32 Debug\" (based on \"Win32 (x86) Console Application\")\r\n!MESSAGE \r\n\r\n# Begin Project\r\n# PROP AllowPerConfigDependencies 0\r\n# PROP Scc_ProjName \"\"\r\n# PROP Scc_LocalPath \"\"\r\nCPP=cl.exe\r\nRSC=rc.exe\r\n\r\n!IF  \"$(CFG)\" == \"teststops - Win32 Release\"\r\n\r\n# PROP BASE Use_MFC 0\r\n# PROP BASE Use_Debug_Libraries 0\r\n# PROP BASE Output_Dir \"teststops___Win32_Release\"\r\n# PROP BASE Intermediate_Dir \"teststops___Win32_Release\"\r\n# PROP BASE Target_Dir \"\"\r\n# PROP Use_MFC 0\r\n# PROP Use_Debug_Libraries 0\r\n# PROP Output_Dir \"\"\r\n# PROP Intermediate_Dir \"Release\"\r\n# PROP Ignore_Export_Lib 0\r\n# PROP Target_Dir \"\"\r\n# ADD BASE CPP /nologo /W3 /GX /O2 /D \"WIN32\" /D \"NDEBUG\" /D \"_CONSOLE\" /D \"_MBCS\" /YX /FD /c\r\n# ADD CPP /nologo /MT /W3 /GX /O2 /I \"../../\" /I \"../../include\" /D \"NDEBUG\" /D \"WIN32\" /D \"_CONSOLE\" /D \"_MBCS\" /D \"__WINDOWS_ASIO__\" /D \"__WINDOWS_DS__\" /YX /FD /c\r\n# ADD BASE RSC /l 0x409 /d \"NDEBUG\"\r\n# ADD RSC /l 0x409 /d \"NDEBUG\"\r\nBSC32=bscmake.exe\r\n# ADD BASE BSC32 /nologo\r\n# ADD BSC32 /nologo\r\nLINK32=link.exe\r\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\r\n# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib dsound.lib /nologo /subsystem:console /machine:I386\r\n\r\n!ELSEIF  \"$(CFG)\" == \"teststops - Win32 Debug\"\r\n\r\n# PROP BASE Use_MFC 0\r\n# PROP BASE Use_Debug_Libraries 1\r\n# PROP BASE Output_Dir \"teststops___Win32_Debug\"\r\n# PROP BASE Intermediate_Dir \"teststops___Win32_Debug\"\r\n# PROP BASE Target_Dir \"\"\r\n# PROP Use_MFC 0\r\n# PROP Use_Debug_Libraries 1\r\n# PROP Output_Dir \"\"\r\n# PROP Intermediate_Dir \"Debug\"\r\n# PROP Ignore_Export_Lib 0\r\n# PROP Target_Dir \"\"\r\n# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D \"WIN32\" /D \"_DEBUG\" /D \"_CONSOLE\" /D \"_MBCS\" /YX /FD /GZ /c\r\n# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I \"../../\" /I \"../../include\" /D \"_DEBUG\" /D \"WIN32\" /D \"_CONSOLE\" /D \"_MBCS\" /D \"__WINDOWS_ASIO__\" /D \"__WINDOWS_DS__\" /YX /FD /GZ /c\r\n# ADD BASE RSC /l 0x409 /d \"_DEBUG\"\r\n# ADD RSC /l 0x409 /d \"_DEBUG\"\r\nBSC32=bscmake.exe\r\n# ADD BASE BSC32 /nologo\r\n# ADD BSC32 /nologo\r\nLINK32=link.exe\r\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r\n# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib dsound.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r\n\r\n!ENDIF \r\n\r\n# Begin Target\r\n\r\n# Name \"teststops - Win32 Release\"\r\n# Name \"teststops - Win32 Debug\"\r\n# Begin Group \"Source Files\"\r\n\r\n# PROP Default_Filter \"cpp;c;cxx;rc;def;r;odl;idl;hpj;bat\"\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\asio.cpp\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\asiodrivers.cpp\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\asiolist.cpp\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\iasiothiscallresolver.cpp\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\RtAudio.cpp\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\teststops.cpp\r\n# End Source File\r\n# End Group\r\n# Begin Group \"Header Files\"\r\n\r\n# PROP Default_Filter \"h;hpp;hxx;hm;inl\"\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\asio.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\asiodrivers.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\asiodrvr.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\asiolist.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\asiosys.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\ginclude.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\iasiodrv.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\include\\iasiothiscallresolver.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\RtAudio.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\..\\RtError.h\r\n# End Source File\r\n# End Group\r\n# Begin Group \"Resource Files\"\r\n\r\n# PROP Default_Filter \"ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe\"\r\n# End Group\r\n# End Target\r\n# End Project\r\n"
  },
  {
    "path": "rtaudio/tests/audioprobe.cpp",
    "content": "/******************************************/\n/*\n  audioprobe.cpp\n  by Gary P. Scavone, 2001\n\n  Probe audio system and prints device info.\n*/\n/******************************************/\n\n#include \"RtAudio.h\"\n#include <iostream>\n#include <map>\n\nint main()\n{\n  // Create an api map.\n  std::map<int, std::string> apiMap;\n  apiMap[RtAudio::MACOSX_CORE] = \"OS-X Core Audio\";\n  apiMap[RtAudio::WINDOWS_ASIO] = \"Windows ASIO\";\n  apiMap[RtAudio::WINDOWS_DS] = \"Windows Direct Sound\";\n  apiMap[RtAudio::UNIX_JACK] = \"Jack Client\";\n  apiMap[RtAudio::LINUX_ALSA] = \"Linux ALSA\";\n  apiMap[RtAudio::LINUX_PULSE] = \"Linux PulseAudio\";\n  apiMap[RtAudio::LINUX_OSS] = \"Linux OSS\";\n  apiMap[RtAudio::RTAUDIO_DUMMY] = \"RtAudio Dummy\";\n\n  std::vector< RtAudio::Api > apis;\n  RtAudio :: getCompiledApi( apis );\n\n  std::cout << \"\\nRtAudio Version \" << RtAudio::getVersion() << std::endl;\n\n  std::cout << \"\\nCompiled APIs:\\n\";\n  for ( unsigned int i=0; i<apis.size(); i++ )\n    std::cout << \"  \" << apiMap[ apis[i] ] << std::endl;\n\n  RtAudio audio;\n  RtAudio::DeviceInfo info;\n\n  std::cout << \"\\nCurrent API: \" << apiMap[ audio.getCurrentApi() ] << std::endl;\n\n  unsigned int devices = audio.getDeviceCount();\n  std::cout << \"\\nFound \" << devices << \" device(s) ...\\n\";\n\n  for (unsigned int i=0; i<devices; i++) {\n    info = audio.getDeviceInfo(i);\n\n    std::cout << \"\\nDevice Name = \" << info.name << '\\n';\n    if ( info.probed == false )\n      std::cout << \"Probe Status = UNsuccessful\\n\";\n    else {\n      std::cout << \"Probe Status = Successful\\n\";\n      std::cout << \"Output Channels = \" << info.outputChannels << '\\n';\n      std::cout << \"Input Channels = \" << info.inputChannels << '\\n';\n      std::cout << \"Duplex Channels = \" << info.duplexChannels << '\\n';\n      if ( info.isDefaultOutput ) std::cout << \"This is the default output device.\\n\";\n      else std::cout << \"This is NOT the default output device.\\n\";\n      if ( info.isDefaultInput ) std::cout << \"This is the default input device.\\n\";\n      else std::cout << \"This is NOT the default input device.\\n\";\n      if ( info.nativeFormats == 0 )\n        std::cout << \"No natively supported data formats(?)!\";\n      else {\n        std::cout << \"Natively supported data formats:\\n\";\n        if ( info.nativeFormats & RTAUDIO_SINT8 )\n          std::cout << \"  8-bit int\\n\";\n        if ( info.nativeFormats & RTAUDIO_SINT16 )\n          std::cout << \"  16-bit int\\n\";\n        if ( info.nativeFormats & RTAUDIO_SINT24 )\n          std::cout << \"  24-bit int\\n\";\n        if ( info.nativeFormats & RTAUDIO_SINT32 )\n          std::cout << \"  32-bit int\\n\";\n        if ( info.nativeFormats & RTAUDIO_FLOAT32 )\n          std::cout << \"  32-bit float\\n\";\n        if ( info.nativeFormats & RTAUDIO_FLOAT64 )\n          std::cout << \"  64-bit float\\n\";\n      }\n      if ( info.sampleRates.size() < 1 )\n        std::cout << \"No supported sample rates found!\";\n      else {\n        std::cout << \"Supported sample rates = \";\n        for (unsigned int j=0; j<info.sampleRates.size(); j++)\n          std::cout << info.sampleRates[j] << \" \";\n      }\n      std::cout << std::endl;\n    }\n  }\n  std::cout << std::endl;\n\n  return 0;\n}\n"
  },
  {
    "path": "rtaudio/tests/duplex.cpp",
    "content": "/******************************************/\n/*\n  duplex.cpp\n  by Gary P. Scavone, 2006-2007.\n\n  This program opens a duplex stream and passes\n  input directly through to the output.\n*/\n/******************************************/\n\n#include \"RtAudio.h\"\n#include <iostream>\n#include <cstdlib>\n#include <cstring>\n\n/*\ntypedef char MY_TYPE;\n#define FORMAT RTAUDIO_SINT8\n*/\n\ntypedef signed short MY_TYPE;\n#define FORMAT RTAUDIO_SINT16\n\n/*\ntypedef S24 MY_TYPE;\n#define FORMAT RTAUDIO_SINT24\n\ntypedef signed long MY_TYPE;\n#define FORMAT RTAUDIO_SINT32\n\ntypedef float MY_TYPE;\n#define FORMAT RTAUDIO_FLOAT32\n\ntypedef double MY_TYPE;\n#define FORMAT RTAUDIO_FLOAT64\n*/\n\nvoid usage( void ) {\n  // Error function in case of incorrect command-line\n  // argument specifications\n  std::cout << \"\\nuseage: duplex N fs <iDevice> <oDevice> <iChannelOffset> <oChannelOffset>\\n\";\n  std::cout << \"    where N = number of channels,\\n\";\n  std::cout << \"    fs = the sample rate,\\n\";\n  std::cout << \"    iDevice = optional input device to use (default = 0),\\n\";\n  std::cout << \"    oDevice = optional output device to use (default = 0),\\n\";\n  std::cout << \"    iChannelOffset = an optional input channel offset (default = 0),\\n\";\n  std::cout << \"    and oChannelOffset = optional output channel offset (default = 0).\\n\\n\";\n  exit( 0 );\n}\n\nint inout( void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames,\n           double streamTime, RtAudioStreamStatus status, void *data )\n{\n  // Since the number of input and output channels is equal, we can do\n  // a simple buffer copy operation here.\n  if ( status ) std::cout << \"Stream over/underflow detected.\" << std::endl;\n\n  unsigned int *bytes = (unsigned int *) data;\n  memcpy( outputBuffer, inputBuffer, *bytes );\n  return 0;\n}\n\nint main( int argc, char *argv[] )\n{\n  unsigned int channels, fs, bufferBytes, oDevice = 0, iDevice = 0, iOffset = 0, oOffset = 0;\n\n  // Minimal command-line checking\n  if (argc < 3 || argc > 7 ) usage();\n\n  RtAudio adac;\n  if ( adac.getDeviceCount() < 1 ) {\n    std::cout << \"\\nNo audio devices found!\\n\";\n    exit( 1 );\n  }\n\n  channels = (unsigned int) atoi(argv[1]);\n  fs = (unsigned int) atoi(argv[2]);\n  if ( argc > 3 )\n    iDevice = (unsigned int) atoi(argv[3]);\n  if ( argc > 4 )\n    oDevice = (unsigned int) atoi(argv[4]);\n  if ( argc > 5 )\n    iOffset = (unsigned int) atoi(argv[5]);\n  if ( argc > 6 )\n    oOffset = (unsigned int) atoi(argv[6]);\n\n  // Let RtAudio print messages to stderr.\n  adac.showWarnings( true );\n\n  // Set the same number of channels for both input and output.\n  unsigned int bufferFrames = 512;\n  RtAudio::StreamParameters iParams, oParams;\n  iParams.deviceId = iDevice;\n  iParams.nChannels = channels;\n  iParams.firstChannel = iOffset;\n  oParams.deviceId = oDevice;\n  oParams.nChannels = channels;\n  oParams.firstChannel = oOffset;\n\n  RtAudio::StreamOptions options;\n  //options.flags |= RTAUDIO_NONINTERLEAVED;\n\n  try {\n    adac.openStream( &oParams, &iParams, FORMAT, fs, &bufferFrames, &inout, (void *)&bufferBytes, &options );\n  }\n  catch ( RtError& e ) {\n    std::cout << '\\n' << e.getMessage() << '\\n' << std::endl;\n    exit( 1 );\n  }\n\n  bufferBytes = bufferFrames * channels * sizeof( MY_TYPE );\n\n  // Test RtAudio functionality for reporting latency.\n  std::cout << \"\\nStream latency = \" << adac.getStreamLatency() << \" frames\" << std::endl;\n\n  try {\n    adac.startStream();\n\n    char input;\n    std::cout << \"\\nRunning ... press <enter> to quit (buffer frames = \" << bufferFrames << \").\\n\";\n    std::cin.get(input);\n\n    // Stop the stream.\n    adac.stopStream();\n  }\n  catch ( RtError& e ) {\n    std::cout << '\\n' << e.getMessage() << '\\n' << std::endl;\n    goto cleanup;\n  }\n\n cleanup:\n  if ( adac.isStreamOpen() ) adac.closeStream();\n\n  return 0;\n}\n"
  },
  {
    "path": "rtaudio/tests/playraw.cpp",
    "content": "/******************************************/\n/*\n  playraw.cpp\n  by Gary P. Scavone, 2007\n\n  Play a specified raw file.  It is necessary\n  that the file be of the same data format as\n  defined below.\n*/\n/******************************************/\n\n#include \"RtAudio.h\"\n#include <iostream>\n#include <cstdlib>\n#include <cstring>\n#include <stdio.h>\n\n/*\ntypedef char  MY_TYPE;\n#define FORMAT RTAUDIO_SINT8\n#define SCALE  127.0\n*/\n\ntypedef signed short  MY_TYPE;\n#define FORMAT RTAUDIO_SINT16\n#define SCALE  32767.0\n\n/*\ntypedef S24 MY_TYPE;\n#define FORMAT RTAUDIO_SINT24\n#define SCALE  8388607.0\n\ntypedef signed int  MY_TYPE;\n#define FORMAT RTAUDIO_SINT32\n#define SCALE  2147483647.0\n\ntypedef float  MY_TYPE;\n#define FORMAT RTAUDIO_FLOAT32\n#define SCALE  1.0;\n\ntypedef double  MY_TYPE;\n#define FORMAT RTAUDIO_FLOAT64\n#define SCALE  1.0;\n*/\n\n// Platform-dependent sleep routines.\n#if defined( __WINDOWS_ASIO__ ) || defined( __WINDOWS_DS__ )\n  #include <windows.h>\n  #define SLEEP( milliseconds ) Sleep( (DWORD) milliseconds ) \n#else // Unix variants\n  #include <unistd.h>\n  #define SLEEP( milliseconds ) usleep( (unsigned long) (milliseconds * 1000.0) )\n#endif\n\nvoid usage( void ) {\n  // Error function in case of incorrect command-line\n  // argument specifications\n  std::cout << \"\\nuseage: playraw N fs file <device> <channelOffset>\\n\";\n  std::cout << \"    where N = number of channels,\\n\";\n  std::cout << \"    fs = the sample rate, \\n\";\n  std::cout << \"    file = the raw file to play,\\n\";\n  std::cout << \"    device = optional device to use (default = 0),\\n\";\n  std::cout << \"    and channelOffset = an optional channel offset on the device (default = 0).\\n\\n\";\n  exit( 0 );\n}\n\nstruct OutputData {\n  FILE *fd;\n  unsigned int channels;\n};\n\n// Interleaved buffers\nint output( void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames,\n            double streamTime, RtAudioStreamStatus status, void *data )\n{\n  OutputData *oData = (OutputData*) data;\n\n  // In general, it's not a good idea to do file input in the audio\n  // callback function but I'm doing it here because I don't know the\n  // length of the file we are reading.\n  unsigned int count = fread( outputBuffer, oData->channels * sizeof( MY_TYPE ), nBufferFrames, oData->fd);\n  if ( count < nBufferFrames ) {\n    unsigned int bytes = (nBufferFrames - count) * oData->channels * sizeof( MY_TYPE );\n    unsigned int startByte = count * oData->channels * sizeof( MY_TYPE );\n    memset( (char *)(outputBuffer)+startByte, 0, bytes );\n    return 1;\n  }\n\n  return 0;\n}\n\nint main( int argc, char *argv[] )\n{\n  unsigned int channels, fs, bufferFrames, device = 0, offset = 0;\n  char *file;\n\n  // minimal command-line checking\n  if ( argc < 4 || argc > 6 ) usage();\n\n  RtAudio dac;\n  if ( dac.getDeviceCount() < 1 ) {\n    std::cout << \"\\nNo audio devices found!\\n\";\n    exit( 0 );\n  }\n\n  channels = (unsigned int) atoi( argv[1]) ;\n  fs = (unsigned int) atoi( argv[2] );\n  file = argv[3];\n  if ( argc > 4 )\n    device = (unsigned int) atoi( argv[4] );\n  if ( argc > 5 )\n    offset = (unsigned int) atoi( argv[5] );\n\n  OutputData data;\n  data.fd = fopen( file, \"rb\" );\n  if ( !data.fd ) {\n    std::cout << \"Unable to find or open file!\\n\";\n    exit( 1 );\n  }\n\n  // Set our stream parameters for output only.\n  bufferFrames = 512;\n  RtAudio::StreamParameters oParams;\n  oParams.deviceId = device;\n  oParams.nChannels = channels;\n  oParams.firstChannel = offset;\n\n  data.channels = channels;\n  try {\n    dac.openStream( &oParams, NULL, FORMAT, fs, &bufferFrames, &output, (void *)&data );\n    dac.startStream();\n  }\n  catch ( RtError& e ) {\n    std::cout << '\\n' << e.getMessage() << '\\n' << std::endl;\n    goto cleanup;\n  }\n\n  std::cout << \"\\nPlaying raw file \" << file << \" (buffer frames = \" << bufferFrames << \").\" << std::endl;\n  while ( 1 ) {\n    SLEEP( 100 ); // wake every 100 ms to check if we're done\n    if ( dac.isStreamRunning() == false ) break;\n  }\n\n cleanup:\n  fclose( data.fd );\n  dac.closeStream();\n\n  return 0;\n}\n"
  },
  {
    "path": "rtaudio/tests/playsaw.cpp",
    "content": "/******************************************/\n/*\n  playsaw.cpp\n  by Gary P. Scavone, 2006\n\n  This program will output sawtooth waveforms\n  of different frequencies on each channel.\n*/\n/******************************************/\n\n#include \"RtAudio.h\"\n#include <iostream>\n#include <cstdlib>\n\n/*\ntypedef char MY_TYPE;\n#define FORMAT RTAUDIO_SINT8\n#define SCALE  127.0\n*/\n\ntypedef signed short MY_TYPE;\n#define FORMAT RTAUDIO_SINT16\n#define SCALE  32767.0\n\n/*\ntypedef S24 MY_TYPE;\n#define FORMAT RTAUDIO_SINT24\n#define SCALE  8388607.0\n\ntypedef signed long MY_TYPE;\n#define FORMAT RTAUDIO_SINT32\n#define SCALE  2147483647.0\n\ntypedef float MY_TYPE;\n#define FORMAT RTAUDIO_FLOAT32\n#define SCALE  1.0\n\ntypedef double MY_TYPE;\n#define FORMAT RTAUDIO_FLOAT64\n#define SCALE  1.0\n*/\n\n// Platform-dependent sleep routines.\n#if defined( __WINDOWS_ASIO__ ) || defined( __WINDOWS_DS__ )\n  #include <windows.h>\n  #define SLEEP( milliseconds ) Sleep( (DWORD) milliseconds ) \n#else // Unix variants\n  #include <unistd.h>\n  #define SLEEP( milliseconds ) usleep( (unsigned long) (milliseconds * 1000.0) )\n#endif\n\n#define BASE_RATE 0.005\n#define TIME   1.0\n\nvoid usage( void ) {\n  // Error function in case of incorrect command-line\n  // argument specifications\n  std::cout << \"\\nuseage: playsaw N fs <device> <channelOffset> <time>\\n\";\n  std::cout << \"    where N = number of channels,\\n\";\n  std::cout << \"    fs = the sample rate,\\n\";\n  std::cout << \"    device = optional device to use (default = 0),\\n\";\n  std::cout << \"    channelOffset = an optional channel offset on the device (default = 0),\\n\";\n  std::cout << \"    and time = an optional time duration in seconds (default = no limit).\\n\\n\";\n  exit( 0 );\n}\n\nunsigned int channels;\nRtAudio::StreamOptions options;\nunsigned int frameCounter = 0;\nbool checkCount = false;\nunsigned int nFrames = 0;\nconst unsigned int callbackReturnValue = 1;\n\n//#define USE_INTERLEAVED\n#if defined( USE_INTERLEAVED )\n\n// Interleaved buffers\nint saw( void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames,\n         double streamTime, RtAudioStreamStatus status, void *data )\n{\n  unsigned int i, j;\n  extern unsigned int channels;\n  MY_TYPE *buffer = (MY_TYPE *) outputBuffer;\n  double *lastValues = (double *) data;\n\n  if ( status )\n    std::cout << \"Stream underflow detected!\" << std::endl;\n\n  for ( i=0; i<nBufferFrames; i++ ) {\n    for ( j=0; j<channels; j++ ) {\n      *buffer++ = (MY_TYPE) (lastValues[j] * SCALE * 0.5);\n      lastValues[j] += BASE_RATE * (j+1+(j*0.1));\n      if ( lastValues[j] >= 1.0 ) lastValues[j] -= 2.0;\n    }\n  }\n\n  frameCounter += nBufferFrames;\n  if ( checkCount && ( frameCounter >= nFrames ) ) return callbackReturnValue;\n  return 0;\n}\n\n#else // Use non-interleaved buffers\n\nint saw( void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames,\n         double streamTime, RtAudioStreamStatus status, void *data )\n{\n  unsigned int i, j;\n  extern unsigned int channels;\n  MY_TYPE *buffer = (MY_TYPE *) outputBuffer;\n  double *lastValues = (double *) data;\n\n  if ( status )\n    std::cout << \"Stream underflow detected!\" << std::endl;\n\n  double increment;\n  for ( j=0; j<channels; j++ ) {\n    increment = BASE_RATE * (j+1+(j*0.1));\n    for ( i=0; i<nBufferFrames; i++ ) {\n      *buffer++ = (MY_TYPE) (lastValues[j] * SCALE * 0.5);\n      lastValues[j] += increment;\n      if ( lastValues[j] >= 1.0 ) lastValues[j] -= 2.0;\n    }\n  }\n\n  frameCounter += nBufferFrames;\n  if ( checkCount && ( frameCounter >= nFrames ) ) return callbackReturnValue;\n  return 0;\n}\n#endif\n\nint main( int argc, char *argv[] )\n{\n  unsigned int bufferFrames, fs, device = 0, offset = 0;\n\n  // minimal command-line checking\n  if (argc < 3 || argc > 6 ) usage();\n\n  RtAudio dac;\n  if ( dac.getDeviceCount() < 1 ) {\n    std::cout << \"\\nNo audio devices found!\\n\";\n    exit( 1 );\n  }\n\n  channels = (unsigned int) atoi( argv[1] );\n  fs = (unsigned int) atoi( argv[2] );\n  if ( argc > 3 )\n    device = (unsigned int) atoi( argv[3] );\n  if ( argc > 4 )\n    offset = (unsigned int) atoi( argv[4] );\n  if ( argc > 5 )\n    nFrames = (unsigned int) (fs * atof( argv[5] ));\n  if ( nFrames > 0 ) checkCount = true;\n\n  double *data = (double *) calloc( channels, sizeof( double ) );\n\n  // Let RtAudio print messages to stderr.\n  dac.showWarnings( true );\n\n  // Set our stream parameters for output only.\n  bufferFrames = 512;\n  RtAudio::StreamParameters oParams;\n  oParams.deviceId = device;\n  oParams.nChannels = channels;\n  oParams.firstChannel = offset;\n\n  options.flags = RTAUDIO_HOG_DEVICE;\n  options.flags |= RTAUDIO_SCHEDULE_REALTIME;\n#if !defined( USE_INTERLEAVED )\n  options.flags |= RTAUDIO_NONINTERLEAVED;\n#endif\n  try {\n    dac.openStream( &oParams, NULL, FORMAT, fs, &bufferFrames, &saw, (void *)data, &options );\n    dac.startStream();\n  }\n  catch ( RtError& e ) {\n    e.printMessage();\n    goto cleanup;\n  }\n\n  if ( checkCount ) {\n    while ( dac.isStreamRunning() == true ) SLEEP( 100 );\n  }\n  else {\n    char input;\n    //std::cout << \"Stream latency = \" << dac.getStreamLatency() << \"\\n\" << std::endl;\n    std::cout << \"\\nPlaying ... press <enter> to quit (buffer size = \" << bufferFrames << \").\\n\";\n    std::cin.get( input );\n\n    try {\n      // Stop the stream\n      dac.stopStream();\n    }\n    catch ( RtError& e ) {\n      e.printMessage();\n    }\n  }\n\n cleanup:\n  if ( dac.isStreamOpen() ) dac.closeStream();\n  free( data );\n\n  return 0;\n}\n"
  },
  {
    "path": "rtaudio/tests/record.cpp",
    "content": "/******************************************/\n/*\n  record.cpp\n  by Gary P. Scavone, 2007\n\n  This program records audio from a device and writes it to a\n  header-less binary file.  Use the 'playraw', with the same\n  parameters and format settings, to playback the audio.\n*/\n/******************************************/\n\n#include \"RtAudio.h\"\n#include <iostream>\n#include <cstdlib>\n#include <cstring>\n#include <stdio.h>\n\n/*\ntypedef char MY_TYPE;\n#define FORMAT RTAUDIO_SINT8\n*/\n\ntypedef signed short MY_TYPE;\n#define FORMAT RTAUDIO_SINT16\n\n/*\ntypedef S24 MY_TYPE;\n#define FORMAT RTAUDIO_SINT24\n\ntypedef signed long MY_TYPE;\n#define FORMAT RTAUDIO_SINT32\n\ntypedef float MY_TYPE;\n#define FORMAT RTAUDIO_FLOAT32\n\ntypedef double MY_TYPE;\n#define FORMAT RTAUDIO_FLOAT64\n*/\n\n// Platform-dependent sleep routines.\n#if defined( __WINDOWS_ASIO__ ) || defined( __WINDOWS_DS__ )\n  #include <windows.h>\n  #define SLEEP( milliseconds ) Sleep( (DWORD) milliseconds ) \n#else // Unix variants\n  #include <unistd.h>\n  #define SLEEP( milliseconds ) usleep( (unsigned long) (milliseconds * 1000.0) )\n#endif\n\nvoid usage( void ) {\n  // Error function in case of incorrect command-line\n  // argument specifications\n  std::cout << \"\\nuseage: record N fs <duration> <device> <channelOffset>\\n\";\n  std::cout << \"    where N = number of channels,\\n\";\n  std::cout << \"    fs = the sample rate,\\n\";\n  std::cout << \"    duration = optional time in seconds to record (default = 2.0),\\n\";\n  std::cout << \"    device = optional device to use (default = 0),\\n\";\n  std::cout << \"    and channelOffset = an optional channel offset on the device (default = 0).\\n\\n\";\n  exit( 0 );\n}\n\nstruct InputData {\n  MY_TYPE* buffer;\n  unsigned long bufferBytes;\n  unsigned long totalFrames;\n  unsigned long frameCounter;\n  unsigned int channels;\n};\n\n// Interleaved buffers\nint input( void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames,\n           double streamTime, RtAudioStreamStatus status, void *data )\n{\n  InputData *iData = (InputData *) data;\n\n  // Simply copy the data to our allocated buffer.\n  unsigned int frames = nBufferFrames;\n  if ( iData->frameCounter + nBufferFrames > iData->totalFrames ) {\n    frames = iData->totalFrames - iData->frameCounter;\n    iData->bufferBytes = frames * iData->channels * sizeof( MY_TYPE );\n  }\n\n  unsigned long offset = iData->frameCounter * iData->channels;\n  memcpy( iData->buffer+offset, inputBuffer, iData->bufferBytes );\n  iData->frameCounter += frames;\n\n  if ( iData->frameCounter >= iData->totalFrames ) return 2;\n  return 0;\n}\n\nint main( int argc, char *argv[] )\n{\n  unsigned int channels, fs, bufferFrames, device = 0, offset = 0;\n  double time = 2.0;\n  FILE *fd;\n\n  // minimal command-line checking\n  if ( argc < 3 || argc > 6 ) usage();\n\n  RtAudio adc;\n  if ( adc.getDeviceCount() < 1 ) {\n    std::cout << \"\\nNo audio devices found!\\n\";\n    exit( 1 );\n  }\n\n  channels = (unsigned int) atoi( argv[1] );\n  fs = (unsigned int) atoi( argv[2] );\n  if ( argc > 3 )\n    time = (double) atof( argv[3] );\n  if ( argc > 4 )\n    device = (unsigned int) atoi( argv[4] );\n  if ( argc > 5 )\n    offset = (unsigned int) atoi( argv[5] );\n\n  // Let RtAudio print messages to stderr.\n  adc.showWarnings( true );\n\n  // Set our stream parameters for input only.\n  bufferFrames = 512;\n  RtAudio::StreamParameters iParams;\n  iParams.deviceId = device;\n  iParams.nChannels = channels;\n  iParams.firstChannel = offset;\n\n  InputData data;\n  data.buffer = 0;\n  try {\n    adc.openStream( NULL, &iParams, FORMAT, fs, &bufferFrames, &input, (void *)&data );\n  }\n  catch ( RtError& e ) {\n    std::cout << '\\n' << e.getMessage() << '\\n' << std::endl;\n    goto cleanup;\n  }\n\n  data.bufferBytes = bufferFrames * channels * sizeof( MY_TYPE );\n  data.totalFrames = (unsigned long) (fs * time);\n  data.frameCounter = 0;\n  data.channels = channels;\n  unsigned long totalBytes;\n  totalBytes = data.totalFrames * channels * sizeof( MY_TYPE );\n\n  // Allocate the entire data buffer before starting stream.\n  data.buffer = (MY_TYPE*) malloc( totalBytes );\n  if ( data.buffer == 0 ) {\n    std::cout << \"Memory allocation error ... quitting!\\n\";\n    goto cleanup;\n  }\n\n  try {\n    adc.startStream();\n  }\n  catch ( RtError& e ) {\n    std::cout << '\\n' << e.getMessage() << '\\n' << std::endl;\n    goto cleanup;\n  }\n\n  std::cout << \"\\nRecording for \" << time << \" seconds ... writing file 'record.raw' (buffer frames = \" << bufferFrames << \").\" << std::endl;\n  while ( adc.isStreamRunning() ) {\n    SLEEP( 100 ); // wake every 100 ms to check if we're done\n  }\n\n  // Now write the entire data to the file.\n  fd = fopen( \"record.raw\", \"wb\" );\n  fwrite( data.buffer, sizeof( MY_TYPE ), data.totalFrames * channels, fd );\n  fclose( fd );\n\n cleanup:\n  if ( adc.isStreamOpen() ) adc.closeStream();\n  if ( data.buffer ) free( data.buffer );\n\n  return 0;\n}\n"
  },
  {
    "path": "rtaudio/tests/testall.cpp",
    "content": "/******************************************/\n/*\n  testall.cpp\n  by Gary P. Scavone, 2007-2008\n\n  This program will make a variety of calls\n  to extensively test RtAudio functionality.\n*/\n/******************************************/\n\n#include \"RtAudio.h\"\n#include <iostream>\n#include <cstdlib>\n#include <cstring>\n\n#define BASE_RATE 0.005\n#define TIME   1.0\n\nvoid usage( void ) {\n  // Error function in case of incorrect command-line\n  // argument specifications\n  std::cout << \"\\nuseage: testall N fs <iDevice> <oDevice> <iChannelOffset> <oChannelOffset>\\n\";\n  std::cout << \"    where N = number of channels,\\n\";\n  std::cout << \"    fs = the sample rate,\\n\";\n  std::cout << \"    iDevice = optional input device to use (default = 0),\\n\";\n  std::cout << \"    oDevice = optional output device to use (default = 0),\\n\";\n  std::cout << \"    iChannelOffset = an optional input channel offset (default = 0),\\n\";\n  std::cout << \"    and oChannelOffset = optional output channel offset (default = 0).\\n\\n\";\n  exit( 0 );\n}\n\nunsigned int channels;\n\n// Interleaved buffers\nint sawi( void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames,\n          double streamTime, RtAudioStreamStatus status, void *data )\n{\n  unsigned int i, j;\n  extern unsigned int channels;\n  double *buffer = (double *) outputBuffer;\n  double *lastValues = (double *) data;\n\n  if ( status )\n    std::cout << \"Stream underflow detected!\" << std::endl;\n\n  for ( i=0; i<nBufferFrames; i++ ) {\n    for ( j=0; j<channels; j++ ) {\n      *buffer++ = (double) lastValues[j];\n      lastValues[j] += BASE_RATE * (j+1+(j*0.1));\n      if ( lastValues[j] >= 1.0 ) lastValues[j] -= 2.0;\n    }\n  }\n\n  return 0;\n}\n\n// Non-interleaved buffers\nint sawni( void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames,\n           double streamTime, RtAudioStreamStatus status, void *data )\n{\n  unsigned int i, j;\n  extern unsigned int channels;\n  double *buffer = (double *) outputBuffer;\n  double *lastValues = (double *) data;\n\n  if ( status )\n    std::cout << \"Stream underflow detected!\" << std::endl;\n\n  float increment;\n  for ( j=0; j<channels; j++ ) {\n    increment = BASE_RATE * (j+1+(j*0.1));\n    for ( i=0; i<nBufferFrames; i++ ) {\n      *buffer++ = (double) lastValues[j];\n      lastValues[j] += increment;\n      if ( lastValues[j] >= 1.0 ) lastValues[j] -= 2.0;\n    }\n  }\n\n  return 0;\n}\n\nint inout( void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames,\n           double streamTime, RtAudioStreamStatus status, void *data )\n{\n  // Since the number of input and output channels is equal, we can do\n  // a simple buffer copy operation here.\n  if ( status ) std::cout << \"Stream over/underflow detected.\" << std::endl;\n\n  unsigned int *bytes = (unsigned int *) data;\n  memcpy( outputBuffer, inputBuffer, *bytes );\n  return 0;\n}\n\nint main( int argc, char *argv[] )\n{\n  unsigned int bufferFrames, fs, oDevice = 0, iDevice = 0, iOffset = 0, oOffset = 0;\n  char input;\n\n  // minimal command-line checking\n  if (argc < 3 || argc > 7 ) usage();\n\n  RtAudio dac;\n  if ( dac.getDeviceCount() < 1 ) {\n    std::cout << \"\\nNo audio devices found!\\n\";\n    exit( 1 );\n  }\n\n  channels = (unsigned int) atoi( argv[1] );\n  fs = (unsigned int) atoi( argv[2] );\n  if ( argc > 3 )\n    iDevice = (unsigned int) atoi( argv[3] );\n  if ( argc > 4 )\n    oDevice = (unsigned int) atoi(argv[4]);\n  if ( argc > 5 )\n    iOffset = (unsigned int) atoi(argv[5]);\n  if ( argc > 6 )\n    oOffset = (unsigned int) atoi(argv[6]);\n\n  double *data = (double *) calloc( channels, sizeof( double ) );\n\n  // Let RtAudio print messages to stderr.\n  dac.showWarnings( true );\n\n  // Set our stream parameters for output only.\n  bufferFrames = 512;\n  RtAudio::StreamParameters oParams, iParams;\n  oParams.deviceId = oDevice;\n  oParams.nChannels = channels;\n  oParams.firstChannel = oOffset;\n\n  RtAudio::StreamOptions options;\n  options.flags = RTAUDIO_HOG_DEVICE;\n  try {\n    dac.openStream( &oParams, NULL, RTAUDIO_FLOAT64, fs, &bufferFrames, &sawi, (void *)data, &options );\n    std::cout << \"\\nStream latency = \" << dac.getStreamLatency() << std::endl;\n\n    // Start the stream\n    dac.startStream();\n    std::cout << \"\\nPlaying ... press <enter> to stop.\\n\";\n    std::cin.get( input );\n\n    // Stop the stream\n    dac.stopStream();\n\n    // Restart again\n    std::cout << \"Press <enter> to restart.\\n\";\n    std::cin.get( input );\n    dac.startStream();\n\n    // Test abort function\n    std::cout << \"Playing again ... press <enter> to abort.\\n\";\n    std::cin.get( input );\n    dac.abortStream();\n\n    // Restart another time\n    std::cout << \"Press <enter> to restart again.\\n\";\n    std::cin.get( input );\n    dac.startStream();\n\n    std::cout << \"Playing again ... press <enter> to close the stream.\\n\";\n    std::cin.get( input );\n  }\n  catch ( RtError& e ) {\n    e.printMessage();\n    goto cleanup;\n  }\n\n  if ( dac.isStreamOpen() ) dac.closeStream();\n\n  // Test non-interleaved functionality\n  options.flags = RTAUDIO_NONINTERLEAVED;\n  try {\n    dac.openStream( &oParams, NULL, RTAUDIO_FLOAT64, fs, &bufferFrames, &sawni, (void *)data, &options );\n\n    std::cout << \"Press <enter> to start non-interleaved playback.\\n\";\n    std::cin.get( input );\n\n    // Start the stream\n    dac.startStream();\n    std::cout << \"\\nPlaying ... press <enter> to stop.\\n\";\n    std::cin.get( input );\n  }\n  catch ( RtError& e ) {\n    e.printMessage();\n    goto cleanup;\n  }\n\n  if ( dac.isStreamOpen() ) dac.closeStream();\n\n  // Now open a duplex stream.\n  unsigned int bufferBytes;\n  iParams.deviceId = iDevice;\n  iParams.nChannels = channels;\n  iParams.firstChannel = iOffset;\n  options.flags = RTAUDIO_NONINTERLEAVED;\n  try {\n    dac.openStream( &oParams, &iParams, RTAUDIO_SINT32, fs, &bufferFrames, &inout, (void *)&bufferBytes, &options );\n\n    bufferBytes = bufferFrames * channels * 4;\n\n    std::cout << \"Press <enter> to start duplex operation.\\n\";\n    std::cin.get( input );\n\n    // Start the stream\n    dac.startStream();\n    std::cout << \"\\nRunning ... press <enter> to stop.\\n\";\n    std::cin.get( input );\n\n    // Stop the stream\n    dac.stopStream();\n    std::cout << \"\\nStopped ... press <enter> to restart.\\n\";\n    std::cin.get( input );\n\n    // Restart the stream\n    dac.startStream();\n    std::cout << \"\\nRunning ... press <enter> to stop.\\n\";\n    std::cin.get( input );\n  }\n  catch ( RtError& e ) {\n    e.printMessage();\n  }\n\n cleanup:\n  if ( dac.isStreamOpen() ) dac.closeStream();\n  free( data );\n\n  return 0;\n}\n"
  },
  {
    "path": "rtaudio/tests/teststops.cpp",
    "content": "/******************************************/\r\n/*\r\n  teststop.cpp\r\n  by Gary P. Scavone, 2011\r\n\r\n  This program starts and stops an RtAudio\r\n  stream many times in succession and in\r\n  different ways to to test its functionality.\r\n*/\r\n/******************************************/\r\n\r\n#include \"RtAudio.h\"\r\n#include <iostream>\r\n#include <cstdlib>\r\n#include <cstring>\r\n#include <cstdio>\r\n\r\n#define PULSE_RATE 0.01  // seconds\r\n#define RUNTIME    0.4   // seconds\r\n#define PAUSETIME  0.1   // seconds\r\n#define REPETITIONS 10\r\n\r\n// Platform-dependent sleep routines.\r\n#if defined( __WINDOWS_ASIO__ ) || defined( __WINDOWS_DS__ )\r\n  #include <windows.h>\r\n  #define SLEEP( milliseconds ) Sleep( (DWORD) milliseconds ) \r\n#else // Unix variants\r\n  #include <unistd.h>\r\n  #define SLEEP( milliseconds ) usleep( (unsigned long) (milliseconds * 1000.0) )\r\n#endif\r\n\r\nvoid usage( void ) {\r\n  // Error function in case of incorrect command-line\r\n  // argument specifications\r\n  std::cout << \"\\nuseage: teststops N fs <iDevice> <oDevice> <iChannelOffset> <oChannelOffset>\\n\";\r\n  std::cout << \"    where N = number of channels,\\n\";\r\n  std::cout << \"    fs = the sample rate,\\n\";\r\n  std::cout << \"    iDevice = optional input device to use (default = 0),\\n\";\r\n  std::cout << \"    oDevice = optional output device to use (default = 0),\\n\";\r\n  std::cout << \"    iChannelOffset = an optional input channel offset (default = 0),\\n\";\r\n  std::cout << \"    and oChannelOffset = optional output channel offset (default = 0).\\n\\n\";\r\n  exit( 0 );\r\n}\r\n\r\nstruct MyData {\r\n  unsigned int channels;\r\n  unsigned int pulseCount;\r\n  unsigned int frameCounter;\r\n  unsigned int nFrames;\r\n  unsigned int returnValue;\r\n};\r\n\r\n// Interleaved buffers\r\nint pulse( void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames,\r\n           double streamTime, RtAudioStreamStatus status, void *mydata )\r\n{\r\n  // Write out a pulse signal and ignore the input buffer.\r\n  unsigned int i, j;\r\n  float sample;\r\n  float *buffer = (float *) outputBuffer;\r\n  MyData *data = (MyData *) mydata;\r\n\r\n  if ( status ) std::cout << \"Stream over/underflow detected!\" << std::endl;\r\n\r\n  for ( i=0; i<nBufferFrames; i++ ) {\r\n    if ( data->frameCounter % data->pulseCount == 0 ) sample = 0.9;\r\n    else sample = 0.0;\r\n    for ( j=0; j<data->channels; j++ )\r\n      *buffer++ = sample;\r\n\r\n    data->frameCounter++;\r\n  }\r\n\r\n  if ( data->frameCounter >= data->nFrames )\r\n    return data->returnValue;\r\n  else\r\n    return 0;\r\n}\r\n\r\nint main( int argc, char *argv[] )\r\n{\r\n  unsigned int bufferFrames, fs, oDevice = 0, iDevice = 0, iOffset = 0, oOffset = 0;\r\n  unsigned int runtime, pausetime;\r\n  char input;\r\n\r\n  // minimal command-line checking\r\n  if (argc < 3 || argc > 7 ) usage();\r\n\r\n  RtAudio *adc = new RtAudio();\r\n  if ( adc->getDeviceCount() < 1 ) {\r\n    std::cout << \"\\nNo audio devices found!\\n\";\r\n    exit( 1 );\r\n  }\r\n\r\n  MyData mydata;\r\n  mydata.channels = (unsigned int) atoi( argv[1] );\r\n  fs = (unsigned int) atoi( argv[2] );\r\n  if ( argc > 3 )\r\n    iDevice = (unsigned int) atoi( argv[3] );\r\n  if ( argc > 4 )\r\n    oDevice = (unsigned int) atoi(argv[4]);\r\n  if ( argc > 5 )\r\n    iOffset = (unsigned int) atoi(argv[5]);\r\n  if ( argc > 6 )\r\n    oOffset = (unsigned int) atoi(argv[6]);\r\n\r\n  // Let RtAudio print messages to stderr.\r\n  adc->showWarnings( true );\r\n\r\n  runtime = RUNTIME * 1000;\r\n  pausetime = PAUSETIME * 1000;\r\n\r\n  // Set our stream parameters for a duplex stream.\r\n  bufferFrames = 512;\r\n  RtAudio::StreamParameters oParams, iParams;\r\n  oParams.deviceId = oDevice;\r\n  oParams.nChannels = mydata.channels;\r\n  oParams.firstChannel = oOffset;\r\n\r\n  iParams.deviceId = iDevice;\r\n  iParams.nChannels = mydata.channels;\r\n  iParams.firstChannel = iOffset;\r\n\r\n  // First, test external stopStream() calls.\r\n  mydata.pulseCount = PULSE_RATE * fs;\r\n  mydata.nFrames = 50 * fs;\r\n  mydata.returnValue = 0;\r\n  try {\r\n    adc->openStream( &oParams, &iParams, RTAUDIO_SINT32, fs, &bufferFrames, &pulse, (void *)&mydata );\r\n\r\n    std::cout << \"Press <enter> to start test.\\n\";\r\n    std::cin.get( input );\r\n\r\n    for (int i=0; i<REPETITIONS; i++ ) {\r\n      mydata.frameCounter = 0;\r\n      adc->startStream();\r\n      std::cout << \"Stream started ... \";\r\n      SLEEP( runtime );\r\n      adc->stopStream();\r\n      std::cout << \"stream externally stopped.\\n\";\r\n      SLEEP( pausetime );\r\n    }\r\n  }\r\n  catch ( RtError& e ) {\r\n    e.printMessage();\r\n    goto cleanup;\r\n  }\r\n\r\n  adc->closeStream();\r\n\r\n  // Next, test internal stopStream() calls.\r\n  mydata.nFrames = (unsigned int) (RUNTIME * fs);\r\n  mydata.returnValue = 1;\r\n  try {\r\n    adc->openStream( &oParams, &iParams, RTAUDIO_SINT32, fs, &bufferFrames, &pulse, (void *)&mydata );\r\n\r\n    std::cin.clear();\r\n    fflush(stdin);\r\n    std::cout << \"\\nPress <enter> to continue test.\\n\";\r\n    std::cin.get( input );\r\n\r\n    for (int i=0; i<REPETITIONS; i++ ) {\r\n      mydata.frameCounter = 0;\r\n      adc->startStream();\r\n      std::cout << \"Stream started ... \";\r\n      while ( adc->isStreamRunning() ) SLEEP( 5 );\r\n      std::cout << \"stream stopped via callback return value = 1.\\n\";\r\n      SLEEP( pausetime );\r\n    }\r\n  }\r\n  catch ( RtError& e ) {\r\n    e.printMessage();\r\n    goto cleanup;\r\n  }\r\n\r\n  adc->closeStream();\r\n\r\n  // Test internal abortStream() calls.\r\n  mydata.returnValue = 2;\r\n  try {\r\n    adc->openStream( &oParams, &iParams, RTAUDIO_SINT32, fs, &bufferFrames, &pulse, (void *)&mydata );\r\n    std::cin.clear();\r\n    fflush(stdin);\r\n    std::cout << \"\\nPress <enter> to continue test.\\n\";\r\n    std::cin.get( input );\r\n\r\n    for (int i=0; i<REPETITIONS; i++ ) {\r\n      mydata.frameCounter = 0;\r\n      adc->startStream();\r\n      std::cout << \"Stream started ... \";\r\n      while ( adc->isStreamRunning() ) SLEEP( 5 );\r\n      std::cout << \"stream aborted via callback return value = 2.\\n\";\r\n      SLEEP( pausetime );\r\n    }\r\n  }\r\n  catch ( RtError& e ) {\r\n    e.printMessage();\r\n    goto cleanup;\r\n  }\r\n\r\n  adc->closeStream();\r\n\r\n  // Test consecutive stream re-opening.\r\n  mydata.returnValue = 0;\r\n  mydata.nFrames = 50 * fs;\r\n  try {\r\n\r\n    std::cin.clear();\r\n    fflush(stdin);\r\n    std::cout << \"\\nPress <enter> to continue test.\\n\";\r\n    std::cin.get( input );\r\n\r\n    for (int i=0; i<REPETITIONS; i++ ) {\r\n      adc->openStream( &oParams, &iParams, RTAUDIO_SINT32, fs, &bufferFrames, &pulse, (void *)&mydata );\r\n      mydata.frameCounter = 0;\r\n      adc->startStream();\r\n      std::cout << \"New stream started ... \";\r\n      SLEEP( runtime );\r\n      adc->stopStream();\r\n      adc->closeStream();\r\n      std::cout << \"stream stopped externally and closed.\\n\";\r\n      SLEEP( pausetime );\r\n    }\r\n  }\r\n  catch ( RtError& e ) {\r\n    e.printMessage();\r\n    goto cleanup;\r\n  }\r\n\r\n  delete adc;\r\n  adc = 0;\r\n\r\n  // Test consecutive RtAudio creating and deletion.\r\n  try {\r\n\r\n    std::cin.clear();\r\n    fflush(stdin);\r\n    std::cout << \"\\nPress <enter> to continue test.\\n\";\r\n    std::cin.get( input );\r\n\r\n    for (int i=0; i<REPETITIONS; i++ ) {\r\n      adc = new RtAudio();      \r\n      adc->openStream( &oParams, &iParams, RTAUDIO_SINT32, fs, &bufferFrames, &pulse, (void *)&mydata );\r\n      mydata.frameCounter = 0;\r\n      adc->startStream();\r\n      std::cout << \"New instance and stream started ... \";\r\n      SLEEP( runtime );\r\n      adc->stopStream();\r\n      adc->closeStream();\r\n      delete adc;\r\n      adc = 0;\r\n      std::cout << \"stream stopped and instance deleted.\\n\";\r\n      SLEEP( pausetime );\r\n    }\r\n  }\r\n  catch ( RtError& e ) {\r\n    e.printMessage();\r\n    goto cleanup;\r\n  }\r\n\r\n cleanup:\r\n  if ( adc && adc->isStreamOpen() ) adc->closeStream();\r\n  if ( adc ) delete adc;\r\n\r\n  return 0;\r\n}\r\n"
  },
  {
    "path": "rtmidi/.gitignore",
    "content": "librtmidi.so*\nlibrtmidi.dylib.4\nrtmidi-config\nlibrtmidi.pc\n"
  },
  {
    "path": "rtmidi/Makefile.am",
    "content": "noinst_LIBRARIES = librtmidi.a\nlibrtmidi_a_SOURCES = RtMidi.cpp RtMidi.h RtError.h\n"
  },
  {
    "path": "rtmidi/RtError.h",
    "content": "/************************************************************************/\n/*! \\class RtError\n    \\brief Exception handling class for RtAudio & RtMidi.\n\n    The RtError class is quite simple but it does allow errors to be\n    \"caught\" by RtError::Type. See the RtAudio and RtMidi\n    documentation to know which methods can throw an RtError.\n\n*/\n/************************************************************************/\n\n#ifndef RTERROR_H\n#define RTERROR_H\n\n#include <exception>\n#include <iostream>\n#include <string>\n\nclass RtError : public std::exception\n{\n public:\n  //! Defined RtError types.\n  enum Type {\n    WARNING,           /*!< A non-critical error. */\n    DEBUG_WARNING,     /*!< A non-critical error which might be useful for debugging. */\n    UNSPECIFIED,       /*!< The default, unspecified error type. */\n    NO_DEVICES_FOUND,  /*!< No devices found on system. */\n    INVALID_DEVICE,    /*!< An invalid device ID was specified. */\n    MEMORY_ERROR,      /*!< An error occured during memory allocation. */\n    INVALID_PARAMETER, /*!< An invalid parameter was specified to a function. */\n    INVALID_USE,       /*!< The function was called incorrectly. */\n    DRIVER_ERROR,      /*!< A system driver error occured. */\n    SYSTEM_ERROR,      /*!< A system error occured. */\n    THREAD_ERROR       /*!< A thread error occured. */\n  };\n\n  //! The constructor.\n  RtError( const std::string& message, Type type = RtError::UNSPECIFIED ) throw() : message_(message), type_(type) {}\n \n  //! The destructor.\n  virtual ~RtError( void ) throw() {}\n\n  //! Prints thrown error message to stderr.\n  virtual void printMessage( void ) const throw() { std::cerr << '\\n' << message_ << \"\\n\\n\"; }\n\n  //! Returns the thrown error message type.\n  virtual const Type& getType(void) const throw() { return type_; }\n\n  //! Returns the thrown error message string.\n  virtual const std::string& getMessage(void) const throw() { return message_; }\n\n  //! Returns the thrown error message as a c-style string.\n  virtual const char* what( void ) const throw() { return message_.c_str(); }\n\n protected:\n  std::string message_;\n  Type type_;\n};\n\n#endif\n"
  },
  {
    "path": "rtmidi/RtMidi.cpp",
    "content": "/**********************************************************************/\n/*! \\class RtMidi\n    \\brief An abstract base class for realtime MIDI input/output.\n\n    This class implements some common functionality for the realtime\n    MIDI input/output subclasses RtMidiIn and RtMidiOut.\n\n    RtMidi WWW site: http://music.mcgill.ca/~gary/rtmidi/\n\n    RtMidi: realtime MIDI i/o C++ classes\n    Copyright (c) 2003-2012 Gary P. Scavone\n\n    Permission is hereby granted, free of charge, to any person\n    obtaining a copy of this software and associated documentation files\n    (the \"Software\"), to deal in the Software without restriction,\n    including without limitation the rights to use, copy, modify, merge,\n    publish, distribute, sublicense, and/or sell copies of the Software,\n    and to permit persons to whom the Software is furnished to do so,\n    subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be\n    included in all copies or substantial portions of the Software.\n\n    Any person wishing to distribute modifications to the Software is\n    asked to send the modifications to the original developer so that\n    they can be incorporated into the canonical version.  This is,\n    however, not a binding provision of this license.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR\n    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF\n    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\n    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n*/\n/**********************************************************************/\n\n// RtMidi: Version 2.0.1\n\n#include \"RtMidi.h\"\n#include <sstream>\n\n//*********************************************************************//\n//  RtMidi Definitions\n//*********************************************************************//\n\nvoid RtMidi :: getCompiledApi( std::vector<RtMidi::Api> &apis ) throw()\n{\n  apis.clear();\n\n  // The order here will control the order of RtMidi's API search in\n  // the constructor.\n#if defined(__MACOSX_CORE__)\n  apis.push_back( MACOSX_CORE );\n#endif\n#if defined(__LINUX_ALSA__)\n  apis.push_back( LINUX_ALSA );\n#endif\n#if defined(__UNIX_JACK__)\n  apis.push_back( UNIX_JACK );\n#endif\n#if defined(__WINDOWS_MM__)\n  apis.push_back( WINDOWS_MM );\n#endif\n#if defined(__WINDOWS_KS__)\n  apis.push_back( WINDOWS_KS );\n#endif\n#if defined(__RTMIDI_DUMMY__)\n  apis.push_back( RTMIDI_DUMMY );\n#endif\n}\n\nvoid RtMidi :: error( RtError::Type type, std::string errorString )\n{\n  if (type == RtError::WARNING) {\n    std::cerr << '\\n' << errorString << \"\\n\\n\";\n  }\n  else if (type == RtError::DEBUG_WARNING) {\n#if defined(__RTMIDI_DEBUG__)\n    std::cerr << '\\n' << errorString << \"\\n\\n\";\n#endif\n  }\n  else {\n    std::cerr << '\\n' << errorString << \"\\n\\n\";\n    throw RtError( errorString, type );\n  }\n}\n\n//*********************************************************************//\n//  RtMidiIn Definitions\n//*********************************************************************//\n\nvoid RtMidiIn :: openMidiApi( RtMidi::Api api, const std::string clientName, unsigned int queueSizeLimit )\n{\n  if ( rtapi_ )\n    delete rtapi_;\n  rtapi_ = 0;\n\n#if defined(__UNIX_JACK__)\n  if ( api == UNIX_JACK )\n    rtapi_ = new MidiInJack( clientName, queueSizeLimit );\n#endif\n#if defined(__LINUX_ALSA__)\n  if ( api == LINUX_ALSA )\n    rtapi_ = new MidiInAlsa( clientName, queueSizeLimit );\n#endif\n#if defined(__WINDOWS_MM__)\n  if ( api == WINDOWS_MM )\n    rtapi_ = new MidiInWinMM( clientName, queueSizeLimit );\n#endif\n#if defined(__WINDOWS_KS__)\n  if ( api == WINDOWS_KS )\n    rtapi_ = new MidiInWinKS( clientName, queueSizeLimit );\n#endif\n#if defined(__MACOSX_CORE__)\n  if ( api == MACOSX_CORE )\n    rtapi_ = new MidiInCore( clientName, queueSizeLimit );\n#endif\n#if defined(__RTMIDI_DUMMY__)\n  if ( api == RTMIDI_DUMMY )\n    rtapi_ = new MidiInDummy( clientName, queueSizeLimit );\n#endif\n}\n\nRtMidiIn :: RtMidiIn( RtMidi::Api api, const std::string clientName, unsigned int queueSizeLimit )\n{\n  rtapi_ = 0;\n\n  if ( api != UNSPECIFIED ) {\n    // Attempt to open the specified API.\n    openMidiApi( api, clientName, queueSizeLimit );\n    if ( rtapi_ ) return;\n\n    // No compiled support for specified API value.  Issue a debug\n    // warning and continue as if no API was specified.\n    RtMidi::error( RtError::WARNING, \"RtMidiIn: no compiled support for specified API argument!\" );\n  }\n\n  // Iterate through the compiled APIs and return as soon as we find\n  // one with at least one port or we reach the end of the list.\n  std::vector< RtMidi::Api > apis;\n  getCompiledApi( apis );\n  for ( unsigned int i=0; i<apis.size(); i++ ) {\n    openMidiApi( apis[i], clientName, queueSizeLimit );\n    if ( rtapi_->getPortCount() ) break;\n  }\n\n  if ( rtapi_ ) return;\n\n  // It should not be possible to get here because the preprocessor\n  // definition __RTMIDI_DUMMY__ is automatically defined if no\n  // API-specific definitions are passed to the compiler. But just in\n  // case something weird happens, we'll print out an error message.\n  RtMidi::error( RtError::WARNING, \"RtMidiIn: no compiled API support found ... critical error!!\" );\n}\n\nRtMidiIn :: ~RtMidiIn() throw()\n{\n  delete rtapi_;\n}\n\n\n//*********************************************************************//\n//  RtMidiOut Definitions\n//*********************************************************************//\n\nvoid RtMidiOut :: openMidiApi( RtMidi::Api api, const std::string clientName )\n{\n  if ( rtapi_ )\n    delete rtapi_;\n  rtapi_ = 0;\n\n#if defined(__UNIX_JACK__)\n  if ( api == UNIX_JACK )\n    rtapi_ = new MidiOutJack( clientName );\n#endif\n#if defined(__LINUX_ALSA__)\n  if ( api == LINUX_ALSA )\n    rtapi_ = new MidiOutAlsa( clientName );\n#endif\n#if defined(__WINDOWS_MM__)\n  if ( api == WINDOWS_MM )\n    rtapi_ = new MidiOutWinMM( clientName );\n#endif\n#if defined(__WINDOWS_KS__)\n  if ( api == WINDOWS_KS )\n    rtapi_ = new MidiOutWinKS( clientName );\n#endif\n#if defined(__MACOSX_CORE__)\n  if ( api == MACOSX_CORE )\n    rtapi_ = new MidiOutCore( clientName );\n#endif\n#if defined(__RTMIDI_DUMMY__)\n  if ( api == RTMIDI_DUMMY )\n    rtapi_ = new MidiOutDummy( clientName );\n#endif\n}\n\nRtMidiOut :: RtMidiOut( RtMidi::Api api, const std::string clientName )\n{\n  rtapi_ = 0;\n\n  if ( api != UNSPECIFIED ) {\n    // Attempt to open the specified API.\n    openMidiApi( api, clientName );\n    if ( rtapi_ ) return;\n\n    // No compiled support for specified API value.  Issue a debug\n    // warning and continue as if no API was specified.\n    RtMidi::error( RtError::WARNING, \"RtMidiOut: no compiled support for specified API argument!\" );\n  }\n\n  // Iterate through the compiled APIs and return as soon as we find\n  // one with at least one port or we reach the end of the list.\n  std::vector< RtMidi::Api > apis;\n  getCompiledApi( apis );\n  for ( unsigned int i=0; i<apis.size(); i++ ) {\n    openMidiApi( apis[i], clientName );\n    if ( rtapi_->getPortCount() ) break;\n  }\n\n  if ( rtapi_ ) return;\n\n  // It should not be possible to get here because the preprocessor\n  // definition __RTMIDI_DUMMY__ is automatically defined if no\n  // API-specific definitions are passed to the compiler. But just in\n  // case something weird happens, we'll print out an error message.\n  RtMidi::error( RtError::WARNING, \"RtMidiOut: no compiled API support found ... critical error!!\" );\n}\n\nRtMidiOut :: ~RtMidiOut() throw()\n{\n  delete rtapi_;\n}\n\n//*********************************************************************//\n//  Common MidiInApi Definitions\n//*********************************************************************//\n\nMidiInApi :: MidiInApi( unsigned int queueSizeLimit )\n  : apiData_( 0 ), connected_( false )\n{\n  // Allocate the MIDI queue.\n  inputData_.queue.ringSize = queueSizeLimit;\n  if ( inputData_.queue.ringSize > 0 )\n    inputData_.queue.ring = new MidiMessage[ inputData_.queue.ringSize ];\n}\n\nMidiInApi :: ~MidiInApi( void )\n{\n  // Delete the MIDI queue.\n  if ( inputData_.queue.ringSize > 0 ) delete [] inputData_.queue.ring;\n}\n\nvoid MidiInApi :: setCallback( RtMidiIn::RtMidiCallback callback, void *userData )\n{\n  if ( inputData_.usingCallback ) {\n    errorString_ = \"MidiInApi::setCallback: a callback function is already set!\";\n    RtMidi::error( RtError::WARNING, errorString_ );\n    return;\n  }\n\n  if ( !callback ) {\n    errorString_ = \"RtMidiIn::setCallback: callback function value is invalid!\";\n    RtMidi::error( RtError::WARNING, errorString_ );\n    return;\n  }\n\n  inputData_.userCallback = (void *) callback;\n  inputData_.userData = userData;\n  inputData_.usingCallback = true;\n}\n\nvoid MidiInApi :: cancelCallback()\n{\n  if ( !inputData_.usingCallback ) {\n    errorString_ = \"RtMidiIn::cancelCallback: no callback function was set!\";\n    RtMidi::error( RtError::WARNING, errorString_ );\n    return;\n  }\n\n  inputData_.userCallback = 0;\n  inputData_.userData = 0;\n  inputData_.usingCallback = false;\n}\n\nvoid MidiInApi :: ignoreTypes( bool midiSysex, bool midiTime, bool midiSense )\n{\n  inputData_.ignoreFlags = 0;\n  if ( midiSysex ) inputData_.ignoreFlags = 0x01;\n  if ( midiTime ) inputData_.ignoreFlags |= 0x02;\n  if ( midiSense ) inputData_.ignoreFlags |= 0x04;\n}\n\ndouble MidiInApi :: getMessage( std::vector<unsigned char> *message )\n{\n  message->clear();\n\n  if ( inputData_.usingCallback ) {\n    errorString_ = \"RtMidiIn::getNextMessage: a user callback is currently set for this port.\";\n    RtMidi::error( RtError::WARNING, errorString_ );\n    return 0.0;\n  }\n\n  if ( inputData_.queue.size == 0 ) return 0.0;\n\n  // Copy queued message to the vector pointer argument and then \"pop\" it.\n  std::vector<unsigned char> *bytes = &(inputData_.queue.ring[inputData_.queue.front].bytes);\n  message->assign( bytes->begin(), bytes->end() );\n  double deltaTime = inputData_.queue.ring[inputData_.queue.front].timeStamp;\n  inputData_.queue.size--;\n  inputData_.queue.front++;\n  if ( inputData_.queue.front == inputData_.queue.ringSize )\n    inputData_.queue.front = 0;\n\n  return deltaTime;\n}\n\n//*********************************************************************//\n//  Common MidiOutApi Definitions\n//*********************************************************************//\n\nMidiOutApi :: MidiOutApi( void )\n  : apiData_( 0 ), connected_( false )\n{\n}\n\nMidiOutApi :: ~MidiOutApi( void )\n{\n}\n\n// *************************************************** //\n//\n// OS/API-specific methods.\n//\n// *************************************************** //\n\n#if defined(__MACOSX_CORE__)\n\n// The CoreMIDI API is based on the use of a callback function for\n// MIDI input.  We convert the system specific time stamps to delta\n// time values.\n\n// OS-X CoreMIDI header files.\n#include <CoreMIDI/CoreMIDI.h>\n#include <CoreAudio/HostTime.h>\n#include <CoreServices/CoreServices.h>\n\n// A structure to hold variables related to the CoreMIDI API\n// implementation.\nstruct CoreMidiData {\n  MIDIClientRef client;\n  MIDIPortRef port;\n  MIDIEndpointRef endpoint;\n  MIDIEndpointRef destinationId;\n  unsigned long long lastTime;\n  MIDISysexSendRequest sysexreq;\n};\n\n//*********************************************************************//\n//  API: OS-X\n//  Class Definitions: MidiInCore\n//*********************************************************************//\n\nvoid midiInputCallback( const MIDIPacketList *list, void *procRef, void *srcRef )\n{\n  MidiInApi::RtMidiInData *data = static_cast<MidiInApi::RtMidiInData *> (procRef);\n  CoreMidiData *apiData = static_cast<CoreMidiData *> (data->apiData);\n\n  unsigned char status;\n  unsigned short nBytes, iByte, size;\n  unsigned long long time;\n\n  bool& continueSysex = data->continueSysex;\n  MidiInApi::MidiMessage& message = data->message;\n\n  const MIDIPacket *packet = &list->packet[0];\n  for ( unsigned int i=0; i<list->numPackets; ++i ) {\n\n    // My interpretation of the CoreMIDI documentation: all message\n    // types, except sysex, are complete within a packet and there may\n    // be several of them in a single packet.  Sysex messages can be\n    // broken across multiple packets and PacketLists but are bundled\n    // alone within each packet (these packets do not contain other\n    // message types).  If sysex messages are split across multiple\n    // MIDIPacketLists, they must be handled by multiple calls to this\n    // function.\n\n    nBytes = packet->length;\n    if ( nBytes == 0 ) continue;\n\n    // Calculate time stamp.\n\n    if ( data->firstMessage ) {\n      message.timeStamp = 0.0;\n      data->firstMessage = false;\n    }\n    else {\n      time = packet->timeStamp;\n      if ( time == 0 ) { // this happens when receiving asynchronous sysex messages\n        time = AudioGetCurrentHostTime();\n      }\n      time -= apiData->lastTime;\n      time = AudioConvertHostTimeToNanos( time );\n      if ( !continueSysex )\n        message.timeStamp = time * 0.000000001;\n    }\n    apiData->lastTime = packet->timeStamp;\n    if ( apiData->lastTime == 0 ) { // this happens when receiving asynchronous sysex messages\n      apiData->lastTime = AudioGetCurrentHostTime();\n    }\n    //std::cout << \"TimeStamp = \" << packet->timeStamp << std::endl;\n\n    iByte = 0;\n    if ( continueSysex ) {\n      // We have a continuing, segmented sysex message.\n      if ( !( data->ignoreFlags & 0x01 ) ) {\n        // If we're not ignoring sysex messages, copy the entire packet.\n        for ( unsigned int j=0; j<nBytes; ++j )\n          message.bytes.push_back( packet->data[j] );\n      }\n      continueSysex = packet->data[nBytes-1] != 0xF7;\n\n      if ( !continueSysex ) {\n        // If not a continuing sysex message, invoke the user callback function or queue the message.\n        if ( data->usingCallback ) {\n          RtMidiIn::RtMidiCallback callback = (RtMidiIn::RtMidiCallback) data->userCallback;\n          callback( message.timeStamp, &message.bytes, data->userData );\n        }\n        else {\n          // As long as we haven't reached our queue size limit, push the message.\n          if ( data->queue.size < data->queue.ringSize ) {\n            data->queue.ring[data->queue.back++] = message;\n            if ( data->queue.back == data->queue.ringSize )\n              data->queue.back = 0;\n            data->queue.size++;\n          }\n          else\n            std::cerr << \"\\nMidiInCore: message queue limit reached!!\\n\\n\";\n        }\n        message.bytes.clear();\n      }\n    }\n    else {\n      while ( iByte < nBytes ) {\n        size = 0;\n        // We are expecting that the next byte in the packet is a status byte.\n        status = packet->data[iByte];\n        if ( !(status & 0x80) ) break;\n        // Determine the number of bytes in the MIDI message.\n        if ( status < 0xC0 ) size = 3;\n        else if ( status < 0xE0 ) size = 2;\n        else if ( status < 0xF0 ) size = 3;\n        else if ( status == 0xF0 ) {\n          // A MIDI sysex\n          if ( data->ignoreFlags & 0x01 ) {\n            size = 0;\n            iByte = nBytes;\n          }\n          else size = nBytes - iByte;\n          continueSysex = packet->data[nBytes-1] != 0xF7;\n        }\n        else if ( status == 0xF1 ) {\n            // A MIDI time code message\n           if ( data->ignoreFlags & 0x02 ) {\n            size = 0;\n            iByte += 2;\n           }\n           else size = 2;\n        }\n        else if ( status == 0xF2 ) size = 3;\n        else if ( status == 0xF3 ) size = 2;\n        else if ( status == 0xF8 && ( data->ignoreFlags & 0x02 ) ) {\n          // A MIDI timing tick message and we're ignoring it.\n          size = 0;\n          iByte += 1;\n        }\n        else if ( status == 0xFE && ( data->ignoreFlags & 0x04 ) ) {\n          // A MIDI active sensing message and we're ignoring it.\n          size = 0;\n          iByte += 1;\n        }\n        else size = 1;\n\n        // Copy the MIDI data to our vector.\n        if ( size ) {\n          message.bytes.assign( &packet->data[iByte], &packet->data[iByte+size] );\n          if ( !continueSysex ) {\n            // If not a continuing sysex message, invoke the user callback function or queue the message.\n            if ( data->usingCallback ) {\n              RtMidiIn::RtMidiCallback callback = (RtMidiIn::RtMidiCallback) data->userCallback;\n              callback( message.timeStamp, &message.bytes, data->userData );\n            }\n            else {\n              // As long as we haven't reached our queue size limit, push the message.\n              if ( data->queue.size < data->queue.ringSize ) {\n                data->queue.ring[data->queue.back++] = message;\n                if ( data->queue.back == data->queue.ringSize )\n                  data->queue.back = 0;\n                data->queue.size++;\n              }\n              else\n                std::cerr << \"\\nMidiInCore: message queue limit reached!!\\n\\n\";\n            }\n            message.bytes.clear();\n          }\n          iByte += size;\n        }\n      }\n    }\n    packet = MIDIPacketNext(packet);\n  }\n}\n\nMidiInCore :: MidiInCore( const std::string clientName, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit )\n{\n  initialize( clientName );\n}\n\nMidiInCore :: ~MidiInCore( void )\n{\n  // Close a connection if it exists.\n  closePort();\n\n  // Cleanup.\n  CoreMidiData *data = static_cast<CoreMidiData *> (apiData_);\n  MIDIClientDispose( data->client );\n  if ( data->endpoint ) MIDIEndpointDispose( data->endpoint );\n  delete data;\n}\n\nvoid MidiInCore :: initialize( const std::string& clientName )\n{\n  // Set up our client.\n  MIDIClientRef client;\n  OSStatus result = MIDIClientCreate( CFStringCreateWithCString( NULL, clientName.c_str(), kCFStringEncodingASCII ), NULL, NULL, &client );\n  if ( result != noErr ) {\n    errorString_ = \"MidiInCore::initialize: error creating OS-X MIDI client object.\";\n    RtMidi::error( RtError::DRIVER_ERROR, errorString_ );\n  }\n\n  // Save our api-specific connection information.\n  CoreMidiData *data = (CoreMidiData *) new CoreMidiData;\n  data->client = client;\n  data->endpoint = 0;\n  apiData_ = (void *) data;\n  inputData_.apiData = (void *) data;\n}\n\nvoid MidiInCore :: openPort( unsigned int portNumber, const std::string portName )\n{\n  if ( connected_ ) {\n    errorString_ = \"MidiInCore::openPort: a valid connection already exists!\";\n    RtMidi::error( RtError::WARNING, errorString_ );\n    return;\n  }\n\n  unsigned int nSrc = MIDIGetNumberOfSources();\n  if (nSrc < 1) {\n    errorString_ = \"MidiInCore::openPort: no MIDI input sources found!\";\n    RtMidi::error( RtError::NO_DEVICES_FOUND, errorString_ );\n  }\n\n  std::ostringstream ost;\n  if ( portNumber >= nSrc ) {\n    ost << \"MidiInCore::openPort: the 'portNumber' argument (\" << portNumber << \") is invalid.\";\n    errorString_ = ost.str();\n    RtMidi::error( RtError::INVALID_PARAMETER, errorString_ );\n  }\n\n  MIDIPortRef port;\n  CoreMidiData *data = static_cast<CoreMidiData *> (apiData_);\n  OSStatus result = MIDIInputPortCreate( data->client, \n                                         CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII ),\n                                         midiInputCallback, (void *)&inputData_, &port );\n  if ( result != noErr ) {\n    MIDIClientDispose( data->client );\n    errorString_ = \"MidiInCore::openPort: error creating OS-X MIDI input port.\";\n    RtMidi::error( RtError::DRIVER_ERROR, errorString_ );\n  }\n\n  // Get the desired input source identifier.\n  MIDIEndpointRef endpoint = MIDIGetSource( portNumber );\n  if ( endpoint == 0 ) {\n    MIDIPortDispose( port );\n    MIDIClientDispose( data->client );\n    errorString_ = \"MidiInCore::openPort: error getting MIDI input source reference.\";\n    RtMidi::error( RtError::DRIVER_ERROR, errorString_ );\n  }\n\n  // Make the connection.\n  result = MIDIPortConnectSource( port, endpoint, NULL );\n  if ( result != noErr ) {\n    MIDIPortDispose( port );\n    MIDIClientDispose( data->client );\n    errorString_ = \"MidiInCore::openPort: error connecting OS-X MIDI input port.\";\n    RtMidi::error( RtError::DRIVER_ERROR, errorString_ );\n  }\n\n  // Save our api-specific port information.\n  data->port = port;\n\n  connected_ = true;\n}\n\nvoid MidiInCore :: openVirtualPort( const std::string portName )\n{\n  CoreMidiData *data = static_cast<CoreMidiData *> (apiData_);\n\n  // Create a virtual MIDI input destination.\n  MIDIEndpointRef endpoint;\n  OSStatus result = MIDIDestinationCreate( data->client,\n                                           CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII ),\n                                           midiInputCallback, (void *)&inputData_, &endpoint );\n  if ( result != noErr ) {\n    errorString_ = \"MidiInCore::openVirtualPort: error creating virtual OS-X MIDI destination.\";\n    RtMidi::error( RtError::DRIVER_ERROR, errorString_ );\n  }\n\n  // Save our api-specific connection information.\n  data->endpoint = endpoint;\n}\n\nvoid MidiInCore :: closePort( void )\n{\n  if ( connected_ ) {\n    CoreMidiData *data = static_cast<CoreMidiData *> (apiData_);\n    MIDIPortDispose( data->port );\n    connected_ = false;\n  }\n}\n\nunsigned int MidiInCore :: getPortCount()\n{\n  return MIDIGetNumberOfSources();\n}\n\n// This function was submitted by Douglas Casey Tucker and apparently\n// derived largely from PortMidi.\nCFStringRef EndpointName( MIDIEndpointRef endpoint, bool isExternal )\n{\n  CFMutableStringRef result = CFStringCreateMutable( NULL, 0 );\n  CFStringRef str;\n\n  // Begin with the endpoint's name.\n  str = NULL;\n  MIDIObjectGetStringProperty( endpoint, kMIDIPropertyName, &str );\n  if ( str != NULL ) {\n    CFStringAppend( result, str );\n    CFRelease( str );\n  }\n\n  MIDIEntityRef entity = 0;\n  MIDIEndpointGetEntity( endpoint, &entity );\n  if ( entity == 0 )\n    // probably virtual\n    return result;\n\n  if ( CFStringGetLength( result ) == 0 ) {\n    // endpoint name has zero length -- try the entity\n    str = NULL;\n    MIDIObjectGetStringProperty( entity, kMIDIPropertyName, &str );\n    if ( str != NULL ) {\n      CFStringAppend( result, str );\n      CFRelease( str );\n    }\n  }\n  // now consider the device's name\n  MIDIDeviceRef device = 0;\n  MIDIEntityGetDevice( entity, &device );\n  if ( device == 0 )\n    return result;\n\n  str = NULL;\n  MIDIObjectGetStringProperty( device, kMIDIPropertyName, &str );\n  if ( CFStringGetLength( result ) == 0 ) {\n      CFRelease( result );\n      return str;\n  }\n  if ( str != NULL ) {\n    // if an external device has only one entity, throw away\n    // the endpoint name and just use the device name\n    if ( isExternal && MIDIDeviceGetNumberOfEntities( device ) < 2 ) {\n      CFRelease( result );\n      return str;\n    } else {\n      if ( CFStringGetLength( str ) == 0 ) {\n        CFRelease( str );\n        return result;\n      }\n      // does the entity name already start with the device name?\n      // (some drivers do this though they shouldn't)\n      // if so, do not prepend\n        if ( CFStringCompareWithOptions( result, /* endpoint name */\n             str /* device name */,\n             CFRangeMake(0, CFStringGetLength( str ) ), 0 ) != kCFCompareEqualTo ) {\n        // prepend the device name to the entity name\n        if ( CFStringGetLength( result ) > 0 )\n          CFStringInsert( result, 0, CFSTR(\" \") );\n        CFStringInsert( result, 0, str );\n      }\n      CFRelease( str );\n    }\n  }\n  return result;\n}\n\n// This function was submitted by Douglas Casey Tucker and apparently\n// derived largely from PortMidi.\nstatic CFStringRef ConnectedEndpointName( MIDIEndpointRef endpoint )\n{\n  CFMutableStringRef result = CFStringCreateMutable( NULL, 0 );\n  CFStringRef str;\n  OSStatus err;\n  int i;\n\n  // Does the endpoint have connections?\n  CFDataRef connections = NULL;\n  int nConnected = 0;\n  bool anyStrings = false;\n  err = MIDIObjectGetDataProperty( endpoint, kMIDIPropertyConnectionUniqueID, &connections );\n  if ( connections != NULL ) {\n    // It has connections, follow them\n    // Concatenate the names of all connected devices\n    nConnected = CFDataGetLength( connections ) / sizeof(MIDIUniqueID);\n    if ( nConnected ) {\n      const SInt32 *pid = (const SInt32 *)(CFDataGetBytePtr(connections));\n      for ( i=0; i<nConnected; ++i, ++pid ) {\n        MIDIUniqueID id = EndianS32_BtoN( *pid );\n        MIDIObjectRef connObject;\n        MIDIObjectType connObjectType;\n        err = MIDIObjectFindByUniqueID( id, &connObject, &connObjectType );\n        if ( err == noErr ) {\n          if ( connObjectType == kMIDIObjectType_ExternalSource  ||\n              connObjectType == kMIDIObjectType_ExternalDestination ) {\n            // Connected to an external device's endpoint (10.3 and later).\n            str = EndpointName( (MIDIEndpointRef)(connObject), true );\n          } else {\n            // Connected to an external device (10.2) (or something else, catch-\n            str = NULL;\n            MIDIObjectGetStringProperty( connObject, kMIDIPropertyName, &str );\n          }\n          if ( str != NULL ) {\n            if ( anyStrings )\n              CFStringAppend( result, CFSTR(\", \") );\n            else anyStrings = true;\n            CFStringAppend( result, str );\n            CFRelease( str );\n          }\n        }\n      }\n    }\n    CFRelease( connections );\n  }\n  if ( anyStrings )\n    return result;\n\n  // Here, either the endpoint had no connections, or we failed to obtain names \n  return EndpointName( endpoint, false );\n}\n\nstd::string MidiInCore :: getPortName( unsigned int portNumber )\n{\n  CFStringRef nameRef;\n  MIDIEndpointRef portRef;\n  std::ostringstream ost;\n  char name[128];\n\n  std::string stringName;\n  if ( portNumber >= MIDIGetNumberOfSources() ) {\n    ost << \"MidiInCore::getPortName: the 'portNumber' argument (\" << portNumber << \") is invalid.\";\n    errorString_ = ost.str();\n    RtMidi::error( RtError::WARNING, errorString_ );\n    //RtMidi::error( RtError::INVALID_PARAMETER, errorString_ );\n    return stringName;\n  }\n\n  portRef = MIDIGetSource( portNumber );\n  nameRef = ConnectedEndpointName(portRef);\n  CFStringGetCString( nameRef, name, sizeof(name), 0);\n  CFRelease( nameRef );\n\n  return stringName = name;\n}\n\n//*********************************************************************//\n//  API: OS-X\n//  Class Definitions: MidiOutCore\n//*********************************************************************//\n\nMidiOutCore :: MidiOutCore( const std::string clientName ) : MidiOutApi()\n{\n  initialize( clientName );\n}\n\nMidiOutCore :: ~MidiOutCore( void )\n{\n  // Close a connection if it exists.\n  closePort();\n\n  // Cleanup.\n  CoreMidiData *data = static_cast<CoreMidiData *> (apiData_);\n  MIDIClientDispose( data->client );\n  if ( data->endpoint ) MIDIEndpointDispose( data->endpoint );\n  delete data;\n}\n\nvoid MidiOutCore :: initialize( const std::string& clientName )\n{\n  // Set up our client.\n  MIDIClientRef client;\n  OSStatus result = MIDIClientCreate( CFStringCreateWithCString( NULL, clientName.c_str(), kCFStringEncodingASCII ), NULL, NULL, &client );\n  if ( result != noErr ) {\n    errorString_ = \"MidiOutCore::initialize: error creating OS-X MIDI client object.\";\n    RtMidi::error( RtError::DRIVER_ERROR, errorString_ );\n  }\n\n  // Save our api-specific connection information.\n  CoreMidiData *data = (CoreMidiData *) new CoreMidiData;\n  data->client = client;\n  data->endpoint = 0;\n  apiData_ = (void *) data;\n}\n\nunsigned int MidiOutCore :: getPortCount()\n{\n  return MIDIGetNumberOfDestinations();\n}\n\nstd::string MidiOutCore :: getPortName( unsigned int portNumber )\n{\n  CFStringRef nameRef;\n  MIDIEndpointRef portRef;\n  std::ostringstream ost;\n  char name[128];\n\n  std::string stringName;\n  if ( portNumber >= MIDIGetNumberOfDestinations() ) {\n    ost << \"MidiOutCore::getPortName: the 'portNumber' argument (\" << portNumber << \") is invalid.\";\n    errorString_ = ost.str();\n    RtMidi::error( RtError::WARNING, errorString_ );\n    return stringName;\n    //RtMidi::error( RtError::INVALID_PARAMETER, errorString_ );\n  }\n\n  portRef = MIDIGetDestination( portNumber );\n  nameRef = ConnectedEndpointName(portRef);\n  CFStringGetCString( nameRef, name, sizeof(name), 0);\n  CFRelease( nameRef );\n  \n  return stringName = name;\n}\n\nvoid MidiOutCore :: openPort( unsigned int portNumber, const std::string portName )\n{\n  if ( connected_ ) {\n    errorString_ = \"MidiOutCore::openPort: a valid connection already exists!\";\n    RtMidi::error( RtError::WARNING, errorString_ );\n    return;\n  }\n\n  unsigned int nDest = MIDIGetNumberOfDestinations();\n  if (nDest < 1) {\n    errorString_ = \"MidiOutCore::openPort: no MIDI output destinations found!\";\n    RtMidi::error( RtError::NO_DEVICES_FOUND, errorString_ );\n  }\n\n  std::ostringstream ost;\n  if ( portNumber >= nDest ) {\n    ost << \"MidiOutCore::openPort: the 'portNumber' argument (\" << portNumber << \") is invalid.\";\n    errorString_ = ost.str();\n    RtMidi::error( RtError::INVALID_PARAMETER, errorString_ );\n  }\n\n  MIDIPortRef port;\n  CoreMidiData *data = static_cast<CoreMidiData *> (apiData_);\n  OSStatus result = MIDIOutputPortCreate( data->client, \n                                          CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII ),\n                                          &port );\n  if ( result != noErr ) {\n    MIDIClientDispose( data->client );\n    errorString_ = \"MidiOutCore::openPort: error creating OS-X MIDI output port.\";\n    RtMidi::error( RtError::DRIVER_ERROR, errorString_ );\n  }\n\n  // Get the desired output port identifier.\n  MIDIEndpointRef destination = MIDIGetDestination( portNumber );\n  if ( destination == 0 ) {\n    MIDIPortDispose( port );\n    MIDIClientDispose( data->client );\n    errorString_ = \"MidiOutCore::openPort: error getting MIDI output destination reference.\";\n    RtMidi::error( RtError::DRIVER_ERROR, errorString_ );\n  }\n\n  // Save our api-specific connection information.\n  data->port = port;\n  data->destinationId = destination;\n  connected_ = true;\n}\n\nvoid MidiOutCore :: closePort( void )\n{\n  if ( connected_ ) {\n    CoreMidiData *data = static_cast<CoreMidiData *> (apiData_);\n    MIDIPortDispose( data->port );\n    connected_ = false;\n  }\n}\n\nvoid MidiOutCore :: openVirtualPort( std::string portName )\n{\n  CoreMidiData *data = static_cast<CoreMidiData *> (apiData_);\n\n  if ( data->endpoint ) {\n    errorString_ = \"MidiOutCore::openVirtualPort: a virtual output port already exists!\";\n    RtMidi::error( RtError::WARNING, errorString_ );\n    return;\n  }\n\n  // Create a virtual MIDI output source.\n  MIDIEndpointRef endpoint;\n  OSStatus result = MIDISourceCreate( data->client,\n                                      CFStringCreateWithCString( NULL, portName.c_str(), kCFStringEncodingASCII ),\n                                      &endpoint );\n  if ( result != noErr ) {\n    errorString_ = \"MidiOutCore::initialize: error creating OS-X virtual MIDI source.\";\n    RtMidi::error( RtError::DRIVER_ERROR, errorString_ );\n  }\n\n  // Save our api-specific connection information.\n  data->endpoint = endpoint;\n}\n\nchar *sysexBuffer = 0;\n\nvoid sysexCompletionProc( MIDISysexSendRequest * sreq )\n{\n  //std::cout << \"Completed SysEx send\\n\";\n delete sysexBuffer;\n sysexBuffer = 0;\n}\n\nvoid MidiOutCore :: sendMessage( std::vector<unsigned char> *message )\n{\n  // We use the MIDISendSysex() function to asynchronously send sysex\n  // messages.  Otherwise, we use a single CoreMidi MIDIPacket.\n  unsigned int nBytes = message->size();\n  if ( nBytes == 0 ) {\n    errorString_ = \"MidiOutCore::sendMessage: no data in message argument!\";      \n    RtMidi::error( RtError::WARNING, errorString_ );\n    return;\n  }\n\n  //  unsigned int packetBytes, bytesLeft = nBytes;\n  //  unsigned int messageIndex = 0;\n  MIDITimeStamp timeStamp = AudioGetCurrentHostTime();\n  CoreMidiData *data = static_cast<CoreMidiData *> (apiData_);\n  OSStatus result;\n\n  if ( message->at(0) == 0xF0 ) {\n\n    while ( sysexBuffer != 0 ) usleep( 1000 ); // sleep 1 ms\n\n   sysexBuffer = new char[nBytes];\n   if ( sysexBuffer == NULL ) {\n     errorString_ = \"MidiOutCore::sendMessage: error allocating sysex message memory!\";\n     RtMidi::error( RtError::MEMORY_ERROR, errorString_ );\n   }\n\n   // Copy data to buffer.\n   for ( unsigned int i=0; i<nBytes; ++i ) sysexBuffer[i] = message->at(i);\n\n   data->sysexreq.destination = data->destinationId;\n   data->sysexreq.data = (Byte *)sysexBuffer;\n   data->sysexreq.bytesToSend = nBytes;\n   data->sysexreq.complete = 0;\n   data->sysexreq.completionProc = sysexCompletionProc;\n   data->sysexreq.completionRefCon = &(data->sysexreq);\n\n   result = MIDISendSysex( &(data->sysexreq) );\n   if ( result != noErr ) {\n     errorString_ = \"MidiOutCore::sendMessage: error sending MIDI to virtual destinations.\";\n     RtMidi::error( RtError::WARNING, errorString_ );\n   }\n   return;\n  }\n  else if ( nBytes > 3 ) {\n   errorString_ = \"MidiOutCore::sendMessage: message format problem ... not sysex but > 3 bytes?\";\n   RtMidi::error( RtError::WARNING, errorString_ );\n   return;\n  }\n\n  MIDIPacketList packetList;\n  MIDIPacket *packet = MIDIPacketListInit( &packetList );\n  packet = MIDIPacketListAdd( &packetList, sizeof(packetList), packet, timeStamp, nBytes, (const Byte *) &message->at( 0 ) );\n  if ( !packet ) {\n    errorString_ = \"MidiOutCore::sendMessage: could not allocate packet list\";      \n    RtMidi::error( RtError::DRIVER_ERROR, errorString_ );\n  }\n\n  // Send to any destinations that may have connected to us.\n  if ( data->endpoint ) {\n    result = MIDIReceived( data->endpoint, &packetList );\n    if ( result != noErr ) {\n      errorString_ = \"MidiOutCore::sendMessage: error sending MIDI to virtual destinations.\";\n      RtMidi::error( RtError::WARNING, errorString_ );\n    }\n  }\n\n  // And send to an explicit destination port if we're connected.\n  if ( connected_ ) {\n    result = MIDISend( data->port, data->destinationId, &packetList );\n    if ( result != noErr ) {\n      errorString_ = \"MidiOutCore::sendMessage: error sending MIDI message to port.\";\n      RtMidi::error( RtError::WARNING, errorString_ );\n    }\n  }\n\n}\n\n#endif  // __MACOSX_CORE__\n\n\n//*********************************************************************//\n//  API: LINUX ALSA SEQUENCER\n//*********************************************************************//\n\n// API information found at:\n//   - http://www.alsa-project.org/documentation.php#Library\n\n#if defined(__LINUX_ALSA__)\n\n// The ALSA Sequencer API is based on the use of a callback function for\n// MIDI input.\n//\n// Thanks to Pedro Lopez-Cabanillas for help with the ALSA sequencer\n// time stamps and other assorted fixes!!!\n\n// If you don't need timestamping for incoming MIDI events, define the\n// preprocessor definition AVOID_TIMESTAMPING to save resources\n// associated with the ALSA sequencer queues.\n\n#include <pthread.h>\n#include <sys/time.h>\n\n// ALSA header file.\n#include <alsa/asoundlib.h>\n\n// Global sequencer instance created when first In/Out object is\n// created, then destroyed when last In/Out is deleted.\nstatic snd_seq_t *s_seq = NULL;\n\n// Variable to keep track of how many ports are open.\nstatic unsigned int s_numPorts = 0;\n\n// The client name to use when creating the sequencer, which is\n// currently set on the first call to createSequencer.\nstatic std::string s_clientName = \"RtMidi Client\";\n\n// A structure to hold variables related to the ALSA API\n// implementation.\nstruct AlsaMidiData {\n  snd_seq_t *seq;\n  unsigned int portNum;\n  int vport;\n  snd_seq_port_subscribe_t *subscription;\n  snd_midi_event_t *coder;\n  unsigned int bufferSize;\n  unsigned char *buffer;\n  pthread_t thread;\n  pthread_t dummy_thread_id;\n  unsigned long long lastTime;\n  int queue_id; // an input queue is needed to get timestamped events\n  int trigger_fds[2];\n};\n\n#define PORT_TYPE( pinfo, bits ) ((snd_seq_port_info_get_capability(pinfo) & (bits)) == (bits))\n\nsnd_seq_t* createSequencer( const std::string& clientName )\n{\n  // Set up the ALSA sequencer client.\n  if ( s_seq == NULL ) {\n    int result = snd_seq_open(&s_seq, \"default\", SND_SEQ_OPEN_DUPLEX, SND_SEQ_NONBLOCK);\n    if ( result < 0 ) {\n      s_seq = NULL;\n    }\n    else {\n      // Set client name, use current name if given string is empty.\n      if ( clientName != \"\" ) {\n        s_clientName = clientName;\n      }\n      snd_seq_set_client_name( s_seq, s_clientName.c_str() );\n    }\n  }\n\n  // Increment port count.\n  s_numPorts++;\n\n  return s_seq;\n}\n\nvoid freeSequencer ( void )\n{\n  s_numPorts--;\n  if ( s_numPorts == 0 && s_seq != NULL ) {\n    snd_seq_close( s_seq );\n    s_seq = NULL;\n  }\n}\n\n//*********************************************************************//\n//  API: LINUX ALSA\n//  Class Definitions: MidiInAlsa\n//*********************************************************************//\n\nextern \"C\" void *alsaMidiHandler( void *ptr )\n{\n  MidiInApi::RtMidiInData *data = static_cast<MidiInApi::RtMidiInData *> (ptr);\n  AlsaMidiData *apiData = static_cast<AlsaMidiData *> (data->apiData);\n\n  long nBytes;\n  unsigned long long time, lastTime;\n  bool continueSysex = false;\n  bool doDecode = false;\n  MidiInApi::MidiMessage message;\n  int poll_fd_count;\n  struct pollfd *poll_fds;\n\n  snd_seq_event_t *ev;\n  int result;\n  apiData->bufferSize = 32;\n  result = snd_midi_event_new( 0, &apiData->coder );\n  if ( result < 0 ) {\n    data->doInput = false;\n    std::cerr << \"\\nMidiInAlsa::alsaMidiHandler: error initializing MIDI event parser!\\n\\n\";\n    return 0;\n  }\n  unsigned char *buffer = (unsigned char *) malloc( apiData->bufferSize );\n  if ( buffer == NULL ) {\n    data->doInput = false;\n    snd_midi_event_free( apiData->coder );\n    apiData->coder = 0;\n    std::cerr << \"\\nMidiInAlsa::alsaMidiHandler: error initializing buffer memory!\\n\\n\";\n    return 0;\n  }\n  snd_midi_event_init( apiData->coder );\n  snd_midi_event_no_status( apiData->coder, 1 ); // suppress running status messages\n\n  poll_fd_count = snd_seq_poll_descriptors_count( apiData->seq, POLLIN ) + 1;\n  poll_fds = (struct pollfd*)alloca( poll_fd_count * sizeof( struct pollfd ));\n  snd_seq_poll_descriptors( apiData->seq, poll_fds + 1, poll_fd_count - 1, POLLIN );\n  poll_fds[0].fd = apiData->trigger_fds[0];\n  poll_fds[0].events = POLLIN;\n\n  while ( data->doInput ) {\n\n    if ( snd_seq_event_input_pending( apiData->seq, 1 ) == 0 ) {\n      // No data pending\n      if ( poll( poll_fds, poll_fd_count, -1) >= 0 ) {\n        if ( poll_fds[0].revents & POLLIN ) {\n          bool dummy;\n          int res = read( poll_fds[0].fd, &dummy, sizeof(dummy) );\n          (void) res;\n        }\n      }\n      continue;\n    }\n\n    // If here, there should be data.\n    result = snd_seq_event_input( apiData->seq, &ev );\n    if ( result == -ENOSPC ) {\n      std::cerr << \"\\nMidiInAlsa::alsaMidiHandler: MIDI input buffer overrun!\\n\\n\";\n      continue;\n    }\n    else if ( result <= 0 ) {\n      std::cerr << \"MidiInAlsa::alsaMidiHandler: unknown MIDI input error!\\n\";\n      continue;\n    }\n\n    // This is a bit weird, but we now have to decode an ALSA MIDI\n    // event (back) into MIDI bytes.  We'll ignore non-MIDI types.\n    if ( !continueSysex ) message.bytes.clear();\n\n    doDecode = false;\n    switch ( ev->type ) {\n\n\t\tcase SND_SEQ_EVENT_PORT_SUBSCRIBED:\n#if defined(__RTMIDI_DEBUG__)\n      std::cout << \"MidiInAlsa::alsaMidiHandler: port connection made!\\n\";\n#endif\n      break;\n\n\t\tcase SND_SEQ_EVENT_PORT_UNSUBSCRIBED:\n#if defined(__RTMIDI_DEBUG__)\n      std::cerr << \"MidiInAlsa::alsaMidiHandler: port connection has closed!\\n\";\n      std::cout << \"sender = \" << (int) ev->data.connect.sender.client << \":\"\n                << (int) ev->data.connect.sender.port\n                << \", dest = \" << (int) ev->data.connect.dest.client << \":\"\n                << (int) ev->data.connect.dest.port\n                << std::endl;\n#endif\n      break;\n\n    case SND_SEQ_EVENT_QFRAME: // MIDI time code\n      if ( !( data->ignoreFlags & 0x02 ) ) doDecode = true;\n      break;\n\n    case SND_SEQ_EVENT_TICK: // MIDI timing tick\n      if ( !( data->ignoreFlags & 0x02 ) ) doDecode = true;\n      break;\n\n    case SND_SEQ_EVENT_SENSING: // Active sensing\n      if ( !( data->ignoreFlags & 0x04 ) ) doDecode = true;\n      break;\n\n\t\tcase SND_SEQ_EVENT_SYSEX:\n      if ( (data->ignoreFlags & 0x01) ) break;\n      if ( ev->data.ext.len > apiData->bufferSize ) {\n        apiData->bufferSize = ev->data.ext.len;\n        free( buffer );\n        buffer = (unsigned char *) malloc( apiData->bufferSize );\n        if ( buffer == NULL ) {\n          data->doInput = false;\n          std::cerr << \"\\nMidiInAlsa::alsaMidiHandler: error resizing buffer memory!\\n\\n\";\n          break;\n        }\n      }\n\n    default:\n      doDecode = true;\n    }\n\n    if ( doDecode ) {\n\n      nBytes = snd_midi_event_decode( apiData->coder, buffer, apiData->bufferSize, ev );\n      if ( nBytes > 0 ) {\n        // The ALSA sequencer has a maximum buffer size for MIDI sysex\n        // events of 256 bytes.  If a device sends sysex messages larger\n        // than this, they are segmented into 256 byte chunks.  So,\n        // we'll watch for this and concatenate sysex chunks into a\n        // single sysex message if necessary.\n        if ( !continueSysex )\n          message.bytes.assign( buffer, &buffer[nBytes] );\n        else\n          message.bytes.insert( message.bytes.end(), buffer, &buffer[nBytes] );\n\n        continueSysex = ( ( ev->type == SND_SEQ_EVENT_SYSEX ) && ( message.bytes.back() != 0xF7 ) );\n        if ( !continueSysex ) {\n\n          // Calculate the time stamp:\n          message.timeStamp = 0.0;\n\n          // Method 1: Use the system time.\n          //(void)gettimeofday(&tv, (struct timezone *)NULL);\n          //time = (tv.tv_sec * 1000000) + tv.tv_usec;\n\n          // Method 2: Use the ALSA sequencer event time data.\n          // (thanks to Pedro Lopez-Cabanillas!).\n          time = ( ev->time.time.tv_sec * 1000000 ) + ( ev->time.time.tv_nsec/1000 );\n          lastTime = time;\n          time -= apiData->lastTime;\n          apiData->lastTime = lastTime;\n          if ( data->firstMessage == true )\n            data->firstMessage = false;\n          else\n            message.timeStamp = time * 0.000001;\n        }\n        else {\n#if defined(__RTMIDI_DEBUG__)\n          std::cerr << \"\\nMidiInAlsa::alsaMidiHandler: event parsing error or not a MIDI event!\\n\\n\";\n#endif\n        }\n      }\n    }\n\n    snd_seq_free_event( ev );\n    if ( message.bytes.size() == 0 || continueSysex ) continue;\n\n    if ( data->usingCallback ) {\n      RtMidiIn::RtMidiCallback callback = (RtMidiIn::RtMidiCallback) data->userCallback;\n      callback( message.timeStamp, &message.bytes, data->userData );\n    }\n    else {\n      // As long as we haven't reached our queue size limit, push the message.\n      if ( data->queue.size < data->queue.ringSize ) {\n        data->queue.ring[data->queue.back++] = message;\n        if ( data->queue.back == data->queue.ringSize )\n          data->queue.back = 0;\n        data->queue.size++;\n      }\n      else\n        std::cerr << \"\\nMidiInAlsa: message queue limit reached!!\\n\\n\";\n    }\n  }\n\n  if ( buffer ) free( buffer );\n  snd_midi_event_free( apiData->coder );\n  apiData->coder = 0;\n  apiData->thread = apiData->dummy_thread_id;\n  return 0;\n}\n\nMidiInAlsa :: MidiInAlsa( const std::string clientName, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit )\n{\n  initialize( clientName );\n}\n\nMidiInAlsa :: ~MidiInAlsa()\n{\n  // Close a connection if it exists.\n  closePort();\n\n  // Shutdown the input thread.\n  AlsaMidiData *data = static_cast<AlsaMidiData *> (apiData_);\n  if ( inputData_.doInput ) {\n    inputData_.doInput = false;\n    int res = write( data->trigger_fds[1], &inputData_.doInput, sizeof(inputData_.doInput) );\n    (void) res;\n    if ( !pthread_equal(data->thread, data->dummy_thread_id) )\n      pthread_join( data->thread, NULL );\n  }\n\n  // Cleanup.\n  close ( data->trigger_fds[0] );\n  close ( data->trigger_fds[1] );\n  if ( data->vport >= 0 ) snd_seq_delete_port( data->seq, data->vport );\n#ifndef AVOID_TIMESTAMPING\n  snd_seq_free_queue( data->seq, data->queue_id );\n#endif\n  freeSequencer();\n  delete data;\n}\n\nvoid MidiInAlsa :: initialize( const std::string& clientName )\n{\n  snd_seq_t* seq = createSequencer( clientName );\n  if ( seq == NULL ) {\n    s_seq = NULL;\n    errorString_ = \"MidiInAlsa::initialize: error creating ALSA sequencer client object.\";\n    RtMidi::error( RtError::DRIVER_ERROR, errorString_ );\n  }\n\n  // Save our api-specific connection information.\n  AlsaMidiData *data = (AlsaMidiData *) new AlsaMidiData;\n  data->seq = seq;\n  data->portNum = -1;\n  data->vport = -1;\n  data->subscription = 0;\n  data->dummy_thread_id = pthread_self();\n  data->thread = data->dummy_thread_id;\n  data->trigger_fds[0] = -1;\n  data->trigger_fds[1] = -1;\n  apiData_ = (void *) data;\n  inputData_.apiData = (void *) data;\n\n   if ( pipe(data->trigger_fds) == -1 ) {\n    errorString_ = \"MidiInAlsa::initialize: error creating pipe objects.\";\n    RtMidi::error( RtError::DRIVER_ERROR, errorString_ );\n  }\n\n  // Create the input queue\n#ifndef AVOID_TIMESTAMPING\n  data->queue_id = snd_seq_alloc_named_queue(s_seq, \"RtMidi Queue\");\n  // Set arbitrary tempo (mm=100) and resolution (240)\n  snd_seq_queue_tempo_t *qtempo;\n  snd_seq_queue_tempo_alloca(&qtempo);\n  snd_seq_queue_tempo_set_tempo(qtempo, 600000);\n  snd_seq_queue_tempo_set_ppq(qtempo, 240);\n  snd_seq_set_queue_tempo(data->seq, data->queue_id, qtempo);\n  snd_seq_drain_output(data->seq);\n#endif\n}\n\n// This function is used to count or get the pinfo structure for a given port number.\nunsigned int portInfo( snd_seq_t *seq, snd_seq_port_info_t *pinfo, unsigned int type, int portNumber )\n{\n  snd_seq_client_info_t *cinfo;\n  int client;\n  int count = 0;\n  snd_seq_client_info_alloca( &cinfo );\n\n  snd_seq_client_info_set_client( cinfo, -1 );\n  while ( snd_seq_query_next_client( seq, cinfo ) >= 0 ) {\n    client = snd_seq_client_info_get_client( cinfo );\n    if ( client == 0 ) continue;\n    // Reset query info\n    snd_seq_port_info_set_client( pinfo, client );\n    snd_seq_port_info_set_port( pinfo, -1 );\n    while ( snd_seq_query_next_port( seq, pinfo ) >= 0 ) {\n      unsigned int atyp = snd_seq_port_info_get_type( pinfo );\n      if ( ( atyp & SND_SEQ_PORT_TYPE_MIDI_GENERIC ) == 0 ) continue;\n      unsigned int caps = snd_seq_port_info_get_capability( pinfo );\n      if ( ( caps & type ) != type ) continue;\n      if ( count == portNumber ) return 1;\n      ++count;\n    }\n  }\n\n  // If a negative portNumber was used, return the port count.\n  if ( portNumber < 0 ) return count;\n  return 0;\n}\n\nunsigned int MidiInAlsa :: getPortCount()\n{\n  snd_seq_port_info_t *pinfo;\n  snd_seq_port_info_alloca( &pinfo );\n\n  AlsaMidiData *data = static_cast<AlsaMidiData *> (apiData_);\n  return portInfo( data->seq, pinfo, SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, -1 );\n}\n\nstd::string MidiInAlsa :: getPortName( unsigned int portNumber )\n{\n  snd_seq_client_info_t *cinfo;\n  snd_seq_port_info_t *pinfo;\n  snd_seq_client_info_alloca( &cinfo );\n  snd_seq_port_info_alloca( &pinfo );\n\n  std::string stringName;\n  AlsaMidiData *data = static_cast<AlsaMidiData *> (apiData_);\n  if ( portInfo( data->seq, pinfo, SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, (int) portNumber ) ) {\n    int cnum = snd_seq_port_info_get_client( pinfo );\n    snd_seq_get_any_client_info( data->seq, cnum, cinfo );\n    std::ostringstream os;\n    os << snd_seq_client_info_get_name( cinfo );\n    os << \" \";                                    // GO: These lines added to make sure devices are listed\n    os << snd_seq_port_info_get_client( pinfo );  // GO: with full portnames added to ensure individual device names\n    os << \":\";\n    os << snd_seq_port_info_get_port( pinfo );\n    stringName = os.str();\n    return stringName;\n  }\n\n  // If we get here, we didn't find a match.\n  errorString_ = \"MidiInAlsa::getPortName: error looking for port name!\";\n  RtMidi::error( RtError::WARNING, errorString_ );\n  return stringName;\n  //RtMidi::error( RtError::INVALID_PARAMETER, errorString_ );\n}\n\nvoid MidiInAlsa :: openPort( unsigned int portNumber, const std::string portName )\n{\n  if ( connected_ ) {\n    errorString_ = \"MidiInAlsa::openPort: a valid connection already exists!\";\n    RtMidi::error( RtError::WARNING, errorString_ );\n    return;\n  }\n\n  unsigned int nSrc = this->getPortCount();\n  if (nSrc < 1) {\n    errorString_ = \"MidiInAlsa::openPort: no MIDI input sources found!\";\n    RtMidi::error( RtError::NO_DEVICES_FOUND, errorString_ );\n  }\n\n  snd_seq_port_info_t *pinfo;\n  snd_seq_port_info_alloca( &pinfo );\n  std::ostringstream ost;\n  AlsaMidiData *data = static_cast<AlsaMidiData *> (apiData_);\n  if ( portInfo( data->seq, pinfo, SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, (int) portNumber ) == 0 ) {\n    ost << \"MidiInAlsa::openPort: the 'portNumber' argument (\" << portNumber << \") is invalid.\";\n    errorString_ = ost.str();\n    RtMidi::error( RtError::INVALID_PARAMETER, errorString_ );\n  }\n\n\n  snd_seq_addr_t sender, receiver;\n  sender.client = snd_seq_port_info_get_client( pinfo );\n  sender.port = snd_seq_port_info_get_port( pinfo );\n  receiver.client = snd_seq_client_id( data->seq );\n  if ( data->vport < 0 ) {\n    snd_seq_port_info_set_client( pinfo, 0 );\n    snd_seq_port_info_set_port( pinfo, 0 );\n    snd_seq_port_info_set_capability( pinfo,\n                                      SND_SEQ_PORT_CAP_WRITE |\n                                      SND_SEQ_PORT_CAP_SUBS_WRITE );\n    snd_seq_port_info_set_type( pinfo,\n                                SND_SEQ_PORT_TYPE_MIDI_GENERIC |\n                                SND_SEQ_PORT_TYPE_APPLICATION );\n    snd_seq_port_info_set_midi_channels(pinfo, 16);\n#ifndef AVOID_TIMESTAMPING\n    snd_seq_port_info_set_timestamping(pinfo, 1);\n    snd_seq_port_info_set_timestamp_real(pinfo, 1);    \n    snd_seq_port_info_set_timestamp_queue(pinfo, data->queue_id);\n#endif\n    snd_seq_port_info_set_name(pinfo,  portName.c_str() );\n    data->vport = snd_seq_create_port(data->seq, pinfo);\n  \n    if ( data->vport < 0 ) {\n      errorString_ = \"MidiInAlsa::openPort: ALSA error creating input port.\";\n      RtMidi::error( RtError::DRIVER_ERROR, errorString_ );\n    }\n  }\n\n  receiver.port = data->vport;\n\n  if ( !data->subscription ) {\n    // Make subscription\n    if (snd_seq_port_subscribe_malloc( &data->subscription ) < 0) {\n      errorString_ = \"MidiInAlsa::openPort: ALSA error allocation port subscription.\";\n      RtMidi::error( RtError::DRIVER_ERROR, errorString_ );\n    }\n    snd_seq_port_subscribe_set_sender(data->subscription, &sender);\n    snd_seq_port_subscribe_set_dest(data->subscription, &receiver);\n    if ( snd_seq_subscribe_port(data->seq, data->subscription) ) {\n      snd_seq_port_subscribe_free( data->subscription );\n      data->subscription = 0;\n      errorString_ = \"MidiInAlsa::openPort: ALSA error making port connection.\";\n      RtMidi::error( RtError::DRIVER_ERROR, errorString_ );\n    }\n  }\n\n  if ( inputData_.doInput == false ) {\n    // Start the input queue\n#ifndef AVOID_TIMESTAMPING\n    snd_seq_start_queue( data->seq, data->queue_id, NULL );\n    snd_seq_drain_output( data->seq );\n#endif\n    // Start our MIDI input thread.\n    pthread_attr_t attr;\n    pthread_attr_init(&attr);\n    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);\n    pthread_attr_setschedpolicy(&attr, SCHED_OTHER);\n\n    inputData_.doInput = true;\n    int err = pthread_create(&data->thread, &attr, alsaMidiHandler, &inputData_);\n    pthread_attr_destroy(&attr);\n    if ( err ) {\n      snd_seq_unsubscribe_port( data->seq, data->subscription );\n      snd_seq_port_subscribe_free( data->subscription );\n      data->subscription = 0;\n      inputData_.doInput = false;\n      errorString_ = \"MidiInAlsa::openPort: error starting MIDI input thread!\";\n      RtMidi::error( RtError::THREAD_ERROR, errorString_ );\n    }\n  }\n\n  connected_ = true;\n}\n\nvoid MidiInAlsa :: openVirtualPort( std::string portName )\n{\n  AlsaMidiData *data = static_cast<AlsaMidiData *> (apiData_);\n  if ( data->vport < 0 ) {\n    snd_seq_port_info_t *pinfo;\n    snd_seq_port_info_alloca( &pinfo );\n    snd_seq_port_info_set_capability( pinfo,\n\t\t\t\t      SND_SEQ_PORT_CAP_WRITE |\n\t\t\t\t      SND_SEQ_PORT_CAP_SUBS_WRITE );\n    snd_seq_port_info_set_type( pinfo,\n\t\t\t\tSND_SEQ_PORT_TYPE_MIDI_GENERIC |\n\t\t\t\tSND_SEQ_PORT_TYPE_APPLICATION );\n    snd_seq_port_info_set_midi_channels(pinfo, 16);\n#ifndef AVOID_TIMESTAMPING\n    snd_seq_port_info_set_timestamping(pinfo, 1);\n    snd_seq_port_info_set_timestamp_real(pinfo, 1);    \n    snd_seq_port_info_set_timestamp_queue(pinfo, data->queue_id);\n#endif\n    snd_seq_port_info_set_name(pinfo, portName.c_str());\n    data->vport = snd_seq_create_port(data->seq, pinfo);\n\n    if ( data->vport < 0 ) {\n      errorString_ = \"MidiInAlsa::openVirtualPort: ALSA error creating virtual port.\";\n      RtMidi::error( RtError::DRIVER_ERROR, errorString_ );\n    }\n  }\n\n  if ( inputData_.doInput == false ) {\n    // Wait for old thread to stop, if still running\n    if ( !pthread_equal(data->thread, data->dummy_thread_id) )\n      pthread_join( data->thread, NULL );\n\n    // Start the input queue\n#ifndef AVOID_TIMESTAMPING\n    snd_seq_start_queue( data->seq, data->queue_id, NULL );\n    snd_seq_drain_output( data->seq );\n#endif\n    // Start our MIDI input thread.\n    pthread_attr_t attr;\n    pthread_attr_init(&attr);\n    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);\n    pthread_attr_setschedpolicy(&attr, SCHED_OTHER);\n\n    inputData_.doInput = true;\n    int err = pthread_create(&data->thread, &attr, alsaMidiHandler, &inputData_);\n    pthread_attr_destroy(&attr);\n    if ( err ) {\n      if ( data->subscription ) {\n        snd_seq_unsubscribe_port( data->seq, data->subscription );\n        snd_seq_port_subscribe_free( data->subscription );\n        data->subscription = 0;\n      }\n      inputData_.doInput = false;\n      errorString_ = \"MidiInAlsa::openPort: error starting MIDI input thread!\";\n      RtMidi::error( RtError::THREAD_ERROR, errorString_ );\n    }\n  }\n}\n\nvoid MidiInAlsa :: closePort( void )\n{\n  AlsaMidiData *data = static_cast<AlsaMidiData *> (apiData_);\n\n  if ( connected_ ) {\n    if ( data->subscription ) {\n      snd_seq_unsubscribe_port( data->seq, data->subscription );\n      snd_seq_port_subscribe_free( data->subscription );\n      data->subscription = 0;\n    }\n    // Stop the input queue\n#ifndef AVOID_TIMESTAMPING\n    snd_seq_stop_queue( data->seq, data->queue_id, NULL );\n    snd_seq_drain_output( data->seq );\n#endif\n    connected_ = false;\n  }\n\n  // Stop thread to avoid triggering the callback, while the port is intended to be closed\n  if ( inputData_.doInput ) {\n    inputData_.doInput = false;\n    int res = write( data->trigger_fds[1], &inputData_.doInput, sizeof(inputData_.doInput) );\n    (void) res;\n    if ( !pthread_equal(data->thread, data->dummy_thread_id) )\n      pthread_join( data->thread, NULL );\n  }\n}\n\n//*********************************************************************//\n//  API: LINUX ALSA\n//  Class Definitions: MidiOutAlsa\n//*********************************************************************//\n\nMidiOutAlsa :: MidiOutAlsa( const std::string clientName ) : MidiOutApi()\n{\n  initialize( clientName );\n}\n\nMidiOutAlsa :: ~MidiOutAlsa()\n{\n  // Close a connection if it exists.\n  closePort();\n\n  // Cleanup.\n  AlsaMidiData *data = static_cast<AlsaMidiData *> (apiData_);\n  if ( data->vport >= 0 ) snd_seq_delete_port( data->seq, data->vport );\n  if ( data->coder ) snd_midi_event_free( data->coder );\n  if ( data->buffer ) free( data->buffer );\n  freeSequencer();\n  delete data;\n}\n\nvoid MidiOutAlsa :: initialize( const std::string& clientName )\n{\n  snd_seq_t* seq = createSequencer( clientName );\n  if ( seq == NULL ) {\n    s_seq = NULL;\n    errorString_ = \"MidiOutAlsa::initialize: error creating ALSA sequencer client object.\";\n    RtMidi::error( RtError::DRIVER_ERROR, errorString_ );\n\t}\n\n  // Save our api-specific connection information.\n  AlsaMidiData *data = (AlsaMidiData *) new AlsaMidiData;\n  data->seq = seq;\n  data->portNum = -1;\n  data->vport = -1;\n  data->bufferSize = 32;\n  data->coder = 0;\n  data->buffer = 0;\n  int result = snd_midi_event_new( data->bufferSize, &data->coder );\n  if ( result < 0 ) {\n    delete data;\n    errorString_ = \"MidiOutAlsa::initialize: error initializing MIDI event parser!\\n\\n\";\n    RtMidi::error( RtError::DRIVER_ERROR, errorString_ );\n  }\n  data->buffer = (unsigned char *) malloc( data->bufferSize );\n  if ( data->buffer == NULL ) {\n    delete data;\n    errorString_ = \"MidiOutAlsa::initialize: error allocating buffer memory!\\n\\n\";\n    RtMidi::error( RtError::MEMORY_ERROR, errorString_ );\n  }\n  snd_midi_event_init( data->coder );\n  apiData_ = (void *) data;\n}\n\nunsigned int MidiOutAlsa :: getPortCount()\n{\n\tsnd_seq_port_info_t *pinfo;\n\tsnd_seq_port_info_alloca( &pinfo );\n\n  AlsaMidiData *data = static_cast<AlsaMidiData *> (apiData_);\n  return portInfo( data->seq, pinfo, SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE, -1 );\n}\n\nstd::string MidiOutAlsa :: getPortName( unsigned int portNumber )\n{\n  snd_seq_client_info_t *cinfo;\n  snd_seq_port_info_t *pinfo;\n  snd_seq_client_info_alloca( &cinfo );\n  snd_seq_port_info_alloca( &pinfo );\n\n  std::string stringName;\n  AlsaMidiData *data = static_cast<AlsaMidiData *> (apiData_);\n  if ( portInfo( data->seq, pinfo, SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE, (int) portNumber ) ) {\n    int cnum = snd_seq_port_info_get_client(pinfo);\n    snd_seq_get_any_client_info( data->seq, cnum, cinfo );\n    std::ostringstream os;\n    os << snd_seq_client_info_get_name(cinfo);\n    os << \":\";\n    os << snd_seq_port_info_get_port(pinfo);\n    stringName = os.str();\n    return stringName;\n  }\n\n  // If we get here, we didn't find a match.\n  errorString_ = \"MidiOutAlsa::getPortName: error looking for port name!\";\n  //RtMidi::error( RtError::INVALID_PARAMETER, errorString_ );\n  RtMidi::error( RtError::WARNING, errorString_ );\n  return stringName;\n}\n\nvoid MidiOutAlsa :: openPort( unsigned int portNumber, const std::string portName )\n{\n  if ( connected_ ) {\n    errorString_ = \"MidiOutAlsa::openPort: a valid connection already exists!\";\n    RtMidi::error( RtError::WARNING, errorString_ );\n    return;\n  }\n\n  unsigned int nSrc = this->getPortCount();\n  if (nSrc < 1) {\n    errorString_ = \"MidiOutAlsa::openPort: no MIDI output sources found!\";\n    RtMidi::error( RtError::NO_DEVICES_FOUND, errorString_ );\n  }\n\n\tsnd_seq_port_info_t *pinfo;\n\tsnd_seq_port_info_alloca( &pinfo );\n  std::ostringstream ost;\n  AlsaMidiData *data = static_cast<AlsaMidiData *> (apiData_);\n  if ( portInfo( data->seq, pinfo, SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE, (int) portNumber ) == 0 ) {\n    ost << \"MidiOutAlsa::openPort: the 'portNumber' argument (\" << portNumber << \") is invalid.\";\n    errorString_ = ost.str();\n    RtMidi::error( RtError::INVALID_PARAMETER, errorString_ );\n  }\n\n  snd_seq_addr_t sender, receiver;\n  receiver.client = snd_seq_port_info_get_client( pinfo );\n  receiver.port = snd_seq_port_info_get_port( pinfo );\n  sender.client = snd_seq_client_id( data->seq );\n\n  if ( data->vport < 0 ) {\n    data->vport = snd_seq_create_simple_port( data->seq, portName.c_str(),\n                                              SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ,\n                                              SND_SEQ_PORT_TYPE_MIDI_GENERIC|SND_SEQ_PORT_TYPE_APPLICATION );\n    if ( data->vport < 0 ) {\n      errorString_ = \"MidiOutAlsa::openPort: ALSA error creating output port.\";\n      RtMidi::error( RtError::DRIVER_ERROR, errorString_ );\n    }\n  }\n\n  sender.port = data->vport;\n\n  // Make subscription\n  if (snd_seq_port_subscribe_malloc( &data->subscription ) < 0) {\n    snd_seq_port_subscribe_free( data->subscription );\n    errorString_ = \"MidiOutAlsa::openPort: error allocation port subscribtion.\";\n    RtMidi::error( RtError::DRIVER_ERROR, errorString_ );\n  }\n  snd_seq_port_subscribe_set_sender(data->subscription, &sender);\n  snd_seq_port_subscribe_set_dest(data->subscription, &receiver);\n  snd_seq_port_subscribe_set_time_update(data->subscription, 1);\n  snd_seq_port_subscribe_set_time_real(data->subscription, 1);\n  if ( snd_seq_subscribe_port(data->seq, data->subscription) ) {\n    snd_seq_port_subscribe_free( data->subscription );\n    errorString_ = \"MidiOutAlsa::openPort: ALSA error making port connection.\";\n    RtMidi::error( RtError::DRIVER_ERROR, errorString_ );\n  }\n\n  connected_ = true;\n}\n\nvoid MidiOutAlsa :: closePort( void )\n{\n  if ( connected_ ) {\n    AlsaMidiData *data = static_cast<AlsaMidiData *> (apiData_);\n    snd_seq_unsubscribe_port( data->seq, data->subscription );\n    snd_seq_port_subscribe_free( data->subscription );\n    connected_ = false;\n  }\n}\n\nvoid MidiOutAlsa :: openVirtualPort( std::string portName )\n{\n  AlsaMidiData *data = static_cast<AlsaMidiData *> (apiData_);\n  if ( data->vport < 0 ) {\n    data->vport = snd_seq_create_simple_port( data->seq, portName.c_str(),\n                                              SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ,\n                                              SND_SEQ_PORT_TYPE_MIDI_GENERIC|SND_SEQ_PORT_TYPE_APPLICATION );\n\n    if ( data->vport < 0 ) {\n      errorString_ = \"MidiOutAlsa::openVirtualPort: ALSA error creating virtual port.\";\n      RtMidi::error( RtError::DRIVER_ERROR, errorString_ );\n    }\n  }\n}\n\nvoid MidiOutAlsa :: sendMessage( std::vector<unsigned char> *message )\n{\n  int result;\n  AlsaMidiData *data = static_cast<AlsaMidiData *> (apiData_);\n  unsigned int nBytes = message->size();\n  if ( nBytes > data->bufferSize ) {\n    data->bufferSize = nBytes;\n    result = snd_midi_event_resize_buffer ( data->coder, nBytes);\n    if ( result != 0 ) {\n      errorString_ = \"MidiOutAlsa::sendMessage: ALSA error resizing MIDI event buffer.\";\n      RtMidi::error( RtError::DRIVER_ERROR, errorString_ );\n    }\n    free (data->buffer);\n    data->buffer = (unsigned char *) malloc( data->bufferSize );\n    if ( data->buffer == NULL ) {\n    errorString_ = \"MidiOutAlsa::initialize: error allocating buffer memory!\\n\\n\";\n    RtMidi::error( RtError::MEMORY_ERROR, errorString_ );\n    }\n  }\n\n  snd_seq_event_t ev;\n  snd_seq_ev_clear(&ev);\n  snd_seq_ev_set_source(&ev, data->vport);\n  snd_seq_ev_set_subs(&ev);\n  snd_seq_ev_set_direct(&ev);\n  for ( unsigned int i=0; i<nBytes; ++i ) data->buffer[i] = message->at(i);\n  result = snd_midi_event_encode( data->coder, data->buffer, (long)nBytes, &ev );\n  if ( result < (int)nBytes ) {\n    errorString_ = \"MidiOutAlsa::sendMessage: event parsing error!\";\n    RtMidi::error( RtError::WARNING, errorString_ );\n    return;\n  }\n\n  // Send the event.\n  result = snd_seq_event_output(data->seq, &ev);\n  if ( result < 0 ) {\n    errorString_ = \"MidiOutAlsa::sendMessage: error sending MIDI message to port.\";\n    RtMidi::error( RtError::WARNING, errorString_ );\n  }\n  snd_seq_drain_output(data->seq);\n}\n\n#endif // __LINUX_ALSA__\n\n\n//*********************************************************************//\n//  API: Windows Multimedia Library (MM)\n//*********************************************************************//\n\n// API information deciphered from:\n//  - http://msdn.microsoft.com/library/default.asp?url=/library/en-us/multimed/htm/_win32_midi_reference.asp\n\n// Thanks to Jean-Baptiste Berruchon for the sysex code.\n\n#if defined(__WINDOWS_MM__)\n\n// The Windows MM API is based on the use of a callback function for\n// MIDI input.  We convert the system specific time stamps to delta\n// time values.\n\n// Windows MM MIDI header files.\n#include <windows.h>\n#include <mmsystem.h>\n\n#define  RT_SYSEX_BUFFER_SIZE 1024\n#define  RT_SYSEX_BUFFER_COUNT 4\n\n// A structure to hold variables related to the CoreMIDI API\n// implementation.\nstruct WinMidiData {\n  HMIDIIN inHandle;    // Handle to Midi Input Device\n  HMIDIOUT outHandle;  // Handle to Midi Output Device\n  DWORD lastTime;\n  MidiInApi::MidiMessage message;\n  LPMIDIHDR sysexBuffer[RT_SYSEX_BUFFER_COUNT];\n};\n\n//*********************************************************************//\n//  API: Windows MM\n//  Class Definitions: MidiInWinMM\n//*********************************************************************//\n\nstatic void CALLBACK midiInputCallback( HMIDIIN hmin,\n                                        UINT inputStatus, \n                                        DWORD_PTR instancePtr,\n                                        DWORD_PTR midiMessage,\n                                        DWORD timestamp )\n{\n  if ( inputStatus != MIM_DATA && inputStatus != MIM_LONGDATA && inputStatus != MIM_LONGERROR ) return;\n\n  //MidiInApi::RtMidiInData *data = static_cast<MidiInApi::RtMidiInData *> (instancePtr);\n  MidiInApi::RtMidiInData *data = (MidiInApi::RtMidiInData *)instancePtr;\n  WinMidiData *apiData = static_cast<WinMidiData *> (data->apiData);\n\n  // Calculate time stamp.\n  if ( data->firstMessage == true ) {\n    apiData->message.timeStamp = 0.0;\n    data->firstMessage = false;\n  }\n  else apiData->message.timeStamp = (double) ( timestamp - apiData->lastTime ) * 0.001;\n  apiData->lastTime = timestamp;\n\n  if ( inputStatus == MIM_DATA ) { // Channel or system message\n\n    // Make sure the first byte is a status byte.\n    unsigned char status = (unsigned char) (midiMessage & 0x000000FF);\n    if ( !(status & 0x80) ) return;\n\n    // Determine the number of bytes in the MIDI message.\n    unsigned short nBytes = 1;\n    if ( status < 0xC0 ) nBytes = 3;\n    else if ( status < 0xE0 ) nBytes = 2;\n    else if ( status < 0xF0 ) nBytes = 3;\n    else if ( status == 0xF1 ) {\n      if ( data->ignoreFlags & 0x02 ) return;\n      else nBytes = 2;\n    }\n    else if ( status == 0xF2 ) nBytes = 3;\n    else if ( status == 0xF3 ) nBytes = 2;\n    else if ( status == 0xF8 && (data->ignoreFlags & 0x02) ) {\n      // A MIDI timing tick message and we're ignoring it.\n      return;\n    }\n    else if ( status == 0xFE && (data->ignoreFlags & 0x04) ) {\n      // A MIDI active sensing message and we're ignoring it.\n      return;\n    }\n\n    // Copy bytes to our MIDI message.\n    unsigned char *ptr = (unsigned char *) &midiMessage;\n    for ( int i=0; i<nBytes; ++i ) apiData->message.bytes.push_back( *ptr++ );\n  }\n  else { // Sysex message ( MIM_LONGDATA or MIM_LONGERROR )\n    MIDIHDR *sysex = ( MIDIHDR *) midiMessage; \n    if ( !( data->ignoreFlags & 0x01 ) && inputStatus != MIM_LONGERROR ) {  \n      // Sysex message and we're not ignoring it\n      for ( int i=0; i<(int)sysex->dwBytesRecorded; ++i )\n        apiData->message.bytes.push_back( sysex->lpData[i] );\n    }\n\n    // The WinMM API requires that the sysex buffer be requeued after\n    // input of each sysex message.  Even if we are ignoring sysex\n    // messages, we still need to requeue the buffer in case the user\n    // decides to not ignore sysex messages in the future.  However,\n    // it seems that WinMM calls this function with an empty sysex\n    // buffer when an application closes and in this case, we should\n    // avoid requeueing it, else the computer suddenly reboots after\n    // one or two minutes.\n\tif ( apiData->sysexBuffer[sysex->dwUser]->dwBytesRecorded > 0 ) {\n    //if ( sysex->dwBytesRecorded > 0 ) {\n      MMRESULT result = midiInAddBuffer( apiData->inHandle, apiData->sysexBuffer[sysex->dwUser], sizeof(MIDIHDR) );\n      if ( result != MMSYSERR_NOERROR )\n        std::cerr << \"\\nRtMidiIn::midiInputCallback: error sending sysex to Midi device!!\\n\\n\";\n\n      if ( data->ignoreFlags & 0x01 ) return;\n    }\n    else return;\n  }\n\n  if ( data->usingCallback ) {\n    RtMidiIn::RtMidiCallback callback = (RtMidiIn::RtMidiCallback) data->userCallback;\n    callback( apiData->message.timeStamp, &apiData->message.bytes, data->userData );\n  }\n  else {\n    // As long as we haven't reached our queue size limit, push the message.\n    if ( data->queue.size < data->queue.ringSize ) {\n      data->queue.ring[data->queue.back++] = apiData->message;\n      if ( data->queue.back == data->queue.ringSize )\n        data->queue.back = 0;\n      data->queue.size++;\n    }\n    else\n      std::cerr << \"\\nRtMidiIn: message queue limit reached!!\\n\\n\";\n  }\n\n  // Clear the vector for the next input message.\n  apiData->message.bytes.clear();\n}\n\nMidiInWinMM :: MidiInWinMM( const std::string clientName, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit )\n{\n  initialize( clientName );\n}\n\nMidiInWinMM :: ~MidiInWinMM()\n{\n  // Close a connection if it exists.\n  closePort();\n\n  // Cleanup.\n  WinMidiData *data = static_cast<WinMidiData *> (apiData_);\n  delete data;\n}\n\nvoid MidiInWinMM :: initialize( const std::string& /*clientName*/ )\n{\n  // We'll issue a warning here if no devices are available but not\n  // throw an error since the user can plugin something later.\n  unsigned int nDevices = midiInGetNumDevs();\n  if ( nDevices == 0 ) {\n    errorString_ = \"MidiInWinMM::initialize: no MIDI input devices currently available.\";\n    RtMidi::error( RtError::WARNING, errorString_ );\n  }\n\n  // Save our api-specific connection information.\n  WinMidiData *data = (WinMidiData *) new WinMidiData;\n  apiData_ = (void *) data;\n  inputData_.apiData = (void *) data;\n  data->message.bytes.clear();  // needs to be empty for first input message\n}\n\nvoid MidiInWinMM :: openPort( unsigned int portNumber, const std::string /*portName*/ )\n{\n  if ( connected_ ) {\n    errorString_ = \"MidiInWinMM::openPort: a valid connection already exists!\";\n    RtMidi::error( RtError::WARNING, errorString_ );\n    return;\n  }\n\n  unsigned int nDevices = midiInGetNumDevs();\n  if (nDevices == 0) {\n    errorString_ = \"MidiInWinMM::openPort: no MIDI input sources found!\";\n    RtMidi::error( RtError::NO_DEVICES_FOUND, errorString_ );\n  }\n\n  std::ostringstream ost;\n  if ( portNumber >= nDevices ) {\n    ost << \"MidiInWinMM::openPort: the 'portNumber' argument (\" << portNumber << \") is invalid.\";\n    errorString_ = ost.str();\n    RtMidi::error( RtError::INVALID_PARAMETER, errorString_ );\n  }\n\n  WinMidiData *data = static_cast<WinMidiData *> (apiData_);\n  MMRESULT result = midiInOpen( &data->inHandle,\n                                portNumber,\n                                (DWORD_PTR)&midiInputCallback,\n                                (DWORD_PTR)&inputData_,\n                                CALLBACK_FUNCTION );\n  if ( result != MMSYSERR_NOERROR ) {\n    errorString_ = \"MidiInWinMM::openPort: error creating Windows MM MIDI input port.\";\n    RtMidi::error( RtError::DRIVER_ERROR, errorString_ );\n  }\n\n  // Allocate and init the sysex buffers.\n  for ( int i=0; i<RT_SYSEX_BUFFER_COUNT; ++i ) {\n    data->sysexBuffer[i] = (MIDIHDR*) new char[ sizeof(MIDIHDR) ];\n    data->sysexBuffer[i]->lpData = new char[ RT_SYSEX_BUFFER_SIZE ];\n    data->sysexBuffer[i]->dwBufferLength = RT_SYSEX_BUFFER_SIZE;\n    data->sysexBuffer[i]->dwUser = i; // We use the dwUser parameter as buffer indicator\n    data->sysexBuffer[i]->dwFlags = 0;\n\n    result = midiInPrepareHeader( data->inHandle, data->sysexBuffer[i], sizeof(MIDIHDR) );\n    if ( result != MMSYSERR_NOERROR ) {\n      midiInClose( data->inHandle );\n      errorString_ = \"MidiInWinMM::openPort: error starting Windows MM MIDI input port (PrepareHeader).\";\n      RtMidi::error( RtError::DRIVER_ERROR, errorString_ );\n    }\n\n    // Register the buffer.\n    result = midiInAddBuffer( data->inHandle, data->sysexBuffer[i], sizeof(MIDIHDR) );\n    if ( result != MMSYSERR_NOERROR ) {\n      midiInClose( data->inHandle );\n      errorString_ = \"MidiInWinMM::openPort: error starting Windows MM MIDI input port (AddBuffer).\";\n      RtMidi::error( RtError::DRIVER_ERROR, errorString_ );\n    }\n  }\n\n  result = midiInStart( data->inHandle );\n  if ( result != MMSYSERR_NOERROR ) {\n    midiInClose( data->inHandle );\n    errorString_ = \"MidiInWinMM::openPort: error starting Windows MM MIDI input port.\";\n    RtMidi::error( RtError::DRIVER_ERROR, errorString_ );\n  }\n\n  connected_ = true;\n}\n\nvoid MidiInWinMM :: openVirtualPort( std::string portName )\n{\n  // This function cannot be implemented for the Windows MM MIDI API.\n  errorString_ = \"MidiInWinMM::openVirtualPort: cannot be implemented in Windows MM MIDI API!\";\n  RtMidi::error( RtError::WARNING, errorString_ );\n}\n\nvoid MidiInWinMM :: closePort( void )\n{\n  if ( connected_ ) {\n    WinMidiData *data = static_cast<WinMidiData *> (apiData_);\n    midiInReset( data->inHandle );\n    midiInStop( data->inHandle );\n\n    for ( int i=0; i<RT_SYSEX_BUFFER_COUNT; ++i ) {\n      int result = midiInUnprepareHeader(data->inHandle, data->sysexBuffer[i], sizeof(MIDIHDR));\n      delete [] data->sysexBuffer[i]->lpData;\n      delete [] data->sysexBuffer[i];\n      if ( result != MMSYSERR_NOERROR ) {\n        midiInClose( data->inHandle );\n        errorString_ = \"MidiInWinMM::openPort: error closing Windows MM MIDI input port (midiInUnprepareHeader).\";\n        RtMidi::error( RtError::DRIVER_ERROR, errorString_ );\n      }\n    }\n\n    midiInClose( data->inHandle );\n    connected_ = false;\n  }\n}\n\nunsigned int MidiInWinMM :: getPortCount()\n{\n  return midiInGetNumDevs();\n}\n\nstd::string MidiInWinMM :: getPortName( unsigned int portNumber )\n{\n  std::string stringName;\n  unsigned int nDevices = midiInGetNumDevs();\n  if ( portNumber >= nDevices ) {\n    std::ostringstream ost;\n    ost << \"MidiInWinMM::getPortName: the 'portNumber' argument (\" << portNumber << \") is invalid.\";\n    errorString_ = ost.str();\n    //RtMidi::error( RtError::INVALID_PARAMETER, errorString_ );\n    RtMidi::error( RtError::WARNING, errorString_ );\n    return stringName;\n  }\n\n  MIDIINCAPS deviceCaps;\n  midiInGetDevCaps( portNumber, &deviceCaps, sizeof(MIDIINCAPS));\n\n#if defined( UNICODE ) || defined( _UNICODE )\n  int length = WideCharToMultiByte(CP_UTF8, 0, deviceCaps.szPname, -1, NULL, 0, NULL, NULL);\n  stringName.assign( length, 0 );\n  length = WideCharToMultiByte(CP_UTF8, 0, deviceCaps.szPname, wcslen(deviceCaps.szPname), &stringName[0], length, NULL, NULL);\n#else\n  stringName = std::string( deviceCaps.szPname );\n#endif\n\n  // Next lines added to add the portNumber to the name so that \n  // the device's names are sure to be listed with individual names\n  // even when they have the same brand name\n  std::ostringstream os;\n  os << \" \";\n  os << portNumber;\n  stringName += os.str();\n\n  return stringName;\n}\n\n//*********************************************************************//\n//  API: Windows MM\n//  Class Definitions: MidiOutWinMM\n//*********************************************************************//\n\nMidiOutWinMM :: MidiOutWinMM( const std::string clientName ) : MidiOutApi()\n{\n  initialize( clientName );\n}\n\nMidiOutWinMM :: ~MidiOutWinMM()\n{\n  // Close a connection if it exists.\n  closePort();\n\n  // Cleanup.\n  WinMidiData *data = static_cast<WinMidiData *> (apiData_);\n  delete data;\n}\n\nvoid MidiOutWinMM :: initialize( const std::string& /*clientName*/ )\n{\n  // We'll issue a warning here if no devices are available but not\n  // throw an error since the user can plug something in later.\n  unsigned int nDevices = midiOutGetNumDevs();\n  if ( nDevices == 0 ) {\n    errorString_ = \"MidiOutWinMM::initialize: no MIDI output devices currently available.\";\n    RtMidi::error( RtError::WARNING, errorString_ );\n  }\n\n  // Save our api-specific connection information.\n  WinMidiData *data = (WinMidiData *) new WinMidiData;\n  apiData_ = (void *) data;\n}\n\nunsigned int MidiOutWinMM :: getPortCount()\n{\n  return midiOutGetNumDevs();\n}\n\nstd::string MidiOutWinMM :: getPortName( unsigned int portNumber )\n{\n  std::string stringName;\n  unsigned int nDevices = midiOutGetNumDevs();\n  if ( portNumber >= nDevices ) {\n    std::ostringstream ost;\n    ost << \"MidiOutWinMM::getPortName: the 'portNumber' argument (\" << portNumber << \") is invalid.\";\n    errorString_ = ost.str();\n    //RtMidi::error( RtError::INVALID_PARAMETER, errorString_ );\n    RtMidi::error( RtError::WARNING, errorString_ );\n    return stringName;\n  }\n\n  MIDIOUTCAPS deviceCaps;\n  midiOutGetDevCaps( portNumber, &deviceCaps, sizeof(MIDIOUTCAPS));\n\n#if defined( UNICODE ) || defined( _UNICODE )\n  int length = WideCharToMultiByte(CP_UTF8, 0, deviceCaps.szPname, -1, NULL, 0, NULL, NULL);\n  stringName.assign( length, 0 );\n  length = WideCharToMultiByte(CP_UTF8, 0, deviceCaps.szPname, wcslen(deviceCaps.szPname), &stringName[0], length, NULL, NULL);\n#else\n  stringName = std::string( deviceCaps.szPname );\n#endif\n\n  return stringName;\n}\n\nvoid MidiOutWinMM :: openPort( unsigned int portNumber, const std::string /*portName*/ )\n{\n  if ( connected_ ) {\n    errorString_ = \"MidiOutWinMM::openPort: a valid connection already exists!\";\n    RtMidi::error( RtError::WARNING, errorString_ );\n    return;\n  }\n\n  unsigned int nDevices = midiOutGetNumDevs();\n  if (nDevices < 1) {\n    errorString_ = \"MidiOutWinMM::openPort: no MIDI output destinations found!\";\n    RtMidi::error( RtError::NO_DEVICES_FOUND, errorString_ );\n  }\n\n  std::ostringstream ost;\n  if ( portNumber >= nDevices ) {\n    ost << \"MidiOutWinMM::openPort: the 'portNumber' argument (\" << portNumber << \") is invalid.\";\n    errorString_ = ost.str();\n    RtMidi::error( RtError::INVALID_PARAMETER, errorString_ );\n  }\n\n  WinMidiData *data = static_cast<WinMidiData *> (apiData_);\n  MMRESULT result = midiOutOpen( &data->outHandle,\n                                 portNumber,\n                                 (DWORD)NULL,\n                                 (DWORD)NULL,\n                                 CALLBACK_NULL );\n  if ( result != MMSYSERR_NOERROR ) {\n    errorString_ = \"MidiOutWinMM::openPort: error creating Windows MM MIDI output port.\";\n    RtMidi::error( RtError::DRIVER_ERROR, errorString_ );\n  }\n\n  connected_ = true;\n}\n\nvoid MidiOutWinMM :: closePort( void )\n{\n  if ( connected_ ) {\n    WinMidiData *data = static_cast<WinMidiData *> (apiData_);\n    midiOutReset( data->outHandle );\n    midiOutClose( data->outHandle );\n    connected_ = false;\n  }\n}\n\nvoid MidiOutWinMM :: openVirtualPort( std::string portName )\n{\n  // This function cannot be implemented for the Windows MM MIDI API.\n  errorString_ = \"MidiOutWinMM::openVirtualPort: cannot be implemented in Windows MM MIDI API!\";\n  RtMidi::error( RtError::WARNING, errorString_ );\n}\n\nvoid MidiOutWinMM :: sendMessage( std::vector<unsigned char> *message )\n{\n  unsigned int nBytes = static_cast<unsigned int>(message->size());\n  if ( nBytes == 0 ) {\n    errorString_ = \"MidiOutWinMM::sendMessage: message argument is empty!\";\n    RtMidi::error( RtError::WARNING, errorString_ );\n    return;\n  }\n\n  MMRESULT result;\n  WinMidiData *data = static_cast<WinMidiData *> (apiData_);\n  if ( message->at(0) == 0xF0 ) { // Sysex message\n\n    // Allocate buffer for sysex data.\n    char *buffer = (char *) malloc( nBytes );\n    if ( buffer == NULL ) {\n      errorString_ = \"MidiOutWinMM::sendMessage: error allocating sysex message memory!\";\n      RtMidi::error( RtError::MEMORY_ERROR, errorString_ );\n    }\n\n    // Copy data to buffer.\n    for ( unsigned int i=0; i<nBytes; ++i ) buffer[i] = message->at(i);\n\n    // Create and prepare MIDIHDR structure.\n    MIDIHDR sysex;\n    sysex.lpData = (LPSTR) buffer;\n    sysex.dwBufferLength = nBytes;\n    sysex.dwFlags = 0;\n    result = midiOutPrepareHeader( data->outHandle,  &sysex, sizeof(MIDIHDR) ); \n    if ( result != MMSYSERR_NOERROR ) {\n      free( buffer );\n      errorString_ = \"MidiOutWinMM::sendMessage: error preparing sysex header.\";\n      RtMidi::error( RtError::DRIVER_ERROR, errorString_ );\n    }\n\n    // Send the message.\n    result = midiOutLongMsg( data->outHandle, &sysex, sizeof(MIDIHDR) );\n    if ( result != MMSYSERR_NOERROR ) {\n      free( buffer );\n      errorString_ = \"MidiOutWinMM::sendMessage: error sending sysex message.\";\n      RtMidi::error( RtError::DRIVER_ERROR, errorString_ );\n    }\n\n    // Unprepare the buffer and MIDIHDR.\n    while ( MIDIERR_STILLPLAYING == midiOutUnprepareHeader( data->outHandle, &sysex, sizeof (MIDIHDR) ) ) Sleep( 1 );\n    free( buffer );\n\n  }\n  else { // Channel or system message.\n\n    // Make sure the message size isn't too big.\n    if ( nBytes > 3 ) {\n      errorString_ = \"MidiOutWinMM::sendMessage: message size is greater than 3 bytes (and not sysex)!\";\n      RtMidi::error( RtError::WARNING, errorString_ );\n      return;\n    }\n\n    // Pack MIDI bytes into double word.\n    DWORD packet;\n    unsigned char *ptr = (unsigned char *) &packet;\n    for ( unsigned int i=0; i<nBytes; ++i ) {\n      *ptr = message->at(i);\n      ++ptr;\n    }\n\n    // Send the message immediately.\n    result = midiOutShortMsg( data->outHandle, packet );\n    if ( result != MMSYSERR_NOERROR ) {\n      errorString_ = \"MidiOutWinMM::sendMessage: error sending MIDI message.\";\n      RtMidi::error( RtError::DRIVER_ERROR, errorString_ );\n    }\n  }\n}\n\n#endif  // __WINDOWS_MM__\n\n// *********************************************************************//\n// API: WINDOWS Kernel Streaming\n//\n// Written by Sebastien Alaiwan, 2012.\n//\n// NOTE BY GARY: much of the KS-specific code below probably should go in a separate file.\n//\n// *********************************************************************//\n\n#if defined(__WINDOWS_KS__)\n\n#include <string>\n#include <vector>\n#include <memory>\n#include <stdexcept>\n#include <sstream>\n#include <windows.h>\n#include <setupapi.h>\n#include <mmsystem.h>\n\n#include \"ks.h\"\n#include \"ksmedia.h\"\n\n#define INSTANTIATE_GUID(a) GUID const a = { STATIC_ ## a }\n\nINSTANTIATE_GUID(GUID_NULL);\nINSTANTIATE_GUID(KSPROPSETID_Pin);\nINSTANTIATE_GUID(KSPROPSETID_Connection);\nINSTANTIATE_GUID(KSPROPSETID_Topology);\nINSTANTIATE_GUID(KSINTERFACESETID_Standard);\nINSTANTIATE_GUID(KSMEDIUMSETID_Standard);\nINSTANTIATE_GUID(KSDATAFORMAT_TYPE_MUSIC);\nINSTANTIATE_GUID(KSDATAFORMAT_SUBTYPE_MIDI);\nINSTANTIATE_GUID(KSDATAFORMAT_SPECIFIER_NONE);\n\n#undef INSTANTIATE_GUID\n\ntypedef std::basic_string<TCHAR> tstring;\n\ninline bool IsValid(HANDLE handle)\n{\n  return handle != NULL && handle != INVALID_HANDLE_VALUE;\n}\n\nclass ComException : public std::runtime_error\n{\nprivate:\n  static std::string MakeString(std::string const& s, HRESULT hr)\n  {\n    std::stringstream ss;\n    ss << \"(error 0x\" << std::hex << hr << \")\";\n    return s + ss.str();\n  }\n\npublic:\n  ComException(std::string const& s, HRESULT hr) :\n    std::runtime_error(MakeString(s, hr))\n  {\n  }\n};\n\ntemplate<typename TFilterType>\nclass CKsEnumFilters\n{\npublic:\n  ~CKsEnumFilters()\n  {\n    DestroyLists();\n  }\n\n  void EnumFilters(GUID const* categories, size_t numCategories)\n  {\n    DestroyLists();\n\n    if (categories == 0)\n      throw std::runtime_error(\"CKsEnumFilters: invalid argument\");\n\n    // Get a handle to the device set specified by the guid\n    HDEVINFO hDevInfo = ::SetupDiGetClassDevs(&categories[0], NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);\n    if (!IsValid(hDevInfo))\n      throw std::runtime_error(\"CKsEnumFilters: no devices found\");\n\n    // Loop through members of the set and get details for each\n    for (int iClassMember=0;;iClassMember++) {\n      try {\n        SP_DEVICE_INTERFACE_DATA DID;\n        DID.cbSize = sizeof(DID);\n        DID.Reserved = 0;\n\n        bool fRes = ::SetupDiEnumDeviceInterfaces(hDevInfo, NULL, &categories[0], iClassMember, &DID);\n        if (!fRes)\n          break;\n\n        // Get filter friendly name\n        HKEY hRegKey = ::SetupDiOpenDeviceInterfaceRegKey(hDevInfo, &DID, 0, KEY_READ);\n        if (hRegKey == INVALID_HANDLE_VALUE)\n          throw std::runtime_error(\"CKsEnumFilters: interface has no registry\");\n\n        char friendlyName[256];\n        DWORD dwSize = sizeof friendlyName;\n        LONG lval = ::RegQueryValueEx(hRegKey, TEXT(\"FriendlyName\"), NULL, NULL, (LPBYTE)friendlyName, &dwSize);\n        ::RegCloseKey(hRegKey);\n        if (lval != ERROR_SUCCESS)\n          throw std::runtime_error(\"CKsEnumFilters: interface has no friendly name\");\n\n        // Get details for the device registered in this class\n        DWORD const cbItfDetails = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA) + MAX_PATH * sizeof(WCHAR);\n        std::vector<BYTE> buffer(cbItfDetails);\n\n        SP_DEVICE_INTERFACE_DETAIL_DATA* pDevInterfaceDetails = reinterpret_cast<SP_DEVICE_INTERFACE_DETAIL_DATA*>(&buffer[0]);\n        pDevInterfaceDetails->cbSize = sizeof(*pDevInterfaceDetails);\n\n        SP_DEVINFO_DATA DevInfoData;\n        DevInfoData.cbSize = sizeof(DevInfoData);\n        DevInfoData.Reserved = 0;\n\n        fRes = ::SetupDiGetDeviceInterfaceDetail(hDevInfo, &DID, pDevInterfaceDetails, cbItfDetails, NULL, &DevInfoData);\n        if (!fRes)\n          throw std::runtime_error(\"CKsEnumFilters: could not get interface details\");\n\n        // check additional category guids which may (or may not) have been supplied\n        for (size_t i=1; i < numCategories; ++i) {\n          SP_DEVICE_INTERFACE_DATA DIDAlias;\n          DIDAlias.cbSize = sizeof(DIDAlias);\n          DIDAlias.Reserved = 0;\n\n          fRes = ::SetupDiGetDeviceInterfaceAlias(hDevInfo, &DID, &categories[i], &DIDAlias);\n          if (!fRes)\n            throw std::runtime_error(\"CKsEnumFilters: could not get interface alias\");\n\n          // Check if the this interface alias is enabled.\n          if (!DIDAlias.Flags || (DIDAlias.Flags & SPINT_REMOVED))\n            throw std::runtime_error(\"CKsEnumFilters: interface alias is not enabled\");\n        }\n\n        std::auto_ptr<TFilterType> pFilter(new TFilterType(pDevInterfaceDetails->DevicePath, friendlyName));\n\n        pFilter->Instantiate();\n        pFilter->FindMidiPins();\n        pFilter->Validate();\n\n        m_Filters.push_back(pFilter.release());\n      }\n      catch (std::runtime_error const& e) {\n      }\n    }\n\n    ::SetupDiDestroyDeviceInfoList(hDevInfo);\n  }\n\nprivate:\n  void DestroyLists()\n  {\n    for (size_t i=0;i < m_Filters.size();++i)\n      delete m_Filters[i];\n    m_Filters.clear();\n  }\n\npublic:\n  // TODO: make this private.\n  std::vector<TFilterType*> m_Filters;\n};\n\nclass CKsObject\n{\npublic:\n  CKsObject(HANDLE handle) : m_handle(handle)\n  {\n  }\n\nprotected:\n  HANDLE m_handle;\n\n  void SetProperty(REFGUID guidPropertySet, ULONG nProperty, void* pvValue, ULONG cbValue)\n  {\n    KSPROPERTY ksProperty;\n    memset(&ksProperty, 0, sizeof ksProperty);\n    ksProperty.Set = guidPropertySet;\n    ksProperty.Id = nProperty;\n    ksProperty.Flags = KSPROPERTY_TYPE_SET;\n\n    HRESULT hr = DeviceIoControlKsProperty(ksProperty, pvValue, cbValue);\n    if (FAILED(hr))\n      throw ComException(\"CKsObject::SetProperty: could not set property\", hr);\n  }\n\nprivate:\n\n  HRESULT DeviceIoControlKsProperty(KSPROPERTY& ksProperty, void* pvValue, ULONG cbValue)\n  {\n    ULONG ulReturned;\n    return ::DeviceIoControl(\n             m_handle,\n             IOCTL_KS_PROPERTY,\n             &ksProperty,\n             sizeof(ksProperty),\n             pvValue,\n             cbValue,\n             &ulReturned,\n             NULL);\n  }\n};\n\nclass CKsPin;\n\nclass CKsFilter : public CKsObject\n{\n  friend class CKsPin;\n\npublic:\n  CKsFilter(tstring const& name, std::string const& sFriendlyName);\n  virtual ~CKsFilter();\n\n  virtual void Instantiate();\n\n  template<typename T>\n  T GetPinProperty(ULONG nPinId, ULONG nProperty)\n  {\n    ULONG ulReturned = 0;\n    T value;\n\n    KSP_PIN ksPProp;\n    ksPProp.Property.Set = KSPROPSETID_Pin;\n    ksPProp.Property.Id = nProperty;\n    ksPProp.Property.Flags = KSPROPERTY_TYPE_GET;\n    ksPProp.PinId = nPinId;\n    ksPProp.Reserved = 0;\n\n    HRESULT hr = ::DeviceIoControl(\n      m_handle,\n      IOCTL_KS_PROPERTY,\n      &ksPProp,\n      sizeof(KSP_PIN),\n      &value,\n      sizeof(value),\n      &ulReturned,\n      NULL);\n    if (FAILED(hr))\n      throw ComException(\"CKsFilter::GetPinProperty: failed to retrieve property\", hr);\n\n    return value;\n  }\n\n  void GetPinPropertyMulti(ULONG nPinId, REFGUID guidPropertySet, ULONG nProperty, PKSMULTIPLE_ITEM* ppKsMultipleItem)\n  {\n    HRESULT hr;\n\n    KSP_PIN ksPProp;\n    ksPProp.Property.Set = guidPropertySet;\n    ksPProp.Property.Id = nProperty;\n    ksPProp.Property.Flags = KSPROPERTY_TYPE_GET;\n    ksPProp.PinId = nPinId;\n    ksPProp.Reserved = 0;\n\n    ULONG cbMultipleItem = 0;\n    hr = ::DeviceIoControl(m_handle,\n        IOCTL_KS_PROPERTY,\n        &ksPProp.Property,\n        sizeof(KSP_PIN),\n        NULL,\n        0,\n        &cbMultipleItem,\n        NULL);\n    if (FAILED(hr))\n      throw ComException(\"CKsFilter::GetPinPropertyMulti: cannot get property\", hr);\n\n    *ppKsMultipleItem = (PKSMULTIPLE_ITEM) new BYTE[cbMultipleItem];\n\n    ULONG ulReturned = 0;\n    hr = ::DeviceIoControl(\n        m_handle,\n        IOCTL_KS_PROPERTY,\n        &ksPProp,\n        sizeof(KSP_PIN),\n        (PVOID)*ppKsMultipleItem,\n        cbMultipleItem,\n        &ulReturned,\n        NULL);\n    if (FAILED(hr))\n      throw ComException(\"CKsFilter::GetPinPropertyMulti: cannot get property\", hr);\n  }\n\n  std::string const& GetFriendlyName() const\n  {\n    return m_sFriendlyName;\n  }\n\nprotected:\n\n  std::vector<CKsPin*> m_Pins; // this list owns the pins.\n\n  std::vector<CKsPin*> m_RenderPins;\n  std::vector<CKsPin*> m_CapturePins;\n\nprivate:\n  std::string const m_sFriendlyName; // friendly name eg \"Virus TI Synth\"\n  tstring const m_sName; // Filter path, eg \"\\\\?\\usb#vid_133e&pid_0815...\\vtimidi02\"\n};\n\nclass CKsPin : public CKsObject\n{\npublic:\n  CKsPin(CKsFilter* pFilter, ULONG nId);\n  virtual ~CKsPin();\n\n  virtual void Instantiate();\n\n  void ClosePin();\n\n  void SetState(KSSTATE ksState);\n\n  void WriteData(KSSTREAM_HEADER* pKSSTREAM_HEADER, OVERLAPPED* pOVERLAPPED);\n  void ReadData(KSSTREAM_HEADER* pKSSTREAM_HEADER, OVERLAPPED* pOVERLAPPED);\n\n  KSPIN_DATAFLOW GetDataFlow() const\n  {\n    return m_DataFlow;\n  }\n\n  bool IsSink() const\n  {\n    return m_Communication == KSPIN_COMMUNICATION_SINK\n      || m_Communication == KSPIN_COMMUNICATION_BOTH;\n  }\n\n\nprotected:\n  PKSPIN_CONNECT m_pKsPinConnect;    // creation parameters of pin\n  CKsFilter* const m_pFilter;\n\n  ULONG m_cInterfaces;\n  PKSIDENTIFIER m_pInterfaces;\n  PKSMULTIPLE_ITEM m_pmiInterfaces;\n\n  ULONG m_cMediums;\n  PKSIDENTIFIER m_pMediums;\n  PKSMULTIPLE_ITEM m_pmiMediums;\n\n  ULONG m_cDataRanges;\n  PKSDATARANGE m_pDataRanges;\n  PKSMULTIPLE_ITEM m_pmiDataRanges;\n\n  KSPIN_DATAFLOW m_DataFlow;\n  KSPIN_COMMUNICATION m_Communication;\n};\n\nCKsFilter::CKsFilter(tstring const& sName, std::string const& sFriendlyName) :\n  CKsObject(INVALID_HANDLE_VALUE),\n  m_sFriendlyName(sFriendlyName),\n  m_sName(sName)\n{\n  if (sName.empty())\n    throw std::runtime_error(\"CKsFilter::CKsFilter: name can't be empty\");\n}\n\nCKsFilter::~CKsFilter()\n{\n  for (size_t i=0;i < m_Pins.size();++i)\n    delete m_Pins[i];\n\n  if (IsValid(m_handle))\n    ::CloseHandle(m_handle);\n}\n\nvoid CKsFilter::Instantiate()\n{\n  m_handle = CreateFile(\n    m_sName.c_str(),\n    GENERIC_READ | GENERIC_WRITE,\n    0,\n    NULL,\n    OPEN_EXISTING,\n    FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,\n    NULL);\n\n  if (!IsValid(m_handle))\n  {\n    DWORD const dwError = GetLastError();\n    throw ComException(\"CKsFilter::Instantiate: can't open driver\", HRESULT_FROM_WIN32(dwError));\n  }\n}\n\nCKsPin::CKsPin(CKsFilter* pFilter, ULONG PinId) :\n  CKsObject(INVALID_HANDLE_VALUE),\n  m_pKsPinConnect(NULL),\n  m_pFilter(pFilter)\n{\n  m_Communication = m_pFilter->GetPinProperty<KSPIN_COMMUNICATION>(PinId, KSPROPERTY_PIN_COMMUNICATION);\n  m_DataFlow = m_pFilter->GetPinProperty<KSPIN_DATAFLOW>(PinId, KSPROPERTY_PIN_DATAFLOW);\n\n  // Interfaces\n  m_pFilter->GetPinPropertyMulti(\n      PinId,\n      KSPROPSETID_Pin,\n      KSPROPERTY_PIN_INTERFACES,\n      &m_pmiInterfaces);\n\n  m_cInterfaces = m_pmiInterfaces->Count;\n  m_pInterfaces = (PKSPIN_INTERFACE)(m_pmiInterfaces + 1);\n\n  // Mediums\n  m_pFilter->GetPinPropertyMulti(\n      PinId,\n      KSPROPSETID_Pin,\n      KSPROPERTY_PIN_MEDIUMS,\n      &m_pmiMediums);\n\n  m_cMediums = m_pmiMediums->Count;\n  m_pMediums = (PKSPIN_MEDIUM)(m_pmiMediums + 1);\n\n  // Data ranges\n  m_pFilter->GetPinPropertyMulti(\n      PinId,\n      KSPROPSETID_Pin,\n      KSPROPERTY_PIN_DATARANGES,\n      &m_pmiDataRanges);\n\n  m_cDataRanges = m_pmiDataRanges->Count;\n  m_pDataRanges = (PKSDATARANGE)(m_pmiDataRanges + 1);\n}\n\nCKsPin::~CKsPin()\n{\n  ClosePin();\n\n  delete[] (BYTE*)m_pKsPinConnect;\n  delete[] (BYTE*)m_pmiDataRanges;\n  delete[] (BYTE*)m_pmiInterfaces;\n  delete[] (BYTE*)m_pmiMediums;\n}\n\nvoid CKsPin::ClosePin()\n{\n  if (IsValid(m_handle)) {\n    SetState(KSSTATE_STOP);\n    ::CloseHandle(m_handle);\n  }\n  m_handle = INVALID_HANDLE_VALUE;\n}\n\nvoid CKsPin::SetState(KSSTATE ksState)\n{\n  SetProperty(KSPROPSETID_Connection, KSPROPERTY_CONNECTION_STATE, &ksState, sizeof(ksState));\n}\n\nvoid CKsPin::Instantiate()\n{\n  if (!m_pKsPinConnect)\n    throw std::runtime_error(\"CKsPin::Instanciate: abstract pin\");\n\n  DWORD const dwResult = KsCreatePin(m_pFilter->m_handle, m_pKsPinConnect, GENERIC_WRITE | GENERIC_READ, &m_handle);\n  if (dwResult != ERROR_SUCCESS)\n    throw ComException(\"CKsMidiCapFilter::CreateRenderPin: Pin instanciation failed\", HRESULT_FROM_WIN32(dwResult));\n}\n\nvoid CKsPin::WriteData(KSSTREAM_HEADER* pKSSTREAM_HEADER, OVERLAPPED* pOVERLAPPED)\n{\n  DWORD cbWritten;\n  BOOL fRes = ::DeviceIoControl(\n    m_handle,\n    IOCTL_KS_WRITE_STREAM,\n    NULL,\n    0,\n    pKSSTREAM_HEADER,\n    pKSSTREAM_HEADER->Size,\n    &cbWritten,\n    pOVERLAPPED);\n  if (!fRes) {\n    DWORD const dwError = GetLastError();\n    if (dwError != ERROR_IO_PENDING)\n      throw ComException(\"CKsPin::WriteData: DeviceIoControl failed\", HRESULT_FROM_WIN32(dwError));\n  }\n}\n\nvoid CKsPin::ReadData(KSSTREAM_HEADER* pKSSTREAM_HEADER, OVERLAPPED* pOVERLAPPED)\n{\n  DWORD cbReturned;\n  BOOL fRes = ::DeviceIoControl(\n    m_handle,\n    IOCTL_KS_READ_STREAM,\n    NULL,\n    0,\n    pKSSTREAM_HEADER,\n    pKSSTREAM_HEADER->Size,\n    &cbReturned,\n    pOVERLAPPED);\n  if (!fRes) {\n    DWORD const dwError = GetLastError();\n    if (dwError != ERROR_IO_PENDING)\n      throw ComException(\"CKsPin::ReadData: DeviceIoControl failed\", HRESULT_FROM_WIN32(dwError));\n  }\n}\n\nclass CKsMidiFilter : public CKsFilter\n{\npublic:\n  void FindMidiPins();\n\nprotected:\n  CKsMidiFilter(tstring const& sPath, std::string const& sFriendlyName);\n};\n\nclass CKsMidiPin : public CKsPin\n{\npublic:\n  CKsMidiPin(CKsFilter* pFilter, ULONG nId);\n};\n\nclass CKsMidiRenFilter : public CKsMidiFilter\n{\npublic:\n  CKsMidiRenFilter(tstring const& sPath, std::string const& sFriendlyName);\n  CKsMidiPin* CreateRenderPin();\n\n  void Validate()\n  {\n    if (m_RenderPins.empty())\n      throw std::runtime_error(\"Could not find a MIDI render pin\");\n  }\n};\n\nclass CKsMidiCapFilter : public CKsMidiFilter\n{\npublic:\n  CKsMidiCapFilter(tstring const& sPath, std::string const& sFriendlyName);\n  CKsMidiPin* CreateCapturePin();\n\n  void Validate()\n  {\n    if (m_CapturePins.empty())\n      throw std::runtime_error(\"Could not find a MIDI capture pin\");\n  }\n};\n\nCKsMidiFilter::CKsMidiFilter(tstring const& sPath, std::string const& sFriendlyName) :\n  CKsFilter(sPath, sFriendlyName)\n{\n}\n\nvoid CKsMidiFilter::FindMidiPins()\n{\n  ULONG numPins = GetPinProperty<ULONG>(0, KSPROPERTY_PIN_CTYPES);\n\n  for (ULONG iPin = 0; iPin < numPins; ++iPin) {\n    try {\n      KSPIN_COMMUNICATION com = GetPinProperty<KSPIN_COMMUNICATION>(iPin, KSPROPERTY_PIN_COMMUNICATION);\n      if (com != KSPIN_COMMUNICATION_SINK && com != KSPIN_COMMUNICATION_BOTH)\n        throw std::runtime_error(\"Unknown pin communication value\");\n\n      m_Pins.push_back(new CKsMidiPin(this, iPin));\n    }\n    catch (std::runtime_error const&) {\n      // pin instanciation has failed, continue to the next pin.\n    }\n  }\n\n  m_RenderPins.clear();\n  m_CapturePins.clear();\n\n  for (size_t i = 0; i < m_Pins.size(); ++i) {\n    CKsPin* const pPin = m_Pins[i];\n\n    if (pPin->IsSink()) {\n      if (pPin->GetDataFlow() == KSPIN_DATAFLOW_IN)\n        m_RenderPins.push_back(pPin);\n      else\n        m_CapturePins.push_back(pPin);\n    }\n  }\n\n  if (m_RenderPins.empty() && m_CapturePins.empty())\n    throw std::runtime_error(\"No valid pins found on the filter.\");\n}\n\nCKsMidiRenFilter::CKsMidiRenFilter(tstring const& sPath, std::string const& sFriendlyName) :\n  CKsMidiFilter(sPath, sFriendlyName)\n{\n}\n\nCKsMidiPin* CKsMidiRenFilter::CreateRenderPin()\n{\n  if (m_RenderPins.empty())\n    throw std::runtime_error(\"Could not find a MIDI render pin\");\n\n  CKsMidiPin* pPin = (CKsMidiPin*)m_RenderPins[0];\n  pPin->Instantiate();\n  return pPin;\n}\n\nCKsMidiCapFilter::CKsMidiCapFilter(tstring const& sPath, std::string const& sFriendlyName) :\n  CKsMidiFilter(sPath, sFriendlyName)\n{\n}\n\nCKsMidiPin* CKsMidiCapFilter::CreateCapturePin()\n{\n  if (m_CapturePins.empty())\n    throw std::runtime_error(\"Could not find a MIDI capture pin\");\n\n  CKsMidiPin* pPin = (CKsMidiPin*)m_CapturePins[0];\n  pPin->Instantiate();\n  return pPin;\n}\n\nCKsMidiPin::CKsMidiPin(CKsFilter* pFilter, ULONG nId) :\n  CKsPin(pFilter, nId)\n{\n  DWORD const cbPinCreateSize = sizeof(KSPIN_CONNECT) + sizeof(KSDATAFORMAT);\n  m_pKsPinConnect = (PKSPIN_CONNECT) new BYTE[cbPinCreateSize];\n\n  m_pKsPinConnect->Interface.Set = KSINTERFACESETID_Standard;\n  m_pKsPinConnect->Interface.Id = KSINTERFACE_STANDARD_STREAMING;\n  m_pKsPinConnect->Interface.Flags = 0;\n  m_pKsPinConnect->Medium.Set = KSMEDIUMSETID_Standard;\n  m_pKsPinConnect->Medium.Id = KSMEDIUM_TYPE_ANYINSTANCE;\n  m_pKsPinConnect->Medium.Flags = 0;\n  m_pKsPinConnect->PinId = nId;\n  m_pKsPinConnect->PinToHandle = NULL;\n  m_pKsPinConnect->Priority.PriorityClass = KSPRIORITY_NORMAL;\n  m_pKsPinConnect->Priority.PrioritySubClass = 1;\n\n  // point m_pDataFormat to just after the pConnect struct\n  KSDATAFORMAT* m_pDataFormat = (KSDATAFORMAT*)(m_pKsPinConnect + 1);\n  m_pDataFormat->FormatSize = sizeof(KSDATAFORMAT);\n  m_pDataFormat->Flags = 0;\n  m_pDataFormat->SampleSize = 0;\n  m_pDataFormat->Reserved = 0;\n  m_pDataFormat->MajorFormat = GUID(KSDATAFORMAT_TYPE_MUSIC);\n  m_pDataFormat->SubFormat = GUID(KSDATAFORMAT_SUBTYPE_MIDI);\n  m_pDataFormat->Specifier = GUID(KSDATAFORMAT_SPECIFIER_NONE);\n\n  bool hasStdStreamingInterface = false;\n  bool hasStdStreamingMedium = false;\n\n  for ( ULONG i = 0; i < m_cInterfaces; i++ ) {\n    if (m_pInterfaces[i].Set == KSINTERFACESETID_Standard\n        && m_pInterfaces[i].Id == KSINTERFACE_STANDARD_STREAMING)\n      hasStdStreamingInterface = true;\n  }\n\n  for (ULONG i = 0; i < m_cMediums; i++) {\n    if (m_pMediums[i].Set == KSMEDIUMSETID_Standard\n        && m_pMediums[i].Id == KSMEDIUM_STANDARD_DEVIO)\n      hasStdStreamingMedium = true;\n  }\n\n  if (!hasStdStreamingInterface) // No standard streaming interfaces on the pin\n    throw std::runtime_error(\"CKsMidiPin::CKsMidiPin: no standard streaming interface\");\n\n  if (!hasStdStreamingMedium) // No standard streaming mediums on the pin\n    throw std::runtime_error(\"CKsMidiPin::CKsMidiPin: no standard streaming medium\");\n\n  bool hasMidiDataRange = false;\n\n  BYTE const* pDataRangePtr = reinterpret_cast<BYTE const*>(m_pDataRanges);\n\n  for (ULONG i = 0; i < m_cDataRanges; ++i) {\n    KSDATARANGE const* pDataRange = reinterpret_cast<KSDATARANGE const*>(pDataRangePtr);\n\n    if (pDataRange->SubFormat == KSDATAFORMAT_SUBTYPE_MIDI) {\n      hasMidiDataRange = true;\n      break;\n    }\n\n    pDataRangePtr += pDataRange->FormatSize;\n  }\n\n  if (!hasMidiDataRange) // No MIDI dataranges on the pin\n    throw std::runtime_error(\"CKsMidiPin::CKsMidiPin: no MIDI datarange\");\n}\n\n\nstruct WindowsKsData\n{\n  WindowsKsData() : m_pPin(NULL), m_Buffer(1024), m_hInputThread(NULL)\n  {\n    memset(&overlapped, 0, sizeof(OVERLAPPED));\n    m_hExitEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);\n    overlapped.hEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);\n    m_hInputThread = NULL;\n  }\n\n  ~WindowsKsData()\n  {\n    ::CloseHandle(overlapped.hEvent);\n    ::CloseHandle(m_hExitEvent);\n  }\n\n  OVERLAPPED overlapped;\n  CKsPin* m_pPin;\n  std::vector<unsigned char> m_Buffer;\n  std::auto_ptr<CKsEnumFilters<CKsMidiCapFilter> > m_pCaptureEnum;\n  std::auto_ptr<CKsEnumFilters<CKsMidiRenFilter> > m_pRenderEnum;\n  HANDLE m_hInputThread;\n  HANDLE m_hExitEvent;\n};\n\n// *********************************************************************//\n// API: WINDOWS Kernel Streaming\n// Class Definitions: MidiInWinKS\n// *********************************************************************//\n\nDWORD WINAPI midiKsInputThread(VOID* pUser)\n{\n  MidiInApi::RtMidiInData* data = static_cast<MidiInApi::RtMidiInData*>(pUser);\n  WindowsKsData* apiData = static_cast<WindowsKsData*>(data->apiData);\n\n  HANDLE hEvents[] = { apiData->overlapped.hEvent, apiData->m_hExitEvent };\n\n  while ( true ) {\n    KSSTREAM_HEADER packet;\n    memset(&packet, 0, sizeof packet);\n    packet.Size = sizeof(KSSTREAM_HEADER);\n    packet.PresentationTime.Time = 0;\n    packet.PresentationTime.Numerator = 1;\n    packet.PresentationTime.Denominator = 1;\n    packet.Data = &apiData->m_Buffer[0];\n    packet.DataUsed = 0;\n    packet.FrameExtent = apiData->m_Buffer.size();\n    apiData->m_pPin->ReadData(&packet, &apiData->overlapped);\n\n    DWORD dwRet = ::WaitForMultipleObjects(2, hEvents, FALSE, INFINITE);\n\n    if ( dwRet == WAIT_OBJECT_0 ) {\n      // parse packet\n      unsigned char* pData = (unsigned char*)packet.Data;\n      unsigned int iOffset = 0;\n\n      while ( iOffset < packet.DataUsed ) {\n        KSMUSICFORMAT* pMusic = (KSMUSICFORMAT*)&pData[iOffset];\n        iOffset += sizeof(KSMUSICFORMAT);\n\n        MidiInApi::MidiMessage message;\n        message.timeStamp = 0;\n        for(size_t i=0;i < pMusic->ByteCount;++i)\n          message.bytes.push_back(pData[iOffset+i]);\n\n        if ( data->usingCallback ) {\n          RtMidiIn::RtMidiCallback callback = (RtMidiIn::RtMidiCallback)data->userCallback;\n          callback(message.timeStamp, &message.bytes, data->userData);\n        }\n        else {\n          // As long as we haven't reached our queue size limit, push the message.\n          if ( data->queue.size < data->queue.ringSize ) {\n            data->queue.ring[data->queue.back++] = message;\n            if(data->queue.back == data->queue.ringSize)\n              data->queue.back = 0;\n            data->queue.size++;\n          }\n          else\n            std::cerr << \"\\nRtMidiIn: message queue limit reached!!\\n\\n\";\n        }\n\n        iOffset += pMusic->ByteCount;\n\n        // re-align on 32 bits\n        if ( iOffset % 4 != 0 )\n          iOffset += (4 - iOffset % 4);\n      }\n    }\n    else\n      break;\n  }\n  return 0;\n}\n\nMidiInWinKS :: MidiInWinKS( const std::string clientName, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit )\n{\n  initialize( clientName );\n}\n\nvoid MidiInWinKS :: initialize( const std::string& clientName )\n{\n  WindowsKsData* data = new WindowsKsData;\n  apiData_ = (void*)data;\n  inputData_.apiData = data;\n\n  GUID const aguidEnumCats[] =\n  {\n    { STATIC_KSCATEGORY_AUDIO }, { STATIC_KSCATEGORY_CAPTURE }\n  };\n  data->m_pCaptureEnum.reset(new CKsEnumFilters<CKsMidiCapFilter> );\n  data->m_pCaptureEnum->EnumFilters(aguidEnumCats, 2);\n}\n\nMidiInWinKS :: ~MidiInWinKS()\n{\n  WindowsKsData* data = static_cast<WindowsKsData*>(apiData_);\n  try {\n    if ( data->m_pPin )\n      closePort();\n  }\n  catch(...) {\n  }\n\n  delete data;\n}\n\nvoid MidiInWinKS :: openPort( unsigned int portNumber, const std::string portName )\n{\n  WindowsKsData* data = static_cast<WindowsKsData*>(apiData_);\n\n  if ( portNumber < 0 || portNumber >= data->m_pCaptureEnum->m_Filters.size() ) {\n    std::stringstream ost;\n    ost << \"MidiInWinKS::openPort: the 'portNumber' argument (\" << portNumber << \") is invalid.\";\n    errorString_ = ost.str();\n    RtMidi::error( RtError::WARNING, errorString_ );\n  }\n\n  CKsMidiCapFilter* pFilter = data->m_pCaptureEnum->m_Filters[portNumber];\n  data->m_pPin = pFilter->CreateCapturePin();\n\n  if ( data->m_pPin == NULL ) {\n    std::stringstream ost;\n    ost << \"MidiInWinKS::openPort: KS error opening port (could not create pin)\";\n    errorString_ = ost.str();\n    RtMidi::error( RtError::WARNING, errorString_ );\n  }\n\n  data->m_pPin->SetState(KSSTATE_RUN);\n\n  DWORD threadId;\n  data->m_hInputThread = ::CreateThread(NULL, 0, &midiKsInputThread, &inputData_, 0, &threadId);\n  if ( data->m_hInputThread == NULL ) {\n    std::stringstream ost;\n    ost << \"MidiInWinKS::initialize: Could not create input thread : Windows error \" << GetLastError() << std::endl;;\n    errorString_ = ost.str();\n    RtMidi::error( RtError::WARNING, errorString_ );\n  }\n\n  connected_ = true;\n}\n\nvoid MidiInWinKS :: openVirtualPort( const std::string portName )\n{\n  // This function cannot be implemented for the Windows KS MIDI API.\n  errorString_ = \"MidiInWinKS::openVirtualPort: cannot be implemented in Windows KS MIDI API!\";\n  RtMidi::error( RtError::WARNING, errorString_ );\n}\n\nunsigned int MidiInWinKS :: getPortCount()\n{\n  WindowsKsData* data = static_cast<WindowsKsData*>(apiData_);\n  return (unsigned int)data->m_pCaptureEnum->m_Filters.size();\n}\n\nstd::string MidiInWinKS :: getPortName(unsigned int portNumber)\n{\n  WindowsKsData* data = static_cast<WindowsKsData*>(apiData_);\n\n  if(portNumber < 0 || portNumber >= data->m_pCaptureEnum->m_Filters.size()) {\n    std::stringstream ost;\n    ost << \"MidiInWinKS::getPortName: the 'portNumber' argument (\" << portNumber << \") is invalid.\";\n    errorString_ = ost.str();\n    RtMidi::error( RtError::WARNING, errorString_ );\n  }\n\n  CKsMidiCapFilter* pFilter = data->m_pCaptureEnum->m_Filters[portNumber];\n  return pFilter->GetFriendlyName();\n}\n\nvoid MidiInWinKS :: closePort()\n{\n  WindowsKsData* data = static_cast<WindowsKsData*>(apiData_);\n  connected_ = false;\n\n  if(data->m_hInputThread) {\n    ::SignalObjectAndWait(data->m_hExitEvent, data->m_hInputThread, INFINITE, FALSE);\n    ::CloseHandle(data->m_hInputThread);\n  }\n\n  if(data->m_pPin) {\n    data->m_pPin->SetState(KSSTATE_PAUSE);\n    data->m_pPin->SetState(KSSTATE_STOP);\n    data->m_pPin->ClosePin();\n    data->m_pPin = NULL;\n  }\n}\n\n// *********************************************************************//\n// API: WINDOWS Kernel Streaming\n// Class Definitions: MidiOutWinKS\n// *********************************************************************//\n\nMidiOutWinKS :: MidiOutWinKS( const std::string clientName ) : MidiOutApi()\n{\n  initialize( clientName );\n}\n\nvoid MidiOutWinKS :: initialize( const std::string& clientName )\n{\n  WindowsKsData* data = new WindowsKsData;\n\n  data->m_pPin = NULL;\n  data->m_pRenderEnum.reset(new CKsEnumFilters<CKsMidiRenFilter> );\n  GUID const aguidEnumCats[] =\n  {\n    { STATIC_KSCATEGORY_AUDIO }, { STATIC_KSCATEGORY_RENDER }\n  };\n  data->m_pRenderEnum->EnumFilters(aguidEnumCats, 2);\n\n  apiData_ = (void*)data;\n}\n\nMidiOutWinKS :: ~MidiOutWinKS()\n{\n  // Close a connection if it exists.\n  closePort();\n\n  // Cleanup.\n  WindowsKsData* data = static_cast<WindowsKsData*>(apiData_);\n  delete data;\n}\n\nvoid MidiOutWinKS :: openPort( unsigned int portNumber, const std::string portName )\n{\n  WindowsKsData* data = static_cast<WindowsKsData*>(apiData_);\n\n  if(portNumber < 0 || portNumber >= data->m_pRenderEnum->m_Filters.size()) {\n    std::stringstream ost;\n    ost << \"MidiOutWinKS::openPort: the 'portNumber' argument (\" << portNumber << \") is invalid.\";\n    errorString_ = ost.str();\n    RtMidi::error( RtError::WARNING, errorString_ );\n  }\n\n  CKsMidiRenFilter* pFilter = data->m_pRenderEnum->m_Filters[portNumber];\n  data->m_pPin = pFilter->CreateRenderPin();\n\n  if(data->m_pPin == NULL) {\n    std::stringstream ost;\n    ost << \"MidiOutWinKS::openPort: KS error opening port (could not create pin)\";\n    errorString_ = ost.str();\n    RtMidi::error( RtError::WARNING, errorString_ );\n  }\n\n  data->m_pPin->SetState(KSSTATE_RUN);\n  connected_ = true;\n}\n\nvoid MidiOutWinKS :: openVirtualPort( const std::string portName )\n{\n  // This function cannot be implemented for the Windows KS MIDI API.\n  errorString_ = \"MidiOutWinKS::openVirtualPort: cannot be implemented in Windows KS MIDI API!\";\n  RtMidi::error( RtError::WARNING, errorString_ );\n}\n\nunsigned int MidiOutWinKS :: getPortCount()\n{\n  WindowsKsData* data = static_cast<WindowsKsData*>(apiData_);\n\n  return (unsigned int)data->m_pRenderEnum->m_Filters.size();\n}\n\nstd::string MidiOutWinKS :: getPortName( unsigned int portNumber )\n{\n  WindowsKsData* data = static_cast<WindowsKsData*>(apiData_);\n\n  if ( portNumber < 0 || portNumber >= data->m_pRenderEnum->m_Filters.size() ) {\n    std::stringstream ost;\n    ost << \"MidiOutWinKS::getPortName: the 'portNumber' argument (\" << portNumber << \") is invalid.\";\n    errorString_ = ost.str();\n    RtMidi::error( RtError::WARNING, errorString_ );\n  }\n\n  CKsMidiRenFilter* pFilter = data->m_pRenderEnum->m_Filters[portNumber];\n  return pFilter->GetFriendlyName();\n}\n\nvoid MidiOutWinKS :: closePort()\n{\n  WindowsKsData* data = static_cast<WindowsKsData*>(apiData_);\n  connected_ = false;\n\n  if ( data->m_pPin ) {\n    data->m_pPin->SetState(KSSTATE_PAUSE);\n    data->m_pPin->SetState(KSSTATE_STOP);\n    data->m_pPin->ClosePin();\n    data->m_pPin = NULL;\n  }\n}\n\nvoid MidiOutWinKS :: sendMessage(std::vector<unsigned char>* pMessage)\n{\n  std::vector<unsigned char> const& msg = *pMessage;\n  WindowsKsData* data = static_cast<WindowsKsData*>(apiData_);\n  size_t iNumMidiBytes = msg.size();\n  size_t pos = 0;\n\n  // write header\n  KSMUSICFORMAT* pKsMusicFormat = reinterpret_cast<KSMUSICFORMAT*>(&data->m_Buffer[pos]);\n  pKsMusicFormat->TimeDeltaMs = 0;\n  pKsMusicFormat->ByteCount = iNumMidiBytes;\n  pos += sizeof(KSMUSICFORMAT);\n\n  // write MIDI bytes\n  if ( pos + iNumMidiBytes > data->m_Buffer.size() ) {\n    std::stringstream ost;\n    ost << \"KsMidiInput::Write: MIDI buffer too small. Required \" << pos + iNumMidiBytes << \" bytes, only has \" << data->m_Buffer.size();\n    errorString_ = ost.str();\n    RtMidi::error( RtError::WARNING, errorString_ );\n  }\n\n  if ( data->m_pPin == NULL ) {\n    std::stringstream ost;\n    ost << \"MidiOutWinKS::sendMessage: port is not open\";\n    errorString_ = ost.str();\n    RtMidi::error( RtError::WARNING, errorString_ );\n  }\n\n  memcpy(&data->m_Buffer[pos], &msg[0], iNumMidiBytes);\n  pos += iNumMidiBytes;\n\n  KSSTREAM_HEADER packet;\n  memset(&packet, 0, sizeof packet);\n  packet.Size = sizeof(packet);\n  packet.PresentationTime.Time = 0;\n  packet.PresentationTime.Numerator = 1;\n  packet.PresentationTime.Denominator = 1;\n  packet.Data = const_cast<unsigned char*>(&data->m_Buffer[0]);\n  packet.DataUsed = ((pos+3)/4)*4;\n  packet.FrameExtent = data->m_Buffer.size();\n\n  data->m_pPin->WriteData(&packet, NULL);\n}\n\n#endif  // __WINDOWS_KS__\n\n//*********************************************************************//\n//  API: UNIX JACK\n//\n//  Written primarily by Alexander Svetalkin, with updates for delta\n//  time by Gary Scavone, April 2011.\n//\n//  *********************************************************************//\n\n#if defined(__UNIX_JACK__)\n\n// JACK header files\n#include <jack/jack.h>\n#include <jack/midiport.h>\n#include <jack/ringbuffer.h>\n\n#define JACK_RINGBUFFER_SIZE 16384 // Default size for ringbuffer\n\nstruct JackMidiData {\n  jack_client_t *client;\n  jack_port_t *port;\n  jack_ringbuffer_t *buffSize;\n  jack_ringbuffer_t *buffMessage;\n  jack_time_t lastTime;\n  MidiInApi :: RtMidiInData *rtMidiIn;\n  };\n\n//*********************************************************************//\n//  API: JACK\n//  Class Definitions: MidiInJack\n//*********************************************************************//\n\nint jackProcessIn( jack_nframes_t nframes, void *arg )\n{\n  JackMidiData *jData = (JackMidiData *) arg;\n  MidiInApi :: RtMidiInData *rtData = jData->rtMidiIn;\n  jack_midi_event_t event;\n  jack_time_t time;\n\n  // Is port created?\n  if ( jData->port == NULL ) return 0;\n  void *buff = jack_port_get_buffer( jData->port, nframes );\n\n  // We have midi events in buffer\n  int evCount = jack_midi_get_event_count( buff );\n  if ( evCount > 0 ) {\n    MidiInApi::MidiMessage message;\n    message.bytes.clear();\n\n    jack_midi_event_get( &event, buff, 0 );\n\n    for (unsigned int i = 0; i < event.size; i++ )\n      message.bytes.push_back( event.buffer[i] );\n\n    // Compute the delta time.\n    time = jack_get_time();\n    if ( rtData->firstMessage == true )\n      rtData->firstMessage = false;\n    else\n      message.timeStamp = ( time - jData->lastTime ) * 0.000001;\n\n    jData->lastTime = time;\n\n    if ( !rtData->continueSysex ) {\n      if ( rtData->usingCallback ) {\n        RtMidiIn::RtMidiCallback callback = (RtMidiIn::RtMidiCallback) rtData->userCallback;\n        callback( message.timeStamp, &message.bytes, rtData->userData );\n      }\n      else {\n        // As long as we haven't reached our queue size limit, push the message.\n        if ( rtData->queue.size < rtData->queue.ringSize ) {\n          rtData->queue.ring[rtData->queue.back++] = message;\n          if ( rtData->queue.back == rtData->queue.ringSize )\n            rtData->queue.back = 0;\n          rtData->queue.size++;\n        }\n        else\n          std::cerr << \"\\nMidiInJack: message queue limit reached!!\\n\\n\";\n      }\n    }\n  }\n\n  return 0;\n}\n\nMidiInJack :: MidiInJack( const std::string clientName, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit )\n{\n  initialize( clientName );\n}\n\nvoid MidiInJack :: initialize( const std::string& clientName )\n{\n  JackMidiData *data = new JackMidiData;\n  apiData_ = (void *) data;\n\n  // Initialize JACK client\n  if (( data->client = jack_client_open( clientName.c_str(), JackNullOption, NULL )) == 0) {\n    errorString_ = \"MidiInJack::initialize: JACK server not running?\";\n    RtMidi::error( RtError::DRIVER_ERROR, errorString_ );\n    return;\n  }\n\n  data->rtMidiIn = &inputData_;\n  data->port = NULL;\n\n  jack_set_process_callback( data->client, jackProcessIn, data );\n  jack_activate( data->client );\n}\n\nMidiInJack :: ~MidiInJack()\n{\n  JackMidiData *data = static_cast<JackMidiData *> (apiData_);\n  closePort();\n\n  jack_client_close( data->client );\n}\n\nvoid MidiInJack :: openPort( unsigned int portNumber, const std::string portName )\n{\n  JackMidiData *data = static_cast<JackMidiData *> (apiData_);\n\n  // Creating new port\n  if ( data->port == NULL)\n    data->port = jack_port_register( data->client, portName.c_str(),\n                                     JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0 );\n\n  if ( data->port == NULL) {\n    errorString_ = \"MidiInJack::openVirtualPort: JACK error creating virtual port\";\n    RtMidi::error( RtError::DRIVER_ERROR, errorString_ );\n  }\n\n  // Connecting to the output\n  std::string name = getPortName( portNumber );\n  jack_connect( data->client, name.c_str(), jack_port_name( data->port ) );\n}\n\nvoid MidiInJack :: openVirtualPort( const std::string portName )\n{\n  JackMidiData *data = static_cast<JackMidiData *> (apiData_);\n\n  if ( data->port == NULL )\n    data->port = jack_port_register( data->client, portName.c_str(),\n                                     JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0 );\n\n  if ( data->port == NULL ) {\n    errorString_ = \"MidiInJack::openVirtualPort: JACK error creating virtual port\";\n    RtMidi::error( RtError::DRIVER_ERROR, errorString_ );\n  }\n}\n\nunsigned int MidiInJack :: getPortCount()\n{\n  int count = 0;\n  JackMidiData *data = static_cast<JackMidiData *> (apiData_);\n\n  // List of available ports\n  const char **ports = jack_get_ports( data->client, NULL, JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput );\n\n  if ( ports == NULL ) return 0;\n  while ( ports[count] != NULL )\n    count++;\n\n  free( ports );\n\n  return count;\n}\n\nstd::string MidiInJack :: getPortName( unsigned int portNumber )\n{\n  JackMidiData *data = static_cast<JackMidiData *> (apiData_);\n  std::ostringstream ost;\n  std::string retStr(\"\");\n\n  // List of available ports\n  const char **ports = jack_get_ports( data->client, NULL,\n                                       JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput );\n\n  // Check port validity\n  if ( ports == NULL ) {\n    errorString_ = \"MidiInJack::getPortName: no ports available!\";\n    RtMidi::error( RtError::WARNING, errorString_ );\n    return retStr;\n  }\n\n  if ( ports[portNumber] == NULL ) {\n    ost << \"MidiInJack::getPortName: the 'portNumber' argument (\" << portNumber << \") is invalid.\";\n    errorString_ = ost.str();\n    RtMidi::error( RtError::WARNING, errorString_ );\n  }\n  else retStr.assign( ports[portNumber] );\n\n  free( ports );\n\n  return retStr;\n}\n\nvoid MidiInJack :: closePort()\n{\n  JackMidiData *data = static_cast<JackMidiData *> (apiData_);\n\n  if ( data->port == NULL ) return;\n  jack_port_unregister( data->client, data->port );\n  data->port = NULL;\n}\n\n//*********************************************************************//\n//  API: JACK\n//  Class Definitions: MidiOutJack\n//*********************************************************************//\n\n// Jack process callback\nint jackProcessOut( jack_nframes_t nframes, void *arg )\n{\n  JackMidiData *data = (JackMidiData *) arg;\n  jack_midi_data_t *midiData;\n  int space;\n\n  // Is port created?\n  if ( data->port == NULL ) return 0;\n\n  void *buff = jack_port_get_buffer( data->port, nframes );\n  jack_midi_clear_buffer( buff );\n\n  while ( jack_ringbuffer_read_space( data->buffSize ) > 0 ) {\n    jack_ringbuffer_read( data->buffSize, (char *) &space, (size_t) sizeof(space) );\n    midiData = jack_midi_event_reserve( buff, 0, space );\n\n    jack_ringbuffer_read( data->buffMessage, (char *) midiData, (size_t) space );\n  }\n\n  return 0;\n}\n\nMidiOutJack :: MidiOutJack( const std::string clientName ) : MidiOutApi()\n{\n  initialize( clientName );\n}\n\nvoid MidiOutJack :: initialize( const std::string& clientName )\n{\n  JackMidiData *data = new JackMidiData;\n\n  data->port = NULL;\n\n  // Initialize JACK client\n  if (( data->client = jack_client_open( clientName.c_str(), JackNullOption, NULL )) == 0) {\n    errorString_ = \"MidiOutJack::initialize: JACK server not running?\";\n    RtMidi::error( RtError::DRIVER_ERROR, errorString_ );\n    return;\n  }\n\n  jack_set_process_callback( data->client, jackProcessOut, data );\n  data->buffSize = jack_ringbuffer_create( JACK_RINGBUFFER_SIZE );\n  data->buffMessage = jack_ringbuffer_create( JACK_RINGBUFFER_SIZE );\n  jack_activate( data->client );\n\n  apiData_ = (void *) data;\n}\n\nMidiOutJack :: ~MidiOutJack()\n{\n  JackMidiData *data = static_cast<JackMidiData *> (apiData_);\n  closePort();\n\n  // Cleanup\n  jack_client_close( data->client );\n  jack_ringbuffer_free( data->buffSize );\n  jack_ringbuffer_free( data->buffMessage );\n\n  delete data;\n}\n\nvoid MidiOutJack :: openPort( unsigned int portNumber, const std::string portName )\n{\n  JackMidiData *data = static_cast<JackMidiData *> (apiData_);\n\n  // Creating new port\n  if ( data->port == NULL )\n    data->port = jack_port_register( data->client, portName.c_str(),\n      JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0 );\n\n  if ( data->port == NULL ) {\n    errorString_ = \"MidiOutJack::openVirtualPort: JACK error creating virtual port\";\n    RtMidi::error( RtError::DRIVER_ERROR, errorString_ );\n  }\n\n  // Connecting to the output\n  std::string name = getPortName( portNumber );\n  jack_connect( data->client, jack_port_name( data->port ), name.c_str() );\n}\n\nvoid MidiOutJack :: openVirtualPort( const std::string portName )\n{\n  JackMidiData *data = static_cast<JackMidiData *> (apiData_);\n\n  if ( data->port == NULL )\n    data->port = jack_port_register( data->client, portName.c_str(),\n      JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0 );\n\n  if ( data->port == NULL ) {\n    errorString_ = \"MidiOutJack::openVirtualPort: JACK error creating virtual port\";\n    RtMidi::error( RtError::DRIVER_ERROR, errorString_ );\n  }\n}\n\nunsigned int MidiOutJack :: getPortCount()\n{\n  int count = 0;\n  JackMidiData *data = static_cast<JackMidiData *> (apiData_);\n\n  // List of available ports\n  const char **ports = jack_get_ports( data->client, NULL,\n    JACK_DEFAULT_MIDI_TYPE, JackPortIsInput );\n\n  if ( ports == NULL ) return 0;\n  while ( ports[count] != NULL )\n    count++;\n\n  free( ports );\n\n  return count;\n}\n\nstd::string MidiOutJack :: getPortName( unsigned int portNumber )\n{\n  JackMidiData *data = static_cast<JackMidiData *> (apiData_);\n  std::ostringstream ost;\n  std::string retStr(\"\");\n\n  // List of available ports\n  const char **ports = jack_get_ports( data->client, NULL,\n    JACK_DEFAULT_MIDI_TYPE, JackPortIsInput );\n\n  // Check port validity\n  if ( ports == NULL) {\n    errorString_ = \"MidiOutJack::getPortName: no ports available!\";\n    RtMidi::error( RtError::WARNING, errorString_ );\n    return retStr;\n  }\n\n  if ( ports[portNumber] == NULL) {\n    ost << \"MidiOutJack::getPortName: the 'portNumber' argument (\" << portNumber << \") is invalid.\";\n    errorString_ = ost.str();\n    RtMidi::error( RtError::WARNING, errorString_ );\n  }\n  else retStr.assign( ports[portNumber] );\n\n  free( ports );\n\n  return retStr;\n}\n\nvoid MidiOutJack :: closePort()\n{\n  JackMidiData *data = static_cast<JackMidiData *> (apiData_);\n\n  if ( data->port == NULL ) return;\n  jack_port_unregister( data->client, data->port );\n  data->port = NULL;\n}\n\nvoid MidiOutJack :: sendMessage( std::vector<unsigned char> *message )\n{\n  int nBytes = message->size();\n  JackMidiData *data = static_cast<JackMidiData *> (apiData_);\n\n  // Write full message to buffer\n  jack_ringbuffer_write( data->buffMessage, ( const char * ) &( *message )[0],\n                         message->size() );\n  jack_ringbuffer_write( data->buffSize, ( char * ) &nBytes, sizeof( nBytes ) );\n}\n\n#endif  // __UNIX_JACK__\n"
  },
  {
    "path": "rtmidi/RtMidi.h",
    "content": "/**********************************************************************/\n/*! \\class RtMidi\n    \\brief An abstract base class for realtime MIDI input/output.\n\n    This class implements some common functionality for the realtime\n    MIDI input/output subclasses RtMidiIn and RtMidiOut.\n\n    RtMidi WWW site: http://music.mcgill.ca/~gary/rtmidi/\n\n    RtMidi: realtime MIDI i/o C++ classes\n    Copyright (c) 2003-2012 Gary P. Scavone\n\n    Permission is hereby granted, free of charge, to any person\n    obtaining a copy of this software and associated documentation files\n    (the \"Software\"), to deal in the Software without restriction,\n    including without limitation the rights to use, copy, modify, merge,\n    publish, distribute, sublicense, and/or sell copies of the Software,\n    and to permit persons to whom the Software is furnished to do so,\n    subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be\n    included in all copies or substantial portions of the Software.\n\n    Any person wishing to distribute modifications to the Software is\n    asked to send the modifications to the original developer so that\n    they can be incorporated into the canonical version.  This is,\n    however, not a binding provision of this license.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR\n    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF\n    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\n    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n*/\n/**********************************************************************/\n\n/*!\n  \\file RtMidi.h\n */\n\n// RtMidi: Version 2.0.1\n\n#ifndef RTMIDI_H\n#define RTMIDI_H\n\n#include \"RtError.h\"\n#include <string>\n#include <vector>\n\nclass RtMidi\n{\n public:\n\n  //! MIDI API specifier arguments.\n  enum Api {\n    UNSPECIFIED,    /*!< Search for a working compiled API. */\n    MACOSX_CORE,    /*!< Macintosh OS-X Core Midi API. */\n    LINUX_ALSA,     /*!< The Advanced GNU/Linux Sound Architecture API. */\n    UNIX_JACK,      /*!< The Jack Low-Latency MIDI Server API. */\n    WINDOWS_MM,     /*!< The Microsoft Multimedia MIDI API. */\n    WINDOWS_KS,     /*!< The Microsoft Kernel Streaming MIDI API. */\n    RTMIDI_DUMMY    /*!< A compilable but non-functional API. */\n  };\n\n  //! A static function to determine the available compiled MIDI APIs.\n  /*!\n    The values returned in the std::vector can be compared against\n    the enumerated list values.  Note that there can be more than one\n    API compiled for certain operating systems.\n  */\n  static void getCompiledApi( std::vector<RtMidi::Api> &apis ) throw();\n\n  //! Pure virtual openPort() function.\n  virtual void openPort( unsigned int portNumber = 0, const std::string portName = std::string( \"RtMidi\" ) ) = 0;\n\n  //! Pure virtual openVirtualPort() function.\n  virtual void openVirtualPort( const std::string portName = std::string( \"RtMidi\" ) ) = 0;\n\n  //! Pure virtual getPortCount() function.\n  virtual unsigned int getPortCount() = 0;\n\n  //! Pure virtual getPortName() function.\n  virtual std::string getPortName( unsigned int portNumber = 0 ) = 0;\n\n  //! Pure virtual closePort() function.\n  virtual void closePort( void ) = 0;\n\n  //! A basic error reporting function for RtMidi classes.\n  static void error( RtError::Type type, std::string errorString );\n\n protected:\n\n  RtMidi() {};\n  virtual ~RtMidi() {};\n};\n\n/**********************************************************************/\n/*! \\class RtMidiIn\n    \\brief A realtime MIDI input class.\n\n    This class provides a common, platform-independent API for\n    realtime MIDI input.  It allows access to a single MIDI input\n    port.  Incoming MIDI messages are either saved to a queue for\n    retrieval using the getMessage() function or immediately passed to\n    a user-specified callback function.  Create multiple instances of\n    this class to connect to more than one MIDI device at the same\n    time.  With the OS-X and GNU/Linux ALSA MIDI APIs, it is also possible\n    to open a virtual input port to which other MIDI software clients\n    can connect.\n\n    by Gary P. Scavone, 2003-2012.\n*/\n/**********************************************************************/\n\n// **************************************************************** //\n//\n// RtMidiIn and RtMidiOut class declarations.\n//\n// RtMidiIn / RtMidiOut are \"controllers\" used to select an available\n// MIDI input or output interface.  They present common APIs for the\n// user to call but all functionality is implemented by the classes\n// MidiInApi, MidiOutApi and their subclasses.  RtMidiIn and RtMidiOut\n// each create an instance of a MidiInApi or MidiOutApi subclass based\n// on the user's API choice.  If no choice is made, they attempt to\n// make a \"logical\" API selection.\n//\n// **************************************************************** //\n\nclass MidiInApi;\nclass MidiOutApi;\n\nclass RtMidiIn : public RtMidi\n{\n public:\n\n  //! User callback function type definition.\n  typedef void (*RtMidiCallback)( double timeStamp, std::vector<unsigned char> *message, void *userData);\n\n  //! Default constructor that allows an optional api, client name and queue size.\n  /*!\n    An exception will be thrown if a MIDI system initialization\n    error occurs.  The queue size defines the maximum number of\n    messages that can be held in the MIDI queue (when not using a\n    callback function).  If the queue size limit is reached,\n    incoming messages will be ignored.\n\n    If no API argument is specified and multiple API support has been\n    compiled, the default order of use is JACK, ALSA (GNU/Linux) and CORE,\n    Jack (OS-X).\n  */\n  RtMidiIn( RtMidi::Api api=UNSPECIFIED,\n            const std::string clientName = std::string( \"RtMidi Input Client\"),\n            unsigned int queueSizeLimit = 100 );\n\n  //! If a MIDI connection is still open, it will be closed by the destructor.\n  ~RtMidiIn ( void ) throw();\n\n  //! Returns the MIDI API specifier for the current instance of RtMidiIn.\n  RtMidi::Api getCurrentApi( void ) throw();\n\n  //! Open a MIDI input connection.\n  /*!\n    An optional port number greater than 0 can be specified.\n    Otherwise, the default or first port found is opened.\n  */\n  void openPort( unsigned int portNumber = 0, const std::string portName = std::string( \"RtMidi Input\" ) );\n\n  //! Create a virtual input port, with optional name, to allow software connections (OS X and ALSA only).\n  /*!\n    This function creates a virtual MIDI input port to which other\n    software applications can connect.  This type of functionality\n    is currently only supported by the Macintosh OS-X and GNU/Linux ALSA\n    APIs (the function does nothing for the other APIs).\n  */\n  void openVirtualPort( const std::string portName = std::string( \"RtMidi Input\" ) );\n\n  //! Set a callback function to be invoked for incoming MIDI messages.\n  /*!\n    The callback function will be called whenever an incoming MIDI\n    message is received.  While not absolutely necessary, it is best\n    to set the callback function before opening a MIDI port to avoid\n    leaving some messages in the queue.\n  */\n  void setCallback( RtMidiCallback callback, void *userData = 0 );\n\n  //! Cancel use of the current callback function (if one exists).\n  /*!\n    Subsequent incoming MIDI messages will be written to the queue\n    and can be retrieved with the \\e getMessage function.\n  */\n  void cancelCallback();\n\n  //! Close an open MIDI connection (if one exists).\n  void closePort( void );\n\n  //! Return the number of available MIDI input ports.\n  unsigned int getPortCount();\n\n  //! Return a string identifier for the specified MIDI input port number.\n  /*!\n    An empty string is returned if an invalid port specifier is provided.\n  */\n  std::string getPortName( unsigned int portNumber = 0 );\n\n  //! Specify whether certain MIDI message types should be queued or ignored during input.\n  /*!\n    o      By default, MIDI timing and active sensing messages are ignored\n    during message input because of their relative high data rates.\n    MIDI sysex messages are ignored by default as well.  Variable\n    values of \"true\" imply that the respective message type will be\n    ignored.\n  */\n  void ignoreTypes( bool midiSysex = true, bool midiTime = true, bool midiSense = true );\n\n  //! 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.\n  /*!\n    This function returns immediately whether a new message is\n    available or not.  A valid message is indicated by a non-zero\n    vector size.  An exception is thrown if an error occurs during\n    message retrieval or an input connection was not previously\n    established.\n  */\n  double getMessage( std::vector<unsigned char> *message );\n\n protected:\n  void openMidiApi( RtMidi::Api api, const std::string clientName, unsigned int queueSizeLimit );\n  MidiInApi *rtapi_;\n\n};\n\n/**********************************************************************/\n/*! \\class RtMidiOut\n    \\brief A realtime MIDI output class.\n\n    This class provides a common, platform-independent API for MIDI\n    output.  It allows one to probe available MIDI output ports, to\n    connect to one such port, and to send MIDI bytes immediately over\n    the connection.  Create multiple instances of this class to\n    connect to more than one MIDI device at the same time.  With the\n    OS-X and GNU/Linux ALSA MIDI APIs, it is also possible to open a\n    virtual port to which other MIDI software clients can connect.\n\n    by Gary P. Scavone, 2003-2012.\n*/\n/**********************************************************************/\n\nclass RtMidiOut : public RtMidi\n{\n public:\n\n  //! Default constructor that allows an optional client name.\n  /*!\n    An exception will be thrown if a MIDI system initialization error occurs.\n\n    If no API argument is specified and multiple API support has been\n    compiled, the default order of use is JACK, ALSA (GNU/Linux) and CORE,\n    Jack (OS-X).\n  */\n  RtMidiOut( RtMidi::Api api=UNSPECIFIED,\n             const std::string clientName = std::string( \"RtMidi Output Client\") );\n\n  //! The destructor closes any open MIDI connections.\n  ~RtMidiOut( void ) throw();\n\n  //! Returns the MIDI API specifier for the current instance of RtMidiOut.\n  RtMidi::Api getCurrentApi( void ) throw();\n\n  //! Open a MIDI output connection.\n  /*!\n      An optional port number greater than 0 can be specified.\n      Otherwise, the default or first port found is opened.  An\n      exception is thrown if an error occurs while attempting to make\n      the port connection.\n  */\n  void openPort( unsigned int portNumber = 0, const std::string portName = std::string( \"RtMidi Output\" ) );\n\n  //! Close an open MIDI connection (if one exists).\n  void closePort( void );\n\n  //! Create a virtual output port, with optional name, to allow software connections (OS X and ALSA only).\n  /*!\n      This function creates a virtual MIDI output port to which other\n      software applications can connect.  This type of functionality\n      is currently only supported by the Macintosh OS-X and GNU/Linux ALSA\n      APIs (the function does nothing with the other APIs).  An\n      exception is thrown if an error occurs while attempting to create\n      the virtual port.\n  */\n  void openVirtualPort( const std::string portName = std::string( \"RtMidi Output\" ) );\n\n  //! Return the number of available MIDI output ports.\n  unsigned int getPortCount( void );\n\n  //! Return a string identifier for the specified MIDI port type and number.\n  /*!\n      An empty string is returned if an invalid port specifier is provided.\n  */\n  std::string getPortName( unsigned int portNumber = 0 );\n\n  //! Immediately send a single message out an open MIDI output port.\n  /*!\n      An exception is thrown if an error occurs during output or an\n      output connection was not previously established.\n  */\n  void sendMessage( std::vector<unsigned char> *message );\n\n protected:\n  void openMidiApi( RtMidi::Api api, const std::string clientName );\n  MidiOutApi *rtapi_;\n};\n\n\n// **************************************************************** //\n//\n// MidiInApi / MidiOutApi class declarations.\n//\n// Subclasses of MidiInApi and MidiOutApi contain all API- and\n// OS-specific code necessary to fully implement the RtMidi API.\n//\n// Note that MidiInApi and MidiOutApi are abstract base classes and\n// cannot be explicitly instantiated.  RtMidiIn and RtMidiOut will\n// create instances of a MidiInApi or MidiOutApi subclass.\n//\n// **************************************************************** //\n\nclass MidiInApi\n{\n public:\n\n  MidiInApi( unsigned int queueSizeLimit );\n  virtual ~MidiInApi( void );\n  virtual RtMidi::Api getCurrentApi( void ) = 0;\n  virtual void openPort( unsigned int portNumber, const std::string portName ) = 0;\n  virtual void openVirtualPort( const std::string portName ) = 0;\n  virtual void closePort( void ) = 0;\n  void setCallback( RtMidiIn::RtMidiCallback callback, void *userData );\n  void cancelCallback( void );\n  virtual unsigned int getPortCount( void ) = 0;\n  virtual std::string getPortName( unsigned int portNumber ) = 0;\n  virtual void ignoreTypes( bool midiSysex, bool midiTime, bool midiSense );\n  double getMessage( std::vector<unsigned char> *message );\n\n  // A MIDI structure used internally by the class to store incoming\n  // messages.  Each message represents one and only one MIDI message.\n  struct MidiMessage { \n    std::vector<unsigned char> bytes; \n    double timeStamp;\n\n    // Default constructor.\n  MidiMessage()\n  :bytes(0), timeStamp(0.0) {}\n  };\n\n  struct MidiQueue {\n    unsigned int front;\n    unsigned int back;\n    unsigned int size;\n    unsigned int ringSize;\n    MidiMessage *ring;\n\n    // Default constructor.\n  MidiQueue()\n  :front(0), back(0), size(0), ringSize(0) {}\n  };\n\n  // The RtMidiInData structure is used to pass private class data to\n  // the MIDI input handling function or thread.\n  struct RtMidiInData {\n    MidiQueue queue;\n    MidiMessage message;\n    unsigned char ignoreFlags;\n    bool doInput;\n    bool firstMessage;\n    void *apiData;\n    bool usingCallback;\n    void *userCallback;\n    void *userData;\n    bool continueSysex;\n\n    // Default constructor.\n  RtMidiInData()\n  : ignoreFlags(7), doInput(false), firstMessage(true),\n      apiData(0), usingCallback(false), userCallback(0), userData(0),\n      continueSysex(false) {}\n  };\n\n protected:\n  virtual void initialize( const std::string& clientName ) = 0;\n  RtMidiInData inputData_;\n\n  void *apiData_;\n  bool connected_;\n  std::string errorString_;\n};\n\nclass MidiOutApi\n{\n public:\n\n  MidiOutApi( void );\n  virtual ~MidiOutApi( void );\n  virtual RtMidi::Api getCurrentApi( void ) = 0;\n  virtual void openPort( unsigned int portNumber, const std::string portName ) = 0;\n  virtual void openVirtualPort( const std::string portName ) = 0;\n  virtual void closePort( void ) = 0;\n  virtual unsigned int getPortCount( void ) = 0;\n  virtual std::string getPortName( unsigned int portNumber ) = 0;\n  virtual void sendMessage( std::vector<unsigned char> *message ) = 0;\n\n protected:\n  virtual void initialize( const std::string& clientName ) = 0;\n\n  void *apiData_;\n  bool connected_;\n  std::string errorString_;\n};\n\n// **************************************************************** //\n//\n// Inline RtMidiIn and RtMidiOut definitions.\n//\n// **************************************************************** //\n\ninline RtMidi::Api RtMidiIn :: getCurrentApi( void ) throw() { return rtapi_->getCurrentApi(); }\ninline void RtMidiIn :: openPort( unsigned int portNumber, const std::string portName ) { return rtapi_->openPort( portNumber, portName ); }\ninline void RtMidiIn :: openVirtualPort( const std::string portName ) { return rtapi_->openVirtualPort( portName ); }\ninline void RtMidiIn :: closePort( void ) { return rtapi_->closePort(); }\ninline void RtMidiIn :: setCallback( RtMidiCallback callback, void *userData ) { return rtapi_->setCallback( callback, userData ); }\ninline void RtMidiIn :: cancelCallback( void ) { return rtapi_->cancelCallback(); }\ninline unsigned int RtMidiIn :: getPortCount( void ) { return rtapi_->getPortCount(); }\ninline std::string RtMidiIn :: getPortName( unsigned int portNumber ) { return rtapi_->getPortName( portNumber ); }\ninline void RtMidiIn :: ignoreTypes( bool midiSysex, bool midiTime, bool midiSense ) { return rtapi_->ignoreTypes( midiSysex, midiTime, midiSense ); }\ninline double RtMidiIn :: getMessage( std::vector<unsigned char> *message ) { return rtapi_->getMessage( message ); }\n\ninline RtMidi::Api RtMidiOut :: getCurrentApi( void ) throw() { return rtapi_->getCurrentApi(); }\ninline void RtMidiOut :: openPort( unsigned int portNumber, const std::string portName ) { return rtapi_->openPort( portNumber, portName ); }\ninline void RtMidiOut :: openVirtualPort( const std::string portName ) { return rtapi_->openVirtualPort( portName ); }\ninline void RtMidiOut :: closePort( void ) { return rtapi_->closePort(); }\ninline unsigned int RtMidiOut :: getPortCount( void ) { return rtapi_->getPortCount(); }\ninline std::string RtMidiOut :: getPortName( unsigned int portNumber ) { return rtapi_->getPortName( portNumber ); }\ninline void RtMidiOut :: sendMessage( std::vector<unsigned char> *message ) { return rtapi_->sendMessage( message ); }\n\n// **************************************************************** //\n//\n// MidiInApi and MidiOutApi subclass prototypes.\n//\n// **************************************************************** //\n\n#if !defined(__LINUX_ALSA__) && !defined(__UNIX_JACK__) && !defined(__MACOSX_CORE__) && !defined(__WINDOWS_MM__) && !defined(__WINDOWS_KS__)\n  #define __RTMIDI_DUMMY__\n#endif\n\n#if defined(__MACOSX_CORE__)\n\nclass MidiInCore: public MidiInApi\n{\n public:\n  MidiInCore( const std::string clientName, unsigned int queueSizeLimit );\n  ~MidiInCore( void );\n  RtMidi::Api getCurrentApi( void ) { return RtMidi::MACOSX_CORE; };\n  void openPort( unsigned int portNumber, const std::string portName );\n  void openVirtualPort( const std::string portName );\n  void closePort( void );\n  unsigned int getPortCount( void );\n  std::string getPortName( unsigned int portNumber );\n\n protected:\n  void initialize( const std::string& clientName );\n};\n\nclass MidiOutCore: public MidiOutApi\n{\n public:\n  MidiOutCore( const std::string clientName );\n  ~MidiOutCore( void );\n  RtMidi::Api getCurrentApi( void ) { return RtMidi::MACOSX_CORE; };\n  void openPort( unsigned int portNumber, const std::string portName );\n  void openVirtualPort( const std::string portName );\n  void closePort( void );\n  unsigned int getPortCount( void );\n  std::string getPortName( unsigned int portNumber );\n  void sendMessage( std::vector<unsigned char> *message );\n\n protected:\n  void initialize( const std::string& clientName );\n};\n\n#endif\n\n#if defined(__UNIX_JACK__)\n\nclass MidiInJack: public MidiInApi\n{\n public:\n  MidiInJack( const std::string clientName, unsigned int queueSizeLimit );\n  ~MidiInJack( void );\n  RtMidi::Api getCurrentApi( void ) { return RtMidi::UNIX_JACK; };\n  void openPort( unsigned int portNumber, const std::string portName );\n  void openVirtualPort( const std::string portName );\n  void closePort( void );\n  unsigned int getPortCount( void );\n  std::string getPortName( unsigned int portNumber );\n\n protected:\n  void initialize( const std::string& clientName );\n};\n\nclass MidiOutJack: public MidiOutApi\n{\n public:\n  MidiOutJack( const std::string clientName );\n  ~MidiOutJack( void );\n  RtMidi::Api getCurrentApi( void ) { return RtMidi::UNIX_JACK; };\n  void openPort( unsigned int portNumber, const std::string portName );\n  void openVirtualPort( const std::string portName );\n  void closePort( void );\n  unsigned int getPortCount( void );\n  std::string getPortName( unsigned int portNumber );\n  void sendMessage( std::vector<unsigned char> *message );\n\n protected:\n  void initialize( const std::string& clientName );\n};\n\n#endif\n\n#if defined(__LINUX_ALSA__)\n\nclass MidiInAlsa: public MidiInApi\n{\n public:\n  MidiInAlsa( const std::string clientName, unsigned int queueSizeLimit );\n  ~MidiInAlsa( void );\n  RtMidi::Api getCurrentApi( void ) { return RtMidi::LINUX_ALSA; };\n  void openPort( unsigned int portNumber, const std::string portName );\n  void openVirtualPort( const std::string portName );\n  void closePort( void );\n  unsigned int getPortCount( void );\n  std::string getPortName( unsigned int portNumber );\n\n protected:\n  void initialize( const std::string& clientName );\n};\n\nclass MidiOutAlsa: public MidiOutApi\n{\n public:\n  MidiOutAlsa( const std::string clientName );\n  ~MidiOutAlsa( void );\n  RtMidi::Api getCurrentApi( void ) { return RtMidi::LINUX_ALSA; };\n  void openPort( unsigned int portNumber, const std::string portName );\n  void openVirtualPort( const std::string portName );\n  void closePort( void );\n  unsigned int getPortCount( void );\n  std::string getPortName( unsigned int portNumber );\n  void sendMessage( std::vector<unsigned char> *message );\n\n protected:\n  void initialize( const std::string& clientName );\n};\n\n#endif\n\n#if defined(__WINDOWS_MM__)\n\nclass MidiInWinMM: public MidiInApi\n{\n public:\n  MidiInWinMM( const std::string clientName, unsigned int queueSizeLimit );\n  ~MidiInWinMM( void );\n  RtMidi::Api getCurrentApi( void ) { return RtMidi::WINDOWS_MM; };\n  void openPort( unsigned int portNumber, const std::string portName );\n  void openVirtualPort( const std::string portName );\n  void closePort( void );\n  unsigned int getPortCount( void );\n  std::string getPortName( unsigned int portNumber );\n\n protected:\n  void initialize( const std::string& clientName );\n};\n\nclass MidiOutWinMM: public MidiOutApi\n{\n public:\n  MidiOutWinMM( const std::string clientName );\n  ~MidiOutWinMM( void );\n  RtMidi::Api getCurrentApi( void ) { return RtMidi::WINDOWS_MM; };\n  void openPort( unsigned int portNumber, const std::string portName );\n  void openVirtualPort( const std::string portName );\n  void closePort( void );\n  unsigned int getPortCount( void );\n  std::string getPortName( unsigned int portNumber );\n  void sendMessage( std::vector<unsigned char> *message );\n\n protected:\n  void initialize( const std::string& clientName );\n};\n\n#endif\n\n#if defined(__WINDOWS_KS__)\n\nclass MidiInWinKS: public MidiInApi\n{\n public:\n  MidiInWinKS( const std::string clientName, unsigned int queueSizeLimit );\n  ~MidiInWinKS( void );\n  RtMidi::Api getCurrentApi( void ) { return RtMidi::WINDOWS_KS; };\n  void openPort( unsigned int portNumber, const std::string portName );\n  void openVirtualPort( const std::string portName );\n  void closePort( void );\n  unsigned int getPortCount( void );\n  std::string getPortName( unsigned int portNumber );\n\n protected:\n  void initialize( const std::string& clientName );\n};\n\nclass MidiOutWinKS: public MidiOutApi\n{\n public:\n  MidiOutWinKS( const std::string clientName );\n  ~MidiOutWinKS( void );\n  RtMidi::Api getCurrentApi( void ) { return RtMidi::WINDOWS_KS; };\n  void openPort( unsigned int portNumber, const std::string portName );\n  void openVirtualPort( const std::string portName );\n  void closePort( void );\n  unsigned int getPortCount( void );\n  std::string getPortName( unsigned int portNumber );\n  void sendMessage( std::vector<unsigned char> *message );\n\n protected:\n  void initialize( const std::string& clientName );\n};\n\n#endif\n\n#if defined(__RTMIDI_DUMMY__)\n\nclass MidiInDummy: public MidiInApi\n{\n public:\n MidiInDummy( const std::string clientName, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) { errorString_ = \"MidiInDummy: This class provides no functionality.\"; RtMidi::error( RtError::WARNING, errorString_ ); };\n  RtMidi::Api getCurrentApi( void ) { return RtMidi::RTMIDI_DUMMY; };\n  void openPort( unsigned int portNumber, const std::string portName ) {};\n  void openVirtualPort( const std::string portName ) {};\n  void closePort( void ) {};\n  unsigned int getPortCount( void ) { return 0; };\n  std::string getPortName( unsigned int portNumber ) { return \"\"; };\n\n protected:\n  void initialize( const std::string& clientName ) {};\n};\n\nclass MidiOutDummy: public MidiOutApi\n{\n public:\n  MidiOutDummy( const std::string clientName ) { errorString_ = \"MidiOutDummy: This class provides no functionality.\"; RtMidi::error( RtError::WARNING, errorString_ ); };\n  RtMidi::Api getCurrentApi( void ) { return RtMidi::RTMIDI_DUMMY; };\n  void openPort( unsigned int portNumber, const std::string portName ) {};\n  void openVirtualPort( const std::string portName ) {};\n  void closePort( void ) {};\n  unsigned int getPortCount( void ) { return 0; };\n  std::string getPortName( unsigned int portNumber ) { return \"\"; };\n  void sendMessage( std::vector<unsigned char> *message ) {};\n\n protected:\n  void initialize( const std::string& clientName ) {};\n};\n\n#endif\n\n#endif\n"
  },
  {
    "path": "rtmidi/configure.ac",
    "content": "# Process this file with autoconf to produce a configure script.\nAC_INIT(RtMidi, 2.0, gary@music.mcgill.ca, rtmidi)\nAC_CONFIG_AUX_DIR(config)\nAC_CONFIG_SRCDIR(RtMidi.cpp)\nAC_CONFIG_FILES(rtmidi-config Makefile tests/Makefile)\nAM_INIT_AUTOMAKE([-Wall -Werror foreign])\nAM_SILENT_RULES([yes])\n\n# Fill GXX with something before test.\nAC_SUBST( GXX, [\"no\"] )\n\nAM_PROG_AR\n\n# Checks for programs.\nAC_PROG_CXX(c++ g++ CC cxx)\nAC_PROG_RANLIB\nAC_PATH_PROG(AR, ar, no)\nif [[ $AR = \"no\" ]] ; then\n    AC_MSG_ERROR(\"Could not find ar - needed to create a library\");\nfi\n\n# Checks for header files.\nAC_HEADER_STDC\n#AC_CHECK_HEADERS(sys/ioctl.h unistd.h)\n\n# Check for debug\nAC_MSG_CHECKING(whether to compile debug version)\nAC_ARG_ENABLE(debug,\n  [  --enable-debug = enable various debug output],\n  [AC_SUBST( cppflag, [-D__RTMIDI_DEBUG__] ) AC_SUBST( cxxflag, [-g] ) AC_SUBST( object_path, [Debug] ) AC_MSG_RESULT(yes)],\n  [AC_SUBST( cppflag, [] ) AC_SUBST( cxxflag, [-O3] ) AC_SUBST( object_path, [Release] ) AC_MSG_RESULT(no)])\n\n# For -I and -D flags\nCPPFLAGS=\"$CPPFLAGS $cppflag\"\n\n# For debugging and optimization ... overwrite default because it has both -g and -O2\n#CXXFLAGS=\"$CXXFLAGS $cxxflag\"\nCXXFLAGS=\"$cxxflag\"\n\n# Check compiler and use -Wall if gnu.\nif [test $GXX = \"yes\" ;] then\n  AC_SUBST( cxxflag, [-Wall] )\nfi\n\nCXXFLAGS=\"$CXXFLAGS $cxxflag\"\n\n# Checks for package options and external software\nAC_CANONICAL_HOST\n\nAC_SUBST( sharedlib, [\"librtmidi.so\"] )\nAC_SUBST( sharedname, [\"librtmidi.so.\\$(RELEASE)\"] )\nAC_SUBST( libflags, [\"-shared -Wl,-soname,\\$(SHARED).\\$(MAJOR) -o \\$(SHARED).\\$(RELEASE)\"] )\ncase $host in\n  *-apple*)\n  AC_SUBST( sharedlib, [\"librtmidi.dylib\"] )\n  AC_SUBST( sharedname, [\"librtmidi.\\$(RELEASE).dylib\"] )\n  AC_SUBST( libflags, [\"-dynamiclib -o librtmidi.\\$(RELEASE).dylib\"] )\nesac\n\nAC_SUBST( api, [\"\"] )\nAC_MSG_CHECKING(for MIDI API)\ncase $host in\n  *-*-linux*)\n  AC_ARG_WITH(jack, [  --with-jack = choose JACK server support (Mac OSC and GNU/Linux only)], [\n  api=\"$api -D__UNIX_JACK__\"\n  AC_MSG_RESULT(using JACK)\n  AC_CHECK_LIB(jack, jack_client_open, , AC_MSG_ERROR(JACK support requires the jack library!))], )\n\n  # Look for ALSA flag\n  AC_ARG_WITH(alsa, [  --with-alsa = choose native ALSA sequencer API support (GNU/Linux only)], [\n    api=\"$api -D__LINUX_ALSA__\"\n    AC_MSG_RESULT(using ALSA)\n    AC_CHECK_LIB(asound, snd_seq_open, , AC_MSG_ERROR(ALSA support requires the asound library!))], )\n\n  if [test \"$api\" == \"\";] then\n    AC_MSG_RESULT(using ALSA)\n    AC_SUBST( api, [-D__LINUX_ALSA__] )\n    AC_CHECK_LIB(asound, snd_seq_open, , AC_MSG_ERROR(ALSA sequencer support requires the asound library!))\n  fi\n\n  # Checks for pthread library.\n  AC_CHECK_LIB(pthread, pthread_create, , AC_MSG_ERROR(RtMidi requires the pthread library!))\n  ;;\n\n  *-apple*)\n  AC_ARG_WITH(jack, [  --with-jack = choose JACK server support (Mac OSX and GNU/Linux only)], [\n  api=\"$api -D__UNIX_JACK__\"\n  AC_MSG_RESULT(using JACK)\n  AC_CHECK_LIB(jack, jack_client_open, , AC_MSG_ERROR(JACK support requires the jack library!))], )\n\n  # Look for Core flag\n  AC_ARG_WITH(core, [  --with-core = choose CoreMidi API support (Mac OSX only)], [\n    api=\"$api -D__MACOSX_CORE__\"\n    AC_MSG_RESULT(using CoreMidi)\n    AC_CHECK_HEADER(CoreMIDI/CoreMIDI.h, [], [AC_MSG_ERROR(CoreMIDI header files not found!)] )\n    LIBS=\"$LIBS -framework CoreMIDI -framework CoreFoundation -framework CoreAudio\" ], )\n\n  # If no api flags specified, use CoreMidi\n  if [test \"$api\" == \"\"; ] then\n    AC_SUBST( api, [-D__MACOSX_CORE__] )\n    AC_MSG_RESULT(using CoreMidi)\n    AC_CHECK_HEADER(CoreMIDI/CoreMIDI.h,\n      [],\n      [AC_MSG_ERROR(CoreMIDI header files not found!)] )\n    AC_SUBST( LIBS, [\"-framework CoreMIDI -framework CoreFoundation -framework CoreAudio\"] )\n  fi\n  ;;\n\n  *-mingw32*)\n  # Look for WinMM flag\n  AC_ARG_WITH(winmm, [  --with-winmm = choose Windows MultiMedia (MM) API support (windoze only)], [\n    api=\"$api -D__WINDOWS_MM__\"\n    AC_MSG_RESULT(using WinMM)\n    AC_SUBST( LIBS, [-lwinmm] )], )\n\n  AC_ARG_WITH(winks, [  --with-winks = choose kernel streaming support (windoze only)], [\n    api=\"$api -D__WINDOWS_KS__\"\n    AC_SUBST( LIBS, [\"-lsetupapi -lksuser\"] )\n    AC_MSG_RESULT(using kernel streaming) ], )\n\n  # I can't get the following check to work so just manually add the library\n\t# or could try the following?  AC_LIB_WINMM([midiOutGetNumDevs])\n  # AC_CHECK_LIB(winmm, midiInGetNumDevs, , AC_MSG_ERROR(Windows MIDI support requires the winmm library!) )],)\n\n  # If no api flags specified, use WinMM\n  if [test \"$api\" == \"\";] then\n    AC_SUBST( api, [-D__WINDOWS_MM__] )\n    AC_MSG_RESULT(using WinMM)\n    AC_SUBST( LIBS, [-lwinmm] )\n  fi\n  ;;\n\n  *)\n  # Default case for unknown realtime systems.\n  AC_MSG_ERROR(Unknown system type for MIDI support!)\n  ;;\nesac\n\nCPPFLAGS=\"$CPPFLAGS $api\"\n\nAC_OUTPUT\n\nchmod oug+x rtmidi-config\n"
  },
  {
    "path": "rtmidi/include/ks.h",
    "content": "/**\n * This file has no copyright assigned and is placed in the Public Domain.\n * This file is part of the w64 mingw-runtime package.\n * No warranty is given.\n */\n#ifndef _KS_\n#define _KS_\n\n#include <winioctl.h>\n\n#if __GNUC__ >= 3\n # pragma GCC system_header\n#endif\n\n#ifndef __MINGW_EXTENSION\n # if defined(__GNUC__) || defined(__GNUG__)\n  #  define __MINGW_EXTENSION __extension__\n # else\n  #  define __MINGW_EXTENSION\n # endif\n#endif\n\n#ifdef __TCS__\n # define _KS_NO_ANONYMOUS_STRUCTURES_ 1\n#endif\n\n#ifdef  _KS_NO_ANONYMOUS_STRUCTURES_\n # define _KS_ANON_STRUCT(X) struct X\n#else\n # define _KS_ANON_STRUCT(X) __MINGW_EXTENSION struct\n#endif\n\n#ifndef _NTRTL_\n # ifndef DEFINE_GUIDEX\n  #  define DEFINE_GUIDEX(name) EXTERN_C const GUID name\n # endif\n # ifndef STATICGUIDOF\n  #  define STATICGUIDOF(guid) STATIC_ ## guid\n # endif\n#endif /* _NTRTL_ */\n\n#ifndef SIZEOF_ARRAY\n # define SIZEOF_ARRAY(ar) (sizeof(ar) / sizeof((ar)[0]))\n#endif\n\n#define DEFINE_GUIDSTRUCT(g, n) DEFINE_GUIDEX(n)\n#define DEFINE_GUIDNAMED(n) n\n\n#define STATIC_GUID_NULL                        \\\n  0x00000000L, 0x0000, 0x0000, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }\n\nDEFINE_GUIDSTRUCT(\"00000000-0000-0000-0000-000000000000\", GUID_NULL);\n#define GUID_NULL DEFINE_GUIDNAMED(GUID_NULL)\n\n#define IOCTL_KS_PROPERTY CTL_CODE(FILE_DEVICE_KS, 0x000, METHOD_NEITHER, FILE_ANY_ACCESS)\n#define IOCTL_KS_ENABLE_EVENT CTL_CODE(FILE_DEVICE_KS, 0x001, METHOD_NEITHER, FILE_ANY_ACCESS)\n#define IOCTL_KS_DISABLE_EVENT CTL_CODE(FILE_DEVICE_KS, 0x002, METHOD_NEITHER, FILE_ANY_ACCESS)\n#define IOCTL_KS_METHOD CTL_CODE(FILE_DEVICE_KS, 0x003, METHOD_NEITHER, FILE_ANY_ACCESS)\n#define IOCTL_KS_WRITE_STREAM CTL_CODE(FILE_DEVICE_KS, 0x004, METHOD_NEITHER, FILE_WRITE_ACCESS)\n#define IOCTL_KS_READ_STREAM CTL_CODE(FILE_DEVICE_KS, 0x005, METHOD_NEITHER, FILE_READ_ACCESS)\n#define IOCTL_KS_RESET_STATE CTL_CODE(FILE_DEVICE_KS, 0x006, METHOD_NEITHER, FILE_ANY_ACCESS)\n\ntypedef enum\n{\n  KSRESET_BEGIN,\n  KSRESET_END\n}KSRESET;\n\ntypedef enum\n{\n  KSSTATE_STOP,\n  KSSTATE_ACQUIRE,\n  KSSTATE_PAUSE,\n  KSSTATE_RUN\n}KSSTATE, * PKSSTATE;\n\n#define KSPRIORITY_LOW 0x00000001\n#define KSPRIORITY_NORMAL 0x40000000\n#define KSPRIORITY_HIGH 0x80000000\n#define KSPRIORITY_EXCLUSIVE 0xFFFFFFFF\n\ntypedef struct\n{\n  ULONG PriorityClass;\n  ULONG PrioritySubClass;\n}KSPRIORITY, * PKSPRIORITY;\n\ntypedef struct\n{\n  __MINGW_EXTENSION union\n  {\n    _KS_ANON_STRUCT(_IDENTIFIER)\n    {\n      GUID Set;\n      ULONG Id;\n      ULONG Flags;\n    };\n    LONGLONG Alignment;\n  };\n}KSIDENTIFIER, * PKSIDENTIFIER;\n\ntypedef KSIDENTIFIER KSPROPERTY, * PKSPROPERTY, KSMETHOD, * PKSMETHOD, KSEVENT, * PKSEVENT;\n\n#define KSMETHOD_TYPE_NONE 0x00000000\n#define KSMETHOD_TYPE_READ 0x00000001\n#define KSMETHOD_TYPE_WRITE 0x00000002\n#define KSMETHOD_TYPE_MODIFY 0x00000003\n#define KSMETHOD_TYPE_SOURCE 0x00000004\n\n#define KSMETHOD_TYPE_SEND 0x00000001\n#define KSMETHOD_TYPE_SETSUPPORT 0x00000100\n#define KSMETHOD_TYPE_BASICSUPPORT 0x00000200\n\n#define KSMETHOD_TYPE_TOPOLOGY 0x10000000\n\n#define KSPROPERTY_TYPE_GET 0x00000001\n#define KSPROPERTY_TYPE_SET 0x00000002\n#define KSPROPERTY_TYPE_SETSUPPORT 0x00000100\n#define KSPROPERTY_TYPE_BASICSUPPORT 0x00000200\n#define KSPROPERTY_TYPE_RELATIONS 0x00000400\n#define KSPROPERTY_TYPE_SERIALIZESET 0x00000800\n#define KSPROPERTY_TYPE_UNSERIALIZESET 0x00001000\n#define KSPROPERTY_TYPE_SERIALIZERAW 0x00002000\n#define KSPROPERTY_TYPE_UNSERIALIZERAW 0x00004000\n#define KSPROPERTY_TYPE_SERIALIZESIZE 0x00008000\n#define KSPROPERTY_TYPE_DEFAULTVALUES 0x00010000\n\n#define KSPROPERTY_TYPE_TOPOLOGY 0x10000000\n\ntypedef struct\n{\n  KSPROPERTY Property;\n  ULONG NodeId;\n  ULONG Reserved;\n}KSP_NODE, * PKSP_NODE;\n\ntypedef struct\n{\n  KSMETHOD Method;\n  ULONG NodeId;\n  ULONG Reserved;\n}KSM_NODE, * PKSM_NODE;\n\ntypedef struct\n{\n  KSEVENT Event;\n  ULONG NodeId;\n  ULONG Reserved;\n}KSE_NODE, * PKSE_NODE;\n\n#define STATIC_KSPROPTYPESETID_General                  \\\n  0x97E99BA0L, 0xBDEA, 0x11CF, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00\nDEFINE_GUIDSTRUCT(\"97E99BA0-BDEA-11CF-A5D6-28DB04C10000\", KSPROPTYPESETID_General);\n#define KSPROPTYPESETID_General DEFINE_GUIDNAMED(KSPROPTYPESETID_General)\n\ntypedef struct\n{\n  ULONG Size;\n  ULONG Count;\n}KSMULTIPLE_ITEM, * PKSMULTIPLE_ITEM;\n\ntypedef struct\n{\n  ULONG AccessFlags;\n  ULONG DescriptionSize;\n  KSIDENTIFIER PropTypeSet;\n  ULONG MembersListCount;\n  ULONG Reserved;\n}KSPROPERTY_DESCRIPTION, * PKSPROPERTY_DESCRIPTION;\n\n#define KSPROPERTY_MEMBER_RANGES 0x00000001\n#define KSPROPERTY_MEMBER_STEPPEDRANGES 0x00000002\n#define KSPROPERTY_MEMBER_VALUES 0x00000003\n\n#define KSPROPERTY_MEMBER_FLAG_DEFAULT 0x00000001\n#define KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_MULTICHANNEL 0x00000002\n#define KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_UNIFORM 0x00000004\n\ntypedef struct\n{\n  ULONG MembersFlags;\n  ULONG MembersSize;\n  ULONG MembersCount;\n  ULONG Flags;\n}KSPROPERTY_MEMBERSHEADER, * PKSPROPERTY_MEMBERSHEADER;\n\ntypedef union\n{\n  _KS_ANON_STRUCT(_SIGNED)\n  {\n    LONG SignedMinimum;\n    LONG SignedMaximum;\n  };\n  _KS_ANON_STRUCT(_UNSIGNED)\n  {\n    ULONG UnsignedMinimum;\n    ULONG UnsignedMaximum;\n  };\n}KSPROPERTY_BOUNDS_LONG, * PKSPROPERTY_BOUNDS_LONG;\n\ntypedef union\n{\n  _KS_ANON_STRUCT(_SIGNED64)\n  {\n    LONGLONG SignedMinimum;\n    LONGLONG SignedMaximum;\n  };\n  _KS_ANON_STRUCT(_UNSIGNED64)\n  {\n    DWORDLONG UnsignedMinimum;\n    DWORDLONG UnsignedMaximum;\n  };\n}KSPROPERTY_BOUNDS_LONGLONG, * PKSPROPERTY_BOUNDS_LONGLONG;\n\ntypedef struct\n{\n  ULONG SteppingDelta;\n  ULONG Reserved;\n  KSPROPERTY_BOUNDS_LONG Bounds;\n}KSPROPERTY_STEPPING_LONG, * PKSPROPERTY_STEPPING_LONG;\n\ntypedef struct\n{\n  DWORDLONG SteppingDelta;\n  KSPROPERTY_BOUNDS_LONGLONG Bounds;\n}KSPROPERTY_STEPPING_LONGLONG, * PKSPROPERTY_STEPPING_LONGLONG;\n\n#if defined(_NTDDK_)\ntypedef struct _KSDEVICE_DESCRIPTOR KSDEVICE_DESCRIPTOR, * PKSDEVICE_DESCRIPTOR;\ntypedef struct _KSDEVICE_DISPATCH KSDEVICE_DISPATCH, * PKSDEVICE_DISPATCH;\ntypedef struct _KSDEVICE KSDEVICE, * PKSDEVICE;\ntypedef struct _KSFILTERFACTORY KSFILTERFACTORY, * PKSFILTERFACTORY;\ntypedef struct _KSFILTER_DESCRIPTOR KSFILTER_DESCRIPTOR, * PKSFILTER_DESCRIPTOR;\ntypedef struct _KSFILTER_DISPATCH KSFILTER_DISPATCH, * PKSFILTER_DISPATCH;\ntypedef struct _KSFILTER KSFILTER, * PKSFILTER;\ntypedef struct _KSPIN_DESCRIPTOR_EX KSPIN_DESCRIPTOR_EX, * PKSPIN_DESCRIPTOR_EX;\ntypedef struct _KSPIN_DISPATCH KSPIN_DISPATCH, * PKSPIN_DISPATCH;\ntypedef struct _KSCLOCK_DISPATCH KSCLOCK_DISPATCH, * PKSCLOCK_DISPATCH;\ntypedef struct _KSALLOCATOR_DISPATCH KSALLOCATOR_DISPATCH, * PKSALLOCATOR_DISPATCH;\ntypedef struct _KSPIN KSPIN, * PKSPIN;\ntypedef struct _KSNODE_DESCRIPTOR KSNODE_DESCRIPTOR, * PKSNODE_DESCRIPTOR;\ntypedef struct _KSSTREAM_POINTER_OFFSET KSSTREAM_POINTER_OFFSET, * PKSSTREAM_POINTER_OFFSET;\ntypedef struct _KSSTREAM_POINTER KSSTREAM_POINTER, * PKSSTREAM_POINTER;\ntypedef struct _KSMAPPING KSMAPPING, * PKSMAPPING;\ntypedef struct _KSPROCESSPIN KSPROCESSPIN, * PKSPROCESSPIN;\ntypedef struct _KSPROCESSPIN_INDEXENTRY KSPROCESSPIN_INDEXENTRY, * PKSPROCESSPIN_INDEXENTRY;\n#endif /* _NTDDK_ */\n\ntypedef PVOID PKSWORKER;\n\ntypedef struct\n{\n  ULONG NotificationType;\n  __MINGW_EXTENSION union\n  {\n    struct\n    {\n      HANDLE Event;\n      ULONG_PTR Reserved[2];\n    }EventHandle;\n    struct\n    {\n      HANDLE Semaphore;\n      ULONG Reserved;\n      LONG Adjustment;\n    }SemaphoreHandle;\n#if defined(_NTDDK_)\n    struct\n    {\n      PVOID Event;\n      KPRIORITY Increment;\n      ULONG_PTR Reserved;\n    }EventObject;\n    struct\n    {\n      PVOID Semaphore;\n      KPRIORITY Increment;\n      LONG Adjustment;\n    }SemaphoreObject;\n    struct\n    {\n      PKDPC Dpc;\n      ULONG ReferenceCount;\n      ULONG_PTR Reserved;\n    }Dpc;\n    struct\n    {\n      PWORK_QUEUE_ITEM WorkQueueItem;\n      WORK_QUEUE_TYPE WorkQueueType;\n      ULONG_PTR Reserved;\n    }WorkItem;\n    struct\n    {\n      PWORK_QUEUE_ITEM WorkQueueItem;\n      PKSWORKER KsWorkerObject;\n      ULONG_PTR Reserved;\n    }KsWorkItem;\n#endif /* _NTDDK_ */\n    struct\n    {\n      PVOID Unused;\n      LONG_PTR Alignment[2];\n    }Alignment;\n  };\n}KSEVENTDATA, * PKSEVENTDATA;\n\n#define KSEVENTF_EVENT_HANDLE 0x00000001\n#define KSEVENTF_SEMAPHORE_HANDLE 0x00000002\n#if defined(_NTDDK_)\n # define KSEVENTF_EVENT_OBJECT 0x00000004\n # define KSEVENTF_SEMAPHORE_OBJECT 0x00000008\n # define KSEVENTF_DPC 0x00000010\n # define KSEVENTF_WORKITEM 0x00000020\n # define KSEVENTF_KSWORKITEM 0x00000080\n#endif /* _NTDDK_ */\n\n#define KSEVENT_TYPE_ENABLE 0x00000001\n#define KSEVENT_TYPE_ONESHOT 0x00000002\n#define KSEVENT_TYPE_ENABLEBUFFERED 0x00000004\n#define KSEVENT_TYPE_SETSUPPORT 0x00000100\n#define KSEVENT_TYPE_BASICSUPPORT 0x00000200\n#define KSEVENT_TYPE_QUERYBUFFER 0x00000400\n\n#define KSEVENT_TYPE_TOPOLOGY 0x10000000\n\ntypedef struct\n{\n  KSEVENT Event;\n  PKSEVENTDATA EventData;\n  PVOID Reserved;\n}KSQUERYBUFFER, * PKSQUERYBUFFER;\n\ntypedef struct\n{\n  ULONG Size;\n  ULONG Flags;\n  __MINGW_EXTENSION union\n  {\n    HANDLE ObjectHandle;\n    PVOID ObjectPointer;\n  };\n  PVOID Reserved;\n  KSEVENT Event;\n  KSEVENTDATA EventData;\n}KSRELATIVEEVENT;\n\n#define KSRELATIVEEVENT_FLAG_HANDLE 0x00000001\n#define KSRELATIVEEVENT_FLAG_POINTER 0x00000002\n\ntypedef struct\n{\n  KSEVENTDATA EventData;\n  LONGLONG MarkTime;\n}KSEVENT_TIME_MARK, * PKSEVENT_TIME_MARK;\n\ntypedef struct\n{\n  KSEVENTDATA EventData;\n  LONGLONG TimeBase;\n  LONGLONG Interval;\n}KSEVENT_TIME_INTERVAL, * PKSEVENT_TIME_INTERVAL;\n\ntypedef struct\n{\n  LONGLONG TimeBase;\n  LONGLONG Interval;\n}KSINTERVAL, * PKSINTERVAL;\n\n#define STATIC_KSPROPSETID_General                  \\\n  0x1464EDA5L, 0x6A8F, 0x11D1, 0x9A, 0xA7, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96\nDEFINE_GUIDSTRUCT(\"1464EDA5-6A8F-11D1-9AA7-00A0C9223196\", KSPROPSETID_General);\n#define KSPROPSETID_General DEFINE_GUIDNAMED(KSPROPSETID_General)\n\ntypedef enum\n{\n  KSPROPERTY_GENERAL_COMPONENTID\n}KSPROPERTY_GENERAL;\n\ntypedef struct\n{\n  GUID Manufacturer;\n  GUID Product;\n  GUID Component;\n  GUID Name;\n  ULONG Version;\n  ULONG Revision;\n}KSCOMPONENTID, * PKSCOMPONENTID;\n\n#define DEFINE_KSPROPERTY_ITEM_GENERAL_COMPONENTID(Handler)     \\\n  DEFINE_KSPROPERTY_ITEM(                     \\\n    KSPROPERTY_GENERAL_COMPONENTID,     \\\n    (Handler),              \\\n    sizeof(KSPROPERTY),         \\\n    sizeof(KSCOMPONENTID),          \\\n    NULL, NULL, 0, NULL, NULL, 0)\n\n#define STATIC_KSMETHODSETID_StreamIo   \\\n  0x65D003CAL, 0x1523, 0x11D2, 0xB2, 0x7A, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96\nDEFINE_GUIDSTRUCT(\"65D003CA-1523-11D2-B27A-00A0C9223196\", KSMETHODSETID_StreamIo);\n#define KSMETHODSETID_StreamIo DEFINE_GUIDNAMED(KSMETHODSETID_StreamIo)\n\ntypedef enum\n{\n  KSMETHOD_STREAMIO_READ,\n  KSMETHOD_STREAMIO_WRITE\n}KSMETHOD_STREAMIO;\n\n#define DEFINE_KSMETHOD_ITEM_STREAMIO_READ(Handler)         \\\n  DEFINE_KSMETHOD_ITEM(                       \\\n    KSMETHOD_STREAMIO_READ,         \\\n    KSMETHOD_TYPE_WRITE,            \\\n    (Handler),              \\\n    sizeof(KSMETHOD),           \\\n    0,                  \\\n    NULL)\n\n#define DEFINE_KSMETHOD_ITEM_STREAMIO_WRITE(Handler)            \\\n  DEFINE_KSMETHOD_ITEM(                       \\\n    KSMETHOD_STREAMIO_WRITE,        \\\n    KSMETHOD_TYPE_READ,         \\\n    (Handler),              \\\n    sizeof(KSMETHOD),           \\\n    0,                  \\\n    NULL)\n\n#define STATIC_KSPROPSETID_MediaSeeking                 \\\n  0xEE904F0CL, 0xD09B, 0x11D0, 0xAB, 0xE9, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96\nDEFINE_GUIDSTRUCT(\"EE904F0C-D09B-11D0-ABE9-00A0C9223196\", KSPROPSETID_MediaSeeking);\n#define KSPROPSETID_MediaSeeking DEFINE_GUIDNAMED(KSPROPSETID_MediaSeeking)\n\ntypedef enum\n{\n  KSPROPERTY_MEDIASEEKING_CAPABILITIES,\n  KSPROPERTY_MEDIASEEKING_FORMATS,\n  KSPROPERTY_MEDIASEEKING_TIMEFORMAT,\n  KSPROPERTY_MEDIASEEKING_POSITION,\n  KSPROPERTY_MEDIASEEKING_STOPPOSITION,\n  KSPROPERTY_MEDIASEEKING_POSITIONS,\n  KSPROPERTY_MEDIASEEKING_DURATION,\n  KSPROPERTY_MEDIASEEKING_AVAILABLE,\n  KSPROPERTY_MEDIASEEKING_PREROLL,\n  KSPROPERTY_MEDIASEEKING_CONVERTTIMEFORMAT\n}KSPROPERTY_MEDIASEEKING;\n\ntypedef enum\n{\n  KS_SEEKING_NoPositioning,\n  KS_SEEKING_AbsolutePositioning,\n  KS_SEEKING_RelativePositioning,\n  KS_SEEKING_IncrementalPositioning,\n  KS_SEEKING_PositioningBitsMask = 0x3,\n  KS_SEEKING_SeekToKeyFrame,\n  KS_SEEKING_ReturnTime = 0x8\n}KS_SEEKING_FLAGS;\n\ntypedef enum\n{\n  KS_SEEKING_CanSeekAbsolute = 0x1,\n  KS_SEEKING_CanSeekForwards = 0x2,\n  KS_SEEKING_CanSeekBackwards = 0x4,\n  KS_SEEKING_CanGetCurrentPos = 0x8,\n  KS_SEEKING_CanGetStopPos = 0x10,\n  KS_SEEKING_CanGetDuration = 0x20,\n  KS_SEEKING_CanPlayBackwards = 0x40\n}KS_SEEKING_CAPABILITIES;\n\ntypedef struct\n{\n  LONGLONG Current;\n  LONGLONG Stop;\n  KS_SEEKING_FLAGS CurrentFlags;\n  KS_SEEKING_FLAGS StopFlags;\n}KSPROPERTY_POSITIONS, * PKSPROPERTY_POSITIONS;\n\ntypedef struct\n{\n  LONGLONG Earliest;\n  LONGLONG Latest;\n}KSPROPERTY_MEDIAAVAILABLE, * PKSPROPERTY_MEDIAAVAILABLE;\n\ntypedef struct\n{\n  KSPROPERTY Property;\n  GUID SourceFormat;\n  GUID TargetFormat;\n  LONGLONG Time;\n}KSP_TIMEFORMAT, * PKSP_TIMEFORMAT;\n\n#define DEFINE_KSPROPERTY_ITEM_MEDIASEEKING_CAPABILITIES(Handler)   \\\n  DEFINE_KSPROPERTY_ITEM(                     \\\n    KSPROPERTY_MEDIASEEKING_CAPABILITIES,   \\\n    (Handler),              \\\n    sizeof(KSPROPERTY),         \\\n    sizeof(KS_SEEKING_CAPABILITIES),    \\\n    NULL, NULL, 0, NULL, NULL, 0)\n\n#define DEFINE_KSPROPERTY_ITEM_MEDIASEEKING_FORMATS(Handler)        \\\n  DEFINE_KSPROPERTY_ITEM(                     \\\n    KSPROPERTY_MEDIASEEKING_FORMATS,    \\\n    (Handler),              \\\n    sizeof(KSPROPERTY),         \\\n    0,                  \\\n    NULL, NULL, 0, NULL, NULL, 0)\n\n#define DEFINE_KSPROPERTY_ITEM_MEDIASEEKING_TIMEFORMAT(GetHandler, SetHandler) \\\n  DEFINE_KSPROPERTY_ITEM(                     \\\n    KSPROPERTY_MEDIASEEKING_TIMEFORMAT, \\\n    (GetHandler),               \\\n    sizeof(KSPROPERTY),         \\\n    sizeof(GUID),               \\\n    (SetHandler),               \\\n    NULL, 0, NULL, NULL, 0)\n\n#define DEFINE_KSPROPERTY_ITEM_MEDIASEEKING_POSITION(Handler)       \\\n  DEFINE_KSPROPERTY_ITEM(                     \\\n    KSPROPERTY_MEDIASEEKING_POSITION,   \\\n    (Handler),              \\\n    sizeof(KSPROPERTY),         \\\n    sizeof(LONGLONG),           \\\n    NULL, NULL, 0, NULL, NULL, 0)\n\n#define DEFINE_KSPROPERTY_ITEM_MEDIASEEKING_STOPPOSITION(Handler)   \\\n  DEFINE_KSPROPERTY_ITEM(                     \\\n    KSPROPERTY_MEDIASEEKING_STOPPOSITION,   \\\n    (Handler),              \\\n    sizeof(KSPROPERTY),         \\\n    sizeof(LONGLONG),           \\\n    NULL, NULL, 0, NULL, NULL, 0)\n\n#define DEFINE_KSPROPERTY_ITEM_MEDIASEEKING_POSITIONS(Handler)      \\\n  DEFINE_KSPROPERTY_ITEM(                     \\\n    KSPROPERTY_MEDIASEEKING_POSITIONS,  \\\n    NULL,                   \\\n    sizeof(KSPROPERTY),         \\\n    sizeof(KSPROPERTY_POSITIONS),       \\\n    (Handler),              \\\n    NULL, 0, NULL, NULL, 0)\n\n#define DEFINE_KSPROPERTY_ITEM_MEDIASEEKING_DURATION(Handler)       \\\n  DEFINE_KSPROPERTY_ITEM(                     \\\n    KSPROPERTY_MEDIASEEKING_DURATION,   \\\n    (Handler),              \\\n    sizeof(KSPROPERTY),         \\\n    sizeof(LONGLONG),           \\\n    NULL, NULL, 0, NULL, NULL, 0)\n\n#define DEFINE_KSPROPERTY_ITEM_MEDIASEEKING_AVAILABLE(Handler)      \\\n  DEFINE_KSPROPERTY_ITEM(                     \\\n    KSPROPERTY_MEDIASEEKING_AVAILABLE,  \\\n    (Handler),              \\\n    sizeof(KSPROPERTY),         \\\n    sizeof(KSPROPERTY_MEDIAAVAILABLE),  \\\n    NULL, NULL, 0, NULL, NULL, 0)\n\n#define DEFINE_KSPROPERTY_ITEM_MEDIASEEKING_PREROLL(Handler)        \\\n  DEFINE_KSPROPERTY_ITEM(                     \\\n    KSPROPERTY_MEDIASEEKING_PREROLL,    \\\n    (Handler),              \\\n    sizeof(KSPROPERTY),         \\\n    sizeof(LONGLONG),           \\\n    NULL, NULL, 0, NULL, NULL, 0)\n\n#define DEFINE_KSPROPERTY_ITEM_MEDIASEEKING_CONVERTTIMEFORMAT(Handler)  \\\n  DEFINE_KSPROPERTY_ITEM(                     \\\n    KSPROPERTY_MEDIASEEKING_CONVERTTIMEFORMAT, \\\n    (Handler),              \\\n    sizeof(KSP_TIMEFORMAT),         \\\n    sizeof(LONGLONG),           \\\n    NULL, NULL, 0, NULL, NULL, 0)\n\n#define STATIC_KSPROPSETID_Topology                 \\\n  0x720D4AC0L, 0x7533, 0x11D0, { 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 }\nDEFINE_GUIDSTRUCT(\"720D4AC0-7533-11D0-A5D6-28DB04C10000\", KSPROPSETID_Topology);\n#define KSPROPSETID_Topology DEFINE_GUIDNAMED(KSPROPSETID_Topology)\n\ntypedef enum\n{\n  KSPROPERTY_TOPOLOGY_CATEGORIES,\n  KSPROPERTY_TOPOLOGY_NODES,\n  KSPROPERTY_TOPOLOGY_CONNECTIONS,\n  KSPROPERTY_TOPOLOGY_NAME\n}KSPROPERTY_TOPOLOGY;\n\n#define DEFINE_KSPROPERTY_ITEM_TOPOLOGY_CATEGORIES(Handler)     \\\n  DEFINE_KSPROPERTY_ITEM(                     \\\n    KSPROPERTY_TOPOLOGY_CATEGORIES,     \\\n    (Handler),              \\\n    sizeof(KSPROPERTY),         \\\n    0,                  \\\n    NULL, NULL, 0, NULL, NULL, 0)\n\n#define DEFINE_KSPROPERTY_ITEM_TOPOLOGY_NODES(Handler)          \\\n  DEFINE_KSPROPERTY_ITEM(                     \\\n    KSPROPERTY_TOPOLOGY_NODES,      \\\n    (Handler),              \\\n    sizeof(KSPROPERTY),         \\\n    0,                  \\\n    NULL, NULL, 0, NULL, NULL, 0)\n\n#define DEFINE_KSPROPERTY_ITEM_TOPOLOGY_CONNECTIONS(Handler)        \\\n  DEFINE_KSPROPERTY_ITEM(                     \\\n    KSPROPERTY_TOPOLOGY_CONNECTIONS,    \\\n    (Handler),              \\\n    sizeof(KSPROPERTY),         \\\n    0,                  \\\n    NULL, NULL, 0, NULL, NULL, 0)\n\n#define DEFINE_KSPROPERTY_ITEM_TOPOLOGY_NAME(Handler)           \\\n  DEFINE_KSPROPERTY_ITEM(                     \\\n    KSPROPERTY_TOPOLOGY_NAME,       \\\n    (Handler),              \\\n    sizeof(KSP_NODE),           \\\n    0,                  \\\n    NULL, NULL, 0, NULL, NULL, 0)\n\n#define DEFINE_KSPROPERTY_TOPOLOGYSET(TopologySet, Handler)      \\\n  DEFINE_KSPROPERTY_TABLE(TopologySet) {                  \\\n    DEFINE_KSPROPERTY_ITEM_TOPOLOGY_CATEGORIES(Handler),        \\\n    DEFINE_KSPROPERTY_ITEM_TOPOLOGY_NODES(Handler),         \\\n    DEFINE_KSPROPERTY_ITEM_TOPOLOGY_CONNECTIONS(Handler),       \\\n    DEFINE_KSPROPERTY_ITEM_TOPOLOGY_NAME(Handler)           \\\n  }\n\n#define STATIC_KSCATEGORY_BRIDGE                    \\\n  0x085AFF00L, 0x62CE, 0x11CF, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00\nDEFINE_GUIDSTRUCT(\"085AFF00-62CE-11CF-A5D6-28DB04C10000\", KSCATEGORY_BRIDGE);\n#define KSCATEGORY_BRIDGE DEFINE_GUIDNAMED(KSCATEGORY_BRIDGE)\n\n#define STATIC_KSCATEGORY_CAPTURE                   \\\n  0x65E8773DL, 0x8F56, 0x11D0, { 0xA3, 0xB9, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 }\nDEFINE_GUIDSTRUCT(\"65E8773D-8F56-11D0-A3B9-00A0C9223196\", KSCATEGORY_CAPTURE);\n#define KSCATEGORY_CAPTURE DEFINE_GUIDNAMED(KSCATEGORY_CAPTURE)\n\n#define STATIC_KSCATEGORY_RENDER                    \\\n  0x65E8773EL, 0x8F56, 0x11D0, { 0xA3, 0xB9, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 }\nDEFINE_GUIDSTRUCT(\"65E8773E-8F56-11D0-A3B9-00A0C9223196\", KSCATEGORY_RENDER);\n#define KSCATEGORY_RENDER DEFINE_GUIDNAMED(KSCATEGORY_RENDER)\n\n#define STATIC_KSCATEGORY_MIXER                     \\\n  0xAD809C00L, 0x7B88, 0x11D0, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00\nDEFINE_GUIDSTRUCT(\"AD809C00-7B88-11D0-A5D6-28DB04C10000\", KSCATEGORY_MIXER);\n#define KSCATEGORY_MIXER DEFINE_GUIDNAMED(KSCATEGORY_MIXER)\n\n#define STATIC_KSCATEGORY_SPLITTER                  \\\n  0x0A4252A0L, 0x7E70, 0x11D0, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00\nDEFINE_GUIDSTRUCT(\"0A4252A0-7E70-11D0-A5D6-28DB04C10000\", KSCATEGORY_SPLITTER);\n#define KSCATEGORY_SPLITTER DEFINE_GUIDNAMED(KSCATEGORY_SPLITTER)\n\n#define STATIC_KSCATEGORY_DATACOMPRESSOR                \\\n  0x1E84C900L, 0x7E70, 0x11D0, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00\nDEFINE_GUIDSTRUCT(\"1E84C900-7E70-11D0-A5D6-28DB04C10000\", KSCATEGORY_DATACOMPRESSOR);\n#define KSCATEGORY_DATACOMPRESSOR DEFINE_GUIDNAMED(KSCATEGORY_DATACOMPRESSOR)\n\n#define STATIC_KSCATEGORY_DATADECOMPRESSOR              \\\n  0x2721AE20L, 0x7E70, 0x11D0, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00\nDEFINE_GUIDSTRUCT(\"2721AE20-7E70-11D0-A5D6-28DB04C10000\", KSCATEGORY_DATADECOMPRESSOR);\n#define KSCATEGORY_DATADECOMPRESSOR DEFINE_GUIDNAMED(KSCATEGORY_DATADECOMPRESSOR)\n\n#define STATIC_KSCATEGORY_DATATRANSFORM                 \\\n  0x2EB07EA0L, 0x7E70, 0x11D0, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00\nDEFINE_GUIDSTRUCT(\"2EB07EA0-7E70-11D0-A5D6-28DB04C10000\", KSCATEGORY_DATATRANSFORM);\n#define KSCATEGORY_DATATRANSFORM DEFINE_GUIDNAMED(KSCATEGORY_DATATRANSFORM)\n\n#define STATIC_KSCATEGORY_COMMUNICATIONSTRANSFORM           \\\n  0xCF1DDA2CL, 0x9743, 0x11D0, 0xA3, 0xEE, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96\nDEFINE_GUIDSTRUCT(\"CF1DDA2C-9743-11D0-A3EE-00A0C9223196\", KSCATEGORY_COMMUNICATIONSTRANSFORM);\n#define KSCATEGORY_COMMUNICATIONSTRANSFORM DEFINE_GUIDNAMED(KSCATEGORY_COMMUNICATIONSTRANSFORM)\n\n#define STATIC_KSCATEGORY_INTERFACETRANSFORM                \\\n  0xCF1DDA2DL, 0x9743, 0x11D0, 0xA3, 0xEE, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96\nDEFINE_GUIDSTRUCT(\"CF1DDA2D-9743-11D0-A3EE-00A0C9223196\", KSCATEGORY_INTERFACETRANSFORM);\n#define KSCATEGORY_INTERFACETRANSFORM DEFINE_GUIDNAMED(KSCATEGORY_INTERFACETRANSFORM)\n\n#define STATIC_KSCATEGORY_MEDIUMTRANSFORM               \\\n  0xCF1DDA2EL, 0x9743, 0x11D0, 0xA3, 0xEE, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96\nDEFINE_GUIDSTRUCT(\"CF1DDA2E-9743-11D0-A3EE-00A0C9223196\", KSCATEGORY_MEDIUMTRANSFORM);\n#define KSCATEGORY_MEDIUMTRANSFORM DEFINE_GUIDNAMED(KSCATEGORY_MEDIUMTRANSFORM)\n\n#define STATIC_KSCATEGORY_FILESYSTEM                    \\\n  0x760FED5EL, 0x9357, 0x11D0, 0xA3, 0xCC, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96\nDEFINE_GUIDSTRUCT(\"760FED5E-9357-11D0-A3CC-00A0C9223196\", KSCATEGORY_FILESYSTEM);\n#define KSCATEGORY_FILESYSTEM DEFINE_GUIDNAMED(KSCATEGORY_FILESYSTEM)\n\n#define STATIC_KSCATEGORY_CLOCK                     \\\n  0x53172480L, 0x4791, 0x11D0, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00\nDEFINE_GUIDSTRUCT(\"53172480-4791-11D0-A5D6-28DB04C10000\", KSCATEGORY_CLOCK);\n#define KSCATEGORY_CLOCK DEFINE_GUIDNAMED(KSCATEGORY_CLOCK)\n\n#define STATIC_KSCATEGORY_PROXY                     \\\n  0x97EBAACAL, 0x95BD, 0x11D0, 0xA3, 0xEA, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96\nDEFINE_GUIDSTRUCT(\"97EBAACA-95BD-11D0-A3EA-00A0C9223196\", KSCATEGORY_PROXY);\n#define KSCATEGORY_PROXY DEFINE_GUIDNAMED(KSCATEGORY_PROXY)\n\n#define STATIC_KSCATEGORY_QUALITY                   \\\n  0x97EBAACBL, 0x95BD, 0x11D0, 0xA3, 0xEA, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96\nDEFINE_GUIDSTRUCT(\"97EBAACB-95BD-11D0-A3EA-00A0C9223196\", KSCATEGORY_QUALITY);\n#define KSCATEGORY_QUALITY DEFINE_GUIDNAMED(KSCATEGORY_QUALITY)\n\ntypedef struct\n{\n  ULONG FromNode;\n  ULONG FromNodePin;\n  ULONG ToNode;\n  ULONG ToNodePin;\n}KSTOPOLOGY_CONNECTION, * PKSTOPOLOGY_CONNECTION;\n\ntypedef struct\n{\n  ULONG CategoriesCount;\n  const GUID* Categories;\n  ULONG TopologyNodesCount;\n  const GUID* TopologyNodes;\n  ULONG TopologyConnectionsCount;\n  const KSTOPOLOGY_CONNECTION* TopologyConnections;\n  const GUID* TopologyNodesNames;\n  ULONG Reserved;\n}KSTOPOLOGY, * PKSTOPOLOGY;\n\n#define KSFILTER_NODE ((ULONG)-1)\n#define KSALL_NODES ((ULONG)-1)\n\ntypedef struct\n{\n  ULONG CreateFlags;\n  ULONG Node;\n}KSNODE_CREATE, * PKSNODE_CREATE;\n\n#define STATIC_KSTIME_FORMAT_NONE STATIC_GUID_NULL\n#define KSTIME_FORMAT_NONE GUID_NULL\n\n#define STATIC_KSTIME_FORMAT_FRAME                  \\\n  0x7b785570L, 0x8c82, 0x11cf, 0xbc, 0x0c, 0x00, 0xaa, 0x00, 0xac, 0x74, 0xf6\nDEFINE_GUIDSTRUCT(\"7b785570-8c82-11cf-bc0c-00aa00ac74f6\", KSTIME_FORMAT_FRAME);\n#define KSTIME_FORMAT_FRAME DEFINE_GUIDNAMED(KSTIME_FORMAT_FRAME)\n\n#define STATIC_KSTIME_FORMAT_BYTE                   \\\n  0x7b785571L, 0x8c82, 0x11cf, 0xbc, 0x0c, 0x00, 0xaa, 0x00, 0xac, 0x74, 0xf6\nDEFINE_GUIDSTRUCT(\"7b785571-8c82-11cf-bc0c-00aa00ac74f6\", KSTIME_FORMAT_BYTE);\n#define KSTIME_FORMAT_BYTE DEFINE_GUIDNAMED(KSTIME_FORMAT_BYTE)\n\n#define STATIC_KSTIME_FORMAT_SAMPLE                 \\\n  0x7b785572L, 0x8c82, 0x11cf, 0xbc, 0x0c, 0x00, 0xaa, 0x00, 0xac, 0x74, 0xf6\nDEFINE_GUIDSTRUCT(\"7b785572-8c82-11cf-bc0c-00aa00ac74f6\", KSTIME_FORMAT_SAMPLE);\n#define KSTIME_FORMAT_SAMPLE DEFINE_GUIDNAMED(KSTIME_FORMAT_SAMPLE)\n\n#define STATIC_KSTIME_FORMAT_FIELD                  \\\n  0x7b785573L, 0x8c82, 0x11cf, 0xbc, 0x0c, 0x00, 0xaa, 0x00, 0xac, 0x74, 0xf6\nDEFINE_GUIDSTRUCT(\"7b785573-8c82-11cf-bc0c-00aa00ac74f6\", KSTIME_FORMAT_FIELD);\n#define KSTIME_FORMAT_FIELD DEFINE_GUIDNAMED(KSTIME_FORMAT_FIELD)\n\n#define STATIC_KSTIME_FORMAT_MEDIA_TIME                 \\\n  0x7b785574L, 0x8c82, 0x11cf, 0xbc, 0x0c, 0x00, 0xaa, 0x00, 0xac, 0x74, 0xf6\nDEFINE_GUIDSTRUCT(\"7b785574-8c82-11cf-bc0c-00aa00ac74f6\", KSTIME_FORMAT_MEDIA_TIME);\n#define KSTIME_FORMAT_MEDIA_TIME DEFINE_GUIDNAMED(KSTIME_FORMAT_MEDIA_TIME)\n\ntypedef KSIDENTIFIER KSPIN_INTERFACE, * PKSPIN_INTERFACE;\n\n#define STATIC_KSINTERFACESETID_Standard                \\\n  0x1A8766A0L, 0x62CE, 0x11CF, { 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 }\nDEFINE_GUIDSTRUCT(\"1A8766A0-62CE-11CF-A5D6-28DB04C10000\", KSINTERFACESETID_Standard);\n#define KSINTERFACESETID_Standard DEFINE_GUIDNAMED(KSINTERFACESETID_Standard)\n\ntypedef enum\n{\n  KSINTERFACE_STANDARD_STREAMING,\n  KSINTERFACE_STANDARD_LOOPED_STREAMING,\n  KSINTERFACE_STANDARD_CONTROL\n}KSINTERFACE_STANDARD;\n\n#define STATIC_KSINTERFACESETID_FileIo                  \\\n  0x8C6F932CL, 0xE771, 0x11D0, 0xB8, 0xFF, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96\nDEFINE_GUIDSTRUCT(\"8C6F932C-E771-11D0-B8FF-00A0C9223196\", KSINTERFACESETID_FileIo);\n#define KSINTERFACESETID_FileIo DEFINE_GUIDNAMED(KSINTERFACESETID_FileIo)\n\ntypedef enum\n{\n  KSINTERFACE_FILEIO_STREAMING\n}KSINTERFACE_FILEIO;\n\n#define KSMEDIUM_TYPE_ANYINSTANCE 0\n\n#define STATIC_KSMEDIUMSETID_Standard                   \\\n  0x4747B320L, 0x62CE, 0x11CF, { 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 }\nDEFINE_GUIDSTRUCT(\"4747B320-62CE-11CF-A5D6-28DB04C10000\", KSMEDIUMSETID_Standard);\n#define KSMEDIUMSETID_Standard DEFINE_GUIDNAMED(KSMEDIUMSETID_Standard)\n\n#define KSMEDIUM_STANDARD_DEVIO KSMEDIUM_TYPE_ANYINSTANCE\n\n#define STATIC_KSPROPSETID_Pin                      \\\n  0x8C134960L, 0x51AD, 0x11CF, { 0x87, 0x8A, 0x94, 0xF8, 0x01, 0xC1, 0x00, 0x00 }\nDEFINE_GUIDSTRUCT(\"8C134960-51AD-11CF-878A-94F801C10000\", KSPROPSETID_Pin);\n#define KSPROPSETID_Pin DEFINE_GUIDNAMED(KSPROPSETID_Pin)\n\ntypedef enum\n{\n  KSPROPERTY_PIN_CINSTANCES,\n  KSPROPERTY_PIN_CTYPES,\n  KSPROPERTY_PIN_DATAFLOW,\n  KSPROPERTY_PIN_DATARANGES,\n  KSPROPERTY_PIN_DATAINTERSECTION,\n  KSPROPERTY_PIN_INTERFACES,\n  KSPROPERTY_PIN_MEDIUMS,\n  KSPROPERTY_PIN_COMMUNICATION,\n  KSPROPERTY_PIN_GLOBALCINSTANCES,\n  KSPROPERTY_PIN_NECESSARYINSTANCES,\n  KSPROPERTY_PIN_PHYSICALCONNECTION,\n  KSPROPERTY_PIN_CATEGORY,\n  KSPROPERTY_PIN_NAME,\n  KSPROPERTY_PIN_CONSTRAINEDDATARANGES,\n  KSPROPERTY_PIN_PROPOSEDATAFORMAT\n}KSPROPERTY_PIN;\n\ntypedef struct\n{\n  KSPROPERTY Property;\n  ULONG PinId;\n  ULONG Reserved;\n}KSP_PIN, * PKSP_PIN;\n\n#define KSINSTANCE_INDETERMINATE ((ULONG)-1)\n\ntypedef struct\n{\n  ULONG PossibleCount;\n  ULONG CurrentCount;\n}KSPIN_CINSTANCES, * PKSPIN_CINSTANCES;\n\ntypedef enum\n{\n  KSPIN_DATAFLOW_IN = 1,\n  KSPIN_DATAFLOW_OUT\n}KSPIN_DATAFLOW, * PKSPIN_DATAFLOW;\n\n#define KSDATAFORMAT_BIT_TEMPORAL_COMPRESSION 0\n#define KSDATAFORMAT_TEMPORAL_COMPRESSION (1 << KSDATAFORMAT_BIT_TEMPORAL_COMPRESSION)\n#define KSDATAFORMAT_BIT_ATTRIBUTES 1\n#define KSDATAFORMAT_ATTRIBUTES (1 << KSDATAFORMAT_BIT_ATTRIBUTES)\n\n#define KSDATARANGE_BIT_ATTRIBUTES 1\n#define KSDATARANGE_ATTRIBUTES (1 << KSDATARANGE_BIT_ATTRIBUTES)\n#define KSDATARANGE_BIT_REQUIRED_ATTRIBUTES 2\n#define KSDATARANGE_REQUIRED_ATTRIBUTES (1 << KSDATARANGE_BIT_REQUIRED_ATTRIBUTES)\n\ntypedef union\n{\n  __MINGW_EXTENSION struct\n  {\n    ULONG FormatSize;\n    ULONG Flags;\n    ULONG SampleSize;\n    ULONG Reserved;\n    GUID MajorFormat;\n    GUID SubFormat;\n    GUID Specifier;\n  };\n  LONGLONG Alignment;\n}KSDATAFORMAT, * PKSDATAFORMAT, KSDATARANGE, * PKSDATARANGE;\n\n#define KSATTRIBUTE_REQUIRED 0x00000001\n\ntypedef struct\n{\n  ULONG Size;\n  ULONG Flags;\n  GUID Attribute;\n}KSATTRIBUTE, * PKSATTRIBUTE;\n\n#if defined(_NTDDK_)\ntypedef struct\n{\n  ULONG Count;\n  PKSATTRIBUTE* Attributes;\n}KSATTRIBUTE_LIST, * PKSATTRIBUTE_LIST;\n#endif /* _NTDDK_ */\n\ntypedef enum\n{\n  KSPIN_COMMUNICATION_NONE,\n  KSPIN_COMMUNICATION_SINK,\n  KSPIN_COMMUNICATION_SOURCE,\n  KSPIN_COMMUNICATION_BOTH,\n  KSPIN_COMMUNICATION_BRIDGE\n}KSPIN_COMMUNICATION, * PKSPIN_COMMUNICATION;\n\ntypedef KSIDENTIFIER KSPIN_MEDIUM, * PKSPIN_MEDIUM;\n\ntypedef struct\n{\n  KSPIN_INTERFACE Interface;\n  KSPIN_MEDIUM Medium;\n  ULONG PinId;\n  HANDLE PinToHandle;\n  KSPRIORITY Priority;\n}KSPIN_CONNECT, * PKSPIN_CONNECT;\n\ntypedef struct\n{\n  ULONG Size;\n  ULONG Pin;\n  WCHAR SymbolicLinkName[1];\n}KSPIN_PHYSICALCONNECTION, * PKSPIN_PHYSICALCONNECTION;\n\n#if defined(_NTDDK_)\ntypedef NTSTATUS (*PFNKSINTERSECTHANDLER)(PIRP Irp, PKSP_PIN Pin,\n                                          PKSDATARANGE DataRange,\n                                          PVOID Data);\ntypedef NTSTATUS (*PFNKSINTERSECTHANDLEREX)(PVOID Context, PIRP Irp,\n                                            PKSP_PIN Pin,\n                                            PKSDATARANGE DataRange,\n                                            PKSDATARANGE MatchingDataRange,\n                                            ULONG DataBufferSize,\n                                            PVOID Data,\n                                            PULONG DataSize);\n#endif /* _NTDDK_ */\n\n#define DEFINE_KSPIN_INTERFACE_TABLE(tablename)             \\\n  const KSPIN_INTERFACE tablename[] =\n\n#define DEFINE_KSPIN_INTERFACE_ITEM(guid, _interFace)            \\\n  {                               \\\n    STATICGUIDOF(guid),                 \\\n    (_interFace),                       \\\n    0                           \\\n  }\n\n#define DEFINE_KSPIN_MEDIUM_TABLE(tablename)                \\\n  const KSPIN_MEDIUM tablename[] =\n\n#define DEFINE_KSPIN_MEDIUM_ITEM(guid, medium)               \\\n  DEFINE_KSPIN_INTERFACE_ITEM(guid, medium)\n\n#define DEFINE_KSPROPERTY_ITEM_PIN_CINSTANCES(Handler)          \\\n  DEFINE_KSPROPERTY_ITEM(                     \\\n    KSPROPERTY_PIN_CINSTANCES,      \\\n    (Handler),              \\\n    sizeof(KSP_PIN),            \\\n    sizeof(KSPIN_CINSTANCES),       \\\n    NULL, NULL, 0, NULL, NULL, 0)\n\n#define DEFINE_KSPROPERTY_ITEM_PIN_CTYPES(Handler)          \\\n  DEFINE_KSPROPERTY_ITEM(                     \\\n    KSPROPERTY_PIN_CTYPES,          \\\n    (Handler),              \\\n    sizeof(KSPROPERTY),         \\\n    sizeof(ULONG),              \\\n    NULL, NULL, 0, NULL, NULL, 0)\n\n#define DEFINE_KSPROPERTY_ITEM_PIN_DATAFLOW(Handler)            \\\n  DEFINE_KSPROPERTY_ITEM(                     \\\n    KSPROPERTY_PIN_DATAFLOW,        \\\n    (Handler),              \\\n    sizeof(KSP_PIN),            \\\n    sizeof(KSPIN_DATAFLOW),         \\\n    NULL, NULL, 0, NULL, NULL, 0)\n\n#define DEFINE_KSPROPERTY_ITEM_PIN_DATARANGES(Handler)          \\\n  DEFINE_KSPROPERTY_ITEM(                     \\\n    KSPROPERTY_PIN_DATARANGES,      \\\n    (Handler),              \\\n    sizeof(KSP_PIN),            \\\n    0,                  \\\n    NULL, NULL, 0, NULL, NULL, 0)\n\n#define DEFINE_KSPROPERTY_ITEM_PIN_DATAINTERSECTION(Handler)        \\\n  DEFINE_KSPROPERTY_ITEM(                     \\\n    KSPROPERTY_PIN_DATAINTERSECTION,    \\\n    (Handler),              \\\n    sizeof(KSP_PIN) + sizeof(KSMULTIPLE_ITEM), \\\n    0,                  \\\n    NULL, NULL, 0, NULL, NULL, 0)\n\n#define DEFINE_KSPROPERTY_ITEM_PIN_INTERFACES(Handler)          \\\n  DEFINE_KSPROPERTY_ITEM(                     \\\n    KSPROPERTY_PIN_INTERFACES,      \\\n    (Handler),              \\\n    sizeof(KSP_PIN),            \\\n    0,                  \\\n    NULL, NULL, 0, NULL, NULL, 0)\n\n#define DEFINE_KSPROPERTY_ITEM_PIN_MEDIUMS(Handler)         \\\n  DEFINE_KSPROPERTY_ITEM(                     \\\n    KSPROPERTY_PIN_MEDIUMS,         \\\n    (Handler),              \\\n    sizeof(KSP_PIN),            \\\n    0,                  \\\n    NULL, NULL, 0, NULL, NULL, 0)\n\n#define DEFINE_KSPROPERTY_ITEM_PIN_COMMUNICATION(Handler)       \\\n  DEFINE_KSPROPERTY_ITEM(                     \\\n    KSPROPERTY_PIN_COMMUNICATION,       \\\n    (Handler),              \\\n    sizeof(KSP_PIN),            \\\n    sizeof(KSPIN_COMMUNICATION),        \\\n    NULL, NULL, 0, NULL, NULL, 0)\n\n#define DEFINE_KSPROPERTY_ITEM_PIN_GLOBALCINSTANCES(Handler)        \\\n  DEFINE_KSPROPERTY_ITEM(                     \\\n    KSPROPERTY_PIN_GLOBALCINSTANCES,    \\\n    (Handler),              \\\n    sizeof(KSP_PIN),            \\\n    sizeof(KSPIN_CINSTANCES),       \\\n    NULL, NULL, 0, NULL, NULL, 0)\n\n#define DEFINE_KSPROPERTY_ITEM_PIN_NECESSARYINSTANCES(Handler)      \\\n  DEFINE_KSPROPERTY_ITEM(                     \\\n    KSPROPERTY_PIN_NECESSARYINSTANCES,  \\\n    (Handler),              \\\n    sizeof(KSP_PIN),            \\\n    sizeof(ULONG),              \\\n    NULL, NULL, 0, NULL, NULL, 0)\n\n#define DEFINE_KSPROPERTY_ITEM_PIN_PHYSICALCONNECTION(Handler)      \\\n  DEFINE_KSPROPERTY_ITEM(                     \\\n    KSPROPERTY_PIN_PHYSICALCONNECTION,  \\\n    (Handler),              \\\n    sizeof(KSP_PIN),            \\\n    0,                  \\\n    NULL, NULL, 0, NULL, NULL, 0)\n\n#define DEFINE_KSPROPERTY_ITEM_PIN_CATEGORY(Handler)            \\\n  DEFINE_KSPROPERTY_ITEM(                     \\\n    KSPROPERTY_PIN_CATEGORY,        \\\n    (Handler),              \\\n    sizeof(KSP_PIN),            \\\n    sizeof(GUID),               \\\n    NULL, NULL, 0, NULL, NULL, 0)\n\n#define DEFINE_KSPROPERTY_ITEM_PIN_NAME(Handler)            \\\n  DEFINE_KSPROPERTY_ITEM(                     \\\n    KSPROPERTY_PIN_NAME,            \\\n    (Handler),              \\\n    sizeof(KSP_PIN),            \\\n    0,                  \\\n    NULL, NULL, 0, NULL, NULL, 0)\n\n#define DEFINE_KSPROPERTY_ITEM_PIN_CONSTRAINEDDATARANGES(Handler)   \\\n  DEFINE_KSPROPERTY_ITEM(                     \\\n    KSPROPERTY_PIN_CONSTRAINEDDATARANGES,   \\\n    (Handler),              \\\n    sizeof(KSP_PIN),            \\\n    0,                  \\\n    NULL, NULL, 0, NULL, NULL, 0)\n\n#define DEFINE_KSPROPERTY_ITEM_PIN_PROPOSEDATAFORMAT(Handler)       \\\n  DEFINE_KSPROPERTY_ITEM(                     \\\n    KSPROPERTY_PIN_PROPOSEDATAFORMAT,   \\\n    NULL,                   \\\n    sizeof(KSP_PIN),            \\\n    sizeof(KSDATAFORMAT),           \\\n    (Handler), NULL, 0, NULL, NULL, 0)\n\n#define DEFINE_KSPROPERTY_PINSET(PinSet, PropGeneral, PropInstances, PropIntersection) \\\n  DEFINE_KSPROPERTY_TABLE(PinSet) {                   \\\n    DEFINE_KSPROPERTY_ITEM_PIN_CINSTANCES(PropInstances),       \\\n    DEFINE_KSPROPERTY_ITEM_PIN_CTYPES(PropGeneral),         \\\n    DEFINE_KSPROPERTY_ITEM_PIN_DATAFLOW(PropGeneral),       \\\n    DEFINE_KSPROPERTY_ITEM_PIN_DATARANGES(PropGeneral),     \\\n    DEFINE_KSPROPERTY_ITEM_PIN_DATAINTERSECTION(PropIntersection),  \\\n    DEFINE_KSPROPERTY_ITEM_PIN_INTERFACES(PropGeneral),     \\\n    DEFINE_KSPROPERTY_ITEM_PIN_MEDIUMS(PropGeneral),        \\\n    DEFINE_KSPROPERTY_ITEM_PIN_COMMUNICATION(PropGeneral),      \\\n    DEFINE_KSPROPERTY_ITEM_PIN_CATEGORY(PropGeneral),       \\\n    DEFINE_KSPROPERTY_ITEM_PIN_NAME(PropGeneral)            \\\n  }\n\n#define DEFINE_KSPROPERTY_PINSETCONSTRAINED(PinSet, PropGeneral, PropInstances, PropIntersection) \\\n  DEFINE_KSPROPERTY_TABLE(PinSet) {                   \\\n    DEFINE_KSPROPERTY_ITEM_PIN_CINSTANCES(PropInstances),       \\\n    DEFINE_KSPROPERTY_ITEM_PIN_CTYPES(PropGeneral),         \\\n    DEFINE_KSPROPERTY_ITEM_PIN_DATAFLOW(PropGeneral),       \\\n    DEFINE_KSPROPERTY_ITEM_PIN_DATARANGES(PropGeneral),     \\\n    DEFINE_KSPROPERTY_ITEM_PIN_DATAINTERSECTION(PropIntersection),  \\\n    DEFINE_KSPROPERTY_ITEM_PIN_INTERFACES(PropGeneral),     \\\n    DEFINE_KSPROPERTY_ITEM_PIN_MEDIUMS(PropGeneral),        \\\n    DEFINE_KSPROPERTY_ITEM_PIN_COMMUNICATION(PropGeneral),      \\\n    DEFINE_KSPROPERTY_ITEM_PIN_CATEGORY(PropGeneral),       \\\n    DEFINE_KSPROPERTY_ITEM_PIN_NAME(PropGeneral),           \\\n    DEFINE_KSPROPERTY_ITEM_PIN_CONSTRAINEDDATARANGES(PropGeneral)   \\\n  }\n\n#define STATIC_KSNAME_Filter                        \\\n  0x9b365890L, 0x165f, 0x11d0, 0xa1, 0x95, 0x00, 0x20, 0xaf, 0xd1, 0x56, 0xe4\nDEFINE_GUIDSTRUCT(\"9b365890-165f-11d0-a195-0020afd156e4\", KSNAME_Filter);\n#define KSNAME_Filter DEFINE_GUIDNAMED(KSNAME_Filter)\n\n#define KSSTRING_Filter L\"{9B365890-165F-11D0-A195-0020AFD156E4}\"\n\n#define STATIC_KSNAME_Pin                       \\\n  0x146F1A80L, 0x4791, 0x11D0, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00\nDEFINE_GUIDSTRUCT(\"146F1A80-4791-11D0-A5D6-28DB04C10000\", KSNAME_Pin);\n#define KSNAME_Pin DEFINE_GUIDNAMED(KSNAME_Pin)\n\n#define KSSTRING_Pin L\"{146F1A80-4791-11D0-A5D6-28DB04C10000}\"\n\n#define STATIC_KSNAME_Clock                     \\\n  0x53172480L, 0x4791, 0x11D0, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00\nDEFINE_GUIDSTRUCT(\"53172480-4791-11D0-A5D6-28DB04C10000\", KSNAME_Clock);\n#define KSNAME_Clock DEFINE_GUIDNAMED(KSNAME_Clock)\n\n#define KSSTRING_Clock L\"{53172480-4791-11D0-A5D6-28DB04C10000}\"\n\n#define STATIC_KSNAME_Allocator                     \\\n  0x642F5D00L, 0x4791, 0x11D0, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00\nDEFINE_GUIDSTRUCT(\"642F5D00-4791-11D0-A5D6-28DB04C10000\", KSNAME_Allocator);\n#define KSNAME_Allocator DEFINE_GUIDNAMED(KSNAME_Allocator)\n\n#define KSSTRING_Allocator L\"{642F5D00-4791-11D0-A5D6-28DB04C10000}\"\n\n#define KSSTRING_AllocatorEx L\"{091BB63B-603F-11D1-B067-00A0C9062802}\"\n\n#define STATIC_KSNAME_TopologyNode                  \\\n  0x0621061AL, 0xEE75, 0x11D0, 0xB9, 0x15, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96\nDEFINE_GUIDSTRUCT(\"0621061A-EE75-11D0-B915-00A0C9223196\", KSNAME_TopologyNode);\n#define KSNAME_TopologyNode DEFINE_GUIDNAMED(KSNAME_TopologyNode)\n\n#define KSSTRING_TopologyNode L\"{0621061A-EE75-11D0-B915-00A0C9223196}\"\n\n#if defined(_NTDDK_)\ntypedef struct\n{\n  ULONG InterfacesCount;\n  const KSPIN_INTERFACE* Interfaces;\n  ULONG MediumsCount;\n  const KSPIN_MEDIUM* Mediums;\n  ULONG DataRangesCount;\n  const PKSDATARANGE* DataRanges;\n  KSPIN_DATAFLOW DataFlow;\n  KSPIN_COMMUNICATION Communication;\n  const GUID* Category;\n  const GUID* Name;\n  __MINGW_EXTENSION union\n  {\n    LONGLONG Reserved;\n    __MINGW_EXTENSION struct\n    {\n      ULONG ConstrainedDataRangesCount;\n      PKSDATARANGE* ConstrainedDataRanges;\n    };\n  };\n}KSPIN_DESCRIPTOR, * PKSPIN_DESCRIPTOR;\ntypedef const KSPIN_DESCRIPTOR* PCKSPIN_DESCRIPTOR;\n\n # define DEFINE_KSPIN_DESCRIPTOR_TABLE(tablename)            \\\n  const KSPIN_DESCRIPTOR tablename[] =\n\n # define DEFINE_KSPIN_DESCRIPTOR_ITEM(InterfacesCount, Interfaces, MediumsCount, Mediums, DataRangesCount, DataRanges, DataFlow, Communication) \\\n  {                                   \\\n    InterfacesCount, Interfaces, MediumsCount, Mediums, \\\n    DataRangesCount, DataRanges, DataFlow, Communication,   \\\n    NULL, NULL, 0                       \\\n  }\n\n # define DEFINE_KSPIN_DESCRIPTOR_ITEMEX(InterfacesCount, Interfaces, MediumsCount, Mediums, DataRangesCount, DataRanges, DataFlow, Communication, Category, Name) \\\n  {                                   \\\n    InterfacesCount, Interfaces, MediumsCount, Mediums, \\\n    DataRangesCount, DataRanges, DataFlow, Communication,   \\\n    Category, Name, 0                   \\\n  }\n#endif /* _NTDDK_ */\n\n#define STATIC_KSDATAFORMAT_TYPE_WILDCARD STATIC_GUID_NULL\n#define KSDATAFORMAT_TYPE_WILDCARD GUID_NULL\n\n#define STATIC_KSDATAFORMAT_SUBTYPE_WILDCARD STATIC_GUID_NULL\n#define KSDATAFORMAT_SUBTYPE_WILDCARD GUID_NULL\n\n#define STATIC_KSDATAFORMAT_TYPE_STREAM                 \\\n  0xE436EB83L, 0x524F, 0x11CE, 0x9F, 0x53, 0x00, 0x20, 0xAF, 0x0B, 0xA7, 0x70\nDEFINE_GUIDSTRUCT(\"E436EB83-524F-11CE-9F53-0020AF0BA770\", KSDATAFORMAT_TYPE_STREAM);\n#define KSDATAFORMAT_TYPE_STREAM DEFINE_GUIDNAMED(KSDATAFORMAT_TYPE_STREAM)\n\n#define STATIC_KSDATAFORMAT_SUBTYPE_NONE                \\\n  0xE436EB8EL, 0x524F, 0x11CE, 0x9F, 0x53, 0x00, 0x20, 0xAF, 0x0B, 0xA7, 0x70\nDEFINE_GUIDSTRUCT(\"E436EB8E-524F-11CE-9F53-0020AF0BA770\", KSDATAFORMAT_SUBTYPE_NONE);\n#define KSDATAFORMAT_SUBTYPE_NONE DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_NONE)\n\n#define STATIC_KSDATAFORMAT_SPECIFIER_WILDCARD STATIC_GUID_NULL\n#define KSDATAFORMAT_SPECIFIER_WILDCARD GUID_NULL\n\n#define STATIC_KSDATAFORMAT_SPECIFIER_FILENAME              \\\n  0xAA797B40L, 0xE974, 0x11CF, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00\nDEFINE_GUIDSTRUCT(\"AA797B40-E974-11CF-A5D6-28DB04C10000\", KSDATAFORMAT_SPECIFIER_FILENAME);\n#define KSDATAFORMAT_SPECIFIER_FILENAME DEFINE_GUIDNAMED(KSDATAFORMAT_SPECIFIER_FILENAME)\n\n#define STATIC_KSDATAFORMAT_SPECIFIER_FILEHANDLE            \\\n  0x65E8773CL, 0x8F56, 0x11D0, 0xA3, 0xB9, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96\nDEFINE_GUIDSTRUCT(\"65E8773C-8F56-11D0-A3B9-00A0C9223196\", KSDATAFORMAT_SPECIFIER_FILEHANDLE);\n#define KSDATAFORMAT_SPECIFIER_FILEHANDLE DEFINE_GUIDNAMED(KSDATAFORMAT_SPECIFIER_FILEHANDLE)\n\n#define STATIC_KSDATAFORMAT_SPECIFIER_NONE              \\\n  0x0F6417D6L, 0xC318, 0x11D0, { 0xA4, 0x3F, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 }\nDEFINE_GUIDSTRUCT(\"0F6417D6-C318-11D0-A43F-00A0C9223196\", KSDATAFORMAT_SPECIFIER_NONE);\n#define KSDATAFORMAT_SPECIFIER_NONE DEFINE_GUIDNAMED(KSDATAFORMAT_SPECIFIER_NONE)\n\n#define STATIC_KSPROPSETID_Quality                  \\\n  0xD16AD380L, 0xAC1A, 0x11CF, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00\nDEFINE_GUIDSTRUCT(\"D16AD380-AC1A-11CF-A5D6-28DB04C10000\", KSPROPSETID_Quality);\n#define KSPROPSETID_Quality DEFINE_GUIDNAMED(KSPROPSETID_Quality)\n\ntypedef enum\n{\n  KSPROPERTY_QUALITY_REPORT,\n  KSPROPERTY_QUALITY_ERROR\n}KSPROPERTY_QUALITY;\n\n#define DEFINE_KSPROPERTY_ITEM_QUALITY_REPORT(GetHandler, SetHandler)    \\\n  DEFINE_KSPROPERTY_ITEM(                     \\\n    KSPROPERTY_QUALITY_REPORT,      \\\n    (GetHandler),               \\\n    sizeof(KSPROPERTY),         \\\n    sizeof(KSQUALITY),          \\\n    (SetHandler),               \\\n    NULL, 0, NULL, NULL, 0)\n\n#define DEFINE_KSPROPERTY_ITEM_QUALITY_ERROR(GetHandler, SetHandler) \\\n  DEFINE_KSPROPERTY_ITEM(                     \\\n    KSPROPERTY_QUALITY_ERROR,       \\\n    (GetHandler),               \\\n    sizeof(KSPROPERTY),         \\\n    sizeof(KSERROR),            \\\n    (SetHandler),               \\\n    NULL, 0, NULL, NULL, 0)\n\n#define STATIC_KSPROPSETID_Connection                   \\\n  0x1D58C920L, 0xAC9B, 0x11CF, { 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 }\nDEFINE_GUIDSTRUCT(\"1D58C920-AC9B-11CF-A5D6-28DB04C10000\", KSPROPSETID_Connection);\n#define KSPROPSETID_Connection DEFINE_GUIDNAMED(KSPROPSETID_Connection)\n\ntypedef enum\n{\n  KSPROPERTY_CONNECTION_STATE,\n  KSPROPERTY_CONNECTION_PRIORITY,\n  KSPROPERTY_CONNECTION_DATAFORMAT,\n  KSPROPERTY_CONNECTION_ALLOCATORFRAMING,\n  KSPROPERTY_CONNECTION_PROPOSEDATAFORMAT,\n  KSPROPERTY_CONNECTION_ACQUIREORDERING,\n  KSPROPERTY_CONNECTION_ALLOCATORFRAMING_EX,\n  KSPROPERTY_CONNECTION_STARTAT\n}KSPROPERTY_CONNECTION;\n\n#define DEFINE_KSPROPERTY_ITEM_CONNECTION_STATE(GetHandler, SetHandler)  \\\n  DEFINE_KSPROPERTY_ITEM(                     \\\n    KSPROPERTY_CONNECTION_STATE,        \\\n    (GetHandler),               \\\n    sizeof(KSPROPERTY),         \\\n    sizeof(KSSTATE),            \\\n    (SetHandler),               \\\n    NULL, 0, NULL, NULL, 0)\n\n#define DEFINE_KSPROPERTY_ITEM_CONNECTION_PRIORITY(GetHandler, SetHandler) \\\n  DEFINE_KSPROPERTY_ITEM(                     \\\n    KSPROPERTY_CONNECTION_PRIORITY,     \\\n    (GetHandler),               \\\n    sizeof(KSPROPERTY),         \\\n    sizeof(KSPRIORITY),         \\\n    (SetHandler),               \\\n    NULL, 0, NULL, NULL, 0)\n\n#define DEFINE_KSPROPERTY_ITEM_CONNECTION_DATAFORMAT(GetHandler, SetHandler) \\\n  DEFINE_KSPROPERTY_ITEM(                     \\\n    KSPROPERTY_CONNECTION_DATAFORMAT,   \\\n    (GetHandler),               \\\n    sizeof(KSPROPERTY),         \\\n    0,                  \\\n    (SetHandler),               \\\n    NULL, 0, NULL, NULL, 0)\n\n#define DEFINE_KSPROPERTY_ITEM_CONNECTION_ALLOCATORFRAMING(Handler) \\\n  DEFINE_KSPROPERTY_ITEM(                     \\\n    KSPROPERTY_CONNECTION_ALLOCATORFRAMING, \\\n    (Handler),              \\\n    sizeof(KSPROPERTY),         \\\n    sizeof(KSALLOCATOR_FRAMING),        \\\n    NULL, NULL, 0, NULL, NULL, 0)\n\n#define DEFINE_KSPROPERTY_ITEM_CONNECTION_ALLOCATORFRAMING_EX(Handler)  \\\n  DEFINE_KSPROPERTY_ITEM(                     \\\n    KSPROPERTY_CONNECTION_ALLOCATORFRAMING_EX, \\\n    (Handler),              \\\n    sizeof(KSPROPERTY),         \\\n    0,                  \\\n    NULL, NULL, 0, NULL, NULL, 0)\n\n#define DEFINE_KSPROPERTY_ITEM_CONNECTION_PROPOSEDATAFORMAT(Handler)    \\\n  DEFINE_KSPROPERTY_ITEM(                     \\\n    KSPROPERTY_CONNECTION_PROPOSEDATAFORMAT, \\\n    NULL,                   \\\n    sizeof(KSPROPERTY),         \\\n    sizeof(KSDATAFORMAT),           \\\n    (Handler),              \\\n    NULL, 0, NULL, NULL, 0)\n\n#define DEFINE_KSPROPERTY_ITEM_CONNECTION_ACQUIREORDERING(Handler)  \\\n  DEFINE_KSPROPERTY_ITEM(                     \\\n    KSPROPERTY_CONNECTION_ACQUIREORDERING,  \\\n    (Handler),              \\\n    sizeof(KSPROPERTY),         \\\n    sizeof(int),                \\\n    NULL, NULL, 0, NULL, NULL, 0)\n\n#define DEFINE_KSPROPERTY_ITEM_CONNECTION_STARTAT(Handler)      \\\n  DEFINE_KSPROPERTY_ITEM(                     \\\n    KSPROPERTY_CONNECTION_STARTAT,      \\\n    NULL,                   \\\n    sizeof(KSPROPERTY),         \\\n    sizeof(KSRELATIVEEVENT),        \\\n    (Handler),              \\\n    NULL, 0, NULL, NULL, 0)\n\n#define KSALLOCATOR_REQUIREMENTF_INPLACE_MODIFIER 0x00000001\n#define KSALLOCATOR_REQUIREMENTF_SYSTEM_MEMORY 0x00000002\n#define KSALLOCATOR_REQUIREMENTF_FRAME_INTEGRITY 0x00000004\n#define KSALLOCATOR_REQUIREMENTF_MUST_ALLOCATE 0x00000008\n#define KSALLOCATOR_REQUIREMENTF_PREFERENCES_ONLY 0x80000000\n\n#define KSALLOCATOR_OPTIONF_COMPATIBLE 0x00000001\n#define KSALLOCATOR_OPTIONF_SYSTEM_MEMORY 0x00000002\n#define KSALLOCATOR_OPTIONF_VALID 0x00000003\n\n#define KSALLOCATOR_FLAG_PARTIAL_READ_SUPPORT 0x00000010\n#define KSALLOCATOR_FLAG_DEVICE_SPECIFIC 0x00000020\n#define KSALLOCATOR_FLAG_CAN_ALLOCATE 0x00000040\n#define KSALLOCATOR_FLAG_INSIST_ON_FRAMESIZE_RATIO 0x00000080\n#define KSALLOCATOR_FLAG_NO_FRAME_INTEGRITY 0x00000100\n#define KSALLOCATOR_FLAG_MULTIPLE_OUTPUT 0x00000200\n#define KSALLOCATOR_FLAG_CYCLE 0x00000400\n#define KSALLOCATOR_FLAG_ALLOCATOR_EXISTS 0x00000800\n#define KSALLOCATOR_FLAG_INDEPENDENT_RANGES 0x00001000\n#define KSALLOCATOR_FLAG_ATTENTION_STEPPING 0x00002000\n\ntypedef struct\n{\n  __MINGW_EXTENSION union\n  {\n    ULONG OptionsFlags;\n    ULONG RequirementsFlags;\n  };\n#if defined(_NTDDK_)\n  POOL_TYPE PoolType;\n#else\n  ULONG PoolType;\n#endif /* _NTDDK_ */\n  ULONG Frames;\n  ULONG FrameSize;\n  ULONG FileAlignment;\n  ULONG Reserved;\n}KSALLOCATOR_FRAMING, * PKSALLOCATOR_FRAMING;\n\n#if defined(_NTDDK_)\ntypedef PVOID (*PFNKSDEFAULTALLOCATE)(PVOID Context);\ntypedef VOID (*PFNKSDEFAULTFREE)(PVOID Context, PVOID Buffer);\ntypedef NTSTATUS (*PFNKSINITIALIZEALLOCATOR)(PVOID InitialContext,\n                                             PKSALLOCATOR_FRAMING AllocatorFraming,\n                                             PVOID* Context);\ntypedef VOID (*PFNKSDELETEALLOCATOR)(PVOID Context);\n#endif /* _NTDDK_ */\n\ntypedef struct\n{\n  ULONG MinFrameSize;\n  ULONG MaxFrameSize;\n  ULONG Stepping;\n}KS_FRAMING_RANGE, * PKS_FRAMING_RANGE;\n\ntypedef struct\n{\n  KS_FRAMING_RANGE Range;\n  ULONG InPlaceWeight;\n  ULONG NotInPlaceWeight;\n}KS_FRAMING_RANGE_WEIGHTED, * PKS_FRAMING_RANGE_WEIGHTED;\n\ntypedef struct\n{\n  ULONG RatioNumerator;\n  ULONG RatioDenominator;\n  ULONG RatioConstantMargin;\n}KS_COMPRESSION, * PKS_COMPRESSION;\n\ntypedef struct\n{\n  GUID MemoryType;\n  GUID BusType;\n  ULONG MemoryFlags;\n  ULONG BusFlags;\n  ULONG Flags;\n  ULONG Frames;\n  ULONG FileAlignment;\n  ULONG MemoryTypeWeight;\n  KS_FRAMING_RANGE PhysicalRange;\n  KS_FRAMING_RANGE_WEIGHTED FramingRange;\n}KS_FRAMING_ITEM, * PKS_FRAMING_ITEM;\n\ntypedef struct\n{\n  ULONG CountItems;\n  ULONG PinFlags;\n  KS_COMPRESSION OutputCompression;\n  ULONG PinWeight;\n  KS_FRAMING_ITEM FramingItem[1];\n}KSALLOCATOR_FRAMING_EX, * PKSALLOCATOR_FRAMING_EX;\n\n#define KSMEMORY_TYPE_WILDCARD GUID_NULL\n#define STATIC_KSMEMORY_TYPE_WILDCARD STATIC_GUID_NULL\n\n#define KSMEMORY_TYPE_DONT_CARE GUID_NULL\n#define STATIC_KSMEMORY_TYPE_DONT_CARE STATIC_GUID_NULL\n\n#define KS_TYPE_DONT_CARE GUID_NULL\n#define STATIC_KS_TYPE_DONT_CARE STATIC_GUID_NULL\n\n#define STATIC_KSMEMORY_TYPE_SYSTEM                 \\\n  0x091bb638L, 0x603f, 0x11d1, 0xb0, 0x67, 0x00, 0xa0, 0xc9, 0x06, 0x28, 0x02\nDEFINE_GUIDSTRUCT(\"091bb638-603f-11d1-b067-00a0c9062802\", KSMEMORY_TYPE_SYSTEM);\n#define KSMEMORY_TYPE_SYSTEM DEFINE_GUIDNAMED(KSMEMORY_TYPE_SYSTEM)\n\n#define STATIC_KSMEMORY_TYPE_USER                   \\\n  0x8cb0fc28L, 0x7893, 0x11d1, 0xb0, 0x69, 0x00, 0xa0, 0xc9, 0x06, 0x28, 0x02\nDEFINE_GUIDSTRUCT(\"8cb0fc28-7893-11d1-b069-00a0c9062802\", KSMEMORY_TYPE_USER);\n#define KSMEMORY_TYPE_USER DEFINE_GUIDNAMED(KSMEMORY_TYPE_USER)\n\n#define STATIC_KSMEMORY_TYPE_KERNEL_PAGED               \\\n  0xd833f8f8L, 0x7894, 0x11d1, 0xb0, 0x69, 0x00, 0xa0, 0xc9, 0x06, 0x28, 0x02\nDEFINE_GUIDSTRUCT(\"d833f8f8-7894-11d1-b069-00a0c9062802\", KSMEMORY_TYPE_KERNEL_PAGED);\n#define KSMEMORY_TYPE_KERNEL_PAGED DEFINE_GUIDNAMED(KSMEMORY_TYPE_KERNEL_PAGED)\n\n#define STATIC_KSMEMORY_TYPE_KERNEL_NONPAGED                \\\n  0x4a6d5fc4L, 0x7895, 0x11d1, 0xb0, 0x69, 0x00, 0xa0, 0xc9, 0x06, 0x28, 0x02\nDEFINE_GUIDSTRUCT(\"4a6d5fc4-7895-11d1-b069-00a0c9062802\", KSMEMORY_TYPE_KERNEL_NONPAGED);\n#define KSMEMORY_TYPE_KERNEL_NONPAGED DEFINE_GUIDNAMED(KSMEMORY_TYPE_KERNEL_NONPAGED)\n\n#define STATIC_KSMEMORY_TYPE_DEVICE_UNKNOWN             \\\n  0x091bb639L, 0x603f, 0x11d1, 0xb0, 0x67, 0x00, 0xa0, 0xc9, 0x06, 0x28, 0x02\nDEFINE_GUIDSTRUCT(\"091bb639-603f-11d1-b067-00a0c9062802\", KSMEMORY_TYPE_DEVICE_UNKNOWN);\n#define KSMEMORY_TYPE_DEVICE_UNKNOWN DEFINE_GUIDNAMED(KSMEMORY_TYPE_DEVICE_UNKNOWN)\n\n#define DECLARE_SIMPLE_FRAMING_EX(FramingExName, MemoryType, Flags, Frames, Alignment, MinFrameSize, MaxFrameSize) \\\n  const KSALLOCATOR_FRAMING_EX FramingExName =                \\\n  {                                   \\\n    1,                              \\\n    0,                              \\\n    {                               \\\n      1,                          \\\n      1,                          \\\n      0                           \\\n    },                              \\\n    0,                              \\\n    {                               \\\n      {                           \\\n        MemoryType,                 \\\n        STATIC_KS_TYPE_DONT_CARE,           \\\n        0,                      \\\n        0,                      \\\n        Flags,                      \\\n        Frames,                     \\\n        Alignment,                  \\\n        0,                      \\\n        {                       \\\n          0,                  \\\n          (ULONG)-1,              \\\n          1                   \\\n        },                      \\\n        {                       \\\n          {                   \\\n            MinFrameSize,           \\\n            MaxFrameSize,           \\\n            1               \\\n          },                  \\\n          0,                  \\\n          0                   \\\n        }                       \\\n      }                           \\\n    }                               \\\n  }\n\n#define SetDefaultKsCompression(KsCompressionPointer)           \\\n  {                                   \\\n    KsCompressionPointer->RatioNumerator = 1;           \\\n    KsCompressionPointer->RatioDenominator = 1;         \\\n    KsCompressionPointer->RatioConstantMargin = 0;          \\\n  }\n\n#define SetDontCareKsFramingRange(KsFramingRangePointer)        \\\n  {                                   \\\n    KsFramingRangePointer->MinFrameSize = 0;            \\\n    KsFramingRangePointer->MaxFrameSize = (ULONG)-1;       \\\n    KsFramingRangePointer->Stepping = 1;                \\\n  }\n\n#define SetKsFramingRange(KsFramingRangePointer, P_MinFrameSize, P_MaxFrameSize) \\\n  {                                   \\\n    KsFramingRangePointer->MinFrameSize = P_MinFrameSize;       \\\n    KsFramingRangePointer->MaxFrameSize = P_MaxFrameSize;       \\\n    KsFramingRangePointer->Stepping = 1;                \\\n  }\n\n#define SetKsFramingRangeWeighted(KsFramingRangeWeightedPointer, P_MinFrameSize, P_MaxFrameSize) \\\n  {                                   \\\n    KS_FRAMING_RANGE* KsFramingRange =              \\\n      &KsFramingRangeWeightedPointer->Range;  \\\n    SetKsFramingRange(KsFramingRange, P_MinFrameSize, P_MaxFrameSize); \\\n    KsFramingRangeWeightedPointer->InPlaceWeight = 0;       \\\n    KsFramingRangeWeightedPointer->NotInPlaceWeight = 0;        \\\n  }\n\n#define INITIALIZE_SIMPLE_FRAMING_EX(FramingExPointer, P_MemoryType, P_Flags, P_Frames, P_Alignment, P_MinFrameSize, P_MaxFrameSize) \\\n  {                                   \\\n    KS_COMPRESSION* KsCompression =                 \\\n      &FramingExPointer->OutputCompression;       \\\n    KS_FRAMING_RANGE* KsFramingRange =              \\\n      &FramingExPointer->FramingItem[0].PhysicalRange; \\\n    KS_FRAMING_RANGE_WEIGHTED* KsFramingRangeWeighted =     \\\n      &FramingExPointer->FramingItem[0].FramingRange; \\\n    FramingExPointer->CountItems = 1;               \\\n    FramingExPointer->PinFlags = 0;                 \\\n    SetDefaultKsCompression(KsCompression);             \\\n    FramingExPointer->PinWeight = 0;                \\\n    FramingExPointer->FramingItem[0].MemoryType = P_MemoryType; \\\n    FramingExPointer->FramingItem[0].BusType = KS_TYPE_DONT_CARE;   \\\n    FramingExPointer->FramingItem[0].MemoryFlags = 0;       \\\n    FramingExPointer->FramingItem[0].BusFlags = 0;          \\\n    FramingExPointer->FramingItem[0].Flags = P_Flags;       \\\n    FramingExPointer->FramingItem[0].Frames = P_Frames;     \\\n    FramingExPointer->FramingItem[0].FileAlignment = P_Alignment;   \\\n    FramingExPointer->FramingItem[0].MemoryTypeWeight = 0;      \\\n    SetDontCareKsFramingRange(KsFramingRange);          \\\n    SetKsFramingRangeWeighted(KsFramingRangeWeighted,       \\\n                              P_MinFrameSize, P_MaxFrameSize);   \\\n  }\n\n#define STATIC_KSEVENTSETID_StreamAllocator             \\\n  0x75d95571L, 0x073c, 0x11d0, 0xa1, 0x61, 0x00, 0x20, 0xaf, 0xd1, 0x56, 0xe4\nDEFINE_GUIDSTRUCT(\"75d95571-073c-11d0-a161-0020afd156e4\", KSEVENTSETID_StreamAllocator);\n#define KSEVENTSETID_StreamAllocator DEFINE_GUIDNAMED(KSEVENTSETID_StreamAllocator)\n\ntypedef enum\n{\n  KSEVENT_STREAMALLOCATOR_INTERNAL_FREEFRAME,\n  KSEVENT_STREAMALLOCATOR_FREEFRAME\n}KSEVENT_STREAMALLOCATOR;\n\n#define STATIC_KSMETHODSETID_StreamAllocator                \\\n  0xcf6e4341L, 0xec87, 0x11cf, 0xa1, 0x30, 0x00, 0x20, 0xaf, 0xd1, 0x56, 0xe4\nDEFINE_GUIDSTRUCT(\"cf6e4341-ec87-11cf-a130-0020afd156e4\", KSMETHODSETID_StreamAllocator);\n#define KSMETHODSETID_StreamAllocator DEFINE_GUIDNAMED(KSMETHODSETID_StreamAllocator)\n\ntypedef enum\n{\n  KSMETHOD_STREAMALLOCATOR_ALLOC,\n  KSMETHOD_STREAMALLOCATOR_FREE\n}KSMETHOD_STREAMALLOCATOR;\n\n#define DEFINE_KSMETHOD_ITEM_STREAMALLOCATOR_ALLOC(Handler)     \\\n  DEFINE_KSMETHOD_ITEM(                       \\\n    KSMETHOD_STREAMALLOCATOR_ALLOC,     \\\n    KSMETHOD_TYPE_WRITE,            \\\n    (Handler),              \\\n    sizeof(KSMETHOD),           \\\n    sizeof(PVOID),              \\\n    NULL)\n\n#define DEFINE_KSMETHOD_ITEM_STREAMALLOCATOR_FREE(Handler)      \\\n  DEFINE_KSMETHOD_ITEM(                       \\\n    KSMETHOD_STREAMALLOCATOR_FREE,      \\\n    KSMETHOD_TYPE_READ,         \\\n    (Handler),              \\\n    sizeof(KSMETHOD),           \\\n    sizeof(PVOID),              \\\n    NULL)\n\n#define DEFINE_KSMETHOD_ALLOCATORSET(AllocatorSet, MethodAlloc, MethodFree) \\\n  DEFINE_KSMETHOD_TABLE(AllocatorSet) {                   \\\n    DEFINE_KSMETHOD_ITEM_STREAMALLOCATOR_ALLOC(MethodAlloc),    \\\n    DEFINE_KSMETHOD_ITEM_STREAMALLOCATOR_FREE(MethodFree)       \\\n  }\n\n#define STATIC_KSPROPSETID_StreamAllocator              \\\n  0xcf6e4342L, 0xec87, 0x11cf, 0xa1, 0x30, 0x00, 0x20, 0xaf, 0xd1, 0x56, 0xe4\nDEFINE_GUIDSTRUCT(\"cf6e4342-ec87-11cf-a130-0020afd156e4\", KSPROPSETID_StreamAllocator);\n#define KSPROPSETID_StreamAllocator DEFINE_GUIDNAMED(KSPROPSETID_StreamAllocator)\n\n#if defined(_NTDDK_)\ntypedef enum\n{\n  KSPROPERTY_STREAMALLOCATOR_FUNCTIONTABLE,\n  KSPROPERTY_STREAMALLOCATOR_STATUS\n}KSPROPERTY_STREAMALLOCATOR;\n\n # define DEFINE_KSPROPERTY_ITEM_STREAMALLOCATOR_FUNCTIONTABLE(Handler)   \\\n  DEFINE_KSPROPERTY_ITEM(                     \\\n    KSPROPERTY_STREAMALLOCATOR_FUNCTIONTABLE, \\\n    (Handler),              \\\n    sizeof(KSPROPERTY),         \\\n    sizeof(KSSTREAMALLOCATOR_FUNCTIONTABLE), \\\n    NULL, NULL, 0, NULL, NULL, 0)\n\n # define DEFINE_KSPROPERTY_ITEM_STREAMALLOCATOR_STATUS(Handler)      \\\n  DEFINE_KSPROPERTY_ITEM(                     \\\n    KSPROPERTY_STREAMALLOCATOR_STATUS,  \\\n    (Handler),              \\\n    sizeof(KSPROPERTY),         \\\n    sizeof(KSSTREAMALLOCATOR_STATUS),   \\\n    NULL, NULL, 0, NULL, NULL, 0)\n\n # define DEFINE_KSPROPERTY_ALLOCATORSET(AllocatorSet, PropFunctionTable, PropStatus) \\\n  DEFINE_KSPROPERTY_TABLE(AllocatorSet) {                 \\\n    DEFINE_KSPROPERTY_ITEM_STREAMALLOCATOR_STATUS(PropStatus),  \\\n    DEFINE_KSPROPERTY_ITEM_STREAMALLOCATOR_FUNCTIONTABLE(PropFunctionTable) \\\n  }\n\ntypedef NTSTATUS (*PFNALLOCATOR_ALLOCATEFRAME)(PFILE_OBJECT FileObject,\n                                               PVOID* Frame);\ntypedef VOID (*PFNALLOCATOR_FREEFRAME)(PFILE_OBJECT FileObject, PVOID Frame);\n\ntypedef struct\n{\n  PFNALLOCATOR_ALLOCATEFRAME AllocateFrame;\n  PFNALLOCATOR_FREEFRAME FreeFrame;\n}KSSTREAMALLOCATOR_FUNCTIONTABLE, * PKSSTREAMALLOCATOR_FUNCTIONTABLE;\n#endif /* _NTDDK_ */\n\ntypedef struct\n{\n  KSALLOCATOR_FRAMING Framing;\n  ULONG AllocatedFrames;\n  ULONG Reserved;\n}KSSTREAMALLOCATOR_STATUS, * PKSSTREAMALLOCATOR_STATUS;\n\ntypedef struct\n{\n  KSALLOCATOR_FRAMING_EX Framing;\n  ULONG AllocatedFrames;\n  ULONG Reserved;\n}KSSTREAMALLOCATOR_STATUS_EX, * PKSSTREAMALLOCATOR_STATUS_EX;\n\n#define KSSTREAM_HEADER_OPTIONSF_SPLICEPOINT 0x00000001\n#define KSSTREAM_HEADER_OPTIONSF_PREROLL 0x00000002\n#define KSSTREAM_HEADER_OPTIONSF_DATADISCONTINUITY 0x00000004\n#define KSSTREAM_HEADER_OPTIONSF_TYPECHANGED 0x00000008\n#define KSSTREAM_HEADER_OPTIONSF_TIMEVALID 0x00000010\n#define KSSTREAM_HEADER_OPTIONSF_TIMEDISCONTINUITY 0x00000040\n#define KSSTREAM_HEADER_OPTIONSF_FLUSHONPAUSE 0x00000080\n#define KSSTREAM_HEADER_OPTIONSF_DURATIONVALID 0x00000100\n#define KSSTREAM_HEADER_OPTIONSF_ENDOFSTREAM 0x00000200\n#define KSSTREAM_HEADER_OPTIONSF_LOOPEDDATA 0x80000000\n\ntypedef struct\n{\n  LONGLONG Time;\n  ULONG Numerator;\n  ULONG Denominator;\n}KSTIME, * PKSTIME;\n\ntypedef struct\n{\n  ULONG Size;\n  ULONG TypeSpecificFlags;\n  KSTIME PresentationTime;\n  LONGLONG Duration;\n  ULONG FrameExtent;\n  ULONG DataUsed;\n  PVOID Data;\n  ULONG OptionsFlags;\n#ifdef _WIN64\n  ULONG Reserved;\n#endif\n}KSSTREAM_HEADER, * PKSSTREAM_HEADER;\n\n#define STATIC_KSPROPSETID_StreamInterface              \\\n  0x1fdd8ee1L, 0x9cd3, 0x11d0, 0x82, 0xaa, 0x00, 0x00, 0xf8, 0x22, 0xfe, 0x8a\nDEFINE_GUIDSTRUCT(\"1fdd8ee1-9cd3-11d0-82aa-0000f822fe8a\", KSPROPSETID_StreamInterface);\n#define KSPROPSETID_StreamInterface DEFINE_GUIDNAMED(KSPROPSETID_StreamInterface)\n\ntypedef enum\n{\n  KSPROPERTY_STREAMINTERFACE_HEADERSIZE\n}KSPROPERTY_STREAMINTERFACE;\n\n#define DEFINE_KSPROPERTY_ITEM_STREAMINTERFACE_HEADERSIZE(GetHandler)   \\\n  DEFINE_KSPROPERTY_ITEM(                     \\\n    KSPROPERTY_STREAMINTERFACE_HEADERSIZE,  \\\n    (GetHandler),               \\\n    sizeof(KSPROPERTY),         \\\n    sizeof(ULONG),              \\\n    NULL, NULL, 0, NULL, NULL, 0)\n\n#define DEFINE_KSPROPERTY_STREAMINTERFACESET(StreamInterfaceSet, HeaderSizeHandler) \\\n  DEFINE_KSPROPERTY_TABLE(StreamInterfaceSet) {               \\\n    DEFINE_KSPROPERTY_ITEM_STREAMINTERFACE_HEADERSIZE(HeaderSizeHandler) \\\n  }\n\n#define STATIC_KSPROPSETID_Stream                   \\\n  0x65aaba60L, 0x98ae, 0x11cf, 0xa1, 0x0d, 0x00, 0x20, 0xaf, 0xd1, 0x56, 0xe4\nDEFINE_GUIDSTRUCT(\"65aaba60-98ae-11cf-a10d-0020afd156e4\", KSPROPSETID_Stream);\n#define KSPROPSETID_Stream DEFINE_GUIDNAMED(KSPROPSETID_Stream)\n\ntypedef enum\n{\n  KSPROPERTY_STREAM_ALLOCATOR,\n  KSPROPERTY_STREAM_QUALITY,\n  KSPROPERTY_STREAM_DEGRADATION,\n  KSPROPERTY_STREAM_MASTERCLOCK,\n  KSPROPERTY_STREAM_TIMEFORMAT,\n  KSPROPERTY_STREAM_PRESENTATIONTIME,\n  KSPROPERTY_STREAM_PRESENTATIONEXTENT,\n  KSPROPERTY_STREAM_FRAMETIME,\n  KSPROPERTY_STREAM_RATECAPABILITY,\n  KSPROPERTY_STREAM_RATE,\n  KSPROPERTY_STREAM_PIPE_ID\n}KSPROPERTY_STREAM;\n\n#define DEFINE_KSPROPERTY_ITEM_STREAM_ALLOCATOR(GetHandler, SetHandler)  \\\n  DEFINE_KSPROPERTY_ITEM(                     \\\n    KSPROPERTY_STREAM_ALLOCATOR,        \\\n    (GetHandler),               \\\n    sizeof(KSPROPERTY),         \\\n    sizeof(HANDLE),             \\\n    (SetHandler),               \\\n    NULL, 0, NULL, NULL, 0)\n\n#define DEFINE_KSPROPERTY_ITEM_STREAM_QUALITY(Handler)          \\\n  DEFINE_KSPROPERTY_ITEM(                     \\\n    KSPROPERTY_STREAM_QUALITY,      \\\n    (Handler),              \\\n    sizeof(KSPROPERTY),         \\\n    sizeof(KSQUALITY_MANAGER),      \\\n    NULL, NULL, 0, NULL, NULL, 0)\n\n#define DEFINE_KSPROPERTY_ITEM_STREAM_DEGRADATION(GetHandler, SetHandler) \\\n  DEFINE_KSPROPERTY_ITEM(                     \\\n    KSPROPERTY_STREAM_DEGRADATION,      \\\n    (GetHandler),               \\\n    sizeof(KSPROPERTY),         \\\n    0,                  \\\n    (SetHandler),               \\\n    NULL, 0, NULL, NULL, 0)\n\n#define DEFINE_KSPROPERTY_ITEM_STREAM_MASTERCLOCK(GetHandler, SetHandler) \\\n  DEFINE_KSPROPERTY_ITEM(                     \\\n    KSPROPERTY_STREAM_MASTERCLOCK,      \\\n    (GetHandler),               \\\n    sizeof(KSPROPERTY),         \\\n    sizeof(HANDLE),             \\\n    (SetHandler),               \\\n    NULL, 0, NULL, NULL, 0)\n\n#define DEFINE_KSPROPERTY_ITEM_STREAM_TIMEFORMAT(Handler)       \\\n  DEFINE_KSPROPERTY_ITEM(                     \\\n    KSPROPERTY_STREAM_TIMEFORMAT,       \\\n    (Handler),              \\\n    sizeof(KSPROPERTY),         \\\n    sizeof(GUID),               \\\n    NULL, NULL, 0, NULL, NULL, 0)\n\n#define DEFINE_KSPROPERTY_ITEM_STREAM_PRESENTATIONTIME(GetHandler, SetHandler) \\\n  DEFINE_KSPROPERTY_ITEM(                     \\\n    KSPROPERTY_STREAM_PRESENTATIONTIME, \\\n    (GetHandler),               \\\n    sizeof(KSPROPERTY),         \\\n    sizeof(KSTIME),             \\\n    (SetHandler),               \\\n    NULL, 0, NULL, NULL, 0)\n\n#define DEFINE_KSPROPERTY_ITEM_STREAM_PRESENTATIONEXTENT(Handler)   \\\n  DEFINE_KSPROPERTY_ITEM(                     \\\n    KSPROPERTY_STREAM_PRESENTATIONEXTENT,   \\\n    (Handler),              \\\n    sizeof(KSPROPERTY),         \\\n    sizeof(LONGLONG),           \\\n    NULL, NULL, 0, NULL, NULL, 0)\n\n#define DEFINE_KSPROPERTY_ITEM_STREAM_FRAMETIME(Handler)        \\\n  DEFINE_KSPROPERTY_ITEM(                     \\\n    KSPROPERTY_STREAM_FRAMETIME,        \\\n    (Handler),              \\\n    sizeof(KSPROPERTY),         \\\n    sizeof(KSFRAMETIME),            \\\n    NULL, NULL, 0, NULL, NULL, 0)\n\n#define DEFINE_KSPROPERTY_ITEM_STREAM_RATECAPABILITY(Handler)       \\\n  DEFINE_KSPROPERTY_ITEM(                     \\\n    KSPROPERTY_STREAM_RATECAPABILITY,   \\\n    (Handler),              \\\n    sizeof(KSRATE_CAPABILITY),      \\\n    sizeof(KSRATE),             \\\n    NULL, NULL, 0, NULL, NULL, 0)\n\n#define DEFINE_KSPROPERTY_ITEM_STREAM_RATE(GetHandler, SetHandler)   \\\n  DEFINE_KSPROPERTY_ITEM(                     \\\n    KSPROPERTY_STREAM_RATE,         \\\n    (GetHandler),               \\\n    sizeof(KSPROPERTY),         \\\n    sizeof(KSRATE),             \\\n    (SetHandler),               \\\n    NULL, 0, NULL, NULL, 0)\n\n#define DEFINE_KSPROPERTY_ITEM_STREAM_PIPE_ID(GetHandler, SetHandler)    \\\n  DEFINE_KSPROPERTY_ITEM(                     \\\n    KSPROPERTY_STREAM_PIPE_ID,      \\\n    (GetHandler),               \\\n    sizeof(KSPROPERTY),         \\\n    sizeof(HANDLE),             \\\n    (SetHandler),               \\\n    NULL, 0, NULL, NULL, 0)\n\ntypedef struct\n{\n  HANDLE QualityManager;\n  PVOID Context;\n}KSQUALITY_MANAGER, * PKSQUALITY_MANAGER;\n\ntypedef struct\n{\n  LONGLONG Duration;\n  ULONG FrameFlags;\n  ULONG Reserved;\n}KSFRAMETIME, * PKSFRAMETIME;\n\n#define KSFRAMETIME_VARIABLESIZE 0x00000001\n\ntypedef struct\n{\n  LONGLONG PresentationStart;\n  LONGLONG Duration;\n  KSPIN_INTERFACE Interface;\n  LONG Rate;\n  ULONG Flags;\n}KSRATE, * PKSRATE;\n\n#define KSRATE_NOPRESENTATIONSTART 0x00000001\n#define KSRATE_NOPRESENTATIONDURATION 0x00000002\n\ntypedef struct\n{\n  KSPROPERTY Property;\n  KSRATE Rate;\n}KSRATE_CAPABILITY, * PKSRATE_CAPABILITY;\n\n#define STATIC_KSPROPSETID_Clock                    \\\n  0xDF12A4C0L, 0xAC17, 0x11CF, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00\nDEFINE_GUIDSTRUCT(\"DF12A4C0-AC17-11CF-A5D6-28DB04C10000\", KSPROPSETID_Clock);\n#define KSPROPSETID_Clock DEFINE_GUIDNAMED(KSPROPSETID_Clock)\n\n#define NANOSECONDS 10000000\n#define KSCONVERT_PERFORMANCE_TIME(Frequency, PerformanceTime)       \\\n  ((((ULONGLONG)(ULONG)(PerformanceTime).HighPart * NANOSECONDS / (Frequency)) << 32) +    \\\n   ((((((ULONGLONG)(ULONG)(PerformanceTime).HighPart * NANOSECONDS) % (Frequency)) << 32) + \\\n     ((ULONGLONG)(PerformanceTime).LowPart * NANOSECONDS)) / (Frequency)))\n\ntypedef struct\n{\n  ULONG CreateFlags;\n}KSCLOCK_CREATE, * PKSCLOCK_CREATE;\n\ntypedef struct\n{\n  LONGLONG Time;\n  LONGLONG SystemTime;\n}KSCORRELATED_TIME, * PKSCORRELATED_TIME;\n\ntypedef struct\n{\n  LONGLONG Granularity;\n  LONGLONG Error;\n}KSRESOLUTION, * PKSRESOLUTION;\n\ntypedef enum\n{\n  KSPROPERTY_CLOCK_TIME,\n  KSPROPERTY_CLOCK_PHYSICALTIME,\n  KSPROPERTY_CLOCK_CORRELATEDTIME,\n  KSPROPERTY_CLOCK_CORRELATEDPHYSICALTIME,\n  KSPROPERTY_CLOCK_RESOLUTION,\n  KSPROPERTY_CLOCK_STATE,\n#if defined(_NTDDK_)\n  KSPROPERTY_CLOCK_FUNCTIONTABLE\n#endif /* _NTDDK_ */\n}KSPROPERTY_CLOCK;\n\n#if defined(_NTDDK_)\ntypedef LONGLONG (FASTCALL * PFNKSCLOCK_GETTIME)(PFILE_OBJECT FileObject);\ntypedef LONGLONG (FASTCALL * PFNKSCLOCK_CORRELATEDTIME)(PFILE_OBJECT FileObject,\n                                                        PLONGLONG SystemTime);\n\ntypedef struct\n{\n  PFNKSCLOCK_GETTIME GetTime;\n  PFNKSCLOCK_GETTIME GetPhysicalTime;\n  PFNKSCLOCK_CORRELATEDTIME GetCorrelatedTime;\n  PFNKSCLOCK_CORRELATEDTIME GetCorrelatedPhysicalTime;\n}KSCLOCK_FUNCTIONTABLE, * PKSCLOCK_FUNCTIONTABLE;\n\ntypedef BOOLEAN (*PFNKSSETTIMER)(PVOID Context, PKTIMER Timer,\n                                 LARGE_INTEGER DueTime, PKDPC Dpc);\ntypedef BOOLEAN (*PFNKSCANCELTIMER)(PVOID Context, PKTIMER Timer);\ntypedef LONGLONG (FASTCALL * PFNKSCORRELATEDTIME)(PVOID Context,\n                                                  PLONGLONG SystemTime);\n\ntypedef PVOID PKSDEFAULTCLOCK;\n\n # define DEFINE_KSPROPERTY_ITEM_CLOCK_TIME(Handler)          \\\n  DEFINE_KSPROPERTY_ITEM(                     \\\n    KSPROPERTY_CLOCK_TIME,          \\\n    (Handler),              \\\n    sizeof(KSPROPERTY), sizeof(LONGLONG),   \\\n    NULL, NULL, 0, NULL, NULL, 0)\n\n # define DEFINE_KSPROPERTY_ITEM_CLOCK_PHYSICALTIME(Handler)      \\\n  DEFINE_KSPROPERTY_ITEM(                     \\\n    KSPROPERTY_CLOCK_PHYSICALTIME,      \\\n    (Handler),              \\\n    sizeof(KSPROPERTY), sizeof(LONGLONG),   \\\n    NULL, NULL, 0, NULL, NULL, 0)\n\n # define DEFINE_KSPROPERTY_ITEM_CLOCK_CORRELATEDTIME(Handler)        \\\n  DEFINE_KSPROPERTY_ITEM(                     \\\n    KSPROPERTY_CLOCK_CORRELATEDTIME,    \\\n    (Handler),              \\\n    sizeof(KSPROPERTY),         \\\n    sizeof(KSCORRELATED_TIME),      \\\n    NULL, NULL, 0, NULL, NULL, 0)\n\n # define DEFINE_KSPROPERTY_ITEM_CLOCK_CORRELATEDPHYSICALTIME(Handler)    \\\n  DEFINE_KSPROPERTY_ITEM(                     \\\n    KSPROPERTY_CLOCK_CORRELATEDPHYSICALTIME, \\\n    (Handler),              \\\n    sizeof(KSPROPERTY),         \\\n    sizeof(KSCORRELATED_TIME),      \\\n    NULL, NULL, 0, NULL, NULL, 0)\n\n # define DEFINE_KSPROPERTY_ITEM_CLOCK_RESOLUTION(Handler)        \\\n  DEFINE_KSPROPERTY_ITEM(                     \\\n    KSPROPERTY_CLOCK_RESOLUTION,        \\\n    (Handler),              \\\n    sizeof(KSPROPERTY), sizeof(KSRESOLUTION), \\\n    NULL, NULL, 0, NULL, NULL, 0)\n\n # define DEFINE_KSPROPERTY_ITEM_CLOCK_STATE(Handler)         \\\n  DEFINE_KSPROPERTY_ITEM(                     \\\n    KSPROPERTY_CLOCK_STATE,         \\\n    (Handler),              \\\n    sizeof(KSPROPERTY), sizeof(KSSTATE),    \\\n    NULL, NULL, 0, NULL, NULL, 0)\n\n # define DEFINE_KSPROPERTY_ITEM_CLOCK_FUNCTIONTABLE(Handler)     \\\n  DEFINE_KSPROPERTY_ITEM(                     \\\n    KSPROPERTY_CLOCK_FUNCTIONTABLE,     \\\n    (Handler),              \\\n    sizeof(KSPROPERTY),         \\\n    sizeof(KSCLOCK_FUNCTIONTABLE),      \\\n    NULL, NULL, 0, NULL, NULL, 0)\n\n # define DEFINE_KSPROPERTY_CLOCKSET(ClockSet, PropTime, PropPhysicalTime, PropCorrelatedTime, PropCorrelatedPhysicalTime, PropResolution, PropState, PropFunctionTable) \\\n  DEFINE_KSPROPERTY_TABLE(ClockSet) {                 \\\n    DEFINE_KSPROPERTY_ITEM_CLOCK_TIME(PropTime),            \\\n    DEFINE_KSPROPERTY_ITEM_CLOCK_PHYSICALTIME(PropPhysicalTime),    \\\n    DEFINE_KSPROPERTY_ITEM_CLOCK_CORRELATEDTIME(PropCorrelatedTime), \\\n    DEFINE_KSPROPERTY_ITEM_CLOCK_CORRELATEDPHYSICALTIME(PropCorrelatedPhysicalTime), \\\n    DEFINE_KSPROPERTY_ITEM_CLOCK_RESOLUTION(PropResolution),    \\\n    DEFINE_KSPROPERTY_ITEM_CLOCK_STATE(PropState),          \\\n    DEFINE_KSPROPERTY_ITEM_CLOCK_FUNCTIONTABLE(PropFunctionTable),  \\\n  }\n#endif /* _NTDDK_ */\n\n#define STATIC_KSEVENTSETID_Clock                   \\\n  0x364D8E20L, 0x62C7, 0x11CF, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00\nDEFINE_GUIDSTRUCT(\"364D8E20-62C7-11CF-A5D6-28DB04C10000\", KSEVENTSETID_Clock);\n#define KSEVENTSETID_Clock DEFINE_GUIDNAMED(KSEVENTSETID_Clock)\n\ntypedef enum\n{\n  KSEVENT_CLOCK_INTERVAL_MARK,\n  KSEVENT_CLOCK_POSITION_MARK\n}KSEVENT_CLOCK_POSITION;\n\n#define STATIC_KSEVENTSETID_Connection                  \\\n  0x7f4bcbe0L, 0x9ea5, 0x11cf, 0xa5, 0xd6, 0x28, 0xdb, 0x04, 0xc1, 0x00, 0x00\nDEFINE_GUIDSTRUCT(\"7f4bcbe0-9ea5-11cf-a5d6-28db04c10000\", KSEVENTSETID_Connection);\n#define KSEVENTSETID_Connection DEFINE_GUIDNAMED(KSEVENTSETID_Connection)\n\ntypedef enum\n{\n  KSEVENT_CONNECTION_POSITIONUPDATE,\n  KSEVENT_CONNECTION_DATADISCONTINUITY,\n  KSEVENT_CONNECTION_TIMEDISCONTINUITY,\n  KSEVENT_CONNECTION_PRIORITY,\n  KSEVENT_CONNECTION_ENDOFSTREAM\n}KSEVENT_CONNECTION;\n\ntypedef struct\n{\n  PVOID Context;\n  ULONG Proportion;\n  LONGLONG DeltaTime;\n}KSQUALITY, * PKSQUALITY;\n\ntypedef struct\n{\n  PVOID Context;\n  ULONG Status;\n}KSERROR, * PKSERROR;\n\ntypedef KSIDENTIFIER KSDEGRADE, * PKSDEGRADE;\n\n#define STATIC_KSDEGRADESETID_Standard                  \\\n  0x9F564180L, 0x704C, 0x11D0, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00\nDEFINE_GUIDSTRUCT(\"9F564180-704C-11D0-A5D6-28DB04C10000\", KSDEGRADESETID_Standard);\n#define KSDEGRADESETID_Standard DEFINE_GUIDNAMED(KSDEGRADESETID_Standard)\n\ntypedef enum\n{\n  KSDEGRADE_STANDARD_SAMPLE,\n  KSDEGRADE_STANDARD_QUALITY,\n  KSDEGRADE_STANDARD_COMPUTATION,\n  KSDEGRADE_STANDARD_SKIP\n}KSDEGRADE_STANDARD;\n\n#if defined(_NTDDK_)\n\n # define KSPROBE_STREAMREAD 0x00000000\n # define KSPROBE_STREAMWRITE 0x00000001\n # define KSPROBE_ALLOCATEMDL 0x00000010\n # define KSPROBE_PROBEANDLOCK 0x00000020\n # define KSPROBE_SYSTEMADDRESS 0x00000040\n # define KSPROBE_MODIFY 0x00000200\n # define KSPROBE_STREAMWRITEMODIFY (KSPROBE_MODIFY | KSPROBE_STREAMWRITE)\n # define KSPROBE_ALLOWFORMATCHANGE 0x00000080\n # define KSSTREAM_READ KSPROBE_STREAMREAD\n # define KSSTREAM_WRITE KSPROBE_STREAMWRITE\n # define KSSTREAM_PAGED_DATA 0x00000000\n # define KSSTREAM_NONPAGED_DATA 0x00000100\n # define KSSTREAM_SYNCHRONOUS 0x00001000\n # define KSSTREAM_FAILUREEXCEPTION 0x00002000\n\ntypedef NTSTATUS (*PFNKSCONTEXT_DISPATCH)(PVOID Context, PIRP Irp);\ntypedef NTSTATUS (*PFNKSHANDLER)(PIRP Irp, PKSIDENTIFIER Request, PVOID Data);\ntypedef BOOLEAN (*PFNKSFASTHANDLER)(PFILE_OBJECT FileObject,\n                                    PKSIDENTIFIER Request,\n                                    ULONG RequestLength, PVOID Data,\n                                    ULONG DataLength,\n                                    PIO_STATUS_BLOCK IoStatus);\ntypedef NTSTATUS (*PFNKSALLOCATOR)(PIRP Irp, ULONG BufferSize,\n                                   BOOLEAN InputOperation);\n\ntypedef struct\n{\n  KSPROPERTY_MEMBERSHEADER MembersHeader;\n  const VOID* Members;\n}KSPROPERTY_MEMBERSLIST, * PKSPROPERTY_MEMBERSLIST;\n\ntypedef struct\n{\n  KSIDENTIFIER PropTypeSet;\n  ULONG MembersListCount;\n  const KSPROPERTY_MEMBERSLIST* MembersList;\n}KSPROPERTY_VALUES, * PKSPROPERTY_VALUES;\n\n # define DEFINE_KSPROPERTY_TABLE(tablename)              \\\n  const KSPROPERTY_ITEM tablename[] =\n\n # define DEFINE_KSPROPERTY_ITEM(PropertyId, GetHandler, MinProperty, MinData, SetHandler, Values, RelationsCount, Relations, SupportHandler, SerializedSize) \\\n  {                                   \\\n    PropertyId, (PFNKSHANDLER)GetHandler,       \\\n    MinProperty, MinData,               \\\n    (PFNKSHANDLER)SetHandler,           \\\n    (PKSPROPERTY_VALUES)Values, RelationsCount, \\\n    (PKSPROPERTY)Relations,             \\\n    (PFNKSHANDLER)SupportHandler,           \\\n    (ULONG)SerializedSize               \\\n  }\n\ntypedef struct\n{\n  ULONG PropertyId;\n  __MINGW_EXTENSION union\n  {\n    PFNKSHANDLER GetPropertyHandler;\n    BOOLEAN GetSupported;\n  };\n  ULONG MinProperty;\n  ULONG MinData;\n  __MINGW_EXTENSION union\n  {\n    PFNKSHANDLER SetPropertyHandler;\n    BOOLEAN SetSupported;\n  };\n  const KSPROPERTY_VALUES* Values;\n  ULONG RelationsCount;\n  const KSPROPERTY* Relations;\n  PFNKSHANDLER SupportHandler;\n  ULONG SerializedSize;\n}KSPROPERTY_ITEM, * PKSPROPERTY_ITEM;\n\n # define DEFINE_KSFASTPROPERTY_ITEM(PropertyId, GetHandler, SetHandler)  \\\n  {                                   \\\n    PropertyId, (PFNKSFASTHANDLER)GetHandler,   \\\n    (PFNKSFASTHANDLER)SetHandler, 0         \\\n  }\n\ntypedef struct\n{\n  ULONG PropertyId;\n  __MINGW_EXTENSION union\n  {\n    PFNKSFASTHANDLER GetPropertyHandler;\n    BOOLEAN GetSupported;\n  };\n  __MINGW_EXTENSION union\n  {\n    PFNKSFASTHANDLER SetPropertyHandler;\n    BOOLEAN SetSupported;\n  };\n  ULONG Reserved;\n}KSFASTPROPERTY_ITEM, * PKSFASTPROPERTY_ITEM;\n\n # define DEFINE_KSPROPERTY_SET(Set, PropertiesCount, PropertyItem, FastIoCount, FastIoTable) \\\n  {                                   \\\n    Set,                        \\\n    PropertiesCount, PropertyItem,          \\\n    FastIoCount, FastIoTable            \\\n  }\n\n # define DEFINE_KSPROPERTY_SET_TABLE(tablename)              \\\n  const KSPROPERTY_SET tablename[] =\n\ntypedef struct\n{\n  const GUID* Set;\n  ULONG PropertiesCount;\n  const KSPROPERTY_ITEM* PropertyItem;\n  ULONG FastIoCount;\n  const KSFASTPROPERTY_ITEM* FastIoTable;\n}KSPROPERTY_SET, * PKSPROPERTY_SET;\n\n # define DEFINE_KSMETHOD_TABLE(tablename)                \\\n  const KSMETHOD_ITEM tablename[] =\n\n # define DEFINE_KSMETHOD_ITEM(MethodId, Flags, MethodHandler, MinMethod, MinData, SupportHandler) \\\n  {                                   \\\n    MethodId, (PFNKSHANDLER)MethodHandler,      \\\n    MinMethod, MinData,             \\\n    SupportHandler, Flags               \\\n  }\n\ntypedef struct\n{\n  ULONG MethodId;\n  __MINGW_EXTENSION union\n  {\n    PFNKSHANDLER MethodHandler;\n    BOOLEAN MethodSupported;\n  };\n  ULONG MinMethod;\n  ULONG MinData;\n  PFNKSHANDLER SupportHandler;\n  ULONG Flags;\n}KSMETHOD_ITEM, * PKSMETHOD_ITEM;\n\n # define DEFINE_KSFASTMETHOD_ITEM(MethodId, MethodHandler)        \\\n  {                                   \\\n    MethodId, (PFNKSFASTHANDLER)MethodHandler   \\\n  }\n\ntypedef struct\n{\n  ULONG MethodId;\n  __MINGW_EXTENSION union\n  {\n    PFNKSFASTHANDLER MethodHandler;\n    BOOLEAN MethodSupported;\n  };\n}KSFASTMETHOD_ITEM, * PKSFASTMETHOD_ITEM;\n\n # define DEFINE_KSMETHOD_SET(Set, MethodsCount, MethodItem, FastIoCount, FastIoTable) \\\n  {                                   \\\n    Set,                        \\\n    MethodsCount, MethodItem,           \\\n    FastIoCount, FastIoTable            \\\n  }\n\n # define DEFINE_KSMETHOD_SET_TABLE(tablename)                \\\n  const KSMETHOD_SET tablename[] =\n\ntypedef struct\n{\n  const GUID* Set;\n  ULONG MethodsCount;\n  const KSMETHOD_ITEM* MethodItem;\n  ULONG FastIoCount;\n  const KSFASTMETHOD_ITEM* FastIoTable;\n}KSMETHOD_SET, * PKSMETHOD_SET;\n\ntypedef struct _KSEVENT_ENTRY KSEVENT_ENTRY, * PKSEVENT_ENTRY;\ntypedef NTSTATUS (*PFNKSADDEVENT)(PIRP Irp, PKSEVENTDATA EventData,\n                                  struct _KSEVENT_ENTRY* EventEntry);\ntypedef VOID (*PFNKSREMOVEEVENT)(PFILE_OBJECT FileObject,\n                                 struct _KSEVENT_ENTRY* EventEntry);\n\n # define DEFINE_KSEVENT_TABLE(tablename)                 \\\n  const KSEVENT_ITEM tablename[] =\n\n # define DEFINE_KSEVENT_ITEM(EventId, DataInput, ExtraEntryData, AddHandler, RemoveHandler, SupportHandler) \\\n  {                                   \\\n    EventId, DataInput, ExtraEntryData,     \\\n    AddHandler, RemoveHandler, SupportHandler   \\\n  }\n\ntypedef struct\n{\n  ULONG EventId;\n  ULONG DataInput;\n  ULONG ExtraEntryData;\n  PFNKSADDEVENT AddHandler;\n  PFNKSREMOVEEVENT RemoveHandler;\n  PFNKSHANDLER SupportHandler;\n}KSEVENT_ITEM, * PKSEVENT_ITEM;\n\n # define DEFINE_KSEVENT_SET(Set, EventsCount, EventItem)           \\\n  {                                   \\\n    Set, EventsCount, EventItem         \\\n  }\n\n # define DEFINE_KSEVENT_SET_TABLE(tablename)             \\\n  const KSEVENT_SET tablename[] =\n\ntypedef struct\n{\n  const GUID* Set;\n  ULONG EventsCount;\n  const KSEVENT_ITEM* EventItem;\n}KSEVENT_SET, * PKSEVENT_SET;\n\ntypedef struct\n{\n  KDPC Dpc;\n  ULONG ReferenceCount;\n  KSPIN_LOCK AccessLock;\n}KSDPC_ITEM, * PKSDPC_ITEM;\n\ntypedef struct\n{\n  KSDPC_ITEM DpcItem;\n  LIST_ENTRY BufferList;\n}KSBUFFER_ITEM, * PKSBUFFER_ITEM;\n\n # define KSEVENT_ENTRY_DELETED 1\n # define KSEVENT_ENTRY_ONESHOT 2\n # define KSEVENT_ENTRY_BUFFERED 4\n\nstruct _KSEVENT_ENTRY\n{\n  LIST_ENTRY ListEntry;\n  PVOID Object;\n  __MINGW_EXTENSION union\n  {\n    PKSDPC_ITEM DpcItem;\n    PKSBUFFER_ITEM BufferItem;\n  };\n  PKSEVENTDATA EventData;\n  ULONG NotificationType;\n  const KSEVENT_SET* EventSet;\n  const KSEVENT_ITEM* EventItem;\n  PFILE_OBJECT FileObject;\n  ULONG SemaphoreAdjustment;\n  ULONG Reserved;\n  ULONG Flags;\n};\n\ntypedef enum\n{\n  KSEVENTS_NONE,\n  KSEVENTS_SPINLOCK,\n  KSEVENTS_MUTEX,\n  KSEVENTS_FMUTEX,\n  KSEVENTS_FMUTEXUNSAFE,\n  KSEVENTS_INTERRUPT,\n  KSEVENTS_ERESOURCE\n}KSEVENTS_LOCKTYPE;\n\n # define KSDISPATCH_FASTIO 0x80000000\n\ntypedef struct\n{\n  PDRIVER_DISPATCH Create;\n  PVOID Context;\n  UNICODE_STRING ObjectClass;\n  PSECURITY_DESCRIPTOR SecurityDescriptor;\n  ULONG Flags;\n}KSOBJECT_CREATE_ITEM, * PKSOBJECT_CREATE_ITEM;\n\ntypedef VOID (*PFNKSITEMFREECALLBACK)(PKSOBJECT_CREATE_ITEM CreateItem);\n\n # define KSCREATE_ITEM_SECURITYCHANGED 0x00000001\n # define KSCREATE_ITEM_WILDCARD 0x00000002\n # define KSCREATE_ITEM_NOPARAMETERS 0x00000004\n # define KSCREATE_ITEM_FREEONSTOP 0x00000008\n\n # define DEFINE_KSCREATE_DISPATCH_TABLE(tablename)         \\\n  KSOBJECT_CREATE_ITEM tablename[] =\n\n # define DEFINE_KSCREATE_ITEM(DispatchCreate, TypeName, Context)       \\\n  {                                   \\\n    (DispatchCreate), (PVOID)(Context),     \\\n    {                       \\\n      sizeof(TypeName) - sizeof(UNICODE_NULL), \\\n      sizeof(TypeName),           \\\n      (PWCHAR)(TypeName)          \\\n    },                      \\\n    NULL, 0                     \\\n  }\n\n # define DEFINE_KSCREATE_ITEMEX(DispatchCreate, TypeName, Context, Flags)   \\\n  {                                   \\\n    (DispatchCreate),               \\\n    (PVOID)(Context),               \\\n    {                       \\\n      sizeof(TypeName) - sizeof(UNICODE_NULL), \\\n      sizeof(TypeName),           \\\n      (PWCHAR)(TypeName)          \\\n    },                      \\\n    NULL, (Flags)                   \\\n  }\n\n # define DEFINE_KSCREATE_ITEMNULL(DispatchCreate, Context)        \\\n  {                                   \\\n    DispatchCreate, Context,            \\\n    {                       \\\n      0, 0, NULL,             \\\n    },                      \\\n    NULL, 0                     \\\n  }\n\ntypedef struct\n{\n  ULONG CreateItemsCount;\n  PKSOBJECT_CREATE_ITEM CreateItemsList;\n}KSOBJECT_CREATE, * PKSOBJECT_CREATE;\n\ntypedef struct\n{\n  PDRIVER_DISPATCH DeviceIoControl;\n  PDRIVER_DISPATCH Read;\n  PDRIVER_DISPATCH Write;\n  PDRIVER_DISPATCH Flush;\n  PDRIVER_DISPATCH Close;\n  PDRIVER_DISPATCH QuerySecurity;\n  PDRIVER_DISPATCH SetSecurity;\n  PFAST_IO_DEVICE_CONTROL FastDeviceIoControl;\n  PFAST_IO_READ FastRead;\n  PFAST_IO_WRITE FastWrite;\n}KSDISPATCH_TABLE, * PKSDISPATCH_TABLE;\n\n # define DEFINE_KSDISPATCH_TABLE(tablename, DeviceIoControl, Read, Write, Flush, Close, QuerySecurity, SetSecurity, FastDeviceIoControl, FastRead, FastWrite) \\\n  const KSDISPATCH_TABLE tablename =              \\\n  {                               \\\n    DeviceIoControl,                    \\\n    Read,                           \\\n    Write,                          \\\n    Flush,                          \\\n    Close,                          \\\n    QuerySecurity,                      \\\n    SetSecurity,                        \\\n    FastDeviceIoControl,                    \\\n    FastRead,                       \\\n    FastWrite,                      \\\n  }\n\n # define KSCREATE_ITEM_IRP_STORAGE(Irp)                  \\\n  (*(PKSOBJECT_CREATE_ITEM*)&(Irp)->Tail.Overlay.DriverContext[0])\n # define KSEVENT_SET_IRP_STORAGE(Irp)                    \\\n  (*(const KSEVENT_SET**)&(Irp)->Tail.Overlay.DriverContext[0])\n # define KSEVENT_ITEM_IRP_STORAGE(Irp)                   \\\n  (*(const KSEVENT_ITEM**)&(Irp)->Tail.Overlay.DriverContext[3])\n # define KSEVENT_ENTRY_IRP_STORAGE(Irp)                  \\\n  (*(PKSEVENT_ENTRY*)&(Irp)->Tail.Overlay.DriverContext[0])\n # define KSMETHOD_SET_IRP_STORAGE(Irp)                   \\\n  (*(const KSMETHOD_SET**)&(Irp)->Tail.Overlay.DriverContext[0])\n # define KSMETHOD_ITEM_IRP_STORAGE(Irp)                  \\\n  (*(const KSMETHOD_ITEM**)&(Irp)->Tail.Overlay.DriverContext[3])\n # define KSMETHOD_TYPE_IRP_STORAGE(Irp)                  \\\n  (*(ULONG_PTR*)(&(Irp)->Tail.Overlay.DriverContext[2]))\n # define KSQUEUE_SPINLOCK_IRP_STORAGE(Irp)               \\\n  (*(PKSPIN_LOCK*)&(Irp)->Tail.Overlay.DriverContext[1])\n # define KSPROPERTY_SET_IRP_STORAGE(Irp)                 \\\n  (*(const KSPROPERTY_SET**)&(Irp)->Tail.Overlay.DriverContext[0])\n # define KSPROPERTY_ITEM_IRP_STORAGE(Irp)                \\\n  (*(const KSPROPERTY_ITEM**)&(Irp)->Tail.Overlay.DriverContext[3])\n # define KSPROPERTY_ATTRIBUTES_IRP_STORAGE(Irp)              \\\n  (*(PKSATTRIBUTE_LIST*)&(Irp)->Tail.Overlay.DriverContext[2])\n\ntypedef PVOID KSDEVICE_HEADER, KSOBJECT_HEADER;\n\ntypedef enum\n{\n  KsInvokeOnSuccess = 1,\n  KsInvokeOnError = 2,\n  KsInvokeOnCancel = 4\n}KSCOMPLETION_INVOCATION;\n\ntypedef enum\n{\n  KsListEntryTail,\n  KsListEntryHead\n}KSLIST_ENTRY_LOCATION;\n\ntypedef enum\n{\n  KsAcquireOnly,\n  KsAcquireAndRemove,\n  KsAcquireOnlySingleItem,\n  KsAcquireAndRemoveOnlySingleItem\n}KSIRP_REMOVAL_OPERATION;\n\ntypedef enum\n{\n  KsStackCopyToNewLocation,\n  KsStackReuseCurrentLocation,\n  KsStackUseNewLocation\n}KSSTACK_USE;\n\ntypedef enum\n{\n  KSTARGET_STATE_DISABLED,\n  KSTARGET_STATE_ENABLED\n}KSTARGET_STATE;\n\ntypedef NTSTATUS (*PFNKSIRPLISTCALLBACK)(PIRP Irp, PVOID Context);\ntypedef VOID (*PFNREFERENCEDEVICEOBJECT)(PVOID Context);\ntypedef VOID (*PFNDEREFERENCEDEVICEOBJECT)(PVOID Context);\ntypedef NTSTATUS (*PFNQUERYREFERENCESTRING)(PVOID Context, PWCHAR* String);\n\n # define BUS_INTERFACE_REFERENCE_VERSION 0x100\n\ntypedef struct\n{\n  INTERFACE Interface;\n\n  PFNREFERENCEDEVICEOBJECT ReferenceDeviceObject;\n  PFNDEREFERENCEDEVICEOBJECT DereferenceDeviceObject;\n  PFNQUERYREFERENCESTRING QueryReferenceString;\n}BUS_INTERFACE_REFERENCE, * PBUS_INTERFACE_REFERENCE;\n\n # define STATIC_REFERENCE_BUS_INTERFACE STATIC_KSMEDIUMSETID_Standard\n # define REFERENCE_BUS_INTERFACE KSMEDIUMSETID_Standard\n\n#endif /* _NTDDK_ */\n\n#ifndef PACK_PRAGMAS_NOT_SUPPORTED\n # include <pshpack1.h>\n#endif\n\ntypedef struct\n{\n  GUID PropertySet;\n  ULONG Count;\n}KSPROPERTY_SERIALHDR, * PKSPROPERTY_SERIALHDR;\n\n#ifndef PACK_PRAGMAS_NOT_SUPPORTED\n # include <poppack.h>\n#endif\n\ntypedef struct\n{\n  KSIDENTIFIER PropTypeSet;\n  ULONG Id;\n  ULONG PropertyLength;\n}KSPROPERTY_SERIAL, * PKSPROPERTY_SERIAL;\n\n#if defined(_NTDDK_)\n\n # define IOCTL_KS_HANDSHAKE                      \\\n  CTL_CODE(FILE_DEVICE_KS, 0x007, METHOD_NEITHER, FILE_ANY_ACCESS)\n\ntypedef struct\n{\n  GUID ProtocolId;\n  PVOID Argument1;\n  PVOID Argument2;\n}KSHANDSHAKE, * PKSHANDSHAKE;\n\ntypedef struct _KSGATE KSGATE, * PKSGATE;\n\nstruct _KSGATE\n{\n  LONG Count;\n  PKSGATE NextGate;\n};\n\ntypedef PVOID KSOBJECT_BAG;\n\ntypedef BOOLEAN (*PFNKSGENERATEEVENTCALLBACK)(PVOID Context,\n                                              PKSEVENT_ENTRY EventEntry);\n\ntypedef NTSTATUS (*PFNKSDEVICECREATE)(PKSDEVICE Device);\n\ntypedef NTSTATUS (*PFNKSDEVICEPNPSTART)(PKSDEVICE Device, PIRP Irp,\n                                        PCM_RESOURCE_LIST TranslatedResourceList,\n                                        PCM_RESOURCE_LIST UntranslatedResourceList);\n\ntypedef NTSTATUS (*PFNKSDEVICE)(PKSDEVICE Device);\n\ntypedef NTSTATUS (*PFNKSDEVICEIRP)(PKSDEVICE Device, PIRP Irp);\n\ntypedef void (*PFNKSDEVICEIRPVOID)(PKSDEVICE Device, PIRP Irp);\n\ntypedef NTSTATUS (*PFNKSDEVICEQUERYCAPABILITIES)(PKSDEVICE Device, PIRP Irp,\n                                                 PDEVICE_CAPABILITIES Capabilities);\n\ntypedef NTSTATUS (*PFNKSDEVICEQUERYPOWER)(PKSDEVICE Device, PIRP Irp,\n                                          DEVICE_POWER_STATE DeviceTo,\n                                          DEVICE_POWER_STATE DeviceFrom,\n                                          SYSTEM_POWER_STATE SystemTo,\n                                          SYSTEM_POWER_STATE SystemFrom,\n                                          POWER_ACTION Action);\n\ntypedef void (*PFNKSDEVICESETPOWER)(PKSDEVICE Device, PIRP Irp,\n                                    DEVICE_POWER_STATE To,\n                                    DEVICE_POWER_STATE From);\n\ntypedef NTSTATUS (*PFNKSFILTERFACTORYVOID)(PKSFILTERFACTORY FilterFactory);\n\ntypedef void (*PFNKSFILTERFACTORYPOWER)(PKSFILTERFACTORY FilterFactory,\n                                        DEVICE_POWER_STATE State);\n\ntypedef NTSTATUS (*PFNKSFILTERIRP)(PKSFILTER Filter, PIRP Irp);\n\ntypedef NTSTATUS (*PFNKSFILTERPROCESS)(PKSFILTER Filter,\n                                       PKSPROCESSPIN_INDEXENTRY Index);\n\ntypedef NTSTATUS (*PFNKSFILTERVOID)(PKSFILTER Filter);\n\ntypedef void (*PFNKSFILTERPOWER)(PKSFILTER Filter, DEVICE_POWER_STATE State);\n\ntypedef NTSTATUS (*PFNKSPINIRP)(PKSPIN Pin, PIRP Irp);\n\ntypedef NTSTATUS (*PFNKSPINSETDEVICESTATE)(PKSPIN Pin, KSSTATE ToState,\n                                           KSSTATE FromState);\n\ntypedef NTSTATUS (*PFNKSPINSETDATAFORMAT)(PKSPIN Pin, PKSDATAFORMAT OldFormat,\n                                          PKSMULTIPLE_ITEM OldAttributeList,\n                                          const KSDATARANGE* DataRange,\n                                          const KSATTRIBUTE_LIST* AttributeRange);\n\ntypedef NTSTATUS (*PFNKSPINHANDSHAKE)(PKSPIN Pin, PKSHANDSHAKE In,\n                                      PKSHANDSHAKE Out);\n\ntypedef NTSTATUS (*PFNKSPIN)(PKSPIN Pin);\n\ntypedef void (*PFNKSPINVOID)(PKSPIN Pin);\n\ntypedef void (*PFNKSPINPOWER)(PKSPIN Pin, DEVICE_POWER_STATE State);\n\ntypedef BOOLEAN (*PFNKSPINSETTIMER)(PKSPIN Pin, PKTIMER Timer,\n                                    LARGE_INTEGER DueTime, PKDPC Dpc);\n\ntypedef BOOLEAN (*PFNKSPINCANCELTIMER)(PKSPIN Pin, PKTIMER Timer);\n\ntypedef LONGLONG (FASTCALL * PFNKSPINCORRELATEDTIME)(PKSPIN Pin,\n                                                     PLONGLONG SystemTime);\n\ntypedef void (*PFNKSPINRESOLUTION)(PKSPIN Pin, PKSRESOLUTION Resolution);\n\ntypedef NTSTATUS (*PFNKSPININITIALIZEALLOCATOR)(PKSPIN Pin,\n                                                PKSALLOCATOR_FRAMING AllocatorFraming,\n                                                PVOID* Context);\n\ntypedef void (*PFNKSSTREAMPOINTER)(PKSSTREAM_POINTER StreamPointer);\n\ntypedef struct KSAUTOMATION_TABLE_ KSAUTOMATION_TABLE, * PKSAUTOMATION_TABLE;\n\nstruct KSAUTOMATION_TABLE_\n{\n  ULONG PropertySetsCount;\n  ULONG PropertyItemSize;\n  const KSPROPERTY_SET* PropertySets;\n  ULONG MethodSetsCount;\n  ULONG MethodItemSize;\n  const KSMETHOD_SET* MethodSets;\n  ULONG EventSetsCount;\n  ULONG EventItemSize;\n  const KSEVENT_SET* EventSets;\n # ifndef _WIN64\n  PVOID Alignment;\n # endif\n};\n\n # define DEFINE_KSAUTOMATION_TABLE(table)                \\\n  const KSAUTOMATION_TABLE table =\n\n # define DEFINE_KSAUTOMATION_PROPERTIES(table)               \\\n  SIZEOF_ARRAY(table),                    \\\n  sizeof(KSPROPERTY_ITEM),                \\\n  table\n\n # define DEFINE_KSAUTOMATION_METHODS(table)              \\\n  SIZEOF_ARRAY(table),                    \\\n  sizeof(KSMETHOD_ITEM),                  \\\n  table\n\n # define DEFINE_KSAUTOMATION_EVENTS(table)               \\\n  SIZEOF_ARRAY(table),                    \\\n  sizeof(KSEVENT_ITEM),                   \\\n  table\n\n # define DEFINE_KSAUTOMATION_PROPERTIES_NULL             \\\n  0,                          \\\n  sizeof(KSPROPERTY_ITEM),                \\\n  NULL\n\n # define DEFINE_KSAUTOMATION_METHODS_NULL                \\\n  0,                          \\\n  sizeof(KSMETHOD_ITEM),                  \\\n  NULL\n\n # define DEFINE_KSAUTOMATION_EVENTS_NULL                 \\\n  0,                          \\\n  sizeof(KSEVENT_ITEM),                   \\\n  NULL\n\n # define MIN_DEV_VER_FOR_QI (0x100)\n\nstruct _KSDEVICE_DISPATCH\n{\n  PFNKSDEVICECREATE Add;\n  PFNKSDEVICEPNPSTART Start;\n  PFNKSDEVICE PostStart;\n  PFNKSDEVICEIRP QueryStop;\n  PFNKSDEVICEIRPVOID CancelStop;\n  PFNKSDEVICEIRPVOID Stop;\n  PFNKSDEVICEIRP QueryRemove;\n  PFNKSDEVICEIRPVOID CancelRemove;\n  PFNKSDEVICEIRPVOID Remove;\n  PFNKSDEVICEQUERYCAPABILITIES QueryCapabilities;\n  PFNKSDEVICEIRPVOID SurpriseRemoval;\n  PFNKSDEVICEQUERYPOWER QueryPower;\n  PFNKSDEVICESETPOWER SetPower;\n  PFNKSDEVICEIRP QueryInterface;\n};\n\nstruct _KSFILTER_DISPATCH\n{\n  PFNKSFILTERIRP Create;\n  PFNKSFILTERIRP Close;\n  PFNKSFILTERPROCESS Process;\n  PFNKSFILTERVOID Reset;\n};\n\nstruct _KSPIN_DISPATCH\n{\n  PFNKSPINIRP Create;\n  PFNKSPINIRP Close;\n  PFNKSPIN Process;\n  PFNKSPINVOID Reset;\n  PFNKSPINSETDATAFORMAT SetDataFormat;\n  PFNKSPINSETDEVICESTATE SetDeviceState;\n  PFNKSPIN Connect;\n  PFNKSPINVOID Disconnect;\n  const KSCLOCK_DISPATCH* Clock;\n  const KSALLOCATOR_DISPATCH* Allocator;\n};\n\nstruct _KSCLOCK_DISPATCH\n{\n  PFNKSPINSETTIMER SetTimer;\n  PFNKSPINCANCELTIMER CancelTimer;\n  PFNKSPINCORRELATEDTIME CorrelatedTime;\n  PFNKSPINRESOLUTION Resolution;\n};\n\nstruct _KSALLOCATOR_DISPATCH\n{\n  PFNKSPININITIALIZEALLOCATOR InitializeAllocator;\n  PFNKSDELETEALLOCATOR DeleteAllocator;\n  PFNKSDEFAULTALLOCATE Allocate;\n  PFNKSDEFAULTFREE Free;\n};\n\n # define KSDEVICE_DESCRIPTOR_VERSION (0x100)\n\nstruct _KSDEVICE_DESCRIPTOR\n{\n  const KSDEVICE_DISPATCH* Dispatch;\n  ULONG FilterDescriptorsCount;\n  const KSFILTER_DESCRIPTOR* const* FilterDescriptors;\n  ULONG Version;\n};\n\nstruct _KSFILTER_DESCRIPTOR\n{\n  const KSFILTER_DISPATCH* Dispatch;\n  const KSAUTOMATION_TABLE* AutomationTable;\n  ULONG Version;\n # define KSFILTER_DESCRIPTOR_VERSION ((ULONG)-1)\n  ULONG Flags;\n # define KSFILTER_FLAG_DISPATCH_LEVEL_PROCESSING 0x00000001\n # define KSFILTER_FLAG_CRITICAL_PROCESSING 0x00000002\n # define KSFILTER_FLAG_HYPERCRITICAL_PROCESSING 0x00000004\n # define KSFILTER_FLAG_RECEIVE_ZERO_LENGTH_SAMPLES 0x00000008\n # define KSFILTER_FLAG_DENY_USERMODE_ACCESS 0x80000000\n  const GUID* ReferenceGuid;\n  ULONG PinDescriptorsCount;\n  ULONG PinDescriptorSize;\n  const KSPIN_DESCRIPTOR_EX* PinDescriptors;\n  ULONG CategoriesCount;\n  const GUID* Categories;\n  ULONG NodeDescriptorsCount;\n  ULONG NodeDescriptorSize;\n  const KSNODE_DESCRIPTOR* NodeDescriptors;\n  ULONG ConnectionsCount;\n  const KSTOPOLOGY_CONNECTION* Connections;\n  const KSCOMPONENTID* ComponentId;\n};\n\n # define DEFINE_KSFILTER_DESCRIPTOR(descriptor)              \\\n  const KSFILTER_DESCRIPTOR descriptor =\n\n # define DEFINE_KSFILTER_PIN_DESCRIPTORS(table)              \\\n  SIZEOF_ARRAY(table),                        \\\n  sizeof(table[0]),                       \\\n  table\n\n # define DEFINE_KSFILTER_CATEGORIES(table)               \\\n  SIZEOF_ARRAY(table),                        \\\n  table\n\n # define DEFINE_KSFILTER_CATEGORY(category)              \\\n  1,                              \\\n  &(category)\n\n # define DEFINE_KSFILTER_CATEGORIES_NULL                 \\\n  0,                              \\\n  NULL\n\n # define DEFINE_KSFILTER_NODE_DESCRIPTORS(table)             \\\n  SIZEOF_ARRAY(table),                        \\\n  sizeof(table[0]),                       \\\n  table\n\n # define DEFINE_KSFILTER_NODE_DESCRIPTORS_NULL               \\\n  0,                              \\\n  sizeof(KSNODE_DESCRIPTOR),                  \\\n  NULL\n\n # define DEFINE_KSFILTER_CONNECTIONS(table)              \\\n  SIZEOF_ARRAY(table),                        \\\n  table\n\n # define DEFINE_KSFILTER_DEFAULT_CONNECTIONS             \\\n  0,                              \\\n  NULL\n\n # define DEFINE_KSFILTER_DESCRIPTOR_TABLE(table)             \\\n  const KSFILTER_DESCRIPTOR * const table[] =\n\nstruct _KSPIN_DESCRIPTOR_EX\n{\n  const KSPIN_DISPATCH* Dispatch;\n  const KSAUTOMATION_TABLE* AutomationTable;\n  KSPIN_DESCRIPTOR PinDescriptor;\n  ULONG Flags;\n # define KSPIN_FLAG_DISPATCH_LEVEL_PROCESSING KSFILTER_FLAG_DISPATCH_LEVEL_PROCESSING\n # define KSPIN_FLAG_CRITICAL_PROCESSING KSFILTER_FLAG_CRITICAL_PROCESSING\n # define KSPIN_FLAG_HYPERCRITICAL_PROCESSING KSFILTER_FLAG_HYPERCRITICAL_PROCESSING\n # define KSPIN_FLAG_ASYNCHRONOUS_PROCESSING 0x00000008\n # define KSPIN_FLAG_DO_NOT_INITIATE_PROCESSING 0x00000010\n # define KSPIN_FLAG_INITIATE_PROCESSING_ON_EVERY_ARRIVAL 0x00000020\n # define KSPIN_FLAG_FRAMES_NOT_REQUIRED_FOR_PROCESSING 0x00000040\n # define KSPIN_FLAG_ENFORCE_FIFO 0x00000080\n # define KSPIN_FLAG_GENERATE_MAPPINGS 0x00000100\n # define KSPIN_FLAG_DISTINCT_TRAILING_EDGE 0x00000200\n # define KSPIN_FLAG_PROCESS_IN_RUN_STATE_ONLY 0x00010000\n # define KSPIN_FLAG_SPLITTER 0x00020000\n # define KSPIN_FLAG_USE_STANDARD_TRANSPORT 0x00040000\n # define KSPIN_FLAG_DO_NOT_USE_STANDARD_TRANSPORT 0x00080000\n # define KSPIN_FLAG_FIXED_FORMAT 0x00100000\n # define KSPIN_FLAG_GENERATE_EOS_EVENTS 0x00200000\n # define KSPIN_FLAG_RENDERER (KSPIN_FLAG_PROCESS_IN_RUN_STATE_ONLY | KSPIN_FLAG_GENERATE_EOS_EVENTS)\n # define KSPIN_FLAG_IMPLEMENT_CLOCK 0x00400000\n # define KSPIN_FLAG_SOME_FRAMES_REQUIRED_FOR_PROCESSING 0x00800000\n # define KSPIN_FLAG_PROCESS_IF_ANY_IN_RUN_STATE 0x01000000\n # define KSPIN_FLAG_DENY_USERMODE_ACCESS 0x80000000\n  ULONG InstancesPossible;\n  ULONG InstancesNecessary;\n  const KSALLOCATOR_FRAMING_EX* AllocatorFraming;\n  PFNKSINTERSECTHANDLEREX IntersectHandler;\n};\n\n # define DEFINE_KSPIN_DEFAULT_INTERFACES                 \\\n  0,                              \\\n  NULL\n\n # define DEFINE_KSPIN_DEFAULT_MEDIUMS                    \\\n  0,                              \\\n  NULL\n\nstruct _KSNODE_DESCRIPTOR\n{\n  const KSAUTOMATION_TABLE* AutomationTable;\n  const GUID* Type;\n  const GUID* Name;\n # ifndef _WIN64\n  PVOID Alignment;\n # endif\n};\n\n # ifndef _WIN64\n  #  define DEFINE_NODE_DESCRIPTOR(automation, type, name)            \\\n  { (automation), (type), (name), NULL }\n # else\n  #  define DEFINE_NODE_DESCRIPTOR(automation, type, name)            \\\n  { (automation), (type), (name) }\n # endif\n\nstruct _KSDEVICE\n{\n  const KSDEVICE_DESCRIPTOR* Descriptor;\n  KSOBJECT_BAG Bag;\n  PVOID Context;\n  PDEVICE_OBJECT FunctionalDeviceObject;\n  PDEVICE_OBJECT PhysicalDeviceObject;\n  PDEVICE_OBJECT NextDeviceObject;\n  BOOLEAN Started;\n  SYSTEM_POWER_STATE SystemPowerState;\n  DEVICE_POWER_STATE DevicePowerState;\n};\n\nstruct _KSFILTERFACTORY\n{\n  const KSFILTER_DESCRIPTOR* FilterDescriptor;\n  KSOBJECT_BAG Bag;\n  PVOID Context;\n};\n\nstruct _KSFILTER\n{\n  const KSFILTER_DESCRIPTOR* Descriptor;\n  KSOBJECT_BAG Bag;\n  PVOID Context;\n};\n\nstruct _KSPIN\n{\n  const KSPIN_DESCRIPTOR_EX* Descriptor;\n  KSOBJECT_BAG Bag;\n  PVOID Context;\n  ULONG Id;\n  KSPIN_COMMUNICATION Communication;\n  BOOLEAN ConnectionIsExternal;\n  KSPIN_INTERFACE ConnectionInterface;\n  KSPIN_MEDIUM ConnectionMedium;\n  KSPRIORITY ConnectionPriority;\n  PKSDATAFORMAT ConnectionFormat;\n  PKSMULTIPLE_ITEM AttributeList;\n  ULONG StreamHeaderSize;\n  KSPIN_DATAFLOW DataFlow;\n  KSSTATE DeviceState;\n  KSRESET ResetState;\n  KSSTATE ClientState;\n};\n\nstruct _KSMAPPING\n{\n  PHYSICAL_ADDRESS PhysicalAddress;\n  ULONG ByteCount;\n  ULONG Alignment;\n};\n\nstruct _KSSTREAM_POINTER_OFFSET\n{\n # if defined(_NTDDK_)\n  __MINGW_EXTENSION union\n  {\n    PUCHAR Data;\n    PKSMAPPING Mappings;\n  };\n # else\n  PUCHAR Data;\n # endif /* _NTDDK_ */\n # ifndef _WIN64\n  PVOID Alignment;\n # endif\n  ULONG Count;\n  ULONG Remaining;\n};\n\nstruct _KSSTREAM_POINTER\n{\n  PVOID Context;\n  PKSPIN Pin;\n  PKSSTREAM_HEADER StreamHeader;\n  PKSSTREAM_POINTER_OFFSET Offset;\n  KSSTREAM_POINTER_OFFSET OffsetIn;\n  KSSTREAM_POINTER_OFFSET OffsetOut;\n};\n\nstruct _KSPROCESSPIN\n{\n  PKSPIN Pin;\n  PKSSTREAM_POINTER StreamPointer;\n  PKSPROCESSPIN InPlaceCounterpart;\n  PKSPROCESSPIN DelegateBranch;\n  PKSPROCESSPIN CopySource;\n  PVOID Data;\n  ULONG BytesAvailable;\n  ULONG BytesUsed;\n  ULONG Flags;\n  BOOLEAN Terminate;\n};\n\nstruct _KSPROCESSPIN_INDEXENTRY\n{\n  PKSPROCESSPIN* Pins;\n  ULONG Count;\n};\n\ntypedef enum\n{\n  KsObjectTypeDevice,\n  KsObjectTypeFilterFactory,\n  KsObjectTypeFilter,\n  KsObjectTypePin\n}KSOBJECTTYPE;\n\ntypedef void (*PFNKSFREE)(PVOID Data);\n\ntypedef void (*PFNKSPINFRAMERETURN)(PKSPIN Pin, PVOID Data, ULONG Size, PMDL Mdl,\n                                    PVOID Context, NTSTATUS Status);\n\ntypedef void (*PFNKSPINIRPCOMPLETION)(PKSPIN Pin, PIRP Irp);\n\n # if defined(_UNKNOWN_H_) || defined(__IUnknown_INTERFACE_DEFINED__)\n  #  ifndef _IKsControl_\n   #   define _IKsControl_\n\ntypedef struct IKsControl* PIKSCONTROL;\n\n   #   ifndef DEFINE_ABSTRACT_UNKNOWN\n    #    define DEFINE_ABSTRACT_UNKNOWN()                   \\\n  STDMETHOD_(NTSTATUS, QueryInterface) (THIS_          \\\n                                        REFIID InterfaceId, \\\n                                        PVOID * Interface    \\\n                                        )PURE;         \\\n  STDMETHOD_(ULONG, AddRef) (THIS)PURE;                \\\n  STDMETHOD_(ULONG, Release) (THIS)PURE;\n   #   endif\n\n   #   undef INTERFACE\n   #   define INTERFACE IKsControl\nDECLARE_INTERFACE_(IKsControl, IUnknown)\n{\n  DEFINE_ABSTRACT_UNKNOWN()\n  STDMETHOD_(NTSTATUS, KsProperty) (THIS_\n                                    PKSPROPERTY Property,\n                                    ULONG PropertyLength,\n                                    PVOID PropertyData,\n                                    ULONG DataLength,\n                                    ULONG * BytesReturned\n                                    ) PURE;\n  STDMETHOD_(NTSTATUS, KsMethod) (THIS_\n                                  PKSMETHOD Method,\n                                  ULONG MethodLength,\n                                  PVOID MethodData,\n                                  ULONG DataLength,\n                                  ULONG * BytesReturned\n                                  ) PURE;\n  STDMETHOD_(NTSTATUS, KsEvent)  (THIS_\n                                  PKSEVENT Event,\n                                  ULONG EventLength,\n                                  PVOID EventData,\n                                  ULONG DataLength,\n                                  ULONG * BytesReturned\n                                  ) PURE;\n};\ntypedef struct IKsReferenceClock* PIKSREFERENCECLOCK;\n\n   #   undef INTERFACE\n   #   define INTERFACE IKsReferenceClock\nDECLARE_INTERFACE_(IKsReferenceClock, IUnknown)\n{\n  DEFINE_ABSTRACT_UNKNOWN()\n  STDMETHOD_(LONGLONG, GetTime)      (THIS) PURE;\n  STDMETHOD_(LONGLONG, GetPhysicalTime)  (THIS) PURE;\n  STDMETHOD_(LONGLONG, GetCorrelatedTime) (THIS_\n                                           PLONGLONG SystemTime\n                                           ) PURE;\n  STDMETHOD_(LONGLONG, GetCorrelatedPhysicalTime) (THIS_\n                                                   PLONGLONG SystemTime\n                                                   ) PURE;\n  STDMETHOD_(NTSTATUS, GetResolution)    (THIS_\n                                          PKSRESOLUTION Resolution\n                                          ) PURE;\n  STDMETHOD_(NTSTATUS, GetState)     (THIS_\n                                      PKSSTATE State\n                                      ) PURE;\n};\n   #   undef INTERFACE\n\n   #   define INTERFACE IKsDeviceFunctions\nDECLARE_INTERFACE_(IKsDeviceFunctions, IUnknown)\n{\n  DEFINE_ABSTRACT_UNKNOWN()\n  STDMETHOD_(NTSTATUS, RegisterAdapterObjectEx)  (THIS_\n                                                  PADAPTER_OBJECT AdapterObject,\n                                                  PDEVICE_DESCRIPTION DeviceDescription,\n                                                  ULONG NumberOfMapRegisters,\n                                                  ULONG MaxMappingsByteCount,\n                                                  ULONG MappingTableStride\n                                                  ) PURE;\n};\n\n   #   undef INTERFACE\n   #   define STATIC_IID_IKsControl                       \\\n  0x28F54685L, 0x06FD, 0x11D2, 0xB2, 0x7A, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96\nDEFINE_GUID(IID_IKsControl,\n            0x28F54685L, 0x06FD, 0x11D2, 0xB2, 0x7A, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96);\n   #   define STATIC_IID_IKsFastClock                     \\\n  0xc9902485, 0xc180, 0x11d2, 0x84, 0x73, 0xd4, 0x23, 0x94, 0x45, 0x9e, 0x5e\nDEFINE_GUID(IID_IKsFastClock,\n            0xc9902485, 0xc180, 0x11d2, 0x84, 0x73, 0xd4, 0x23, 0x94, 0x45, 0x9e, 0x5e);\n   #   define STATIC_IID_IKsDeviceFunctions                   \\\n  0xe234f2e2, 0xbd69, 0x4f8c, 0xb3, 0xf2, 0x7c, 0xd7, 0x9e, 0xd4, 0x66, 0xbd\nDEFINE_GUID(IID_IKsDeviceFunctions,\n            0xe234f2e2, 0xbd69, 0x4f8c, 0xb3, 0xf2, 0x7c, 0xd7, 0x9e, 0xd4, 0x66, 0xbd);\n  #  endif /* _IKsControl_ */\n # endif /* defined(_UNKNOWN_H_) || defined(__IUnknown_INTERFACE_DEFINED__) */\n\n#endif /* _NTDDK_ */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#ifdef _KSDDK_\n # define KSDDKAPI\n#else\n # define KSDDKAPI DECLSPEC_IMPORT\n#endif\n\n#if defined(_NTDDK_)\n\nKSDDKAPI NTSTATUS NTAPI KsEnableEvent(PIRP Irp, ULONG EventSetsCount, const KSEVENT_SET* EventSet, PLIST_ENTRY EventsList, KSEVENTS_LOCKTYPE EventsFlags, PVOID EventsLock);\n\nKSDDKAPI NTSTATUS NTAPI KsEnableEventWithAllocator(PIRP Irp, ULONG EventSetsCount, const KSEVENT_SET* EventSet, PLIST_ENTRY EventsList, KSEVENTS_LOCKTYPE EventsFlags, PVOID EventsLock, PFNKSALLOCATOR Allocator, ULONG EventItemSize);\n\nKSDDKAPI NTSTATUS NTAPI KsDisableEvent(PIRP Irp, PLIST_ENTRY EventsList, KSEVENTS_LOCKTYPE EventsFlags, PVOID EventsLock);\n\nKSDDKAPI VOID NTAPI KsDiscardEvent(PKSEVENT_ENTRY EventEntry);\n\nKSDDKAPI VOID NTAPI KsFreeEventList(PFILE_OBJECT FileObject, PLIST_ENTRY EventsList, KSEVENTS_LOCKTYPE EventsFlags, PVOID EventsLock);\n\nKSDDKAPI NTSTATUS NTAPI KsGenerateEvent(PKSEVENT_ENTRY EventEntry);\n\nKSDDKAPI NTSTATUS NTAPI KsGenerateDataEvent(PKSEVENT_ENTRY EventEntry, ULONG DataSize, PVOID Data);\n\nKSDDKAPI VOID NTAPI KsGenerateEventList(GUID* Set, ULONG EventId, PLIST_ENTRY EventsList, KSEVENTS_LOCKTYPE EventsFlags, PVOID EventsLock);\n\nKSDDKAPI NTSTATUS NTAPI KsPropertyHandler(PIRP Irp, ULONG PropertySetsCount, const KSPROPERTY_SET* PropertySet);\n\nKSDDKAPI NTSTATUS NTAPI KsPropertyHandlerWithAllocator(PIRP Irp, ULONG PropertySetsCount, const KSPROPERTY_SET* PropertySet, PFNKSALLOCATOR Allocator, ULONG PropertyItemSize);\n\nKSDDKAPI BOOLEAN NTAPI KsFastPropertyHandler(PFILE_OBJECT FileObject, PKSPROPERTY Property, ULONG PropertyLength, PVOID Data, ULONG DataLength, PIO_STATUS_BLOCK IoStatus, ULONG PropertySetsCount, const KSPROPERTY_SET* PropertySet);\n\nKSDDKAPI NTSTATUS NTAPI KsMethodHandler(PIRP Irp, ULONG MethodSetsCount, const KSMETHOD_SET* MethodSet);\n\nKSDDKAPI NTSTATUS NTAPI KsMethodHandlerWithAllocator(PIRP Irp, ULONG MethodSetsCount, const KSMETHOD_SET* MethodSet, PFNKSALLOCATOR Allocator, ULONG MethodItemSize);\n\nKSDDKAPI BOOLEAN NTAPI KsFastMethodHandler(PFILE_OBJECT FileObject, PKSMETHOD Method, ULONG MethodLength, PVOID Data, ULONG DataLength, PIO_STATUS_BLOCK IoStatus, ULONG MethodSetsCount, const KSMETHOD_SET* MethodSet);\n\nKSDDKAPI NTSTATUS NTAPI KsCreateDefaultAllocator(PIRP Irp);\n\nKSDDKAPI NTSTATUS NTAPI KsCreateDefaultAllocatorEx(PIRP Irp, PVOID InitializeContext, PFNKSDEFAULTALLOCATE DefaultAllocate, PFNKSDEFAULTFREE DefaultFree, PFNKSINITIALIZEALLOCATOR InitializeAllocator, PFNKSDELETEALLOCATOR DeleteAllocator);\n\nKSDDKAPI NTSTATUS NTAPI KsCreateAllocator(HANDLE ConnectionHandle, PKSALLOCATOR_FRAMING AllocatorFraming, PHANDLE AllocatorHandle);\n\nKSDDKAPI NTSTATUS NTAPI KsValidateAllocatorCreateRequest(PIRP Irp, PKSALLOCATOR_FRAMING* AllocatorFraming);\n\nKSDDKAPI NTSTATUS NTAPI KsValidateAllocatorFramingEx(PKSALLOCATOR_FRAMING_EX Framing, ULONG BufferSize, const KSALLOCATOR_FRAMING_EX* PinFraming);\n\nKSDDKAPI NTSTATUS NTAPI KsAllocateDefaultClock(PKSDEFAULTCLOCK* DefaultClock);\n\nKSDDKAPI NTSTATUS NTAPI KsAllocateDefaultClockEx(PKSDEFAULTCLOCK* DefaultClock, PVOID Context, PFNKSSETTIMER SetTimer, PFNKSCANCELTIMER CancelTimer, PFNKSCORRELATEDTIME CorrelatedTime, const KSRESOLUTION* Resolution, ULONG Flags);\n\nKSDDKAPI VOID NTAPI KsFreeDefaultClock(PKSDEFAULTCLOCK DefaultClock);\nKSDDKAPI NTSTATUS NTAPI KsCreateDefaultClock(PIRP Irp, PKSDEFAULTCLOCK DefaultClock);\n\nKSDDKAPI NTSTATUS NTAPI KsCreateClock(HANDLE ConnectionHandle, PKSCLOCK_CREATE ClockCreate, PHANDLE ClockHandle);\n\nKSDDKAPI NTSTATUS NTAPI KsValidateClockCreateRequest(PIRP Irp, PKSCLOCK_CREATE* ClockCreate);\n\nKSDDKAPI KSSTATE NTAPI KsGetDefaultClockState(PKSDEFAULTCLOCK DefaultClock);\nKSDDKAPI VOID NTAPI KsSetDefaultClockState(PKSDEFAULTCLOCK DefaultClock, KSSTATE State);\nKSDDKAPI LONGLONG NTAPI KsGetDefaultClockTime(PKSDEFAULTCLOCK DefaultClock);\nKSDDKAPI VOID NTAPI KsSetDefaultClockTime(PKSDEFAULTCLOCK DefaultClock, LONGLONG Time);\n\nKSDDKAPI NTSTATUS NTAPI KsCreatePin(HANDLE FilterHandle, PKSPIN_CONNECT Connect, ACCESS_MASK DesiredAccess, PHANDLE ConnectionHandle);\n\nKSDDKAPI NTSTATUS NTAPI KsValidateConnectRequest(PIRP Irp, ULONG DescriptorsCount, const KSPIN_DESCRIPTOR* Descriptor, PKSPIN_CONNECT* Connect);\n\nKSDDKAPI NTSTATUS NTAPI KsPinPropertyHandler(PIRP Irp, PKSPROPERTY Property, PVOID Data, ULONG DescriptorsCount, const KSPIN_DESCRIPTOR* Descriptor);\n\nKSDDKAPI NTSTATUS NTAPI KsPinDataIntersection(PIRP Irp, PKSP_PIN Pin, PVOID Data, ULONG DescriptorsCount, const KSPIN_DESCRIPTOR* Descriptor, PFNKSINTERSECTHANDLER IntersectHandler);\n\nKSDDKAPI NTSTATUS NTAPI KsPinDataIntersectionEx(PIRP Irp, PKSP_PIN Pin, PVOID Data, ULONG DescriptorsCount, const KSPIN_DESCRIPTOR* Descriptor, ULONG DescriptorSize, PFNKSINTERSECTHANDLEREX IntersectHandler, PVOID HandlerContext);\n\nKSDDKAPI NTSTATUS NTAPI KsHandleSizedListQuery(PIRP Irp, ULONG DataItemsCount, ULONG DataItemSize, const VOID* DataItems);\n\n # ifndef MAKEINTRESOURCE\n  #  define MAKEINTRESOURCE(r) ((ULONG_PTR)(USHORT)r)\n # endif\n # ifndef RT_STRING\n  #  define RT_STRING MAKEINTRESOURCE(6)\n  #  define RT_RCDATA MAKEINTRESOURCE(10)\n # endif\n\nKSDDKAPI NTSTATUS NTAPI KsLoadResource(PVOID ImageBase, POOL_TYPE PoolType, ULONG_PTR ResourceName, ULONG ResourceType, PVOID* Resource, PULONG ResourceSize);\n\nKSDDKAPI NTSTATUS NTAPI KsGetImageNameAndResourceId(HANDLE RegKey, PUNICODE_STRING ImageName, PULONG_PTR ResourceId, PULONG ValueType);\n\nKSDDKAPI NTSTATUS NTAPI KsMapModuleName(PDEVICE_OBJECT PhysicalDeviceObject, PUNICODE_STRING ModuleName, PUNICODE_STRING ImageName, PULONG_PTR ResourceId, PULONG ValueType);\n\nKSDDKAPI NTSTATUS NTAPI KsReferenceBusObject(KSDEVICE_HEADER Header);\nKSDDKAPI VOID NTAPI KsDereferenceBusObject(KSDEVICE_HEADER Header);\nKSDDKAPI NTSTATUS NTAPI KsDispatchQuerySecurity(PDEVICE_OBJECT DeviceObject, PIRP Irp);\nKSDDKAPI NTSTATUS NTAPI KsDispatchSetSecurity(PDEVICE_OBJECT DeviceObject, PIRP Irp);\nKSDDKAPI NTSTATUS NTAPI KsDispatchSpecificProperty(PIRP Irp, PFNKSHANDLER Handler);\nKSDDKAPI NTSTATUS NTAPI KsDispatchSpecificMethod(PIRP Irp, PFNKSHANDLER Handler);\n\nKSDDKAPI NTSTATUS NTAPI KsReadFile(PFILE_OBJECT FileObject, PKEVENT Event, PVOID PortContext, PIO_STATUS_BLOCK IoStatusBlock, PVOID Buffer, ULONG Length, ULONG Key, KPROCESSOR_MODE RequestorMode);\n\nKSDDKAPI NTSTATUS NTAPI KsWriteFile(PFILE_OBJECT FileObject, PKEVENT Event, PVOID PortContext, PIO_STATUS_BLOCK IoStatusBlock, PVOID Buffer, ULONG Length, ULONG Key, KPROCESSOR_MODE RequestorMode);\n\nKSDDKAPI NTSTATUS NTAPI KsQueryInformationFile(PFILE_OBJECT FileObject, PVOID FileInformation, ULONG Length, FILE_INFORMATION_CLASS FileInformationClass);\n\nKSDDKAPI NTSTATUS NTAPI KsSetInformationFile(PFILE_OBJECT FileObject, PVOID FileInformation, ULONG Length, FILE_INFORMATION_CLASS FileInformationClass);\n\nKSDDKAPI 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);\n\nKSDDKAPI NTSTATUS NTAPI KsProbeStreamIrp(PIRP Irp, ULONG ProbeFlags, ULONG HeaderSize);\nKSDDKAPI NTSTATUS NTAPI KsAllocateExtraData(PIRP Irp, ULONG ExtraSize, PVOID* ExtraBuffer);\nKSDDKAPI VOID NTAPI KsNullDriverUnload(PDRIVER_OBJECT DriverObject);\n\nKSDDKAPI NTSTATUS NTAPI KsSetMajorFunctionHandler(PDRIVER_OBJECT DriverObject, ULONG MajorFunction);\n\nKSDDKAPI NTSTATUS NTAPI KsDispatchInvalidDeviceRequest(PDEVICE_OBJECT DeviceObject, PIRP Irp);\n\nKSDDKAPI NTSTATUS NTAPI KsDefaultDeviceIoCompletion(PDEVICE_OBJECT DeviceObject, PIRP Irp);\n\nKSDDKAPI NTSTATUS NTAPI KsDispatchIrp(PDEVICE_OBJECT DeviceObject, PIRP Irp);\n\nKSDDKAPI 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);\n\nKSDDKAPI BOOLEAN NTAPI KsDispatchFastReadFailure(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, ULONG Length, BOOLEAN Wait, ULONG LockKey, PVOID Buffer, PIO_STATUS_BLOCK IoStatus, PDEVICE_OBJECT DeviceObject);\n\n # define KsDispatchFastWriteFailure KsDispatchFastReadFailure\n\nKSDDKAPI VOID NTAPI KsCancelRoutine(PDEVICE_OBJECT DeviceObject, PIRP Irp);\nKSDDKAPI VOID NTAPI KsCancelIo(PLIST_ENTRY QueueHead, PKSPIN_LOCK SpinLock);\nKSDDKAPI VOID NTAPI KsReleaseIrpOnCancelableQueue(PIRP Irp, PDRIVER_CANCEL DriverCancel);\n\nKSDDKAPI PIRP NTAPI KsRemoveIrpFromCancelableQueue(PLIST_ENTRY QueueHead, PKSPIN_LOCK SpinLock, KSLIST_ENTRY_LOCATION ListLocation, KSIRP_REMOVAL_OPERATION RemovalOperation);\n\nKSDDKAPI NTSTATUS NTAPI KsMoveIrpsOnCancelableQueue(PLIST_ENTRY SourceList, PKSPIN_LOCK SourceLock, PLIST_ENTRY DestinationList, PKSPIN_LOCK DestinationLock, KSLIST_ENTRY_LOCATION ListLocation, PFNKSIRPLISTCALLBACK ListCallback, PVOID Context);\n\nKSDDKAPI VOID NTAPI KsRemoveSpecificIrpFromCancelableQueue(PIRP Irp);\n\nKSDDKAPI VOID NTAPI KsAddIrpToCancelableQueue(PLIST_ENTRY QueueHead, PKSPIN_LOCK SpinLock, PIRP Irp, KSLIST_ENTRY_LOCATION ListLocation, PDRIVER_CANCEL DriverCancel);\n\nKSDDKAPI NTSTATUS NTAPI KsAcquireResetValue(PIRP Irp, KSRESET* ResetValue);\n\nKSDDKAPI NTSTATUS NTAPI KsTopologyPropertyHandler(PIRP Irp, PKSPROPERTY Property, PVOID Data, const KSTOPOLOGY* Topology);\n\nKSDDKAPI VOID NTAPI KsAcquireDeviceSecurityLock(KSDEVICE_HEADER Header, BOOLEAN Exclusive);\nKSDDKAPI VOID NTAPI KsReleaseDeviceSecurityLock(KSDEVICE_HEADER Header);\nKSDDKAPI NTSTATUS NTAPI KsDefaultDispatchPnp(PDEVICE_OBJECT DeviceObject, PIRP Irp);\nKSDDKAPI NTSTATUS NTAPI KsDefaultDispatchPower(PDEVICE_OBJECT DeviceObject, PIRP Irp);\nKSDDKAPI NTSTATUS NTAPI KsDefaultForwardIrp(PDEVICE_OBJECT DeviceObject, PIRP Irp);\n\nKSDDKAPI VOID NTAPI KsSetDevicePnpAndBaseObject(KSDEVICE_HEADER Header, PDEVICE_OBJECT PnpDeviceObject, PDEVICE_OBJECT BaseObject);\n\nKSDDKAPI PDEVICE_OBJECT NTAPI KsQueryDevicePnpObject(KSDEVICE_HEADER Header);\nKSDDKAPI ACCESS_MASK NTAPI KsQueryObjectAccessMask(KSOBJECT_HEADER Header);\n\nKSDDKAPI VOID NTAPI KsRecalculateStackDepth(KSDEVICE_HEADER Header, BOOLEAN ReuseStackLocation);\n\nKSDDKAPI VOID NTAPI KsSetTargetState(KSOBJECT_HEADER Header, KSTARGET_STATE TargetState);\n\nKSDDKAPI VOID NTAPI KsSetTargetDeviceObject(KSOBJECT_HEADER Header, PDEVICE_OBJECT TargetDevice);\n\nKSDDKAPI VOID NTAPI KsSetPowerDispatch(KSOBJECT_HEADER Header, PFNKSCONTEXT_DISPATCH PowerDispatch, PVOID PowerContext);\n\nKSDDKAPI PKSOBJECT_CREATE_ITEM NTAPI KsQueryObjectCreateItem(KSOBJECT_HEADER Header);\n\nKSDDKAPI NTSTATUS NTAPI KsAllocateDeviceHeader(KSDEVICE_HEADER* Header, ULONG ItemsCount, PKSOBJECT_CREATE_ITEM ItemsList);\n\nKSDDKAPI VOID NTAPI KsFreeDeviceHeader(KSDEVICE_HEADER Header);\n\nKSDDKAPI NTSTATUS NTAPI KsAllocateObjectHeader(KSOBJECT_HEADER* Header, ULONG ItemsCount, PKSOBJECT_CREATE_ITEM ItemsList, PIRP Irp, const KSDISPATCH_TABLE* Table);\n\nKSDDKAPI VOID NTAPI KsFreeObjectHeader(KSOBJECT_HEADER Header);\n\nKSDDKAPI NTSTATUS NTAPI KsAddObjectCreateItemToDeviceHeader(KSDEVICE_HEADER Header, PDRIVER_DISPATCH Create, PVOID Context, PWSTR ObjectClass, PSECURITY_DESCRIPTOR SecurityDescriptor);\n\nKSDDKAPI NTSTATUS NTAPI KsAddObjectCreateItemToObjectHeader(KSOBJECT_HEADER Header, PDRIVER_DISPATCH Create, PVOID Context, PWSTR ObjectClass, PSECURITY_DESCRIPTOR SecurityDescriptor);\n\nKSDDKAPI NTSTATUS NTAPI KsAllocateObjectCreateItem(KSDEVICE_HEADER Header, PKSOBJECT_CREATE_ITEM CreateItem, BOOLEAN AllocateEntry, PFNKSITEMFREECALLBACK ItemFreeCallback);\n\nKSDDKAPI NTSTATUS NTAPI KsFreeObjectCreateItem(KSDEVICE_HEADER Header, PUNICODE_STRING CreateItem);\n\nKSDDKAPI NTSTATUS NTAPI KsFreeObjectCreateItemsByContext(KSDEVICE_HEADER Header, PVOID Context);\n\nKSDDKAPI NTSTATUS NTAPI KsCreateDefaultSecurity(PSECURITY_DESCRIPTOR ParentSecurity, PSECURITY_DESCRIPTOR* DefaultSecurity);\n\nKSDDKAPI NTSTATUS NTAPI KsForwardIrp(PIRP Irp, PFILE_OBJECT FileObject, BOOLEAN ReuseStackLocation);\n\nKSDDKAPI NTSTATUS NTAPI KsForwardAndCatchIrp(PDEVICE_OBJECT DeviceObject, PIRP Irp, PFILE_OBJECT FileObject, KSSTACK_USE StackUse);\n\nKSDDKAPI NTSTATUS NTAPI KsSynchronousIoControlDevice(PFILE_OBJECT FileObject, KPROCESSOR_MODE RequestorMode, ULONG IoControl, PVOID InBuffer, ULONG InSize, PVOID OutBuffer, ULONG OutSize, PULONG BytesReturned);\n\nKSDDKAPI NTSTATUS NTAPI KsUnserializeObjectPropertiesFromRegistry(PFILE_OBJECT FileObject, HANDLE ParentKey, PUNICODE_STRING RegistryPath);\n\nKSDDKAPI NTSTATUS NTAPI KsCacheMedium(PUNICODE_STRING SymbolicLink, PKSPIN_MEDIUM Medium, ULONG PinDirection);\n\nKSDDKAPI NTSTATUS NTAPI KsRegisterWorker(WORK_QUEUE_TYPE WorkQueueType, PKSWORKER* Worker);\n\nKSDDKAPI NTSTATUS NTAPI KsRegisterCountedWorker(WORK_QUEUE_TYPE WorkQueueType, PWORK_QUEUE_ITEM CountedWorkItem, PKSWORKER* Worker);\n\nKSDDKAPI VOID NTAPI KsUnregisterWorker(PKSWORKER Worker);\nKSDDKAPI NTSTATUS NTAPI KsQueueWorkItem(PKSWORKER Worker, PWORK_QUEUE_ITEM WorkItem);\nKSDDKAPI ULONG NTAPI KsIncrementCountedWorker(PKSWORKER Worker);\nKSDDKAPI ULONG NTAPI KsDecrementCountedWorker(PKSWORKER Worker);\n\nKSDDKAPI NTSTATUS NTAPI KsCreateTopologyNode(HANDLE ParentHandle, PKSNODE_CREATE NodeCreate, ACCESS_MASK DesiredAccess, PHANDLE NodeHandle);\n\nKSDDKAPI NTSTATUS NTAPI KsValidateTopologyNodeCreateRequest(PIRP Irp, PKSTOPOLOGY Topology, PKSNODE_CREATE* NodeCreate);\n\nKSDDKAPI NTSTATUS NTAPI KsMergeAutomationTables(PKSAUTOMATION_TABLE* AutomationTableAB, PKSAUTOMATION_TABLE AutomationTableA, PKSAUTOMATION_TABLE AutomationTableB, KSOBJECT_BAG Bag);\n\nKSDDKAPI NTSTATUS NTAPI KsInitializeDriver(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPathName, const KSDEVICE_DESCRIPTOR* Descriptor);\n\nKSDDKAPI NTSTATUS NTAPI KsAddDevice(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT PhysicalDeviceObject);\n\nKSDDKAPI NTSTATUS NTAPI KsCreateDevice(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT PhysicalDeviceObject, const KSDEVICE_DESCRIPTOR* Descriptor, ULONG ExtensionSize, PKSDEVICE* Device);\n\nKSDDKAPI NTSTATUS NTAPI KsInitializeDevice(PDEVICE_OBJECT FunctionalDeviceObject, PDEVICE_OBJECT PhysicalDeviceObject, PDEVICE_OBJECT NextDeviceObject, const KSDEVICE_DESCRIPTOR* Descriptor);\n\nKSDDKAPI void NTAPI KsTerminateDevice(PDEVICE_OBJECT DeviceObject);\nKSDDKAPI PKSDEVICE NTAPI KsGetDeviceForDeviceObject(PDEVICE_OBJECT FunctionalDeviceObject);\nKSDDKAPI void NTAPI KsAcquireDevice(PKSDEVICE Device);\nKSDDKAPI void NTAPI KsReleaseDevice(PKSDEVICE Device);\n\nKSDDKAPI void NTAPI KsDeviceRegisterAdapterObject(PKSDEVICE Device, PADAPTER_OBJECT AdapterObject, ULONG MaxMappingsByteCount, ULONG MappingTableStride);\n\nKSDDKAPI ULONG NTAPI KsDeviceGetBusData(PKSDEVICE Device, ULONG DataType, PVOID Buffer, ULONG Offset, ULONG Length);\n\nKSDDKAPI ULONG NTAPI KsDeviceSetBusData(PKSDEVICE Device, ULONG DataType, PVOID Buffer, ULONG Offset, ULONG Length);\n\nKSDDKAPI NTSTATUS NTAPI KsCreateFilterFactory(PDEVICE_OBJECT DeviceObject, const KSFILTER_DESCRIPTOR* Descriptor, PWSTR RefString, PSECURITY_DESCRIPTOR SecurityDescriptor, ULONG CreateItemFlags, PFNKSFILTERFACTORYPOWER SleepCallback, PFNKSFILTERFACTORYPOWER WakeCallback, PKSFILTERFACTORY* FilterFactory);\n\n # define KsDeleteFilterFactory(FilterFactory)                                                \\\n  KsFreeObjectCreateItemsByContext(*(KSDEVICE_HEADER*)(                                     \\\n                                     KsFilterFactoryGetParentDevice(FilterFactory)->FunctionalDeviceObject->DeviceExtension), \\\n                                   FilterFactory)\n\nKSDDKAPI NTSTATUS NTAPI KsFilterFactoryUpdateCacheData(PKSFILTERFACTORY FilterFactory, const KSFILTER_DESCRIPTOR* FilterDescriptor);\n\nKSDDKAPI NTSTATUS NTAPI KsFilterFactoryAddCreateItem(PKSFILTERFACTORY FilterFactory, PWSTR RefString, PSECURITY_DESCRIPTOR SecurityDescriptor, ULONG CreateItemFlags);\n\nKSDDKAPI NTSTATUS NTAPI KsFilterFactorySetDeviceClassesState(PKSFILTERFACTORY FilterFactory, BOOLEAN NewState);\n\nKSDDKAPI PUNICODE_STRING NTAPI KsFilterFactoryGetSymbolicLink(PKSFILTERFACTORY FilterFactory);\n\nKSDDKAPI void NTAPI KsAddEvent(PVOID Object, PKSEVENT_ENTRY EventEntry);\n\nvoid __forceinline KsFilterAddEvent(PKSFILTER Filter, PKSEVENT_ENTRY EventEntry)\n{\n  KsAddEvent(Filter, EventEntry);\n}\n\nvoid __forceinline KsPinAddEvent(PKSPIN Pin, PKSEVENT_ENTRY EventEntry)\n{\n  KsAddEvent(Pin, EventEntry);\n}\n\nKSDDKAPI NTSTATUS NTAPI KsDefaultAddEventHandler(PIRP Irp, PKSEVENTDATA EventData, PKSEVENT_ENTRY EventEntry);\n\nKSDDKAPI void NTAPI KsGenerateEvents(PVOID Object, const GUID* EventSet, ULONG EventId, ULONG DataSize, PVOID Data, PFNKSGENERATEEVENTCALLBACK CallBack, PVOID CallBackContext);\n\nvoid __forceinline KsFilterGenerateEvents(PKSFILTER Filter, const GUID* EventSet, ULONG EventId, ULONG DataSize, PVOID Data, PFNKSGENERATEEVENTCALLBACK CallBack, PVOID CallBackContext)\n{\n  KsGenerateEvents(Filter, EventSet, EventId, DataSize, Data, CallBack,\n                   CallBackContext);\n}\n\nvoid __forceinline KsPinGenerateEvents(PKSPIN Pin, const GUID* EventSet, ULONG EventId, ULONG DataSize, PVOID Data, PFNKSGENERATEEVENTCALLBACK CallBack, PVOID CallBackContext)\n{\n  KsGenerateEvents(Pin, EventSet, EventId, DataSize, Data, CallBack,\n                   CallBackContext);\n}\n\ntypedef enum\n{\n  KSSTREAM_POINTER_STATE_UNLOCKED = 0,\n  KSSTREAM_POINTER_STATE_LOCKED\n}KSSTREAM_POINTER_STATE;\n\nKSDDKAPI NTSTATUS NTAPI KsPinGetAvailableByteCount(PKSPIN Pin, PLONG InputDataBytes, PLONG OutputBufferBytes);\n\nKSDDKAPI PKSSTREAM_POINTER NTAPI KsPinGetLeadingEdgeStreamPointer(PKSPIN Pin, KSSTREAM_POINTER_STATE State);\n\nKSDDKAPI PKSSTREAM_POINTER NTAPI KsPinGetTrailingEdgeStreamPointer(PKSPIN Pin, KSSTREAM_POINTER_STATE State);\n\nKSDDKAPI NTSTATUS NTAPI KsStreamPointerSetStatusCode(PKSSTREAM_POINTER StreamPointer, NTSTATUS Status);\n\nKSDDKAPI NTSTATUS NTAPI KsStreamPointerLock(PKSSTREAM_POINTER StreamPointer);\nKSDDKAPI void NTAPI KsStreamPointerUnlock(PKSSTREAM_POINTER StreamPointer, BOOLEAN Eject);\n\nKSDDKAPI void NTAPI KsStreamPointerAdvanceOffsetsAndUnlock(PKSSTREAM_POINTER StreamPointer, ULONG InUsed, ULONG OutUsed, BOOLEAN Eject);\n\nKSDDKAPI void NTAPI KsStreamPointerDelete(PKSSTREAM_POINTER StreamPointer);\n\nKSDDKAPI NTSTATUS NTAPI KsStreamPointerClone(PKSSTREAM_POINTER StreamPointer, PFNKSSTREAMPOINTER CancelCallback, ULONG ContextSize, PKSSTREAM_POINTER* CloneStreamPointer);\n\nKSDDKAPI NTSTATUS NTAPI KsStreamPointerAdvanceOffsets(PKSSTREAM_POINTER StreamPointer, ULONG InUsed, ULONG OutUsed, BOOLEAN Eject);\n\nKSDDKAPI NTSTATUS NTAPI KsStreamPointerAdvance(PKSSTREAM_POINTER StreamPointer);\nKSDDKAPI PMDL NTAPI KsStreamPointerGetMdl(PKSSTREAM_POINTER StreamPointer);\n\nKSDDKAPI PIRP NTAPI KsStreamPointerGetIrp(PKSSTREAM_POINTER StreamPointer, PBOOLEAN FirstFrameInIrp, PBOOLEAN LastFrameInIrp);\n\nKSDDKAPI void NTAPI KsStreamPointerScheduleTimeout(PKSSTREAM_POINTER StreamPointer, PFNKSSTREAMPOINTER Callback, ULONGLONG Interval);\n\nKSDDKAPI void NTAPI KsStreamPointerCancelTimeout(PKSSTREAM_POINTER StreamPointer);\nKSDDKAPI PKSSTREAM_POINTER NTAPI KsPinGetFirstCloneStreamPointer(PKSPIN Pin);\n\nKSDDKAPI PKSSTREAM_POINTER NTAPI KsStreamPointerGetNextClone(PKSSTREAM_POINTER StreamPointer);\n\nKSDDKAPI NTSTATUS NTAPI KsPinHandshake(PKSPIN Pin, PKSHANDSHAKE In, PKSHANDSHAKE Out);\nKSDDKAPI void NTAPI KsCompletePendingRequest(PIRP Irp);\nKSDDKAPI KSOBJECTTYPE NTAPI KsGetObjectTypeFromIrp(PIRP Irp);\nKSDDKAPI PVOID NTAPI KsGetObjectFromFileObject(PFILE_OBJECT FileObject);\nKSDDKAPI KSOBJECTTYPE NTAPI KsGetObjectTypeFromFileObject(PFILE_OBJECT FileObject);\n\nPKSFILTER __forceinline KsGetFilterFromFileObject(PFILE_OBJECT FileObject)\n{\n  return (PKSFILTER)KsGetObjectFromFileObject(FileObject);\n}\n\nPKSPIN __forceinline KsGetPinFromFileObject(PFILE_OBJECT FileObject)\n{\n  return (PKSPIN)KsGetObjectFromFileObject(FileObject);\n}\n\nKSDDKAPI PKSGATE NTAPI KsFilterGetAndGate(PKSFILTER Filter);\nKSDDKAPI void NTAPI KsFilterAcquireProcessingMutex(PKSFILTER Filter);\nKSDDKAPI void NTAPI KsFilterReleaseProcessingMutex(PKSFILTER Filter);\nKSDDKAPI void NTAPI KsFilterAttemptProcessing(PKSFILTER Filter, BOOLEAN Asynchronous);\nKSDDKAPI PKSGATE NTAPI KsPinGetAndGate(PKSPIN Pin);\nKSDDKAPI void NTAPI KsPinAttachAndGate(PKSPIN Pin, PKSGATE AndGate);\nKSDDKAPI void NTAPI KsPinAttachOrGate(PKSPIN Pin, PKSGATE OrGate);\nKSDDKAPI void NTAPI KsPinAcquireProcessingMutex(PKSPIN Pin);\nKSDDKAPI void NTAPI KsPinReleaseProcessingMutex(PKSPIN Pin);\nKSDDKAPI BOOLEAN NTAPI KsProcessPinUpdate(PKSPROCESSPIN ProcessPin);\n\nKSDDKAPI void NTAPI KsPinGetCopyRelationships(PKSPIN Pin, PKSPIN* CopySource, PKSPIN* DelegateBranch);\n\nKSDDKAPI void NTAPI KsPinAttemptProcessing(PKSPIN Pin, BOOLEAN Asynchronous);\nKSDDKAPI PVOID NTAPI KsGetParent(PVOID Object);\n\nPKSDEVICE __forceinline KsFilterFactoryGetParentDevice(PKSFILTERFACTORY FilterFactory)\n{\n  return (PKSDEVICE)KsGetParent((PVOID)FilterFactory);\n}\n\nPKSFILTERFACTORY __forceinline KsFilterGetParentFilterFactory(PKSFILTER Filter)\n{\n  return (PKSFILTERFACTORY)KsGetParent((PVOID)Filter);\n}\n\nKSDDKAPI PKSFILTER NTAPI KsPinGetParentFilter(PKSPIN Pin);\nKSDDKAPI PVOID NTAPI KsGetFirstChild(PVOID Object);\n\nPKSFILTERFACTORY __forceinline KsDeviceGetFirstChildFilterFactory(PKSDEVICE Device)\n{\n  return (PKSFILTERFACTORY)KsGetFirstChild((PVOID)Device);\n}\n\nPKSFILTER __forceinline KsFilterFactoryGetFirstChildFilter(PKSFILTERFACTORY FilterFactory)\n{\n  return (PKSFILTER)KsGetFirstChild((PVOID)FilterFactory);\n}\n\nKSDDKAPI ULONG NTAPI KsFilterGetChildPinCount(PKSFILTER Filter, ULONG PinId);\nKSDDKAPI PKSPIN NTAPI KsFilterGetFirstChildPin(PKSFILTER Filter, ULONG PinId);\nKSDDKAPI PVOID NTAPI KsGetNextSibling(PVOID Object);\nKSDDKAPI PKSPIN NTAPI KsPinGetNextSiblingPin(PKSPIN Pin);\n\nPKSFILTERFACTORY __forceinline KsFilterFactoryGetNextSiblingFilterFactory(PKSFILTERFACTORY FilterFactory)\n{\n  return (PKSFILTERFACTORY)KsGetNextSibling((PVOID)FilterFactory);\n}\n\nPKSFILTER __forceinline KsFilterGetNextSiblingFilter(PKSFILTER Filter)\n{\n  return (PKSFILTER)KsGetNextSibling((PVOID)Filter);\n}\n\nKSDDKAPI PKSDEVICE NTAPI KsGetDevice(PVOID Object);\n\nPKSDEVICE __forceinline KsFilterFactoryGetDevice(PKSFILTERFACTORY FilterFactory)\n{\n  return KsGetDevice((PVOID)FilterFactory);\n}\n\nPKSDEVICE __forceinline KsFilterGetDevice(PKSFILTER Filter)\n{\n  return KsGetDevice((PVOID)Filter);\n}\n\nPKSDEVICE __forceinline KsPinGetDevice(PKSPIN Pin)\n{\n  return KsGetDevice((PVOID)Pin);\n}\n\nKSDDKAPI PKSFILTER NTAPI KsGetFilterFromIrp(PIRP Irp);\nKSDDKAPI PKSPIN NTAPI KsGetPinFromIrp(PIRP Irp);\nKSDDKAPI ULONG NTAPI KsGetNodeIdFromIrp(PIRP Irp);\nKSDDKAPI void NTAPI KsAcquireControl(PVOID Object);\nKSDDKAPI void NTAPI KsReleaseControl(PVOID Object);\n\nvoid __forceinline KsFilterAcquireControl(PKSFILTER Filter)\n{\n  KsAcquireControl((PVOID)Filter);\n}\n\nvoid __forceinline KsFilterReleaseControl(PKSFILTER Filter)\n{\n  KsReleaseControl((PVOID)Filter);\n}\n\nvoid __forceinline KsPinAcquireControl(PKSPIN Pin)\n{\n  KsAcquireControl((PVOID)Pin);\n}\n\nvoid __forceinline KsPinReleaseControl(PKSPIN Pin)\n{\n  KsReleaseControl((PVOID)Pin);\n}\n\nKSDDKAPI NTSTATUS NTAPI KsAddItemToObjectBag(KSOBJECT_BAG ObjectBag, PVOID Item, PFNKSFREE Free);\n\nKSDDKAPI ULONG NTAPI KsRemoveItemFromObjectBag(KSOBJECT_BAG ObjectBag, PVOID Item, BOOLEAN Free);\n\n # define KsDiscard(Object, Pointer)                   \\\n  KsRemoveItemFromObjectBag((Object)->Bag, (PVOID)(Pointer), TRUE)\n\nKSDDKAPI NTSTATUS NTAPI KsAllocateObjectBag(PKSDEVICE Device, KSOBJECT_BAG* ObjectBag);\nKSDDKAPI void NTAPI KsFreeObjectBag(KSOBJECT_BAG ObjectBag);\n\nKSDDKAPI NTSTATUS NTAPI KsCopyObjectBagItems(KSOBJECT_BAG ObjectBagDestination, KSOBJECT_BAG ObjectBagSource);\n\nKSDDKAPI NTSTATUS NTAPI _KsEdit(KSOBJECT_BAG ObjectBag, PVOID* PointerToPointerToItem, ULONG NewSize, ULONG OldSize, ULONG Tag);\n\n # define KsEdit(Object, PointerToPointer, Tag)                       \\\n  _KsEdit((Object)->Bag, (PVOID*)(PointerToPointer),              \\\n          sizeof(**(PointerToPointer)), sizeof(**(PointerToPointer)), (Tag))\n\n # define KsEditSized(Object, PointerToPointer, NewSize, OldSize, Tag)            \\\n  _KsEdit((Object)->Bag, (PVOID*)(PointerToPointer), (NewSize), (OldSize), (Tag))\n\nKSDDKAPI NTSTATUS NTAPI KsRegisterFilterWithNoKSPins(PDEVICE_OBJECT DeviceObject, const GUID* InterfaceClassGUID, ULONG PinCount, WINBOOL* PinDirection, KSPIN_MEDIUM* MediumList, GUID* CategoryList);\n\nKSDDKAPI NTSTATUS NTAPI KsFilterCreatePinFactory(PKSFILTER Filter, const KSPIN_DESCRIPTOR_EX* const PinDescriptor, PULONG PinID);\n\nKSDDKAPI NTSTATUS NTAPI KsFilterCreateNode(PKSFILTER Filter, const KSNODE_DESCRIPTOR* const NodeDescriptor, PULONG NodeID);\n\nKSDDKAPI NTSTATUS NTAPI KsFilterAddTopologyConnections(PKSFILTER Filter, ULONG NewConnectionsCount, const KSTOPOLOGY_CONNECTION* const NewTopologyConnections);\n\nKSDDKAPI NTSTATUS NTAPI KsPinGetConnectedPinInterface(PKSPIN Pin, const GUID* InterfaceId, PVOID* Interface);\n\nKSDDKAPI PFILE_OBJECT NTAPI KsPinGetConnectedPinFileObject(PKSPIN Pin);\nKSDDKAPI PDEVICE_OBJECT NTAPI KsPinGetConnectedPinDeviceObject(PKSPIN Pin);\n\nKSDDKAPI NTSTATUS NTAPI KsPinGetConnectedFilterInterface(PKSPIN Pin, const GUID* InterfaceId, PVOID* Interface);\n\n # if defined(_UNKNOWN_H_) || defined(__IUnknown_INTERFACE_DEFINED__)\nKSDDKAPI NTSTATUS NTAPI KsPinGetReferenceClockInterface(PKSPIN Pin, PIKSREFERENCECLOCK* Interface);\n # endif /* defined(_UNKNOWN_H_) || defined(__IUnknown_INTERFACE_DEFINED__) */\n\nKSDDKAPI VOID NTAPI KsPinSetPinClockTime(PKSPIN Pin, LONGLONG Time);\n\nKSDDKAPI NTSTATUS NTAPI KsPinSubmitFrame(PKSPIN Pin, PVOID Data, ULONG Size, PKSSTREAM_HEADER StreamHeader, PVOID Context);\n\nKSDDKAPI NTSTATUS NTAPI KsPinSubmitFrameMdl(PKSPIN Pin, PMDL Mdl, PKSSTREAM_HEADER StreamHeader, PVOID Context);\n\nKSDDKAPI void NTAPI KsPinRegisterFrameReturnCallback(PKSPIN Pin, PFNKSPINFRAMERETURN FrameReturn);\n\nKSDDKAPI void NTAPI KsPinRegisterIrpCompletionCallback(PKSPIN Pin, PFNKSPINIRPCOMPLETION IrpCompletion);\n\nKSDDKAPI void NTAPI KsPinRegisterHandshakeCallback(PKSPIN Pin, PFNKSPINHANDSHAKE Handshake);\n\nKSDDKAPI void NTAPI KsFilterRegisterPowerCallbacks(PKSFILTER Filter, PFNKSFILTERPOWER Sleep, PFNKSFILTERPOWER Wake);\n\nKSDDKAPI void NTAPI KsPinRegisterPowerCallbacks(PKSPIN Pin, PFNKSPINPOWER Sleep, PFNKSPINPOWER Wake);\n\n # if defined(_UNKNOWN_H_) || defined(__IUnknown_INTERFACE_DEFINED__)\nKSDDKAPI PUNKNOWN NTAPI KsRegisterAggregatedClientUnknown(PVOID Object, PUNKNOWN ClientUnknown);\n\nKSDDKAPI PUNKNOWN NTAPI KsGetOuterUnknown(PVOID Object);\n\nPUNKNOWN __forceinline KsDeviceRegisterAggregatedClientUnknown(PKSDEVICE Device, PUNKNOWN ClientUnknown)\n{\n  return KsRegisterAggregatedClientUnknown((PVOID)Device, ClientUnknown);\n}\n\nPUNKNOWN __forceinline KsDeviceGetOuterUnknown(PKSDEVICE Device)\n{\n  return KsGetOuterUnknown((PVOID)Device);\n}\n\nPUNKNOWN __forceinline KsFilterFactoryRegisterAggregatedClientUnknown(PKSFILTERFACTORY FilterFactory, PUNKNOWN ClientUnknown)\n{\n  return KsRegisterAggregatedClientUnknown((PVOID)FilterFactory, ClientUnknown);\n}\n\nPUNKNOWN __forceinline KsFilterFactoryGetOuterUnknown(PKSFILTERFACTORY FilterFactory)\n{\n  return KsGetOuterUnknown((PVOID)FilterFactory);\n}\n\nPUNKNOWN __forceinline KsFilterRegisterAggregatedClientUnknown(PKSFILTER Filter, PUNKNOWN ClientUnknown)\n{\n  return KsRegisterAggregatedClientUnknown((PVOID)Filter, ClientUnknown);\n}\n\nPUNKNOWN __forceinline KsFilterGetOuterUnknown(PKSFILTER Filter)\n{\n  return KsGetOuterUnknown((PVOID)Filter);\n}\n\nPUNKNOWN __forceinline KsPinRegisterAggregatedClientUnknown(PKSPIN Pin, PUNKNOWN ClientUnknown)\n{\n  return KsRegisterAggregatedClientUnknown((PVOID)Pin, ClientUnknown);\n}\n\nPUNKNOWN __forceinline KsPinGetOuterUnknown(PKSPIN Pin)\n{\n  return KsGetOuterUnknown((PVOID)Pin);\n}\n\n # endif /* defined(_UNKNOWN_H_) || defined(__IUnknown_INTERFACE_DEFINED__) */\n\n#else /* _NTDDK_ */\n\n # ifndef KS_NO_CREATE_FUNCTIONS\nKSDDKAPI DWORD WINAPI KsCreateAllocator(HANDLE ConnectionHandle, PKSALLOCATOR_FRAMING AllocatorFraming, PHANDLE AllocatorHandle);\nKSDDKAPI DWORD NTAPI KsCreateClock(HANDLE ConnectionHandle, PKSCLOCK_CREATE ClockCreate, PHANDLE ClockHandle);\nKSDDKAPI DWORD WINAPI KsCreatePin(HANDLE FilterHandle, PKSPIN_CONNECT Connect, ACCESS_MASK DesiredAccess, PHANDLE ConnectionHandle);\nKSDDKAPI DWORD WINAPI KsCreateTopologyNode(HANDLE ParentHandle, PKSNODE_CREATE NodeCreate, ACCESS_MASK DesiredAccess, PHANDLE NodeHandle);\n # endif\n\n#endif /* _NTDDK_ */\n\n#ifdef __cplusplus\n}\n#endif\n\n#define DENY_USERMODE_ACCESS(pIrp, CompleteRequest)          \\\n  if(pIrp->RequestorMode != KernelMode){               \\\n    pIrp->IoStatus.Information = 0;             \\\n    pIrp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;  \\\n    if(CompleteRequest){                 \\\n      IoCompleteRequest(pIrp, IO_NO_INCREMENT); }   \\\n    return STATUS_INVALID_DEVICE_REQUEST;           \\\n  }\n\n#endif /* _KS_ */\n\n"
  },
  {
    "path": "rtmidi/include/ksmedia.h",
    "content": "/**\n * This file has no copyright assigned and is placed in the Public Domain.\n * This file is part of the w64 mingw-runtime package.\n */\n#if !defined(_KS_)\n # warning ks.h must be included before ksmedia.h\n # include \"ks.h\"\n#endif\n\n#if __GNUC__ >= 3\n # pragma GCC system_header\n#endif\n\n#if !defined(_KSMEDIA_)\n # define _KSMEDIA_\n\ntypedef struct\n{\n  KSPROPERTY Property;\n  KSMULTIPLE_ITEM MultipleItem;\n}KSMULTIPLE_DATA_PROP, * PKSMULTIPLE_DATA_PROP;\n\n # define STATIC_KSMEDIUMSETID_MidiBus                    \\\n  0x05908040L, 0x3246, 0x11D0, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00\nDEFINE_GUIDSTRUCT(\"05908040-3246-11D0-A5D6-28DB04C10000\", KSMEDIUMSETID_MidiBus);\n # define KSMEDIUMSETID_MidiBus DEFINE_GUIDNAMED(KSMEDIUMSETID_MidiBus)\n\n # define STATIC_KSMEDIUMSETID_VPBus                  \\\n  0xA18C15ECL, 0xCE43, 0x11D0, 0xAB, 0xE7, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96\nDEFINE_GUIDSTRUCT(\"A18C15EC-CE43-11D0-ABE7-00A0C9223196\", KSMEDIUMSETID_VPBus);\n # define KSMEDIUMSETID_VPBus DEFINE_GUIDNAMED(KSMEDIUMSETID_VPBus)\n\n # define STATIC_KSINTERFACESETID_Media                   \\\n  0x3A13EB40L, 0x30A7, 0x11D0, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00\nDEFINE_GUIDSTRUCT(\"3A13EB40-30A7-11D0-A5D6-28DB04C10000\", KSINTERFACESETID_Media);\n # define KSINTERFACESETID_Media DEFINE_GUIDNAMED(KSINTERFACESETID_Media)\n\ntypedef enum\n{\n  KSINTERFACE_MEDIA_MUSIC,\n  KSINTERFACE_MEDIA_WAVE_BUFFERED,\n  KSINTERFACE_MEDIA_WAVE_QUEUED\n}KSINTERFACE_MEDIA;\n\n # ifndef INIT_USBAUDIO_MID\n  #  define INIT_USBAUDIO_MID(guid, id)                  \\\n  {                                   \\\n    (guid)->Data1 = 0x4e1cecd2 + (USHORT)(id);          \\\n    (guid)->Data2 = 0x1679;                     \\\n    (guid)->Data3 = 0x463b;                     \\\n    (guid)->Data4[0] = 0xa7;                    \\\n    (guid)->Data4[1] = 0x2f;                    \\\n    (guid)->Data4[2] = 0xa5;                    \\\n    (guid)->Data4[3] = 0xbf;                    \\\n    (guid)->Data4[4] = 0x64;                    \\\n    (guid)->Data4[5] = 0xc8;                    \\\n    (guid)->Data4[6] = 0x6e;                    \\\n    (guid)->Data4[7] = 0xba;                    \\\n  }\n  #  define EXTRACT_USBAUDIO_MID(guid)                  \\\n  (USHORT)((guid)->Data1 - 0x4e1cecd2)\n  #  define DEFINE_USBAUDIO_MID_GUID(id)                    \\\n  0x4e1cecd2 + (USHORT)(id), 0x1679, 0x463b, 0xa7, 0x2f, 0xa5, 0xbf, 0x64, 0xc8, 0x6e, 0xba\n  #  define IS_COMPATIBLE_USBAUDIO_MID(guid)                \\\n  (((guid)->Data1 >= 0x4e1cecd2) &&               \\\n   ((guid)->Data1 < 0x4e1cecd2 + 0xffff) &&           \\\n   ((guid)->Data2 == 0x1679) &&                   \\\n   ((guid)->Data3 == 0x463b) &&                   \\\n   ((guid)->Data4[0] == 0xa7) &&                  \\\n   ((guid)->Data4[1] == 0x2f) &&                  \\\n   ((guid)->Data4[2] == 0xa5) &&                  \\\n   ((guid)->Data4[3] == 0xbf) &&                  \\\n   ((guid)->Data4[4] == 0x64) &&                  \\\n   ((guid)->Data4[5] == 0xc8) &&                  \\\n   ((guid)->Data4[6] == 0x6e) &&                  \\\n   ((guid)->Data4[7] == 0xba))\n # endif /* INIT_USBAUDIO_MID */\n\n # ifndef INIT_USBAUDIO_PID\n  #  define INIT_USBAUDIO_PID(guid, id)                  \\\n  {                                   \\\n    (guid)->Data1 = 0xabcc5a5e + (USHORT)(id);          \\\n    (guid)->Data2 = 0xc263;                     \\\n    (guid)->Data3 = 0x463b;                     \\\n    (guid)->Data4[0] = 0xa7;                    \\\n    (guid)->Data4[1] = 0x2f;                    \\\n    (guid)->Data4[2] = 0xa5;                    \\\n    (guid)->Data4[3] = 0xbf;                    \\\n    (guid)->Data4[4] = 0x64;                    \\\n    (guid)->Data4[5] = 0xc8;                    \\\n    (guid)->Data4[6] = 0x6e;                    \\\n    (guid)->Data4[7] = 0xba;                    \\\n  }\n  #  define EXTRACT_USBAUDIO_PID(guid)                  \\\n  (USHORT)((guid)->Data1 - 0xabcc5a5e)\n  #  define DEFINE_USBAUDIO_PID_GUID(id)                    \\\n  0xabcc5a5e + (USHORT)(id), 0xc263, 0x463b, 0xa7, 0x2f, 0xa5, 0xbf, 0x64, 0xc8, 0x6e, 0xba\n  #  define IS_COMPATIBLE_USBAUDIO_PID(guid)                \\\n  (((guid)->Data1 >= 0xabcc5a5e) &&               \\\n   ((guid)->Data1 < 0xabcc5a5e + 0xffff) &&           \\\n   ((guid)->Data2 == 0xc263) &&                   \\\n   ((guid)->Data3 == 0x463b) &&                   \\\n   ((guid)->Data4[0] == 0xa7) &&                  \\\n   ((guid)->Data4[1] == 0x2f) &&                  \\\n   ((guid)->Data4[2] == 0xa5) &&                  \\\n   ((guid)->Data4[3] == 0xbf) &&                  \\\n   ((guid)->Data4[4] == 0x64) &&                  \\\n   ((guid)->Data4[5] == 0xc8) &&                  \\\n   ((guid)->Data4[6] == 0x6e) &&                  \\\n   ((guid)->Data4[7] == 0xba))\n # endif /* INIT_USBAUDIO_PID */\n\n # ifndef INIT_USBAUDIO_PRODUCT_NAME\n  #  define INIT_USBAUDIO_PRODUCT_NAME(guid, vid, pid, strIndex)       \\\n  {                                   \\\n    (guid)->Data1 = 0XFC575048 + (USHORT)(vid);         \\\n    (guid)->Data2 = 0x2E08 + (USHORT)(pid);             \\\n    (guid)->Data3 = 0x463B + (USHORT)(strIndex);            \\\n    (guid)->Data4[0] = 0xA7;                    \\\n    (guid)->Data4[1] = 0x2F;                    \\\n    (guid)->Data4[2] = 0xA5;                    \\\n    (guid)->Data4[3] = 0xBF;                    \\\n    (guid)->Data4[4] = 0x64;                    \\\n    (guid)->Data4[5] = 0xC8;                    \\\n    (guid)->Data4[6] = 0x6E;                    \\\n    (guid)->Data4[7] = 0xBA;                    \\\n  }\n  #  define DEFINE_USBAUDIO_PRODUCT_NAME(vid, pid, strIndex)          \\\n  0xFC575048 + (USHORT)(vid), 0x2E08 + (USHORT)(pid), 0x463B + (USHORT)(strIndex), 0xA7, 0x2F, 0xA5, 0xBF, 0x64, 0xC8, 0x6E, 0xBA\n # endif /* INIT_USBAUDIO_PRODUCT_NAME */\n\n # define STATIC_KSCOMPONENTID_USBAUDIO                   \\\n  0x8F1275F0, 0x26E9, 0x4264, 0xBA, 0x4D, 0x39, 0xFF, 0xF0, 0x1D, 0x94, 0xAA\nDEFINE_GUIDSTRUCT(\"8F1275F0-26E9-4264-BA4D-39FFF01D94AA\", KSCOMPONENTID_USBAUDIO);\n # define KSCOMPONENTID_USBAUDIO DEFINE_GUIDNAMED(KSCOMPONENTID_USBAUDIO)\n\n # define INIT_USB_TERMINAL(guid, id)                  \\\n  {                                   \\\n    (guid)->Data1 = 0xDFF219E0 + (USHORT)(id);          \\\n    (guid)->Data2 = 0xF70F;                     \\\n    (guid)->Data3 = 0x11D0;                     \\\n    (guid)->Data4[0] = 0xb9;                    \\\n    (guid)->Data4[1] = 0x17;                    \\\n    (guid)->Data4[2] = 0x00;                    \\\n    (guid)->Data4[3] = 0xa0;                    \\\n    (guid)->Data4[4] = 0xc9;                    \\\n    (guid)->Data4[5] = 0x22;                    \\\n    (guid)->Data4[6] = 0x31;                    \\\n    (guid)->Data4[7] = 0x96;                    \\\n  }\n # define EXTRACT_USB_TERMINAL(guid)                  \\\n  (USHORT)((guid)->Data1 - 0xDFF219E0)\n # define DEFINE_USB_TERMINAL_GUID(id)                    \\\n  0xDFF219E0 + (USHORT)(id), 0xF70F, 0x11D0, 0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96\n\n # define STATIC_KSNODETYPE_MICROPHONE                    \\\n  DEFINE_USB_TERMINAL_GUID(0x0201)\nDEFINE_GUIDSTRUCT(\"DFF21BE1-F70F-11D0-B917-00A0C9223196\", KSNODETYPE_MICROPHONE);\n # define KSNODETYPE_MICROPHONE DEFINE_GUIDNAMED(KSNODETYPE_MICROPHONE)\n\n # define STATIC_KSNODETYPE_DESKTOP_MICROPHONE                \\\n  DEFINE_USB_TERMINAL_GUID(0x0202)\nDEFINE_GUIDSTRUCT(\"DFF21BE2-F70F-11D0-B917-00A0C9223196\", KSNODETYPE_DESKTOP_MICROPHONE);\n # define KSNODETYPE_DESKTOP_MICROPHONE DEFINE_GUIDNAMED(KSNODETYPE_DESKTOP_MICROPHONE)\n\n # define STATIC_KSNODETYPE_PERSONAL_MICROPHONE               \\\n  DEFINE_USB_TERMINAL_GUID(0x0203)\nDEFINE_GUIDSTRUCT(\"DFF21BE3-F70F-11D0-B917-00A0C9223196\", KSNODETYPE_PERSONAL_MICROPHONE);\n # define KSNODETYPE_PERSONAL_MICROPHONE DEFINE_GUIDNAMED(KSNODETYPE_PERSONAL_MICROPHONE)\n\n # define STATIC_KSNODETYPE_OMNI_DIRECTIONAL_MICROPHONE           \\\n  DEFINE_USB_TERMINAL_GUID(0x0204)\nDEFINE_GUIDSTRUCT(\"DFF21BE4-F70F-11D0-B917-00A0C9223196\", KSNODETYPE_OMNI_DIRECTIONAL_MICROPHONE);\n # define KSNODETYPE_OMNI_DIRECTIONAL_MICROPHONE DEFINE_GUIDNAMED(KSNODETYPE_OMNI_DIRECTIONAL_MICROPHONE)\n\n # define STATIC_KSNODETYPE_MICROPHONE_ARRAY              \\\n  DEFINE_USB_TERMINAL_GUID(0x0205)\nDEFINE_GUIDSTRUCT(\"DFF21BE5-F70F-11D0-B917-00A0C9223196\", KSNODETYPE_MICROPHONE_ARRAY);\n # define KSNODETYPE_MICROPHONE_ARRAY DEFINE_GUIDNAMED(KSNODETYPE_MICROPHONE_ARRAY)\n\n # define STATIC_KSNODETYPE_PROCESSING_MICROPHONE_ARRAY           \\\n  DEFINE_USB_TERMINAL_GUID(0x0206)\nDEFINE_GUIDSTRUCT(\"DFF21BE6-F70F-11D0-B917-00A0C9223196\", KSNODETYPE_PROCESSING_MICROPHONE_ARRAY);\n # define KSNODETYPE_PROCESSING_MICROPHONE_ARRAY DEFINE_GUIDNAMED(KSNODETYPE_PROCESSING_MICROPHONE_ARRAY)\n\n # define STATIC_KSCATEGORY_MICROPHONE_ARRAY_PROCESSOR            \\\n  0x830a44f2, 0xa32d, 0x476b, 0xbe, 0x97, 0x42, 0x84, 0x56, 0x73, 0xb3, 0x5a\nDEFINE_GUIDSTRUCT(\"830a44f2-a32d-476b-be97-42845673b35a\", KSCATEGORY_MICROPHONE_ARRAY_PROCESSOR);\n # define KSCATEGORY_MICROPHONE_ARRAY_PROCESSOR DEFINE_GUIDNAMED(KSCATEGORY_MICROPHONE_ARRAY_PROCESSOR)\n\n # define STATIC_KSNODETYPE_SPEAKER                   \\\n  DEFINE_USB_TERMINAL_GUID(0x0301)\nDEFINE_GUIDSTRUCT(\"DFF21CE1-F70F-11D0-B917-00A0C9223196\", KSNODETYPE_SPEAKER);\n # define KSNODETYPE_SPEAKER DEFINE_GUIDNAMED(KSNODETYPE_SPEAKER)\n\n # define STATIC_KSNODETYPE_HEADPHONES                    \\\n  DEFINE_USB_TERMINAL_GUID(0x0302)\nDEFINE_GUIDSTRUCT(\"DFF21CE2-F70F-11D0-B917-00A0C9223196\", KSNODETYPE_HEADPHONES);\n # define KSNODETYPE_HEADPHONES DEFINE_GUIDNAMED(KSNODETYPE_HEADPHONES)\n\n # define STATIC_KSNODETYPE_HEAD_MOUNTED_DISPLAY_AUDIO            \\\n  DEFINE_USB_TERMINAL_GUID(0x0303)\nDEFINE_GUIDSTRUCT(\"DFF21CE3-F70F-11D0-B917-00A0C9223196\", KSNODETYPE_HEAD_MOUNTED_DISPLAY_AUDIO);\n # define KSNODETYPE_HEAD_MOUNTED_DISPLAY_AUDIO DEFINE_GUIDNAMED(KSNODETYPE_HEAD_MOUNTED_DISPLAY_AUDIO)\n\n # define STATIC_KSNODETYPE_DESKTOP_SPEAKER               \\\n  DEFINE_USB_TERMINAL_GUID(0x0304)\nDEFINE_GUIDSTRUCT(\"DFF21CE4-F70F-11D0-B917-00A0C9223196\", KSNODETYPE_DESKTOP_SPEAKER);\n # define KSNODETYPE_DESKTOP_SPEAKER DEFINE_GUIDNAMED(KSNODETYPE_DESKTOP_SPEAKER)\n\n # define STATIC_KSNODETYPE_ROOM_SPEAKER                  \\\n  DEFINE_USB_TERMINAL_GUID(0x0305)\nDEFINE_GUIDSTRUCT(\"DFF21CE5-F70F-11D0-B917-00A0C9223196\", KSNODETYPE_ROOM_SPEAKER);\n # define KSNODETYPE_ROOM_SPEAKER DEFINE_GUIDNAMED(KSNODETYPE_ROOM_SPEAKER)\n\n # define STATIC_KSNODETYPE_COMMUNICATION_SPEAKER             \\\n  DEFINE_USB_TERMINAL_GUID(0x0306)\nDEFINE_GUIDSTRUCT(\"DFF21CE6-F70F-11D0-B917-00A0C9223196\", KSNODETYPE_COMMUNICATION_SPEAKER);\n # define KSNODETYPE_COMMUNICATION_SPEAKER DEFINE_GUIDNAMED(KSNODETYPE_COMMUNICATION_SPEAKER)\n\n # define STATIC_KSNODETYPE_LOW_FREQUENCY_EFFECTS_SPEAKER         \\\n  DEFINE_USB_TERMINAL_GUID(0x0307)\nDEFINE_GUIDSTRUCT(\"DFF21CE7-F70F-11D0-B917-00A0C9223196\", KSNODETYPE_LOW_FREQUENCY_EFFECTS_SPEAKER);\n # define KSNODETYPE_LOW_FREQUENCY_EFFECTS_SPEAKER DEFINE_GUIDNAMED(KSNODETYPE_LOW_FREQUENCY_EFFECTS_SPEAKER)\n\n # define STATIC_KSNODETYPE_HANDSET                   \\\n  DEFINE_USB_TERMINAL_GUID(0x0401)\nDEFINE_GUIDSTRUCT(\"DFF21DE1-F70F-11D0-B917-00A0C9223196\", KSNODETYPE_HANDSET);\n # define KSNODETYPE_HANDSET DEFINE_GUIDNAMED(KSNODETYPE_HANDSET)\n\n # define STATIC_KSNODETYPE_HEADSET                   \\\n  DEFINE_USB_TERMINAL_GUID(0x0402)\nDEFINE_GUIDSTRUCT(\"DFF21DE2-F70F-11D0-B917-00A0C9223196\", KSNODETYPE_HEADSET);\n # define KSNODETYPE_HEADSET DEFINE_GUIDNAMED(KSNODETYPE_HEADSET)\n\n # define STATIC_KSNODETYPE_SPEAKERPHONE_NO_ECHO_REDUCTION        \\\n  DEFINE_USB_TERMINAL_GUID(0x0403)\nDEFINE_GUIDSTRUCT(\"DFF21DE3-F70F-11D0-B917-00A0C9223196\", KSNODETYPE_SPEAKERPHONE_NO_ECHO_REDUCTION);\n # define KSNODETYPE_SPEAKERPHONE_NO_ECHO_REDUCTION DEFINE_GUIDNAMED(KSNODETYPE_SPEAKERPHONE_NO_ECHO_REDUCTION)\n\n # define STATIC_KSNODETYPE_ECHO_SUPPRESSING_SPEAKERPHONE         \\\n  DEFINE_USB_TERMINAL_GUID(0x0404)\nDEFINE_GUIDSTRUCT(\"DFF21DE4-F70F-11D0-B917-00A0C9223196\", KSNODETYPE_ECHO_SUPPRESSING_SPEAKERPHONE);\n # define KSNODETYPE_ECHO_SUPPRESSING_SPEAKERPHONE DEFINE_GUIDNAMED(KSNODETYPE_ECHO_SUPPRESSING_SPEAKERPHONE)\n\n # define STATIC_KSNODETYPE_ECHO_CANCELING_SPEAKERPHONE           \\\n  DEFINE_USB_TERMINAL_GUID(0x0405)\nDEFINE_GUIDSTRUCT(\"DFF21DE5-F70F-11D0-B917-00A0C9223196\", KSNODETYPE_ECHO_CANCELING_SPEAKERPHONE);\n # define KSNODETYPE_ECHO_CANCELING_SPEAKERPHONE DEFINE_GUIDNAMED(KSNODETYPE_ECHO_CANCELING_SPEAKERPHONE)\n\n # define STATIC_KSNODETYPE_PHONE_LINE                    \\\n  DEFINE_USB_TERMINAL_GUID(0x0501)\nDEFINE_GUIDSTRUCT(\"DFF21EE1-F70F-11D0-B917-00A0C9223196\", KSNODETYPE_PHONE_LINE);\n # define KSNODETYPE_PHONE_LINE DEFINE_GUIDNAMED(KSNODETYPE_PHONE_LINE)\n\n # define STATIC_KSNODETYPE_TELEPHONE                 \\\n  DEFINE_USB_TERMINAL_GUID(0x0502)\nDEFINE_GUIDSTRUCT(\"DFF21EE2-F70F-11D0-B917-00A0C9223196\", KSNODETYPE_TELEPHONE);\n # define KSNODETYPE_TELEPHONE DEFINE_GUIDNAMED(KSNODETYPE_TELEPHONE)\n\n # define STATIC_KSNODETYPE_DOWN_LINE_PHONE               \\\n  DEFINE_USB_TERMINAL_GUID(0x0503)\nDEFINE_GUIDSTRUCT(\"DFF21EE3-F70F-11D0-B917-00A0C9223196\", KSNODETYPE_DOWN_LINE_PHONE);\n # define KSNODETYPE_DOWN_LINE_PHONE DEFINE_GUIDNAMED(KSNODETYPE_DOWN_LINE_PHONE)\n\n # define STATIC_KSNODETYPE_ANALOG_CONNECTOR              \\\n  DEFINE_USB_TERMINAL_GUID(0x601)\nDEFINE_GUIDSTRUCT(\"DFF21FE1-F70F-11D0-B917-00A0C9223196\", KSNODETYPE_ANALOG_CONNECTOR);\n # define KSNODETYPE_ANALOG_CONNECTOR DEFINE_GUIDNAMED(KSNODETYPE_ANALOG_CONNECTOR)\n\n # define STATIC_KSNODETYPE_DIGITAL_AUDIO_INTERFACE           \\\n  DEFINE_USB_TERMINAL_GUID(0x0602)\nDEFINE_GUIDSTRUCT(\"DFF21FE2-F70F-11D0-B917-00A0C9223196\", KSNODETYPE_DIGITAL_AUDIO_INTERFACE);\n # define KSNODETYPE_DIGITAL_AUDIO_INTERFACE DEFINE_GUIDNAMED(KSNODETYPE_DIGITAL_AUDIO_INTERFACE)\n\n # define STATIC_KSNODETYPE_LINE_CONNECTOR                \\\n  DEFINE_USB_TERMINAL_GUID(0x0603)\nDEFINE_GUIDSTRUCT(\"DFF21FE3-F70F-11D0-B917-00A0C9223196\", KSNODETYPE_LINE_CONNECTOR);\n # define KSNODETYPE_LINE_CONNECTOR DEFINE_GUIDNAMED(KSNODETYPE_LINE_CONNECTOR)\n\n # define STATIC_KSNODETYPE_LEGACY_AUDIO_CONNECTOR            \\\n  DEFINE_USB_TERMINAL_GUID(0x0604)\nDEFINE_GUIDSTRUCT(\"DFF21FE4-F70F-11D0-B917-00A0C9223196\", KSNODETYPE_LEGACY_AUDIO_CONNECTOR);\n # define KSNODETYPE_LEGACY_AUDIO_CONNECTOR DEFINE_GUIDNAMED(KSNODETYPE_LEGACY_AUDIO_CONNECTOR)\n\n # define STATIC_KSNODETYPE_SPDIF_INTERFACE               \\\n  DEFINE_USB_TERMINAL_GUID(0x0605)\nDEFINE_GUIDSTRUCT(\"DFF21FE5-F70F-11D0-B917-00A0C9223196\", KSNODETYPE_SPDIF_INTERFACE);\n # define KSNODETYPE_SPDIF_INTERFACE DEFINE_GUIDNAMED(KSNODETYPE_SPDIF_INTERFACE)\n\n # define STATIC_KSNODETYPE_1394_DA_STREAM                \\\n  DEFINE_USB_TERMINAL_GUID(0x0606)\nDEFINE_GUIDSTRUCT(\"DFF21FE6-F70F-11D0-B917-00A0C9223196\", KSNODETYPE_1394_DA_STREAM);\n # define KSNODETYPE_1394_DA_STREAM DEFINE_GUIDNAMED(KSNODETYPE_1394_DA_STREAM)\n\n # define STATIC_KSNODETYPE_1394_DV_STREAM_SOUNDTRACK         \\\n  DEFINE_USB_TERMINAL_GUID(0x0607)\nDEFINE_GUIDSTRUCT(\"DFF21FE7-F70F-11D0-B917-00A0C9223196\", KSNODETYPE_1394_DV_STREAM_SOUNDTRACK);\n # define KSNODETYPE_1394_DV_STREAM_SOUNDTRACK DEFINE_GUIDNAMED(KSNODETYPE_1394_DV_STREAM_SOUNDTRACK)\n\n # define STATIC_KSNODETYPE_LEVEL_CALIBRATION_NOISE_SOURCE        \\\n  DEFINE_USB_TERMINAL_GUID(0x0701)\nDEFINE_GUIDSTRUCT(\"DFF220E1-F70F-11D0-B917-00A0C9223196\", KSNODETYPE_LEVEL_CALIBRATION_NOISE_SOURCE);\n # define KSNODETYPE_LEVEL_CALIBRATION_NOISE_SOURCE DEFINE_GUIDNAMED(KSNODETYPE_LEVEL_CALIBRATION_NOISE_SOURCE)\n\n # define STATIC_KSNODETYPE_EQUALIZATION_NOISE                \\\n  DEFINE_USB_TERMINAL_GUID(0x0702)\nDEFINE_GUIDSTRUCT(\"DFF220E2-F70F-11D0-B917-00A0C9223196\", KSNODETYPE_EQUALIZATION_NOISE);\n # define KSNODETYPE_EQUALIZATION_NOISE DEFINE_GUIDNAMED(KSNODETYPE_EQUALIZATION_NOISE)\n\n # define STATIC_KSNODETYPE_CD_PLAYER                 \\\n  DEFINE_USB_TERMINAL_GUID(0x0703)\nDEFINE_GUIDSTRUCT(\"DFF220E3-F70F-11D0-B917-00A0C9223196\", KSNODETYPE_CD_PLAYER);\n # define KSNODETYPE_CD_PLAYER DEFINE_GUIDNAMED(KSNODETYPE_CD_PLAYER)\n\n # define STATIC_KSNODETYPE_DAT_IO_DIGITAL_AUDIO_TAPE         \\\n  DEFINE_USB_TERMINAL_GUID(0x0704)\nDEFINE_GUIDSTRUCT(\"DFF220E4-F70F-11D0-B917-00A0C9223196\", KSNODETYPE_DAT_IO_DIGITAL_AUDIO_TAPE);\n # define KSNODETYPE_DAT_IO_DIGITAL_AUDIO_TAPE DEFINE_GUIDNAMED(KSNODETYPE_DAT_IO_DIGITAL_AUDIO_TAPE)\n\n # define STATIC_KSNODETYPE_DCC_IO_DIGITAL_COMPACT_CASSETTE       \\\n  DEFINE_USB_TERMINAL_GUID(0x0705)\nDEFINE_GUIDSTRUCT(\"DFF220E5-F70F-11D0-B917-00A0C9223196\", KSNODETYPE_DCC_IO_DIGITAL_COMPACT_CASSETTE);\n # define KSNODETYPE_DCC_IO_DIGITAL_COMPACT_CASSETTE DEFINE_GUIDNAMED(KSNODETYPE_DCC_IO_DIGITAL_COMPACT_CASSETTE)\n\n # define STATIC_KSNODETYPE_MINIDISK                  \\\n  DEFINE_USB_TERMINAL_GUID(0x0706)\nDEFINE_GUIDSTRUCT(\"DFF220E6-F70F-11D0-B917-00A0C9223196\", KSNODETYPE_MINIDISK);\n # define KSNODETYPE_MINIDISK DEFINE_GUIDNAMED(KSNODETYPE_MINIDISK)\n\n # define STATIC_KSNODETYPE_ANALOG_TAPE                   \\\n  DEFINE_USB_TERMINAL_GUID(0x0707)\nDEFINE_GUIDSTRUCT(\"DFF220E7-F70F-11D0-B917-00A0C9223196\", KSNODETYPE_ANALOG_TAPE);\n # define KSNODETYPE_ANALOG_TAPE DEFINE_GUIDNAMED(KSNODETYPE_ANALOG_TAPE)\n\n # define STATIC_KSNODETYPE_PHONOGRAPH                    \\\n  DEFINE_USB_TERMINAL_GUID(0x0708)\nDEFINE_GUIDSTRUCT(\"DFF220E8-F70F-11D0-B917-00A0C9223196\", KSNODETYPE_PHONOGRAPH);\n # define KSNODETYPE_PHONOGRAPH DEFINE_GUIDNAMED(KSNODETYPE_PHONOGRAPH)\n\n # define STATIC_KSNODETYPE_VCR_AUDIO                 \\\n  DEFINE_USB_TERMINAL_GUID(0x0708)\nDEFINE_GUIDSTRUCT(\"DFF220E9-F70F-11D0-B917-00A0C9223196\", KSNODETYPE_VCR_AUDIO);\n # define KSNODETYPE_VCR_AUDIO DEFINE_GUIDNAMED(KSNODETYPE_VCR_AUDIO)\n\n # define STATIC_KSNODETYPE_VIDEO_DISC_AUDIO              \\\n  DEFINE_USB_TERMINAL_GUID(0x070A)\nDEFINE_GUIDSTRUCT(\"DFF220EA-F70F-11D0-B917-00A0C9223196\", KSNODETYPE_VIDEO_DISC_AUDIO);\n # define KSNODETYPE_VIDEO_DISC_AUDIO DEFINE_GUIDNAMED(KSNODETYPE_VIDEO_DISC_AUDIO)\n\n # define STATIC_KSNODETYPE_DVD_AUDIO                 \\\n  DEFINE_USB_TERMINAL_GUID(0x070B)\nDEFINE_GUIDSTRUCT(\"DFF220EB-F70F-11D0-B917-00A0C9223196\", KSNODETYPE_DVD_AUDIO);\n # define KSNODETYPE_DVD_AUDIO DEFINE_GUIDNAMED(KSNODETYPE_DVD_AUDIO)\n\n # define STATIC_KSNODETYPE_TV_TUNER_AUDIO                \\\n  DEFINE_USB_TERMINAL_GUID(0x070C)\nDEFINE_GUIDSTRUCT(\"DFF220EC-F70F-11D0-B917-00A0C9223196\", KSNODETYPE_TV_TUNER_AUDIO);\n # define KSNODETYPE_TV_TUNER_AUDIO DEFINE_GUIDNAMED(KSNODETYPE_TV_TUNER_AUDIO)\n\n # define STATIC_KSNODETYPE_SATELLITE_RECEIVER_AUDIO          \\\n  DEFINE_USB_TERMINAL_GUID(0x070D)\nDEFINE_GUIDSTRUCT(\"DFF220ED-F70F-11D0-B917-00A0C9223196\", KSNODETYPE_SATELLITE_RECEIVER_AUDIO);\n # define KSNODETYPE_SATELLITE_RECEIVER_AUDIO DEFINE_GUIDNAMED(KSNODETYPE_SATELLITE_RECEIVER_AUDIO)\n\n # define STATIC_KSNODETYPE_CABLE_TUNER_AUDIO             \\\n  DEFINE_USB_TERMINAL_GUID(0x070E)\nDEFINE_GUIDSTRUCT(\"DFF220EE-F70F-11D0-B917-00A0C9223196\", KSNODETYPE_CABLE_TUNER_AUDIO);\n # define KSNODETYPE_CABLE_TUNER_AUDIO DEFINE_GUIDNAMED(KSNODETYPE_CABLE_TUNER_AUDIO)\n\n # define STATIC_KSNODETYPE_DSS_AUDIO                 \\\n  DEFINE_USB_TERMINAL_GUID(0x070F)\nDEFINE_GUIDSTRUCT(\"DFF220EF-F70F-11D0-B917-00A0C9223196\", KSNODETYPE_DSS_AUDIO);\n # define KSNODETYPE_DSS_AUDIO DEFINE_GUIDNAMED(KSNODETYPE_DSS_AUDIO)\n\n # define STATIC_KSNODETYPE_RADIO_RECEIVER                \\\n  DEFINE_USB_TERMINAL_GUID(0x0710)\nDEFINE_GUIDSTRUCT(\"DFF220F0-F70F-11D0-B917-00A0C9223196\", KSNODETYPE_RADIO_RECEIVER);\n # define KSNODETYPE_RADIO_RECEIVER DEFINE_GUIDNAMED(KSNODETYPE_RADIO_RECEIVER)\n\n # define STATIC_KSNODETYPE_RADIO_TRANSMITTER             \\\n  DEFINE_USB_TERMINAL_GUID(0x0711)\nDEFINE_GUIDSTRUCT(\"DFF220F1-F70F-11D0-B917-00A0C9223196\", KSNODETYPE_RADIO_TRANSMITTER);\n # define KSNODETYPE_RADIO_TRANSMITTER DEFINE_GUIDNAMED(KSNODETYPE_RADIO_TRANSMITTER)\n\n # define STATIC_KSNODETYPE_MULTITRACK_RECORDER               \\\n  DEFINE_USB_TERMINAL_GUID(0x0712)\nDEFINE_GUIDSTRUCT(\"DFF220F2-F70F-11D0-B917-00A0C9223196\", KSNODETYPE_MULTITRACK_RECORDER);\n # define KSNODETYPE_MULTITRACK_RECORDER DEFINE_GUIDNAMED(KSNODETYPE_MULTITRACK_RECORDER)\n\n # define STATIC_KSNODETYPE_SYNTHESIZER                   \\\n  DEFINE_USB_TERMINAL_GUID(0x0713)\nDEFINE_GUIDSTRUCT(\"DFF220F3-F70F-11D0-B917-00A0C9223196\", KSNODETYPE_SYNTHESIZER);\n # define KSNODETYPE_SYNTHESIZER DEFINE_GUIDNAMED(KSNODETYPE_SYNTHESIZER)\n\n # define STATIC_KSNODETYPE_SWSYNTH                   \\\n  0x423274A0L, 0x8B81, 0x11D1, 0xA0, 0x50, 0x00, 0x00, 0xF8, 0x00, 0x47, 0x88\nDEFINE_GUIDSTRUCT(\"423274A0-8B81-11D1-A050-0000F8004788\", KSNODETYPE_SWSYNTH);\n # define KSNODETYPE_SWSYNTH DEFINE_GUIDNAMED(KSNODETYPE_SWSYNTH)\n\n # define STATIC_KSNODETYPE_SWMIDI                    \\\n  0xCB9BEFA0L, 0xA251, 0x11D1, 0xA0, 0x50, 0x00, 0x00, 0xF8, 0x00, 0x47, 0x88\nDEFINE_GUIDSTRUCT(\"CB9BEFA0-A251-11D1-A050-0000F8004788\", KSNODETYPE_SWMIDI);\n # define KSNODETYPE_SWMIDI DEFINE_GUIDNAMED(KSNODETYPE_SWMIDI)\n\n # define STATIC_KSNODETYPE_DRM_DESCRAMBLE                \\\n  0xFFBB6E3FL, 0xCCFE, 0x4D84, 0x90, 0xD9, 0x42, 0x14, 0x18, 0xB0, 0x3A, 0x8E\nDEFINE_GUIDSTRUCT(\"FFBB6E3F-CCFE-4D84-90D9-421418B03A8E\", KSNODETYPE_DRM_DESCRAMBLE);\n # define KSNODETYPE_DRM_DESCRAMBLE DEFINE_GUIDNAMED(KSNODETYPE_DRM_DESCRAMBLE)\n\n # define STATIC_KSCATEGORY_AUDIO                     \\\n  0x6994AD04L, 0x93EF, 0x11D0, { 0xA3, 0xCC, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 }\nDEFINE_GUIDSTRUCT(\"6994AD04-93EF-11D0-A3CC-00A0C9223196\", KSCATEGORY_AUDIO);\n # define KSCATEGORY_AUDIO DEFINE_GUIDNAMED(KSCATEGORY_AUDIO)\n\n # define STATIC_KSCATEGORY_VIDEO                     \\\n  0x6994AD05L, 0x93EF, 0x11D0, 0xA3, 0xCC, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96\nDEFINE_GUIDSTRUCT(\"6994AD05-93EF-11D0-A3CC-00A0C9223196\", KSCATEGORY_VIDEO);\n # define KSCATEGORY_VIDEO DEFINE_GUIDNAMED(KSCATEGORY_VIDEO)\n\n # define STATIC_KSCATEGORY_TEXT                      \\\n  0x6994AD06L, 0x93EF, 0x11D0, 0xA3, 0xCC, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96\nDEFINE_GUIDSTRUCT(\"6994AD06-93EF-11D0-A3CC-00A0C9223196\", KSCATEGORY_TEXT);\n # define KSCATEGORY_TEXT DEFINE_GUIDNAMED(KSCATEGORY_TEXT)\n\n # define STATIC_KSCATEGORY_NETWORK                   \\\n  0x67C9CC3CL, 0x69C4, 0x11D2, 0x87, 0x59, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96\nDEFINE_GUIDSTRUCT(\"67C9CC3C-69C4-11D2-8759-00A0C9223196\", KSCATEGORY_NETWORK);\n # define KSCATEGORY_NETWORK DEFINE_GUIDNAMED(KSCATEGORY_NETWORK)\n\n # define STATIC_KSCATEGORY_TOPOLOGY                  \\\n  0xDDA54A40L, 0x1E4C, 0x11D1, 0xA0, 0x50, 0x40, 0x57, 0x05, 0xC1, 0x00, 0x00\nDEFINE_GUIDSTRUCT(\"DDA54A40-1E4C-11D1-A050-405705C10000\", KSCATEGORY_TOPOLOGY);\n # define KSCATEGORY_TOPOLOGY DEFINE_GUIDNAMED(KSCATEGORY_TOPOLOGY)\n\n # define STATIC_KSCATEGORY_VIRTUAL                   \\\n  0x3503EAC4L, 0x1F26, 0x11D1, 0x8A, 0xB0, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96\nDEFINE_GUIDSTRUCT(\"3503EAC4-1F26-11D1-8AB0-00A0C9223196\", KSCATEGORY_VIRTUAL);\n # define KSCATEGORY_VIRTUAL DEFINE_GUIDNAMED(KSCATEGORY_VIRTUAL)\n\n # define STATIC_KSCATEGORY_ACOUSTIC_ECHO_CANCEL              \\\n  0xBF963D80L, 0xC559, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1\nDEFINE_GUIDSTRUCT(\"BF963D80-C559-11D0-8A2B-00A0C9255AC1\", KSCATEGORY_ACOUSTIC_ECHO_CANCEL);\n # define KSCATEGORY_ACOUSTIC_ECHO_CANCEL DEFINE_GUIDNAMED(KSCATEGORY_ACOUSTIC_ECHO_CANCEL)\n\n # define STATIC_KSCATEGORY_SYSAUDIO                  \\\n  0xA7C7A5B1L, 0x5AF3, 0x11D1, 0x9C, 0xED, 0x00, 0xA0, 0x24, 0xBF, 0x04, 0x07\nDEFINE_GUIDSTRUCT(\"A7C7A5B1-5AF3-11D1-9CED-00A024BF0407\", KSCATEGORY_SYSAUDIO);\n # define KSCATEGORY_SYSAUDIO DEFINE_GUIDNAMED(KSCATEGORY_SYSAUDIO)\n\n # define STATIC_KSCATEGORY_WDMAUD                    \\\n  0x3E227E76L, 0x690D, 0x11D2, 0x81, 0x61, 0x00, 0x00, 0xF8, 0x77, 0x5B, 0xF1\nDEFINE_GUIDSTRUCT(\"3E227E76-690D-11D2-8161-0000F8775BF1\", KSCATEGORY_WDMAUD);\n # define KSCATEGORY_WDMAUD DEFINE_GUIDNAMED(KSCATEGORY_WDMAUD)\n\n # define STATIC_KSCATEGORY_AUDIO_GFX                 \\\n  0x9BAF9572L, 0x340C, 0x11D3, 0xAB, 0xDC, 0x00, 0xA0, 0xC9, 0x0A, 0xB1, 0x6F\nDEFINE_GUIDSTRUCT(\"9BAF9572-340C-11D3-ABDC-00A0C90AB16F\", KSCATEGORY_AUDIO_GFX);\n # define KSCATEGORY_AUDIO_GFX DEFINE_GUIDNAMED(KSCATEGORY_AUDIO_GFX)\n\n # define STATIC_KSCATEGORY_AUDIO_SPLITTER                \\\n  0x9EA331FAL, 0xB91B, 0x45F8, 0x92, 0x85, 0xBD, 0x2B, 0xC7, 0x7A, 0xFC, 0xDE\nDEFINE_GUIDSTRUCT(\"9EA331FA-B91B-45F8-9285-BD2BC77AFCDE\", KSCATEGORY_AUDIO_SPLITTER);\n # define KSCATEGORY_AUDIO_SPLITTER DEFINE_GUIDNAMED(KSCATEGORY_AUDIO_SPLITTER)\n\n # define STATIC_KSCATEGORY_SYNTHESIZER STATIC_KSNODETYPE_SYNTHESIZER\n # define KSCATEGORY_SYNTHESIZER KSNODETYPE_SYNTHESIZER\n\n # define STATIC_KSCATEGORY_DRM_DESCRAMBLE STATIC_KSNODETYPE_DRM_DESCRAMBLE\n # define KSCATEGORY_DRM_DESCRAMBLE KSNODETYPE_DRM_DESCRAMBLE\n\n # define STATIC_KSCATEGORY_AUDIO_DEVICE                  \\\n  0xFBF6F530L, 0x07B9, 0x11D2, 0xA7, 0x1E, 0x00, 0x00, 0xF8, 0x00, 0x47, 0x88\nDEFINE_GUIDSTRUCT(\"FBF6F530-07B9-11D2-A71E-0000F8004788\", KSCATEGORY_AUDIO_DEVICE);\n # define KSCATEGORY_AUDIO_DEVICE DEFINE_GUIDNAMED(KSCATEGORY_AUDIO_DEVICE)\n\n # define STATIC_KSCATEGORY_PREFERRED_WAVEOUT_DEVICE          \\\n  0xD6C5066EL, 0x72C1, 0x11D2, 0x97, 0x55, 0x00, 0x00, 0xF8, 0x00, 0x47, 0x88\nDEFINE_GUIDSTRUCT(\"D6C5066E-72C1-11D2-9755-0000F8004788\", KSCATEGORY_PREFERRED_WAVEOUT_DEVICE);\n # define KSCATEGORY_PREFERRED_WAVEOUT_DEVICE DEFINE_GUIDNAMED(KSCATEGORY_PREFERRED_WAVEOUT_DEVICE)\n\n # define STATIC_KSCATEGORY_PREFERRED_WAVEIN_DEVICE           \\\n  0xD6C50671L, 0x72C1, 0x11D2, 0x97, 0x55, 0x00, 0x00, 0xF8, 0x00, 0x47, 0x88\nDEFINE_GUIDSTRUCT(\"D6C50671-72C1-11D2-9755-0000F8004788\", KSCATEGORY_PREFERRED_WAVEIN_DEVICE);\n # define KSCATEGORY_PREFERRED_WAVEIN_DEVICE DEFINE_GUIDNAMED(KSCATEGORY_PREFERRED_WAVEIN_DEVICE)\n\n # define STATIC_KSCATEGORY_PREFERRED_MIDIOUT_DEVICE          \\\n  0xD6C50674L, 0x72C1, 0x11D2, 0x97, 0x55, 0x00, 0x00, 0xF8, 0x00, 0x47, 0x88\nDEFINE_GUIDSTRUCT(\"D6C50674-72C1-11D2-9755-0000F8004788\", KSCATEGORY_PREFERRED_MIDIOUT_DEVICE);\n # define KSCATEGORY_PREFERRED_MIDIOUT_DEVICE DEFINE_GUIDNAMED(KSCATEGORY_PREFERRED_MIDIOUT_DEVICE)\n\n # define STATIC_KSCATEGORY_WDMAUD_USE_PIN_NAME               \\\n  0x47A4FA20L, 0xA251, 0x11D1, 0xA0, 0x50, 0x00, 0x00, 0xF8, 0x00, 0x47, 0x88\nDEFINE_GUIDSTRUCT(\"47A4FA20-A251-11D1-A050-0000F8004788\", KSCATEGORY_WDMAUD_USE_PIN_NAME);\n # define KSCATEGORY_WDMAUD_USE_PIN_NAME DEFINE_GUIDNAMED(KSCATEGORY_WDMAUD_USE_PIN_NAME)\n\n # define STATIC_KSCATEGORY_ESCALANTE_PLATFORM_DRIVER         \\\n  0x74f3aea8L, 0x9768, 0x11d1, 0x8e, 0x07, 0x00, 0xa0, 0xc9, 0x5e, 0xc2, 0x2e\nDEFINE_GUIDSTRUCT(\"74f3aea8-9768-11d1-8e07-00a0c95ec22e\", KSCATEGORY_ESCALANTE_PLATFORM_DRIVER);\n # define KSCATEGORY_ESCALANTE_PLATFORM_DRIVER DEFINE_GUIDNAMED(KSCATEGORY_ESCALANTE_PLATFORM_DRIVER)\n\n # define STATIC_KSDATAFORMAT_TYPE_VIDEO                  \\\n  0x73646976L, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71\nDEFINE_GUIDSTRUCT(\"73646976-0000-0010-8000-00aa00389b71\", KSDATAFORMAT_TYPE_VIDEO);\n # define KSDATAFORMAT_TYPE_VIDEO DEFINE_GUIDNAMED(KSDATAFORMAT_TYPE_VIDEO)\n\n # define STATIC_KSDATAFORMAT_TYPE_AUDIO                  \\\n  0x73647561L, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71\nDEFINE_GUIDSTRUCT(\"73647561-0000-0010-8000-00aa00389b71\", KSDATAFORMAT_TYPE_AUDIO);\n # define KSDATAFORMAT_TYPE_AUDIO DEFINE_GUIDNAMED(KSDATAFORMAT_TYPE_AUDIO)\n\n # define STATIC_KSDATAFORMAT_TYPE_TEXT                   \\\n  0x73747874L, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71\nDEFINE_GUIDSTRUCT(\"73747874-0000-0010-8000-00aa00389b71\", KSDATAFORMAT_TYPE_TEXT);\n # define KSDATAFORMAT_TYPE_TEXT DEFINE_GUIDNAMED(KSDATAFORMAT_TYPE_TEXT)\n\n # if !defined(DEFINE_WAVEFORMATEX_GUID)\n  #  define DEFINE_WAVEFORMATEX_GUID(x)                 \\\n  (USHORT)(x), 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }\n # endif\n\n # define STATIC_KSDATAFORMAT_SUBTYPE_WAVEFORMATEX            \\\n  0x00000000L, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71\nDEFINE_GUIDSTRUCT(\"00000000-0000-0010-8000-00aa00389b71\", KSDATAFORMAT_SUBTYPE_WAVEFORMATEX);\n # define KSDATAFORMAT_SUBTYPE_WAVEFORMATEX DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_WAVEFORMATEX)\n\n # define INIT_WAVEFORMATEX_GUID(Guid, x)                  \\\n  {                                   \\\n    *(Guid) = KSDATAFORMAT_SUBTYPE_WAVEFORMATEX;            \\\n    (Guid)->Data1 = (USHORT)(x);                    \\\n  }\n\n # define EXTRACT_WAVEFORMATEX_ID(Guid)                   \\\n  (USHORT)((Guid)->Data1)\n\n # define IS_VALID_WAVEFORMATEX_GUID(Guid)                \\\n  (!memcmp(((PUSHORT)&KSDATAFORMAT_SUBTYPE_WAVEFORMATEX) + 1, ((PUSHORT)(Guid)) + 1, sizeof(GUID) - sizeof(USHORT)))\n\n # ifndef INIT_MMREG_MID\n  #  define INIT_MMREG_MID(guid, id)                     \\\n  {                                   \\\n    (guid)->Data1 = 0xd5a47fa7 + (USHORT)(id);          \\\n    (guid)->Data2 = 0x6d98;                     \\\n    (guid)->Data3 = 0x11d1;                     \\\n    (guid)->Data4[0] = 0xa2;                    \\\n    (guid)->Data4[1] = 0x1a;                    \\\n    (guid)->Data4[2] = 0x00;                    \\\n    (guid)->Data4[3] = 0xa0;                    \\\n    (guid)->Data4[4] = 0xc9;                    \\\n    (guid)->Data4[5] = 0x22;                    \\\n    (guid)->Data4[6] = 0x31;                    \\\n    (guid)->Data4[7] = 0x96;                    \\\n  }\n  #  define EXTRACT_MMREG_MID(guid)                     \\\n  (USHORT)((guid)->Data1 - 0xd5a47fa7)\n  #  define DEFINE_MMREG_MID_GUID(id)                   \\\n  0xd5a47fa7 + (USHORT)(id), 0x6d98, 0x11d1, 0xa2, 0x1a, 0x00, 0xa0, 0xc9, 0x22, 0x31, 0x96\n\n  #  define IS_COMPATIBLE_MMREG_MID(guid)                   \\\n  (((guid)->Data1 >= 0xd5a47fa7) &&               \\\n   ((guid)->Data1 < 0xd5a47fa7 + 0xffff) &&           \\\n   ((guid)->Data2 == 0x6d98) &&                   \\\n   ((guid)->Data3 == 0x11d1) &&                   \\\n   ((guid)->Data4[0] == 0xa2) &&                  \\\n   ((guid)->Data4[1] == 0x1a) &&                  \\\n   ((guid)->Data4[2] == 0x00) &&                  \\\n   ((guid)->Data4[3] == 0xa0) &&                  \\\n   ((guid)->Data4[4] == 0xc9) &&                  \\\n   ((guid)->Data4[5] == 0x22) &&                  \\\n   ((guid)->Data4[6] == 0x31) &&                  \\\n   ((guid)->Data4[7] == 0x96))\n # endif /* INIT_MMREG_MID */\n\n # ifndef INIT_MMREG_PID\n  #  define INIT_MMREG_PID(guid, id)                     \\\n  {                                   \\\n    (guid)->Data1 = 0xe36dc2ac + (USHORT)(id);          \\\n    (guid)->Data2 = 0x6d9a;                     \\\n    (guid)->Data3 = 0x11d1;                     \\\n    (guid)->Data4[0] = 0xa2;                    \\\n    (guid)->Data4[1] = 0x1a;                    \\\n    (guid)->Data4[2] = 0x00;                    \\\n    (guid)->Data4[3] = 0xa0;                    \\\n    (guid)->Data4[4] = 0xc9;                    \\\n    (guid)->Data4[5] = 0x22;                    \\\n    (guid)->Data4[6] = 0x31;                    \\\n    (guid)->Data4[7] = 0x96;                    \\\n  }\n  #  define EXTRACT_MMREG_PID(guid)                     \\\n  (USHORT)((guid)->Data1 - 0xe36dc2ac)\n  #  define DEFINE_MMREG_PID_GUID(id)                   \\\n  0xe36dc2ac + (USHORT)(id), 0x6d9a, 0x11d1, 0xa2, 0x1a, 0x00, 0xa0, 0xc9, 0x22, 0x31, 0x96\n\n  #  define IS_COMPATIBLE_MMREG_PID(guid)                   \\\n  (((guid)->Data1 >= 0xe36dc2ac) &&               \\\n   ((guid)->Data1 < 0xe36dc2ac + 0xffff) &&           \\\n   ((guid)->Data2 == 0x6d9a) &&                   \\\n   ((guid)->Data3 == 0x11d1) &&                   \\\n   ((guid)->Data4[0] == 0xa2) &&                  \\\n   ((guid)->Data4[1] == 0x1a) &&                  \\\n   ((guid)->Data4[2] == 0x00) &&                  \\\n   ((guid)->Data4[3] == 0xa0) &&                  \\\n   ((guid)->Data4[4] == 0xc9) &&                  \\\n   ((guid)->Data4[5] == 0x22) &&                  \\\n   ((guid)->Data4[6] == 0x31) &&                  \\\n   ((guid)->Data4[7] == 0x96))\n # endif /* INIT_MMREG_PID */\n\n # define STATIC_KSDATAFORMAT_SUBTYPE_ANALOG              \\\n  0x6dba3190L, 0x67bd, 0x11cf, 0xa0, 0xf7, 0x00, 0x20, 0xaf, 0xd1, 0x56, 0xe4\nDEFINE_GUIDSTRUCT(\"6dba3190-67bd-11cf-a0f7-0020afd156e4\", KSDATAFORMAT_SUBTYPE_ANALOG);\n # define KSDATAFORMAT_SUBTYPE_ANALOG DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_ANALOG)\n\n # define STATIC_KSDATAFORMAT_SUBTYPE_PCM                 \\\n  DEFINE_WAVEFORMATEX_GUID(WAVE_FORMAT_PCM)\nDEFINE_GUIDSTRUCT(\"00000001-0000-0010-8000-00aa00389b71\", KSDATAFORMAT_SUBTYPE_PCM);\n # define KSDATAFORMAT_SUBTYPE_PCM DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_PCM)\n\n # ifdef _INC_MMREG\n  #  define STATIC_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT              \\\n  DEFINE_WAVEFORMATEX_GUID(WAVE_FORMAT_IEEE_FLOAT)\nDEFINE_GUIDSTRUCT(\"00000003-0000-0010-8000-00aa00389b71\", KSDATAFORMAT_SUBTYPE_IEEE_FLOAT);\n  #  define KSDATAFORMAT_SUBTYPE_IEEE_FLOAT DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)\n\n  #  define STATIC_KSDATAFORMAT_SUBTYPE_DRM                 \\\n  DEFINE_WAVEFORMATEX_GUID(WAVE_FORMAT_DRM)\nDEFINE_GUIDSTRUCT(\"00000009-0000-0010-8000-00aa00389b71\", KSDATAFORMAT_SUBTYPE_DRM);\n  #  define KSDATAFORMAT_SUBTYPE_DRM DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_DRM)\n\n  #  define STATIC_KSDATAFORMAT_SUBTYPE_ALAW                \\\n  DEFINE_WAVEFORMATEX_GUID(WAVE_FORMAT_ALAW)\nDEFINE_GUIDSTRUCT(\"00000006-0000-0010-8000-00aa00389b71\", KSDATAFORMAT_SUBTYPE_ALAW);\n  #  define KSDATAFORMAT_SUBTYPE_ALAW DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_ALAW)\n\n  #  define STATIC_KSDATAFORMAT_SUBTYPE_MULAW               \\\n  DEFINE_WAVEFORMATEX_GUID(WAVE_FORMAT_MULAW)\nDEFINE_GUIDSTRUCT(\"00000007-0000-0010-8000-00aa00389b71\", KSDATAFORMAT_SUBTYPE_MULAW);\n  #  define KSDATAFORMAT_SUBTYPE_MULAW DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_MULAW)\n\n  #  define STATIC_KSDATAFORMAT_SUBTYPE_ADPCM               \\\n  DEFINE_WAVEFORMATEX_GUID(WAVE_FORMAT_ADPCM)\nDEFINE_GUIDSTRUCT(\"00000002-0000-0010-8000-00aa00389b71\", KSDATAFORMAT_SUBTYPE_ADPCM);\n  #  define KSDATAFORMAT_SUBTYPE_ADPCM DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_ADPCM)\n\n  #  define STATIC_KSDATAFORMAT_SUBTYPE_MPEG                \\\n  DEFINE_WAVEFORMATEX_GUID(WAVE_FORMAT_MPEG)\nDEFINE_GUIDSTRUCT(\"00000050-0000-0010-8000-00aa00389b71\", KSDATAFORMAT_SUBTYPE_MPEG);\n  #  define KSDATAFORMAT_SUBTYPE_MPEG DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_MPEG)\n # endif /* _INC_MMREG */\n\n # define STATIC_KSDATAFORMAT_SPECIFIER_VC_ID             \\\n  0xAD98D184L, 0xAAC3, 0x11D0, 0xA4, 0x1C, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96\nDEFINE_GUIDSTRUCT(\"AD98D184-AAC3-11D0-A41C-00A0C9223196\", KSDATAFORMAT_SPECIFIER_VC_ID);\n # define KSDATAFORMAT_SPECIFIER_VC_ID DEFINE_GUIDNAMED(KSDATAFORMAT_SPECIFIER_VC_ID)\n\n # define STATIC_KSDATAFORMAT_SPECIFIER_WAVEFORMATEX          \\\n  0x05589f81L, 0xc356, 0x11ce, 0xbf, 0x01, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a\nDEFINE_GUIDSTRUCT(\"05589f81-c356-11ce-bf01-00aa0055595a\", KSDATAFORMAT_SPECIFIER_WAVEFORMATEX);\n # define KSDATAFORMAT_SPECIFIER_WAVEFORMATEX DEFINE_GUIDNAMED(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)\n\n # define STATIC_KSDATAFORMAT_SPECIFIER_DSOUND                \\\n  0x518590a2L, 0xa184, 0x11d0, 0x85, 0x22, 0x00, 0xc0, 0x4f, 0xd9, 0xba, 0xf3\nDEFINE_GUIDSTRUCT(\"518590a2-a184-11d0-8522-00c04fd9baf3\", KSDATAFORMAT_SPECIFIER_DSOUND);\n # define KSDATAFORMAT_SPECIFIER_DSOUND DEFINE_GUIDNAMED(KSDATAFORMAT_SPECIFIER_DSOUND)\n\n # if defined(_INC_MMSYSTEM) || defined(_INC_MMREG) || 1\n  #  if !defined(PACK_PRAGMAS_NOT_SUPPORTED)\n   #   include <pshpack1.h>\n  #  endif\ntypedef struct\n{\n  KSDATAFORMAT DataFormat;\n  WAVEFORMATEX WaveFormatEx;\n}KSDATAFORMAT_WAVEFORMATEX, * PKSDATAFORMAT_WAVEFORMATEX;\n\n  #  ifndef _WAVEFORMATEXTENSIBLE_\n   #   define _WAVEFORMATEXTENSIBLE_\ntypedef struct\n{\n  WAVEFORMATEX Format;\n  union\n  {\n    WORD wValidBitsPerSample;\n    WORD wSamplesPerBlock;\n    WORD wReserved;\n  }Samples;\n  DWORD dwChannelMask;\n\n  GUID SubFormat;\n}WAVEFORMATEXTENSIBLE, * PWAVEFORMATEXTENSIBLE;\n  #  endif /* _WAVEFORMATEXTENSIBLE_ */\n\n  #  if !defined(WAVE_FORMAT_EXTENSIBLE)\n   #   define WAVE_FORMAT_EXTENSIBLE 0xFFFE\n  #  endif\n\ntypedef struct\n{\n  ULONG Flags;\n  ULONG Control;\n  WAVEFORMATEX WaveFormatEx;\n}KSDSOUND_BUFFERDESC, * PKSDSOUND_BUFFERDESC;\n\ntypedef struct\n{\n  KSDATAFORMAT DataFormat;\n  KSDSOUND_BUFFERDESC BufferDesc;\n}KSDATAFORMAT_DSOUND, * PKSDATAFORMAT_DSOUND;\n\n  #  if !defined(PACK_PRAGMAS_NOT_SUPPORTED)\n   #   include <poppack.h>\n  #  endif\n # endif /* defined(_INC_MMSYSTEM) || defined(_INC_MMREG) */\n\n # define KSDSOUND_BUFFER_PRIMARY 0x00000001\n # define KSDSOUND_BUFFER_STATIC 0x00000002\n # define KSDSOUND_BUFFER_LOCHARDWARE 0x00000004\n # define KSDSOUND_BUFFER_LOCSOFTWARE 0x00000008\n\n # define KSDSOUND_BUFFER_CTRL_3D 0x00000001\n # define KSDSOUND_BUFFER_CTRL_FREQUENCY 0x00000002\n # define KSDSOUND_BUFFER_CTRL_PAN 0x00000004\n # define KSDSOUND_BUFFER_CTRL_VOLUME 0x00000008\n # define KSDSOUND_BUFFER_CTRL_POSITIONNOTIFY 0x00000010\n\ntypedef struct\n{\n  DWORDLONG PlayOffset;\n  DWORDLONG WriteOffset;\n}KSAUDIO_POSITION, * PKSAUDIO_POSITION;\n\ntypedef struct _DS3DVECTOR\n{\n  __MINGW_EXTENSION union\n  {\n    FLOAT x;\n    FLOAT dvX;\n  };\n  __MINGW_EXTENSION union\n  {\n    FLOAT y;\n    FLOAT dvY;\n  };\n  __MINGW_EXTENSION union\n  {\n    FLOAT z;\n    FLOAT dvZ;\n  };\n}DS3DVECTOR, * PDS3DVECTOR;\n\n # define STATIC_KSPROPSETID_DirectSound3DListener            \\\n  0x437b3414L, 0xd060, 0x11d0, 0x85, 0x83, 0x00, 0xc0, 0x4f, 0xd9, 0xba, 0xf3\nDEFINE_GUIDSTRUCT(\"437b3414-d060-11d0-8583-00c04fd9baf3\", KSPROPSETID_DirectSound3DListener);\n # define KSPROPSETID_DirectSound3DListener DEFINE_GUIDNAMED(KSPROPSETID_DirectSound3DListener)\n\ntypedef enum\n{\n  KSPROPERTY_DIRECTSOUND3DLISTENER_ALL,\n  KSPROPERTY_DIRECTSOUND3DLISTENER_POSITION,\n  KSPROPERTY_DIRECTSOUND3DLISTENER_VELOCITY,\n  KSPROPERTY_DIRECTSOUND3DLISTENER_ORIENTATION,\n  KSPROPERTY_DIRECTSOUND3DLISTENER_DISTANCEFACTOR,\n  KSPROPERTY_DIRECTSOUND3DLISTENER_ROLLOFFFACTOR,\n  KSPROPERTY_DIRECTSOUND3DLISTENER_DOPPLERFACTOR,\n  KSPROPERTY_DIRECTSOUND3DLISTENER_BATCH,\n  KSPROPERTY_DIRECTSOUND3DLISTENER_ALLOCATION\n}KSPROPERTY_DIRECTSOUND3DLISTENER;\n\ntypedef struct\n{\n  DS3DVECTOR Position;\n  DS3DVECTOR Velocity;\n  DS3DVECTOR OrientFront;\n  DS3DVECTOR OrientTop;\n  FLOAT DistanceFactor;\n  FLOAT RolloffFactor;\n  FLOAT DopplerFactor;\n}KSDS3D_LISTENER_ALL, * PKSDS3D_LISTENER_ALL;\n\ntypedef struct\n{\n  DS3DVECTOR Front;\n  DS3DVECTOR Top;\n}KSDS3D_LISTENER_ORIENTATION, * PKSDS3D_LISTENER_ORIENTATION;\n\n # define STATIC_KSPROPSETID_DirectSound3DBuffer              \\\n  0x437b3411L, 0xd060, 0x11d0, 0x85, 0x83, 0x00, 0xc0, 0x4f, 0xd9, 0xba, 0xf3\nDEFINE_GUIDSTRUCT(\"437b3411-d060-11d0-8583-00c04fd9baf3\", KSPROPSETID_DirectSound3DBuffer);\n # define KSPROPSETID_DirectSound3DBuffer DEFINE_GUIDNAMED(KSPROPSETID_DirectSound3DBuffer)\n\ntypedef enum\n{\n  KSPROPERTY_DIRECTSOUND3DBUFFER_ALL,\n  KSPROPERTY_DIRECTSOUND3DBUFFER_POSITION,\n  KSPROPERTY_DIRECTSOUND3DBUFFER_VELOCITY,\n  KSPROPERTY_DIRECTSOUND3DBUFFER_CONEANGLES,\n  KSPROPERTY_DIRECTSOUND3DBUFFER_CONEORIENTATION,\n  KSPROPERTY_DIRECTSOUND3DBUFFER_CONEOUTSIDEVOLUME,\n  KSPROPERTY_DIRECTSOUND3DBUFFER_MINDISTANCE,\n  KSPROPERTY_DIRECTSOUND3DBUFFER_MAXDISTANCE,\n  KSPROPERTY_DIRECTSOUND3DBUFFER_MODE\n}KSPROPERTY_DIRECTSOUND3DBUFFER;\n\ntypedef struct\n{\n  DS3DVECTOR Position;\n  DS3DVECTOR Velocity;\n  ULONG InsideConeAngle;\n  ULONG OutsideConeAngle;\n  DS3DVECTOR ConeOrientation;\n  LONG ConeOutsideVolume;\n  FLOAT MinDistance;\n  FLOAT MaxDistance;\n  ULONG Mode;\n}KSDS3D_BUFFER_ALL, * PKSDS3D_BUFFER_ALL;\n\ntypedef struct\n{\n  ULONG InsideConeAngle;\n  ULONG OutsideConeAngle;\n}KSDS3D_BUFFER_CONE_ANGLES, * PKSDS3D_BUFFER_CONE_ANGLES;\n\n # define KSAUDIO_STEREO_SPEAKER_GEOMETRY_HEADPHONE (-1)\n # define KSAUDIO_STEREO_SPEAKER_GEOMETRY_MIN 5\n # define KSAUDIO_STEREO_SPEAKER_GEOMETRY_NARROW 10\n # define KSAUDIO_STEREO_SPEAKER_GEOMETRY_WIDE 20\n # define KSAUDIO_STEREO_SPEAKER_GEOMETRY_MAX 180\n\n # define KSDSOUND_3D_MODE_NORMAL 0x00000000\n # define KSDSOUND_3D_MODE_HEADRELATIVE 0x00000001\n # define KSDSOUND_3D_MODE_DISABLE 0x00000002\n\n # define KSDSOUND_BUFFER_CTRL_HRTF_3D 0x40000000\n\ntypedef struct\n{\n  ULONG Size;\n  ULONG Enabled;\n  WINBOOL SwapChannels;\n  WINBOOL ZeroAzimuth;\n  WINBOOL CrossFadeOutput;\n  ULONG FilterSize;\n}KSDS3D_HRTF_PARAMS_MSG, * PKSDS3D_HRTF_PARAMS_MSG;\n\ntypedef enum\n{\n  FULL_FILTER,\n  LIGHT_FILTER,\n  KSDS3D_FILTER_QUALITY_COUNT\n}KSDS3D_HRTF_FILTER_QUALITY;\n\ntypedef struct\n{\n  ULONG Size;\n  KSDS3D_HRTF_FILTER_QUALITY Quality;\n  FLOAT SampleRate;\n  ULONG MaxFilterSize;\n  ULONG FilterTransientMuteLength;\n  ULONG FilterOverlapBufferLength;\n  ULONG OutputOverlapBufferLength;\n  ULONG Reserved;\n}KSDS3D_HRTF_INIT_MSG, * PKSDS3D_HRTF_INIT_MSG;\n\ntypedef enum\n{\n  FLOAT_COEFF,\n  SHORT_COEFF,\n  KSDS3D_COEFF_COUNT\n}KSDS3D_HRTF_COEFF_FORMAT;\n\ntypedef enum\n{\n  DIRECT_FORM,\n  CASCADE_FORM,\n  KSDS3D_FILTER_METHOD_COUNT\n}KSDS3D_HRTF_FILTER_METHOD;\n\ntypedef enum\n{\n  DS3D_HRTF_VERSION_1\n}KSDS3D_HRTF_FILTER_VERSION;\n\ntypedef struct\n{\n  KSDS3D_HRTF_FILTER_METHOD FilterMethod;\n  KSDS3D_HRTF_COEFF_FORMAT CoeffFormat;\n  KSDS3D_HRTF_FILTER_VERSION Version;\n  ULONG Reserved;\n}KSDS3D_HRTF_FILTER_FORMAT_MSG, * PKSDS3D_HRTF_FILTER_FORMAT_MSG;\n\n # define STATIC_KSPROPSETID_Hrtf3d                   \\\n  0xb66decb0L, 0xa083, 0x11d0, 0x85, 0x1e, 0x00, 0xc0, 0x4f, 0xd9, 0xba, 0xf3\nDEFINE_GUIDSTRUCT(\"b66decb0-a083-11d0-851e-00c04fd9baf3\", KSPROPSETID_Hrtf3d);\n # define KSPROPSETID_Hrtf3d DEFINE_GUIDNAMED(KSPROPSETID_Hrtf3d)\n\ntypedef enum\n{\n  KSPROPERTY_HRTF3D_PARAMS = 0,\n  KSPROPERTY_HRTF3D_INITIALIZE,\n  KSPROPERTY_HRTF3D_FILTER_FORMAT\n}KSPROPERTY_HRTF3D;\n\ntypedef struct\n{\n  LONG Channel;\n  FLOAT VolSmoothScale;\n  FLOAT TotalDryAttenuation;\n  FLOAT TotalWetAttenuation;\n  LONG SmoothFrequency;\n  LONG Delay;\n}KSDS3D_ITD_PARAMS, * PKSDS3D_ITD_PARAMS;\n\ntypedef struct\n{\n  ULONG Enabled;\n  KSDS3D_ITD_PARAMS LeftParams;\n  KSDS3D_ITD_PARAMS RightParams;\n  ULONG Reserved;\n}KSDS3D_ITD_PARAMS_MSG, * PKSDS3D_ITD_PARAMS_MSG;\n\n # define STATIC_KSPROPSETID_Itd3d                    \\\n  0x6429f090L, 0x9fd9, 0x11d0, 0xa7, 0x5b, 0x00, 0xa0, 0xc9, 0x03, 0x65, 0xe3\nDEFINE_GUIDSTRUCT(\"6429f090-9fd9-11d0-a75b-00a0c90365e3\", KSPROPSETID_Itd3d);\n # define KSPROPSETID_Itd3d DEFINE_GUIDNAMED(KSPROPSETID_Itd3d)\n\ntypedef enum\n{\n  KSPROPERTY_ITD3D_PARAMS = 0\n}KSPROPERTY_ITD3D;\n\ntypedef struct\n{\n  KSDATARANGE DataRange;\n  ULONG MaximumChannels;\n  ULONG MinimumBitsPerSample;\n  ULONG MaximumBitsPerSample;\n  ULONG MinimumSampleFrequency;\n  ULONG MaximumSampleFrequency;\n}KSDATARANGE_AUDIO, * PKSDATARANGE_AUDIO;\n\n # define STATIC_KSDATAFORMAT_SUBTYPE_RIFF                \\\n  0x4995DAEEL, 0x9EE6, 0x11D0, 0xA4, 0x0E, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96\nDEFINE_GUIDSTRUCT(\"4995DAEE-9EE6-11D0-A40E-00A0C9223196\", KSDATAFORMAT_SUBTYPE_RIFF);\n # define KSDATAFORMAT_SUBTYPE_RIFF DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_RIFF)\n\n # define STATIC_KSDATAFORMAT_SUBTYPE_RIFFWAVE                \\\n  0xe436eb8bL, 0x524f, 0x11ce, 0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70\nDEFINE_GUIDSTRUCT(\"e436eb8b-524f-11ce-9f53-0020af0ba770\", KSDATAFORMAT_SUBTYPE_RIFFWAVE);\n # define KSDATAFORMAT_SUBTYPE_RIFFWAVE DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_RIFFWAVE)\n\n # define STATIC_KSPROPSETID_Bibliographic                \\\n  0x07BA150EL, 0xE2B1, 0x11D0, 0xAC, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96\nDEFINE_GUIDSTRUCT(\"07BA150E-E2B1-11D0-AC17-00A0C9223196\", KSPROPSETID_Bibliographic);\n # define KSPROPSETID_Bibliographic DEFINE_GUIDNAMED(KSPROPSETID_Bibliographic)\n\n # define SEB_MK_FOURCC(a, b, c, d) ((a << 24) | (b << 16) | (c << 8) | (d << 0))\n\ntypedef enum\n{\n  KSPROPERTY_BIBLIOGRAPHIC_LEADER = SEB_MK_FOURCC('R', 'D', 'L', ' '),\n  KSPROPERTY_BIBLIOGRAPHIC_LCCN = SEB_MK_FOURCC('0', '1', '0', ' '),\n  KSPROPERTY_BIBLIOGRAPHIC_ISBN = SEB_MK_FOURCC('0', '2', '0', ' '),\n  KSPROPERTY_BIBLIOGRAPHIC_ISSN = SEB_MK_FOURCC('2', '2', '0', ' '),\n  KSPROPERTY_BIBLIOGRAPHIC_CATALOGINGSOURCE = SEB_MK_FOURCC('0', '4', '0', ' '),\n  KSPROPERTY_BIBLIOGRAPHIC_MAINPERSONALNAME = SEB_MK_FOURCC('0', '0', '1', ' '),\n  KSPROPERTY_BIBLIOGRAPHIC_MAINCORPORATEBODY = SEB_MK_FOURCC('0', '1', '1', ' '),\n  KSPROPERTY_BIBLIOGRAPHIC_MAINMEETINGNAME = SEB_MK_FOURCC('1', '1', '1', ' '),\n  KSPROPERTY_BIBLIOGRAPHIC_MAINUNIFORMTITLE = SEB_MK_FOURCC('0', '3', '1', ' '),\n  KSPROPERTY_BIBLIOGRAPHIC_UNIFORMTITLE = SEB_MK_FOURCC('0', '4', '2', ' '),\n  KSPROPERTY_BIBLIOGRAPHIC_TITLESTATEMENT = SEB_MK_FOURCC('5', '4', '2', ' '),\n  KSPROPERTY_BIBLIOGRAPHIC_VARYINGFORMTITLE = SEB_MK_FOURCC('6', '4', '2', ' '),\n  KSPROPERTY_BIBLIOGRAPHIC_PUBLICATION = SEB_MK_FOURCC('0', '6', '2', ' '),\n  KSPROPERTY_BIBLIOGRAPHIC_PHYSICALDESCRIPTION = SEB_MK_FOURCC('0', '0', '3', ' '),\n  KSPROPERTY_BIBLIOGRAPHIC_ADDEDENTRYTITLE = SEB_MK_FOURCC('0', '4', '4', ' '),\n  KSPROPERTY_BIBLIOGRAPHIC_SERIESSTATEMENT = SEB_MK_FOURCC('0', '9', '4', ' '),\n  KSPROPERTY_BIBLIOGRAPHIC_GENERALNOTE = SEB_MK_FOURCC('0', '0', '5', ' '),\n  KSPROPERTY_BIBLIOGRAPHIC_BIBLIOGRAPHYNOTE = SEB_MK_FOURCC('4', '0', '5', ' '),\n  KSPROPERTY_BIBLIOGRAPHIC_CONTENTSNOTE = SEB_MK_FOURCC('5', '0', '5', ' '),\n  KSPROPERTY_BIBLIOGRAPHIC_CREATIONCREDIT = SEB_MK_FOURCC('8', '0', '5', ' '),\n  KSPROPERTY_BIBLIOGRAPHIC_CITATION = SEB_MK_FOURCC('0', '1', '5', ' '),\n  KSPROPERTY_BIBLIOGRAPHIC_PARTICIPANT = SEB_MK_FOURCC('1', '1', '5', ' '),\n  KSPROPERTY_BIBLIOGRAPHIC_SUMMARY = SEB_MK_FOURCC('0', '2', '5', ' '),\n  KSPROPERTY_BIBLIOGRAPHIC_TARGETAUDIENCE = SEB_MK_FOURCC('1', '2', '5', ' '),\n  KSPROPERTY_BIBLIOGRAPHIC_ADDEDFORMAVAILABLE = SEB_MK_FOURCC('0', '3', '5', ' '),\n  KSPROPERTY_BIBLIOGRAPHIC_SYSTEMDETAILS = SEB_MK_FOURCC('8', '3', '5', ' '),\n  KSPROPERTY_BIBLIOGRAPHIC_AWARDS = SEB_MK_FOURCC('6', '8', '5', ' '),\n  KSPROPERTY_BIBLIOGRAPHIC_ADDEDENTRYPERSONALNAME = SEB_MK_FOURCC('0', '0', '6', ' '),\n  KSPROPERTY_BIBLIOGRAPHIC_ADDEDENTRYTOPICALTERM = SEB_MK_FOURCC('0', '5', '6', ' '),\n  KSPROPERTY_BIBLIOGRAPHIC_ADDEDENTRYGEOGRAPHIC = SEB_MK_FOURCC('1', '5', '6', ' '),\n  KSPROPERTY_BIBLIOGRAPHIC_INDEXTERMGENRE = SEB_MK_FOURCC('5', '5', '6', ' '),\n  KSPROPERTY_BIBLIOGRAPHIC_INDEXTERMCURRICULUM = SEB_MK_FOURCC('8', '5', '6', ' '),\n  KSPROPERTY_BIBLIOGRAPHIC_ADDEDENTRYUNIFORMTITLE = SEB_MK_FOURCC('0', '3', '7', ' '),\n  KSPROPERTY_BIBLIOGRAPHIC_ADDEDENTRYRELATED = SEB_MK_FOURCC('0', '4', '7', ' '),\n  KSPROPERTY_BIBLIOGRAPHIC_SERIESSTATEMENTPERSONALNAME = SEB_MK_FOURCC('0', '0', '8', ' '),\n  KSPROPERTY_BIBLIOGRAPHIC_SERIESSTATEMENTUNIFORMTITLE = SEB_MK_FOURCC('0', '3', '8', ' ')\n}KSPROPERTY_BIBLIOGRAPHIC;\n\n # undef SEB_MK_FOURCC\n\n # define STATIC_KSPROPSETID_TopologyNode                 \\\n  0x45FFAAA1L, 0x6E1B, 0x11D0, 0xBC, 0xF2, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00\nDEFINE_GUIDSTRUCT(\"45FFAAA1-6E1B-11D0-BCF2-444553540000\", KSPROPSETID_TopologyNode);\n # define KSPROPSETID_TopologyNode DEFINE_GUIDNAMED(KSPROPSETID_TopologyNode)\n\ntypedef enum\n{\n  KSPROPERTY_TOPOLOGYNODE_ENABLE = 1,\n  KSPROPERTY_TOPOLOGYNODE_RESET\n}KSPROPERTY_TOPOLOGYNODE;\n\n # define STATIC_KSPROPSETID_RtAudio                  \\\n  0xa855a48c, 0x2f78, 0x4729, 0x90, 0x51, 0x19, 0x68, 0x74, 0x6b, 0x9e, 0xef\nDEFINE_GUIDSTRUCT(\"A855A48C-2F78-4729-9051-1968746B9EEF\", KSPROPSETID_RtAudio);\n # define KSPROPSETID_RtAudio DEFINE_GUIDNAMED(KSPROPSETID_RtAudio)\n\ntypedef enum\n{\n  KSPROPERTY_RTAUDIO_GETPOSITIONFUNCTION\n}KSPROPERTY_RTAUDIO;\n\n # define STATIC_KSPROPSETID_DrmAudioStream               \\\n  0x2f2c8ddd, 0x4198, 0x4fac, 0xba, 0x29, 0x61, 0xbb, 0x5, 0xb7, 0xde, 0x6\nDEFINE_GUIDSTRUCT(\"2F2C8DDD-4198-4fac-BA29-61BB05B7DE06\", KSPROPSETID_DrmAudioStream);\n # define KSPROPSETID_DrmAudioStream DEFINE_GUIDNAMED(KSPROPSETID_DrmAudioStream)\n\ntypedef enum\n{\n  KSPROPERTY_DRMAUDIOSTREAM_CONTENTID\n}KSPROPERTY_DRMAUDIOSTREAM;\n\n # define STATIC_KSPROPSETID_Audio                    \\\n  0x45FFAAA0L, 0x6E1B, 0x11D0, 0xBC, 0xF2, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00\nDEFINE_GUIDSTRUCT(\"45FFAAA0-6E1B-11D0-BCF2-444553540000\", KSPROPSETID_Audio);\n # define KSPROPSETID_Audio DEFINE_GUIDNAMED(KSPROPSETID_Audio)\n\ntypedef enum\n{\n  KSPROPERTY_AUDIO_LATENCY = 1,\n  KSPROPERTY_AUDIO_COPY_PROTECTION,\n  KSPROPERTY_AUDIO_CHANNEL_CONFIG,\n  KSPROPERTY_AUDIO_VOLUMELEVEL,\n  KSPROPERTY_AUDIO_POSITION,\n  KSPROPERTY_AUDIO_DYNAMIC_RANGE,\n  KSPROPERTY_AUDIO_QUALITY,\n  KSPROPERTY_AUDIO_SAMPLING_RATE,\n  KSPROPERTY_AUDIO_DYNAMIC_SAMPLING_RATE,\n  KSPROPERTY_AUDIO_MIX_LEVEL_TABLE,\n  KSPROPERTY_AUDIO_MIX_LEVEL_CAPS,\n  KSPROPERTY_AUDIO_MUX_SOURCE,\n  KSPROPERTY_AUDIO_MUTE,\n  KSPROPERTY_AUDIO_BASS,\n  KSPROPERTY_AUDIO_MID,\n  KSPROPERTY_AUDIO_TREBLE,\n  KSPROPERTY_AUDIO_BASS_BOOST,\n  KSPROPERTY_AUDIO_EQ_LEVEL,\n  KSPROPERTY_AUDIO_NUM_EQ_BANDS,\n  KSPROPERTY_AUDIO_EQ_BANDS,\n  KSPROPERTY_AUDIO_AGC,\n  KSPROPERTY_AUDIO_DELAY,\n  KSPROPERTY_AUDIO_LOUDNESS,\n  KSPROPERTY_AUDIO_WIDE_MODE,\n  KSPROPERTY_AUDIO_WIDENESS,\n  KSPROPERTY_AUDIO_REVERB_LEVEL,\n  KSPROPERTY_AUDIO_CHORUS_LEVEL,\n  KSPROPERTY_AUDIO_DEV_SPECIFIC,\n  KSPROPERTY_AUDIO_DEMUX_DEST,\n  KSPROPERTY_AUDIO_STEREO_ENHANCE,\n  KSPROPERTY_AUDIO_MANUFACTURE_GUID,\n  KSPROPERTY_AUDIO_PRODUCT_GUID,\n  KSPROPERTY_AUDIO_CPU_RESOURCES,\n  KSPROPERTY_AUDIO_STEREO_SPEAKER_GEOMETRY,\n  KSPROPERTY_AUDIO_SURROUND_ENCODE,\n  KSPROPERTY_AUDIO_3D_INTERFACE,\n  KSPROPERTY_AUDIO_PEAKMETER,\n  KSPROPERTY_AUDIO_ALGORITHM_INSTANCE,\n  KSPROPERTY_AUDIO_FILTER_STATE,\n  KSPROPERTY_AUDIO_PREFERRED_STATUS\n}KSPROPERTY_AUDIO;\n\n # define KSAUDIO_QUALITY_WORST 0x0\n # define KSAUDIO_QUALITY_PC 0x1\n # define KSAUDIO_QUALITY_BASIC 0x2\n # define KSAUDIO_QUALITY_ADVANCED 0x3\n\n # define KSAUDIO_CPU_RESOURCES_NOT_HOST_CPU 0x00000000\n # define KSAUDIO_CPU_RESOURCES_HOST_CPU 0x7FFFFFFF\n\ntypedef struct\n{\n  WINBOOL fCopyrighted;\n  WINBOOL fOriginal;\n}KSAUDIO_COPY_PROTECTION, * PKSAUDIO_COPY_PROTECTION;\n\ntypedef struct\n{\n  LONG ActiveSpeakerPositions;\n}KSAUDIO_CHANNEL_CONFIG, * PKSAUDIO_CHANNEL_CONFIG;\n\n # define SPEAKER_FRONT_LEFT 0x1\n # define SPEAKER_FRONT_RIGHT 0x2\n # define SPEAKER_FRONT_CENTER 0x4\n # define SPEAKER_LOW_FREQUENCY 0x8\n # define SPEAKER_BACK_LEFT 0x10\n # define SPEAKER_BACK_RIGHT 0x20\n # define SPEAKER_FRONT_LEFT_OF_CENTER 0x40\n # define SPEAKER_FRONT_RIGHT_OF_CENTER 0x80\n # define SPEAKER_BACK_CENTER 0x100\n # define SPEAKER_SIDE_LEFT 0x200\n # define SPEAKER_SIDE_RIGHT 0x400\n # define SPEAKER_TOP_CENTER 0x800\n # define SPEAKER_TOP_FRONT_LEFT 0x1000\n # define SPEAKER_TOP_FRONT_CENTER 0x2000\n # define SPEAKER_TOP_FRONT_RIGHT 0x4000\n # define SPEAKER_TOP_BACK_LEFT 0x8000\n # define SPEAKER_TOP_BACK_CENTER 0x10000\n # define SPEAKER_TOP_BACK_RIGHT 0x20000\n\n # define SPEAKER_RESERVED 0x7FFC0000\n\n # define SPEAKER_ALL 0x80000000\n\n # define KSAUDIO_SPEAKER_DIRECTOUT 0\n # define KSAUDIO_SPEAKER_MONO (SPEAKER_FRONT_CENTER)\n # define KSAUDIO_SPEAKER_STEREO (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT)\n # define KSAUDIO_SPEAKER_QUAD (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT |     \\\n                                SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT)\n # define KSAUDIO_SPEAKER_SURROUND (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT |     \\\n                                    SPEAKER_FRONT_CENTER | SPEAKER_BACK_CENTER)\n # define KSAUDIO_SPEAKER_5POINT1 (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT |     \\\n                                   SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY |     \\\n                                   SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT)\n # define KSAUDIO_SPEAKER_7POINT1 (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT |     \\\n                                   SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY |     \\\n                                   SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT |       \\\n                                   SPEAKER_FRONT_LEFT_OF_CENTER | SPEAKER_FRONT_RIGHT_OF_CENTER)\n # define KSAUDIO_SPEAKER_5POINT1_SURROUND (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT |        \\\n                                            SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY |    \\\n                                            SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT)\n # define KSAUDIO_SPEAKER_7POINT1_SURROUND (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT |        \\\n                                            SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY |    \\\n                                            SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT |      \\\n                                            SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT)\n\n # define KSAUDIO_SPEAKER_5POINT1_BACK KSAUDIO_SPEAKER_5POINT1\n # define KSAUDIO_SPEAKER_7POINT1_WIDE KSAUDIO_SPEAKER_7POINT1\n\n # define KSAUDIO_SPEAKER_GROUND_FRONT_LEFT SPEAKER_FRONT_LEFT\n # define KSAUDIO_SPEAKER_GROUND_FRONT_CENTER SPEAKER_FRONT_CENTER\n # define KSAUDIO_SPEAKER_GROUND_FRONT_RIGHT SPEAKER_FRONT_RIGHT\n # define KSAUDIO_SPEAKER_GROUND_REAR_LEFT SPEAKER_BACK_LEFT\n # define KSAUDIO_SPEAKER_GROUND_REAR_RIGHT SPEAKER_BACK_RIGHT\n # define KSAUDIO_SPEAKER_TOP_MIDDLE SPEAKER_TOP_CENTER\n # define KSAUDIO_SPEAKER_SUPER_WOOFER SPEAKER_LOW_FREQUENCY\n\ntypedef struct\n{\n  ULONG QuietCompression;\n  ULONG LoudCompression;\n}KSAUDIO_DYNAMIC_RANGE, * PKSAUDIO_DYNAMIC_RANGE;\n\ntypedef struct\n{\n  WINBOOL Mute;\n  LONG Level;\n}KSAUDIO_MIXLEVEL, * PKSAUDIO_MIXLEVEL;\n\ntypedef struct\n{\n  WINBOOL Mute;\n  LONG Minimum;\n  LONG Maximum;\n  LONG Reset;\n}KSAUDIO_MIX_CAPS, * PKSAUDIO_MIX_CAPS;\n\ntypedef struct\n{\n  ULONG InputChannels;\n  ULONG OutputChannels;\n  KSAUDIO_MIX_CAPS Capabilities[1];\n}KSAUDIO_MIXCAP_TABLE, * PKSAUDIO_MIXCAP_TABLE;\n\ntypedef enum\n{\n  SE_TECH_NONE,\n  SE_TECH_ANALOG_DEVICES_PHAT,\n  SE_TECH_CREATIVE,\n  SE_TECH_NATIONAL_SEMI,\n  SE_TECH_YAMAHA_YMERSION,\n  SE_TECH_BBE,\n  SE_TECH_CRYSTAL_SEMI,\n  SE_TECH_QSOUND_QXPANDER,\n  SE_TECH_SPATIALIZER,\n  SE_TECH_SRS,\n  SE_TECH_PLATFORM_TECH,\n  SE_TECH_AKM,\n  SE_TECH_AUREAL,\n  SE_TECH_AZTECH,\n  SE_TECH_BINAURA,\n  SE_TECH_ESS_TECH,\n  SE_TECH_HARMAN_VMAX,\n  SE_TECH_NVIDEA,\n  SE_TECH_PHILIPS_INCREDIBLE,\n  SE_TECH_TEXAS_INST,\n  SE_TECH_VLSI_TECH\n}SE_TECHNIQUE;\n\ntypedef struct\n{\n  SE_TECHNIQUE Technique;\n  ULONG Center;\n  ULONG Depth;\n  ULONG Reserved;\n}KSAUDIO_STEREO_ENHANCE, * PKSAUDIO_STEREO_ENHANCE;\n\ntypedef enum\n{\n  KSPROPERTY_SYSAUDIO_NORMAL_DEFAULT = 0,\n  KSPROPERTY_SYSAUDIO_PLAYBACK_DEFAULT,\n  KSPROPERTY_SYSAUDIO_RECORD_DEFAULT,\n  KSPROPERTY_SYSAUDIO_MIDI_DEFAULT,\n  KSPROPERTY_SYSAUDIO_MIXER_DEFAULT\n}KSPROPERTY_SYSAUDIO_DEFAULT_TYPE;\n\ntypedef struct\n{\n  WINBOOL Enable;\n  KSPROPERTY_SYSAUDIO_DEFAULT_TYPE DeviceType;\n  ULONG Flags;\n  ULONG Reserved;\n}KSAUDIO_PREFERRED_STATUS, * PKSAUDIO_PREFERRED_STATUS;\n\n # define STATIC_KSNODETYPE_DAC                       \\\n  0x507AE360L, 0xC554, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1\nDEFINE_GUIDSTRUCT(\"507AE360-C554-11D0-8A2B-00A0C9255AC1\", KSNODETYPE_DAC);\n # define KSNODETYPE_DAC DEFINE_GUIDNAMED(KSNODETYPE_DAC)\n\n # define STATIC_KSNODETYPE_ADC                       \\\n  0x4D837FE0L, 0xC555, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1\nDEFINE_GUIDSTRUCT(\"4D837FE0-C555-11D0-8A2B-00A0C9255AC1\", KSNODETYPE_ADC);\n # define KSNODETYPE_ADC DEFINE_GUIDNAMED(KSNODETYPE_ADC)\n\n # define STATIC_KSNODETYPE_SRC                       \\\n  0x9DB7B9E0L, 0xC555, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1\nDEFINE_GUIDSTRUCT(\"9DB7B9E0-C555-11D0-8A2B-00A0C9255AC1\", KSNODETYPE_SRC);\n # define KSNODETYPE_SRC DEFINE_GUIDNAMED(KSNODETYPE_SRC)\n\n # define STATIC_KSNODETYPE_SUPERMIX                  \\\n  0xE573ADC0L, 0xC555, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1\nDEFINE_GUIDSTRUCT(\"E573ADC0-C555-11D0-8A2B-00A0C9255AC1\", KSNODETYPE_SUPERMIX);\n # define KSNODETYPE_SUPERMIX DEFINE_GUIDNAMED(KSNODETYPE_SUPERMIX)\n\n # define STATIC_KSNODETYPE_MUX                       \\\n  0x2CEAF780L, 0xC556, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1\nDEFINE_GUIDSTRUCT(\"2CEAF780-C556-11D0-8A2B-00A0C9255AC1\", KSNODETYPE_MUX);\n # define KSNODETYPE_MUX DEFINE_GUIDNAMED(KSNODETYPE_MUX)\n\n # define STATIC_KSNODETYPE_DEMUX                     \\\n  0xC0EB67D4L, 0xE807, 0x11D0, 0x95, 0x8A, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3\nDEFINE_GUIDSTRUCT(\"C0EB67D4-E807-11D0-958A-00C04FB925D3\", KSNODETYPE_DEMUX);\n # define KSNODETYPE_DEMUX DEFINE_GUIDNAMED(KSNODETYPE_DEMUX)\n\n # define STATIC_KSNODETYPE_SUM                       \\\n  0xDA441A60L, 0xC556, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1\nDEFINE_GUIDSTRUCT(\"DA441A60-C556-11D0-8A2B-00A0C9255AC1\", KSNODETYPE_SUM);\n # define KSNODETYPE_SUM DEFINE_GUIDNAMED(KSNODETYPE_SUM)\n\n # define STATIC_KSNODETYPE_MUTE                      \\\n  0x02B223C0L, 0xC557, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1\nDEFINE_GUIDSTRUCT(\"02B223C0-C557-11D0-8A2B-00A0C9255AC1\", KSNODETYPE_MUTE);\n # define KSNODETYPE_MUTE DEFINE_GUIDNAMED(KSNODETYPE_MUTE)\n\n # define STATIC_KSNODETYPE_VOLUME                    \\\n  0x3A5ACC00L, 0xC557, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1\nDEFINE_GUIDSTRUCT(\"3A5ACC00-C557-11D0-8A2B-00A0C9255AC1\", KSNODETYPE_VOLUME);\n # define KSNODETYPE_VOLUME DEFINE_GUIDNAMED(KSNODETYPE_VOLUME)\n\n # define STATIC_KSNODETYPE_TONE                      \\\n  0x7607E580L, 0xC557, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1\nDEFINE_GUIDSTRUCT(\"7607E580-C557-11D0-8A2B-00A0C9255AC1\", KSNODETYPE_TONE);\n # define KSNODETYPE_TONE DEFINE_GUIDNAMED(KSNODETYPE_TONE)\n\n # define STATIC_KSNODETYPE_EQUALIZER                 \\\n  0x9D41B4A0L, 0xC557, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1\nDEFINE_GUIDSTRUCT(\"9D41B4A0-C557-11D0-8A2B-00A0C9255AC1\", KSNODETYPE_EQUALIZER);\n # define KSNODETYPE_EQUALIZER DEFINE_GUIDNAMED(KSNODETYPE_EQUALIZER)\n\n # define STATIC_KSNODETYPE_AGC                       \\\n  0xE88C9BA0L, 0xC557, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1\nDEFINE_GUIDSTRUCT(\"E88C9BA0-C557-11D0-8A2B-00A0C9255AC1\", KSNODETYPE_AGC);\n # define KSNODETYPE_AGC DEFINE_GUIDNAMED(KSNODETYPE_AGC)\n\n # define STATIC_KSNODETYPE_NOISE_SUPPRESS                \\\n  0xe07f903f, 0x62fd, 0x4e60, 0x8c, 0xdd, 0xde, 0xa7, 0x23, 0x66, 0x65, 0xb5\nDEFINE_GUIDSTRUCT(\"E07F903F-62FD-4e60-8CDD-DEA7236665B5\", KSNODETYPE_NOISE_SUPPRESS);\n # define KSNODETYPE_NOISE_SUPPRESS DEFINE_GUIDNAMED(KSNODETYPE_NOISE_SUPPRESS)\n\n # define STATIC_KSNODETYPE_DELAY                     \\\n  0x144981E0L, 0xC558, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1\nDEFINE_GUIDSTRUCT(\"144981E0-C558-11D0-8A2B-00A0C9255AC1\", KSNODETYPE_DELAY);\n # define KSNODETYPE_DELAY DEFINE_GUIDNAMED(KSNODETYPE_DELAY)\n\n # define STATIC_KSNODETYPE_LOUDNESS                  \\\n  0x41887440L, 0xC558, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1\nDEFINE_GUIDSTRUCT(\"41887440-C558-11D0-8A2B-00A0C9255AC1\", KSNODETYPE_LOUDNESS);\n # define KSNODETYPE_LOUDNESS DEFINE_GUIDNAMED(KSNODETYPE_LOUDNESS)\n\n # define STATIC_KSNODETYPE_PROLOGIC_DECODER              \\\n  0x831C2C80L, 0xC558, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1\nDEFINE_GUIDSTRUCT(\"831C2C80-C558-11D0-8A2B-00A0C9255AC1\", KSNODETYPE_PROLOGIC_DECODER);\n # define KSNODETYPE_PROLOGIC_DECODER DEFINE_GUIDNAMED(KSNODETYPE_PROLOGIC_DECODER)\n\n # define STATIC_KSNODETYPE_STEREO_WIDE                   \\\n  0xA9E69800L, 0xC558, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1\nDEFINE_GUIDSTRUCT(\"A9E69800-C558-11D0-8A2B-00A0C9255AC1\", KSNODETYPE_STEREO_WIDE);\n # define KSNODETYPE_STEREO_WIDE DEFINE_GUIDNAMED(KSNODETYPE_STEREO_WIDE)\n\n # define STATIC_KSNODETYPE_STEREO_ENHANCE                \\\n  0xAF6878ACL, 0xE83F, 0x11D0, 0x95, 0x8A, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3\nDEFINE_GUIDSTRUCT(\"AF6878AC-E83F-11D0-958A-00C04FB925D3\", KSNODETYPE_STEREO_ENHANCE);\n # define KSNODETYPE_STEREO_ENHANCE DEFINE_GUIDNAMED(KSNODETYPE_STEREO_ENHANCE)\n\n # define STATIC_KSNODETYPE_REVERB                    \\\n  0xEF0328E0L, 0xC558, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1\nDEFINE_GUIDSTRUCT(\"EF0328E0-C558-11D0-8A2B-00A0C9255AC1\", KSNODETYPE_REVERB);\n # define KSNODETYPE_REVERB DEFINE_GUIDNAMED(KSNODETYPE_REVERB)\n\n # define STATIC_KSNODETYPE_CHORUS                    \\\n  0x20173F20L, 0xC559, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1\nDEFINE_GUIDSTRUCT(\"20173F20-C559-11D0-8A2B-00A0C9255AC1\", KSNODETYPE_CHORUS);\n # define KSNODETYPE_CHORUS DEFINE_GUIDNAMED(KSNODETYPE_CHORUS)\n\n # define STATIC_KSNODETYPE_3D_EFFECTS                    \\\n  0x55515860L, 0xC559, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1\nDEFINE_GUIDSTRUCT(\"55515860-C559-11D0-8A2B-00A0C9255AC1\", KSNODETYPE_3D_EFFECTS);\n # define KSNODETYPE_3D_EFFECTS DEFINE_GUIDNAMED(KSNODETYPE_3D_EFFECTS)\n\n # define STATIC_KSNODETYPE_ACOUSTIC_ECHO_CANCEL STATIC_KSCATEGORY_ACOUSTIC_ECHO_CANCEL\n # define KSNODETYPE_ACOUSTIC_ECHO_CANCEL KSCATEGORY_ACOUSTIC_ECHO_CANCEL\n\n # define STATIC_KSALGORITHMINSTANCE_SYSTEM_ACOUSTIC_ECHO_CANCEL      \\\n  0x1c22c56dL, 0x9879, 0x4f5b, 0xa3, 0x89, 0x27, 0x99, 0x6d, 0xdc, 0x28, 0x10\nDEFINE_GUIDSTRUCT(\"1C22C56D-9879-4f5b-A389-27996DDC2810\", KSALGORITHMINSTANCE_SYSTEM_ACOUSTIC_ECHO_CANCEL);\n # define KSALGORITHMINSTANCE_SYSTEM_ACOUSTIC_ECHO_CANCEL DEFINE_GUIDNAMED(KSALGORITHMINSTANCE_SYSTEM_ACOUSTIC_ECHO_CANCEL)\n\n # define STATIC_KSALGORITHMINSTANCE_SYSTEM_NOISE_SUPPRESS        \\\n  0x5ab0882eL, 0x7274, 0x4516, 0x87, 0x7d, 0x4e, 0xee, 0x99, 0xba, 0x4f, 0xd0\nDEFINE_GUIDSTRUCT(\"5AB0882E-7274-4516-877D-4EEE99BA4FD0\", KSALGORITHMINSTANCE_SYSTEM_NOISE_SUPPRESS);\n # define KSALGORITHMINSTANCE_SYSTEM_NOISE_SUPPRESS DEFINE_GUIDNAMED(KSALGORITHMINSTANCE_SYSTEM_NOISE_SUPPRESS)\n\n # define STATIC_KSALGORITHMINSTANCE_SYSTEM_AGC               \\\n  0x950e55b9L, 0x877c, 0x4c67, 0xbe, 0x8, 0xe4, 0x7b, 0x56, 0x11, 0x13, 0xa\nDEFINE_GUIDSTRUCT(\"950E55B9-877C-4c67-BE08-E47B5611130A\", KSALGORITHMINSTANCE_SYSTEM_AGC);\n # define KSALGORITHMINSTANCE_SYSTEM_AGC DEFINE_GUIDNAMED(KSALGORITHMINSTANCE_SYSTEM_AGC)\n\n # define STATIC_KSALGORITHMINSTANCE_SYSTEM_MICROPHONE_ARRAY_PROCESSOR    \\\n  0xB6F5A0A0L, 0x9E61, 0x4F8C, 0x91, 0xE3, 0x76, 0xCF, 0xF, 0x3C, 0x47, 0x1F\nDEFINE_GUIDSTRUCT(\"B6F5A0A0-9E61-4f8c-91E3-76CF0F3C471F\", KSALGORITHMINSTANCE_SYSTEM_MICROPHONE_ARRAY_PROCESSOR);\n # define KSALGORITHMINSTANCE_SYSTEM_MICROPHONE_ARRAY_PROCESSOR DEFINE_GUIDNAMED(KSALGORITHMINSTANCE_SYSTEM_MICROPHONE_ARRAY_PROCESSOR)\n\n # define STATIC_KSNODETYPE_MICROPHONE_ARRAY_PROCESSOR STATIC_KSCATEGORY_MICROPHONE_ARRAY_PROCESSOR\n # define KSNODETYPE_MICROPHONE_ARRAY_PROCESSOR KSCATEGORY_MICROPHONE_ARRAY_PROCESSOR\n\n # define STATIC_KSNODETYPE_DEV_SPECIFIC                  \\\n  0x941C7AC0L, 0xC559, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1\nDEFINE_GUIDSTRUCT(\"941C7AC0-C559-11D0-8A2B-00A0C9255AC1\", KSNODETYPE_DEV_SPECIFIC);\n # define KSNODETYPE_DEV_SPECIFIC DEFINE_GUIDNAMED(KSNODETYPE_DEV_SPECIFIC)\n\n # define STATIC_KSNODETYPE_PROLOGIC_ENCODER              \\\n  0x8074C5B2L, 0x3C66, 0x11D2, 0xB4, 0x5A, 0x30, 0x78, 0x30, 0x2C, 0x20, 0x30\nDEFINE_GUIDSTRUCT(\"8074C5B2-3C66-11D2-B45A-3078302C2030\", KSNODETYPE_PROLOGIC_ENCODER);\n # define KSNODETYPE_PROLOGIC_ENCODER DEFINE_GUIDNAMED(KSNODETYPE_PROLOGIC_ENCODER)\n # define KSNODETYPE_SURROUND_ENCODER KSNODETYPE_PROLOGIC_ENCODER\n\n # define STATIC_KSNODETYPE_PEAKMETER                 \\\n  0xa085651eL, 0x5f0d, 0x4b36, 0xa8, 0x69, 0xd1, 0x95, 0xd6, 0xab, 0x4b, 0x9e\nDEFINE_GUIDSTRUCT(\"A085651E-5F0D-4b36-A869-D195D6AB4B9E\", KSNODETYPE_PEAKMETER);\n # define KSNODETYPE_PEAKMETER DEFINE_GUIDNAMED(KSNODETYPE_PEAKMETER)\n\n # define STATIC_KSAUDFNAME_BASS                      \\\n  0x185FEDE0L, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3\nDEFINE_GUIDSTRUCT(\"185FEDE0-9905-11D1-95A9-00C04FB925D3\", KSAUDFNAME_BASS);\n # define KSAUDFNAME_BASS DEFINE_GUIDNAMED(KSAUDFNAME_BASS)\n\n # define STATIC_KSAUDFNAME_TREBLE                    \\\n  0x185FEDE1L, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3\nDEFINE_GUIDSTRUCT(\"185FEDE1-9905-11D1-95A9-00C04FB925D3\", KSAUDFNAME_TREBLE);\n # define KSAUDFNAME_TREBLE DEFINE_GUIDNAMED(KSAUDFNAME_TREBLE)\n\n # define STATIC_KSAUDFNAME_3D_STEREO                 \\\n  0x185FEDE2L, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3\nDEFINE_GUIDSTRUCT(\"185FEDE2-9905-11D1-95A9-00C04FB925D3\", KSAUDFNAME_3D_STEREO);\n # define KSAUDFNAME_3D_STEREO DEFINE_GUIDNAMED(KSAUDFNAME_3D_STEREO)\n\n # define STATIC_KSAUDFNAME_MASTER_VOLUME                 \\\n  0x185FEDE3L, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3\nDEFINE_GUIDSTRUCT(\"185FEDE3-9905-11D1-95A9-00C04FB925D3\", KSAUDFNAME_MASTER_VOLUME);\n # define KSAUDFNAME_MASTER_VOLUME DEFINE_GUIDNAMED(KSAUDFNAME_MASTER_VOLUME)\n\n # define STATIC_KSAUDFNAME_MASTER_MUTE                   \\\n  0x185FEDE4L, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3\nDEFINE_GUIDSTRUCT(\"185FEDE4-9905-11D1-95A9-00C04FB925D3\", KSAUDFNAME_MASTER_MUTE);\n # define KSAUDFNAME_MASTER_MUTE DEFINE_GUIDNAMED(KSAUDFNAME_MASTER_MUTE)\n\n # define STATIC_KSAUDFNAME_WAVE_VOLUME                   \\\n  0x185FEDE5L, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3\nDEFINE_GUIDSTRUCT(\"185FEDE5-9905-11D1-95A9-00C04FB925D3\", KSAUDFNAME_WAVE_VOLUME);\n # define KSAUDFNAME_WAVE_VOLUME DEFINE_GUIDNAMED(KSAUDFNAME_WAVE_VOLUME)\n\n # define STATIC_KSAUDFNAME_WAVE_MUTE                 \\\n  0x185FEDE6L, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3\nDEFINE_GUIDSTRUCT(\"185FEDE6-9905-11D1-95A9-00C04FB925D3\", KSAUDFNAME_WAVE_MUTE);\n # define KSAUDFNAME_WAVE_MUTE DEFINE_GUIDNAMED(KSAUDFNAME_WAVE_MUTE)\n\n # define STATIC_KSAUDFNAME_MIDI_VOLUME                   \\\n  0x185FEDE7L, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3\nDEFINE_GUIDSTRUCT(\"185FEDE7-9905-11D1-95A9-00C04FB925D3\", KSAUDFNAME_MIDI_VOLUME);\n # define KSAUDFNAME_MIDI_VOLUME DEFINE_GUIDNAMED(KSAUDFNAME_MIDI_VOLUME)\n\n # define STATIC_KSAUDFNAME_MIDI_MUTE                 \\\n  0x185FEDE8L, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3\nDEFINE_GUIDSTRUCT(\"185FEDE8-9905-11D1-95A9-00C04FB925D3\", KSAUDFNAME_MIDI_MUTE);\n # define KSAUDFNAME_MIDI_MUTE DEFINE_GUIDNAMED(KSAUDFNAME_MIDI_MUTE)\n\n # define STATIC_KSAUDFNAME_CD_VOLUME                 \\\n  0x185FEDE9L, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3\nDEFINE_GUIDSTRUCT(\"185FEDE9-9905-11D1-95A9-00C04FB925D3\", KSAUDFNAME_CD_VOLUME);\n # define KSAUDFNAME_CD_VOLUME DEFINE_GUIDNAMED(KSAUDFNAME_CD_VOLUME)\n\n # define STATIC_KSAUDFNAME_CD_MUTE                   \\\n  0x185FEDEAL, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3\nDEFINE_GUIDSTRUCT(\"185FEDEA-9905-11D1-95A9-00C04FB925D3\", KSAUDFNAME_CD_MUTE);\n # define KSAUDFNAME_CD_MUTE DEFINE_GUIDNAMED(KSAUDFNAME_CD_MUTE)\n\n # define STATIC_KSAUDFNAME_LINE_VOLUME                   \\\n  0x185FEDEBL, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3\nDEFINE_GUIDSTRUCT(\"185FEDEB-9905-11D1-95A9-00C04FB925D3\", KSAUDFNAME_LINE_VOLUME);\n # define KSAUDFNAME_LINE_VOLUME DEFINE_GUIDNAMED(KSAUDFNAME_LINE_VOLUME)\n\n # define STATIC_KSAUDFNAME_LINE_MUTE                 \\\n  0x185FEDECL, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3\nDEFINE_GUIDSTRUCT(\"185FEDEC-9905-11D1-95A9-00C04FB925D3\", KSAUDFNAME_LINE_MUTE);\n # define KSAUDFNAME_LINE_MUTE DEFINE_GUIDNAMED(KSAUDFNAME_LINE_MUTE)\n\n # define STATIC_KSAUDFNAME_MIC_VOLUME                    \\\n  0x185FEDEDL, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3\nDEFINE_GUIDSTRUCT(\"185FEDED-9905-11D1-95A9-00C04FB925D3\", KSAUDFNAME_MIC_VOLUME);\n # define KSAUDFNAME_MIC_VOLUME DEFINE_GUIDNAMED(KSAUDFNAME_MIC_VOLUME)\n\n # define STATIC_KSAUDFNAME_MIC_MUTE                  \\\n  0x185FEDEEL, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3\nDEFINE_GUIDSTRUCT(\"185FEDEE-9905-11D1-95A9-00C04FB925D3\", KSAUDFNAME_MIC_MUTE);\n # define KSAUDFNAME_MIC_MUTE DEFINE_GUIDNAMED(KSAUDFNAME_MIC_MUTE)\n\n # define STATIC_KSAUDFNAME_RECORDING_SOURCE              \\\n  0x185FEDEFL, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3\nDEFINE_GUIDSTRUCT(\"185FEDEF-9905-11D1-95A9-00C04FB925D3\", KSAUDFNAME_RECORDING_SOURCE);\n # define KSAUDFNAME_RECORDING_SOURCE DEFINE_GUIDNAMED(KSAUDFNAME_RECORDING_SOURCE)\n\n # define STATIC_KSAUDFNAME_PC_SPEAKER_VOLUME             \\\n  0x185FEDF0L, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3\nDEFINE_GUIDSTRUCT(\"185FEDF0-9905-11D1-95A9-00C04FB925D3\", KSAUDFNAME_PC_SPEAKER_VOLUME);\n # define KSAUDFNAME_PC_SPEAKER_VOLUME DEFINE_GUIDNAMED(KSAUDFNAME_PC_SPEAKER_VOLUME)\n\n # define STATIC_KSAUDFNAME_PC_SPEAKER_MUTE               \\\n  0x185FEDF1L, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3\nDEFINE_GUIDSTRUCT(\"185FEDF1-9905-11D1-95A9-00C04FB925D3\", KSAUDFNAME_PC_SPEAKER_MUTE);\n # define KSAUDFNAME_PC_SPEAKER_MUTE DEFINE_GUIDNAMED(KSAUDFNAME_PC_SPEAKER_MUTE)\n\n # define STATIC_KSAUDFNAME_MIDI_IN_VOLUME                \\\n  0x185FEDF2L, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3\nDEFINE_GUIDSTRUCT(\"185FEDF2-9905-11D1-95A9-00C04FB925D3\", KSAUDFNAME_MIDI_IN_VOLUME);\n # define KSAUDFNAME_MIDI_IN_VOLUME DEFINE_GUIDNAMED(KSAUDFNAME_MIDI_IN_VOLUME)\n\n # define STATIC_KSAUDFNAME_CD_IN_VOLUME                  \\\n  0x185FEDF3L, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3\nDEFINE_GUIDSTRUCT(\"185FEDF3-9905-11D1-95A9-00C04FB925D3\", KSAUDFNAME_CD_IN_VOLUME);\n # define KSAUDFNAME_CD_IN_VOLUME DEFINE_GUIDNAMED(KSAUDFNAME_CD_IN_VOLUME)\n\n # define STATIC_KSAUDFNAME_LINE_IN_VOLUME                \\\n  0x185FEDF4L, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3\nDEFINE_GUIDSTRUCT(\"185FEDF4-9905-11D1-95A9-00C04FB925D3\", KSAUDFNAME_LINE_IN_VOLUME);\n # define KSAUDFNAME_LINE_IN_VOLUME DEFINE_GUIDNAMED(KSAUDFNAME_LINE_IN_VOLUME)\n\n # define STATIC_KSAUDFNAME_MIC_IN_VOLUME                 \\\n  0x185FEDF5L, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3\nDEFINE_GUIDSTRUCT(\"185FEDF5-9905-11D1-95A9-00C04FB925D3\", KSAUDFNAME_MIC_IN_VOLUME);\n # define KSAUDFNAME_MIC_IN_VOLUME DEFINE_GUIDNAMED(KSAUDFNAME_MIC_IN_VOLUME)\n\n # define STATIC_KSAUDFNAME_WAVE_IN_VOLUME                \\\n  0x185FEDF6L, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3\nDEFINE_GUIDSTRUCT(\"185FEDF6-9905-11D1-95A9-00C04FB925D3\", KSAUDFNAME_WAVE_IN_VOLUME);\n # define KSAUDFNAME_WAVE_IN_VOLUME DEFINE_GUIDNAMED(KSAUDFNAME_WAVE_IN_VOLUME)\n\n # define STATIC_KSAUDFNAME_VOLUME_CONTROL                \\\n  0x185FEDF7L, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3\nDEFINE_GUIDSTRUCT(\"185FEDF7-9905-11D1-95A9-00C04FB925D3\", KSAUDFNAME_VOLUME_CONTROL);\n # define KSAUDFNAME_VOLUME_CONTROL DEFINE_GUIDNAMED(KSAUDFNAME_VOLUME_CONTROL)\n\n # define STATIC_KSAUDFNAME_MIDI                      \\\n  0x185FEDF8L, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3\nDEFINE_GUIDSTRUCT(\"185FEDF8-9905-11D1-95A9-00C04FB925D3\", KSAUDFNAME_MIDI);\n # define KSAUDFNAME_MIDI DEFINE_GUIDNAMED(KSAUDFNAME_MIDI)\n\n # define STATIC_KSAUDFNAME_LINE_IN                   \\\n  0x185FEDF9L, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3\nDEFINE_GUIDSTRUCT(\"185FEDF9-9905-11D1-95A9-00C04FB925D3\", KSAUDFNAME_LINE_IN);\n # define KSAUDFNAME_LINE_IN DEFINE_GUIDNAMED(KSAUDFNAME_LINE_IN)\n\n # define STATIC_KSAUDFNAME_RECORDING_CONTROL             \\\n  0x185FEDFAL, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3\nDEFINE_GUIDSTRUCT(\"185FEDFA-9905-11D1-95A9-00C04FB925D3\", KSAUDFNAME_RECORDING_CONTROL);\n # define KSAUDFNAME_RECORDING_CONTROL DEFINE_GUIDNAMED(KSAUDFNAME_RECORDING_CONTROL)\n\n # define STATIC_KSAUDFNAME_CD_AUDIO                  \\\n  0x185FEDFBL, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3\nDEFINE_GUIDSTRUCT(\"185FEDFB-9905-11D1-95A9-00C04FB925D3\", KSAUDFNAME_CD_AUDIO);\n # define KSAUDFNAME_CD_AUDIO DEFINE_GUIDNAMED(KSAUDFNAME_CD_AUDIO)\n\n # define STATIC_KSAUDFNAME_AUX_VOLUME                    \\\n  0x185FEDFCL, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3\nDEFINE_GUIDSTRUCT(\"185FEDFC-9905-11D1-95A9-00C04FB925D3\", KSAUDFNAME_AUX_VOLUME);\n # define KSAUDFNAME_AUX_VOLUME DEFINE_GUIDNAMED(KSAUDFNAME_AUX_VOLUME)\n\n # define STATIC_KSAUDFNAME_AUX_MUTE                  \\\n  0x185FEDFDL, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3\nDEFINE_GUIDSTRUCT(\"185FEDFD-9905-11D1-95A9-00C04FB925D3\", KSAUDFNAME_AUX_MUTE);\n # define KSAUDFNAME_AUX_MUTE DEFINE_GUIDNAMED(KSAUDFNAME_AUX_MUTE)\n\n # define STATIC_KSAUDFNAME_AUX                       \\\n  0x185FEDFEL, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3\nDEFINE_GUIDSTRUCT(\"185FEDFE-9905-11D1-95A9-00C04FB925D3\", KSAUDFNAME_AUX);\n # define KSAUDFNAME_AUX DEFINE_GUIDNAMED(KSAUDFNAME_AUX)\n\n # define STATIC_KSAUDFNAME_PC_SPEAKER                    \\\n  0x185FEDFFL, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3\nDEFINE_GUIDSTRUCT(\"185FEDFF-9905-11D1-95A9-00C04FB925D3\", KSAUDFNAME_PC_SPEAKER);\n # define KSAUDFNAME_PC_SPEAKER DEFINE_GUIDNAMED(KSAUDFNAME_PC_SPEAKER)\n\n # define STATIC_KSAUDFNAME_WAVE_OUT_MIX                  \\\n  0x185FEE00L, 0x9905, 0x11D1, 0x95, 0xA9, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3\nDEFINE_GUIDSTRUCT(\"185FEE00-9905-11D1-95A9-00C04FB925D3\", KSAUDFNAME_WAVE_OUT_MIX);\n # define KSAUDFNAME_WAVE_OUT_MIX DEFINE_GUIDNAMED(KSAUDFNAME_WAVE_OUT_MIX)\n\n # define STATIC_KSAUDFNAME_MONO_OUT                  \\\n  0xf9b41dc3L, 0x96e2, 0x11d2, 0xac, 0x4c, 0x0, 0xc0, 0x4f, 0x8e, 0xfb, 0x68\nDEFINE_GUIDSTRUCT(\"F9B41DC3-96E2-11d2-AC4C-00C04F8EFB68\", KSAUDFNAME_MONO_OUT);\n # define KSAUDFNAME_MONO_OUT DEFINE_GUIDNAMED(KSAUDFNAME_MONO_OUT)\n\n # define STATIC_KSAUDFNAME_STEREO_MIX                    \\\n  0xdff077L, 0x96e3, 0x11d2, 0xac, 0x4c, 0x0, 0xc0, 0x4f, 0x8e, 0xfb, 0x68\nDEFINE_GUIDSTRUCT(\"00DFF077-96E3-11d2-AC4C-00C04F8EFB68\", KSAUDFNAME_STEREO_MIX);\n # define KSAUDFNAME_STEREO_MIX DEFINE_GUIDNAMED(KSAUDFNAME_STEREO_MIX)\n\n # define STATIC_KSAUDFNAME_MONO_MIX                  \\\n  0xdff078L, 0x96e3, 0x11d2, 0xac, 0x4c, 0x0, 0xc0, 0x4f, 0x8e, 0xfb, 0x68\nDEFINE_GUIDSTRUCT(\"00DFF078-96E3-11d2-AC4C-00C04F8EFB68\", KSAUDFNAME_MONO_MIX);\n # define KSAUDFNAME_MONO_MIX DEFINE_GUIDNAMED(KSAUDFNAME_MONO_MIX)\n\n # define STATIC_KSAUDFNAME_MONO_OUT_VOLUME               \\\n  0x1ad247ebL, 0x96e3, 0x11d2, 0xac, 0x4c, 0x0, 0xc0, 0x4f, 0x8e, 0xfb, 0x68\nDEFINE_GUIDSTRUCT(\"1AD247EB-96E3-11d2-AC4C-00C04F8EFB68\", KSAUDFNAME_MONO_OUT_VOLUME);\n # define KSAUDFNAME_MONO_OUT_VOLUME DEFINE_GUIDNAMED(KSAUDFNAME_MONO_OUT_VOLUME)\n\n # define STATIC_KSAUDFNAME_MONO_OUT_MUTE                 \\\n  0x1ad247ecL, 0x96e3, 0x11d2, 0xac, 0x4c, 0x0, 0xc0, 0x4f, 0x8e, 0xfb, 0x68\nDEFINE_GUIDSTRUCT(\"1AD247EC-96E3-11d2-AC4C-00C04F8EFB68\", KSAUDFNAME_MONO_OUT_MUTE);\n # define KSAUDFNAME_MONO_OUT_MUTE DEFINE_GUIDNAMED(KSAUDFNAME_MONO_OUT_MUTE)\n\n # define STATIC_KSAUDFNAME_STEREO_MIX_VOLUME             \\\n  0x1ad247edL, 0x96e3, 0x11d2, 0xac, 0x4c, 0x0, 0xc0, 0x4f, 0x8e, 0xfb, 0x68\nDEFINE_GUIDSTRUCT(\"1AD247ED-96E3-11d2-AC4C-00C04F8EFB68\", KSAUDFNAME_STEREO_MIX_VOLUME);\n # define KSAUDFNAME_STEREO_MIX_VOLUME DEFINE_GUIDNAMED(KSAUDFNAME_STEREO_MIX_VOLUME)\n\n # define STATIC_KSAUDFNAME_STEREO_MIX_MUTE               \\\n  0x22b0eafdL, 0x96e3, 0x11d2, 0xac, 0x4c, 0x0, 0xc0, 0x4f, 0x8e, 0xfb, 0x68\nDEFINE_GUIDSTRUCT(\"22B0EAFD-96E3-11d2-AC4C-00C04F8EFB68\", KSAUDFNAME_STEREO_MIX_MUTE);\n # define KSAUDFNAME_STEREO_MIX_MUTE DEFINE_GUIDNAMED(KSAUDFNAME_STEREO_MIX_MUTE)\n\n # define STATIC_KSAUDFNAME_MONO_MIX_VOLUME               \\\n  0x22b0eafeL, 0x96e3, 0x11d2, 0xac, 0x4c, 0x0, 0xc0, 0x4f, 0x8e, 0xfb, 0x68\nDEFINE_GUIDSTRUCT(\"22B0EAFE-96E3-11d2-AC4C-00C04F8EFB68\", KSAUDFNAME_MONO_MIX_VOLUME);\n # define KSAUDFNAME_MONO_MIX_VOLUME DEFINE_GUIDNAMED(KSAUDFNAME_MONO_MIX_VOLUME)\n\n # define STATIC_KSAUDFNAME_MONO_MIX_MUTE                 \\\n  0x2bc31d69L, 0x96e3, 0x11d2, 0xac, 0x4c, 0x0, 0xc0, 0x4f, 0x8e, 0xfb, 0x68\nDEFINE_GUIDSTRUCT(\"2BC31D69-96E3-11d2-AC4C-00C04F8EFB68\", KSAUDFNAME_MONO_MIX_MUTE);\n # define KSAUDFNAME_MONO_MIX_MUTE DEFINE_GUIDNAMED(KSAUDFNAME_MONO_MIX_MUTE)\n\n # define STATIC_KSAUDFNAME_MICROPHONE_BOOST              \\\n  0x2bc31d6aL, 0x96e3, 0x11d2, 0xac, 0x4c, 0x0, 0xc0, 0x4f, 0x8e, 0xfb, 0x68\nDEFINE_GUIDSTRUCT(\"2BC31D6A-96E3-11d2-AC4C-00C04F8EFB68\", KSAUDFNAME_MICROPHONE_BOOST);\n # define KSAUDFNAME_MICROPHONE_BOOST DEFINE_GUIDNAMED(KSAUDFNAME_MICROPHONE_BOOST)\n\n # define STATIC_KSAUDFNAME_ALTERNATE_MICROPHONE              \\\n  0x2bc31d6bL, 0x96e3, 0x11d2, 0xac, 0x4c, 0x0, 0xc0, 0x4f, 0x8e, 0xfb, 0x68\nDEFINE_GUIDSTRUCT(\"2BC31D6B-96E3-11d2-AC4C-00C04F8EFB68\", KSAUDFNAME_ALTERNATE_MICROPHONE);\n # define KSAUDFNAME_ALTERNATE_MICROPHONE DEFINE_GUIDNAMED(KSAUDFNAME_ALTERNATE_MICROPHONE)\n\n # define STATIC_KSAUDFNAME_3D_DEPTH                  \\\n  0x63ff5747L, 0x991f, 0x11d2, 0xac, 0x4d, 0x0, 0xc0, 0x4f, 0x8e, 0xfb, 0x68\nDEFINE_GUIDSTRUCT(\"63FF5747-991F-11d2-AC4D-00C04F8EFB68\", KSAUDFNAME_3D_DEPTH);\n # define KSAUDFNAME_3D_DEPTH DEFINE_GUIDNAMED(KSAUDFNAME_3D_DEPTH)\n\n # define STATIC_KSAUDFNAME_3D_CENTER                 \\\n  0x9f0670b4L, 0x991f, 0x11d2, 0xac, 0x4d, 0x0, 0xc0, 0x4f, 0x8e, 0xfb, 0x68\nDEFINE_GUIDSTRUCT(\"9F0670B4-991F-11d2-AC4D-00C04F8EFB68\", KSAUDFNAME_3D_CENTER);\n # define KSAUDFNAME_3D_CENTER DEFINE_GUIDNAMED(KSAUDFNAME_3D_CENTER)\n\n # define STATIC_KSAUDFNAME_VIDEO_VOLUME                  \\\n  0x9b46e708L, 0x992a, 0x11d2, 0xac, 0x4d, 0x0, 0xc0, 0x4f, 0x8e, 0xfb, 0x68\nDEFINE_GUIDSTRUCT(\"9B46E708-992A-11d2-AC4D-00C04F8EFB68\", KSAUDFNAME_VIDEO_VOLUME);\n # define KSAUDFNAME_VIDEO_VOLUME DEFINE_GUIDNAMED(KSAUDFNAME_VIDEO_VOLUME)\n\n # define STATIC_KSAUDFNAME_VIDEO_MUTE                    \\\n  0x9b46e709L, 0x992a, 0x11d2, 0xac, 0x4d, 0x0, 0xc0, 0x4f, 0x8e, 0xfb, 0x68\nDEFINE_GUIDSTRUCT(\"9B46E709-992A-11d2-AC4D-00C04F8EFB68\", KSAUDFNAME_VIDEO_MUTE);\n # define KSAUDFNAME_VIDEO_MUTE DEFINE_GUIDNAMED(KSAUDFNAME_VIDEO_MUTE)\n\n # define STATIC_KSAUDFNAME_VIDEO                     \\\n  0x915daec4L, 0xa434, 0x11d2, 0xac, 0x52, 0x0, 0xc0, 0x4f, 0x8e, 0xfb, 0x68\nDEFINE_GUIDSTRUCT(\"915DAEC4-A434-11d2-AC52-00C04F8EFB68\", KSAUDFNAME_VIDEO);\n # define KSAUDFNAME_VIDEO DEFINE_GUIDNAMED(KSAUDFNAME_VIDEO)\n\n # define STATIC_KSAUDFNAME_PEAKMETER                 \\\n  0x57e24340L, 0xfc5b, 0x4612, 0xa5, 0x62, 0x72, 0xb1, 0x1a, 0x29, 0xdf, 0xae\nDEFINE_GUIDSTRUCT(\"57E24340-FC5B-4612-A562-72B11A29DFAE\", KSAUDFNAME_PEAKMETER);\n # define KSAUDFNAME_PEAKMETER DEFINE_GUIDNAMED(KSAUDFNAME_PEAKMETER)\n\n # define KSNODEPIN_STANDARD_IN 1\n # define KSNODEPIN_STANDARD_OUT 0\n\n # define KSNODEPIN_SUM_MUX_IN 1\n # define KSNODEPIN_SUM_MUX_OUT 0\n\n # define KSNODEPIN_DEMUX_IN 0\n # define KSNODEPIN_DEMUX_OUT 1\n\n # define KSNODEPIN_AEC_RENDER_IN 1\n # define KSNODEPIN_AEC_RENDER_OUT 0\n # define KSNODEPIN_AEC_CAPTURE_IN 2\n # define KSNODEPIN_AEC_CAPTURE_OUT 3\n\n # define STATIC_KSMETHODSETID_Wavetable                  \\\n  0xDCEF31EBL, 0xD907, 0x11D0, 0x95, 0x83, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3\nDEFINE_GUIDSTRUCT(\"DCEF31EB-D907-11D0-9583-00C04FB925D3\", KSMETHODSETID_Wavetable);\n # define KSMETHODSETID_Wavetable DEFINE_GUIDNAMED(KSMETHODSETID_Wavetable)\n\ntypedef enum\n{\n  KSMETHOD_WAVETABLE_WAVE_ALLOC,\n  KSMETHOD_WAVETABLE_WAVE_FREE,\n  KSMETHOD_WAVETABLE_WAVE_FIND,\n  KSMETHOD_WAVETABLE_WAVE_WRITE\n}KSMETHOD_WAVETABLE;\n\ntypedef struct\n{\n  KSIDENTIFIER Identifier;\n  ULONG Size;\n  WINBOOL Looped;\n  ULONG LoopPoint;\n  WINBOOL InROM;\n  KSDATAFORMAT Format;\n}KSWAVETABLE_WAVE_DESC, * PKSWAVETABLE_WAVE_DESC;\n\n # define STATIC_KSPROPSETID_Acoustic_Echo_Cancel             \\\n  0xd7a4af8bL, 0x3dc1, 0x4902, 0x91, 0xea, 0x8a, 0x15, 0xc9, 0x0e, 0x05, 0xb2\nDEFINE_GUIDSTRUCT(\"D7A4AF8B-3DC1-4902-91EA-8A15C90E05B2\", KSPROPSETID_Acoustic_Echo_Cancel);\n # define KSPROPSETID_Acoustic_Echo_Cancel DEFINE_GUIDNAMED(KSPROPSETID_Acoustic_Echo_Cancel)\n\ntypedef enum\n{\n  KSPROPERTY_AEC_NOISE_FILL_ENABLE = 0,\n  KSPROPERTY_AEC_STATUS,\n  KSPROPERTY_AEC_MODE\n}KSPROPERTY_AEC;\n\n # define AEC_STATUS_FD_HISTORY_UNINITIALIZED 0x0\n # define AEC_STATUS_FD_HISTORY_CONTINUOUSLY_CONVERGED 0x1\n # define AEC_STATUS_FD_HISTORY_PREVIOUSLY_DIVERGED 0x2\n # define AEC_STATUS_FD_CURRENTLY_CONVERGED 0x8\n\n # define AEC_MODE_PASS_THROUGH 0x0\n # define AEC_MODE_HALF_DUPLEX 0x1\n # define AEC_MODE_FULL_DUPLEX 0x2\n\n # define STATIC_KSPROPSETID_Wave                     \\\n  0x924e54b0L, 0x630f, 0x11cf, 0xad, 0xa7, 0x08, 0x00, 0x3e, 0x30, 0x49, 0x4a\nDEFINE_GUIDSTRUCT(\"924e54b0-630f-11cf-ada7-08003e30494a\", KSPROPSETID_Wave);\n # define KSPROPSETID_Wave DEFINE_GUIDNAMED(KSPROPSETID_Wave)\n\ntypedef enum\n{\n  KSPROPERTY_WAVE_COMPATIBLE_CAPABILITIES,\n  KSPROPERTY_WAVE_INPUT_CAPABILITIES,\n  KSPROPERTY_WAVE_OUTPUT_CAPABILITIES,\n  KSPROPERTY_WAVE_BUFFER,\n  KSPROPERTY_WAVE_FREQUENCY,\n  KSPROPERTY_WAVE_VOLUME,\n  KSPROPERTY_WAVE_PAN\n}KSPROPERTY_WAVE;\n\ntypedef struct\n{\n  ULONG ulDeviceType;\n}KSWAVE_COMPATCAPS, * PKSWAVE_COMPATCAPS;\n\n # define KSWAVE_COMPATCAPS_INPUT 0x00000000\n # define KSWAVE_COMPATCAPS_OUTPUT 0x00000001\n\ntypedef struct\n{\n  ULONG MaximumChannelsPerConnection;\n  ULONG MinimumBitsPerSample;\n  ULONG MaximumBitsPerSample;\n  ULONG MinimumSampleFrequency;\n  ULONG MaximumSampleFrequency;\n  ULONG TotalConnections;\n  ULONG ActiveConnections;\n}KSWAVE_INPUT_CAPABILITIES, * PKSWAVE_INPUT_CAPABILITIES;\n\ntypedef struct\n{\n  ULONG MaximumChannelsPerConnection;\n  ULONG MinimumBitsPerSample;\n  ULONG MaximumBitsPerSample;\n  ULONG MinimumSampleFrequency;\n  ULONG MaximumSampleFrequency;\n  ULONG TotalConnections;\n  ULONG StaticConnections;\n  ULONG StreamingConnections;\n  ULONG ActiveConnections;\n  ULONG ActiveStaticConnections;\n  ULONG ActiveStreamingConnections;\n  ULONG Total3DConnections;\n  ULONG Static3DConnections;\n  ULONG Streaming3DConnections;\n  ULONG Active3DConnections;\n  ULONG ActiveStatic3DConnections;\n  ULONG ActiveStreaming3DConnections;\n  ULONG TotalSampleMemory;\n  ULONG FreeSampleMemory;\n  ULONG LargestFreeContiguousSampleMemory;\n}KSWAVE_OUTPUT_CAPABILITIES, * PKSWAVE_OUTPUT_CAPABILITIES;\n\ntypedef struct\n{\n  LONG LeftAttenuation;\n  LONG RightAttenuation;\n}KSWAVE_VOLUME, * PKSWAVE_VOLUME;\n\n # define KSWAVE_BUFFER_ATTRIBUTEF_LOOPING 0x00000001\n # define KSWAVE_BUFFER_ATTRIBUTEF_STATIC 0x00000002\n\ntypedef struct\n{\n  ULONG Attributes;\n  ULONG BufferSize;\n  PVOID BufferAddress;\n}KSWAVE_BUFFER, * PKSWAVE_BUFFER;\n\n # define STATIC_KSMUSIC_TECHNOLOGY_PORT                  \\\n  0x86C92E60L, 0x62E8, 0x11CF, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00\nDEFINE_GUIDSTRUCT(\"86C92E60-62E8-11CF-A5D6-28DB04C10000\", KSMUSIC_TECHNOLOGY_PORT);\n # define KSMUSIC_TECHNOLOGY_PORT DEFINE_GUIDNAMED(KSMUSIC_TECHNOLOGY_PORT)\n\n # define STATIC_KSMUSIC_TECHNOLOGY_SQSYNTH               \\\n  0x0ECF4380L, 0x62E9, 0x11CF, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00\nDEFINE_GUIDSTRUCT(\"0ECF4380-62E9-11CF-A5D6-28DB04C10000\", KSMUSIC_TECHNOLOGY_SQSYNTH);\n # define KSMUSIC_TECHNOLOGY_SQSYNTH DEFINE_GUIDNAMED(KSMUSIC_TECHNOLOGY_SQSYNTH)\n\n # define STATIC_KSMUSIC_TECHNOLOGY_FMSYNTH               \\\n  0x252C5C80L, 0x62E9, 0x11CF, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00\nDEFINE_GUIDSTRUCT(\"252C5C80-62E9-11CF-A5D6-28DB04C10000\", KSMUSIC_TECHNOLOGY_FMSYNTH);\n # define KSMUSIC_TECHNOLOGY_FMSYNTH DEFINE_GUIDNAMED(KSMUSIC_TECHNOLOGY_FMSYNTH)\n\n # define STATIC_KSMUSIC_TECHNOLOGY_WAVETABLE             \\\n  0x394EC7C0L, 0x62E9, 0x11CF, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00\nDEFINE_GUIDSTRUCT(\"394EC7C0-62E9-11CF-A5D6-28DB04C10000\", KSMUSIC_TECHNOLOGY_WAVETABLE);\n # define KSMUSIC_TECHNOLOGY_WAVETABLE DEFINE_GUIDNAMED(KSMUSIC_TECHNOLOGY_WAVETABLE)\n\n # define STATIC_KSMUSIC_TECHNOLOGY_SWSYNTH               \\\n  0x37407736L, 0x3620, 0x11D1, 0x85, 0xD3, 0x00, 0x00, 0xF8, 0x75, 0x43, 0x80\nDEFINE_GUIDSTRUCT(\"37407736-3620-11D1-85D3-0000F8754380\", KSMUSIC_TECHNOLOGY_SWSYNTH);\n # define KSMUSIC_TECHNOLOGY_SWSYNTH DEFINE_GUIDNAMED(KSMUSIC_TECHNOLOGY_SWSYNTH)\n\n # define STATIC_KSPROPSETID_WaveTable                    \\\n  0x8539E660L, 0x62E9, 0x11CF, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00\nDEFINE_GUIDSTRUCT(\"8539E660-62E9-11CF-A5D6-28DB04C10000\", KSPROPSETID_WaveTable);\n # define KSPROPSETID_WaveTable DEFINE_GUIDNAMED(KSPROPSETID_WaveTable)\n\ntypedef enum\n{\n  KSPROPERTY_WAVETABLE_LOAD_SAMPLE,\n  KSPROPERTY_WAVETABLE_UNLOAD_SAMPLE,\n  KSPROPERTY_WAVETABLE_MEMORY,\n  KSPROPERTY_WAVETABLE_VERSION\n}KSPROPERTY_WAVETABLE;\n\ntypedef struct\n{\n  KSDATARANGE DataRange;\n  GUID Technology;\n  ULONG Channels;\n  ULONG Notes;\n  ULONG ChannelMask;\n}KSDATARANGE_MUSIC, * PKSDATARANGE_MUSIC;\n\n # define STATIC_KSEVENTSETID_Cyclic                  \\\n  0x142C1AC0L, 0x072A, 0x11D0, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00\nDEFINE_GUIDSTRUCT(\"142C1AC0-072A-11D0-A5D6-28DB04C10000\", KSEVENTSETID_Cyclic);\n # define KSEVENTSETID_Cyclic DEFINE_GUIDNAMED(KSEVENTSETID_Cyclic)\n\ntypedef enum\n{\n  KSEVENT_CYCLIC_TIME_INTERVAL\n}KSEVENT_CYCLIC_TIME;\n\n # define STATIC_KSPROPSETID_Cyclic                   \\\n  0x3FFEAEA0L, 0x2BEE, 0x11CF, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00\nDEFINE_GUIDSTRUCT(\"3FFEAEA0-2BEE-11CF-A5D6-28DB04C10000\", KSPROPSETID_Cyclic);\n # define KSPROPSETID_Cyclic DEFINE_GUIDNAMED(KSPROPSETID_Cyclic)\n\ntypedef enum\n{\n  KSPROPERTY_CYCLIC_POSITION\n}KSPROPERTY_CYCLIC;\n\n # define STATIC_KSEVENTSETID_AudioControlChange              \\\n  0xE85E9698L, 0xFA2F, 0x11D1, 0x95, 0xBD, 0x00, 0xC0, 0x4F, 0xB9, 0x25, 0xD3\nDEFINE_GUIDSTRUCT(\"E85E9698-FA2F-11D1-95BD-00C04FB925D3\", KSEVENTSETID_AudioControlChange);\n # define KSEVENTSETID_AudioControlChange DEFINE_GUIDNAMED(KSEVENTSETID_AudioControlChange)\n\ntypedef enum\n{\n  KSEVENT_CONTROL_CHANGE\n}KSEVENT_AUDIO_CONTROL_CHANGE;\n\n # define STATIC_KSEVENTSETID_LoopedStreaming             \\\n  0x4682B940L, 0xC6EF, 0x11D0, 0x96, 0xD8, 0x00, 0xAA, 0x00, 0x51, 0xE5, 0x1D\nDEFINE_GUIDSTRUCT(\"4682B940-C6EF-11D0-96D8-00AA0051E51D\", KSEVENTSETID_LoopedStreaming);\n # define KSEVENTSETID_LoopedStreaming DEFINE_GUIDNAMED(KSEVENTSETID_LoopedStreaming)\n\ntypedef enum\n{\n  KSEVENT_LOOPEDSTREAMING_POSITION\n}KSEVENT_LOOPEDSTREAMING;\n\ntypedef struct\n{\n  KSEVENTDATA KsEventData;\n  DWORDLONG Position;\n}LOOPEDSTREAMING_POSITION_EVENT_DATA, * PLOOPEDSTREAMING_POSITION_EVENT_DATA;\n\n # define STATIC_KSPROPSETID_Sysaudio                 \\\n  0xCBE3FAA0L, 0xCC75, 0x11D0, 0xB4, 0x65, 0x00, 0x00, 0x1A, 0x18, 0x18, 0xE6\nDEFINE_GUIDSTRUCT(\"CBE3FAA0-CC75-11D0-B465-00001A1818E6\", KSPROPSETID_Sysaudio);\n # define KSPROPSETID_Sysaudio DEFINE_GUIDNAMED(KSPROPSETID_Sysaudio)\n\ntypedef enum\n{\n  KSPROPERTY_SYSAUDIO_DEVICE_COUNT = 1,\n  KSPROPERTY_SYSAUDIO_DEVICE_FRIENDLY_NAME = 2,\n  KSPROPERTY_SYSAUDIO_DEVICE_INSTANCE = 3,\n  KSPROPERTY_SYSAUDIO_DEVICE_INTERFACE_NAME = 4,\n  KSPROPERTY_SYSAUDIO_SELECT_GRAPH = 5,\n  KSPROPERTY_SYSAUDIO_CREATE_VIRTUAL_SOURCE = 6,\n  KSPROPERTY_SYSAUDIO_DEVICE_DEFAULT = 7,\n  KSPROPERTY_SYSAUDIO_INSTANCE_INFO = 14,\n  KSPROPERTY_SYSAUDIO_COMPONENT_ID = 16\n}KSPROPERTY_SYSAUDIO;\n\ntypedef struct\n{\n  KSPROPERTY Property;\n  GUID PinCategory;\n  GUID PinName;\n}SYSAUDIO_CREATE_VIRTUAL_SOURCE, * PSYSAUDIO_CREATE_VIRTUAL_SOURCE;\n\ntypedef struct\n{\n  KSPROPERTY Property;\n  ULONG PinId;\n  ULONG NodeId;\n  ULONG Flags;\n  ULONG Reserved;\n}SYSAUDIO_SELECT_GRAPH, * PSYSAUDIO_SELECT_GRAPH;\n\ntypedef struct\n{\n  KSPROPERTY Property;\n  ULONG Flags;\n  ULONG DeviceNumber;\n}SYSAUDIO_INSTANCE_INFO, * PSYSAUDIO_INSTANCE_INFO;\n\n # define SYSAUDIO_FLAGS_DONT_COMBINE_PINS 0x00000001\n\n # define STATIC_KSPROPSETID_Sysaudio_Pin                 \\\n  0xA3A53220L, 0xC6E4, 0x11D0, 0xB4, 0x65, 0x00, 0x00, 0x1A, 0x18, 0x18, 0xE6\nDEFINE_GUIDSTRUCT(\"A3A53220-C6E4-11D0-B465-00001A1818E6\", KSPROPSETID_Sysaudio_Pin);\n # define KSPROPSETID_Sysaudio_Pin DEFINE_GUIDNAMED(KSPROPSETID_Sysaudio_Pin)\n\ntypedef enum\n{\n  KSPROPERTY_SYSAUDIO_ATTACH_VIRTUAL_SOURCE = 1\n}KSPROPERTY_SYSAUDIO_PIN;\n\ntypedef struct\n{\n  KSPROPERTY Property;\n  ULONG MixerPinId;\n  ULONG Reserved;\n}SYSAUDIO_ATTACH_VIRTUAL_SOURCE, * PSYSAUDIO_ATTACH_VIRTUAL_SOURCE;\n\ntypedef struct\n{\n  KSPROPERTY Property;\n  ULONG NodeId;\n  ULONG Reserved;\n}KSNODEPROPERTY, * PKSNODEPROPERTY;\n\ntypedef struct\n{\n  KSNODEPROPERTY NodeProperty;\n  LONG Channel;\n  ULONG Reserved;\n}KSNODEPROPERTY_AUDIO_CHANNEL, * PKSNODEPROPERTY_AUDIO_CHANNEL;\n\ntypedef struct\n{\n  KSNODEPROPERTY NodeProperty;\n  ULONG DevSpecificId;\n  ULONG DeviceInfo;\n  ULONG Length;\n}KSNODEPROPERTY_AUDIO_DEV_SPECIFIC, * PKSNODEPROPERTY_AUDIO_DEV_SPECIFIC;\n\ntypedef struct\n{\n  KSNODEPROPERTY NodeProperty;\n  PVOID ListenerId;\n # ifndef _WIN64\n  ULONG Reserved;\n # endif\n}KSNODEPROPERTY_AUDIO_3D_LISTENER, * PKSNODEPROPERTY_AUDIO_3D_LISTENER;\n\ntypedef struct\n{\n  KSNODEPROPERTY NodeProperty;\n  PVOID AppContext;\n  ULONG Length;\n # ifndef _WIN64\n  ULONG Reserved;\n # endif\n}KSNODEPROPERTY_AUDIO_PROPERTY, * PKSNODEPROPERTY_AUDIO_PROPERTY;\n\n # define STATIC_KSPROPSETID_AudioGfx                 \\\n  0x79a9312eL, 0x59ae, 0x43b0, 0xa3, 0x50, 0x8b, 0x5, 0x28, 0x4c, 0xab, 0x24\nDEFINE_GUIDSTRUCT(\"79A9312E-59AE-43b0-A350-8B05284CAB24\", KSPROPSETID_AudioGfx);\n # define KSPROPSETID_AudioGfx DEFINE_GUIDNAMED(KSPROPSETID_AudioGfx)\n\ntypedef enum\n{\n  KSPROPERTY_AUDIOGFX_RENDERTARGETDEVICEID,\n  KSPROPERTY_AUDIOGFX_CAPTURETARGETDEVICEID\n}KSPROPERTY_AUDIOGFX;\n\n # define STATIC_KSPROPSETID_Linear                   \\\n  0x5A2FFE80L, 0x16B9, 0x11D0, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00\nDEFINE_GUIDSTRUCT(\"5A2FFE80-16B9-11D0-A5D6-28DB04C10000\", KSPROPSETID_Linear);\n # define KSPROPSETID_Linear DEFINE_GUIDNAMED(KSPROPSETID_Linear)\n\ntypedef enum\n{\n  KSPROPERTY_LINEAR_POSITION\n}KSPROPERTY_LINEAR;\n\n # define STATIC_KSDATAFORMAT_TYPE_MUSIC                  \\\n  0xE725D360L, 0x62CC, 0x11CF, { 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 }\nDEFINE_GUIDSTRUCT(\"E725D360-62CC-11CF-A5D6-28DB04C10000\", KSDATAFORMAT_TYPE_MUSIC);\n # define KSDATAFORMAT_TYPE_MUSIC DEFINE_GUIDNAMED(KSDATAFORMAT_TYPE_MUSIC)\n\n # define STATIC_KSDATAFORMAT_TYPE_MIDI                   \\\n  0x7364696DL, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71\nDEFINE_GUIDSTRUCT(\"7364696D-0000-0010-8000-00aa00389b71\", KSDATAFORMAT_TYPE_MIDI);\n # define KSDATAFORMAT_TYPE_MIDI DEFINE_GUIDNAMED(KSDATAFORMAT_TYPE_MIDI)\n\n # define STATIC_KSDATAFORMAT_SUBTYPE_MIDI                \\\n  0x1D262760L, 0xE957, 0x11CF, { 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 }\nDEFINE_GUIDSTRUCT(\"1D262760-E957-11CF-A5D6-28DB04C10000\", KSDATAFORMAT_SUBTYPE_MIDI);\n # define KSDATAFORMAT_SUBTYPE_MIDI DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_MIDI)\n\n # define STATIC_KSDATAFORMAT_SUBTYPE_MIDI_BUS                \\\n  0x2CA15FA0L, 0x6CFE, 0x11CF, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00\nDEFINE_GUIDSTRUCT(\"2CA15FA0-6CFE-11CF-A5D6-28DB04C10000\", KSDATAFORMAT_SUBTYPE_MIDI_BUS);\n # define KSDATAFORMAT_SUBTYPE_MIDI_BUS DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_MIDI_BUS)\n\n # define STATIC_KSDATAFORMAT_SUBTYPE_RIFFMIDI                \\\n  0x4995DAF0L, 0x9EE6, 0x11D0, 0xA4, 0x0E, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96\nDEFINE_GUIDSTRUCT(\"4995DAF0-9EE6-11D0-A40E-00A0C9223196\", KSDATAFORMAT_SUBTYPE_RIFFMIDI);\n # define KSDATAFORMAT_SUBTYPE_RIFFMIDI DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_RIFFMIDI)\n\ntypedef struct\n{\n  ULONG TimeDeltaMs;\n\n  ULONG ByteCount;\n}KSMUSICFORMAT, * PKSMUSICFORMAT;\n\n # define STATIC_KSDATAFORMAT_TYPE_STANDARD_ELEMENTARY_STREAM     \\\n  0x36523b11L, 0x8ee5, 0x11d1, 0x8c, 0xa3, 0x00, 0x60, 0xb0, 0x57, 0x66, 0x4a\nDEFINE_GUIDSTRUCT(\"36523B11-8EE5-11d1-8CA3-0060B057664A\", KSDATAFORMAT_TYPE_STANDARD_ELEMENTARY_STREAM);\n # define KSDATAFORMAT_TYPE_STANDARD_ELEMENTARY_STREAM DEFINE_GUIDNAMED(KSDATAFORMAT_TYPE_STANDARD_ELEMENTARY_STREAM)\n\n # define STATIC_KSDATAFORMAT_TYPE_STANDARD_PES_PACKET            \\\n  0x36523b12L, 0x8ee5, 0x11d1, 0x8c, 0xa3, 0x00, 0x60, 0xb0, 0x57, 0x66, 0x4a\nDEFINE_GUIDSTRUCT(\"36523B12-8EE5-11d1-8CA3-0060B057664A\", KSDATAFORMAT_TYPE_STANDARD_PES_PACKET);\n # define KSDATAFORMAT_TYPE_STANDARD_PES_PACKET DEFINE_GUIDNAMED(KSDATAFORMAT_TYPE_STANDARD_PES_PACKET)\n\n # define STATIC_KSDATAFORMAT_TYPE_STANDARD_PACK_HEADER           \\\n  0x36523b13L, 0x8ee5, 0x11d1, 0x8c, 0xa3, 0x00, 0x60, 0xb0, 0x57, 0x66, 0x4a\nDEFINE_GUIDSTRUCT(\"36523B13-8EE5-11d1-8CA3-0060B057664A\", KSDATAFORMAT_TYPE_STANDARD_PACK_HEADER);\n # define KSDATAFORMAT_TYPE_STANDARD_PACK_HEADER DEFINE_GUIDNAMED(KSDATAFORMAT_TYPE_STANDARD_PACK_HEADER)\n\n # define STATIC_KSDATAFORMAT_SUBTYPE_STANDARD_MPEG1_VIDEO        \\\n  0x36523b21L, 0x8ee5, 0x11d1, 0x8c, 0xa3, 0x00, 0x60, 0xb0, 0x57, 0x66, 0x4a\nDEFINE_GUIDSTRUCT(\"36523B21-8EE5-11d1-8CA3-0060B057664A\", KSDATAFORMAT_SUBTYPE_STANDARD_MPEG1_VIDEO);\n # define KSDATAFORMAT_SUBTYPE_STANDARD_MPEG1_VIDEO DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_STANDARD_MPEG1_VIDEO)\n\n # define STATIC_KSDATAFORMAT_SUBTYPE_STANDARD_MPEG1_AUDIO        \\\n  0x36523b22L, 0x8ee5, 0x11d1, 0x8c, 0xa3, 0x00, 0x60, 0xb0, 0x57, 0x66, 0x4a\nDEFINE_GUIDSTRUCT(\"36523B22-8EE5-11d1-8CA3-0060B057664A\", KSDATAFORMAT_SUBTYPE_STANDARD_MPEG1_AUDIO);\n # define KSDATAFORMAT_SUBTYPE_STANDARD_MPEG1_AUDIO DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_STANDARD_MPEG1_AUDIO)\n\n # define STATIC_KSDATAFORMAT_SUBTYPE_STANDARD_MPEG2_VIDEO        \\\n  0x36523b23L, 0x8ee5, 0x11d1, 0x8c, 0xa3, 0x00, 0x60, 0xb0, 0x57, 0x66, 0x4a\nDEFINE_GUIDSTRUCT(\"36523B23-8EE5-11d1-8CA3-0060B057664A\", KSDATAFORMAT_SUBTYPE_STANDARD_MPEG2_VIDEO);\n # define KSDATAFORMAT_SUBTYPE_STANDARD_MPEG2_VIDEO DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_STANDARD_MPEG2_VIDEO)\n\n # define STATIC_KSDATAFORMAT_SUBTYPE_STANDARD_MPEG2_AUDIO        \\\n  0x36523b24L, 0x8ee5, 0x11d1, 0x8c, 0xa3, 0x00, 0x60, 0xb0, 0x57, 0x66, 0x4a\nDEFINE_GUIDSTRUCT(\"36523B24-8EE5-11d1-8CA3-0060B057664A\", KSDATAFORMAT_SUBTYPE_STANDARD_MPEG2_AUDIO);\n # define KSDATAFORMAT_SUBTYPE_STANDARD_MPEG2_AUDIO DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_STANDARD_MPEG2_AUDIO)\n\n # define STATIC_KSDATAFORMAT_SUBTYPE_STANDARD_AC3_AUDIO          \\\n  0x36523b25L, 0x8ee5, 0x11d1, 0x8c, 0xa3, 0x00, 0x60, 0xb0, 0x57, 0x66, 0x4a\nDEFINE_GUIDSTRUCT(\"36523B25-8EE5-11d1-8CA3-0060B057664A\", KSDATAFORMAT_SUBTYPE_STANDARD_AC3_AUDIO);\n # define KSDATAFORMAT_SUBTYPE_STANDARD_AC3_AUDIO DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_STANDARD_AC3_AUDIO)\n\n # define STATIC_KSDATAFORMAT_SPECIFIER_DIALECT_MPEG1_VIDEO       \\\n  0x36523b31L, 0x8ee5, 0x11d1, 0x8c, 0xa3, 0x00, 0x60, 0xb0, 0x57, 0x66, 0x4a\nDEFINE_GUIDSTRUCT(\"36523B31-8EE5-11d1-8CA3-0060B057664A\", KSDATAFORMAT_SPECIFIER_DIALECT_MPEG1_VIDEO);\n # define KSDATAFORMAT_SPECIFIER_DIALECT_MPEG1_VIDEO DEFINE_GUIDNAMED(KSDATAFORMAT_SPECIFIER_DIALECT_MPEG1_VIDEO)\n\n # define STATIC_KSDATAFORMAT_SPECIFIER_DIALECT_MPEG1_AUDIO       \\\n  0x36523b32L, 0x8ee5, 0x11d1, 0x8c, 0xa3, 0x00, 0x60, 0xb0, 0x57, 0x66, 0x4a\nDEFINE_GUIDSTRUCT(\"36523B32-8EE5-11d1-8CA3-0060B057664A\", KSDATAFORMAT_SPECIFIER_DIALECT_MPEG1_AUDIO);\n # define KSDATAFORMAT_SPECIFIER_DIALECT_MPEG1_AUDIO DEFINE_GUIDNAMED(KSDATAFORMAT_SPECIFIER_DIALECT_MPEG1_AUDIO)\n\n # define STATIC_KSDATAFORMAT_SPECIFIER_DIALECT_MPEG2_VIDEO       \\\n  0x36523b33L, 0x8ee5, 0x11d1, 0x8c, 0xa3, 0x00, 0x60, 0xb0, 0x57, 0x66, 0x4a\nDEFINE_GUIDSTRUCT(\"36523B33-8EE5-11d1-8CA3-0060B057664A\", KSDATAFORMAT_SPECIFIER_DIALECT_MPEG2_VIDEO);\n # define KSDATAFORMAT_SPECIFIER_DIALECT_MPEG2_VIDEO DEFINE_GUIDNAMED(KSDATAFORMAT_SPECIFIER_DIALECT_MPEG2_VIDEO)\n\n # define STATIC_KSDATAFORMAT_SPECIFIER_DIALECT_MPEG2_AUDIO       \\\n  0x36523b34L, 0x8ee5, 0x11d1, 0x8c, 0xa3, 0x00, 0x60, 0xb0, 0x57, 0x66, 0x4a\nDEFINE_GUIDSTRUCT(\"36523B34-8EE5-11d1-8CA3-0060B057664A\", KSDATAFORMAT_SPECIFIER_DIALECT_MPEG2_AUDIO);\n # define KSDATAFORMAT_SPECIFIER_DIALECT_MPEG2_AUDIO DEFINE_GUIDNAMED(KSDATAFORMAT_SPECIFIER_DIALECT_MPEG2_AUDIO)\n\n # define STATIC_KSDATAFORMAT_SPECIFIER_DIALECT_AC3_AUDIO         \\\n  0x36523b35L, 0x8ee5, 0x11d1, 0x8c, 0xa3, 0x00, 0x60, 0xb0, 0x57, 0x66, 0x4a\nDEFINE_GUIDSTRUCT(\"36523B35-8EE5-11d1-8CA3-0060B057664A\", KSDATAFORMAT_SPECIFIER_DIALECT_AC3_AUDIO);\n # define KSDATAFORMAT_SPECIFIER_DIALECT_AC3_AUDIO DEFINE_GUIDNAMED(KSDATAFORMAT_SPECIFIER_DIALECT_AC3_AUDIO)\n\n # define STATIC_KSDATAFORMAT_SUBTYPE_DSS_VIDEO               \\\n  0xa0af4f81L, 0xe163, 0x11d0, 0xba, 0xd9, 0x00, 0x60, 0x97, 0x44, 0x11, 0x1a\nDEFINE_GUIDSTRUCT(\"a0af4f81-e163-11d0-bad9-00609744111a\", KSDATAFORMAT_SUBTYPE_DSS_VIDEO);\n # define KSDATAFORMAT_SUBTYPE_DSS_VIDEO DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_DSS_VIDEO)\n\n # define STATIC_KSDATAFORMAT_SUBTYPE_DSS_AUDIO               \\\n  0xa0af4f82L, 0xe163, 0x11d0, 0xba, 0xd9, 0x00, 0x60, 0x97, 0x44, 0x11, 0x1a\nDEFINE_GUIDSTRUCT(\"a0af4f82-e163-11d0-bad9-00609744111a\", KSDATAFORMAT_SUBTYPE_DSS_AUDIO);\n # define KSDATAFORMAT_SUBTYPE_DSS_AUDIO DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_DSS_AUDIO)\n\n # define STATIC_KSDATAFORMAT_SUBTYPE_MPEG1Packet             \\\n  0xe436eb80, 0x524f, 0x11ce, 0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70\nDEFINE_GUIDSTRUCT(\"e436eb80-524f-11ce-9F53-0020af0ba770\", KSDATAFORMAT_SUBTYPE_MPEG1Packet);\n # define KSDATAFORMAT_SUBTYPE_MPEG1Packet DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_MPEG1Packet)\n\n # define STATIC_KSDATAFORMAT_SUBTYPE_MPEG1Payload            \\\n  0xe436eb81, 0x524f, 0x11ce, 0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70\nDEFINE_GUIDSTRUCT(\"e436eb81-524f-11ce-9F53-0020af0ba770\", KSDATAFORMAT_SUBTYPE_MPEG1Payload);\n # define KSDATAFORMAT_SUBTYPE_MPEG1Payload DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_MPEG1Payload)\n\n # define STATIC_KSDATAFORMAT_SUBTYPE_MPEG1Video              \\\n  0xe436eb86, 0x524f, 0x11ce, 0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70\nDEFINE_GUIDSTRUCT(\"e436eb86-524f-11ce-9f53-0020af0ba770\", KSDATAFORMAT_SUBTYPE_MPEG1Video);\n # define KSDATAFORMAT_SUBTYPE_MPEG1Video DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_MPEG1Video)\n\n # define STATIC_KSDATAFORMAT_SPECIFIER_MPEG1_VIDEO           \\\n  0x05589f82L, 0xc356, 0x11ce, 0xbf, 0x01, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a\nDEFINE_GUIDSTRUCT(\"05589f82-c356-11ce-bf01-00aa0055595a\", KSDATAFORMAT_SPECIFIER_MPEG1_VIDEO);\n # define KSDATAFORMAT_SPECIFIER_MPEG1_VIDEO DEFINE_GUIDNAMED(KSDATAFORMAT_SPECIFIER_MPEG1_VIDEO)\n\n # define STATIC_KSDATAFORMAT_TYPE_MPEG2_PES              \\\n  0xe06d8020L, 0xdb46, 0x11cf, 0xb4, 0xd1, 0x00, 0x80, 0x5f, 0x6c, 0xbb, 0xea\nDEFINE_GUIDSTRUCT(\"e06d8020-db46-11cf-b4d1-00805f6cbbea\", KSDATAFORMAT_TYPE_MPEG2_PES);\n # define KSDATAFORMAT_TYPE_MPEG2_PES DEFINE_GUIDNAMED(KSDATAFORMAT_TYPE_MPEG2_PES)\n\n # define STATIC_KSDATAFORMAT_TYPE_MPEG2_PROGRAM              \\\n  0xe06d8022L, 0xdb46, 0x11cf, 0xb4, 0xd1, 0x00, 0x80, 0x5f, 0x6c, 0xbb, 0xea\nDEFINE_GUIDSTRUCT(\"e06d8022-db46-11cf-b4d1-00805f6cbbea\", KSDATAFORMAT_TYPE_MPEG2_PROGRAM);\n # define KSDATAFORMAT_TYPE_MPEG2_PROGRAM DEFINE_GUIDNAMED(KSDATAFORMAT_TYPE_MPEG2_PROGRAM)\n\n # define STATIC_KSDATAFORMAT_TYPE_MPEG2_TRANSPORT            \\\n  0xe06d8023L, 0xdb46, 0x11cf, 0xb4, 0xd1, 0x00, 0x80, 0x5f, 0x6c, 0xbb, 0xea\nDEFINE_GUIDSTRUCT(\"e06d8023-db46-11cf-b4d1-00805f6cbbea\", KSDATAFORMAT_TYPE_MPEG2_TRANSPORT);\n # define KSDATAFORMAT_TYPE_MPEG2_TRANSPORT DEFINE_GUIDNAMED(KSDATAFORMAT_TYPE_MPEG2_TRANSPORT)\n\n # define STATIC_KSDATAFORMAT_SUBTYPE_MPEG2_VIDEO             \\\n  0xe06d8026L, 0xdb46, 0x11cf, 0xb4, 0xd1, 0x00, 0x80, 0x5f, 0x6c, 0xbb, 0xea\nDEFINE_GUIDSTRUCT(\"e06d8026-db46-11cf-b4d1-00805f6cbbea\", KSDATAFORMAT_SUBTYPE_MPEG2_VIDEO);\n # define KSDATAFORMAT_SUBTYPE_MPEG2_VIDEO DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_MPEG2_VIDEO)\n\n # define STATIC_KSDATAFORMAT_SPECIFIER_MPEG2_VIDEO           \\\n  0xe06d80e3L, 0xdb46, 0x11cf, 0xb4, 0xd1, 0x00, 0x80, 0x5f, 0x6c, 0xbb, 0xea\nDEFINE_GUIDSTRUCT(\"e06d80e3-db46-11cf-b4d1-00805f6cbbea\", KSDATAFORMAT_SPECIFIER_MPEG2_VIDEO);\n # define KSDATAFORMAT_SPECIFIER_MPEG2_VIDEO DEFINE_GUIDNAMED(KSDATAFORMAT_SPECIFIER_MPEG2_VIDEO)\n\n # define STATIC_KSPROPSETID_Mpeg2Vid                 \\\n  0xC8E11B60L, 0x0CC9, 0x11D0, 0xBD, 0x69, 0x00, 0x35, 0x05, 0xC1, 0x03, 0xA9\nDEFINE_GUIDSTRUCT(\"C8E11B60-0CC9-11D0-BD69-003505C103A9\", KSPROPSETID_Mpeg2Vid);\n # define KSPROPSETID_Mpeg2Vid DEFINE_GUIDNAMED(KSPROPSETID_Mpeg2Vid)\n\ntypedef enum\n{\n  KSPROPERTY_MPEG2VID_MODES,\n  KSPROPERTY_MPEG2VID_CUR_MODE,\n  KSPROPERTY_MPEG2VID_4_3_RECT,\n  KSPROPERTY_MPEG2VID_16_9_RECT,\n  KSPROPERTY_MPEG2VID_16_9_PANSCAN\n}KSPROPERTY_MPEG2VID;\n\n # define KSMPEGVIDMODE_PANSCAN 0x0001\n # define KSMPEGVIDMODE_LTRBOX 0x0002\n # define KSMPEGVIDMODE_SCALE 0x0004\n\ntypedef struct _KSMPEGVID_RECT\n{\n  ULONG StartX;\n  ULONG StartY;\n  ULONG EndX;\n  ULONG EndY;\n}KSMPEGVID_RECT, * PKSMPEGVID_RECT;\n\n # define STATIC_KSDATAFORMAT_SUBTYPE_MPEG2_AUDIO             \\\n  0xe06d802bL, 0xdb46, 0x11cf, 0xb4, 0xd1, 0x00, 0x80, 0x5f, 0x6c, 0xbb, 0xea\nDEFINE_GUIDSTRUCT(\"e06d802b-db46-11cf-b4d1-00805f6cbbea\", KSDATAFORMAT_SUBTYPE_MPEG2_AUDIO);\n # define KSDATAFORMAT_SUBTYPE_MPEG2_AUDIO DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_MPEG2_AUDIO)\n\n # define STATIC_KSDATAFORMAT_SPECIFIER_MPEG2_AUDIO           \\\n  0xe06d80e5L, 0xdb46, 0x11cf, 0xb4, 0xd1, 0x00, 0x80, 0x5f, 0x6c, 0xbb, 0xea\nDEFINE_GUIDSTRUCT(\"e06d80e5-db46-11cf-b4d1-00805f6cbbea\", KSDATAFORMAT_SPECIFIER_MPEG2_AUDIO);\n # define KSDATAFORMAT_SPECIFIER_MPEG2_AUDIO DEFINE_GUIDNAMED(KSDATAFORMAT_SPECIFIER_MPEG2_AUDIO)\n\n # define STATIC_KSDATAFORMAT_SUBTYPE_LPCM_AUDIO              \\\n  0xe06d8032L, 0xdb46, 0x11cf, 0xb4, 0xd1, 0x00, 0x80, 0x5f, 0x6c, 0xbb, 0xea\nDEFINE_GUIDSTRUCT(\"e06d8032-db46-11cf-b4d1-00805f6cbbea\", KSDATAFORMAT_SUBTYPE_LPCM_AUDIO);\n # define KSDATAFORMAT_SUBTYPE_LPCM_AUDIO DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_LPCM_AUDIO)\n\n # define STATIC_KSDATAFORMAT_SPECIFIER_LPCM_AUDIO            \\\n  0xe06d80e6L, 0xdb46, 0x11cf, 0xb4, 0xd1, 0x00, 0x80, 0x5f, 0x6c, 0xbb, 0xea\nDEFINE_GUIDSTRUCT(\"e06d80e6-db46-11cf-b4d1-00805f6cbbea\", KSDATAFORMAT_SPECIFIER_LPCM_AUDIO);\n # define KSDATAFORMAT_SPECIFIER_LPCM_AUDIO DEFINE_GUIDNAMED(KSDATAFORMAT_SPECIFIER_LPCM_AUDIO)\n\n # define STATIC_KSDATAFORMAT_SUBTYPE_AC3_AUDIO               \\\n  0xe06d802cL, 0xdb46, 0x11cf, 0xb4, 0xd1, 0x00, 0x80, 0x5f, 0x6c, 0xbb, 0xea\nDEFINE_GUIDSTRUCT(\"e06d802c-db46-11cf-b4d1-00805f6cbbea\", KSDATAFORMAT_SUBTYPE_AC3_AUDIO);\n # define KSDATAFORMAT_SUBTYPE_AC3_AUDIO DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_AC3_AUDIO)\n\n # define STATIC_KSDATAFORMAT_SPECIFIER_AC3_AUDIO             \\\n  0xe06d80e4L, 0xdb46, 0x11cf, 0xb4, 0xd1, 0x00, 0x80, 0x5f, 0x6c, 0xbb, 0xea\nDEFINE_GUIDSTRUCT(\"e06d80e4-db46-11cf-b4d1-00805f6cbbea\", KSDATAFORMAT_SPECIFIER_AC3_AUDIO);\n # define KSDATAFORMAT_SPECIFIER_AC3_AUDIO DEFINE_GUIDNAMED(KSDATAFORMAT_SPECIFIER_AC3_AUDIO)\n\n # define STATIC_KSPROPSETID_AC3                      \\\n  0xBFABE720L, 0x6E1F, 0x11D0, 0xBC, 0xF2, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00\nDEFINE_GUIDSTRUCT(\"BFABE720-6E1F-11D0-BCF2-444553540000\", KSPROPSETID_AC3);\n # define KSPROPSETID_AC3 DEFINE_GUIDNAMED(KSPROPSETID_AC3)\n\ntypedef enum\n{\n  KSPROPERTY_AC3_ERROR_CONCEALMENT = 1,\n  KSPROPERTY_AC3_ALTERNATE_AUDIO,\n  KSPROPERTY_AC3_DOWNMIX,\n  KSPROPERTY_AC3_BIT_STREAM_MODE,\n  KSPROPERTY_AC3_DIALOGUE_LEVEL,\n  KSPROPERTY_AC3_LANGUAGE_CODE,\n  KSPROPERTY_AC3_ROOM_TYPE\n}KSPROPERTY_AC3;\n\ntypedef struct\n{\n  WINBOOL fRepeatPreviousBlock;\n  WINBOOL fErrorInCurrentBlock;\n}KSAC3_ERROR_CONCEALMENT, * PKSAC3_ERROR_CONCEALMENT;\n\ntypedef struct\n{\n  WINBOOL fStereo;\n  ULONG DualMode;\n}KSAC3_ALTERNATE_AUDIO, * PKSAC3_ALTERNATE_AUDIO;\n\n # define KSAC3_ALTERNATE_AUDIO_1 1\n # define KSAC3_ALTERNATE_AUDIO_2 2\n # define KSAC3_ALTERNATE_AUDIO_BOTH 3\n\ntypedef struct\n{\n  WINBOOL fDownMix;\n  WINBOOL fDolbySurround;\n}KSAC3_DOWNMIX, * PKSAC3_DOWNMIX;\n\ntypedef struct\n{\n  LONG BitStreamMode;\n}KSAC3_BIT_STREAM_MODE, * PKSAC3_BIT_STREAM_MODE;\n\n # define KSAC3_SERVICE_MAIN_AUDIO 0\n # define KSAC3_SERVICE_NO_DIALOG 1\n # define KSAC3_SERVICE_VISUALLY_IMPAIRED 2\n # define KSAC3_SERVICE_HEARING_IMPAIRED 3\n # define KSAC3_SERVICE_DIALOG_ONLY 4\n # define KSAC3_SERVICE_COMMENTARY 5\n # define KSAC3_SERVICE_EMERGENCY_FLASH 6\n # define KSAC3_SERVICE_VOICE_OVER 7\n\ntypedef struct\n{\n  ULONG DialogueLevel;\n}KSAC3_DIALOGUE_LEVEL, * PKSAC3_DIALOGUE_LEVEL;\n\ntypedef struct\n{\n  WINBOOL fLargeRoom;\n}KSAC3_ROOM_TYPE, * PKSAC3_ROOM_TYPE;\n\n # define STATIC_KSDATAFORMAT_SUBTYPE_DTS_AUDIO               \\\n  0xe06d8033L, 0xdb46, 0x11cf, 0xb4, 0xd1, 0x00, 0x80, 0x5f, 0x6c, 0xbb, 0xea\nDEFINE_GUIDSTRUCT(\"e06d8033-db46-11cf-b4d1-00805f6cbbea\", KSDATAFORMAT_SUBTYPE_DTS_AUDIO);\n # define KSDATAFORMAT_SUBTYPE_DTS_AUDIO DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_DTS_AUDIO)\n\n # define STATIC_KSDATAFORMAT_SUBTYPE_SDDS_AUDIO              \\\n  0xe06d8034L, 0xdb46, 0x11cf, 0xb4, 0xd1, 0x00, 0x80, 0x5f, 0x6c, 0xbb, 0xea\nDEFINE_GUIDSTRUCT(\"e06d8034-db46-11cf-b4d1-00805f6cbbea\", KSDATAFORMAT_SUBTYPE_SDDS_AUDIO);\n # define KSDATAFORMAT_SUBTYPE_SDDS_AUDIO DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_SDDS_AUDIO)\n\n # define STATIC_KSPROPSETID_AudioDecoderOut              \\\n  0x6ca6e020L, 0x43bd, 0x11d0, 0xbd, 0x6a, 0x00, 0x35, 0x05, 0xc1, 0x03, 0xa9\nDEFINE_GUIDSTRUCT(\"6ca6e020-43bd-11d0-bd6a-003505c103a9\", KSPROPSETID_AudioDecoderOut);\n # define KSPROPSETID_AudioDecoderOut DEFINE_GUIDNAMED(KSPROPSETID_AudioDecoderOut)\n\ntypedef enum\n{\n  KSPROPERTY_AUDDECOUT_MODES,\n  KSPROPERTY_AUDDECOUT_CUR_MODE\n}KSPROPERTY_AUDDECOUT;\n\n # define KSAUDDECOUTMODE_STEREO_ANALOG 0x0001\n # define KSAUDDECOUTMODE_PCM_51 0x0002\n # define KSAUDDECOUTMODE_SPDIFF 0x0004\n\n # define STATIC_KSDATAFORMAT_SUBTYPE_SUBPICTURE              \\\n  0xe06d802dL, 0xdb46, 0x11cf, 0xb4, 0xd1, 0x00, 0x80, 0x5f, 0x6c, 0xbb, 0xea\nDEFINE_GUIDSTRUCT(\"e06d802d-db46-11cf-b4d1-00805f6cbbea\", KSDATAFORMAT_SUBTYPE_SUBPICTURE);\n # define KSDATAFORMAT_SUBTYPE_SUBPICTURE DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_SUBPICTURE)\n\n # define STATIC_KSPROPSETID_DvdSubPic                    \\\n  0xac390460L, 0x43af, 0x11d0, 0xbd, 0x6a, 0x00, 0x35, 0x05, 0xc1, 0x03, 0xa9\nDEFINE_GUIDSTRUCT(\"ac390460-43af-11d0-bd6a-003505c103a9\", KSPROPSETID_DvdSubPic);\n # define KSPROPSETID_DvdSubPic DEFINE_GUIDNAMED(KSPROPSETID_DvdSubPic)\n\ntypedef enum\n{\n  KSPROPERTY_DVDSUBPIC_PALETTE,\n  KSPROPERTY_DVDSUBPIC_HLI,\n  KSPROPERTY_DVDSUBPIC_COMPOSIT_ON\n}KSPROPERTY_DVDSUBPIC;\n\ntypedef struct _KS_DVD_YCrCb\n{\n  UCHAR Reserved;\n  UCHAR Y;\n  UCHAR Cr;\n  UCHAR Cb;\n}KS_DVD_YCrCb, * PKS_DVD_YCrCb;\n\ntypedef struct _KS_DVD_YUV\n{\n  UCHAR Reserved;\n  UCHAR Y;\n  UCHAR V;\n  UCHAR U;\n}KS_DVD_YUV, * PKS_DVD_YUV;\n\ntypedef struct _KSPROPERTY_SPPAL\n{\n  KS_DVD_YUV sppal[16];\n}KSPROPERTY_SPPAL, * PKSPROPERTY_SPPAL;\n\ntypedef struct _KS_COLCON\n{\n  UCHAR emph1col : 4;\n  UCHAR emph2col : 4;\n  UCHAR backcol : 4;\n  UCHAR patcol : 4;\n  UCHAR emph1con : 4;\n  UCHAR emph2con : 4;\n  UCHAR backcon : 4;\n  UCHAR patcon : 4;\n}KS_COLCON, * PKS_COLCON;\n\ntypedef struct _KSPROPERTY_SPHLI\n{\n  USHORT HLISS;\n  USHORT Reserved;\n  ULONG StartPTM;\n  ULONG EndPTM;\n  USHORT StartX;\n  USHORT StartY;\n  USHORT StopX;\n  USHORT StopY;\n  KS_COLCON ColCon;\n}KSPROPERTY_SPHLI, * PKSPROPERTY_SPHLI;\n\ntypedef WINBOOL KSPROPERTY_COMPOSIT_ON, * PKSPROPERTY_COMPOSIT_ON;\n\n # define STATIC_KSPROPSETID_CopyProt                 \\\n  0x0E8A0A40L, 0x6AEF, 0x11D0, 0x9E, 0xD0, 0x00, 0xA0, 0x24, 0xCA, 0x19, 0xB3\nDEFINE_GUIDSTRUCT(\"0E8A0A40-6AEF-11D0-9ED0-00A024CA19B3\", KSPROPSETID_CopyProt);\n # define KSPROPSETID_CopyProt DEFINE_GUIDNAMED(KSPROPSETID_CopyProt)\n\ntypedef enum\n{\n  KSPROPERTY_DVDCOPY_CHLG_KEY = 0x01,\n  KSPROPERTY_DVDCOPY_DVD_KEY1,\n  KSPROPERTY_DVDCOPY_DEC_KEY2,\n  KSPROPERTY_DVDCOPY_TITLE_KEY,\n  KSPROPERTY_COPY_MACROVISION,\n  KSPROPERTY_DVDCOPY_REGION,\n  KSPROPERTY_DVDCOPY_SET_COPY_STATE,\n  KSPROPERTY_DVDCOPY_DISC_KEY = 0x80\n}KSPROPERTY_COPYPROT;\n\ntypedef struct _KS_DVDCOPY_CHLGKEY\n{\n  BYTE ChlgKey[10];\n  BYTE Reserved[2];\n}KS_DVDCOPY_CHLGKEY, * PKS_DVDCOPY_CHLGKEY;\n\ntypedef struct _KS_DVDCOPY_BUSKEY\n{\n  BYTE BusKey[5];\n  BYTE Reserved[1];\n}KS_DVDCOPY_BUSKEY, * PKS_DVDCOPY_BUSKEY;\n\ntypedef struct _KS_DVDCOPY_DISCKEY\n{\n  BYTE DiscKey[2048];\n}KS_DVDCOPY_DISCKEY, * PKS_DVDCOPY_DISCKEY;\n\ntypedef struct _KS_DVDCOPY_REGION\n{\n  UCHAR Reserved;\n  UCHAR RegionData;\n  UCHAR Reserved2[2];\n}KS_DVDCOPY_REGION, * PKS_DVDCOPY_REGION;\n\ntypedef struct _KS_DVDCOPY_TITLEKEY\n{\n  ULONG KeyFlags;\n  ULONG ReservedNT[2];\n  UCHAR TitleKey[6];\n  UCHAR Reserved[2];\n}KS_DVDCOPY_TITLEKEY, * PKS_DVDCOPY_TITLEKEY;\n\ntypedef struct _KS_COPY_MACROVISION\n{\n  ULONG MACROVISIONLevel;\n}KS_COPY_MACROVISION, * PKS_COPY_MACROVISION;\n\ntypedef struct _KS_DVDCOPY_SET_COPY_STATE\n{\n  ULONG DVDCopyState;\n}KS_DVDCOPY_SET_COPY_STATE, * PKS_DVDCOPY_SET_COPY_STATE;\n\ntypedef enum\n{\n  KS_DVDCOPYSTATE_INITIALIZE,\n  KS_DVDCOPYSTATE_INITIALIZE_TITLE,\n  KS_DVDCOPYSTATE_AUTHENTICATION_NOT_REQUIRED,\n  KS_DVDCOPYSTATE_AUTHENTICATION_REQUIRED,\n  KS_DVDCOPYSTATE_DONE\n}KS_DVDCOPYSTATE;\n\ntypedef enum\n{\n  KS_MACROVISION_DISABLED,\n  KS_MACROVISION_LEVEL1,\n  KS_MACROVISION_LEVEL2,\n  KS_MACROVISION_LEVEL3\n}KS_COPY_MACROVISION_LEVEL, * PKS_COPY_MACROVISION_LEVEL;\n\n # define KS_DVD_CGMS_RESERVED_MASK 0x00000078\n\n # define KS_DVD_CGMS_COPY_PROTECT_MASK 0x00000018\n # define KS_DVD_CGMS_COPY_PERMITTED 0x00000000\n # define KS_DVD_CGMS_COPY_ONCE 0x00000010\n # define KS_DVD_CGMS_NO_COPY 0x00000018\n\n # define KS_DVD_COPYRIGHT_MASK 0x00000040\n # define KS_DVD_NOT_COPYRIGHTED 0x00000000\n # define KS_DVD_COPYRIGHTED 0x00000040\n\n # define KS_DVD_SECTOR_PROTECT_MASK 0x00000020\n # define KS_DVD_SECTOR_NOT_PROTECTED 0x00000000\n # define KS_DVD_SECTOR_PROTECTED 0x00000020\n\n # define STATIC_KSCATEGORY_TVTUNER                   \\\n  0xa799a800L, 0xa46d, 0x11d0, 0xa1, 0x8c, 0x00, 0xa0, 0x24, 0x01, 0xdc, 0xd4\nDEFINE_GUIDSTRUCT(\"a799a800-a46d-11d0-a18c-00a02401dcd4\", KSCATEGORY_TVTUNER);\n # define KSCATEGORY_TVTUNER DEFINE_GUIDNAMED(KSCATEGORY_TVTUNER)\n\n # define STATIC_KSCATEGORY_CROSSBAR                  \\\n  0xa799a801L, 0xa46d, 0x11d0, 0xa1, 0x8c, 0x00, 0xa0, 0x24, 0x01, 0xdc, 0xd4\nDEFINE_GUIDSTRUCT(\"a799a801-a46d-11d0-a18c-00a02401dcd4\", KSCATEGORY_CROSSBAR);\n # define KSCATEGORY_CROSSBAR DEFINE_GUIDNAMED(KSCATEGORY_CROSSBAR)\n\n # define STATIC_KSCATEGORY_TVAUDIO                   \\\n  0xa799a802L, 0xa46d, 0x11d0, 0xa1, 0x8c, 0x00, 0xa0, 0x24, 0x01, 0xdc, 0xd4\nDEFINE_GUIDSTRUCT(\"a799a802-a46d-11d0-a18c-00a02401dcd4\", KSCATEGORY_TVAUDIO);\n # define KSCATEGORY_TVAUDIO DEFINE_GUIDNAMED(KSCATEGORY_TVAUDIO)\n\n # define STATIC_KSCATEGORY_VPMUX                     \\\n  0xa799a803L, 0xa46d, 0x11d0, 0xa1, 0x8c, 0x00, 0xa0, 0x24, 0x01, 0xdc, 0xd4\nDEFINE_GUIDSTRUCT(\"a799a803-a46d-11d0-a18c-00a02401dcd4\", KSCATEGORY_VPMUX);\n # define KSCATEGORY_VPMUX DEFINE_GUIDNAMED(KSCATEGORY_VPMUX)\n\n # define STATIC_KSCATEGORY_VBICODEC                  \\\n  0x07dad660L, 0x22f1, 0x11d1, 0xa9, 0xf4, 0x00, 0xc0, 0x4f, 0xbb, 0xde, 0x8f\nDEFINE_GUIDSTRUCT(\"07dad660-22f1-11d1-a9f4-00c04fbbde8f\", KSCATEGORY_VBICODEC);\n # define KSCATEGORY_VBICODEC DEFINE_GUIDNAMED(KSCATEGORY_VBICODEC)\n\n # define STATIC_KSDATAFORMAT_SUBTYPE_VPVideo             \\\n  0x5a9b6a40L, 0x1a22, 0x11d1, 0xba, 0xd9, 0x0, 0x60, 0x97, 0x44, 0x11, 0x1a\nDEFINE_GUIDSTRUCT(\"5a9b6a40-1a22-11d1-bad9-00609744111a\", KSDATAFORMAT_SUBTYPE_VPVideo);\n # define KSDATAFORMAT_SUBTYPE_VPVideo DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_VPVideo)\n\n # define STATIC_KSDATAFORMAT_SUBTYPE_VPVBI               \\\n  0x5a9b6a41L, 0x1a22, 0x11d1, 0xba, 0xd9, 0x0, 0x60, 0x97, 0x44, 0x11, 0x1a\nDEFINE_GUIDSTRUCT(\"5a9b6a41-1a22-11d1-bad9-00609744111a\", KSDATAFORMAT_SUBTYPE_VPVBI);\n # define KSDATAFORMAT_SUBTYPE_VPVBI DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_VPVBI)\n\n # define STATIC_KSDATAFORMAT_SPECIFIER_VIDEOINFO             \\\n  0x05589f80L, 0xc356, 0x11ce, 0xbf, 0x01, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a\nDEFINE_GUIDSTRUCT(\"05589f80-c356-11ce-bf01-00aa0055595a\", KSDATAFORMAT_SPECIFIER_VIDEOINFO);\n # define KSDATAFORMAT_SPECIFIER_VIDEOINFO DEFINE_GUIDNAMED(KSDATAFORMAT_SPECIFIER_VIDEOINFO)\n\n # define STATIC_KSDATAFORMAT_SPECIFIER_VIDEOINFO2            \\\n  0xf72a76A0L, 0xeb0a, 0x11d0, 0xac, 0xe4, 0x00, 0x00, 0xc0, 0xcc, 0x16, 0xba\nDEFINE_GUIDSTRUCT(\"f72a76A0-eb0a-11d0-ace4-0000c0cc16ba\", KSDATAFORMAT_SPECIFIER_VIDEOINFO2);\n # define KSDATAFORMAT_SPECIFIER_VIDEOINFO2 DEFINE_GUIDNAMED(KSDATAFORMAT_SPECIFIER_VIDEOINFO2)\n\n # define STATIC_KSDATAFORMAT_TYPE_ANALOGVIDEO                \\\n  0x0482dde1L, 0x7817, 0x11cf, 0x8a, 0x03, 0x00, 0xaa, 0x00, 0x6e, 0xcb, 0x65\nDEFINE_GUIDSTRUCT(\"0482dde1-7817-11cf-8a03-00aa006ecb65\", KSDATAFORMAT_TYPE_ANALOGVIDEO);\n # define KSDATAFORMAT_TYPE_ANALOGVIDEO DEFINE_GUIDNAMED(KSDATAFORMAT_TYPE_ANALOGVIDEO)\n\n # define STATIC_KSDATAFORMAT_SPECIFIER_ANALOGVIDEO           \\\n  0x0482dde0L, 0x7817, 0x11cf, 0x8a, 0x03, 0x00, 0xaa, 0x00, 0x6e, 0xcb, 0x65\nDEFINE_GUIDSTRUCT(\"0482dde0-7817-11cf-8a03-00aa006ecb65\", KSDATAFORMAT_SPECIFIER_ANALOGVIDEO);\n # define KSDATAFORMAT_SPECIFIER_ANALOGVIDEO DEFINE_GUIDNAMED(KSDATAFORMAT_SPECIFIER_ANALOGVIDEO)\n\n # define STATIC_KSDATAFORMAT_TYPE_ANALOGAUDIO                \\\n  0x0482dee1L, 0x7817, 0x11cf, 0x8a, 0x03, 0x00, 0xaa, 0x00, 0x6e, 0xcb, 0x65\nDEFINE_GUIDSTRUCT(\"0482DEE1-7817-11cf-8a03-00aa006ecb65\", KSDATAFORMAT_TYPE_ANALOGAUDIO);\n # define KSDATAFORMAT_TYPE_ANALOGAUDIO DEFINE_GUIDNAMED(KSDATAFORMAT_TYPE_ANALOGAUDIO)\n\n # define STATIC_KSDATAFORMAT_SPECIFIER_VBI               \\\n  0xf72a76e0L, 0xeb0a, 0x11d0, 0xac, 0xe4, 0x00, 0x00, 0xc0, 0xcc, 0x16, 0xba\nDEFINE_GUIDSTRUCT(\"f72a76e0-eb0a-11d0-ace4-0000c0cc16ba\", KSDATAFORMAT_SPECIFIER_VBI);\n # define KSDATAFORMAT_SPECIFIER_VBI DEFINE_GUIDNAMED(KSDATAFORMAT_SPECIFIER_VBI)\n\n # define STATIC_KSDATAFORMAT_TYPE_VBI                    \\\n  0xf72a76e1L, 0xeb0a, 0x11d0, 0xac, 0xe4, 0x00, 0x00, 0xc0, 0xcc, 0x16, 0xba\nDEFINE_GUIDSTRUCT(\"f72a76e1-eb0a-11d0-ace4-0000c0cc16ba\", KSDATAFORMAT_TYPE_VBI);\n # define KSDATAFORMAT_TYPE_VBI DEFINE_GUIDNAMED(KSDATAFORMAT_TYPE_VBI)\n\n # define STATIC_KSDATAFORMAT_SUBTYPE_RAW8                \\\n  0xca20d9a0, 0x3e3e, 0x11d1, 0x9b, 0xf9, 0x0, 0xc0, 0x4f, 0xbb, 0xde, 0xbf\nDEFINE_GUIDSTRUCT(\"ca20d9a0-3e3e-11d1-9bf9-00c04fbbdebf\", KSDATAFORMAT_SUBTYPE_RAW8);\n # define KSDATAFORMAT_SUBTYPE_RAW8 DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_RAW8)\n\n # define STATIC_KSDATAFORMAT_SUBTYPE_CC                  \\\n  0x33214cc1, 0x11f, 0x11d2, 0xb4, 0xb1, 0x0, 0xa0, 0xd1, 0x2, 0xcf, 0xbe\nDEFINE_GUIDSTRUCT(\"33214CC1-011F-11D2-B4B1-00A0D102CFBE\", KSDATAFORMAT_SUBTYPE_CC);\n # define KSDATAFORMAT_SUBTYPE_CC DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_CC)\n\n # define STATIC_KSDATAFORMAT_SUBTYPE_NABTS               \\\n  0xf72a76e2L, 0xeb0a, 0x11d0, 0xac, 0xe4, 0x00, 0x00, 0xc0, 0xcc, 0x16, 0xba\nDEFINE_GUIDSTRUCT(\"f72a76e2-eb0a-11d0-ace4-0000c0cc16ba\", KSDATAFORMAT_SUBTYPE_NABTS);\n # define KSDATAFORMAT_SUBTYPE_NABTS DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_NABTS)\n\n # define STATIC_KSDATAFORMAT_SUBTYPE_TELETEXT                \\\n  0xf72a76e3L, 0xeb0a, 0x11d0, 0xac, 0xe4, 0x00, 0x00, 0xc0, 0xcc, 0x16, 0xba\nDEFINE_GUIDSTRUCT(\"f72a76e3-eb0a-11d0-ace4-0000c0cc16ba\", KSDATAFORMAT_SUBTYPE_TELETEXT);\n # define KSDATAFORMAT_SUBTYPE_TELETEXT DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_TELETEXT)\n\n # define KS_BI_RGB 0L\n # define KS_BI_RLE8 1L\n # define KS_BI_RLE4 2L\n # define KS_BI_BITFIELDS 3L\n\ntypedef struct tagKS_RGBQUAD\n{\n  BYTE rgbBlue;\n  BYTE rgbGreen;\n  BYTE rgbRed;\n  BYTE rgbReserved;\n}KS_RGBQUAD, * PKS_RGBQUAD;\n\n # define KS_iPALETTE_COLORS 256\n # define KS_iEGA_COLORS 16\n # define KS_iMASK_COLORS 3\n # define KS_iTRUECOLOR 16\n # define KS_iRED 0\n # define KS_iGREEN 1\n # define KS_iBLUE 2\n # define KS_iPALETTE 8\n # define KS_iMAXBITS 8\n # define KS_SIZE_EGA_PALETTE (KS_iEGA_COLORS * sizeof(KS_RGBQUAD))\n # define KS_SIZE_PALETTE (KS_iPALETTE_COLORS * sizeof(KS_RGBQUAD))\n\ntypedef struct tagKS_BITMAPINFOHEADER\n{\n  DWORD biSize;\n  LONG biWidth;\n  LONG biHeight;\n  WORD biPlanes;\n  WORD biBitCount;\n  DWORD biCompression;\n  DWORD biSizeImage;\n  LONG biXPelsPerMeter;\n  LONG biYPelsPerMeter;\n  DWORD biClrUsed;\n  DWORD biClrImportant;\n}KS_BITMAPINFOHEADER, * PKS_BITMAPINFOHEADER;\n\ntypedef struct tag_KS_TRUECOLORINFO\n{\n  DWORD dwBitMasks[KS_iMASK_COLORS];\n  KS_RGBQUAD bmiColors[KS_iPALETTE_COLORS];\n}KS_TRUECOLORINFO, * PKS_TRUECOLORINFO;\n\n # define KS_WIDTHBYTES(bits) ((DWORD)(((bits) + 31) & (~31)) / 8)\n # define KS_DIBWIDTHBYTES(bi) (DWORD)KS_WIDTHBYTES((DWORD)(bi).biWidth * (DWORD)(bi).biBitCount)\n # define KS__DIBSIZE(bi) (KS_DIBWIDTHBYTES(bi) * (DWORD)(bi).biHeight)\n # define KS_DIBSIZE(bi) ((bi).biHeight < 0 ? (-1) * (KS__DIBSIZE(bi)) : KS__DIBSIZE(bi))\n\ntypedef LONGLONG REFERENCE_TIME;\n\ntypedef struct tagKS_VIDEOINFOHEADER\n{\n  RECT rcSource;\n  RECT rcTarget;\n  DWORD dwBitRate;\n  DWORD dwBitErrorRate;\n  REFERENCE_TIME AvgTimePerFrame;\n  KS_BITMAPINFOHEADER bmiHeader;\n}KS_VIDEOINFOHEADER, * PKS_VIDEOINFOHEADER;\n\ntypedef struct tagKS_VIDEOINFO\n{\n  RECT rcSource;\n  RECT rcTarget;\n  DWORD dwBitRate;\n  DWORD dwBitErrorRate;\n  REFERENCE_TIME AvgTimePerFrame;\n  KS_BITMAPINFOHEADER bmiHeader;\n  __MINGW_EXTENSION union\n  {\n    KS_RGBQUAD bmiColors[KS_iPALETTE_COLORS];\n    DWORD dwBitMasks[KS_iMASK_COLORS];\n    KS_TRUECOLORINFO TrueColorInfo;\n  };\n}KS_VIDEOINFO, * PKS_VIDEOINFO;\n\n # define KS_SIZE_MASKS (KS_iMASK_COLORS * sizeof(DWORD))\n # define KS_SIZE_PREHEADER (FIELD_OFFSET(KS_VIDEOINFOHEADER, bmiHeader))\n\n # define KS_SIZE_VIDEOHEADER(pbmi) ((pbmi)->bmiHeader.biSize + KS_SIZE_PREHEADER)\n\ntypedef struct tagKS_VBIINFOHEADER\n{\n  ULONG StartLine;\n  ULONG EndLine;\n  ULONG SamplingFrequency;\n  ULONG MinLineStartTime;\n  ULONG MaxLineStartTime;\n  ULONG ActualLineStartTime;\n  ULONG ActualLineEndTime;\n  ULONG VideoStandard;\n  ULONG SamplesPerLine;\n  ULONG StrideInBytes;\n  ULONG BufferSize;\n}KS_VBIINFOHEADER, * PKS_VBIINFOHEADER;\n\n # define KS_VBIDATARATE_NABTS (5727272L)\n # define KS_VBIDATARATE_CC (503493L)\n # define KS_VBISAMPLINGRATE_4X_NABTS ((long)(4 * KS_VBIDATARATE_NABTS))\n # define KS_VBISAMPLINGRATE_47X_NABTS ((long)(27000000))\n # define KS_VBISAMPLINGRATE_5X_NABTS ((long)(5 * KS_VBIDATARATE_NABTS))\n\n # define KS_47NABTS_SCALER (KS_VBISAMPLINGRATE_47X_NABTS / (double)KS_VBIDATARATE_NABTS)\n\ntypedef struct tagKS_AnalogVideoInfo\n{\n  RECT rcSource;\n  RECT rcTarget;\n  DWORD dwActiveWidth;\n  DWORD dwActiveHeight;\n  REFERENCE_TIME AvgTimePerFrame;\n}KS_ANALOGVIDEOINFO, * PKS_ANALOGVIDEOINFO;\n\n # define KS_TVTUNER_CHANGE_BEGIN_TUNE 0x0001L\n # define KS_TVTUNER_CHANGE_END_TUNE 0x0002L\n\ntypedef struct tagKS_TVTUNER_CHANGE_INFO\n{\n  DWORD dwFlags;\n  DWORD dwCountryCode;\n  DWORD dwAnalogVideoStandard;\n  DWORD dwChannel;\n}KS_TVTUNER_CHANGE_INFO, * PKS_TVTUNER_CHANGE_INFO;\n\ntypedef enum\n{\n  KS_MPEG2Level_Low,\n  KS_MPEG2Level_Main,\n  KS_MPEG2Level_High1440,\n  KS_MPEG2Level_High\n}KS_MPEG2Level;\n\ntypedef enum\n{\n  KS_MPEG2Profile_Simple,\n  KS_MPEG2Profile_Main,\n  KS_MPEG2Profile_SNRScalable,\n  KS_MPEG2Profile_SpatiallyScalable,\n  KS_MPEG2Profile_High\n}KS_MPEG2Profile;\n\n # define KS_INTERLACE_IsInterlaced 0x00000001\n # define KS_INTERLACE_1FieldPerSample 0x00000002\n # define KS_INTERLACE_Field1First 0x00000004\n # define KS_INTERLACE_UNUSED 0x00000008\n # define KS_INTERLACE_FieldPatternMask 0x00000030\n # define KS_INTERLACE_FieldPatField1Only 0x00000000\n # define KS_INTERLACE_FieldPatField2Only 0x00000010\n # define KS_INTERLACE_FieldPatBothRegular 0x00000020\n # define KS_INTERLACE_FieldPatBothIrregular 0x00000030\n # define KS_INTERLACE_DisplayModeMask 0x000000c0\n # define KS_INTERLACE_DisplayModeBobOnly 0x00000000\n # define KS_INTERLACE_DisplayModeWeaveOnly 0x00000040\n # define KS_INTERLACE_DisplayModeBobOrWeave 0x00000080\n\n # define KS_MPEG2_DoPanScan 0x00000001\n # define KS_MPEG2_DVDLine21Field1 0x00000002\n # define KS_MPEG2_DVDLine21Field2 0x00000004\n # define KS_MPEG2_SourceIsLetterboxed 0x00000008\n # define KS_MPEG2_FilmCameraMode 0x00000010\n # define KS_MPEG2_LetterboxAnalogOut 0x00000020\n # define KS_MPEG2_DSS_UserData 0x00000040\n # define KS_MPEG2_DVB_UserData 0x00000080\n # define KS_MPEG2_27MhzTimebase 0x00000100\n\ntypedef struct tagKS_VIDEOINFOHEADER2\n{\n  RECT rcSource;\n  RECT rcTarget;\n  DWORD dwBitRate;\n  DWORD dwBitErrorRate;\n  REFERENCE_TIME AvgTimePerFrame;\n  DWORD dwInterlaceFlags;\n  DWORD dwCopyProtectFlags;\n  DWORD dwPictAspectRatioX;\n  DWORD dwPictAspectRatioY;\n  DWORD dwReserved1;\n  DWORD dwReserved2;\n  KS_BITMAPINFOHEADER bmiHeader;\n}KS_VIDEOINFOHEADER2, * PKS_VIDEOINFOHEADER2;\n\ntypedef struct tagKS_MPEG1VIDEOINFO\n{\n  KS_VIDEOINFOHEADER hdr;\n  DWORD dwStartTimeCode;\n  DWORD cbSequenceHeader;\n  BYTE bSequenceHeader[1];\n}KS_MPEG1VIDEOINFO, * PKS_MPEG1VIDEOINFO;\n\n # define KS_MAX_SIZE_MPEG1_SEQUENCE_INFO 140\n # define KS_SIZE_MPEG1VIDEOINFO(pv) (FIELD_OFFSET(KS_MPEG1VIDEOINFO, bSequenceHeader[0]) + (pv)->cbSequenceHeader)\n # define KS_MPEG1_SEQUENCE_INFO(pv) ((const BYTE*)(pv)->bSequenceHeader)\n\ntypedef struct tagKS_MPEGVIDEOINFO2\n{\n  KS_VIDEOINFOHEADER2 hdr;\n  DWORD dwStartTimeCode;\n  DWORD cbSequenceHeader;\n  DWORD dwProfile;\n  DWORD dwLevel;\n  DWORD dwFlags;\n  DWORD bSequenceHeader[1];\n}KS_MPEGVIDEOINFO2, * PKS_MPEGVIDEOINFO2;\n\n # define KS_SIZE_MPEGVIDEOINFO2(pv) (FIELD_OFFSET(KS_MPEGVIDEOINFO2, bSequenceHeader[0]) + (pv)->cbSequenceHeader)\n # define KS_MPEG1_SEQUENCE_INFO(pv) ((const BYTE*)(pv)->bSequenceHeader)\n\n # define KS_MPEGAUDIOINFO_27MhzTimebase 0x00000001\n\ntypedef struct tagKS_MPEAUDIOINFO\n{\n  DWORD dwFlags;\n  DWORD dwReserved1;\n  DWORD dwReserved2;\n  DWORD dwReserved3;\n}KS_MPEGAUDIOINFO, * PKS_MPEGAUDIOINFO;\n\ntypedef struct tagKS_DATAFORMAT_VIDEOINFOHEADER\n{\n  KSDATAFORMAT DataFormat;\n  KS_VIDEOINFOHEADER VideoInfoHeader;\n}KS_DATAFORMAT_VIDEOINFOHEADER, * PKS_DATAFORMAT_VIDEOINFOHEADER;\n\ntypedef struct tagKS_DATAFORMAT_VIDEOINFOHEADER2\n{\n  KSDATAFORMAT DataFormat;\n  KS_VIDEOINFOHEADER2 VideoInfoHeader2;\n}KS_DATAFORMAT_VIDEOINFOHEADER2, * PKS_DATAFORMAT_VIDEOINFOHEADER2;\n\ntypedef struct tagKS_DATAFORMAT_VIDEOINFO_PALETTE\n{\n  KSDATAFORMAT DataFormat;\n  KS_VIDEOINFO VideoInfo;\n}KS_DATAFORMAT_VIDEOINFO_PALETTE, * PKS_DATAFORMAT_VIDEOINFO_PALETTE;\n\ntypedef struct tagKS_DATAFORMAT_VBIINFOHEADER\n{\n  KSDATAFORMAT DataFormat;\n  KS_VBIINFOHEADER VBIInfoHeader;\n}KS_DATAFORMAT_VBIINFOHEADER, * PKS_DATAFORMAT_VBIINFOHEADER;\n\ntypedef struct _KS_VIDEO_STREAM_CONFIG_CAPS\n{\n  GUID guid;\n  ULONG VideoStandard;\n  SIZE InputSize;\n  SIZE MinCroppingSize;\n  SIZE MaxCroppingSize;\n  int CropGranularityX;\n  int CropGranularityY;\n  int CropAlignX;\n  int CropAlignY;\n  SIZE MinOutputSize;\n  SIZE MaxOutputSize;\n  int OutputGranularityX;\n  int OutputGranularityY;\n  int StretchTapsX;\n  int StretchTapsY;\n  int ShrinkTapsX;\n  int ShrinkTapsY;\n  LONGLONG MinFrameInterval;\n  LONGLONG MaxFrameInterval;\n  LONG MinBitsPerSecond;\n  LONG MaxBitsPerSecond;\n}KS_VIDEO_STREAM_CONFIG_CAPS, * PKS_VIDEO_STREAM_CONFIG_CAPS;\n\ntypedef struct tagKS_DATARANGE_VIDEO\n{\n  KSDATARANGE DataRange;\n  WINBOOL bFixedSizeSamples;\n  WINBOOL bTemporalCompression;\n  DWORD StreamDescriptionFlags;\n  DWORD MemoryAllocationFlags;\n  KS_VIDEO_STREAM_CONFIG_CAPS ConfigCaps;\n  KS_VIDEOINFOHEADER VideoInfoHeader;\n}KS_DATARANGE_VIDEO, * PKS_DATARANGE_VIDEO;\n\ntypedef struct tagKS_DATARANGE_VIDEO2\n{\n  KSDATARANGE DataRange;\n  WINBOOL bFixedSizeSamples;\n  WINBOOL bTemporalCompression;\n  DWORD StreamDescriptionFlags;\n  DWORD MemoryAllocationFlags;\n  KS_VIDEO_STREAM_CONFIG_CAPS ConfigCaps;\n  KS_VIDEOINFOHEADER2 VideoInfoHeader;\n}KS_DATARANGE_VIDEO2, * PKS_DATARANGE_VIDEO2;\n\ntypedef struct tagKS_DATARANGE_MPEG1_VIDEO\n{\n  KSDATARANGE DataRange;\n  WINBOOL bFixedSizeSamples;\n  WINBOOL bTemporalCompression;\n  DWORD StreamDescriptionFlags;\n  DWORD MemoryAllocationFlags;\n  KS_VIDEO_STREAM_CONFIG_CAPS ConfigCaps;\n  KS_MPEG1VIDEOINFO VideoInfoHeader;\n}KS_DATARANGE_MPEG1_VIDEO, * PKS_DATARANGE_MPEG1_VIDEO;\n\ntypedef struct tagKS_DATARANGE_MPEG2_VIDEO\n{\n  KSDATARANGE DataRange;\n  WINBOOL bFixedSizeSamples;\n  WINBOOL bTemporalCompression;\n  DWORD StreamDescriptionFlags;\n  DWORD MemoryAllocationFlags;\n  KS_VIDEO_STREAM_CONFIG_CAPS ConfigCaps;\n  KS_MPEGVIDEOINFO2 VideoInfoHeader;\n}KS_DATARANGE_MPEG2_VIDEO, * PKS_DATARANGE_MPEG2_VIDEO;\n\ntypedef struct tagKS_DATARANGE_VIDEO_PALETTE\n{\n  KSDATARANGE DataRange;\n  WINBOOL bFixedSizeSamples;\n  WINBOOL bTemporalCompression;\n  DWORD StreamDescriptionFlags;\n  DWORD MemoryAllocationFlags;\n  KS_VIDEO_STREAM_CONFIG_CAPS ConfigCaps;\n  KS_VIDEOINFO VideoInfo;\n}KS_DATARANGE_VIDEO_PALETTE, * PKS_DATARANGE_VIDEO_PALETTE;\n\ntypedef struct tagKS_DATARANGE_VIDEO_VBI\n{\n  KSDATARANGE DataRange;\n  WINBOOL bFixedSizeSamples;\n  WINBOOL bTemporalCompression;\n  DWORD StreamDescriptionFlags;\n  DWORD MemoryAllocationFlags;\n  KS_VIDEO_STREAM_CONFIG_CAPS ConfigCaps;\n  KS_VBIINFOHEADER VBIInfoHeader;\n}KS_DATARANGE_VIDEO_VBI, * PKS_DATARANGE_VIDEO_VBI;\n\ntypedef struct tagKS_DATARANGE_ANALOGVIDEO\n{\n  KSDATARANGE DataRange;\n  KS_ANALOGVIDEOINFO AnalogVideoInfo;\n}KS_DATARANGE_ANALOGVIDEO, * PKS_DATARANGE_ANALOGVIDEO;\n\n # define KS_VIDEOSTREAM_PREVIEW 0x0001\n # define KS_VIDEOSTREAM_CAPTURE 0x0002\n # define KS_VIDEOSTREAM_VBI 0x0010\n # define KS_VIDEOSTREAM_NABTS 0x0020\n # define KS_VIDEOSTREAM_CC 0x0100\n # define KS_VIDEOSTREAM_EDS 0x0200\n # define KS_VIDEOSTREAM_TELETEXT 0x0400\n # define KS_VIDEOSTREAM_STILL 0x1000\n # define KS_VIDEOSTREAM_IS_VPE 0x8000\n\n # define KS_VIDEO_ALLOC_VPE_SYSTEM 0x0001\n # define KS_VIDEO_ALLOC_VPE_DISPLAY 0x0002\n # define KS_VIDEO_ALLOC_VPE_AGP 0x0004\n\n # define STATIC_KSPROPSETID_VBICAP_PROPERTIES                \\\n  0xf162c607, 0x7b35, 0x496f, 0xad, 0x7f, 0x2d, 0xca, 0x3b, 0x46, 0xb7, 0x18\nDEFINE_GUIDSTRUCT(\"F162C607-7B35-496f-AD7F-2DCA3B46B718\", KSPROPSETID_VBICAP_PROPERTIES);\n # define KSPROPSETID_VBICAP_PROPERTIES DEFINE_GUIDNAMED(KSPROPSETID_VBICAP_PROPERTIES)\n\ntypedef enum\n{\n  KSPROPERTY_VBICAP_PROPERTIES_PROTECTION = 0x01\n}KSPROPERTY_VBICAP;\n\ntypedef struct _VBICAP_PROPERTIES_PROTECTION_S\n{\n  KSPROPERTY Property;\n  ULONG StreamIndex;\n  ULONG Status;\n}VBICAP_PROPERTIES_PROTECTION_S, * PVBICAP_PROPERTIES_PROTECTION_S;\n\n # define KS_VBICAP_PROTECTION_MV_PRESENT 0x0001L\n # define KS_VBICAP_PROTECTION_MV_HARDWARE 0x0002L\n # define KS_VBICAP_PROTECTION_MV_DETECTED 0x0004L\n\n # define KS_NABTS_GROUPID_ORIGINAL_CONTENT_BASE 0x800\n # define KS_NABTS_GROUPID_ORIGINAL_CONTENT_ADVERTISER_BASE 0x810\n\n # define KS_NABTS_GROUPID_PRODUCTION_COMPANY_CONTENT_BASE 0x820\n # define KS_NABTS_GROUPID_PRODUCTION_COMPANY_ADVERTISER_BASE 0x830\n\n # define KS_NABTS_GROUPID_SYNDICATED_SHOW_CONTENT_BASE 0x840\n # define KS_NABTS_GROUPID_SYNDICATED_SHOW_ADVERTISER_BASE 0x850\n\n # define KS_NABTS_GROUPID_NETWORK_WIDE_CONTENT_BASE 0x860\n # define KS_NABTS_GROUPID_NETWORK_WIDE_ADVERTISER_BASE 0x870\n\n # define KS_NABTS_GROUPID_TELEVISION_STATION_CONTENT_BASE 0x880\n # define KS_NABTS_GROUPID_TELEVISION_STATION_ADVERTISER_BASE 0x890\n\n # define KS_NABTS_GROUPID_LOCAL_CABLE_SYSTEM_CONTENT_BASE 0x8A0\n # define KS_NABTS_GROUPID_LOCAL_CABLE_SYSTEM_ADVERTISER_BASE 0x8B0\n\n # define KS_NABTS_GROUPID_MICROSOFT_RESERVED_TEST_DATA_BASE 0x8F0\n\n # define STATIC_KSDATAFORMAT_TYPE_NABTS                  \\\n  0xe757bca0, 0x39ac, 0x11d1, 0xa9, 0xf5, 0x0, 0xc0, 0x4f, 0xbb, 0xde, 0x8f\nDEFINE_GUIDSTRUCT(\"E757BCA0-39AC-11d1-A9F5-00C04FBBDE8F\", KSDATAFORMAT_TYPE_NABTS);\n # define KSDATAFORMAT_TYPE_NABTS DEFINE_GUIDNAMED(KSDATAFORMAT_TYPE_NABTS)\n\n # define STATIC_KSDATAFORMAT_SUBTYPE_NABTS_FEC               \\\n  0xe757bca1, 0x39ac, 0x11d1, 0xa9, 0xf5, 0x0, 0xc0, 0x4f, 0xbb, 0xde, 0x8f\nDEFINE_GUIDSTRUCT(\"E757BCA1-39AC-11d1-A9F5-00C04FBBDE8F\", KSDATAFORMAT_SUBTYPE_NABTS_FEC);\n # define KSDATAFORMAT_SUBTYPE_NABTS_FEC DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_NABTS_FEC)\n\n # define MAX_NABTS_VBI_LINES_PER_FIELD 11\n # define NABTS_LINES_PER_BUNDLE 16\n # define NABTS_PAYLOAD_PER_LINE 28\n # define NABTS_BYTES_PER_LINE 36\n\ntypedef struct _NABTSFEC_BUFFER\n{\n  ULONG dataSize;\n  USHORT groupID;\n  USHORT Reserved;\n  UCHAR data[NABTS_LINES_PER_BUNDLE * NABTS_PAYLOAD_PER_LINE];\n}NABTSFEC_BUFFER, * PNABTSFEC_BUFFER;\n\n # define STATIC_KSPROPSETID_VBICodecFiltering                \\\n  0xcafeb0caL, 0x8715, 0x11d0, 0xbd, 0x6a, 0x00, 0x35, 0xc0, 0xed, 0xba, 0xbe\nDEFINE_GUIDSTRUCT(\"cafeb0ca-8715-11d0-bd6a-0035c0edbabe\", KSPROPSETID_VBICodecFiltering);\n # define KSPROPSETID_VBICodecFiltering DEFINE_GUIDNAMED(KSPROPSETID_VBICodecFiltering)\n\ntypedef enum\n{\n  KSPROPERTY_VBICODECFILTERING_SCANLINES_REQUESTED_BIT_ARRAY = 0x01,\n  KSPROPERTY_VBICODECFILTERING_SCANLINES_DISCOVERED_BIT_ARRAY,\n  KSPROPERTY_VBICODECFILTERING_SUBSTREAMS_REQUESTED_BIT_ARRAY,\n  KSPROPERTY_VBICODECFILTERING_SUBSTREAMS_DISCOVERED_BIT_ARRAY,\n  KSPROPERTY_VBICODECFILTERING_STATISTICS\n}KSPROPERTY_VBICODECFILTERING;\n\ntypedef struct _VBICODECFILTERING_SCANLINES\n{\n  DWORD DwordBitArray[32];\n}VBICODECFILTERING_SCANLINES, * PVBICODECFILTERING_SCANLINES;\n\ntypedef struct _VBICODECFILTERING_NABTS_SUBSTREAMS\n{\n  DWORD SubstreamMask[128];\n}VBICODECFILTERING_NABTS_SUBSTREAMS, * PVBICODECFILTERING_NABTS_SUBSTREAMS;\n\ntypedef struct _VBICODECFILTERING_CC_SUBSTREAMS\n{\n  DWORD SubstreamMask;\n}VBICODECFILTERING_CC_SUBSTREAMS, * PVBICODECFILTERING_CC_SUBSTREAMS;\n\n # define KS_CC_SUBSTREAM_ODD 0x0001L\n # define KS_CC_SUBSTREAM_EVEN 0x0002L\n\n # define KS_CC_SUBSTREAM_FIELD1_MASK 0x00F0L\n # define KS_CC_SUBSTREAM_SERVICE_CC1 0x0010L\n # define KS_CC_SUBSTREAM_SERVICE_CC2 0x0020L\n # define KS_CC_SUBSTREAM_SERVICE_T1 0x0040L\n # define KS_CC_SUBSTREAM_SERVICE_T2 0x0080L\n\n # define KS_CC_SUBSTREAM_FIELD2_MASK 0x1F00L\n # define KS_CC_SUBSTREAM_SERVICE_CC3 0x0100L\n # define KS_CC_SUBSTREAM_SERVICE_CC4 0x0200L\n # define KS_CC_SUBSTREAM_SERVICE_T3 0x0400L\n # define KS_CC_SUBSTREAM_SERVICE_T4 0x0800L\n # define KS_CC_SUBSTREAM_SERVICE_XDS 0x1000L\n\n # define CC_MAX_HW_DECODE_LINES 12\ntypedef struct _CC_BYTE_PAIR\n{\n  BYTE Decoded[2];\n  USHORT Reserved;\n}CC_BYTE_PAIR, * PCC_BYTE_PAIR;\n\ntypedef struct _CC_HW_FIELD\n{\n  VBICODECFILTERING_SCANLINES ScanlinesRequested;\n  ULONG fieldFlags;\n  LONGLONG PictureNumber;\n  CC_BYTE_PAIR Lines[CC_MAX_HW_DECODE_LINES];\n}CC_HW_FIELD, * PCC_HW_FIELD;\n\n # ifndef PACK_PRAGMAS_NOT_SUPPORTED\n  #  include <pshpack1.h>\n # endif\ntypedef struct _NABTS_BUFFER_LINE\n{\n  BYTE Confidence;\n  BYTE Bytes[NABTS_BYTES_PER_LINE];\n}NABTS_BUFFER_LINE, * PNABTS_BUFFER_LINE;\n\n # define NABTS_BUFFER_PICTURENUMBER_SUPPORT 1\ntypedef struct _NABTS_BUFFER\n{\n  VBICODECFILTERING_SCANLINES ScanlinesRequested;\n  LONGLONG PictureNumber;\n  NABTS_BUFFER_LINE NabtsLines[MAX_NABTS_VBI_LINES_PER_FIELD];\n}NABTS_BUFFER, * PNABTS_BUFFER;\n # ifndef PACK_PRAGMAS_NOT_SUPPORTED\n  #  include <poppack.h>\n # endif\n\n # define WST_TVTUNER_CHANGE_BEGIN_TUNE 0x1000L\n # define WST_TVTUNER_CHANGE_END_TUNE 0x2000L\n\n # define MAX_WST_VBI_LINES_PER_FIELD 17\n # define WST_BYTES_PER_LINE 42\n\ntypedef struct _WST_BUFFER_LINE\n{\n  BYTE Confidence;\n  BYTE Bytes[WST_BYTES_PER_LINE];\n}WST_BUFFER_LINE, * PWST_BUFFER_LINE;\n\ntypedef struct _WST_BUFFER\n{\n  VBICODECFILTERING_SCANLINES ScanlinesRequested;\n  WST_BUFFER_LINE WstLines[MAX_WST_VBI_LINES_PER_FIELD];\n}WST_BUFFER, * PWST_BUFFER;\n\ntypedef struct _VBICODECFILTERING_STATISTICS_COMMON\n{\n  DWORD InputSRBsProcessed;\n  DWORD OutputSRBsProcessed;\n  DWORD SRBsIgnored;\n  DWORD InputSRBsMissing;\n  DWORD OutputSRBsMissing;\n  DWORD OutputFailures;\n  DWORD InternalErrors;\n  DWORD ExternalErrors;\n  DWORD InputDiscontinuities;\n  DWORD DSPFailures;\n  DWORD TvTunerChanges;\n  DWORD VBIHeaderChanges;\n  DWORD LineConfidenceAvg;\n  DWORD BytesOutput;\n}VBICODECFILTERING_STATISTICS_COMMON, * PVBICODECFILTERING_STATISTICS_COMMON;\n\ntypedef struct _VBICODECFILTERING_STATISTICS_COMMON_PIN\n{\n  DWORD SRBsProcessed;\n  DWORD SRBsIgnored;\n  DWORD SRBsMissing;\n  DWORD InternalErrors;\n  DWORD ExternalErrors;\n  DWORD Discontinuities;\n  DWORD LineConfidenceAvg;\n  DWORD BytesOutput;\n}VBICODECFILTERING_STATISTICS_COMMON_PIN, * PVBICODECFILTERING_STATISTICS_COMMON_PIN;\n\ntypedef struct _VBICODECFILTERING_STATISTICS_NABTS\n{\n  VBICODECFILTERING_STATISTICS_COMMON Common;\n  DWORD FECBundleBadLines;\n  DWORD FECQueueOverflows;\n  DWORD FECCorrectedLines;\n  DWORD FECUncorrectableLines;\n  DWORD BundlesProcessed;\n  DWORD BundlesSent2IP;\n  DWORD FilteredLines;\n}VBICODECFILTERING_STATISTICS_NABTS, * PVBICODECFILTERING_STATISTICS_NABTS;\n\ntypedef struct _VBICODECFILTERING_STATISTICS_NABTS_PIN\n{\n  VBICODECFILTERING_STATISTICS_COMMON_PIN Common;\n}VBICODECFILTERING_STATISTICS_NABTS_PIN, * PVBICODECFILTERING_STATISTICS_NABTS_PIN;\n\ntypedef struct _VBICODECFILTERING_STATISTICS_CC\n{\n  VBICODECFILTERING_STATISTICS_COMMON Common;\n}VBICODECFILTERING_STATISTICS_CC, * PVBICODECFILTERING_STATISTICS_CC;\n\ntypedef struct _VBICODECFILTERING_STATISTICS_CC_PIN\n{\n  VBICODECFILTERING_STATISTICS_COMMON_PIN Common;\n}VBICODECFILTERING_STATISTICS_CC_PIN, * PVBICODECFILTERING_STATISTICS_CC_PIN;\n\ntypedef struct _VBICODECFILTERING_STATISTICS_TELETEXT\n{\n  VBICODECFILTERING_STATISTICS_COMMON Common;\n}VBICODECFILTERING_STATISTICS_TELETEXT, * PVBICODECFILTERING_STATISTICS_TELETEXT;\n\ntypedef struct _VBICODECFILTERING_STATISTICS_TELETEXT_PIN\n{\n  VBICODECFILTERING_STATISTICS_COMMON_PIN Common;\n}VBICODECFILTERING_STATISTICS_TELETEXT_PIN, * PVBICODECFILTERING_STATISTICS_TELETEXT_PIN;\n\ntypedef struct\n{\n  KSPROPERTY Property;\n  VBICODECFILTERING_SCANLINES Scanlines;\n}KSPROPERTY_VBICODECFILTERING_SCANLINES_S, * PKSPROPERTY_VBICODECFILTERING_SCANLINES_S;\n\ntypedef struct\n{\n  KSPROPERTY Property;\n  VBICODECFILTERING_NABTS_SUBSTREAMS Substreams;\n}KSPROPERTY_VBICODECFILTERING_NABTS_SUBSTREAMS_S, * PKSPROPERTY_VBICODECFILTERING_NABTS_SUBSTREAMS_S;\n\ntypedef struct\n{\n  KSPROPERTY Property;\n  VBICODECFILTERING_CC_SUBSTREAMS Substreams;\n}KSPROPERTY_VBICODECFILTERING_CC_SUBSTREAMS_S, * PKSPROPERTY_VBICODECFILTERING_CC_SUBSTREAMS_S;\n\ntypedef struct\n{\n  KSPROPERTY Property;\n  VBICODECFILTERING_STATISTICS_COMMON Statistics;\n}KSPROPERTY_VBICODECFILTERING_STATISTICS_COMMON_S, * PKSPROPERTY_VBICODECFILTERING_STATISTICS_COMMON_S;\n\ntypedef struct\n{\n  KSPROPERTY Property;\n  VBICODECFILTERING_STATISTICS_COMMON_PIN Statistics;\n}KSPROPERTY_VBICODECFILTERING_STATISTICS_COMMON_PIN_S, * PKSPROPERTY_VBICODECFILTERING_STATISTICS_COMMON_PIN_S;\n\ntypedef struct\n{\n  KSPROPERTY Property;\n  VBICODECFILTERING_STATISTICS_NABTS Statistics;\n}KSPROPERTY_VBICODECFILTERING_STATISTICS_NABTS_S, * PKSPROPERTY_VBICODECFILTERING_STATISTICS_NABTS_S;\n\ntypedef struct\n{\n  KSPROPERTY Property;\n  VBICODECFILTERING_STATISTICS_NABTS_PIN Statistics;\n}KSPROPERTY_VBICODECFILTERING_STATISTICS_NABTS_PIN_S, * PKSPROPERTY_VBICODECFILTERING_STATISTICS_NABTS_PIN_S;\n\ntypedef struct\n{\n  KSPROPERTY Property;\n  VBICODECFILTERING_STATISTICS_CC Statistics;\n}KSPROPERTY_VBICODECFILTERING_STATISTICS_CC_S, * PKSPROPERTY_VBICODECFILTERING_STATISTICS_CC_S;\n\ntypedef struct\n{\n  KSPROPERTY Property;\n  VBICODECFILTERING_STATISTICS_CC_PIN Statistics;\n}KSPROPERTY_VBICODECFILTERING_STATISTICS_CC_PIN_S, * PKSPROPERTY_VBICODECFILTERING_STATISTICS_CC_PIN_S;\n\n # define STATIC_PINNAME_VIDEO_CAPTURE                    \\\n  0xfb6c4281, 0x353, 0x11d1, 0x90, 0x5f, 0x0, 0x0, 0xc0, 0xcc, 0x16, 0xba\n # define STATIC_PINNAME_CAPTURE STATIC_PINNAME_VIDEO_CAPTURE\nDEFINE_GUIDSTRUCT(\"FB6C4281-0353-11d1-905F-0000C0CC16BA\", PINNAME_VIDEO_CAPTURE);\n # define PINNAME_VIDEO_CAPTURE DEFINE_GUIDNAMED(PINNAME_VIDEO_CAPTURE)\n # define PINNAME_CAPTURE PINNAME_VIDEO_CAPTURE\n\n # define STATIC_PINNAME_VIDEO_CC_CAPTURE                 \\\n  0x1aad8061, 0x12d, 0x11d2, 0xb4, 0xb1, 0x0, 0xa0, 0xd1, 0x2, 0xcf, 0xbe\n # define STATIC_PINNAME_CC_CAPTURE STATIC_PINNAME_VIDEO_CC_CAPTURE\nDEFINE_GUIDSTRUCT(\"1AAD8061-012D-11d2-B4B1-00A0D102CFBE\", PINNAME_VIDEO_CC_CAPTURE);\n # define PINNAME_VIDEO_CC_CAPTURE DEFINE_GUIDNAMED(PINNAME_VIDEO_CC_CAPTURE)\n\n # define STATIC_PINNAME_VIDEO_NABTS_CAPTURE              \\\n  0x29703660, 0x498a, 0x11d2, 0xb4, 0xb1, 0x0, 0xa0, 0xd1, 0x2, 0xcf, 0xbe\n # define STATIC_PINNAME_NABTS_CAPTURE STATIC_PINNAME_VIDEO_NABTS_CAPTURE\nDEFINE_GUIDSTRUCT(\"29703660-498A-11d2-B4B1-00A0D102CFBE\", PINNAME_VIDEO_NABTS_CAPTURE);\n # define PINNAME_VIDEO_NABTS_CAPTURE DEFINE_GUIDNAMED(PINNAME_VIDEO_NABTS_CAPTURE)\n\n # define STATIC_PINNAME_VIDEO_PREVIEW                    \\\n  0xfb6c4282, 0x353, 0x11d1, 0x90, 0x5f, 0x0, 0x0, 0xc0, 0xcc, 0x16, 0xba\n # define STATIC_PINNAME_PREVIEW STATIC_PINNAME_VIDEO_PREVIEW\nDEFINE_GUIDSTRUCT(\"FB6C4282-0353-11d1-905F-0000C0CC16BA\", PINNAME_VIDEO_PREVIEW);\n # define PINNAME_VIDEO_PREVIEW DEFINE_GUIDNAMED(PINNAME_VIDEO_PREVIEW)\n # define PINNAME_PREVIEW PINNAME_VIDEO_PREVIEW\n\n # define STATIC_PINNAME_VIDEO_ANALOGVIDEOIN              \\\n  0xfb6c4283, 0x353, 0x11d1, 0x90, 0x5f, 0x0, 0x0, 0xc0, 0xcc, 0x16, 0xba\nDEFINE_GUIDSTRUCT(\"FB6C4283-0353-11d1-905F-0000C0CC16BA\", PINNAME_VIDEO_ANALOGVIDEOIN);\n # define PINNAME_VIDEO_ANALOGVIDEOIN DEFINE_GUIDNAMED(PINNAME_VIDEO_ANALOGVIDEOIN)\n\n # define STATIC_PINNAME_VIDEO_VBI                    \\\n  0xfb6c4284, 0x353, 0x11d1, 0x90, 0x5f, 0x0, 0x0, 0xc0, 0xcc, 0x16, 0xba\nDEFINE_GUIDSTRUCT(\"FB6C4284-0353-11d1-905F-0000C0CC16BA\", PINNAME_VIDEO_VBI);\n # define PINNAME_VIDEO_VBI DEFINE_GUIDNAMED(PINNAME_VIDEO_VBI)\n\n # define STATIC_PINNAME_VIDEO_VIDEOPORT                  \\\n  0xfb6c4285, 0x353, 0x11d1, 0x90, 0x5f, 0x0, 0x0, 0xc0, 0xcc, 0x16, 0xba\nDEFINE_GUIDSTRUCT(\"FB6C4285-0353-11d1-905F-0000C0CC16BA\", PINNAME_VIDEO_VIDEOPORT);\n # define PINNAME_VIDEO_VIDEOPORT DEFINE_GUIDNAMED(PINNAME_VIDEO_VIDEOPORT)\n\n # define STATIC_PINNAME_VIDEO_NABTS                  \\\n  0xfb6c4286, 0x353, 0x11d1, 0x90, 0x5f, 0x0, 0x0, 0xc0, 0xcc, 0x16, 0xba\nDEFINE_GUIDSTRUCT(\"FB6C4286-0353-11d1-905F-0000C0CC16BA\", PINNAME_VIDEO_NABTS);\n # define PINNAME_VIDEO_NABTS DEFINE_GUIDNAMED(PINNAME_VIDEO_NABTS)\n\n # define STATIC_PINNAME_VIDEO_EDS                    \\\n  0xfb6c4287, 0x353, 0x11d1, 0x90, 0x5f, 0x0, 0x0, 0xc0, 0xcc, 0x16, 0xba\nDEFINE_GUIDSTRUCT(\"FB6C4287-0353-11d1-905F-0000C0CC16BA\", PINNAME_VIDEO_EDS);\n # define PINNAME_VIDEO_EDS DEFINE_GUIDNAMED(PINNAME_VIDEO_EDS)\n\n # define STATIC_PINNAME_VIDEO_TELETEXT                   \\\n  0xfb6c4288, 0x353, 0x11d1, 0x90, 0x5f, 0x0, 0x0, 0xc0, 0xcc, 0x16, 0xba\nDEFINE_GUIDSTRUCT(\"FB6C4288-0353-11d1-905F-0000C0CC16BA\", PINNAME_VIDEO_TELETEXT);\n # define PINNAME_VIDEO_TELETEXT DEFINE_GUIDNAMED(PINNAME_VIDEO_TELETEXT)\n\n # define STATIC_PINNAME_VIDEO_CC                     \\\n  0xfb6c4289, 0x353, 0x11d1, 0x90, 0x5f, 0x0, 0x0, 0xc0, 0xcc, 0x16, 0xba\nDEFINE_GUIDSTRUCT(\"FB6C4289-0353-11d1-905F-0000C0CC16BA\", PINNAME_VIDEO_CC);\n # define PINNAME_VIDEO_CC DEFINE_GUIDNAMED(PINNAME_VIDEO_CC)\n\n # define STATIC_PINNAME_VIDEO_STILL                  \\\n  0xfb6c428A, 0x353, 0x11d1, 0x90, 0x5f, 0x0, 0x0, 0xc0, 0xcc, 0x16, 0xba\nDEFINE_GUIDSTRUCT(\"FB6C428A-0353-11d1-905F-0000C0CC16BA\", PINNAME_VIDEO_STILL);\n # define PINNAME_VIDEO_STILL DEFINE_GUIDNAMED(PINNAME_VIDEO_STILL)\n\n # define STATIC_PINNAME_VIDEO_TIMECODE                   \\\n  0xfb6c428B, 0x353, 0x11d1, 0x90, 0x5f, 0x0, 0x0, 0xc0, 0xcc, 0x16, 0xba\nDEFINE_GUIDSTRUCT(\"FB6C428B-0353-11d1-905F-0000C0CC16BA\", PINNAME_VIDEO_TIMECODE);\n # define PINNAME_VIDEO_TIMECODE DEFINE_GUIDNAMED(PINNAME_VIDEO_TIMECODE)\n\n # define STATIC_PINNAME_VIDEO_VIDEOPORT_VBI              \\\n  0xfb6c428C, 0x353, 0x11d1, 0x90, 0x5f, 0x0, 0x0, 0xc0, 0xcc, 0x16, 0xba\nDEFINE_GUIDSTRUCT(\"FB6C428C-0353-11d1-905F-0000C0CC16BA\", PINNAME_VIDEO_VIDEOPORT_VBI);\n # define PINNAME_VIDEO_VIDEOPORT_VBI DEFINE_GUIDNAMED(PINNAME_VIDEO_VIDEOPORT_VBI)\n\n # define KS_VIDEO_FLAG_FRAME 0x0000L\n # define KS_VIDEO_FLAG_FIELD1 0x0001L\n # define KS_VIDEO_FLAG_FIELD2 0x0002L\n\n # define KS_VIDEO_FLAG_I_FRAME 0x0000L\n # define KS_VIDEO_FLAG_P_FRAME 0x0010L\n # define KS_VIDEO_FLAG_B_FRAME 0x0020L\n\ntypedef struct tagKS_FRAME_INFO\n{\n  ULONG ExtendedHeaderSize;\n  DWORD dwFrameFlags;\n  LONGLONG PictureNumber;\n  LONGLONG DropCount;\n  HANDLE hDirectDraw;\n  HANDLE hSurfaceHandle;\n  RECT DirectDrawRect;\n\n  DWORD Reserved1;\n  DWORD Reserved2;\n  DWORD Reserved3;\n  DWORD Reserved4;\n}KS_FRAME_INFO, * PKS_FRAME_INFO;\n\n # define KS_VBI_FLAG_FIELD1 0x0001L\n # define KS_VBI_FLAG_FIELD2 0x0002L\n\n # define KS_VBI_FLAG_MV_PRESENT 0x0100L\n # define KS_VBI_FLAG_MV_HARDWARE 0x0200L\n # define KS_VBI_FLAG_MV_DETECTED 0x0400L\n\n # define KS_VBI_FLAG_TVTUNER_CHANGE 0x0010L\n # define KS_VBI_FLAG_VBIINFOHEADER_CHANGE 0x0020L\n\ntypedef struct tagKS_VBI_FRAME_INFO\n{\n  ULONG ExtendedHeaderSize;\n  DWORD dwFrameFlags;\n  LONGLONG PictureNumber;\n  LONGLONG DropCount;\n  DWORD dwSamplingFrequency;\n  KS_TVTUNER_CHANGE_INFO TvTunerChangeInfo;\n  KS_VBIINFOHEADER VBIInfoHeader;\n}KS_VBI_FRAME_INFO, * PKS_VBI_FRAME_INFO;\n\ntypedef enum\n{\n  KS_AnalogVideo_None = 0x00000000,\n  KS_AnalogVideo_NTSC_M = 0x00000001,\n  KS_AnalogVideo_NTSC_M_J = 0x00000002,\n  KS_AnalogVideo_NTSC_433 = 0x00000004,\n  KS_AnalogVideo_PAL_B = 0x00000010,\n  KS_AnalogVideo_PAL_D = 0x00000020,\n  KS_AnalogVideo_PAL_G = 0x00000040,\n  KS_AnalogVideo_PAL_H = 0x00000080,\n  KS_AnalogVideo_PAL_I = 0x00000100,\n  KS_AnalogVideo_PAL_M = 0x00000200,\n  KS_AnalogVideo_PAL_N = 0x00000400,\n  KS_AnalogVideo_PAL_60 = 0x00000800,\n  KS_AnalogVideo_SECAM_B = 0x00001000,\n  KS_AnalogVideo_SECAM_D = 0x00002000,\n  KS_AnalogVideo_SECAM_G = 0x00004000,\n  KS_AnalogVideo_SECAM_H = 0x00008000,\n  KS_AnalogVideo_SECAM_K = 0x00010000,\n  KS_AnalogVideo_SECAM_K1 = 0x00020000,\n  KS_AnalogVideo_SECAM_L = 0x00040000,\n  KS_AnalogVideo_SECAM_L1 = 0x00080000,\n  KS_AnalogVideo_PAL_N_COMBO = 0x00100000\n}KS_AnalogVideoStandard;\n\n # define KS_AnalogVideo_NTSC_Mask 0x00000007\n # define KS_AnalogVideo_PAL_Mask 0x00100FF0\n # define KS_AnalogVideo_SECAM_Mask 0x000FF000\n\n # define STATIC_PROPSETID_ALLOCATOR_CONTROL              \\\n  0x53171960, 0x148e, 0x11d2, 0x99, 0x79, 0x0, 0x0, 0xc0, 0xcc, 0x16, 0xba\nDEFINE_GUIDSTRUCT(\"53171960-148E-11d2-9979-0000C0CC16BA\", PROPSETID_ALLOCATOR_CONTROL);\n # define PROPSETID_ALLOCATOR_CONTROL DEFINE_GUIDNAMED(PROPSETID_ALLOCATOR_CONTROL)\n\ntypedef enum\n{\n  KSPROPERTY_ALLOCATOR_CONTROL_HONOR_COUNT,\n  KSPROPERTY_ALLOCATOR_CONTROL_SURFACE_SIZE,\n  KSPROPERTY_ALLOCATOR_CONTROL_CAPTURE_CAPS,\n  KSPROPERTY_ALLOCATOR_CONTROL_CAPTURE_INTERLEAVE\n}KSPROPERTY_ALLOCATOR_CONTROL;\n\ntypedef struct\n{\n  ULONG CX;\n  ULONG CY;\n}KSPROPERTY_ALLOCATOR_CONTROL_SURFACE_SIZE_S, * PKSPROPERTY_ALLOCATOR_CONTROL_SURFACE_SIZE_S;\n\ntypedef struct\n{\n  ULONG InterleavedCapSupported;\n}KSPROPERTY_ALLOCATOR_CONTROL_CAPTURE_CAPS_S, * PKSPROPERTY_ALLOCATOR_CONTROL_CAPTURE_CAPS_S;\n\ntypedef struct\n{\n  ULONG InterleavedCapPossible;\n}KSPROPERTY_ALLOCATOR_CONTROL_CAPTURE_INTERLEAVE_S, * PKSPROPERTY_ALLOCATOR_CONTROL_CAPTURE_INTERLEAVE_S;\n\n # define STATIC_PROPSETID_VIDCAP_VIDEOPROCAMP                \\\n  0xC6E13360L, 0x30AC, 0x11d0, 0xa1, 0x8c, 0x00, 0xA0, 0xC9, 0x11, 0x89, 0x56\nDEFINE_GUIDSTRUCT(\"C6E13360-30AC-11d0-A18C-00A0C9118956\", PROPSETID_VIDCAP_VIDEOPROCAMP);\n # define PROPSETID_VIDCAP_VIDEOPROCAMP DEFINE_GUIDNAMED(PROPSETID_VIDCAP_VIDEOPROCAMP)\n\ntypedef enum\n{\n  KSPROPERTY_VIDEOPROCAMP_BRIGHTNESS,\n  KSPROPERTY_VIDEOPROCAMP_CONTRAST,\n  KSPROPERTY_VIDEOPROCAMP_HUE,\n  KSPROPERTY_VIDEOPROCAMP_SATURATION,\n  KSPROPERTY_VIDEOPROCAMP_SHARPNESS,\n  KSPROPERTY_VIDEOPROCAMP_GAMMA,\n  KSPROPERTY_VIDEOPROCAMP_COLORENABLE,\n  KSPROPERTY_VIDEOPROCAMP_WHITEBALANCE,\n  KSPROPERTY_VIDEOPROCAMP_BACKLIGHT_COMPENSATION,\n  KSPROPERTY_VIDEOPROCAMP_GAIN,\n  KSPROPERTY_VIDEOPROCAMP_DIGITAL_MULTIPLIER,\n  KSPROPERTY_VIDEOPROCAMP_DIGITAL_MULTIPLIER_LIMIT,\n  KSPROPERTY_VIDEOPROCAMP_WHITEBALANCE_COMPONENT,\n  KSPROPERTY_VIDEOPROCAMP_POWERLINE_FREQUENCY\n}KSPROPERTY_VIDCAP_VIDEOPROCAMP;\n\ntypedef struct\n{\n  KSPROPERTY Property;\n  LONG Value;\n  ULONG Flags;\n  ULONG Capabilities;\n}KSPROPERTY_VIDEOPROCAMP_S, * PKSPROPERTY_VIDEOPROCAMP_S;\n\ntypedef struct\n{\n  KSP_NODE NodeProperty;\n  LONG Value;\n  ULONG Flags;\n  ULONG Capabilities;\n}KSPROPERTY_VIDEOPROCAMP_NODE_S, * PKSPROPERTY_VIDEOPROCAMP_NODE_S;\n\ntypedef struct\n{\n  KSPROPERTY Property;\n  LONG Value1;\n  ULONG Flags;\n  ULONG Capabilities;\n  LONG Value2;\n}KSPROPERTY_VIDEOPROCAMP_S2, * PKSPROPERTY_VIDEOPROCAMP_S2;\n\ntypedef struct\n{\n  KSP_NODE NodeProperty;\n  LONG Value1;\n  ULONG Flags;\n  ULONG Capabilities;\n  LONG Value2;\n}KSPROPERTY_VIDEOPROCAMP_NODE_S2, * PKSPROPERTY_VIDEOPROCAMP_NODE_S2;\n\n # define KSPROPERTY_VIDEOPROCAMP_FLAGS_AUTO 0X0001L\n # define KSPROPERTY_VIDEOPROCAMP_FLAGS_MANUAL 0X0002L\n\n # define STATIC_PROPSETID_VIDCAP_SELECTOR                \\\n  0x1ABDAECA, 0x68B6, 0x4F83, 0x93, 0x71, 0xB4, 0x13, 0x90, 0x7C, 0x7B, 0x9F\nDEFINE_GUIDSTRUCT(\"1ABDAECA-68B6-4F83-9371-B413907C7B9F\", PROPSETID_VIDCAP_SELECTOR);\n # define PROPSETID_VIDCAP_SELECTOR DEFINE_GUIDNAMED(PROPSETID_VIDCAP_SELECTOR)\n\ntypedef enum\n{\n  KSPROPERTY_SELECTOR_SOURCE_NODE_ID,\n  KSPROPERTY_SELECTOR_NUM_SOURCES\n}KSPROPERTY_VIDCAP_SELECTOR, * PKSPROPERTY_VIDCAP_SELECTOR;\n\ntypedef struct\n{\n  KSPROPERTY Property;\n  LONG Value;\n  ULONG Flags;\n  ULONG Capabilities;\n}KSPROPERTY_SELECTOR_S, * PKSPROPERTY_SELECTOR_S;\n\ntypedef struct\n{\n  KSP_NODE NodeProperty;\n  LONG Value;\n  ULONG Flags;\n  ULONG Capabilities;\n}KSPROPERTY_SELECTOR_NODE_S, * PKSPROPERTY_SELECTOR_NODE_S;\n\n # define STATIC_PROPSETID_TUNER                      \\\n  0x6a2e0605L, 0x28e4, 0x11d0, 0xa1, 0x8c, 0x00, 0xa0, 0xc9, 0x11, 0x89, 0x56\nDEFINE_GUIDSTRUCT(\"6a2e0605-28e4-11d0-a18c-00a0c9118956\", PROPSETID_TUNER);\n # define PROPSETID_TUNER DEFINE_GUIDNAMED(PROPSETID_TUNER)\n\ntypedef enum\n{\n  KSPROPERTY_TUNER_CAPS,\n  KSPROPERTY_TUNER_MODE_CAPS,\n  KSPROPERTY_TUNER_MODE,\n  KSPROPERTY_TUNER_STANDARD,\n  KSPROPERTY_TUNER_FREQUENCY,\n  KSPROPERTY_TUNER_INPUT,\n  KSPROPERTY_TUNER_STATUS,\n  KSPROPERTY_TUNER_IF_MEDIUM\n}KSPROPERTY_TUNER;\n\ntypedef enum\n{\n  KSPROPERTY_TUNER_MODE_TV = 0X0001,\n  KSPROPERTY_TUNER_MODE_FM_RADIO = 0X0002,\n  KSPROPERTY_TUNER_MODE_AM_RADIO = 0X0004,\n  KSPROPERTY_TUNER_MODE_DSS = 0X0008,\n  KSPROPERTY_TUNER_MODE_ATSC = 0X0010\n}KSPROPERTY_TUNER_MODES;\n\ntypedef enum\n{\n  KS_TUNER_TUNING_EXACT = 1,\n  KS_TUNER_TUNING_FINE,\n  KS_TUNER_TUNING_COARSE\n}KS_TUNER_TUNING_FLAGS;\n\ntypedef enum\n{\n  KS_TUNER_STRATEGY_PLL = 0X01,\n  KS_TUNER_STRATEGY_SIGNAL_STRENGTH = 0X02,\n  KS_TUNER_STRATEGY_DRIVER_TUNES = 0X04\n}KS_TUNER_STRATEGY;\n\ntypedef struct\n{\n  KSPROPERTY Property;\n  ULONG ModesSupported;\n  KSPIN_MEDIUM VideoMedium;\n  KSPIN_MEDIUM TVAudioMedium;\n  KSPIN_MEDIUM RadioAudioMedium;\n}KSPROPERTY_TUNER_CAPS_S, * PKSPROPERTY_TUNER_CAPS_S;\n\ntypedef struct\n{\n  KSPROPERTY Property;\n  KSPIN_MEDIUM IFMedium;\n}KSPROPERTY_TUNER_IF_MEDIUM_S, * PKSPROPERTY_TUNER_IF_MEDIUM_S;\n\ntypedef struct\n{\n  KSPROPERTY Property;\n  ULONG Mode;\n  ULONG StandardsSupported;\n  ULONG MinFrequency;\n  ULONG MaxFrequency;\n  ULONG TuningGranularity;\n  ULONG NumberOfInputs;\n  ULONG SettlingTime;\n  ULONG Strategy;\n}KSPROPERTY_TUNER_MODE_CAPS_S, * PKSPROPERTY_TUNER_MODE_CAPS_S;\n\ntypedef struct\n{\n  KSPROPERTY Property;\n  ULONG Mode;\n}KSPROPERTY_TUNER_MODE_S, * PKSPROPERTY_TUNER_MODE_S;\n\ntypedef struct\n{\n  KSPROPERTY Property;\n  ULONG Frequency;\n  ULONG LastFrequency;\n  ULONG TuningFlags;\n  ULONG VideoSubChannel;\n  ULONG AudioSubChannel;\n  ULONG Channel;\n  ULONG Country;\n}KSPROPERTY_TUNER_FREQUENCY_S, * PKSPROPERTY_TUNER_FREQUENCY_S;\n\ntypedef struct\n{\n  KSPROPERTY Property;\n  ULONG Standard;\n}KSPROPERTY_TUNER_STANDARD_S, * PKSPROPERTY_TUNER_STANDARD_S;\n\ntypedef struct\n{\n  KSPROPERTY Property;\n  ULONG InputIndex;\n}KSPROPERTY_TUNER_INPUT_S, * PKSPROPERTY_TUNER_INPUT_S;\n\ntypedef struct\n{\n  KSPROPERTY Property;\n  ULONG CurrentFrequency;\n  ULONG PLLOffset;\n  ULONG SignalStrength;\n  ULONG Busy;\n}KSPROPERTY_TUNER_STATUS_S, * PKSPROPERTY_TUNER_STATUS_S;\n\n # define STATIC_EVENTSETID_TUNER                     \\\n  0x6a2e0606L, 0x28e4, 0x11d0, 0xa1, 0x8c, 0x00, 0xa0, 0xc9, 0x11, 0x89, 0x56\nDEFINE_GUIDSTRUCT(\"6a2e0606-28e4-11d0-a18c-00a0c9118956\", EVENTSETID_TUNER);\n # define EVENTSETID_TUNER DEFINE_GUIDNAMED(EVENTSETID_TUNER)\n\ntypedef enum\n{\n  KSEVENT_TUNER_CHANGED\n}KSEVENT_TUNER;\n\n # define STATIC_KSNODETYPE_VIDEO_STREAMING               \\\n  0xDFF229E1L, 0xF70F, 0x11D0, 0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96\nDEFINE_GUIDSTRUCT(\"DFF229E1-F70F-11D0-B917-00A0C9223196\", KSNODETYPE_VIDEO_STREAMING);\n # define KSNODETYPE_VIDEO_STREAMING DEFINE_GUIDNAMED(KSNODETYPE_VIDEO_STREAMING)\n\n # define STATIC_KSNODETYPE_VIDEO_INPUT_TERMINAL              \\\n  0xDFF229E2L, 0xF70F, 0x11D0, 0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96\nDEFINE_GUIDSTRUCT(\"DFF229E2-F70F-11D0-B917-00A0C9223196\", KSNODETYPE_VIDEO_INPUT_TERMINAL);\n # define KSNODETYPE_VIDEO_INPUT_TERMINAL DEFINE_GUIDNAMED(KSNODETYPE_VIDEO_INPUT_TERMINAL)\n\n # define STATIC_KSNODETYPE_VIDEO_OUTPUT_TERMINAL             \\\n  0xDFF229E3L, 0xF70F, 0x11D0, 0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96\nDEFINE_GUIDSTRUCT(\"DFF229E3-F70F-11D0-B917-00A0C9223196\", KSNODETYPE_VIDEO_OUTPUT_TERMINAL);\n # define KSNODETYPE_VIDEO_OUTPUT_TERMINAL DEFINE_GUIDNAMED(KSNODETYPE_VIDEO_OUTPUT_TERMINAL)\n\n # define STATIC_KSNODETYPE_VIDEO_SELECTOR                \\\n  0xDFF229E4L, 0xF70F, 0x11D0, 0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96\nDEFINE_GUIDSTRUCT(\"DFF229E4-F70F-11D0-B917-00A0C9223196\", KSNODETYPE_VIDEO_SELECTOR);\n # define KSNODETYPE_VIDEO_SELECTOR DEFINE_GUIDNAMED(KSNODETYPE_VIDEO_SELECTOR)\n\n # define STATIC_KSNODETYPE_VIDEO_PROCESSING              \\\n  0xDFF229E5L, 0xF70F, 0x11D0, 0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96\nDEFINE_GUIDSTRUCT(\"DFF229E5-F70F-11D0-B917-00A0C9223196\", KSNODETYPE_VIDEO_PROCESSING);\n # define KSNODETYPE_VIDEO_PROCESSING DEFINE_GUIDNAMED(KSNODETYPE_VIDEO_PROCESSING)\n\n # define STATIC_KSNODETYPE_VIDEO_CAMERA_TERMINAL             \\\n  0xDFF229E6L, 0xF70F, 0x11D0, 0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96\nDEFINE_GUIDSTRUCT(\"DFF229E6-F70F-11D0-B917-00A0C9223196\", KSNODETYPE_VIDEO_CAMERA_TERMINAL);\n # define KSNODETYPE_VIDEO_CAMERA_TERMINAL DEFINE_GUIDNAMED(KSNODETYPE_VIDEO_CAMERA_TERMINAL)\n\n # define STATIC_KSNODETYPE_VIDEO_INPUT_MTT               \\\n  0xDFF229E7L, 0xF70F, 0x11D0, 0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96\nDEFINE_GUIDSTRUCT(\"DFF229E7-F70F-11D0-B917-00A0C9223196\", KSNODETYPE_VIDEO_INPUT_MTT);\n # define KSNODETYPE_VIDEO_INPUT_MTT DEFINE_GUIDNAMED(KSNODETYPE_VIDEO_INPUT_MTT)\n\n # define STATIC_KSNODETYPE_VIDEO_OUTPUT_MTT              \\\n  0xDFF229E8L, 0xF70F, 0x11D0, 0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96\nDEFINE_GUIDSTRUCT(\"DFF229E8-F70F-11D0-B917-00A0C9223196\", KSNODETYPE_VIDEO_OUTPUT_MTT);\n # define KSNODETYPE_VIDEO_OUTPUT_MTT DEFINE_GUIDNAMED(KSNODETYPE_VIDEO_OUTPUT_MTT)\n\n # define STATIC_PROPSETID_VIDCAP_VIDEOENCODER                \\\n  0x6a2e0610L, 0x28e4, 0x11d0, 0xa1, 0x8c, 0x00, 0xa0, 0xc9, 0x11, 0x89, 0x56\nDEFINE_GUIDSTRUCT(\"6a2e0610-28e4-11d0-a18c-00a0c9118956\", PROPSETID_VIDCAP_VIDEOENCODER);\n # define PROPSETID_VIDCAP_VIDEOENCODER DEFINE_GUIDNAMED(PROPSETID_VIDCAP_VIDEOENCODER)\n\ntypedef enum\n{\n  KSPROPERTY_VIDEOENCODER_CAPS,\n  KSPROPERTY_VIDEOENCODER_STANDARD,\n  KSPROPERTY_VIDEOENCODER_COPYPROTECTION,\n  KSPROPERTY_VIDEOENCODER_CC_ENABLE\n}KSPROPERTY_VIDCAP_VIDEOENCODER;\n\ntypedef struct\n{\n  KSPROPERTY Property;\n  LONG Value;\n  ULONG Flags;\n  ULONG Capabilities;\n}KSPROPERTY_VIDEOENCODER_S, * PKSPROPERTY_VIDEOENCODER_S;\n\n # define STATIC_PROPSETID_VIDCAP_VIDEODECODER                \\\n  0xC6E13350L, 0x30AC, 0x11d0, 0xA1, 0x8C, 0x00, 0xA0, 0xC9, 0x11, 0x89, 0x56\nDEFINE_GUIDSTRUCT(\"C6E13350-30AC-11d0-A18C-00A0C9118956\", PROPSETID_VIDCAP_VIDEODECODER);\n # define PROPSETID_VIDCAP_VIDEODECODER DEFINE_GUIDNAMED(PROPSETID_VIDCAP_VIDEODECODER)\n\ntypedef enum\n{\n  KSPROPERTY_VIDEODECODER_CAPS,\n  KSPROPERTY_VIDEODECODER_STANDARD,\n  KSPROPERTY_VIDEODECODER_STATUS,\n  KSPROPERTY_VIDEODECODER_OUTPUT_ENABLE,\n  KSPROPERTY_VIDEODECODER_VCR_TIMING\n}KSPROPERTY_VIDCAP_VIDEODECODER;\n\ntypedef enum\n{\n  KS_VIDEODECODER_FLAGS_CAN_DISABLE_OUTPUT = 0X0001,\n  KS_VIDEODECODER_FLAGS_CAN_USE_VCR_LOCKING = 0X0002,\n  KS_VIDEODECODER_FLAGS_CAN_INDICATE_LOCKED = 0X0004\n}KS_VIDEODECODER_FLAGS;\n\ntypedef struct\n{\n  KSPROPERTY Property;\n  ULONG StandardsSupported;\n  ULONG Capabilities;\n  ULONG SettlingTime;\n  ULONG HSyncPerVSync;\n}KSPROPERTY_VIDEODECODER_CAPS_S, * PKSPROPERTY_VIDEODECODER_CAPS_S;\n\ntypedef struct\n{\n  KSPROPERTY Property;\n  ULONG NumberOfLines;\n  ULONG SignalLocked;\n}KSPROPERTY_VIDEODECODER_STATUS_S, * PKSPROPERTY_VIDEODECODER_STATUS_S;\n\ntypedef struct\n{\n  KSPROPERTY Property;\n  ULONG Value;\n}KSPROPERTY_VIDEODECODER_S, * PKSPROPERTY_VIDEODECODER_S;\n\n # define STATIC_EVENTSETID_VIDEODECODER                  \\\n  0x6a2e0621L, 0x28e4, 0x11d0, 0xa1, 0x8c, 0x00, 0xa0, 0xc9, 0x11, 0x89, 0x56\nDEFINE_GUIDSTRUCT(\"6a2e0621-28e4-11d0-a18c-00a0c9118956\", EVENTSETID_VIDEODECODER);\n # define EVENTSETID_VIDEODECODER DEFINE_GUIDNAMED(EVENTSETID_VIDEODECODER)\n\ntypedef enum\n{\n  KSEVENT_VIDEODECODER_CHANGED\n}KSEVENT_VIDEODECODER;\n\n # define STATIC_PROPSETID_VIDCAP_CAMERACONTROL               \\\n  0xC6E13370L, 0x30AC, 0x11d0, 0xa1, 0x8C, 0x00, 0xA0, 0xC9, 0x11, 0x89, 0x56\nDEFINE_GUIDSTRUCT(\"C6E13370-30AC-11d0-A18C-00A0C9118956\", PROPSETID_VIDCAP_CAMERACONTROL);\n # define PROPSETID_VIDCAP_CAMERACONTROL DEFINE_GUIDNAMED(PROPSETID_VIDCAP_CAMERACONTROL)\n\ntypedef enum\n{\n  KSPROPERTY_CAMERACONTROL_PAN,\n  KSPROPERTY_CAMERACONTROL_TILT,\n  KSPROPERTY_CAMERACONTROL_ROLL,\n  KSPROPERTY_CAMERACONTROL_ZOOM,\n  KSPROPERTY_CAMERACONTROL_EXPOSURE,\n  KSPROPERTY_CAMERACONTROL_IRIS,\n  KSPROPERTY_CAMERACONTROL_FOCUS,\n  KSPROPERTY_CAMERACONTROL_SCANMODE,\n  KSPROPERTY_CAMERACONTROL_PRIVACY,\n  KSPROPERTY_CAMERACONTROL_PANTILT,\n  KSPROPERTY_CAMERACONTROL_PAN_RELATIVE,\n  KSPROPERTY_CAMERACONTROL_TILT_RELATIVE,\n  KSPROPERTY_CAMERACONTROL_ROLL_RELATIVE,\n  KSPROPERTY_CAMERACONTROL_ZOOM_RELATIVE,\n  KSPROPERTY_CAMERACONTROL_EXPOSURE_RELATIVE,\n  KSPROPERTY_CAMERACONTROL_IRIS_RELATIVE,\n  KSPROPERTY_CAMERACONTROL_FOCUS_RELATIVE,\n  KSPROPERTY_CAMERACONTROL_PANTILT_RELATIVE,\n  KSPROPERTY_CAMERACONTROL_FOCAL_LENGTH\n}KSPROPERTY_VIDCAP_CAMERACONTROL;\n\ntypedef struct\n{\n  KSPROPERTY Property;\n  LONG Value;\n  ULONG Flags;\n  ULONG Capabilities;\n}KSPROPERTY_CAMERACONTROL_S, * PKSPROPERTY_CAMERACONTROL_S;\n\ntypedef struct\n{\n  KSP_NODE NodeProperty;\n  LONG Value;\n  ULONG Flags;\n  ULONG Capabilities;\n}KSPROPERTY_CAMERACONTROL_NODE_S, PKSPROPERTY_CAMERACONTROL_NODE_S;\n\ntypedef struct\n{\n  KSPROPERTY Property;\n  LONG Value1;\n  ULONG Flags;\n  ULONG Capabilities;\n  LONG Value2;\n}KSPROPERTY_CAMERACONTROL_S2, * PKSPROPERTY_CAMERACONTROL_S2;\n\ntypedef struct\n{\n  KSP_NODE NodeProperty;\n  LONG Value1;\n  ULONG Flags;\n  ULONG Capabilities;\n  LONG Value2;\n}KSPROPERTY_CAMERACONTROL_NODE_S2, * PKSPROPERTY_CAMERACONTROL_NODE_S2;\n\ntypedef struct\n{\n  KSPROPERTY Property;\n  LONG lOcularFocalLength;\n  LONG lObjectiveFocalLengthMin;\n  LONG lObjectiveFocalLengthMax;\n}KSPROPERTY_CAMERACONTROL_FOCAL_LENGTH_S, * PKSPROPERTY_CAMERACONTROL_FOCAL_LENGTH_S;\n\ntypedef struct\n{\n  KSNODEPROPERTY NodeProperty;\n  LONG lOcularFocalLength;\n  LONG lObjectiveFocalLengthMin;\n  LONG lObjectiveFocalLengthMax;\n}KSPROPERTY_CAMERACONTROL_NODE_FOCAL_LENGTH_S, * PKSPROPERTY_CAMERACONTROL_NODE_FOCAL_LENGTH_S;\n\n # define KSPROPERTY_CAMERACONTROL_FLAGS_AUTO 0X0001L\n # define KSPROPERTY_CAMERACONTROL_FLAGS_MANUAL 0X0002L\n\n # define KSPROPERTY_CAMERACONTROL_FLAGS_ABSOLUTE 0X0000L\n # define KSPROPERTY_CAMERACONTROL_FLAGS_RELATIVE 0X0010L\n\n # ifndef __EDevCtrl__\n  #  define __EDevCtrl__\n\n  #  define STATIC_PROPSETID_EXT_DEVICE                 \\\n  0xB5730A90L, 0x1A2C, 0x11cf, 0x8c, 0x23, 0x00, 0xAA, 0x00, 0x6B, 0x68, 0x14\nDEFINE_GUIDSTRUCT(\"B5730A90-1A2C-11cf-8C23-00AA006B6814\", PROPSETID_EXT_DEVICE);\n  #  define PROPSETID_EXT_DEVICE DEFINE_GUIDNAMED(PROPSETID_EXT_DEVICE)\n\ntypedef enum\n{\n  KSPROPERTY_EXTDEVICE_ID,\n  KSPROPERTY_EXTDEVICE_VERSION,\n  KSPROPERTY_EXTDEVICE_POWER_STATE,\n  KSPROPERTY_EXTDEVICE_PORT,\n  KSPROPERTY_EXTDEVICE_CAPABILITIES\n}KSPROPERTY_EXTDEVICE;\n\ntypedef struct tagDEVCAPS\n{\n  LONG CanRecord;\n  LONG CanRecordStrobe;\n  LONG HasAudio;\n  LONG HasVideo;\n  LONG UsesFiles;\n  LONG CanSave;\n  LONG DeviceType;\n  LONG TCRead;\n  LONG TCWrite;\n  LONG CTLRead;\n  LONG IndexRead;\n  LONG Preroll;\n  LONG Postroll;\n  LONG SyncAcc;\n  LONG NormRate;\n  LONG CanPreview;\n  LONG CanMonitorSrc;\n  LONG CanTest;\n  LONG VideoIn;\n  LONG AudioIn;\n  LONG Calibrate;\n  LONG SeekType;\n  LONG SimulatedHardware;\n}DEVCAPS, * PDEVCAPS;\n\ntypedef struct\n{\n  KSPROPERTY Property;\n  union\n  {\n    DEVCAPS Capabilities;\n    ULONG DevPort;\n    ULONG PowerState;\n    WCHAR pawchString[MAX_PATH];\n    DWORD NodeUniqueID[2];\n  }u;\n}KSPROPERTY_EXTDEVICE_S, * PKSPROPERTY_EXTDEVICE_S;\n\n  #  define STATIC_PROPSETID_EXT_TRANSPORT                  \\\n  0xA03CD5F0L, 0x3045, 0x11cf, 0x8c, 0x44, 0x00, 0xAA, 0x00, 0x6B, 0x68, 0x14\nDEFINE_GUIDSTRUCT(\"A03CD5F0-3045-11cf-8C44-00AA006B6814\", PROPSETID_EXT_TRANSPORT);\n  #  define PROPSETID_EXT_TRANSPORT DEFINE_GUIDNAMED(PROPSETID_EXT_TRANSPORT)\n\ntypedef enum\n{\n  KSPROPERTY_EXTXPORT_CAPABILITIES,\n  KSPROPERTY_EXTXPORT_INPUT_SIGNAL_MODE,\n  KSPROPERTY_EXTXPORT_OUTPUT_SIGNAL_MODE,\n  KSPROPERTY_EXTXPORT_LOAD_MEDIUM,\n  KSPROPERTY_EXTXPORT_MEDIUM_INFO,\n  KSPROPERTY_EXTXPORT_STATE,\n  KSPROPERTY_EXTXPORT_STATE_NOTIFY,\n  KSPROPERTY_EXTXPORT_TIMECODE_SEARCH,\n  KSPROPERTY_EXTXPORT_ATN_SEARCH,\n  KSPROPERTY_EXTXPORT_RTC_SEARCH,\n  KSPROPERTY_RAW_AVC_CMD\n}KSPROPERTY_EXTXPORT;\n\ntypedef struct tagTRANSPORTSTATUS\n{\n  LONG Mode;\n  LONG LastError;\n  LONG RecordInhibit;\n  LONG ServoLock;\n  LONG MediaPresent;\n  LONG MediaLength;\n  LONG MediaSize;\n  LONG MediaTrackCount;\n  LONG MediaTrackLength;\n  LONG MediaTrackSide;\n  LONG MediaType;\n  LONG LinkMode;\n  LONG NotifyOn;\n}TRANSPORTSTATUS, * PTRANSPORTSTATUS;\n\ntypedef struct tagTRANSPORTBASICPARMS\n{\n  LONG TimeFormat;\n  LONG TimeReference;\n  LONG Superimpose;\n  LONG EndStopAction;\n  LONG RecordFormat;\n  LONG StepFrames;\n  LONG SetpField;\n  LONG Preroll;\n  LONG RecPreroll;\n  LONG Postroll;\n  LONG EditDelay;\n  LONG PlayTCDelay;\n  LONG RecTCDelay;\n  LONG EditField;\n  LONG FrameServo;\n  LONG ColorFrameServo;\n  LONG ServoRef;\n  LONG WarnGenlock;\n  LONG SetTracking;\n  TCHAR VolumeName[40];\n  LONG Ballistic[20];\n  LONG Speed;\n  LONG CounterFormat;\n  LONG TunerChannel;\n  LONG TunerNumber;\n  LONG TimerEvent;\n  LONG TimerStartDay;\n  LONG TimerStartTime;\n  LONG TimerStopDay;\n  LONG TimerStopTime;\n}TRANSPORTBASICPARMS, * PTRANSPORTBASICPARMS;\n\ntypedef struct tagTRANSPORTVIDEOPARMS\n{\n  LONG OutputMode;\n  LONG Input;\n}TRANSPORTVIDEOPARMS, * PTRANSPORTVIDEOPARMS;\n\ntypedef struct tagTRANSPORTAUDIOPARMS\n{\n  LONG EnableOutput;\n  LONG EnableRecord;\n  LONG EnableSelsync;\n  LONG Input;\n  LONG MonitorSource;\n}TRANSPORTAUDIOPARMS, * PTRANSPORTAUDIOPARMS;\n\ntypedef struct\n{\n  WINBOOL MediaPresent;\n  ULONG MediaType;\n  WINBOOL RecordInhibit;\n}MEDIUM_INFO, * PMEDIUM_INFO;\n\ntypedef struct\n{\n  ULONG Mode;\n  ULONG State;\n}TRANSPORT_STATE, * PTRANSPORT_STATE;\n\ntypedef struct\n{\n  KSPROPERTY Property;\n  union\n  {\n    ULONG Capabilities;\n    ULONG SignalMode;\n    ULONG LoadMedium;\n    MEDIUM_INFO MediumInfo;\n    TRANSPORT_STATE XPrtState;\n    struct\n    {\n      BYTE frame;\n      BYTE second;\n      BYTE minute;\n      BYTE hour;\n    }Timecode;\n    DWORD dwTimecode;\n    DWORD dwAbsTrackNumber;\n    struct\n    {\n      ULONG PayloadSize;\n      BYTE Payload[512];\n    }RawAVC;\n  }u;\n}KSPROPERTY_EXTXPORT_S, * PKSPROPERTY_EXTXPORT_S;\n\ntypedef struct\n{\n  KSP_NODE NodeProperty;\n  union\n  {\n    ULONG Capabilities;\n    ULONG SignalMode;\n    ULONG LoadMedium;\n    MEDIUM_INFO MediumInfo;\n    TRANSPORT_STATE XPrtState;\n    struct\n    {\n      BYTE frame;\n      BYTE second;\n      BYTE minute;\n      BYTE hour;\n    }Timecode;\n    DWORD dwTimecode;\n    DWORD dwAbsTrackNumber;\n    struct\n    {\n      ULONG PayloadSize;\n      BYTE Payload[512];\n    }RawAVC;\n  }u;\n}KSPROPERTY_EXTXPORT_NODE_S, * PKSPROPERTY_EXTXPORT_NODE_S;\n\n  #  define STATIC_PROPSETID_TIMECODE_READER                \\\n  0x9B496CE1L, 0x811B, 0x11cf, 0x8C, 0x77, 0x00, 0xAA, 0x00, 0x6B, 0x68, 0x14\nDEFINE_GUIDSTRUCT(\"9B496CE1-811B-11cf-8C77-00AA006B6814\", PROPSETID_TIMECODE_READER);\n  #  define PROPSETID_TIMECODE_READER DEFINE_GUIDNAMED(PROPSETID_TIMECODE_READER)\n\ntypedef enum\n{\n  KSPROPERTY_TIMECODE_READER,\n  KSPROPERTY_ATN_READER,\n  KSPROPERTY_RTC_READER\n}KSPROPERTY_TIMECODE;\n\n  #  ifndef TIMECODE_DEFINED\n   #   define TIMECODE_DEFINED\ntypedef union _timecode\n{\n  struct\n  {\n    WORD wFrameRate;\n    WORD wFrameFract;\n    DWORD dwFrames;\n  };\n  DWORDLONG qw;\n}TIMECODE;\ntypedef TIMECODE* PTIMECODE;\n\ntypedef struct tagTIMECODE_SAMPLE\n{\n  LONGLONG qwTick;\n  TIMECODE timecode;\n  DWORD dwUser;\n  DWORD dwFlags;\n}TIMECODE_SAMPLE;\n\ntypedef TIMECODE_SAMPLE* PTIMECODE_SAMPLE;\n  #  endif /* TIMECODE_DEFINED */\n\ntypedef struct\n{\n  KSPROPERTY Property;\n  TIMECODE_SAMPLE TimecodeSamp;\n}KSPROPERTY_TIMECODE_S, * PKSPROPERTY_TIMECODE_S;\n\ntypedef struct\n{\n  KSP_NODE NodeProperty;\n  TIMECODE_SAMPLE TimecodeSamp;\n}KSPROPERTY_TIMECODE_NODE_S, * PKSPROPERTY_TIMECODE_NODE_S;\n\n  #  define STATIC_KSEVENTSETID_EXTDEV_Command              \\\n  0x109c7988L, 0xb3cb, 0x11d2, 0xb4, 0x8e, 0x00, 0x60, 0x97, 0xb3, 0x39, 0x1b\nDEFINE_GUIDSTRUCT(\"109c7988-b3cb-11d2-b48e-006097b3391b\", KSEVENTSETID_EXTDEV_Command);\n  #  define KSEVENTSETID_EXTDEV_Command DEFINE_GUIDNAMED(KSEVENTSETID_EXTDEV_Command)\n\ntypedef enum\n{\n  KSEVENT_EXTDEV_COMMAND_NOTIFY_INTERIM_READY,\n  KSEVENT_EXTDEV_COMMAND_CONTROL_INTERIM_READY,\n  KSEVENT_EXTDEV_COMMAND_BUSRESET,\n  KSEVENT_EXTDEV_TIMECODE_UPDATE,\n  KSEVENT_EXTDEV_OPERATION_MODE_UPDATE,\n  KSEVENT_EXTDEV_TRANSPORT_STATE_UPDATE,\n  KSEVENT_EXTDEV_NOTIFY_REMOVAL,\n  KSEVENT_EXTDEV_NOTIFY_MEDIUM_CHANGE\n}KSEVENT_DEVCMD;\n # endif /* __EDevCtrl__ */\n\n # define STATIC_PROPSETID_VIDCAP_CROSSBAR                \\\n  0x6a2e0640L, 0x28e4, 0x11d0, 0xa1, 0x8c, 0x00, 0xa0, 0xc9, 0x11, 0x89, 0x56\nDEFINE_GUIDSTRUCT(\"6a2e0640-28e4-11d0-a18c-00a0c9118956\", PROPSETID_VIDCAP_CROSSBAR);\n # define PROPSETID_VIDCAP_CROSSBAR DEFINE_GUIDNAMED(PROPSETID_VIDCAP_CROSSBAR)\n\ntypedef enum\n{\n  KSPROPERTY_CROSSBAR_CAPS,\n  KSPROPERTY_CROSSBAR_PININFO,\n  KSPROPERTY_CROSSBAR_CAN_ROUTE,\n  KSPROPERTY_CROSSBAR_ROUTE\n}KSPROPERTY_VIDCAP_CROSSBAR;\n\ntypedef struct\n{\n  KSPROPERTY Property;\n  ULONG NumberOfInputs;\n  ULONG NumberOfOutputs;\n}KSPROPERTY_CROSSBAR_CAPS_S, * PKSPROPERTY_CROSSBAR_CAPS_S;\n\ntypedef struct\n{\n  KSPROPERTY Property;\n  KSPIN_DATAFLOW Direction;\n  ULONG Index;\n  ULONG PinType;\n  ULONG RelatedPinIndex;\n  KSPIN_MEDIUM Medium;\n}KSPROPERTY_CROSSBAR_PININFO_S, * PKSPROPERTY_CROSSBAR_PININFO_S;\n\ntypedef struct\n{\n  KSPROPERTY Property;\n  ULONG IndexInputPin;\n  ULONG IndexOutputPin;\n  ULONG CanRoute;\n}KSPROPERTY_CROSSBAR_ROUTE_S, * PKSPROPERTY_CROSSBAR_ROUTE_S;\n\n # define STATIC_EVENTSETID_CROSSBAR                  \\\n  0x6a2e0641L, 0x28e4, 0x11d0, 0xa1, 0x8c, 0x00, 0xa0, 0xc9, 0x11, 0x89, 0x56\nDEFINE_GUIDSTRUCT(\"6a2e0641-28e4-11d0-a18c-00a0c9118956\", EVENTSETID_CROSSBAR);\n # define EVENTSETID_CROSSBAR DEFINE_GUIDNAMED(EVENTSETID_CROSSBAR)\n\ntypedef enum\n{\n  KSEVENT_CROSSBAR_CHANGED\n}KSEVENT_CROSSBAR;\n\ntypedef enum\n{\n  KS_PhysConn_Video_Tuner = 1,\n  KS_PhysConn_Video_Composite,\n  KS_PhysConn_Video_SVideo,\n  KS_PhysConn_Video_RGB,\n  KS_PhysConn_Video_YRYBY,\n  KS_PhysConn_Video_SerialDigital,\n  KS_PhysConn_Video_ParallelDigital,\n  KS_PhysConn_Video_SCSI,\n  KS_PhysConn_Video_AUX,\n  KS_PhysConn_Video_1394,\n  KS_PhysConn_Video_USB,\n  KS_PhysConn_Video_VideoDecoder,\n  KS_PhysConn_Video_VideoEncoder,\n  KS_PhysConn_Video_SCART,\n  KS_PhysConn_Audio_Tuner = 4096,\n  KS_PhysConn_Audio_Line,\n  KS_PhysConn_Audio_Mic,\n  KS_PhysConn_Audio_AESDigital,\n  KS_PhysConn_Audio_SPDIFDigital,\n  KS_PhysConn_Audio_SCSI,\n  KS_PhysConn_Audio_AUX,\n  KS_PhysConn_Audio_1394,\n  KS_PhysConn_Audio_USB,\n  KS_PhysConn_Audio_AudioDecoder\n}KS_PhysicalConnectorType;\n\n # define STATIC_PROPSETID_VIDCAP_TVAUDIO                 \\\n  0x6a2e0650L, 0x28e4, 0x11d0, 0xa1, 0x8c, 0x00, 0xa0, 0xc9, 0x11, 0x89, 0x56\nDEFINE_GUIDSTRUCT(\"6a2e0650-28e4-11d0-a18c-00a0c9118956\", PROPSETID_VIDCAP_TVAUDIO);\n # define PROPSETID_VIDCAP_TVAUDIO DEFINE_GUIDNAMED(PROPSETID_VIDCAP_TVAUDIO)\n\ntypedef enum\n{\n  KSPROPERTY_TVAUDIO_CAPS,\n  KSPROPERTY_TVAUDIO_MODE,\n  KSPROPERTY_TVAUDIO_CURRENTLY_AVAILABLE_MODES\n}KSPROPERTY_VIDCAP_TVAUDIO;\n\n # define KS_TVAUDIO_MODE_MONO 0x0001\n # define KS_TVAUDIO_MODE_STEREO 0x0002\n # define KS_TVAUDIO_MODE_LANG_A 0x0010\n # define KS_TVAUDIO_MODE_LANG_B 0x0020\n # define KS_TVAUDIO_MODE_LANG_C 0x0040\n\ntypedef struct\n{\n  KSPROPERTY Property;\n  ULONG Capabilities;\n  KSPIN_MEDIUM InputMedium;\n  KSPIN_MEDIUM OutputMedium;\n}KSPROPERTY_TVAUDIO_CAPS_S, * PKSPROPERTY_TVAUDIO_CAPS_S;\n\ntypedef struct\n{\n  KSPROPERTY Property;\n  ULONG Mode;\n}KSPROPERTY_TVAUDIO_S, * PKSPROPERTY_TVAUDIO_S;\n\n # define STATIC_KSEVENTSETID_VIDCAP_TVAUDIO              \\\n  0x6a2e0651L, 0x28e4, 0x11d0, 0xa1, 0x8c, 0x00, 0xa0, 0xc9, 0x11, 0x89, 0x56\nDEFINE_GUIDSTRUCT(\"6a2e0651-28e4-11d0-a18c-00a0c9118956\", KSEVENTSETID_VIDCAP_TVAUDIO);\n # define KSEVENTSETID_VIDCAP_TVAUDIO DEFINE_GUIDNAMED(KSEVENTSETID_VIDCAP_TVAUDIO)\n\ntypedef enum\n{\n  KSEVENT_TVAUDIO_CHANGED\n}KSEVENT_TVAUDIO;\n\n # define STATIC_PROPSETID_VIDCAP_VIDEOCOMPRESSION            \\\n  0xC6E13343L, 0x30AC, 0x11d0, 0xA1, 0x8C, 0x00, 0xA0, 0xC9, 0x11, 0x89, 0x56\nDEFINE_GUIDSTRUCT(\"C6E13343-30AC-11d0-A18C-00A0C9118956\", PROPSETID_VIDCAP_VIDEOCOMPRESSION);\n # define PROPSETID_VIDCAP_VIDEOCOMPRESSION DEFINE_GUIDNAMED(PROPSETID_VIDCAP_VIDEOCOMPRESSION)\n\ntypedef enum\n{\n  KSPROPERTY_VIDEOCOMPRESSION_GETINFO,\n  KSPROPERTY_VIDEOCOMPRESSION_KEYFRAME_RATE,\n  KSPROPERTY_VIDEOCOMPRESSION_PFRAMES_PER_KEYFRAME,\n  KSPROPERTY_VIDEOCOMPRESSION_QUALITY,\n  KSPROPERTY_VIDEOCOMPRESSION_OVERRIDE_KEYFRAME,\n  KSPROPERTY_VIDEOCOMPRESSION_OVERRIDE_FRAME_SIZE,\n  KSPROPERTY_VIDEOCOMPRESSION_WINDOWSIZE\n}KSPROPERTY_VIDCAP_VIDEOCOMPRESSION;\n\ntypedef enum\n{\n  KS_CompressionCaps_CanQuality = 1,\n  KS_CompressionCaps_CanCrunch = 2,\n  KS_CompressionCaps_CanKeyFrame = 4,\n  KS_CompressionCaps_CanBFrame = 8,\n  KS_CompressionCaps_CanWindow = 0x10\n}KS_CompressionCaps;\n\ntypedef enum\n{\n  KS_StreamingHint_FrameInterval = 0x0100,\n  KS_StreamingHint_KeyFrameRate = 0x0200,\n  KS_StreamingHint_PFrameRate = 0x0400,\n  KS_StreamingHint_CompQuality = 0x0800,\n  KS_StreamingHint_CompWindowSize = 0x1000\n}KS_VideoStreamingHints;\n\ntypedef struct\n{\n  KSPROPERTY Property;\n  ULONG StreamIndex;\n  LONG DefaultKeyFrameRate;\n  LONG DefaultPFrameRate;\n  LONG DefaultQuality;\n  LONG NumberOfQualitySettings;\n  LONG Capabilities;\n}KSPROPERTY_VIDEOCOMPRESSION_GETINFO_S, * PKSPROPERTY_VIDEOCOMPRESSION_GETINFO_S;\n\ntypedef struct\n{\n  KSPROPERTY Property;\n  ULONG StreamIndex;\n  LONG Value;\n}KSPROPERTY_VIDEOCOMPRESSION_S, * PKSPROPERTY_VIDEOCOMPRESSION_S;\n\ntypedef struct\n{\n  KSPROPERTY Property;\n  ULONG StreamIndex;\n  LONG Value;\n  ULONG Flags;\n}KSPROPERTY_VIDEOCOMPRESSION_S1, * PKSPROPERTY_VIDEOCOMPRESSION_S1;\n\n # define STATIC_KSDATAFORMAT_SUBTYPE_OVERLAY             \\\n  0xe436eb7fL, 0x524f, 0x11ce, 0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70\nDEFINE_GUIDSTRUCT(\"e436eb7f-524f-11ce-9f53-0020af0ba770\", KSDATAFORMAT_SUBTYPE_OVERLAY);\n # define KSDATAFORMAT_SUBTYPE_OVERLAY DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_OVERLAY)\n\n # define STATIC_KSPROPSETID_OverlayUpdate                \\\n  0x490EA5CFL, 0x7681, 0x11D1, 0xA2, 0x1C, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96\nDEFINE_GUIDSTRUCT(\"490EA5CF-7681-11D1-A21C-00A0C9223196\", KSPROPSETID_OverlayUpdate);\n # define KSPROPSETID_OverlayUpdate DEFINE_GUIDNAMED(KSPROPSETID_OverlayUpdate)\n\ntypedef enum\n{\n  KSPROPERTY_OVERLAYUPDATE_INTERESTS,\n  KSPROPERTY_OVERLAYUPDATE_CLIPLIST = 0x1,\n  KSPROPERTY_OVERLAYUPDATE_PALETTE = 0x2,\n  KSPROPERTY_OVERLAYUPDATE_COLORKEY = 0x4,\n  KSPROPERTY_OVERLAYUPDATE_VIDEOPOSITION = 0x8,\n  KSPROPERTY_OVERLAYUPDATE_DISPLAYCHANGE = 0x10,\n  KSPROPERTY_OVERLAYUPDATE_COLORREF = 0x10000000\n}KSPROPERTY_OVERLAYUPDATE;\n\ntypedef struct\n{\n  ULONG PelsWidth;\n  ULONG PelsHeight;\n  ULONG BitsPerPel;\n  WCHAR DeviceID[1];\n}KSDISPLAYCHANGE, * PKSDISPLAYCHANGE;\n\n # define DEFINE_KSPROPERTY_ITEM_OVERLAYUPDATE_INTERESTS(Handler)     \\\n  DEFINE_KSPROPERTY_ITEM(                     \\\n    KSPROPERTY_OVERLAYUPDATE_INTERESTS, \\\n    (Handler),              \\\n    sizeof(KSPROPERTY),         \\\n    sizeof(ULONG),              \\\n    NULL, NULL, 0, NULL, NULL, 0)\n\n # define DEFINE_KSPROPERTY_ITEM_OVERLAYUPDATE_PALETTE(Handler)       \\\n  DEFINE_KSPROPERTY_ITEM(                     \\\n    KSPROPERTY_OVERLAYUPDATE_PALETTE,   \\\n    NULL,                   \\\n    sizeof(KSPROPERTY),         \\\n    0,                  \\\n    (Handler),              \\\n    NULL, 0, NULL, NULL, 0)\n\n # define DEFINE_KSPROPERTY_ITEM_OVERLAYUPDATE_COLORKEY(Handler)      \\\n  DEFINE_KSPROPERTY_ITEM(                     \\\n    KSPROPERTY_OVERLAYUPDATE_COLORKEY,  \\\n    NULL,                   \\\n    sizeof(KSPROPERTY),         \\\n    sizeof(COLORKEY),           \\\n    (Handler),              \\\n    NULL, 0, NULL, NULL, 0)\n\n # define DEFINE_KSPROPERTY_ITEM_OVERLAYUPDATE_CLIPLIST(Handler)      \\\n  DEFINE_KSPROPERTY_ITEM(                     \\\n    KSPROPERTY_OVERLAYUPDATE_CLIPLIST,  \\\n    NULL,                   \\\n    sizeof(KSPROPERTY),         \\\n    2 * sizeof(RECT) + sizeof(RGNDATAHEADER), \\\n    (Handler),              \\\n    NULL, 0, NULL, NULL, 0)\n\n # define DEFINE_KSPROPERTY_ITEM_OVERLAYUPDATE_VIDEOPOSITION(Handler) \\\n  DEFINE_KSPROPERTY_ITEM(                     \\\n    KSPROPERTY_OVERLAYUPDATE_VIDEOPOSITION, \\\n    NULL,                   \\\n    sizeof(KSPROPERTY),         \\\n    2 * sizeof(RECT),            \\\n    (Handler),              \\\n    NULL, 0, NULL, NULL, 0)\n\n # define DEFINE_KSPROPERTY_ITEM_OVERLAYUPDATE_DISPLAYCHANGE(Handler) \\\n  DEFINE_KSPROPERTY_ITEM(                     \\\n    KSPROPERTY_OVERLAYUPDATE_DISPLAYCHANGE, \\\n    NULL,                   \\\n    sizeof(KSPROPERTY),         \\\n    sizeof(KSDISPLAYCHANGE),        \\\n    (Handler),              \\\n    NULL, 0, NULL, NULL, 0)\n\n # define DEFINE_KSPROPERTY_ITEM_OVERLAYUPDATE_COLORREF(Handler)      \\\n  DEFINE_KSPROPERTY_ITEM(                     \\\n    KSPROPERTY_OVERLAYUPDATE_COLORREF,  \\\n    (Handler),              \\\n    sizeof(KSPROPERTY),         \\\n    sizeof(COLORREF),           \\\n    NULL,                   \\\n    NULL, 0, NULL, NULL, 0)\n\n # define STATIC_PROPSETID_VIDCAP_VIDEOCONTROL                \\\n  0x6a2e0670L, 0x28e4, 0x11d0, 0xa1, 0x8c, 0x00, 0xa0, 0xc9, 0x11, 0x89, 0x56\nDEFINE_GUIDSTRUCT(\"6a2e0670-28e4-11d0-a18c-00a0c9118956\", PROPSETID_VIDCAP_VIDEOCONTROL);\n # define PROPSETID_VIDCAP_VIDEOCONTROL DEFINE_GUIDNAMED(PROPSETID_VIDCAP_VIDEOCONTROL)\n\ntypedef enum\n{\n  KSPROPERTY_VIDEOCONTROL_CAPS,\n  KSPROPERTY_VIDEOCONTROL_ACTUAL_FRAME_RATE,\n  KSPROPERTY_VIDEOCONTROL_FRAME_RATES,\n  KSPROPERTY_VIDEOCONTROL_MODE\n}KSPROPERTY_VIDCAP_VIDEOCONTROL;\n\ntypedef enum\n{\n  KS_VideoControlFlag_FlipHorizontal = 0x0001,\n  KS_VideoControlFlag_FlipVertical = 0x0002,\n  KS_Obsolete_VideoControlFlag_ExternalTriggerEnable = 0x0010,\n  KS_Obsolete_VideoControlFlag_Trigger = 0x0020,\n  KS_VideoControlFlag_ExternalTriggerEnable = 0x0004,\n  KS_VideoControlFlag_Trigger = 0x0008\n}KS_VideoControlFlags;\n\ntypedef struct\n{\n  KSPROPERTY Property;\n  ULONG StreamIndex;\n  ULONG VideoControlCaps;\n}KSPROPERTY_VIDEOCONTROL_CAPS_S, * PKSPROPERTY_VIDEOCONTROL_CAPS_S;\n\ntypedef struct\n{\n  KSPROPERTY Property;\n  ULONG StreamIndex;\n  LONG Mode;\n}KSPROPERTY_VIDEOCONTROL_MODE_S, * PKSPROPERTY_VIDEOCONTROL_MODE_S;\n\ntypedef struct\n{\n  KSPROPERTY Property;\n  ULONG StreamIndex;\n  ULONG RangeIndex;\n  SIZE Dimensions;\n  LONGLONG CurrentActualFrameRate;\n  LONGLONG CurrentMaxAvailableFrameRate;\n}KSPROPERTY_VIDEOCONTROL_ACTUAL_FRAME_RATE_S, * PKSPROPERTY_VIDEOCONTROL_ACTUAL_FRAME_RATE_S;\n\ntypedef struct\n{\n  KSPROPERTY Property;\n  ULONG StreamIndex;\n  ULONG RangeIndex;\n  SIZE Dimensions;\n}KSPROPERTY_VIDEOCONTROL_FRAME_RATES_S, * PKSPROPERTY_VIDEOCONTROL_FRAME_RATES_S;\n\n # define STATIC_PROPSETID_VIDCAP_DROPPEDFRAMES               \\\n  0xC6E13344L, 0x30AC, 0x11d0, 0xa1, 0x8c, 0x00, 0xa0, 0xc9, 0x11, 0x89, 0x56\nDEFINE_GUIDSTRUCT(\"C6E13344-30AC-11d0-A18C-00A0C9118956\", PROPSETID_VIDCAP_DROPPEDFRAMES);\n # define PROPSETID_VIDCAP_DROPPEDFRAMES DEFINE_GUIDNAMED(PROPSETID_VIDCAP_DROPPEDFRAMES)\n\ntypedef enum\n{\n  KSPROPERTY_DROPPEDFRAMES_CURRENT\n}KSPROPERTY_VIDCAP_DROPPEDFRAMES;\n\ntypedef struct\n{\n  KSPROPERTY Property;\n  LONGLONG PictureNumber;\n  LONGLONG DropCount;\n  ULONG AverageFrameSize;\n}KSPROPERTY_DROPPEDFRAMES_CURRENT_S, * PKSPROPERTY_DROPPEDFRAMES_CURRENT_S;\n\n # define STATIC_KSPROPSETID_VPConfig                 \\\n  0xbc29a660L, 0x30e3, 0x11d0, 0x9e, 0x69, 0x00, 0xc0, 0x4f, 0xd7, 0xc1, 0x5b\nDEFINE_GUIDSTRUCT(\"bc29a660-30e3-11d0-9e69-00c04fd7c15b\", KSPROPSETID_VPConfig);\n # define KSPROPSETID_VPConfig DEFINE_GUIDNAMED(KSPROPSETID_VPConfig)\n\n # define STATIC_KSPROPSETID_VPVBIConfig                  \\\n  0xec529b00L, 0x1a1f, 0x11d1, 0xba, 0xd9, 0x0, 0x60, 0x97, 0x44, 0x11, 0x1a\nDEFINE_GUIDSTRUCT(\"ec529b00-1a1f-11d1-bad9-00609744111a\", KSPROPSETID_VPVBIConfig);\n # define KSPROPSETID_VPVBIConfig DEFINE_GUIDNAMED(KSPROPSETID_VPVBIConfig)\n\ntypedef enum\n{\n  KSPROPERTY_VPCONFIG_NUMCONNECTINFO,\n  KSPROPERTY_VPCONFIG_GETCONNECTINFO,\n  KSPROPERTY_VPCONFIG_SETCONNECTINFO,\n  KSPROPERTY_VPCONFIG_VPDATAINFO,\n  KSPROPERTY_VPCONFIG_MAXPIXELRATE,\n  KSPROPERTY_VPCONFIG_INFORMVPINPUT,\n  KSPROPERTY_VPCONFIG_NUMVIDEOFORMAT,\n  KSPROPERTY_VPCONFIG_GETVIDEOFORMAT,\n  KSPROPERTY_VPCONFIG_SETVIDEOFORMAT,\n  KSPROPERTY_VPCONFIG_INVERTPOLARITY,\n  KSPROPERTY_VPCONFIG_DECIMATIONCAPABILITY,\n  KSPROPERTY_VPCONFIG_SCALEFACTOR,\n  KSPROPERTY_VPCONFIG_DDRAWHANDLE,\n  KSPROPERTY_VPCONFIG_VIDEOPORTID,\n  KSPROPERTY_VPCONFIG_DDRAWSURFACEHANDLE,\n  KSPROPERTY_VPCONFIG_SURFACEPARAMS\n}KSPROPERTY_VPCONFIG;\n\n # define STATIC_CLSID_KsIBasicAudioInterfaceHandler          \\\n  0xb9f8ac3e, 0x0f71, 0x11d2, 0xb7, 0x2c, 0x00, 0xc0, 0x4f, 0xb6, 0xbd, 0x3d\nDEFINE_GUIDSTRUCT(\"b9f8ac3e-0f71-11d2-b72c-00c04fb6bd3d\", CLSID_KsIBasicAudioInterfaceHandler);\n # define CLSID_KsIBasicAudioInterfaceHandler DEFINE_GUIDNAMED(CLSID_KsIBasicAudioInterfaceHandler)\n\n # ifdef __IVPType__\ntypedef struct\n{\n  AMVPSIZE Size;\n  DWORD MaxPixelsPerSecond;\n  DWORD Reserved;\n}KSVPMAXPIXELRATE, * PKSVPMAXPIXELRATE;\n\ntypedef struct\n{\n  KSPROPERTY Property;\n  AMVPSIZE Size;\n}KSVPSIZE_PROP, * PKSVPSIZE_PROP;\n\ntypedef struct\n{\n  DWORD dwPitch;\n  DWORD dwXOrigin;\n  DWORD dwYOrigin;\n}KSVPSURFACEPARAMS, * PKSVPSURFACEPARAMS;\n # else /* __IVPType__ */\n\n  #  ifndef __DDRAW_INCLUDED__\n   #   define DDPF_FOURCC 0x00000004l\n\ntypedef struct _DDPIXELFORMAT\n{\n  DWORD dwSize;\n  DWORD dwFlags;\n  DWORD dwFourCC;\n  __MINGW_EXTENSION union\n  {\n    DWORD dwRGBBitCount;\n    DWORD dwYUVBitCount;\n    DWORD dwZBufferBitDepth;\n    DWORD dwAlphaBitDepth;\n  };\n  __MINGW_EXTENSION union\n  {\n    DWORD dwRBitMask;\n    DWORD dwYBitMask;\n  };\n  __MINGW_EXTENSION union\n  {\n    DWORD dwGBitMask;\n    DWORD dwUBitMask;\n  };\n  __MINGW_EXTENSION union\n  {\n    DWORD dwBBitMask;\n    DWORD dwVBitMask;\n  };\n  __MINGW_EXTENSION union\n  {\n    DWORD dwRGBAlphaBitMask;\n    DWORD dwYUVAlphaBitMask;\n    DWORD dwRGBZBitMask;\n    DWORD dwYUVZBitMask;\n  };\n}DDPIXELFORMAT, * LPDDPIXELFORMAT;\n  #  endif /* __DDRAW_INCLUDED__ */\n\n  #  ifndef __DVP_INCLUDED__\ntypedef struct _DDVIDEOPORTCONNECT\n{\n  DWORD dwSize;\n  DWORD dwPortWidth;\n  GUID guidTypeID;\n  DWORD dwFlags;\n  ULONG_PTR dwReserved1;\n}DDVIDEOPORTCONNECT, * LPDDVIDEOPORTCONNECT;\n\n   #   define DDVPTYPE_E_HREFH_VREFH                      \\\n  0x54F39980L, 0xDA60, 0x11CF, 0x9B, 0x06, 0x00, 0xA0, 0xC9, 0x03, 0xA3, 0xB8\n\n   #   define DDVPTYPE_E_HREFL_VREFL                      \\\n  0xE09C77E0L, 0xDA60, 0x11CF, 0x9B, 0x06, 0x00, 0xA0, 0xC9, 0x03, 0xA3, 0xB8\n  #  endif /* __DVP_INCLUDED__ */\n\ntypedef enum\n{\n  KS_PixAspectRatio_NTSC4x3,\n  KS_PixAspectRatio_NTSC16x9,\n  KS_PixAspectRatio_PAL4x3,\n  KS_PixAspectRatio_PAL16x9\n}KS_AMPixAspectRatio;\n\ntypedef enum\n{\n  KS_AMVP_DO_NOT_CARE,\n  KS_AMVP_BEST_BANDWIDTH,\n  KS_AMVP_INPUT_SAME_AS_OUTPUT\n}KS_AMVP_SELECTFORMATBY;\n\ntypedef enum\n{\n  KS_AMVP_MODE_WEAVE,\n  KS_AMVP_MODE_BOBINTERLEAVED,\n  KS_AMVP_MODE_BOBNONINTERLEAVED,\n  KS_AMVP_MODE_SKIPEVEN,\n  KS_AMVP_MODE_SKIPODD\n}KS_AMVP_MODE;\n\ntypedef struct tagKS_AMVPDIMINFO\n{\n  DWORD dwFieldWidth;\n  DWORD dwFieldHeight;\n  DWORD dwVBIWidth;\n  DWORD dwVBIHeight;\n  RECT rcValidRegion;\n}KS_AMVPDIMINFO, * PKS_AMVPDIMINFO;\n\ntypedef struct tagKS_AMVPDATAINFO\n{\n  DWORD dwSize;\n  DWORD dwMicrosecondsPerField;\n  KS_AMVPDIMINFO amvpDimInfo;\n  DWORD dwPictAspectRatioX;\n  DWORD dwPictAspectRatioY;\n  WINBOOL bEnableDoubleClock;\n  WINBOOL bEnableVACT;\n  WINBOOL bDataIsInterlaced;\n  LONG lHalfLinesOdd;\n  WINBOOL bFieldPolarityInverted;\n  DWORD dwNumLinesInVREF;\n  LONG lHalfLinesEven;\n  DWORD dwReserved1;\n}KS_AMVPDATAINFO, * PKS_AMVPDATAINFO;\n\ntypedef struct tagKS_AMVPSIZE\n{\n  DWORD dwWidth;\n  DWORD dwHeight;\n}KS_AMVPSIZE, * PKS_AMVPSIZE;\n\ntypedef struct\n{\n  KS_AMVPSIZE Size;\n  DWORD MaxPixelsPerSecond;\n  DWORD Reserved;\n}KSVPMAXPIXELRATE, * PKSVPMAXPIXELRATE;\n\ntypedef struct\n{\n  KSPROPERTY Property;\n  KS_AMVPSIZE Size;\n}KSVPSIZE_PROP, * PKSVPSIZE_PROP;\n\ntypedef struct\n{\n  DWORD dwPitch;\n  DWORD dwXOrigin;\n  DWORD dwYOrigin;\n}KSVPSURFACEPARAMS, * PKSVPSURFACEPARAMS;\n # endif /* __IVPType__ */\n\n # define STATIC_KSEVENTSETID_VPNotify                    \\\n  0x20c5598eL, 0xd3c8, 0x11d0, 0x8d, 0xfc, 0x00, 0xc0, 0x4f, 0xd7, 0xc0, 0x8b\nDEFINE_GUIDSTRUCT(\"20c5598e-d3c8-11d0-8dfc-00c04fd7c08b\", KSEVENTSETID_VPNotify);\n # define KSEVENTSETID_VPNotify DEFINE_GUIDNAMED(KSEVENTSETID_VPNotify)\n\ntypedef enum\n{\n  KSEVENT_VPNOTIFY_FORMATCHANGE\n}KSEVENT_VPNOTIFY;\n\n # define STATIC_KSEVENTSETID_VIDCAPTOSTI                 \\\n  0xdb47de20, 0xf628, 0x11d1, 0xba, 0x41, 0x0, 0xa0, 0xc9, 0xd, 0x2b, 0x5\nDEFINE_GUIDSTRUCT(\"DB47DE20-F628-11d1-BA41-00A0C90D2B05\", KSEVENTSETID_VIDCAPTOSTI);\n # define KSEVENTSETID_VIDCAPNotify DEFINE_GUIDNAMED(KSEVENTSETID_VIDCAPTOSTI)\n\ntypedef enum\n{\n  KSEVENT_VIDCAPTOSTI_EXT_TRIGGER,\n  KSEVENT_VIDCAP_AUTO_UPDATE,\n  KSEVENT_VIDCAP_SEARCH\n}KSEVENT_VIDCAPTOSTI;\n\ntypedef enum\n{\n  KSPROPERTY_EXTENSION_UNIT_INFO,\n  KSPROPERTY_EXTENSION_UNIT_CONTROL,\n  KSPROPERTY_EXTENSION_UNIT_PASS_THROUGH = 0xffff\n}KSPROPERTY_EXTENSION_UNIT, * PKSPROPERTY_EXTENSION_UNIT;\n\n # define STATIC_KSEVENTSETID_VPVBINotify                 \\\n  0xec529b01L, 0x1a1f, 0x11d1, 0xba, 0xd9, 0x0, 0x60, 0x97, 0x44, 0x11, 0x1a\nDEFINE_GUIDSTRUCT(\"ec529b01-1a1f-11d1-bad9-00609744111a\", KSEVENTSETID_VPVBINotify);\n # define KSEVENTSETID_VPVBINotify DEFINE_GUIDNAMED(KSEVENTSETID_VPVBINotify)\n\ntypedef enum\n{\n  KSEVENT_VPVBINOTIFY_FORMATCHANGE\n}KSEVENT_VPVBINOTIFY;\n\n # define STATIC_KSDATAFORMAT_TYPE_AUXLine21Data              \\\n  0x670aea80L, 0x3a82, 0x11d0, 0xb7, 0x9b, 0x00, 0xaa, 0x00, 0x37, 0x67, 0xa7\nDEFINE_GUIDSTRUCT(\"670aea80-3a82-11d0-b79b-00aa003767a7\", KSDATAFORMAT_TYPE_AUXLine21Data);\n # define KSDATAFORMAT_TYPE_AUXLine21Data DEFINE_GUIDNAMED(KSDATAFORMAT_TYPE_AUXLine21Data)\n\n # define STATIC_KSDATAFORMAT_SUBTYPE_Line21_BytePair         \\\n  0x6e8d4a22L, 0x310c, 0x11d0, 0xb7, 0x9a, 0x00, 0xaa, 0x00, 0x37, 0x67, 0xa7\nDEFINE_GUIDSTRUCT(\"6e8d4a22-310c-11d0-b79a-00aa003767a7\", KSDATAFORMAT_SUBTYPE_Line21_BytePair);\n # define KSDATAFORMAT_SUBTYPE_Line21_BytePair DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_Line21_BytePair)\n\n # define STATIC_KSDATAFORMAT_SUBTYPE_Line21_GOPPacket            \\\n  0x6e8d4a23L, 0x310c, 0x11d0, 0xb7, 0x9a, 0x00, 0xaa, 0x00, 0x37, 0x67, 0xa7\nDEFINE_GUIDSTRUCT(\"6e8d4a23-310c-11d0-b79a-00aa003767a7\", KSDATAFORMAT_SUBTYPE_Line21_GOPPacket);\n # define KSDATAFORMAT_SUBTYPE_Line21_GOPPacket DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_Line21_GOPPacket)\n\ntypedef struct _KSGOP_USERDATA\n{\n  ULONG sc;\n  ULONG reserved1;\n  BYTE cFields;\n  CHAR l21Data[3];\n}KSGOP_USERDATA, * PKSGOP_USERDATA;\n\n # define STATIC_KSDATAFORMAT_TYPE_DVD_ENCRYPTED_PACK         \\\n  0xed0b916a, 0x044d, 0x11d1, 0xaa, 0x78, 0x00, 0xc0, 0x4f, 0xc3, 0x1d, 0x60\nDEFINE_GUIDSTRUCT(\"ed0b916a-044d-11d1-aa78-00c04fc31d60\", KSDATAFORMAT_TYPE_DVD_ENCRYPTED_PACK);\n # define KSDATAFORMAT_TYPE_DVD_ENCRYPTED_PACK DEFINE_GUIDNAMED(KSDATAFORMAT_TYPE_DVD_ENCRYPTED_PACK)\n\n # define KS_AM_UseNewCSSKey 0x1\n\n # define STATIC_KSPROPSETID_TSRateChange                 \\\n  0xa503c5c0, 0x1d1d, 0x11d1, 0xad, 0x80, 0x44, 0x45, 0x53, 0x54, 0x0, 0x0\nDEFINE_GUIDSTRUCT(\"A503C5C0-1D1D-11D1-AD80-444553540000\", KSPROPSETID_TSRateChange);\n # define KSPROPSETID_TSRateChange DEFINE_GUIDNAMED(KSPROPSETID_TSRateChange)\n\ntypedef enum\n{\n  KS_AM_RATE_SimpleRateChange = 1,\n  KS_AM_RATE_ExactRateChange = 2,\n  KS_AM_RATE_MaxFullDataRate = 3,\n  KS_AM_RATE_Step = 4\n}KS_AM_PROPERTY_TS_RATE_CHANGE;\n\ntypedef struct\n{\n  REFERENCE_TIME StartTime;\n  LONG Rate;\n}KS_AM_SimpleRateChange, * PKS_AM_SimpleRateChange;\n\ntypedef struct\n{\n  REFERENCE_TIME OutputZeroTime;\n  LONG Rate;\n}KS_AM_ExactRateChange, * PKS_AM_ExactRateChange;\n\ntypedef LONG KS_AM_MaxFullDataRate;\ntypedef DWORD KS_AM_Step;\n\n # define STATIC_KSCATEGORY_ENCODER                   \\\n  0x19689bf6, 0xc384, 0x48fd, 0xad, 0x51, 0x90, 0xe5, 0x8c, 0x79, 0xf7, 0xb\nDEFINE_GUIDSTRUCT(\"19689BF6-C384-48fd-AD51-90E58C79F70B\", KSCATEGORY_ENCODER);\n # define KSCATEGORY_ENCODER DEFINE_GUIDNAMED(KSCATEGORY_ENCODER)\n\n # define STATIC_KSCATEGORY_MULTIPLEXER                   \\\n  0x7a5de1d3, 0x1a1, 0x452c, 0xb4, 0x81, 0x4f, 0xa2, 0xb9, 0x62, 0x71, 0xe8\nDEFINE_GUIDSTRUCT(\"7A5DE1D3-01A1-452c-B481-4FA2B96271E8\", KSCATEGORY_MULTIPLEXER);\n # define KSCATEGORY_MULTIPLEXER DEFINE_GUIDNAMED(KSCATEGORY_MULTIPLEXER)\n\n # ifndef __ENCODER_API_GUIDS__\n  #  define __ENCODER_API_GUIDS__\n\n  #  define STATIC_ENCAPIPARAM_BITRATE                  \\\n  0x49cc4c43, 0xca83, 0x4ad4, 0xa9, 0xaf, 0xf3, 0x69, 0x6a, 0xf6, 0x66, 0xdf\nDEFINE_GUIDSTRUCT(\"49CC4C43-CA83-4ad4-A9AF-F3696AF666DF\", ENCAPIPARAM_BITRATE);\n  #  define ENCAPIPARAM_BITRATE DEFINE_GUIDNAMED(ENCAPIPARAM_BITRATE)\n\n  #  define STATIC_ENCAPIPARAM_PEAK_BITRATE                 \\\n  0x703f16a9, 0x3d48, 0x44a1, 0xb0, 0x77, 0x1, 0x8d, 0xff, 0x91, 0x5d, 0x19\nDEFINE_GUIDSTRUCT(\"703F16A9-3D48-44a1-B077-018DFF915D19\", ENCAPIPARAM_PEAK_BITRATE);\n  #  define ENCAPIPARAM_PEAK_BITRATE DEFINE_GUIDNAMED(ENCAPIPARAM_PEAK_BITRATE)\n\n  #  define STATIC_ENCAPIPARAM_BITRATE_MODE                 \\\n  0xee5fb25c, 0xc713, 0x40d1, 0x9d, 0x58, 0xc0, 0xd7, 0x24, 0x1e, 0x25, 0xf\nDEFINE_GUIDSTRUCT(\"EE5FB25C-C713-40d1-9D58-C0D7241E250F\", ENCAPIPARAM_BITRATE_MODE);\n  #  define ENCAPIPARAM_BITRATE_MODE DEFINE_GUIDNAMED(ENCAPIPARAM_BITRATE_MODE)\n\n  #  define STATIC_CODECAPI_CHANGELISTS                 \\\n  0x62b12acf, 0xf6b0, 0x47d9, 0x94, 0x56, 0x96, 0xf2, 0x2c, 0x4e, 0x0b, 0x9d\nDEFINE_GUIDSTRUCT(\"62B12ACF-F6B0-47D9-9456-96F22C4E0B9D\", CODECAPI_CHANGELISTS);\n  #  define CODECAPI_CHANGELISTS DEFINE_GUIDNAMED(CODECAPI_CHANGELISTS)\n\n  #  define STATIC_CODECAPI_VIDEO_ENCODER                   \\\n  0x7112e8e1, 0x3d03, 0x47ef, 0x8e, 0x60, 0x03, 0xf1, 0xcf, 0x53, 0x73, 0x01\nDEFINE_GUIDSTRUCT(\"7112E8E1-3D03-47EF-8E60-03F1CF537301\", CODECAPI_VIDEO_ENCODER);\n  #  define CODECAPI_VIDEO_ENCODER DEFINE_GUIDNAMED(CODECAPI_VIDEO_ENCODER)\n\n  #  define STATIC_CODECAPI_AUDIO_ENCODER                   \\\n  0xb9d19a3e, 0xf897, 0x429c, 0xbc, 0x46, 0x81, 0x38, 0xb7, 0x27, 0x2b, 0x2d\nDEFINE_GUIDSTRUCT(\"B9D19A3E-F897-429C-BC46-8138B7272B2D\", CODECAPI_AUDIO_ENCODER);\n  #  define CODECAPI_AUDIO_ENCODER DEFINE_GUIDNAMED(CODECAPI_AUDIO_ENCODER)\n\n  #  define STATIC_CODECAPI_SETALLDEFAULTS                  \\\n  0x6c5e6a7c, 0xacf8, 0x4f55, 0xa9, 0x99, 0x1a, 0x62, 0x81, 0x09, 0x05, 0x1b\nDEFINE_GUIDSTRUCT(\"6C5E6A7C-ACF8-4F55-A999-1A628109051B\", CODECAPI_SETALLDEFAULTS);\n  #  define CODECAPI_SETALLDEFAULTS DEFINE_GUIDNAMED(CODECAPI_SETALLDEFAULTS)\n\n  #  define STATIC_CODECAPI_ALLSETTINGS                 \\\n  0x6a577e92, 0x83e1, 0x4113, 0xad, 0xc2, 0x4f, 0xce, 0xc3, 0x2f, 0x83, 0xa1\nDEFINE_GUIDSTRUCT(\"6A577E92-83E1-4113-ADC2-4FCEC32F83A1\", CODECAPI_ALLSETTINGS);\n  #  define CODECAPI_ALLSETTINGS DEFINE_GUIDNAMED(CODECAPI_ALLSETTINGS)\n\n  #  define STATIC_CODECAPI_SUPPORTSEVENTS                  \\\n  0x0581af97, 0x7693, 0x4dbd, 0x9d, 0xca, 0x3f, 0x9e, 0xbd, 0x65, 0x85, 0xa1\nDEFINE_GUIDSTRUCT(\"0581AF97-7693-4DBD-9DCA-3F9EBD6585A1\", CODECAPI_SUPPORTSEVENTS);\n  #  define CODECAPI_SUPPORTSEVENTS DEFINE_GUIDNAMED(CODECAPI_SUPPORTSEVENTS)\n\n  #  define STATIC_CODECAPI_CURRENTCHANGELIST               \\\n  0x1cb14e83, 0x7d72, 0x4657, 0x83, 0xfd, 0x47, 0xa2, 0xc5, 0xb9, 0xd1, 0x3d\nDEFINE_GUIDSTRUCT(\"1CB14E83-7D72-4657-83FD-47A2C5B9D13D\", CODECAPI_CURRENTCHANGELIST);\n  #  define CODECAPI_CURRENTCHANGELIST DEFINE_GUIDNAMED(CODECAPI_CURRENTCHANGELIST)\n # endif /* __ENCODER_API_GUIDS__ */\n\n # ifndef __ENCODER_API_DEFINES__\n  #  define __ENCODER_API_DEFINES__\ntypedef enum\n{\n  ConstantBitRate = 0,\n  VariableBitRateAverage,\n  VariableBitRatePeak\n}VIDEOENCODER_BITRATE_MODE;\n # endif /* __ENCODER_API_DEFINES__ */\n\n # define STATIC_KSPROPSETID_Jack \\\n  0x4509f757, 0x2d46, 0x4637, 0x8e, 0x62, 0xce, 0x7d, 0xb9, 0x44, 0xf5, 0x7b\nDEFINE_GUIDSTRUCT(\"4509F757-2D46-4637-8E62-CE7DB944F57B\", KSPROPSETID_Jack);\n # define KSPROPSETID_Jack DEFINE_GUIDNAMED(KSPROPSETID_Jack)\n\ntypedef enum\n{\n  KSPROPERTY_JACK_DESCRIPTION = 1,\n  KSPROPERTY_JACK_DESCRIPTION2,\n  KSPROPERTY_JACK_SINK_INFO\n}KSPROPERTY_JACK;\n\ntypedef enum\n{\n  eConnTypeUnknown,\n  eConnType3Point5mm,\n  eConnTypeQuarter,\n  eConnTypeAtapiInternal,\n  eConnTypeRCA,\n  eConnTypeOptical,\n  eConnTypeOtherDigital,\n  eConnTypeOtherAnalog,\n  eConnTypeMultichannelAnalogDIN,\n  eConnTypeXlrProfessional,\n  eConnTypeRJ11Modem,\n  eConnTypeCombination\n}EPcxConnectionType;\n\ntypedef enum\n{\n  eGeoLocRear = 0x1,\n  eGeoLocFront,\n  eGeoLocLeft,\n  eGeoLocRight,\n  eGeoLocTop,\n  eGeoLocBottom,\n  eGeoLocRearPanel,\n  eGeoLocRiser,\n  eGeoLocInsideMobileLid,\n  eGeoLocDrivebay,\n  eGeoLocHDMI,\n  eGeoLocOutsideMobileLid,\n  eGeoLocATAPI,\n  eGeoLocReserved5,\n  eGeoLocReserved6,\n  EPcxGeoLocation_enum_count\n}EPcxGeoLocation;\n\ntypedef enum\n{\n  eGenLocPrimaryBox = 0,\n  eGenLocInternal,\n  eGenLocSeparate,\n  eGenLocOther,\n  EPcxGenLocation_enum_count\n}EPcxGenLocation;\n\ntypedef enum\n{\n  ePortConnJack = 0,\n  ePortConnIntegratedDevice,\n  ePortConnBothIntegratedAndJack,\n  ePortConnUnknown\n}EPxcPortConnection;\n\ntypedef struct\n{\n  DWORD ChannelMapping;\n  COLORREF Color;\n  EPcxConnectionType ConnectionType;\n  EPcxGeoLocation GeoLocation;\n  EPcxGenLocation GenLocation;\n  EPxcPortConnection PortConnection;\n  BOOL IsConnected;\n}KSJACK_DESCRIPTION, * PKSJACK_DESCRIPTION;\n\ntypedef enum\n{\n  KSJACK_SINK_CONNECTIONTYPE_HDMI = 0,\n  KSJACK_SINK_CONNECTIONTYPE_DISPLAYPORT,\n}KSJACK_SINK_CONNECTIONTYPE;\n\n # define MAX_SINK_DESCRIPTION_NAME_LENGTH 32\ntypedef struct _tagKSJACK_SINK_INFORMATION\n{\n  KSJACK_SINK_CONNECTIONTYPE ConnType;\n  WORD ManufacturerId;\n  WORD ProductId;\n  WORD AudioLatency;\n  BOOL HDCPCapable;\n  BOOL AICapable;\n  UCHAR SinkDescriptionLength;\n  WCHAR SinkDescription[MAX_SINK_DESCRIPTION_NAME_LENGTH];\n  LUID PortId;\n}KSJACK_SINK_INFORMATION, * PKSJACK_SINK_INFORMATION;\n\n # define JACKDESC2_PRESENCE_DETECT_CAPABILITY 0x00000001\n # define JACKDESC2_DYNAMIC_FORMAT_CHANGE_CAPABILITY 0x00000002\n\ntypedef struct _tagKSJACK_DESCRIPTION2\n{\n  DWORD DeviceStateInfo;\n  DWORD JackCapabilities;\n}KSJACK_DESCRIPTION2, * PKSJACK_DESCRIPTION2;\n\n#endif /* _KSMEDIA_ */\n\n"
  },
  {
    "path": "rtmidi/msw/readme",
    "content": "This directory contains a Visual Studio 2008 project, contributed by Jason Champion, to build rtmidi as a library.  The library builds to the <rtmidi-x.x.x>\\lib directory."
  },
  {
    "path": "rtmidi/msw/rtmidilib.sln",
    "content": "﻿\r\nMicrosoft Visual Studio Solution File, Format Version 10.00\r\n# Visual Studio 2008\r\nProject(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"rtmidilib\", \"rtmidilib.vcproj\", \"{EBFE5EB3-182A-47A6-922B-52ECF777F6A3}\"\r\nEndProject\r\nGlobal\r\n\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\r\n\t\tDebug|Win32 = Debug|Win32\r\n\t\tRelease|Win32 = Release|Win32\r\n\tEndGlobalSection\r\n\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\r\n\t\t{EBFE5EB3-182A-47A6-922B-52ECF777F6A3}.Debug|Win32.ActiveCfg = Debug|Win32\r\n\t\t{EBFE5EB3-182A-47A6-922B-52ECF777F6A3}.Debug|Win32.Build.0 = Debug|Win32\r\n\t\t{EBFE5EB3-182A-47A6-922B-52ECF777F6A3}.Release|Win32.ActiveCfg = Release|Win32\r\n\t\t{EBFE5EB3-182A-47A6-922B-52ECF777F6A3}.Release|Win32.Build.0 = Release|Win32\r\n\tEndGlobalSection\r\n\tGlobalSection(SolutionProperties) = preSolution\r\n\t\tHideSolutionNode = FALSE\r\n\tEndGlobalSection\r\nEndGlobal\r\n"
  },
  {
    "path": "rtmidi/msw/rtmidilib.vcproj",
    "content": "<?xml version=\"1.0\" encoding=\"Windows-1252\"?>\r\n<VisualStudioProject\r\n\tProjectType=\"Visual C++\"\r\n\tVersion=\"9.00\"\r\n\tName=\"rtmidilib\"\r\n\tProjectGUID=\"{EBFE5EB3-182A-47A6-922B-52ECF777F6A3}\"\r\n\tRootNamespace=\"rtmidilib\"\r\n\tTargetFrameworkVersion=\"196613\"\r\n\t>\r\n\t<Platforms>\r\n\t\t<Platform\r\n\t\t\tName=\"Win32\"\r\n\t\t/>\r\n\t</Platforms>\r\n\t<ToolFiles>\r\n\t</ToolFiles>\r\n\t<Configurations>\r\n\t\t<Configuration\r\n\t\t\tName=\"Debug|Win32\"\r\n\t\t\tOutputDirectory=\"$(SolutionDir)$(ConfigurationName)\"\r\n\t\t\tIntermediateDirectory=\"$(ConfigurationName)\"\r\n\t\t\tConfigurationType=\"4\"\r\n\t\t\tCharacterSet=\"1\"\r\n\t\t\t>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCPreBuildEventTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCCustomBuildTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCXMLDataGeneratorTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCMIDLTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCCLCompilerTool\"\r\n\t\t\t\tOptimization=\"0\"\r\n\t\t\t\tPreprocessorDefinitions=\"__WINDOWS_MM__\"\r\n\t\t\t\tMinimalRebuild=\"true\"\r\n\t\t\t\tBasicRuntimeChecks=\"3\"\r\n\t\t\t\tRuntimeLibrary=\"3\"\r\n\t\t\t\tWarningLevel=\"3\"\r\n\t\t\t\tDebugInformationFormat=\"4\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCResourceCompilerTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCPreLinkEventTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCLibrarianTool\"\r\n\t\t\t\tOutputFile=\"..\\lib\\rtmidid.lib\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCALinkTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCXDCMakeTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCBscMakeTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCFxCopTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCPostBuildEventTool\"\r\n\t\t\t/>\r\n\t\t</Configuration>\r\n\t\t<Configuration\r\n\t\t\tName=\"Release|Win32\"\r\n\t\t\tOutputDirectory=\"$(SolutionDir)$(ConfigurationName)\"\r\n\t\t\tIntermediateDirectory=\"$(ConfigurationName)\"\r\n\t\t\tConfigurationType=\"4\"\r\n\t\t\tCharacterSet=\"1\"\r\n\t\t\tWholeProgramOptimization=\"1\"\r\n\t\t\t>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCPreBuildEventTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCCustomBuildTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCXMLDataGeneratorTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCWebServiceProxyGeneratorTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCMIDLTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCCLCompilerTool\"\r\n\t\t\t\tOptimization=\"2\"\r\n\t\t\t\tEnableIntrinsicFunctions=\"true\"\r\n\t\t\t\tPreprocessorDefinitions=\"__WINDOWS_MM__\"\r\n\t\t\t\tRuntimeLibrary=\"2\"\r\n\t\t\t\tEnableFunctionLevelLinking=\"true\"\r\n\t\t\t\tWarningLevel=\"3\"\r\n\t\t\t\tDebugInformationFormat=\"3\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCManagedResourceCompilerTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCResourceCompilerTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCPreLinkEventTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCLibrarianTool\"\r\n\t\t\t\tOutputFile=\"..\\lib\\rtmidi.lib\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCALinkTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCXDCMakeTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCBscMakeTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCFxCopTool\"\r\n\t\t\t/>\r\n\t\t\t<Tool\r\n\t\t\t\tName=\"VCPostBuildEventTool\"\r\n\t\t\t/>\r\n\t\t</Configuration>\r\n\t</Configurations>\r\n\t<References>\r\n\t</References>\r\n\t<Files>\r\n\t\t<Filter\r\n\t\t\tName=\"Source Files\"\r\n\t\t\tFilter=\"cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx\"\r\n\t\t\tUniqueIdentifier=\"{4FC737F1-C7A5-4376-A066-2A32D752A2FF}\"\r\n\t\t\t>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\RtMidi.cpp\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t</Filter>\r\n\t\t<Filter\r\n\t\t\tName=\"Header Files\"\r\n\t\t\tFilter=\"h;hpp;hxx;hm;inl;inc;xsd\"\r\n\t\t\tUniqueIdentifier=\"{93995380-89BD-4b04-88EB-625FBE52EBFB}\"\r\n\t\t\t>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\RtError.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t\t<File\r\n\t\t\t\tRelativePath=\"..\\RtMidi.h\"\r\n\t\t\t\t>\r\n\t\t\t</File>\r\n\t\t</Filter>\r\n\t\t<Filter\r\n\t\t\tName=\"Resource Files\"\r\n\t\t\tFilter=\"rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav\"\r\n\t\t\tUniqueIdentifier=\"{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}\"\r\n\t\t\t>\r\n\t\t</Filter>\r\n\t</Files>\r\n\t<Globals>\r\n\t</Globals>\r\n</VisualStudioProject>\r\n"
  },
  {
    "path": "rtmidi/readme",
    "content": "RtMidi - a set of C++ classes that provide a common API for realtime MIDI input/output across GNU/Linux (ALSA & Jack), Macintosh OS X (CoreMidi) and Windows (Multimedia & Kernel Streaming).\n\nBy Gary P. Scavone, 2003-2012.\n\nThis distribution of RtMidi contains the following:\n\ndoc:      RtMidi documentation (see doc/html/index.html)\ntests:    example RtMidi programs\n\nOn 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.\n\nOVERVIEW:\n\nRtMidi 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 GNU/Linux (ALSA, Jack), Macintosh OS X (CoreMidi, Jack), SGI, 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:\n\n  - object oriented C++ design\n  - simple, common API across all supported platforms\n  - only two header files and one source file for easy inclusion in programming projects\n  - MIDI device enumeration\n\nMIDI 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<unsigned char>.\n\nFURTHER READING:\n\nFor complete documentation on RtMidi, see the doc directory of the distribution or surf to http://music.mcgill.ca/~gary/rtmidi/.\n\n\nLEGAL AND ETHICAL:\n\nThe RtMidi license is similar to the the MIT License, with the added \"feature\" that modifications be sent to the developer.\n\n    RtMidi: realtime MIDI i/o C++ classes\n    Copyright (c) 2003-2012 Gary P. Scavone\n\n    Permission is hereby granted, free of charge, to any person\n    obtaining a copy of this software and associated documentation files\n    (the \"Software\"), to deal in the Software without restriction,\n    including without limitation the rights to use, copy, modify, merge,\n    publish, distribute, sublicense, and/or sell copies of the Software,\n    and to permit persons to whom the Software is furnished to do so,\n    subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be\n    included in all copies or substantial portions of the Software.\n\n    Any person wishing to distribute modifications to the Software is\n    asked to send the modifications to the original developer so that\n    they can be incorporated into the canonical version.  This is,\n    however, not a binding provision of this license.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR\n    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF\n    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\n    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "rtmidi/rtmidi-config.in",
    "content": "#! /bin/sh\nif (test \"x$#\" != \"x1\") ; then\n  echo \"Usage: $0 [--libs | --cxxflags | --cppflags]\"\n  exit;\nfi\n\nLIBRARY=\"@LIBS@\"\nCXXFLAGS=\"@CXXFLAGS@\"\nCPPFLAGS=\"@CPPFLAGS@\"\n\nif (test \"x$1\" == \"x--libs\") ; then\n  echo \"$LIBRARY\"\nelif (test \"x$1\" == \"x--cxxflags\") ; then\n  echo \"$CXXFLAGS\"\nelif (test \"x$1\" == \"x--cppflags\") ; then\n  echo \"$CPPFLAGS\"\nelse\n  echo \"Unknown option: $1\"\nfi\n"
  },
  {
    "path": "rtmidi/tests/RtMidi.dsw",
    "content": "Microsoft Developer Studio Workspace File, Format Version 6.00\r\n# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!\r\n\r\n###############################################################################\r\n\r\nProject: \"cmidiin\"=\".\\cmidiin.dsp\" - Package Owner=<4>\r\n\r\nPackage=<5>\r\n{{{\r\n}}}\r\n\r\nPackage=<4>\r\n{{{\r\n}}}\r\n\r\n###############################################################################\r\n\r\nProject: \"midiout\"=\".\\midiout.dsp\" - Package Owner=<4>\r\n\r\nPackage=<5>\r\n{{{\r\n}}}\r\n\r\nPackage=<4>\r\n{{{\r\n}}}\r\n\r\n###############################################################################\r\n\r\nProject: \"midiprobe\"=\".\\midiprobe.dsp\" - Package Owner=<4>\r\n\r\nPackage=<5>\r\n{{{\r\n}}}\r\n\r\nPackage=<4>\r\n{{{\r\n}}}\r\n\r\n###############################################################################\r\n\r\nProject: \"qmidiin\"=\".\\qmidiin.dsp\" - Package Owner=<4>\r\n\r\nPackage=<5>\r\n{{{\r\n}}}\r\n\r\nPackage=<4>\r\n{{{\r\n}}}\r\n\r\n###############################################################################\r\n\r\nProject: \"sysextest\"=\".\\sysextest.dsp\" - Package Owner=<4>\r\n\r\nPackage=<5>\r\n{{{\r\n}}}\r\n\r\nPackage=<4>\r\n{{{\r\n}}}\r\n\r\n###############################################################################\r\n\r\nGlobal:\r\n\r\nPackage=<5>\r\n{{{\r\n}}}\r\n\r\nPackage=<3>\r\n{{{\r\n}}}\r\n\r\n###############################################################################\r\n\r\n"
  },
  {
    "path": "rtmidi/tests/cmidiin.cpp",
    "content": "//*****************************************//\n//  cmidiin.cpp\n//  by Gary Scavone, 2003-2004.\n//\n//  Simple program to test MIDI input and\n//  use of a user callback function.\n//\n//*****************************************//\n\n#include <iostream>\n#include <cstdlib>\n#include \"RtMidi.h\"\n\nvoid usage( void ) {\n  // Error function in case of incorrect command-line\n  // argument specifications.\n  std::cout << \"\\nuseage: cmidiin <port>\\n\";\n  std::cout << \"    where port = the device to use (default = 0).\\n\\n\";\n  exit( 0 );\n}\n\nvoid mycallback( double deltatime, std::vector< unsigned char > *message, void *userData )\n{\n  unsigned int nBytes = message->size();\n  for ( unsigned int i=0; i<nBytes; i++ )\n    std::cout << \"Byte \" << i << \" = \" << (int)message->at(i) << \", \";\n  if ( nBytes > 0 )\n    std::cout << \"stamp = \" << deltatime << std::endl;\n}\n\n// This function should be embedded in a try/catch block in case of\n// an exception.  It offers the user a choice of MIDI ports to open.\n// It returns false if there are no ports available.\nbool chooseMidiPort( RtMidiIn *rtmidi );\n\nint main( int argc, char *argv[] )\n{\n  RtMidiIn *midiin = 0;\n\n  // Minimal command-line check.\n  if ( argc > 2 ) usage();\n\n  try {\n\n    // RtMidiIn constructor\n    midiin = new RtMidiIn();\n\n    // Call function to select port.\n    if ( chooseMidiPort( midiin ) == false ) goto cleanup;\n\n    // Set our callback function.  This should be done immediately after\n    // opening the port to avoid having incoming messages written to the\n    // queue instead of sent to the callback function.\n    midiin->setCallback( &mycallback );\n\n    // Don't ignore sysex, timing, or active sensing messages.\n    midiin->ignoreTypes( false, false, false );\n\n    std::cout << \"\\nReading MIDI input ... press <enter> to quit.\\n\";\n    char input;\n    std::cin.get(input);\n\n  } catch ( RtError &error ) {\n    error.printMessage();\n  }\n\n cleanup:\n\n  delete midiin;\n\n  return 0;\n}\n\nbool chooseMidiPort( RtMidiIn *rtmidi )\n{\n  std::cout << \"\\nWould you like to open a virtual input port? [y/N] \";\n\n  std::string keyHit;\n  std::getline( std::cin, keyHit );\n  if ( keyHit == \"y\" ) {\n    rtmidi->openVirtualPort();\n    return true;\n  }\n\n  std::string portName;\n  unsigned int i = 0, nPorts = rtmidi->getPortCount();\n  if ( nPorts == 0 ) {\n    std::cout << \"No input ports available!\" << std::endl;\n    return false;\n  }\n\n  if ( nPorts == 1 ) {\n    std::cout << \"\\nOpening \" << rtmidi->getPortName() << std::endl;\n  }\n  else {\n    for ( i=0; i<nPorts; i++ ) {\n      portName = rtmidi->getPortName(i);\n      std::cout << \"  Input port #\" << i << \": \" << portName << '\\n';\n    }\n\n    do {\n      std::cout << \"\\nChoose a port number: \";\n      std::cin >> i;\n    } while ( i >= nPorts );\n  }\n\n  std::getline( std::cin, keyHit );  // used to clear out stdin\n  rtmidi->openPort( i );\n\n  return true;\n}\n"
  },
  {
    "path": "rtmidi/tests/cmidiin.dsp",
    "content": "# Microsoft Developer Studio Project File - Name=\"cmidiin\" - Package Owner=<4>\r\n# Microsoft Developer Studio Generated Build File, Format Version 6.00\r\n# ** DO NOT EDIT **\r\n\r\n# TARGTYPE \"Win32 (x86) Console Application\" 0x0103\r\n\r\nCFG=cmidiin - Win32 Debug\r\n!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r\n!MESSAGE use the Export Makefile command and run\r\n!MESSAGE \r\n!MESSAGE NMAKE /f \"cmidiin.mak\".\r\n!MESSAGE \r\n!MESSAGE You can specify a configuration when running NMAKE\r\n!MESSAGE by defining the macro CFG on the command line. For example:\r\n!MESSAGE \r\n!MESSAGE NMAKE /f \"cmidiin.mak\" CFG=\"cmidiin - Win32 Debug\"\r\n!MESSAGE \r\n!MESSAGE Possible choices for configuration are:\r\n!MESSAGE \r\n!MESSAGE \"cmidiin - Win32 Release\" (based on \"Win32 (x86) Console Application\")\r\n!MESSAGE \"cmidiin - Win32 Debug\" (based on \"Win32 (x86) Console Application\")\r\n!MESSAGE \r\n\r\n# Begin Project\r\n# PROP AllowPerConfigDependencies 0\r\n# PROP Scc_ProjName \"\"\r\n# PROP Scc_LocalPath \"\"\r\nCPP=cl.exe\r\nRSC=rc.exe\r\n\r\n!IF  \"$(CFG)\" == \"cmidiin - Win32 Release\"\r\n\r\n# PROP BASE Use_MFC 0\r\n# PROP BASE Use_Debug_Libraries 0\r\n# PROP BASE Output_Dir \"cmidiin___Win32_Release\"\r\n# PROP BASE Intermediate_Dir \"cmidiin___Win32_Release\"\r\n# PROP BASE Target_Dir \"\"\r\n# PROP Use_MFC 0\r\n# PROP Use_Debug_Libraries 0\r\n# PROP Output_Dir \"\"\r\n# PROP Intermediate_Dir \"Release\"\r\n# PROP Ignore_Export_Lib 0\r\n# PROP Target_Dir \"\"\r\n# ADD BASE CPP /nologo /W3 /GX /O2 /D \"WIN32\" /D \"NDEBUG\" /D \"_CONSOLE\" /D \"_MBCS\" /YX /FD /c\r\n# ADD CPP /nologo /W3 /GX /O2 /I \"../\" /D \"NDEBUG\" /D \"WIN32\" /D \"_CONSOLE\" /D \"_MBCS\" /D \"__WINDOWS_MM__\" /YX /FD /c\r\n# ADD BASE RSC /l 0x409 /d \"NDEBUG\"\r\n# ADD RSC /l 0x409 /d \"NDEBUG\"\r\nBSC32=bscmake.exe\r\n# ADD BASE BSC32 /nologo\r\n# ADD BSC32 /nologo\r\nLINK32=link.exe\r\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\r\n# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /subsystem:console /machine:I386\r\n\r\n!ELSEIF  \"$(CFG)\" == \"cmidiin - Win32 Debug\"\r\n\r\n# PROP BASE Use_MFC 0\r\n# PROP BASE Use_Debug_Libraries 1\r\n# PROP BASE Output_Dir \"cmidiin___Win32_Debug\"\r\n# PROP BASE Intermediate_Dir \"cmidiin___Win32_Debug\"\r\n# PROP BASE Target_Dir \"\"\r\n# PROP Use_MFC 0\r\n# PROP Use_Debug_Libraries 1\r\n# PROP Output_Dir \"\"\r\n# PROP Intermediate_Dir \"Debug\"\r\n# PROP Ignore_Export_Lib 0\r\n# PROP Target_Dir \"\"\r\n# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D \"WIN32\" /D \"_DEBUG\" /D \"_CONSOLE\" /D \"_MBCS\" /YX /FD /GZ /c\r\n# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I \"../\" /D \"_DEBUG\" /D \"WIN32\" /D \"_CONSOLE\" /D \"_MBCS\" /D \"__WINDOWS_MM__\" /YX /FD /GZ /c\r\n# ADD BASE RSC /l 0x409 /d \"_DEBUG\"\r\n# ADD RSC /l 0x409 /d \"_DEBUG\"\r\nBSC32=bscmake.exe\r\n# ADD BASE BSC32 /nologo\r\n# ADD BSC32 /nologo\r\nLINK32=link.exe\r\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r\n# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r\n\r\n!ENDIF \r\n\r\n# Begin Target\r\n\r\n# Name \"cmidiin - Win32 Release\"\r\n# Name \"cmidiin - Win32 Debug\"\r\n# Begin Group \"Source Files\"\r\n\r\n# PROP Default_Filter \"cpp;c;cxx;rc;def;r;odl;idl;hpj;bat\"\r\n# Begin Source File\r\n\r\nSOURCE=.\\cmidiin.cpp\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\RtMidi.cpp\r\n# End Source File\r\n# End Group\r\n# Begin Group \"Header Files\"\r\n\r\n# PROP Default_Filter \"h;hpp;hxx;hm;inl\"\r\n# Begin Source File\r\n\r\nSOURCE=..\\RtError.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\RtMidi.h\r\n# End Source File\r\n# End Group\r\n# Begin Group \"Resource Files\"\r\n\r\n# PROP Default_Filter \"ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe\"\r\n# End Group\r\n# End Target\r\n# End Project\r\n"
  },
  {
    "path": "rtmidi/tests/midiout.cpp",
    "content": "//*****************************************//\n//  midiout.cpp\n//  by Gary Scavone, 2003-2004.\n//\n//  Simple program to test MIDI output.\n//\n//*****************************************//\n\n#include <iostream>\n#include <cstdlib>\n#include \"RtMidi.h\"\n\n// Platform-dependent sleep routines.\n#if defined(__WINDOWS_MM__)\n  #include <windows.h>\n  #define SLEEP( milliseconds ) Sleep( (DWORD) milliseconds ) \n#else // Unix variants\n  #include <unistd.h>\n  #define SLEEP( milliseconds ) usleep( (unsigned long) (milliseconds * 1000.0) )\n#endif\n\n// This function should be embedded in a try/catch block in case of\n// an exception.  It offers the user a choice of MIDI ports to open.\n// It returns false if there are no ports available.\nbool chooseMidiPort( RtMidiOut *rtmidi );\n\nint main( int argc, char *argv[] )\n{\n  RtMidiOut *midiout = 0;\n  std::vector<unsigned char> message;\n\n  // RtMidiOut constructor\n  try {\n    midiout = new RtMidiOut();\n  }\n  catch ( RtError &error ) {\n    error.printMessage();\n    exit( EXIT_FAILURE );\n  }\n\n  // Call function to select port.\n  try {\n    if ( chooseMidiPort( midiout ) == false ) goto cleanup;\n  }\n  catch ( RtError &error ) {\n    error.printMessage();\n    goto cleanup;\n  }\n\n  // Send out a series of MIDI messages.\n\n  // Program change: 192, 5\n  message.push_back( 192 );\n  message.push_back( 5 );\n  midiout->sendMessage( &message );\n\n  SLEEP( 500 );\n\n  message[0] = 0xF1;\n  message[1] = 60;\n  midiout->sendMessage( &message );\n\n  // Control Change: 176, 7, 100 (volume)\n  message[0] = 176;\n  message[1] = 7;\n  message.push_back( 100 );\n  midiout->sendMessage( &message );\n\n  // Note On: 144, 64, 90\n  message[0] = 144;\n  message[1] = 64;\n  message[2] = 90;\n  midiout->sendMessage( &message );\n\n  SLEEP( 500 );\n\n  // Note Off: 128, 64, 40\n  message[0] = 128;\n  message[1] = 64;\n  message[2] = 40;\n  midiout->sendMessage( &message );\n\n  SLEEP( 500 );\n\n  // Control Change: 176, 7, 40\n  message[0] = 176;\n  message[1] = 7;\n  message[2] = 40;\n  midiout->sendMessage( &message );\n\n  SLEEP( 500 );\n\n  // Sysex: 240, 67, 4, 3, 2, 247\n  message[0] = 240;\n  message[1] = 67;\n  message[2] = 4;\n  message.push_back( 3 );\n  message.push_back( 2 );\n  message.push_back( 247 );\n  midiout->sendMessage( &message );\n\n  // Clean up\n cleanup:\n  delete midiout;\n\n  return 0;\n}\n\nbool chooseMidiPort( RtMidiOut *rtmidi )\n{\n  std::cout << \"\\nWould you like to open a virtual output port? [y/N] \";\n\n  std::string keyHit;\n  std::getline( std::cin, keyHit );\n  if ( keyHit == \"y\" ) {\n    rtmidi->openVirtualPort();\n    return true;\n  }\n\n  std::string portName;\n  unsigned int i = 0, nPorts = rtmidi->getPortCount();\n  if ( nPorts == 0 ) {\n    std::cout << \"No output ports available!\" << std::endl;\n    return false;\n  }\n\n  if ( nPorts == 1 ) {\n    std::cout << \"\\nOpening \" << rtmidi->getPortName() << std::endl;\n  }\n  else {\n    for ( i=0; i<nPorts; i++ ) {\n      portName = rtmidi->getPortName(i);\n      std::cout << \"  Output port #\" << i << \": \" << portName << '\\n';\n    }\n\n    do {\n      std::cout << \"\\nChoose a port number: \";\n      std::cin >> i;\n    } while ( i >= nPorts );\n  }\n\n  std::cout << \"\\n\";\n  rtmidi->openPort( i );\n\n  return true;\n}\n"
  },
  {
    "path": "rtmidi/tests/midiout.dsp",
    "content": "# Microsoft Developer Studio Project File - Name=\"midiout\" - Package Owner=<4>\r\n# Microsoft Developer Studio Generated Build File, Format Version 6.00\r\n# ** DO NOT EDIT **\r\n\r\n# TARGTYPE \"Win32 (x86) Console Application\" 0x0103\r\n\r\nCFG=midiout - Win32 Debug\r\n!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r\n!MESSAGE use the Export Makefile command and run\r\n!MESSAGE \r\n!MESSAGE NMAKE /f \"midiout.mak\".\r\n!MESSAGE \r\n!MESSAGE You can specify a configuration when running NMAKE\r\n!MESSAGE by defining the macro CFG on the command line. For example:\r\n!MESSAGE \r\n!MESSAGE NMAKE /f \"midiout.mak\" CFG=\"midiout - Win32 Debug\"\r\n!MESSAGE \r\n!MESSAGE Possible choices for configuration are:\r\n!MESSAGE \r\n!MESSAGE \"midiout - Win32 Release\" (based on \"Win32 (x86) Console Application\")\r\n!MESSAGE \"midiout - Win32 Debug\" (based on \"Win32 (x86) Console Application\")\r\n!MESSAGE \r\n\r\n# Begin Project\r\n# PROP AllowPerConfigDependencies 0\r\n# PROP Scc_ProjName \"\"\r\n# PROP Scc_LocalPath \"\"\r\nCPP=cl.exe\r\nRSC=rc.exe\r\n\r\n!IF  \"$(CFG)\" == \"midiout - Win32 Release\"\r\n\r\n# PROP BASE Use_MFC 0\r\n# PROP BASE Use_Debug_Libraries 0\r\n# PROP BASE Output_Dir \"midiout___Win32_Release\"\r\n# PROP BASE Intermediate_Dir \"midiout___Win32_Release\"\r\n# PROP BASE Target_Dir \"\"\r\n# PROP Use_MFC 0\r\n# PROP Use_Debug_Libraries 0\r\n# PROP Output_Dir \"\"\r\n# PROP Intermediate_Dir \"Release\"\r\n# PROP Ignore_Export_Lib 0\r\n# PROP Target_Dir \"\"\r\n# ADD BASE CPP /nologo /W3 /GX /O2 /D \"WIN32\" /D \"NDEBUG\" /D \"_CONSOLE\" /D \"_MBCS\" /YX /FD /c\r\n# ADD CPP /nologo /W3 /GX /O2 /I \"../\" /D \"NDEBUG\" /D \"WIN32\" /D \"_CONSOLE\" /D \"_MBCS\" /D \"__WINDOWS_MM__\" /YX /FD /c\r\n# ADD BASE RSC /l 0x409 /d \"NDEBUG\"\r\n# ADD RSC /l 0x409 /d \"NDEBUG\"\r\nBSC32=bscmake.exe\r\n# ADD BASE BSC32 /nologo\r\n# ADD BSC32 /nologo\r\nLINK32=link.exe\r\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\r\n# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /subsystem:console /machine:I386\r\n\r\n!ELSEIF  \"$(CFG)\" == \"midiout - Win32 Debug\"\r\n\r\n# PROP BASE Use_MFC 0\r\n# PROP BASE Use_Debug_Libraries 1\r\n# PROP BASE Output_Dir \"midiout___Win32_Debug\"\r\n# PROP BASE Intermediate_Dir \"midiout___Win32_Debug\"\r\n# PROP BASE Target_Dir \"\"\r\n# PROP Use_MFC 0\r\n# PROP Use_Debug_Libraries 1\r\n# PROP Output_Dir \"\"\r\n# PROP Intermediate_Dir \"Debug\"\r\n# PROP Ignore_Export_Lib 0\r\n# PROP Target_Dir \"\"\r\n# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D \"WIN32\" /D \"_DEBUG\" /D \"_CONSOLE\" /D \"_MBCS\" /YX /FD /GZ /c\r\n# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I \"../\" /D \"_DEBUG\" /D \"WIN32\" /D \"_CONSOLE\" /D \"_MBCS\" /D \"__WINDOWS_MM__\" /YX /FD /GZ /c\r\n# ADD BASE RSC /l 0x409 /d \"_DEBUG\"\r\n# ADD RSC /l 0x409 /d \"_DEBUG\"\r\nBSC32=bscmake.exe\r\n# ADD BASE BSC32 /nologo\r\n# ADD BSC32 /nologo\r\nLINK32=link.exe\r\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r\n# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r\n\r\n!ENDIF \r\n\r\n# Begin Target\r\n\r\n# Name \"midiout - Win32 Release\"\r\n# Name \"midiout - Win32 Debug\"\r\n# Begin Group \"Source Files\"\r\n\r\n# PROP Default_Filter \"cpp;c;cxx;rc;def;r;odl;idl;hpj;bat\"\r\n# Begin Source File\r\n\r\nSOURCE=.\\midiout.cpp\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\RtMidi.cpp\r\n# End Source File\r\n# End Group\r\n# Begin Group \"Header Files\"\r\n\r\n# PROP Default_Filter \"h;hpp;hxx;hm;inl\"\r\n# Begin Source File\r\n\r\nSOURCE=..\\RtError.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\RtMidi.h\r\n# End Source File\r\n# End Group\r\n# Begin Group \"Resource Files\"\r\n\r\n# PROP Default_Filter \"ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe\"\r\n# End Group\r\n# End Target\r\n# End Project\r\n"
  },
  {
    "path": "rtmidi/tests/midiprobe.cpp",
    "content": "// midiprobe.cpp\n//\n// Simple program to check MIDI inputs and outputs.\n//\n// by Gary Scavone, 2003-2012.\n\n#include <iostream>\n#include <cstdlib>\n#include <map>\n#include \"RtMidi.h\"\n\nint main()\n{\n  // Create an api map.\n  std::map<int, std::string> apiMap;\n  apiMap[RtMidi::MACOSX_CORE] = \"OS-X CoreMidi\";\n  apiMap[RtMidi::WINDOWS_MM] = \"Windows MultiMedia\";\n  apiMap[RtMidi::WINDOWS_KS] = \"Windows Kernel Straming\";\n  apiMap[RtMidi::UNIX_JACK] = \"Jack Client\";\n  apiMap[RtMidi::LINUX_ALSA] = \"Linux ALSA\";\n  apiMap[RtMidi::RTMIDI_DUMMY] = \"RtMidi Dummy\";\n\n  std::vector< RtMidi::Api > apis;\n  RtMidi :: getCompiledApi( apis );\n\n  std::cout << \"\\nCompiled APIs:\\n\";\n  for ( unsigned int i=0; i<apis.size(); i++ )\n    std::cout << \"  \" << apiMap[ apis[i] ] << std::endl;\n\n  RtMidiIn  *midiin = 0;\n  RtMidiOut *midiout = 0;\n\n  try {\n\n    // RtMidiIn constructor ... exception possible\n    midiin = new RtMidiIn();\n\n    std::cout << \"\\nCurrent input API: \" << apiMap[ midiin->getCurrentApi() ] << std::endl;\n\n    // Check inputs.\n    unsigned int nPorts = midiin->getPortCount();\n    std::cout << \"\\nThere are \" << nPorts << \" MIDI input sources available.\\n\";\n\n    for ( unsigned i=0; i<nPorts; i++ ) {\n      std::string portName = midiin->getPortName(i);\n      std::cout << \"  Input Port #\" << i+1 << \": \" << portName << '\\n';\n    }\n\n    // RtMidiOut constructor ... exception possible\n    midiout = new RtMidiOut();\n\n    std::cout << \"\\nCurrent output API: \" << apiMap[ midiout->getCurrentApi() ] << std::endl;\n\n    // Check outputs.\n    nPorts = midiout->getPortCount();\n    std::cout << \"\\nThere are \" << nPorts << \" MIDI output ports available.\\n\";\n\n    for ( unsigned i=0; i<nPorts; i++ ) {\n      std::string portName = midiout->getPortName(i);\n      std::cout << \"  Output Port #\" << i+1 << \": \" << portName << std::endl;\n    }\n    std::cout << std::endl;\n\n  } catch ( RtError &error ) {\n    error.printMessage();\n  }\n\n  delete midiin;\n  delete midiout;\n\n  return 0;\n}\n"
  },
  {
    "path": "rtmidi/tests/midiprobe.dsp",
    "content": "# Microsoft Developer Studio Project File - Name=\"midiprobe\" - Package Owner=<4>\r\n# Microsoft Developer Studio Generated Build File, Format Version 6.00\r\n# ** DO NOT EDIT **\r\n\r\n# TARGTYPE \"Win32 (x86) Console Application\" 0x0103\r\n\r\nCFG=midiprobe - Win32 Debug\r\n!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r\n!MESSAGE use the Export Makefile command and run\r\n!MESSAGE \r\n!MESSAGE NMAKE /f \"midiprobe.mak\".\r\n!MESSAGE \r\n!MESSAGE You can specify a configuration when running NMAKE\r\n!MESSAGE by defining the macro CFG on the command line. For example:\r\n!MESSAGE \r\n!MESSAGE NMAKE /f \"midiprobe.mak\" CFG=\"midiprobe - Win32 Debug\"\r\n!MESSAGE \r\n!MESSAGE Possible choices for configuration are:\r\n!MESSAGE \r\n!MESSAGE \"midiprobe - Win32 Release\" (based on \"Win32 (x86) Console Application\")\r\n!MESSAGE \"midiprobe - Win32 Debug\" (based on \"Win32 (x86) Console Application\")\r\n!MESSAGE \r\n\r\n# Begin Project\r\n# PROP AllowPerConfigDependencies 0\r\n# PROP Scc_ProjName \"\"\r\n# PROP Scc_LocalPath \"\"\r\nCPP=cl.exe\r\nRSC=rc.exe\r\n\r\n!IF  \"$(CFG)\" == \"midiprobe - Win32 Release\"\r\n\r\n# PROP BASE Use_MFC 0\r\n# PROP BASE Use_Debug_Libraries 0\r\n# PROP BASE Output_Dir \"midiprobe___Win32_Release\"\r\n# PROP BASE Intermediate_Dir \"midiprobe___Win32_Release\"\r\n# PROP BASE Target_Dir \"\"\r\n# PROP Use_MFC 0\r\n# PROP Use_Debug_Libraries 0\r\n# PROP Output_Dir \"\"\r\n# PROP Intermediate_Dir \"Release\"\r\n# PROP Ignore_Export_Lib 0\r\n# PROP Target_Dir \"\"\r\n# ADD BASE CPP /nologo /W3 /GX /O2 /D \"WIN32\" /D \"NDEBUG\" /D \"_CONSOLE\" /D \"_MBCS\" /YX /FD /c\r\n# ADD CPP /nologo /W3 /GX /O2 /I \"../\" /D \"NDEBUG\" /D \"WIN32\" /D \"_CONSOLE\" /D \"_MBCS\" /D \"__WINDOWS_MM__\" /YX /FD /c\r\n# ADD BASE RSC /l 0x409 /d \"NDEBUG\"\r\n# ADD RSC /l 0x409 /d \"NDEBUG\"\r\nBSC32=bscmake.exe\r\n# ADD BASE BSC32 /nologo\r\n# ADD BSC32 /nologo\r\nLINK32=link.exe\r\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib  kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\r\n# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /subsystem:console /machine:I386\r\n\r\n!ELSEIF  \"$(CFG)\" == \"midiprobe - Win32 Debug\"\r\n\r\n# PROP BASE Use_MFC 0\r\n# PROP BASE Use_Debug_Libraries 1\r\n# PROP BASE Output_Dir \"midiprobe___Win32_Debug\"\r\n# PROP BASE Intermediate_Dir \"midiprobe___Win32_Debug\"\r\n# PROP BASE Target_Dir \"\"\r\n# PROP Use_MFC 0\r\n# PROP Use_Debug_Libraries 1\r\n# PROP Output_Dir \"\"\r\n# PROP Intermediate_Dir \"Debug\"\r\n# PROP Ignore_Export_Lib 0\r\n# PROP Target_Dir \"\"\r\n# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D \"WIN32\" /D \"_DEBUG\" /D \"_CONSOLE\" /D \"_MBCS\" /YX /FD /GZ  /c\r\n# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I \"../\" /D \"_DEBUG\" /D \"WIN32\" /D \"_CONSOLE\" /D \"_MBCS\" /D \"__WINDOWS_MM__\" /YX /FD /GZ  /c\r\n# ADD BASE RSC /l 0x409 /d \"_DEBUG\"\r\n# ADD RSC /l 0x409 /d \"_DEBUG\"\r\nBSC32=bscmake.exe\r\n# ADD BASE BSC32 /nologo\r\n# ADD BSC32 /nologo\r\nLINK32=link.exe\r\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib  kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r\n# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r\n\r\n!ENDIF \r\n\r\n# Begin Target\r\n\r\n# Name \"midiprobe - Win32 Release\"\r\n# Name \"midiprobe - Win32 Debug\"\r\n# Begin Group \"Source Files\"\r\n\r\n# PROP Default_Filter \"cpp;c;cxx;rc;def;r;odl;idl;hpj;bat\"\r\n# Begin Source File\r\n\r\nSOURCE=.\\midiprobe.cpp\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\RtMidi.cpp\r\n# End Source File\r\n# End Group\r\n# Begin Group \"Header Files\"\r\n\r\n# PROP Default_Filter \"h;hpp;hxx;hm;inl\"\r\n# Begin Source File\r\n\r\nSOURCE=..\\RtError.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\RtMidi.h\r\n# End Source File\r\n# End Group\r\n# Begin Group \"Resource Files\"\r\n\r\n# PROP Default_Filter \"ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe\"\r\n# End Group\r\n# End Target\r\n# End Project\r\n"
  },
  {
    "path": "rtmidi/tests/qmidiin.cpp",
    "content": "//*****************************************//\n//  qmidiin.cpp\n//  by Gary Scavone, 2003-2004.\n//\n//  Simple program to test MIDI input and\n//  retrieval from the queue.\n//\n//*****************************************//\n\n#include <iostream>\n#include <cstdlib>\n#include <signal.h>\n#include \"RtMidi.h\"\n\n// Platform-dependent sleep routines.\n#if defined(__WINDOWS_MM__)\n  #include <windows.h>\n  #define SLEEP( milliseconds ) Sleep( (DWORD) milliseconds ) \n#else // Unix variants\n  #include <unistd.h>\n  #define SLEEP( milliseconds ) usleep( (unsigned long) (milliseconds * 1000.0) )\n#endif\n\nbool done;\nstatic void finish( int ignore ){ done = true; }\n\nvoid usage( void ) {\n  // Error function in case of incorrect command-line\n  // argument specifications.\n  std::cout << \"\\nusage: qmidiin <port>\\n\";\n  std::cout << \"    where port = the device to use (default = 0).\\n\\n\";\n  exit( 0 );\n}\n\nint main( int argc, char *argv[] )\n{\n  RtMidiIn *midiin = 0;\n  std::vector<unsigned char> message;\n  int nBytes, i;\n  double stamp;\n\n  // Minimal command-line check.\n  if ( argc > 2 ) usage();\n\n  // RtMidiIn constructor\n  try {\n    midiin = new RtMidiIn();\n  }\n  catch ( RtError &error ) {\n    error.printMessage();\n    exit( EXIT_FAILURE );\n  }\n\n  // Check available ports vs. specified.\n  unsigned int port = 0;\n  unsigned int nPorts = midiin->getPortCount();\n  if ( argc == 2 ) port = (unsigned int) atoi( argv[1] );\n  if ( port >= nPorts ) {\n    delete midiin;\n    std::cout << \"Invalid port specifier!\\n\";\n    usage();\n  }\n\n  try {\n    midiin->openPort( port );\n  }\n  catch ( RtError &error ) {\n    error.printMessage();\n    goto cleanup;\n  }\n\n  // Don't ignore sysex, timing, or active sensing messages.\n  midiin->ignoreTypes( false, false, false );\n\n  // Install an interrupt handler function.\n  done = false;\n  (void) signal(SIGINT, finish);\n\n  // Periodically check input queue.\n  std::cout << \"Reading MIDI from port ... quit with Ctrl-C.\\n\";\n  while ( !done ) {\n    stamp = midiin->getMessage( &message );\n    nBytes = message.size();\n    for ( i=0; i<nBytes; i++ )\n      std::cout << \"Byte \" << i << \" = \" << (int)message[i] << \", \";\n    if ( nBytes > 0 )\n      std::cout << \"stamp = \" << stamp << std::endl;\n\n    // Sleep for 10 milliseconds.\n    SLEEP( 10 );\n  }\n\n  // Clean up\n cleanup:\n  delete midiin;\n\n  return 0;\n}\n"
  },
  {
    "path": "rtmidi/tests/qmidiin.dsp",
    "content": "# Microsoft Developer Studio Project File - Name=\"qmidiin\" - Package Owner=<4>\r\n# Microsoft Developer Studio Generated Build File, Format Version 6.00\r\n# ** DO NOT EDIT **\r\n\r\n# TARGTYPE \"Win32 (x86) Console Application\" 0x0103\r\n\r\nCFG=qmidiin - Win32 Debug\r\n!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r\n!MESSAGE use the Export Makefile command and run\r\n!MESSAGE \r\n!MESSAGE NMAKE /f \"qmidiin.mak\".\r\n!MESSAGE \r\n!MESSAGE You can specify a configuration when running NMAKE\r\n!MESSAGE by defining the macro CFG on the command line. For example:\r\n!MESSAGE \r\n!MESSAGE NMAKE /f \"qmidiin.mak\" CFG=\"qmidiin - Win32 Debug\"\r\n!MESSAGE \r\n!MESSAGE Possible choices for configuration are:\r\n!MESSAGE \r\n!MESSAGE \"qmidiin - Win32 Release\" (based on \"Win32 (x86) Console Application\")\r\n!MESSAGE \"qmidiin - Win32 Debug\" (based on \"Win32 (x86) Console Application\")\r\n!MESSAGE \r\n\r\n# Begin Project\r\n# PROP AllowPerConfigDependencies 0\r\n# PROP Scc_ProjName \"\"\r\n# PROP Scc_LocalPath \"\"\r\nCPP=cl.exe\r\nRSC=rc.exe\r\n\r\n!IF  \"$(CFG)\" == \"qmidiin - Win32 Release\"\r\n\r\n# PROP BASE Use_MFC 0\r\n# PROP BASE Use_Debug_Libraries 0\r\n# PROP BASE Output_Dir \"qmidiin___Win32_Release\"\r\n# PROP BASE Intermediate_Dir \"qmidiin___Win32_Release\"\r\n# PROP BASE Target_Dir \"\"\r\n# PROP Use_MFC 0\r\n# PROP Use_Debug_Libraries 0\r\n# PROP Output_Dir \"\"\r\n# PROP Intermediate_Dir \"Release\"\r\n# PROP Ignore_Export_Lib 0\r\n# PROP Target_Dir \"\"\r\n# ADD BASE CPP /nologo /W3 /GX /O2 /D \"WIN32\" /D \"NDEBUG\" /D \"_CONSOLE\" /D \"_MBCS\" /YX /FD /c\r\n# ADD CPP /nologo /W3 /GX /O2 /I \"../\" /D \"NDEBUG\" /D \"WIN32\" /D \"_CONSOLE\" /D \"_MBCS\" /D \"__WINDOWS_MM__\" /YX /FD /c\r\n# ADD BASE RSC /l 0x409 /d \"NDEBUG\"\r\n# ADD RSC /l 0x409 /d \"NDEBUG\"\r\nBSC32=bscmake.exe\r\n# ADD BASE BSC32 /nologo\r\n# ADD BSC32 /nologo\r\nLINK32=link.exe\r\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\r\n# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /subsystem:console /machine:I386\r\n\r\n!ELSEIF  \"$(CFG)\" == \"qmidiin - Win32 Debug\"\r\n\r\n# PROP BASE Use_MFC 0\r\n# PROP BASE Use_Debug_Libraries 1\r\n# PROP BASE Output_Dir \"qmidiin___Win32_Debug\"\r\n# PROP BASE Intermediate_Dir \"qmidiin___Win32_Debug\"\r\n# PROP BASE Target_Dir \"\"\r\n# PROP Use_MFC 0\r\n# PROP Use_Debug_Libraries 1\r\n# PROP Output_Dir \"\"\r\n# PROP Intermediate_Dir \"Debug\"\r\n# PROP Ignore_Export_Lib 0\r\n# PROP Target_Dir \"\"\r\n# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D \"WIN32\" /D \"_DEBUG\" /D \"_CONSOLE\" /D \"_MBCS\" /YX /FD /GZ /c\r\n# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I \"../\" /D \"_DEBUG\" /D \"WIN32\" /D \"_CONSOLE\" /D \"_MBCS\" /D \"__WINDOWS_MM__\" /YX /FD /GZ /c\r\n# ADD BASE RSC /l 0x409 /d \"_DEBUG\"\r\n# ADD RSC /l 0x409 /d \"_DEBUG\"\r\nBSC32=bscmake.exe\r\n# ADD BASE BSC32 /nologo\r\n# ADD BSC32 /nologo\r\nLINK32=link.exe\r\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r\n# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r\n\r\n!ENDIF \r\n\r\n# Begin Target\r\n\r\n# Name \"qmidiin - Win32 Release\"\r\n# Name \"qmidiin - Win32 Debug\"\r\n# Begin Group \"Source Files\"\r\n\r\n# PROP Default_Filter \"cpp;c;cxx;rc;def;r;odl;idl;hpj;bat\"\r\n# Begin Source File\r\n\r\nSOURCE=.\\qmidiin.cpp\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\RtMidi.cpp\r\n# End Source File\r\n# End Group\r\n# Begin Group \"Header Files\"\r\n\r\n# PROP Default_Filter \"h;hpp;hxx;hm;inl\"\r\n# Begin Source File\r\n\r\nSOURCE=..\\RtError.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\RtMidi.h\r\n# End Source File\r\n# End Group\r\n# Begin Group \"Resource Files\"\r\n\r\n# PROP Default_Filter \"ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe\"\r\n# End Group\r\n# End Target\r\n# End Project\r\n"
  },
  {
    "path": "rtmidi/tests/sysextest.cpp",
    "content": "//*****************************************//\n//  sysextest.cpp\n//  by Gary Scavone, 2003-2005.\n//\n//  Simple program to test MIDI sysex sending and receiving.\n//\n//*****************************************//\n\n#include <iostream>\n#include <cstdlib>\n#include <typeinfo>\n#include \"RtMidi.h\"\n\nvoid usage( void ) {\n  std::cout << \"\\nuseage: sysextest N\\n\";\n  std::cout << \"    where N = length of sysex message to send / receive.\\n\\n\";\n  exit( 0 );\n}\n\n// Platform-dependent sleep routines.\n#if defined(__WINDOWS_MM__)\n  #include <windows.h>\n  #define SLEEP( milliseconds ) Sleep( (DWORD) milliseconds ) \n#else // Unix variants\n  #include <unistd.h>\n  #define SLEEP( milliseconds ) usleep( (unsigned long) (milliseconds * 1000.0) )\n#endif\n\n// This function should be embedded in a try/catch block in case of\n// an exception.  It offers the user a choice of MIDI ports to open.\n// It returns false if there are no ports available.\nbool chooseMidiPort( RtMidi *rtmidi );\n\nvoid mycallback( double deltatime, std::vector< unsigned char > *message, void *userData )\n{\n  unsigned int nBytes = message->size();\n  for ( unsigned int i=0; i<nBytes; i++ )\n    std::cout << \"Byte \" << i << \" = \" << (int)message->at(i) << \", \";\n  if ( nBytes > 0 )\n    std::cout << \"stamp = \" << deltatime << std::endl;\n}\n\nint main( int argc, char *argv[] )\n{\n  RtMidiOut *midiout = 0;\n  RtMidiIn *midiin = 0;\n  std::vector<unsigned char> message;\n  unsigned int i, nBytes;\n\n  // Minimal command-line check.\n  if ( argc != 2 ) usage();\n  nBytes = (unsigned int) atoi( argv[1] );\n\n  // RtMidiOut and RtMidiIn constructors\n  try {\n    midiout = new RtMidiOut();\n    midiin = new RtMidiIn();\n  }\n  catch ( RtError &error ) {\n    error.printMessage();\n    goto cleanup;\n  }\n\n  // Don't ignore sysex, timing, or active sensing messages.\n  midiin->ignoreTypes( false, true, true );\n\n  // Call function to select ports\n  try {\n    if ( chooseMidiPort( midiin ) == false ) goto cleanup;\n    if ( chooseMidiPort( midiout ) == false ) goto cleanup;\n  }\n  catch ( RtError &error ) {\n    error.printMessage();\n    goto cleanup;\n  }\n\n  midiin->setCallback( &mycallback );\n\n  message.push_back( 0xF6 );\n  midiout->sendMessage( &message );\n  SLEEP( 500 ); // pause a little\n\n  // Create a long sysex messages of numbered bytes and send it out.\n  for ( int n=0; n<2; n++ ) {\n  message.clear();\n  message.push_back( 240 );\n  for ( i=0; i<nBytes; i++ )\n    message.push_back( i % 128 );\n  message.push_back( 247 );\n  midiout->sendMessage( &message );\n\n  SLEEP( 500 ); // pause a little\n\n}\n\n  // Clean up\n cleanup:\n  delete midiout;\n  delete midiin;\n\n  return 0;\n}\n\nbool chooseMidiPort( RtMidi *rtmidi )\n{\n  bool isInput = false;\n  if ( typeid( *rtmidi ) == typeid( RtMidiIn ) )\n    isInput = true;\n\n  if ( isInput )\n    std::cout << \"\\nWould you like to open a virtual input port? [y/N] \";\n  else\n    std::cout << \"\\nWould you like to open a virtual output port? [y/N] \";\n\n  std::string keyHit;\n  std::getline( std::cin, keyHit );\n  if ( keyHit == \"y\" ) {\n    rtmidi->openVirtualPort();\n    return true;\n  }\n\n  std::string portName;\n  unsigned int i = 0, nPorts = rtmidi->getPortCount();\n  if ( nPorts == 0 ) {\n    if ( isInput )\n      std::cout << \"No input ports available!\" << std::endl;\n    else\n      std::cout << \"No output ports available!\" << std::endl;\n    return false;\n  }\n\n  if ( nPorts == 1 ) {\n    std::cout << \"\\nOpening \" << rtmidi->getPortName() << std::endl;\n  }\n  else {\n    for ( i=0; i<nPorts; i++ ) {\n      portName = rtmidi->getPortName(i);\n      if ( isInput )\n        std::cout << \"  Input port #\" << i << \": \" << portName << '\\n';\n      else\n        std::cout << \"  Output port #\" << i << \": \" << portName << '\\n';\n    }\n\n    do {\n      std::cout << \"\\nChoose a port number: \";\n      std::cin >> i;\n    } while ( i >= nPorts );\n  }\n\n  std::cout << std::endl;\n  rtmidi->openPort( i );\n\n  return true;\n}\n"
  },
  {
    "path": "rtmidi/tests/sysextest.dsp",
    "content": "# Microsoft Developer Studio Project File - Name=\"sysextest\" - Package Owner=<4>\r\n# Microsoft Developer Studio Generated Build File, Format Version 6.00\r\n# ** DO NOT EDIT **\r\n\r\n# TARGTYPE \"Win32 (x86) Console Application\" 0x0103\r\n\r\nCFG=sysextest - Win32 Debug\r\n!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r\n!MESSAGE use the Export Makefile command and run\r\n!MESSAGE \r\n!MESSAGE NMAKE /f \"sysextest.mak\".\r\n!MESSAGE \r\n!MESSAGE You can specify a configuration when running NMAKE\r\n!MESSAGE by defining the macro CFG on the command line. For example:\r\n!MESSAGE \r\n!MESSAGE NMAKE /f \"sysextest.mak\" CFG=\"sysextest - Win32 Debug\"\r\n!MESSAGE \r\n!MESSAGE Possible choices for configuration are:\r\n!MESSAGE \r\n!MESSAGE \"sysextest - Win32 Release\" (based on \"Win32 (x86) Console Application\")\r\n!MESSAGE \"sysextest - Win32 Debug\" (based on \"Win32 (x86) Console Application\")\r\n!MESSAGE \r\n\r\n# Begin Project\r\n# PROP AllowPerConfigDependencies 0\r\n# PROP Scc_ProjName \"\"\r\n# PROP Scc_LocalPath \"\"\r\nCPP=cl.exe\r\nRSC=rc.exe\r\n\r\n!IF  \"$(CFG)\" == \"sysextest - Win32 Release\"\r\n\r\n# PROP BASE Use_MFC 0\r\n# PROP BASE Use_Debug_Libraries 0\r\n# PROP BASE Output_Dir \"sysextest___Win32_Release\"\r\n# PROP BASE Intermediate_Dir \"sysextest___Win32_Release\"\r\n# PROP BASE Target_Dir \"\"\r\n# PROP Use_MFC 0\r\n# PROP Use_Debug_Libraries 0\r\n# PROP Output_Dir \"\"\r\n# PROP Intermediate_Dir \"Release\"\r\n# PROP Ignore_Export_Lib 0\r\n# PROP Target_Dir \"\"\r\n# ADD BASE CPP /nologo /W3 /GX /O2 /D \"WIN32\" /D \"NDEBUG\" /D \"_CONSOLE\" /D \"_MBCS\" /YX /FD /c\r\n# ADD CPP /nologo /W3 /GR /GX /O2 /I \"../\" /D \"NDEBUG\" /D \"WIN32\" /D \"_CONSOLE\" /D \"_MBCS\" /D \"__WINDOWS_MM__\" /YX /FD /c\r\n# ADD BASE RSC /l 0x409 /d \"NDEBUG\"\r\n# ADD RSC /l 0x409 /d \"NDEBUG\"\r\nBSC32=bscmake.exe\r\n# ADD BASE BSC32 /nologo\r\n# ADD BSC32 /nologo\r\nLINK32=link.exe\r\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\r\n# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /subsystem:console /machine:I386\r\n\r\n!ELSEIF  \"$(CFG)\" == \"sysextest - Win32 Debug\"\r\n\r\n# PROP BASE Use_MFC 0\r\n# PROP BASE Use_Debug_Libraries 1\r\n# PROP BASE Output_Dir \"sysextest___Win32_Debug\"\r\n# PROP BASE Intermediate_Dir \"sysextest___Win32_Debug\"\r\n# PROP BASE Target_Dir \"\"\r\n# PROP Use_MFC 0\r\n# PROP Use_Debug_Libraries 1\r\n# PROP Output_Dir \"\"\r\n# PROP Intermediate_Dir \"Debug\"\r\n# PROP Ignore_Export_Lib 0\r\n# PROP Target_Dir \"\"\r\n# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D \"WIN32\" /D \"_DEBUG\" /D \"_CONSOLE\" /D \"_MBCS\" /YX /FD /GZ /c\r\n# ADD CPP /nologo /W3 /Gm /GR /GX /ZI /Od /I \"../\" /D \"_DEBUG\" /D \"WIN32\" /D \"_CONSOLE\" /D \"_MBCS\" /D \"__WINDOWS_MM__\" /YX /FD /GZ /c\r\n# ADD BASE RSC /l 0x409 /d \"_DEBUG\"\r\n# ADD RSC /l 0x409 /d \"_DEBUG\"\r\nBSC32=bscmake.exe\r\n# ADD BASE BSC32 /nologo\r\n# ADD BSC32 /nologo\r\nLINK32=link.exe\r\n# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r\n# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r\n\r\n!ENDIF \r\n\r\n# Begin Target\r\n\r\n# Name \"sysextest - Win32 Release\"\r\n# Name \"sysextest - Win32 Debug\"\r\n# Begin Group \"Source Files\"\r\n\r\n# PROP Default_Filter \"cpp;c;cxx;rc;def;r;odl;idl;hpj;bat\"\r\n# Begin Source File\r\n\r\nSOURCE=..\\RtMidi.cpp\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=.\\sysextest.cpp\r\n# End Source File\r\n# End Group\r\n# Begin Group \"Header Files\"\r\n\r\n# PROP Default_Filter \"h;hpp;hxx;hm;inl\"\r\n# Begin Source File\r\n\r\nSOURCE=..\\RtError.h\r\n# End Source File\r\n# Begin Source File\r\n\r\nSOURCE=..\\RtMidi.h\r\n# End Source File\r\n# End Group\r\n# Begin Group \"Resource Files\"\r\n\r\n# PROP Default_Filter \"ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe\"\r\n# End Group\r\n# End Target\r\n# End Project\r\n"
  },
  {
    "path": "src/Makefile.am",
    "content": "bin_PROGRAMS = cursynth\npatchesdir = $(pkgdatadir)/patches\n\ncursynth_SOURCES = main.cpp \\\n                   cursynth.cpp \\\n                   cursynth_engine.cpp \\\n                   cursynth_gui.cpp \\\n                   cursynth_strings.cpp \\\n                   cursynth.h \\\n                   cursynth_common.h \\\n                   cursynth_engine.h \\\n                   cursynth_gui.h \\\n                   cursynth_strings.h\n\ncursynth_CPPFLAGS = -I. \\\n                    -I.. \\\n                    -I$(top_srcdir)/cJSON \\\n                    -I$(top_srcdir)/rtaudio \\\n                    -I$(top_srcdir)/rtmidi \\\n                    -I$(top_srcdir)/mopo/src \\\n                    -I$(top_srcdir)/mopo/src \\\n\t\t\t\t\t\t\t\t\t\t-I/usr/local/opt/gettext/include \\\n                    -DPATCHES_DIRECTORY=\\\"$(patchesdir)\\\"\n\ncursynth_LDADD = ../cJSON/libcJSON.a \\\n                 ../rtaudio/librtaudio.a \\\n                 ../rtmidi/librtmidi.a \\\n                 ../mopo/src/libmopo.a\n"
  },
  {
    "path": "src/cursynth.cpp",
    "content": "/* Copyright 2013-2015 Matt Tytel\n *\n * cursynth is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * cursynth is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with cursynth.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"cursynth.h\"\n\n#include \"cJSON.h\"\n\n#include <cstdio>\n#include <cstdlib>\n#include <dirent.h>\n#include <fstream>\n#include <iostream>\n#include <ncurses.h>\n#include <sstream>\n#include <string>\n#include <sys/stat.h>\n\n#define KEYBOARD \"awsedftgyhujkolp;'\"\n#define SLIDER \"`1234567890\"\n#define EXTENSION \".mite\"\n#define CONFIG_DIR \".cursynth/\"\n#define USER_PATCHES_DIR \"patches/\"\n#define CONFIG_FILE \".cursynth_conf\"\n#define NUM_CHANNELS 2\n#define MOD_WHEEL_ID 1\n#define PITCH_BEND_PORT 224\n#define SUSTAIN_PORT 176\n#define SUSTAIN_ID 64\n\nnamespace {\n\n  // Receive MIDI data and send it to the synth.\n  void midiCallback(double delta_time, std::vector<unsigned char>* message,\n                    void* user_data) {\n    UNUSED(delta_time);\n    mopo::Cursynth* cursynth = static_cast<mopo::Cursynth*>(user_data);\n    cursynth->processMidi(message);\n  }\n\n  // Receive audio buffers and send them to the synth.\n  int audioCallback(void *out_buffer, void *in_buffer,\n                    unsigned int n_frames, double stream_time,\n                    RtAudioStreamStatus status, void *user_data) {\n    UNUSED(in_buffer);\n    UNUSED(stream_time);\n    if (status)\n      std::cout << \"Stream underflow detected!\" << std::endl;\n\n    mopo::Cursynth* cursynth = static_cast<mopo::Cursynth*>(user_data);\n    cursynth->processAudio((mopo::mopo_float*)out_buffer, n_frames);\n    return 0;\n  }\n\n  // Return the directory containing the configuration file and patches.\n  std::string getConfigPath() {\n    std::stringstream config_path;\n    config_path << getenv(\"HOME\") << \"/\" << CONFIG_DIR;\n    return config_path.str();\n  }\n\n  // Return the location of the configuration file.\n  std::string getConfigFile() {\n    std::stringstream config_path;\n    config_path << getConfigPath() << CONFIG_FILE;\n    return config_path.str();\n  }\n\n  // Return the location of the user patches.\n  std::string getUserPatchesPath() {\n    std::stringstream patches_path;\n    patches_path << getConfigPath() << USER_PATCHES_DIR;\n    return patches_path.str();\n  }\n\n  // Check if the directory _path_ exists, if not, create it.\n  void confirmPathExists(std::string path) {\n    if (opendir(path.c_str()) == NULL)\n      mkdir(path.c_str(), 0755);\n  }\n\n  // Returns all files in directory _dir_ with extenstion _ext_.\n  std::vector<std::string> getAllFiles(std::string dir, std::string ext) {\n    std::vector<std::string> file_names;\n    DIR *directory = NULL;\n    struct dirent *ent = NULL;\n\n    if ((directory = opendir(dir.c_str())) != NULL) {\n      while ((ent = readdir(directory)) != NULL) {\n        std::string name = ent->d_name;\n        if (name.find(ext) != std::string::npos)\n          file_names.push_back(name);\n      }\n      closedir(directory);\n    }\n\n    return file_names;\n  }\n} // namespace\n\nnamespace mopo {\n  Cursynth::Cursynth() : state_(STANDARD), patch_load_index_(0) {\n    pthread_mutex_init(&mutex_, 0);\n  }\n\n  void Cursynth::start(unsigned sample_rate, unsigned buffer_size) {\n    // Setup all callbacks.\n    setupAudio(sample_rate, buffer_size);\n    setupMidi();\n    setupGui();\n    loadConfiguration();\n\n    // Wait for computer keyboard input.\n    while(textInput(getch()))\n      ;\n\n    stop();\n  }\n\n  void Cursynth::loadConfiguration() {\n    // Try to open the configuration file.\n    std::ifstream config_file;\n    config_file.open(getConfigFile().c_str());\n    if (!config_file.is_open())\n      return;\n\n    // Read file contents into buffer.\n    config_file.seekg(0, std::ios::end);\n    int length = config_file.tellg();\n    config_file.seekg(0, std::ios::beg);\n    char file_contents[length];\n    config_file.read(file_contents, length);\n\n    // Parse the JSON configuration file.\n    cJSON* root = cJSON_Parse(file_contents);\n\n    // For all controls, try to load the MIDI learn assignment.\n    std::string current = gui_.getCurrentControl();\n    std::string name = current;\n    do {\n      cJSON* value = cJSON_GetObjectItem(root, name.c_str());\n      if (value)\n        midi_learn_[value->valueint] = name;\n\n      name = gui_.getNextControl();\n    } while(name != current);\n\n    // Delete the parsing data.\n    cJSON_Delete(root);\n  }\n\n  void Cursynth::saveConfiguration() {\n    confirmPathExists(getConfigPath());\n\n    // Store all the MIDI learn data into JSON.\n    cJSON* root = cJSON_CreateObject();\n    std::map<int, std::string>::iterator iter = midi_learn_.begin();\n    for (; iter != midi_learn_.end(); ++iter) {\n      cJSON* midi = cJSON_CreateNumber(iter->first);\n      cJSON_AddItemToObject(root, iter->second.c_str(), midi);\n    }\n\n    // Write the configuration JSON to the configuration file.\n    char* json = cJSON_Print(root);\n    std::ofstream save_file;\n    save_file.open(getConfigFile().c_str());\n    MOPO_ASSERT(save_file.is_open());\n    save_file << json;\n    save_file.close();\n\n    free(json);\n    cJSON_Delete(root);\n  }\n\n  bool Cursynth::textInput(int key) {\n    if (state_ == PATCH_LOADING) {\n      int num_patches = patches_.size();\n      switch(key) {\n        case '\\n':\n          // Finish loading patches.\n          state_ = STANDARD;\n          gui_.clearPatches();\n          return true;\n        case KEY_UP:\n          // Go to previous patch.\n          patch_load_index_ = CLAMP(patch_load_index_ - 1, 0, num_patches - 1);\n          gui_.drawPatchLoading(patches_, patch_load_index_);\n          loadFromFile(patches_[patch_load_index_]);\n          return true;\n        case KEY_DOWN:\n          // Go to next patch.\n          patch_load_index_ = CLAMP(patch_load_index_ + 1, 0, num_patches - 1);\n          gui_.drawPatchLoading(patches_, patch_load_index_);\n          loadFromFile(patches_[patch_load_index_]);\n          return true;\n      }\n    }\n\n    std::string current_control = gui_.getCurrentControl();\n    Control* control = controls_.at(current_control);\n    bool should_redraw_control = false;\n    lock();\n    switch(key) {\n      case 'H':\n      case KEY_F(1):\n        startHelp();\n        break;\n      case 'S':\n        startSave();\n        break;\n      case 'L':\n        startLoad();\n        break;\n      case 'M':\n      case 'm':\n        if (state_ != MIDI_LEARN)\n          state_ = MIDI_LEARN;\n        else\n          state_ = STANDARD;\n        should_redraw_control = true;\n        break;\n      case 'C':\n      case 'c':\n        eraseMidiLearn(control);\n        state_ = STANDARD;\n        should_redraw_control = true;\n        break;\n      case KEY_UP:\n        current_control = gui_.getPrevControl();\n        state_ = STANDARD;\n        gui_.drawControl(control, false);\n        should_redraw_control = true;\n        break;\n      case KEY_DOWN:\n        current_control = gui_.getNextControl();\n        state_ = STANDARD;\n        gui_.drawControl(control, false);\n        should_redraw_control = true;\n        break;\n      case KEY_RIGHT:\n        control->increment();\n        should_redraw_control = true;\n        break;\n      case KEY_LEFT:\n        control->decrement();\n        should_redraw_control = true;\n        break;\n      case KEY_RESIZE:\n        refreshGui();\n        break;\n      default:\n        // Check if they pressed the slider keys and change the current value.\n        size_t slider_size = strlen(SLIDER) - 1;\n        for (size_t i = 0; i <= slider_size; ++i) {\n          if (SLIDER[i] == key) {\n            control->setPercentage((1.0 * i) / slider_size);\n            should_redraw_control = true;\n            break;\n          }\n        }\n\n        // Check if they pressed note keys and play the corresponding note.\n        for (size_t i = 0; i < strlen(KEYBOARD); ++i) {\n          if (KEYBOARD[i] == key) {\n            synth_.noteOn(48 + i);\n            break;\n          }\n        }\n    }\n\n    if (should_redraw_control) {\n      control = controls_.at(current_control);\n      gui_.drawControl(control, true);\n      gui_.drawControlStatus(control, state_ == MIDI_LEARN);\n    }\n\n    unlock();\n    return true;\n  }\n\n  unsigned int Cursynth::chooseSampleRate(const RtAudio::DeviceInfo& device,\n                                          unsigned preferred_sample_rate) {\n    for (int i = 0; i < device.sampleRates.size(); ++i) {\n      if (device.sampleRates[i] == preferred_sample_rate)\n        return preferred_sample_rate;\n    }\n\n    return device.sampleRates[0];\n  }\n\n  void Cursynth::setupAudio(unsigned sample_rate, unsigned buffer_size) {\n    // Make sure we have a device to make sound with.\n    if (dac_.getDeviceCount() < 1) {\n      std::cout << \"No audio devices found.\\n\";\n      exit(0);\n    }\n\n    // Setup audio preferences.\n    RtAudio::StreamParameters parameters;\n    parameters.deviceId = dac_.getDefaultOutputDevice();\n    parameters.nChannels = NUM_CHANNELS;\n    parameters.firstChannel = 0;\n    RtAudio::DeviceInfo device_info = dac_.getDeviceInfo(parameters.deviceId);\n\n    unsigned actual_sample_rate = chooseSampleRate(device_info, sample_rate);\n    synth_.setSampleRate(actual_sample_rate);\n    buffer_size = CLAMP(buffer_size, 0, mopo::MAX_BUFFER_SIZE);\n\n    // Start the audio callbacks.\n    try {\n      dac_.openStream(&parameters, NULL, RTAUDIO_FLOAT64, actual_sample_rate,\n                      &buffer_size, &audioCallback, (void*)this);\n      dac_.startStream();\n    }\n    catch (RtError& error) {\n      error.printMessage();\n      exit(0);\n    }\n\n    synth_.setBufferSize(buffer_size);\n  }\n\n  void Cursynth::setupGui() {\n    gui_.start();\n\n    // Add the controls to the GUI for viewing.\n    controls_ = synth_.getControls();\n    gui_.addControls(controls_);\n\n    // Make sure we are drawing he current control.\n    Control* control = controls_.at(gui_.getCurrentControl());\n    gui_.drawControl(control, true);\n    gui_.drawControlStatus(control, false);\n  }\n\n  void Cursynth::refreshGui() {\n    gui_.redrawBase();\n    controls_ = synth_.getControls();\n    gui_.addControls(controls_);\n\n    // Make sure we are drawing the current control.\n    Control* control = controls_.at(gui_.getCurrentControl());\n    gui_.drawControl(control, true);\n    gui_.drawControlStatus(control, false);\n  }\n\n  void Cursynth::processAudio(mopo_float *out_buffer, unsigned int n_frames) {\n    // Run the synth.\n    lock();\n    synth_.process();\n    unlock();\n\n    // Copy the synth output to the output buffer.\n    const mopo_float* buffer = synth_.output()->buffer;\n    for (size_t i = 0; i < n_frames; ++i) {\n      for (int c = 0; c < NUM_CHANNELS; ++c)\n        out_buffer[NUM_CHANNELS * i + c] = buffer[i];\n    }\n  }\n\n  void Cursynth::eraseMidiLearn(Control* control) {\n    if (control->midi_learn()) {\n      midi_learn_.erase(control->midi_learn());\n      control->midi_learn(0);\n    }\n  }\n\n  void Cursynth::setupMidi() {\n    RtMidiIn* midi_in = new RtMidiIn();\n    if (midi_in->getPortCount() <= 0) {\n      std::cout << \"No midi devices found.\\n\";\n    }\n\n    // Setup MIDI callbacks for every MIDI device.\n    // TODO: Have a menu for only enabling some MIDI devices.\n    for (unsigned int i = 0; i < midi_in->getPortCount(); ++i) {\n      RtMidiIn* device = new RtMidiIn();\n      device->openPort(i);\n      device->setCallback(&midiCallback, (void*)this);\n      midi_ins_.push_back(device);\n    }\n\n    delete midi_in;\n  }\n\n  void Cursynth::processMidi(std::vector<unsigned char>* message) {\n    if (message->size() < 3)\n      return;\n\n    lock();\n    int midi_port = message->at(0);\n    int midi_id = message->at(1);\n    int midi_val = message->at(2);\n    std::string selected_control_name = gui_.getCurrentControl();\n    Control* selected_control = controls_.at(selected_control_name);\n    if (midi_port >= 144 && midi_port < 160) {\n      // A MIDI keyboard key was pressed. Play a note.\n      int midi_note = midi_id;\n      int midi_velocity = midi_val;\n\n      if (midi_velocity)\n        synth_.noteOn(midi_note, (1.0 * midi_velocity) / MIDI_SIZE);\n      else\n        synth_.noteOff(midi_note);\n    }\n    else if (midi_port >= 128 && midi_port < 144) {\n      // A MIDI keyboard key was released. Release that note.\n      int midi_note = midi_id;\n      synth_.noteOff(midi_note);\n    }\n    else if (midi_port == PITCH_BEND_PORT)\n      synth_.setPitchWheel((2.0 * midi_val) / (MIDI_SIZE - 1) - 1);\n    else if (midi_port == SUSTAIN_PORT && midi_id == SUSTAIN_ID) {\n      if (midi_val)\n        synth_.sustainOn();\n      else\n        synth_.sustainOff();\n    }\n    else if (midi_port < 254) {\n      // Must have gotten MIDI from some knob or other control.\n      if (state_ == MIDI_LEARN && midi_port < 254) {\n        // MIDI learn is armed so map this MIDI signal to the current control.\n        eraseMidiLearn(selected_control);\n\n        midi_learn_[midi_id] = selected_control_name;\n        selected_control->midi_learn(midi_id);\n        state_ = STANDARD;\n        gui_.drawControlStatus(selected_control, false);\n        saveConfiguration();\n      }\n      else if (midi_learn_.find(midi_id) != midi_learn_.end()) {\n        // MIDI learn is enabled for this control. Change the paired control.\n        Control* midi_control = controls_.at(midi_learn_[midi_id]);\n        midi_control->setMidi(midi_val);\n        gui_.drawControl(midi_control, selected_control == midi_control);\n        gui_.drawControlStatus(midi_control, false);\n      }\n\n      if (midi_id == MOD_WHEEL_ID)\n        synth_.setModWheel(midi_val);\n    }\n    unlock();\n  }\n\n  void Cursynth::stop() {\n    pthread_mutex_destroy(&mutex_);\n    gui_.stop();\n    try {\n      dac_.stopStream();\n    }\n    catch (RtError& error) {\n      error.printMessage();\n    }\n\n    if (dac_.isStreamOpen())\n      dac_.closeStream();\n  }\n\n  void Cursynth::startHelp() {\n    gui_.drawHelp();\n    getch();\n\n    gui_.drawMain();\n    std::string current = gui_.getCurrentControl();\n    std::string name = gui_.getNextControl();\n    while (name != current) {\n      gui_.drawControl(controls_.at(name), false);\n      name = gui_.getNextControl();\n    }\n    gui_.drawControl(controls_.at(current), true);\n  }\n\n  void Cursynth::startSave() {\n    gui_.clearPatches();\n    curs_set(1);\n    std::stringstream save_stream;\n    gui_.drawPatchSaving(save_stream.str());\n    int key = 0;\n    while(1) {\n      key = getch();\n      std::string current = save_stream.str();\n      switch(key) {\n        case KEY_DC:\n        case KEY_BACKSPACE:\n        case 127:\n          // Pressed delete, so remove the last character from the file name.\n          save_stream.str(current.substr(0, current.length() - 1));\n          save_stream.seekp(save_stream.str().length());\n          gui_.drawPatchSaving(save_stream.str());\n          break;\n        case '\\n':\n          // Pressed enter, so save to the current file name.\n          // Then go back to the normal input state.\n          if (save_stream.str().length() > 0)\n            saveToFile(save_stream.str() + EXTENSION);\n          state_ = STANDARD;\n          gui_.clearPatches();\n          curs_set(0);\n          return;\n        default:\n          // If it's a printable character, append it to the file name.\n          if (isprint(key))\n            save_stream << static_cast<char>(key);\n          gui_.drawPatchSaving(save_stream.str());\n          break;\n      }\n    }\n  }\n\n  void Cursynth::startLoad() {\n    // Store all patche names from system and user patch directories.\n    patches_ = getAllFiles(PATCHES_DIRECTORY, EXTENSION);\n    std::vector<std::string> user_patches =\n        getAllFiles(getUserPatchesPath(), EXTENSION);\n    patches_.insert(patches_.end(), user_patches.begin(), user_patches.end());\n\n    if (patches_.size() == 0)\n      return;\n\n    // Start patch loading by loading last patch browsed.\n    state_ = PATCH_LOADING;\n    patch_load_index_ = std::min<int>(patch_load_index_, patches_.size() - 1);\n    loadFromFile(patches_[patch_load_index_]);\n  }\n\n  void Cursynth::saveToFile(const std::string& file_name) {\n    confirmPathExists(getConfigPath());\n    confirmPathExists(getUserPatchesPath());\n    std::ofstream save_file;\n    std::string path = getUserPatchesPath();\n    path = path + \"/\" + file_name;\n    save_file.open(path.c_str());\n    save_file << writeStateToString();\n    save_file.close();\n  }\n\n  void Cursynth::loadFromFile(const std::string& file_name) {\n    std::ifstream load_file;\n\n    // First try to load the patch from user patches.\n    std::string path = getUserPatchesPath();\n    path += \"/\";\n    path += file_name;\n    load_file.open(path.c_str());\n\n    // If we can't find the patch try default system patches.\n    if (!load_file.is_open()) {\n      path = PATCHES_DIRECTORY;\n      path += \"/\";\n      path += file_name;\n      load_file.open(path.c_str());\n    }\n\n    if (!load_file.is_open())\n      return;\n\n    // Read file into buffer and load it.\n    load_file.seekg(0, std::ios::end);\n    int length = load_file.tellg();\n    load_file.seekg(0, std::ios::beg);\n    char file_contents[length];\n    load_file.read(file_contents, length);\n    readStateFromString(file_contents);\n    load_file.close();\n\n    // Draw the patch loading happen.\n    gui_.drawPatchLoading(patches_, patch_load_index_);\n  }\n\n  std::string Cursynth::writeStateToString() {\n    // Write all controls to JSON.\n    cJSON* root = cJSON_CreateObject();\n    control_map::iterator iter = controls_.begin();\n    for (; iter != controls_.end(); ++iter) {\n      cJSON* value = cJSON_CreateNumber(iter->second->value()->value());\n      cJSON_AddItemToObject(root, iter->first.c_str(), value);\n    }\n\n    // Write the JSON to a string and free the JSON.\n    char* json = cJSON_Print(root);\n    std::string output = json;\n    free(json);\n    cJSON_Delete(root);\n\n    return output;\n  }\n\n  void Cursynth::readStateFromString(const std::string& state) {\n    // Parse state into JSON and read all controls.\n    cJSON* root = cJSON_Parse(state.c_str());\n    control_map::iterator iter = controls_.begin();\n    for (; iter != controls_.end(); ++iter) {\n      cJSON* value = cJSON_GetObjectItem(root, iter->first.c_str());\n\n      if (value) {\n        Control* control = iter->second;\n        control->set(value->valuedouble);\n        gui_.drawControl(control, false);\n      }\n    }\n\n    // Setup current control.\n    Control* current_control = controls_.at(gui_.getCurrentControl());\n    gui_.drawControl(current_control, true);\n    gui_.drawControlStatus(current_control, false);\n\n    cJSON_Delete(root);\n  }\n} // namespace mopo\n"
  },
  {
    "path": "src/cursynth.h",
    "content": "/* Copyright 2013-2015 Matt Tytel\n *\n * cursynth is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * cursynth is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with cursynth.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#pragma once\n#ifndef CURSYNTH_H\n#define CURSYNTH_H\n\n#include \"RtAudio.h\"\n#include \"RtMidi.h\"\n#include \"cursynth_gui.h\"\n#include \"cursynth_engine.h\"\n\n#include <pthread.h>\n\nnamespace mopo {\n\n  class Cursynth {\n    public:\n      // Computer keyboard reading states.\n      enum InputState {\n        STANDARD,\n        MIDI_LEARN,\n        PATCH_LOADING,\n        PATCH_SAVING,\n      };\n\n      Cursynth();\n\n      // Start/stop everything - UI, synth engine, input/output.\n      void start(unsigned sample_rate, unsigned buffer_size);\n      void stop();\n\n      // Runs the synth engine for _n_frames_ samples and copies the output\n      // to _out_buffer_.\n      void processAudio(mopo_float *out_buffer, unsigned int n_frames);\n\n      // Processes MIDI data like note and velocity, and knob data.\n      void processMidi(std::vector<unsigned char>* message);\n\n      // If we're working with the synth or UI, lock so we don't break\n      // something. Then unlock when we're done.\n      void lock() { pthread_mutex_lock(&mutex_); }\n      void unlock() { pthread_mutex_unlock(&mutex_); }\n\n    private:\n      unsigned int chooseSampleRate(const RtAudio::DeviceInfo& device,\n                                    unsigned preferred_sample_rate);\n\n      // Load and save global configuration settings (like MIDI learn).\n      void loadConfiguration();\n      void saveConfiguration();\n\n      // Writes the synth state to a string so we can save it to a patch.\n      std::string writeStateToString();\n      // Read the synth state from a string.\n      void readStateFromString(const std::string& state);\n\n      // Saves the state to a given filename.\n      void saveToFile(const std::string& file_name);\n      void loadFromFile(const std::string& file_name);\n\n      // When the user enters help state. Show controls and contact.\n      void startHelp();\n\n      // When user starts to load, launch patch browser.\n      void startLoad();\n\n      // When user starts to save, start save text field.\n      void startSave();\n\n      // Computer keyboard text input callback.\n      bool textInput(int key);\n\n      // Setup functions initialize objects and callbacks.\n      void setupAudio(unsigned sample_rate, unsigned buffer_size);\n      void setupMidi();\n      void setupControls();\n      void setupGui();\n\n      // Clear screen and redraw GUI\n      void refreshGui();\n\n      // Helper function to erase all evidence of MIDI learn for a control.\n      void eraseMidiLearn(Control* control);\n\n      // Cursynth parts.\n      CursynthEngine synth_;\n      CursynthGui gui_;\n\n      // IO.\n      RtAudio dac_;\n      std::vector<RtMidiIn*> midi_ins_;\n      std::map<int, std::string> midi_learn_;\n\n      // State.\n      InputState state_;\n      control_map controls_;\n      pthread_mutex_t mutex_;\n\n      // Loading and Saving.\n      std::vector<std::string> patches_;\n      int patch_load_index_;\n  };\n} // namespace mopo\n\n#endif // CURSYNTH_H\n"
  },
  {
    "path": "src/cursynth_common.h",
    "content": "/* Copyright 2013-2015 Matt Tytel\n *\n * cursynth is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * cursynth is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with cursynth.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#pragma once\n#ifndef CURSYNTH_COMMON_H\n#define CURSYNTH_COMMON_H\n\n#include \"config.h\"\n#include \"value.h\"\n\n#include <map>\n#include <string>\n\nnamespace mopo {\n\n  // A container for a given control its metadata such as maximum and minimum\n  // value.\n  class Control {\n    public:\n      Control(Value* value, mopo_float min, mopo_float max, int resolution) :\n          value_(value), min_(min), max_(max),\n          resolution_(resolution), midi_learn_(0) {\n        current_value_ = value->value();\n      }\n\n      Control(Value* value, std::vector<std::string> strings, int resolution) :\n          value_(value), min_(0), max_(resolution),\n          resolution_(resolution), midi_learn_(0), display_strings_(strings) {\n        current_value_ = value->value();\n      }\n\n      Control() : value_(0), min_(0), max_(0), current_value_(0),\n                  resolution_(0), midi_learn_(0) { }\n\n      void set(mopo_float val) {\n        current_value_ = CLAMP(val, min_, max_);\n        value_->set(current_value_);\n      }\n\n      mopo_float getPercentage() const {\n        return (current_value_ - min_) / (max_ - min_);\n      }\n\n      void setPercentage(mopo_float percentage) {\n        int index = resolution_ * percentage;\n        set(min_ + index * (max_ - min_) / resolution_);\n      }\n\n      void setMidi(int midi_val) {\n        setPercentage(midi_val / (MIDI_SIZE - 1.0));\n      }\n\n      void increment() {\n        set(current_value_ + (max_ - min_) / resolution_);\n      }\n\n      void decrement() {\n        set(current_value_ - (max_ - min_) / resolution_);\n      }\n\n      int midi_learn() const { return midi_learn_; }\n\n      void midi_learn(float midi) { midi_learn_ = midi; }\n\n      std::vector<std::string> display_strings() const {\n        return display_strings_;\n      }\n\n      mopo_float current_value() const { return current_value_; }\n\n      const Value* value() const { return value_; }\n\n      bool isBipolar() const { return max_ == -min_; }\n\n    private:\n      Value* value_;\n      mopo_float min_, max_, current_value_;\n      int resolution_, midi_learn_;\n      std::vector<std::string> display_strings_;\n  };\n\n  typedef std::map<std::string, Control*> control_map;\n  typedef std::map<std::string, Processor*> input_map;\n  typedef std::map<std::string, Processor::Output*> output_map;\n\n} // namespace mopo\n\n#endif // CURSYNTH_COMMON_H\n"
  },
  {
    "path": "src/cursynth_engine.cpp",
    "content": "/* Copyright 2013-2015 Matt Tytel\n *\n * cursynth is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * cursynth is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with cursynth.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"cursynth_engine.h\"\n\n#include \"delay.h\"\n#include \"envelope.h\"\n#include \"filter.h\"\n#include \"operators.h\"\n#include \"oscillator.h\"\n#include \"processor_router.h\"\n#include \"linear_slope.h\"\n#include \"smooth_value.h\"\n#include \"cursynth_strings.h\"\n#include \"trigger_operators.h\"\n#include \"value.h\"\n\n#include <sstream>\n\n#define PITCH_MOD_RANGE 12\n\nnamespace mopo {\n\n  CursynthOscillators::CursynthOscillators() : TickRouter(0, 0) {\n    oscillator1_ = new Oscillator();\n    oscillator2_ = new Oscillator();\n    frequency1_ = new Multiply();\n    frequency2_ = new Multiply();\n    freq_mod1_ = new Multiply();\n    freq_mod2_ = new Multiply();\n    normalized_fm1_ = new Add();\n    normalized_fm2_ = new Add();\n    Value* one = new Value(1);\n\n    addProcessor(normalized_fm1_);\n    addProcessor(normalized_fm2_);\n    addProcessor(frequency1_);\n    addProcessor(frequency2_);\n    addProcessor(freq_mod1_);\n    addProcessor(freq_mod2_);\n    addProcessor(oscillator1_);\n    addProcessor(oscillator2_);\n\n    registerInput(oscillator1_->input(Oscillator::kWaveform));\n    registerInput(oscillator2_->input(Oscillator::kWaveform));\n    registerInput(oscillator1_->input(Oscillator::kReset));\n    registerInput(oscillator2_->input(Oscillator::kReset));\n    registerInput(frequency1_->input(0));\n    registerInput(frequency2_->input(0));\n    registerInput(freq_mod1_->input(0));\n    registerInput(freq_mod2_->input(0));\n\n    normalized_fm1_->plug(freq_mod1_, 0);\n    normalized_fm2_->plug(freq_mod2_, 0);\n    normalized_fm1_->plug(one, 1);\n    normalized_fm2_->plug(one, 1);\n    frequency1_->plug(normalized_fm1_, 1);\n    frequency2_->plug(normalized_fm2_, 1);\n    oscillator1_->plug(frequency1_, Oscillator::kFrequency);\n    oscillator2_->plug(frequency2_, Oscillator::kFrequency);\n    freq_mod2_->plug(oscillator1_, 1);\n    freq_mod1_->plug(oscillator2_, 1);\n\n    registerOutput(oscillator1_->output());\n    registerOutput(oscillator2_->output());\n  }\n\n  void CursynthOscillators::process() {\n    int num_feedbacks = feedback_order_->size();\n    for (int i = 0; i < num_feedbacks; ++i)\n      feedback_processors_[feedback_order_->at(i)]->tickBeginRefreshOutput();\n\n    oscillator1_->preprocess();\n    oscillator2_->preprocess();\n    tick(0);\n\n    for (int i = 1; i < buffer_size_; ++i) {\n      for (int f = 0; f < num_feedbacks; ++f)\n        feedback_processors_[feedback_order_->at(f)]->tickRefreshOutput(i);\n\n      tick(i);\n\n      for (int f = 0; f < num_feedbacks; ++f)\n        feedback_processors_[feedback_order_->at(f)]->tick(i);\n    }\n  }\n\n  void CursynthVoiceHandler::createOscillators(Output* midi, Output* reset) {\n    // Pitch bend.\n    Value* pitch_bend_range = new Value(2);\n    Multiply* pitch_bend = new Multiply();\n    pitch_bend->plug(pitch_wheel_amount_, 0);\n    pitch_bend->plug(pitch_bend_range, 1);\n    Add* bent_midi = new Add();\n    bent_midi->plug(midi, 0);\n    bent_midi->plug(pitch_bend, 1);\n\n    Value* pitch_mod_range = new Value(PITCH_MOD_RANGE);\n    VariableAdd* midi_mod_sources = new VariableAdd(MOD_MATRIX_SIZE);\n    Multiply* midi_mod = new Multiply();\n    midi_mod->plug(pitch_mod_range, 0);\n    midi_mod->plug(midi_mod_sources, 1);\n    Add* final_midi = new Add();\n    final_midi->plug(bent_midi, 0);\n    final_midi->plug(midi_mod, 1);\n\n    addGlobalProcessor(pitch_bend);\n    addProcessor(bent_midi);\n    addProcessor(midi_mod_sources);\n    addProcessor(midi_mod);\n    addProcessor(final_midi);\n\n    controls_[\"pitch bend range\"] = new Control(pitch_bend_range, 0, 48, 48);\n\n    // Oscillator 1.\n    oscillators_ = new CursynthOscillators();\n    Value* oscillator1_waveform = new Value(Wave::kDownSaw);\n    MidiScale* oscillator1_frequency = new MidiScale();\n    oscillator1_frequency->plug(final_midi);\n    oscillators_->plug(oscillator1_waveform, 0);\n    oscillators_->plug(reset, 2);\n    oscillators_->plug(reset, 3);\n    oscillators_->plug(oscillator1_frequency, 4);\n\n    Value* cross_mod = new Value(0.15);\n    VariableAdd* cross_mod_mod_sources = new VariableAdd(MOD_MATRIX_SIZE);\n    Add* cross_mod_total = new Add();\n    cross_mod_total->plug(cross_mod, 0);\n    cross_mod_total->plug(cross_mod_mod_sources, 1);\n\n    oscillators_->plug(cross_mod_total, 6);\n    oscillators_->plug(cross_mod_total, 7);\n\n    addProcessor(cross_mod_mod_sources);\n    addProcessor(cross_mod_total);\n    addProcessor(oscillator1_frequency);\n    addProcessor(oscillators_);\n\n    controls_[\"cross modulation\"] = new Control(cross_mod, 0, 1, MIDI_SIZE);\n\n    std::vector<std::string> wave_strings = std::vector<std::string>(\n        CursynthStrings::wave_strings_,\n        CursynthStrings::wave_strings_ + Wave::kNumWaveforms);\n    int wave_resolution = Wave::kNumWaveforms - 1;\n    controls_[\"osc 1 waveform\"] = new Control(oscillator1_waveform,\n                                              wave_strings,\n                                              wave_resolution);\n\n    // Oscillator 2.\n    Value* oscillator2_waveform = new Value(Wave::kDownSaw);\n    Value* oscillator2_transpose = new Value(-12);\n    Value* oscillator2_tune = new Value(0.08);\n    Add* oscillator2_transposed = new Add();\n    oscillator2_transposed->plug(final_midi, 0);\n    oscillator2_transposed->plug(oscillator2_transpose, 1);\n    Add* oscillator2_midi = new Add();\n    oscillator2_midi->plug(oscillator2_transposed, 0);\n    oscillator2_midi->plug(oscillator2_tune, 1);\n\n    MidiScale* oscillator2_frequency = new MidiScale();\n    oscillator2_frequency->plug(oscillator2_midi);\n    oscillators_->plug(oscillator2_waveform, 1);\n    oscillators_->plug(oscillator2_frequency, 5);\n\n    addProcessor(oscillator2_transposed);\n    addProcessor(oscillator2_midi);\n    addProcessor(oscillator2_frequency);\n\n    controls_[\"osc 2 waveform\"] = new Control(oscillator2_waveform,\n                                              wave_strings,\n                                              wave_resolution);\n    controls_[\"osc 2 transpose\"] =\n        new Control(oscillator2_transpose, -48, 48, 96);\n    controls_[\"osc 2 tune\"] =\n        new Control(oscillator2_tune, -1, 1, MIDI_SIZE);\n\n    // Oscillator mix.\n    Value* oscillator_mix_amount = new Value(0.5);\n    VariableAdd* mix_mod_sources = new VariableAdd(MOD_MATRIX_SIZE);\n    Add* mix_total = new Add();\n    mix_total->plug(oscillator_mix_amount, 0);\n    mix_total->plug(mix_mod_sources, 1);\n\n    Clamp* clamp_mix = new Clamp(0, 1);\n    clamp_mix->plug(mix_total);\n    oscillator_mix_ = new Interpolate();\n    oscillator_mix_->plug(oscillators_->output(0), Interpolate::kFrom);\n    oscillator_mix_->plug(oscillators_->output(1), Interpolate::kTo);\n    oscillator_mix_->plug(clamp_mix, Interpolate::kFractional);\n\n    addProcessor(oscillator_mix_);\n    addProcessor(mix_mod_sources);\n    addProcessor(mix_total);\n    addProcessor(clamp_mix);\n    controls_[\"osc mix\"] =\n        new Control(oscillator_mix_amount, 0, 1, MIDI_SIZE);\n\n    // LFO 1.\n    Value* lfo1_waveform = new Value(Wave::kSin);\n    Value* lfo1_frequency = new Value(2);\n    lfo1_ = new Oscillator();\n    lfo1_->plug(reset, Oscillator::kReset);\n    lfo1_->plug(lfo1_waveform, Oscillator::kWaveform);\n    lfo1_->plug(lfo1_frequency, Oscillator::kFrequency);\n\n    int lfo_wave_resolution = wave_resolution - 1;\n    addProcessor(lfo1_);\n    controls_[\"lfo 1 waveform\"] = new Control(lfo1_waveform,\n                                              wave_strings,\n                                              lfo_wave_resolution);\n    controls_[\"lfo 1 frequency\"] =\n        new Control(lfo1_frequency, 0, 10, MIDI_SIZE);\n\n    // LFO 2.\n    Value* lfo2_waveform = new Value(Wave::kSin);\n    Value* lfo2_frequency = new Value(2);\n    lfo2_ = new Oscillator();\n    lfo2_->plug(reset, Oscillator::kReset);\n    lfo2_->plug(lfo2_waveform, Oscillator::kWaveform);\n    lfo2_->plug(lfo2_frequency, Oscillator::kFrequency);\n\n    addProcessor(lfo2_);\n    controls_[\"lfo 2 waveform\"] = new Control(lfo2_waveform,\n                                              wave_strings,\n                                              lfo_wave_resolution);\n    controls_[\"lfo 2 frequency\"] =\n        new Control(lfo2_frequency, 0, 10, MIDI_SIZE);\n\n    // Modulation sources/destinations.\n    mod_sources_[\"lfo 1\"] = lfo1_->output();\n    mod_sources_[\"lfo 2\"] = lfo2_->output();\n\n    mod_destinations_[\"cross modulation\"] = cross_mod_mod_sources;\n    mod_destinations_[\"pitch\"] = midi_mod_sources;\n    mod_destinations_[\"osc mix\"] = mix_mod_sources;\n  }\n\n  void CursynthVoiceHandler::createFilter(\n      Output* audio, Output* keytrack, Output* reset) {\n    // Filter envelope.\n    Value* filter_attack = new Value(0.0);\n    Value* filter_decay = new Value(0.3);\n    Value* filter_sustain = new Value(0.0);\n    Value* filter_release = new Value(0.3);\n\n    filter_envelope_ = new Envelope();\n    filter_envelope_->plug(filter_attack, Envelope::kAttack);\n    filter_envelope_->plug(filter_decay, Envelope::kDecay);\n    filter_envelope_->plug(filter_sustain, Envelope::kSustain);\n    filter_envelope_->plug(filter_release, Envelope::kRelease);\n    filter_envelope_->plug(reset, Envelope::kTrigger);\n\n    Value* filter_envelope_depth = new Value(12);\n    Multiply* scaled_envelope = new Multiply();\n    scaled_envelope->plug(filter_envelope_, 0);\n    scaled_envelope->plug(filter_envelope_depth, 1);\n\n    addProcessor(filter_envelope_);\n    addProcessor(scaled_envelope);\n\n    controls_[\"fil attack\"] = new Control(filter_attack, 0, 3, MIDI_SIZE);\n    controls_[\"fil decay\"] = new Control(filter_decay, 0, 3, MIDI_SIZE);\n    controls_[\"fil sustain\"] = new Control(filter_sustain, 0, 1, MIDI_SIZE);\n    controls_[\"fil release\"] = new Control(filter_release, 0, 3, MIDI_SIZE);\n    controls_[\"fil env depth\"] =\n        new Control(filter_envelope_depth, -MIDI_SIZE, MIDI_SIZE, MIDI_SIZE);\n\n    // Filter.\n    Value* filter_type = new Value(Filter::kLP12);\n    Value* keytrack_amount = new Value(0);\n    Multiply* current_keytrack = new Multiply();\n    current_keytrack->plug(keytrack, 0);\n    current_keytrack->plug(keytrack_amount, 1);\n\n    SmoothValue* base_cutoff = new SmoothValue(92);\n    Add* keytracked_cutoff = new Add();\n    keytracked_cutoff->plug(base_cutoff, 0);\n    keytracked_cutoff->plug(current_keytrack, 1);\n\n    Add* midi_cutoff = new Add();\n    midi_cutoff->plug(keytracked_cutoff, 0);\n    midi_cutoff->plug(scaled_envelope, 1);\n\n    VariableAdd* cutoff_mod_sources = new VariableAdd(MOD_MATRIX_SIZE);\n    Value* cutoff_mod_scale = new Value(MIDI_SIZE / 2);\n    Multiply* cutoff_modulation_scaled = new Multiply();\n    cutoff_modulation_scaled->plug(cutoff_mod_sources, 0);\n    cutoff_modulation_scaled->plug(cutoff_mod_scale, 1);\n    Add* midi_cutoff_modulated = new Add();\n    midi_cutoff_modulated->plug(midi_cutoff, 0);\n    midi_cutoff_modulated->plug(cutoff_modulation_scaled, 1);\n\n    MidiScale* frequency_cutoff = new MidiScale();\n    frequency_cutoff->plug(midi_cutoff_modulated);\n\n    Value* resonance = new Value(3);\n\n    VariableAdd* resonance_mod_sources = new VariableAdd(MOD_MATRIX_SIZE);\n    Value* resonance_mod_scale = new Value(8);\n    Multiply* resonance_modulation_scaled = new Multiply();\n    resonance_modulation_scaled->plug(resonance_mod_sources, 0);\n    resonance_modulation_scaled->plug(resonance_mod_scale, 1);\n    Add* resonance_modulated = new Add();\n    resonance_modulated->plug(resonance, 0);\n    resonance_modulated->plug(resonance_modulation_scaled, 1);\n    Clamp* clamp_resonance = new Clamp(0.5, 30);\n    clamp_resonance->plug(resonance_modulated);\n\n    filter_ = new Filter();\n    filter_->plug(audio, Filter::kAudio);\n    filter_->plug(filter_type, Filter::kType);\n    filter_->plug(reset, Filter::kReset);\n    filter_->plug(frequency_cutoff, Filter::kCutoff);\n    filter_->plug(clamp_resonance, Filter::kResonance);\n\n    addGlobalProcessor(base_cutoff);\n    addProcessor(current_keytrack);\n    addProcessor(keytracked_cutoff);\n    addProcessor(midi_cutoff);\n    addProcessor(cutoff_mod_sources);\n    addProcessor(cutoff_modulation_scaled);\n    addProcessor(midi_cutoff_modulated);\n    addProcessor(resonance_mod_sources);\n    addProcessor(resonance_modulation_scaled);\n    addProcessor(resonance_modulated);\n    addProcessor(clamp_resonance);\n    addProcessor(frequency_cutoff);\n    addProcessor(filter_);\n\n    std::vector<std::string> filter_strings = std::vector<std::string>(\n        CursynthStrings::filter_strings_,\n        CursynthStrings::filter_strings_ + Filter::kHP12 + 1);\n    controls_[\"filter type\"] = new Control(filter_type, filter_strings,\n                                           Filter::kHP12);\n    controls_[\"cutoff\"] =\n        new Control(base_cutoff, 28, MIDI_SIZE - 1, MIDI_SIZE);\n    controls_[\"keytrack\"] = new Control(keytrack_amount, -1, 1, MIDI_SIZE);\n    controls_[\"resonance\"] = new Control(resonance, 0.5, 15, MIDI_SIZE);\n\n    mod_sources_[\"filter env\"] = filter_envelope_->output();\n    mod_destinations_[\"cutoff\"] = cutoff_mod_sources;\n    mod_destinations_[\"resonance\"] = resonance_mod_sources;\n  }\n\n  void CursynthVoiceHandler::createModMatrix() {\n    std::vector<std::string> source_names;\n    source_names.push_back(\"\");\n    output_map::iterator s_iter = mod_sources_.begin();\n    for (; s_iter != mod_sources_.end(); ++s_iter)\n      source_names.push_back(s_iter->first);\n\n    std::vector<std::string> destination_names;\n    destination_names.push_back(\"\");\n    input_map::iterator d_iter = mod_destinations_.begin();\n    for (; d_iter != mod_destinations_.end(); ++d_iter)\n      destination_names.push_back(d_iter->first);\n\n    for (int i = 0; i < MOD_MATRIX_SIZE; ++i) {\n      mod_matrix_scales_[i] = new Value(0.01);\n      mod_matrix_[i] = new Multiply();\n      mod_matrix_[i]->plug(mod_matrix_scales_[i], 1);\n\n      addGlobalProcessor(mod_matrix_scales_[i]);\n      addProcessor(mod_matrix_[i]);\n\n      MatrixSourceValue* source_value = new MatrixSourceValue(this);\n      source_value->setSources(source_names);\n      source_value->setModulationIndex(i);\n\n      MatrixDestinationValue* destination_value =\n          new MatrixDestinationValue(this);\n      destination_value->setDestinations(destination_names);\n      destination_value->setModulationIndex(i);\n\n      std::stringstream scale_name;\n      scale_name << \"mod scale \" << i + 1;\n      controls_[scale_name.str()] =\n          new Control(mod_matrix_scales_[i], -1, 1, MIDI_SIZE);\n\n      std::stringstream source_name;\n      source_name << \"mod source \" << i + 1;\n      int source_size = source_names.size() - 1;\n      controls_[source_name.str()] =\n          new Control(source_value, source_names, source_size);\n\n      std::stringstream destination_name;\n      destination_name << \"mod destination \" << i + 1;\n      int dest_size = destination_names.size() - 1;\n      controls_[destination_name.str()] =\n          new Control(destination_value, destination_names, dest_size);\n    }\n  }\n\n  void CursynthVoiceHandler::createArticulation(\n      Output* note, Output* velocity, Output* trigger) {\n    // Legato.\n    Value* legato = new Value(0);\n    LegatoFilter* legato_filter = new LegatoFilter();\n    legato_filter->plug(legato, LegatoFilter::kLegato);\n    legato_filter->plug(trigger, LegatoFilter::kTrigger);\n\n    std::vector<std::string> legato_strings = std::vector<std::string>(\n        CursynthStrings::legato_strings_,\n        CursynthStrings::legato_strings_ + 2);\n    controls_[\"legato\"] =\n        new Control(legato, legato_strings, 1);\n    addProcessor(legato_filter);\n\n    // Amplitude envelope.\n    Value* amplitude_attack = new Value(0.01);\n    Value* amplitude_decay = new Value(0.7);\n    Value* amplitude_sustain = new SmoothValue(0.0);\n    Value* amplitude_release = new Value(0.3);\n\n    amplitude_envelope_ = new Envelope();\n    amplitude_envelope_->plug(legato_filter->output(LegatoFilter::kRetrigger),\n                              Envelope::kTrigger);\n    amplitude_envelope_->plug(amplitude_attack, Envelope::kAttack);\n    amplitude_envelope_->plug(amplitude_decay, Envelope::kDecay);\n    amplitude_envelope_->plug(amplitude_sustain, Envelope::kSustain);\n    amplitude_envelope_->plug(amplitude_release, Envelope::kRelease);\n\n    addProcessor(amplitude_envelope_);\n    addGlobalProcessor(amplitude_sustain);\n\n    controls_[\"amp attack\"] = new Control(amplitude_attack, 0, 3, MIDI_SIZE);\n    controls_[\"amp decay\"] = new Control(amplitude_decay, 0, 3, MIDI_SIZE);\n    controls_[\"amp sustain\"] = new Control(amplitude_sustain, 0, 1, MIDI_SIZE);\n    controls_[\"amp release\"] = new Control(amplitude_release, 0, 3, MIDI_SIZE);\n\n    // Voice and frequency resetting logic.\n    TriggerCombiner* frequency_trigger = new TriggerCombiner();\n    frequency_trigger->plug(legato_filter->output(LegatoFilter::kRemain), 0);\n    frequency_trigger->plug(\n        amplitude_envelope_->output(Envelope::kFinished), 1);\n\n    TriggerWait* note_wait = new TriggerWait();\n    Value* current_note = new Value();\n    note_wait->plug(note, TriggerWait::kWait);\n    note_wait->plug(frequency_trigger, TriggerWait::kTrigger);\n    current_note->plug(note_wait);\n\n    Value* max_midi_invert = new Value(1.0 / (MIDI_SIZE - 1));\n    Multiply* note_percentage = new Multiply();\n    note_percentage->plug(max_midi_invert, 0);\n    note_percentage->plug(current_note, 1);\n\n    addProcessor(frequency_trigger);\n    addProcessor(note_wait);\n    addProcessor(current_note);\n\n    // Key tracking.\n    Value* center_adjust = new Value(-MIDI_SIZE / 2);\n    note_from_center_ = new Add();\n    note_from_center_->plug(center_adjust, 0);\n    note_from_center_->plug(current_note, 1);\n\n    addProcessor(note_from_center_);\n    addProcessor(note_percentage);\n    addGlobalProcessor(center_adjust);\n\n    // Velocity tracking.\n    TriggerWait* velocity_wait = new TriggerWait();\n    Value* current_velocity = new Value();\n    velocity_wait->plug(velocity, TriggerWait::kWait);\n    velocity_wait->plug(frequency_trigger, TriggerWait::kTrigger);\n    current_velocity->plug(velocity_wait);\n\n    addProcessor(velocity_wait);\n    addProcessor(current_velocity);\n\n    Value* velocity_track_amount = new Value(0.3);\n    Value* one = new Value(1.0);\n\n    Interpolate* velocity_track_mult = new Interpolate();\n    velocity_track_mult->plug(one, Interpolate::kFrom);\n    velocity_track_mult->plug(current_velocity, Interpolate::kTo);\n    velocity_track_mult->plug(velocity_track_amount, Interpolate::kFractional);\n\n    addProcessor(velocity_track_mult);\n    controls_[\"velocity track\"] =\n        new Control(velocity_track_amount, 0.0, 1.0, MIDI_SIZE);\n\n    // Current amplitude using envelope and velocity.\n    amplitude_ = new Multiply();\n    amplitude_->plug(amplitude_envelope_->output(Envelope::kValue), 0);\n    amplitude_->plug(velocity_track_mult, 1);\n\n    addProcessor(amplitude_);\n\n    // Portamento.\n    Value* portamento = new Value(0.01);\n    Value* portamento_type = new Value(0);\n    PortamentoFilter* portamento_filter = new PortamentoFilter();\n    portamento_filter->plug(portamento_type, PortamentoFilter::kPortamento);\n    portamento_filter->plug(frequency_trigger, PortamentoFilter::kTrigger);\n    addProcessor(portamento_filter);\n\n    current_frequency_ = new LinearSlope();\n    current_frequency_->plug(current_note, LinearSlope::kTarget);\n    current_frequency_->plug(portamento, LinearSlope::kRunSeconds);\n    current_frequency_->plug(portamento_filter, LinearSlope::kTriggerJump);\n\n    addProcessor(current_frequency_);\n    controls_[\"portamento\"] = new Control(portamento, 0.0, 0.2, MIDI_SIZE);\n    std::vector<std::string> portamento_strings = std::vector<std::string>(\n        CursynthStrings::portamento_strings_,\n        CursynthStrings::portamento_strings_ +\n        PortamentoFilter::kNumPortamentoStates);\n    int port_type_resolution = PortamentoFilter::kNumPortamentoStates - 1;\n    controls_[\"portamento type\"] =\n        new Control(portamento_type, portamento_strings, port_type_resolution);\n\n    mod_sources_[\"amp env\"] = amplitude_envelope_->output();\n    mod_sources_[\"note\"] = note_percentage->output();\n    mod_sources_[\"velocity\"] = current_velocity->output();\n  }\n\n  CursynthVoiceHandler::CursynthVoiceHandler() {\n    // Create modulation and pitch wheels.\n    mod_wheel_amount_ = new SmoothValue(0);\n    pitch_wheel_amount_ = new SmoothValue(0);\n\n    mod_sources_[\"pitch wheel\"] = pitch_wheel_amount_->output();\n    mod_sources_[\"mod wheel\"] = mod_wheel_amount_->output();\n\n    // Create all synthesizer voice components.\n    createArticulation(note(), velocity(), voice_event());\n    createOscillators(current_frequency_->output(),\n                      amplitude_envelope_->output(Envelope::kFinished));\n    createFilter(oscillator_mix_->output(), note_from_center_->output(),\n                 amplitude_envelope_->output(Envelope::kFinished));\n    createModMatrix();\n\n    output_ = new Multiply();\n    output_->plug(filter_->output(), 0);\n    output_->plug(amplitude_, 1);\n\n    addProcessor(output_);\n    addGlobalProcessor(pitch_wheel_amount_);\n    addGlobalProcessor(mod_wheel_amount_);\n\n    setVoiceOutput(output_);\n    setVoiceKiller(amplitude_envelope_->output(Envelope::kValue));\n  }\n\n  CursynthEngine::CursynthEngine() {\n    // Voice Handler.\n    Value* polyphony = new Value(1);\n    voice_handler_ = new CursynthVoiceHandler();\n    voice_handler_->setPolyphony(64);\n    voice_handler_->plug(polyphony, VoiceHandler::kPolyphony);\n\n    addProcessor(voice_handler_);\n    controls_[\"polyphony\"] = new Control(polyphony, 1, 32, 31);\n\n    // Delay effect.\n    SmoothValue* delay_time = new SmoothValue(0.06);\n    SmoothValue* delay_feedback = new SmoothValue(-0.3);\n    SmoothValue* delay_wet = new SmoothValue(0.3);\n\n    Delay* delay = new Delay();\n    delay->plug(voice_handler_, Delay::kAudio);\n    delay->plug(delay_time, Delay::kDelayTime);\n    delay->plug(delay_feedback, Delay::kFeedback);\n    delay->plug(delay_wet, Delay::kWet);\n\n    addProcessor(delay_time);\n    addProcessor(delay_feedback);\n    addProcessor(delay_wet);\n    addProcessor(delay);\n\n    controls_[\"delay time\"] = new Control(delay_time, 0.01, 1, MIDI_SIZE);\n    controls_[\"delay feedback\"] =\n        new Control(delay_feedback, -1, 1, MIDI_SIZE);\n    controls_[\"delay dry/wet\"] = new Control(delay_wet, 0, 1, MIDI_SIZE);\n\n    // Volume.\n    SmoothValue* volume = new SmoothValue(0.6);\n    Multiply* scaled_audio = new Multiply();\n    scaled_audio->plug(delay, 0);\n    scaled_audio->plug(volume, 1);\n    Clamp* clamp = new Clamp();\n    clamp->plug(scaled_audio);\n\n    addProcessor(clamp);\n    addProcessor(volume);\n    addProcessor(scaled_audio);\n    registerOutput(clamp->output());\n\n    controls_[\"volume\"] = new Control(volume, 0, 1, MIDI_SIZE);\n  }\n\n  control_map CursynthEngine::getControls() {\n    control_map voice_controls = voice_handler_->getControls();\n    voice_controls.insert(controls_.begin(), controls_.end());\n    return voice_controls;\n  }\n\n  void CursynthEngine::noteOn(mopo_float note, mopo_float velocity) {\n    voice_handler_->noteOn(note, velocity);\n  }\n\n  void CursynthEngine::noteOff(mopo_float note) {\n    voice_handler_->noteOff(note);\n  }\n\n  void CursynthVoiceHandler::setModWheel(mopo_float value) {\n    mod_wheel_amount_->set(value);\n  }\n\n  void CursynthVoiceHandler::setPitchWheel(mopo_float value) {\n    pitch_wheel_amount_->set(value);\n  }\n\n  void CursynthVoiceHandler::setModulationSource(int matrix_index,\n                                                 std::string source) {\n    mod_matrix_[matrix_index]->unplugIndex(0);\n    if (source.length())\n      mod_matrix_[matrix_index]->plug(mod_sources_[source], 0);\n  }\n\n  void CursynthVoiceHandler::setModulationDestination(\n      int matrix_index, std::string destination) {\n    std::string current = current_mod_destinations_[matrix_index];\n\n    // First unplug the previous destination.\n    if (current.length())\n      mod_destinations_[current]->unplug(mod_matrix_[matrix_index]);\n\n    // Then plug in to the new destination.\n    current_mod_destinations_[matrix_index] = destination;\n    if (destination.length())\n      mod_destinations_[destination]->plugNext(mod_matrix_[matrix_index]);\n  }\n} // namespace mopo\n"
  },
  {
    "path": "src/cursynth_engine.h",
    "content": "/* Copyright 2013-2015 Matt Tytel\n *\n * cursynth is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * cursynth is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with cursynth.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#pragma once\n#ifndef CURSYNTH_SYNTH_H\n#define CURSYNTH_SYNTH_H\n\n#include \"feedback.h\"\n#include \"operators.h\"\n#include \"oscillator.h\"\n#include \"cursynth_common.h\"\n#include \"tick_router.h\"\n#include \"voice_handler.h\"\n\n#include <vector>\n\n#define MOD_MATRIX_SIZE 5\n\nnamespace mopo {\n  class Add;\n  class Envelope;\n  class Filter;\n  class Interpolate;\n  class LinearSlope;\n  class Multiply;\n  class Oscillator;\n  class SmoothValue;\n\n  // The oscillators of the synthesizer. This section of the synth is processed\n  // sample by sample to allow for cross modulation.\n  class CursynthOscillators : public TickRouter {\n    public:\n      CursynthOscillators();\n      CursynthOscillators(const CursynthOscillators& original) :\n          TickRouter(original) {\n        oscillator1_ = new Oscillator(*original.oscillator1_);\n        oscillator2_ = new Oscillator(*original.oscillator2_);\n        frequency1_ = new Multiply(*original.frequency1_);\n        frequency2_ = new Multiply(*original.frequency2_);\n        freq_mod1_ = new Multiply(*original.freq_mod1_);\n        freq_mod2_ = new Multiply(*original.freq_mod2_);\n        normalized_fm1_ = new Add(*original.normalized_fm1_);\n        normalized_fm2_ = new Add(*original.normalized_fm2_);\n      }\n\n      virtual void process();\n      virtual Processor* clone() const { return new CursynthOscillators(*this); }\n\n      // Process one sample of the oscillators. Must be done in the correct\n      // order currently.\n      void tick(int i) {\n        freq_mod1_->tick(i);\n        normalized_fm1_->tick(i);\n        frequency1_->tick(i);\n        oscillator1_->tick(i);\n        freq_mod2_->tick(i);\n        normalized_fm2_->tick(i);\n        frequency2_->tick(i);\n        oscillator2_->tick(i);\n      }\n\n    protected:\n      Oscillator* oscillator1_;\n      Oscillator* oscillator2_;\n      Multiply* frequency1_;\n      Multiply* frequency2_;\n      Multiply* freq_mod1_;\n      Multiply* freq_mod2_;\n      Add* normalized_fm1_;\n      Add* normalized_fm2_;\n  };\n\n  // The voice handler duplicates processors to produce polyphony.\n  // Everything in the synthesizer we want per-voice instances of must be\n  // contained in here.\n  class CursynthVoiceHandler : public VoiceHandler {\n    public:\n      CursynthVoiceHandler();\n\n      control_map getControls() { return controls_; }\n\n      void setModWheel(mopo_float value);\n      void setPitchWheel(mopo_float value);\n\n      void setModulationSource(int index, std::string source);\n      void setModulationDestination(int index, std::string destination);\n\n    private:\n      // Create the portamento, legato, amplifier envelope and other processors\n      // that effect how voices start and turn into other notes.\n      void createArticulation(Output* note, Output* velocity, Output* trigger);\n\n      // Create the oscillators and hook up frequency controls.\n      void createOscillators(Output* frequency, Output* reset);\n\n      // Create the filter and filter envelope.\n      void createFilter(Output* audio, Output* keytrack, Output* reset);\n\n      // Create the modulation matrix.\n      void createModMatrix();\n\n      Add* note_from_center_;\n      SmoothValue* mod_wheel_amount_;\n      SmoothValue* pitch_wheel_amount_;\n      LinearSlope* current_frequency_;\n      Envelope* amplitude_envelope_;\n      Multiply* amplitude_;\n\n      CursynthOscillators* oscillators_;\n      Oscillator* lfo1_;\n      Oscillator* lfo2_;\n      Interpolate* oscillator_mix_;\n\n      Filter* filter_;\n      Envelope* filter_envelope_;\n\n      Multiply* output_;\n\n      control_map controls_;\n      output_map mod_sources_;\n      input_map mod_destinations_;\n\n      std::vector<std::string> mod_source_names_;\n      std::vector<std::string> mod_destination_names_;\n      Value* mod_matrix_scales_[MOD_MATRIX_SIZE];\n      Multiply* mod_matrix_[MOD_MATRIX_SIZE];\n      std::string current_mod_destinations_[MOD_MATRIX_SIZE];\n  };\n\n  // A modulation matrix source entry.\n  class MatrixSourceValue : public Value {\n    public:\n      MatrixSourceValue(CursynthVoiceHandler* handler) :\n          Value(0), handler_(handler), mod_index_(0) { }\n\n      virtual Processor* clone() const { return new MatrixSourceValue(*this); }\n\n      void setSources(const std::vector<std::string> &sources) {\n        sources_ = sources;\n      }\n\n      void setModulationIndex(int mod_index) {\n        mod_index_ = mod_index;\n      }\n\n      void set(mopo_float value) {\n        Value::set(static_cast<int>(value));\n        handler_->setModulationSource(mod_index_, sources_[value_]);\n      }\n\n    private:\n      CursynthVoiceHandler* handler_;\n      std::vector<std::string> sources_;\n      int mod_index_;\n  };\n\n  // A modulation matrix destination entry.\n  class MatrixDestinationValue : public Value {\n    public:\n      MatrixDestinationValue(CursynthVoiceHandler* handler) :\n          Value(0), handler_(handler), mod_index_(0) { }\n\n      virtual Processor* clone() const {\n        return new MatrixDestinationValue(*this);\n      }\n\n      void setDestinations(const std::vector<std::string> &destinations) {\n        destinations_ = destinations;\n      }\n\n      void setModulationIndex(int mod_index) {\n        mod_index_ = mod_index;\n      }\n\n      void set(mopo_float value) {\n        Value::set(static_cast<int>(value));\n        handler_->setModulationDestination(mod_index_, destinations_[value_]);\n      }\n\n    private:\n      CursynthVoiceHandler* handler_;\n      std::vector<std::string> destinations_;\n      int mod_index_;\n  };\n\n  // The overall cursynth engine. All audio processing is contained in here.\n  class CursynthEngine : public ProcessorRouter {\n    public:\n      CursynthEngine();\n\n      control_map getControls();\n\n      void setModWheel(mopo_float value) {\n        voice_handler_->setModWheel(value);\n      }\n      void setPitchWheel(mopo_float value) {\n        voice_handler_->setPitchWheel(value);\n      }\n\n      // Keyboard events.\n      void noteOn(mopo_float note, mopo_float velocity = 1.0);\n      void noteOff(mopo_float note);\n\n      // Sustain pedal events.\n      void sustainOn() { voice_handler_->sustainOn(); }\n      void sustainOff() { voice_handler_->sustainOff(); }\n\n    private:\n      CursynthVoiceHandler* voice_handler_;\n\n      control_map controls_;\n  };\n} // namespace mopo\n\n#endif // CURSYNTH_SYNTH_H\n"
  },
  {
    "path": "src/cursynth_gui.cpp",
    "content": "/* Copyright 2013-2015 Matt Tytel\n *\n * cursynth is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * cursynth is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with cursynth.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"cursynth_gui.h\"\n\n#include \"value.h\"\n\n#include <cmath>\n#include <cstdlib>\n#include <libintl.h>\n#include <locale.h>\n#include <ncurses.h>\n#include <sstream>\n#include <unistd.h>\n\n#define gettext_noop(String) String\n\n#define WIDTH 120\n#define HEIGHT 44\n\n#define LOGO_WIDTH 44\n#define LOGO_Y 0\n#define SPACE 3\n#define TOTAL_COLUMNS 3\n#define MAX_STATUS_SIZE 20\n#define MAX_SAVE_SIZE 40\n#define SAVE_COLUMN 2\n#define PATCH_BROWSER_ROWS 5\n#define PATCH_BROWSER_WIDTH 26\n\nnamespace mopo {\n\n  void CursynthGui::drawHelp() {\n    erase();\n    drawLogo();\n    move(7, 41);\n    attron(A_BOLD);\n    printw(gettext(\"INFO\"));\n    attroff(A_BOLD);\n    move(8, 43);\n    printw(gettext(\"version\"));\n    printw(\" - \");\n    printw(VERSION);\n    move(9, 43);\n    printw(gettext(\"website\"));\n    printw(\" - gnu.org/software/cursynth\");\n    move(10, 43);\n    printw(gettext(\"contact\"));\n    printw(\" - \");\n    printw(PACKAGE_BUGREPORT);\n    move(12, 41);\n    attron(A_BOLD);\n    printw(gettext(\"CONTROLS\"));\n    attroff(A_BOLD);\n    move(14, 43);\n    printw(\"awsedftgyhujkolp;' - \");\n    printw(gettext(\"a playable keyboard\"));\n    move(16, 43);\n    printw(\"`1234567890 - \");\n    printw(gettext(\"a slider for the current selected control\"));\n    move(18, 43);\n    printw(gettext(\"up/down\"));\n    printw(\" - \");\n    printw(gettext(\"previous/next control\"));\n    move(20, 43);\n    printw(gettext(\"left/right\"));\n    printw(\" - \");\n    printw(gettext(\"decrement/increment control\"));\n    move(22, 43);\n    printw(gettext(\"F1 (or [shift] + H)\"));\n    printw(\" - \");\n    printw(gettext(\"help/controls\"));\n    move(24, 43);\n    printw(gettext(\"[shift] + L\"));\n    printw(\" - \");\n    printw(gettext(\"browse/load patches\"));\n    move(26, 43);\n    printw(gettext(\"[shift] + S\"));\n    printw(\" - \");\n    printw(gettext(\"save patch\"));\n    move(28, 43);\n    printw(\"m - \");\n    printw(gettext(\"arm MIDI learn\"));\n    move(30, 43);\n    printw(\"c - \");\n    printw(gettext(\"erase MIDI learn\"));\n  }\n\n  void CursynthGui::drawMain() {\n    erase();\n    drawLogo();\n    drawModulationMatrix();\n  }\n\n  void CursynthGui::drawLogo() {\n    attron(A_BOLD);\n    attron(COLOR_PAIR(LOGO_COLOR));\n    int logo_x = (WIDTH - LOGO_WIDTH) / 2 + 1;\n\n    move(LOGO_Y, logo_x);\n    printw(\"                                    __  __\");\n    move(LOGO_Y + 1, logo_x);\n    printw(\"  _______  ______________  ______  / /_/ /_\");\n    move(LOGO_Y + 2, logo_x);\n    printw(\" / ___/ / / / ___/ ___/ / / / __ \\\\/ __/ __ \\\\\");\n    move(LOGO_Y + 3, logo_x);\n    printw(\"/ /__/ /_/ / /  /__  / /_/ / / / / /_/ / / /\");\n    move(LOGO_Y + 4, logo_x);\n    printw(\"\\\\___/\\\\____/_/  /____/\\\\__  /_/ /_/\\\\__/_/ /_/\");\n    move(LOGO_Y + 5, logo_x);\n    printw(\"                    /____/\");\n\n    attroff(A_BOLD);\n    attroff(COLOR_PAIR(LOGO_COLOR));\n\n    move(LOGO_Y + 5, logo_x + 33);\n    printw(\"Matt Tytel\");\n  }\n\n  void CursynthGui::drawModulationMatrix() {\n    move(34, 26);\n    attron(A_BOLD);\n    printw(\"----------------------------------------------------------------------\");\n    move(34, 53);\n    printw(gettext(\"Modulation Matrix\"));\n    attroff(A_BOLD);\n\n    move(35, 26);\n    printw(\"                     \");\n    move(35, 34);\n    printw(gettext(\"source\"));\n    move(35, 50);\n    printw(\"                     \");\n    move(35, 58);\n    printw(gettext(\"scale\"));\n    move(35, 74);\n    printw(\"                     \");\n    move(35, 79);\n    printw(gettext(\"destination\"));\n  }\n\n  void CursynthGui::drawMidi(std::string status) {\n    move(2, 2);\n    printw(gettext(\"MIDI Learn: \"));\n    attron(A_BOLD);\n    hline(' ', MAX_STATUS_SIZE);\n    printw(status.substr(0, MAX_STATUS_SIZE).c_str());\n    attroff(A_BOLD);\n    refresh();\n  }\n\n  void CursynthGui::drawStatus(std::string status) {\n    move(1, 2);\n    printw(gettext(\"Current Value: \"));\n    attron(A_BOLD);\n    hline(' ', MAX_STATUS_SIZE);\n    printw(gettext(status.substr(0, MAX_STATUS_SIZE).c_str()));\n    attroff(A_BOLD);\n    refresh();\n  }\n\n  void CursynthGui::clearPatches() {\n    int selection_row = (PATCH_BROWSER_ROWS - 1) / 2;\n    move(1 + selection_row, 83);\n    hline(' ', PATCH_BROWSER_WIDTH);\n    for (int i = 0; i < PATCH_BROWSER_ROWS; ++i) {\n      move(1 + i, 94);\n      hline(' ', PATCH_BROWSER_WIDTH);\n    }\n  }\n\n  void CursynthGui::drawPatchSaving(std::string patch_name) {\n    int selection_row = (PATCH_BROWSER_ROWS - 1) / 2;\n    move(1 + selection_row, 83);\n    printw(\"            \");\n    hline(' ', PATCH_BROWSER_WIDTH);\n    move(1 + selection_row, 83);\n    printw(gettext(\"Save Patch: \"));\n    printw(patch_name.c_str());\n  }\n\n  void CursynthGui::drawPatchLoading(std::vector<std::string> patches,\n                                     int selected_index) {\n    int selection_row = (PATCH_BROWSER_ROWS - 1) / 2;\n    move(1 + selection_row, 83);\n    printw(gettext(\"Load Patch:\"));\n\n    int patch_index = selected_index - selection_row;\n    int num_patches = patches.size();\n    for (int i = 0; i < PATCH_BROWSER_ROWS; ++i) {\n      if (i % 2)\n        attroff(COLOR_PAIR(PATCH_LOAD_COLOR));\n      else\n        attron(COLOR_PAIR(PATCH_LOAD_COLOR));\n\n      move(1 + i, 94);\n      hline(' ', PATCH_BROWSER_WIDTH);\n      if (patch_index == selected_index)\n        attron(A_BOLD);\n\n      if (patch_index >= 0 && patch_index < num_patches)\n        printw(patches[patch_index].c_str());\n      attroff(A_BOLD);\n      patch_index++;\n    }\n    attroff(COLOR_PAIR(PATCH_LOAD_COLOR));\n    refresh();\n  }\n\n  void CursynthGui::drawSlider(const DisplayDetails* slider,\n                               float percentage, bool active) {\n    int y = slider->y;\n    if (slider->label.size())\n      y += 1;\n\n    // Clear slider.\n    move(y, slider->x - 1);\n    attron(COLOR_PAIR(BG_COLOR));\n    hline(' ', slider->width + 2);\n\n    char slider_char = active ? '=' : ' ';\n    move(y, slider->x);\n    attron(COLOR_PAIR(SLIDER_BG_COLOR));\n    hline(slider_char, slider->width);\n\n    // If active draw a bit different.\n    if (active) {\n      move(y, slider->x - 1);\n      attron(COLOR_PAIR(LOGO_COLOR));\n      hline('|', 1);\n      move(y, slider->x + slider->width);\n      hline('|', 1);\n    }\n\n    // Find slider position.\n    int position = round(slider->width * percentage);\n    int slider_midpoint = (slider->width + 1) / 2;\n\n    attron(COLOR_PAIR(SLIDER_FG_COLOR));\n    if (slider->bipolar) {\n      if (position < slider_midpoint) {\n        move(y, slider->x + position);\n        hline(' ', slider_midpoint - position);\n      }\n      else {\n        move(y, slider->x + slider_midpoint);\n        hline(' ', position - slider_midpoint);\n      }\n    }\n    else {\n      move(y, slider->x);\n      hline(' ', position);\n    }\n\n    attroff(COLOR_PAIR(SLIDER_FG_COLOR));\n    refresh();\n  }\n\n  void CursynthGui::drawText(const DisplayDetails* details,\n                             std::string text, bool active) {\n    int y = details->y;\n    if (details->label.size())\n      y += 1;\n\n    // Clear area.\n    move(y, details->x - 1);\n    attron(COLOR_PAIR(BG_COLOR));\n    hline(' ', details->width + 2);\n    move(y, details->x);\n    attron(COLOR_PAIR(CONTROL_TEXT_COLOR));\n    hline(' ', details->width);\n\n    // If active draw a bit different.\n    if (active) {\n      move(y, details->x - 1);\n      attron(COLOR_PAIR(LOGO_COLOR));\n      hline('|', 1);\n      move(y, details->x + details->width);\n      hline('|', 1);\n      attron(A_BOLD);\n    }\n\n    // Draw text.\n    attron(COLOR_PAIR(CONTROL_TEXT_COLOR));\n    move(y, details->x);\n    printw(gettext(text.c_str()));\n    attroff(A_BOLD);\n    attroff(COLOR_PAIR(CONTROL_TEXT_COLOR));\n  }\n\n  void CursynthGui::drawControl(const Control* control, bool active) {\n    DisplayDetails* details = details_lookup_[control];\n    if (!details)\n      return;\n\n    // Draw label.\n    if (details->label.size()) {\n      if (active)\n        attron(A_BOLD);\n      move(details->y, details->x);\n      printw(gettext(details->label.c_str()));\n      attroff(A_BOLD);\n    }\n\n    // Draw status.\n    if (control->display_strings().size()) {\n      int display_index = static_cast<int>(control->current_value());\n      drawText(details, control->display_strings()[display_index], active);\n    }\n    else\n      drawSlider(details, control->getPercentage(), active);\n  }\n\n  void CursynthGui::drawControlStatus(const Control* control,\n                                      bool midi_armed) {\n    std::ostringstream midi_learn;\n    if (midi_armed)\n      midi_learn << \"ARMED\";\n    else if (control->midi_learn())\n      midi_learn << control->midi_learn();\n    else\n      midi_learn << \"-\";\n    drawMidi(midi_learn.str());\n\n    std::ostringstream status;\n    if (control->display_strings().size()) {\n      int display_index = static_cast<int>(control->current_value());\n      status << control->display_strings()[display_index];\n    }\n    else\n      status << control->current_value();\n    drawStatus(status.str());\n  }\n\n  void CursynthGui::start() {\n    initscr();\n    cbreak();\n    noecho();\n    keypad(stdscr, TRUE);\n\n    // Make sure we have color.\n    if(has_colors() == FALSE) {\n      endwin();\n      printf(\"Your terminal does not support color\\n\");\n      return;\n    }\n\n    // Setup gettext for internationalization.\n    setlocale(LC_ALL, \"\");\n    bindtextdomain(\"cursynth\", \"/usr/share/locale\");\n    textdomain(\"cursynth\");\n\n    // Prepare all the color schemes.\n    start_color();\n    init_pair(BG_COLOR, COLOR_BLACK, COLOR_BLACK);\n    init_pair(SLIDER_FG_COLOR, COLOR_WHITE, COLOR_YELLOW);\n    init_pair(SLIDER_BG_COLOR, COLOR_YELLOW, COLOR_WHITE);\n    init_pair(LOGO_COLOR, COLOR_RED, COLOR_BLACK);\n    init_pair(PATCH_LOAD_COLOR, COLOR_BLACK, COLOR_CYAN);\n    init_pair(CONTROL_TEXT_COLOR, COLOR_BLACK, COLOR_WHITE);\n\n    // Start initial drawing.\n    redrawBase();\n  }\n\n  void CursynthGui::stop() {\n    endwin();\n  }\n\n  void CursynthGui::redrawBase() {\n    erase();\n    refresh();\n    drawLogo();\n    drawModulationMatrix();\n    curs_set(0);\n  }\n\n  DisplayDetails* CursynthGui::initControl(std::string name,\n                                           const Control* control) {\n    std::map<const Control*, DisplayDetails*>::iterator found =\n        details_lookup_.find(control);\n\n    // If we've already created this control, just return that one.\n    if (found != details_lookup_.end())\n      return found->second;\n\n    control_order_.push_back(name);\n    return new DisplayDetails();\n  }\n\n  void CursynthGui::placeMinimalControl(std::string name,\n                                        const Control* control,\n                                        int x, int y, int width) {\n    DisplayDetails* details = initControl(name, control);\n    details->x = x;\n    details->y = y;\n    details->width = width;\n    details->label = \"\";\n    details->bipolar = control->isBipolar();\n\n    details_lookup_[control] = details;\n    drawControl(control, false);\n  }\n\n  void CursynthGui::placeControl(std::string name, const Control* control,\n                                 int x, int y, int width) {\n    DisplayDetails* details = initControl(name, control);\n    details->x = x;\n    details->y = y;\n    details->width = width;\n    details->label = name;\n    details->bipolar = control->isBipolar();\n\n    details_lookup_[control] = details;\n    drawControl(control, false);\n  }\n\n  void CursynthGui::addControls(const control_map& controls) {\n    // Oscillators.\n    placeControl(gettext_noop(\"osc 1 waveform\"),\n                 controls.at(\"osc 1 waveform\"),\n                 2, 7, 18);\n    placeControl(gettext_noop(\"osc 2 waveform\"),\n                 controls.at(\"osc 2 waveform\"),\n                 22, 7, 18);\n    placeControl(gettext_noop(\"cross modulation\"),\n                 controls.at(\"cross modulation\"),\n                 2, 10, 18);\n    placeControl(gettext_noop(\"osc mix\"),\n                 controls.at(\"osc mix\"),\n                 22, 10, 18);\n    placeControl(gettext_noop(\"osc 2 transpose\"),\n                 controls.at(\"osc 2 transpose\"),\n                 2, 13, 18);\n    placeControl(gettext_noop(\"osc 2 tune\"),\n                 controls.at(\"osc 2 tune\"),\n                 22, 13, 18);\n\n    // LFOs.\n    placeControl(gettext_noop(\"lfo 1 waveform\"),\n                 controls.at(\"lfo 1 waveform\"),\n                 2, 19, 18);\n    placeControl(gettext_noop(\"lfo 1 frequency\"),\n                 controls.at(\"lfo 1 frequency\"),\n                 22, 19, 18);\n    placeControl(gettext_noop(\"lfo 2 waveform\"),\n                 controls.at(\"lfo 2 waveform\"),\n                 2, 22, 18);\n    placeControl(gettext_noop(\"lfo 2 frequency\"),\n                 controls.at(\"lfo 2 frequency\"),\n                 22, 22, 18);\n\n    // Volume / Delay.\n    placeControl(gettext_noop(\"volume\"),\n                 controls.at(\"volume\"),\n                 2, 25, 38);\n    placeControl(gettext_noop(\"delay time\"),\n                 controls.at(\"delay time\"),\n                 2, 28, 38);\n    placeControl(gettext_noop(\"delay feedback\"),\n                 controls.at(\"delay feedback\"),\n                 2, 31, 18);\n    placeControl(gettext_noop(\"delay dry/wet\"),\n                 controls.at(\"delay dry/wet\"),\n                 22, 31, 18);\n\n    // Filter.\n    placeControl(gettext_noop(\"filter type\"),\n                 controls.at(\"filter type\"),\n                 42, 7, 38);\n    placeControl(gettext_noop(\"cutoff\"),\n                 controls.at(\"cutoff\"),\n                 42, 10, 38);\n    placeControl(gettext_noop(\"resonance\"),\n                 controls.at(\"resonance\"),\n                 42, 13, 38);\n    placeControl(gettext_noop(\"keytrack\"),\n                 controls.at(\"keytrack\"),\n                 42, 16, 38);\n    placeControl(gettext_noop(\"fil env depth\"),\n                 controls.at(\"fil env depth\"),\n                 42, 19, 38);\n    placeControl(gettext_noop(\"fil attack\"),\n                 controls.at(\"fil attack\"),\n                 42, 22, 38);\n    placeControl(gettext_noop(\"fil decay\"),\n                 controls.at(\"fil decay\"),\n                 42, 25, 38);\n    placeControl(gettext_noop(\"fil sustain\"),\n                 controls.at(\"fil sustain\"),\n                 42, 28, 38);\n    placeControl(gettext_noop(\"fil release\"),\n                 controls.at(\"fil release\"),\n                 42, 31, 38);\n\n    // Performance.\n    placeControl(gettext_noop(\"polyphony\"),\n                 controls.at(\"polyphony\"),\n                 82, 7, 30);\n    placeControl(gettext_noop(\"legato\"),\n                 controls.at(\"legato\"),\n                 114, 7, 6);\n    placeControl(gettext_noop(\"portamento\"),\n                 controls.at(\"portamento\"),\n                 82, 10, 21);\n    placeControl(gettext_noop(\"portamento type\"),\n                 controls.at(\"portamento type\"),\n                 105, 10, 15);\n    placeControl(gettext_noop(\"pitch bend range\"),\n                 controls.at(\"pitch bend range\"),\n                 82, 13, 38);\n\n    // Amplitude Envelope.\n    placeControl(gettext_noop(\"amp attack\"),\n                 controls.at(\"amp attack\"),\n                 82, 19, 38);\n    placeControl(gettext_noop(\"amp decay\"),\n                 controls.at(\"amp decay\"),\n                 82, 22, 38);\n    placeControl(gettext_noop(\"amp sustain\"),\n                 controls.at(\"amp sustain\"),\n                 82, 25, 38);\n    placeControl(gettext_noop(\"amp release\"),\n                 controls.at(\"amp release\"),\n                 82, 28, 38);\n    placeControl(gettext_noop(\"velocity track\"),\n                 controls.at(\"velocity track\"),\n                 82, 31, 38);\n\n    // Modulation Matrix.\n    placeMinimalControl(gettext_noop(\"mod source 1\"),\n                        controls.at(\"mod source 1\"),\n                        26, 36, 22);\n    placeMinimalControl(gettext_noop(\"mod scale 1\"),\n                        controls.at(\"mod scale 1\"),\n                        50, 36, 22);\n    placeMinimalControl(gettext_noop(\"mod destination 1\"),\n                        controls.at(\"mod destination 1\"),\n                        74, 36, 22);\n    placeMinimalControl(gettext_noop(\"mod source 2\"),\n                        controls.at(\"mod source 2\"),\n                        26, 37, 22);\n    placeMinimalControl(gettext_noop(\"mod scale 2\"),\n                        controls.at(\"mod scale 2\"),\n                        50, 37, 22);\n    placeMinimalControl(gettext_noop(\"mod destination 2\"),\n                        controls.at(\"mod destination 2\"),\n                        74, 37, 22);\n    placeMinimalControl(gettext_noop(\"mod source 3\"),\n                        controls.at(\"mod source 3\"),\n                        26, 38, 22);\n    placeMinimalControl(gettext_noop(\"mod scale 3\"),\n                        controls.at(\"mod scale 3\"),\n                        50, 38, 22);\n    placeMinimalControl(gettext_noop(\"mod destination 3\"),\n                        controls.at(\"mod destination 3\"),\n                        74, 38, 22);\n    placeMinimalControl(gettext_noop(\"mod source 4\"),\n                        controls.at(\"mod source 4\"),\n                        26, 39, 22);\n    placeMinimalControl(gettext_noop(\"mod scale 4\"),\n                        controls.at(\"mod scale 4\"),\n                        50, 39, 22);\n    placeMinimalControl(gettext_noop(\"mod destination 4\"),\n                        controls.at(\"mod destination 4\"),\n                        74, 39, 22);\n    placeMinimalControl(gettext_noop(\"mod source 5\"),\n                        controls.at(\"mod source 5\"),\n                        26, 40, 22);\n    placeMinimalControl(gettext_noop(\"mod scale 5\"),\n                        controls.at(\"mod scale 5\"),\n                        50, 40, 22);\n    placeMinimalControl(gettext_noop(\"mod destination 5\"),\n                        controls.at(\"mod destination 5\"),\n                        74, 40, 22);\n  }\n\n  std::string CursynthGui::getCurrentControl() {\n    return control_order_[control_index_];\n  }\n\n  std::string CursynthGui::getNextControl() {\n    control_index_ = (control_index_ + 1) % control_order_.size();\n    return getCurrentControl();\n  }\n\n  std::string CursynthGui::getPrevControl() {\n    control_index_ = (control_index_ + control_order_.size() - 1) %\n      control_order_.size();\n    return getCurrentControl();\n  }\n} // namespace mopo\n"
  },
  {
    "path": "src/cursynth_gui.h",
    "content": "/* Copyright 2013-2015 Matt Tytel\n *\n * cursynth is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * cursynth is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with cursynth.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#pragma once\n#ifndef CURSYNTH_GUI_H\n#define CURSYNTH_GUI_H\n\n#include \"mopo.h\"\n#include \"cursynth_common.h\"\n\n#include <map>\n#include <ncurses.h>\n#include <string>\n\nnamespace mopo {\n  class Value;\n\n  // Stores information on how and where to draw a control.\n  struct DisplayDetails {\n    int x, y, width;\n    std::string label;\n    bool bipolar;\n  };\n\n  class CursynthGui {\n    public:\n      enum ColorIds {\n        BG_COLOR = 1,\n        SLIDER_FG_COLOR,\n        SLIDER_BG_COLOR,\n        LOGO_COLOR,\n        SELECTED_COLOR,\n        PATCH_LOAD_COLOR,\n        CONTROL_TEXT_COLOR\n      };\n\n      CursynthGui() : control_index_(0) { }\n\n      // Start and stop the GUI.\n      void start();\n      void stop();\n      void redrawBase();\n\n      // Add all of the controls for drawing.\n      void addControls(const control_map& controls);\n\n      void drawHelp();\n      void drawMain();\n      void drawSlider(const DisplayDetails* slider,\n                      float percentage, bool active);\n      void drawControl(const Control* control, bool active);\n      void drawControlStatus(const Control* control, bool armed);\n      void drawPatchLoading(std::vector<std::string> patches, int index);\n      void drawPatchSaving(std::string patch_name);\n\n      void clearPatches();\n\n      // Linear navigation of controls.\n      std::string getCurrentControl();\n      std::string getNextControl();\n      std::string getPrevControl();\n\n    private:\n      void drawLogo();\n      void drawModulationMatrix();\n      void drawMidi(std::string status);\n      void drawStatus(std::string status);\n      void drawText(const DisplayDetails* details,\n                    std::string text, bool active);\n\n      // Creates control details and places control in the control order.\n      DisplayDetails* initControl(std::string name, const Control* control);\n\n      // Place a given control with text display at a location and width.\n      void placeControl(std::string name, const Control* control,\n                        int x, int y, int width);\n\n      // Place a given control (slider only) at a location and width.\n      void placeMinimalControl(std::string name, const Control* control,\n                               int x, int y, int width);\n\n      std::map<const Control*, DisplayDetails*> details_lookup_;\n      std::vector<std::string> control_order_;\n      int control_index_;\n  };\n} // namespace mopo\n\n#endif // CURSYNTH_GUI_H\n"
  },
  {
    "path": "src/cursynth_strings.cpp",
    "content": "/* Copyright 2013-2015 Matt Tytel\n *\n * cursynth is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * cursynth is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with cursynth.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"cursynth_strings.h\"\n\nnamespace mopo {\n\n  const char* CursynthStrings::filter_strings_[] = {\n    \"low pass\",\n    \"high pass\",\n    \"band pass\",\n    \"all pass\"\n  };\n\n  const char* CursynthStrings::legato_strings_[] = {\n    \"off\",\n    \"on\"\n  };\n\n  const char* CursynthStrings::portamento_strings_[] = {\n    \"off\",\n    \"auto\",\n    \"on\"\n  };\n\n  const char* CursynthStrings::wave_strings_[] = {\n    \"sin\",\n    \"triangle\",\n    \"square\",\n    \"down saw\",\n    \"up saw\",\n    \"three step\",\n    \"four step\",\n    \"eight step\",\n    \"three pyramid\",\n    \"five pyramid\",\n    \"nine pyramid\",\n    \"white noise\",\n  };\n} // namespace mopo\n"
  },
  {
    "path": "src/cursynth_strings.h",
    "content": "/* Copyright 2013-2015 Matt Tytel\n *\n * cursynth is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * cursynth is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with cursynth.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#pragma once\n#ifndef CURSYNTH_STRINGS_H\n#define CURSYNTH_STRINGS_H\n\nnamespace mopo {\n\n  // Container for all the strings we'll use in the UI.\n  class CursynthStrings {\n    public:\n      static const char* filter_strings_[];\n      static const char* legato_strings_[];\n      static const char* portamento_strings_[];\n      static const char* wave_strings_[];\n  };\n} // namespace mopo\n\n#endif // CURSYNTH_STRINGS_H\n"
  },
  {
    "path": "src/main.cpp",
    "content": "/* Copyright 2013-2015 Matt Tytel\n *\n * cursynth is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * cursynth is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with cursynth.  If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"cursynth.h\"\n#include <iostream>\n#include <stdlib.h>\n#include <getopt.h>\n\nint main(int argc, char **argv) {\n  unsigned buffer_size = mopo::DEFAULT_BUFFER_SIZE;\n  unsigned sample_rate = mopo::DEFAULT_SAMPLE_RATE;\n\n  int getopt_response = 0;\n  int digit_optind = 0;\n\n  while (getopt_response != -1) {\n    static const struct option long_options[] = {\n      {\"sample-rate\", required_argument, 0, 's'},\n      {\"buffer-size\", required_argument, 0, 'b'},\n      {\"version\", no_argument, 0, 'V'},\n      {0, 0, 0, 0}\n    };\n\n    int option_index = 0;\n    getopt_response = getopt_long(argc, argv, \"s:b:V\",\n                                  long_options, &option_index);\n\n    switch (getopt_response) {\n      case 's':\n        sample_rate = atoi(optarg);\n        break;\n      case 'b':\n        buffer_size = atoi(optarg);\n        break;\n      case 'V':\n        std::cout << \"Cursynth \" << VERSION << std::endl;\n        exit(EXIT_SUCCESS);\n        break;\n      case -1:\n        break;\n      default:\n        std::cout << std::endl << \"Usage:\" << std::endl\n                  << \"cursynth [--buffer-size OR -b preferred-buffer-size]\"\n                  << std::endl\n                  << \"         [--sample-rate OR -s preferred-sample-rate]\"\n                  << std::endl\n                  << \"         [--version OR -V]\"\n                  << std::endl;\n        exit(EXIT_FAILURE);\n        break;\n    }\n  }\n\n  mopo::Cursynth cursynth;\n  cursynth.start(sample_rate, buffer_size);\n\n  return 0;\n}\n"
  }
]